<commit_before>package testing

import (
	"testing"

	rbacv1 "k8s.io/api/rbac/v1beta1"

	navinformers "github.com/jetstack/navigator/pkg/client/informers/externalversions"
	"github.com/jetstack/navigator/pkg/controllers"

	"github.com/jetstack/navigator/pkg/apis/navigator/v1alpha1"
	"github.com/jetstack/navigator/pkg/controllers/cassandra"
	"github.com/jetstack/navigator/pkg/controllers/cassandra/nodepool"
	"github.com/jetstack/navigator/pkg/controllers/cassandra/pilot"
	"github.com/jetstack/navigator/pkg/controllers/cassandra/role"
	"github.com/jetstack/navigator/pkg/controllers/cassandra/rolebinding"
	"github.com/jetstack/navigator/pkg/controllers/cassandra/seedlabeller"
	"github.com/jetstack/navigator/pkg/controllers/cassandra/service"
	"github.com/jetstack/navigator/pkg/controllers/cassandra/serviceaccount"

	"k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	apps "k8s.io/api/apps/v1beta1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/client-go/informers"
	"k8s.io/client-go/kubernetes/fake"
	"k8s.io/client-go/tools/cache"
	"k8s.io/client-go/tools/record"

	navigatorfake "github.com/jetstack/navigator/pkg/client/clientset/versioned/fake"
)

func ClusterForTest() *v1alpha1.CassandraCluster {
	c := &v1alpha1.CassandraCluster{
		Spec: v1alpha1.CassandraClusterSpec{
			NodePools: []v1alpha1.CassandraClusterNodePool{
				v1alpha1.CassandraClusterNodePool{
					Name:     "RingNodes",
					Replicas: 3,
				},
			},
		},
	}
	c.SetName("cassandra-1")
	c.SetNamespace("app-1")
	return c
}

type Fixture struct {
	t                          *testing.T
	Cluster                    *v1alpha1.CassandraCluster
	SeedProviderServiceControl cassandra.ControlInterface
	NodesServiceControl        cassandra.ControlInterface
	NodepoolControl            nodepool.Interface
	PilotControl               pilot.Interface
	ServiceAccountControl      serviceaccount.Interface
	RoleControl                role.Interface
	RoleBindingControl         rolebinding.Interface
	SeedLabellerControl        seedlabeller.Interface
	k8sClient                  *fake.Clientset
	k8sObjects                 []runtime.Object
	naviClient                 *navigatorfake.Clientset
	naviObjects                []runtime.Object
}

func NewFixture(t *testing.T) *Fixture {
	return &Fixture{
		t:       t,
		Cluster: ClusterForTest(),
	}
}

func (f *Fixture) AddObjectK(o runtime.Object) {
	f.k8sObjects = append(f.k8sObjects, o)
}

func (f *Fixture) AddObjectN(o runtime.Object) {
	f.naviObjects = append(f.naviObjects, o)
}

func (f *Fixture) setupAndSync() error {
	recorder := record.NewFakeRecorder(0)
	finished := make(chan struct{})
	defer func() {
		close(recorder.Events)
		<-finished
	}()
	go func() {
		for e := range recorder.Events {
			f.t.Logf("EVENT: %q", e)
		}
		close(finished)
	}()
	f.k8sClient = fake.NewSimpleClientset(f.k8sObjects...)
	k8sFactory := informers.NewSharedInformerFactory(f.k8sClient, 0)

	services := k8sFactory.Core().V1().Services().Lister()
	if f.SeedProviderServiceControl == nil {
		f.SeedProviderServiceControl = service.NewControl(
			f.k8sClient,
			services,
			recorder,
			service.SeedsServiceForCluster,
		)
	}
	if f.NodesServiceControl == nil {
		f.NodesServiceControl = service.NewControl(
			f.k8sClient,
			services,
			recorder,
			service.NodesServiceForCluster,
		)
	}
	statefulSets := k8sFactory.Apps().V1beta1().StatefulSets().Lister()
	pods := k8sFactory.Core().V1().Pods().Lister()
	if f.NodepoolControl == nil {
		f.NodepoolControl = nodepool.NewControl(
			f.k8sClient,
			statefulSets,
			recorder,
		)
	}
	f.naviClient = navigatorfake.NewSimpleClientset(f.naviObjects...)
	naviFactory := navinformers.NewSharedInformerFactory(f.naviClient, 0)
	pilots := naviFactory.Navigator().V1alpha1().Pilots().Lister()
	if f.PilotControl == nil {
		f.PilotControl = pilot.NewControl(
			f.naviClient,
			pilots,
			pods,
			statefulSets,
			recorder,
		)
	}
	serviceAccounts := k8sFactory.Core().V1().ServiceAccounts().Lister()
	if f.ServiceAccountControl == nil {
		f.ServiceAccountControl = serviceaccount.NewControl(
			f.k8sClient,
			serviceAccounts,
			recorder,
		)
	}

	roles := k8sFactory.Rbac().V1beta1().Roles().Lister()
	if f.RoleControl == nil {
		f.RoleControl = role.NewControl(
			f.k8sClient,
			roles,
			recorder,
		)
	}

	roleBindings := k8sFactory.Rbac().V1beta1().RoleBindings().Lister()
	if f.RoleBindingControl == nil {
		f.RoleBindingControl = rolebinding.NewControl(
			f.k8sClient,
			roleBindings,
			recorder,
		)
	}

	if f.SeedLabellerControl == nil {
		f.SeedLabellerControl = seedlabeller.NewControl(
			f.k8sClient,
			statefulSets,
			pods,
			recorder,
		)
	}

	c := cassandra.NewControl(
		f.SeedProviderServiceControl,
		f.NodesServiceControl,
		f.NodepoolControl,
		f.PilotControl,
		f.ServiceAccountControl,
		f.RoleControl,
		f.RoleBindingControl,
		f.SeedLabellerControl,
		recorder,
		&controllers.State{
			Clientset:         f.k8sClient,
			StatefulSetLister: statefulSets,
			Recorder:          recorder,
		},
	)
	stopCh := make(chan struct{})
	defer close(stopCh)
	k8sFactory.Start(stopCh)
	naviFactory.Start(stopCh)
	if !cache.WaitForCacheSync(
		stopCh,
		k8sFactory.Core().V1().Pods().Informer().HasSynced,
		k8sFactory.Core().V1().Services().Informer().HasSynced,
		k8sFactory.Apps().V1beta1().StatefulSets().Informer().HasSynced,
		naviFactory.Navigator().V1alpha1().Pilots().Informer().HasSynced,
		k8sFactory.Core().V1().ServiceAccounts().Informer().HasSynced,
		k8sFactory.Rbac().V1beta1().Roles().Informer().HasSynced,
		k8sFactory.Rbac().V1beta1().RoleBindings().Informer().HasSynced,
	) {
		f.t.Fatal("WaitForCacheSync failure")
	}
	return c.Sync(f.Cluster)
}

func (f *Fixture) Run() {
	err := f.setupAndSync()
	if err != nil {
		f.t.Error(err)
	}
}

func (f *Fixture) RunExpectError() {
	err := f.setupAndSync()
	if err == nil {
		f.t.Error("Sync was expected to return an error. Got nil.")
	}
}

func (f *Fixture) Services() *v1.ServiceList {
	services, err := f.k8sClient.
		CoreV1().
		Services(f.Cluster.Namespace).
		List(metav1.ListOptions{})
	if err != nil {
		f.t.Fatal(err)
	}
	return services
}

func (f *Fixture) AssertServicesLength(l int) {
	services := f.Services()
	servicesLength := len(services.Items)
	if servicesLength != l {
		f.t.Log(services)
		f.t.Errorf(
			"Incorrect number of services: %#v", servicesLength,
		)
	}
}

func (f *Fixture) ServiceAccounts() *v1.ServiceAccountList {
	serviceAccounts, err := f.k8sClient.
		CoreV1().
		ServiceAccounts(f.Cluster.Namespace).
		List(metav1.ListOptions{})
	if err != nil {
		f.t.Fatal(err)
	}
	return serviceAccounts
}

func (f *Fixture) AssertServiceAccountsLength(l int) {
	serviceAccounts := f.ServiceAccounts()
	serviceAccountsLength := len(serviceAccounts.Items)
	if serviceAccountsLength != l {
		f.t.Log(serviceAccounts)
		f.t.Errorf(
			"Incorrect number of services accounts. Expected %d. Got %d.",
			l,
			serviceAccountsLength,
		)
	}
}

func (f *Fixture) Roles() *rbacv1.RoleList {
	roles, err := f.k8sClient.
		RbacV1beta1().
		Roles(f.Cluster.Namespace).
		List(metav1.ListOptions{})
	if err != nil {
		f.t.Fatal(err)
	}
	return roles
}

func (f *Fixture) AssertRolesLength(l int) {
	roles := f.Roles()
	rolesLength := len(roles.Items)
	if rolesLength != l {
		f.t.Log(roles)
		f.t.Errorf(
			"Incorrect number of roles. Expected %d. Got %d.",
			l,
			rolesLength,
		)
	}
}

func (f *Fixture) RoleBindings() *rbacv1.RoleBindingList {
	roleBindings, err := f.k8sClient.
		RbacV1beta1().
		RoleBindings(f.Cluster.Namespace).
		List(metav1.ListOptions{})
	if err != nil {
		f.t.Fatal(err)
	}
	return roleBindings
}

func (f *Fixture) AssertRoleBindingsLength(l int) {
	roleBindings := f.RoleBindings()
	roleBindingsLength := len(roleBindings.Items)
	if roleBindingsLength != l {
		f.t.Log(roleBindings)
		f.t.Errorf(
			"Incorrect number of role bindings. Expected %d. Got %d.",
			l,
			roleBindingsLength,
		)
	}
}

func (f *Fixture) StatefulSets() *apps.StatefulSetList {
	sets, err := f.k8sClient.
		AppsV1beta1().
		StatefulSets(f.Cluster.Namespace).
		List(metav1.ListOptions{})
	if err != nil {
		f.t.Fatal(err)
	}
	return sets
}

