k8s.io/kubernetes@v1.29.3/pkg/controller/volume/persistentvolume/binder_test.go (about)

     1  /*
     2  Copyright 2016 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package persistentvolume
    18  
    19  import (
    20  	"testing"
    21  
    22  	v1 "k8s.io/api/core/v1"
    23  	storage "k8s.io/api/storage/v1"
    24  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    25  	"k8s.io/component-helpers/storage/volume"
    26  	"k8s.io/klog/v2/ktesting"
    27  )
    28  
    29  // Test single call to syncClaim and syncVolume methods.
    30  //  1. Fill in the controller with initial data
    31  //  2. Call the tested function (syncClaim/syncVolume) via
    32  //     controllerTest.testCall *once*.
    33  //  3. Compare resulting volumes and claims with expected volumes and claims.
    34  func TestSync(t *testing.T) {
    35  	labels := map[string]string{
    36  		"foo": "true",
    37  		"bar": "false",
    38  	}
    39  
    40  	tests := []controllerTest{
    41  		// [Unit test set 1] User did not care which PV they get.
    42  		// Test the matching with no claim.Spec.VolumeName and with various
    43  		// volumes.
    44  		{
    45  			// syncClaim binds to a matching unbound volume.
    46  			name:            "1-1 - successful bind",
    47  			initialVolumes:  newVolumeArray("volume1-1", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
    48  			expectedVolumes: newVolumeArray("volume1-1", "1Gi", "uid1-1", "claim1-1", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController),
    49  			initialClaims:   newClaimArray("claim1-1", "uid1-1", "1Gi", "", v1.ClaimPending, nil),
    50  			expectedClaims:  newClaimArray("claim1-1", "uid1-1", "1Gi", "volume1-1", v1.ClaimBound, nil, volume.AnnBoundByController, volume.AnnBindCompleted),
    51  			expectedEvents:  noevents,
    52  			errors:          noerrors,
    53  			test:            testSyncClaim,
    54  		},
    55  		{
    56  			// syncClaim does not do anything when there is no matching volume.
    57  			name:            "1-2 - noop",
    58  			initialVolumes:  newVolumeArray("volume1-2", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
    59  			expectedVolumes: newVolumeArray("volume1-2", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
    60  			initialClaims:   newClaimArray("claim1-2", "uid1-2", "10Gi", "", v1.ClaimPending, nil),
    61  			expectedClaims:  newClaimArray("claim1-2", "uid1-2", "10Gi", "", v1.ClaimPending, nil),
    62  			expectedEvents:  []string{"Normal FailedBinding"},
    63  			errors:          noerrors,
    64  			test:            testSyncClaim,
    65  		},
    66  		{
    67  			// syncClaim resets claim.Status to Pending when there is no
    68  			// matching volume.
    69  			name:            "1-3 - reset to Pending",
    70  			initialVolumes:  newVolumeArray("volume1-3", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
    71  			expectedVolumes: newVolumeArray("volume1-3", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
    72  			initialClaims:   newClaimArray("claim1-3", "uid1-3", "10Gi", "", v1.ClaimBound, nil),
    73  			expectedClaims:  newClaimArray("claim1-3", "uid1-3", "10Gi", "", v1.ClaimPending, nil),
    74  			expectedEvents:  []string{"Normal FailedBinding"},
    75  			errors:          noerrors,
    76  			test:            testSyncClaim,
    77  		},
    78  		{
    79  			// syncClaim binds claims to the smallest matching volume
    80  			name: "1-4 - smallest volume",
    81  			initialVolumes: []*v1.PersistentVolume{
    82  				newVolume("volume1-4_1", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
    83  				newVolume("volume1-4_2", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
    84  			},
    85  			expectedVolumes: []*v1.PersistentVolume{
    86  				newVolume("volume1-4_1", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
    87  				newVolume("volume1-4_2", "1Gi", "uid1-4", "claim1-4", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController),
    88  			},
    89  			initialClaims:  newClaimArray("claim1-4", "uid1-4", "1Gi", "", v1.ClaimPending, nil),
    90  			expectedClaims: newClaimArray("claim1-4", "uid1-4", "1Gi", "volume1-4_2", v1.ClaimBound, nil, volume.AnnBoundByController, volume.AnnBindCompleted),
    91  			expectedEvents: noevents,
    92  			errors:         noerrors,
    93  			test:           testSyncClaim,
    94  		},
    95  		{
    96  			// syncClaim binds a claim only to volume that points to it (by
    97  			// name), even though a smaller one is available.
    98  			name: "1-5 - prebound volume by name - success",
    99  			initialVolumes: []*v1.PersistentVolume{
   100  				newVolume("volume1-5_1", "10Gi", "", "claim1-5", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   101  				newVolume("volume1-5_2", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   102  			},
   103  			expectedVolumes: []*v1.PersistentVolume{
   104  				newVolume("volume1-5_1", "10Gi", "uid1-5", "claim1-5", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty),
   105  				newVolume("volume1-5_2", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   106  			},
   107  			initialClaims:  newClaimArray("claim1-5", "uid1-5", "1Gi", "", v1.ClaimPending, nil),
   108  			expectedClaims: withExpectedCapacity("10Gi", newClaimArray("claim1-5", "uid1-5", "1Gi", "volume1-5_1", v1.ClaimBound, nil, volume.AnnBoundByController, volume.AnnBindCompleted)),
   109  			expectedEvents: noevents,
   110  			errors:         noerrors,
   111  			test:           testSyncClaim,
   112  		},
   113  		{
   114  			// syncClaim binds a claim only to volume that points to it (by
   115  			// UID), even though a smaller one is available.
   116  			name: "1-6 - prebound volume by UID - success",
   117  			initialVolumes: []*v1.PersistentVolume{
   118  				newVolume("volume1-6_1", "10Gi", "uid1-6", "claim1-6", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   119  				newVolume("volume1-6_2", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   120  			},
   121  			expectedVolumes: []*v1.PersistentVolume{
   122  				newVolume("volume1-6_1", "10Gi", "uid1-6", "claim1-6", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty),
   123  				newVolume("volume1-6_2", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   124  			},
   125  			initialClaims:  newClaimArray("claim1-6", "uid1-6", "1Gi", "", v1.ClaimPending, nil),
   126  			expectedClaims: withExpectedCapacity("10Gi", newClaimArray("claim1-6", "uid1-6", "1Gi", "volume1-6_1", v1.ClaimBound, nil, volume.AnnBoundByController, volume.AnnBindCompleted)),
   127  			expectedEvents: noevents,
   128  			errors:         noerrors,
   129  			test:           testSyncClaim,
   130  		},
   131  		{
   132  			// syncClaim does not bind claim to a volume prebound to a claim with
   133  			// same name and different UID
   134  			name:            "1-7 - prebound volume to different claim",
   135  			initialVolumes:  newVolumeArray("volume1-7", "10Gi", "uid1-777", "claim1-7", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   136  			expectedVolumes: newVolumeArray("volume1-7", "10Gi", "uid1-777", "claim1-7", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   137  			initialClaims:   newClaimArray("claim1-7", "uid1-7", "1Gi", "", v1.ClaimPending, nil),
   138  			expectedClaims:  newClaimArray("claim1-7", "uid1-7", "1Gi", "", v1.ClaimPending, nil),
   139  			expectedEvents:  []string{"Normal FailedBinding"},
   140  			errors:          noerrors,
   141  			test:            testSyncClaim,
   142  		},
   143  		{
   144  			// syncClaim completes binding - simulates controller crash after
   145  			// PV.ClaimRef is saved
   146  			name:            "1-8 - complete bind after crash - PV bound",
   147  			initialVolumes:  newVolumeArray("volume1-8", "1Gi", "uid1-8", "claim1-8", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController),
   148  			expectedVolumes: newVolumeArray("volume1-8", "1Gi", "uid1-8", "claim1-8", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController),
   149  			initialClaims:   newClaimArray("claim1-8", "uid1-8", "1Gi", "", v1.ClaimPending, nil),
   150  			expectedClaims:  newClaimArray("claim1-8", "uid1-8", "1Gi", "volume1-8", v1.ClaimBound, nil, volume.AnnBoundByController, volume.AnnBindCompleted),
   151  			expectedEvents:  noevents,
   152  			errors:          noerrors,
   153  			test:            testSyncClaim,
   154  		},
   155  		{
   156  			// syncClaim completes binding - simulates controller crash after
   157  			// PV.Status is saved
   158  			name:            "1-9 - complete bind after crash - PV status saved",
   159  			initialVolumes:  newVolumeArray("volume1-9", "1Gi", "uid1-9", "claim1-9", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController),
   160  			expectedVolumes: newVolumeArray("volume1-9", "1Gi", "uid1-9", "claim1-9", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController),
   161  			initialClaims:   newClaimArray("claim1-9", "uid1-9", "1Gi", "", v1.ClaimPending, nil),
   162  			expectedClaims:  newClaimArray("claim1-9", "uid1-9", "1Gi", "volume1-9", v1.ClaimBound, nil, volume.AnnBoundByController, volume.AnnBindCompleted),
   163  			expectedEvents:  noevents,
   164  			errors:          noerrors,
   165  			test:            testSyncClaim,
   166  		},
   167  		{
   168  			// syncClaim completes binding - simulates controller crash after
   169  			// PVC.VolumeName is saved
   170  			name:            "1-10 - complete bind after crash - PVC bound",
   171  			initialVolumes:  newVolumeArray("volume1-10", "1Gi", "uid1-10", "claim1-10", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController),
   172  			expectedVolumes: newVolumeArray("volume1-10", "1Gi", "uid1-10", "claim1-10", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController),
   173  			initialClaims:   newClaimArray("claim1-10", "uid1-10", "1Gi", "volume1-10", v1.ClaimPending, nil, volume.AnnBoundByController, volume.AnnBindCompleted),
   174  			expectedClaims:  newClaimArray("claim1-10", "uid1-10", "1Gi", "volume1-10", v1.ClaimBound, nil, volume.AnnBoundByController, volume.AnnBindCompleted),
   175  			expectedEvents:  noevents,
   176  			errors:          noerrors,
   177  			test:            testSyncClaim,
   178  		},
   179  		{
   180  			// syncClaim binds a claim only when the label selector matches the volume
   181  			name:            "1-11 - bind when selector matches",
   182  			initialVolumes:  withLabels(labels, newVolumeArray("volume1-1", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
   183  			expectedVolumes: withLabels(labels, newVolumeArray("volume1-1", "1Gi", "uid1-1", "claim1-1", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController)),
   184  			initialClaims:   withLabelSelector(labels, newClaimArray("claim1-1", "uid1-1", "1Gi", "", v1.ClaimPending, nil)),
   185  			expectedClaims:  withLabelSelector(labels, newClaimArray("claim1-1", "uid1-1", "1Gi", "volume1-1", v1.ClaimBound, nil, volume.AnnBoundByController, volume.AnnBindCompleted)),
   186  			expectedEvents:  noevents,
   187  			errors:          noerrors,
   188  			test:            testSyncClaim,
   189  		},
   190  		{
   191  			// syncClaim does not bind a claim when the label selector doesn't match
   192  			name:            "1-12 - do not bind when selector does not match",
   193  			initialVolumes:  newVolumeArray("volume1-1", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   194  			expectedVolumes: newVolumeArray("volume1-1", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   195  			initialClaims:   withLabelSelector(labels, newClaimArray("claim1-1", "uid1-1", "1Gi", "", v1.ClaimPending, nil)),
   196  			expectedClaims:  withLabelSelector(labels, newClaimArray("claim1-1", "uid1-1", "1Gi", "", v1.ClaimPending, nil)),
   197  			expectedEvents:  []string{"Normal FailedBinding"},
   198  			errors:          noerrors,
   199  			test:            testSyncClaim,
   200  		},
   201  		{
   202  			// syncClaim does not do anything when binding is delayed
   203  			name:            "1-13 - delayed binding",
   204  			initialVolumes:  newVolumeArray("volume1-1", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classWait),
   205  			expectedVolumes: newVolumeArray("volume1-1", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classWait),
   206  			initialClaims:   newClaimArray("claim1-1", "uid1-1", "1Gi", "", v1.ClaimPending, &classWait),
   207  			expectedClaims:  newClaimArray("claim1-1", "uid1-1", "1Gi", "", v1.ClaimPending, &classWait),
   208  			expectedEvents:  []string{"Normal WaitForFirstConsumer"},
   209  			errors:          noerrors,
   210  			test:            testSyncClaim,
   211  		},
   212  		{
   213  			// syncClaim binds when binding is delayed but PV is prebound to PVC
   214  			name:            "1-14 - successful prebound PV",
   215  			initialVolumes:  newVolumeArray("volume1-1", "1Gi", "", "claim1-1", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classWait),
   216  			expectedVolumes: newVolumeArray("volume1-1", "1Gi", "uid1-1", "claim1-1", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classWait),
   217  			initialClaims:   newClaimArray("claim1-1", "uid1-1", "1Gi", "", v1.ClaimPending, &classWait),
   218  			expectedClaims:  newClaimArray("claim1-1", "uid1-1", "1Gi", "volume1-1", v1.ClaimBound, &classWait, volume.AnnBoundByController, volume.AnnBindCompleted),
   219  			expectedEvents:  noevents,
   220  			errors:          noerrors,
   221  			test:            testSyncClaim,
   222  		},
   223  		{
   224  			// syncClaim binds pre-bound PVC only to the volume it points to,
   225  			// even if there is smaller volume available
   226  			name: "1-15 - successful prebound PVC",
   227  			initialVolumes: []*v1.PersistentVolume{
   228  				newVolume("volume1-15_1", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   229  				newVolume("volume1-15_2", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   230  			},
   231  			expectedVolumes: []*v1.PersistentVolume{
   232  				newVolume("volume1-15_1", "10Gi", "uid1-15", "claim1-15", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController),
   233  				newVolume("volume1-15_2", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   234  			},
   235  			initialClaims:  newClaimArray("claim1-15", "uid1-15", "1Gi", "volume1-15_1", v1.ClaimPending, nil),
   236  			expectedClaims: withExpectedCapacity("10Gi", newClaimArray("claim1-15", "uid1-15", "1Gi", "volume1-15_1", v1.ClaimBound, nil, volume.AnnBindCompleted)),
   237  			expectedEvents: noevents,
   238  			errors:         noerrors,
   239  			test:           testSyncClaim,
   240  		},
   241  		{
   242  			// syncClaim does not bind pre-bound PVC to PV with different AccessMode
   243  			name: "1-16 - successful prebound PVC",
   244  			// PV has ReadWriteOnce
   245  			initialVolumes:  newVolumeArray("volume1-16", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   246  			expectedVolumes: newVolumeArray("volume1-16", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   247  			initialClaims:   claimWithAccessMode([]v1.PersistentVolumeAccessMode{v1.ReadWriteMany}, newClaimArray("claim1-16", "uid1-16", "1Gi", "volume1-16", v1.ClaimPending, nil)),
   248  			expectedClaims:  claimWithAccessMode([]v1.PersistentVolumeAccessMode{v1.ReadWriteMany}, newClaimArray("claim1-16", "uid1-16", "1Gi", "volume1-16", v1.ClaimPending, nil)),
   249  			expectedEvents:  noevents,
   250  			errors:          noerrors,
   251  			test:            testSyncClaim,
   252  		},
   253  		{
   254  			// syncClaim does not bind PVC to non-available PV if it's not pre-bind
   255  			name: "1-17 - skip non-available PV if it's not pre-bind",
   256  			initialVolumes: []*v1.PersistentVolume{
   257  				newVolume("volume1-17-pending", "1Gi", "", "", v1.VolumePending, v1.PersistentVolumeReclaimRetain, classEmpty),
   258  				newVolume("volume1-17-failed", "1Gi", "", "", v1.VolumeFailed, v1.PersistentVolumeReclaimRetain, classEmpty),
   259  				newVolume("volume1-17-released", "1Gi", "", "", v1.VolumeReleased, v1.PersistentVolumeReclaimRetain, classEmpty),
   260  				newVolume("volume1-17-empty", "1Gi", "", "", "", v1.PersistentVolumeReclaimRetain, classEmpty),
   261  			},
   262  			expectedVolumes: []*v1.PersistentVolume{
   263  				newVolume("volume1-17-pending", "1Gi", "", "", v1.VolumePending, v1.PersistentVolumeReclaimRetain, classEmpty),
   264  				newVolume("volume1-17-failed", "1Gi", "", "", v1.VolumeFailed, v1.PersistentVolumeReclaimRetain, classEmpty),
   265  				newVolume("volume1-17-released", "1Gi", "", "", v1.VolumeReleased, v1.PersistentVolumeReclaimRetain, classEmpty),
   266  				newVolume("volume1-17-empty", "1Gi", "", "", "", v1.PersistentVolumeReclaimRetain, classEmpty),
   267  			},
   268  			initialClaims: []*v1.PersistentVolumeClaim{
   269  				newClaim("claim1-17", "uid1-17", "1Gi", "", v1.ClaimPending, nil),
   270  			},
   271  			expectedClaims: []*v1.PersistentVolumeClaim{
   272  				newClaim("claim1-17", "uid1-17", "1Gi", "", v1.ClaimPending, nil),
   273  			},
   274  			expectedEvents: noevents,
   275  			errors:         noerrors,
   276  			test:           testSyncClaim,
   277  		},
   278  		{
   279  			// syncClaim that scheduled to a selected node
   280  			name:            "1-18 - successful pre-bound PV to PVC provisioning",
   281  			initialVolumes:  newVolumeArray("volume1-18", "1Gi", "uid1-18", "claim1-18", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classWait),
   282  			expectedVolumes: newVolumeArray("volume1-18", "1Gi", "uid1-18", "claim1-18", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classWait),
   283  			initialClaims: claimWithAnnotation(volume.AnnSelectedNode, "node1",
   284  				newClaimArray("claim1-18", "uid1-18", "1Gi", "", v1.ClaimPending, &classWait)),
   285  			expectedClaims: claimWithAnnotation(volume.AnnSelectedNode, "node1",
   286  				newClaimArray("claim1-18", "uid1-18", "1Gi", "volume1-18", v1.ClaimBound, &classWait, volume.AnnBoundByController, volume.AnnBindCompleted)),
   287  			expectedEvents: noevents,
   288  			errors:         noerrors,
   289  			test:           testSyncClaim,
   290  		},
   291  
   292  		// [Unit test set 2] User asked for a specific PV.
   293  		// Test the binding when pv.ClaimRef is already set by controller or
   294  		// by user.
   295  		{
   296  			// syncClaim with claim pre-bound to a PV that does not exist
   297  			name:            "2-1 - claim prebound to non-existing volume - noop",
   298  			initialVolumes:  novolumes,
   299  			expectedVolumes: novolumes,
   300  			initialClaims:   newClaimArray("claim2-1", "uid2-1", "10Gi", "volume2-1", v1.ClaimPending, nil),
   301  			expectedClaims:  newClaimArray("claim2-1", "uid2-1", "10Gi", "volume2-1", v1.ClaimPending, nil),
   302  			expectedEvents:  noevents,
   303  			errors:          noerrors,
   304  			test:            testSyncClaim,
   305  		},
   306  		{
   307  			// syncClaim with claim pre-bound to a PV that does not exist.
   308  			// Check that the claim status is reset to Pending
   309  			name:            "2-2 - claim prebound to non-existing volume - reset status",
   310  			initialVolumes:  novolumes,
   311  			expectedVolumes: novolumes,
   312  			initialClaims:   newClaimArray("claim2-2", "uid2-2", "10Gi", "volume2-2", v1.ClaimBound, nil),
   313  			expectedClaims:  newClaimArray("claim2-2", "uid2-2", "10Gi", "volume2-2", v1.ClaimPending, nil),
   314  			expectedEvents:  noevents,
   315  			errors:          noerrors,
   316  			test:            testSyncClaim,
   317  		},
   318  		{
   319  			// syncClaim with claim pre-bound to a PV that exists and is
   320  			// unbound. Check it gets bound and no volume.AnnBoundByController is set.
   321  			name:            "2-3 - claim prebound to unbound volume",
   322  			initialVolumes:  newVolumeArray("volume2-3", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   323  			expectedVolumes: newVolumeArray("volume2-3", "1Gi", "uid2-3", "claim2-3", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController),
   324  			initialClaims:   newClaimArray("claim2-3", "uid2-3", "1Gi", "volume2-3", v1.ClaimPending, nil),
   325  			expectedClaims:  newClaimArray("claim2-3", "uid2-3", "1Gi", "volume2-3", v1.ClaimBound, nil, volume.AnnBindCompleted),
   326  			expectedEvents:  noevents,
   327  			errors:          noerrors,
   328  			test:            testSyncClaim,
   329  		},
   330  		{
   331  			// claim with claim pre-bound to a PV that is pre-bound to the claim
   332  			// by name. Check it gets bound and no volume.AnnBoundByController is set.
   333  			name:            "2-4 - claim prebound to prebound volume by name",
   334  			initialVolumes:  newVolumeArray("volume2-4", "1Gi", "", "claim2-4", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   335  			expectedVolumes: newVolumeArray("volume2-4", "1Gi", "uid2-4", "claim2-4", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty),
   336  			initialClaims:   newClaimArray("claim2-4", "uid2-4", "1Gi", "volume2-4", v1.ClaimPending, nil),
   337  			expectedClaims:  newClaimArray("claim2-4", "uid2-4", "1Gi", "volume2-4", v1.ClaimBound, nil, volume.AnnBindCompleted),
   338  			expectedEvents:  noevents,
   339  			errors:          noerrors,
   340  			test:            testSyncClaim,
   341  		},
   342  		{
   343  			// syncClaim with claim pre-bound to a PV that is pre-bound to the
   344  			// claim by UID. Check it gets bound and no volume.AnnBoundByController is
   345  			// set.
   346  			name:            "2-5 - claim prebound to prebound volume by UID",
   347  			initialVolumes:  newVolumeArray("volume2-5", "1Gi", "uid2-5", "claim2-5", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   348  			expectedVolumes: newVolumeArray("volume2-5", "1Gi", "uid2-5", "claim2-5", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty),
   349  			initialClaims:   newClaimArray("claim2-5", "uid2-5", "1Gi", "volume2-5", v1.ClaimPending, nil),
   350  			expectedClaims:  newClaimArray("claim2-5", "uid2-5", "1Gi", "volume2-5", v1.ClaimBound, nil, volume.AnnBindCompleted),
   351  			expectedEvents:  noevents,
   352  			errors:          noerrors,
   353  			test:            testSyncClaim,
   354  		},
   355  		{
   356  			// syncClaim with claim pre-bound to a PV that is bound to different
   357  			// claim. Check it's reset to Pending.
   358  			name:            "2-6 - claim prebound to already bound volume",
   359  			initialVolumes:  newVolumeArray("volume2-6", "1Gi", "uid2-6_1", "claim2-6_1", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty),
   360  			expectedVolumes: newVolumeArray("volume2-6", "1Gi", "uid2-6_1", "claim2-6_1", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty),
   361  			initialClaims:   newClaimArray("claim2-6", "uid2-6", "1Gi", "volume2-6", v1.ClaimBound, nil),
   362  			expectedClaims:  newClaimArray("claim2-6", "uid2-6", "1Gi", "volume2-6", v1.ClaimPending, nil),
   363  			expectedEvents:  noevents,
   364  			errors:          noerrors,
   365  			test:            testSyncClaim,
   366  		},
   367  		{
   368  			// syncClaim with claim bound by controller to a PV that is bound to
   369  			// different claim. Check it throws an error.
   370  			name:            "2-7 - claim bound by controller to already bound volume",
   371  			initialVolumes:  newVolumeArray("volume2-7", "1Gi", "uid2-7_1", "claim2-7_1", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty),
   372  			expectedVolumes: newVolumeArray("volume2-7", "1Gi", "uid2-7_1", "claim2-7_1", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty),
   373  			initialClaims:   newClaimArray("claim2-7", "uid2-7", "1Gi", "volume2-7", v1.ClaimBound, nil, volume.AnnBoundByController),
   374  			expectedClaims:  newClaimArray("claim2-7", "uid2-7", "1Gi", "volume2-7", v1.ClaimBound, nil, volume.AnnBoundByController),
   375  			expectedEvents:  noevents,
   376  			errors:          noerrors,
   377  			test:            testSyncClaimError,
   378  		},
   379  		{
   380  			// syncClaim with claim pre-bound to a PV that exists and is
   381  			// unbound, but does not match the selector. Check it gets bound
   382  			// and no volume.AnnBoundByController is set.
   383  			name:            "2-8 - claim prebound to unbound volume that does not match the selector",
   384  			initialVolumes:  newVolumeArray("volume2-8", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   385  			expectedVolumes: newVolumeArray("volume2-8", "1Gi", "uid2-8", "claim2-8", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController),
   386  			initialClaims:   withLabelSelector(labels, newClaimArray("claim2-8", "uid2-8", "1Gi", "volume2-8", v1.ClaimPending, nil)),
   387  			expectedClaims:  withLabelSelector(labels, newClaimArray("claim2-8", "uid2-8", "1Gi", "volume2-8", v1.ClaimBound, nil, volume.AnnBindCompleted)),
   388  			expectedEvents:  noevents,
   389  			errors:          noerrors,
   390  			test:            testSyncClaim,
   391  		},
   392  		{
   393  			// syncClaim with claim pre-bound to a PV that exists and is
   394  			// unbound, but its size is smaller than requested.
   395  			//Check that the claim status is reset to Pending
   396  			name:            "2-9 - claim prebound to unbound volume that size is smaller than requested",
   397  			initialVolumes:  newVolumeArray("volume2-9", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   398  			expectedVolumes: newVolumeArray("volume2-9", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   399  			initialClaims:   newClaimArray("claim2-9", "uid2-9", "2Gi", "volume2-9", v1.ClaimBound, nil),
   400  			expectedClaims:  newClaimArray("claim2-9", "uid2-9", "2Gi", "volume2-9", v1.ClaimPending, nil),
   401  			expectedEvents:  []string{"Warning VolumeMismatch"},
   402  			errors:          noerrors,
   403  			test:            testSyncClaim,
   404  		},
   405  		{
   406  			// syncClaim with claim pre-bound to a PV that exists and is
   407  			// unbound, but its class does not match. Check that the claim status is reset to Pending
   408  			name:            "2-10 - claim prebound to unbound volume that class is different",
   409  			initialVolumes:  newVolumeArray("volume2-10", "1Gi", "1", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classGold),
   410  			expectedVolumes: newVolumeArray("volume2-10", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classGold),
   411  			initialClaims:   newClaimArray("claim2-10", "uid2-10", "1Gi", "volume2-10", v1.ClaimBound, nil),
   412  			expectedClaims:  newClaimArray("claim2-10", "uid2-10", "1Gi", "volume2-10", v1.ClaimPending, nil),
   413  			expectedEvents:  []string{"Warning VolumeMismatch"},
   414  			errors:          noerrors,
   415  			test:            testSyncClaim,
   416  		},
   417  
   418  		// [Unit test set 3] Syncing bound claim
   419  		{
   420  			// syncClaim with claim  bound and its claim.Spec.VolumeName is
   421  			// removed. Check it's marked as Lost.
   422  			name:            "3-1 - bound claim with missing VolumeName",
   423  			initialVolumes:  novolumes,
   424  			expectedVolumes: novolumes,
   425  			initialClaims:   newClaimArray("claim3-1", "uid3-1", "10Gi", "", v1.ClaimBound, nil, volume.AnnBoundByController, volume.AnnBindCompleted),
   426  			expectedClaims:  newClaimArray("claim3-1", "uid3-1", "10Gi", "", v1.ClaimLost, nil, volume.AnnBoundByController, volume.AnnBindCompleted),
   427  			expectedEvents:  []string{"Warning ClaimLost"},
   428  			errors:          noerrors,
   429  			test:            testSyncClaim,
   430  		},
   431  		{
   432  			// syncClaim with claim bound to non-existing volume. Check it's
   433  			// marked as Lost.
   434  			name:            "3-2 - bound claim with missing volume",
   435  			initialVolumes:  novolumes,
   436  			expectedVolumes: novolumes,
   437  			initialClaims:   newClaimArray("claim3-2", "uid3-2", "10Gi", "volume3-2", v1.ClaimBound, nil, volume.AnnBoundByController, volume.AnnBindCompleted),
   438  			expectedClaims:  newClaimArray("claim3-2", "uid3-2", "10Gi", "volume3-2", v1.ClaimLost, nil, volume.AnnBoundByController, volume.AnnBindCompleted),
   439  			expectedEvents:  []string{"Warning ClaimLost"},
   440  			errors:          noerrors,
   441  			test:            testSyncClaim,
   442  		},
   443  		{
   444  			// syncClaim with claim bound to unbound volume. Check it's bound.
   445  			// Also check that Pending phase is set to Bound
   446  			name:            "3-3 - bound claim with unbound volume",
   447  			initialVolumes:  newVolumeArray("volume3-3", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   448  			expectedVolumes: newVolumeArray("volume3-3", "10Gi", "uid3-3", "claim3-3", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController),
   449  			initialClaims:   newClaimArray("claim3-3", "uid3-3", "10Gi", "volume3-3", v1.ClaimPending, nil, volume.AnnBoundByController, volume.AnnBindCompleted),
   450  			expectedClaims:  newClaimArray("claim3-3", "uid3-3", "10Gi", "volume3-3", v1.ClaimBound, nil, volume.AnnBoundByController, volume.AnnBindCompleted),
   451  			expectedEvents:  noevents,
   452  			errors:          noerrors,
   453  			test:            testSyncClaim,
   454  		},
   455  		{
   456  			// syncClaim with claim bound to volume with missing (or different)
   457  			// volume.Spec.ClaimRef.UID. Check that the claim is marked as lost.
   458  			name:            "3-4 - bound claim with prebound volume",
   459  			initialVolumes:  newVolumeArray("volume3-4", "10Gi", "claim3-4-x", "claim3-4", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   460  			expectedVolumes: newVolumeArray("volume3-4", "10Gi", "claim3-4-x", "claim3-4", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   461  			initialClaims:   newClaimArray("claim3-4", "uid3-4", "10Gi", "volume3-4", v1.ClaimPending, nil, volume.AnnBoundByController, volume.AnnBindCompleted),
   462  			expectedClaims:  newClaimArray("claim3-4", "uid3-4", "10Gi", "volume3-4", v1.ClaimLost, nil, volume.AnnBoundByController, volume.AnnBindCompleted),
   463  			expectedEvents:  []string{"Warning ClaimMisbound"},
   464  			errors:          noerrors,
   465  			test:            testSyncClaim,
   466  		},
   467  		{
   468  			// syncClaim with claim bound to bound volume. Check that the
   469  			// controller does not do anything. Also check that Pending phase is
   470  			// set to Bound
   471  			name:            "3-5 - bound claim with bound volume",
   472  			initialVolumes:  newVolumeArray("volume3-5", "10Gi", "uid3-5", "claim3-5", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   473  			expectedVolumes: newVolumeArray("volume3-5", "10Gi", "uid3-5", "claim3-5", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty),
   474  			initialClaims:   newClaimArray("claim3-5", "uid3-5", "10Gi", "volume3-5", v1.ClaimPending, nil, volume.AnnBindCompleted),
   475  			expectedClaims:  newClaimArray("claim3-5", "uid3-5", "10Gi", "volume3-5", v1.ClaimBound, nil, volume.AnnBindCompleted),
   476  			expectedEvents:  noevents,
   477  			errors:          noerrors,
   478  			test:            testSyncClaim,
   479  		},
   480  		{
   481  			// syncClaim with claim bound to a volume that is bound to different
   482  			// claim. Check that the claim is marked as lost.
   483  			// TODO: test that an event is emitted
   484  			name:            "3-6 - bound claim with bound volume",
   485  			initialVolumes:  newVolumeArray("volume3-6", "10Gi", "uid3-6-x", "claim3-6-x", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   486  			expectedVolumes: newVolumeArray("volume3-6", "10Gi", "uid3-6-x", "claim3-6-x", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   487  			initialClaims:   newClaimArray("claim3-6", "uid3-6", "10Gi", "volume3-6", v1.ClaimPending, nil, volume.AnnBindCompleted),
   488  			expectedClaims:  newClaimArray("claim3-6", "uid3-6", "10Gi", "volume3-6", v1.ClaimLost, nil, volume.AnnBindCompleted),
   489  			expectedEvents:  []string{"Warning ClaimMisbound"},
   490  			errors:          noerrors,
   491  			test:            testSyncClaim,
   492  		},
   493  		{
   494  			// syncClaim with claim bound to unbound volume. Check it's bound
   495  			// even if the claim's selector doesn't match the volume. Also
   496  			// check that Pending phase is set to Bound
   497  			name:            "3-7 - bound claim with unbound volume where selector doesn't match",
   498  			initialVolumes:  newVolumeArray("volume3-3", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   499  			expectedVolumes: newVolumeArray("volume3-3", "10Gi", "uid3-3", "claim3-3", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController),
   500  			initialClaims:   withLabelSelector(labels, newClaimArray("claim3-3", "uid3-3", "10Gi", "volume3-3", v1.ClaimPending, nil, volume.AnnBoundByController, volume.AnnBindCompleted)),
   501  			expectedClaims:  withLabelSelector(labels, newClaimArray("claim3-3", "uid3-3", "10Gi", "volume3-3", v1.ClaimBound, nil, volume.AnnBoundByController, volume.AnnBindCompleted)),
   502  			expectedEvents:  noevents,
   503  			errors:          noerrors,
   504  			test:            testSyncClaim,
   505  		},
   506  		// [Unit test set 4] All syncVolume tests.
   507  		{
   508  			// syncVolume with pending volume. Check it's marked as Available.
   509  			name:            "4-1 - pending volume",
   510  			initialVolumes:  newVolumeArray("volume4-1", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   511  			expectedVolumes: newVolumeArray("volume4-1", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   512  			initialClaims:   noclaims,
   513  			expectedClaims:  noclaims,
   514  			expectedEvents:  noevents,
   515  			errors:          noerrors,
   516  			test:            testSyncVolume,
   517  		},
   518  		{
   519  			// syncVolume with prebound pending volume. Check it's marked as
   520  			// Available.
   521  			name:            "4-2 - pending prebound volume",
   522  			initialVolumes:  newVolumeArray("volume4-2", "10Gi", "", "claim4-2", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   523  			expectedVolumes: newVolumeArray("volume4-2", "10Gi", "", "claim4-2", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   524  			initialClaims:   noclaims,
   525  			expectedClaims:  noclaims,
   526  			expectedEvents:  noevents,
   527  			errors:          noerrors,
   528  			test:            testSyncVolume,
   529  		},
   530  		{
   531  			// syncVolume with volume bound to missing claim.
   532  			// Check the volume gets Released
   533  			name:            "4-3 - bound volume with missing claim",
   534  			initialVolumes:  newVolumeArray("volume4-3", "10Gi", "uid4-3", "claim4-3", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty),
   535  			expectedVolumes: newVolumeArray("volume4-3", "10Gi", "uid4-3", "claim4-3", v1.VolumeReleased, v1.PersistentVolumeReclaimRetain, classEmpty),
   536  			initialClaims:   noclaims,
   537  			expectedClaims:  noclaims,
   538  			expectedEvents:  noevents,
   539  			errors:          noerrors,
   540  			test:            testSyncVolume,
   541  		},
   542  		{
   543  			// syncVolume with volume bound to claim with different UID.
   544  			// Check the volume gets Released.
   545  			name:            "4-4 - volume bound to claim with different UID",
   546  			initialVolumes:  newVolumeArray("volume4-4", "10Gi", "uid4-4", "claim4-4", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty),
   547  			expectedVolumes: newVolumeArray("volume4-4", "10Gi", "uid4-4", "claim4-4", v1.VolumeReleased, v1.PersistentVolumeReclaimRetain, classEmpty),
   548  			initialClaims:   newClaimArray("claim4-4", "uid4-4-x", "10Gi", "volume4-4", v1.ClaimBound, nil, volume.AnnBindCompleted),
   549  			expectedClaims:  newClaimArray("claim4-4", "uid4-4-x", "10Gi", "volume4-4", v1.ClaimBound, nil, volume.AnnBindCompleted),
   550  			expectedEvents:  noevents,
   551  			errors:          noerrors,
   552  			test:            testSyncVolume,
   553  		},
   554  		{
   555  			// syncVolume with volume bound by controller to unbound claim.
   556  			// Check syncVolume does not do anything.
   557  			name:            "4-5 - volume bound by controller to unbound claim",
   558  			initialVolumes:  newVolumeArray("volume4-5", "10Gi", "uid4-5", "claim4-5", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController),
   559  			expectedVolumes: newVolumeArray("volume4-5", "10Gi", "uid4-5", "claim4-5", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController),
   560  			initialClaims:   newClaimArray("claim4-5", "uid4-5", "10Gi", "", v1.ClaimPending, nil),
   561  			expectedClaims:  newClaimArray("claim4-5", "uid4-5", "10Gi", "", v1.ClaimPending, nil),
   562  			expectedEvents:  noevents,
   563  			errors:          noerrors,
   564  			test:            testSyncVolume,
   565  		},
   566  		{
   567  			// syncVolume with volume bound by user to unbound claim.
   568  			// Check syncVolume does not do anything.
   569  			name:            "4-5 - volume bound by user to bound claim",
   570  			initialVolumes:  newVolumeArray("volume4-5", "10Gi", "uid4-5", "claim4-5", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty),
   571  			expectedVolumes: newVolumeArray("volume4-5", "10Gi", "uid4-5", "claim4-5", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty),
   572  			initialClaims:   newClaimArray("claim4-5", "uid4-5", "10Gi", "", v1.ClaimPending, nil),
   573  			expectedClaims:  newClaimArray("claim4-5", "uid4-5", "10Gi", "", v1.ClaimPending, nil),
   574  			expectedEvents:  noevents,
   575  			errors:          noerrors,
   576  			test:            testSyncVolume,
   577  		},
   578  		{
   579  			// syncVolume with volume bound to bound claim.
   580  			// Check that the volume is marked as Bound.
   581  			name:            "4-6 - volume bound by to bound claim",
   582  			initialVolumes:  newVolumeArray("volume4-6", "10Gi", "uid4-6", "claim4-6", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   583  			expectedVolumes: newVolumeArray("volume4-6", "10Gi", "uid4-6", "claim4-6", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty),
   584  			initialClaims:   newClaimArray("claim4-6", "uid4-6", "10Gi", "volume4-6", v1.ClaimBound, nil),
   585  			expectedClaims:  newClaimArray("claim4-6", "uid4-6", "10Gi", "volume4-6", v1.ClaimBound, nil),
   586  			expectedEvents:  noevents,
   587  			errors:          noerrors,
   588  			test:            testSyncVolume,
   589  		},
   590  		{
   591  			// syncVolume with volume bound by controller to claim bound to
   592  			// another volume. Check that the volume is rolled back.
   593  			name:            "4-7 - volume bound by controller to claim bound somewhere else",
   594  			initialVolumes:  newVolumeArray("volume4-7", "10Gi", "uid4-7", "claim4-7", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController),
   595  			expectedVolumes: newVolumeArray("volume4-7", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   596  			initialClaims:   newClaimArray("claim4-7", "uid4-7", "10Gi", "volume4-7-x", v1.ClaimBound, nil),
   597  			expectedClaims:  newClaimArray("claim4-7", "uid4-7", "10Gi", "volume4-7-x", v1.ClaimBound, nil),
   598  			expectedEvents:  noevents,
   599  			errors:          noerrors,
   600  			test:            testSyncVolume,
   601  		},
   602  		{
   603  			// syncVolume with volume bound by user to claim bound to
   604  			// another volume. Check that the volume is marked as Available
   605  			// and its UID is reset.
   606  			name:            "4-8 - volume bound by user to claim bound somewhere else",
   607  			initialVolumes:  newVolumeArray("volume4-8", "10Gi", "uid4-8", "claim4-8", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty),
   608  			expectedVolumes: newVolumeArray("volume4-8", "10Gi", "", "claim4-8", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   609  			initialClaims:   newClaimArray("claim4-8", "uid4-8", "10Gi", "volume4-8-x", v1.ClaimBound, nil),
   610  			expectedClaims:  newClaimArray("claim4-8", "uid4-8", "10Gi", "volume4-8-x", v1.ClaimBound, nil),
   611  			expectedEvents:  noevents,
   612  			errors:          noerrors,
   613  			test:            testSyncVolume,
   614  		},
   615  		{
   616  			// syncVolume with volume bound to bound claim.
   617  			// Check that the volume is not deleted.
   618  			name:            "4-9 - volume bound to bound claim, with PersistentVolumeReclaimDelete",
   619  			initialVolumes:  newVolumeArray("volume4-9", "10Gi", "uid4-9", "claim4-9", v1.VolumeAvailable, v1.PersistentVolumeReclaimDelete, classEmpty),
   620  			expectedVolumes: newVolumeArray("volume4-9", "10Gi", "uid4-9", "claim4-9", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
   621  			initialClaims:   newClaimArray("claim4-9", "uid4-9", "10Gi", "volume4-9", v1.ClaimBound, nil),
   622  			expectedClaims:  newClaimArray("claim4-9", "uid4-9", "10Gi", "volume4-9", v1.ClaimBound, nil),
   623  			expectedEvents:  noevents,
   624  			errors:          noerrors,
   625  			test:            testSyncVolume,
   626  		},
   627  		{
   628  			// syncVolume with volume bound to missing claim.
   629  			// Check that a volume deletion is attempted. It fails because there is no deleter.
   630  			name:           "4-10 - volume bound to missing claim",
   631  			initialVolumes: newVolumeArray("volume4-10", "10Gi", "uid4-10", "claim4-10", v1.VolumeAvailable, v1.PersistentVolumeReclaimDelete, classEmpty),
   632  			expectedVolumes: func() []*v1.PersistentVolume {
   633  				volumes := newVolumeArray("volume4-10", "10Gi", "uid4-10", "claim4-10", v1.VolumeFailed, v1.PersistentVolumeReclaimDelete, classEmpty)
   634  				volumes[0].Status.Message = `error getting deleter volume plugin for volume "volume4-10": no volume plugin matched`
   635  				return volumes
   636  			}(),
   637  			initialClaims:  noclaims,
   638  			expectedClaims: noclaims,
   639  			expectedEvents: noevents,
   640  			errors:         noerrors,
   641  			test:           testSyncVolume,
   642  		},
   643  		{
   644  			// syncVolume with volume bound to claim which exists in etcd but not in the local cache.
   645  			// Check that nothing changes, in contrast to case 4-10 above.
   646  			name:            "4-11 - volume bound to unknown claim",
   647  			initialVolumes:  newVolumeArray("volume4-11", "10Gi", "uid4-11", "claim4-11", v1.VolumeAvailable, v1.PersistentVolumeReclaimDelete, classEmpty),
   648  			expectedVolumes: newVolumeArray("volume4-11", "10Gi", "uid4-11", "claim4-11", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
   649  			initialClaims:   newClaimArray("claim4-11", "uid4-11", "10Gi", "volume4-11", v1.ClaimBound, nil, annSkipLocalStore),
   650  			expectedClaims:  newClaimArray("claim4-11", "uid4-11", "10Gi", "volume4-11", v1.ClaimBound, nil, annSkipLocalStore),
   651  			expectedEvents:  noevents,
   652  			errors:          noerrors,
   653  			test:            testSyncVolume,
   654  		},
   655  
   656  		{
   657  			// syncVolume with volume bound to claim which exists in etcd but not updated to local cache.
   658  			name:            "4-12 - volume bound to newest claim but not updated to local cache",
   659  			initialVolumes:  newVolumeArray("volume4-12", "10Gi", "uid4-12-new", "claim4-12", v1.VolumeAvailable, v1.PersistentVolumeReclaimDelete, classEmpty),
   660  			expectedVolumes: newVolumeArray("volume4-12", "10Gi", "uid4-12-new", "claim4-12", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
   661  			initialClaims: func() []*v1.PersistentVolumeClaim {
   662  				newClaim := newClaimArray("claim4-12", "uid4-12", "10Gi", "volume4-12", v1.ClaimBound, nil, "")
   663  				// update uid to new-uid and not sync to cache.
   664  				newClaim = append(newClaim, newClaimArray("claim4-12", "uid4-12-new", "10Gi", "volume4-12", v1.ClaimBound, nil, annSkipLocalStore)...)
   665  				return newClaim
   666  			}(),
   667  			expectedClaims: newClaimArray("claim4-12", "uid4-12-new", "10Gi", "volume4-12", v1.ClaimBound, nil, annSkipLocalStore),
   668  			expectedEvents: noevents,
   669  			errors:         noerrors,
   670  			test:           testSyncVolume,
   671  		},
   672  
   673  		// PVC with class
   674  		{
   675  			// syncVolume binds a claim to requested class even if there is a
   676  			// smaller PV available
   677  			name: "13-1 - binding to class",
   678  			initialVolumes: []*v1.PersistentVolume{
   679  				newVolume("volume13-1-1", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   680  				newVolume("volume13-1-2", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classGold),
   681  			},
   682  			expectedVolumes: []*v1.PersistentVolume{
   683  				newVolume("volume13-1-1", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   684  				newVolume("volume13-1-2", "10Gi", "uid13-1", "claim13-1", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classGold, volume.AnnBoundByController),
   685  			},
   686  			initialClaims:  newClaimArray("claim13-1", "uid13-1", "1Gi", "", v1.ClaimPending, &classGold),
   687  			expectedClaims: withExpectedCapacity("10Gi", newClaimArray("claim13-1", "uid13-1", "1Gi", "volume13-1-2", v1.ClaimBound, &classGold, volume.AnnBoundByController, volume.AnnBindCompleted)),
   688  			expectedEvents: noevents,
   689  			errors:         noerrors,
   690  			test:           testSyncClaim,
   691  		},
   692  		{
   693  			// syncVolume binds a claim without a class even if there is a
   694  			// smaller PV with a class available
   695  			name: "13-2 - binding without a class",
   696  			initialVolumes: []*v1.PersistentVolume{
   697  				newVolume("volume13-2-1", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classGold),
   698  				newVolume("volume13-2-2", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   699  			},
   700  			expectedVolumes: []*v1.PersistentVolume{
   701  				newVolume("volume13-2-1", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classGold),
   702  				newVolume("volume13-2-2", "10Gi", "uid13-2", "claim13-2", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController),
   703  			},
   704  			initialClaims:  newClaimArray("claim13-2", "uid13-2", "1Gi", "", v1.ClaimPending, nil),
   705  			expectedClaims: withExpectedCapacity("10Gi", newClaimArray("claim13-2", "uid13-2", "1Gi", "volume13-2-2", v1.ClaimBound, nil, volume.AnnBoundByController, volume.AnnBindCompleted)),
   706  			expectedEvents: noevents,
   707  			errors:         noerrors,
   708  			test:           testSyncClaim,
   709  		},
   710  		{
   711  			// syncVolume binds a claim with given class even if there is a
   712  			// smaller PV with different class available
   713  			name: "13-3 - binding to specific a class",
   714  			initialVolumes: []*v1.PersistentVolume{
   715  				newVolume("volume13-3-1", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classSilver),
   716  				newVolume("volume13-3-2", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classGold),
   717  			},
   718  			expectedVolumes: []*v1.PersistentVolume{
   719  				newVolume("volume13-3-1", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classSilver),
   720  				newVolume("volume13-3-2", "10Gi", "uid13-3", "claim13-3", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classGold, volume.AnnBoundByController),
   721  			},
   722  			initialClaims:  newClaimArray("claim13-3", "uid13-3", "1Gi", "", v1.ClaimPending, &classGold),
   723  			expectedClaims: withExpectedCapacity("10Gi", newClaimArray("claim13-3", "uid13-3", "1Gi", "volume13-3-2", v1.ClaimBound, &classGold, volume.AnnBoundByController, volume.AnnBindCompleted)),
   724  			expectedEvents: noevents,
   725  			errors:         noerrors,
   726  			test:           testSyncClaim,
   727  		},
   728  		{
   729  			// syncVolume binds claim requesting class "" to claim to PV with
   730  			// class=""
   731  			name:            "13-4 - empty class",
   732  			initialVolumes:  newVolumeArray("volume13-4", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   733  			expectedVolumes: newVolumeArray("volume13-4", "1Gi", "uid13-4", "claim13-4", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController),
   734  			initialClaims:   newClaimArray("claim13-4", "uid13-4", "1Gi", "", v1.ClaimPending, &classEmpty),
   735  			expectedClaims:  newClaimArray("claim13-4", "uid13-4", "1Gi", "volume13-4", v1.ClaimBound, &classEmpty, volume.AnnBoundByController, volume.AnnBindCompleted),
   736  			expectedEvents:  noevents,
   737  			errors:          noerrors,
   738  			test:            testSyncClaim,
   739  		},
   740  		{
   741  			// syncVolume binds claim requesting class nil to claim to PV with
   742  			// class = ""
   743  			name:            "13-5 - nil class",
   744  			initialVolumes:  newVolumeArray("volume13-5", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
   745  			expectedVolumes: newVolumeArray("volume13-5", "1Gi", "uid13-5", "claim13-5", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController),
   746  			initialClaims:   newClaimArray("claim13-5", "uid13-5", "1Gi", "", v1.ClaimPending, nil),
   747  			expectedClaims:  newClaimArray("claim13-5", "uid13-5", "1Gi", "volume13-5", v1.ClaimBound, nil, volume.AnnBoundByController, volume.AnnBindCompleted),
   748  			expectedEvents:  noevents,
   749  			errors:          noerrors,
   750  			test:            testSyncClaim,
   751  		},
   752  	}
   753  	_, ctx := ktesting.NewTestContext(t)
   754  	runSyncTests(t, ctx, tests, []*storage.StorageClass{
   755  		{
   756  			ObjectMeta:        metav1.ObjectMeta{Name: classWait},
   757  			VolumeBindingMode: &modeWait,
   758  		},
   759  	}, []*v1.Pod{})
   760  }
   761  
   762  func TestSyncBlockVolume(t *testing.T) {
   763  	modeBlock := v1.PersistentVolumeBlock
   764  	modeFile := v1.PersistentVolumeFilesystem
   765  
   766  	// Tests assume defaulting, so feature enabled will never have nil volumeMode
   767  	tests := []controllerTest{
   768  		// PVC with VolumeMode
   769  		{
   770  			// syncVolume binds a requested block claim to a block volume
   771  			name:            "14-1 - binding to volumeMode block",
   772  			initialVolumes:  withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-1", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
   773  			expectedVolumes: withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-1", "10Gi", "uid14-1", "claim14-1", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController)),
   774  			initialClaims:   withClaimVolumeMode(&modeBlock, newClaimArray("claim14-1", "uid14-1", "10Gi", "", v1.ClaimPending, nil)),
   775  			expectedClaims:  withClaimVolumeMode(&modeBlock, newClaimArray("claim14-1", "uid14-1", "10Gi", "volume14-1", v1.ClaimBound, nil, volume.AnnBoundByController, volume.AnnBindCompleted)),
   776  			expectedEvents:  noevents,
   777  			errors:          noerrors,
   778  			test:            testSyncClaim,
   779  		},
   780  		{
   781  			// syncVolume binds a requested filesystem claim to a filesystem volume
   782  			name:            "14-2 - binding to volumeMode filesystem",
   783  			initialVolumes:  withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-2", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
   784  			expectedVolumes: withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-2", "10Gi", "uid14-2", "claim14-2", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController)),
   785  			initialClaims:   withClaimVolumeMode(&modeFile, newClaimArray("claim14-2", "uid14-2", "10Gi", "", v1.ClaimPending, nil)),
   786  			expectedClaims:  withClaimVolumeMode(&modeFile, newClaimArray("claim14-2", "uid14-2", "10Gi", "volume14-2", v1.ClaimBound, nil, volume.AnnBoundByController, volume.AnnBindCompleted)),
   787  			expectedEvents:  noevents,
   788  			errors:          noerrors,
   789  			test:            testSyncClaim,
   790  		},
   791  		{
   792  			// failed syncVolume do not bind to an unspecified volumemode for claim to a specified filesystem volume
   793  			name:            "14-3 - do not bind pv volumeMode filesystem and pvc volumeMode block",
   794  			initialVolumes:  withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-3", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
   795  			expectedVolumes: withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-3", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
   796  			initialClaims:   withClaimVolumeMode(&modeBlock, newClaimArray("claim14-3", "uid14-3", "10Gi", "", v1.ClaimPending, nil)),
   797  			expectedClaims:  withClaimVolumeMode(&modeBlock, newClaimArray("claim14-3", "uid14-3", "10Gi", "", v1.ClaimPending, nil)),
   798  			expectedEvents:  []string{"Normal FailedBinding"},
   799  			errors:          noerrors,
   800  			test:            testSyncClaim,
   801  		},
   802  		{
   803  			// failed syncVolume do not bind a requested filesystem claim to an unspecified volumeMode for volume
   804  			name:            "14-4 - do not bind pv volumeMode block and pvc volumeMode filesystem",
   805  			initialVolumes:  withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-4", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
   806  			expectedVolumes: withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-4", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
   807  			initialClaims:   withClaimVolumeMode(&modeFile, newClaimArray("claim14-4", "uid14-4", "10Gi", "", v1.ClaimPending, nil)),
   808  			expectedClaims:  withClaimVolumeMode(&modeFile, newClaimArray("claim14-4", "uid14-4", "10Gi", "", v1.ClaimPending, nil)),
   809  			expectedEvents:  []string{"Normal FailedBinding"},
   810  			errors:          noerrors,
   811  			test:            testSyncClaim,
   812  		},
   813  		{
   814  			// failed syncVolume do not bind when matching class but not matching volumeModes
   815  			name:            "14-5 - do not bind when matching class but not volumeMode",
   816  			initialVolumes:  withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-5", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classGold)),
   817  			expectedVolumes: withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-5", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classGold)),
   818  			initialClaims:   withClaimVolumeMode(&modeBlock, newClaimArray("claim14-5", "uid14-5", "10Gi", "", v1.ClaimPending, &classGold)),
   819  			expectedClaims:  withClaimVolumeMode(&modeBlock, newClaimArray("claim14-5", "uid14-5", "10Gi", "", v1.ClaimPending, &classGold)),
   820  			expectedEvents:  []string{"Warning ProvisioningFailed"},
   821  			errors:          noerrors,
   822  			test:            testSyncClaim,
   823  		},
   824  		{
   825  			// failed syncVolume do not bind when matching volumeModes but class does not match
   826  			name:            "14-5-1 - do not bind when matching volumeModes but class does not match",
   827  			initialVolumes:  withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-5-1", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classGold)),
   828  			expectedVolumes: withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-5-1", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classGold)),
   829  			initialClaims:   withClaimVolumeMode(&modeFile, newClaimArray("claim14-5-1", "uid14-5-1", "10Gi", "", v1.ClaimPending, &classSilver)),
   830  			expectedClaims:  withClaimVolumeMode(&modeFile, newClaimArray("claim14-5-1", "uid14-5-1", "10Gi", "", v1.ClaimPending, &classSilver)),
   831  			expectedEvents:  []string{"Warning ProvisioningFailed"},
   832  			errors:          noerrors,
   833  			test:            testSyncClaim,
   834  		},
   835  		{
   836  			// failed syncVolume do not bind when pvc is prebound to pv with matching volumeModes but class does not match
   837  			name:            "14-5-2 - do not bind when pvc is prebound to pv with matching volumeModes but class does not match",
   838  			initialVolumes:  withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-5-2", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classGold)),
   839  			expectedVolumes: withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-5-2", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classGold)),
   840  			initialClaims:   withClaimVolumeMode(&modeFile, newClaimArray("claim14-5-2", "uid14-5-2", "10Gi", "volume14-5-2", v1.ClaimPending, &classSilver)),
   841  			expectedClaims:  withClaimVolumeMode(&modeFile, newClaimArray("claim14-5-2", "uid14-5-2", "10Gi", "volume14-5-2", v1.ClaimPending, &classSilver)),
   842  			expectedEvents:  []string{"Warning VolumeMismatch"},
   843  			errors:          noerrors,
   844  			test:            testSyncClaim,
   845  		},
   846  		{
   847  			// syncVolume bind when pv is prebound and volumeModes match
   848  			name:            "14-7 - bind when pv volume is prebound and volumeModes match",
   849  			initialVolumes:  withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-7", "10Gi", "", "claim14-7", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
   850  			expectedVolumes: withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-7", "10Gi", "uid14-7", "claim14-7", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty)),
   851  			initialClaims:   withClaimVolumeMode(&modeBlock, newClaimArray("claim14-7", "uid14-7", "10Gi", "", v1.ClaimPending, nil)),
   852  			expectedClaims:  withClaimVolumeMode(&modeBlock, newClaimArray("claim14-7", "uid14-7", "10Gi", "volume14-7", v1.ClaimBound, nil, volume.AnnBoundByController, volume.AnnBindCompleted)),
   853  			expectedEvents:  noevents,
   854  			errors:          noerrors,
   855  			test:            testSyncClaim,
   856  		},
   857  		{
   858  			// failed syncVolume do not bind when pvc is prebound to pv with mismatching volumeModes
   859  			name:            "14-8 - do not bind when pvc is prebound to pv with mismatching volumeModes",
   860  			initialVolumes:  withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-8", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
   861  			expectedVolumes: withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-8", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
   862  			initialClaims:   withClaimVolumeMode(&modeFile, newClaimArray("claim14-8", "uid14-8", "10Gi", "volume14-8", v1.ClaimPending, nil)),
   863  			expectedClaims:  withClaimVolumeMode(&modeFile, newClaimArray("claim14-8", "uid14-8", "10Gi", "volume14-8", v1.ClaimPending, nil)),
   864  			expectedEvents:  []string{"Warning VolumeMismatch"},
   865  			errors:          noerrors,
   866  			test:            testSyncClaim,
   867  		},
   868  		{
   869  			// failed syncVolume do not bind when pvc is prebound to pv with mismatching volumeModes
   870  			name:            "14-8-1 - do not bind when pvc is prebound to pv with mismatching volumeModes",
   871  			initialVolumes:  withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-8-1", "10Gi", "", "claim14-8-1", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
   872  			expectedVolumes: withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-8-1", "10Gi", "", "claim14-8-1", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
   873  			initialClaims:   withClaimVolumeMode(&modeFile, newClaimArray("claim14-8-1", "uid14-8-1", "10Gi", "", v1.ClaimPending, nil)),
   874  			expectedClaims:  withClaimVolumeMode(&modeFile, newClaimArray("claim14-8-1", "uid14-8-1", "10Gi", "", v1.ClaimPending, nil)),
   875  			expectedEvents:  []string{"Normal FailedBinding"},
   876  			errors:          noerrors,
   877  			test:            testSyncClaim,
   878  		},
   879  		{
   880  			// syncVolume binds when pvc is prebound to pv with matching volumeModes block
   881  			name:            "14-9 - bind when pvc is prebound to pv with matching volumeModes block",
   882  			initialVolumes:  withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-9", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
   883  			expectedVolumes: withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-9", "10Gi", "uid14-9", "claim14-9", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController)),
   884  			initialClaims:   withClaimVolumeMode(&modeBlock, newClaimArray("claim14-9", "uid14-9", "10Gi", "volume14-9", v1.ClaimPending, nil)),
   885  			expectedClaims:  withClaimVolumeMode(&modeBlock, newClaimArray("claim14-9", "uid14-9", "10Gi", "volume14-9", v1.ClaimBound, nil, volume.AnnBindCompleted)),
   886  			expectedEvents:  noevents,
   887  			errors:          noerrors,
   888  			test:            testSyncClaim,
   889  		},
   890  		{
   891  			// syncVolume binds when pv is prebound to pvc with matching volumeModes block
   892  			name:            "14-10 - bind when pv is prebound to pvc with matching volumeModes block",
   893  			initialVolumes:  withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-10", "10Gi", "", "claim14-10", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
   894  			expectedVolumes: withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-10", "10Gi", "uid14-10", "claim14-10", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty)),
   895  			initialClaims:   withClaimVolumeMode(&modeBlock, newClaimArray("claim14-10", "uid14-10", "10Gi", "", v1.ClaimPending, nil)),
   896  			expectedClaims:  withClaimVolumeMode(&modeBlock, newClaimArray("claim14-10", "uid14-10", "10Gi", "volume14-10", v1.ClaimBound, nil, volume.AnnBoundByController, volume.AnnBindCompleted)),
   897  			expectedEvents:  noevents,
   898  			errors:          noerrors,
   899  			test:            testSyncClaim,
   900  		},
   901  		{
   902  			// syncVolume binds when pvc is prebound to pv with matching volumeModes filesystem
   903  			name:            "14-11 - bind when pvc is prebound to pv with matching volumeModes filesystem",
   904  			initialVolumes:  withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-11", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
   905  			expectedVolumes: withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-11", "10Gi", "uid14-11", "claim14-11", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController)),
   906  			initialClaims:   withClaimVolumeMode(&modeFile, newClaimArray("claim14-11", "uid14-11", "10Gi", "volume14-11", v1.ClaimPending, nil)),
   907  			expectedClaims:  withClaimVolumeMode(&modeFile, newClaimArray("claim14-11", "uid14-11", "10Gi", "volume14-11", v1.ClaimBound, nil, volume.AnnBindCompleted)),
   908  			expectedEvents:  noevents,
   909  			errors:          noerrors,
   910  			test:            testSyncClaim,
   911  		},
   912  		{
   913  			// syncVolume binds when pv is prebound to pvc with matching volumeModes filesystem
   914  			name:            "14-12 - bind when pv is prebound to pvc with matching volumeModes filesystem",
   915  			initialVolumes:  withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-12", "10Gi", "", "claim14-12", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
   916  			expectedVolumes: withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-12", "10Gi", "uid14-12", "claim14-12", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty)),
   917  			initialClaims:   withClaimVolumeMode(&modeFile, newClaimArray("claim14-12", "uid14-12", "10Gi", "", v1.ClaimPending, nil)),
   918  			expectedClaims:  withClaimVolumeMode(&modeFile, newClaimArray("claim14-12", "uid14-12", "10Gi", "volume14-12", v1.ClaimBound, nil, volume.AnnBoundByController, volume.AnnBindCompleted)),
   919  			expectedEvents:  noevents,
   920  			errors:          noerrors,
   921  			test:            testSyncClaim,
   922  		},
   923  		{
   924  			// syncVolume output warning when pv is prebound to pvc with mismatching volumeMode
   925  			name:            "14-13 - output warning when pv is prebound to pvc with different volumeModes",
   926  			initialVolumes:  withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-13", "10Gi", "uid14-13", "claim14-13", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController)),
   927  			expectedVolumes: withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-13", "10Gi", "uid14-13", "claim14-13", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController)),
   928  			initialClaims:   withClaimVolumeMode(&modeBlock, newClaimArray("claim14-13", "uid14-13", "10Gi", "", v1.ClaimPending, nil)),
   929  			expectedClaims:  withClaimVolumeMode(&modeBlock, newClaimArray("claim14-13", "uid14-13", "10Gi", "", v1.ClaimPending, nil)),
   930  			expectedEvents:  []string{"Warning VolumeMismatch"},
   931  			errors:          noerrors,
   932  			test:            testSyncVolume,
   933  		},
   934  		{
   935  			// syncVolume output warning when pv is prebound to pvc with mismatching volumeMode
   936  			name:            "14-13-1 - output warning when pv is prebound to pvc with different volumeModes",
   937  			initialVolumes:  withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-13-1", "10Gi", "uid14-13-1", "claim14-13-1", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController)),
   938  			expectedVolumes: withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-13-1", "10Gi", "uid14-13-1", "claim14-13-1", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController)),
   939  			initialClaims:   withClaimVolumeMode(&modeFile, newClaimArray("claim14-13-1", "uid14-13-1", "10Gi", "", v1.ClaimPending, nil)),
   940  			expectedClaims:  withClaimVolumeMode(&modeFile, newClaimArray("claim14-13-1", "uid14-13-1", "10Gi", "", v1.ClaimPending, nil)),
   941  			expectedEvents:  []string{"Warning VolumeMismatch"},
   942  			errors:          noerrors,
   943  			test:            testSyncVolume,
   944  		},
   945  		{
   946  			// syncVolume waits for synClaim without warning when pv is prebound to pvc with matching volumeMode block
   947  			name:            "14-14 - wait for synClaim without warning when pv is prebound to pvc with matching volumeModes block",
   948  			initialVolumes:  withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-14", "10Gi", "uid14-14", "claim14-14", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController)),
   949  			expectedVolumes: withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-14", "10Gi", "uid14-14", "claim14-14", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController)),
   950  			initialClaims:   withClaimVolumeMode(&modeBlock, newClaimArray("claim14-14", "uid14-14", "10Gi", "", v1.ClaimPending, nil)),
   951  			expectedClaims:  withClaimVolumeMode(&modeBlock, newClaimArray("claim14-14", "uid14-14", "10Gi", "", v1.ClaimPending, nil)),
   952  			expectedEvents:  noevents,
   953  			errors:          noerrors,
   954  			test:            testSyncVolume,
   955  		},
   956  		{
   957  			// syncVolume waits for synClaim without warning when pv is prebound to pvc with matching volumeMode file
   958  			name:            "14-14-1 - wait for synClaim without warning when pv is prebound to pvc with matching volumeModes file",
   959  			initialVolumes:  withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-14-1", "10Gi", "uid14-14-1", "claim14-14-1", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController)),
   960  			expectedVolumes: withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-14-1", "10Gi", "uid14-14-1", "claim14-14-1", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController)),
   961  			initialClaims:   withClaimVolumeMode(&modeFile, newClaimArray("claim14-14-1", "uid14-14-1", "10Gi", "", v1.ClaimPending, nil)),
   962  			expectedClaims:  withClaimVolumeMode(&modeFile, newClaimArray("claim14-14-1", "uid14-14-1", "10Gi", "", v1.ClaimPending, nil)),
   963  			expectedEvents:  noevents,
   964  			errors:          noerrors,
   965  			test:            testSyncVolume,
   966  		},
   967  	}
   968  	_, ctx := ktesting.NewTestContext(t)
   969  	runSyncTests(t, ctx, tests, []*storage.StorageClass{}, []*v1.Pod{})
   970  }
   971  
   972  // Test multiple calls to syncClaim/syncVolume and periodic sync of all
   973  // volume/claims. The test follows this pattern:
   974  //  0. Load the controller with initial data.
   975  //  1. Call controllerTest.testCall() once as in TestSync()
   976  //  2. For all volumes/claims changed by previous syncVolume/syncClaim calls,
   977  //     call appropriate syncVolume/syncClaim (simulating "volume/claim changed"
   978  //     events). Go to 2. if these calls change anything.
   979  //  3. When all changes are processed and no new changes were made, call
   980  //     syncVolume/syncClaim on all volumes/claims (simulating "periodic sync").
   981  //  4. If some changes were done by step 3., go to 2. (simulation of
   982  //     "volume/claim updated" events, eventually performing step 3. again)
   983  //  5. When 3. does not do any changes, finish the tests and compare final set
   984  //     of volumes/claims with expected claims/volumes and report differences.
   985  //
   986  // Some limit of calls in enforced to prevent endless loops.
   987  func TestMultiSync(t *testing.T) {
   988  	tests := []controllerTest{
   989  		// Test simple binding
   990  		{
   991  			// syncClaim binds to a matching unbound volume.
   992  			name:            "10-1 - successful bind",
   993  			initialVolumes:  newVolumeArray("volume10-1", "1Gi", "", "", v1.VolumePending, v1.PersistentVolumeReclaimRetain, classEmpty),
   994  			expectedVolumes: newVolumeArray("volume10-1", "1Gi", "uid10-1", "claim10-1", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController),
   995  			initialClaims:   newClaimArray("claim10-1", "uid10-1", "1Gi", "", v1.ClaimPending, nil),
   996  			expectedClaims:  newClaimArray("claim10-1", "uid10-1", "1Gi", "volume10-1", v1.ClaimBound, nil, volume.AnnBoundByController, volume.AnnBindCompleted),
   997  			expectedEvents:  noevents,
   998  			errors:          noerrors,
   999  			test:            testSyncClaim,
  1000  		},
  1001  		{
  1002  			// Two controllers bound two PVs to single claim. Test one of them
  1003  			// wins and the second rolls back.
  1004  			name: "10-2 - bind PV race",
  1005  			initialVolumes: []*v1.PersistentVolume{
  1006  				newVolume("volume10-2-1", "1Gi", "uid10-2", "claim10-2", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController),
  1007  				newVolume("volume10-2-2", "1Gi", "uid10-2", "claim10-2", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController),
  1008  			},
  1009  			expectedVolumes: []*v1.PersistentVolume{
  1010  				newVolume("volume10-2-1", "1Gi", "uid10-2", "claim10-2", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, volume.AnnBoundByController),
  1011  				newVolume("volume10-2-2", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty),
  1012  			},
  1013  			initialClaims:  newClaimArray("claim10-2", "uid10-2", "1Gi", "volume10-2-1", v1.ClaimBound, nil, volume.AnnBoundByController, volume.AnnBindCompleted),
  1014  			expectedClaims: newClaimArray("claim10-2", "uid10-2", "1Gi", "volume10-2-1", v1.ClaimBound, nil, volume.AnnBoundByController, volume.AnnBindCompleted),
  1015  			expectedEvents: noevents,
  1016  			errors:         noerrors,
  1017  			test:           testSyncClaim,
  1018  		},
  1019  	}
  1020  	_, ctx := ktesting.NewTestContext(t)
  1021  	runMultisyncTests(t, ctx, tests, []*storage.StorageClass{}, "")
  1022  }