k8s.io/kubernetes@v1.29.3/pkg/controller/volume/attachdetach/cache/actual_state_of_world_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 cache
    18  
    19  import (
    20  	"testing"
    21  	"time"
    22  
    23  	v1 "k8s.io/api/core/v1"
    24  	"k8s.io/apimachinery/pkg/types"
    25  	"k8s.io/klog/v2/ktesting"
    26  	controllervolumetesting "k8s.io/kubernetes/pkg/controller/volume/attachdetach/testing"
    27  	volumetesting "k8s.io/kubernetes/pkg/volume/testing"
    28  	volumeutil "k8s.io/kubernetes/pkg/volume/util"
    29  )
    30  
    31  // Calls AddVolumeNode() once with attached set to true.
    32  // Verifies a single volume/node entry exists.
    33  func Test_AddVolumeNode_Positive_NewVolumeNewNode(t *testing.T) {
    34  	// Arrange
    35  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
    36  	asw := NewActualStateOfWorld(volumePluginMgr)
    37  	volumeName := v1.UniqueVolumeName("volume-name")
    38  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
    39  
    40  	nodeName := types.NodeName("node-name")
    41  	devicePath := "fake/device/path"
    42  
    43  	// Act
    44  	logger, _ := ktesting.NewTestContext(t)
    45  	generatedVolumeName, err := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true)
    46  
    47  	// Assert
    48  	if err != nil {
    49  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", err)
    50  	}
    51  
    52  	volumeNodeComboState := asw.GetAttachState(generatedVolumeName, nodeName)
    53  	if volumeNodeComboState != AttachStateAttached {
    54  		t.Fatalf("%q/%q volume/node combo is marked %q; expected 'Attached'.", generatedVolumeName, nodeName, volumeNodeComboState)
    55  	}
    56  
    57  	attachedVolumes := asw.GetAttachedVolumes()
    58  	if len(attachedVolumes) != 1 {
    59  		t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes))
    60  	}
    61  
    62  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
    63  }
    64  
    65  // Calls AddVolumeNode() once with attached set to false.
    66  // Verifies a single volume/node entry exists.
    67  // Then calls AddVolumeNode() with attached set to true
    68  // Verifies volume is attached to the node according to asw.
    69  func Test_AddVolumeNode_Positive_NewVolumeNewNodeWithFalseAttached(t *testing.T) {
    70  	// Arrange
    71  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
    72  	asw := NewActualStateOfWorld(volumePluginMgr)
    73  	volumeName := v1.UniqueVolumeName("volume-name")
    74  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
    75  
    76  	nodeName := types.NodeName("node-name")
    77  	devicePath := "fake/device/path"
    78  
    79  	// Act
    80  	logger, _ := ktesting.NewTestContext(t)
    81  	generatedVolumeName, err := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, false)
    82  
    83  	// Assert
    84  	if err != nil {
    85  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", err)
    86  	}
    87  
    88  	volumeNodeComboState := asw.GetAttachState(generatedVolumeName, nodeName)
    89  	if volumeNodeComboState != AttachStateUncertain {
    90  		t.Fatalf("%q/%q volume/node combo is marked %q, expected 'Uncertain'.", generatedVolumeName, nodeName, volumeNodeComboState)
    91  	}
    92  
    93  	allVolumes := asw.GetAttachedVolumes()
    94  	if len(allVolumes) != 1 {
    95  		t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(allVolumes))
    96  	}
    97  	verifyAttachedVolume(t, allVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
    98  
    99  	reportAsAttachedVolumesMap := asw.GetVolumesToReportAttached(logger)
   100  	_, exists := reportAsAttachedVolumesMap[nodeName]
   101  	if exists {
   102  		t.Fatalf("AddVolumeNode_Positive_NewVolumeNewNodeWithFalseAttached failed. Actual: <node %q exist> Expect: <node does not exist in the reportedAsAttached map", nodeName)
   103  	}
   104  
   105  	volumesForNode := asw.GetAttachedVolumesForNode(nodeName)
   106  	if len(volumesForNode) != 1 {
   107  		t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(volumesForNode))
   108  	}
   109  	verifyAttachedVolume(t, volumesForNode, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
   110  
   111  	attachedVolumesMap := asw.GetAttachedVolumesPerNode()
   112  	_, exists = attachedVolumesMap[nodeName]
   113  	if exists {
   114  		t.Fatalf("AddVolumeNode_Positive_NewVolumeNewNodeWithFalseAttached failed. Actual: <node %q exist> Expect: <node does not exist in the reportedAsAttached map", nodeName)
   115  	}
   116  
   117  	nodes := asw.GetNodesForAttachedVolume(volumeName)
   118  	if len(nodes) > 0 {
   119  		t.Fatalf("AddVolumeNode_Positive_NewVolumeNewNodeWithFalseAttached failed. Expect no nodes returned.")
   120  	}
   121  
   122  	// Add the volume to the node second time with attached set to true
   123  	generatedVolumeName2, add2Err := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true)
   124  
   125  	// Assert
   126  	if add2Err != nil {
   127  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add2Err)
   128  	}
   129  
   130  	if generatedVolumeName != generatedVolumeName2 {
   131  		t.Fatalf(
   132  			"Generated volume names for the same volume should be the same but they are not: %q and %q",
   133  			generatedVolumeName,
   134  			generatedVolumeName2)
   135  	}
   136  
   137  	volumeNodeComboState = asw.GetAttachState(generatedVolumeName, nodeName)
   138  	if volumeNodeComboState != AttachStateAttached {
   139  		t.Fatalf("%q/%q volume/node combo is marked %q; expected 'Attached'.", generatedVolumeName, nodeName, volumeNodeComboState)
   140  	}
   141  
   142  	attachedVolumes := asw.GetAttachedVolumes()
   143  	if len(attachedVolumes) != 1 {
   144  		t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes))
   145  	}
   146  
   147  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
   148  
   149  	nodes = asw.GetNodesForAttachedVolume(volumeName)
   150  	if len(nodes) != 1 {
   151  		t.Fatalf("AddVolumeNode_Positive_NewVolumeNewNodeWithFalseAttached failed. Expect one node returned.")
   152  	}
   153  	if nodes[0] != nodeName {
   154  		t.Fatalf("AddVolumeNode_Positive_NewVolumeNewNodeWithFalseAttached failed. Expect node %v, Actual node %v", nodeName, nodes[0])
   155  	}
   156  
   157  	attachedVolumesMap = asw.GetAttachedVolumesPerNode()
   158  	_, exists = attachedVolumesMap[nodeName]
   159  	if !exists {
   160  		t.Fatalf("AddVolumeNode_Positive_NewVolumeNewNodeWithFalseAttached failed. Actual: <node %q does not exist> Expect: <node does exist in the reportedAsAttached map", nodeName)
   161  	}
   162  
   163  }
   164  
   165  // Calls AddVolumeNode() once with attached set to false.
   166  // Verifies a single volume/node entry exists.
   167  // Then calls AddVolumeNode() to attach the volume to a different node with attached set to true
   168  // Verifies volume is attached to the node according to asw.
   169  func Test_AddVolumeNode_Positive_NewVolumeTwoNodesWithFalseAttached(t *testing.T) {
   170  	// Arrange
   171  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
   172  	asw := NewActualStateOfWorld(volumePluginMgr)
   173  	volumeName := v1.UniqueVolumeName("volume-name")
   174  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
   175  
   176  	node1Name := types.NodeName("node1-name")
   177  	node2Name := types.NodeName("node2-name")
   178  	devicePath := "fake/device/path"
   179  
   180  	// Act
   181  	logger, _ := ktesting.NewTestContext(t)
   182  	generatedVolumeName, err := asw.AddVolumeNode(logger, volumeName, volumeSpec, node1Name, devicePath, false)
   183  
   184  	// Assert
   185  	if err != nil {
   186  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", err)
   187  	}
   188  
   189  	volumeNodeComboState := asw.GetAttachState(generatedVolumeName, node1Name)
   190  	if volumeNodeComboState != AttachStateUncertain {
   191  		t.Fatalf("%q/%q volume/node combo is marked %q, expected 'Uncertain'.", generatedVolumeName, node1Name, volumeNodeComboState)
   192  	}
   193  
   194  	generatedVolumeName2, add2Err := asw.AddVolumeNode(logger, volumeName, volumeSpec, node2Name, devicePath, true)
   195  
   196  	// Assert
   197  	if add2Err != nil {
   198  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add2Err)
   199  	}
   200  
   201  	if generatedVolumeName != generatedVolumeName2 {
   202  		t.Fatalf(
   203  			"Generated volume names for the same volume should be the same but they are not: %q and %q",
   204  			generatedVolumeName,
   205  			generatedVolumeName2)
   206  	}
   207  
   208  	volumeNodeComboState = asw.GetAttachState(generatedVolumeName, node2Name)
   209  	if volumeNodeComboState != AttachStateAttached {
   210  		t.Fatalf("%q/%q volume/node combo is marked %q; expected 'Attached'.", generatedVolumeName, node2Name, volumeNodeComboState)
   211  	}
   212  
   213  	attachedVolumes := asw.GetAttachedVolumes()
   214  	if len(attachedVolumes) != 2 {
   215  		t.Fatalf("len(attachedVolumes) Expected: <2> Actual: <%v>", len(attachedVolumes))
   216  	}
   217  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), node1Name, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
   218  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), node2Name, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
   219  
   220  	volumesForNode := asw.GetAttachedVolumesForNode(node2Name)
   221  	if len(volumesForNode) != 1 {
   222  		t.Fatalf("len(attachedVolumes) Expected: <2> Actual: <%v>", len(volumesForNode))
   223  	}
   224  	verifyAttachedVolume(t, volumesForNode, generatedVolumeName, string(volumeName), node2Name, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
   225  
   226  	attachedVolumesMap := asw.GetAttachedVolumesPerNode()
   227  	attachedVolumesPerNode, exists := attachedVolumesMap[node2Name]
   228  	if !exists || len(attachedVolumesPerNode) != 1 {
   229  		t.Fatalf("AddVolumeNode_Positive_NewVolumeTwoNodesWithFalseAttached failed. Actual: <node %q does not exist> Expect: <node does exist in the reportedAsAttached map", node2Name)
   230  	}
   231  
   232  	nodes := asw.GetNodesForAttachedVolume(volumeName)
   233  	if len(nodes) != 1 {
   234  		t.Fatalf("AddVolumeNode_Positive_NewVolumeNewNodeWithFalseAttached failed. Expect one node returned.")
   235  	}
   236  
   237  	reportAsAttachedVolumesMap := asw.GetVolumesToReportAttached(logger)
   238  	reportedVolumes, exists := reportAsAttachedVolumesMap[node2Name]
   239  	if !exists || len(reportedVolumes) != 1 {
   240  		t.Fatalf("AddVolumeNode_Positive_NewVolumeNewNodeWithFalseAttached failed. Actual: <node %q exist> Expect: <node does not exist in the reportedAsAttached map", node2Name)
   241  	}
   242  }
   243  
   244  // Calls AddVolumeNode() twice. Second time use a different node name.
   245  // Verifies two volume/node entries exist with the same volumeSpec.
   246  func Test_AddVolumeNode_Positive_ExistingVolumeNewNode(t *testing.T) {
   247  	// Arrange
   248  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
   249  	asw := NewActualStateOfWorld(volumePluginMgr)
   250  	volumeName := v1.UniqueVolumeName("volume-name")
   251  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
   252  	node1Name := types.NodeName("node1-name")
   253  	node2Name := types.NodeName("node2-name")
   254  	devicePath := "fake/device/path"
   255  
   256  	// Act
   257  	logger, _ := ktesting.NewTestContext(t)
   258  	generatedVolumeName1, add1Err := asw.AddVolumeNode(logger, volumeName, volumeSpec, node1Name, devicePath, true)
   259  	generatedVolumeName2, add2Err := asw.AddVolumeNode(logger, volumeName, volumeSpec, node2Name, devicePath, true)
   260  
   261  	// Assert
   262  	if add1Err != nil {
   263  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add1Err)
   264  	}
   265  	if add2Err != nil {
   266  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add2Err)
   267  	}
   268  
   269  	if generatedVolumeName1 != generatedVolumeName2 {
   270  		t.Fatalf(
   271  			"Generated volume names for the same volume should be the same but they are not: %q and %q",
   272  			generatedVolumeName1,
   273  			generatedVolumeName2)
   274  	}
   275  
   276  	volumeNode1ComboState := asw.GetAttachState(generatedVolumeName1, node1Name)
   277  	if volumeNode1ComboState != AttachStateAttached {
   278  		t.Fatalf("%q/%q volume/node combo is marked %q; expected 'Attached'.", generatedVolumeName1, node1Name, volumeNode1ComboState)
   279  	}
   280  
   281  	volumeNode2ComboState := asw.GetAttachState(generatedVolumeName1, node2Name)
   282  	if volumeNode2ComboState != AttachStateAttached {
   283  		t.Fatalf("%q/%q volume/node combo is marked %q; expected 'Attached'.", generatedVolumeName1, node2Name, volumeNode2ComboState)
   284  	}
   285  
   286  	attachedVolumes := asw.GetAttachedVolumes()
   287  	if len(attachedVolumes) != 2 {
   288  		t.Fatalf("len(attachedVolumes) Expected: <2> Actual: <%v>", len(attachedVolumes))
   289  	}
   290  
   291  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName1, string(volumeName), node1Name, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
   292  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName1, string(volumeName), node2Name, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
   293  }
   294  
   295  // Calls AddVolumeNode() twice. Uses the same volume and node both times.
   296  // Verifies a single volume/node entry exists.
   297  func Test_AddVolumeNode_Positive_ExistingVolumeExistingNode(t *testing.T) {
   298  	// Arrange
   299  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
   300  	asw := NewActualStateOfWorld(volumePluginMgr)
   301  	volumeName := v1.UniqueVolumeName("volume-name")
   302  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
   303  	nodeName := types.NodeName("node-name")
   304  	devicePath := "fake/device/path"
   305  
   306  	// Act
   307  	logger, _ := ktesting.NewTestContext(t)
   308  	generatedVolumeName1, add1Err := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true)
   309  	generatedVolumeName2, add2Err := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true)
   310  
   311  	// Assert
   312  	if add1Err != nil {
   313  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add1Err)
   314  	}
   315  	if add2Err != nil {
   316  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add2Err)
   317  	}
   318  
   319  	if generatedVolumeName1 != generatedVolumeName2 {
   320  		t.Fatalf(
   321  			"Generated volume names for the same volume should be the same but they are not: %q and %q",
   322  			generatedVolumeName1,
   323  			generatedVolumeName2)
   324  	}
   325  
   326  	volumeNodeComboState := asw.GetAttachState(generatedVolumeName1, nodeName)
   327  	if volumeNodeComboState != AttachStateAttached {
   328  		t.Fatalf("%q/%q volume/node combo is marked %q; expected 'Attached'.", generatedVolumeName1, nodeName, volumeNodeComboState)
   329  	}
   330  
   331  	attachedVolumes := asw.GetAttachedVolumes()
   332  	if len(attachedVolumes) != 1 {
   333  		t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes))
   334  	}
   335  
   336  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName1, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
   337  }
   338  
   339  // Populates data struct with one volume/node entry.
   340  // Calls DeleteVolumeNode() to delete volume/node.
   341  // Verifies no volume/node entries exists.
   342  func Test_DeleteVolumeNode_Positive_VolumeExistsNodeExists(t *testing.T) {
   343  	// Arrange
   344  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
   345  	asw := NewActualStateOfWorld(volumePluginMgr)
   346  	volumeName := v1.UniqueVolumeName("volume-name")
   347  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
   348  	nodeName := types.NodeName("node-name")
   349  	devicePath := "fake/device/path"
   350  	logger, _ := ktesting.NewTestContext(t)
   351  	generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true)
   352  	if addErr != nil {
   353  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr)
   354  	}
   355  
   356  	// Act
   357  	asw.DeleteVolumeNode(generatedVolumeName, nodeName)
   358  
   359  	// Assert
   360  	volumeNodeComboState := asw.GetAttachState(generatedVolumeName, nodeName)
   361  	if volumeNodeComboState != AttachStateDetached {
   362  		t.Fatalf("%q/%q volume/node combo is marked %q, expected 'Detached'.", generatedVolumeName, nodeName, volumeNodeComboState)
   363  	}
   364  
   365  	attachedVolumes := asw.GetAttachedVolumes()
   366  	if len(attachedVolumes) != 0 {
   367  		t.Fatalf("len(attachedVolumes) Expected: <0> Actual: <%v>", len(attachedVolumes))
   368  	}
   369  }
   370  
   371  // Calls DeleteVolumeNode() to delete volume/node on empty data struct
   372  // Verifies no volume/node entries exists.
   373  func Test_DeleteVolumeNode_Positive_VolumeDoesntExistNodeDoesntExist(t *testing.T) {
   374  	// Arrange
   375  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
   376  	asw := NewActualStateOfWorld(volumePluginMgr)
   377  	volumeName := v1.UniqueVolumeName("volume-name")
   378  	nodeName := types.NodeName("node-name")
   379  
   380  	// Act
   381  	asw.DeleteVolumeNode(volumeName, nodeName)
   382  
   383  	// Assert
   384  	volumeNodeComboState := asw.GetAttachState(volumeName, nodeName)
   385  	if volumeNodeComboState != AttachStateDetached {
   386  		t.Fatalf("%q/%q volume/node combo is marked %q, expected 'Detached'.", volumeName, nodeName, volumeNodeComboState)
   387  	}
   388  
   389  	attachedVolumes := asw.GetAttachedVolumes()
   390  	if len(attachedVolumes) != 0 {
   391  		t.Fatalf("len(attachedVolumes) Expected: <0> Actual: <%v>", len(attachedVolumes))
   392  	}
   393  }
   394  
   395  // Populates data struct with two volume/node entries the second one using a
   396  // different node.
   397  // Calls DeleteVolumeNode() to delete first volume/node.
   398  // Verifies only second volume/node entry exists.
   399  func Test_DeleteVolumeNode_Positive_TwoNodesOneDeleted(t *testing.T) {
   400  	// Arrange
   401  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
   402  	asw := NewActualStateOfWorld(volumePluginMgr)
   403  	volumeName := v1.UniqueVolumeName("volume-name")
   404  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
   405  	node1Name := types.NodeName("node1-name")
   406  	node2Name := types.NodeName("node2-name")
   407  	devicePath := "fake/device/path"
   408  	logger, _ := ktesting.NewTestContext(t)
   409  	generatedVolumeName1, add1Err := asw.AddVolumeNode(logger, volumeName, volumeSpec, node1Name, devicePath, true)
   410  	if add1Err != nil {
   411  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add1Err)
   412  	}
   413  	generatedVolumeName2, add2Err := asw.AddVolumeNode(logger, volumeName, volumeSpec, node2Name, devicePath, true)
   414  	if add2Err != nil {
   415  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add2Err)
   416  	}
   417  	if generatedVolumeName1 != generatedVolumeName2 {
   418  		t.Fatalf(
   419  			"Generated volume names for the same volume should be the same but they are not: %q and %q",
   420  			generatedVolumeName1,
   421  			generatedVolumeName2)
   422  	}
   423  
   424  	// Act
   425  	asw.DeleteVolumeNode(generatedVolumeName1, node1Name)
   426  
   427  	// Assert
   428  	volumeNodeComboState := asw.GetAttachState(generatedVolumeName1, node1Name)
   429  	if volumeNodeComboState != AttachStateDetached {
   430  		t.Fatalf("%q/%q volume/node combo is marked %q, expected 'Detached'.", generatedVolumeName1, node1Name, volumeNodeComboState)
   431  	}
   432  
   433  	volumeNodeComboState = asw.GetAttachState(generatedVolumeName1, node2Name)
   434  	if volumeNodeComboState != AttachStateAttached {
   435  		t.Fatalf("%q/%q volume/node combo is marked %q; expected 'Attached'.", generatedVolumeName1, node2Name, volumeNodeComboState)
   436  	}
   437  
   438  	attachedVolumes := asw.GetAttachedVolumes()
   439  	if len(attachedVolumes) != 1 {
   440  		t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes))
   441  	}
   442  
   443  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName1, string(volumeName), node2Name, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
   444  }
   445  
   446  // Populates data struct with one volume/node entry.
   447  // Calls GetAttachState() to verify entry.
   448  // Verifies the populated volume/node entry exists.
   449  func Test_VolumeNodeExists_Positive_VolumeExistsNodeExists(t *testing.T) {
   450  	// Arrange
   451  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
   452  	asw := NewActualStateOfWorld(volumePluginMgr)
   453  	volumeName := v1.UniqueVolumeName("volume-name")
   454  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
   455  	nodeName := types.NodeName("node-name")
   456  	devicePath := "fake/device/path"
   457  	logger, _ := ktesting.NewTestContext(t)
   458  	generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true)
   459  	if addErr != nil {
   460  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr)
   461  	}
   462  
   463  	// Act
   464  	volumeNodeComboState := asw.GetAttachState(generatedVolumeName, nodeName)
   465  
   466  	// Assert
   467  	if volumeNodeComboState != AttachStateAttached {
   468  		t.Fatalf("%q/%q volume/node combo is marked %q; expected 'Attached'.", generatedVolumeName, nodeName, volumeNodeComboState)
   469  	}
   470  
   471  	attachedVolumes := asw.GetAttachedVolumes()
   472  	if len(attachedVolumes) != 1 {
   473  		t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes))
   474  	}
   475  
   476  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
   477  }
   478  
   479  // Populates data struct with one volume1/node1 entry.
   480  // Calls GetAttachState() with volume1/node2.
   481  // Verifies requested entry does not exist, but populated entry does.
   482  func Test_VolumeNodeExists_Positive_VolumeExistsNodeDoesntExist(t *testing.T) {
   483  	// Arrange
   484  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
   485  	asw := NewActualStateOfWorld(volumePluginMgr)
   486  	volumeName := v1.UniqueVolumeName("volume-name")
   487  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
   488  	node1Name := types.NodeName("node1-name")
   489  	node2Name := types.NodeName("node2-name")
   490  	devicePath := "fake/device/path"
   491  	logger, _ := ktesting.NewTestContext(t)
   492  	generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, node1Name, devicePath, true)
   493  	if addErr != nil {
   494  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr)
   495  	}
   496  
   497  	// Act
   498  	volumeNodeComboState := asw.GetAttachState(generatedVolumeName, node2Name)
   499  
   500  	// Assert
   501  	if volumeNodeComboState != AttachStateDetached {
   502  		t.Fatalf("%q/%q volume/node combo is marked %q, expected 'Detached'.", generatedVolumeName, node2Name, volumeNodeComboState)
   503  	}
   504  
   505  	attachedVolumes := asw.GetAttachedVolumes()
   506  	if len(attachedVolumes) != 1 {
   507  		t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes))
   508  	}
   509  
   510  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), node1Name, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
   511  }
   512  
   513  // Calls GetAttachState() on empty data struct.
   514  // Verifies requested entry does not exist.
   515  func Test_VolumeNodeExists_Positive_VolumeAndNodeDontExist(t *testing.T) {
   516  	// Arrange
   517  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
   518  	asw := NewActualStateOfWorld(volumePluginMgr)
   519  	volumeName := v1.UniqueVolumeName("volume-name")
   520  	nodeName := types.NodeName("node-name")
   521  
   522  	// Act
   523  	volumeNodeComboState := asw.GetAttachState(volumeName, nodeName)
   524  
   525  	// Assert
   526  	if volumeNodeComboState != AttachStateDetached {
   527  		t.Fatalf("%q/%q volume/node combo is marked %q, expected 'Detached'.", volumeName, nodeName, volumeNodeComboState)
   528  	}
   529  
   530  	attachedVolumes := asw.GetAttachedVolumes()
   531  	if len(attachedVolumes) != 0 {
   532  		t.Fatalf("len(attachedVolumes) Expected: <0> Actual: <%v>", len(attachedVolumes))
   533  	}
   534  }
   535  
   536  // Calls GetAttachedVolumes() on empty data struct.
   537  // Verifies no volume/node entries are returned.
   538  func Test_GetAttachedVolumes_Positive_NoVolumesOrNodes(t *testing.T) {
   539  	// Arrange
   540  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
   541  	asw := NewActualStateOfWorld(volumePluginMgr)
   542  
   543  	// Act
   544  	attachedVolumes := asw.GetAttachedVolumes()
   545  
   546  	// Assert
   547  	if len(attachedVolumes) != 0 {
   548  		t.Fatalf("len(attachedVolumes) Expected: <0> Actual: <%v>", len(attachedVolumes))
   549  	}
   550  }
   551  
   552  // Populates data struct with one volume/node entry.
   553  // Calls GetAttachedVolumes() to get list of entries.
   554  // Verifies one volume/node entry is returned.
   555  func Test_GetAttachedVolumes_Positive_OneVolumeOneNode(t *testing.T) {
   556  	// Arrange
   557  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
   558  	asw := NewActualStateOfWorld(volumePluginMgr)
   559  	volumeName := v1.UniqueVolumeName("volume-name")
   560  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
   561  	nodeName := types.NodeName("node-name")
   562  	devicePath := "fake/device/path"
   563  	logger, _ := ktesting.NewTestContext(t)
   564  	generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true)
   565  	if addErr != nil {
   566  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr)
   567  	}
   568  
   569  	// Act
   570  	attachedVolumes := asw.GetAttachedVolumes()
   571  
   572  	// Assert
   573  	if len(attachedVolumes) != 1 {
   574  		t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes))
   575  	}
   576  
   577  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
   578  }
   579  
   580  // Populates data struct with two volume/node entries (different node and volume).
   581  // Calls GetAttachedVolumes() to get list of entries.
   582  // Verifies both volume/node entries are returned.
   583  func Test_GetAttachedVolumes_Positive_TwoVolumeTwoNodes(t *testing.T) {
   584  	// Arrange
   585  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
   586  	asw := NewActualStateOfWorld(volumePluginMgr)
   587  	volume1Name := v1.UniqueVolumeName("volume1-name")
   588  	volume1Spec := controllervolumetesting.GetTestVolumeSpec(string(volume1Name), volume1Name)
   589  	node1Name := types.NodeName("node1-name")
   590  	devicePath := "fake/device/path"
   591  	logger, _ := ktesting.NewTestContext(t)
   592  	generatedVolumeName1, add1Err := asw.AddVolumeNode(logger, volume1Name, volume1Spec, node1Name, devicePath, true)
   593  	if add1Err != nil {
   594  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add1Err)
   595  	}
   596  	volume2Name := v1.UniqueVolumeName("volume2-name")
   597  	volume2Spec := controllervolumetesting.GetTestVolumeSpec(string(volume2Name), volume2Name)
   598  	node2Name := types.NodeName("node2-name")
   599  	generatedVolumeName2, add2Err := asw.AddVolumeNode(logger, volume2Name, volume2Spec, node2Name, devicePath, true)
   600  	if add2Err != nil {
   601  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add2Err)
   602  	}
   603  
   604  	// Act
   605  	attachedVolumes := asw.GetAttachedVolumes()
   606  
   607  	// Assert
   608  	if len(attachedVolumes) != 2 {
   609  		t.Fatalf("len(attachedVolumes) Expected: <2> Actual: <%v>", len(attachedVolumes))
   610  	}
   611  
   612  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName1, string(volume1Name), node1Name, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
   613  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName2, string(volume2Name), node2Name, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
   614  }
   615  
   616  // Populates data struct with two volume/node entries (same volume different node).
   617  // Calls GetAttachedVolumes() to get list of entries.
   618  // Verifies both volume/node entries are returned.
   619  func Test_GetAttachedVolumes_Positive_OneVolumeTwoNodes(t *testing.T) {
   620  	// Arrange
   621  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
   622  	asw := NewActualStateOfWorld(volumePluginMgr)
   623  	volumeName := v1.UniqueVolumeName("volume-name")
   624  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
   625  	node1Name := types.NodeName("node1-name")
   626  	devicePath := "fake/device/path"
   627  	plugin, err := volumePluginMgr.FindAttachablePluginBySpec(volumeSpec)
   628  	if err != nil || plugin == nil {
   629  		t.Fatalf("Failed to get volume plugin from spec %v, %v", volumeSpec, err)
   630  	}
   631  	uniqueVolumeName, err := volumeutil.GetUniqueVolumeNameFromSpec(plugin, volumeSpec)
   632  	if err != nil || plugin == nil {
   633  		t.Fatalf("Failed to get uniqueVolumeName from spec %v, %v", volumeSpec, err)
   634  	}
   635  	logger, _ := ktesting.NewTestContext(t)
   636  	generatedVolumeName1, add1Err := asw.AddVolumeNode(logger, uniqueVolumeName, volumeSpec, node1Name, devicePath, true)
   637  	if add1Err != nil {
   638  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add1Err)
   639  	}
   640  	node2Name := types.NodeName("node2-name")
   641  	generatedVolumeName2, add2Err := asw.AddVolumeNode(logger, v1.UniqueVolumeName(""), volumeSpec, node2Name, devicePath, true)
   642  	if add2Err != nil {
   643  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add2Err)
   644  	}
   645  
   646  	if generatedVolumeName1 != generatedVolumeName2 {
   647  		t.Fatalf(
   648  			"Generated volume names for the same volume should be the same but they are not: %q and %q",
   649  			generatedVolumeName1,
   650  			generatedVolumeName2)
   651  	}
   652  
   653  	// Act
   654  	attachedVolumes := asw.GetAttachedVolumes()
   655  
   656  	// Assert
   657  	if len(attachedVolumes) != 2 {
   658  		t.Fatalf("len(attachedVolumes) Expected: <2> Actual: <%v>", len(attachedVolumes))
   659  	}
   660  
   661  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName1, string(volumeName), node1Name, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
   662  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName1, string(volumeName), node2Name, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
   663  }
   664  
   665  // Populates data struct with one volume/node entry.
   666  // Verifies mountedByNode is true and DetachRequestedTime is zero.
   667  func Test_SetVolumeMountedByNode_Positive_Set(t *testing.T) {
   668  	// Arrange
   669  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
   670  	asw := NewActualStateOfWorld(volumePluginMgr)
   671  	volumeName := v1.UniqueVolumeName("volume-name")
   672  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
   673  	nodeName := types.NodeName("node-name")
   674  	devicePath := "fake/device/path"
   675  	logger, _ := ktesting.NewTestContext(t)
   676  	generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true)
   677  	if addErr != nil {
   678  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr)
   679  	}
   680  
   681  	// Act: do not mark -- test default value
   682  
   683  	// Assert
   684  	attachedVolumes := asw.GetAttachedVolumes()
   685  	if len(attachedVolumes) != 1 {
   686  		t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes))
   687  	}
   688  
   689  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
   690  }
   691  
   692  // Populates data struct with one volume/node entry.
   693  // Calls SetVolumeMountedByNode twice, first setting mounted to true then false.
   694  // Verifies mountedByNode is false.
   695  func Test_SetVolumeMountedByNode_Positive_UnsetWithInitialSet(t *testing.T) {
   696  	// Arrange
   697  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
   698  	asw := NewActualStateOfWorld(volumePluginMgr)
   699  	volumeName := v1.UniqueVolumeName("volume-name")
   700  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
   701  	nodeName := types.NodeName("node-name")
   702  	devicePath := "fake/device/path"
   703  	logger, _ := ktesting.NewTestContext(t)
   704  	generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true)
   705  	if addErr != nil {
   706  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr)
   707  	}
   708  
   709  	// Act
   710  	setVolumeMountedErr1 := asw.SetVolumeMountedByNode(logger, generatedVolumeName, nodeName, true /* mounted */)
   711  	setVolumeMountedErr2 := asw.SetVolumeMountedByNode(logger, generatedVolumeName, nodeName, false /* mounted */)
   712  
   713  	// Assert
   714  	if setVolumeMountedErr1 != nil {
   715  		t.Fatalf("SetVolumeMountedByNode1 failed. Expected <no error> Actual: <%v>", setVolumeMountedErr1)
   716  	}
   717  	if setVolumeMountedErr2 != nil {
   718  		t.Fatalf("SetVolumeMountedByNode2 failed. Expected <no error> Actual: <%v>", setVolumeMountedErr2)
   719  	}
   720  
   721  	attachedVolumes := asw.GetAttachedVolumes()
   722  	if len(attachedVolumes) != 1 {
   723  		t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes))
   724  	}
   725  
   726  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, false /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
   727  }
   728  
   729  // Populates data struct with one volume/node entry.
   730  // Calls SetVolumeMountedByNode once, setting mounted to false.
   731  // Verifies mountedByNode is false because value is overwritten
   732  func Test_SetVolumeMountedByNode_Positive_UnsetWithoutInitialSet(t *testing.T) {
   733  	// Arrange
   734  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
   735  	asw := NewActualStateOfWorld(volumePluginMgr)
   736  	volumeName := v1.UniqueVolumeName("volume-name")
   737  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
   738  	nodeName := types.NodeName("node-name")
   739  	devicePath := "fake/device/path"
   740  	logger, _ := ktesting.NewTestContext(t)
   741  	generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true)
   742  	if addErr != nil {
   743  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr)
   744  	}
   745  
   746  	attachedVolumes := asw.GetAttachedVolumes()
   747  	if len(attachedVolumes) != 1 {
   748  		t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes))
   749  	}
   750  
   751  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
   752  
   753  	// Act
   754  	setVolumeMountedErr := asw.SetVolumeMountedByNode(logger, generatedVolumeName, nodeName, false /* mounted */)
   755  
   756  	// Assert
   757  	if setVolumeMountedErr != nil {
   758  		t.Fatalf("SetVolumeMountedByNode failed. Expected <no error> Actual: <%v>", setVolumeMountedErr)
   759  	}
   760  
   761  	attachedVolumes = asw.GetAttachedVolumes()
   762  	if len(attachedVolumes) != 1 {
   763  		t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes))
   764  	}
   765  
   766  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, false /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
   767  }
   768  
   769  // Populates data struct with one volume/node entry.
   770  // Calls SetVolumeMountedByNode twice, first setting mounted to true then false.
   771  // Calls AddVolumeNode to readd the same volume/node.
   772  // Verifies mountedByNode is false and detachRequestedTime is zero.
   773  func Test_SetVolumeMountedByNode_Positive_UnsetWithInitialSetAddVolumeNodeNotReset(t *testing.T) {
   774  	// Arrange
   775  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
   776  	asw := NewActualStateOfWorld(volumePluginMgr)
   777  	volumeName := v1.UniqueVolumeName("volume-name")
   778  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
   779  	nodeName := types.NodeName("node-name")
   780  	devicePath := "fake/device/path"
   781  	logger, _ := ktesting.NewTestContext(t)
   782  	generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true)
   783  	if addErr != nil {
   784  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr)
   785  	}
   786  
   787  	// Act
   788  	setVolumeMountedErr1 := asw.SetVolumeMountedByNode(logger, generatedVolumeName, nodeName, true /* mounted */)
   789  	setVolumeMountedErr2 := asw.SetVolumeMountedByNode(logger, generatedVolumeName, nodeName, false /* mounted */)
   790  	generatedVolumeName, addErr = asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true)
   791  
   792  	// Assert
   793  	if setVolumeMountedErr1 != nil {
   794  		t.Fatalf("SetVolumeMountedByNode1 failed. Expected <no error> Actual: <%v>", setVolumeMountedErr1)
   795  	}
   796  	if setVolumeMountedErr2 != nil {
   797  		t.Fatalf("SetVolumeMountedByNode2 failed. Expected <no error> Actual: <%v>", setVolumeMountedErr2)
   798  	}
   799  	if addErr != nil {
   800  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr)
   801  	}
   802  
   803  	attachedVolumes := asw.GetAttachedVolumes()
   804  	if len(attachedVolumes) != 1 {
   805  		t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes))
   806  	}
   807  
   808  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, false /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
   809  }
   810  
   811  // Populates data struct with one volume/node entry.
   812  // Calls RemoveVolumeFromReportAsAttached() once on volume/node entry.
   813  // Calls SetVolumeMountedByNode() twice, first setting mounted to true then false.
   814  // Verifies mountedByNode is false and detachRequestedTime is NOT zero.
   815  func Test_SetVolumeMountedByNode_Positive_UnsetWithInitialSetVerifyDetachRequestedTimePerserved(t *testing.T) {
   816  	// Arrange
   817  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
   818  	asw := NewActualStateOfWorld(volumePluginMgr)
   819  	volumeName := v1.UniqueVolumeName("volume-name")
   820  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
   821  	nodeName := types.NodeName("node-name")
   822  	devicePath := "fake/device/path"
   823  	logger, _ := ktesting.NewTestContext(t)
   824  	generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true)
   825  	if addErr != nil {
   826  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr)
   827  	}
   828  	_, err := asw.SetDetachRequestTime(logger, generatedVolumeName, nodeName)
   829  	if err != nil {
   830  		t.Fatalf("SetDetachRequestTime failed. Expected: <no error> Actual: <%v>", err)
   831  	}
   832  	err = asw.RemoveVolumeFromReportAsAttached(generatedVolumeName, nodeName)
   833  	if err != nil {
   834  		t.Fatalf("RemoveVolumeFromReportAsAttached failed. Expected: <no error> Actual: <%v>", err)
   835  	}
   836  	expectedDetachRequestedTime := asw.GetAttachedVolumes()[0].DetachRequestedTime
   837  
   838  	// Act
   839  	setVolumeMountedErr1 := asw.SetVolumeMountedByNode(logger, generatedVolumeName, nodeName, true /* mounted */)
   840  	setVolumeMountedErr2 := asw.SetVolumeMountedByNode(logger, generatedVolumeName, nodeName, false /* mounted */)
   841  
   842  	// Assert
   843  	if setVolumeMountedErr1 != nil {
   844  		t.Fatalf("SetVolumeMountedByNode1 failed. Expected <no error> Actual: <%v>", setVolumeMountedErr1)
   845  	}
   846  	if setVolumeMountedErr2 != nil {
   847  		t.Fatalf("SetVolumeMountedByNode2 failed. Expected <no error> Actual: <%v>", setVolumeMountedErr2)
   848  	}
   849  
   850  	attachedVolumes := asw.GetAttachedVolumes()
   851  	if len(attachedVolumes) != 1 {
   852  		t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes))
   853  	}
   854  
   855  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, false /* expectedMountedByNode */, true /* expectNonZeroDetachRequestedTime */)
   856  	if !expectedDetachRequestedTime.Equal(attachedVolumes[0].DetachRequestedTime) {
   857  		t.Fatalf("DetachRequestedTime changed. Expected: <%v> Actual: <%v>", expectedDetachRequestedTime, attachedVolumes[0].DetachRequestedTime)
   858  	}
   859  }
   860  
   861  // Populates data struct with one volume/node entry.
   862  // Verifies mountedByNode is true and detachRequestedTime is zero (default values).
   863  func Test_RemoveVolumeFromReportAsAttached_Positive_Set(t *testing.T) {
   864  	// Arrange
   865  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
   866  	asw := NewActualStateOfWorld(volumePluginMgr)
   867  	volumeName := v1.UniqueVolumeName("volume-name")
   868  	devicePath := "fake/device/path"
   869  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
   870  	nodeName := types.NodeName("node-name")
   871  	logger, _ := ktesting.NewTestContext(t)
   872  	generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true)
   873  	if addErr != nil {
   874  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr)
   875  	}
   876  
   877  	// Act: do not mark -- test default value
   878  
   879  	// Assert
   880  	attachedVolumes := asw.GetAttachedVolumes()
   881  	if len(attachedVolumes) != 1 {
   882  		t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes))
   883  	}
   884  
   885  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
   886  }
   887  
   888  // Populates data struct with one volume/node entry.
   889  // Calls RemoveVolumeFromReportAsAttached() once on volume/node entry.
   890  // Verifies mountedByNode is true and detachRequestedTime is NOT zero.
   891  func Test_RemoveVolumeFromReportAsAttached_Positive_Marked(t *testing.T) {
   892  	// Arrange
   893  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
   894  	asw := NewActualStateOfWorld(volumePluginMgr)
   895  	volumeName := v1.UniqueVolumeName("volume-name")
   896  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
   897  	nodeName := types.NodeName("node-name")
   898  	devicePath := "fake/device/path"
   899  	logger, _ := ktesting.NewTestContext(t)
   900  	generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true)
   901  	if addErr != nil {
   902  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr)
   903  	}
   904  
   905  	// Act
   906  	_, err := asw.SetDetachRequestTime(logger, generatedVolumeName, nodeName)
   907  	if err != nil {
   908  		t.Fatalf("SetDetachRequestTime failed. Expected: <no error> Actual: <%v>", err)
   909  	}
   910  	markDesireToDetachErr := asw.RemoveVolumeFromReportAsAttached(generatedVolumeName, nodeName)
   911  	if markDesireToDetachErr != nil {
   912  		t.Fatalf("MarkDesireToDetach failed. Expected: <no error> Actual: <%v>", markDesireToDetachErr)
   913  	}
   914  
   915  	// Assert
   916  	attachedVolumes := asw.GetAttachedVolumes()
   917  	if len(attachedVolumes) != 1 {
   918  		t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes))
   919  	}
   920  
   921  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, true /* expectNonZeroDetachRequestedTime */)
   922  }
   923  
   924  // Populates data struct with one volume/node entry.
   925  // Calls MarkDesireToDetach() once on volume/node entry.
   926  // Calls ResetDetachRequestTime() to reset the detach request time value back to 0.
   927  // Verifies mountedByNode is true and detachRequestedTime is reset to zero.
   928  func Test_MarkDesireToDetach_Positive_MarkedAddVolumeNodeReset(t *testing.T) {
   929  	// Arrange
   930  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
   931  	asw := NewActualStateOfWorld(volumePluginMgr)
   932  	volumeName := v1.UniqueVolumeName("volume-name")
   933  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
   934  	nodeName := types.NodeName("node-name")
   935  	devicePath := "fake/device/path"
   936  	logger, _ := ktesting.NewTestContext(t)
   937  	generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true)
   938  	if addErr != nil {
   939  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr)
   940  	}
   941  
   942  	// Act
   943  	_, err := asw.SetDetachRequestTime(logger, generatedVolumeName, nodeName)
   944  	if err != nil {
   945  		t.Fatalf("SetDetachRequestTime failed. Expected: <no error> Actual: <%v>", err)
   946  	}
   947  	markDesireToDetachErr := asw.RemoveVolumeFromReportAsAttached(generatedVolumeName, nodeName)
   948  	// Reset detach request time to 0
   949  	asw.ResetDetachRequestTime(logger, generatedVolumeName, nodeName)
   950  
   951  	// Assert
   952  	if markDesireToDetachErr != nil {
   953  		t.Fatalf("RemoveVolumeFromReportAsAttached failed. Expected: <no error> Actual: <%v>", markDesireToDetachErr)
   954  	}
   955  	if addErr != nil {
   956  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr)
   957  	}
   958  
   959  	// Assert
   960  	attachedVolumes := asw.GetAttachedVolumes()
   961  	if len(attachedVolumes) != 1 {
   962  		t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes))
   963  	}
   964  
   965  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
   966  }
   967  
   968  // Populates data struct with one volume/node entry.
   969  // Calls SetVolumeMountedByNode() twice, first setting mounted to true then false.
   970  // Calls RemoveVolumeFromReportAsAttached() once on volume/node entry.
   971  // Verifies mountedByNode is false and detachRequestedTime is NOT zero.
   972  func Test_RemoveVolumeFromReportAsAttached_Positive_UnsetWithInitialSetVolumeMountedByNodePreserved(t *testing.T) {
   973  	// Arrange
   974  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
   975  	asw := NewActualStateOfWorld(volumePluginMgr)
   976  	volumeName := v1.UniqueVolumeName("volume-name")
   977  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
   978  	nodeName := types.NodeName("node-name")
   979  	devicePath := "fake/device/path"
   980  	logger, _ := ktesting.NewTestContext(t)
   981  	generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true)
   982  	if addErr != nil {
   983  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr)
   984  	}
   985  	setVolumeMountedErr1 := asw.SetVolumeMountedByNode(logger, generatedVolumeName, nodeName, true /* mounted */)
   986  	setVolumeMountedErr2 := asw.SetVolumeMountedByNode(logger, generatedVolumeName, nodeName, false /* mounted */)
   987  	if setVolumeMountedErr1 != nil {
   988  		t.Fatalf("SetVolumeMountedByNode1 failed. Expected <no error> Actual: <%v>", setVolumeMountedErr1)
   989  	}
   990  	if setVolumeMountedErr2 != nil {
   991  		t.Fatalf("SetVolumeMountedByNode2 failed. Expected <no error> Actual: <%v>", setVolumeMountedErr2)
   992  	}
   993  
   994  	// Act
   995  	_, err := asw.SetDetachRequestTime(logger, generatedVolumeName, nodeName)
   996  	if err != nil {
   997  		t.Fatalf("SetDetachRequestTime failed. Expected: <no error> Actual: <%v>", err)
   998  	}
   999  	removeVolumeDetachErr := asw.RemoveVolumeFromReportAsAttached(generatedVolumeName, nodeName)
  1000  	if removeVolumeDetachErr != nil {
  1001  		t.Fatalf("RemoveVolumeFromReportAsAttached failed. Expected: <no error> Actual: <%v>", removeVolumeDetachErr)
  1002  	}
  1003  
  1004  	// Assert
  1005  	attachedVolumes := asw.GetAttachedVolumes()
  1006  	if len(attachedVolumes) != 1 {
  1007  		t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes))
  1008  	}
  1009  
  1010  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, false /* expectedMountedByNode */, true /* expectNonZeroDetachRequestedTime */)
  1011  }
  1012  
  1013  // Populates data struct with one volume/node entry.
  1014  // Calls RemoveVolumeFromReportAsAttached
  1015  // Verifies there is no volume as reported as attached
  1016  func Test_RemoveVolumeFromReportAsAttached(t *testing.T) {
  1017  	// Arrange
  1018  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
  1019  	asw := NewActualStateOfWorld(volumePluginMgr)
  1020  	volumeName := v1.UniqueVolumeName("volume-name")
  1021  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
  1022  	nodeName := types.NodeName("node-name")
  1023  	devicePath := "fake/device/path"
  1024  	logger, _ := ktesting.NewTestContext(t)
  1025  	generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true)
  1026  	if addErr != nil {
  1027  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr)
  1028  	}
  1029  
  1030  	removeVolumeDetachErr := asw.RemoveVolumeFromReportAsAttached(generatedVolumeName, nodeName)
  1031  	if removeVolumeDetachErr != nil {
  1032  		t.Fatalf("RemoveVolumeFromReportAsAttached failed. Expected: <no error> Actual: <%v>", removeVolumeDetachErr)
  1033  	}
  1034  
  1035  	reportAsAttachedVolumesMap := asw.GetVolumesToReportAttached(logger)
  1036  	volumes, exists := reportAsAttachedVolumesMap[nodeName]
  1037  	if !exists {
  1038  		t.Fatalf("MarkDesireToDetach_UnmarkDesireToDetach failed. Expected: <node %q exist> Actual: <node does not exist in the reportedAsAttached map", nodeName)
  1039  	}
  1040  	if len(volumes) > 0 {
  1041  		t.Fatalf("len(reportAsAttachedVolumes) Expected: <0> Actual: <%v>", len(volumes))
  1042  	}
  1043  
  1044  }
  1045  
  1046  // Populates data struct with one volume/node entry.
  1047  // Calls RemoveVolumeFromReportAsAttached
  1048  // Calls AddVolumeToReportAsAttached to add volume back as attached
  1049  // Verifies there is one volume as reported as attached
  1050  func Test_RemoveVolumeFromReportAsAttached_AddVolumeToReportAsAttached_Positive(t *testing.T) {
  1051  	// Arrange
  1052  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
  1053  	asw := NewActualStateOfWorld(volumePluginMgr)
  1054  	volumeName := v1.UniqueVolumeName("volume-name")
  1055  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
  1056  	nodeName := types.NodeName("node-name")
  1057  	devicePath := "fake/device/path"
  1058  	logger, _ := ktesting.NewTestContext(t)
  1059  	generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true)
  1060  	if addErr != nil {
  1061  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr)
  1062  	}
  1063  
  1064  	removeVolumeDetachErr := asw.RemoveVolumeFromReportAsAttached(generatedVolumeName, nodeName)
  1065  	if removeVolumeDetachErr != nil {
  1066  		t.Fatalf("RemoveVolumeFromReportAsAttached failed. Expected: <no error> Actual: <%v>", removeVolumeDetachErr)
  1067  	}
  1068  
  1069  	reportAsAttachedVolumesMap := asw.GetVolumesToReportAttached(logger)
  1070  	volumes, exists := reportAsAttachedVolumesMap[nodeName]
  1071  	if !exists {
  1072  		t.Fatalf("Test_RemoveVolumeFromReportAsAttached_AddVolumeToReportAsAttached_Positive failed. Expected: <node %q exist> Actual: <node does not exist in the reportedAsAttached map", nodeName)
  1073  	}
  1074  	if len(volumes) > 0 {
  1075  		t.Fatalf("len(reportAsAttachedVolumes) Expected: <0> Actual: <%v>", len(volumes))
  1076  	}
  1077  
  1078  	asw.AddVolumeToReportAsAttached(logger, generatedVolumeName, nodeName)
  1079  	reportAsAttachedVolumesMap = asw.GetVolumesToReportAttached(logger)
  1080  	volumes, exists = reportAsAttachedVolumesMap[nodeName]
  1081  	if !exists {
  1082  		t.Fatalf("Test_RemoveVolumeFromReportAsAttached_AddVolumeToReportAsAttached_Positive failed. Expected: <node %q exist> Actual: <node does not exist in the reportedAsAttached map", nodeName)
  1083  	}
  1084  	if len(volumes) != 1 {
  1085  		t.Fatalf("len(reportAsAttachedVolumes) Expected: <1> Actual: <%v>", len(volumes))
  1086  	}
  1087  }
  1088  
  1089  // Populates data struct with one volume/node entry.
  1090  // Calls RemoveVolumeFromReportAsAttached
  1091  // Calls DeleteVolumeNode
  1092  // Calls AddVolumeNode
  1093  // Verifies there is no volume as reported as attached
  1094  func Test_RemoveVolumeFromReportAsAttached_Delete_AddVolumeNode(t *testing.T) {
  1095  	// Arrange
  1096  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
  1097  	asw := NewActualStateOfWorld(volumePluginMgr)
  1098  	volumeName := v1.UniqueVolumeName("volume-name")
  1099  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
  1100  	nodeName := types.NodeName("node-name")
  1101  	devicePath := "fake/device/path"
  1102  	logger, _ := ktesting.NewTestContext(t)
  1103  	generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true)
  1104  	if addErr != nil {
  1105  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr)
  1106  	}
  1107  
  1108  	removeVolumeDetachErr := asw.RemoveVolumeFromReportAsAttached(generatedVolumeName, nodeName)
  1109  	if removeVolumeDetachErr != nil {
  1110  		t.Fatalf("RemoveVolumeFromReportAsAttached failed. Expected: <no error> Actual: <%v>", removeVolumeDetachErr)
  1111  	}
  1112  
  1113  	reportAsAttachedVolumesMap := asw.GetVolumesToReportAttached(logger)
  1114  	volumes, exists := reportAsAttachedVolumesMap[nodeName]
  1115  	if !exists {
  1116  		t.Fatalf("Test_RemoveVolumeFromReportAsAttached_Delete_AddVolumeNode failed. Expected: <node %q exists> Actual: <node does not exist in the reportedAsAttached map", nodeName)
  1117  	}
  1118  	if len(volumes) > 0 {
  1119  		t.Fatalf("len(reportAsAttachedVolumes) Expected: <0> Actual: <%v>", len(volumes))
  1120  	}
  1121  
  1122  	asw.DeleteVolumeNode(generatedVolumeName, nodeName)
  1123  
  1124  	asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, "" /*device path*/, true)
  1125  
  1126  	reportAsAttachedVolumesMap = asw.GetVolumesToReportAttached(logger)
  1127  	volumes, exists = reportAsAttachedVolumesMap[nodeName]
  1128  	if !exists {
  1129  		t.Fatalf("Test_RemoveVolumeFromReportAsAttached_Delete_AddVolumeNode failed. Expected: <node %q exists> Actual: <node does not exist in the reportedAsAttached map", nodeName)
  1130  	}
  1131  	if len(volumes) != 1 {
  1132  		t.Fatalf("len(reportAsAttachedVolumes) Expected: <1> Actual: <%v>", len(volumes))
  1133  	}
  1134  }
  1135  
  1136  // Populates data struct with one volume/node entry.
  1137  // Calls SetDetachRequestTime twice and sleep maxWaitTime (1 second) in between
  1138  // The elapsed time returned from the first SetDetachRequestTime call should be smaller than maxWaitTime
  1139  // The elapsed time returned from the second SetDetachRequestTime call should be larger than maxWaitTime
  1140  func Test_SetDetachRequestTime_Positive(t *testing.T) {
  1141  	// Arrange
  1142  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
  1143  	asw := NewActualStateOfWorld(volumePluginMgr)
  1144  	volumeName := v1.UniqueVolumeName("volume-name")
  1145  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
  1146  	nodeName := types.NodeName("node-name")
  1147  	devicePath := "fake/device/path"
  1148  	logger, _ := ktesting.NewTestContext(t)
  1149  	generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true)
  1150  	if addErr != nil {
  1151  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr)
  1152  	}
  1153  
  1154  	maxWaitTime := 1 * time.Second
  1155  	etime, err := asw.SetDetachRequestTime(logger, generatedVolumeName, nodeName)
  1156  	if err != nil {
  1157  		t.Fatalf("SetDetachRequestTime failed. Expected: <no error> Actual: <%v>", err)
  1158  	}
  1159  	if etime >= maxWaitTime {
  1160  		t.Logf("SetDetachRequestTim Expected: <elapsed time %v is smaller than maxWaitTime %v> Actual <elapsed time is larger than maxWaitTime>", etime, maxWaitTime)
  1161  	}
  1162  	// Sleep and call SetDetachRequestTime again
  1163  	time.Sleep(maxWaitTime)
  1164  	etime, err = asw.SetDetachRequestTime(logger, generatedVolumeName, nodeName)
  1165  	if err != nil {
  1166  		t.Fatalf("SetDetachRequestTime failed. Expected: <no error> Actual: <%v>", err)
  1167  	}
  1168  	if etime < maxWaitTime {
  1169  		t.Fatalf("SetDetachRequestTim Expected: <elapsed time %v is larger than maxWaitTime %v> Actual <elapsed time is smaller>", etime, maxWaitTime)
  1170  	}
  1171  }
  1172  
  1173  func Test_GetAttachedVolumesForNode_Positive_NoVolumesOrNodes(t *testing.T) {
  1174  	// Arrange
  1175  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
  1176  	asw := NewActualStateOfWorld(volumePluginMgr)
  1177  	node := types.NodeName("random")
  1178  
  1179  	// Act
  1180  	attachedVolumes := asw.GetAttachedVolumesForNode(node)
  1181  
  1182  	// Assert
  1183  	if len(attachedVolumes) != 0 {
  1184  		t.Fatalf("len(attachedVolumes) Expected: <0> Actual: <%v>", len(attachedVolumes))
  1185  	}
  1186  }
  1187  
  1188  func Test_GetAttachedVolumesForNode_Positive_OneVolumeOneNode(t *testing.T) {
  1189  	// Arrange
  1190  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
  1191  	asw := NewActualStateOfWorld(volumePluginMgr)
  1192  	volumeName := v1.UniqueVolumeName("volume-name")
  1193  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
  1194  	nodeName := types.NodeName("node-name")
  1195  	devicePath := "fake/device/path"
  1196  	logger, _ := ktesting.NewTestContext(t)
  1197  	generatedVolumeName, addErr := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true)
  1198  	if addErr != nil {
  1199  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", addErr)
  1200  	}
  1201  
  1202  	// Act
  1203  	attachedVolumes := asw.GetAttachedVolumesForNode(nodeName)
  1204  
  1205  	// Assert
  1206  	if len(attachedVolumes) != 1 {
  1207  		t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes))
  1208  	}
  1209  
  1210  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
  1211  }
  1212  
  1213  func Test_GetAttachedVolumesForNode_Positive_TwoVolumeTwoNodes(t *testing.T) {
  1214  	// Arrange
  1215  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
  1216  	asw := NewActualStateOfWorld(volumePluginMgr)
  1217  	volume1Name := v1.UniqueVolumeName("volume1-name")
  1218  	volume1Spec := controllervolumetesting.GetTestVolumeSpec(string(volume1Name), volume1Name)
  1219  	node1Name := types.NodeName("node1-name")
  1220  	devicePath := "fake/device/path"
  1221  	logger, _ := ktesting.NewTestContext(t)
  1222  	_, add1Err := asw.AddVolumeNode(logger, volume1Name, volume1Spec, node1Name, devicePath, true)
  1223  	if add1Err != nil {
  1224  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add1Err)
  1225  	}
  1226  	volume2Name := v1.UniqueVolumeName("volume2-name")
  1227  	volume2Spec := controllervolumetesting.GetTestVolumeSpec(string(volume2Name), volume2Name)
  1228  	node2Name := types.NodeName("node2-name")
  1229  	generatedVolumeName2, add2Err := asw.AddVolumeNode(logger, volume2Name, volume2Spec, node2Name, devicePath, true)
  1230  	if add2Err != nil {
  1231  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add2Err)
  1232  	}
  1233  
  1234  	// Act
  1235  	attachedVolumes := asw.GetAttachedVolumesForNode(node2Name)
  1236  
  1237  	// Assert
  1238  	if len(attachedVolumes) != 1 {
  1239  		t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes))
  1240  	}
  1241  
  1242  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName2, string(volume2Name), node2Name, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
  1243  }
  1244  
  1245  func Test_GetAttachedVolumesForNode_Positive_OneVolumeTwoNodes(t *testing.T) {
  1246  	// Arrange
  1247  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
  1248  	asw := NewActualStateOfWorld(volumePluginMgr)
  1249  	volumeName := v1.UniqueVolumeName("volume-name")
  1250  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
  1251  	node1Name := types.NodeName("node1-name")
  1252  	devicePath := "fake/device/path"
  1253  	logger, _ := ktesting.NewTestContext(t)
  1254  	plugin, err := volumePluginMgr.FindAttachablePluginBySpec(volumeSpec)
  1255  	if err != nil || plugin == nil {
  1256  		t.Fatalf("Failed to get volume plugin from spec %v, %v", volumeSpec, err)
  1257  	}
  1258  	uniqueVolumeName, err := volumeutil.GetUniqueVolumeNameFromSpec(plugin, volumeSpec)
  1259  	if err != nil || plugin == nil {
  1260  		t.Fatalf("Failed to get uniqueVolumeName from spec %v, %v", volumeSpec, err)
  1261  	}
  1262  	generatedVolumeName1, add1Err := asw.AddVolumeNode(logger, uniqueVolumeName, volumeSpec, node1Name, devicePath, true)
  1263  	if add1Err != nil {
  1264  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add1Err)
  1265  	}
  1266  	node2Name := types.NodeName("node2-name")
  1267  	generatedVolumeName2, add2Err := asw.AddVolumeNode(logger, v1.UniqueVolumeName(""), volumeSpec, node2Name, devicePath, true)
  1268  	if add2Err != nil {
  1269  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add2Err)
  1270  	}
  1271  
  1272  	if generatedVolumeName1 != generatedVolumeName2 {
  1273  		t.Fatalf(
  1274  			"Generated volume names for the same volume should be the same but they are not: %q and %q",
  1275  			generatedVolumeName1,
  1276  			generatedVolumeName2)
  1277  	}
  1278  
  1279  	// Act
  1280  	attachedVolumes := asw.GetAttachedVolumesForNode(node1Name)
  1281  
  1282  	// Assert
  1283  	if len(attachedVolumes) != 1 {
  1284  		t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes))
  1285  	}
  1286  
  1287  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName1, string(volumeName), node1Name, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
  1288  }
  1289  
  1290  func Test_OneVolumeTwoNodes_TwoDevicePaths(t *testing.T) {
  1291  	// Arrange
  1292  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
  1293  	asw := NewActualStateOfWorld(volumePluginMgr)
  1294  	volumeName := v1.UniqueVolumeName("volume-name")
  1295  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
  1296  	node1Name := types.NodeName("node1-name")
  1297  	devicePath1 := "fake/device/path1"
  1298  	logger, _ := ktesting.NewTestContext(t)
  1299  	plugin, err := volumePluginMgr.FindAttachablePluginBySpec(volumeSpec)
  1300  	if err != nil || plugin == nil {
  1301  		t.Fatalf("Failed to get volume plugin from spec %v, %v", volumeSpec, err)
  1302  	}
  1303  	uniqueVolumeName, err := volumeutil.GetUniqueVolumeNameFromSpec(plugin, volumeSpec)
  1304  	if err != nil || plugin == nil {
  1305  		t.Fatalf("Failed to get uniqueVolumeName from spec %v, %v", volumeSpec, err)
  1306  	}
  1307  	generatedVolumeName1, add1Err := asw.AddVolumeNode(logger, uniqueVolumeName, volumeSpec, node1Name, devicePath1, true)
  1308  	if add1Err != nil {
  1309  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add1Err)
  1310  	}
  1311  	node2Name := types.NodeName("node2-name")
  1312  	devicePath2 := "fake/device/path2"
  1313  	generatedVolumeName2, add2Err := asw.AddVolumeNode(logger, v1.UniqueVolumeName(""), volumeSpec, node2Name, devicePath2, true)
  1314  	if add2Err != nil {
  1315  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", add2Err)
  1316  	}
  1317  
  1318  	if generatedVolumeName1 != generatedVolumeName2 {
  1319  		t.Fatalf(
  1320  			"Generated volume names for the same volume should be the same but they are not: %q and %q",
  1321  			generatedVolumeName1,
  1322  			generatedVolumeName2)
  1323  	}
  1324  
  1325  	// Act
  1326  	attachedVolumes := asw.GetAttachedVolumesForNode(node2Name)
  1327  
  1328  	// Assert
  1329  	if len(attachedVolumes) != 1 {
  1330  		t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes))
  1331  	}
  1332  
  1333  	verifyAttachedVolume(t, attachedVolumes, generatedVolumeName2, string(volumeName), node2Name, devicePath2, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
  1334  }
  1335  
  1336  // Test_SetNodeStatusUpdateNeededError expects the map nodesToUpdateStatusFor
  1337  // to be empty if the SetNodeStatusUpdateNeeded is called on a node that
  1338  // does not exist in the actual state of the world
  1339  func Test_SetNodeStatusUpdateNeededError(t *testing.T) {
  1340  	// Arrange
  1341  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
  1342  	asw := NewActualStateOfWorld(volumePluginMgr)
  1343  	nodeName := types.NodeName("node-1")
  1344  
  1345  	// Act
  1346  	logger, _ := ktesting.NewTestContext(t)
  1347  	asw.SetNodeStatusUpdateNeeded(logger, nodeName)
  1348  
  1349  	// Assert
  1350  	nodesToUpdateStatusFor := asw.GetNodesToUpdateStatusFor()
  1351  	if len(nodesToUpdateStatusFor) != 0 {
  1352  		t.Fatalf("nodesToUpdateStatusFor should be empty as nodeName does not exist")
  1353  	}
  1354  }
  1355  
  1356  // Test_updateNodeStatusUpdateNeeded expects statusUpdateNeeded to be properly updated if
  1357  // updateNodeStatusUpdateNeeded is called on a node that exists in the actual state of the world
  1358  func Test_updateNodeStatusUpdateNeeded(t *testing.T) {
  1359  	// Arrange
  1360  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
  1361  	asw := &actualStateOfWorld{
  1362  		attachedVolumes:        make(map[v1.UniqueVolumeName]attachedVolume),
  1363  		nodesToUpdateStatusFor: make(map[types.NodeName]nodeToUpdateStatusFor),
  1364  		volumePluginMgr:        volumePluginMgr,
  1365  	}
  1366  	nodeName := types.NodeName("node-1")
  1367  	nodeToUpdate := nodeToUpdateStatusFor{
  1368  		nodeName:                  nodeName,
  1369  		statusUpdateNeeded:        true,
  1370  		volumesToReportAsAttached: make(map[v1.UniqueVolumeName]v1.UniqueVolumeName),
  1371  	}
  1372  	asw.nodesToUpdateStatusFor[nodeName] = nodeToUpdate
  1373  
  1374  	// Act
  1375  	err := asw.updateNodeStatusUpdateNeeded(nodeName, false)
  1376  
  1377  	// Assert
  1378  	if err != nil {
  1379  		t.Fatalf("updateNodeStatusUpdateNeeded should not return error, but got: %v", err)
  1380  	}
  1381  	nodesToUpdateStatusFor := asw.GetNodesToUpdateStatusFor()
  1382  	if nodesToUpdateStatusFor[nodeName].statusUpdateNeeded {
  1383  		t.Fatalf("nodesToUpdateStatusFor should be updated to: false, but got: true")
  1384  	}
  1385  }
  1386  
  1387  // Test_updateNodeStatusUpdateNeededError expects statusUpdateNeeded to report error if
  1388  // updateNodeStatusUpdateNeeded is called on a node that does not exist in the actual state of the world
  1389  func Test_updateNodeStatusUpdateNeededError(t *testing.T) {
  1390  	// Arrange
  1391  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
  1392  	asw := &actualStateOfWorld{
  1393  		attachedVolumes:        make(map[v1.UniqueVolumeName]attachedVolume),
  1394  		nodesToUpdateStatusFor: make(map[types.NodeName]nodeToUpdateStatusFor),
  1395  		volumePluginMgr:        volumePluginMgr,
  1396  	}
  1397  	nodeName := types.NodeName("node-1")
  1398  
  1399  	// Act
  1400  	err := asw.updateNodeStatusUpdateNeeded(nodeName, false)
  1401  
  1402  	// Assert
  1403  	if err == nil {
  1404  		t.Fatalf("updateNodeStatusUpdateNeeded should return error, but got nothing")
  1405  	}
  1406  }
  1407  
  1408  // Mark a volume as attached to a node.
  1409  // Verify GetAttachState returns AttachedState
  1410  // Verify GetAttachedVolumes return this volume
  1411  func Test_MarkVolumeAsAttached(t *testing.T) {
  1412  	// Arrange
  1413  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
  1414  	asw := NewActualStateOfWorld(volumePluginMgr)
  1415  	volumeName := v1.UniqueVolumeName("volume-name")
  1416  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
  1417  
  1418  	nodeName := types.NodeName("node-name")
  1419  	devicePath := "fake/device/path"
  1420  
  1421  	plugin, err := volumePluginMgr.FindAttachablePluginBySpec(volumeSpec)
  1422  	if err != nil || plugin == nil {
  1423  		t.Fatalf("Failed to get volume plugin from spec %v, %v", volumeSpec, err)
  1424  	}
  1425  
  1426  	// Act
  1427  	logger, _ := ktesting.NewTestContext(t)
  1428  	err = asw.MarkVolumeAsAttached(logger, volumeName, volumeSpec, nodeName, devicePath)
  1429  
  1430  	// Assert
  1431  	if err != nil {
  1432  		t.Fatalf("MarkVolumeAsAttached failed. Expected: <no error> Actual: <%v>", err)
  1433  	}
  1434  
  1435  	volumeNodeComboState := asw.GetAttachState(volumeName, nodeName)
  1436  	if volumeNodeComboState != AttachStateAttached {
  1437  		t.Fatalf("asw says the volume: %q is not attached (%v) to node:%q, it should.",
  1438  			volumeName, AttachStateAttached, nodeName)
  1439  	}
  1440  	attachedVolumes := asw.GetAttachedVolumes()
  1441  	if len(attachedVolumes) != 1 {
  1442  		t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes))
  1443  	}
  1444  	verifyAttachedVolume(t, attachedVolumes, volumeName, string(volumeName), nodeName, devicePath, true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
  1445  }
  1446  
  1447  // Mark a volume as attachment as uncertain.
  1448  // Verify GetAttachState returns UncertainState
  1449  // Verify GetAttachedVolumes return this volume
  1450  func Test_MarkVolumeAsUncertain(t *testing.T) {
  1451  	// Arrange
  1452  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
  1453  	asw := NewActualStateOfWorld(volumePluginMgr)
  1454  	volumeName := v1.UniqueVolumeName("volume-name")
  1455  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
  1456  	nodeName := types.NodeName("node-name")
  1457  
  1458  	plugin, err := volumePluginMgr.FindAttachablePluginBySpec(volumeSpec)
  1459  	if err != nil || plugin == nil {
  1460  		t.Fatalf("Failed to get volume plugin from spec %v, %v", volumeSpec, err)
  1461  	}
  1462  
  1463  	// Act
  1464  	logger, _ := ktesting.NewTestContext(t)
  1465  	err = asw.MarkVolumeAsUncertain(logger, volumeName, volumeSpec, nodeName)
  1466  
  1467  	// Assert
  1468  	if err != nil {
  1469  		t.Fatalf("MarkVolumeAsUncertain failed. Expected: <no error> Actual: <%v>", err)
  1470  	}
  1471  	volumeNodeComboState := asw.GetAttachState(volumeName, nodeName)
  1472  	if volumeNodeComboState != AttachStateUncertain {
  1473  		t.Fatalf("asw says the volume: %q is attached (%v) to node:%q, it should not.",
  1474  			volumeName, volumeNodeComboState, nodeName)
  1475  	}
  1476  	attachedVolumes := asw.GetAttachedVolumes()
  1477  	if len(attachedVolumes) != 1 {
  1478  		t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes))
  1479  	}
  1480  	verifyAttachedVolume(t, attachedVolumes, volumeName, string(volumeName), nodeName, "", true /* expectedMountedByNode */, false /* expectNonZeroDetachRequestedTime */)
  1481  }
  1482  
  1483  // Calls AddVolumeNode() once with attached set to true.
  1484  // Verifies GetVolumesToReportAttachedForNode has an update for the node.
  1485  // Call GetVolumesToReportAttachedForNode a second time for the node, verify it does not report
  1486  // an update is needed any more
  1487  // Then calls RemoveVolumeFromReportAsAttached()
  1488  // Verifies GetVolumesToReportAttachedForNode reports an update is needed
  1489  func Test_GetVolumesToReportAttachedForNode_Positive(t *testing.T) {
  1490  	// Arrange
  1491  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
  1492  	asw := NewActualStateOfWorld(volumePluginMgr)
  1493  	volumeName := v1.UniqueVolumeName("volume-name")
  1494  	volumeSpec := controllervolumetesting.GetTestVolumeSpec(string(volumeName), volumeName)
  1495  
  1496  	nodeName := types.NodeName("node-name")
  1497  	devicePath := "fake/device/path"
  1498  
  1499  	// Act
  1500  	logger, _ := ktesting.NewTestContext(t)
  1501  	generatedVolumeName, err := asw.AddVolumeNode(logger, volumeName, volumeSpec, nodeName, devicePath, true)
  1502  
  1503  	// Assert
  1504  	if err != nil {
  1505  		t.Fatalf("AddVolumeNode failed. Expected: <no error> Actual: <%v>", err)
  1506  	}
  1507  
  1508  	needsUpdate, attachedVolumes := asw.GetVolumesToReportAttachedForNode(logger, nodeName)
  1509  	if !needsUpdate {
  1510  		t.Fatalf("GetVolumesToReportAttachedForNode_Positive_NewVolumeNewNodeWithTrueAttached failed. Actual: <node %q does not need an update> Expect: <node exists in the reportedAsAttached map and needs an update", nodeName)
  1511  	}
  1512  	if len(attachedVolumes) != 1 {
  1513  		t.Fatalf("len(attachedVolumes) Expected: <1> Actual: <%v>", len(attachedVolumes))
  1514  	}
  1515  
  1516  	needsUpdate, _ = asw.GetVolumesToReportAttachedForNode(logger, nodeName)
  1517  	if needsUpdate {
  1518  		t.Fatalf("GetVolumesToReportAttachedForNode_Positive_NewVolumeNewNodeWithTrueAttached failed. Actual: <node %q needs an update> Expect: <node exists in the reportedAsAttached map and does not need an update", nodeName)
  1519  	}
  1520  
  1521  	removeVolumeDetachErr := asw.RemoveVolumeFromReportAsAttached(generatedVolumeName, nodeName)
  1522  	if removeVolumeDetachErr != nil {
  1523  		t.Fatalf("RemoveVolumeFromReportAsAttached failed. Expected: <no error> Actual: <%v>", removeVolumeDetachErr)
  1524  	}
  1525  
  1526  	needsUpdate, attachedVolumes = asw.GetVolumesToReportAttachedForNode(logger, nodeName)
  1527  	if !needsUpdate {
  1528  		t.Fatalf("GetVolumesToReportAttachedForNode_Positive_NewVolumeNewNodeWithTrueAttached failed. Actual: <node %q does not need an update> Expect: <node exists in the reportedAsAttached map and needs an update", nodeName)
  1529  	}
  1530  	if len(attachedVolumes) != 0 {
  1531  		t.Fatalf("len(attachedVolumes) Expected: <0> Actual: <%v>", len(attachedVolumes))
  1532  	}
  1533  }
  1534  
  1535  // Verifies GetVolumesToReportAttachedForNode reports no update needed for an unknown node.
  1536  func Test_GetVolumesToReportAttachedForNode_UnknownNode(t *testing.T) {
  1537  	// Arrange
  1538  	volumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
  1539  	asw := NewActualStateOfWorld(volumePluginMgr)
  1540  	nodeName := types.NodeName("node-name")
  1541  	logger, _ := ktesting.NewTestContext(t)
  1542  	needsUpdate, _ := asw.GetVolumesToReportAttachedForNode(logger, nodeName)
  1543  	if needsUpdate {
  1544  		t.Fatalf("GetVolumesToReportAttachedForNode_UnknownNode failed. Actual: <node %q needs an update> Expect: <node does not exist in the reportedAsAttached map and does not need an update", nodeName)
  1545  	}
  1546  }
  1547  
  1548  func verifyAttachedVolume(
  1549  	t *testing.T,
  1550  	attachedVolumes []AttachedVolume,
  1551  	expectedVolumeName v1.UniqueVolumeName,
  1552  	expectedVolumeSpecName string,
  1553  	expectedNodeName types.NodeName,
  1554  	expectedDevicePath string,
  1555  	expectedMountedByNode,
  1556  	expectNonZeroDetachRequestedTime bool) {
  1557  	for _, attachedVolume := range attachedVolumes {
  1558  		if attachedVolume.VolumeName == expectedVolumeName &&
  1559  			attachedVolume.VolumeSpec.Name() == expectedVolumeSpecName &&
  1560  			attachedVolume.NodeName == expectedNodeName &&
  1561  			attachedVolume.DevicePath == expectedDevicePath &&
  1562  			attachedVolume.MountedByNode == expectedMountedByNode &&
  1563  			attachedVolume.DetachRequestedTime.IsZero() == !expectNonZeroDetachRequestedTime {
  1564  			return
  1565  		}
  1566  	}
  1567  
  1568  	t.Fatalf(
  1569  		"attachedVolumes (%v) should contain the volume/node combo %q/%q with DevicePath=%q MountedByNode=%v and NonZeroDetachRequestedTime=%v. It does not.",
  1570  		attachedVolumes,
  1571  		expectedVolumeName,
  1572  		expectedNodeName,
  1573  		expectedDevicePath,
  1574  		expectedMountedByNode,
  1575  		expectNonZeroDetachRequestedTime)
  1576  }