<commit_before>// Copyright 2011 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 builtin provides documentation for Go's predeclared identifiers.
	The items documented here are not actually in package builtin
	but their descriptions here allow godoc to present documentation
	for the language's special identifiers.
*/
package builtin

// bool is the set of boolean values, true and false.
type bool bool

// uint8 is the set of all unsigned 8-bit integers.
// Range: 0 through 255.
type uint8 uint8

// uint16 is the set of all unsigned 16-bit integers.
// Range: 0 through 65535.
type uint16 uint16

// uint32 is the set of all unsigned 32-bit integers.
// Range: 0 through 4294967295.
type uint32 uint32

// uint64 is the set of all unsigned 64-bit integers.
// Range: 0 through 18446744073709551615.
type uint64 uint64

// int8 is the set of all signed 8-bit integers.
// Range: -128 through 127.
type int8 int8

// int16 is the set of all signed 16-bit integers.
// Range: -32768 through 32767.
type int16 int16

// int32 is the set of all signed 32-bit integers.
// Range: -2147483648 through 2147483647.
type int32 int32

// int64 is the set of all signed 64-bit integers.
// Range: -9223372036854775808 through 9223372036854775807.
type int64 int64

// float32 is the set of all IEEE-754 32-bit floating-point numbers.
type float32 float32

// float64 is the set of all IEEE-754 64-bit floating-point numbers.
type float64 float64

// complex64 is the set of all complex numbers with float32 real and
// imaginary parts.
type complex64 complex64

// complex128 is the set of all complex numbers with float64 real and
// imaginary parts.
type complex128 complex128

// string is the set of all strings of 8-bit bytes, conventionally but not
// necessarily representing UTF-8-encoded text. A string may be empty, but
// not nil. Values of string type are immutable.
type string string

// int is a signed integer type that is at least 32 bits in size. It is a
// distinct type, however, and not an alias for, say, int32.
type int int

// uint is an unsigned integer type that is at least 32 bits in size. It is a
// distinct type, however, and not an alias for, say, uint32.
type uint uint

// uintptr is an integer type that is large enough to hold the bit pattern of
// any pointer.
type uintptr uintptr

// byte is an alias for uint8 and is equivalent to uint8 in all ways. It is
// used, by convention, to distinguish byte values from 8-bit unsigned
// integer values.
type byte byte

// rune is an alias for int and is equivalent to int in all ways. It is
// used, by convention, to distinguish character values from integer values.
// In a future version of Go, it will change to an alias of int32.
type rune rune

// Type is here for the purposes of documentation only. It is a stand-in
// for any Go type, but represents the same type for any given function
// invocation.
type Type int

// Type1 is here for the purposes of documentation only. It is a stand-in
// for any Go type, but represents the same type for any given function
// invocation.
type Type1 int

// IntegerType is here for the purposes of documentation only. It is a stand-in
// for any integer type: int, uint, int8 etc.
type IntegerType int

// FloatType is here for the purposes of documentation only. It is a stand-in
// for either float type: float32 or float64.
type FloatType float32

// ComplexType is here for the purposes of documentation only. It is a
// stand-in for either complex type: complex64 or complex128.
type ComplexType complex64

// The append built-in function appends elements to the end of a slice. If
// it has sufficient capacity, the destination is resliced to accommodate the
// new elements. If it does not, a new underlying array will be allocated.
// Append returns the updated slice. It is therefore necessary to store the
// result of append, often in the variable holding the slice itself:
//	slice = append(slice, elem1, elem2)
//	slice = append(slice, anotherSlice...)
func append(slice []Type, elems ...Type) []Type

// The copy built-in function copies elements from a source slice into a
// destination slice. (As a special case, it also will copy bytes from a
// string to a slice of bytes.) The source and destination may overlap. Copy
// returns the number of elements copied, which will be the minimum of
// len(src) and len(dst).
func copy(dst, src []Type) int

// The delete built-in function deletes the element with the specified key
// (m[key]) from the map. If there is no such element, delete is a no-op.
// If m is nil, delete panics.
func delete(m map[Type]Type1, key Type)

// The len built-in function returns the length of v, according to its type:
//	Array: the number of elements in v.
//	Pointer to array: the number of elements in *v (even if v is nil).
//	Slice, or map: the number of elements in v; if v is nil, len(v) is zero.
//	String: the number of bytes in v.
//	Channel: the number of elements queued (unread) in the channel buffer;
//	if v is nil, len(v) is zero.
func len(v Type) int

// The cap built-in function returns the capacity of v, according to its type:
//	Array: the number of elements in v (same as len(v)).
//	Pointer to array: the number of elements in *v (same as len(v)).
//	Slice: the maximum length the slice can reach when resliced;
//	if v is nil, cap(v) is zero.
//	Channel: the channel buffer capacity, in units of elements;
//	if v is nil, cap(v) is zero.
func cap(v Type) int

// The make built-in function allocates and initializes an object of type
// slice, map, or chan (only). Like new, the first argument is a type, not a
// value. Unlike new, make's return type is the same as the type of its
// argument, not a pointer to it. The specification of the result depends on
// the type:
//	Slice: The size specifies the length. The capacity of the slice is
//	equal to its length. A second integer argument may be provided to
//	specify a different capacity; it must be no smaller than the
//	length, so make([]int, 0, 10) allocates a slice of length 0 and
//	capacity 10.
//	Map: An initial allocation is made according to the size but the
//	resulting map has length 0. The size may be omitted, in which case
//	a small starting size is allocated.
//	Channel: The channel's buffer is initialized with the specified
//	buffer capacity. If zero, or the size is omitted, the channel is
//	unbuffered.
func make(Type, size IntegerType) Type

// The new built-in function allocates memory. The first argument is a type,
// not a value, and the value returned is a pointer to a newly
// allocated zero value of that type.
func new(Type) *Type

// The complex built-in function constructs a complex value from two
// floating-point values. The real and imaginary parts must be of the same
// size, either float32 or float64 (or assignable to them), and the return
// value will be the corresponding complex type (complex64 for float32,
// complex128 for float64).
func complex(r, i FloatType) ComplexType

// The real built-in function returns the real part of the complex number c.
// The return value will be floating point type corresponding to the type of c.
func real(c ComplexType) FloatType

// The imag built-in function returns the imaginary part of the complex
// number c. The return value will be floating point type corresponding to
// the type of c.
func imag(c ComplexType) FloatType

// The close built-in function closes a channel, which must be either
// bidirectional or send-only. It should be executed only by the sender,
// never the receiver, and has the effect of shutting down the channel after
// the last sent value is received. After the last value has been received
// from a closed channel c, any receive from c will succeed without
// blocking, returning the zero value for the channel element. The form
//	x, ok := <-c
// will also set ok to false for a closed channel.
func close(c chan<- Type)

// The panic built-in function stops normal execution of the current
// goroutine. When a function F calls panic, normal execution of F stops
// immediately. Any functions whose execution was deferred by F are run in
// the usual way, and then F returns to its caller. To the caller G, the
// invocation of F then behaves like a call to panic, terminating G's
// execution and running any deferred functions. This continues until all
// functions in the executing goroutine have stopped, in reverse order. At
// that point, the program is terminated and the error condition is reported,
// including the value of the argument to panic. This termination sequence
// is called panicking and can be controlled by the built-in function
// recover.
func panic(v interface{})

// The recover built-in function allows a program to manage behavior of a
// panicking goroutine. Executing a call to recover inside a deferred
// function (but not any function called by it) stops the panicking sequence
// by restoring normal execution and retrieves the error value passed to the
// call of panic. If recover is called outside the deferred function it will
// not stop a panicking sequence. In this case, or when the goroutine is not
// panicking, or if the argument supplied to panic was nil, recover returns
// nil. Thus the return value from recover reports whether the goroutine is
// panicking.
func recover() interface{}

// The error built-in interface type is the conventional interface for
// representing an error condition, with the nil value representing no error.
type error interface {
	Error() string
}
<commit_msg>builtin: Changed documentation for rune type. Fixes #4093.<commit_after>// Copyright 2011 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 builtin provides documentation for Go's predeclared identifiers.
	The items documented here are not actually in package builtin
	but their descriptions here allow godoc to present documentation
	for the language's special identifiers.
*/
package builtin

// bool is the set of boolean values, true and false.
type bool bool

// uint8 is the set of all unsigned 8-bit integers.
// Range: 0 through 255.
type uint8 uint8

// uint16 is the set of all unsigned 16-bit integers.
// Range: 0 through 65535.
type uint16 uint16

// uint32 is the set of all unsigned 32-bit integers.
// Range: 0 through 4294967295.
type uint32 uint32

// uint64 is the set of all unsigned 64-bit integers.
// Range: 0 through 18446744073709551615.
type uint64 uint64

// int8 is the set of all signed 8-bit integers.
// Range: -128 through 127.
type int8 int8

// int16 is the set of all signed 16-bit integers.
// Range: -32768 through 32767.
type int16 int16

// int32 is the set of all signed 32-bit integers.
// Range: -2147483648 through 2147483647.
type int32 int32

// int64 is the set of all signed 64-bit integers.
// Range: -9223372036854775808 through 9223372036854775807.
type int64 int64

// float32 is the set of all IEEE-754 32-bit floating-point numbers.
type float32 float32

// float64 is the set of all IEEE-754 64-bit floating-point numbers.
type float64 float64

// complex64 is the set of all complex numbers with float32 real and
// imaginary parts.
type complex64 complex64

// complex128 is the set of all complex numbers with float64 real and
// imaginary parts.
type complex128 complex128

// string is the set of all strings of 8-bit bytes, conventionally but not
// necessarily representing UTF-8-encoded text. A string may be empty, but
// not nil. Values of string type are immutable.
type string string

// int is a signed integer type that is at least 32 bits in size. It is a
// distinct type, however, and not an alias for, say, int32.
type int int

// uint is an unsigned integer type that is at least 32 bits in size. It is a
// distinct type, however, and not an alias for, say, uint32.
type uint uint

// uintptr is an integer type that is large enough to hold the bit pattern of
// any pointer.
type uintptr uintptr

// byte is an alias for uint8 and is equivalent to uint8 in all ways. It is
// used, by convention, to distinguish byte values from 8-bit unsigned
// integer values.
type byte byte

// rune is an alias for int32 and is equivalent to int32 in all ways. It is
// used, by convention, to distinguish character values from integer values.
type rune rune

// Type is here for the purposes of documentation only. It is a stand-in
// for any Go type, but represents the same type for any given function
// invocation.
type Type int

// Type1 is here for the purposes of documentation only. It is a stand-in
// for any Go type, but represents the same type for any given function
// invocation.
type Type1 int

// IntegerType is here for the purposes of documentation only. It is a stand-in
// for any integer type: int, uint, int8 etc.
type IntegerType int

// FloatType is here for the purposes of documentation only. It is a stand-in
// for either float type: float32 or float64.
type FloatType float32

// ComplexType is here for the purposes of documentation only. It is a
// stand-in for either complex type: complex64 or complex128.
type ComplexType complex64

// The append built-in function appends elements to the end of a slice. If
// it has sufficient capacity, the destination is resliced to accommodate the
// new elements. If it does not, a new underlying array will be allocated.
// Append returns the updated slice. It is therefore necessary to store the
// result of append, often in the variable holding the slice itself:
//	slice = append(slice, elem1, elem2)
//	slice = append(slice, anotherSlice...)
func append(slice []Type, elems ...Type) []Type

// The copy built-in function copies elements from a source slice into a
// destination slice. (As a special case, it also will copy bytes from a
// string to a slice of bytes.) The source and destination may overlap. Copy
// returns the number of elements copied, which will be the minimum of
// len(src) and len(dst).
func copy(dst, src []Type) int

// The delete built-in function deletes the element with the specified key
// (m[key]) from the map. If there is no such element, delete is a no-op.
// If m is nil, delete panics.
func delete(m map[Type]Type1, key Type)

// The len built-in function returns the length of v, according to its type:
//	Array: the number of elements in v.
//	Pointer to array: the number of elements in *v (even if v is nil).
//	Slice, or map: the number of elements in v; if v is nil, len(v) is zero.
//	String: the number of bytes in v.
//	Channel: the number of elements queued (unread) in the channel buffer;
//	if v is nil, len(v) is zero.
func len(v Type) int

// The cap built-in function returns the capacity of v, according to its type:
//	Array: the number of elements in v (same as len(v)).
//	Pointer to array: the number of elements in *v (same as len(v)).
//	Slice: the maximum length the slice can reach when resliced;
//	if v is nil, cap(v) is zero.
//	Channel: the channel buffer capacity, in units of elements;
//	if v is nil, cap(v) is zero.
func cap(v Type) int

