<commit_before>// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package atomic

import "unsafe"

// Int32 is an atomically accessed int32 value.
//
// An Int32 must not be copied.
type Int32 struct {
	noCopy noCopy
	value  int32
}

// Load accesses and returns the value atomically.
func (i *Int32) Load() int32 {
	return Loadint32(&i.value)
}

// Store updates the value atomically.
func (i *Int32) Store(value int32) {
	Storeint32(&i.value, value)
}

// CompareAndSwap atomically compares i's value with old,
// and if they're equal, swaps i's value with new.
//
// Returns true if the operation succeeded.
func (i *Int32) CompareAndSwap(old, new int32) bool {
	return Casint32(&i.value, old, new)
}

// Swap replaces i's value with new, returning
// i's value before the replacement.
func (i *Int32) Swap(new int32) int32 {
	return Xchgint32(&i.value, new)
}

// Add adds delta to i atomically, returning
// the new updated value.
//
// This operation wraps around in the usual
// two's-complement way.
func (i *Int32) Add(delta int32) int32 {
	return Xaddint32(&i.value, delta)
}

// Int64 is an atomically accessed int64 value.
//
// 8-byte aligned on all platforms, unlike a regular int64.
//
// An Int64 must not be copied.
type Int64 struct {
	noCopy noCopy
	_      align64
	value  int64
}

// Load accesses and returns the value atomically.
func (i *Int64) Load() int64 {
	return Loadint64(&i.value)
}

// Store updates the value atomically.
func (i *Int64) Store(value int64) {
	Storeint64(&i.value, value)
}

// CompareAndSwap atomically compares i's value with old,
// and if they're equal, swaps i's value with new.
//
// Returns true if the operation succeeded.
func (i *Int64) CompareAndSwap(old, new int64) bool {
	return Casint64(&i.value, old, new)
}

// Swap replaces i's value with new, returning
// i's value before the replacement.
func (i *Int64) Swap(new int64) int64 {
	return Xchgint64(&i.value, new)
}

// Add adds delta to i atomically, returning
// the new updated value.
//
// This operation wraps around in the usual
// two's-complement way.
func (i *Int64) Add(delta int64) int64 {
	return Xaddint64(&i.value, delta)
}

// Uint8 is an atomically accessed uint8 value.
//
// A Uint8 must not be copied.
type Uint8 struct {
	noCopy noCopy
	value  uint8
}

// Load accesses and returns the value atomically.
func (u *Uint8) Load() uint8 {
	return Load8(&u.value)
}

// Store updates the value atomically.
func (u *Uint8) Store(value uint8) {
	Store8(&u.value, value)
}

// And takes value and performs a bit-wise
// "and" operation with the value of u, storing
// the result into u.
//
// The full process is performed atomically.
func (u *Uint8) And(value uint8) {
	And8(&u.value, value)
}

// Or takes value and performs a bit-wise
// "or" operation with the value of u, storing
// the result into u.
//
// The full process is performed atomically.
func (u *Uint8) Or(value uint8) {
	Or8(&u.value, value)
}

// Bool is an atomically accessed bool value.
//
// A Bool must not be copied.
type Bool struct {
	// Inherits noCopy from Uint8.
	u Uint8
}

// Load accesses and returns the value atomically.
func (b *Bool) Load() bool {
	return b.u.Load() != 0
}

// Store updates the value atomically.
func (b *Bool) Store(value bool) {
	s := uint8(0)
	if value {
		s = 1
	}
	b.u.Store(s)
}

// Uint32 is an atomically accessed uint32 value.
//
// A Uint32 must not be copied.
type Uint32 struct {
	noCopy noCopy
	value  uint32
}

// Load accesses and returns the value atomically.
func (u *Uint32) Load() uint32 {
	return Load(&u.value)
}

// LoadAcquire is a partially unsynchronized version
// of Load that relaxes ordering constraints. Other threads
// may observe operations that precede this operation to
// occur after it, but no operation that occurs after it
// on this thread can be observed to occur before it.
//
// WARNING: Use sparingly and with great care.
func (u *Uint32) LoadAcquire() uint32 {
	return LoadAcq(&u.value)
}

// Store updates the value atomically.
func (u *Uint32) Store(value uint32) {
	Store(&u.value, value)
}

// StoreRelease is a partially unsynchronized version
// of Store that relaxes ordering constraints. Other threads
// may observe operations that occur after this operation to
// precede it, but no operation that precedes it
// on this thread can be observed to occur after it.
//
// WARNING: Use sparingly and with great care.
func (u *Uint32) StoreRelease(value uint32) {
	StoreRel(&u.value, value)
}

// CompareAndSwap atomically compares u's value with old,
// and if they're equal, swaps u's value with new.
//
// Returns true if the operation succeeded.
func (u *Uint32) CompareAndSwap(old, new uint32) bool {
	return Cas(&u.value, old, new)
}

// CompareAndSwapRelease is a partially unsynchronized version
// of Cas that relaxes ordering constraints. Other threads
// may observe operations that occur after this operation to
// precede it, but no operation that precedes it
// on this thread can be observed to occur after it.
//
// Returns true if the operation succeeded.
//
// WARNING: Use sparingly and with great care.
func (u *Uint32) CompareAndSwapRelease(old, new uint32) bool {
	return CasRel(&u.value, old, new)
}

// Swap replaces u's value with new, returning
// u's value before the replacement.
func (u *Uint32) Swap(value uint32) uint32 {
	return Xchg(&u.value, value)
}

// And takes value and performs a bit-wise
// "and" operation with the value of u, storing
// the result into u.
//
// The full process is performed atomically.
func (u *Uint32) And(value uint32) {
	And(&u.value, value)
}

// Or takes value and performs a bit-wise
// "or" operation with the value of u, storing
// the result into u.
//
// The full process is performed atomically.
func (u *Uint32) Or(value uint32) {
	Or(&u.value, value)
}

// Add adds delta to u atomically, returning
// the new updated value.
//
// This operation wraps around in the usual
// two's-complement way.
func (u *Uint32) Add(delta int32) uint32 {
	return Xadd(&u.value, delta)
}

// Uint64 is an atomically accessed uint64 value.
//
// 8-byte aligned on all platforms, unlike a regular uint64.
//
// A Uint64 must not be copied.
type Uint64 struct {
	noCopy noCopy
	_      align64
	value  uint64
}

// Load accesses and returns the value atomically.
func (u *Uint64) Load() uint64 {
	return Load64(&u.value)
}

// Store updates the value atomically.
func (u *Uint64) Store(value uint64) {
	Store64(&u.value, value)
}

// CompareAndSwap atomically compares u's value with old,
// and if they're equal, swaps u's value with new.
//
// Returns true if the operation succeeded.
func (u *Uint64) CompareAndSwap(old, new uint64) bool {
	return Cas64(&u.value, old, new)
}

// Swap replaces u's value with new, returning
// u's value before the replacement.
func (u *Uint64) Swap(value uint64) uint64 {
	return Xchg64(&u.value, value)
}

// Add adds delta to u atomically, returning
// the new updated value.
//
// This operation wraps around in the usual
// two's-complement way.
func (u *Uint64) Add(delta int64) uint64 {
	return Xadd64(&u.value, delta)
}

// Uintptr is an atomically accessed uintptr value.
//
// A Uintptr must not be copied.
type Uintptr struct {
	noCopy noCopy
	value  uintptr
}

// Load accesses and returns the value atomically.
func (u *Uintptr) Load() uintptr {
	return Loaduintptr(&u.value)
}

// LoadAcquire is a partially unsynchronized version
// of Load that relaxes ordering constraints. Other threads
// may observe operations that precede this operation to
// occur after it, but no operation that occurs after it
// on this thread can be observed to occur before it.
//
// WARNING: Use sparingly and with great care.
func (u *Uintptr) LoadAcquire() uintptr {
	return LoadAcquintptr(&u.value)
}

// Store updates the value atomically.
func (u *Uintptr) Store(value uintptr) {
	Storeuintptr(&u.value, value)
}

// StoreRelease is a partially unsynchronized version
// of Store that relaxes ordering constraints. Other threads
// may observe operations that occur after this operation to
// precede it, but no operation that precedes it
// on this thread can be observed to occur after it.
//
// WARNING: Use sparingly and with great care.
func (u *Uintptr) StoreRelease(value uintptr) {
	StoreReluintptr(&u.value, value)
}

// CompareAndSwap atomically compares u's value with old,
// and if they're equal, swaps u's value with new.
//
// Returns true if the operation succeeded.
func (u *Uintptr) CompareAndSwap(old, new uintptr) bool {
	return Casuintptr(&u.value, old, new)
}

// Swap replaces u's value with new, returning
// u's value before the replacement.
func (u *Uintptr) Swap(value uintptr) uintptr {
	return Xchguintptr(&u.value, value)
}

// Add adds delta to u atomically, returning
// the new updated value.
//
// This operation wraps around in the usual
// two's-complement way.
func (u *Uintptr) Add(delta uintptr) uintptr {
	return Xadduintptr(&u.value, delta)
}

// Float64 is an atomically accessed float64 value.
//
// 8-byte aligned on all platforms, unlike a regular float64.
//
// A Float64 must not be copied.
type Float64 struct {
	// Inherits noCopy and align64 from Uint64.
	u Uint64
}

// Load accesses and returns the value atomically.
func (f *Float64) Load() float64 {
	r := f.u.Load()
	return *(*float64)(unsafe.Pointer(&r))
}

// Store updates the value atomically.
func (f *Float64) Store(value float64) {
	f.u.Store(*(*uint64)(unsafe.Pointer(&value)))
}

// UnsafePointer is an atomically accessed unsafe.Pointer value.
//
// Note that because of the atomicity guarantees, stores to values
// of this type never trigger a write barrier, and the relevant
// methods are suffixed with "NoWB" to indicate that explicitly.
// As a result, this type should be used carefully, and sparingly,
// mostly with values that do not live in the Go heap anyway.
//
// An UnsafePointer must not be copied.
type UnsafePointer struct {
	noCopy noCopy
	value  unsafe.Pointer
}

// Load accesses and returns the value atomically.
func (u *UnsafePointer) Load() unsafe.Pointer {
	return Loadp(unsafe.Pointer(&u.value))
}

// StoreNoWB updates the value atomically.
//
// WARNING: As the name implies this operation does *not*
// perform a write barrier on value, and so this operation may
// hide pointers from the GC. Use with care and sparingly.
// It is safe to use with values not found in the Go heap.
func (u *UnsafePointer) StoreNoWB(value unsafe.Pointer) {
	StorepNoWB(unsafe.Pointer(&u.value), value)
}

// CompareAndSwapNoWB atomically (with respect to other methods)
// compares u's value with old, and if they're equal,
// swaps u's value with new.
//
// Returns true if the operation succeeded.
//
// WARNING: As the name implies this operation does *not*
// perform a write barrier on value, and so this operation may
// hide pointers from the GC. Use with care and sparingly.
// It is safe to use with values not found in the Go heap.
func (u *UnsafePointer) CompareAndSwapNoWB(old, new unsafe.Pointer) bool {
	return Casp1(&u.value, old, new)
}

// noCopy may be embedded into structs which must not be copied
// after the first use.
//
// See https://golang.org/issues/8005#issuecomment-190753527
// for details.
type noCopy struct{}

// Lock is a no-op used by -copylocks checker from `go vet`.
func (*noCopy) Lock()   {}
func (*noCopy) Unlock() {}

// align64 may be added to structs that must be 64-bit aligned.
// This struct is recognized by a special case in the compiler
// and will not work if copied to any other package.
type align64 struct{}
<commit_msg>runtime/internal/atomic: add Pointer[T] type<commit_after>// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package atomic

import "unsafe"

// Int32 is an atomically accessed int32 value.
//
// An Int32 must not be copied.
type Int32 struct {
	noCopy noCopy
	value  int32
}

// Load accesses and returns the value atomically.
func (i *Int32) Load() int32 {
	return Loadint32(&i.value)
}

// Store updates the value atomically.
func (i *Int32) Store(value int32) {
	Storeint32(&i.value, value)
}

// CompareAndSwap atomically compares i's value with old,
// and if they're equal, swaps i's value with new.
//
// Returns true if the operation succeeded.
func (i *Int32) CompareAndSwap(old, new int32) bool {
	return Casint32(&i.value, old, new)
}

// Swap replaces i's value with new, returning
// i's value before the replacement.
func (i *Int32) Swap(new int32) int32 {
	return Xchgint32(&i.value, new)
}

// Add adds delta to i atomically, returning
// the new updated value.
//
// This operation wraps around in the usual
// two's-complement way.
func (i *Int32) Add(delta int32) int32 {
	return Xaddint32(&i.value, delta)
}

// Int64 is an atomically accessed int64 value.
//
// 8-byte aligned on all platforms, unlike a regular int64.
//
// An Int64 must not be copied.
type Int64 struct {
	noCopy noCopy
	_      align64
	value  int64
}

// Load accesses and returns the value atomically.
func (i *Int64) Load() int64 {
	return Loadint64(&i.value)
}

// Store updates the value atomically.
func (i *Int64) Store(value int64) {
	Storeint64(&i.value, value)
}

// CompareAndSwap atomically compares i's value with old,
// and if they're equal, swaps i's value with new.
//
// Returns true if the operation succeeded.
func (i *Int64) CompareAndSwap(old, new int64) bool {
	return Casint64(&i.value, old, new)
}

// Swap replaces i's value with new, returning
// i's value before the replacement.
func (i *Int64) Swap(new int64) int64 {
	return Xchgint64(&i.value, new)
}

// Add adds delta to i atomically, returning
// the new updated value.
//
// This operation wraps around in the usual
// two's-complement way.
func (i *Int64) Add(delta int64) int64 {
	return Xaddint64(&i.value, delta)
}

// Uint8 is an atomically accessed uint8 value.
//
// A Uint8 must not be copied.
type Uint8 struct {
	noCopy noCopy
	value  uint8
}