func (f *Fixture) AssertStatefulSetsLength(l int) {
	sets := f.StatefulSets()
	setsLength := len(sets.Items)
	if setsLength != l {
		f.t.Log(sets)
		f.t.Errorf(
			"Incorrect number of StatefulSets: %#v", setsLength,
		)
	}
}

func (f *Fixture) Pilots() *v1alpha1.PilotList {
	pilots, err := f.naviClient.
		NavigatorV1alpha1().
		Pilots(f.Cluster.Namespace).
		List(metav1.ListOptions{})
	if err != nil {
		f.t.Fatal(err)
	}
	return pilots
}

func (f *Fixture) AssertPilotsLength(l int) {
	sets := f.Pilots()
	setsLength := len(sets.Items)
	if setsLength != l {
		f.t.Log(sets)
		f.t.Errorf(
			"Incorrect number of Pilots: %#v", setsLength,
		)
	}
}

type FakeControl struct {
	SyncError error
}

func (c *FakeControl) Sync(cluster *v1alpha1.CassandraCluster) error {
	return c.SyncError
}
<commit_msg>Remove Cassandra testing fixture<commit_after>package testing

import (
	"github.com/jetstack/navigator/pkg/apis/navigator/v1alpha1"
)

func ClusterForTest() *v1alpha1.CassandraCluster {
	c := &v1alpha1.CassandraCluster{
		Spec: v1alpha1.CassandraClusterSpec{
			NodePools: []v1alpha1.CassandraClusterNodePool{
				v1alpha1.CassandraClusterNodePool{
					Name:     "RingNodes",
					Replicas: 3,
				},
			},
		},
	}
	c.SetName("cassandra-1")
	c.SetNamespace("app-1")
	return c
}
<|endoftext|>


<commit_before>package chronos

import (
	"fmt"
	"github.com/squioc/axis"
	"testing"
	"time"
)

/****************************************
*                                       *
*                 Tests                 *
*                                       *
****************************************/

func expect(t *testing.T, expected EntryTest, actual Entry, stopChan chan bool) {
	if actual == nil {
		stopChan <- true
		t.Fatalf("The actual element wasn't expected to be nil")
	}
	if actual.(*EntryTest).Element != expected.Element {
		stopChan <- true
		t.Fatalf("The actual element wasn't the expected one")
	}
}

func TestRunWithJobsInOrder(t *testing.T) {
	fmt.Println("Test Run with jobs in order should send in order")
	// Arrange
	position := axis.Position(0)
	newPosition := axis.Position(1500)
	provider := axis.NewFakeTime(position)
	pq := new(PriorityQueue)
	chronos := NewChronos(provider, pq)
	pushChan := make(chan Entry, 2)
	workerChan := make(chan Entry, 2)
	stopChan := make(chan bool, 1)
	firstEntry := &EntryTest{
		position: axis.Position(500),
		Element:  "First",
	}
	secondEntry := &EntryTest{
		position: axis.Position(1000),
		Element:  "Second",
	}

	// Act
	go chronos.Run(pushChan, workerChan, stopChan)
	pushChan <- firstEntry
	pushChan <- secondEntry
	// Lets the goroutine starts then updates the position
	time.Sleep(5)
	provider.Update(newPosition)

	// Assert
	firstElement := <-workerChan
	expect(t, *firstEntry, firstElement, stopChan)
	secondElement := <-workerChan
	expect(t, *secondEntry, secondElement, stopChan)
	stopChan <- true
}

func TestRunWithJobsInReverseOrder(t *testing.T) {
	fmt.Println("Test Run with jobs in reverse order should send in reverse order")
	// Arrange
	position := axis.Position(0)
	newPosition := axis.Position(1500)
	provider := axis.NewFakeTime(position)
	pq := new(PriorityQueue)
	chronos := NewChronos(provider, pq)
	pushChan := make(chan Entry, 2)
	workerChan := make(chan Entry, 2)
	stopChan := make(chan bool, 1)
	firstEntry := &EntryTest{
		position: axis.Position(1000),
		Element:  "First",
	}
	secondEntry := &EntryTest{
		position: axis.Position(500),
		Element:  "Second",
	}

	// Act
	go chronos.Run(pushChan, workerChan, stopChan)
	pushChan <- firstEntry
	pushChan <- secondEntry
	// Lets the goroutine starts then updates the position
	time.Sleep(5)
	provider.Update(newPosition)

	// Assert
	firstElement := <-workerChan
	expect(t, *secondEntry, firstElement, stopChan)
	secondElement := <-workerChan
	expect(t, *firstEntry, secondElement, stopChan)
	stopChan <- true
}

func TestRunWithStop(t *testing.T) {
	fmt.Println("Test Run with Stop should exit")
	// Arrange
	position := axis.Position(0)
	provider := axis.NewFakeTime(position)
	pq := new(PriorityQueue)
	chronos := NewChronos(provider, pq)
	pushChan := make(chan Entry, 2)
	workerChan := make(chan Entry, 2)
	stopChan := make(chan bool, 1)
	firstEntry := &EntryTest{
		position: axis.Position(1000),
		Element:  "First",
	}

	// Act
	exitChan := make(chan bool, 1)
	// go routine to check that we leave the Run method when we send a booleen on stopChan
	go func(exitChan chan bool) {
		chronos.Run(pushChan, workerChan, stopChan)
		// Send boolean on the channel when the Run method exits
		exitChan <- true
	}(exitChan)
	// Lets the goroutine starts then stop the goroutine
	time.Sleep(5)
	stopChan <- true
	// Sends an entry to the goroutine
	pushChan <- firstEntry

	// Assert
	select {
	case <-exitChan:
		// PASS
		return
	case <-workerChan:
		// FAIL, we expected to exit, not to receive an item
		t.Fatalf("Expected exit, not item")
	case <-time.After(2 * time.Second):
		// FAIL, timeout
		t.Fatalf("Timeout. the test exceed the expected duration")
	}
}

/****************************************
*                                       *
*        Structs implementations        *
*                                       *
****************************************/

type EntryTest struct {
	position axis.Position
	Element  interface{}
	index    int
}

func (e EntryTest) Position() axis.Position {
	return e.position
}

type PriorityQueue []*EntryTest

func (pq *PriorityQueue) Len() int {
	return len(*pq)
}

func (pq *PriorityQueue) Less(i, j int) bool {
	ll := *pq
	return ll[i].Position() < ll[j].Position()
}

func (pq *PriorityQueue) Swap(i, j int) {
	ll := *pq
	ll[i], ll[j] = ll[j], ll[i]
	ll[i].index = i
	ll[j].index = j
}

func (pq *PriorityQueue) Push(v interface{}) {
	n := len(*pq)
	item := v.(*EntryTest)
	item.index = n
	*pq = append(*pq, item)
}

func (pq *PriorityQueue) Pop() interface{} {
	ll := *pq
	n := len(ll)
	item := ll[n-1]
	item.index = -1
	*pq = ll[0 : n-1]
	return item
}

func (pq *PriorityQueue) Peek() interface{} {
	ll := *pq
	n := len(ll)
	if n <= 0 {
		return nil
	}
	item := ll[n-1]
	return item
}
<commit_msg>Use goroutine instead of time.Sleep<commit_after>package chronos

import (
	"fmt"
	"github.com/squioc/axis"
	"testing"
	"time"
)

/****************************************
*                                       *
*                 Tests                 *
*                                       *
****************************************/

func expect(t *testing.T, expected EntryTest, actual Entry, stopChan chan bool) {
	if actual == nil {
		stopChan <- true
		t.Fatalf("The actual element wasn't expected to be nil")
	}
	if actual.(*EntryTest).Element != expected.Element {
		stopChan <- true
		t.Fatalf("The actual element wasn't the expected one")
	}
}

func TestRunWithJobsInOrder(t *testing.T) {
	fmt.Println("Test Run with jobs in order should send in order")
	// Arrange
	position := axis.Position(0)
	newPosition := axis.Position(1500)
	provider := axis.NewFakeTime(position)
	pq := new(PriorityQueue)
	chronos := NewChronos(provider, pq)
	pushChan := make(chan Entry, 2)
	workerChan := make(chan Entry, 2)
	stopChan := make(chan bool, 1)
	firstEntry := &EntryTest{
		position: axis.Position(500),
		Element:  "First",
	}
	secondEntry := &EntryTest{
		position: axis.Position(1000),
		Element:  "Second",
	}

	// Act
	go chronos.Run(pushChan, workerChan, stopChan)
	pushChan <- firstEntry
	pushChan <- secondEntry
	// Updates the position
	go provider.Update(newPosition)

	// Assert
	firstElement := <-workerChan
	expect(t, *firstEntry, firstElement, stopChan)
	secondElement := <-workerChan
	expect(t, *secondEntry, secondElement, stopChan)
	stopChan <- true
}

func TestRunWithJobsInReverseOrder(t *testing.T) {
	fmt.Println("Test Run with jobs in reverse order should send in reverse order")
	// Arrange
	position := axis.Position(0)
	newPosition := axis.Position(1500)
	provider := axis.NewFakeTime(position)
	pq := new(PriorityQueue)
	chronos := NewChronos(provider, pq)
	pushChan := make(chan Entry, 2)
	workerChan := make(chan Entry, 2)
	stopChan := make(chan bool, 1)
	firstEntry := &EntryTest{
		position: axis.Position(1000),
		Element:  "First",
	}
	secondEntry := &EntryTest{
		position: axis.Position(500),
		Element:  "Second",
	}

	// Act
	go chronos.Run(pushChan, workerChan, stopChan)
	pushChan <- firstEntry
	pushChan <- secondEntry
	// Updates the position
	go provider.Update(newPosition)

	// Assert
	firstElement := <-workerChan
	expect(t, *secondEntry, firstElement, stopChan)
	secondElement := <-workerChan
	expect(t, *firstEntry, secondElement, stopChan)
	stopChan <- true
}