// The make built-in function allocates and initializes an object of type
// slice, map, or chan (only). Like new, the first argument is a type, not a
// value. Unlike new, make's return type is the same as the type of its
// argument, not a pointer to it. The specification of the result depends on
// the type:
//	Slice: The size specifies the length. The capacity of the slice is
//	equal to its length. A second integer argument may be provided to
//	specify a different capacity; it must be no smaller than the
//	length, so make([]int, 0, 10) allocates a slice of length 0 and
//	capacity 10.
//	Map: An initial allocation is made according to the size but the
//	resulting map has length 0. The size may be omitted, in which case
//	a small starting size is allocated.
//	Channel: The channel's buffer is initialized with the specified
//	buffer capacity. If zero, or the size is omitted, the channel is
//	unbuffered.
func make(Type, size IntegerType) Type

// The new built-in function allocates memory. The first argument is a type,
// not a value, and the value returned is a pointer to a newly
// allocated zero value of that type.
func new(Type) *Type

// The complex built-in function constructs a complex value from two
// floating-point values. The real and imaginary parts must be of the same
// size, either float32 or float64 (or assignable to them), and the return
// value will be the corresponding complex type (complex64 for float32,
// complex128 for float64).
func complex(r, i FloatType) ComplexType

// The real built-in function returns the real part of the complex number c.
// The return value will be floating point type corresponding to the type of c.
func real(c ComplexType) FloatType

// The imag built-in function returns the imaginary part of the complex
// number c. The return value will be floating point type corresponding to
// the type of c.
func imag(c ComplexType) FloatType

// The close built-in function closes a channel, which must be either
// bidirectional or send-only. It should be executed only by the sender,
// never the receiver, and has the effect of shutting down the channel after
// the last sent value is received. After the last value has been received
// from a closed channel c, any receive from c will succeed without
// blocking, returning the zero value for the channel element. The form
//	x, ok := <-c
// will also set ok to false for a closed channel.
func close(c chan<- Type)

// The panic built-in function stops normal execution of the current
// goroutine. When a function F calls panic, normal execution of F stops
// immediately. Any functions whose execution was deferred by F are run in
// the usual way, and then F returns to its caller. To the caller G, the
// invocation of F then behaves like a call to panic, terminating G's
// execution and running any deferred functions. This continues until all
// functions in the executing goroutine have stopped, in reverse order. At
// that point, the program is terminated and the error condition is reported,
// including the value of the argument to panic. This termination sequence
// is called panicking and can be controlled by the built-in function
// recover.
func panic(v interface{})

// The recover built-in function allows a program to manage behavior of a
// panicking goroutine. Executing a call to recover inside a deferred
// function (but not any function called by it) stops the panicking sequence
// by restoring normal execution and retrieves the error value passed to the
// call of panic. If recover is called outside the deferred function it will
// not stop a panicking sequence. In this case, or when the goroutine is not
// panicking, or if the argument supplied to panic was nil, recover returns
// nil. Thus the return value from recover reports whether the goroutine is
// panicking.
func recover() interface{}

// The error built-in interface type is the conventional interface for
// representing an error condition, with the nil value representing no error.
type error interface {
	Error() string
}
<|endoftext|>


<commit_before>package grpcutil

import (
	"fmt"
	"sync"

	"google.golang.org/grpc"
)

type dialer struct {
	opts []grpc.DialOption
	// TODO: this is insane for so many reasons
	addressToClientConn map[string]*grpc.ClientConn
	lock                *sync.RWMutex
}

func newDialer(opts ...grpc.DialOption) *dialer {
	return &dialer{opts, make(map[string]*grpc.ClientConn), &sync.RWMutex{}}
}

func (d *dialer) Dial(address string) (*grpc.ClientConn, error) {
	d.lock.RLock()
	clientConn, ok := d.addressToClientConn[address]
	d.lock.RUnlock()
	state, err := clientConn.State()
	if err != nil {
		return nil, err
	}
	if ok && clientConn != nil && state != grpc.Shutdown {
		return clientConn, nil
	}
	newClientConn, err := grpc.Dial(address, d.opts...)
	if err != nil {
		return nil, err
	}
	d.lock.Lock()
	defer d.lock.Unlock()
	clientConn, ok = d.addressToClientConn[address]
	state, err = clientConn.State()
	if err != nil {
		return nil, err
	}
	if ok && clientConn != nil && state != grpc.Shutdown {
		_ = newClientConn.Close()
		return clientConn, nil
	}
	d.addressToClientConn[address] = newClientConn
	return newClientConn, nil
}

func (d *dialer) Clean() error {
	d.lock.Lock()
	defer d.lock.Unlock()
	var errs []error
	for _, clientConn := range d.addressToClientConn {
		if err := clientConn.Close(); err != nil && err != grpc.ErrClientConnClosing {
			errs = append(errs, err)
		}
	}
	d.addressToClientConn = make(map[string]*grpc.ClientConn)
	if len(errs) > 0 {
		return fmt.Errorf("%v", errs)
	}
	return nil
}
<commit_msg>Fixes a crash.<commit_after>package grpcutil

import (
	"fmt"
	"sync"

	"google.golang.org/grpc"
)

type dialer struct {
	opts []grpc.DialOption
	// TODO: this is insane for so many reasons
	addressToClientConn map[string]*grpc.ClientConn
	lock                *sync.RWMutex
}

func newDialer(opts ...grpc.DialOption) *dialer {
	return &dialer{opts, make(map[string]*grpc.ClientConn), &sync.RWMutex{}}
}

func (d *dialer) Dial(address string) (*grpc.ClientConn, error) {
	d.lock.RLock()
	clientConn, ok := d.addressToClientConn[address]
	d.lock.RUnlock()
	if ok && clientConn != nil {
		state, err := clientConn.State()
		if err != nil {
			return nil, err
		}
		if state != grpc.Shutdown {
			return clientConn, nil
		}
	}
	newClientConn, err := grpc.Dial(address, d.opts...)
	if err != nil {
		return nil, err
	}
	d.lock.Lock()
	defer d.lock.Unlock()
	clientConn, ok = d.addressToClientConn[address]
	if ok && clientConn != nil {
		state, err := clientConn.State()
		if err != nil {
			return nil, err
		}
		if state != grpc.Shutdown {
			_ = newClientConn.Close()
			return clientConn, nil
		}
	}
	d.addressToClientConn[address] = newClientConn
	return newClientConn, nil
}

