@@ -517,4 +517,92 @@ xqc_test_cid_handshake_exclusion()
517517 CU_ASSERT (ret == XQC_OK );
518518
519519 xqc_engine_destroy (conn -> engine );
520- }
520+ }
521+
522+ /*
523+ * Test mark_original idempotency: calling xqc_cid_set_mark_original twice
524+ * on the same CID must not inflate original_cid_cnt.
525+ */
526+ void
527+ xqc_test_cid_mark_original_idempotent ()
528+ {
529+ xqc_int_t ret ;
530+ xqc_connection_t * conn ;
531+
532+ conn = test_engine_connect ();
533+ CU_ASSERT_FATAL (conn != NULL );
534+
535+ /* test_engine_connect already marks initial DCID as original (cnt=1) */
536+ xqc_cid_set_inner_t * inner_set = xqc_get_path_cid_set (& conn -> dcid_set ,
537+ XQC_INITIAL_PATH_ID );
538+ CU_ASSERT_FATAL (inner_set != NULL );
539+ uint64_t cnt_before = inner_set -> original_cid_cnt ;
540+
541+ /* call mark_original again on the same CID — must be a no-op */
542+ xqc_cid_set_mark_original (& conn -> dcid_set ,
543+ & conn -> dcid_set .current_dcid ,
544+ XQC_INITIAL_PATH_ID );
545+ CU_ASSERT (inner_set -> original_cid_cnt == cnt_before );
546+
547+ /* call a third time for good measure */
548+ xqc_cid_set_mark_original (& conn -> dcid_set ,
549+ & conn -> dcid_set .current_dcid ,
550+ XQC_INITIAL_PATH_ID );
551+ CU_ASSERT (inner_set -> original_cid_cnt == cnt_before );
552+
553+ xqc_engine_destroy (conn -> engine );
554+ }
555+
556+ /*
557+ * Test that xqc_cid_set_delete_cid correctly decrements original_cid_cnt
558+ * when an original CID is deleted (rather than state-transitioned).
559+ */
560+ void
561+ xqc_test_cid_delete_original ()
562+ {
563+ xqc_int_t ret ;
564+ xqc_connection_t * conn ;
565+
566+ conn = test_engine_connect ();
567+ CU_ASSERT_FATAL (conn != NULL );
568+
569+ /* insert a new CID and mark it as original */
570+ xqc_cid_t extra_cid ;
571+ ret = xqc_generate_cid (conn -> engine , NULL , & extra_cid , 0 );
572+ CU_ASSERT (ret == XQC_OK );
573+ ret = xqc_cid_set_insert_cid (& conn -> dcid_set , & extra_cid , XQC_CID_USED ,
574+ conn -> local_settings .active_connection_id_limit ,
575+ XQC_INITIAL_PATH_ID );
576+ CU_ASSERT (ret == XQC_OK );
577+ xqc_cid_set_mark_original (& conn -> dcid_set , & extra_cid , XQC_INITIAL_PATH_ID );
578+
579+ xqc_cid_set_inner_t * inner_set = xqc_get_path_cid_set (& conn -> dcid_set ,
580+ XQC_INITIAL_PATH_ID );
581+ CU_ASSERT_FATAL (inner_set != NULL );
582+ uint64_t cnt_before = inner_set -> original_cid_cnt ;
583+ CU_ASSERT (cnt_before >= 2 );
584+
585+ /* delete the extra original CID — original_cid_cnt must decrease */
586+ ret = xqc_cid_set_delete_cid (& conn -> dcid_set , & extra_cid ,
587+ XQC_INITIAL_PATH_ID );
588+ CU_ASSERT (ret == XQC_OK );
589+ CU_ASSERT (inner_set -> original_cid_cnt == cnt_before - 1 );
590+
591+ /* delete a non-original CID — original_cid_cnt must NOT change */
592+ xqc_cid_t normal_cid ;
593+ ret = xqc_generate_cid (conn -> engine , NULL , & normal_cid , 200 );
594+ CU_ASSERT (ret == XQC_OK );
595+ ret = xqc_cid_set_insert_cid (& conn -> dcid_set , & normal_cid , XQC_CID_UNUSED ,
596+ conn -> local_settings .active_connection_id_limit ,
597+ XQC_INITIAL_PATH_ID );
598+ CU_ASSERT (ret == XQC_OK );
599+
600+ uint64_t cnt_after_insert = inner_set -> original_cid_cnt ;
601+ ret = xqc_cid_set_delete_cid (& conn -> dcid_set , & normal_cid ,
602+ XQC_INITIAL_PATH_ID );
603+ CU_ASSERT (ret == XQC_OK );
604+ CU_ASSERT (inner_set -> original_cid_cnt == cnt_after_insert );
605+
606+ xqc_engine_destroy (conn -> engine );
607+ }
608+
0 commit comments