func TestRunWithStop(t *testing.T) {
	fmt.Println("Test Run with Stop should exit")
	// Arrange
	position := axis.Position(0)
	provider := axis.NewFakeTime(position)
	pq := new(PriorityQueue)
	chronos := NewChronos(provider, pq)
	pushChan := make(chan Entry, 2)
	workerChan := make(chan Entry, 2)
	stopChan := make(chan bool, 1)
	firstEntry := &EntryTest{
		position: axis.Position(1000),
		Element:  "First",
	}

	// Act
	exitChan := make(chan bool, 1)
	// go routine to check that we leave the Run method when we send a booleen on stopChan
	go func(exitChan chan bool) {
		chronos.Run(pushChan, workerChan, stopChan)
		// Send boolean on the channel when the Run method exits
		exitChan <- true
	}(exitChan)
	// Lets the goroutine starts then stop the goroutine
	time.Sleep(5)
	stopChan <- true
	// Sends an entry to the goroutine
	pushChan <- firstEntry

	// Assert
	select {
	case <-exitChan:
		// PASS
		return
	case <-workerChan:
		// FAIL, we expected to exit, not to receive an item
		t.Fatalf("Expected exit, not item")
	case <-time.After(2 * time.Second):
		// FAIL, timeout
		t.Fatalf("Timeout. the test exceed the expected duration")
	}
}

/****************************************
*                                       *
*        Structs implementations        *
*                                       *
****************************************/

type EntryTest struct {
	position axis.Position
	Element  interface{}
	index    int
}

func (e EntryTest) Position() axis.Position {
	return e.position
}

type PriorityQueue []*EntryTest

func (pq *PriorityQueue) Len() int {
	return len(*pq)
}

func (pq *PriorityQueue) Less(i, j int) bool {
	ll := *pq
	return ll[i].Position() < ll[j].Position()
}

func (pq *PriorityQueue) Swap(i, j int) {
	ll := *pq
	ll[i], ll[j] = ll[j], ll[i]
	ll[i].index = i
	ll[j].index = j
}

func (pq *PriorityQueue) Push(v interface{}) {
	n := len(*pq)
	item := v.(*EntryTest)
	item.index = n
	*pq = append(*pq, item)
}

func (pq *PriorityQueue) Pop() interface{} {
	ll := *pq
	n := len(ll)
	item := ll[n-1]
	item.index = -1
	*pq = ll[0 : n-1]
	return item
}

func (pq *PriorityQueue) Peek() interface{} {
	ll := *pq
	n := len(ll)
	if n <= 0 {
		return nil
	}
	item := ll[n-1]
	return item
}
<|endoftext|>


<commit_before>// Copyright 2016 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.
//
// +build !windows

package libfuse

import (
	"bytes"
	"errors"
	"fmt"
	"os"
	"os/exec"
	"path"
	"runtime"
	"strings"

	"bazil.org/fuse"
	"github.com/keybase/client/go/kbconst"
	"github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/logger"
	keybase1 "github.com/keybase/client/go/protocol/keybase1"
)

type mounter struct {
	options StartOptions
	c       *fuse.Conn
	log     logger.Logger
	runMode kbconst.RunMode
}

// fuseMount tries to mount the mountpoint.
// On a force mount then unmount, re-mount if unsuccessful
func (m *mounter) Mount() (err error) {
	defer func() {
		if err != nil {
			msg := fmt.Sprintf("KBFS failed to FUSE mount at %s: %s", m.options.MountPoint, err)
			fmt.Println(msg)
			m.log.Warning(msg)
		}
	}()

	m.c, err = fuseMountDir(m.options.MountPoint, m.options.PlatformParams)
	// Exit if we were successful or we are not a force mounting on error.
	// Otherwise, try unmounting and mounting again.
	if err == nil || !m.options.ForceMount {
		return err
	}

	// Mount failed, let's try to unmount and then try mounting again, even
	// if unmounting errors here.
	m.Unmount()

	// In case we are on darwin, ask the installer to reinstall the mount dir
	// and try again as the last resort. This specifically fixes a situation
	// where /keybase gets created and owned by root after Keybase app is
	// started, and `kbfs` later fails to mount because of a permission error.
	m.reinstallMountDirIfPossible()
	m.c, err = fuseMountDir(m.options.MountPoint, m.options.PlatformParams)

	return err
}

func fuseMountDir(dir string, platformParams PlatformParams) (*fuse.Conn, error) {
	// Create mountdir directory on Linux.
	switch libkb.RuntimeGroup() {
	case keybase1.RuntimeGroup_LINUXLIKE:
		// Inherit permissions from containing directory and umask.
		err := os.MkdirAll(dir, os.ModeDir|os.ModePerm)
		if err != nil {
			return nil, err
		}
	default:
	}

	fi, err := os.Stat(dir)
	if err != nil {
		return nil, err
	}
	if !fi.IsDir() {
		return nil, errors.New("mount point is not a directory")
	}
	options, err := getPlatformSpecificMountOptions(dir, platformParams)
	if err != nil {
		return nil, err
	}
	c, err := fuse.Mount(dir, options...)
	if err != nil {
		err = translatePlatformSpecificError(err, platformParams)
		return nil, err
	}
	return c, nil
}

func isFusermountMountNotFoundError(output []byte, err error) bool {
	if err == nil {
		return false
	}
	return bytes.Contains(output, []byte("not found in /etc/mtab"))
}

func (m *mounter) Unmount() (err error) {
	m.log.Info("Unmounting.")
	dir := m.options.MountPoint
	// Try normal unmount
	switch runtime.GOOS {
	case "darwin":
		_, err = exec.Command("/sbin/umount", dir).Output()
	case "linux":
		fusermountOutput, fusermountErr := exec.Command("fusermount", "-u", dir).CombinedOutput()
		// Only clean up mountdir on a clean unmount.
		if fusermountErr == nil {
			m.log.Info("Successfully unmounted.")
			defer m.DeleteMountdirIfEmpty()
		}
		if fusermountErr != nil {
			// Ignore errors where the mount was never mounted in the first place
			if isFusermountMountNotFoundError(fusermountOutput, fusermountErr) {
				m.log.Info("Ignoring mount-not-found fusermount error")
			} else {
				returnErr := fmt.Errorf("fusermount unmount resulted in unknown error: output=%v; err=%s.", fusermountOutput, fusermountErr)
				m.log.Warning(returnErr.Error())
				err = returnErr
			}
		}
	default:
		err = fuse.Unmount(dir)
	}
	if err != nil && m.options.ForceMount {
		// Unmount failed, so let's try and force it.
		switch runtime.GOOS {
		case "darwin":
			_, err = exec.Command(
				"/usr/sbin/diskutil", "unmountDisk", "force", dir).Output()
		case "linux":
			// Lazy unmount; will unmount when KBFS is no longer in use.
			_, err = exec.Command("fusermount", "-u", "-z", dir).Output()
		default:
			err = errors.New("Forced unmount is not supported on this platform yet")
		}
	}
	if execErr, ok := err.(*exec.ExitError); ok && execErr.Stderr != nil {
		err = fmt.Errorf("%s (%s)", execErr, execErr.Stderr)
	}
	return
}

func (m *mounter) DeleteMountdirIfEmpty() (err error) {
	m.log.Info("Deleting mountdir.")
	// os.Remove refuses to delete non-empty directories.
	err = os.Remove(m.options.MountPoint)
	if err != nil {
		m.log.Errorf("Unable to delete mountdir: %s.", err)
	}
	return
}

// volumeName returns the first word of the directory (base) name
func volumeName(dir string) (string, error) {
	volName := path.Base(dir)
	if volName == "." || volName == "/" {
		err := fmt.Errorf("Bad volume name: %v", volName)
		return "", err
	}
	s := strings.Split(volName, " ")
	if len(s) == 0 {
		return "", fmt.Errorf("Bad volume name: %v", volName)
	}
	return s[0], nil
}
<commit_msg>style<commit_after>// Copyright 2016 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.
//
// +build !windows

package libfuse

import (
	"bytes"
	"errors"
	"fmt"
	"os"
	"os/exec"
	"path"
	"runtime"
	"strings"

	"bazil.org/fuse"
	"github.com/keybase/client/go/kbconst"
	"github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/logger"
	keybase1 "github.com/keybase/client/go/protocol/keybase1"
)

type mounter struct {
	options StartOptions
	c       *fuse.Conn
	log     logger.Logger
	runMode kbconst.RunMode
}

// fuseMount tries to mount the mountpoint.
// On a force mount then unmount, re-mount if unsuccessful
func (m *mounter) Mount() (err error) {
	defer func() {
		if err != nil {
			msg := fmt.Sprintf("KBFS failed to FUSE mount at %s: %s", m.options.MountPoint, err)
			fmt.Println(msg)
			m.log.Warning(msg)
		}
	}()

	m.c, err = fuseMountDir(m.options.MountPoint, m.options.PlatformParams)
	// Exit if we were successful or we are not a force mounting on error.
	// Otherwise, try unmounting and mounting again.
	if err == nil || !m.options.ForceMount {
		return err
	}

	// Mount failed, let's try to unmount and then try mounting again, even
	// if unmounting errors here.
	m.Unmount()

	// In case we are on darwin, ask the installer to reinstall the mount dir
	// and try again as the last resort. This specifically fixes a situation
	// where /keybase gets created and owned by root after Keybase app is
	// started, and `kbfs` later fails to mount because of a permission error.
	m.reinstallMountDirIfPossible()
	m.c, err = fuseMountDir(m.options.MountPoint, m.options.PlatformParams)

	return err
}

func fuseMountDir(dir string, platformParams PlatformParams) (*fuse.Conn, error) {
	// Create mountdir directory on Linux.
	switch libkb.RuntimeGroup() {
	case keybase1.RuntimeGroup_LINUXLIKE:
		// Inherit permissions from containing directory and umask.
		err := os.MkdirAll(dir, os.ModeDir|os.ModePerm)
		if err != nil {
			return nil, err
		}
	default:
	}

	fi, err := os.Stat(dir)
	if err != nil {
		return nil, err
	}
	if !fi.IsDir() {
		return nil, errors.New("mount point is not a directory")
	}
	options, err := getPlatformSpecificMountOptions(dir, platformParams)
	if err != nil {
		return nil, err
	}
	c, err := fuse.Mount(dir, options...)
	if err != nil {
		err = translatePlatformSpecificError(err, platformParams)
		return nil, err
	}
	return c, nil
}

func isFusermountMountNotFoundError(output []byte, err error) bool {
	if err == nil {
		return false
	}
	return bytes.Contains(output, []byte("not found in /etc/mtab"))
}