func (d *dialer) Clean() error {
	d.lock.Lock()
	defer d.lock.Unlock()
	var errs []error
	for _, clientConn := range d.addressToClientConn {
		if err := clientConn.Close(); err != nil && err != grpc.ErrClientConnClosing {
			errs = append(errs, err)
		}
	}
	d.addressToClientConn = make(map[string]*grpc.ClientConn)
	if len(errs) > 0 {
		return fmt.Errorf("%v", errs)
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2009 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 net

import (
	"flag"
	"io"
	"os"
	"strings"
	"syscall"
	"testing"
)

// Do not test empty datagrams by default.
// It causes unexplained timeouts on some systems,
// including Snow Leopard.  I think that the kernel
// doesn't quite expect them.
var testEmptyDatagrams = flag.Bool("empty_datagrams", false, "whether to test empty datagrams")

func runEcho(fd io.ReadWriter, done chan<- int) {
	var buf [1024]byte

	for {
		n, err := fd.Read(&buf)
		if err != nil || n == 0 {
			break
		}
		fd.Write(buf[0:n])
	}
	done <- 1
}

func runServe(t *testing.T, network, addr string, listening chan<- string, done chan<- int) {
	l, err := Listen(network, addr)
	if err != nil {
		t.Fatalf("net.Listen(%q, %q) = _, %v", network, addr, err)
	}
	listening <- l.Addr().String()

	for {
		fd, err := l.Accept()
		if err != nil {
			break
		}
		echodone := make(chan int)
		go runEcho(fd, echodone)
		<-echodone // make sure Echo stops
		l.Close()
	}
	done <- 1
}

func connect(t *testing.T, network, addr string, isEmpty bool) {
	var laddr string
	if network == "unixgram" {
		laddr = addr + ".local"
	}
	fd, err := Dial(network, laddr, addr)
	if err != nil {
		t.Fatalf("net.Dial(%q, %q, %q) = _, %v", network, laddr, addr, err)
	}
	fd.SetReadTimeout(1e9) // 1s

	var b []byte
	if !isEmpty {
		b = strings.Bytes("hello, world\n")
	}
	var b1 [100]byte

	n, err := fd.Write(b)
	if n != len(b) {
		t.Fatalf("fd.Write(%q) = %d, %v", b, n, err)
	}

	n, err = fd.Read(&b1)
	if n != len(b) || err != nil {
		t.Fatalf("fd.Read() = %d, %v (want %d, nil)", n, err, len(b))
	}
	fd.Close()
}

func doTest(t *testing.T, network, listenaddr, dialaddr string) {
	t.Logf("Test %s %s %s\n", network, listenaddr, dialaddr)
	listening := make(chan string)
	done := make(chan int)
	if network == "tcp" {
		listenaddr += ":0" // any available port
	}
	go runServe(t, network, listenaddr, listening, done)
	addr := <-listening // wait for server to start
	if network == "tcp" {
		dialaddr += addr[strings.LastIndex(addr, ":"):]
	}
	connect(t, network, dialaddr, false)
	<-done // make sure server stopped
}

func TestTCPServer(t *testing.T) {
	doTest(t, "tcp", "0.0.0.0", "127.0.0.1")
	doTest(t, "tcp", "", "127.0.0.1")
	if kernelSupportsIPv6() {
		doTest(t, "tcp", "[::]", "[::ffff:127.0.0.1]")
		doTest(t, "tcp", "[::]", "127.0.0.1")
		doTest(t, "tcp", "0.0.0.0", "[::ffff:127.0.0.1]")
	}
}

func TestUnixServer(t *testing.T) {
	os.Remove("/tmp/gotest.net")
	doTest(t, "unix", "/tmp/gotest.net", "/tmp/gotest.net")
	os.Remove("/tmp/gotest.net")
	if syscall.OS == "linux" {
		// Test abstract unix domain socket, a Linux-ism
		doTest(t, "unix", "@gotest/net", "@gotest/net")
	}
}

func runPacket(t *testing.T, network, addr string, listening chan<- string, done chan<- int) {
	c, err := ListenPacket(network, addr)
	if err != nil {
		t.Fatalf("net.ListenPacket(%q, %q) = _, %v", network, addr, err)
	}
	listening <- c.LocalAddr().String()
	c.SetReadTimeout(10e6) // 10ms
	var buf [1000]byte
	for {
		n, addr, err := c.ReadFrom(&buf)
		if isEAGAIN(err) {
			if done <- 1 {
				break
			}
			continue
		}
		if err != nil {
			break
		}
		if _, err = c.WriteTo(buf[0:n], addr); err != nil {
			t.Fatalf("WriteTo %v: %v", addr, err)
		}
	}
	c.Close()
	done <- 1
}

func doTestPacket(t *testing.T, network, listenaddr, dialaddr string, isEmpty bool) {
	t.Logf("TestPacket %s %s %s\n", network, listenaddr, dialaddr)
	listening := make(chan string)
	done := make(chan int)
	if network == "udp" {
		listenaddr += ":0" // any available port
	}
	go runPacket(t, network, listenaddr, listening, done)
	addr := <-listening // wait for server to start
	if network == "udp" {
		dialaddr += addr[strings.LastIndex(addr, ":"):]
	}
	connect(t, network, dialaddr, isEmpty)
	<-done // tell server to stop
	<-done // wait for stop
}

func TestUDPServer(t *testing.T) {
	for _, isEmpty := range []bool{false, *testEmptyDatagrams} {
		doTestPacket(t, "udp", "0.0.0.0", "127.0.0.1", isEmpty)
		doTestPacket(t, "udp", "", "127.0.0.1", isEmpty)
		if kernelSupportsIPv6() {
			doTestPacket(t, "udp", "[::]", "[::ffff:127.0.0.1]", isEmpty)
			doTestPacket(t, "udp", "[::]", "127.0.0.1", isEmpty)
			doTestPacket(t, "udp", "0.0.0.0", "[::ffff:127.0.0.1]", isEmpty)
		}
	}
}

func TestUnixDatagramServer(t *testing.T) {
	for _, isEmpty := range []bool{false, *testEmptyDatagrams} {
		os.Remove("/tmp/gotest1.net")
		os.Remove("/tmp/gotest1.net.local")
		doTestPacket(t, "unixgram", "/tmp/gotest1.net", "/tmp/gotest1.net", isEmpty)
		os.Remove("/tmp/gotest1.net")
		os.Remove("/tmp/gotest1.net.local")
		if syscall.OS == "linux" {
			// Test abstract unix domain socket, a Linux-ism
			doTestPacket(t, "unixgram", "@gotest1/net", "@gotest1/net", isEmpty)
		}
	}
}
<commit_msg>net: disable UDP server test<commit_after>// Copyright 2009 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 net

import (
	"flag"
	"io"
	"os"
	"strings"
	"syscall"
	"testing"
)

// Do not test empty datagrams by default.
// It causes unexplained timeouts on some systems,
// including Snow Leopard.  I think that the kernel
// doesn't quite expect them.
var testUDP = flag.Bool("udp", false, "whether to test UDP datagrams")

func runEcho(fd io.ReadWriter, done chan<- int) {
	var buf [1024]byte

	for {
		n, err := fd.Read(&buf)
		if err != nil || n == 0 {
			break
		}
		fd.Write(buf[0:n])
	}
	done <- 1
}

func runServe(t *testing.T, network, addr string, listening chan<- string, done chan<- int) {
	l, err := Listen(network, addr)
	if err != nil {
		t.Fatalf("net.Listen(%q, %q) = _, %v", network, addr, err)
	}
	listening <- l.Addr().String()

	for {
		fd, err := l.Accept()
		if err != nil {
			break
		}
		echodone := make(chan int)
		go runEcho(fd, echodone)
		<-echodone // make sure Echo stops
		l.Close()
	}
	done <- 1
}

func connect(t *testing.T, network, addr string, isEmpty bool) {
	var laddr string
	if network == "unixgram" {
		laddr = addr + ".local"
	}
	fd, err := Dial(network, laddr, addr)
	if err != nil {
		t.Fatalf("net.Dial(%q, %q, %q) = _, %v", network, laddr, addr, err)
	}
	fd.SetReadTimeout(1e9) // 1s

	var b []byte
	if !isEmpty {
		b = strings.Bytes("hello, world\n")
	}
	var b1 [100]byte

	n, err := fd.Write(b)
	if n != len(b) {
		t.Fatalf("fd.Write(%q) = %d, %v", b, n, err)
	}

	n, err = fd.Read(&b1)
	if n != len(b) || err != nil {
		t.Fatalf("fd.Read() = %d, %v (want %d, nil)", n, err, len(b))
	}
	fd.Close()
}

func doTest(t *testing.T, network, listenaddr, dialaddr string) {
	t.Logf("Test %s %s %s\n", network, listenaddr, dialaddr)
	listening := make(chan string)
	done := make(chan int)
	if network == "tcp" {
		listenaddr += ":0" // any available port
	}
	go runServe(t, network, listenaddr, listening, done)
	addr := <-listening // wait for server to start
	if network == "tcp" {
		dialaddr += addr[strings.LastIndex(addr, ":"):]
	}
	connect(t, network, dialaddr, false)
	<-done // make sure server stopped
}

func TestTCPServer(t *testing.T) {
	doTest(t, "tcp", "0.0.0.0", "127.0.0.1")
	doTest(t, "tcp", "", "127.0.0.1")
	if kernelSupportsIPv6() {
		doTest(t, "tcp", "[::]", "[::ffff:127.0.0.1]")
		doTest(t, "tcp", "[::]", "127.0.0.1")
		doTest(t, "tcp", "0.0.0.0", "[::ffff:127.0.0.1]")
	}
}

func TestUnixServer(t *testing.T) {
	os.Remove("/tmp/gotest.net")
	doTest(t, "unix", "/tmp/gotest.net", "/tmp/gotest.net")
	os.Remove("/tmp/gotest.net")
	if syscall.OS == "linux" {
		// Test abstract unix domain socket, a Linux-ism
		doTest(t, "unix", "@gotest/net", "@gotest/net")
	}
}

func runPacket(t *testing.T, network, addr string, listening chan<- string, done chan<- int) {
	c, err := ListenPacket(network, addr)
	if err != nil {
		t.Fatalf("net.ListenPacket(%q, %q) = _, %v", network, addr, err)
	}
	listening <- c.LocalAddr().String()
	c.SetReadTimeout(10e6) // 10ms
	var buf [1000]byte
	for {
		n, addr, err := c.ReadFrom(&buf)
		if isEAGAIN(err) {
			if done <- 1 {
				break
			}
			continue
		}
		if err != nil {
			break
		}
		if _, err = c.WriteTo(buf[0:n], addr); err != nil {
			t.Fatalf("WriteTo %v: %v", addr, err)
		}
	}
	c.Close()
	done <- 1
}

func doTestPacket(t *testing.T, network, listenaddr, dialaddr string, isEmpty bool) {
	t.Logf("TestPacket %s %s %s\n", network, listenaddr, dialaddr)
	listening := make(chan string)
	done := make(chan int)
	if network == "udp" {
		listenaddr += ":0" // any available port
	}
	go runPacket(t, network, listenaddr, listening, done)
	addr := <-listening // wait for server to start
	if network == "udp" {
		dialaddr += addr[strings.LastIndex(addr, ":"):]
	}
	connect(t, network, dialaddr, isEmpty)
	<-done // tell server to stop
	<-done // wait for stop
}

func TestUDPServer(t *testing.T) {
	if !*testUDP {
		return
	}
	for _, isEmpty := range []bool{false, true} {
		doTestPacket(t, "udp", "0.0.0.0", "127.0.0.1", isEmpty)
		doTestPacket(t, "udp", "", "127.0.0.1", isEmpty)
		if kernelSupportsIPv6() {
			doTestPacket(t, "udp", "[::]", "[::ffff:127.0.0.1]", isEmpty)
			doTestPacket(t, "udp", "[::]", "127.0.0.1", isEmpty)
			doTestPacket(t, "udp", "0.0.0.0", "[::ffff:127.0.0.1]", isEmpty)
		}
	}
}

func TestUnixDatagramServer(t *testing.T) {
	for _, isEmpty := range []bool{false} {
		os.Remove("/tmp/gotest1.net")
		os.Remove("/tmp/gotest1.net.local")
		doTestPacket(t, "unixgram", "/tmp/gotest1.net", "/tmp/gotest1.net", isEmpty)
		os.Remove("/tmp/gotest1.net")
		os.Remove("/tmp/gotest1.net.local")
		if syscall.OS == "linux" {
			// Test abstract unix domain socket, a Linux-ism
			doTestPacket(t, "unixgram", "@gotest1/net", "@gotest1/net", isEmpty)
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2009 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 net

import (
	"flag"
	"io"
	"os"
	"strings"
	"syscall"
	"testing"
	"runtime"
)

// Do not test empty datagrams by default.
// It causes unexplained timeouts on some systems,
// including Snow Leopard.  I think that the kernel
// doesn't quite expect them.
var testUDP = flag.Bool("udp", false, "whether to test UDP datagrams")

func runEcho(fd io.ReadWriter, done chan<- int) {
	var buf [1024]byte

	for {
		n, err := fd.Read(buf[0:])
		if err != nil || n == 0 || string(buf[:n]) == "END" {
			break
		}
		fd.Write(buf[0:n])
	}
	done <- 1
}

func runServe(t *testing.T, network, addr string, listening chan<- string, done chan<- int) {
	l, err := Listen(network, addr)
	if err != nil {
		t.Fatalf("net.Listen(%q, %q) = _, %v", network, addr, err)
	}
	listening <- l.Addr().String()

	for {
		fd, err := l.Accept()
		if err != nil {
			break
		}
		echodone := make(chan int)
		go runEcho(fd, echodone)
		<-echodone // make sure Echo stops
		l.Close()
	}
	done <- 1
}

func connect(t *testing.T, network, addr string, isEmpty bool) {
	var fd Conn
	var err os.Error
	if network == "unixgram" {
		fd, err = DialUnix(network, &UnixAddr{addr + ".local", network}, &UnixAddr{addr, network})
	} else {
		fd, err = Dial(network, addr)
	}
	if err != nil {
		t.Fatalf("net.Dial(%q, %q) = _, %v", network, addr, err)
	}
	fd.SetReadTimeout(1e9) // 1s

	var b []byte
	if !isEmpty {
		b = []byte("hello, world\n")
	}
	var b1 [100]byte

	n, err1 := fd.Write(b)
	if n != len(b) {
		t.Fatalf("fd.Write(%q) = %d, %v", b, n, err1)
	}

	n, err1 = fd.Read(b1[0:])
	if n != len(b) || err1 != nil {
		t.Fatalf("fd.Read() = %d, %v (want %d, nil)", n, err1, len(b))
	}

	// Send explicit ending for unixpacket.
	// Older Linux kernels do stop reads on close.
	if network == "unixpacket" {
		fd.Write([]byte("END"))
	}

	fd.Close()
}

func doTest(t *testing.T, network, listenaddr, dialaddr string) {
	if listenaddr == "" {
		t.Logf("Test %s %s %s\n", network, "<nil>", dialaddr)
	} else {
		t.Logf("Test %s %s %s\n", network, listenaddr, dialaddr)
	}
	listening := make(chan string)
	done := make(chan int)
	if network == "tcp" || network == "tcp4" || network == "tcp6" {
		listenaddr += ":0" // any available port
	}
	go runServe(t, network, listenaddr, listening, done)
	addr := <-listening // wait for server to start
	if network == "tcp" || network == "tcp4" || network == "tcp6" {
		dialaddr += addr[strings.LastIndex(addr, ":"):]
	}
	connect(t, network, dialaddr, false)
	<-done // make sure server stopped
}

func TestTCPServer(t *testing.T) {
	doTest(t, "tcp", "", "127.0.0.1")
	doTest(t, "tcp", "0.0.0.0", "127.0.0.1")
	doTest(t, "tcp", "127.0.0.1", "127.0.0.1")
	doTest(t, "tcp4", "", "127.0.0.1")
	doTest(t, "tcp4", "0.0.0.0", "127.0.0.1")
	doTest(t, "tcp4", "127.0.0.1", "127.0.0.1")
	if supportsIPv6 {
		doTest(t, "tcp", "", "[::1]")
		doTest(t, "tcp", "[::]", "[::1]")
		doTest(t, "tcp", "[::1]", "[::1]")
		doTest(t, "tcp6", "", "[::1]")
		doTest(t, "tcp6", "[::]", "[::1]")
		doTest(t, "tcp6", "[::1]", "[::1]")
	}
	if supportsIPv6 && supportsIPv4map {
		doTest(t, "tcp", "[::ffff:0.0.0.0]", "127.0.0.1")
		doTest(t, "tcp", "[::]", "127.0.0.1")
		doTest(t, "tcp4", "[::ffff:0.0.0.0]", "127.0.0.1")
		doTest(t, "tcp6", "", "127.0.0.1")
		doTest(t, "tcp6", "[::ffff:0.0.0.0]", "127.0.0.1")
		doTest(t, "tcp6", "[::]", "127.0.0.1")
		doTest(t, "tcp", "127.0.0.1", "[::ffff:127.0.0.1]")
		doTest(t, "tcp", "[::ffff:127.0.0.1]", "127.0.0.1")
		doTest(t, "tcp4", "127.0.0.1", "[::ffff:127.0.0.1]")
		doTest(t, "tcp4", "[::ffff:127.0.0.1]", "127.0.0.1")
		doTest(t, "tcp6", "127.0.0.1", "[::ffff:127.0.0.1]")
		doTest(t, "tcp6", "[::ffff:127.0.0.1]", "127.0.0.1")
	}
}

func TestUnixServer(t *testing.T) {
	// "unix" sockets are not supported on windows.
	if runtime.GOOS == "windows" {
		return
	}
	os.Remove("/tmp/gotest.net")
	doTest(t, "unix", "/tmp/gotest.net", "/tmp/gotest.net")
	os.Remove("/tmp/gotest.net")
	if syscall.OS == "linux" {
		doTest(t, "unixpacket", "/tmp/gotest.net", "/tmp/gotest.net")
		os.Remove("/tmp/gotest.net")
		// Test abstract unix domain socket, a Linux-ism
		doTest(t, "unix", "@gotest/net", "@gotest/net")
		doTest(t, "unixpacket", "@gotest/net", "@gotest/net")
	}
}

func runPacket(t *testing.T, network, addr string, listening chan<- string, done chan<- int) {
	c, err := ListenPacket(network, addr)
	if err != nil {
		t.Fatalf("net.ListenPacket(%q, %q) = _, %v", network, addr, err)
	}
	listening <- c.LocalAddr().String()
	c.SetReadTimeout(10e6) // 10ms
	var buf [1000]byte
Run:
	for {
		n, addr, err := c.ReadFrom(buf[0:])
		if e, ok := err.(Error); ok && e.Timeout() {
			select {
			case done <- 1:
				break Run
			default:
				continue Run
			}
		}
		if err != nil {
			break
		}
		if _, err = c.WriteTo(buf[0:n], addr); err != nil {
			t.Fatalf("WriteTo %v: %v", addr, err)
		}
	}
	c.Close()
	done <- 1
}

func doTestPacket(t *testing.T, network, listenaddr, dialaddr string, isEmpty bool) {
	t.Logf("TestPacket %s %s %s\n", network, listenaddr, dialaddr)
	listening := make(chan string)
	done := make(chan int)
	if network == "udp" {
		listenaddr += ":0" // any available port
	}
	go runPacket(t, network, listenaddr, listening, done)
	addr := <-listening // wait for server to start
	if network == "udp" {
		dialaddr += addr[strings.LastIndex(addr, ":"):]
	}
	connect(t, network, dialaddr, isEmpty)
	<-done // tell server to stop
	<-done // wait for stop
}

func TestUDPServer(t *testing.T) {
	if !*testUDP {
		return
	}
	for _, isEmpty := range []bool{false, true} {
		doTestPacket(t, "udp", "0.0.0.0", "127.0.0.1", isEmpty)
		doTestPacket(t, "udp", "", "127.0.0.1", isEmpty)
		if supportsIPv6 && supportsIPv4map {
			doTestPacket(t, "udp", "[::]", "[::ffff:127.0.0.1]", isEmpty)
			doTestPacket(t, "udp", "[::]", "127.0.0.1", isEmpty)
			doTestPacket(t, "udp", "0.0.0.0", "[::ffff:127.0.0.1]", isEmpty)
		}
	}
}

func TestUnixDatagramServer(t *testing.T) {
	// "unix" sockets are not supported on windows.
	if runtime.GOOS == "windows" {
		return
	}
	for _, isEmpty := range []bool{false} {
		os.Remove("/tmp/gotest1.net")
		os.Remove("/tmp/gotest1.net.local")
		doTestPacket(t, "unixgram", "/tmp/gotest1.net", "/tmp/gotest1.net", isEmpty)
		os.Remove("/tmp/gotest1.net")
		os.Remove("/tmp/gotest1.net.local")
		if syscall.OS == "linux" {
			// Test abstract unix domain socket, a Linux-ism
			doTestPacket(t, "unixgram", "@gotest1/net", "@gotest1/net", isEmpty)
		}
	}
}
<commit_msg>net: stop Mac popups<commit_after>// Copyright 2009 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 net

import (
	"flag"
	"io"
	"os"
	"strings"
	"syscall"
	"testing"
	"runtime"
)

// Do not test empty datagrams by default.
// It causes unexplained timeouts on some systems,
// including Snow Leopard.  I think that the kernel
// doesn't quite expect them.
var testUDP = flag.Bool("udp", false, "whether to test UDP datagrams")

func runEcho(fd io.ReadWriter, done chan<- int) {
	var buf [1024]byte

	for {
		n, err := fd.Read(buf[0:])
		if err != nil || n == 0 || string(buf[:n]) == "END" {
			break
		}
		fd.Write(buf[0:n])
	}
	done <- 1
}

func runServe(t *testing.T, network, addr string, listening chan<- string, done chan<- int) {
	l, err := Listen(network, addr)
	if err != nil {
		t.Fatalf("net.Listen(%q, %q) = _, %v", network, addr, err)
	}
	listening <- l.Addr().String()

	for {
		fd, err := l.Accept()
		if err != nil {
			break
		}
		echodone := make(chan int)
		go runEcho(fd, echodone)
		<-echodone // make sure Echo stops
		l.Close()
	}
	done <- 1
}

func connect(t *testing.T, network, addr string, isEmpty bool) {
	var fd Conn
	var err os.Error
	if network == "unixgram" {
		fd, err = DialUnix(network, &UnixAddr{addr + ".local", network}, &UnixAddr{addr, network})
	} else {
		fd, err = Dial(network, addr)
	}
	if err != nil {
		t.Fatalf("net.Dial(%q, %q) = _, %v", network, addr, err)
	}
	fd.SetReadTimeout(1e9) // 1s

	var b []byte
	if !isEmpty {
		b = []byte("hello, world\n")
	}
	var b1 [100]byte

	n, err1 := fd.Write(b)
	if n != len(b) {
		t.Fatalf("fd.Write(%q) = %d, %v", b, n, err1)
	}

	n, err1 = fd.Read(b1[0:])
	if n != len(b) || err1 != nil {
		t.Fatalf("fd.Read() = %d, %v (want %d, nil)", n, err1, len(b))
	}

	// Send explicit ending for unixpacket.
	// Older Linux kernels do stop reads on close.
	if network == "unixpacket" {
		fd.Write([]byte("END"))
	}

	fd.Close()
}

func doTest(t *testing.T, network, listenaddr, dialaddr string) {
	t.Logf("Test %q %q %q\n", network, listenaddr, dialaddr)
	switch listenaddr {
	case "", "0.0.0.0", "[::]", "[::ffff:0.0.0.0]":
		if testing.Short() || avoidMacFirewall {
			t.Logf("skip wildcard listen during short test")
			return
		}
	}
	listening := make(chan string)
	done := make(chan int)
	if network == "tcp" || network == "tcp4" || network == "tcp6" {
		listenaddr += ":0" // any available port
	}
	go runServe(t, network, listenaddr, listening, done)
	addr := <-listening // wait for server to start
	if network == "tcp" || network == "tcp4" || network == "tcp6" {
		dialaddr += addr[strings.LastIndex(addr, ":"):]
	}
	connect(t, network, dialaddr, false)
	<-done // make sure server stopped
}

func TestTCPServer(t *testing.T) {
	doTest(t, "tcp", "", "127.0.0.1")
	doTest(t, "tcp", "0.0.0.0", "127.0.0.1")
	doTest(t, "tcp", "127.0.0.1", "127.0.0.1")
	doTest(t, "tcp4", "", "127.0.0.1")
	doTest(t, "tcp4", "0.0.0.0", "127.0.0.1")
	doTest(t, "tcp4", "127.0.0.1", "127.0.0.1")
	if supportsIPv6 {
		doTest(t, "tcp", "", "[::1]")
		doTest(t, "tcp", "[::]", "[::1]")
		doTest(t, "tcp", "[::1]", "[::1]")
		doTest(t, "tcp6", "", "[::1]")
		doTest(t, "tcp6", "[::]", "[::1]")
		doTest(t, "tcp6", "[::1]", "[::1]")
	}
	if supportsIPv6 && supportsIPv4map {
		doTest(t, "tcp", "[::ffff:0.0.0.0]", "127.0.0.1")
		doTest(t, "tcp", "[::]", "127.0.0.1")
		doTest(t, "tcp4", "[::ffff:0.0.0.0]", "127.0.0.1")
		doTest(t, "tcp6", "", "127.0.0.1")
		doTest(t, "tcp6", "[::ffff:0.0.0.0]", "127.0.0.1")
		doTest(t, "tcp6", "[::]", "127.0.0.1")
		doTest(t, "tcp", "127.0.0.1", "[::ffff:127.0.0.1]")
		doTest(t, "tcp", "[::ffff:127.0.0.1]", "127.0.0.1")
		doTest(t, "tcp4", "127.0.0.1", "[::ffff:127.0.0.1]")
		doTest(t, "tcp4", "[::ffff:127.0.0.1]", "127.0.0.1")
		doTest(t, "tcp6", "127.0.0.1", "[::ffff:127.0.0.1]")
		doTest(t, "tcp6", "[::ffff:127.0.0.1]", "127.0.0.1")
	}
}

func TestUnixServer(t *testing.T) {
	// "unix" sockets are not supported on windows.
	if runtime.GOOS == "windows" {
		return
	}
	os.Remove("/tmp/gotest.net")
	doTest(t, "unix", "/tmp/gotest.net", "/tmp/gotest.net")
	os.Remove("/tmp/gotest.net")
	if syscall.OS == "linux" {
		doTest(t, "unixpacket", "/tmp/gotest.net", "/tmp/gotest.net")
		os.Remove("/tmp/gotest.net")
		// Test abstract unix domain socket, a Linux-ism
		doTest(t, "unix", "@gotest/net", "@gotest/net")
		doTest(t, "unixpacket", "@gotest/net", "@gotest/net")
	}
}

func runPacket(t *testing.T, network, addr string, listening chan<- string, done chan<- int) {
	c, err := ListenPacket(network, addr)
	if err != nil {
		t.Fatalf("net.ListenPacket(%q, %q) = _, %v", network, addr, err)
	}
	listening <- c.LocalAddr().String()
	c.SetReadTimeout(10e6) // 10ms
	var buf [1000]byte
Run:
	for {
		n, addr, err := c.ReadFrom(buf[0:])
		if e, ok := err.(Error); ok && e.Timeout() {
			select {
			case done <- 1:
				break Run
			default:
				continue Run
			}
		}
		if err != nil {
			break
		}
		if _, err = c.WriteTo(buf[0:n], addr); err != nil {
			t.Fatalf("WriteTo %v: %v", addr, err)
		}
	}
	c.Close()
	done <- 1
}

func doTestPacket(t *testing.T, network, listenaddr, dialaddr string, isEmpty bool) {
	t.Logf("TestPacket %s %s %s\n", network, listenaddr, dialaddr)
	listening := make(chan string)
	done := make(chan int)
	if network == "udp" {
		listenaddr += ":0" // any available port
	}
	go runPacket(t, network, listenaddr, listening, done)
	addr := <-listening // wait for server to start
	if network == "udp" {
		dialaddr += addr[strings.LastIndex(addr, ":"):]
	}
	connect(t, network, dialaddr, isEmpty)
	<-done // tell server to stop
	<-done // wait for stop
}

func TestUDPServer(t *testing.T) {
	if !*testUDP {
		return
	}
	for _, isEmpty := range []bool{false, true} {
		doTestPacket(t, "udp", "0.0.0.0", "127.0.0.1", isEmpty)
		doTestPacket(t, "udp", "", "127.0.0.1", isEmpty)
		if supportsIPv6 && supportsIPv4map {
			doTestPacket(t, "udp", "[::]", "[::ffff:127.0.0.1]", isEmpty)
			doTestPacket(t, "udp", "[::]", "127.0.0.1", isEmpty)
			doTestPacket(t, "udp", "0.0.0.0", "[::ffff:127.0.0.1]", isEmpty)
		}
	}
}

func TestUnixDatagramServer(t *testing.T) {
	// "unix" sockets are not supported on windows.
	if runtime.GOOS == "windows" {
		return
	}
	for _, isEmpty := range []bool{false} {
		os.Remove("/tmp/gotest1.net")
		os.Remove("/tmp/gotest1.net.local")
		doTestPacket(t, "unixgram", "/tmp/gotest1.net", "/tmp/gotest1.net", isEmpty)
		os.Remove("/tmp/gotest1.net")
		os.Remove("/tmp/gotest1.net.local")
		if syscall.OS == "linux" {
			// Test abstract unix domain socket, a Linux-ism
			doTestPacket(t, "unixgram", "@gotest1/net", "@gotest1/net", isEmpty)
		}
	}
}
<|endoftext|>


<commit_before>package zfs

import "errors"
import "fmt"
import "io"
import "path"
import "path/filepath"
import "strings"

import "../run"

func ZPools() ([]string, error) {
	return run.Command("/sbin/zpool", "list", "-Hp", "-oname").OutputLines()
}

func zfs(command string, args []string) *run.Cmd {
	return run.Command("/sbin/zfs", append([]string{command}, args...)...)
}

func zfsHp(command string, args []string) *run.Cmd {
	return zfs(command, append([]string{"-Hp"}, args...))
}

func Zfs(cmd string, args ...string) error {
	return zfs(cmd, args).Run()
}

func ZfsOutput(cmd string, args ...string) (string, error) {
	return zfsHp(cmd, args).OutputString()
}

func ZfsLines(cmd string, args ...string) ([]string, error) {
	return zfsHp(cmd, args).OutputLines()
}

func ZfsFields(cmd string, args ...string) ([][]string, error) {
	if lines, err := ZfsLines(cmd, args...); err != nil {
		return nil, err
	} else {
		rv := make([][]string, len(lines))
		for i, line := range lines {
			rv[i] = strings.Split(line, "\t")
		}
		return rv, nil
	}
}

func ZfsReceive(r io.Reader, args ...string) error {
	return zfs("receive", args).ReadFrom(r).Run()
}

func ZfsSend(w io.Writer, args ...string) error {
	return zfs("send", args).WriteTo(w).Run()
}

type Dataset struct {
	Name       string
	Type       string
	Mounted    bool
	Mountpoint string
	Origin     string
}

func (ds *Dataset) String() string {
	pieces := []string{"ZFS", ds.Type, ds.Name, "unmounted"}
	if ds.Mounted {
		pieces[3] = "mounted"
	}
	if ds.Mountpoint != "" {
		pieces = append(pieces, "at", ds.Mountpoint)
	}
	return strings.Join(pieces, " ")
}

func (ds *Dataset) Zfs(cmd string, args ...string) error {
	return Zfs(cmd, append(args, ds.Name)...)
}

func (ds *Dataset) ZfsOutput(cmd string, args ...string) (string, error) {
	return ZfsOutput(cmd, append(args, ds.Name)...)
}

func (ds *Dataset) ZfsFields(cmd string, args ...string) ([][]string, error) {
	return ZfsFields(cmd, append(args, ds.Name)...)
}

var ErrNotFound = errors.New("Not found")

func ListDatasets(typ string) ([]string, error) {
	if typ == "" {
		typ = "all"
	}
	return ZfsLines("list", "-t"+typ, "-oname")
}

func (ds *Dataset) load() error {
	if props, err := ds.GetMany("type", "mounted", "mountpoint", "origin"); err != nil {
		return err
	} else {
		ds.Type = props["type"]
		if props["mountpoint"] != "none" {
			ds.Mountpoint = props["mountpoint"]
		}
		if props["origin"] != "-" {
			ds.Origin = props["origin"]
		}
		ds.Mounted = (props["mounted"] == "yes")
		return nil
	}
}

func GetDataset(name string) (*Dataset, error) {
	ds := &Dataset{Name: name}
	if err := ds.load(); err != nil {
		// Check if dataset exists
		if dss, err2 := ListDatasets(""); err2 != nil {
			// Can't list datasets, assume original error was not "not
			// found" and return it rather than the new one
			return nil, err
		} else {
			for _, ds := range dss {
				if ds == name {
					// Dataset exists, the error was legit after all
					return nil, err
				}
			}
			return nil, ErrNotFound
		}
	}
	return ds, nil
}

func ReceiveDataset(r io.Reader, name string, mounted bool) (*Dataset, error) {
	var args []string
	if mounted {
		args = []string{name}
	} else {
		args = []string{"-u", name}
	}
	if err := ZfsReceive(r, args...); err != nil {
		return nil, err
	}
	return GetDataset(name)
}

func CreateDataset(name string, args ...string) (*Dataset, error) {
	if err := Zfs("create", append(args, name)...); err != nil {
		return nil, err
	}
	return GetDataset(name)
}

func (ds *Dataset) Get(name string) (string, error) {
	return ds.ZfsOutput("get", "-oproperty", name)
}

func (ds *Dataset) GetMany(attr ...string) (map[string]string, error) {
	attrArg := "all"
	if len(attr) > 0 {
		attrArg = strings.Join(attr, ",")
	}

	if lines, err := ds.ZfsFields("get", "-oproperty,value", attrArg); err != nil {
		return nil, err
	} else {
		rv := make(map[string]string)
		for _, line := range lines {
			rv[line[0]] = line[1]
		}
		return rv, nil
	}
}

func firstError(err1, err2 error) error {
	if err1 == nil {
		return err2
	}
	return err1
}

func (ds *Dataset) Set(name, value string) (err error) {
	if name == "mountpoint" {
		defer func() {
			err = firstError(err, ds.load())
		}()
	}
	return ds.Zfs("set", name+"="+value)
}

func (ds *Dataset) SetMany(attr map[string]string) (err error) {
	reload := false
	args := make([]string, 0, len(attr))
	for k, v := range attr {
		if k == "mountpoint" {
			reload = true
		}
		args = append(args, k+"="+v)
	}
	if reload {
		defer func() {
			err = firstError(err, ds.load())
		}()
	}
	return ds.Zfs("set", args...)
}

func (ds *Dataset) SnapshotName(name string) string {
	return ds.Name + "@" + name
}

func (ds *Dataset) Snapshot(name string, args ...string) (*Dataset, error) {
	name = ds.SnapshotName(name)
	if err := Zfs("snapshot", append(args, name)...); err != nil {
		return nil, err
	} else {
		return GetDataset(name)
	}
}

func (ds *Dataset) GetSnapshot(name string) (*Dataset, error) {
	return GetDataset(ds.SnapshotName(name))
}

func (ds *Dataset) RollbackTo(name string, args ...string) error {
	if snap, err := ds.GetSnapshot(name); err != nil {
		return err
	} else {
		return snap.Rollback(args...)
	}
}

func (ds *Dataset) Send(w io.Writer, args ...string) error {
	if ds.Type != "snapshot" {
		return fmt.Errorf("Not a snapshot: %v", ds)
	}
	return ZfsSend(w, append(args, ds.Name)...)
}

func (ds *Dataset) Clone(name string, args ...string) (*Dataset, error) {
	if ds.Type != "snapshot" {
		return nil, fmt.Errorf("Not a snapshot: %v", ds)
	}
	if err := Zfs("clone", append(args, ds.Name, name)...); err != nil {
		return nil, err
	}
	return GetDataset(name)
}

func (ds *Dataset) Rollback(args ...string) error {
	if ds.Type != "snapshot" {
		return fmt.Errorf("Not a snapshot: %v", ds)
	}
	return ds.Zfs("rollback", args...)
}

func (ds *Dataset) Mount() (err error) {
	defer func() {
		err = firstError(err, ds.load())
	}()
	return ds.Zfs("mount")
}

func (ds *Dataset) Unmount() (err error) {
	defer func() {
		err = firstError(err, ds.load())
	}()
	return ds.Zfs("unmount")
}

func (ds *Dataset) Rename(name string, args ...string) (err error) {
	if err := Zfs("rename", append(args, ds.Name, name)...); err != nil {
		return err
	}
	ds.Name = name
	return ds.load()
}

func (ds *Dataset) ChildName(name string) string {
	return path.Join(ds.Name, name)
}

func (ds *Dataset) GetDataset(name string) (*Dataset, error) {
	return GetDataset(ds.ChildName(name))
}

func (ds *Dataset) CreateDataset(name string, args ...string) (*Dataset, error) {
	return CreateDataset(ds.ChildName(name), args...)
}

func (ds *Dataset) Path(elem ...string) string {
	return filepath.Join(append([]string{ds.Mountpoint}, elem...)...)
}

// depth: -1: self and all descendants (unlimited recursion); 0: only
// all descendants (unlimited recursion); >0: set depth, not include
// self
func (ds *Dataset) Children(depth int, args ...string) ([]*Dataset, error) {
	args = append([]string{"-r", "-oname"}, args...)
	if depth > 0 {
		args[0] = fmt.Sprintf("-d%d", depth)
	}
	if lines, err := ds.ZfsFields("list", args...); err != nil {
		return nil, err
	} else {
		rv := make([]*Dataset, len(lines))
		for i, ln := range lines {
			// TODO: use "zfs get" to get data of all children at the same
			// time and excessive forking
			if ds, err := GetDataset(ln[0]); err != nil {
				return nil, err
			} else {
				rv[i] = ds
			}
		}
		if depth < 0 {
			return rv, nil
		} else {
			return rv[1:], nil
		}
	}
}

func (ds *Dataset) Destroy(flags ...string) error {
	return ds.Zfs("destroy", flags...)
}
<commit_msg>Quiet ZFS commands<commit_after>package zfs

import "errors"
import "fmt"
import "io"
import "path"
import "path/filepath"
import "strings"

import "../run"

func ZPools() ([]string, error) {
	return run.Command("/sbin/zpool", "list", "-Hp", "-oname").OutputLines()
}

func zfs(command string, args []string) *run.Cmd {
	quiet := false
	if command[0] == '@' {
		quiet = true
		command = command[1:]
	}
	cmd := run.Command("/sbin/zfs", append([]string{command}, args...)...)
	if quiet {
		cmd.Cmd.Stderr = nil
	}
	return cmd
}

func zfsHp(command string, args []string) *run.Cmd {
	return zfs(command, append([]string{"-Hp"}, args...))
}

func Zfs(cmd string, args ...string) error {
	return zfs(cmd, args).Run()
}

func ZfsOutput(cmd string, args ...string) (string, error) {
	return zfsHp(cmd, args).OutputString()
}

func ZfsLines(cmd string, args ...string) ([]string, error) {
	return zfsHp(cmd, args).OutputLines()
}

func ZfsFields(cmd string, args ...string) ([][]string, error) {
	if lines, err := ZfsLines(cmd, args...); err != nil {
		return nil, err
	} else {
		rv := make([][]string, len(lines))
		for i, line := range lines {
			rv[i] = strings.Split(line, "\t")
		}
		return rv, nil
	}
}

func ZfsReceive(r io.Reader, args ...string) error {
	return zfs("receive", args).ReadFrom(r).Run()
}

func ZfsSend(w io.Writer, args ...string) error {
	return zfs("send", args).WriteTo(w).Run()
}

type Dataset struct {
	Name       string
	Type       string
	Mounted    bool
	Mountpoint string
	Origin     string
}

func (ds *Dataset) String() string {
	pieces := []string{"ZFS", ds.Type, ds.Name, "unmounted"}
	if ds.Mounted {
		pieces[3] = "mounted"
	}
	if ds.Mountpoint != "" {
		pieces = append(pieces, "at", ds.Mountpoint)
	}
	return strings.Join(pieces, " ")
}

func (ds *Dataset) Zfs(cmd string, args ...string) error {
	return Zfs(cmd, append(args, ds.Name)...)
}

func (ds *Dataset) ZfsOutput(cmd string, args ...string) (string, error) {
	return ZfsOutput(cmd, append(args, ds.Name)...)
}

func (ds *Dataset) ZfsFields(cmd string, args ...string) ([][]string, error) {
	return ZfsFields(cmd, append(args, ds.Name)...)
}

var ErrNotFound = errors.New("Not found")

func ListDatasets(typ string) ([]string, error) {
	if typ == "" {
		typ = "all"
	}
	return ZfsLines("list", "-t"+typ, "-oname")
}

func (ds *Dataset) load() error {
	if props, err := ds.GetMany("type", "mounted", "mountpoint", "origin"); err != nil {
		return err
	} else {
		ds.Type = props["type"]
		if props["mountpoint"] != "none" {
			ds.Mountpoint = props["mountpoint"]
		}
		if props["origin"] != "-" {
			ds.Origin = props["origin"]
		}
		ds.Mounted = (props["mounted"] == "yes")
		return nil
	}
}

func GetDataset(name string) (*Dataset, error) {
	ds := &Dataset{Name: name}
	if err := ds.load(); err != nil {
		// Check if dataset exists
		if dss, err2 := ListDatasets(""); err2 != nil {
			// Can't list datasets, assume original error was not "not
			// found" and return it rather than the new one
			return nil, err
		} else {
			for _, ds := range dss {
				if ds == name {
					// Dataset exists, the error was legit after all
					return nil, err
				}
			}
			return nil, ErrNotFound
		}
	}
	return ds, nil
}

func ReceiveDataset(r io.Reader, name string, mounted bool) (*Dataset, error) {
	var args []string
	if mounted {
		args = []string{name}
	} else {
		args = []string{"-u", name}
	}
	if err := ZfsReceive(r, args...); err != nil {
		return nil, err
	}
	return GetDataset(name)
}

func CreateDataset(name string, args ...string) (*Dataset, error) {
	if err := Zfs("create", append(args, name)...); err != nil {
		return nil, err
	}
	return GetDataset(name)
}

func (ds *Dataset) Get(name string) (string, error) {
	return ds.ZfsOutput("get", "-oproperty", name)
}

func (ds *Dataset) GetMany(attr ...string) (map[string]string, error) {
	attrArg := "all"
	if len(attr) > 0 {
		attrArg = strings.Join(attr, ",")
	}

	if lines, err := ds.ZfsFields("get", "-oproperty,value", attrArg); err != nil {
		return nil, err
	} else {
		rv := make(map[string]string)
		for _, line := range lines {
			rv[line[0]] = line[1]
		}
		return rv, nil
	}
}

func firstError(err1, err2 error) error {
	if err1 == nil {
		return err2
	}
	return err1
}

func (ds *Dataset) Set(name, value string) (err error) {
	if name == "mountpoint" {
		defer func() {
			err = firstError(err, ds.load())
		}()
	}
	return ds.Zfs("set", name+"="+value)
}

func (ds *Dataset) SetMany(attr map[string]string) (err error) {
	reload := false
	args := make([]string, 0, len(attr))
	for k, v := range attr {
		if k == "mountpoint" {
			reload = true
		}
		args = append(args, k+"="+v)
	}
	if reload {
		defer func() {
			err = firstError(err, ds.load())
		}()
	}
	return ds.Zfs("set", args...)
}

func (ds *Dataset) SnapshotName(name string) string {
	return ds.Name + "@" + name
}

func (ds *Dataset) Snapshot(name string, args ...string) (*Dataset, error) {
	name = ds.SnapshotName(name)
	if err := Zfs("snapshot", append(args, name)...); err != nil {
		return nil, err
	} else {
		return GetDataset(name)
	}
}

func (ds *Dataset) GetSnapshot(name string) (*Dataset, error) {
	return GetDataset(ds.SnapshotName(name))
}

func (ds *Dataset) RollbackTo(name string, args ...string) error {
	if snap, err := ds.GetSnapshot(name); err != nil {
		return err
	} else {
		return snap.Rollback(args...)
	}
}

func (ds *Dataset) Send(w io.Writer, args ...string) error {
	if ds.Type != "snapshot" {
		return fmt.Errorf("Not a snapshot: %v", ds)
	}
	return ZfsSend(w, append(args, ds.Name)...)
}

func (ds *Dataset) Clone(name string, args ...string) (*Dataset, error) {
	if ds.Type != "snapshot" {
		return nil, fmt.Errorf("Not a snapshot: %v", ds)
	}
	if err := Zfs("clone", append(args, ds.Name, name)...); err != nil {
		return nil, err
	}
	return GetDataset(name)
}

func (ds *Dataset) Rollback(args ...string) error {
	if ds.Type != "snapshot" {
		return fmt.Errorf("Not a snapshot: %v", ds)
	}
	return ds.Zfs("rollback", args...)
}

func (ds *Dataset) Mount() (err error) {
	defer func() {
		err = firstError(err, ds.load())
	}()
	return ds.Zfs("mount")
}

func (ds *Dataset) Unmount() (err error) {
	defer func() {
		err = firstError(err, ds.load())
	}()
	return ds.Zfs("unmount")
}

func (ds *Dataset) Rename(name string, args ...string) (err error) {
	if err := Zfs("rename", append(args, ds.Name, name)...); err != nil {
		return err
	}
	ds.Name = name
	return ds.load()
}

func (ds *Dataset) ChildName(name string) string {
	return path.Join(ds.Name, name)
}

func (ds *Dataset) GetDataset(name string) (*Dataset, error) {
	return GetDataset(ds.ChildName(name))
}

func (ds *Dataset) CreateDataset(name string, args ...string) (*Dataset, error) {
	return CreateDataset(ds.ChildName(name), args...)
}

func (ds *Dataset) Path(elem ...string) string {
	return filepath.Join(append([]string{ds.Mountpoint}, elem...)...)
}

// depth: -1: self and all descendants (unlimited recursion); 0: only
// all descendants (unlimited recursion); >0: set depth, not include
// self
func (ds *Dataset) Children(depth int, args ...string) ([]*Dataset, error) {
	args = append([]string{"-r", "-oname"}, args...)
	if depth > 0 {
		args[0] = fmt.Sprintf("-d%d", depth)
	}
	if lines, err := ds.ZfsFields("list", args...); err != nil {
		return nil, err
	} else {
		rv := make([]*Dataset, len(lines))
		for i, ln := range lines {
			// TODO: use "zfs get" to get data of all children at the same
			// time and excessive forking
			if ds, err := GetDataset(ln[0]); err != nil {
				return nil, err
			} else {
				rv[i] = ds
			}
		}
		if depth < 0 {
			return rv, nil
		} else {
			return rv[1:], nil
		}
	}
}

func (ds *Dataset) Destroy(flags ...string) error {
	return ds.Zfs("destroy", flags...)
}
<|endoftext|>


<commit_before>package libcarina

import (
	"archive/zip"
	"bytes"
	"crypto/tls"
	"crypto/x509"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"path"
	"reflect"
	"strconv"
	"strings"

	"github.com/rackspace/gophercloud"
	"github.com/rackspace/gophercloud/rackspace"
)

// BetaEndpoint reflects the default endpoint for this library
const BetaEndpoint = "https://mycluster.rackspacecloud.com"
const mimetypeJSON = "application/json"
const authHeaderKey = "X-Auth-Token"
const userAgent = "rackerlabs/libcarina"

// ZipURLResponse is the response that comes back from the zip endpoint
type ZipURLResponse struct {
	URL string `json:"zip_url"`
}

// ClusterClient accesses Carina directly
type ClusterClient struct {
	client   *http.Client
	Username string
	Token    string
	Endpoint string
}

// ErrorResponse is the JSON formatted error response from Carina
type ErrorResponse struct {
	Error string `json:"error"`
}

// Cluster is a cluster
type Cluster struct {
	ClusterName string `json:"cluster_name"`
	Username    string `json:"username"`

	// Flavor of compute to use for cluster, should be a default value currently
	Flavor string `json:"flavor,omitempty"`

	// UUID of image to use for cluster, should be a default value currently
	Image string `json:"image,omitempty"`

	// Node is optional, but allowed on create
	// Sadly it comes back as string instead of int in all cases
	// with the API
	Nodes number `json:"nodes,omitempty"`

	AutoScale bool   `json:"autoscale,omitempty"`
	Status    string `json:"status,omitempty"`
	TaskID    string `json:"task_id,omitempty"`
	Token     string `json:"token,omitempty"`
}

// Credentials holds the keys to the kingdom
type Credentials struct {
	README     []byte
	Cert       []byte
	Key        []byte
	CA         []byte
	CAKey      []byte
	DockerEnv  []byte
	DockerHost string
	Files      map[string][]byte
	UUID       UUID
}

// Specify this type for any struct fields that
// might be unmarshaled from JSON numbers of the following
// types: floats, integers, scientific notation, or strings
type number float64

func (n number) Int64() int64 {
	return int64(n)
}

func (n number) Int() int {
	return int(n)
}

func (n number) Float64() float64 {
	return float64(n)
}

// Required to enforce that string values are attempted to be parsed as numbers
func (n *number) UnmarshalJSON(data []byte) error {
	var f float64
	var err error
	if data[0] == '"' {
		f, err = strconv.ParseFloat(string(data[1:len(data)-1]), 64)
		if err != nil {
			return &json.UnmarshalTypeError{
				Value: string(data),
				Type:  reflect.TypeOf(*n),
			}
		}
	} else {
		if err := json.Unmarshal(data, &f); err != nil {
			return &json.UnmarshalTypeError{
				Value: string(data),
				Type:  reflect.TypeOf(*n),
			}
		}
	}
	*n = number(f)
	return nil
}

func newClusterClient(endpoint string, ao gophercloud.AuthOptions) (*ClusterClient, error) {
	provider, err := rackspace.AuthenticatedClient(ao)
	if err != nil {
		return nil, err
	}

	return &ClusterClient{
		client:   &http.Client{},
		Username: ao.Username,
		Token:    provider.TokenID,
		Endpoint: endpoint,
	}, nil
}

// NewClusterClient create a new clusterclient by API Key
func NewClusterClient(endpoint, username, apikey string) (*ClusterClient, error) {
	ao := gophercloud.AuthOptions{
		Username:         username,
		APIKey:           apikey,
		IdentityEndpoint: rackspace.RackspaceUSIdentity,
	}

	return newClusterClient(endpoint, ao)
}

// NewRequest handles a request using auth used by Carina
func (c *ClusterClient) NewRequest(method string, uri string, body io.Reader) (*http.Response, error) {
	req, err := http.NewRequest(method, c.Endpoint+uri, body)
	if err != nil {
		return nil, err
	}
	req.Header.Set("User-Agent", userAgent)
	req.Header.Add("Content-Type", mimetypeJSON)
	req.Header.Add(authHeaderKey, c.Token)
	resp, err := c.client.Do(req)
	if err != nil {
		return nil, err
	}

	if resp.StatusCode >= 400 {
		b, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return nil, errors.New(resp.Status)
		}
		return nil, errors.New(string(b))
	}

	return resp, nil
}

// List the current clusters
func (c *ClusterClient) List() ([]Cluster, error) {
	clusters := []Cluster{}

	resp, err := c.NewRequest("GET", "/clusters/"+c.Username, nil)
	if err != nil {
		return nil, err
	}

	err = json.NewDecoder(resp.Body).Decode(&clusters)
	if err != nil {
		return nil, err
	}
	return clusters, nil
}

func clusterFromResponse(resp *http.Response, err error) (*Cluster, error) {
	if err != nil {
		return nil, err
	}
	cluster := new(Cluster)
	err = json.NewDecoder(resp.Body).Decode(&cluster)
	if err != nil {
		return nil, err
	}
	return cluster, nil
}

// Get a cluster by cluster name
func (c *ClusterClient) Get(clusterName string) (*Cluster, error) {
	uri := path.Join("/clusters", c.Username, clusterName)
	resp, err := c.NewRequest("GET", uri, nil)
	return clusterFromResponse(resp, err)
}

// Create a new cluster with cluster options
func (c *ClusterClient) Create(clusterOpts Cluster) (*Cluster, error) {
	// Even though username is in the URI path, the API expects the username
	// inside the body
	if clusterOpts.Username == "" {
		clusterOpts.Username = c.Username
	}
	clusterOptsJSON, err := json.Marshal(clusterOpts)
	if err != nil {
		return nil, err
	}

	body := bytes.NewReader(clusterOptsJSON)
	uri := path.Join("/clusters", c.Username)
	resp, err := c.NewRequest("POST", uri, body)
	return clusterFromResponse(resp, err)
}

// GetZipURL returns the URL for downloading credentials
func (c *ClusterClient) GetZipURL(clusterName string) (string, error) {
	uri := path.Join("/clusters", c.Username, clusterName, "zip")
	resp, err := c.NewRequest("GET", uri, nil)
	if err != nil {
		return "", err
	}

	var zipURLResp ZipURLResponse

	err = json.NewDecoder(resp.Body).Decode(&zipURLResp)

	if err != nil {
		return "", err
	}

	return zipURLResp.URL, nil
}

// UUID represents a UUID value. UUIDs can be compared and set to other values
// and accessed by byte.
type UUID [16]byte

func extractUUID(s string) (UUID, error) {
	s = strings.Trim(s, "/")
	var u UUID
	var err error

	if len(s) != 36 {
		return UUID{}, fmt.Errorf("Invalid UUID")
	}
	format := "%08x-%04x-%04x-%04x-%012x"

	// create stack addresses for each section of the uuid.
	p := make([][]byte, 5)

	if _, err := fmt.Sscanf(s, format, &p[0], &p[1], &p[2], &p[3], &p[4]); err != nil {
		return u, err
	}

	copy(u[0:4], p[0])
	copy(u[4:6], p[1])
	copy(u[6:8], p[2])
	copy(u[8:10], p[3])
	copy(u[10:16], p[4])

	return u, err
}

// GetCredentials returns a Credentials struct for the given cluster name
func (c *ClusterClient) GetCredentials(clusterName string) (*Credentials, error) {
	url, err := c.GetZipURL(clusterName)
	if err != nil {
		return nil, err
	}
	zr, err := fetchZip(url)
	if err != nil || len(zr.File) < 6 {
		return nil, err
	}

	// fetch the contents for each credential/note
	creds := new(Credentials)
	creds.Files = make(map[string][]byte)
	for _, zf := range zr.File {
		// dir should be the UUID that comes out in the bundle
		dir, fname := path.Split(zf.Name)
		fi := zf.FileInfo()

		if fi.IsDir() {
			// get uuid that's part of the zip dump
			creds.UUID, err = extractUUID(dir)
			if err != nil {
				return nil, errors.New("Unable to read UUID from directory name in zip file: " + err.Error())
			}
			continue
		}

		rc, err := zf.Open()
		if err != nil {
			return nil, err
		}

		b, err := ioutil.ReadAll(rc)
		if err != nil {
			return nil, err
		}
		creds.Files[fname] = b

		switch fname {
		case "ca.pem":
			creds.CA = b
		case "README.md":
			creds.README = b
		case "ca-key.pem":
			creds.CAKey = b
		case "docker.env":
			creds.DockerEnv = b
		case "cert.pem":
			creds.Cert = b
		case "key.pem":
			creds.Key = b
		}
	}

	sourceLines := strings.Split(string(creds.DockerEnv), "\n")
	for _, line := range sourceLines {
		if strings.Index(line, "export ") == 0 {
			varDecl := strings.TrimRight(line[7:], "\n")
			eqLocation := strings.Index(varDecl, "=")

			varName := varDecl[:eqLocation]
			varValue := varDecl[eqLocation+1:]

			switch varName {
			case "DOCKER_HOST":
				creds.DockerHost = varValue
			}

		}
	}

	return creds, nil
}

// GetDockerConfig returns the hostname and tls.Config for a given clustername
func (c *ClusterClient) GetDockerConfig(clusterName string) (hostname string, tlsConfig *tls.Config, err error) {
	creds, err := c.GetCredentials(clusterName)
	if err != nil {
		return "", nil, err
	}
	tlsConfig, err = creds.GetTLSConfig()
	return creds.DockerHost, tlsConfig, err
}

// GetTLSConfig returns a tls.Config for a credential set
func (creds *Credentials) GetTLSConfig() (*tls.Config, error) {
	// TLS config
	var tlsConfig tls.Config
	tlsConfig.InsecureSkipVerify = true
	certPool := x509.NewCertPool()

	certPool.AppendCertsFromPEM(creds.CA)
	tlsConfig.RootCAs = certPool
	keypair, err := tls.X509KeyPair(creds.Cert, creds.Key)
	if err != nil {
		return &tlsConfig, err
	}
	tlsConfig.Certificates = []tls.Certificate{keypair}

	return &tlsConfig, nil
}

func fetchZip(zipurl string) (*zip.Reader, error) {
	req, err := http.NewRequest("GET", zipurl, nil)
	if err != nil {
		return nil, err
	}

	req.Header.Set("User-Agent", userAgent)

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		b, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return nil, errors.New(resp.Status)
		}
		return nil, errors.New(string(b))
	}

	buf := &bytes.Buffer{}

	_, err = io.Copy(buf, resp.Body)
	if err != nil {
		return nil, err
	}

	b := bytes.NewReader(buf.Bytes())
	return zip.NewReader(b, int64(b.Len()))
}

// Grow increases a cluster by the provided number of nodes
func (c *ClusterClient) Grow(clusterName string, nodes int) (*Cluster, error) {
	incr := map[string]int{
		"nodes": nodes,
	}

	growthRequest, err := json.Marshal(incr)
	if err != nil {
		return nil, err
	}
	r := bytes.NewReader(growthRequest)

	uri := path.Join("/clusters", c.Username, clusterName, "grow")
	resp, err := c.NewRequest("POST", uri, r)
	return clusterFromResponse(resp, err)
}

// Delete nukes a cluster out of existence
func (c *ClusterClient) Delete(clusterName string) (*Cluster, error) {
	uri := path.Join("/clusters", c.Username, clusterName)
	resp, err := c.NewRequest("DELETE", uri, nil)
	return clusterFromResponse(resp, err)
}
<commit_msg>Export the `Number` type.<commit_after>package libcarina

import (
	"archive/zip"
	"bytes"
	"crypto/tls"
	"crypto/x509"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"path"
	"reflect"
	"strconv"
	"strings"

	"github.com/rackspace/gophercloud"
	"github.com/rackspace/gophercloud/rackspace"
)

// BetaEndpoint reflects the default endpoint for this library
const BetaEndpoint = "https://mycluster.rackspacecloud.com"
const mimetypeJSON = "application/json"
const authHeaderKey = "X-Auth-Token"
const userAgent = "rackerlabs/libcarina"

// ZipURLResponse is the response that comes back from the zip endpoint
type ZipURLResponse struct {
	URL string `json:"zip_url"`
}

// ClusterClient accesses Carina directly
type ClusterClient struct {
	client   *http.Client
	Username string
	Token    string
	Endpoint string
}

// ErrorResponse is the JSON formatted error response from Carina
type ErrorResponse struct {
	Error string `json:"error"`
}

// Cluster is a cluster
type Cluster struct {
	ClusterName string `json:"cluster_name"`
	Username    string `json:"username"`

	// Flavor of compute to use for cluster, should be a default value currently
	Flavor string `json:"flavor,omitempty"`

	// UUID of image to use for cluster, should be a default value currently
	Image string `json:"image,omitempty"`

	// Node is optional, but allowed on create
	// Sadly it comes back as string instead of int in all cases
	// with the API
	Nodes Number `json:"nodes,omitempty"`

	AutoScale bool   `json:"autoscale,omitempty"`
	Status    string `json:"status,omitempty"`
	TaskID    string `json:"task_id,omitempty"`
	Token     string `json:"token,omitempty"`
}

// Credentials holds the keys to the kingdom
type Credentials struct {
	README     []byte
	Cert       []byte
	Key        []byte
	CA         []byte
	CAKey      []byte
	DockerEnv  []byte
	DockerHost string
	Files      map[string][]byte
	UUID       UUID
}

// Number - specify this type for any struct fields that
// might be unmarshaled from JSON numbers of the following
// types: floats, integers, scientific notation, or strings
type Number float64

// Int64 return the Int64 version of this
func (n Number) Int64() int64 {
	return int64(n)
}

// Int return the Int version of this
func (n Number) Int() int {
	return int(n)
}

// Float64 return the Float64 version of this
func (n Number) Float64() float64 {
	return float64(n)
}

// UnmarshalJSON required to enforce that string values are attempted to be parsed as numbers
func (n *Number) UnmarshalJSON(data []byte) error {
	var f float64
	var err error
	if data[0] == '"' {
		f, err = strconv.ParseFloat(string(data[1:len(data)-1]), 64)
		if err != nil {
			return &json.UnmarshalTypeError{
				Value: string(data),
				Type:  reflect.TypeOf(*n),
			}
		}
	} else {
		if err := json.Unmarshal(data, &f); err != nil {
			return &json.UnmarshalTypeError{
				Value: string(data),
				Type:  reflect.TypeOf(*n),
			}
		}
	}
	*n = Number(f)
	return nil
}

func newClusterClient(endpoint string, ao gophercloud.AuthOptions) (*ClusterClient, error) {
	provider, err := rackspace.AuthenticatedClient(ao)
	if err != nil {
		return nil, err
	}

	return &ClusterClient{
		client:   &http.Client{},
		Username: ao.Username,
		Token:    provider.TokenID,
		Endpoint: endpoint,
	}, nil
}

// NewClusterClient create a new clusterclient by API Key
func NewClusterClient(endpoint, username, apikey string) (*ClusterClient, error) {
	ao := gophercloud.AuthOptions{
		Username:         username,
		APIKey:           apikey,
		IdentityEndpoint: rackspace.RackspaceUSIdentity,
	}

	return newClusterClient(endpoint, ao)
}

// NewRequest handles a request using auth used by Carina
func (c *ClusterClient) NewRequest(method string, uri string, body io.Reader) (*http.Response, error) {
	req, err := http.NewRequest(method, c.Endpoint+uri, body)
	if err != nil {
		return nil, err
	}
	req.Header.Set("User-Agent", userAgent)
	req.Header.Add("Content-Type", mimetypeJSON)
	req.Header.Add(authHeaderKey, c.Token)
	resp, err := c.client.Do(req)
	if err != nil {
		return nil, err
	}

	if resp.StatusCode >= 400 {
		b, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return nil, errors.New(resp.Status)
		}
		return nil, errors.New(string(b))
	}

	return resp, nil
}

// List the current clusters
func (c *ClusterClient) List() ([]Cluster, error) {
	clusters := []Cluster{}

	resp, err := c.NewRequest("GET", "/clusters/"+c.Username, nil)
	if err != nil {
		return nil, err
	}

	err = json.NewDecoder(resp.Body).Decode(&clusters)
	if err != nil {
		return nil, err
	}
	return clusters, nil
}

func clusterFromResponse(resp *http.Response, err error) (*Cluster, error) {
	if err != nil {
		return nil, err
	}
	cluster := new(Cluster)
	err = json.NewDecoder(resp.Body).Decode(&cluster)
	if err != nil {
		return nil, err
	}
	return cluster, nil
}

// Get a cluster by cluster name
func (c *ClusterClient) Get(clusterName string) (*Cluster, error) {
	uri := path.Join("/clusters", c.Username, clusterName)
	resp, err := c.NewRequest("GET", uri, nil)
	return clusterFromResponse(resp, err)
}

// Create a new cluster with cluster options
func (c *ClusterClient) Create(clusterOpts Cluster) (*Cluster, error) {
	// Even though username is in the URI path, the API expects the username
	// inside the body
	if clusterOpts.Username == "" {
		clusterOpts.Username = c.Username
	}
	clusterOptsJSON, err := json.Marshal(clusterOpts)
	if err != nil {
		return nil, err
	}

	body := bytes.NewReader(clusterOptsJSON)
	uri := path.Join("/clusters", c.Username)
	resp, err := c.NewRequest("POST", uri, body)
	return clusterFromResponse(resp, err)
}

// GetZipURL returns the URL for downloading credentials
func (c *ClusterClient) GetZipURL(clusterName string) (string, error) {
	uri := path.Join("/clusters", c.Username, clusterName, "zip")
	resp, err := c.NewRequest("GET", uri, nil)
	if err != nil {
		return "", err
	}

	var zipURLResp ZipURLResponse

	err = json.NewDecoder(resp.Body).Decode(&zipURLResp)

	if err != nil {
		return "", err
	}

	return zipURLResp.URL, nil
}

// UUID represents a UUID value. UUIDs can be compared and set to other values
// and accessed by byte.
type UUID [16]byte

func extractUUID(s string) (UUID, error) {
	s = strings.Trim(s, "/")
	var u UUID
	var err error

	if len(s) != 36 {
		return UUID{}, fmt.Errorf("Invalid UUID")
	}
	format := "%08x-%04x-%04x-%04x-%012x"

	// create stack addresses for each section of the uuid.
	p := make([][]byte, 5)

	if _, err := fmt.Sscanf(s, format, &p[0], &p[1], &p[2], &p[3], &p[4]); err != nil {
		return u, err
	}

	copy(u[0:4], p[0])
	copy(u[4:6], p[1])
	copy(u[6:8], p[2])
	copy(u[8:10], p[3])
	copy(u[10:16], p[4])

	return u, err
}

// GetCredentials returns a Credentials struct for the given cluster name
func (c *ClusterClient) GetCredentials(clusterName string) (*Credentials, error) {
	url, err := c.GetZipURL(clusterName)
	if err != nil {
		return nil, err
	}
	zr, err := fetchZip(url)
	if err != nil || len(zr.File) < 6 {
		return nil, err
	}

	// fetch the contents for each credential/note
	creds := new(Credentials)
	creds.Files = make(map[string][]byte)
	for _, zf := range zr.File {
		// dir should be the UUID that comes out in the bundle
		dir, fname := path.Split(zf.Name)
		fi := zf.FileInfo()

		if fi.IsDir() {
			// get uuid that's part of the zip dump
			creds.UUID, err = extractUUID(dir)
			if err != nil {
				return nil, errors.New("Unable to read UUID from directory name in zip file: " + err.Error())
			}
			continue
		}

		rc, err := zf.Open()
		if err != nil {
			return nil, err
		}

		b, err := ioutil.ReadAll(rc)
		if err != nil {
			return nil, err
		}
		creds.Files[fname] = b

		switch fname {
		case "ca.pem":
			creds.CA = b
		case "README.md":
			creds.README = b
		case "ca-key.pem":
			creds.CAKey = b
		case "docker.env":
			creds.DockerEnv = b
		case "cert.pem":
			creds.Cert = b
		case "key.pem":
			creds.Key = b
		}
	}

	sourceLines := strings.Split(string(creds.DockerEnv), "\n")
	for _, line := range sourceLines {
		if strings.Index(line, "export ") == 0 {
			varDecl := strings.TrimRight(line[7:], "\n")
			eqLocation := strings.Index(varDecl, "=")

			varName := varDecl[:eqLocation]
			varValue := varDecl[eqLocation+1:]

			switch varName {
			case "DOCKER_HOST":
				creds.DockerHost = varValue
			}

		}
	}

	return creds, nil
}

// GetDockerConfig returns the hostname and tls.Config for a given clustername
func (c *ClusterClient) GetDockerConfig(clusterName string) (hostname string, tlsConfig *tls.Config, err error) {
	creds, err := c.GetCredentials(clusterName)
	if err != nil {
		return "", nil, err
	}
	tlsConfig, err = creds.GetTLSConfig()
	return creds.DockerHost, tlsConfig, err
}

// GetTLSConfig returns a tls.Config for a credential set
func (creds *Credentials) GetTLSConfig() (*tls.Config, error) {
	// TLS config
	var tlsConfig tls.Config
	tlsConfig.InsecureSkipVerify = true
	certPool := x509.NewCertPool()

	certPool.AppendCertsFromPEM(creds.CA)
	tlsConfig.RootCAs = certPool
	keypair, err := tls.X509KeyPair(creds.Cert, creds.Key)
	if err != nil {
		return &tlsConfig, err
	}
	tlsConfig.Certificates = []tls.Certificate{keypair}

	return &tlsConfig, nil
}

func fetchZip(zipurl string) (*zip.Reader, error) {
	req, err := http.NewRequest("GET", zipurl, nil)
	if err != nil {
		return nil, err
	}

	req.Header.Set("User-Agent", userAgent)

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		b, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return nil, errors.New(resp.Status)
		}
		return nil, errors.New(string(b))
	}

	buf := &bytes.Buffer{}

	_, err = io.Copy(buf, resp.Body)
	if err != nil {
		return nil, err
	}

	b := bytes.NewReader(buf.Bytes())
	return zip.NewReader(b, int64(b.Len()))
}

