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: csi_mounter_test.go
    path of file: ./repos/kubernetes/pkg/volume/csi
    
    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 csi

import (
	"context"
	"fmt"
	"math/rand"
	"os"
	"path/filepath"
	"reflect"
	goruntime "runtime"
	"testing"
	"time"

	"github.com/google/go-cmp/cmp"
	"github.com/stretchr/testify/assert"
	authenticationv1 "k8s.io/api/authentication/v1"
	corev1 "k8s.io/api/core/v1"
	storage "k8s.io/api/storage/v1"
	meta "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/types"
	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
	utilfeature "k8s.io/apiserver/pkg/util/feature"
	fakeclient "k8s.io/client-go/kubernetes/fake"
	clitesting "k8s.io/client-go/testing"
	featuregatetesting "k8s.io/component-base/featuregate/testing"
	pkgauthenticationv1 "k8s.io/kubernetes/pkg/apis/authentication/v1"
	pkgcorev1 "k8s.io/kubernetes/pkg/apis/core/v1"
	pkgstoragev1 "k8s.io/kubernetes/pkg/apis/storage/v1"
	"k8s.io/kubernetes/pkg/features"
	"k8s.io/kubernetes/pkg/volume"
	fakecsi "k8s.io/kubernetes/pkg/volume/csi/fake"
	"k8s.io/kubernetes/pkg/volume/util"
	volumetypes "k8s.io/kubernetes/pkg/volume/util/types"
)

var (
	testDriver  = "test-driver"
	testVol     = "vol-123"
	testns      = "test-ns"
	testPod     = "test-pod"
	testPodUID  = types.UID("test-pod")
	testAccount = "test-service-account"
)

func prepareVolumeInfoFile(mountPath string, plug *csiPlugin, specVolumeName, volumeID, driverName, lifecycleMode, seLinuxMountContext string) error {
	nodeName := string(plug.host.GetNodeName())
	volData := map[string]string{
		volDataKey.specVolID:           specVolumeName,
		volDataKey.volHandle:           volumeID,
		volDataKey.driverName:          driverName,
		volDataKey.nodeName:            nodeName,
		volDataKey.attachmentID:        getAttachmentName(volumeID, driverName, nodeName),
		volDataKey.volumeLifecycleMode: lifecycleMode,
		volDataKey.seLinuxMountContext: seLinuxMountContext,
	}
	if err := os.MkdirAll(mountPath, 0755); err != nil {
		return fmt.Errorf("failed to create dir for volume info file: %s", err)
	}
	if err := saveVolumeData(mountPath, volDataFileName, volData); err != nil {
		return fmt.Errorf("failed to save volume info file: %s", err)
	}
	return nil
}