func (m *mounter) Unmount() (err error) {
	m.log.Info("Unmounting")
	dir := m.options.MountPoint
	// Try normal unmount
	switch runtime.GOOS {
	case "darwin":
		_, err = exec.Command("/sbin/umount", dir).Output()
	case "linux":
		fusermountOutput, fusermountErr := exec.Command("fusermount", "-u", dir).CombinedOutput()
		// Only clean up mountdir on a clean unmount.
		if fusermountErr == nil {
			m.log.Info("Successfully unmounted")
			defer m.DeleteMountdirIfEmpty()
		}
		if fusermountErr != nil {
			// Ignore errors where the mount was never mounted in the first place
			if isFusermountMountNotFoundError(fusermountOutput, fusermountErr) {
				m.log.Info("Ignoring mount-not-found fusermount error")
			} else {
				returnErr := fmt.Errorf("fusermount unmount resulted in unknown error: output=%v; err=%s", fusermountOutput, fusermountErr)
				m.log.Warning(returnErr.Error())
				err = returnErr
			}
		}
	default:
		err = fuse.Unmount(dir)
	}
	if err != nil && m.options.ForceMount {
		// Unmount failed, so let's try and force it.
		switch runtime.GOOS {
		case "darwin":
			_, err = exec.Command(
				"/usr/sbin/diskutil", "unmountDisk", "force", dir).Output()
		case "linux":
			// Lazy unmount; will unmount when KBFS is no longer in use.
			_, err = exec.Command("fusermount", "-u", "-z", dir).Output()
		default:
			err = errors.New("Forced unmount is not supported on this platform yet")
		}
	}
	if execErr, ok := err.(*exec.ExitError); ok && execErr.Stderr != nil {
		err = fmt.Errorf("%s (%s)", execErr, execErr.Stderr)
	}
	return
}

func (m *mounter) DeleteMountdirIfEmpty() (err error) {
	m.log.Info("Deleting mountdir")
	// os.Remove refuses to delete non-empty directories.
	err = os.Remove(m.options.MountPoint)
	if err != nil {
		m.log.Errorf("Unable to delete mountdir: %s", err)
	}
	return
}

// volumeName returns the first word of the directory (base) name
func volumeName(dir string) (string, error) {
	volName := path.Base(dir)
	if volName == "." || volName == "/" {
		err := fmt.Errorf("Bad volume name: %v", volName)
		return "", err
	}
	s := strings.Split(volName, " ")
	if len(s) == 0 {
		return "", fmt.Errorf("Bad volume name: %v", volName)
	}
	return s[0], nil
}
<|endoftext|>


<commit_before>package modules

import (
	"testing"

	"github.com/rivine/rivine/encoding"
	"github.com/rivine/rivine/types"
)

// TestConsensusConflict checks that the consensus conflict type is correctly
// assembling consensus conflict errors.
func TestConsensusConflict(t *testing.T) {
	t.Parallel()

	ncc := NewConsensusConflict("problem")
	if ncc.Error() != "consensus conflict: problem" {
		t.Error("wrong error message being reported in a consensus conflict")
	}

	err := func() error {
		return ncc
	}()
	if err.Error() != "consensus conflict: problem" {
		t.Error("wrong error message being reported in a consensus conflict")
	}
	if _, ok := err.(ConsensusConflict); !ok {
		t.Error("error is not maintaining consensus conflict type")
	}
}

// TestCalculateFee checks that the CalculateFee function is correctly tallying
// the number of fees in a transaction set.
func TestCalculateFee(t *testing.T) {
	t.Parallel()

	// Try calculating the fees on a nil transaction set.
	if CalculateFee(nil).Cmp(types.ZeroCurrency) != 0 {
		t.Error("CalculateFee is incorrectly handling nil input")
	}
	// Try a single transaction with no fees.
	txnSet := []types.Transaction{{}}
	if CalculateFee(txnSet).Cmp(types.ZeroCurrency) != 0 {
		t.Error("CalculateFee is not correctly calculating the fees on an empty transaction set")
	}
	// Try a non-empty transaction.
	txnSet = []types.Transaction{{
		SiacoinOutputs: []types.SiacoinOutput{{
			Value: types.NewCurrency64(253e9),
		}},
	}}
	if CalculateFee(txnSet).Cmp(types.ZeroCurrency) != 0 {
		t.Error("CalculateFee is not correctly calculating the fees on a non-empty transaction set")
	}

	// Try a transaction set with a single miner fee.
	baseFee := types.NewCurrency64(12e3)
	txnSet = []types.Transaction{{
		MinerFees: []types.Currency{
			baseFee,
		},
	}}
	setLen := uint64(len(encoding.Marshal(txnSet)))
	expectedFee := baseFee.Div64(setLen)
	if CalculateFee(txnSet).Cmp(expectedFee) != 0 {
		t.Error("CalculateFee doesn't seem to be calculating the correct transaction fee")
	}

	// Try a transaction set with multiple transactions and multiple fees per
	// transaction.
	fee1 := types.NewCurrency64(1e6)
	fee2 := types.NewCurrency64(2e6)
	fee3 := types.NewCurrency64(3e6)
	fee4 := types.NewCurrency64(4e6)
	txnSet = []types.Transaction{
		{
			MinerFees: []types.Currency{
				fee1,
				fee2,
			},
		},
		{
			MinerFees: []types.Currency{
				fee3,
				fee4,
			},
		},
	}
	currencyLen := types.NewCurrency64(uint64(len(encoding.Marshal(txnSet))))
	multiExpectedFee := fee1.Add(fee2).Add(fee3).Add(fee4).Div(currencyLen)
	if CalculateFee(txnSet).Cmp(multiExpectedFee) != 0 {
		t.Error("got the wrong fee for a multi transaction set")
	}
}
<commit_msg>Fix unit test compilation<commit_after>package modules

import (
	"testing"

	"github.com/rivine/rivine/encoding"
	"github.com/rivine/rivine/types"
)

// TestConsensusConflict checks that the consensus conflict type is correctly
// assembling consensus conflict errors.
func TestConsensusConflict(t *testing.T) {
	t.Parallel()

	ncc := NewConsensusConflict("problem")
	if ncc.Error() != "consensus conflict: problem" {
		t.Error("wrong error message being reported in a consensus conflict")
	}

	err := func() error {
		return ncc
	}()
	if err.Error() != "consensus conflict: problem" {
		t.Error("wrong error message being reported in a consensus conflict")
	}
	if _, ok := err.(ConsensusConflict); !ok {
		t.Error("error is not maintaining consensus conflict type")
	}
}

// TestCalculateFee checks that the CalculateFee function is correctly tallying
// the number of fees in a transaction set.
func TestCalculateFee(t *testing.T) {
	t.Parallel()

	// Try calculating the fees on a nil transaction set.
	if CalculateFee(nil).Cmp(types.ZeroCurrency) != 0 {
		t.Error("CalculateFee is incorrectly handling nil input")
	}
	// Try a single transaction with no fees.
	txnSet := []types.Transaction{{}}
	if CalculateFee(txnSet).Cmp(types.ZeroCurrency) != 0 {
		t.Error("CalculateFee is not correctly calculating the fees on an empty transaction set")
	}
	// Try a non-empty transaction.
	txnSet = []types.Transaction{{
		CoinOutputs: []types.CoinOutput{{
			Value: types.NewCurrency64(253e9),
		}},
	}}
	if CalculateFee(txnSet).Cmp(types.ZeroCurrency) != 0 {
		t.Error("CalculateFee is not correctly calculating the fees on a non-empty transaction set")
	}

	// Try a transaction set with a single miner fee.
	baseFee := types.NewCurrency64(12e3)
	txnSet = []types.Transaction{{
		MinerFees: []types.Currency{
			baseFee,
		},
	}}
	setLen := uint64(len(encoding.Marshal(txnSet)))
	expectedFee := baseFee.Div64(setLen)
	if CalculateFee(txnSet).Cmp(expectedFee) != 0 {
		t.Error("CalculateFee doesn't seem to be calculating the correct transaction fee")
	}

	// Try a transaction set with multiple transactions and multiple fees per
	// transaction.
	fee1 := types.NewCurrency64(1e6)
	fee2 := types.NewCurrency64(2e6)
	fee3 := types.NewCurrency64(3e6)
	fee4 := types.NewCurrency64(4e6)
	txnSet = []types.Transaction{
		{
			MinerFees: []types.Currency{
				fee1,
				fee2,
			},
		},
		{
			MinerFees: []types.Currency{
				fee3,
				fee4,
			},
		},
	}
	currencyLen := types.NewCurrency64(uint64(len(encoding.Marshal(txnSet))))
	multiExpectedFee := fee1.Add(fee2).Add(fee3).Add(fee4).Div(currencyLen)
	if CalculateFee(txnSet).Cmp(multiExpectedFee) != 0 {
		t.Error("got the wrong fee for a multi transaction set")
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2015 The Kubernetes Authors.

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

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

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

package storage

import (
	"context"
	"net"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apiserver/pkg/registry/generic"
	genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
	"k8s.io/apiserver/pkg/registry/rest"
	utilfeature "k8s.io/apiserver/pkg/util/feature"
	api "k8s.io/kubernetes/pkg/apis/core"
	"k8s.io/kubernetes/pkg/features"
	"k8s.io/kubernetes/pkg/printers"
	printersinternal "k8s.io/kubernetes/pkg/printers/internalversion"
	printerstorage "k8s.io/kubernetes/pkg/printers/storage"
	"k8s.io/kubernetes/pkg/registry/core/service"
	registry "k8s.io/kubernetes/pkg/registry/core/service"
	svcreg "k8s.io/kubernetes/pkg/registry/core/service"
	"sigs.k8s.io/structured-merge-diff/v4/fieldpath"

	netutil "k8s.io/utils/net"
)

type GenericREST struct {
	*genericregistry.Store
	primaryIPFamily *api.IPFamily
	secondaryFamily *api.IPFamily
}

// NewREST returns a RESTStorage object that will work against services.
func NewGenericREST(optsGetter generic.RESTOptionsGetter, serviceCIDR net.IPNet, hasSecondary bool) (*GenericREST, *StatusREST, error) {
	strategy, _ := registry.StrategyForServiceCIDRs(serviceCIDR, hasSecondary)

	store := &genericregistry.Store{
		NewFunc:                  func() runtime.Object { return &api.Service{} },
		NewListFunc:              func() runtime.Object { return &api.ServiceList{} },
		DefaultQualifiedResource: api.Resource("services"),
		ReturnDeletedObject:      true,

		CreateStrategy:      strategy,
		UpdateStrategy:      strategy,
		DeleteStrategy:      strategy,
		ResetFieldsStrategy: strategy,

		TableConvertor: printerstorage.TableConvertor{TableGenerator: printers.NewTableGenerator().With(printersinternal.AddHandlers)},
	}
	options := &generic.StoreOptions{RESTOptions: optsGetter}
	if err := store.CompleteWithOptions(options); err != nil {
		return nil, nil, err
	}

	statusStore := *store
	statusStrategy := service.NewServiceStatusStrategy(strategy)
	statusStore.UpdateStrategy = statusStrategy
	statusStore.ResetFieldsStrategy = statusStrategy

	ipv4 := api.IPv4Protocol
	ipv6 := api.IPv6Protocol
	var primaryIPFamily *api.IPFamily
	var secondaryFamily *api.IPFamily
	if netutil.IsIPv6CIDR(&serviceCIDR) {
		primaryIPFamily = &ipv6
		if hasSecondary {
			secondaryFamily = &ipv4
		}
	} else {
		primaryIPFamily = &ipv4
		if hasSecondary {
			secondaryFamily = &ipv6
		}
	}
	genericStore := &GenericREST{store, primaryIPFamily, secondaryFamily}
	store.Decorator = genericStore.defaultOnRead

	return genericStore, &StatusREST{store: &statusStore}, nil
}

var (
	_ rest.ShortNamesProvider = &GenericREST{}
	_ rest.CategoriesProvider = &GenericREST{}
)

// ShortNames implements the ShortNamesProvider interface. Returns a list of short names for a resource.
func (r *GenericREST) ShortNames() []string {
	return []string{"svc"}
}

// Categories implements the CategoriesProvider interface. Returns a list of categories a resource is part of.
func (r *GenericREST) Categories() []string {
	return []string{"all"}
}

// StatusREST implements the GenericREST endpoint for changing the status of a service.
type StatusREST struct {
	store *genericregistry.Store
}

func (r *StatusREST) New() runtime.Object {
	return &api.Service{}
}

// Get retrieves the object from the storage. It is required to support Patch.
func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
	return r.store.Get(ctx, name, options)
}

// Update alters the status subset of an object.
func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) {
	// We are explicitly setting forceAllowCreate to false in the call to the underlying storage because
	// subresources should never allow create on update.
	return r.store.Update(ctx, name, objInfo, createValidation, updateValidation, false, options)
}

