@@ -601,3 +601,295 @@ func TestSymmetricRoutingParseError(t *testing.T) {
601601 err = setSymmetricRouting (cniFilePath )
602602 require .Error (t , err , "parse error" )
603603}
604+
605+ // TestDualStackWithNilConfig tests dualStack with nil eniCfg
606+ func TestDualStackWithNilConfig (t * testing.T ) {
607+ tempFile , err := os .CreateTemp ("" , "test_node_capabilities" )
608+ assert .NoError (t , err )
609+ defer os .Remove (tempFile .Name ())
610+
611+ // Set eniCfg to nil to test error handling
612+ originalEniCfg := eniCfg
613+ eniCfg = nil
614+ defer func () { eniCfg = originalEniCfg }()
615+
616+ cmd := & cobra.Command {}
617+ args := []string {}
618+
619+ // Create a test function that uses the temp file
620+ testDualStack := func (cmd * cobra.Command , args []string ) error {
621+ store := nodecap .NewFileNodeCapabilities (tempFile .Name ())
622+
623+ val := ""
624+ if eniCfg != nil {
625+ switch eniCfg .IPStack {
626+ case "dual" , "ipv6" :
627+ val = True
628+ default :
629+ val = False
630+ }
631+ } else {
632+ val = False // default behavior when eniCfg is nil
633+ }
634+
635+ err := store .Load ()
636+ if err != nil {
637+ return err
638+ }
639+
640+ store .Set (nodecap .NodeCapabilityIPv6 , val )
641+ return store .Save ()
642+ }
643+
644+ err = testDualStack (cmd , args )
645+ assert .NoError (t , err )
646+
647+ // Verify the capability was set to False when eniCfg is nil
648+ store := nodecap .NewFileNodeCapabilities (tempFile .Name ())
649+ err = store .Load ()
650+ assert .NoError (t , err )
651+ assert .Equal (t , False , store .Get (nodecap .NodeCapabilityIPv6 ))
652+ }
653+
654+ // TestDualStackStoreLoadError tests dualStack when store.Load() fails
655+ func TestDualStackStoreLoadError (t * testing.T ) {
656+ // Use a directory path instead of file path to cause Load() to fail
657+ tempDir , err := os .MkdirTemp ("" , "test_node_capabilities_dir" )
658+ assert .NoError (t , err )
659+ defer os .RemoveAll (tempDir )
660+
661+ eniCfg = & daemon.Config {IPStack : "dual" }
662+
663+ testDualStack := func (cmd * cobra.Command , args []string ) error {
664+ store := nodecap .NewFileNodeCapabilities (tempDir ) // directory instead of file
665+
666+ val := ""
667+ switch eniCfg .IPStack {
668+ case "dual" , "ipv6" :
669+ val = True
670+ default :
671+ val = False
672+ }
673+
674+ err := store .Load ()
675+ if err != nil {
676+ return err
677+ }
678+
679+ store .Set (nodecap .NodeCapabilityIPv6 , val )
680+ return store .Save ()
681+ }
682+
683+ cmd := & cobra.Command {}
684+ args := []string {}
685+ err = testDualStack (cmd , args )
686+ assert .Error (t , err ) // Should error because Load() fails on directory
687+ }
688+
689+ // TestEnableKPRFeatureDisabled tests enableKPR when KubeProxyReplacement feature is disabled
690+ func TestEnableKPRFeatureDisabled (t * testing.T ) {
691+ tempFile , err := os .CreateTemp ("" , "test_node_capabilities" )
692+ assert .NoError (t , err )
693+ defer os .Remove (tempFile .Name ())
694+
695+ cmd := & cobra.Command {}
696+ args := []string {}
697+
698+ // Create a test function that mimics enableKPR but without feature gate check
699+ testEnableKPRDisabled := func (cmd * cobra.Command , args []string ) error {
700+ // Simulate feature disabled by returning early
701+ return nil
702+ }
703+
704+ err = testEnableKPRDisabled (cmd , args )
705+ assert .NoError (t , err )
706+ }
707+
708+ // TestEnableKPRStoreLoadError tests enableKPR when store.Load() fails
709+ func TestEnableKPRStoreLoadError (t * testing.T ) {
710+ // Use a directory path instead of file path to cause Load() to fail
711+ tempDir , err := os .MkdirTemp ("" , "test_node_capabilities_dir" )
712+ assert .NoError (t , err )
713+ defer os .RemoveAll (tempDir )
714+
715+ cmd := & cobra.Command {}
716+ args := []string {}
717+
718+ testEnableKPRLoadError := func (cmd * cobra.Command , args []string ) error {
719+ store := nodecap .NewFileNodeCapabilities (tempDir ) // directory instead of file
720+
721+ err := store .Load ()
722+ if err != nil {
723+ return err
724+ }
725+
726+ prev := store .Get (nodecap .NodeCapabilityKubeProxyReplacement )
727+ if prev != "" {
728+ return nil
729+ }
730+
731+ store .Set (nodecap .NodeCapabilityKubeProxyReplacement , True )
732+ return store .Save ()
733+ }
734+
735+ err = testEnableKPRLoadError (cmd , args )
736+ assert .Error (t , err ) // Should error because Load() fails on directory
737+ }
738+
739+ // TestEnableKPRAlreadySet tests enableKPR when capability is already set
740+ func TestEnableKPRAlreadySet (t * testing.T ) {
741+ tempFile , err := os .CreateTemp ("" , "test_node_capabilities" )
742+ assert .NoError (t , err )
743+ defer os .Remove (tempFile .Name ())
744+
745+ // Pre-populate the file with existing capability
746+ err = os .WriteFile (tempFile .Name (), []byte ("cni_kube_proxy_replacement = true" ), 0644 )
747+ assert .NoError (t , err )
748+
749+ cmd := & cobra.Command {}
750+ args := []string {}
751+
752+ testEnableKPRAlreadySet := func (cmd * cobra.Command , args []string ) error {
753+ store := nodecap .NewFileNodeCapabilities (tempFile .Name ())
754+
755+ err := store .Load ()
756+ if err != nil {
757+ return err
758+ }
759+
760+ prev := store .Get (nodecap .NodeCapabilityKubeProxyReplacement )
761+ if prev != "" {
762+ return nil // Should return early
763+ }
764+
765+ store .Set (nodecap .NodeCapabilityKubeProxyReplacement , True )
766+ return store .Save ()
767+ }
768+
769+ err = testEnableKPRAlreadySet (cmd , args )
770+ assert .NoError (t , err )
771+
772+ // Verify the capability remains unchanged
773+ store := nodecap .NewFileNodeCapabilities (tempFile .Name ())
774+ err = store .Load ()
775+ assert .NoError (t , err )
776+ assert .Equal (t , "true" , store .Get (nodecap .NodeCapabilityKubeProxyReplacement ))
777+ }
778+
779+ // TestEnableKPRStoreSaveError tests enableKPR when store.Save() fails
780+ func TestEnableKPRStoreSaveError (t * testing.T ) {
781+ tempFile , err := os .CreateTemp ("" , "test_node_capabilities" )
782+ assert .NoError (t , err )
783+ defer os .Remove (tempFile .Name ())
784+
785+ cmd := & cobra.Command {}
786+ args := []string {}
787+
788+ testEnableKPRSaveError := func (cmd * cobra.Command , args []string ) error {
789+ store := nodecap .NewFileNodeCapabilities (tempFile .Name ())
790+
791+ err := store .Load ()
792+ if err != nil {
793+ return err
794+ }
795+
796+ prev := store .Get (nodecap .NodeCapabilityKubeProxyReplacement )
797+ if prev != "" {
798+ return nil
799+ }
800+
801+ store .Set (nodecap .NodeCapabilityKubeProxyReplacement , True )
802+
803+ // Remove the file to make Save() fail
804+ os .Remove (tempFile .Name ())
805+ // Create a directory with the same name to make Save() fail
806+ os .Mkdir (tempFile .Name (), 0755 )
807+ defer os .RemoveAll (tempFile .Name ())
808+
809+ return store .Save ()
810+ }
811+
812+ err = testEnableKPRSaveError (cmd , args )
813+ assert .Error (t , err ) // Should error because Save() fails
814+ }
815+
816+ // TestOverrideCNIGetAllConfigError tests overrideCNI when getAllConfig fails
817+ func TestOverrideCNIGetAllConfigError (t * testing.T ) {
818+ // Set environment variable for node name
819+ os .Setenv ("K8S_NODE_NAME" , "test-node" )
820+ defer os .Unsetenv ("K8S_NODE_NAME" )
821+
822+ // Create a temporary directory without required files to make getAllConfig fail
823+ tempDir , err := os .MkdirTemp ("" , "test_override_cni" )
824+ assert .NoError (t , err )
825+ defer os .RemoveAll (tempDir )
826+
827+ cmd := & cobra.Command {}
828+ args := []string {}
829+
830+ // Test function that mimics getENIConfig but uses our temp directory
831+ testGetENIConfigError := func (cmd * cobra.Command , args []string ) error {
832+ _ , err := getAllConfig (tempDir ) // This should fail due to missing files
833+ return err
834+ }
835+
836+ err = testGetENIConfigError (cmd , args )
837+ assert .Error (t , err ) // Should error because required files are missing
838+ }
839+
840+ // TestSetExclusiveModeWithInvalidCNIPath tests setExclusiveMode with invalid CNI path
841+ func TestSetExclusiveModeWithInvalidCNIPath (t * testing.T ) {
842+ tempFile , err := os .CreateTemp ("" , "test_node_capabilities" )
843+ assert .NoError (t , err )
844+ defer os .Remove (tempFile .Name ())
845+
846+ store := nodecap .NewFileNodeCapabilities (tempFile .Name ())
847+ labels := map [string ]string {
848+ "k8s.aliyun.com/exclusive-mode-eni-type" : "eniOnly" ,
849+ }
850+ // Use an invalid directory path for CNI config
851+ cniPath := "/invalid/directory/path/cni_config"
852+
853+ err = setExclusiveMode (store , labels , cniPath )
854+ assert .Error (t , err ) // Should error because CNI path is invalid
855+ }
856+
857+ // TestSetExclusiveModeWithMissingLabel tests setExclusiveMode with missing exclusive mode label
858+ func TestSetExclusiveModeWithMissingLabel (t * testing.T ) {
859+ tempFile , err := os .CreateTemp ("" , "test_node_capabilities" )
860+ assert .NoError (t , err )
861+ defer os .Remove (tempFile .Name ())
862+
863+ store := nodecap .NewFileNodeCapabilities (tempFile .Name ())
864+ labels := map [string ]string {} // Empty labels
865+ cniPath := tempFile .Name () + "_cni_config"
866+
867+ err = setExclusiveMode (store , labels , cniPath )
868+ assert .NoError (t , err )
869+
870+ // Verify default mode was set
871+ err = store .Load ()
872+ assert .NoError (t , err )
873+ assert .Equal (t , "default" , store .Get (nodecap .NodeCapabilityExclusiveENI ))
874+ }
875+
876+ // TestSetExclusiveModeWithUnknownLabel tests setExclusiveMode with unknown exclusive mode label
877+ func TestSetExclusiveModeWithUnknownLabel (t * testing.T ) {
878+ tempFile , err := os .CreateTemp ("" , "test_node_capabilities" )
879+ assert .NoError (t , err )
880+ defer os .Remove (tempFile .Name ())
881+
882+ store := nodecap .NewFileNodeCapabilities (tempFile .Name ())
883+ labels := map [string ]string {
884+ "k8s.aliyun.com/exclusive-mode-eni-type" : "unknown" ,
885+ }
886+ cniPath := tempFile .Name () + "_cni_config"
887+
888+ err = setExclusiveMode (store , labels , cniPath )
889+ assert .NoError (t , err )
890+
891+ // Verify default mode was set for unknown label value
892+ err = store .Load ()
893+ assert .NoError (t , err )
894+ assert .Equal (t , "default" , store .Get (nodecap .NodeCapabilityExclusiveENI ))
895+ }
0 commit comments