text:
package testing

import (
	"context"
	"fmt"
	"net"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"testing"
	"time"

	"k8s.io/utils/exec"
	testingexec "k8s.io/utils/exec/testing"
	"k8s.io/utils/mount"
	utilstrings "k8s.io/utils/strings"

	authenticationv1 "k8s.io/api/authentication/v1"
	v1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/types"
	"k8s.io/apimachinery/pkg/util/uuid"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/client-go/informers"
	clientset "k8s.io/client-go/kubernetes"
	storagelistersv1 "k8s.io/client-go/listers/storage/v1"
	"k8s.io/client-go/tools/cache"
	"k8s.io/client-go/tools/record"
	utiltesting "k8s.io/client-go/util/testing"
	cloudprovider "k8s.io/cloud-provider"
	. "k8s.io/kubernetes/pkg/volume"
	"k8s.io/kubernetes/pkg/volume/util"
	"k8s.io/kubernetes/pkg/volume/util/hostutil"
	"k8s.io/kubernetes/pkg/volume/util/recyclerclient"
	"k8s.io/kubernetes/pkg/volume/util/subpath"
	volumetypes "k8s.io/kubernetes/pkg/volume/util/types"
	"k8s.io/kubernetes/pkg/volume/util/volumepathhandler"
)

const (
	// A hook specified in storage class to indicate it's provisioning
	// is expected to fail.
	ExpectProvisionFailureKey = "expect-provision-failure"
	// The node is marked as uncertain. The attach operation will fail and return timeout error
	// for the first attach call. The following call will return sucesssfully.
	UncertainAttachNode = "uncertain-attach-node"
	// The node is marked as timeout. The attach operation will always fail and return timeout error
	// but the operation is actually succeeded.
	TimeoutAttachNode = "timeout-attach-node"
	// The node is marked as multi-attach which means it is allowed to attach the volume to multiple nodes.
	MultiAttachNode = "multi-attach-node"
	// TimeoutOnSetupVolumeName will cause Setup call to timeout but volume will finish mounting.
	TimeoutOnSetupVolumeName = "timeout-setup-volume"
	// FailOnSetupVolumeName will cause setup call to fail
	FailOnSetupVolumeName = "fail-setup-volume"
	//TimeoutAndFailOnSetupVolumeName will first timeout and then fail the setup
	TimeoutAndFailOnSetupVolumeName = "timeout-and-fail-setup-volume"
	// SuccessAndTimeoutSetupVolumeName will cause first mount operation to succeed but subsequent attempts to timeout
	SuccessAndTimeoutSetupVolumeName = "success-and-timeout-setup-volume-name"
	// SuccessAndFailOnSetupVolumeName will cause first mount operation to succeed but subsequent attempts to fail
	SuccessAndFailOnSetupVolumeName = "success-and-failed-setup-device-name"

	// TimeoutOnMountDeviceVolumeName will cause MountDevice call to timeout but Setup will finish.
	TimeoutOnMountDeviceVolumeName = "timeout-mount-device-volume"
	// TimeoutAndFailOnMountDeviceVolumeName will cause first MountDevice call to timeout but second call will fail
	TimeoutAndFailOnMountDeviceVolumeName = "timeout-and-fail-mount-device-name"
	// FailMountDeviceVolumeName will cause MountDevice operation on volume to fail
	FailMountDeviceVolumeName = "fail-mount-device-volume-name"
	// SuccessAndTimeoutDeviceName will cause first mount operation to succeed but subsequent attempts to timeout
	SuccessAndTimeoutDeviceName = "success-and-timeout-device-name"
	// SuccessAndFailOnMountDeviceName will cause first mount operation to succeed but subsequent attempts to fail
	SuccessAndFailOnMountDeviceName = "success-and-failed-mount-device-name"

	deviceNotMounted     = "deviceNotMounted"
	deviceMountUncertain = "deviceMountUncertain"
	deviceMounted        = "deviceMounted"

	volumeNotMounted     = "volumeNotMounted"
	volumeMountUncertain = "volumeMountUncertain"
	volumeMounted        = "volumeMounted"
)

// fakeVolumeHost is useful for testing volume plugins.
type fakeVolumeHost struct {
	rootDir         string
	kubeClient      clientset.Interface
	pluginMgr       *VolumePluginMgr
	cloud           cloudprovider.Interface
	mounter         mount.Interface
	hostUtil        hostutil.HostUtils
	exec            *testingexec.FakeExec
	nodeLabels      map[string]string
	nodeName        string
	subpather       subpath.Interface
	csiDriverLister storagelistersv1.CSIDriverLister
	informerFactory informers.SharedInformerFactory
	kubeletErr      error
	mux             sync.Mutex
}

var _ VolumeHost = &fakeVolumeHost{}
var _ AttachDetachVolumeHost = &fakeVolumeHost{}

func NewFakeVolumeHost(t *testing.T, rootDir string, kubeClient clientset.Interface, plugins []VolumePlugin) *fakeVolumeHost {
	return newFakeVolumeHost(t, rootDir, kubeClient, plugins, nil, nil, "", nil)
}

func NewFakeVolumeHostWithCloudProvider(t *testing.T, rootDir string, kubeClient clientset.Interface, plugins []VolumePlugin, cloud cloudprovider.Interface) *fakeVolumeHost {
	return newFakeVolumeHost(t, rootDir, kubeClient, plugins, cloud, nil, "", nil)
}

func NewFakeVolumeHostWithNodeLabels(t *testing.T, rootDir string, kubeClient clientset.Interface, plugins []VolumePlugin, labels map[string]string) *fakeVolumeHost {
	volHost := newFakeVolumeHost(t, rootDir, kubeClient, plugins, nil, nil, "", nil)
	volHost.nodeLabels = labels
	return volHost
}

func NewFakeVolumeHostWithCSINodeName(t *testing.T, rootDir string, kubeClient clientset.Interface, plugins []VolumePlugin, nodeName string, driverLister storagelistersv1.CSIDriverLister) *fakeVolumeHost {
	return newFakeVolumeHost(t, rootDir, kubeClient, plugins, nil, nil, nodeName, driverLister)
}

func NewFakeVolumeHostWithMounterFSType(t *testing.T, rootDir string, kubeClient clientset.Interface, plugins []VolumePlugin, pathToTypeMap map[string]hostutil.FileType) *fakeVolumeHost {
	return newFakeVolumeHost(t, rootDir, kubeClient, plugins, nil, pathToTypeMap, "", nil)
}

func newFakeVolumeHost(t *testing.T, rootDir string, kubeClient clientset.Interface, plugins []VolumePlugin, cloud cloudprovider.Interface, pathToTypeMap map[string]hostutil.FileType, nodeName string, driverLister storagelistersv1.CSIDriverLister) *fakeVolumeHost {
	host := &fakeVolumeHost{rootDir: rootDir, kubeClient: kubeClient, cloud: cloud, nodeName: nodeName, csiDriverLister: driverLister}
	host.mounter = mount.NewFakeMounter(nil)
	host.hostUtil = hostutil.NewFakeHostUtil(pathToTypeMap)
	host.exec = &testingexec.FakeExec{DisableScripts: true}
	host.pluginMgr = &VolumePluginMgr{}
	if err := host.pluginMgr.InitPlugins(plugins, nil /* prober */, host); err != nil {
		t.Fatalf("Failed to init plugins while creating fake volume host: %v", err)
	}
	host.subpather = &subpath.FakeSubpath{}
	host.informerFactory = informers.NewSharedInformerFactory(kubeClient, time.Minute)
	// Wait until the InitPlugins setup is finished before returning from this setup func
	if err := host.WaitForKubeletErrNil(); err != nil {
		t.Fatalf("Failed to wait for kubelet err to be nil while creating fake volume host: %v", err)
	}
	return host
}

func (f *fakeVolumeHost) GetPluginDir(podUID string) string {
	return filepath.Join(f.rootDir, "plugins", podUID)
}

func (f *fakeVolumeHost) GetVolumeDevicePluginDir(pluginName string) string {
	return filepath.Join(f.rootDir, "plugins", pluginName, "volumeDevices")
}

func (f *fakeVolumeHost) GetPodsDir() string {
	return filepath.Join(f.rootDir, "pods")
}

func (f *fakeVolumeHost) GetPodVolumeDir(podUID types.UID, pluginName, volumeName string) string {
	return filepath.Join(f.rootDir, "pods", string(podUID), "volumes", pluginName, volumeName)
}

func (f *fakeVolumeHost) GetPodVolumeDeviceDir(podUID types.UID, pluginName string) string {
	return filepath.Join(f.rootDir, "pods", string(podUID), "volumeDevices", pluginName)
}

func (f *fakeVolumeHost) GetPodPluginDir(podUID types.UID, pluginName string) string {
	return filepath.Join(f.rootDir, "pods", string(podUID), "plugins", pluginName)
}

func (f *fakeVolumeHost) GetKubeClient() clientset.Interface {
	return f.kubeClient
}

func (f *fakeVolumeHost) GetCloudProvider() cloudprovider.Interface {
	return f.cloud
}

func (f *fakeVolumeHost) GetMounter(pluginName string) mount.Interface {
	return f.mounter
}

func (f *fakeVolumeHost) GetHostUtil() hostutil.HostUtils {
	return f.hostUtil
}

func (f *fakeVolumeHost) GetSubpather() subpath.Interface {
	return f.subpather
}

func (f *fakeVolumeHost) GetPluginMgr() *VolumePluginMgr {
	return f.pluginMgr
}

func (f *fakeVolumeHost) NewWrapperMounter(volName string, spec Spec, pod *v1.Pod, opts VolumeOptions) (Mounter, error) {
	// The name of wrapper volume is set to "wrapped_{wrapped_volume_name}"
	wrapperVolumeName := "wrapped_" + volName
	if spec.Volume != nil {
		spec.Volume.Name = wrapperVolumeName
	}
	plug, err := f.pluginMgr.FindPluginBySpec(&spec)
	if err != nil {
		return nil, err
	}
	return plug.NewMounter(&spec, pod, opts)
}

func (f *fakeVolumeHost) NewWrapperUnmounter(volName string, spec Spec, podUID types.UID) (Unmounter, error) {
	// The name of wrapper volume is set to "wrapped_{wrapped_volume_name}"
	wrapperVolumeName := "wrapped_" + volName
	if spec.Volume != nil {
		spec.Volume.Name = wrapperVolumeName
	}
	plug, err := f.pluginMgr.FindPluginBySpec(&spec)
	if err != nil {
		return nil, err
	}
	return plug.NewUnmounter(spec.Name(), podUID)
}

// Returns the hostname of the host kubelet is running on
func (f *fakeVolumeHost) GetHostName() string {
	return "fakeHostName"
}

// Returns host IP or nil in the case of error.
func (f *fakeVolumeHost) GetHostIP() (net.IP, error) {
	return nil, fmt.Errorf("GetHostIP() not implemented")
}

func (f *fakeVolumeHost) GetNodeAllocatable() (v1.ResourceList, error) {
	return v1.ResourceList{}, nil
}

func (f *fakeVolumeHost) GetSecretFunc() func(namespace, name string) (*v1.Secret, error) {
	return func(namespace, name string) (*v1.Secret, error) {
		return f.kubeClient.CoreV1().Secrets(namespace).Get(context.TODO(), name, metav1.GetOptions{})
	}
}

func (f *fakeVolumeHost) GetExec(pluginName string) exec.Interface {
	return f.exec
}

func (f *fakeVolumeHost) GetConfigMapFunc() func(namespace, name string) (*v1.ConfigMap, error) {
	return func(namespace, name string) (*v1.ConfigMap, error) {
		return f.kubeClient.CoreV1().ConfigMaps(namespace).Get(context.TODO(), name, metav1.GetOptions{})
	}
}

func (f *fakeVolumeHost) GetServiceAccountTokenFunc() func(string, string, *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) {
	return func(namespace, name string, tr *authenticationv1.TokenRequest) (*authenticationv1.TokenRequest, error) {
		return f.kubeClient.CoreV1().ServiceAccounts(namespace).CreateToken(context.TODO(), name, tr, metav1.CreateOptions{})
	}
}

func (f *fakeVolumeHost) DeleteServiceAccountTokenFunc() func(types.UID) {
	return func(types.UID) {}
}

func (f *fakeVolumeHost) GetNodeLabels() (map[string]string, error) {
	if f.nodeLabels == nil {
		f.nodeLabels = map[string]string{"test-label": "test-value"}
	}
	return f.nodeLabels, nil
}

func (f *fakeVolumeHost) GetNodeName() types.NodeName {
	return types.NodeName(f.nodeName)
}

func (f *fakeVolumeHost) GetEventRecorder() record.EventRecorder {
	return nil
}

func (f *fakeVolumeHost) ScriptCommands(scripts []CommandScript) {
	ScriptCommands(f.exec, scripts)
}

// CommandScript is used to pre-configure a command that will be executed and
// optionally set it's output (stdout and stderr combined) and return code.
type CommandScript struct {
	// Cmd is the command to execute, e.g. "ls"
	Cmd string
	// Args is a slice of arguments to pass to the command, e.g. "-a"
	Args []string
	// Output is the combined stdout and stderr of the command to return
	Output string
	// ReturnCode is the exit code for the command. Setting this to non-zero will
	// cause the command to return an error with this exit code set.
	ReturnCode int
}