func TestMounterGetPath(t *testing.T) {
	plug, tmpDir := newTestPlugin(t, nil)
	defer os.RemoveAll(tmpDir)

	// TODO (vladimirvivien) specName with slashes will not work
	testCases := []struct {
		name           string
		specVolumeName string
		path           string
	}{
		{
			name:           "simple specName",
			specVolumeName: "spec-0",
			path:           filepath.Join(tmpDir, fmt.Sprintf("pods/%s/volumes/kubernetes.io~csi/%s/%s", testPodUID, "spec-0", "/mount")),
		},
		{
			name:           "specName with dots",
			specVolumeName: "test.spec.1",
			path:           filepath.Join(tmpDir, fmt.Sprintf("pods/%s/volumes/kubernetes.io~csi/%s/%s", testPodUID, "test.spec.1", "/mount")),
		},
	}
	for _, tc := range testCases {
		t.Logf("test case: %s", tc.name)
		registerFakePlugin(testDriver, "endpoint", []string{"1.0.0"}, t)
		pv := makeTestPV(tc.specVolumeName, 10, testDriver, testVol)
		spec := volume.NewSpecFromPersistentVolume(pv, pv.Spec.PersistentVolumeSource.CSI.ReadOnly)
		mounter, err := plug.NewMounter(
			spec,
			&corev1.Pod{ObjectMeta: meta.ObjectMeta{UID: testPodUID, Namespace: testns}},
			volume.VolumeOptio
    
func TestMounterSetUpSimple(t *testing.T) {
	fakeClient := fakeclient.NewSimpleClientset()
	plug, tmpDir := newTestPlugin(t, fakeClient)
	transientError := volumetypes.NewTransientOperationFailure("")
	defer os.RemoveAll(tmpDir)

	testCases := []struct {
		name                 string
		podUID               types.UID
		mode                 storage.VolumeLifecycleMode
		fsType               string
		options              []string
		spec                 func(string, []string) *volume.Spec
		newMounterShouldFail bool
		setupShouldFail      bool
		unsetClient          bool
		exitError            error
	}{
		{
			name:            "setup with ephemeral source",
			podUID:          types.UID(fmt.Sprintf("%08X", rand.Uint64())),
			mode:            storage.VolumeLifecycleEphemeral,
			fsType:          "ext4",
			setupShouldFail: true,
			spec: func(fsType string, options []string) *volume.Spec {
				volSrc := makeTestVol("pv1", testDriver)
				volSrc.CSI.FSType = &fsType
				return volume.NewSpecFromVolume(volSrc)
			},
		},
		{
			name:   "setup with persistent source",
			podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
			mode:   storage.VolumeLifecyclePersistent,
			fsType: "zfs",
			spec: func(fsType string, options []string) *volume.Spec {
				pvSrc := makeTestPV("pv1", 20, testDriver, "vol1")
				pvSrc.Spec.CSI.FSType = fsType
				pvSrc.Spec.MountOptions = options
				return volume.NewSpecFromPersistentVolume(pvSrc, false)
			},
		},
		{
			name:   "setup with persistent source without unspecified fstype and options",
			podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
			mode:   storage.VolumeLifecyclePersistent,
			spec: func(fsType string, options []string) *volume.Spec {
				return volume.NewSpecFromPersistentVolume(makeTestPV("pv1", 20, testDriver, "vol2"), false)
			},
		},
		{
			name:                 "setup with missing spec",
			newMounterShouldFail: true,
			spec:                 func(fsType string, options []string) *volume.Spec { return nil },
		},
		{
			name:   "setup with unknown CSI driver",
			podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
			mode:   storage.VolumeLifecyclePersistent,
			fsType: "zfs",
			spec: func(fsType string, options []string) *volume.Spec {
				pvSrc := makeTestPV("pv1", 20, "unknown-driver", "vol1")
				pvSrc.Spec.CSI.FSType = fsType
				pvSrc.Spec.MountOptions = options
				return volume.NewSpecFromPersistentVolume(pvSrc, false)
			},
			setupShouldFail: true,
			unsetClient:     true,
			exitError:       transientError,
		},
	}

	for _, tc := range testCases {
		registerFakePlugin(testDriver, "endpoint", []string{"1.0.0"}, t)
		t.Run(tc.name, func(t *testing.T) {
			mounter, err := plug.NewMounter(
				tc.spec(tc.fsType, tc.options),
				&corev1.Pod{ObjectMeta: meta.ObjectMeta{UID: tc.podUID, Namespace: testns}},
				volume.VolumeOptions{},
			)
			if tc.newMounterShouldFail && err != nil {
				t.Log(err)
				return
			}
			if !tc.newMounterShouldFail && err != nil {
				t.Fatal("unexpected error:", err)
			}
			if mounter == nil {
				t.Fatal("failed to create CSI mounter")
			}

			csiMounter := mounter.(*csiMountMgr)
			csiMounter.csiClient = setupClient(t, true)

			if csiMounter.volumeLifecycleMode != tc.mode {
				t.Fatal("unexpected volume mode: ", csiMounter.volumeLifecycleMode)
			}

			attachID := getAttachmentName(csiMounter.volumeID, string(csiMounter.driverName), string(plug.host.GetNodeName()))
			attachment := makeTestAttachment(attachID, "test-node", csiMounter.spec.Name())
			_, err = csiMounter.k8s.StorageV1().VolumeAttachments().Create(context.TODO(), attachment, meta.CreateOptions{})
			if err != nil {
				t.Fatalf("failed to setup VolumeAttachment: %v", err)
			}

			if tc.unsetClient {
				// Clear out the clients
				csiMounter.csiClient = nil
				csiMounter.csiClientGetter.csiClient = nil
				t.Log("driver name is ", csiMounter.csiClientGetter.driverName)
			}

			// Mounter.SetUp()
			err = csiMounter.SetUp(volume.MounterArgs{})
			if tc.setupShouldFail {
				if err != nil {
					if tc.exitError != nil && reflect.TypeOf(tc.exitError) != reflect.TypeOf(err) {
						t.Fatalf("expected exitError type: %v got: %v (%v)", reflect.TypeOf(tc.exitError), reflect.TypeOf(err), err)
					}
					t.Log(err)
					return
				} else {
					t.Error("test should fail, but no error occurred")
				}
			} else if err != nil {
				t.Fatal("unexpected error:", err)
			}

			// ensure call went all the way
			pubs := csiMounter.csiClient.(*fakeCsiDriverClient).nodeClient.GetNodePublishedVolumes()
			vol, ok := pubs[csiMounter.volumeID]
			if !ok {
				t.Error("csi server may not have received NodePublishVolume call")
			}
			if vol.VolumeHandle != csiMounter.volumeID {
				t.Error("volumeHandle not sent to CSI driver properly")
			}

			devicePath, err := makeDeviceMountPath(plug, csiMounter.spec)
			if err != nil {
				t.Fatal(err)
			}
			if vol.DeviceMountPath != devicePath {
				t.Errorf("DeviceMountPath not sent properly to CSI driver: %s, %s", vol.DeviceMountPath, devicePath)
			}

			if !reflect.DeepEqual(vol.MountFlags, csiMounter.spec.PersistentVolume.Spec.MountOptions) {
				t.Errorf("unexpected mount flags passed to driver: %+v", vol.MountFlags)
			}

			if vol.FSType != tc.fsType {
				t.Error("unexpected FSType sent to driver:", vol.FSType)
			}

			if vol.Path != csiMounter.GetPath() {
				t.Error("csi server may not have received NodePublishVolume call")
			}

			// ensure data file is created
			dataDir := filepath.Dir(mounter.GetPath())
			dataFile := filepath.Join(dataDir, volDataFileName)
			if _, err := os.Stat(dataFile); err != nil {
				if os.IsNotExist(err) {
					t.Errorf("data file not created %s", dataFile)
				} else {
					t.Fatal(err)
				}
			}
			data, err := loadVolumeData(dataDir, volDataFileName)
			if err != nil {
				t.Fatal(err)
			}
			if data[volDataKey.specVolID] != csiMounter.spec.Name() {
				t.Error("volume data file unexpected specVolID:", data[volDataKey.specVolID])
			}
			if data[volDataKey.volHandle] != csiMounter.volumeID {
				t.Error("volume data file unexpected volHandle:", data[volDataKey.volHandle])
			}
			if data[volDataKey.driverName] != string(csiMounter.driverName) {
				t.Error("volume data file unexpected driverName:", data[volDataKey.driverName])
			}
			if data[volDataKey.nodeName] != string(csiMounter.plugin.host.GetNodeName()) {
				t.Error("volume data file unexpected nodeName:", data[volDataKey.nodeName])
			}
			if data[volDataKey.volumeLifecycleMode] != string(tc.mode) {
				t.Error("volume data file unexpected volumeLifecycleMode:", data[volDataKey.volumeLifecycleMode])
			}
		})
	}
}