// Grow increases a cluster by the provided number of nodes
func (c *ClusterClient) Grow(clusterName string, nodes int) (*Cluster, error) {
	incr := map[string]int{
		"nodes": nodes,
	}

	growthRequest, err := json.Marshal(incr)
	if err != nil {
		return nil, err
	}
	r := bytes.NewReader(growthRequest)

	uri := path.Join("/clusters", c.Username, clusterName, "grow")
	resp, err := c.NewRequest("POST", uri, r)
	return clusterFromResponse(resp, err)
}

// Delete nukes a cluster out of existence
func (c *ClusterClient) Delete(clusterName string) (*Cluster, error) {
	uri := path.Join("/clusters", c.Username, clusterName)
	resp, err := c.NewRequest("DELETE", uri, nil)
	return clusterFromResponse(resp, err)
}
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2014 William Miller

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

package fedops_truck

import (
  //
  "fmt"
  "os"
  "bytes"
  "errors"
  //
  "github.com/Fedops/lib/providers"
  "github.com/Fedops/lib/engine"
  "github.com/Fedops/lib/engine/container"
  "github.com/Fedops/lib/engine/network"
)

type Truck struct {
  fedops_provider.ProviderVM
  TruckID  string
  Containers []string
}

type TruckDaemon struct {
  fedops_runtime.Runtime
}