// ScriptCommands configures fe, the FakeExec, to have a pre-configured list of
// commands to expect. Calling more commands using fe than those scripted will
// result in a panic. By default, the fe does not enforce command argument checking
// or order -- if you have given an Output to the command, the first command scripted
// will return its output on the first command call, even if the command called is
// different than the one scripted. This is mostly useful to make sure that the
// right number of commands were called. If you want to check the exact commands
// and arguments were called, set fe.ExectOrder to true.
func ScriptCommands(fe *testingexec.FakeExec, scripts []CommandScript) {
	fe.DisableScripts = false
	for _, script := range scripts {
		fakeCmd := &testingexec.FakeCmd{}
		cmdAction := makeFakeCmd(fakeCmd, script.Cmd, script.Args...)
		outputAction := makeFakeOutput(script.Output, script.ReturnCode)
		fakeCmd.CombinedOutputScript = append(fakeCmd.CombinedOutputScript, outputAction)
		fe.CommandScript = append(fe.CommandScript, cmdAction)
	}
}

func makeFakeCmd(fakeCmd *testingexec.FakeCmd, cmd string, args ...string) testingexec.FakeCommandAction {
	fc := fakeCmd
	c := cmd
	a := args
	return func(cmd string, args ...string) exec.Cmd {
		command := testingexec.InitFakeCmd(fc, c, a...)
		return command
	}
}

func makeFakeOutput(output string, rc int) testingexec.FakeAction {
	o := output
	var e error
	if rc != 0 {
		e = testingexec.FakeExitError{Status: rc}
	}
	return func() ([]byte, []byte, error) {
		return []byte(o), nil, e
	}
}

func ProbeVolumePlugins(config VolumeConfig) []VolumePlugin {
	if _, ok := config.OtherAttributes["fake-property"]; ok {
		return []VolumePlugin{
			&FakeVolumePlugin{
				PluginName: "fake-plugin",
				Host:       nil,
				// SomeFakeProperty: config.OtherAttributes["fake-property"] -- string, may require parsing by plugin
			},
		}
	}
	return []VolumePlugin{&FakeVolumePlugin{PluginName: "fake-plugin"}}
}

// FakeVolumePlugin is useful for testing.  It tries to be a fully compliant
// plugin, but all it does is make empty directories.
// Use as:
//   volume.RegisterPlugin(&FakePlugin{"fake-name"})
type FakeVolumePlugin struct {
	sync.RWMutex
	PluginName             string
	Host                   VolumeHost
	Config                 VolumeConfig
	LastProvisionerOptions VolumeOptions
	NewAttacherCallCount   int
	NewDetacherCallCount   int
	VolumeLimits           map[string]int64
	VolumeLimitsError      error
	LimitKey               string
	ProvisionDelaySeconds  int
	SupportsRemount        bool

	// Add callbacks as needed
	WaitForAttachHook func(spec *Spec, devicePath string, pod *v1.Pod, spectimeout time.Duration) (string, error)
	UnmountDeviceHook func(globalMountPath string) error

	Mounters             []*FakeVolume
	Unmounters           []*FakeVolume
	Attachers            []*FakeVolume
	Detachers            []*FakeVolume
	BlockVolumeMappers   []*FakeVolume
	BlockVolumeUnmappers []*FakeVolume
}

var _ VolumePlugin = &FakeVolumePlugin{}
var _ BlockVolumePlugin = &FakeVolumePlugin{}
var _ RecyclableVolumePlugin = &FakeVolumePlugin{}
var _ DeletableVolumePlugin = &FakeVolumePlugin{}
var _ ProvisionableVolumePlugin = &FakeVolumePlugin{}
var _ AttachableVolumePlugin = &FakeVolumePlugin{}
var _ VolumePluginWithAttachLimits = &FakeVolumePlugin{}
var _ DeviceMountableVolumePlugin = &FakeVolumePlugin{}
var _ NodeExpandableVolumePlugin = &FakeVolumePlugin{}

func (plugin *FakeVolumePlugin) getFakeVolume(list *[]*FakeVolume) *FakeVolume {
	volumeList := *list
	if list != nil && len(volumeList) > 0 {
		volume := volumeList[0]
		volume.Lock()
		defer volume.Unlock()
		volume.WaitForAttachHook = plugin.WaitForAttachHook
		volume.UnmountDeviceHook = plugin.UnmountDeviceHook
		return volume
	}
	volume := &FakeVolume{
		WaitForAttachHook: plugin.WaitForAttachHook,
		UnmountDeviceHook: plugin.UnmountDeviceHook,
	}
	volume.VolumesAttached = make(map[string]types.NodeName)
	volume.DeviceMountState = make(map[string]string)
	volume.VolumeMountState = make(map[string]string)
	*list = append(*list, volume)
	return volume
}

func (plugin *FakeVolumePlugin) Init(host VolumeHost) error {
	plugin.Lock()
	defer plugin.Unlock()
	plugin.Host = host
	return nil
}

func (plugin *FakeVolumePlugin) GetPluginName() string {
	plugin.RLock()
	defer plugin.RUnlock()
	return plugin.PluginName
}

func (plugin *FakeVolumePlugin) GetVolumeName(spec *Spec) (string, error) {
	var volumeName string
	if spec.Volume != nil && spec.Volume.GCEPersistentDisk != nil {
		volumeName = spec.Volume.GCEPersistentDisk.PDName
	} else if spec.PersistentVolume != nil &&
		spec.PersistentVolume.Spec.GCEPersistentDisk != nil {
		volumeName = spec.PersistentVolume.Spec.GCEPersistentDisk.PDName
	}
	if volumeName == "" {
		volumeName = spec.Name()
	}
	return volumeName, nil
}

func (plugin *FakeVolumePlugin) CanSupport(spec *Spec) bool {
	// TODO: maybe pattern-match on spec.Name() to decide?
	return true
}

func (plugin *FakeVolumePlugin) RequiresRemount() bool {
	return plugin.SupportsRemount
}

func (plugin *FakeVolumePlugin) SupportsMountOption() bool {
	return true
}

func (plugin *FakeVolumePlugin) SupportsBulkVolumeVerification() bool {
	return false
}

func (plugin *FakeVolumePlugin) NewMounter(spec *Spec, pod *v1.Pod, opts VolumeOptions) (Mounter, error) {
	plugin.Lock()
	defer plugin.Unlock()
	volume := plugin.getFakeVolume(&plugin.Mounters)
	volume.Lock()
	defer volume.Unlock()
	volume.PodUID = pod.UID
	volume.VolName = spec.Name()
	volume.Plugin = plugin
	volume.MetricsNil = MetricsNil{}
	return volume, nil
}

func (plugin *FakeVolumePlugin) GetMounters() (Mounters []*FakeVolume) {
	plugin.RLock()
	defer plugin.RUnlock()
	return plugin.Mounters
}

func (plugin *FakeVolumePlugin) NewUnmounter(volName string, podUID types.UID) (Unmounter, error) {
	plugin.Lock()
	defer plugin.Unlock()
	volume := plugin.getFakeVolume(&plugin.Unmounters)
	volume.Lock()
	defer volume.Unlock()
	volume.PodUID = podUID
	volume.VolName = volName
	volume.Plugin = plugin
	volume.MetricsNil = MetricsNil{}
	return volume, nil
}

func (plugin *FakeVolumePlugin) GetUnmounters() (Unmounters []*FakeVolume) {
	plugin.RLock()
	defer plugin.RUnlock()
	return plugin.Unmounters
}

// Block volume support
func (plugin *FakeVolumePlugin) NewBlockVolumeMapper(spec *Spec, pod *v1.Pod, opts VolumeOptions) (BlockVolumeMapper, error) {
	plugin.Lock()
	defer plugin.Unlock()
	volume := plugin.getFakeVolume(&plugin.BlockVolumeMappers)
	volume.Lock()
	defer volume.Unlock()
	if pod != nil {
		volume.PodUID = pod.UID
	}
	volume.VolName = spec.Name()
	volume.Plugin = plugin
	return volume, nil
}

// Block volume support
func (plugin *FakeVolumePlugin) GetBlockVolumeMapper() (BlockVolumeMappers []*FakeVolume) {
	plugin.RLock()
	defer plugin.RUnlock()
	return plugin.BlockVolumeMappers
}

// Block volume support
func (plugin *FakeVolumePlugin) NewBlockVolumeUnmapper(volName string, podUID types.UID) (BlockVolumeUnmapper, error) {
	plugin.Lock()
	defer plugin.Unlock()
	volume := plugin.getFakeVolume(&plugin.BlockVolumeUnmappers)
	volume.Lock()
	defer volume.Unlock()
	volume.PodUID = podUID
	volume.VolName = volName
	volume.Plugin = plugin
	return volume, nil
}

// Block volume support
func (plugin *FakeVolumePlugin) GetBlockVolumeUnmapper() (BlockVolumeUnmappers []*FakeVolume) {
	plugin.RLock()
	defer plugin.RUnlock()
	return plugin.BlockVolumeUnmappers
}

func (plugin *FakeVolumePlugin) NewAttacher() (Attacher, error) {
	plugin.Lock()
	defer plugin.Unlock()
	plugin.NewAttacherCallCount = plugin.NewAttacherCallCount + 1
	return plugin.getFakeVolume(&plugin.Attachers), nil
}

func (plugin *FakeVolumePlugin) NewDeviceMounter() (DeviceMounter, error) {
	return plugin.NewAttacher()
}

func (plugin *FakeVolumePlugin) GetAttachers() (Attachers []*FakeVolume) {
	plugin.RLock()
	defer plugin.RUnlock()
	return plugin.Attachers
}

func (plugin *FakeVolumePlugin) GetNewAttacherCallCount() int {
	plugin.RLock()
	defer plugin.RUnlock()
	return plugin.NewAttacherCallCount
}

func (plugin *FakeVolumePlugin) NewDetacher() (Detacher, error) {
	plugin.Lock()
	defer plugin.Unlock()
	plugin.NewDetacherCallCount = plugin.NewDetacherCallCount + 1
	detacher := plugin.getFakeVolume(&plugin.Detachers)
	attacherList := plugin.Attachers
	if attacherList != nil && len(attacherList) > 0 {
		detacherList := plugin.Detachers
		if detacherList != nil && len(detacherList) > 0 {
			detacherList[0].VolumesAttached = attacherList[0].VolumesAttached
		}

	}
	return detacher, nil
}

func (plugin *FakeVolumePlugin) NewDeviceUnmounter() (DeviceUnmounter, error) {
	return plugin.NewDetacher()
}

func (plugin *FakeVolumePlugin) GetDetachers() (Detachers []*FakeVolume) {
	plugin.RLock()
	defer plugin.RUnlock()
	return plugin.Detachers
}

func (plugin *FakeVolumePlugin) GetNewDetacherCallCount() int {
	plugin.RLock()
	defer plugin.RUnlock()
	return plugin.NewDetacherCallCount
}

func (plugin *FakeVolumePlugin) CanAttach(spec *Spec) (bool, error) {
	return true, nil
}

func (plugin *FakeVolumePlugin) CanDeviceMount(spec *Spec) (bool, error) {
	return true, nil
}

func (plugin *FakeVolumePlugin) Recycle(pvName string, spec *Spec, eventRecorder recyclerclient.RecycleEventRecorder) error {
	return nil
}

func (plugin *FakeVolumePlugin) NewDeleter(spec *Spec) (Deleter, error) {
	return &FakeDeleter{"/attributesTransferredFromSpec", MetricsNil{}}, nil
}

func (plugin *FakeVolumePlugin) NewProvisioner(options VolumeOptions) (Provisioner, error) {
	plugin.Lock()
	defer plugin.Unlock()
	plugin.LastProvisionerOptions = options
	return &FakeProvisioner{options, plugin.Host, plugin.ProvisionDelaySeconds}, nil
}

func (plugin *FakeVolumePlugin) GetAccessModes() []v1.PersistentVolumeAccessMode {
	return []v1.PersistentVolumeAccessMode{}
}

func (plugin *FakeVolumePlugin) ConstructVolumeSpec(volumeName, mountPath string) (*Spec, error) {
	return &Spec{
		Volume: &v1.Volume{
			Name: volumeName,
		},
	}, nil
}

// Block volume support
func (plugin *FakeVolumePlugin) ConstructBlockVolumeSpec(podUID types.UID, volumeName, mountPath string) (*Spec, error) {
	return &Spec{
		Volume: &v1.Volume{
			Name: volumeName,
		},
	}, nil
}

func (plugin *FakeVolumePlugin) GetDeviceMountRefs(deviceMountPath string) ([]string, error) {
	return []string{}, nil
}

// Expandable volume support
func (plugin *FakeVolumePlugin) ExpandVolumeDevice(spec *Spec, newSize resource.Quantity, oldSize resource.Quantity) (resource.Quantity, error) {
	return resource.Quantity{}, nil
}

func (plugin *FakeVolumePlugin) RequiresFSResize() bool {
	return true
}

func (plugin *FakeVolumePlugin) NodeExpand(resizeOptions NodeResizeOptions) (bool, error) {
	return true, nil
}

func (plugin *FakeVolumePlugin) GetVolumeLimits() (map[string]int64, error) {
	return plugin.VolumeLimits, plugin.VolumeLimitsError
}