// GetResetFields implements rest.ResetFieldsStrategy
func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
	return r.store.GetResetFields()
}

// defaultOnRead sets interlinked fields that were not previously set on read.
// We can't do this in the normal defaulting path because that same logic
// applies on Get, Create, and Update, but we need to distinguish between them.
//
// This will be called on both Service and ServiceList types.
func (r *GenericREST) defaultOnRead(obj runtime.Object) {
	switch s := obj.(type) {
	case *api.Service:
		r.defaultOnReadService(s)
	case *api.ServiceList:
		r.defaultOnReadServiceList(s)
	default:
		// This was not an object we can default.  This is not an error, as the
		// caching layer can pass through here, too.
	}
}

// defaultOnReadServiceList defaults a ServiceList.
func (r *GenericREST) defaultOnReadServiceList(serviceList *api.ServiceList) {
	if serviceList == nil {
		return
	}

	for i := range serviceList.Items {
		r.defaultOnReadService(&serviceList.Items[i])
	}
}

// defaultOnReadService defaults a single Service.
func (r *GenericREST) defaultOnReadService(service *api.Service) {
	if service == nil {
		return
	}

	// We might find Services that were written before ClusterIP became plural.
	// We still want to present a consistent view of them.
	// NOTE: the args are (old, new)
	svcreg.NormalizeClusterIPs(nil, service)

	// The rest of this does not apply unless dual-stack is enabled.
	if !utilfeature.DefaultFeatureGate.Enabled(features.IPv6DualStack) {
		return
	}

	if len(service.Spec.IPFamilies) > 0 {
		return // already defaulted
	}

	// set clusterIPs based on ClusterIP
	if len(service.Spec.ClusterIPs) == 0 {
		if len(service.Spec.ClusterIP) > 0 {
			service.Spec.ClusterIPs = []string{service.Spec.ClusterIP}
		}
	}

	requireDualStack := api.IPFamilyPolicyRequireDualStack
	singleStack := api.IPFamilyPolicySingleStack
	preferDualStack := api.IPFamilyPolicyPreferDualStack
	// headless services
	if len(service.Spec.ClusterIPs) == 1 && service.Spec.ClusterIPs[0] == api.ClusterIPNone {
		service.Spec.IPFamilies = []api.IPFamily{*r.primaryIPFamily}

		// headless+selectorless
		// headless+selectorless takes both families. Why?
		// at this stage we don't know what kind of endpoints (specifically their IPFamilies) the
		// user has assigned to this selectorless service. We assume it has dualstack and we default
		// it to PreferDualStack on any cluster (single or dualstack configured).
		if len(service.Spec.Selector) == 0 {
			service.Spec.IPFamilyPolicy = &preferDualStack
			if *r.primaryIPFamily == api.IPv4Protocol {
				service.Spec.IPFamilies = append(service.Spec.IPFamilies, api.IPv6Protocol)
			} else {
				service.Spec.IPFamilies = append(service.Spec.IPFamilies, api.IPv4Protocol)
			}
		} else {
			// headless w/ selector
			// this service type follows cluster configuration. this service (selector based) uses a
			// selector and will have to follow how the cluster is configured. If the cluster is
			// configured to dual stack then the service defaults to PreferDualStack. Otherwise we
			// default it to SingleStack.
			if r.secondaryFamily != nil {
				service.Spec.IPFamilies = append(service.Spec.IPFamilies, *r.secondaryFamily)
				service.Spec.IPFamilyPolicy = &preferDualStack
			} else {
				service.Spec.IPFamilyPolicy = &singleStack
			}
		}
	} else {
		// headful
		// make sure a slice exists to receive the families
		service.Spec.IPFamilies = make([]api.IPFamily, len(service.Spec.ClusterIPs), len(service.Spec.ClusterIPs))
		for idx, ip := range service.Spec.ClusterIPs {
			if netutil.IsIPv6String(ip) {
				service.Spec.IPFamilies[idx] = api.IPv6Protocol
			} else {
				service.Spec.IPFamilies[idx] = api.IPv4Protocol
			}

			if len(service.Spec.IPFamilies) == 1 {
				service.Spec.IPFamilyPolicy = &singleStack
			} else if len(service.Spec.IPFamilies) == 2 {
				service.Spec.IPFamilyPolicy = &requireDualStack
			}
		}
	}
}
<commit_msg>Fix doc comment<commit_after>/*
Copyright 2015 The Kubernetes Authors.

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

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

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

package storage

import (
	"context"
	"net"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apiserver/pkg/registry/generic"
	genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
	"k8s.io/apiserver/pkg/registry/rest"
	utilfeature "k8s.io/apiserver/pkg/util/feature"
	api "k8s.io/kubernetes/pkg/apis/core"
	"k8s.io/kubernetes/pkg/features"
	"k8s.io/kubernetes/pkg/printers"
	printersinternal "k8s.io/kubernetes/pkg/printers/internalversion"
	printerstorage "k8s.io/kubernetes/pkg/printers/storage"
	"k8s.io/kubernetes/pkg/registry/core/service"
	registry "k8s.io/kubernetes/pkg/registry/core/service"
	svcreg "k8s.io/kubernetes/pkg/registry/core/service"
	"sigs.k8s.io/structured-merge-diff/v4/fieldpath"

	netutil "k8s.io/utils/net"
)

type GenericREST struct {
	*genericregistry.Store
	primaryIPFamily *api.IPFamily
	secondaryFamily *api.IPFamily
}

// NewGenericREST returns a RESTStorage object that will work against services.
func NewGenericREST(optsGetter generic.RESTOptionsGetter, serviceCIDR net.IPNet, hasSecondary bool) (*GenericREST, *StatusREST, error) {
	strategy, _ := registry.StrategyForServiceCIDRs(serviceCIDR, hasSecondary)

	store := &genericregistry.Store{
		NewFunc:                  func() runtime.Object { return &api.Service{} },
		NewListFunc:              func() runtime.Object { return &api.ServiceList{} },
		DefaultQualifiedResource: api.Resource("services"),
		ReturnDeletedObject:      true,

		CreateStrategy:      strategy,
		UpdateStrategy:      strategy,
		DeleteStrategy:      strategy,
		ResetFieldsStrategy: strategy,

		TableConvertor: printerstorage.TableConvertor{TableGenerator: printers.NewTableGenerator().With(printersinternal.AddHandlers)},
	}
	options := &generic.StoreOptions{RESTOptions: optsGetter}
	if err := store.CompleteWithOptions(options); err != nil {
		return nil, nil, err
	}

	statusStore := *store
	statusStrategy := service.NewServiceStatusStrategy(strategy)
	statusStore.UpdateStrategy = statusStrategy
	statusStore.ResetFieldsStrategy = statusStrategy

	ipv4 := api.IPv4Protocol
	ipv6 := api.IPv6Protocol
	var primaryIPFamily *api.IPFamily
	var secondaryFamily *api.IPFamily
	if netutil.IsIPv6CIDR(&serviceCIDR) {
		primaryIPFamily = &ipv6
		if hasSecondary {
			secondaryFamily = &ipv4
		}
	} else {
		primaryIPFamily = &ipv4
		if hasSecondary {
			secondaryFamily = &ipv6
		}
	}
	genericStore := &GenericREST{store, primaryIPFamily, secondaryFamily}
	store.Decorator = genericStore.defaultOnRead

	return genericStore, &StatusREST{store: &statusStore}, nil
}

var (
	_ rest.ShortNamesProvider = &GenericREST{}
	_ rest.CategoriesProvider = &GenericREST{}
)

// ShortNames implements the ShortNamesProvider interface. Returns a list of short names for a resource.
func (r *GenericREST) ShortNames() []string {
	return []string{"svc"}
}

// Categories implements the CategoriesProvider interface. Returns a list of categories a resource is part of.
func (r *GenericREST) Categories() []string {
	return []string{"all"}
}

// StatusREST implements the GenericREST endpoint for changing the status of a service.
type StatusREST struct {
	store *genericregistry.Store
}

func (r *StatusREST) New() runtime.Object {
	return &api.Service{}
}

// Get retrieves the object from the storage. It is required to support Patch.
func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
	return r.store.Get(ctx, name, options)
}

// Update alters the status subset of an object.
func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) {
	// We are explicitly setting forceAllowCreate to false in the call to the underlying storage because
	// subresources should never allow create on update.
	return r.store.Update(ctx, name, objInfo, createValidation, updateValidation, false, options)
}

// GetResetFields implements rest.ResetFieldsStrategy
func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
	return r.store.GetResetFields()
}

// defaultOnRead sets interlinked fields that were not previously set on read.
// We can't do this in the normal defaulting path because that same logic
// applies on Get, Create, and Update, but we need to distinguish between them.
//
// This will be called on both Service and ServiceList types.
func (r *GenericREST) defaultOnRead(obj runtime.Object) {
	switch s := obj.(type) {
	case *api.Service:
		r.defaultOnReadService(s)
	case *api.ServiceList:
		r.defaultOnReadServiceList(s)
	default:
		// This was not an object we can default.  This is not an error, as the
		// caching layer can pass through here, too.
	}
}

// defaultOnReadServiceList defaults a ServiceList.
func (r *GenericREST) defaultOnReadServiceList(serviceList *api.ServiceList) {
	if serviceList == nil {
		return
	}

	for i := range serviceList.Items {
		r.defaultOnReadService(&serviceList.Items[i])
	}
}

// defaultOnReadService defaults a single Service.
func (r *GenericREST) defaultOnReadService(service *api.Service) {
	if service == nil {
		return
	}

	// We might find Services that were written before ClusterIP became plural.
	// We still want to present a consistent view of them.
	// NOTE: the args are (old, new)
	svcreg.NormalizeClusterIPs(nil, service)

	// The rest of this does not apply unless dual-stack is enabled.
	if !utilfeature.DefaultFeatureGate.Enabled(features.IPv6DualStack) {
		return
	}

	if len(service.Spec.IPFamilies) > 0 {
		return // already defaulted
	}

	// set clusterIPs based on ClusterIP
	if len(service.Spec.ClusterIPs) == 0 {
		if len(service.Spec.ClusterIP) > 0 {
			service.Spec.ClusterIPs = []string{service.Spec.ClusterIP}
		}
	}

	requireDualStack := api.IPFamilyPolicyRequireDualStack
	singleStack := api.IPFamilyPolicySingleStack
	preferDualStack := api.IPFamilyPolicyPreferDualStack
	// headless services
	if len(service.Spec.ClusterIPs) == 1 && service.Spec.ClusterIPs[0] == api.ClusterIPNone {
		service.Spec.IPFamilies = []api.IPFamily{*r.primaryIPFamily}

		// headless+selectorless
		// headless+selectorless takes both families. Why?
		// at this stage we don't know what kind of endpoints (specifically their IPFamilies) the
		// user has assigned to this selectorless service. We assume it has dualstack and we default
		// it to PreferDualStack on any cluster (single or dualstack configured).
		if len(service.Spec.Selector) == 0 {
			service.Spec.IPFamilyPolicy = &preferDualStack
			if *r.primaryIPFamily == api.IPv4Protocol {
				service.Spec.IPFamilies = append(service.Spec.IPFamilies, api.IPv6Protocol)
			} else {
				service.Spec.IPFamilies = append(service.Spec.IPFamilies, api.IPv4Protocol)
			}
		} else {
			// headless w/ selector
			// this service type follows cluster configuration. this service (selector based) uses a
			// selector and will have to follow how the cluster is configured. If the cluster is
			// configured to dual stack then the service defaults to PreferDualStack. Otherwise we
			// default it to SingleStack.
			if r.secondaryFamily != nil {
				service.Spec.IPFamilies = append(service.Spec.IPFamilies, *r.secondaryFamily)
				service.Spec.IPFamilyPolicy = &preferDualStack
			} else {
				service.Spec.IPFamilyPolicy = &singleStack
			}
		}
	} else {
		// headful
		// make sure a slice exists to receive the families
		service.Spec.IPFamilies = make([]api.IPFamily, len(service.Spec.ClusterIPs), len(service.Spec.ClusterIPs))
		for idx, ip := range service.Spec.ClusterIPs {
			if netutil.IsIPv6String(ip) {
				service.Spec.IPFamilies[idx] = api.IPv6Protocol
			} else {
				service.Spec.IPFamilies[idx] = api.IPv4Protocol
			}

			if len(service.Spec.IPFamilies) == 1 {
				service.Spec.IPFamilyPolicy = &singleStack
			} else if len(service.Spec.IPFamilies) == 2 {
				service.Spec.IPFamilyPolicy = &requireDualStack
			}
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2013, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package worker

import (
	"flag"
	"fmt"
	"math/rand"
	"time"

	"github.com/youtube/vitess/go/vt/servenv"
	"github.com/youtube/vitess/go/vt/topo"
	"github.com/youtube/vitess/go/vt/wrangler"
	"golang.org/x/net/context"
)

var (
	minHealthyEndPoints = flag.Int("min_healthy_rdonly_endpoints", 2, "minimum number of healthy rdonly endpoints required for checker")
)

// FindHealthyRdonlyEndPoint returns a random healthy endpoint.
// Since we don't want to use them all, we require at least
// minHealthyEndPoints servers to be healthy.
func FindHealthyRdonlyEndPoint(ctx context.Context, wr *wrangler.Wrangler, cell, keyspace, shard string) (topo.TabletAlias, error) {
	endPoints, _, err := wr.TopoServer().GetEndPoints(ctx, cell, keyspace, shard, topo.TYPE_RDONLY)
	if err != nil {
		return topo.TabletAlias{}, fmt.Errorf("GetEndPoints(%v,%v,%v,rdonly) failed: %v", cell, keyspace, shard, err)
	}
	healthyEndpoints := make([]topo.EndPoint, 0, len(endPoints.Entries))
	for _, entry := range endPoints.Entries {
		if len(entry.Health) == 0 {
			healthyEndpoints = append(healthyEndpoints, entry)
		}
	}
	if len(healthyEndpoints) < *minHealthyEndPoints {
		return topo.TabletAlias{}, fmt.Errorf("Not enough endpoints to chose from in (%v,%v/%v), have %v healthy ones, need at least %v", cell, keyspace, shard, len(healthyEndpoints), *minHealthyEndPoints)
	}

	// random server in the list is what we want
	index := rand.Intn(len(healthyEndpoints))
	return topo.TabletAlias{
		Cell: cell,
		Uid:  healthyEndpoints[index].Uid,
	}, nil
}

// FindWorkerTablet will:
// - find a rdonly instance in the keyspace / shard
// - mark it as worker
// - tag it with our worker process
func FindWorkerTablet(ctx context.Context, wr *wrangler.Wrangler, cleaner *wrangler.Cleaner, cell, keyspace, shard string) (topo.TabletAlias, error) {
	tabletAlias, err := FindHealthyRdonlyEndPoint(ctx, wr, cell, keyspace, shard)
	if err != nil {
		return topo.TabletAlias{}, err
	}

	// We add the tag before calling ChangeSlaveType, so the destination
	// vttablet reloads the worker URL when it reloads the tablet.
	ourURL := servenv.ListeningURL.String()
	wr.Logger().Infof("Adding tag[worker]=%v to tablet %v", ourURL, tabletAlias)
	if err := wr.TopoServer().UpdateTabletFields(ctx, tabletAlias, func(tablet *topo.Tablet) error {
		if tablet.Tags == nil {
			tablet.Tags = make(map[string]string)
		}
		tablet.Tags["worker"] = ourURL
		return nil
	}); err != nil {
		return topo.TabletAlias{}, err
	}
	// we remove the tag *before* calling ChangeSlaveType back, so
	// we need to record this tag change after the change slave
	// type change in the cleaner.
	defer wrangler.RecordTabletTagAction(cleaner, tabletAlias, "worker", "")

	wr.Logger().Infof("Changing tablet %v to 'checker'", tabletAlias)
	shortCtx, cancel := context.WithTimeout(ctx, *remoteActionsTimeout)
	err = wr.ChangeType(shortCtx, tabletAlias, topo.TYPE_WORKER, false /*force*/)
	cancel()
	if err != nil {
		return topo.TabletAlias{}, err
	}

	// Record a clean-up action to take the tablet back to rdonly.
	// We will alter this one later on and let the tablet go back to
	// 'spare' if we have stopped replication for too long on it.
	wrangler.RecordChangeSlaveTypeAction(cleaner, tabletAlias, topo.TYPE_RDONLY)
	return tabletAlias, nil
}