func CreateDaemon() *TruckDaemon{
  pwd := os.Getenv("PWD")

  truckDaemon := TruckDaemon{}
  // Set up the default runtime
  truckDaemon.Configure(pwd)
  // Set up the routes for network calls
  err := truckDaemon.AddRoute(fedops_network.FedopsRequestInfo, "^/container$", truckDaemon.ShipContainer)
  if err != nil {
    fmt.Println(err.Error())
  }
  err = truckDaemon.AddRoute(fedops_network.FedopsRequestCreate, "^/container/[A-Za-z0-9]+$", truckDaemon.ShipContainer)
  if err != nil {
    fmt.Println(err.Error())
  }
  err = truckDaemon.AddRoute(fedops_network.FedopsRequestDestroy, "^/container/[A-Za-z0-9]+$", truckDaemon.UnshipContainer)
  if err != nil {
    fmt.Println(err.Error())
  }
  return &truckDaemon
}

func (d *TruckDaemon) ListContainers(req *fedops_network.FedopsRequest, res *fedops_network.FedopsResponse) error {
  args := bytes.Split(req.Route, []byte("/"))
  fmt.Println("LIST", string(req.Data), args)
  return nil
}

func (d *TruckDaemon) ShipContainer(req *fedops_network.FedopsRequest, res *fedops_network.FedopsResponse) error {
  var containerID, warehouseID string
  args := bytes.Split(req.Route, []byte("/"))
  if len(args) > 1 {
    containerID = string(args[1])
  }
  dataArgs := bytes.Split(req.Data, []byte(":"))
  if len(dataArgs) > 0 {
    warehouseID = string(dataArgs[1])
  }

  if containerID == "" {
    return errors.New("Bad ContainerID")
  }
  fmt.Println("SHIP", containerID, warehouseID)

  d.Config.Containers[containerID] = fedops_container.Container{
    ContainerID: containerID,
  }
  return nil
}