func (plugin *FakeVolumePlugin) VolumeLimitKey(spec *Spec) string {
	return plugin.LimitKey
}

// FakeBasicVolumePlugin implements a basic volume plugin. It wrappers on
// FakeVolumePlugin but implements VolumePlugin interface only.
// It is useful to test logic involving plugin interfaces.
type FakeBasicVolumePlugin struct {
	Plugin FakeVolumePlugin
}

func (f *FakeBasicVolumePlugin) GetPluginName() string {
	return f.Plugin.GetPluginName()
}

func (f *FakeBasicVolumePlugin) GetVolumeName(spec *Spec) (string, error) {
	return f.Plugin.GetVolumeName(spec)
}

// CanSupport tests whether the plugin supports a given volume specification by
// testing volume spec name begins with plugin name or not.
// This is useful to choose plugin by volume in testing.
func (f *FakeBasicVolumePlugin) CanSupport(spec *Spec) bool {
	return strings.HasPrefix(spec.Name(), f.GetPluginName())
}

func (f *FakeBasicVolumePlugin) ConstructVolumeSpec(ame, mountPath string) (*Spec, error) {
	return f.Plugin.ConstructVolumeSpec(ame, mountPath)
}

func (f *FakeBasicVolumePlugin) Init(ost VolumeHost) error {
	return f.Plugin.Init(ost)
}

func (f *FakeBasicVolumePlugin) NewMounter(spec *Spec, pod *v1.Pod, opts VolumeOptions) (Mounter, error) {
	return f.Plugin.NewMounter(spec, pod, opts)
}

func (f *FakeBasicVolumePlugin) NewUnmounter(volName string, podUID types.UID) (Unmounter, error) {
	return f.Plugin.NewUnmounter(volName, podUID)
}

func (f *FakeBasicVolumePlugin) RequiresRemount() bool {
	return f.Plugin.RequiresRemount()
}

func (f *FakeBasicVolumePlugin) SupportsBulkVolumeVerification() bool {
	return f.Plugin.SupportsBulkVolumeVerification()
}

func (f *FakeBasicVolumePlugin) SupportsMountOption() bool {
	return f.Plugin.SupportsMountOption()
}

var _ VolumePlugin = &FakeBasicVolumePlugin{}

// FakeDeviceMountableVolumePlugin implements an device mountable plugin based on FakeBasicVolumePlugin.
type FakeDeviceMountableVolumePlugin struct {
	FakeBasicVolumePlugin
}

func (f *FakeDeviceMountableVolumePlugin) CanDeviceMount(spec *Spec) (bool, error) {
	return true, nil
}

func (f *FakeDeviceMountableVolumePlugin) NewDeviceMounter() (DeviceMounter, error) {
	return f.Plugin.NewDeviceMounter()
}

func (f *FakeDeviceMountableVolumePlugin) NewDeviceUnmounter() (DeviceUnmounter, error) {
	return f.Plugin.NewDeviceUnmounter()
}

func (f *FakeDeviceMountableVolumePlugin) GetDeviceMountRefs(deviceMountPath string) ([]string, error) {
	return f.Plugin.GetDeviceMountRefs(deviceMountPath)
}

var _ VolumePlugin = &FakeDeviceMountableVolumePlugin{}
var _ DeviceMountableVolumePlugin = &FakeDeviceMountableVolumePlugin{}

// FakeAttachableVolumePlugin implements an attachable plugin based on FakeDeviceMountableVolumePlugin.
type FakeAttachableVolumePlugin struct {
	FakeDeviceMountableVolumePlugin
}

func (f *FakeAttachableVolumePlugin) NewAttacher() (Attacher, error) {
	return f.Plugin.NewAttacher()
}

func (f *FakeAttachableVolumePlugin) NewDetacher() (Detacher, error) {
	return f.Plugin.NewDetacher()
}

func (f *FakeAttachableVolumePlugin) CanAttach(spec *Spec) (bool, error) {
	return true, nil
}

var _ VolumePlugin = &FakeAttachableVolumePlugin{}
var _ AttachableVolumePlugin = &FakeAttachableVolumePlugin{}

type FakeFileVolumePlugin struct {
}

func (plugin *FakeFileVolumePlugin) Init(host VolumeHost) error {
	return nil
}

func (plugin *FakeFileVolumePlugin) GetPluginName() string {
	return "fake-file-plugin"
}

func (plugin *FakeFileVolumePlugin) GetVolumeName(spec *Spec) (string, error) {
	return "", nil
}

func (plugin *FakeFileVolumePlugin) CanSupport(spec *Spec) bool {
	return true
}

func (plugin *FakeFileVolumePlugin) RequiresRemount() bool {
	return false
}

func (plugin *FakeFileVolumePlugin) SupportsMountOption() bool {
	return false
}

func (plugin *FakeFileVolumePlugin) SupportsBulkVolumeVerification() bool {
	return false
}

func (plugin *FakeFileVolumePlugin) NewMounter(spec *Spec, podRef *v1.Pod, opts VolumeOptions) (Mounter, error) {
	return nil, nil
}

func (plugin *FakeFileVolumePlugin) NewUnmounter(name string, podUID types.UID) (Unmounter, error) {
	return nil, nil
}

func (plugin *FakeFileVolumePlugin) ConstructVolumeSpec(volumeName, mountPath string) (*Spec, error) {
	return nil, nil
}

func NewFakeFileVolumePlugin() []VolumePlugin {
	return []VolumePlugin{&FakeFileVolumePlugin{}}
}

type FakeVolume struct {
	sync.RWMutex
	PodUID  types.UID
	VolName string
	Plugin  *FakeVolumePlugin
	MetricsNil
	VolumesAttached  map[string]types.NodeName
	DeviceMountState map[string]string
	VolumeMountState map[string]string

	// Add callbacks as needed
	WaitForAttachHook func(spec *Spec, devicePath string, pod *v1.Pod, spectimeout time.Duration) (string, error)
	UnmountDeviceHook func(globalMountPath string) error

	SetUpCallCount              int
	TearDownCallCount           int
	AttachCallCount             int
	DetachCallCount             int
	WaitForAttachCallCount      int
	MountDeviceCallCount        int
	UnmountDeviceCallCount      int
	GetDeviceMountPathCallCount int
	SetUpDeviceCallCount        int
	TearDownDeviceCallCount     int
	MapPodDeviceCallCount       int
	UnmapPodDeviceCallCount     int
	GlobalMapPathCallCount      int
	PodDeviceMapPathCallCount   int
}

func getUniqueVolumeName(spec *Spec) (string, error) {
	var volumeName string
	if spec.Volume != nil && spec.Volume.GCEPersistentDisk != nil {
		volumeName = spec.Volume.GCEPersistentDisk.PDName
	} else if spec.PersistentVolume != nil &&
		spec.PersistentVolume.Spec.GCEPersistentDisk != nil {
		volumeName = spec.PersistentVolume.Spec.GCEPersistentDisk.PDName
	}
	if volumeName == "" {
		volumeName = spec.Name()
	}
	return volumeName, nil
}

func (_ *FakeVolume) GetAttributes() Attributes {
	return Attributes{
		ReadOnly:        false,
		Managed:         true,
		SupportsSELinux: true,
	}
}

func (fv *FakeVolume) CanMount() error {
	return nil
}

func (fv *FakeVolume) SetUp(mounterArgs MounterArgs) error {
	fv.Lock()
	defer fv.Unlock()
	err := fv.setupInternal(mounterArgs)
	fv.SetUpCallCount++
	return err
}

func (fv *FakeVolume) setupInternal(mounterArgs MounterArgs) error {
	if fv.VolName == TimeoutOnSetupVolumeName {
		fv.VolumeMountState[fv.VolName] = volumeMountUncertain
		return volumetypes.NewUncertainProgressError("time out on setup")
	}

	if fv.VolName == FailOnSetupVolumeName {
		fv.VolumeMountState[fv.VolName] = volumeNotMounted
		return fmt.Errorf("mounting volume failed")
	}

	if fv.VolName == TimeoutAndFailOnSetupVolumeName {
		_, ok := fv.VolumeMountState[fv.VolName]
		if !ok {
			fv.VolumeMountState[fv.VolName] = volumeMountUncertain
			return volumetypes.NewUncertainProgressError("time out on setup")
		}
		fv.VolumeMountState[fv.VolName] = volumeNotMounted
		return fmt.Errorf("mounting volume failed")

	}

	if fv.VolName == SuccessAndFailOnSetupVolumeName {
		_, ok := fv.VolumeMountState[fv.VolName]
		if ok {
			fv.VolumeMountState[fv.VolName] = volumeNotMounted
			return fmt.Errorf("mounting volume failed")
		}
	}

	if fv.VolName == SuccessAndTimeoutSetupVolumeName {
		_, ok := fv.VolumeMountState[fv.VolName]
		if ok {
			fv.VolumeMountState[fv.VolName] = volumeMountUncertain
			return volumetypes.NewUncertainProgressError("time out on setup")
		}
	}

	fv.VolumeMountState[fv.VolName] = volumeNotMounted
	return fv.SetUpAt(fv.getPath(), mounterArgs)
}

func (fv *FakeVolume) GetSetUpCallCount() int {
	fv.RLock()
	defer fv.RUnlock()
	return fv.SetUpCallCount
}

func (fv *FakeVolume) SetUpAt(dir string, mounterArgs MounterArgs) error {
	return os.MkdirAll(dir, 0750)
}

func (fv *FakeVolume) GetPath() string {
	fv.RLock()
	defer fv.RUnlock()
	return fv.getPath()
}

func (fv *FakeVolume) getPath() string {
	return filepath.Join(fv.Plugin.Host.GetPodVolumeDir(fv.PodUID, utilstrings.EscapeQualifiedName(fv.Plugin.PluginName), fv.VolName))
}

func (fv *FakeVolume) TearDown() error {
	fv.Lock()
	defer fv.Unlock()
	fv.TearDownCallCount++
	return fv.TearDownAt(fv.getPath())
}

func (fv *FakeVolume) GetTearDownCallCount() int {
	fv.RLock()
	defer fv.RUnlock()
	return fv.TearDownCallCount
}

func (fv *FakeVolume) TearDownAt(dir string) error {
	return os.RemoveAll(dir)
}

// Block volume support
func (fv *FakeVolume) SetUpDevice() error {
	fv.Lock()
	defer fv.Unlock()
	if fv.VolName == TimeoutOnMountDeviceVolumeName {
		fv.DeviceMountState[fv.VolName] = deviceMountUncertain
		return volumetypes.NewUncertainProgressError("mount failed")
	}
	if fv.VolName == FailMountDeviceVolumeName {
		fv.DeviceMountState[fv.VolName] = deviceNotMounted
		return fmt.Errorf("error mapping disk: %s", fv.VolName)
	}

	if fv.VolName == TimeoutAndFailOnMountDeviceVolumeName {
		_, ok := fv.DeviceMountState[fv.VolName]
		if !ok {
			fv.DeviceMountState[fv.VolName] = deviceMountUncertain
			return volumetypes.NewUncertainProgressError("timed out mounting error")
		}
		fv.DeviceMountState[fv.VolName] = deviceNotMounted
		return fmt.Errorf("error mapping disk: %s", fv.VolName)
	}

	if fv.VolName == SuccessAndTimeoutDeviceName {
		_, ok := fv.DeviceMountState[fv.VolName]
		if ok {
			fv.DeviceMountState[fv.VolName] = deviceMountUncertain
			return volumetypes.NewUncertainProgressError("error mounting state")
		}
	}
	if fv.VolName == SuccessAndFailOnMountDeviceName {
		_, ok := fv.DeviceMountState[fv.VolName]
		if ok {
			return fmt.Errorf("error mapping disk: %s", fv.VolName)
		}
	}

	fv.DeviceMountState[fv.VolName] = deviceMounted
	fv.SetUpDeviceCallCount++

	return nil
}

// Block volume support
func (fv *FakeVolume) GetSetUpDeviceCallCount() int {
	fv.RLock()
	defer fv.RUnlock()
	return fv.SetUpDeviceCallCount
}

// Block volume support
func (fv *FakeVolume) GetGlobalMapPath(spec *Spec) (string, error) {
	fv.RLock()
	defer fv.RUnlock()
	fv.GlobalMapPathCallCount++
	return fv.getGlobalMapPath()
}

// Block volume support
func (fv *FakeVolume) getGlobalMapPath() (string, error) {
	return filepath.Join(fv.Plugin.Host.GetVolumeDevicePluginDir(utilstrings.EscapeQualifiedName(fv.Plugin.PluginName)), "pluginDependentPath"), nil
}

// Block volume support
func (fv *FakeVolume) GetGlobalMapPathCallCount() int {
	fv.RLock()
	defer fv.RUnlock()
	return fv.GlobalMapPathCallCount
}

// Block volume support
func (fv *FakeVolume) GetPodDeviceMapPath() (string, string) {
	fv.RLock()
	defer fv.RUnlock()
	fv.PodDeviceMapPathCallCount++
	return fv.getPodDeviceMapPath()
}

// Block volume support
func (fv *FakeVolume) getPodDeviceMapPath() (string, string) {
	return filepath.Join(fv.Plugin.Host.GetPodVolumeDeviceDir(fv.PodUID, utilstrings.EscapeQualifiedName(fv.Plugin.PluginName))), fv.VolName
}