func init() {
	rand.Seed(time.Now().UnixNano())
}
<commit_msg>vtworker: Wait for enough rdonly tablets to become available.<commit_after>// Copyright 2013, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package worker

import (
	"flag"
	"fmt"
	"math/rand"
	"time"

	"github.com/youtube/vitess/go/vt/servenv"
	"github.com/youtube/vitess/go/vt/topo"
	"github.com/youtube/vitess/go/vt/wrangler"
	"golang.org/x/net/context"
)

var (
	minHealthyEndPoints = flag.Int("min_healthy_rdonly_endpoints", 2, "minimum number of healthy rdonly endpoints required for checker")
	// The intent of this timeout is to wait for the healthcheck to automatically return rdonly instances which have been taken out by previous *Clone or *Diff runs.
	// Therefore, the default for this variable must be higher than -health_check_interval.
	waitForHealthyEndPointsTimeout = flag.Duration("wait_for_healthy_rdonly_endpoints_timeout", 60*time.Second, "maximum time to wait if less than --min_healthy_rdonly_endpoints are available")
)

// FindHealthyRdonlyEndPoint returns a random healthy endpoint.
// Since we don't want to use them all, we require at least
// minHealthyEndPoints servers to be healthy.
// May block up to -wait_for_healthy_rdonly_endpoints_timeout.
func FindHealthyRdonlyEndPoint(ctx context.Context, wr *wrangler.Wrangler, cell, keyspace, shard string) (topo.TabletAlias, error) {
	waitDeadline := time.Now().Add(*waitForHealthyEndPointsTimeout)
	var healthyEndpoints []topo.EndPoint
	for {
		endPoints, _, err := wr.TopoServer().GetEndPoints(ctx, cell, keyspace, shard, topo.TYPE_RDONLY)
		if err != nil {
			if err == topo.ErrNoNode {
				// If the node doesn't exist, count that as 0 available rdonly instances.
				endPoints = &topo.EndPoints{}
			} else {
				return topo.TabletAlias{}, fmt.Errorf("GetEndPoints(%v,%v,%v,rdonly) failed: %v", cell, keyspace, shard, err)
			}
		}
		healthyEndpoints = make([]topo.EndPoint, 0, len(endPoints.Entries))
		for _, entry := range endPoints.Entries {
			if len(entry.Health) == 0 {
				healthyEndpoints = append(healthyEndpoints, entry)
			}
		}
		if len(healthyEndpoints) < *minHealthyEndPoints {
			if time.Now().After(waitDeadline) {
				return topo.TabletAlias{}, fmt.Errorf("Not enough endpoints to chose from in (%v,%v/%v), have %v healthy ones, need at least %v", cell, keyspace, shard, len(healthyEndpoints), *minHealthyEndPoints)
			}
			wr.Logger().Infof("Waiting for enough endpoints to become available. available: %v required: %v Waiting up to %.1f more seconds.", len(healthyEndpoints), *minHealthyEndPoints, waitDeadline.Sub(time.Now()).Seconds())
			// Block for 1 second because 2 seconds is the -health_check_interval in integration tests.
			time.Sleep(1 * time.Second)
			continue
		}
		break
	}

	// random server in the list is what we want
	index := rand.Intn(len(healthyEndpoints))
	return topo.TabletAlias{
		Cell: cell,
		Uid:  healthyEndpoints[index].Uid,
	}, nil
}

