@@ -95,6 +95,7 @@ func TestController(t *testing.T) {
9595 expectedCapacities []testCapacity
9696 modify func (ctx context.Context , clientSet * fakeclientset.Clientset , expected []testCapacity ) (modifiedExpected []testCapacity , err error )
9797 capacityChange func (ctx context.Context , storage * mockCapacity , expected []testCapacity ) (modifiedExpected []testCapacity )
98+ topologyChange func (ctx context.Context , topology * mockTopology , expected []testCapacity ) (modifiedExpected []testCapacity )
9899 }{
99100 "empty" : {
100101 expectedCapacities : []testCapacity {},
@@ -764,6 +765,162 @@ func TestController(t *testing.T) {
764765 return expected
765766 },
766767 },
768+ "add storage topology segment" : {
769+ topology : mockTopology {},
770+ storage : mockCapacity {
771+ capacity : map [string ]interface {}{
772+ // This matches layer0.
773+ "foo" : "1Gi" ,
774+ },
775+ },
776+ initialSCs : []testSC {
777+ // We intentionally create a SC with immediate binding first.
778+ // It needs to be skipped while still processing the other one.
779+ // Ordering of the objects is not guaranteed, but in practice
780+ // the informer seems to be "first in, first out", which is what
781+ // we need.
782+ {
783+ name : "immediate-sc" ,
784+ driverName : driverName ,
785+ immediateBinding : true ,
786+ },
787+ {
788+ name : "late-sc" ,
789+ driverName : driverName ,
790+ },
791+ },
792+ expectedCapacities : nil ,
793+ topologyChange : func (ctx context.Context , topo * mockTopology , expected []testCapacity ) []testCapacity {
794+ topo .modify ([]* topology.Segment {& layer0 } /* added */ , nil /* removed */ )
795+ return append (expected , testCapacity {
796+ uid : "CSISC-UID-1" ,
797+ resourceVersion : csiscRev + "0" ,
798+ segment : layer0 ,
799+ storageClassName : "late-sc" ,
800+ quantity : "1Gi" ,
801+ })
802+ },
803+ },
804+ "add storage topology segment, immediate binding" : {
805+ immediateBinding : true ,
806+ topology : mockTopology {},
807+ storage : mockCapacity {
808+ capacity : map [string ]interface {}{
809+ // This matches layer0.
810+ "foo" : "1Gi" ,
811+ },
812+ },
813+ initialSCs : []testSC {
814+ {
815+ name : "immediate-sc" ,
816+ driverName : driverName ,
817+ immediateBinding : true ,
818+ },
819+ {
820+ name : "late-sc" ,
821+ driverName : driverName ,
822+ },
823+ },
824+ expectedCapacities : nil ,
825+ topologyChange : func (ctx context.Context , topo * mockTopology , expected []testCapacity ) []testCapacity {
826+ topo .modify ([]* topology.Segment {& layer0 } /* added */ , nil /* removed */ )
827+ // We don't check the UID here because we don't want to fail when
828+ // ordering of storage classes isn't such that the "immediate-sc" is seen first.
829+ return append (expected , testCapacity {
830+ resourceVersion : csiscRev + "0" ,
831+ segment : layer0 ,
832+ storageClassName : "immediate-sc" ,
833+ quantity : "1Gi" ,
834+ },
835+ testCapacity {
836+ resourceVersion : csiscRev + "0" ,
837+ segment : layer0 ,
838+ storageClassName : "late-sc" ,
839+ quantity : "1Gi" ,
840+ },
841+ )
842+ },
843+ },
844+ "remove storage topology segment" : {
845+ topology : mockTopology {
846+ segments : []* topology.Segment {& layer0 },
847+ },
848+ storage : mockCapacity {
849+ capacity : map [string ]interface {}{
850+ // This matches layer0.
851+ "foo" : "1Gi" ,
852+ },
853+ },
854+ initialSCs : []testSC {
855+ {
856+ name : "immediate-sc" ,
857+ driverName : driverName ,
858+ immediateBinding : true ,
859+ },
860+ {
861+ name : "late-sc" ,
862+ driverName : driverName ,
863+ },
864+ },
865+ expectedCapacities : []testCapacity {
866+ {
867+ uid : "CSISC-UID-1" ,
868+ resourceVersion : csiscRev + "0" ,
869+ segment : layer0 ,
870+ storageClassName : "late-sc" ,
871+ quantity : "1Gi" ,
872+ },
873+ },
874+ topologyChange : func (ctx context.Context , topo * mockTopology , expected []testCapacity ) []testCapacity {
875+ topo .modify (nil /* added */ , topo .segments [:] /* removed */ )
876+ return nil
877+ },
878+ },
879+ "add and remove storage topology segment" : {
880+ topology : mockTopology {
881+ segments : []* topology.Segment {& layer0 },
882+ },
883+ storage : mockCapacity {
884+ capacity : map [string ]interface {}{
885+ // This matches layer0.
886+ "foo" : "1Gi" ,
887+ "bar" : "2Gi" ,
888+ },
889+ },
890+ initialSCs : []testSC {
891+ {
892+ name : "immediate-sc" ,
893+ driverName : driverName ,
894+ immediateBinding : true ,
895+ },
896+ {
897+ name : "late-sc" ,
898+ driverName : driverName ,
899+ },
900+ },
901+ expectedCapacities : []testCapacity {
902+ {
903+ uid : "CSISC-UID-1" ,
904+ resourceVersion : csiscRev + "0" ,
905+ segment : layer0 ,
906+ storageClassName : "late-sc" ,
907+ quantity : "1Gi" ,
908+ },
909+ },
910+ topologyChange : func (ctx context.Context , topo * mockTopology , expected []testCapacity ) []testCapacity {
911+ topo .modify ([]* topology.Segment {& layer0other }, /* added */
912+ topo .segments [:] /* removed */ )
913+ return []testCapacity {
914+ {
915+ uid : "CSISC-UID-2" ,
916+ resourceVersion : csiscRev + "0" ,
917+ segment : layer0other ,
918+ storageClassName : "late-sc" ,
919+ quantity : "2Gi" ,
920+ },
921+ }
922+ },
923+ },
767924 }
768925
769926 for name , tc := range testcases {
@@ -820,6 +977,13 @@ func TestController(t *testing.T) {
820977 t .Fatalf ("modified capacity: %v" , err )
821978 }
822979 }
980+ if tc .topologyChange != nil {
981+ klog .Info ("modifying topology" )
982+ expectedCapacities = tc .topologyChange (ctx , & tc .topology , expectedCapacities )
983+ if err := validateCapacitiesEventually (ctx , c , clientSet , expectedCapacities ); err != nil {
984+ t .Fatalf ("modified capacity: %v" , err )
985+ }
986+ }
823987 })
824988 }
825989}
@@ -1100,6 +1264,35 @@ func (mt *mockTopology) HasSynced() bool {
11001264 return true
11011265}
11021266
1267+ func (mt * mockTopology ) modify (add , remove []* topology.Segment ) {
1268+ var added , removed []* topology.Segment
1269+ for _ , segment := range add {
1270+ if mt .segmentIndex (segment ) == - 1 {
1271+ added = append (added , segment )
1272+ mt .segments = append (mt .segments , segment )
1273+ }
1274+ }
1275+ for _ , segment := range remove {
1276+ index := mt .segmentIndex (segment )
1277+ if index != - 1 {
1278+ removed = append (removed , segment )
1279+ mt .segments = append (mt .segments [0 :index ], mt .segments [index + 1 :]... )
1280+ }
1281+ }
1282+ for _ , cb := range mt .callbacks {
1283+ cb (added , removed )
1284+ }
1285+ }
1286+
1287+ func (mt * mockTopology ) segmentIndex (segment * topology.Segment ) int {
1288+ for i , otherSegment := range mt .segments {
1289+ if otherSegment == segment {
1290+ return i
1291+ }
1292+ }
1293+ return - 1
1294+ }
1295+
11031296type testCapacity struct {
11041297 uid types.UID
11051298 resourceVersion string
0 commit comments