// Load accesses and returns the value atomically.
func (u *Uint8) Load() uint8 {
	return Load8(&u.value)
}

// Store updates the value atomically.
func (u *Uint8) Store(value uint8) {
	Store8(&u.value, value)
}

// And takes value and performs a bit-wise
// "and" operation with the value of u, storing
// the result into u.
//
// The full process is performed atomically.
func (u *Uint8) And(value uint8) {
	And8(&u.value, value)
}

// Or takes value and performs a bit-wise
// "or" operation with the value of u, storing
// the result into u.
//
// The full process is performed atomically.
func (u *Uint8) Or(value uint8) {
	Or8(&u.value, value)
}

// Bool is an atomically accessed bool value.
//
// A Bool must not be copied.
type Bool struct {
	// Inherits noCopy from Uint8.
	u Uint8
}

// Load accesses and returns the value atomically.
func (b *Bool) Load() bool {
	return b.u.Load() != 0
}

// Store updates the value atomically.
func (b *Bool) Store(value bool) {
	s := uint8(0)
	if value {
		s = 1
	}
	b.u.Store(s)
}

// Uint32 is an atomically accessed uint32 value.
//
// A Uint32 must not be copied.
type Uint32 struct {
	noCopy noCopy
	value  uint32
}

// Load accesses and returns the value atomically.
func (u *Uint32) Load() uint32 {
	return Load(&u.value)
}

// LoadAcquire is a partially unsynchronized version
// of Load that relaxes ordering constraints. Other threads
// may observe operations that precede this operation to
// occur after it, but no operation that occurs after it
// on this thread can be observed to occur before it.
//
// WARNING: Use sparingly and with great care.
func (u *Uint32) LoadAcquire() uint32 {
	return LoadAcq(&u.value)
}

// Store updates the value atomically.
func (u *Uint32) Store(value uint32) {
	Store(&u.value, value)
}

// StoreRelease is a partially unsynchronized version
// of Store that relaxes ordering constraints. Other threads
// may observe operations that occur after this operation to
// precede it, but no operation that precedes it
// on this thread can be observed to occur after it.
//
// WARNING: Use sparingly and with great care.
func (u *Uint32) StoreRelease(value uint32) {
	StoreRel(&u.value, value)
}

// CompareAndSwap atomically compares u's value with old,
// and if they're equal, swaps u's value with new.
//
// Returns true if the operation succeeded.
func (u *Uint32) CompareAndSwap(old, new uint32) bool {
	return Cas(&u.value, old, new)
}

// CompareAndSwapRelease is a partially unsynchronized version
// of Cas that relaxes ordering constraints. Other threads
// may observe operations that occur after this operation to
// precede it, but no operation that precedes it
// on this thread can be observed to occur after it.
//
// Returns true if the operation succeeded.
//
// WARNING: Use sparingly and with great care.
func (u *Uint32) CompareAndSwapRelease(old, new uint32) bool {
	return CasRel(&u.value, old, new)
}

// Swap replaces u's value with new, returning
// u's value before the replacement.
func (u *Uint32) Swap(value uint32) uint32 {
	return Xchg(&u.value, value)
}

// And takes value and performs a bit-wise
// "and" operation with the value of u, storing
// the result into u.
//
// The full process is performed atomically.
func (u *Uint32) And(value uint32) {
	And(&u.value, value)
}

// Or takes value and performs a bit-wise
// "or" operation with the value of u, storing
// the result into u.
//
// The full process is performed atomically.
func (u *Uint32) Or(value uint32) {
	Or(&u.value, value)
}

// Add adds delta to u atomically, returning
// the new updated value.
//
// This operation wraps around in the usual
// two's-complement way.
func (u *Uint32) Add(delta int32) uint32 {
	return Xadd(&u.value, delta)
}

// Uint64 is an atomically accessed uint64 value.
//
// 8-byte aligned on all platforms, unlike a regular uint64.
//
// A Uint64 must not be copied.
type Uint64 struct {
	noCopy noCopy
	_      align64
	value  uint64
}

// Load accesses and returns the value atomically.
func (u *Uint64) Load() uint64 {
	return Load64(&u.value)
}

// Store updates the value atomically.
func (u *Uint64) Store(value uint64) {
	Store64(&u.value, value)
}

// CompareAndSwap atomically compares u's value with old,
// and if they're equal, swaps u's value with new.
//
// Returns true if the operation succeeded.
func (u *Uint64) CompareAndSwap(old, new uint64) bool {
	return Cas64(&u.value, old, new)
}

// Swap replaces u's value with new, returning
// u's value before the replacement.
func (u *Uint64) Swap(value uint64) uint64 {
	return Xchg64(&u.value, value)
}

// Add adds delta to u atomically, returning
// the new updated value.
//
// This operation wraps around in the usual
// two's-complement way.
func (u *Uint64) Add(delta int64) uint64 {
	return Xadd64(&u.value, delta)
}

// Uintptr is an atomically accessed uintptr value.
//
// A Uintptr must not be copied.
type Uintptr struct {
	noCopy noCopy
	value  uintptr
}

// Load accesses and returns the value atomically.
func (u *Uintptr) Load() uintptr {
	return Loaduintptr(&u.value)
}

// LoadAcquire is a partially unsynchronized version
// of Load that relaxes ordering constraints. Other threads
// may observe operations that precede this operation to
// occur after it, but no operation that occurs after it
// on this thread can be observed to occur before it.
//
// WARNING: Use sparingly and with great care.
func (u *Uintptr) LoadAcquire() uintptr {
	return LoadAcquintptr(&u.value)
}

// Store updates the value atomically.
func (u *Uintptr) Store(value uintptr) {
	Storeuintptr(&u.value, value)
}

// StoreRelease is a partially unsynchronized version
// of Store that relaxes ordering constraints. Other threads
// may observe operations that occur after this operation to
// precede it, but no operation that precedes it
// on this thread can be observed to occur after it.
//
// WARNING: Use sparingly and with great care.
func (u *Uintptr) StoreRelease(value uintptr) {
	StoreReluintptr(&u.value, value)
}

// CompareAndSwap atomically compares u's value with old,
// and if they're equal, swaps u's value with new.
//
// Returns true if the operation succeeded.
func (u *Uintptr) CompareAndSwap(old, new uintptr) bool {
	return Casuintptr(&u.value, old, new)
}

// Swap replaces u's value with new, returning
// u's value before the replacement.
func (u *Uintptr) Swap(value uintptr) uintptr {
	return Xchguintptr(&u.value, value)
}

// Add adds delta to u atomically, returning
// the new updated value.
//
// This operation wraps around in the usual
// two's-complement way.
func (u *Uintptr) Add(delta uintptr) uintptr {
	return Xadduintptr(&u.value, delta)
}

// Float64 is an atomically accessed float64 value.
//
// 8-byte aligned on all platforms, unlike a regular float64.
//
// A Float64 must not be copied.
type Float64 struct {
	// Inherits noCopy and align64 from Uint64.
	u Uint64
}

// Load accesses and returns the value atomically.
func (f *Float64) Load() float64 {
	r := f.u.Load()
	return *(*float64)(unsafe.Pointer(&r))
}

// Store updates the value atomically.
func (f *Float64) Store(value float64) {
	f.u.Store(*(*uint64)(unsafe.Pointer(&value)))
}

// UnsafePointer is an atomically accessed unsafe.Pointer value.
//
// Note that because of the atomicity guarantees, stores to values
// of this type never trigger a write barrier, and the relevant
// methods are suffixed with "NoWB" to indicate that explicitly.
// As a result, this type should be used carefully, and sparingly,
// mostly with values that do not live in the Go heap anyway.
//
// An UnsafePointer must not be copied.
type UnsafePointer struct {
	noCopy noCopy
	value  unsafe.Pointer
}

// Load accesses and returns the value atomically.
func (u *UnsafePointer) Load() unsafe.Pointer {
	return Loadp(unsafe.Pointer(&u.value))
}

// StoreNoWB updates the value atomically.
//
// WARNING: As the name implies this operation does *not*
// perform a write barrier on value, and so this operation may
// hide pointers from the GC. Use with care and sparingly.
// It is safe to use with values not found in the Go heap.
func (u *UnsafePointer) StoreNoWB(value unsafe.Pointer) {
	StorepNoWB(unsafe.Pointer(&u.value), value)
}

// CompareAndSwapNoWB atomically (with respect to other methods)
// compares u's value with old, and if they're equal,
// swaps u's value with new.
//
// Returns true if the operation succeeded.
//
// WARNING: As the name implies this operation does *not*
// perform a write barrier on value, and so this operation may
// hide pointers from the GC. Use with care and sparingly.
// It is safe to use with values not found in the Go heap.
func (u *UnsafePointer) CompareAndSwapNoWB(old, new unsafe.Pointer) bool {
	return Casp1(&u.value, old, new)
}

// Pointer is an atomic pointer of type *T.
type Pointer[T any] struct {
	u UnsafePointer
}

// Load accesses and returns the value atomically.
func (p *Pointer[T]) Load() *T {
	return (*T)(p.u.Load())
}

// StoreNoWB updates the value atomically.
//
// WARNING: As the name implies this operation does *not*
// perform a write barrier on value, and so this operation may
// hide pointers from the GC. Use with care and sparingly.
// It is safe to use with values not found in the Go heap.
func (p *Pointer[T]) StoreNoWB(value *T) {
	p.u.StoreNoWB(unsafe.Pointer(value))
}

// CompareAndSwapNoWB atomically (with respect to other methods)
// compares u's value with old, and if they're equal,
// swaps u's value with new.
//
// Returns true if the operation succeeded.
//
// WARNING: As the name implies this operation does *not*
// perform a write barrier on value, and so this operation may
// hide pointers from the GC. Use with care and sparingly.
// It is safe to use with values not found in the Go heap.
func (p *Pointer[T]) CompareAndSwapNoWB(old, new *T) bool {
	return p.u.CompareAndSwapNoWB(unsafe.Pointer(old), unsafe.Pointer(new))
}

// noCopy may be embedded into structs which must not be copied
// after the first use.
//
// See https://golang.org/issues/8005#issuecomment-190753527
// for details.
type noCopy struct{}

// Lock is a no-op used by -copylocks checker from `go vet`.
func (*noCopy) Lock()   {}
func (*noCopy) Unlock() {}

// align64 may be added to structs that must be 64-bit aligned.
// This struct is recognized by a special case in the compiler
// and will not work if copied to any other package.
type align64 struct{}
<|endoftext|>


<commit_before>package switchboard

import (
	"fmt"
	"log"
	"net"

	"github.com/pivotal-golang/lager"
)

type Switchboard struct {
	logger   lager.Logger
	listener net.Listener
	backends Backends
}

func New(listener net.Listener, backends Backends, logger lager.Logger) Switchboard {
	return Switchboard{
		logger:   logger,
		listener: listener,
		backends: backends,
	}
}

func (bm *Switchboard) Run() {
	bm.backends.StartHealthchecks()
	for {
		clientConn, err := bm.listener.Accept()
		if err != nil {
			log.Fatal(fmt.Sprintf("Error accepting client connection: %v", err))
		}
		defer clientConn.Close()

		backend := bm.backends.CurrentBackend()
		backendConn, err := backend.Dial()
		if err != nil {
			bm.logger.Error("Error connection to backend.", err)
			return
		}
		defer backendConn.Close()

		bridge := NewConnectionBridge(clientConn, backendConn, bm.logger)
		backend.AddBridge(bridge)

		go func() {
			bridge.Connect()
			backend.RemoveBridge(bridge)
		}()
	}
}
<commit_msg>Avoid defered connection closing<commit_after>package switchboard

import (
	"fmt"
	"log"
	"net"

	"github.com/pivotal-golang/lager"
)

type Switchboard struct {
	logger   lager.Logger
	listener net.Listener
	backends Backends
}

func New(listener net.Listener, backends Backends, logger lager.Logger) Switchboard {
	return Switchboard{
		logger:   logger,
		listener: listener,
		backends: backends,
	}
}

func (bm *Switchboard) Run() {
	bm.backends.StartHealthchecks()
	for {
		clientConn, err := bm.listener.Accept()
		if err != nil {
			log.Fatal(fmt.Sprintf("Error accepting client connection: %v", err))
		}

		backend := bm.backends.CurrentBackend()
		backendConn, err := backend.Dial()
		if err != nil {
			bm.logger.Error("Error connection to backend.", err)
			return
		}

		bridge := NewConnectionBridge(clientConn, backendConn, bm.logger)
		backend.AddBridge(bridge)

		go func() {
			bridge.Connect()
			backend.RemoveBridge(bridge)
		}()
	}
}
<|endoftext|>


<commit_before>package badgerstore

import (
	"bytes"
	"encoding/gob"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/PaluMacil/dwn/database"

	"github.com/dgraph-io/badger"
)

type BadgerStore struct {
	bgr      *badger.DB
	gcTicker *time.Ticker
}

func retry(originalOpts badger.Options) (*BadgerStore, error) {
	lockPath := filepath.Join(originalOpts.Dir, "LOCK")
	if err := os.Remove(lockPath); err != nil {
		return nil, fmt.Errorf(`removing "LOCK": %s`, err)
	}
	retryOpts := originalOpts
	retryOpts.Truncate = true
	bgr, err := badger.Open(retryOpts)
	return &BadgerStore{bgr: bgr}, err
}

func New(dir string) (*BadgerStore, error) {
	bgr, err := badger.Open(opts(dir))
	if err != nil {
		if strings.Contains(err.Error(), "LOCK") {
			log.Println("database locked, probably due to improper shutdown")
			if bgr, err := retry(opts(dir)); err == nil {
				log.Println("database unlocked, value log truncated")
				return bgr, nil
			}
			log.Println("could not unlock database:", err)

		}
		return nil, err
	}

	gcTicker := time.NewTicker(5 * time.Minute)
	bs := &BadgerStore{
		bgr:      bgr,
		gcTicker: gcTicker,
	}
	go func() {
		for range gcTicker.C {
			bs.runGC()
		}
	}()
	return bs, nil
}