// Block volume support
func (fv *FakeVolume) GetPodDeviceMapPathCallCount() int {
	fv.RLock()
	defer fv.RUnlock()
	return fv.PodDeviceMapPathCallCount
}

// Block volume support
func (fv *FakeVolume) TearDownDevice(mapPath string, devicePath string) error {
	fv.Lock()
	defer fv.Unlock()
	fv.TearDownDeviceCallCount++
	return nil
}

// Block volume support
func (fv *FakeVolume) GetTearDownDeviceCallCount() int {
	fv.RLock()
	defer fv.RUnlock()
	return fv.TearDownDeviceCallCount
}

// Block volume support
func (fv *FakeVolume) UnmapPodDevice() error {
	fv.Lock()
	defer fv.Unlock()
	fv.UnmapPodDeviceCallCount++
	return nil
}

// Block volume support
func (fv *FakeVolume) GetUnmapPodDeviceCallCount() int {
	fv.RLock()
	defer fv.RUnlock()
	return fv.UnmapPodDeviceCallCount
}

// Block volume support
func (fv *FakeVolume) MapPodDevice() (string, error) {
	fv.Lock()
	defer fv.Unlock()

	if fv.VolName == TimeoutOnSetupVolumeName {
		fv.VolumeMountState[fv.VolName] = volumeMountUncertain
		return "", volumetypes.NewUncertainProgressError("time out on setup")
	}

	if fv.VolName == FailOnSetupVolumeName {
		fv.VolumeMountState[fv.VolName] = volumeNotMounted
		return "", fmt.Errorf("mounting volume failed")
	}

	if fv.VolName == TimeoutAndFailOnSetupVolumeName {
		_, ok := fv.VolumeMountState[fv.VolName]
		if !ok {
			fv.VolumeMountState[fv.VolName] = volumeMountUncertain
			return "", volumetypes.NewUncertainProgressError("time out on setup")
		}
		fv.VolumeMountState[fv.VolName] = volumeNotMounted
		return "", fmt.Errorf("mounting volume failed")

	}

	if fv.VolName == SuccessAndFailOnSetupVolumeName {
		_, ok := fv.VolumeMountState[fv.VolName]
		if ok {
			fv.VolumeMountState[fv.VolName] = volumeNotMounted
			return "", fmt.Errorf("mounting volume failed")
		}
	}

	if fv.VolName == SuccessAndTimeoutSetupVolumeName {
		_, ok := fv.VolumeMountState[fv.VolName]
		if ok {
			fv.VolumeMountState[fv.VolName] = volumeMountUncertain
			return "", volumetypes.NewUncertainProgressError("time out on setup")
		}
	}

	fv.VolumeMountState[fv.VolName] = volumeMounted
	fv.MapPodDeviceCallCount++
	return "", nil
}

// Block volume support
func (fv *FakeVolume) GetMapPodDeviceCallCount() int {
	fv.RLock()
	defer fv.RUnlock()
	return fv.MapPodDeviceCallCount
}

func (fv *FakeVolume) Attach(spec *Spec, nodeName types.NodeName) (string, error) {
	fv.Lock()
	defer fv.Unlock()
	fv.AttachCallCount++
	volumeName, err := getUniqueVolumeName(spec)
	if err != nil {
		return "", err
	}
	volumeNode, exist := fv.VolumesAttached[volumeName]
	if exist {
		if nodeName == UncertainAttachNode {
			return "/dev/vdb-test", nil
		}
		// even if volume was previously attached to time out, we need to keep returning error
		// so as reconciler can not confirm this volume as attached.
		if nodeName == TimeoutAttachNode {
			return "", fmt.Errorf("Timed out to attach volume %q to node %q", volumeName, nodeName)
		}
		if volumeNode == nodeName || volumeNode == MultiAttachNode || nodeName == MultiAttachNode {
			return "/dev/vdb-test", nil
		}
		return "", fmt.Errorf("volume %q trying to attach to node %q is already attached to node %q", volumeName, nodeName, volumeNode)
	}

	fv.VolumesAttached[volumeName] = nodeName
	if nodeName == UncertainAttachNode || nodeName == TimeoutAttachNode {
		return "", fmt.Errorf("Timed out to attach volume %q to node %q", volumeName, nodeName)
	}
	return "/dev/vdb-test", nil
}

func (fv *FakeVolume) GetAttachCallCount() int {
	fv.RLock()
	defer fv.RUnlock()
	return fv.AttachCallCount
}

func (fv *FakeVolume) WaitForAttach(spec *Spec, devicePath string, pod *v1.Pod, spectimeout time.Duration) (string, error) {
	fv.Lock()
	defer fv.Unlock()
	fv.WaitForAttachCallCount++
	if fv.WaitForAttachHook != nil {
		return fv.WaitForAttachHook(spec, devicePath, pod, spectimeout)
	}
	return "/dev/sdb", nil
}

func (fv *FakeVolume) GetWaitForAttachCallCount() int {
	fv.RLock()
	defer fv.RUnlock()
	return fv.WaitForAttachCallCount
}

func (fv *FakeVolume) GetDeviceMountPath(spec *Spec) (string, error) {
	fv.Lock()
	defer fv.Unlock()
	fv.GetDeviceMountPathCallCount++
	return "", nil
}

func (fv *FakeVolume) mountDeviceInternal(spec *Spec, devicePath string, deviceMountPath string) error {
	fv.Lock()
	defer fv.Unlock()
	if spec.Name() == TimeoutOnMountDeviceVolumeName {
		fv.DeviceMountState[spec.Name()] = deviceMountUncertain
		return volumetypes.NewUncertainProgressError("mount failed")
	}

	if spec.Name() == FailMountDeviceVolumeName {
		fv.DeviceMountState[spec.Name()] = deviceNotMounted
		return fmt.Errorf("error mounting disk: %s", devicePath)
	}

	if spec.Name() == TimeoutAndFailOnMountDeviceVolumeName {
		_, ok := fv.DeviceMountState[spec.Name()]
		if !ok {
			fv.DeviceMountState[spec.Name()] = deviceMountUncertain
			return volumetypes.NewUncertainProgressError("timed out mounting error")
		}
		fv.DeviceMountState[spec.Name()] = deviceNotMounted
		return fmt.Errorf("error mounting disk: %s", devicePath)
	}

	if spec.Name() == SuccessAndTimeoutDeviceName {
		_, ok := fv.DeviceMountState[spec.Name()]
		if ok {
			fv.DeviceMountState[spec.Name()] = deviceMountUncertain
			return volumetypes.NewUncertainProgressError("error mounting state")
		}
	}

	if spec.Name() == SuccessAndFailOnMountDeviceName {
		_, ok := fv.DeviceMountState[spec.Name()]
		if ok {
			return fmt.Errorf("error mounting disk: %s", devicePath)
		}
	}
	fv.DeviceMountState[spec.Name()] = deviceMounted
	fv.MountDeviceCallCount++
	return nil
}

func (fv *FakeVolume) MountDevice(spec *Spec, devicePath string, deviceMountPath string) error {
	return fv.mountDeviceInternal(spec, devicePath, deviceMountPath)
}

func (fv *FakeVolume) GetMountDeviceCallCount() int {
	fv.RLock()
	defer fv.RUnlock()
	return fv.MountDeviceCallCount
}

func (fv *FakeVolume) GetUnmountDeviceCallCount() int {
	fv.RLock()
	defer fv.RUnlock()
	return fv.UnmountDeviceCallCount
}

func (fv *FakeVolume) Detach(volumeName string, nodeName types.NodeName) error {
	fv.Lock()
	defer fv.Unlock()
	fv.DetachCallCount++
	if _, exist := fv.VolumesAttached[volumeName]; !exist {
		return fmt.Errorf("Trying to detach volume %q that is not attached to the node %q", volumeName, nodeName)
	}
	delete(fv.VolumesAttached, volumeName)
	return nil
}

func (fv *FakeVolume) VolumesAreAttached(spec []*Spec, nodeName types.NodeName) (map[*Spec]bool, error) {
	fv.Lock()
	defer fv.Unlock()
	return nil, nil
}

func (fv *FakeVolume) GetDetachCallCount() int {
	fv.RLock()
	defer fv.RUnlock()
	return fv.DetachCallCount
}

func (fv *FakeVolume) UnmountDevice(globalMountPath string) error {
	fv.Lock()
	defer fv.Unlock()
	fv.UnmountDeviceCallCount++
	if fv.UnmountDeviceHook != nil {
		return fv.UnmountDeviceHook(globalMountPath)
	}
	return nil
}

type FakeDeleter struct {
	path string
	MetricsNil
}

func (fd *FakeDeleter) Delete() error {
	// nil is success, else error
	return nil
}

func (fd *FakeDeleter) GetPath() string {
	return fd.path
}

type FakeProvisioner struct {
	Options               VolumeOptions
	Host                  VolumeHost
	ProvisionDelaySeconds int
}

func (fc *FakeProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) {
	// Add provision failure hook
	if fc.Options.Parameters != nil {
		if _, ok := fc.Options.Parameters[ExpectProvisionFailureKey]; ok {
			return nil, fmt.Errorf("expected error")
		}
	}
	fullpath := fmt.Sprintf("/tmp/hostpath_pv/%s", uuid.NewUUID())

	pv := &v1.PersistentVolume{
		ObjectMeta: metav1.ObjectMeta{
			Name: fc.Options.PVName,
			Annotations: map[string]string{
				util.VolumeDynamicallyCreatedByKey: "fakeplugin-provisioner",
			},
		},
		Spec: v1.PersistentVolumeSpec{
			PersistentVolumeReclaimPolicy: fc.Options.PersistentVolumeReclaimPolicy,
			AccessModes:                   fc.Options.PVC.Spec.AccessModes,
			Capacity: v1.ResourceList{
				v1.ResourceName(v1.ResourceStorage): fc.Options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)],
			},
			PersistentVolumeSource: v1.PersistentVolumeSource{
				HostPath: &v1.HostPathVolumeSource{
					Path: fullpath,
				},
			},
		},
	}

	if fc.ProvisionDelaySeconds > 0 {
		time.Sleep(time.Duration(fc.ProvisionDelaySeconds) * time.Second)
	}

	return pv, nil
}

var _ volumepathhandler.BlockVolumePathHandler = &FakeVolumePathHandler{}

//NewDeviceHandler Create a new IoHandler implementation
func NewBlockVolumePathHandler() volumepathhandler.BlockVolumePathHandler {
	return &FakeVolumePathHandler{}
}

type FakeVolumePathHandler struct {
	sync.RWMutex
}

func (fv *FakeVolumePathHandler) MapDevice(devicePath string, mapDir string, linkName string, bindMount bool) error {
	// nil is success, else error
	return nil
}

func (fv *FakeVolumePathHandler) UnmapDevice(mapDir string, linkName string, bindMount bool) error {
	// nil is success, else error
	return nil
}

func (fv *FakeVolumePathHandler) RemoveMapPath(mapPath string) error {
	// nil is success, else error
	return nil
}

func (fv *FakeVolumePathHandler) IsSymlinkExist(mapPath string) (bool, error) {
	// nil is success, else error
	return true, nil
}

func (fv *FakeVolumePathHandler) IsDeviceBindMountExist(mapPath string) (bool, error) {
	// nil is success, else error
	return true, nil
}

func (fv *FakeVolumePathHandler) GetDeviceBindMountRefs(devPath string, mapPath string) ([]string, error) {
	// nil is success, else error
	return []string{}, nil
}

func (fv *FakeVolumePathHandler) FindGlobalMapPathUUIDFromPod(pluginDir, mapPath string, podUID types.UID) (string, error) {
	// nil is success, else error
	return "", nil
}

func (fv *FakeVolumePathHandler) AttachFileDevice(path string) (string, error) {
	// nil is success, else error
	return "", nil
}

func (fv *FakeVolumePathHandler) DetachFileDevice(path string) error {
	// nil is success, else error
	return nil
}

func (fv *FakeVolumePathHandler) GetLoopDevice(path string) (string, error) {
	// nil is success, else error
	return "/dev/loop1", nil
}

// FindEmptyDirectoryUsageOnTmpfs finds the expected usage of an empty directory existing on
// a tmpfs filesystem on this system.
func FindEmptyDirectoryUsageOnTmpfs() (*resource.Quantity, error) {
	tmpDir, err := utiltesting.MkTmpdir("metrics_du_test")
	if err != nil {
		return nil, err
	}
	defer os.RemoveAll(tmpDir)
	out, err := exec.New().Command("nice", "-n", "19", "du", "-x", "-s", "-B", "1", tmpDir).CombinedOutput()
	if err != nil {
		return nil, fmt.Errorf("failed command 'du' on %s with error %v", tmpDir, err)
	}
	used, err := resource.ParseQuantity(strings.Fields(string(out))[0])
	if err != nil {
		return nil, fmt.Errorf("failed to parse 'du' output %s due to error %v", out, err)
	}
	used.Format = resource.BinarySI
	return &used, nil
}

