You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: binder_test.go
    path of file: ./repos/volcano/pkg/scheduler/capabilities/volumebinding
    
    the code of the file until where you have to start completion: /*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package volumebinding

import (
	"context"
	"fmt"
	"os"
	"reflect"
	"sort"
	"testing
    
func TestFindPodVolumesWithCSIMigration(t *testing.T) {
	type scenarioType struct {
		// Inputs
		pvs     []*v1.PersistentVolume
		podPVCs []*v1.PersistentVolumeClaim
		// If nil, use pod PVCs
		cachePVCs []*v1.PersistentVolumeClaim
		// If nil, makePod with podPVCs
		pod *v1.Pod

		// Setup
		initNodes    []*v1.Node
		initCSINodes []*storagev1.CSINode

		// Expected return values
		reasons    ConflictReasons
		shouldFail bool
	}
	scenarios := map[string]scenarioType{
		"pvc-bound": {
			podPVCs:      []*v1.PersistentVolumeClaim{boundMigrationPVC},
			pvs:          []*v1.PersistentVolume{migrationPVBound},
			initNodes:    []*v1.Node{node1Zone1},
			initCSINodes: []*storagev1.CSINode{csiNode1Migrated},
		},
		"pvc-bound,csinode-not-migrated": {
			podPVCs:      []*v1.PersistentVolumeClaim{boundMigrationPVC},
			pvs:          []*v1.PersistentVolume{migrationPVBound},
			initNodes:    []*v1.Node{node1Zone1},
			initCSINodes: []*storagev1.CSINode{csiNode1NotMigrated},
		},
		"pvc-bound,missing-csinode": {
			podPVCs:   []*v1.PersistentVolumeClaim{boundMigrationPVC},
			pvs:       []*v1.PersistentVolume{migrationPVBound},
			initNodes: []*v1.Node{node1Zone1},
		},
		"pvc-bound,node-different-zone": {
			podPVCs:      []*v1.PersistentVolumeClaim{boundMigrationPVC},
			pvs:          []*v1.PersistentVolume{migrationPVBound},
			initNodes:    []*v1.Node{node1Zone2},
			initCSINodes: []*storagev1.CSINode{csiNode1Migrated},
			reasons:      ConflictReasons{ErrReasonNodeConflict},
		},
	}

	run := func(t *testing.T, scenario scenarioType) {
		logger, ctx := ktesting.NewTestContext(t)
		ctx, cancel := context.WithCancel(ctx)
		defer cancel()

		// Setup
		testEnv := newTestBinder(t, ctx)
		testEnv.initVolumes(scenario.pvs, scenario.pvs)

		var node *v1.Node
		if len(scenario.initNodes) > 0 {
			testEnv.initNodes(scenario.initNodes)
			node = scenario.initNodes[0]
		} else {
			node = node1
		}

		if len(scenario.initCSINodes) > 0 {
			testEnv.initCSINodes(scenario.initCSINodes)
		}

		// a. Init pvc cache
		if scenario.cachePVCs == nil {
			scenario.cachePVCs = scenario.podPVCs
		}
		testEnv.initClaims(scenario.cachePVCs, scenario.cachePVCs)

		// b. Generate pod with given claims
		if scenario.pod == nil {
			scenario.pod = makePod("test-pod").
				withNamespace("testns").
				withNodeName("node1").
				withPVCSVolume(scenario.podPVCs).Pod
		}

		// Execute
		_, reasons, err := findPodVolumes(logger, testEnv.binder, scenario.pod, node)

		// Validate
		if !scenario.shouldFail && err != nil {
			t.Errorf("returned error: %v", err)
		}
		if scenario.shouldFail && err == nil {
			t.Error("returned success but expected error")
		}
		checkReasons(t, reasons, scenario.reasons)
	}

	for name, scenario := range scenarios {
		t.Run(name, func(t *testing.T) { run(t, scenario) })
	}
}