// FindWorkerTablet will:
// - find a rdonly instance in the keyspace / shard
// - mark it as worker
// - tag it with our worker process
func FindWorkerTablet(ctx context.Context, wr *wrangler.Wrangler, cleaner *wrangler.Cleaner, cell, keyspace, shard string) (topo.TabletAlias, error) {
	tabletAlias, err := FindHealthyRdonlyEndPoint(ctx, wr, cell, keyspace, shard)
	if err != nil {
		return topo.TabletAlias{}, err
	}

	// We add the tag before calling ChangeSlaveType, so the destination
	// vttablet reloads the worker URL when it reloads the tablet.
	ourURL := servenv.ListeningURL.String()
	wr.Logger().Infof("Adding tag[worker]=%v to tablet %v", ourURL, tabletAlias)
	if err := wr.TopoServer().UpdateTabletFields(ctx, tabletAlias, func(tablet *topo.Tablet) error {
		if tablet.Tags == nil {
			tablet.Tags = make(map[string]string)
		}
		tablet.Tags["worker"] = ourURL
		return nil
	}); err != nil {
		return topo.TabletAlias{}, err
	}
	// we remove the tag *before* calling ChangeSlaveType back, so
	// we need to record this tag change after the change slave
	// type change in the cleaner.
	defer wrangler.RecordTabletTagAction(cleaner, tabletAlias, "worker", "")

	wr.Logger().Infof("Changing tablet %v to 'checker'", tabletAlias)
	shortCtx, cancel := context.WithTimeout(ctx, *remoteActionsTimeout)
	err = wr.ChangeType(shortCtx, tabletAlias, topo.TYPE_WORKER, false /*force*/)
	cancel()
	if err != nil {
		return topo.TabletAlias{}, err
	}

	// Record a clean-up action to take the tablet back to rdonly.
	// We will alter this one later on and let the tablet go back to
	// 'spare' if we have stopped replication for too long on it.
	wrangler.RecordChangeSlaveTypeAction(cleaner, tabletAlias, topo.TYPE_RDONLY)
	return tabletAlias, nil
}

func init() {
	rand.Seed(time.Now().UnixNano())
}
<|endoftext|>


<commit_before>
package main

import (
  "flag"
  "bufio"
  "io"
  "os"
  "os/exec"
  "path/filepath"
  "fmt"
  "strconv"
  "strings"
  "time"
)

var resource = "-l fat,gpu=gtx680"

func GetFiles(inputdir string) []string {
  files, _ := filepath.Glob(inputdir + "/*.gexf")
  return files
}

func GetOutName (outdir, file string, iterations int) string {
  outname := strings.TrimSuffix(file, filepath.Ext(file))
  absout, _ := filepath.Abs(outdir)
  return filepath.Join(absout, outname) + "-" + strconv.Itoa(iterations)
}

func ReserveNode() int {
  //"-native", resource,
  command := exec.Command("preserve","-native", resource,
  "-t", "30:00", "-#", "1")
  fmt.Println(command.Args)
  cmdout, _ := command.Output()

  fmt.Println("Reserve output:", string(cmdout[:]))
  time.Sleep(2 * time.Second)

  getId := exec.Command("preserve", "-list")
  out, _ := getId.Output()
  outputString := string(out[:])
  fmt.Println(outputString)
  lines := strings.Split(outputString, "\n")
  for _, line := range lines {
    if strings.Contains(line, "jdonkerv") {
      res, _ := strconv.Atoi(strings.Fields(line)[0])
      return res
    }
  }
  return -1
}

func CleanNode(nodeid int) {
  command := exec.Command("preserve", "-c", strconv.Itoa(nodeid))
  command.Run()
}

func main () {
  inputDirPtr := flag.String("indir", "", "The directory with the gexf files to run")
  outputDirPtr := flag.String("outdir", "", "The directory where the run time files will be placed.")

  flag.Parse()

  files := GetFiles(*inputDirPtr)

  for _, fin := range files {
    iterations := 10
    outfilename := GetOutName(*outputDirPtr, filepath.Base(fin), iterations)
    fmt.Println(outfilename)

    nodeid := ReserveNode()

    fmt.Println("Using node ", nodeid)
    command := exec.Command("prun", "-no-panda", "-reserve", strconv.Itoa(nodeid),
    "-native", resource, "./ap", "1", "-i", fin,
    "-n", strconv.Itoa(iterations))

    grep := exec.Command("grep", "time", "-A", "1")
    commandOut, _ := command.StdoutPipe()
    grep.Stdin = commandOut

    outfile, _ := os.Create(outfilename)
    defer outfile.Close()

    writer := bufio.NewWriter(outfile)
    defer writer.Flush()

    grepOut, _ := grep.StdoutPipe()
    grep.Start()
    command.Start()
    io.Copy(writer, grepOut)
    grep.Wait()
    command.Wait()

    CleanNode(nodeid)
  }
}
<commit_msg>Updated run script.<commit_after>
package main

import (
  "flag"
  "bufio"
  "io"
  "os"
  "os/exec"
  "path/filepath"
  "fmt"
  "strconv"
  "strings"
  "time"
)

var resource = "-l gpu=GTX680"

func GetFiles(inputdir string) []string {
  files, _ := filepath.Glob(inputdir + "/*.gexf")
  return files
}

func GetOutName (outdir, file string, iterations int) string {
  outname := strings.TrimSuffix(file, filepath.Ext(file))
  absout, _ := filepath.Abs(outdir)
  return filepath.Join(absout, outname) + "-" + strconv.Itoa(iterations)
}

func ReserveNode() int {
  //"-native", resource,
  command := exec.Command("preserve","-native", resource,
  "-t", "02:00:00", "-#", "1")
  fmt.Println(command.Args)
  cmdout, _ := command.Output()

  fmt.Println("Reserve output:", string(cmdout[:]))
  time.Sleep(5 * time.Second)

  getId := exec.Command("preserve", "-list")
  out, _ := getId.Output()
  outputString := string(out[:])
  fmt.Println(outputString)
  lines := strings.Split(outputString, "\n")
  for _, line := range lines {
    if strings.Contains(line, "jdonkerv") {
      res, _ := strconv.Atoi(strings.Fields(line)[0])
      return res
    }
  }
  return -1
}

func CleanNode(nodeid int) {
  command := exec.Command("preserve", "-c", strconv.Itoa(nodeid))
  command.Run()
}

func main () {
  inputDirPtr := flag.String("indir", "", "The directory with the gexf files to run")
  outputDirPtr := flag.String("outdir", "", "The directory where the run time files will be placed.")

  flag.Parse()

  files := GetFiles(*inputDirPtr)

  for _, fin := range files {
    iterations := 100
    outfilename := GetOutName(*outputDirPtr, filepath.Base(fin), iterations)
    fmt.Println(outfilename)

    nodeid := ReserveNode()

    fmt.Println("Using node ", nodeid)
    command := exec.Command("prun", "-no-panda", "-reserve", strconv.Itoa(nodeid),
    "-native", resource, "./ap", "1", "-i", fin,
    "-n", strconv.Itoa(iterations))

    grep := exec.Command("grep", "time", "-A", "1")
    commandOut, _ := command.StdoutPipe()
    grep.Stdin = commandOut

    outfile, _ := os.Create(outfilename)
    defer outfile.Close()

    writer := bufio.NewWriter(outfile)
    defer writer.Flush()

    grepOut, _ := grep.StdoutPipe()
    grep.Start()
    command.Start()
    io.Copy(writer, grepOut)
    grep.Wait()
    command.Wait()

    CleanNode(nodeid)
  }
}
<|endoftext|>


<commit_before>// Copyright 2012 Gary Burd
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.

// Command server is a test server for the Autobahn WebSockets Test Suite.
package main

import (
	"errors"
	"flag"
	"github.com/gorilla/websocket"
	"io"
	"log"
	"net/http"
	"time"
	"unicode/utf8"
)