// VerifyAttachCallCount ensures that at least one of the Attachers for this
// plugin has the expectedAttachCallCount number of calls. Otherwise it returns
// an error.
func VerifyAttachCallCount(
	expectedAttachCallCount int,
	fakeVolumePlugin *FakeVolumePlugin) error {
	for _, attacher := range fakeVolumePlugin.GetAttachers() {
		actualCallCount := attacher.GetAttachCallCount()
		if actualCallCount >= expectedAttachCallCount {
			return nil
		}
	}

	return fmt.Errorf(
		"No attachers have expected AttachCallCount. Expected: <%v>.",
		expectedAttachCallCount)
}

// VerifyZeroAttachCalls ensures that all of the Attachers for this plugin have
// a zero AttachCallCount. Otherwise it returns an error.
func VerifyZeroAttachCalls(fakeVolumePlugin *FakeVolumePlugin) error {
	for _, attacher := range fakeVolumePlugin.GetAttachers() {
		actualCallCount := attacher.GetAttachCallCount()
		if actualCallCount != 0 {
			return fmt.Errorf(
				"At least one attacher has non-zero AttachCallCount: <%v>.",
				actualCallCount)
		}
	}

	return nil
}

// VerifyWaitForAttachCallCount ensures that at least one of the Mounters for
// this plugin has the expectedWaitForAttachCallCount number of calls. Otherwise
// it returns an error.
func VerifyWaitForAttachCallCount(
	expectedWaitForAttachCallCount int,
	fakeVolumePlugin *FakeVolumePlugin) error {
	for _, attacher := range fakeVolumePlugin.GetAttachers() {
		actualCallCount := attacher.GetWaitForAttachCallCount()
		if actualCallCount >= expectedWaitForAttachCallCount {
			return nil
		}
	}

	return fmt.Errorf(
		"No Attachers have expected WaitForAttachCallCount. Expected: <%v>.",
		expectedWaitForAttachCallCount)
}

// VerifyZeroWaitForAttachCallCount ensures that all Attachers for this plugin
// have a zero WaitForAttachCallCount. Otherwise it returns an error.
func VerifyZeroWaitForAttachCallCount(fakeVolumePlugin *FakeVolumePlugin) error {
	for _, attacher := range fakeVolumePlugin.GetAttachers() {
		actualCallCount := attacher.GetWaitForAttachCallCount()
		if actualCallCount != 0 {
			return fmt.Errorf(
				"At least one attacher has non-zero WaitForAttachCallCount: <%v>.",
				actualCallCount)
		}
	}

	return nil
}

// VerifyMountDeviceCallCount ensures that at least one of the Mounters for
// this plugin has the expectedMountDeviceCallCount number of calls. Otherwise
// it returns an error.
func VerifyMountDeviceCallCount(
	expectedMountDeviceCallCount int,
	fakeVolumePlugin *FakeVolumePlugin) error {
	for _, attacher := range fakeVolumePlugin.GetAttachers() {
		actualCallCount := attacher.GetMountDeviceCallCount()
		if actualCallCount >= expectedMountDeviceCallCount {
			return nil
		}
	}

	return fmt.Errorf(
		"No Attachers have expected MountDeviceCallCount. Expected: <%v>.",
		expectedMountDeviceCallCount)
}

func VerifyUnmountDeviceCallCount(expectedCallCount int, fakeVolumePlugin *FakeVolumePlugin) error {
	detachers := fakeVolumePlugin.GetDetachers()
	if len(detachers) == 0 && (expectedCallCount == 0) {
		return nil
	}
	actualCallCount := 0
	for _, detacher := range detachers {
		actualCallCount = detacher.GetUnmountDeviceCallCount()
		if expectedCallCount == 0 && actualCallCount == expectedCallCount {
			return nil
		}

		if (expectedCallCount > 0) && (actualCallCount >= expectedCallCount) {
			return nil
		}
	}

	return fmt.Errorf(
		"Expected DeviceUnmount Call %d, got %d",
		expectedCallCount, actualCallCount)
}

// VerifyZeroMountDeviceCallCount ensures that all Attachers for this plugin
// have a zero MountDeviceCallCount. Otherwise it returns an error.
func VerifyZeroMountDeviceCallCount(fakeVolumePlugin *FakeVolumePlugin) error {
	for _, attacher := range fakeVolumePlugin.GetAttachers() {
		actualCallCount := attacher.GetMountDeviceCallCount()
		if actualCallCount != 0 {
			return fmt.Errorf(
				"At least one attacher has non-zero MountDeviceCallCount: <%v>.",
				actualCallCount)
		}
	}

	return nil
}

// VerifySetUpCallCount ensures that at least one of the Mounters for this
// plugin has the expectedSetUpCallCount number of calls. Otherwise it returns
// an error.
func VerifySetUpCallCount(
	expectedSetUpCallCount int,
	fakeVolumePlugin *FakeVolumePlugin) error {
	for _, mounter := range fakeVolumePlugin.GetMounters() {
		actualCallCount := mounter.GetSetUpCallCount()
		if actualCallCount >= expectedSetUpCallCount {
			return nil
		}
	}

	return fmt.Errorf(
		"No Mounters have expected SetUpCallCount. Expected: <%v>.",
		expectedSetUpCallCount)
}

// VerifyZeroSetUpCallCount ensures that all Mounters for this plugin have a
// zero SetUpCallCount. Otherwise it returns an error.
func VerifyZeroSetUpCallCount(fakeVolumePlugin *FakeVolumePlugin) error {
	for _, mounter := range fakeVolumePlugin.GetMounters() {
		actualCallCount := mounter.GetSetUpCallCount()
		if actualCallCount != 0 {
			return fmt.Errorf(
				"At least one mounter has non-zero SetUpCallCount: <%v>.",
				actualCallCount)
		}
	}

	return nil
}

// VerifyTearDownCallCount ensures that at least one of the Unounters for this
// plugin has the expectedTearDownCallCount number of calls. Otherwise it
// returns an error.
func VerifyTearDownCallCount(
	expectedTearDownCallCount int,
	fakeVolumePlugin *FakeVolumePlugin) error {
	unmounters := fakeVolumePlugin.GetUnmounters()
	if len(unmounters) == 0 && (expectedTearDownCallCount == 0) {
		return nil
	}

	for _, unmounter := range unmounters {
		actualCallCount := unmounter.GetTearDownCallCount()
		if expectedTearDownCallCount == 0 && actualCallCount == expectedTearDownCallCount {
			return nil
		}

		if (expectedTearDownCallCount > 0) && (actualCallCount >= expectedTearDownCallCount) {
			return nil
		}
	}

	return fmt.Errorf(
		"No Unmounters have expected SetUpCallCount. Expected: <%v>.",
		expectedTearDownCallCount)
}

// VerifyZeroTearDownCallCount ensures that all Mounters for this plugin have a
// zero TearDownCallCount. Otherwise it returns an error.
func VerifyZeroTearDownCallCount(fakeVolumePlugin *FakeVolumePlugin) error {
	for _, mounter := range fakeVolumePlugin.GetMounters() {
		actualCallCount := mounter.GetTearDownCallCount()
		if actualCallCount != 0 {
			return fmt.Errorf(
				"At least one mounter has non-zero TearDownCallCount: <%v>.",
				actualCallCount)
		}
	}

	return nil
}

// VerifyDetachCallCount ensures that at least one of the Attachers for this
// plugin has the expectedDetachCallCount number of calls. Otherwise it returns
// an error.
func VerifyDetachCallCount(
	expectedDetachCallCount int,
	fakeVolumePlugin *FakeVolumePlugin) error {
	for _, detacher := range fakeVolumePlugin.GetDetachers() {
		actualCallCount := detacher.GetDetachCallCount()
		if actualCallCount == expectedDetachCallCount {
			return nil
		}
	}

	return fmt.Errorf(
		"No Detachers have expected DetachCallCount. Expected: <%v>.",
		expectedDetachCallCount)
}

// VerifyZeroDetachCallCount ensures that all Detachers for this plugin have a
// zero DetachCallCount. Otherwise it returns an error.
func VerifyZeroDetachCallCount(fakeVolumePlugin *FakeVolumePlugin) error {
	for _, detacher := range fakeVolumePlugin.GetDetachers() {
		actualCallCount := detacher.GetDetachCallCount()
		if actualCallCount != 0 {
			return fmt.Errorf(
				"At least one detacher has non-zero DetachCallCount: <%v>.",
				actualCallCount)
		}
	}

	return nil
}

// VerifySetUpDeviceCallCount ensures that at least one of the Mappers for this
// plugin has the expectedSetUpDeviceCallCount number of calls. Otherwise it
// returns an error.
func VerifySetUpDeviceCallCount(
	expectedSetUpDeviceCallCount int,
	fakeVolumePlugin *FakeVolumePlugin) error {
	for _, mapper := range fakeVolumePlugin.GetBlockVolumeMapper() {
		actualCallCount := mapper.GetSetUpDeviceCallCount()
		if actualCallCount >= expectedSetUpDeviceCallCount {
			return nil
		}
	}

	return fmt.Errorf(
		"No Mapper have expected SetUpDeviceCallCount. Expected: <%v>.",
		expectedSetUpDeviceCallCount)
}

// VerifyTearDownDeviceCallCount ensures that at least one of the Unmappers for this
// plugin has the expectedTearDownDeviceCallCount number of calls. Otherwise it
// returns an error.
func VerifyTearDownDeviceCallCount(
	expectedTearDownDeviceCallCount int,
	fakeVolumePlugin *FakeVolumePlugin) error {
	for _, unmapper := range fakeVolumePlugin.GetBlockVolumeUnmapper() {
		actualCallCount := unmapper.GetTearDownDeviceCallCount()
		if actualCallCount >= expectedTearDownDeviceCallCount {
			return nil
		}
	}

	return fmt.Errorf(
		"No Unmapper have expected TearDownDeviceCallCount. Expected: <%v>.",
		expectedTearDownDeviceCallCount)
}

// VerifyZeroTearDownDeviceCallCount ensures that all Mappers for this plugin have a
// zero TearDownDeviceCallCount. Otherwise it returns an error.
func VerifyZeroTearDownDeviceCallCount(fakeVolumePlugin *FakeVolumePlugin) error {
	for _, unmapper := range fakeVolumePlugin.GetBlockVolumeUnmapper() {
		actualCallCount := unmapper.GetTearDownDeviceCallCount()
		if actualCallCount != 0 {
			return fmt.Errorf(
				"At least one unmapper has non-zero TearDownDeviceCallCount: <%v>.",
				actualCallCount)
		}
	}

	return nil
}

// VerifyUnmapPodDeviceCallCount ensures that at least one of the Unmappers for this
// plugin has the expected number of UnmapPodDevice calls. Otherwise it
// returns an error.
func VerifyUnmapPodDeviceCallCount(
	expectedUnmapPodDeviceCallCount int,
	fakeVolumePlugin *FakeVolumePlugin) error {
	for _, unmapper := range fakeVolumePlugin.GetBlockVolumeUnmapper() {
		actualCallCount := unmapper.GetUnmapPodDeviceCallCount()
		if actualCallCount >= expectedUnmapPodDeviceCallCount {
			return nil
		}
	}

	return fmt.Errorf(
		"No Unmapper have expected UnmapPodDeviceCallCount. Expected: <%v>.",
		expectedUnmapPodDeviceCallCount)
}

// VerifyZeroUnmapPodDeviceCallCount ensures that all Mappers for this plugin have a
// zero UnmapPodDevice calls. Otherwise it returns an error.
func VerifyZeroUnmapPodDeviceCallCount(fakeVolumePlugin *FakeVolumePlugin) error {
	for _, unmapper := range fakeVolumePlugin.GetBlockVolumeUnmapper() {
		actualCallCount := unmapper.GetUnmapPodDeviceCallCount()
		if actualCallCount != 0 {
			return fmt.Errorf(
				"At least one unmapper has non-zero UnmapPodDeviceCallCount: <%v>.",
				actualCallCount)
		}
	}

	return nil
}

// VerifyGetGlobalMapPathCallCount ensures that at least one of the Mappers for this
// plugin has the expectedGlobalMapPathCallCount number of calls. Otherwise it returns
// an error.
func VerifyGetGlobalMapPathCallCount(
	expectedGlobalMapPathCallCount int,
	fakeVolumePlugin *FakeVolumePlugin) error {
	for _, mapper := range fakeVolumePlugin.GetBlockVolumeMapper() {
		actualCallCount := mapper.GetGlobalMapPathCallCount()
		if actualCallCount == expectedGlobalMapPathCallCount {
			return nil
		}
	}

	return fmt.Errorf(
		"No Mappers have expected GetGlobalMapPathCallCount. Expected: <%v>.",
		expectedGlobalMapPathCallCount)
}

// VerifyGetPodDeviceMapPathCallCount ensures that at least one of the Mappers for this
// plugin has the expectedPodDeviceMapPathCallCount number of calls. Otherwise it returns
// an error.
func VerifyGetPodDeviceMapPathCallCount(
	expectedPodDeviceMapPathCallCount int,
	fakeVolumePlugin *FakeVolumePlugin) error {
	for _, mapper := range fakeVolumePlugin.GetBlockVolumeMapper() {
		actualCallCount := mapper.GetPodDeviceMapPathCallCount()
		if actualCallCount == expectedPodDeviceMapPathCallCount {
			return nil
		}
	}

	return fmt.Errorf(
		"No Mappers have expected GetPodDeviceMapPathCallCount. Expected: <%v>.",
		expectedPodDeviceMapPathCallCount)
}