func (d *TruckDaemon) UnshipContainer(req *fedops_network.FedopsRequest, res *fedops_network.FedopsResponse) error {
  args := bytes.Split(req.Route, []byte("/"))
  fmt.Println("UNSHIP", string(req.Data), args)
  return nil
}<commit_msg>debug<commit_after>// The MIT License (MIT)

// Copyright (c) 2014 William Miller

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

package fedops_truck

import (
  //
  "fmt"
  "os"
  "bytes"
  "errors"
  //
  "github.com/Fedops/lib/providers"
  "github.com/Fedops/lib/engine"
  "github.com/Fedops/lib/engine/container"
  "github.com/Fedops/lib/engine/network"
)

type Truck struct {
  fedops_provider.ProviderVM
  TruckID  string
  Containers []string
}

type TruckDaemon struct {
  fedops_runtime.Runtime
}

func CreateDaemon() *TruckDaemon{
  pwd := os.Getenv("PWD")

  truckDaemon := TruckDaemon{}
  // Set up the default runtime
  truckDaemon.Configure(pwd)
  // Set up the routes for network calls
  err := truckDaemon.AddRoute(fedops_network.FedopsRequestInfo, "^/container$", truckDaemon.ShipContainer)
  if err != nil {
    fmt.Println(err.Error())
  }
  err = truckDaemon.AddRoute(fedops_network.FedopsRequestCreate, "^/container/[A-Za-z0-9]+$", truckDaemon.ShipContainer)
  if err != nil {
    fmt.Println(err.Error())
  }
  err = truckDaemon.AddRoute(fedops_network.FedopsRequestDestroy, "^/container/[A-Za-z0-9]+$", truckDaemon.UnshipContainer)
  if err != nil {
    fmt.Println(err.Error())
  }
  return &truckDaemon
}