var upgrader = websocket.Upgrader{
	ReadBufferSize:  4096,
	WriteBufferSize: 4096,
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
}

// echoCopy echoes messages from the client using io.Copy.
func echoCopy(w http.ResponseWriter, r *http.Request, writerOnly bool) {
	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Println("Upgrade:", err)
		http.Error(w, "Bad request", 400)
		return
	}
	defer conn.Close()
	for {
		mt, r, err := conn.NextReader()
		if err != nil {
			if err != io.EOF {
				log.Println("NextReader:", err)
			}
			return
		}
		if mt == websocket.TextMessage {
			r = &validator{r: r}
		}
		w, err := conn.NextWriter(mt)
		if err != nil {
			log.Println("NextWriter:", err)
			return
		}
		if mt == websocket.TextMessage {
			r = &validator{r: r}
		}
		if writerOnly {
			_, err = io.Copy(struct{ io.Writer }{w}, r)
		} else {
			_, err = io.Copy(w, r)
		}
		if err != nil {
			if err == errInvalidUTF8 {
				conn.WriteControl(websocket.CloseMessage,
					websocket.FormatCloseMessage(websocket.CloseInvalidFramePayloadData, ""),
					time.Time{})
			}
			log.Println("Copy:", err)
			return
		}
		err = w.Close()
		if err != nil {
			log.Println("Close:", err)
			return
		}
	}
}

func echoCopyWriterOnly(w http.ResponseWriter, r *http.Request) {
	echoCopy(w, r, true)
}

func echoCopyFull(w http.ResponseWriter, r *http.Request) {
	echoCopy(w, r, false)
}

// echoReadAll echoes messages from the client by reading the entire message
// with ioutil.ReadAll.
func echoReadAll(w http.ResponseWriter, r *http.Request, writeMessage bool) {
	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Println("Upgrade:", err)
		return
	}
	defer conn.Close()
	for {
		mt, b, err := conn.ReadMessage()
		if err != nil {
			if err != io.EOF {
				log.Println("NextReader:", err)
			}
			return
		}
		if mt == websocket.TextMessage {
			if !utf8.Valid(b) {
				conn.WriteControl(websocket.CloseMessage,
					websocket.FormatCloseMessage(websocket.CloseInvalidFramePayloadData, ""),
					time.Time{})
				log.Println("ReadAll: invalid utf8")
			}
		}
		if writeMessage {
			err = conn.WriteMessage(mt, b)
			if err != nil {
				log.Println("WriteMessage:", err)
			}
		} else {
			w, err := conn.NextWriter(mt)
			if err != nil {
				log.Println("NextWriter:", err)
				return
			}
			if _, err := w.Write(b); err != nil {
				log.Println("Writer:", err)
				return
			}
			if err := w.Close(); err != nil {
				log.Println("Close:", err)
				return
			}
		}
	}
}

func echoReadAllWriter(w http.ResponseWriter, r *http.Request) {
	echoReadAll(w, r, false)
}

func echoReadAllWriteMessage(w http.ResponseWriter, r *http.Request) {
	echoReadAll(w, r, true)
}

func serveHome(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" {
		http.Error(w, "Not found.", 404)
		return
	}
	if r.Method != "GET" {
		http.Error(w, "Method not allowed", 405)
		return
	}
	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	io.WriteString(w, "Echo Server</html")
}

var addr = flag.String("addr", ":9000", "http service address")

func main() {
	flag.Parse()
	http.HandleFunc("/", serveHome)
	http.HandleFunc("/c", echoCopyWriterOnly)
	http.HandleFunc("/f", echoCopyFull)
	http.HandleFunc("/r", echoReadAllWriter)
	http.HandleFunc("/m", echoReadAllWriteMessage)
	err := http.ListenAndServe(*addr, nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}

type validator struct {
	state int
	x     rune
	r     io.Reader
}

var errInvalidUTF8 = errors.New("invalid utf8")

func (r *validator) Read(p []byte) (int, error) {
	n, err := r.r.Read(p)
	state := r.state
	x := r.x
	for _, b := range p[:n] {
		state, x = decode(state, x, b)
		if state == utf8Reject {
			break
		}
	}
	r.state = state
	r.x = x
	if state == utf8Reject || (err == io.EOF && state != utf8Accept) {
		return n, errInvalidUTF8
	}
	return n, err
}

// UTF-8 decoder from http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
//
// Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
var utf8d = [...]byte{
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1f
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3f
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5f
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7f
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9f
	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // a0..bf
	8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // c0..df
	0xa, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // e0..ef
	0xb, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // f0..ff
	0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
	1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
	1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
	1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // s7..s8
}

const (
	utf8Accept = 0
	utf8Reject = 1
)

func decode(state int, x rune, b byte) (int, rune) {
	t := utf8d[b]
	if state != utf8Accept {
		x = rune(b&0x3f) | (x << 6)
	} else {
		x = rune((0xff >> t) & b)
	}
	state = int(utf8d[256+state*16+int(t)])
	return state, x
}
<commit_msg>Removed unnecessary call to "http.Error".<commit_after>// Copyright 2012 Gary Burd
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.

// Command server is a test server for the Autobahn WebSockets Test Suite.
package main

import (
	"errors"
	"flag"
	"github.com/gorilla/websocket"
	"io"
	"log"
	"net/http"
	"time"
	"unicode/utf8"
)

var upgrader = websocket.Upgrader{
	ReadBufferSize:  4096,
	WriteBufferSize: 4096,
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
}

// echoCopy echoes messages from the client using io.Copy.
func echoCopy(w http.ResponseWriter, r *http.Request, writerOnly bool) {
	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Println("Upgrade:", err)
		return
	}
	defer conn.Close()
	for {
		mt, r, err := conn.NextReader()
		if err != nil {
			if err != io.EOF {
				log.Println("NextReader:", err)
			}
			return
		}
		if mt == websocket.TextMessage {
			r = &validator{r: r}
		}
		w, err := conn.NextWriter(mt)
		if err != nil {
			log.Println("NextWriter:", err)
			return
		}
		if mt == websocket.TextMessage {
			r = &validator{r: r}
		}
		if writerOnly {
			_, err = io.Copy(struct{ io.Writer }{w}, r)
		} else {
			_, err = io.Copy(w, r)
		}
		if err != nil {
			if err == errInvalidUTF8 {
				conn.WriteControl(websocket.CloseMessage,
					websocket.FormatCloseMessage(websocket.CloseInvalidFramePayloadData, ""),
					time.Time{})
			}
			log.Println("Copy:", err)
			return
		}
		err = w.Close()
		if err != nil {
			log.Println("Close:", err)
			return
		}
	}
}

func echoCopyWriterOnly(w http.ResponseWriter, r *http.Request) {
	echoCopy(w, r, true)
}

func echoCopyFull(w http.ResponseWriter, r *http.Request) {
	echoCopy(w, r, false)
}

// echoReadAll echoes messages from the client by reading the entire message
// with ioutil.ReadAll.
func echoReadAll(w http.ResponseWriter, r *http.Request, writeMessage bool) {
	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Println("Upgrade:", err)
		return
	}
	defer conn.Close()
	for {
		mt, b, err := conn.ReadMessage()
		if err != nil {
			if err != io.EOF {
				log.Println("NextReader:", err)
			}
			return
		}
		if mt == websocket.TextMessage {
			if !utf8.Valid(b) {
				conn.WriteControl(websocket.CloseMessage,
					websocket.FormatCloseMessage(websocket.CloseInvalidFramePayloadData, ""),
					time.Time{})
				log.Println("ReadAll: invalid utf8")
			}
		}
		if writeMessage {
			err = conn.WriteMessage(mt, b)
			if err != nil {
				log.Println("WriteMessage:", err)
			}
		} else {
			w, err := conn.NextWriter(mt)
			if err != nil {
				log.Println("NextWriter:", err)
				return
			}
			if _, err := w.Write(b); err != nil {
				log.Println("Writer:", err)
				return
			}
			if err := w.Close(); err != nil {
				log.Println("Close:", err)
				return
			}
		}
	}
}

func echoReadAllWriter(w http.ResponseWriter, r *http.Request) {
	echoReadAll(w, r, false)
}

func echoReadAllWriteMessage(w http.ResponseWriter, r *http.Request) {
	echoReadAll(w, r, true)
}

func serveHome(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" {
		http.Error(w, "Not found.", 404)
		return
	}
	if r.Method != "GET" {
		http.Error(w, "Method not allowed", 405)
		return
	}
	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	io.WriteString(w, "Echo Server</html")
}

var addr = flag.String("addr", ":9000", "http service address")

func main() {
	flag.Parse()
	http.HandleFunc("/", serveHome)
	http.HandleFunc("/c", echoCopyWriterOnly)
	http.HandleFunc("/f", echoCopyFull)
	http.HandleFunc("/r", echoReadAllWriter)
	http.HandleFunc("/m", echoReadAllWriteMessage)
	err := http.ListenAndServe(*addr, nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}

type validator struct {
	state int
	x     rune
	r     io.Reader
}

var errInvalidUTF8 = errors.New("invalid utf8")

func (r *validator) Read(p []byte) (int, error) {
	n, err := r.r.Read(p)
	state := r.state
	x := r.x
	for _, b := range p[:n] {
		state, x = decode(state, x, b)
		if state == utf8Reject {
			break
		}
	}
	r.state = state
	r.x = x
	if state == utf8Reject || (err == io.EOF && state != utf8Accept) {
		return n, errInvalidUTF8
	}
	return n, err
}

// UTF-8 decoder from http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
//
// Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
var utf8d = [...]byte{
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1f
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3f
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5f
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7f
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9f
	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // a0..bf
	8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // c0..df
	0xa, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // e0..ef
	0xb, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // f0..ff
	0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
	1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
	1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
	1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // s7..s8
}

const (
	utf8Accept = 0
	utf8Reject = 1
)

func decode(state int, x rune, b byte) (int, rune) {
	t := utf8d[b]
	if state != utf8Accept {
		x = rune(b&0x3f) | (x << 6)
	} else {
		x = rune((0xff >> t) & b)
	}
	state = int(utf8d[256+state*16+int(t)])
	return state, x
}
<|endoftext|>