// VerifyGetMapPodDeviceCallCount ensures that at least one of the Mappers for this
// plugin has the expectedMapPodDeviceCallCount number of calls. Otherwise it
// returns an error.
func VerifyGetMapPodDeviceCallCount(
	expectedMapPodDeviceCallCount int,
	fakeVolumePlugin *FakeVolumePlugin) error {
	for _, mapper := range fakeVolumePlugin.GetBlockVolumeMapper() {
		actualCallCount := mapper.GetMapPodDeviceCallCount()
		if actualCallCount >= expectedMapPodDeviceCallCount {
			return nil
		}
	}

	return fmt.Errorf(
		"No Mapper have expected MapPodDeviceCallCount. Expected: <%v>.",
		expectedMapPodDeviceCallCount)
}

// GetTestVolumePluginMgr creates, initializes, and returns a test volume plugin
// manager and fake volume plugin using a fake volume host.
func GetTestVolumePluginMgr(
	t *testing.T) (*VolumePluginMgr, *FakeVolumePlugin) {
	plugins := ProbeVolumePlugins(VolumeConfig{})
	v := NewFakeVolumeHost(
		t,
		"",      /* rootDir */
		nil,     /* kubeClient */
		plugins, /* plugins */
	)
	return v.pluginMgr, plugins[0].(*FakeVolumePlugin)
}

// CreateTestPVC returns a provisionable PVC for tests
func CreateTestPVC(capacity string, accessModes []v1.PersistentVolumeAccessMode) *v1.PersistentVolumeClaim {
	claim := v1.PersistentVolumeClaim{
		ObjectMeta: metav1.ObjectMeta{
			Name:      "dummy",
			Namespace: "default",
		},
		Spec: v1.PersistentVolumeClaimSpec{
			AccessModes: accessModes,
			Resources: v1.ResourceRequirements{
				Requests: v1.ResourceList{
					v1.ResourceName(v1.ResourceStorage): resource.MustParse(capacity),
				},
			},
		},
	}
	return &claim
}

func MetricsEqualIgnoreTimestamp(a *Metrics, b *Metrics) bool {
	available := a.Available == b.Available
	capacity := a.Capacity == b.Capacity
	used := a.Used == b.Used
	inodes := a.Inodes == b.Inodes
	inodesFree := a.InodesFree == b.InodesFree
	inodesUsed := a.InodesUsed == b.InodesUsed
	return available && capacity && used && inodes && inodesFree && inodesUsed
}

func ContainsAccessMode(modes []v1.PersistentVolumeAccessMode, mode v1.PersistentVolumeAccessMode) bool {
	for _, m := range modes {
		if m == mode {
			return true
		}
	}
	return false
}

func (f *fakeVolumeHost) CSIDriverLister() storagelistersv1.CSIDriverLister {
	return f.csiDriverLister
}

func (f *fakeVolumeHost) CSIDriversSynced() cache.InformerSynced {
	// not needed for testing
	return nil
}

func (f *fakeVolumeHost) CSINodeLister() storagelistersv1.CSINodeLister {
	// not needed for testing
	return nil
}

func (f *fakeVolumeHost) GetInformerFactory() informers.SharedInformerFactory {
	return f.informerFactory
}

func (f *fakeVolumeHost) IsAttachDetachController() bool {
	return true
}

func (f *fakeVolumeHost) SetKubeletError(err error) {
	f.mux.Lock()
	defer f.mux.Unlock()
	f.kubeletErr = err
	return
}

func (f *fakeVolumeHost) WaitForCacheSync() error {
	return nil
}

func (f *fakeVolumeHost) WaitForKubeletErrNil() error {
	return wait.PollImmediate(10*time.Millisecond, 10*time.Second, func() (bool, error) {
		f.mux.Lock()
		defer f.mux.Unlock()
		return f.kubeletErr == nil, nil
	})
}


text:
package com.opengamma.util.db.tool;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.util.db.DbDialect;
import com.opengamma.util.db.HSQLDbDialect;
import com.opengamma.util.db.Oracle11gDbDialect;
import com.opengamma.util.db.PostgresDbDialect;
import com.opengamma.util.db.SqlServer2008DbDialect;
import com.opengamma.util.time.DateUtils;

/**
 * Utilities to support database testing.
 */
public final class DbDialectUtils {

  /** Known dialects. */
  private static final Map<String, DbDialect> DB_DIALECTS = new ConcurrentHashMap<>();
  /** Available dialects. */
  private static final Map<String, Boolean> AVAILABLE_DIALECTS = new ConcurrentHashMap<>();

  static {
    // initialize the clock
    DateUtils.initTimeZone();

    // setup the known databases
    addDbDialect("hsqldb", new HSQLDbDialect());
    addDbDialect("postgres", new PostgresDbDialect());
    addDbDialect("sqlserver2008", new SqlServer2008DbDialect());
    addDbDialect("oracle11g", new Oracle11gDbDialect());
  }

  //-------------------------------------------------------------------------
  /**
   * Creates an instance.
   */
  private DbDialectUtils() {
  }

  //-------------------------------------------------------------------------
  /**
   * Gets the supported database types.
   *
   * @return the supported database types, not null
   */
  public static Collection<String> getSupportedDatabaseTypes() {
    return new ArrayList<>(DB_DIALECTS.keySet());
  }

  /**
   * Gets the supported database types as {@code DbDialect} objects.
   *
   * @return the supported database dialects keyed by type, not null
   */
  public static Map<String, DbDialect> getSupportedDbDialects() {
    return new HashMap<>(DB_DIALECTS);
  }

  /**
   * Gets a supported database dialect by type name.
   *
   * @param databaseType  the database type, not null
   * @return the dialect, not null
   */
  public static DbDialect getSupportedDbDialect(final String databaseType) {
    final DbDialect dbDialect = getSupportedDbDialects().get(databaseType);
    if (dbDialect == null) {
      throw new OpenGammaRuntimeException("Config error - no DbDialect setup for " + databaseType);
    }
    return dbDialect;
  }

  //-------------------------------------------------------------------------
  /**
   * Gets the available database types.
   *

   * Not all supported database types may be available at runtime.
   *
   * @return the available database types, not null
   */
  public static Collection<String> getAvailableDatabaseTypes() {
    final Collection<String> databaseTypes = Sets.newHashSet(DB_DIALECTS.keySet());
    for (final Iterator<String> it = databaseTypes.iterator(); it.hasNext();) {
      final String dbType = it.next();
      Boolean available = AVAILABLE_DIALECTS.get(dbType);
      if (available == null) {
        final DbDialect dbDialect = DB_DIALECTS.get(dbType);
        try {
          Objects.requireNonNull(dbDialect.getJDBCDriverClass());
          available = true;
        } catch (RuntimeException | Error ex) {
          available = false;
          System.err.println("Database driver not available: " + dbType);
        }
        AVAILABLE_DIALECTS.put(dbType, available);
      }
      if (!available) {
        it.remove();
      }
    }
    return databaseTypes;
  }

  /**
   * Gets the available database types as {@code DbDialect} objects.
   *

   * Not all supported database types may be available at runtime.
   *
   * @return the available database dialects keyed by type, not null
   */
  public static Map<String, DbDialect> getAvailableDbDialects() {
    final Collection<String> availableTypes = getAvailableDatabaseTypes();
    final Map<String, DbDialect> available = Maps.newHashMap();
    for (final String availableType : availableTypes) {
      available.put(availableType, DB_DIALECTS.get(availableType));
    }
    return available;
  }

  /**
   * Gets an available database dialect by type name.
   *
   * @param databaseType  the database type, not null
   * @return the dialect, not null
   */
  public static DbDialect getAvailableDbDialect(final String databaseType) {
    final DbDialect dbDialect = getAvailableDbDialects().get(databaseType);
    if (dbDialect == null) {
      throw new OpenGammaRuntimeException("Config error - no available DbDialect for " + databaseType);
    }
    return dbDialect;
  }

  //-------------------------------------------------------------------------
  /**
   * Adds a dialect to the map of known.
   *
   * @param dbType  the database type, not null
   * @param dialect  the dialect, not null
   */
  public static void addDbDialect(final String dbType, final DbDialect dialect) {
    DB_DIALECTS.put(dbType, dialect);
  }

}

redpajama_set_name: RedPajamaGithub


text:
ACCEPTED

#### According to
The Catalogue of Life, 3rd January 2011

#### Published in
Gen. sp. orchid. pl. 188. 1833

#### Original name
null

### Remarks
null


text:
<?php

/* @var $this yii\web\View */

$this->title = 'X-FIT';
?>

    <form id="nl-form" class="nl-form" action="/site/order" method="POST">
        <input type="hidden" name="_csrf" value="<?=Yii::$app->request->getCsrfToken()?>" />
        Я из города
        <select name="city">
            <?php
                $count = 1;
                foreach($city as $cy)
                {
                    if($count == 1) echo '<option data-id="'.$cy->id.'" value="'.$count.'" selected>'.$cy->name.'</option>
                    ';
                    else echo '<option data-id="'.$cy->id.'" value="'.$count.'">'.$cy->name.'</option>
                    ';
                    $count++;
                }
            ?>
        </select>
        и хочу
        <select name="want">
            <option value="1" selected>оформить карту</option>
            <option value="2">продлить карту</option>
        </select>
        фитнес-сети X-FIT в
        <select name="club">
            <option value="1" selected>клубе</option>
            <option value="2">клуб 1</option>
            <option value="3">клуб 2</option>
            <option value="4">клуб 3</option>
        </select>

        Наиболее удобное время для посещения клуба это
        <select name="time">
            <option value="1" selected>любое время</option>
            <option value="2">только днем</option>
            <option value="3">только вечером</option>
            <option value="4">только утром</option>
            <option value="5">только в выходные</option>
        </select>

Данную карту приобретаю
        <select name="acquire">
            <option value="1" selected>себе</option>
            <option value="2">в подарок</option>
        </select>
        для
        <select name="age">
            <option value="1" selected>взрослого</option>
            <option value="2">ребенка</option>
            <option value="3">студента</option>
        </select>

        Необходимый срок действия карты -
        <select name="expiry">
            <option value="1" selected>365 дней</option>
            <option value="2">182 дня</option>
            <option value="3">30 дней</option>
            <option value="3">730 дней</option>
        </select>

        Возможность разморозки
        <select name="defrost">
            <option value="1" selected>нужна</option>
            <option value="2">не обязательна</option>
        </select>

        Носитель оформляемой карты ранее посещал клуб
        <input type="text" value="" name="oldClub" placeholder="введите название клуба" data-subline="Пример: Планета фитнес"/>

            <button class="nl-submit" type="submit">Далее</button>

    </form>


text:
"""
Greatest common divisor(GCD) of two integers X and Y is the largest integer that divides both X and Y.

References :
https://en.wikipedia.org/wiki/Euclidean_algorithm
https://proofwiki.org/wiki/Euclidean_Algorithm
http://stackoverflow.com/questions/6005582/how-does-the-euclidean-algorithm-work

Algorithm :
* If X = 0 then GCD(X,Y) = Y, as GCD(0,Y) = Y.
* If Y = 0 then GCD(X,Y) = X, as GCD(X,0) = X.
* Write X in quotient remainder form (X = Y * Q + R).
* Find GCD(Y,R) using the Euclidean algorithm since GCD(X,Y) = GCD(Y,R).
"""

def greatest_common_divisor(x,y):
    return x if y == 0 else greatest_common_divisor(y,x%y)

if __name__ == "__main__":
    print(greatest_common_divisor(20,25))


text:
package org.freebxml.omar.common.spi;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import org.freebxml.omar.common.*;

/**
 *
 * @author  najmi
 */
public class QueryManagerFactory {
    private static QueryManagerFactory instance; //singleton instance
    public static final String QUERY_MANAGER_CLASS_PROPERTY = "omar.common.QueryManagerFactory.queryManagerClass";
    private QueryManager qm = null;
    private static final Log log = LogFactory.getLog(QueryManagerFactory.class);

    /** Creates a new instance of QueryManager */
    protected QueryManagerFactory() {
    }

    public synchronized static QueryManagerFactory getInstance() {
        if (instance == null) {
            instance = new QueryManagerFactory();
        }

        return instance;
    }

    public QueryManager getQueryManager() {
        if (qm == null) {
            synchronized (this) {
                if (qm == null) {
                    try {
                        String pluginClass = CommonProperties.getInstance()
                                                               .getProperty(QUERY_MANAGER_CLASS_PROPERTY);

                        qm = (QueryManager) createPluginInstance(pluginClass);
                    } catch (Exception e) {
                        String errmsg = "[QueryManager] Cannot instantiate " +
                            "QueryManager plugin. Please check that " +
                            "property '" + QUERY_MANAGER_CLASS_PROPERTY +
                            "' is correctly set in omar-common.properties file.";
                        log.error(errmsg, e);
                    }
                }
            }
        }

        return qm;
    }

    /**
    * Creates the instance of the pluginClass
    */
    private Object createPluginInstance(String pluginClass)
        throws Exception {
        Object plugin = null;

        if (log.isDebugEnabled()) {
            log.debug("pluginClass = " + pluginClass);
        }

        Class theClass = Class.forName(pluginClass);

        //try to invoke constructor using Reflection,
        //if this fails then try invoking getInstance()
        try {
            Constructor constructor = theClass.getConstructor((java.lang.Class[])null);
            plugin = constructor.newInstance(new Object[0]);
        } catch (Exception e) {
            //log.warn("No accessible constructor. " +
            //    "invoking getInstance() instead.");

            Method factory = theClass.getDeclaredMethod("getInstance", (java.lang.Class[])null);
            plugin = factory.invoke(null, new Object[0]);
        }

        return plugin;
    }
}