func (bs *BadgerStore) runGC() {
	log.Println("Running GC...")
	var logFiles int
again:
	err := bs.bgr.RunValueLogGC(0.7)
	if err == nil {
		logFiles++
		goto again
	}
	log.Println(logFiles, "log files removed during GC.")
}

func (bs BadgerStore) Close() error {
	bs.gcTicker.Stop()
	bs.runGC()
	return bs.bgr.Close()
}

func (bs BadgerStore) IsKeyNotFoundErr(err error) bool {
	if err == nil {
		return false
	}
	return strings.Contains(err.Error(), badger.ErrKeyNotFound.Error())
}

func (bs *BadgerStore) Get(obj database.Item) (database.Item, error) {
	var rawBytes []byte
	err := bs.bgr.View(func(txn *badger.Txn) error {
		item, err := txn.Get(obj.Key())
		if err != nil {
			return err
		}
		value, err := item.Value()
		if err != nil {
			return err
		}
		rawBytes = make([]byte, len(value))
		copy(rawBytes, value)
		return nil
	})
	if err != nil {
		return obj, fmt.Errorf(`getting "%s" (%T): %s`, string(obj.Key()), obj, err)
	}
	var buf bytes.Buffer
	_, err = buf.Write(rawBytes)
	if err != nil {
		return obj, err
	}
	dec := gob.NewDecoder(&buf)
	err = dec.Decode(&obj)
	if err != nil {
		return obj, err
	}
	return obj, nil
}

func (bs *BadgerStore) Set(obj database.Item) error {
	var buf bytes.Buffer
	enc := gob.NewEncoder(&buf)
	err := enc.Encode(&obj)
	if err != nil {
		return err
	}
	return bs.bgr.Update(func(txn *badger.Txn) error {
		err := txn.Set(obj.Key(), buf.Bytes())
		if err != nil {
			return fmt.Errorf(`setting "%s" (%T): %s`, string(obj.Key()), obj, err)
		}
		return nil
	})
}

func (bs *BadgerStore) Delete(obj database.Item) error {
	return bs.bgr.Update(func(txn *badger.Txn) error {
		return txn.Delete(obj.Key())
	})
}

func (bs *BadgerStore) All(pfx []byte, out *[]database.Item, preload bool) error {
	err := bs.bgr.View(func(txn *badger.Txn) error {
		it := txn.NewIterator(badger.DefaultIteratorOptions)
		defer it.Close()

		for it.Seek(pfx); it.ValidForPrefix(pfx); it.Next() {
			item := it.Item()
			v, err := item.Value()
			if err != nil {
				return err
			}
			var buf bytes.Buffer
			var outItem database.Item
			_, err = buf.Write(v)
			if err != nil {
				return err
			}
			dec := gob.NewDecoder(&buf)
			err = dec.Decode(&outItem)
			if err != nil {
				return err
			}
			*out = append(*out, outItem)
		}
		return nil
	})
	return err
}

func (bs *BadgerStore) Count(pfx []byte) (int, error) {
	var items []database.Item
	err := bs.All(pfx, &items, false)
	return len(items), err
}
<commit_msg>populate ticker during retry<commit_after>package badgerstore

import (
	"bytes"
	"encoding/gob"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/PaluMacil/dwn/database"

	"github.com/dgraph-io/badger"
)

type BadgerStore struct {
	bgr      *badger.DB
	gcTicker *time.Ticker
}

func open(dir string) (*badger.DB, error) {
	originalOpts := opts(dir)
	bgr, err := badger.Open(originalOpts)
	if err != nil {
		if strings.Contains(err.Error(), "LOCK") {
			log.Println("database locked, probably due to improper shutdown")

			lockPath := filepath.Join(originalOpts.Dir, "LOCK")
			if err = os.Remove(lockPath); err != nil {
				return nil, fmt.Errorf(`removing "LOCK": %s`, err)
			}
			retryOpts := originalOpts
			retryOpts.Truncate = true
			log.Println("attempting to unlock database, tuncating value log")
			bgr, err = badger.Open(retryOpts)
			if err != nil {
				return nil, fmt.Errorf("could not unlock database: %s", err)
			}
			return bgr, nil
		}
		return nil, err
	}
	return bgr, nil
}

func New(dir string) (*BadgerStore, error) {
	bgr, err := open(dir)
	if err != nil {
		return nil, fmt.Errorf("opening badger database: %s", err)
	}

	gcTicker := time.NewTicker(5 * time.Minute)
	bs := &BadgerStore{
		bgr:      bgr,
		gcTicker: gcTicker,
	}
	go func() {
		for range gcTicker.C {
			bs.runGC()
		}
	}()
	return bs, nil
}

func (bs *BadgerStore) runGC() {
	log.Println("Running GC...")
	var logFiles int
again:
	err := bs.bgr.RunValueLogGC(0.7)
	if err == nil {
		logFiles++
		goto again
	}
	log.Println(logFiles, "log files removed during GC.")
}

func (bs BadgerStore) Close() error {
	bs.gcTicker.Stop()
	bs.runGC()
	return bs.bgr.Close()
}

func (bs BadgerStore) IsKeyNotFoundErr(err error) bool {
	if err == nil {
		return false
	}
	return strings.Contains(err.Error(), badger.ErrKeyNotFound.Error())
}

func (bs *BadgerStore) Get(obj database.Item) (database.Item, error) {
	var rawBytes []byte
	err := bs.bgr.View(func(txn *badger.Txn) error {
		item, err := txn.Get(obj.Key())
		if err != nil {
			return err
		}
		value, err := item.Value()
		if err != nil {
			return err
		}
		rawBytes = make([]byte, len(value))
		copy(rawBytes, value)
		return nil
	})
	if err != nil {
		return obj, fmt.Errorf(`getting "%s" (%T): %s`, string(obj.Key()), obj, err)
	}
	var buf bytes.Buffer
	_, err = buf.Write(rawBytes)
	if err != nil {
		return obj, err
	}
	dec := gob.NewDecoder(&buf)
	err = dec.Decode(&obj)
	if err != nil {
		return obj, err
	}
	return obj, nil
}

func (bs *BadgerStore) Set(obj database.Item) error {
	var buf bytes.Buffer
	enc := gob.NewEncoder(&buf)
	err := enc.Encode(&obj)
	if err != nil {
		return err
	}
	return bs.bgr.Update(func(txn *badger.Txn) error {
		err := txn.Set(obj.Key(), buf.Bytes())
		if err != nil {
			return fmt.Errorf(`setting "%s" (%T): %s`, string(obj.Key()), obj, err)
		}
		return nil
	})
}

func (bs *BadgerStore) Delete(obj database.Item) error {
	return bs.bgr.Update(func(txn *badger.Txn) error {
		return txn.Delete(obj.Key())
	})
}

func (bs *BadgerStore) All(pfx []byte, out *[]database.Item, preload bool) error {
	err := bs.bgr.View(func(txn *badger.Txn) error {
		it := txn.NewIterator(badger.DefaultIteratorOptions)
		defer it.Close()

		for it.Seek(pfx); it.ValidForPrefix(pfx); it.Next() {
			item := it.Item()
			v, err := item.Value()
			if err != nil {
				return err
			}
			var buf bytes.Buffer
			var outItem database.Item
			_, err = buf.Write(v)
			if err != nil {
				return err
			}
			dec := gob.NewDecoder(&buf)
			err = dec.Decode(&outItem)
			if err != nil {
				return err
			}
			*out = append(*out, outItem)
		}
		return nil
	})
	return err
}

func (bs *BadgerStore) Count(pfx []byte) (int, error) {
	var items []database.Item
	err := bs.All(pfx, &items, false)
	return len(items), err
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"os"
	"sort"
	"strings"

	"github.com/pkg/errors"
	"github.com/spf13/cobra"
	yaml "gopkg.in/yaml.v2"

	"github.com/lxc/lxd/lxc/utils"
	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/api"
	cli "github.com/lxc/lxd/shared/cmd"
	"github.com/lxc/lxd/shared/i18n"
)

type cmdCluster struct {
	global *cmdGlobal
}

func (c *cmdCluster) Command() *cobra.Command {
	cmd := &cobra.Command{}
	cmd.Use = i18n.G("cluster")
	cmd.Short = i18n.G("Manage cluster members")
	cmd.Long = cli.FormatSection(i18n.G("Description"), i18n.G(
		`Manage cluster members`))

	// List
	clusterListCmd := cmdClusterList{global: c.global, cluster: c}
	cmd.AddCommand(clusterListCmd.Command())

	// Rename
	clusterRenameCmd := cmdClusterRename{global: c.global, cluster: c}
	cmd.AddCommand(clusterRenameCmd.Command())

	// Remove
	clusterRemoveCmd := cmdClusterRemove{global: c.global, cluster: c}
	cmd.AddCommand(clusterRemoveCmd.Command())

	// Show
	clusterShowCmd := cmdClusterShow{global: c.global, cluster: c}
	cmd.AddCommand(clusterShowCmd.Command())

	// Enable
	clusterEnableCmd := cmdClusterEnable{global: c.global, cluster: c}
	cmd.AddCommand(clusterEnableCmd.Command())

	return cmd
}

// List
type cmdClusterList struct {
	global  *cmdGlobal
	cluster *cmdCluster

	flagFormat string
}

func (c *cmdClusterList) Command() *cobra.Command {
	cmd := &cobra.Command{}
	cmd.Use = i18n.G("list [<remote>:]")
	cmd.Aliases = []string{"ls"}
	cmd.Short = i18n.G("List all the cluster members")
	cmd.Long = cli.FormatSection(i18n.G("Description"), i18n.G(
		`List all the cluster members`))
	cmd.Flags().StringVar(&c.flagFormat, "format", "table", i18n.G("Format (csv|json|table|yaml)")+"``")

	cmd.RunE = c.Run

	return cmd
}

func (c *cmdClusterList) Run(cmd *cobra.Command, args []string) error {
	// Sanity checks
	exit, err := c.global.CheckArgs(cmd, args, 0, 1)
	if exit {
		return err
	}

	// Parse remote
	remote := ""
	if len(args) == 1 {
		remote = args[0]
	}

	resources, err := c.global.ParseServers(remote)
	if err != nil {
		return err
	}

	resource := resources[0]

	// Check if clustered
	cluster, _, err := resource.server.GetCluster()
	if err != nil {
		return err
	}

	if !cluster.Enabled {
		return fmt.Errorf(i18n.G("LXD server isn't part of a cluster"))
	}

	// Get the cluster members
	members, err := resource.server.GetClusterMembers()
	if err != nil {
		return err
	}

	// Render the table
	data := [][]string{}
	for _, member := range members {
		database := "NO"
		if member.Database {
			database = "YES"
		}
		line := []string{member.ServerName, member.URL, database, strings.ToUpper(member.Status), member.Message, member.Architecture}
		data = append(data, line)
	}
	sort.Sort(byName(data))

	header := []string{
		i18n.G("NAME"),
		i18n.G("URL"),
		i18n.G("DATABASE"),
		i18n.G("STATE"),
		i18n.G("MESSAGE"),
		i18n.G("ARCHITECTURE"),
	}

	return utils.RenderTable(c.flagFormat, header, data, members)
}

// Show
type cmdClusterShow struct {
	global  *cmdGlobal
	cluster *cmdCluster
}

func (c *cmdClusterShow) Command() *cobra.Command {
	cmd := &cobra.Command{}
	cmd.Use = i18n.G("show [<remote>:]<member>")
	cmd.Short = i18n.G("Show details of a cluster member")
	cmd.Long = cli.FormatSection(i18n.G("Description"), i18n.G(
		`Show details of a cluster member`))

	cmd.RunE = c.Run

	return cmd
}

func (c *cmdClusterShow) Run(cmd *cobra.Command, args []string) error {
	// Sanity checks
	exit, err := c.global.CheckArgs(cmd, args, 1, 1)
	if exit {
		return err
	}

	// Parse remote
	resources, err := c.global.ParseServers(args[0])
	if err != nil {
		return err
	}

	resource := resources[0]

	// Get the member information
	member, _, err := resource.server.GetClusterMember(resource.name)
	if err != nil {
		return err
	}

	// Render as YAML
	data, err := yaml.Marshal(&member)
	if err != nil {
		return err
	}

	fmt.Printf("%s", data)
	return nil
}

// Rename
type cmdClusterRename struct {
	global  *cmdGlobal
	cluster *cmdCluster
}

func (c *cmdClusterRename) Command() *cobra.Command {
	cmd := &cobra.Command{}
	cmd.Use = i18n.G("rename [<remote>:]<member> <new-name>")
	cmd.Aliases = []string{"mv"}
	cmd.Short = i18n.G("Rename a cluster member")
	cmd.Long = cli.FormatSection(i18n.G("Description"), i18n.G(
		`Rename a cluster member`))

	cmd.RunE = c.Run

	return cmd
}

func (c *cmdClusterRename) Run(cmd *cobra.Command, args []string) error {
	// Sanity checks
	exit, err := c.global.CheckArgs(cmd, args, 2, 2)
	if exit {
		return err
	}

	// Parse remote
	resources, err := c.global.ParseServers(args[0])
	if err != nil {
		return err
	}

	resource := resources[0]

	// Perform the rename
	err = resource.server.RenameClusterMember(resource.name, api.ClusterMemberPost{ServerName: args[1]})
	if err != nil {
		return err
	}

	if !c.global.flagQuiet {
		fmt.Printf(i18n.G("Member %s renamed to %s")+"\n", resource.name, args[1])
	}

	return nil
}

// Remove
type cmdClusterRemove struct {
	global  *cmdGlobal
	cluster *cmdCluster

	flagForce          bool
	flagNonInteractive bool
}