func (d *TruckDaemon) ListContainers(req *fedops_network.FedopsRequest, res *fedops_network.FedopsResponse) error {
  args := bytes.Split(req.Route, []byte("/"))
  fmt.Println("LIST", string(req.Data), args)
  return nil
}

func (d *TruckDaemon) ShipContainer(req *fedops_network.FedopsRequest, res *fedops_network.FedopsResponse) error {
  var containerID, warehouseID string
  args := bytes.Split(req.Route, []byte("/"))
  if len(args) > 1 {
    containerID = string(args[1])
  }
  dataArgs := bytes.Split(req.Data, []byte(":"))
  fmt.Println(dataArgs)
  if len(dataArgs) > 0 {
    warehouseID = string(dataArgs[1])
  }

  if containerID == "" {
    return errors.New("Bad ContainerID")
  }
  fmt.Println("SHIP", containerID, warehouseID)

  d.Config.Containers[containerID] = fedops_container.Container{
    ContainerID: containerID,
  }
  return nil
}

func (d *TruckDaemon) UnshipContainer(req *fedops_network.FedopsRequest, res *fedops_network.FedopsResponse) error {
  args := bytes.Split(req.Route, []byte("/"))
  fmt.Println("UNSHIP", string(req.Data), args)
  return nil
}<|endoftext|>