text:
<?php

namespace Magento\Email\Model\Template\Config;

class ReaderTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var \Magento\Email\Model\Template\Config\Reader
     */
    protected $_model;

    /**
     * @var \Magento\Catalog\Model\Attribute\Config\Converter|\PHPUnit_Framework_MockObject_MockObject
     */
    protected $_converter;

    /**
     * @var \Magento\Framework\Module\Dir\ReverseResolver|\PHPUnit_Framework_MockObject_MockObject
     */
    protected $_moduleDirResolver;

    /**
     * @var \Magento\Framework\Filesystem\Directory\Read|\PHPUnit_Framework_MockObject_MockObject
     */
    protected $_filesystemDirectoryMock;

    /**
     * Paths to fixtures
     *
     * @var array
     */
    protected $_paths;

    protected function setUp()
    {
        $fileResolver = $this->getMock(
            'Magento\Email\Model\Template\Config\FileResolver',
            [],
            [],
            '',
            false
        );
        $this->_paths = [
            __DIR__ . '/_files/Fixture/ModuleOne/etc/email_templates_one.xml',
            __DIR__ . '/_files/Fixture/ModuleTwo/etc/email_templates_two.xml',
        ];

        $this->_converter = $this->getMock('Magento\Email\Model\Template\Config\Converter', ['convert']);

        $moduleReader = $this->getMock(
            'Magento\Framework\Module\Dir\Reader',
            ['getModuleDir'],
            [],
            '',
            false
        );
        $moduleReader->expects(
            $this->once()
        )->method(
            'getModuleDir'
        )->with(
            'etc',
            'Magento_Email'
        )->will(
            $this->returnValue('stub')
        );
        $schemaLocator = new \Magento\Email\Model\Template\Config\SchemaLocator($moduleReader);

        $validationState = $this->getMock('Magento\Framework\Config\ValidationStateInterface');
        $validationState->expects($this->once())->method('isValidated')->will($this->returnValue(false));

        $this->_moduleDirResolver = $this->getMock(
            'Magento\Framework\Module\Dir\ReverseResolver',
            [],
            [],
            '',
            false
        );
        $this->_filesystemDirectoryMock = $this->getMock(
            '\Magento\Framework\Filesystem\Directory\Read',
            [],
            [],
            '',
            false
        );

        $this->_filesystemDirectoryMock->expects(
            $this->any()
        )->method(
            'getAbsolutePath'
        )->will(
            $this->returnArgument(0)
        );

        $fileIterator = new \Magento\Email\Model\Template\Config\FileIterator(
            $this->_filesystemDirectoryMock,
            $this->_paths,
            $this->_moduleDirResolver
        );
        $fileResolver->expects(
            $this->once()
        )->method(
            'get'
        )->with(
            'email_templates.xml',
            'scope'
        )->will(
            $this->returnValue($fileIterator)
        );

        $this->_model = new \Magento\Email\Model\Template\Config\Reader(
            $fileResolver,
            $this->_converter,
            $schemaLocator,
            $validationState
        );
    }

    public function testRead()
    {
        $this->_filesystemDirectoryMock->expects(
            $this->at(1)
        )->method(
            'readFile'
        )->will(
            $this->returnValue(file_get_contents($this->_paths[0]))
        );
        $this->_filesystemDirectoryMock->expects(
            $this->at(3)
        )->method(
            'readFile'
        )->will(
            $this->returnValue(file_get_contents($this->_paths[1]))
        );
        $this->_moduleDirResolver->expects(
            $this->at(0)
        )->method(
            'getModuleName'
        )->with(
            __DIR__ . '/_files/Fixture/ModuleOne/etc/email_templates_one.xml'
        )->will(
            $this->returnValue('Fixture_ModuleOne')
        );
        $this->_moduleDirResolver->expects(
            $this->at(1)
        )->method(
            'getModuleName'
        )->with(
            __DIR__ . '/_files/Fixture/ModuleTwo/etc/email_templates_two.xml'
        )->will(
            $this->returnValue('Fixture_ModuleTwo')
        );
        $constraint = function (\DOMDocument $actual) {
            try {
                $expected = file_get_contents(__DIR__ . '/_files/email_templates_merged.xml');
                $expectedNorm = preg_replace('/xsi:noNamespaceSchemaLocation="[^"]*"/', '', $expected, 1);
                $actualNorm = preg_replace('/xsi:noNamespaceSchemaLocation="[^"]*"/', '', $actual->saveXML(), 1);
                \PHPUnit_Framework_Assert::assertXmlStringEqualsXmlString($expectedNorm, $actualNorm);
                return true;
            } catch (\PHPUnit_Framework_AssertionFailedError $e) {
                return false;
            }
        };
        $expectedResult = new \stdClass();
        $this->_converter->expects(
            $this->once()
        )->method(
            'convert'
        )->with(
            $this->callback($constraint)
        )->will(
            $this->returnValue($expectedResult)
        );

        $this->assertSame($expectedResult, $this->_model->read('scope'));
    }

    /**
     * @expectedException \UnexpectedValueException
     * @expectedExceptionMessage Unable to determine a module
     */
    public function testReadUnknownModule()
    {
        $this->_moduleDirResolver->expects($this->once())->method('getModuleName')->will($this->returnValue(null));
        $this->_converter->expects($this->never())->method('convert');
        $this->_model->read('scope');
    }
}


text:
package com.facebook.buck.file;

import com.facebook.buck.core.build.buildable.context.BuildableContext;
import com.facebook.buck.core.build.context.BuildContext;
import com.facebook.buck.core.filesystems.RelPath;
import com.facebook.buck.core.model.BuildTarget;
import com.facebook.buck.core.model.BuildTargetWithOutputs;
import com.facebook.buck.core.model.OutputLabel;
import com.facebook.buck.core.model.impl.BuildTargetPaths;
import com.facebook.buck.core.rulekey.AddToRuleKey;
import com.facebook.buck.core.rules.BuildRuleParams;
import com.facebook.buck.core.rules.impl.AbstractBuildRuleWithDeclaredAndExtraDeps;
import com.facebook.buck.core.sourcepath.ExplicitBuildTargetSourcePath;
import com.facebook.buck.core.sourcepath.SourcePath;
import com.facebook.buck.file.downloader.Downloader;
import com.facebook.buck.io.filesystem.BuildCellRelativePath;
import com.facebook.buck.io.filesystem.ProjectFilesystem;
import com.facebook.buck.step.Step;
import com.facebook.buck.step.fs.CopyStep;
import com.facebook.buck.step.fs.MakeCleanDirectoryStep;
import com.facebook.buck.step.fs.MakeExecutableStep;
import com.facebook.buck.unarchive.UnzipStep;
import com.google.common.collect.ImmutableList;
import com.google.common.hash.HashCode;
import java.net.URI;
import java.util.Optional;

/**
 * Represents a remote file that needs to be downloaded. Optionally, this class can be prevented
 * from running at build time, requiring a user to run {@code buck fetch} before executing the
 * build.
 */
public class RemoteFile extends AbstractBuildRuleWithDeclaredAndExtraDeps {

  @AddToRuleKey(stringify = true)
  private final URI uri;

  @AddToRuleKey(stringify = true)
  private final FileHash sha1;

  @AddToRuleKey(stringify = true)
  private final RelPath output;

  private final Downloader downloader;

  @AddToRuleKey(stringify = true)
  private final Type type;

  public RemoteFile(
      BuildTarget buildTarget,
      ProjectFilesystem projectFilesystem,
      BuildRuleParams params,
      Downloader downloader,
      URI uri,
      HashCode sha1,
      String out,
      Type type) {
    super(buildTarget, projectFilesystem, params);

    this.uri = uri;
    this.sha1 = FileHash.ofSha1(sha1);
    this.downloader = downloader;
    this.type = type;
    this.output =
        BuildTargetPaths.getGenPath(
            getProjectFilesystem().getBuckPaths(), buildTarget, "%s/" + out);
  }

  @Override
  public ImmutableList<Step> getBuildSteps(
      BuildContext context, BuildableContext buildableContext) {
    ImmutableList.Builder<Step> steps = ImmutableList.builder();
    RelPath tempFile =
        BuildTargetPaths.getScratchPath(
            getProjectFilesystem(), getBuildTarget(), "%s/" + output.getFileName());

    steps.addAll(
        MakeCleanDirectoryStep.of(
            BuildCellRelativePath.fromCellRelativePath(
                context.getBuildCellRootPath(), getProjectFilesystem(), tempFile.getParent())));
    steps.add(
        new DownloadStep(
            getProjectFilesystem(), downloader, uri, ImmutableList.of(), sha1, tempFile.getPath()));

    steps.addAll(
        MakeCleanDirectoryStep.of(
            BuildCellRelativePath.fromCellRelativePath(
                context.getBuildCellRootPath(), getProjectFilesystem(), output.getParent())));
    if (type == Type.EXPLODED_ZIP) {

      steps.addAll(
          MakeCleanDirectoryStep.of(
              BuildCellRelativePath.fromCellRelativePath(
                  context.getBuildCellRootPath(), getProjectFilesystem(), output)));
      steps.add(
          new UnzipStep(
              getProjectFilesystem(), tempFile.getPath(), output.getPath(), Optional.empty()));
    } else {
      steps.add(CopyStep.forFile(tempFile, output));
    }
    if (type == Type.EXECUTABLE) {
      steps.add(new MakeExecutableStep(getProjectFilesystem(), output));
    }

    buildableContext.recordArtifact(output.getPath());

    return steps.build();
  }

  @Override
  public SourcePath getSourcePathToOutput() {
    // EXPLODED_ZIP remote files can include many files; hashing the exploded files to compute
    // an input-based rule key can take a very long time. But we have an ace up our sleeve:
    // we already have a hash that represents the content in those exploded files!
    // Just pass that hash along so that RuleKeyBuilder can use it.
    return ExplicitBuildTargetSourcePath.of(
        BuildTargetWithOutputs.of(getBuildTarget(), OutputLabel.defaultLabel()),
        output.getPath(),
        Optional.of(sha1.getHashCode()));
  }

  /** Defines how the remote file should be treated when downloaded. */
  public enum Type {
    DATA,
    EXECUTABLE,
    EXPLODED_ZIP,
  }
}


text:
package net.jsign;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ByteChannel;
import java.nio.channels.SeekableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.security.MessageDigest;

/**
 * Helper class for Channel operations.
 *
 * @since 4.0
 */
public class ChannelUtils {

    public static void copy(SeekableByteChannel src, WritableByteChannel dest) throws IOException {
        ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024);
        src.position(0);

        while (src.position() < src.size()) {
            buffer.clear();
            src.read(buffer);
            buffer.flip();
            dest.write(buffer);
        }
    }

    public static void copy(SeekableByteChannel src, SeekableByteChannel dest, long length) throws IOException {
        ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024);
        long remaining = length;
        long destOffset = dest.position();
        long srcOffset = src.position();
        while (remaining > 0) {
            int avail = (int) Math.min(remaining, buffer.capacity());
            buffer.clear();
            buffer.limit(avail);

            src.position(srcOffset);
            src.read(buffer);
            buffer.flip();

            dest.position(destOffset);
            dest.write(buffer);
            remaining -= buffer.position();
            srcOffset += buffer.position();
            destOffset += buffer.position();
        }
    }

    /**
     * Insert data into a SeekableByteChannel at the specified position,
     * shifting the data after the insertion point.
     */
    public static void insert(SeekableByteChannel channel, long position, byte[] data) throws IOException {
        if (position > channel.size()) {
            throw new IOException("Cannot insert data after the end of the file");
        }

        File backupFile = File.createTempFile("jsign", ".tmp");
        try (SeekableByteChannel backupChannel = Files.newByteChannel(backupFile.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) {
            copy(channel, backupChannel);

            channel.position(position);
            channel.write(ByteBuffer.wrap(data));

            backupChannel.position(position);
            copy(backupChannel, channel, backupChannel.size() - position);
        } finally {
            backupFile.delete();
        }
    }

    /**
     * Update the specified digest by reading the SeekableByteChannel
     * from the start offset included to the end offset excluded.
     *
     * @param digest      the message digest to update
     * @param startOffset the start offset
     * @param endOffset   the end offset
     * @throws IOException if an I/O error occurs
     */
    public static void updateDigest(SeekableByteChannel channel, MessageDigest digest, long startOffset, long endOffset) throws IOException {
        channel.position(startOffset);

        ByteBuffer buffer = ByteBuffer.allocate(8192);

        long position = startOffset;
        while (position < endOffset) {
            buffer.clear();
            buffer.limit((int) Math.min(buffer.capacity(), endOffset - position));
            channel.read(buffer);
            buffer.rewind();

            digest.update(buffer);

            position += buffer.limit();
        }
    }

    /**
     * Read a null terminated string from the specified channel.
     */
    public static byte[] readNullTerminatedString(ByteChannel channel) throws IOException {
        try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
            byte singleChar;
            ByteBuffer buffer = ByteBuffer.allocate(1);
            do {
                buffer.clear();
                buffer.limit(1);
                if (channel.read(buffer) < 0) {
                    throw new IOException("End of file reached, cannot read null terminated string");
                }
                buffer.flip();
                singleChar = buffer.array()[0];
                bos.write(singleChar);
            } while (singleChar != 0);
            return bos.toByteArray();
        }
    }
}