func (c *cmdClusterRemove) Command() *cobra.Command {
	cmd := &cobra.Command{}
	cmd.Use = i18n.G("remove [<remote>:]<member>")
	cmd.Aliases = []string{"rm"}
	cmd.Short = i18n.G("Remove a member from the cluster")
	cmd.Long = cli.FormatSection(i18n.G("Description"), i18n.G(
		`Remove a member from the cluster`))

	cmd.RunE = c.Run
	cmd.Flags().BoolVarP(&c.flagForce, "force", "f", false, i18n.G("Force removing a member, even if degraded"))
	cmd.Flags().BoolVarP(&c.flagNonInteractive, "quiet", "q", false, i18n.G("Don't require user confirmation for using --force"))

	return cmd
}

func (c *cmdClusterRemove) promptConfirmation(name string) error {
	reader := bufio.NewReader(os.Stdin)
	fmt.Printf(i18n.G(`Forcefully removing a server from the cluster should only be done as a last
resort.

The removed server will not be functional after this action and will require a
full reset of LXD, losing any remaining instance, image or storage volume
that the server may have held.

When possible, a graceful removal should be preferred, this will require you to
move any affected instance, image or storage volume to another server prior to
the server being cleanly removed from the cluster.

The --force flag should only be used if the server has died, been reinstalled
or is otherwise never expected to come back up.

Are you really sure you want to force removing %s? (yes/no): `), name)
	input, _ := reader.ReadString('\n')
	input = strings.TrimSuffix(input, "\n")

	if !shared.StringInSlice(strings.ToLower(input), []string{i18n.G("yes")}) {
		return fmt.Errorf(i18n.G("User aborted delete operation"))
	}

	return nil
}

func (c *cmdClusterRemove) Run(cmd *cobra.Command, args []string) error {
	// Sanity checks
	exit, err := c.global.CheckArgs(cmd, args, 1, 1)
	if exit {
		return err
	}

	// Parse remote
	resources, err := c.global.ParseServers(args[0])
	if err != nil {
		return err
	}

	resource := resources[0]

	// Prompt for confiromation if --force is used.
	if !c.flagNonInteractive && c.flagForce {
		err := c.promptConfirmation(resource.name)
		if err != nil {
			return err
		}
	}

	// Delete the cluster member
	err = resource.server.DeleteClusterMember(resource.name, c.flagForce)
	if err != nil {
		return err
	}

	if !c.global.flagQuiet {
		fmt.Printf(i18n.G("Member %s removed")+"\n", resource.name)
	}

	return nil
}

// Enable
type cmdClusterEnable struct {
	global  *cmdGlobal
	cluster *cmdCluster

	flagForce bool
}

func (c *cmdClusterEnable) Command() *cobra.Command {
	cmd := &cobra.Command{}
	cmd.Use = i18n.G("enable [<remote>:] <name>")
	cmd.Short = i18n.G("Enable clustering on a single non-clustered LXD server")
	cmd.Long = cli.FormatSection(i18n.G("Description"), i18n.G(
		`Enable clustering on a single non-clustered LXD server

  This command turns a non-clustered LXD server into the first member of a new
  LXD cluster, which will have the given name.

  It's required that the LXD is already available on the network. You can check
  that by running 'lxc config get core.https_address', and possibly set a value
  for the address if not yet set.`))

	cmd.RunE = c.Run

	return cmd
}

func (c *cmdClusterEnable) Run(cmd *cobra.Command, args []string) error {
	// Sanity checks
	exit, err := c.global.CheckArgs(cmd, args, 1, 2)
	if exit {
		return err
	}

	// Parse remote
	remote := ""
	name := args[0]
	if len(args) == 2 {
		remote = args[0]
		name = args[1]
	}

	resources, err := c.global.ParseServers(remote)
	if err != nil {
		return err
	}

	resource := resources[0]

	// Check if the LXD server is available on the network.
	server, _, err := resource.server.GetServer()
	if err != nil {
		return errors.Wrap(err, "Failed to retrieve current server config")
	}

	if server.Config["core.https_address"] == "" {
		return fmt.Errorf("This LXD server is not available on the network")
	}

	// Check if already enabled
	currentCluster, etag, err := resource.server.GetCluster()
	if err != nil {
		return errors.Wrap(err, "Failed to retrieve current cluster config")
	}

	if currentCluster.Enabled {
		return fmt.Errorf("This LXD server is already clustered")
	}

	// Enable clustering.
	req := api.ClusterPut{}
	req.ServerName = name
	req.Enabled = true
	op, err := resource.server.UpdateCluster(req, etag)
	if err != nil {
		return errors.Wrap(err, "Failed to configure cluster")
	}

	err = op.Wait()
	if err != nil {
		return errors.Wrap(err, "Failed to configure cluster")
	}

	fmt.Println(i18n.G("Clustering enabled"))
	return nil
}
<commit_msg>lxd/cluster: Removes unused flagForce<commit_after>package main

import (
	"bufio"
	"fmt"
	"os"
	"sort"
	"strings"

	"github.com/pkg/errors"
	"github.com/spf13/cobra"
	yaml "gopkg.in/yaml.v2"

	"github.com/lxc/lxd/lxc/utils"
	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/api"
	cli "github.com/lxc/lxd/shared/cmd"
	"github.com/lxc/lxd/shared/i18n"
)

type cmdCluster struct {
	global *cmdGlobal
}

func (c *cmdCluster) Command() *cobra.Command {
	cmd := &cobra.Command{}
	cmd.Use = i18n.G("cluster")
	cmd.Short = i18n.G("Manage cluster members")
	cmd.Long = cli.FormatSection(i18n.G("Description"), i18n.G(
		`Manage cluster members`))

	// List
	clusterListCmd := cmdClusterList{global: c.global, cluster: c}
	cmd.AddCommand(clusterListCmd.Command())

	// Rename
	clusterRenameCmd := cmdClusterRename{global: c.global, cluster: c}
	cmd.AddCommand(clusterRenameCmd.Command())

	// Remove
	clusterRemoveCmd := cmdClusterRemove{global: c.global, cluster: c}
	cmd.AddCommand(clusterRemoveCmd.Command())

	// Show
	clusterShowCmd := cmdClusterShow{global: c.global, cluster: c}
	cmd.AddCommand(clusterShowCmd.Command())

	// Enable
	clusterEnableCmd := cmdClusterEnable{global: c.global, cluster: c}
	cmd.AddCommand(clusterEnableCmd.Command())

	return cmd
}

// List
type cmdClusterList struct {
	global  *cmdGlobal
	cluster *cmdCluster

	flagFormat string
}

func (c *cmdClusterList) Command() *cobra.Command {
	cmd := &cobra.Command{}
	cmd.Use = i18n.G("list [<remote>:]")
	cmd.Aliases = []string{"ls"}
	cmd.Short = i18n.G("List all the cluster members")
	cmd.Long = cli.FormatSection(i18n.G("Description"), i18n.G(
		`List all the cluster members`))
	cmd.Flags().StringVar(&c.flagFormat, "format", "table", i18n.G("Format (csv|json|table|yaml)")+"``")

	cmd.RunE = c.Run

	return cmd
}

func (c *cmdClusterList) Run(cmd *cobra.Command, args []string) error {
	// Sanity checks
	exit, err := c.global.CheckArgs(cmd, args, 0, 1)
	if exit {
		return err
	}

	// Parse remote
	remote := ""
	if len(args) == 1 {
		remote = args[0]
	}

	resources, err := c.global.ParseServers(remote)
	if err != nil {
		return err
	}

	resource := resources[0]

	// Check if clustered
	cluster, _, err := resource.server.GetCluster()
	if err != nil {
		return err
	}

	if !cluster.Enabled {
		return fmt.Errorf(i18n.G("LXD server isn't part of a cluster"))
	}

	// Get the cluster members
	members, err := resource.server.GetClusterMembers()
	if err != nil {
		return err
	}

	// Render the table
	data := [][]string{}
	for _, member := range members {
		database := "NO"
		if member.Database {
			database = "YES"
		}
		line := []string{member.ServerName, member.URL, database, strings.ToUpper(member.Status), member.Message, member.Architecture}
		data = append(data, line)
	}
	sort.Sort(byName(data))

	header := []string{
		i18n.G("NAME"),
		i18n.G("URL"),
		i18n.G("DATABASE"),
		i18n.G("STATE"),
		i18n.G("MESSAGE"),
		i18n.G("ARCHITECTURE"),
	}

	return utils.RenderTable(c.flagFormat, header, data, members)
}

// Show
type cmdClusterShow struct {
	global  *cmdGlobal
	cluster *cmdCluster
}

func (c *cmdClusterShow) Command() *cobra.Command {
	cmd := &cobra.Command{}
	cmd.Use = i18n.G("show [<remote>:]<member>")
	cmd.Short = i18n.G("Show details of a cluster member")
	cmd.Long = cli.FormatSection(i18n.G("Description"), i18n.G(
		`Show details of a cluster member`))

	cmd.RunE = c.Run

	return cmd
}

func (c *cmdClusterShow) Run(cmd *cobra.Command, args []string) error {
	// Sanity checks
	exit, err := c.global.CheckArgs(cmd, args, 1, 1)
	if exit {
		return err
	}

	// Parse remote
	resources, err := c.global.ParseServers(args[0])
	if err != nil {
		return err
	}

	resource := resources[0]

	// Get the member information
	member, _, err := resource.server.GetClusterMember(resource.name)
	if err != nil {
		return err
	}

	// Render as YAML
	data, err := yaml.Marshal(&member)
	if err != nil {
		return err
	}

	fmt.Printf("%s", data)
	return nil
}

// Rename
type cmdClusterRename struct {
	global  *cmdGlobal
	cluster *cmdCluster
}

func (c *cmdClusterRename) Command() *cobra.Command {
	cmd := &cobra.Command{}
	cmd.Use = i18n.G("rename [<remote>:]<member> <new-name>")
	cmd.Aliases = []string{"mv"}
	cmd.Short = i18n.G("Rename a cluster member")
	cmd.Long = cli.FormatSection(i18n.G("Description"), i18n.G(
		`Rename a cluster member`))

	cmd.RunE = c.Run

	return cmd
}

func (c *cmdClusterRename) Run(cmd *cobra.Command, args []string) error {
	// Sanity checks
	exit, err := c.global.CheckArgs(cmd, args, 2, 2)
	if exit {
		return err
	}

	// Parse remote
	resources, err := c.global.ParseServers(args[0])
	if err != nil {
		return err
	}

	resource := resources[0]

	// Perform the rename
	err = resource.server.RenameClusterMember(resource.name, api.ClusterMemberPost{ServerName: args[1]})
	if err != nil {
		return err
	}

	if !c.global.flagQuiet {
		fmt.Printf(i18n.G("Member %s renamed to %s")+"\n", resource.name, args[1])
	}

	return nil
}

// Remove
type cmdClusterRemove struct {
	global  *cmdGlobal
	cluster *cmdCluster

	flagForce          bool
	flagNonInteractive bool
}

func (c *cmdClusterRemove) Command() *cobra.Command {
	cmd := &cobra.Command{}
	cmd.Use = i18n.G("remove [<remote>:]<member>")
	cmd.Aliases = []string{"rm"}
	cmd.Short = i18n.G("Remove a member from the cluster")
	cmd.Long = cli.FormatSection(i18n.G("Description"), i18n.G(
		`Remove a member from the cluster`))

	cmd.RunE = c.Run
	cmd.Flags().BoolVarP(&c.flagForce, "force", "f", false, i18n.G("Force removing a member, even if degraded"))
	cmd.Flags().BoolVarP(&c.flagNonInteractive, "quiet", "q", false, i18n.G("Don't require user confirmation for using --force"))

	return cmd
}

func (c *cmdClusterRemove) promptConfirmation(name string) error {
	reader := bufio.NewReader(os.Stdin)
	fmt.Printf(i18n.G(`Forcefully removing a server from the cluster should only be done as a last
resort.

The removed server will not be functional after this action and will require a
full reset of LXD, losing any remaining instance, image or storage volume
that the server may have held.

When possible, a graceful removal should be preferred, this will require you to
move any affected instance, image or storage volume to another server prior to
the server being cleanly removed from the cluster.

The --force flag should only be used if the server has died, been reinstalled
or is otherwise never expected to come back up.

Are you really sure you want to force removing %s? (yes/no): `), name)
	input, _ := reader.ReadString('\n')
	input = strings.TrimSuffix(input, "\n")

	if !shared.StringInSlice(strings.ToLower(input), []string{i18n.G("yes")}) {
		return fmt.Errorf(i18n.G("User aborted delete operation"))
	}

	return nil
}

func (c *cmdClusterRemove) Run(cmd *cobra.Command, args []string) error {
	// Sanity checks
	exit, err := c.global.CheckArgs(cmd, args, 1, 1)
	if exit {
		return err
	}

	// Parse remote
	resources, err := c.global.ParseServers(args[0])
	if err != nil {
		return err
	}

	resource := resources[0]

	// Prompt for confiromation if --force is used.
	if !c.flagNonInteractive && c.flagForce {
		err := c.promptConfirmation(resource.name)
		if err != nil {
			return err
		}
	}

	// Delete the cluster member
	err = resource.server.DeleteClusterMember(resource.name, c.flagForce)
	if err != nil {
		return err
	}

	if !c.global.flagQuiet {
		fmt.Printf(i18n.G("Member %s removed")+"\n", resource.name)
	}

	return nil
}

// Enable
type cmdClusterEnable struct {
	global  *cmdGlobal
	cluster *cmdCluster
}