<commit_before>package timezone

import (
	"fmt"
	"testing"
)

var validCodes = []Timezone{
	{"Europe/Helsinki", "FI", "Finland"},
}

func TestCode(t *testing.T) {

	for _, timezone := range validCodes {

		z, err := Code(timezone.Code)
		if err != nil {
			t.Errorf("%s should have been found, but was not", timezone.Code)
		}
		if len(z) != 1 {
			t.Errorf("%s len should been %d, but it was d", timezone.Location, 1, len(z))
		}
		if z[0].Location != timezone.Location {
			t.Errorf("Location for %s should have been %s, but it was %s", timezone.Code, timezone.Location, z[0].Location)
		}

	}

}

var validLocations = []string{
	"Europe/Helsinki",
}

func TestValidLocation(t *testing.T) {
	for _, loc := range validLocations {
		if !ValidLocation(loc) {
			t.Errorf("%s should have been valid location", loc)
		}
	}
}

func ExampleValidLocation() {
	fmt.Println(ValidLocation("Europe/Helsinki"))
	// Output: true
}

var invalidLocations = []string{
	"Europe/Oulu",
	"FI",
}

func TestInvalidLocation(t *testing.T) {
	for _, loc := range invalidLocations {
		if ValidLocation(loc) {
			t.Errorf("%s should not have been valid location", loc)
		}
	}
}

var expectedOffsets = []int{
	10800,
}

func TestOffset(t *testing.T) {
	for i, expectedOffset := range expectedOffsets {
		zone, offset, err := Offset(validLocations[i])
		if zone != "EEST" {
			t.Errorf("zone of %s should have been %s", validLocations[i], zone)
		}
		if expectedOffset != offset {
			t.Errorf("offset of %s should have been %s", validLocations[i], offset)
		}
		if err != nil {
			t.Errorf("running Offset of %s should not return error, but returned %s", validLocations[i], err)
		}
	}
}

func ExampleOffset() {
	zone, offset, _ := Offset("Europe/Helsinki")
	fmt.Println(zone, offset)
	// Output: EEST 10800
}

func TestCountry(t *testing.T) {
	z, _ := Country("Finland")
	if len(z) != 1 {
		t.Errorf("expected length of Finland to be 1, got %d", len(z))
	}
	if z[0].Code != "FI" {
		t.Errorf("country code of Finland should have been FI, got %s", z[0].Code)
	}
	if z[0].Location != "Europe/Helsinki" {
		t.Errorf("location of Finland should have been Europe/Helsinki, got %s", z[0].Location)
	}
}
<commit_msg>update tests to reflect current time<commit_after>package timezone

import (
	"fmt"
	"testing"
)

var validCodes = []Timezone{
	{"Europe/Helsinki", "FI", "Finland"},
}

func TestCode(t *testing.T) {

	for _, timezone := range validCodes {

		z, err := Code(timezone.Code)
		if err != nil {
			t.Errorf("%s should have been found, but was not", timezone.Code)
		}
		if len(z) != 1 {
			t.Errorf("%s len should been %d, but it was d", timezone.Location, 1, len(z))
		}
		if z[0].Location != timezone.Location {
			t.Errorf("Location for %s should have been %s, but it was %s", timezone.Code, timezone.Location, z[0].Location)
		}

	}

}

var validLocations = []string{
	"Europe/Helsinki",
}

func TestValidLocation(t *testing.T) {
	for _, loc := range validLocations {
		if !ValidLocation(loc) {
			t.Errorf("%s should have been valid location", loc)
		}
	}
}

func ExampleValidLocation() {
	fmt.Println(ValidLocation("Europe/Helsinki"))
	// Output: true
}

var invalidLocations = []string{
	"Europe/Oulu",
	"FI",
}

func TestInvalidLocation(t *testing.T) {
	for _, loc := range invalidLocations {
		if ValidLocation(loc) {
			t.Errorf("%s should not have been valid location", loc)
		}
	}
}

var expectedOffsets = []int{
	7200,
}

func TestOffset(t *testing.T) {
	for i, expectedOffset := range expectedOffsets {
		zone, offset, err := Offset(validLocations[i])
		if zone != "EET" {
			t.Errorf("zone of %s should have been %s", validLocations[i], zone)
		}
		if expectedOffset != offset {
			t.Errorf("offset of %s should have been %s", validLocations[i], offset)
		}
		if err != nil {
			t.Errorf("running Offset of %s should not return error, but returned %s", validLocations[i], err)
		}
	}
}

func ExampleOffset() {
	zone, offset, _ := Offset("Europe/Helsinki")
	fmt.Println(zone, offset)
	// Output: EET 7200
}

func TestCountry(t *testing.T) {
	z, _ := Country("Finland")
	if len(z) != 1 {
		t.Errorf("expected length of Finland to be 1, got %d", len(z))
	}
	if z[0].Code != "FI" {
		t.Errorf("country code of Finland should have been FI, got %s", z[0].Code)
	}
	if z[0].Location != "Europe/Helsinki" {
		t.Errorf("location of Finland should have been Europe/Helsinki, got %s", z[0].Location)
	}
}
<|endoftext|>