text:
package net.java.html.leaflet;

import net.java.html.js.JavaScriptBody;

/**
 * Equirectangular, or Plate Carree projection
 */
public final class LonLatProjection extends IProjection {

    private static final LonLatProjection instance = new LonLatProjection();

    static {
        Options.initJS();
        IProjection.registerProjection("LonLatProjection", instance);
    }

    /**
     * Returns the Instance of LonLatProjection
     * @return instance of LonLatProjection
     */
    public LonLatProjection get() {
        return instance;
    }

    private LonLatProjection() {
        super(getProjectionInternal());
    }

    @JavaScriptBody(args = {}, body = "return L.Projection.LonLat;")
    private static native Object getProjectionInternal();
}


text:
import { Injectable } from '@angular/core';
import { Cordova, Plugin, CordovaFunctionOverride, IonicNativePlugin } from '@ionic-native/core';
import { Observable } from 'rxjs/Observable';

declare var window: any;

/**
 * @name Geofence
 * @description Monitors circular geofences around latitude/longitude coordinates, and sends a notification to the user when the boundary of a geofence is crossed. Notifications can be sent when the user enters and/or exits a geofence.
 * Geofences persist after device reboot. Geofences will be monitored even when the app is not running.
 * @usage
 * ```typescript
 * import { Geofence } from '@ionic-native/geofence';
 *
 * ...
 *
 * constructor(private geofence: Geofence) {
 *   // initialize the plugin
 *   geofence.initialize().then(
 *     // resolved promise does not return a value
 *     () => console.log('Geofence Plugin Ready'),
 *     (err) => console.log(err)
 *   )
 * }
 *
 * ...
 *
 * private addGeofence() {
 *   //options describing geofence
 *   let fence = {
 *     id: '69ca1b88-6fbe-4e80-a4d4-ff4d3748acdb', //any unique ID
 *     latitude:       37.285951, //center of geofence radius
 *     longitude:      -121.936650,
 *     radius:         100, //radius to edge of geofence
 *     transitionType: 3, //see 'Transition Types' below
 *     notification: { //notification settings
 *         id:             1, //any unique ID
 *         title:          'You crossed a fence', //notification title
 *         text:           'You just arrived to Gliwice city center.', //notification body
 *         openAppOnClick: true //open app when notification is tapped
 *     }
 *   }
 *
 *   this.geofence.addOrUpdate(fence).then(
 *      () => console.log('Geofence added'),
 *      (err) => console.log('Geofence failed to add')
 *    );
 * }
 *
 * ```
 * ### Transition Types ###
 * Transition type specifies whether the geofence should trigger when the user enters and/or leaves the geofence.
 *
 * #### Supported values ####
 * - 1: Enter
 * - 2: Leave
 * - 3: Both
 *
 * ### Defining a Geofence ###
 * Geofences are defined by an object that is passed to `addOrUpdate()`. Object properties are:
 * - id: Any unique ID for the geofence. This ID is used to remove and update a geofence
 * - latitude: Latitude coordinate of the center of the geofence radius
 * - longitude: Latitude coordinate of the center of the geofence radius
 * - radius: Radius from the center to the edge of the geofence
 * - transitionType: Type of geofence transition to monitor for. See 'Transition Types' above
 * - notification: Object. Options for defining the notification sent when a geofence is crossed
 *   - id: Any unique ID
 *   - title: Notification title
 *   - text: Notification body
 *   - openAppOnClick: Boolean. Whether to open the app when the notification is tapped by the user
 *
 * ### Troubleshooting ###
 * #### I get compile errors when I run `ionic build ios` or `ionic run ios`. ####
 * This could be caused by the Cordova project directory in `/platforms/ios` not being named correctly.
 * Try running `ionic platform rm <platform>` then run `ionic platform add <platform>` to recreate the
 * platform directories.
 */
@Plugin({
  pluginName: 'Geofence',
  plugin: 'cordova-plugin-geofence',
  pluginRef: 'geofence',
  repo: 'https://github.com/cowbell/cordova-plugin-geofence/',
  platforms: ['Android', 'iOS', 'Windows Phone 8', 'Windows Phone']
})
@Injectable()
export class Geofence extends IonicNativePlugin {

  public TransitionType = {
    ENTER: 1,
    EXIT: 2,
    BOTH: 3
  };

  /**
   * Subscribe to get notified when a transition is received
   * @return {Observable<any>}
   */
  @CordovaFunctionOverride()
  onTrasitionReceived(): Observable<any> { return; };

  /**
   * Initializes the plugin. User will be prompted to allow the app to use location and notifications.
   *
   * @returns {Promise<void>}
   */
  @Cordova()
  initialize(): Promise<void> { return; };

  /**
   * Adds a new geofence or array of geofences. For geofence object, see above.
   *
   * @returns {Promise<void>}
   */
  @Cordova()
  addOrUpdate(geofences: Object | Array<Object>): Promise<void> { return; };

  /**
   * Removes a geofence or array of geofences. `geofenceID` corresponds to one or more IDs specified when the
   * geofence was created.
   *
   * @returns {Promise<void>}
   */
  @Cordova()
  remove(geofenceId: string | Array<string>): Promise<void> { return; };

  /**
   * Removes all geofences.
   *
   * @returns {Promise<void>}
   */
  @Cordova()
  removeAll(): Promise<void> { return; };

  /**
   * Returns an array of geofences currently being monitored.
   *
   * @returns {Promise<Array<string>>}
   */
  @Cordova()
  getWatched(): Promise<string> { return; };

  /**
   * Called when a geofence is crossed in the direction specified by `TransitType`.
   *
   * @returns {Observable<any>}
   */
  onTransitionReceived(): Observable<any> {

    return new Observable<any>((observer) => {
      window && window.geofence && (window.geofence.onTransitionReceived = observer.next.bind(observer));
      return () => window.geofence.onTransitionReceived = () => { };
    });

  }

  /**
   * Called when the user clicks a geofence notification. iOS and Android only.
   *
   * @returns {Observable<any>}
   */
  onNotificationClicked(): Observable<any> {

    return new Observable<any>((observer) => {
      window && window.geofence && (window.geofence.onNotificationClicked = observer.next.bind(observer));
      return () => window.geofence.onNotificationClicked = () => { };
    });

  }

}


text:
Hipermark benchmarks
====================

Various benchmarks and implementations based on the Hipermark infrastructure.

Trying it out
-------------

Remember do to a recursive checkout to get the `hipermark` submodule.
Then run:

    hipermark/hipermark instantiations/ 10 benchmarks/american_options haskell_sequential 8

Yes, the user interface could stand some improvement.  The above will
run the haskell_sequential implementation of the american_options
benchmark on the dataset with the name `8`, running the implementation
ten times and reporting the result.


text:
package aima.logic.fol.inference.proof;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import aima.logic.fol.kb.data.Chain;

/**
 * @author Ciaran O'Reilly
 *
 */
public class ProofStepChainDropped extends AbstractProofStep {
	private List<ProofStep> predecessors = new ArrayList<ProofStep>();
	private Chain dropped = null;
	private Chain droppedOff = null;

	public ProofStepChainDropped(Chain dropped, Chain droppedOff) {
		this.dropped = dropped;
		this.droppedOff = droppedOff;
		this.predecessors.add(droppedOff.getProofStep());
	}

	//
	// START-ProofStep
	public List<ProofStep> getPredecessorSteps() {
		return Collections.unmodifiableList(predecessors);
	}

	public String getProof() {
		return dropped.toString();
	}

	public String getJustification() {
		return "Dropped: " + droppedOff.getProofStep().getStepNumber();
	}
	// END-ProofStep
	//
}


text:
<?php

namespace Yomaah\structureBundle\Classes;

use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\SecurityContextInterface;
/**
 * Le listener implemente un compteur de visite
 * en se basant sur l'adresse ip et la date de connexion
 * le compteur est incrémenté quand :
 *      - la date de dernière connexion est supérieure à 12h
 *      - première visite sur le site
 *
 **/
class RequeteListener
{
    private $db;
    private $secure;

    public function __construct(\Doctrine\DBAL\Connection $db,SecurityContextInterface $secure)
    {
        $this->db = $db;
        $this->secure = $secure;
    }

    /**
     * Implémenter une erreur si $this->secure->getToken() == null
     * Car a chaque fois sa le fait sur une page sans route
     * Comme c la page avec la première erreur
     * L'appli doit passer d'abord par ce code
     **/
    public function onKernelRequest(GetResponseEvent $event)
    {
		$request = $event->getRequest();

		/*
		* Passe 2 fois par ce script je pense lors de l'envoi de la toolbar symfony
		*/
		if (!($request->getSession()->has('secondPass')))
		{
			$request->getSession()->set('secondPass',true);
			$this->setVisite($request);
		}else if (!($request->getSession()->get('secondPass')))
		{
			$this->setVisite($request);
			$request->getSession()->set('secondPass',true);
		}else if ($request->getSession()->has('secondPass'))
		{
			$request->getSession()->set('secondPass',false);
		}
    }

	public function setVisite($request)
	{
		$sql = 'select max(dateConnexion) as date,adresseIp from visites where adresseIp = ?';
	    //$sql = 'select dateConnexion as date,adresseIp from visites where adresseIp = ? and dateConnexion = (select max(dateConnexion) from visites)';

	    $ip = $request->getClientIp();
	    $result = $this->db->executeQuery($sql,array($ip));
	    $result->setFetchMode(\PDO::FETCH_OBJ);
	    foreach ($result as $r)
	    {
			$test = $r->date;
	    }
if ($this->secure->getToken() != null)
{
		$date = new \Datetime($test);

		/**
		* Si visite d'adresse ip inconnu
		*/

	    if (($this->secure->getToken()->getUser() == "anon.") && ($test == null))
	    {
	        $insert = 'insert into visites (adresseIp, dateConnexion) values (?,Now())';
	        $this->db->executeUpdate($insert, array($ip));
		/**
		* Si visite ip connu mais date > 12h
		*/
	    }else if (($this->secure->getToken()->getUser() == "anon.") && ($this->testDate($date)))
	    {
	        $insert = 'insert into visites (adresseIp, dateConnexion) values (?,Now())';
	        $this->db->executeUpdate($insert, array($ip));
		/**
		* Si adresse connu dans tous les cas on associe la visite avec l'admin
		*/
/* A remplacer en prod

}else if ($this->secure->isGranted('ROLE_SUPER_ADMIN') || $this->secure->isGranted('ROLE_ADMIN'))
 */
	    }else if ($this->secure->isGranted('ROLE_SUPER_ADMIN'))
	    {
	        $id = $this->secure->getToken()->getUser()->getIdUser();
	        $sql = 'update visites set idUser = ? where adresseIp = ? and dateConnexion = ?';
	        $this->db->executeUpdate($sql, array($id, $ip, $date->format('Y-m-d H:i:s')));
		/**
		*	Adresse connu et role_user restant
		*	Si la date est supérieure (pas obligatoire car pas de cookie remember me
		*	ie première visite en anonyme forcément enregistré dans le second if)
		*/
	    }else if ($this->testDate($date))
	    {
	        /**
	         * Cette partie pour enregistrer les utilisateurs test
	         * A enlever aussi
	         **/
			$date = new \Datetime($test);
	        $id = $this->secure->getToken()->getUser()->getIdUser();
	        $sql = 'update visites set idUser = ? where adresseIp = ? and dateConnexion = ?';
	        $this->db->executeUpdate($sql, array($id, $ip, $date->format('Y-m-d H:i:s')));
	    }
}
	}

    public function testDate($date)
    {
        $dateNow = new \Datetime();
        $diff = $date->diff($dateNow);
        if ($diff->h >= 12 || $diff->d >= 1)
        {
            return true;
        }else
        {
            return false;
        }

    }

    /*
     * Pas de compteur dans un fichier
     * Enregistrement de tous les ip et dates de connexion différentes
     * Comptage au moment de l'affichage
     * Exclusion ip administrateur plus tard pour alléger la base
     *
     **/
    //public function incrementCompteur()
    //{
        //$fichier = fopen(__DIR__.'/compteur.txt','r+');
        //while (!feof($fichier))
        //{
            //$buffer = fgets($fichier,4096);
            //if ($buffer !== false)
            //{
                //$compteur = (int) $buffer;
                //$compteur +=1;
            //}
        //}
        //fseek($fichier,0);
        //ftruncate($fichier,0);
        //fwrite($fichier,(string) $compteur);
        //fclose($fichier);
    //}

    //private function decrementCompteur()
    //{
        //$fichier = fopen(__DIR__.'/compteur.txt','r+');
        //while (!feof($fichier))
        //{
            //$buffer = fgets($fichier,4096);
            //if ($buffer !== false)
            //{
                //$compteur = (int) $buffer;
                //$compteur -=1;
            //}
        //}
        //fseek($fichier,0);
        //ftruncate($fichier,0);
        //fwrite($fichier,(string) $compteur);
        //fclose($fichier);
    //}

}