21
21
22
22
using namespace syncd ;
23
23
using namespace saivs ;
24
+ using namespace testing ;
24
25
25
26
static void syncd_thread (
26
27
_In_ std::shared_ptr<Syncd> syncd)
@@ -230,17 +231,39 @@ void clearDB()
230
231
r.checkStatusOK ();
231
232
}
232
233
234
+ class MockSaiSwitch : public SaiSwitch {
235
+ public:
236
+ MockSaiSwitch (sai_object_id_t switchVid, sai_object_id_t switchRid,
237
+ std::shared_ptr<RedisClient> client,
238
+ std::shared_ptr<VirtualOidTranslator> translator,
239
+ std::shared_ptr<MockableSaiInterface> sai, bool warmBoot)
240
+ : SaiSwitch(switchVid, switchRid, client, translator, sai, warmBoot) {}
241
+ MOCK_METHOD (void , postPortRemove, (sai_object_id_t portRid), (override ));
242
+ MOCK_METHOD (void , removeExistingObjectReference, (sai_object_id_t rid), (override ));
243
+ MOCK_METHOD (void , eraseRidAndVid, (sai_object_id_t rid, sai_object_id_t vid));
244
+ };
245
+
233
246
class SyncdTest : public ::testing::Test
234
247
{
235
248
protected:
236
249
void SetUp () override
237
250
{
251
+ m_sai = std::make_shared<MockableSaiInterface>();
252
+ m_opt = std::make_shared<CommandLineOptions>();
253
+ m_syncd = std::make_shared<Syncd>(m_sai, m_opt, false );
254
+
255
+ m_opt->m_enableTempView = true ;
256
+ m_opt->m_startType = SAI_START_TYPE_FASTFAST_BOOT;
238
257
clearDB ();
239
258
}
240
259
void TearDown () override
241
260
{
242
261
clearDB ();
243
262
}
263
+
264
+ std::shared_ptr<MockableSaiInterface> m_sai;
265
+ std::shared_ptr<CommandLineOptions> m_opt;
266
+ std::shared_ptr<Syncd> m_syncd;
244
267
};
245
268
246
269
TEST_F (SyncdTest, processNotifySyncd)
@@ -259,4 +282,274 @@ TEST_F(SyncdTest, processNotifySyncd)
259
282
}));
260
283
syncd_object.processEvent (consumer);
261
284
}
285
+
286
+ TEST_F (SyncdTest, BulkCreateTest)
287
+ {
288
+ m_opt->m_enableSaiBulkSupport = true ;
289
+ sai_object_id_t switchVid = 0x21000000000000 ;
290
+ sai_object_id_t switchRid = 0x11000000000001 ;
291
+ sai_object_id_t portVid = 0x10000000000002 ;
292
+ sai_object_id_t portRid = 0x11000000000002 ;
293
+ auto translator = m_syncd->m_translator ;
294
+ translator->insertRidAndVid (switchRid, switchVid);
295
+ translator->insertRidAndVid (portRid, portVid);
296
+ std::vector<uint32_t > lanes = {52 , 53 };
297
+ m_syncd->m_client ->setPortLanes (switchVid, portRid, lanes);
298
+ m_sai->mock_objectTypeQuery = [switchRid, portRid](sai_object_id_t oid) {
299
+ sai_object_type_t ot = SAI_OBJECT_TYPE_NULL;
300
+ if (oid == switchRid)
301
+ ot = SAI_OBJECT_TYPE_SWITCH;
302
+ else if (oid == portRid)
303
+ ot = SAI_OBJECT_TYPE_PORT;
304
+ else
305
+ ot = SAI_OBJECT_TYPE_QUEUE;
306
+ return ot;
307
+ };
308
+ m_sai->mock_switchIdQuery = [switchVid](sai_object_id_t oid) {
309
+ return switchVid;
310
+ };
311
+ m_sai->mock_get = [switchRid, portVid, portRid](sai_object_type_t objectType, sai_object_id_t objectId, uint32_t attrCount, sai_attribute_t * attrList) -> sai_status_t {
312
+ if (attrCount != 1 ) {
313
+ return SAI_STATUS_INVALID_PARAMETER;
314
+ }
315
+ if (attrList[0 ].id == SAI_SWITCH_ATTR_PORT_LIST) {
316
+ if (objectType == SAI_OBJECT_TYPE_SWITCH && objectId == switchRid) {
317
+ attrList[0 ].value .objlist .count = 1 ;
318
+ attrList[0 ].value .objlist .list [0 ] = portRid;
319
+ return SAI_STATUS_SUCCESS;
320
+ }
321
+ return SAI_STATUS_INVALID_PARAMETER;
322
+ }
323
+ if (attrList[0 ].id == SAI_SWITCH_ATTR_PORT_NUMBER) {
324
+ attrList[0 ].value .u32 = 1 ;
325
+ return SAI_STATUS_SUCCESS;
326
+ }
327
+ if (objectType == SAI_OBJECT_TYPE_PORT) {
328
+ if (attrList[0 ].id == SAI_PORT_ATTR_HW_LANE_LIST) {
329
+ if (objectId == portRid) {
330
+ if (attrList[0 ].value .u32list .list != nullptr ) {
331
+ attrList[0 ].value .u32list .count = 2 ;
332
+ static uint32_t hw_lanes[2 ] = {52 , 53 };
333
+ memcpy (attrList[0 ].value .u32list .list , hw_lanes, sizeof (uint32_t ) * 2 );
334
+ } else {
335
+ return SAI_STATUS_BUFFER_OVERFLOW;
336
+ }
337
+ }
338
+ }
339
+ if (attrList[0 ].id == SAI_PORT_ATTR_PORT_SERDES_ID) {
340
+ attrList[0 ].value .oid = SAI_NULL_OBJECT_ID;
341
+ return SAI_STATUS_SUCCESS;
342
+ }
343
+ return SAI_STATUS_SUCCESS;
344
+ }
345
+ if (attrList[0 ].id == SAI_SWITCH_ATTR_SRC_MAC_ADDRESS) {
346
+ if (objectType == SAI_OBJECT_TYPE_SWITCH && objectId == switchRid) {
347
+ static sai_mac_t mac = {0x00 , 0x11 , 0x22 , 0x33 , 0x44 , 0x55 };
348
+ memcpy (attrList[0 ].value .mac , mac, sizeof (sai_mac_t ));
349
+ return SAI_STATUS_SUCCESS;
350
+ }
351
+ return SAI_STATUS_INVALID_PARAMETER;
352
+ }
353
+ return SAI_STATUS_NOT_SUPPORTED;
354
+ };
355
+ // Create a mock switch and set expectations
356
+ auto mockSwitch = std::make_shared<MockSaiSwitch>(switchVid, switchRid, m_syncd->m_client , translator, m_sai, false );
357
+ m_syncd->m_switches [switchVid] = mockSwitch;
358
+ EXPECT_CALL (*mockSwitch, postPortRemove (testing::_))
359
+ .WillRepeatedly (testing::Invoke ([](sai_object_id_t rid) {
360
+ }));
361
+ EXPECT_CALL (*mockSwitch, removeExistingObjectReference (testing::_))
362
+ .WillRepeatedly (testing::Invoke ([](sai_object_id_t rid) {
363
+ }));
364
+ EXPECT_CALL (*mockSwitch, eraseRidAndVid (testing::_, testing::_))
365
+ .WillRepeatedly (testing::Invoke ([](sai_object_id_t rid, sai_object_id_t vid) {
366
+ }));
367
+ swss::KeyOpFieldsValuesTuple kco;
368
+ std::string key = " SAI_OBJECT_TYPE_PORT:bulk:1" ;
369
+ std::string op = " bulkcreate" ;
370
+ std::vector<swss::FieldValueTuple> values = {
371
+ {" oid:0x10000000000002" , " SAI_PORT_ATTR_ADMIN_STATE=true" }
372
+ };
373
+ kco = std::make_tuple (key, op, values);
374
+ auto channel = std::make_shared<MockSelectableChannel>();
375
+ int popCallCount = 0 ;
376
+ EXPECT_CALL (*channel, empty ())
377
+ .WillRepeatedly ([&popCallCount]() {
378
+ return popCallCount > 0 ; // Return true after the first pop call
379
+ });
380
+ EXPECT_CALL (*channel, pop (testing::_, testing::_))
381
+ .Times (testing::AnyNumber ())
382
+ .WillRepeatedly (testing::DoAll (
383
+ testing::SetArgReferee<0 >(kco),
384
+ testing::Invoke ([&popCallCount](swss::KeyOpFieldsValuesTuple&, bool ) {
385
+ popCallCount++;
386
+ })
387
+ ));
388
+ m_sai->mock_bulkCreate = [](
389
+ sai_object_type_t ,
390
+ sai_object_id_t ,
391
+ uint32_t ,
392
+ const uint32_t *,
393
+ const sai_attribute_t **,
394
+ sai_bulk_op_error_mode_t ,
395
+ sai_object_id_t *,
396
+ sai_status_t *) -> sai_status_t {
397
+ return SAI_STATUS_NOT_IMPLEMENTED;
398
+ };
399
+ m_syncd->processEvent (*channel);
400
+ }
401
+
402
+ TEST_F (SyncdTest, BulkSetTest)
403
+ {
404
+ m_opt->m_enableSaiBulkSupport = true ;
405
+ auto translator = m_syncd->m_translator ;
406
+ translator->insertRidAndVid (0x11000000000001 , 0x21000000000000 ); // Switch
407
+ translator->insertRidAndVid (0x1100000000000d , 0x1000000000000d ); // Port 1
408
+ translator->insertRidAndVid (0x1100000000000e , 0x1000000000000e ); // Port 2
409
+ swss::KeyOpFieldsValuesTuple kco;
410
+ std::string key = " SAI_OBJECT_TYPE_PORT:bulk:1" ;
411
+ std::string op = " bulkset" ;
412
+ std::vector<swss::FieldValueTuple> values = {
413
+ {" oid:0x1000000000000d" , " SAI_PORT_ATTR_ADMIN_STATE=true" },
414
+ {" oid:0x1000000000000e" , " SAI_PORT_ATTR_ADMIN_STATE=false" }
415
+ };
416
+ kco = std::make_tuple (key, op, values);
417
+ auto channel = std::make_shared<MockSelectableChannel>();
418
+ EXPECT_CALL (*channel, empty ())
419
+ .WillOnce (testing::Return (false ))
420
+ .WillRepeatedly (testing::Return (true ));
421
+ EXPECT_CALL (*channel, pop (testing::_, testing::_))
422
+ .Times (testing::AnyNumber ())
423
+ .WillRepeatedly (testing::DoAll (
424
+ testing::SetArgReferee<0 >(kco),
425
+ testing::Return ()
426
+ ));
427
+ m_sai->mock_bulkSet = [](
428
+ sai_object_type_t ,
429
+ uint32_t ,
430
+ const sai_object_id_t *,
431
+ const sai_attribute_t *,
432
+ sai_bulk_op_error_mode_t ,
433
+ sai_status_t *) -> sai_status_t {
434
+ return SAI_STATUS_NOT_IMPLEMENTED;
435
+ };
436
+ m_syncd->processEvent (*channel);
437
+ }
438
+
439
+ TEST_F (SyncdTest, BulkRemoveTest)
440
+ {
441
+ m_opt->m_enableSaiBulkSupport = true ;
442
+ sai_object_id_t switchVid = 0x21000000000000 ;
443
+ sai_object_id_t switchRid = 0x11000000000001 ;
444
+ sai_object_id_t portVid = 0x10000000000002 ;
445
+ sai_object_id_t portRid = 0x11000000000002 ;
446
+ auto translator = m_syncd->m_translator ;
447
+ translator->insertRidAndVid (switchRid, switchVid);
448
+ translator->insertRidAndVid (portRid, portVid);
449
+ std::vector<uint32_t > lanes = {52 , 53 };
450
+ m_syncd->m_client ->setPortLanes (switchVid, portRid, lanes);
451
+ std::set<sai_object_id_t > removedRids;
452
+ m_sai->mock_objectTypeQuery = [switchRid, portRid, &removedRids](sai_object_id_t oid) {
453
+ sai_object_type_t ot = SAI_OBJECT_TYPE_NULL;
454
+ if (removedRids.find (oid) != removedRids.end ()) {
455
+ return SAI_OBJECT_TYPE_NULL;
456
+ }
457
+ if (oid == switchRid)
458
+ ot = SAI_OBJECT_TYPE_SWITCH;
459
+ else if (oid == portRid)
460
+ ot = SAI_OBJECT_TYPE_PORT;
461
+ else
462
+ ot = SAI_OBJECT_TYPE_QUEUE;
463
+ return ot;
464
+ };
465
+ m_sai->mock_switchIdQuery = [switchVid](sai_object_id_t oid) {
466
+ return switchVid;
467
+ };
468
+ m_sai->mock_get = [switchRid, portVid, portRid](sai_object_type_t objectType, sai_object_id_t objectId, uint32_t attrCount, sai_attribute_t * attrList) -> sai_status_t {
469
+ if (attrCount != 1 ) {
470
+ return SAI_STATUS_INVALID_PARAMETER;
471
+ }
472
+ if (attrList[0 ].id == SAI_SWITCH_ATTR_PORT_LIST) {
473
+ if (objectType == SAI_OBJECT_TYPE_SWITCH && objectId == switchRid) {
474
+ attrList[0 ].value .objlist .count = 1 ;
475
+ attrList[0 ].value .objlist .list [0 ] = portRid;
476
+ return SAI_STATUS_SUCCESS;
477
+ }
478
+ return SAI_STATUS_INVALID_PARAMETER;
479
+ }
480
+ if (attrList[0 ].id == SAI_SWITCH_ATTR_PORT_NUMBER) {
481
+ attrList[0 ].value .u32 = 1 ;
482
+ return SAI_STATUS_SUCCESS;
483
+ }
484
+ if (objectType == SAI_OBJECT_TYPE_PORT) {
485
+ if (attrList[0 ].id == SAI_PORT_ATTR_HW_LANE_LIST) {
486
+ if (objectId == portRid) {
487
+ if (attrList[0 ].value .u32list .list != nullptr ) {
488
+ attrList[0 ].value .u32list .count = 2 ;
489
+ static uint32_t hw_lanes[2 ] = {52 , 53 };
490
+ memcpy (attrList[0 ].value .u32list .list , hw_lanes, sizeof (uint32_t ) * 2 );
491
+ } else {
492
+ return SAI_STATUS_BUFFER_OVERFLOW;
493
+ }
494
+ }
495
+ }
496
+ if (attrList[0 ].id == SAI_PORT_ATTR_PORT_SERDES_ID) {
497
+ attrList[0 ].value .oid = SAI_NULL_OBJECT_ID;
498
+ return SAI_STATUS_SUCCESS;
499
+ }
500
+ return SAI_STATUS_SUCCESS;
501
+ }
502
+ if (attrList[0 ].id == SAI_SWITCH_ATTR_SRC_MAC_ADDRESS) {
503
+ if (objectType == SAI_OBJECT_TYPE_SWITCH && objectId == switchRid) {
504
+ static sai_mac_t mac = {0x00 , 0x11 , 0x22 , 0x33 , 0x44 , 0x55 };
505
+ memcpy (attrList[0 ].value .mac , mac, sizeof (sai_mac_t ));
506
+ return SAI_STATUS_SUCCESS;
507
+ }
508
+ return SAI_STATUS_INVALID_PARAMETER;
509
+ }
510
+ return SAI_STATUS_NOT_SUPPORTED;
511
+ };
512
+ // Create a mock switch and set expectations
513
+ auto mockSwitch = std::make_shared<MockSaiSwitch>(switchVid, switchRid, m_syncd->m_client , translator, m_sai, false );
514
+ m_syncd->m_switches [switchVid] = mockSwitch;
515
+ EXPECT_CALL (*mockSwitch, postPortRemove (testing::_))
516
+ .WillRepeatedly (testing::Invoke ([](sai_object_id_t rid) {
517
+ }));
518
+ EXPECT_CALL (*mockSwitch, removeExistingObjectReference (testing::_))
519
+ .WillRepeatedly (testing::Invoke ([](sai_object_id_t rid) {
520
+ }));
521
+ EXPECT_CALL (*mockSwitch, eraseRidAndVid (testing::_, testing::_))
522
+ .WillRepeatedly (testing::Invoke ([](sai_object_id_t rid, sai_object_id_t vid) {
523
+ }));
524
+ swss::KeyOpFieldsValuesTuple kco;
525
+ std::string key = " SAI_OBJECT_TYPE_PORT:bulk:1" ;
526
+ std::string op = " bulkremove" ;
527
+ std::vector<swss::FieldValueTuple> values = {
528
+ {" oid:0x10000000000002" , " SAI_PORT_ATTR_ADMIN_STATE=true" }
529
+ };
530
+ kco = std::make_tuple (key, op, values);
531
+ auto channel = std::make_shared<MockSelectableChannel>();
532
+ int popCallCount = 0 ;
533
+ EXPECT_CALL (*channel, empty ())
534
+ .WillRepeatedly ([&popCallCount]() {
535
+ return popCallCount > 0 ; // Return true after the first pop call
536
+ });
537
+ EXPECT_CALL (*channel, pop (testing::_, testing::_))
538
+ .Times (testing::AnyNumber ())
539
+ .WillRepeatedly (testing::DoAll (
540
+ testing::SetArgReferee<0 >(kco),
541
+ testing::Invoke ([&popCallCount](swss::KeyOpFieldsValuesTuple&, bool ) {
542
+ popCallCount++;
543
+ })
544
+ ));
545
+ m_sai->mock_bulkRemove = [](
546
+ sai_object_type_t ,
547
+ uint32_t ,
548
+ const sai_object_id_t *,
549
+ sai_bulk_op_error_mode_t ,
550
+ sai_status_t *) -> sai_status_t {
551
+ return SAI_STATUS_NOT_IMPLEMENTED;
552
+ };
553
+ m_syncd->processEvent (*channel);
554
+ }
262
555
#endif
0 commit comments