func (c *cmdClusterEnable) Command() *cobra.Command {
	cmd := &cobra.Command{}
	cmd.Use = i18n.G("enable [<remote>:] <name>")
	cmd.Short = i18n.G("Enable clustering on a single non-clustered LXD server")
	cmd.Long = cli.FormatSection(i18n.G("Description"), i18n.G(
		`Enable clustering on a single non-clustered LXD server

  This command turns a non-clustered LXD server into the first member of a new
  LXD cluster, which will have the given name.

  It's required that the LXD is already available on the network. You can check
  that by running 'lxc config get core.https_address', and possibly set a value
  for the address if not yet set.`))

	cmd.RunE = c.Run

	return cmd
}

func (c *cmdClusterEnable) Run(cmd *cobra.Command, args []string) error {
	// Sanity checks
	exit, err := c.global.CheckArgs(cmd, args, 1, 2)
	if exit {
		return err
	}

	// Parse remote
	remote := ""
	name := args[0]
	if len(args) == 2 {
		remote = args[0]
		name = args[1]
	}

	resources, err := c.global.ParseServers(remote)
	if err != nil {
		return err
	}

	resource := resources[0]

	// Check if the LXD server is available on the network.
	server, _, err := resource.server.GetServer()
	if err != nil {
		return errors.Wrap(err, "Failed to retrieve current server config")
	}

	if server.Config["core.https_address"] == "" {
		return fmt.Errorf("This LXD server is not available on the network")
	}

	// Check if already enabled
	currentCluster, etag, err := resource.server.GetCluster()
	if err != nil {
		return errors.Wrap(err, "Failed to retrieve current cluster config")
	}

	if currentCluster.Enabled {
		return fmt.Errorf("This LXD server is already clustered")
	}

	// Enable clustering.
	req := api.ClusterPut{}
	req.ServerName = name
	req.Enabled = true
	op, err := resource.server.UpdateCluster(req, etag)
	if err != nil {
		return errors.Wrap(err, "Failed to configure cluster")
	}

	err = op.Wait()
	if err != nil {
		return errors.Wrap(err, "Failed to configure cluster")
	}

	fmt.Println(i18n.G("Clustering enabled"))
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2020, OpenTelemetry 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 tests

import (
	"testing"

	"go.opentelemetry.io/collector/testbed/testbed"
	scenarios "go.opentelemetry.io/collector/testbed/tests"

	"github.com/open-telemetry/opentelemetry-collector-contrib/testbed/datareceivers"
	"github.com/open-telemetry/opentelemetry-collector-contrib/testbed/datasenders"
)

func TestStabilityMetricsOTLP(t *testing.T) {
	scenarios.Scenario10kItemsPerSecond(
		t,
		testbed.NewOTLPMetricDataSender(testbed.DefaultHost, testbed.GetAvailablePort(t)),
		testbed.NewOTLPDataReceiver(testbed.GetAvailablePort(t)),
		testbed.ResourceSpec{
			ExpectedMaxCPU:      50,
			ExpectedMaxRAM:      80,
			ResourceCheckPeriod: resourceCheckPeriod,
		},
		contribPerfResultsSummary,
		nil,
		nil,
	)
}

func TestStabilityMetricsOpenCensus(t *testing.T) {
	scenarios.Scenario10kItemsPerSecond(
		t,
		testbed.NewOCMetricDataSender(testbed.DefaultHost, testbed.GetAvailablePort(t)),
		testbed.NewOCDataReceiver(testbed.GetAvailablePort(t)),
		testbed.ResourceSpec{
			ExpectedMaxCPU:      70,
			ExpectedMaxRAM:      86,
			ResourceCheckPeriod: resourceCheckPeriod,
		},
		contribPerfResultsSummary,
		nil,
		nil,
	)
}

func TestStabilityMetricsCarbon(t *testing.T) {
	scenarios.Scenario10kItemsPerSecond(
		t,
		datasenders.NewCarbonDataSender(testbed.GetAvailablePort(t)),
		datareceivers.NewCarbonDataReceiver(testbed.GetAvailablePort(t)),
		testbed.ResourceSpec{
			ExpectedMaxCPU:      237,
			ExpectedMaxRAM:      120,
			ResourceCheckPeriod: resourceCheckPeriod,
		},
		contribPerfResultsSummary,
		nil,
		nil,
	)
}

func TestStabilityMetricsSignalFx(t *testing.T) {
	scenarios.Scenario10kItemsPerSecond(
		t,
		datasenders.NewSFxMetricDataSender(testbed.GetAvailablePort(t)),
		datareceivers.NewSFxMetricsDataReceiver(testbed.GetAvailablePort(t)),
		testbed.ResourceSpec{
			ExpectedMaxCPU:      120,
			ExpectedMaxRAM:      95,
			ResourceCheckPeriod: resourceCheckPeriod,
		},
		contribPerfResultsSummary,
		nil,
		nil,
	)
}
<commit_msg>Align CPU limit for TestStabilityMetricsOpenCensus with load tests (#1123)<commit_after>// Copyright 2020, OpenTelemetry 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 tests

import (
	"testing"

	"go.opentelemetry.io/collector/testbed/testbed"
	scenarios "go.opentelemetry.io/collector/testbed/tests"

	"github.com/open-telemetry/opentelemetry-collector-contrib/testbed/datareceivers"
	"github.com/open-telemetry/opentelemetry-collector-contrib/testbed/datasenders"
)

func TestStabilityMetricsOTLP(t *testing.T) {
	scenarios.Scenario10kItemsPerSecond(
		t,
		testbed.NewOTLPMetricDataSender(testbed.DefaultHost, testbed.GetAvailablePort(t)),
		testbed.NewOTLPDataReceiver(testbed.GetAvailablePort(t)),
		testbed.ResourceSpec{
			ExpectedMaxCPU:      50,
			ExpectedMaxRAM:      80,
			ResourceCheckPeriod: resourceCheckPeriod,
		},
		contribPerfResultsSummary,
		nil,
		nil,
	)
}

func TestStabilityMetricsOpenCensus(t *testing.T) {
	scenarios.Scenario10kItemsPerSecond(
		t,
		testbed.NewOCMetricDataSender(testbed.DefaultHost, testbed.GetAvailablePort(t)),
		testbed.NewOCDataReceiver(testbed.GetAvailablePort(t)),
		testbed.ResourceSpec{
			ExpectedMaxCPU:      85,
			ExpectedMaxRAM:      86,
			ResourceCheckPeriod: resourceCheckPeriod,
		},
		contribPerfResultsSummary,
		nil,
		nil,
	)
}

func TestStabilityMetricsCarbon(t *testing.T) {
	scenarios.Scenario10kItemsPerSecond(
		t,
		datasenders.NewCarbonDataSender(testbed.GetAvailablePort(t)),
		datareceivers.NewCarbonDataReceiver(testbed.GetAvailablePort(t)),
		testbed.ResourceSpec{
			ExpectedMaxCPU:      237,
			ExpectedMaxRAM:      120,
			ResourceCheckPeriod: resourceCheckPeriod,
		},
		contribPerfResultsSummary,
		nil,
		nil,
	)
}

func TestStabilityMetricsSignalFx(t *testing.T) {
	scenarios.Scenario10kItemsPerSecond(
		t,
		datasenders.NewSFxMetricDataSender(testbed.GetAvailablePort(t)),
		datareceivers.NewSFxMetricsDataReceiver(testbed.GetAvailablePort(t)),
		testbed.ResourceSpec{
			ExpectedMaxCPU:      120,
			ExpectedMaxRAM:      95,
			ResourceCheckPeriod: resourceCheckPeriod,
		},
		contribPerfResultsSummary,
		nil,
		nil,
	)
}
<|endoftext|>


<commit_before>// This package provides a default mysql init.
// Configuration is loaded from config file under 'mysql' section
//
package defaultmysql

import (
	"github.com/byrnedo/apibase/config"
	"github.com/byrnedo/apibase/db/mysql"
	. "github.com/byrnedo/apibase/logger"
	"github.com/byrnedo/typesafe-config/parse"
	mysqlReal "github.com/go-sql-driver/mysql"
)

func init() {

	mysql.Init(func(c *mysql.Config) {
		parse.Populate(c, config.Conf, "mysql")

		c2, err := mysqlReal.ParseDSN(c.ConnectString)
		if err == nil {
			Info.Printf("Attempting to connect to %s@%s\n", c2.User, c2.Addr)
		}
	})
}
<commit_msg>Logs failed dsn parse<commit_after>// This package provides a default mysql init.
// Configuration is loaded from config file under 'mysql' section
//
package defaultmysql

import (
	"github.com/byrnedo/apibase/config"
	"github.com/byrnedo/apibase/db/mysql"
	. "github.com/byrnedo/apibase/logger"
	"github.com/byrnedo/typesafe-config/parse"
	mysqlReal "github.com/go-sql-driver/mysql"
)

func init() {

	mysql.Init(func(c *mysql.Config) {
		parse.Populate(c, config.Conf, "mysql")

		c2, err := mysqlReal.ParseDSN(c.ConnectString)
		if err == nil {
			Info.Printf("Attempting to connect to %s@%s\n", c2.User, c2.Addr)
		} else {
			Error.Println("Error parsing DSN:", c.ConnectString)
		}
	})
}
<|endoftext|>


<commit_before>package verbo

import (
	"testing"
	//"strings"
)

func equal(t *testing.T, src, dest string) {
	if src != dest {
		t.Errorf("Wrong result: %s", src)
	}
}

func TestIsBlank(t *testing.T) {
  if ! IsBlank(" ") {
    t.Errorf("Wrong result: %s", "should not go here")
  }
}

func TestCamelize(t *testing.T) {

	equal(t, Camelize("the_camelize_string_method", false), "theCamelizeStringMethod")
	equal(t, Camelize("webkit-transform", false), "webkitTransform")
	equal(t, Camelize("-the-camelize-string-method", false), "TheCamelizeStringMethod")
	equal(t, Camelize("_the_camelize_string_method", false), "TheCamelizeStringMethod")
	equal(t, Camelize("The-camelize-string-method", false), "TheCamelizeStringMethod")
	equal(t, Camelize("the camelize string method", false), "theCamelizeStringMethod")
	equal(t, Camelize(" the camelize  string method", false), "theCamelizeStringMethod")
	equal(t, Camelize("the camelize   string method", false), "theCamelizeStringMethod")
	equal(t, Camelize(" with   spaces", false), "withSpaces")
	equal(t, Camelize("_som eWeird---name-", false), "SomEWeirdName")
}

func TestCapitalize(t *testing.T) {

	equal(t, Capitalize("fabio", false), "Fabio")
	equal(t, Capitalize("fabio", false), "Fabio")
	equal(t, Capitalize("FOO", false), "FOO")
	equal(t, Capitalize("FOO", false), "FOO")
	equal(t, Capitalize("foO", false), "FoO")
	equal(t, Capitalize("FOO", true), "Foo")
	equal(t, Capitalize("foO", true), "Foo")
	equal(t, Capitalize("f", false), "F")
	equal(t, Capitalize("f", true), "F")
	equal(t, Capitalize("f", false), "F")
}

func TestClassify(t *testing.T) {

	equal(t, Classify("some_class_name"), "SomeClassName")
	equal(t, Classify("my wonderfull class_name"), "MyWonderfullClassName")
	equal(t, Classify("my wonderfull.class.name"), "MyWonderfullClassName")
	equal(t, Classify("myLittleCamel"), "MyLittleCamel")
	equal(t, Classify("myLittleCamel.class.name"), "MyLittleCamelClassName")
}

func TestClean(t *testing.T) {
	equal(t, Clean(" foo    bar   "), "foo bar")
}

func TestClearDiacritics(t *testing.T) {

	from := "ąàáäâãåæăćčĉęèéëêĝĥìíïîĵłľńňòóöőôõðøśșşšŝťțţŭùúüűûñÿýçżźž"
	to := "aaaaaaaaaccceeeeeghiiiijllnnoooooooossssstttuuuuuunyyczzz"

	equal(t, CleanDiacritics(from), to)
	equal(t, CleanDiacritics(strings.ToUpper(from)), strings.ToUpper(to))

	equal(t, CleanDiacritics("ä"), "a")
	equal(t, CleanDiacritics("Ä Ø"), "A O")
	equal(t, CleanDiacritics("1 foo ääkkönen"), "1 foo aakkonen")
	equal(t, CleanDiacritics("Äöö ÖÖ"), "Aoo OO")
	equal(t, CleanDiacritics(" ä "), " a ")
}

func TestDasherize(t *testing.T) {
	equal(t, Dasherize("the_dasherize_string_method"), "the-dasherize-string-method")
  equal(t, Dasherize("TheDasherizeStringMethod"), "-the-dasherize-string-method")
  equal(t, Dasherize("thisIsATest"), "this-is-a-test")
  equal(t, Dasherize("this Is A Test"), "this-is-a-test")
  equal(t, Dasherize("thisIsATest123"), "this-is-a-test123")
  equal(t, Dasherize("123thisIsATest"), "123this-is-a-test")
  equal(t, Dasherize("the dasherize string method"), "the-dasherize-string-method")
  equal(t, Dasherize("the  dasherize string method  "), "the-dasherize-string-method")
  equal(t, Dasherize("téléphone"), "téléphone")
  equal(t, Dasherize("foo$bar"), "foo$bar")
  equal(t, Dasherize("input with a-dash"), "input-with-a-dash")
}

func TestDecapitalize(t *testing.T) {
	equal(t, Decapitalize("Fabio"), "fabio")
	equal(t, Decapitalize("FOO"), "fOO")
}

func TestHumanize(t *testing.T) {
	equal(t, Humanize("the_humanize_string_method"), "The humanize string method")
	equal(t, Humanize("ThehumanizeStringMethod"), "Thehumanize string method")
	equal(t, Humanize("-ThehumanizeStringMethod"), "Thehumanize string method")
	equal(t, Humanize("the humanize string method"), "The humanize string method")
	equal(t, Humanize("the humanize_id string method_id"), "The humanize id string method")
	equal(t, Humanize("the  humanize string method  "), "The humanize string method")
	equal(t, Humanize("   capitalize dash-CamelCase_underscore trim  "), "Capitalize dash camel case underscore trim")
}

func TestPred(t *testing.T) {
	equal(t, Pred("b"), "a")
	equal(t, Pred("B"), "A")
	equal(t, Pred(","), "+")
}

func TestPrune(t *testing.T) {
	equal(t, Prune("Hello, cruel world", 6, " read more"), "Hello read more");
  equal(t, Prune("Hello, world", 5, "read a lot more"), "Hello, world");
  equal(t, Prune("Hello, world", 5, ""), "Hello...");
  equal(t, Prune("Hello, world", 8, ""), "Hello...");
  equal(t, Prune("Hello, cruel world", 15, ""), "Hello, cruel...");
  equal(t, Prune("Hello world", 22, ""), "Hello world");
  equal(t, Prune("Привет, жестокий мир", 6, " read more"), "Привет read more");
  equal(t, Prune("Привет, мир", 6, "read a lot more"), "Привет, мир");
  equal(t, Prune("Привет, мир", 6, ""), "Привет...");
  equal(t, Prune("Привет, мир", 8, ""), "Привет...");
  equal(t, Prune("Привет, жестокий мир", 16, ""), "Привет, жестокий...");
  equal(t, Prune("Привет, мир", 22, ""), "Привет, мир");
  equal(t, Prune("alksjd!!!!!!....", 100, ""), "alksjd!!!!!!....");
}

func TestRepeat(t *testing.T) {
	equal(t, Repeat("foo", 0, ""), "")
  equal(t, Repeat("foo", 3, ""), "foofoofoo")
}

func TestSlugify(t *testing.T) {
	equal(t, Slugify("Jack & Jill like numbers 1,2,3 and 4 and silly characters ?%.$!/"), "jack-jill-like-numbers-1-2-3-and-4-and-silly-characters")
  equal(t, Slugify("Un éléphant à l\"orée du bois"), "un-elephant-a-l-oree-du-bois")
  equal(t, Slugify("I know latin characters: á í ó ú ç ã õ ñ ü ă ș ț"), "i-know-latin-characters-a-i-o-u-c-a-o-n-u-a-s-t")
  equal(t, Slugify("I am a word too, even though I am but a single letter: i!"), "i-am-a-word-too-even-though-i-am-but-a-single-letter-i")
  equal(t, Slugify("Some asian 天地人 characters"), "some-asian-characters")
  equal(t, Slugify("SOME Capital Letters"), "some-capital-letters")
}

func TestSwapCase(t *testing.T) {
	equal(t, SwapCase("AaBbCcDdEe"), "aAbBcCdDeE")
  equal(t, SwapCase("Hello World"), "hELLO wORLD")
}

func TestUnderscored(t *testing.T) {
	equal(t, Underscored("the-underscored-string-method"), "the_underscored_string_method")
	equal(t, Underscored("theUnderscoredStringMethod"), "the_underscored_string_method")
	equal(t, Underscored("TheUnderscoredStringMethod"), "the_underscored_string_method")
	equal(t, Underscored(" the underscored  string method"), "the_underscored_string_method")
}
<commit_msg>Fixing testcase imports<commit_after>package verbo

import (
	"testing"
	"strings"
)

func equal(t *testing.T, src, dest string) {
	if src != dest {
		t.Errorf("Wrong result: %s", src)
	}
}

func TestIsBlank(t *testing.T) {
  if ! IsBlank(" ") {
    t.Errorf("Wrong result: %s", "should not go here")
  }
}

func TestCamelize(t *testing.T) {

	equal(t, Camelize("the_camelize_string_method", false), "theCamelizeStringMethod")
	equal(t, Camelize("webkit-transform", false), "webkitTransform")
	equal(t, Camelize("-the-camelize-string-method", false), "TheCamelizeStringMethod")
	equal(t, Camelize("_the_camelize_string_method", false), "TheCamelizeStringMethod")
	equal(t, Camelize("The-camelize-string-method", false), "TheCamelizeStringMethod")
	equal(t, Camelize("the camelize string method", false), "theCamelizeStringMethod")
	equal(t, Camelize(" the camelize  string method", false), "theCamelizeStringMethod")
	equal(t, Camelize("the camelize   string method", false), "theCamelizeStringMethod")
	equal(t, Camelize(" with   spaces", false), "withSpaces")
	equal(t, Camelize("_som eWeird---name-", false), "SomEWeirdName")
}

func TestCapitalize(t *testing.T) {

	equal(t, Capitalize("fabio", false), "Fabio")
	equal(t, Capitalize("fabio", false), "Fabio")
	equal(t, Capitalize("FOO", false), "FOO")
	equal(t, Capitalize("FOO", false), "FOO")
	equal(t, Capitalize("foO", false), "FoO")
	equal(t, Capitalize("FOO", true), "Foo")
	equal(t, Capitalize("foO", true), "Foo")
	equal(t, Capitalize("f", false), "F")
	equal(t, Capitalize("f", true), "F")
	equal(t, Capitalize("f", false), "F")
}

func TestClassify(t *testing.T) {

	equal(t, Classify("some_class_name"), "SomeClassName")
	equal(t, Classify("my wonderfull class_name"), "MyWonderfullClassName")
	equal(t, Classify("my wonderfull.class.name"), "MyWonderfullClassName")
	equal(t, Classify("myLittleCamel"), "MyLittleCamel")
	equal(t, Classify("myLittleCamel.class.name"), "MyLittleCamelClassName")
}

func TestClean(t *testing.T) {
	equal(t, Clean(" foo    bar   "), "foo bar")
}

func TestClearDiacritics(t *testing.T) {

	from := "ąàáäâãåæăćčĉęèéëêĝĥìíïîĵłľńňòóöőôõðøśșşšŝťțţŭùúüűûñÿýçżźž"
	to := "aaaaaaaaaccceeeeeghiiiijllnnoooooooossssstttuuuuuunyyczzz"

	equal(t, CleanDiacritics(from), to)
	equal(t, CleanDiacritics(strings.ToUpper(from)), strings.ToUpper(to))

	equal(t, CleanDiacritics("ä"), "a")
	equal(t, CleanDiacritics("Ä Ø"), "A O")
	equal(t, CleanDiacritics("1 foo ääkkönen"), "1 foo aakkonen")
	equal(t, CleanDiacritics("Äöö ÖÖ"), "Aoo OO")
	equal(t, CleanDiacritics(" ä "), " a ")
}

func TestDasherize(t *testing.T) {
	equal(t, Dasherize("the_dasherize_string_method"), "the-dasherize-string-method")
  equal(t, Dasherize("TheDasherizeStringMethod"), "-the-dasherize-string-method")
  equal(t, Dasherize("thisIsATest"), "this-is-a-test")
  equal(t, Dasherize("this Is A Test"), "this-is-a-test")
  equal(t, Dasherize("thisIsATest123"), "this-is-a-test123")
  equal(t, Dasherize("123thisIsATest"), "123this-is-a-test")
  equal(t, Dasherize("the dasherize string method"), "the-dasherize-string-method")
  equal(t, Dasherize("the  dasherize string method  "), "the-dasherize-string-method")
  equal(t, Dasherize("téléphone"), "téléphone")
  equal(t, Dasherize("foo$bar"), "foo$bar")
  equal(t, Dasherize("input with a-dash"), "input-with-a-dash")
}

func TestDecapitalize(t *testing.T) {
	equal(t, Decapitalize("Fabio"), "fabio")
	equal(t, Decapitalize("FOO"), "fOO")
}

func TestHumanize(t *testing.T) {
	equal(t, Humanize("the_humanize_string_method"), "The humanize string method")
	equal(t, Humanize("ThehumanizeStringMethod"), "Thehumanize string method")
	equal(t, Humanize("-ThehumanizeStringMethod"), "Thehumanize string method")
	equal(t, Humanize("the humanize string method"), "The humanize string method")
	equal(t, Humanize("the humanize_id string method_id"), "The humanize id string method")
	equal(t, Humanize("the  humanize string method  "), "The humanize string method")
	equal(t, Humanize("   capitalize dash-CamelCase_underscore trim  "), "Capitalize dash camel case underscore trim")
}

func TestPred(t *testing.T) {
	equal(t, Pred("b"), "a")
	equal(t, Pred("B"), "A")
	equal(t, Pred(","), "+")
}

func TestPrune(t *testing.T) {
	equal(t, Prune("Hello, cruel world", 6, " read more"), "Hello read more");
  equal(t, Prune("Hello, world", 5, "read a lot more"), "Hello, world");
  equal(t, Prune("Hello, world", 5, ""), "Hello...");
  equal(t, Prune("Hello, world", 8, ""), "Hello...");
  equal(t, Prune("Hello, cruel world", 15, ""), "Hello, cruel...");
  equal(t, Prune("Hello world", 22, ""), "Hello world");
  equal(t, Prune("Привет, жестокий мир", 6, " read more"), "Привет read more");
  equal(t, Prune("Привет, мир", 6, "read a lot more"), "Привет, мир");
  equal(t, Prune("Привет, мир", 6, ""), "Привет...");
  equal(t, Prune("Привет, мир", 8, ""), "Привет...");
  equal(t, Prune("Привет, жестокий мир", 16, ""), "Привет, жестокий...");
  equal(t, Prune("Привет, мир", 22, ""), "Привет, мир");
  equal(t, Prune("alksjd!!!!!!....", 100, ""), "alksjd!!!!!!....");
}

func TestRepeat(t *testing.T) {
	equal(t, Repeat("foo", 0, ""), "")
  equal(t, Repeat("foo", 3, ""), "foofoofoo")
}

func TestSlugify(t *testing.T) {
	equal(t, Slugify("Jack & Jill like numbers 1,2,3 and 4 and silly characters ?%.$!/"), "jack-jill-like-numbers-1-2-3-and-4-and-silly-characters")
  equal(t, Slugify("Un éléphant à l\"orée du bois"), "un-elephant-a-l-oree-du-bois")
  equal(t, Slugify("I know latin characters: á í ó ú ç ã õ ñ ü ă ș ț"), "i-know-latin-characters-a-i-o-u-c-a-o-n-u-a-s-t")
  equal(t, Slugify("I am a word too, even though I am but a single letter: i!"), "i-am-a-word-too-even-though-i-am-but-a-single-letter-i")
  equal(t, Slugify("Some asian 天地人 characters"), "some-asian-characters")
  equal(t, Slugify("SOME Capital Letters"), "some-capital-letters")
}

func TestSwapCase(t *testing.T) {
	equal(t, SwapCase("AaBbCcDdEe"), "aAbBcCdDeE")
  equal(t, SwapCase("Hello World"), "hELLO wORLD")
}

func TestUnderscored(t *testing.T) {
	equal(t, Underscored("the-underscored-string-method"), "the_underscored_string_method")
	equal(t, Underscored("theUnderscoredStringMethod"), "the_underscored_string_method")
	equal(t, Underscored("TheUnderscoredStringMethod"), "the_underscored_string_method")
	equal(t, Underscored(" the underscored  string method"), "the_underscored_string_method")
}
<|endoftext|>


<commit_before>// Copyright 2013-3014 Adam Presley. All rights reserved
// Use of this source code is governed by the MIT license
// that can be found in the LICENSE file.
package main

import (
	"log"
	"os"
	"runtime"

	"github.com/adampresley/GoHttpService"
	"github.com/adampresley/sigint"
	"github.com/mailslurper/mailslurper/services/listener"
	"github.com/mailslurper/mailslurper/services/middleware"

	"github.com/mailslurper/libmailslurper/configuration"
	"github.com/mailslurper/libmailslurper/receiver"
	"github.com/mailslurper/libmailslurper/server"
	"github.com/mailslurper/libmailslurper/storage"
	"github.com/mailslurper/mailslurper/global"
	serviceListener "github.com/mailslurper/mailslurperservice/listener"
)

func main() {
	var err error
	runtime.GOMAXPROCS(runtime.NumCPU())

	log.Printf("MailSlurper: INFO - Starting MailSlurper Server v%s\n", global.SERVER_VERSION)
	/*
	 * Prepare SIGINT handler (CTRL+C)
	 */
	sigint.ListenForSIGINT(func() {
		log.Println("MailSlurper: INFO - Shutting down via SIGINT.")
		os.Exit(0)
	})

	/*
	 * Load configuration
	 */
	config, err := configuration.LoadConfigurationFromFile(configuration.CONFIGURATION_FILE_NAME)
	if err != nil {
		log.Println("MailSlurper: ERROR - There was an error reading your configuration file:", err)
		os.Exit(0)
	}

	/*
	 * Setup global database connection handle
	 */
	databaseConnection := config.GetDatabaseConfiguration()

	if err = storage.ConnectToStorage(databaseConnection); err != nil {
		log.Println("MailSlurper: ERROR - There was an error connecting to your data storage:", err)
		os.Exit(0)
	}

	defer storage.DisconnectFromStorage()

	/*
	 * Setup the server pool
	 */
	pool := server.NewServerPool(config.MaxWorkers)

	/*
	 * Setup the SMTP listener
	 */
	smtpServer, err := server.SetupSmtpServerListener(config.GetFullSmtpBindingAddress())
	if err != nil {
		log.Println("MailSlurper: ERROR - There was a problem starting the SMTP listener:", err)
		os.Exit(0)
	}

	defer server.CloseSmtpServerListener(smtpServer)

	/*
	 * Setup receivers (subscribers) to handle new mail items.
	 */
	receivers := []receiver.IMailItemReceiver{
		receiver.DatabaseReceiver{},
	}

	/*
	 * Start the SMTP dispatcher
	 */
	go server.Dispatcher(pool, smtpServer, receivers)

	/*
	 * Pre-load layout information
	 */
	layout, err := GoHttpService.NewLayout("./www/", []string{
		"assets/mailslurper/layouts/mainLayout",
	})

	if err != nil {
		log.Printf("MailSlurper: ERROR - Error setting up layout: %s\n", err.Error())
		os.Exit(1)
	}

	/*
	 * Application context gets passed around all over the place
	 */
	appContext := &middleware.AppContext{
		Config: config,
		Layout: layout,
	}

	httpListener := listener.NewHTTPListenerService(config.WWWAddress, config.WWWPort, appContext)

	setupMiddleware(httpListener, appContext)
	setupRoutes(httpListener, appContext)

	/*
	 * Setup the app HTTP listener
	 */
	go func() {
		if err := httpListener.StartHTTPListener(); err != nil {
			log.Printf("MailSlurper: ERROR - Error starting HTTP listener: %s\n", err.Error())
			os.Exit(1)
		}
	}()

	/*
	 * Start the services server
	 */
	err = serviceListener.StartHttpListener(serviceListener.NewHttpListener(config.ServiceAddress, config.ServicePort))

	if err != nil {
		log.Printf("MailSlurper: ERROR - Error starting MailSlurper services server: %s\n", err.Error())
	}
}
<commit_msg>Changed call to renamed function<commit_after>// Copyright 2013-3014 Adam Presley. All rights reserved
// Use of this source code is governed by the MIT license
// that can be found in the LICENSE file.
package main

import (
	"log"
	"os"
	"runtime"

	"github.com/adampresley/GoHttpService"
	"github.com/adampresley/sigint"
	"github.com/mailslurper/mailslurper/services/listener"
	"github.com/mailslurper/mailslurper/services/middleware"

	"github.com/mailslurper/libmailslurper/configuration"
	"github.com/mailslurper/libmailslurper/receiver"
	"github.com/mailslurper/libmailslurper/server"
	"github.com/mailslurper/libmailslurper/storage"
	"github.com/mailslurper/mailslurper/global"
	serviceListener "github.com/mailslurper/mailslurperservice/listener"
)

func main() {
	var err error
	runtime.GOMAXPROCS(runtime.NumCPU())

	log.Printf("MailSlurper: INFO - Starting MailSlurper Server v%s\n", global.SERVER_VERSION)
	/*
	 * Prepare SIGINT handler (CTRL+C)
	 */
	sigint.ListenForSIGINT(func() {
		log.Println("MailSlurper: INFO - Shutting down via SIGINT.")
		os.Exit(0)
	})

	/*
	 * Load configuration
	 */
	config, err := configuration.LoadConfigurationFromFile(configuration.CONFIGURATION_FILE_NAME)
	if err != nil {
		log.Println("MailSlurper: ERROR - There was an error reading your configuration file:", err)
		os.Exit(0)
	}

	/*
	 * Setup global database connection handle
	 */
	databaseConnection := config.GetDatabaseConfiguration()

	if err = storage.ConnectToStorage(databaseConnection); err != nil {
		log.Println("MailSlurper: ERROR - There was an error connecting to your data storage:", err)
		os.Exit(0)
	}

	defer storage.DisconnectFromStorage()

	/*
	 * Setup the server pool
	 */
	pool := server.NewServerPool(config.MaxWorkers)

	/*
	 * Setup the SMTP listener
	 */
	smtpServer, err := server.SetupSmtpServerListener(config.GetFullSmtpBindingAddress())
	if err != nil {
		log.Println("MailSlurper: ERROR - There was a problem starting the SMTP listener:", err)
		os.Exit(0)
	}

	defer server.CloseSmtpServerListener(smtpServer)

	/*
	 * Setup receivers (subscribers) to handle new mail items.
	 */
	receivers := []receiver.IMailItemReceiver{
		receiver.DatabaseReceiver{},
	}

	/*
	 * Start the SMTP dispatcher
	 */
	go server.Dispatch(pool, smtpServer, receivers)

	/*
	 * Pre-load layout information
	 */
	layout, err := GoHttpService.NewLayout("./www/", []string{
		"assets/mailslurper/layouts/mainLayout",
	})

	if err != nil {
		log.Printf("MailSlurper: ERROR - Error setting up layout: %s\n", err.Error())
		os.Exit(1)
	}

	/*
	 * Application context gets passed around all over the place
	 */
	appContext := &middleware.AppContext{
		Config: config,
		Layout: layout,
	}

	httpListener := listener.NewHTTPListenerService(config.WWWAddress, config.WWWPort, appContext)

	setupMiddleware(httpListener, appContext)
	setupRoutes(httpListener, appContext)

	/*
	 * Setup the app HTTP listener
	 */
	go func() {
		if err := httpListener.StartHTTPListener(); err != nil {
			log.Printf("MailSlurper: ERROR - Error starting HTTP listener: %s\n", err.Error())
			os.Exit(1)
		}
	}()

	/*
	 * Start the services server
	 */
	err = serviceListener.StartHttpListener(serviceListener.NewHttpListener(config.ServiceAddress, config.ServicePort))

	if err != nil {
		log.Printf("MailSlurper: ERROR - Error starting MailSlurper services server: %s\n", err.Error())
	}
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/fvbock/tris/server"
	"runtime"
	"time"
)

var (
	config *tris.ServerConfig
)

func init() {
	runtime.GOMAXPROCS(4)
	config = &tris.ServerConfig{
		Protocol:          "tcp",
		Host:              "127.0.0.1",
		Port:              6000,
		DataDir:           "/home/morpheus/tris_data",
		StorageFilePrefix: "trie_",
	}
}

func main() {
	server, err := tris.New(config)
	if err != nil {
		server.Log.Printf("Could not initialize server: %v\n", err)
	}
	server.Start()

	server.Log.Println("Wait for 10 sec")
	time.Sleep(1000 * time.Second)
	server.Stop()
	server.Log.Println("Done")
}
<commit_msg>correct log msg<commit_after>package main

import (
	"github.com/fvbock/tris/server"
	"runtime"
	"time"
)

var (
	config *tris.ServerConfig
)

func init() {
	runtime.GOMAXPROCS(4)
	config = &tris.ServerConfig{
		Protocol:          "tcp",
		Host:              "127.0.0.1",
		Port:              6000,
		DataDir:           "/home/morpheus/tris_data",
		StorageFilePrefix: "trie_",
	}
}

func main() {
	server, err := tris.New(config)
	if err != nil {
		server.Log.Printf("Could not initialize server: %v\n", err)
	}
	server.Start()

	server.Log.Println("Wait for 10 min")
	time.Sleep(1000 * time.Second)
	server.Stop()
	server.Log.Println("Done")
}
<|endoftext|>


<commit_before>package opts // import "github.com/docker/docker/opts"

import (
	"fmt"
	"strings"
	"testing"
)

func TestParseHost(t *testing.T) {
	invalid := []string{
		"something with spaces",
		"://",
		"unknown://",
		"tcp://:port",
		"tcp://invalid:port",
		"tcp://:5555/",
		"tcp://:5555/p",
		"tcp://0.0.0.0:5555/",
		"tcp://0.0.0.0:5555/p",
		"tcp://[::1]:/",
		"tcp://[::1]:5555/",
		"tcp://[::1]:5555/p",
		" tcp://:5555/path ",
	}

	valid := map[string]string{
		"":                         DefaultHost,
		" ":                        DefaultHost,
		"  ":                       DefaultHost,
		"fd://":                    "fd://",
		"fd://something":           "fd://something",
		"tcp://host:":              fmt.Sprintf("tcp://host:%d", DefaultHTTPPort),
		"tcp://":                   DefaultTCPHost,
		"tcp://:2375":              fmt.Sprintf("tcp://%s:2375", DefaultHTTPHost),
		"tcp://:2376":              fmt.Sprintf("tcp://%s:2376", DefaultHTTPHost),
		"tcp://0.0.0.0:8080":       "tcp://0.0.0.0:8080",
		"tcp://192.168.0.0:12000":  "tcp://192.168.0.0:12000",
		"tcp://192.168:8080":       "tcp://192.168:8080",
		"tcp://0.0.0.0:1234567890": "tcp://0.0.0.0:1234567890", // yeah it's valid :P
		"tcp://docker.com:2375":    "tcp://docker.com:2375",
		"unix://":                  "unix://" + DefaultUnixSocket,
		"unix://path/to/socket":    "unix://path/to/socket",
		"npipe://":                 "npipe://" + DefaultNamedPipe,
		"npipe:////./pipe/foo":     "npipe:////./pipe/foo",
	}

	for _, value := range invalid {
		if _, err := ParseHost(false, false, value); err == nil {
			t.Errorf("Expected an error for %v, got [nil]", value)
		}
	}

	for value, expected := range valid {
		if actual, err := ParseHost(false, false, value); err != nil || actual != expected {
			t.Errorf("Expected for %v [%v], got [%v, %v]", value, expected, actual, err)
		}
	}
}

func TestParseDockerDaemonHost(t *testing.T) {
	invalids := map[string]string{
		"tcp:a.b.c.d":                   `parse "tcp://tcp:a.b.c.d": invalid port ":a.b.c.d" after host`,
		"tcp:a.b.c.d/path":              `parse "tcp://tcp:a.b.c.d/path": invalid port ":a.b.c.d" after host`,
		"udp://127.0.0.1":               "Invalid bind address format: udp://127.0.0.1",
		"udp://127.0.0.1:2375":          "Invalid bind address format: udp://127.0.0.1:2375",
		"tcp://unix:///run/docker.sock": "Invalid proto, expected tcp: unix:///run/docker.sock",
		" tcp://:7777/path ":            "Invalid bind address format:  tcp://:7777/path ",
		"":                              "Invalid bind address format: ",
		":5555/path":                    "invalid bind address (:5555/path): should not contain a path element",
		"0.0.0.1:5555/path":             "invalid bind address (0.0.0.1:5555/path): should not contain a path element",
		"[::1]:5555/path":               "invalid bind address ([::1]:5555/path): should not contain a path element",
		"[0:0:0:0:0:0:0:1]:5555/path":   "invalid bind address ([0:0:0:0:0:0:0:1]:5555/path): should not contain a path element",
		"tcp://:5555/path":              "invalid bind address (:5555/path): should not contain a path element",
		"localhost:5555/path":           "invalid bind address (localhost:5555/path): should not contain a path element",
	}
	valids := map[string]string{
		"0.0.0.1:":                "tcp://0.0.0.1:2375",
		"0.0.0.1:5555":            "tcp://0.0.0.1:5555",
		"[::1]:":                  "tcp://[::1]:2375",
		"[0:0:0:0:0:0:0:1]:":      "tcp://[0:0:0:0:0:0:0:1]:2375",
		":6666":                   fmt.Sprintf("tcp://%s:6666", DefaultHTTPHost),
		"tcp://":                  DefaultTCPHost,
		"tcp://:7777":             fmt.Sprintf("tcp://%s:7777", DefaultHTTPHost),
		"unix:///run/docker.sock": "unix:///run/docker.sock",
		"unix://":                 "unix://" + DefaultUnixSocket,
		"fd://":                   "fd://",
		"fd://something":          "fd://something",
		"localhost:":              "tcp://localhost:2375",
		"localhost:5555":          "tcp://localhost:5555",
	}
	for invalidAddr, expectedError := range invalids {
		if addr, err := parseDaemonHost(invalidAddr); err == nil || err.Error() != expectedError {
			t.Errorf("tcp %v address expected error %q return, got %q and addr %v", invalidAddr, expectedError, err, addr)
		}
	}
	for validAddr, expectedAddr := range valids {
		if addr, err := parseDaemonHost(validAddr); err != nil || addr != expectedAddr {
			t.Errorf("%v -> expected %v, got (%v) addr (%v)", validAddr, expectedAddr, err, addr)
		}
	}
}

func TestParseTCP(t *testing.T) {
	var (
		defaultHTTPHost = "tcp://127.0.0.1:2376"
	)
	invalids := map[string]string{
		"tcp:a.b.c.d":                 `parse "tcp://tcp:a.b.c.d": invalid port ":a.b.c.d" after host`,
		"tcp:a.b.c.d/path":            `parse "tcp://tcp:a.b.c.d/path": invalid port ":a.b.c.d" after host`,
		"udp://127.0.0.1":             "Invalid proto, expected tcp: udp://127.0.0.1",
		"udp://127.0.0.1:2375":        "Invalid proto, expected tcp: udp://127.0.0.1:2375",
		":5555/path":                  "invalid bind address (:5555/path): should not contain a path element",
		"0.0.0.1:5555/path":           "invalid bind address (0.0.0.1:5555/path): should not contain a path element",
		"[::1]:5555/path":             "invalid bind address ([::1]:5555/path): should not contain a path element",
		"[0:0:0:0:0:0:0:1]:5555/path": "invalid bind address ([0:0:0:0:0:0:0:1]:5555/path): should not contain a path element",
		"tcp://:5555/path":            "invalid bind address (tcp://:5555/path): should not contain a path element",
		"localhost:5555/path":         "invalid bind address (localhost:5555/path): should not contain a path element",
	}
	valids := map[string]string{
		"":                       defaultHTTPHost,
		"tcp://":                 defaultHTTPHost,
		"0.0.0.1:":               "tcp://0.0.0.1:2376",
		"0.0.0.1:5555":           "tcp://0.0.0.1:5555",
		":6666":                  "tcp://127.0.0.1:6666",
		"tcp://:7777":            "tcp://127.0.0.1:7777",
		"[::1]:":                 "tcp://[::1]:2376",
		"[::1]:5555":             "tcp://[::1]:5555",
		"[0:0:0:0:0:0:0:1]:":     "tcp://[0:0:0:0:0:0:0:1]:2376",
		"[0:0:0:0:0:0:0:1]:5555": "tcp://[0:0:0:0:0:0:0:1]:5555",
		"localhost:":             "tcp://localhost:2376",
		"localhost:5555":         "tcp://localhost:5555",
	}
	for invalidAddr, expectedError := range invalids {
		if addr, err := ParseTCPAddr(invalidAddr, defaultHTTPHost); err == nil || err.Error() != expectedError {
			t.Errorf("tcp %v address expected error %v return, got %s and addr %v", invalidAddr, expectedError, err, addr)
		}
	}
	for validAddr, expectedAddr := range valids {
		if addr, err := ParseTCPAddr(validAddr, defaultHTTPHost); err != nil || addr != expectedAddr {
			t.Errorf("%v -> expected %v, got %v and addr %v", validAddr, expectedAddr, err, addr)
		}
	}
}

func TestParseInvalidUnixAddrInvalid(t *testing.T) {
	if _, err := parseSimpleProtoAddr("unix", "tcp://127.0.0.1", "unix:///var/run/docker.sock"); err == nil || err.Error() != "Invalid proto, expected unix: tcp://127.0.0.1" {
		t.Fatalf("Expected an error, got %v", err)
	}
	if _, err := parseSimpleProtoAddr("unix", "unix://tcp://127.0.0.1", "/var/run/docker.sock"); err == nil || err.Error() != "Invalid proto, expected unix: tcp://127.0.0.1" {
		t.Fatalf("Expected an error, got %v", err)
	}
	if v, err := parseSimpleProtoAddr("unix", "", "/var/run/docker.sock"); err != nil || v != "unix:///var/run/docker.sock" {
		t.Fatalf("Expected an %v, got %v", v, "unix:///var/run/docker.sock")
	}
}

func TestValidateExtraHosts(t *testing.T) {
	valid := []string{
		`myhost:192.168.0.1`,
		`thathost:10.0.2.1`,
		`anipv6host:2003:ab34:e::1`,
		`ipv6local:::1`,
	}

	invalid := map[string]string{
		`myhost:192.notanipaddress.1`:  `invalid IP`,
		`thathost-nosemicolon10.0.0.1`: `bad format`,
		`anipv6host:::::1`:             `invalid IP`,
		`ipv6local:::0::`:              `invalid IP`,
	}

	for _, extrahost := range valid {
		if _, err := ValidateExtraHost(extrahost); err != nil {
			t.Fatalf("ValidateExtraHost(`"+extrahost+"`) should succeed: error %v", err)
		}
	}

	for extraHost, expectedError := range invalid {
		if _, err := ValidateExtraHost(extraHost); err == nil {
			t.Fatalf("ValidateExtraHost(`%q`) should have failed validation", extraHost)
		} else {
			if !strings.Contains(err.Error(), expectedError) {
				t.Fatalf("ValidateExtraHost(`%q`) error should contain %q", extraHost, expectedError)
			}
		}
	}
}
<commit_msg>opts: re-order test-cases and use more consistent values<commit_after>package opts // import "github.com/docker/docker/opts"

import (
	"fmt"
	"strings"
	"testing"
)

func TestParseHost(t *testing.T) {
	invalid := []string{
		"something with spaces",
		"://",
		"unknown://",
		"tcp://:port",
		"tcp://invalid:port",
		"tcp://:5555/",
		"tcp://:5555/p",
		"tcp://0.0.0.0:5555/",
		"tcp://0.0.0.0:5555/p",
		"tcp://[::1]:/",
		"tcp://[::1]:5555/",
		"tcp://[::1]:5555/p",
		" tcp://:5555/path ",
	}

	valid := map[string]string{
		"":                         DefaultHost,
		" ":                        DefaultHost,
		"  ":                       DefaultHost,
		"fd://":                    "fd://",
		"fd://something":           "fd://something",
		"tcp://host:":              fmt.Sprintf("tcp://host:%d", DefaultHTTPPort),
		"tcp://":                   DefaultTCPHost,
		"tcp://:":                  DefaultTCPHost,
		"tcp://:5555":              fmt.Sprintf("tcp://%s:5555", DefaultHTTPHost),
		"tcp://[::1]:":             fmt.Sprintf(`tcp://[::1]:%d`, DefaultHTTPPort),
		"tcp://[::1]:5555":         `tcp://[::1]:5555`,
		"tcp://0.0.0.0:5555":       "tcp://0.0.0.0:5555",
		"tcp://192.168:5555":       "tcp://192.168:5555",
		"tcp://192.168.0.1:5555":   "tcp://192.168.0.1:5555",
		"tcp://0.0.0.0:1234567890": "tcp://0.0.0.0:1234567890", // yeah it's valid :P
		"tcp://docker.com:5555":    "tcp://docker.com:5555",
		"unix://":                  "unix://" + DefaultUnixSocket,
		"unix://path/to/socket":    "unix://path/to/socket",
		"npipe://":                 "npipe://" + DefaultNamedPipe,
		"npipe:////./pipe/foo":     "npipe:////./pipe/foo",
	}

	for _, value := range invalid {
		if _, err := ParseHost(false, false, value); err == nil {
			t.Errorf("Expected an error for %v, got [nil]", value)
		}
	}

	for value, expected := range valid {
		if actual, err := ParseHost(false, false, value); err != nil || actual != expected {
			t.Errorf("Expected for %v [%v], got [%v, %v]", value, expected, actual, err)
		}
	}
}

func TestParseDockerDaemonHost(t *testing.T) {
	invalids := map[string]string{
		"tcp:a.b.c.d":                   `parse "tcp://tcp:a.b.c.d": invalid port ":a.b.c.d" after host`,
		"tcp:a.b.c.d/path":              `parse "tcp://tcp:a.b.c.d/path": invalid port ":a.b.c.d" after host`,
		"udp://127.0.0.1":               "Invalid bind address format: udp://127.0.0.1",
		"udp://127.0.0.1:5555":          "Invalid bind address format: udp://127.0.0.1:5555",
		"tcp://unix:///run/docker.sock": "Invalid proto, expected tcp: unix:///run/docker.sock",
		" tcp://:5555/path ":            "Invalid bind address format:  tcp://:5555/path ",
		"":                              "Invalid bind address format: ",
		":5555/path":                    "invalid bind address (:5555/path): should not contain a path element",
		"0.0.0.1:5555/path":             "invalid bind address (0.0.0.1:5555/path): should not contain a path element",
		"[::1]:5555/path":               "invalid bind address ([::1]:5555/path): should not contain a path element",
		"[0:0:0:0:0:0:0:1]:5555/path":   "invalid bind address ([0:0:0:0:0:0:0:1]:5555/path): should not contain a path element",
		"tcp://:5555/path":              "invalid bind address (:5555/path): should not contain a path element",
		"localhost:5555/path":           "invalid bind address (localhost:5555/path): should not contain a path element",
	}
	valids := map[string]string{
		":":                       DefaultTCPHost,
		":5555":                   fmt.Sprintf("tcp://%s:5555", DefaultHTTPHost),
		"0.0.0.1:":                fmt.Sprintf("tcp://0.0.0.1:%d", DefaultHTTPPort),
		"0.0.0.1:5555":            "tcp://0.0.0.1:5555",
		"[::1]:":                  fmt.Sprintf("tcp://[::1]:%d", DefaultHTTPPort),
		"[::1]:5555":              "tcp://[::1]:5555",
		"[0:0:0:0:0:0:0:1]:":      fmt.Sprintf("tcp://[0:0:0:0:0:0:0:1]:%d", DefaultHTTPPort),
		"[0:0:0:0:0:0:0:1]:5555":  "tcp://[0:0:0:0:0:0:0:1]:5555",
		"localhost":               fmt.Sprintf("tcp://localhost:%d", DefaultHTTPPort),
		"localhost:":              fmt.Sprintf("tcp://localhost:%d", DefaultHTTPPort),
		"localhost:5555":          "tcp://localhost:5555",
		"fd://":                   "fd://",
		"fd://something":          "fd://something",
		"npipe://":                "npipe://" + DefaultNamedPipe,
		"npipe:////./pipe/foo":    "npipe:////./pipe/foo",
		"tcp://":                  DefaultTCPHost,
		"tcp://:5555":             fmt.Sprintf("tcp://%s:5555", DefaultHTTPHost),
		"tcp://[::1]:":            fmt.Sprintf("tcp://[::1]:%d", DefaultHTTPPort),
		"tcp://[::1]:5555":        "tcp://[::1]:5555",
		"unix://":                 "unix://" + DefaultUnixSocket,
		"unix:///run/docker.sock": "unix:///run/docker.sock",
	}
	for invalidAddr, expectedError := range invalids {
		if addr, err := parseDaemonHost(invalidAddr); err == nil || err.Error() != expectedError {
			t.Errorf("tcp %v address expected error %q return, got %q and addr %v", invalidAddr, expectedError, err, addr)
		}
	}
	for validAddr, expectedAddr := range valids {
		if addr, err := parseDaemonHost(validAddr); err != nil || addr != expectedAddr {
			t.Errorf("%v -> expected %v, got (%v) addr (%v)", validAddr, expectedAddr, err, addr)
		}
	}
}

func TestParseTCP(t *testing.T) {
	var (
		defaultHTTPHost = "tcp://127.0.0.1:8888"
	)
	invalids := map[string]string{
		"tcp:a.b.c.d":                 `parse "tcp://tcp:a.b.c.d": invalid port ":a.b.c.d" after host`,
		"tcp:a.b.c.d/path":            `parse "tcp://tcp:a.b.c.d/path": invalid port ":a.b.c.d" after host`,
		"udp://127.0.0.1":             "Invalid proto, expected tcp: udp://127.0.0.1",
		"udp://127.0.0.1:5555":        "Invalid proto, expected tcp: udp://127.0.0.1:5555",
		":5555/path":                  "invalid bind address (:5555/path): should not contain a path element",
		"0.0.0.1:5555/path":           "invalid bind address (0.0.0.1:5555/path): should not contain a path element",
		"[::1]:5555/path":             "invalid bind address ([::1]:5555/path): should not contain a path element",
		"[0:0:0:0:0:0:0:1]:5555/path": "invalid bind address ([0:0:0:0:0:0:0:1]:5555/path): should not contain a path element",
		"tcp://:5555/path":            "invalid bind address (tcp://:5555/path): should not contain a path element",
		"localhost:5555/path":         "invalid bind address (localhost:5555/path): should not contain a path element",
	}
	valids := map[string]string{
		"":                       defaultHTTPHost,
		"0.0.0.1":                "tcp://0.0.0.1:8888",
		"0.0.0.1:":               "tcp://0.0.0.1:8888",
		"0.0.0.1:5555":           "tcp://0.0.0.1:5555",
		":":                      "tcp://127.0.0.1:8888",
		":5555":                  "tcp://127.0.0.1:5555",
		"::1":                    "tcp://[::1]:8888",
		"[::1]:":                 "tcp://[::1]:8888",
		"[::1]:5555":             "tcp://[::1]:5555",
		"[0:0:0:0:0:0:0:1]:":     "tcp://[0:0:0:0:0:0:0:1]:8888",
		"[0:0:0:0:0:0:0:1]:5555": "tcp://[0:0:0:0:0:0:0:1]:5555",
		"localhost":              "tcp://localhost:8888",
		"localhost:":             "tcp://localhost:8888",
		"localhost:5555":         "tcp://localhost:5555",
		"tcp://":                 defaultHTTPHost,
		"tcp://:":                defaultHTTPHost,
		"tcp://:5555":            "tcp://127.0.0.1:5555",
	}
	for invalidAddr, expectedError := range invalids {
		if addr, err := ParseTCPAddr(invalidAddr, defaultHTTPHost); err == nil || err.Error() != expectedError {
			t.Errorf("tcp %v address expected error %v return, got %s and addr %v", invalidAddr, expectedError, err, addr)
		}
	}
	for validAddr, expectedAddr := range valids {
		if addr, err := ParseTCPAddr(validAddr, defaultHTTPHost); err != nil || addr != expectedAddr {
			t.Errorf("%v -> expected %v, got %v and addr %v", validAddr, expectedAddr, err, addr)
		}
	}
}

func TestParseInvalidUnixAddrInvalid(t *testing.T) {
	if _, err := parseSimpleProtoAddr("unix", "tcp://127.0.0.1", "unix:///var/run/docker.sock"); err == nil || err.Error() != "Invalid proto, expected unix: tcp://127.0.0.1" {
		t.Fatalf("Expected an error, got %v", err)
	}
	if _, err := parseSimpleProtoAddr("unix", "unix://tcp://127.0.0.1", "/var/run/docker.sock"); err == nil || err.Error() != "Invalid proto, expected unix: tcp://127.0.0.1" {
		t.Fatalf("Expected an error, got %v", err)
	}
	if v, err := parseSimpleProtoAddr("unix", "", "/var/run/docker.sock"); err != nil || v != "unix:///var/run/docker.sock" {
		t.Fatalf("Expected an %v, got %v", v, "unix:///var/run/docker.sock")
	}
}

func TestValidateExtraHosts(t *testing.T) {
	valid := []string{
		`myhost:192.168.0.1`,
		`thathost:10.0.2.1`,
		`anipv6host:2003:ab34:e::1`,
		`ipv6local:::1`,
	}

	invalid := map[string]string{
		`myhost:192.notanipaddress.1`:  `invalid IP`,
		`thathost-nosemicolon10.0.0.1`: `bad format`,
		`anipv6host:::::1`:             `invalid IP`,
		`ipv6local:::0::`:              `invalid IP`,
	}

	for _, extrahost := range valid {
		if _, err := ValidateExtraHost(extrahost); err != nil {
			t.Fatalf("ValidateExtraHost(`"+extrahost+"`) should succeed: error %v", err)
		}
	}

	for extraHost, expectedError := range invalid {
		if _, err := ValidateExtraHost(extraHost); err == nil {
			t.Fatalf("ValidateExtraHost(`%q`) should have failed validation", extraHost)
		} else {
			if !strings.Contains(err.Error(), expectedError) {
				t.Fatalf("ValidateExtraHost(`%q`) error should contain %q", extraHost, expectedError)
			}
		}
	}
}
<|endoftext|>