<commit_before>/*
 *
 * Copyright 2014, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

package grpc

import (
	"errors"
	"fmt"
	"net"
	"strings"
	"sync"
	"time"

	"golang.org/x/net/context"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/grpclog"
	"google.golang.org/grpc/transport"
)

var (
	// ErrUnspecTarget indicates that the target address is unspecified.
	ErrUnspecTarget = errors.New("grpc: target is unspecified")
	// ErrNoTransportSecurity indicates that there is no transport security
	// being set for ClientConn. Users should either set one or explicityly
	// call WithInsecure DialOption to disable security.
	ErrNoTransportSecurity = errors.New("grpc: no transport security set (use grpc.WithInsecure() explicitly or set credentials)")
	// ErrCredentialsMisuse indicates that users want to transmit security infomation
	// (e.g., oauth2 token) which requires secure connection on an insecure
	// connection.
	ErrCredentialsMisuse = errors.New("grpc: the credentials require transport level security (use grpc.WithTransportAuthenticator() to set)")
	// ErrClientConnClosing indicates that the operation is illegal because
	// the session is closing.
	ErrClientConnClosing = errors.New("grpc: the client connection is closing")
	// ErrClientConnTimeout indicates that the connection could not be
	// established or re-established within the specified timeout.
	ErrClientConnTimeout = errors.New("grpc: timed out trying to connect")
	// minimum time to give a connection to complete
	minConnectTimeout = 20 * time.Second
)

// dialOptions configure a Dial call. dialOptions are set by the DialOption
// values passed to Dial.
type dialOptions struct {
	codec    Codec
	block    bool
	insecure bool
	copts    transport.ConnectOptions
}

// DialOption configures how we set up the connection.
type DialOption func(*dialOptions)

// WithCodec returns a DialOption which sets a codec for message marshaling and unmarshaling.
func WithCodec(c Codec) DialOption {
	return func(o *dialOptions) {
		o.codec = c
	}
}

// WithBlock returns a DialOption which makes caller of Dial blocks until the underlying
// connection is up. Without this, Dial returns immediately and connecting the server
// happens in background.
func WithBlock() DialOption {
	return func(o *dialOptions) {
		o.block = true
	}
}

func WithInsecure() DialOption {
	return func(o *dialOptions) {
		o.insecure = true
	}
}

// WithTransportCredentials returns a DialOption which configures a
// connection level security credentials (e.g., TLS/SSL).
func WithTransportCredentials(creds credentials.TransportAuthenticator) DialOption {
	return func(o *dialOptions) {
		o.copts.AuthOptions = append(o.copts.AuthOptions, creds)
	}
}

// WithPerRPCCredentials returns a DialOption which sets
// credentials which will place auth state on each outbound RPC.
func WithPerRPCCredentials(creds credentials.Credentials) DialOption {
	return func(o *dialOptions) {
		o.copts.AuthOptions = append(o.copts.AuthOptions, creds)
	}
}

// WithTimeout returns a DialOption that configures a timeout for dialing a client connection.
func WithTimeout(d time.Duration) DialOption {
	return func(o *dialOptions) {
		o.copts.Timeout = d
	}
}

// WithDialer returns a DialOption that specifies a function to use for dialing network addresses.
func WithDialer(f func(addr string, timeout time.Duration) (net.Conn, error)) DialOption {
	return func(o *dialOptions) {
		o.copts.Dialer = f
	}
}

// WithUserAgent returns a DialOption that specifies a user agent string for all the RPCs.
func WithUserAgent(s string) DialOption {
	return func(o *dialOptions) {
		o.copts.UserAgent = s
	}
}

// Dial creates a client connection the given target.
func Dial(target string, opts ...DialOption) (*ClientConn, error) {
	if target == "" {
		return nil, ErrUnspecTarget
	}
	cc := &ClientConn{
		target:       target,
		shutdownChan: make(chan struct{}),
	}
	for _, opt := range opts {
		opt(&cc.dopts)
	}
	if !cc.dopts.insecure {
		var ok bool
		for _, c := range cc.dopts.copts.AuthOptions {
			if _, ok := c.(credentials.TransportAuthenticator); !ok {
				continue
			}
			ok = true
		}
		if !ok {
			return nil, ErrNoTransportSecurity
		}
	} else {
		for _, c := range cc.dopts.copts.AuthOptions {
			if c.RequireTransportSecurity() {
				return nil, ErrCredentialsMisuse
			}
		}
	}
	colonPos := strings.LastIndex(target, ":")
	if colonPos == -1 {
		colonPos = len(target)
	}
	cc.authority = target[:colonPos]
	if cc.dopts.codec == nil {
		// Set the default codec.
		cc.dopts.codec = protoCodec{}
	}
	cc.stateCV = sync.NewCond(&cc.mu)
	if cc.dopts.block {
		if err := cc.resetTransport(false); err != nil {
			cc.Close()
			return nil, err
		}
		// Start to monitor the error status of transport.
		go cc.transportMonitor()
	} else {
		// Start a goroutine connecting to the server asynchronously.
		go func() {
			if err := cc.resetTransport(false); err != nil {
				grpclog.Printf("Failed to dial %s: %v; please retry.", target, err)
				cc.Close()
				return
			}
			go cc.transportMonitor()
		}()
	}
	return cc, nil
}

// ConnectivityState indicates the state of a client connection.
type ConnectivityState int

const (
	// Idle indicates the ClientConn is idle.
	Idle ConnectivityState = iota
	// Connecting indicates the ClienConn is connecting.
	Connecting
	// Ready indicates the ClientConn is ready for work.
	Ready
	// TransientFailure indicates the ClientConn has seen a failure but expects to recover.
	TransientFailure
	// Shutdown indicates the ClientConn has started shutting down.
	Shutdown
)

func (s ConnectivityState) String() string {
	switch s {
	case Idle:
		return "IDLE"
	case Connecting:
		return "CONNECTING"
	case Ready:
		return "READY"
	case TransientFailure:
		return "TRANSIENT_FAILURE"
	case Shutdown:
		return "SHUTDOWN"
	default:
		panic(fmt.Sprintf("unknown connectivity state: %d", s))
	}
}

// ClientConn represents a client connection to an RPC service.
type ClientConn struct {
	target       string
	authority    string
	dopts        dialOptions
	shutdownChan chan struct{}

	mu      sync.Mutex
	state   ConnectivityState
	stateCV *sync.Cond
	// ready is closed and becomes nil when a new transport is up or failed
	// due to timeout.
	ready chan struct{}
	// Every time a new transport is created, this is incremented by 1. Used
	// to avoid trying to recreate a transport while the new one is already
	// under construction.
	transportSeq int
	transport    transport.ClientTransport
}

// State returns the connectivity state of the ClientConn
func (cc *ClientConn) State() ConnectivityState {
	cc.mu.Lock()
	defer cc.mu.Unlock()
	return cc.state
}

// WaitForStateChange blocks until the state changes to something other than the sourceState
// or timeout fires. It returns false if timeout fires and true otherwise.
func (cc *ClientConn) WaitForStateChange(timeout time.Duration, sourceState ConnectivityState) bool {
	start := time.Now()
	cc.mu.Lock()
	defer cc.mu.Unlock()
	if sourceState != cc.state {
		return true
	}
	expired := timeout <= time.Since(start)
	if expired {
		return false
	}
	done := make(chan struct{})
	go func() {
		select {
		case <-time.After(timeout - time.Since(start)):
			cc.mu.Lock()
			expired = true
			cc.stateCV.Broadcast()
			cc.mu.Unlock()
		case <-done:
		}
	}()
	defer close(done)
	for sourceState == cc.state {
		cc.stateCV.Wait()
		if expired {
			return false
		}
	}
	return true
}

func (cc *ClientConn) resetTransport(closeTransport bool) error {
	var retries int
	start := time.Now()
	cc.mu.Lock()
	ts := cc.transportSeq
	// Avoid wait() picking up a dying transport unnecessarily.
	cc.transportSeq = 0
	cc.mu.Unlock()
	for {
		cc.mu.Lock()
		cc.state = Connecting
		cc.stateCV.Broadcast()
		t := cc.transport
		if cc.state == Shutdown {
			cc.mu.Unlock()
			return ErrClientConnClosing
		}
		cc.mu.Unlock()
		if closeTransport {
			t.Close()
		}
		// Adjust timeout for the current try.
		copts := cc.dopts.copts
		if copts.Timeout < 0 {
			cc.Close()
			return ErrClientConnTimeout
		}
		if copts.Timeout > 0 {
			copts.Timeout -= time.Since(start)
			if copts.Timeout <= 0 {
				cc.Close()
				return ErrClientConnTimeout
			}
		}
		sleepTime := backoff(retries)
		timeout := sleepTime
		if timeout < minConnectTimeout {
			timeout = minConnectTimeout
		}
		if copts.Timeout == 0 || copts.Timeout > timeout {
			copts.Timeout = timeout
		}
		connectTime := time.Now()
		newTransport, err := transport.NewClientTransport(cc.target, &copts)
		if err != nil {
			cc.mu.Lock()
			cc.state = TransientFailure
			cc.stateCV.Broadcast()
			cc.mu.Unlock()
			sleepTime -= time.Since(connectTime)
			if sleepTime < 0 {
				sleepTime = 0
			}
			// Fail early before falling into sleep.
			if cc.dopts.copts.Timeout > 0 && cc.dopts.copts.Timeout < sleepTime+time.Since(start) {
				cc.Close()
				return ErrClientConnTimeout
			}
			closeTransport = false
			time.Sleep(sleepTime)
			retries++
			grpclog.Printf("grpc: ClientConn.resetTransport failed to create client transport: %v; Reconnecting to %q", err, cc.target)
			continue
		}
		cc.mu.Lock()
		if cc.state == Shutdown {
			// cc.Close() has been invoked.
			cc.mu.Unlock()
			newTransport.Close()
			return ErrClientConnClosing
		}
		cc.state = Ready
		cc.stateCV.Broadcast()
		cc.transport = newTransport
		cc.transportSeq = ts + 1
		if cc.ready != nil {
			close(cc.ready)
			cc.ready = nil
		}
		cc.mu.Unlock()
		return nil
	}
}

// Run in a goroutine to track the error in transport and create the
// new transport if an error happens. It returns when the channel is closing.
func (cc *ClientConn) transportMonitor() {
	for {
		select {
		// shutdownChan is needed to detect the teardown when
		// the ClientConn is idle (i.e., no RPC in flight).
		case <-cc.shutdownChan:
			return
		case <-cc.transport.Error():
			cc.mu.Lock()
			cc.state = TransientFailure
			cc.stateCV.Broadcast()
			cc.mu.Unlock()
			if err := cc.resetTransport(true); err != nil {
				// The ClientConn is closing.
				grpclog.Printf("grpc: ClientConn.transportMonitor exits due to: %v", err)
				return
			}
			continue
		}
	}
}

// When wait returns, either the new transport is up or ClientConn is
// closing.
func (cc *ClientConn) wait(ctx context.Context) (transport.ClientTransport, error) {
	for {
		cc.mu.Lock()
		switch {
		case cc.state == Shutdown:
			cc.mu.Unlock()
			return nil, ErrClientConnClosing
		case cc.state == Ready:
			cc.mu.Unlock()
			return cc.transport, nil
		default:
			ready := cc.ready
			if ready == nil {
				ready = make(chan struct{})
				cc.ready = ready
			}
			cc.mu.Unlock()
			select {
			case <-ctx.Done():
				return nil, transport.ContextErr(ctx.Err())
			// Wait until the new transport is ready or failed.
			case <-ready:
			}
		}
	}
}

// Close starts to tear down the ClientConn. Returns ErrClientConnClosing if
// it has been closed (mostly due to dial time-out).
// TODO(zhaoq): Make this synchronous to avoid unbounded memory consumption in
// some edge cases (e.g., the caller opens and closes many ClientConn's in a
// tight loop.
func (cc *ClientConn) Close() error {
	cc.mu.Lock()
	defer cc.mu.Unlock()
	if cc.state == Shutdown {
		return ErrClientConnClosing
	}
	cc.state = Shutdown
	cc.stateCV.Broadcast()
	if cc.ready != nil {
		close(cc.ready)
		cc.ready = nil
	}
	if cc.transport != nil {
		cc.transport.Close()
	}
	if cc.shutdownChan != nil {
		close(cc.shutdownChan)
	}
	return nil
}
<commit_msg>remove a dead member var<commit_after>/*
 *
 * Copyright 2014, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

package grpc

import (
	"errors"
	"fmt"
	"net"
	"strings"
	"sync"
	"time"

	"golang.org/x/net/context"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/grpclog"
	"google.golang.org/grpc/transport"
)

var (
	// ErrUnspecTarget indicates that the target address is unspecified.
	ErrUnspecTarget = errors.New("grpc: target is unspecified")
	// ErrNoTransportSecurity indicates that there is no transport security
	// being set for ClientConn. Users should either set one or explicityly
	// call WithInsecure DialOption to disable security.
	ErrNoTransportSecurity = errors.New("grpc: no transport security set (use grpc.WithInsecure() explicitly or set credentials)")
	// ErrCredentialsMisuse indicates that users want to transmit security infomation
	// (e.g., oauth2 token) which requires secure connection on an insecure
	// connection.
	ErrCredentialsMisuse = errors.New("grpc: the credentials require transport level security (use grpc.WithTransportAuthenticator() to set)")
	// ErrClientConnClosing indicates that the operation is illegal because
	// the session is closing.
	ErrClientConnClosing = errors.New("grpc: the client connection is closing")
	// ErrClientConnTimeout indicates that the connection could not be
	// established or re-established within the specified timeout.
	ErrClientConnTimeout = errors.New("grpc: timed out trying to connect")
	// minimum time to give a connection to complete
	minConnectTimeout = 20 * time.Second
)

// dialOptions configure a Dial call. dialOptions are set by the DialOption
// values passed to Dial.
type dialOptions struct {
	codec    Codec
	block    bool
	insecure bool
	copts    transport.ConnectOptions
}

// DialOption configures how we set up the connection.
type DialOption func(*dialOptions)

// WithCodec returns a DialOption which sets a codec for message marshaling and unmarshaling.
func WithCodec(c Codec) DialOption {
	return func(o *dialOptions) {
		o.codec = c
	}
}

// WithBlock returns a DialOption which makes caller of Dial blocks until the underlying
// connection is up. Without this, Dial returns immediately and connecting the server
// happens in background.
func WithBlock() DialOption {
	return func(o *dialOptions) {
		o.block = true
	}
}

func WithInsecure() DialOption {
	return func(o *dialOptions) {
		o.insecure = true
	}
}

// WithTransportCredentials returns a DialOption which configures a
// connection level security credentials (e.g., TLS/SSL).
func WithTransportCredentials(creds credentials.TransportAuthenticator) DialOption {
	return func(o *dialOptions) {
		o.copts.AuthOptions = append(o.copts.AuthOptions, creds)
	}
}

// WithPerRPCCredentials returns a DialOption which sets
// credentials which will place auth state on each outbound RPC.
func WithPerRPCCredentials(creds credentials.Credentials) DialOption {
	return func(o *dialOptions) {
		o.copts.AuthOptions = append(o.copts.AuthOptions, creds)
	}
}

// WithTimeout returns a DialOption that configures a timeout for dialing a client connection.
func WithTimeout(d time.Duration) DialOption {
	return func(o *dialOptions) {
		o.copts.Timeout = d
	}
}

// WithDialer returns a DialOption that specifies a function to use for dialing network addresses.
func WithDialer(f func(addr string, timeout time.Duration) (net.Conn, error)) DialOption {
	return func(o *dialOptions) {
		o.copts.Dialer = f
	}
}

// WithUserAgent returns a DialOption that specifies a user agent string for all the RPCs.
func WithUserAgent(s string) DialOption {
	return func(o *dialOptions) {
		o.copts.UserAgent = s
	}
}

// Dial creates a client connection the given target.
func Dial(target string, opts ...DialOption) (*ClientConn, error) {
	if target == "" {
		return nil, ErrUnspecTarget
	}
	cc := &ClientConn{
		target:       target,
		shutdownChan: make(chan struct{}),
	}
	for _, opt := range opts {
		opt(&cc.dopts)
	}
	if !cc.dopts.insecure {
		var ok bool
		for _, c := range cc.dopts.copts.AuthOptions {
			if _, ok := c.(credentials.TransportAuthenticator); !ok {
				continue
			}
			ok = true
		}
		if !ok {
			return nil, ErrNoTransportSecurity
		}
	} else {
		for _, c := range cc.dopts.copts.AuthOptions {
			if c.RequireTransportSecurity() {
				return nil, ErrCredentialsMisuse
			}
		}
	}
	colonPos := strings.LastIndex(target, ":")
	if colonPos == -1 {
		colonPos = len(target)
	}
	cc.authority = target[:colonPos]
	if cc.dopts.codec == nil {
		// Set the default codec.
		cc.dopts.codec = protoCodec{}
	}
	cc.stateCV = sync.NewCond(&cc.mu)
	if cc.dopts.block {
		if err := cc.resetTransport(false); err != nil {
			cc.Close()
			return nil, err
		}
		// Start to monitor the error status of transport.
		go cc.transportMonitor()
	} else {
		// Start a goroutine connecting to the server asynchronously.
		go func() {
			if err := cc.resetTransport(false); err != nil {
				grpclog.Printf("Failed to dial %s: %v; please retry.", target, err)
				cc.Close()
				return
			}
			go cc.transportMonitor()
		}()
	}
	return cc, nil
}

// ConnectivityState indicates the state of a client connection.
type ConnectivityState int

const (
	// Idle indicates the ClientConn is idle.
	Idle ConnectivityState = iota
	// Connecting indicates the ClienConn is connecting.
	Connecting
	// Ready indicates the ClientConn is ready for work.
	Ready
	// TransientFailure indicates the ClientConn has seen a failure but expects to recover.
	TransientFailure
	// Shutdown indicates the ClientConn has started shutting down.
	Shutdown
)

func (s ConnectivityState) String() string {
	switch s {
	case Idle:
		return "IDLE"
	case Connecting:
		return "CONNECTING"
	case Ready:
		return "READY"
	case TransientFailure:
		return "TRANSIENT_FAILURE"
	case Shutdown:
		return "SHUTDOWN"
	default:
		panic(fmt.Sprintf("unknown connectivity state: %d", s))
	}
}

// ClientConn represents a client connection to an RPC service.
type ClientConn struct {
	target       string
	authority    string
	dopts        dialOptions
	shutdownChan chan struct{}

	mu      sync.Mutex
	state   ConnectivityState
	stateCV *sync.Cond
	// ready is closed and becomes nil when a new transport is up or failed
	// due to timeout.
	ready chan struct{}
	transport    transport.ClientTransport
}

// State returns the connectivity state of the ClientConn
func (cc *ClientConn) State() ConnectivityState {
	cc.mu.Lock()
	defer cc.mu.Unlock()
	return cc.state
}

// WaitForStateChange blocks until the state changes to something other than the sourceState
// or timeout fires. It returns false if timeout fires and true otherwise.
func (cc *ClientConn) WaitForStateChange(timeout time.Duration, sourceState ConnectivityState) bool {
	start := time.Now()
	cc.mu.Lock()
	defer cc.mu.Unlock()
	if sourceState != cc.state {
		return true
	}
	expired := timeout <= time.Since(start)
	if expired {
		return false
	}
	done := make(chan struct{})
	go func() {
		select {
		case <-time.After(timeout - time.Since(start)):
			cc.mu.Lock()
			expired = true
			cc.stateCV.Broadcast()
			cc.mu.Unlock()
		case <-done:
		}
	}()
	defer close(done)
	for sourceState == cc.state {
		cc.stateCV.Wait()
		if expired {
			return false
		}
	}
	return true
}

func (cc *ClientConn) resetTransport(closeTransport bool) error {
	var retries int
	start := time.Now()
	for {
		cc.mu.Lock()
		cc.state = Connecting
		cc.stateCV.Broadcast()
		t := cc.transport
		if cc.state == Shutdown {
			cc.mu.Unlock()
			return ErrClientConnClosing
		}
		cc.mu.Unlock()
		if closeTransport {
			t.Close()
		}
		// Adjust timeout for the current try.
		copts := cc.dopts.copts
		if copts.Timeout < 0 {
			cc.Close()
			return ErrClientConnTimeout
		}
		if copts.Timeout > 0 {
			copts.Timeout -= time.Since(start)
			if copts.Timeout <= 0 {
				cc.Close()
				return ErrClientConnTimeout
			}
		}
		sleepTime := backoff(retries)
		timeout := sleepTime
		if timeout < minConnectTimeout {
			timeout = minConnectTimeout
		}
		if copts.Timeout == 0 || copts.Timeout > timeout {
			copts.Timeout = timeout
		}
		connectTime := time.Now()
		newTransport, err := transport.NewClientTransport(cc.target, &copts)
		if err != nil {
			cc.mu.Lock()
			cc.state = TransientFailure
			cc.stateCV.Broadcast()
			cc.mu.Unlock()
			sleepTime -= time.Since(connectTime)
			if sleepTime < 0 {
				sleepTime = 0
			}
			// Fail early before falling into sleep.
			if cc.dopts.copts.Timeout > 0 && cc.dopts.copts.Timeout < sleepTime+time.Since(start) {
				cc.Close()
				return ErrClientConnTimeout
			}
			closeTransport = false
			time.Sleep(sleepTime)
			retries++
			grpclog.Printf("grpc: ClientConn.resetTransport failed to create client transport: %v; Reconnecting to %q", err, cc.target)
			continue
		}
		cc.mu.Lock()
		if cc.state == Shutdown {
			// cc.Close() has been invoked.
			cc.mu.Unlock()
			newTransport.Close()
			return ErrClientConnClosing
		}
		cc.state = Ready
		cc.stateCV.Broadcast()
		cc.transport = newTransport
		if cc.ready != nil {
			close(cc.ready)
			cc.ready = nil
		}
		cc.mu.Unlock()
		return nil
	}
}

// Run in a goroutine to track the error in transport and create the
// new transport if an error happens. It returns when the channel is closing.
func (cc *ClientConn) transportMonitor() {
	for {
		select {
		// shutdownChan is needed to detect the teardown when
		// the ClientConn is idle (i.e., no RPC in flight).
		case <-cc.shutdownChan:
			return
		case <-cc.transport.Error():
			cc.mu.Lock()
			cc.state = TransientFailure
			cc.stateCV.Broadcast()
			cc.mu.Unlock()
			if err := cc.resetTransport(true); err != nil {
				// The ClientConn is closing.
				grpclog.Printf("grpc: ClientConn.transportMonitor exits due to: %v", err)
				return
			}
			continue
		}
	}
}

// When wait returns, either the new transport is up or ClientConn is
// closing.
func (cc *ClientConn) wait(ctx context.Context) (transport.ClientTransport, error) {
	for {
		cc.mu.Lock()
		switch {
		case cc.state == Shutdown:
			cc.mu.Unlock()
			return nil, ErrClientConnClosing
		case cc.state == Ready:
			cc.mu.Unlock()
			return cc.transport, nil
		default:
			ready := cc.ready
			if ready == nil {
				ready = make(chan struct{})
				cc.ready = ready
			}
			cc.mu.Unlock()
			select {
			case <-ctx.Done():
				return nil, transport.ContextErr(ctx.Err())
			// Wait until the new transport is ready or failed.
			case <-ready:
			}
		}
	}
}

// Close starts to tear down the ClientConn. Returns ErrClientConnClosing if
// it has been closed (mostly due to dial time-out).
// TODO(zhaoq): Make this synchronous to avoid unbounded memory consumption in
// some edge cases (e.g., the caller opens and closes many ClientConn's in a
// tight loop.
func (cc *ClientConn) Close() error {
	cc.mu.Lock()
	defer cc.mu.Unlock()
	if cc.state == Shutdown {
		return ErrClientConnClosing
	}
	cc.state = Shutdown
	cc.stateCV.Broadcast()
	if cc.ready != nil {
		close(cc.ready)
		cc.ready = nil
	}
	if cc.transport != nil {
		cc.transport.Close()
	}
	if cc.shutdownChan != nil {
		close(cc.shutdownChan)
	}
	return nil
}
<|endoftext|>


<commit_before>package linq

// ParallelQuery is the type returned from functions executing in parallel.
// To transform a Query into ParallelQuery, use AsParallel() and use
// AsSequential() to do vice versa.
type ParallelQuery struct {
	values  []T
	ordered bool
	err     error
}

type parallelBinaryResult struct {
	ok    bool
	err   error
	index int
}

type parallelValueResult struct {
	val   T
	err   error
	index int
}

// Results evaluates the query and returns the results as T slice.
// An error occurred in during evaluation of the query will be returned.
func (q ParallelQuery) Results() ([]T, error) {
	return q.values, q.err
}

// AsSequential returns a Query from the same source and the query functions
// can be executed in serial for each element of the source sequence.
// This is for undoing AsParallel().
func (q ParallelQuery) AsSequential() Query {
	return Query{values: q.values, err: q.err}
}

// copyMeta copies all fields of ParallelQuery except 'values' into a new
// instance. This should be used for retaining options e.g. 'ordered'.
func (q ParallelQuery) copyMeta() ParallelQuery {
	return ParallelQuery{err: q.err,
		ordered: q.ordered}
}

// copyMetaWithValues copies all fields of ParallelQuery. This should be used
// for retaining options e.g. 'ordered' as well as values.
func (q ParallelQuery) copyMetaWithValues() ParallelQuery {
	return ParallelQuery{err: q.err,
		ordered: q.ordered,
		values:  q.values}
}

// AsOrdered makes the parallel queries to preserve original order. By default,
// parallel queries do not preserve the order and process the parallel
// executions in first-come-first-served fashion.
//
// Not applicable for all query methods and comes
// with a performance penalty in some queries, please refer to
// http://msdn.microsoft.com/en-us/library/dd460677(v=vs.110).aspx .
func (q ParallelQuery) AsOrdered() (p ParallelQuery) {
	p = q.copyMetaWithValues()
	p.ordered = true
	return
}

// AsUnordered undoes the effect of AsOrdered() and do not enforce parallel
// query to preserve the original order.
//
// See AsOrdered() for remarks.
func (q ParallelQuery) AsUnordered() (p ParallelQuery) {
	p = q.copyMetaWithValues()
	p.ordered = true
	return
}

// Where filters a sequence of values by running given predicate function
// in parallel for each element.
//
// This function will take elements of the source (or results of previous query)
// as interface[] so it should make type assertion to work on the types.
// Returns a query with elements satisfy the condition.
//
// If any of the parallel executions return with an error, this function
// immediately returns with the error.
//
// If you would like to preserve order from the original sequence, use
// AsOrdered() on the query beforehand.
func (q ParallelQuery) Where(f func(T) (bool, error)) (r ParallelQuery) {
	r = q.copyMeta()
	if r.err != nil {
		return r
	}
	if f == nil {
		r.err = ErrNilFunc
		return
	}

	count := len(q.values)
	ch := make(chan *parallelBinaryResult)
	for i := 0; i < count; i++ {
		go func(ind int, f func(T) (bool, error), in T) {
			out := parallelBinaryResult{index: ind}
			ok, err := f(in)
			if err != nil {
				out.err = err
			} else {
				out.ok = ok
			}
			ch <- &out
		}(i, f, q.values[i])
	}

	tmp := make([]T, count)
	take := make([]bool, count)

	for j := 0; j < count; j++ {
		out := <-ch
		if out.err != nil {
			r.err = out.err
			return
		}
		if out.ok {
			origI := out.index
			val := q.values[origI]
			if r.ordered {
				tmp[origI] = val
				take[origI] = true
			} else {
				r.values = append(r.values, val)
			}
		}
	}

	if r.ordered {
		// iterate over the flag slice to take marked elements
		for i, v := range tmp {
			if take[i] {
				r.values = append(r.values, v)
			}
		}
	}
	return
}

// Select projects each element of a sequence into a new form by running
// the given transform function in parallel for each element.
// Returns a query with the return values of invoking the transform function
// on each element of original source.
func (q ParallelQuery) Select(f func(T) (T, error)) (r ParallelQuery) {
	r = q.copyMeta()
	if r.err != nil {
		return r
	}
	if f == nil {
		r.err = ErrNilFunc
		return
	}

	ch := make(chan *parallelValueResult)
	r.values = make([]T, len(q.values))
	for i, v := range q.values {
		go func(ind int, f func(T) (T, error), in T) {
			out := parallelValueResult{index: ind}
			val, err := f(in)
			if err != nil {
				out.err = err
			} else {
				out.val = val
			}
			ch <- &out
		}(i, f, v)
	}

	for i := 0; i < len(q.values); i++ {
		out := <-ch
		if out.err != nil {
			r.err = out.err
			return
		}
		r.values[out.index] = out.val
	}
	return
}

// AnyWith determines whether the query source contains any elements satisfying
// the provided predicate function.
func (q ParallelQuery) AnyWith(f func(T) (bool, error)) (exists bool, err error) {
	if q.err != nil {
		err = q.err
		return
	}
	if f == nil {
		err = ErrNilFunc
		return
	}

	ch := make(chan parallelBinaryResult)
	for _, v := range q.values {
		go func(f func(T) (bool, error), value T) {
			out := parallelBinaryResult{}
			ok, e := f(value)
			out.ok = ok
			out.err = e
			ch <- out
		}(f, v)
	}

	for i := 0; i < len(q.values); i++ {
		out := <-ch
		if out.err != nil {
			err = out.err
			return
		}
		if out.ok {
			exists = true
			return
		}
	}
	return
}

// All determines whether all elements of the query source satisfy the provided
// predicate function by executing the function for each element in parallel.
//
// Returns early if one element does not meet the conditions provided.
func (q ParallelQuery) All(f func(T) (bool, error)) (all bool, err error) {
	if q.err != nil {
		err = q.err
		return
	}
	if f == nil {
		err = ErrNilFunc
		return
	}

	ch := make(chan parallelBinaryResult)
	for v := range q.values {
		go func(f func(T) (bool, error), value T) {
			ok, e := f(value)
			ch <- parallelBinaryResult{ok: ok, err: e}
		}(f, v)
	}

	for i := 0; i < len(q.values); i++ {
		out := <-ch
		if out.err != nil {
			err = out.err
			return
		}
		if !out.ok {
			return false, nil
		}
	}
	return true, nil
}
<commit_msg>fix: make AsUnordered really unordered<commit_after>package linq

// ParallelQuery is the type returned from functions executing in parallel.
// To transform a Query into ParallelQuery, use AsParallel() and use
// AsSequential() to do vice versa.
type ParallelQuery struct {
	values  []T
	ordered bool
	err     error
}

type parallelBinaryResult struct {
	ok    bool
	err   error
	index int
}

type parallelValueResult struct {
	val   T
	err   error
	index int
}

// Results evaluates the query and returns the results as T slice.
// An error occurred in during evaluation of the query will be returned.
func (q ParallelQuery) Results() ([]T, error) {
	return q.values, q.err
}

// AsSequential returns a Query from the same source and the query functions
// can be executed in serial for each element of the source sequence.
// This is for undoing AsParallel().
func (q ParallelQuery) AsSequential() Query {
	return Query{values: q.values, err: q.err}
}

// copyMeta copies all fields of ParallelQuery except 'values' into a new
// instance. This should be used for retaining options e.g. 'ordered'.
func (q ParallelQuery) copyMeta() ParallelQuery {
	return ParallelQuery{err: q.err,
		ordered: q.ordered}
}

// copyMetaWithValues copies all fields of ParallelQuery. This should be used
// for retaining options e.g. 'ordered' as well as values.
func (q ParallelQuery) copyMetaWithValues() ParallelQuery {
	return ParallelQuery{err: q.err,
		ordered: q.ordered,
		values:  q.values}
}

// AsOrdered makes the parallel queries to preserve original order. By default,
// parallel queries do not preserve the order and process the parallel
// executions in first-come-first-served fashion.
//
// Not applicable for all query methods and comes
// with a performance penalty in some queries, please refer to
// http://msdn.microsoft.com/en-us/library/dd460677(v=vs.110).aspx .
func (q ParallelQuery) AsOrdered() (p ParallelQuery) {
	p = q.copyMetaWithValues()
	p.ordered = true
	return
}

// AsUnordered undoes the effect of AsOrdered() and do not enforce parallel
// query to preserve the original order.
//
// See AsOrdered() for remarks.
func (q ParallelQuery) AsUnordered() (p ParallelQuery) {
	p = q.copyMetaWithValues()
	p.ordered = false
	return
}

// Where filters a sequence of values by running given predicate function
// in parallel for each element.
//
// This function will take elements of the source (or results of previous query)
// as interface[] so it should make type assertion to work on the types.
// Returns a query with elements satisfy the condition.
//
// If any of the parallel executions return with an error, this function
// immediately returns with the error.
//
// If you would like to preserve order from the original sequence, use
// AsOrdered() on the query beforehand.
func (q ParallelQuery) Where(f func(T) (bool, error)) (r ParallelQuery) {
	r = q.copyMeta()
	if r.err != nil {
		return r
	}
	if f == nil {
		r.err = ErrNilFunc
		return
	}

	count := len(q.values)
	ch := make(chan *parallelBinaryResult)
	for i := 0; i < count; i++ {
		go func(ind int, f func(T) (bool, error), in T) {
			out := parallelBinaryResult{index: ind}
			ok, err := f(in)
			if err != nil {
				out.err = err
			} else {
				out.ok = ok
			}
			ch <- &out
		}(i, f, q.values[i])
	}

	tmp := make([]T, count)
	take := make([]bool, count)

	for j := 0; j < count; j++ {
		out := <-ch
		if out.err != nil {
			r.err = out.err
			return
		}
		if out.ok {
			origI := out.index
			val := q.values[origI]
			if r.ordered {
				tmp[origI] = val
				take[origI] = true
			} else {
				r.values = append(r.values, val)
			}
		}
	}

	if r.ordered {
		// iterate over the flag slice to take marked elements
		for i, v := range tmp {
			if take[i] {
				r.values = append(r.values, v)
			}
		}
	}
	return
}

// Select projects each element of a sequence into a new form by running
// the given transform function in parallel for each element.
// Returns a query with the return values of invoking the transform function
// on each element of original source.
func (q ParallelQuery) Select(f func(T) (T, error)) (r ParallelQuery) {
	r = q.copyMeta()
	if r.err != nil {
		return r
	}
	if f == nil {
		r.err = ErrNilFunc
		return
	}

	ch := make(chan *parallelValueResult)
	r.values = make([]T, len(q.values))
	for i, v := range q.values {
		go func(ind int, f func(T) (T, error), in T) {
			out := parallelValueResult{index: ind}
			val, err := f(in)
			if err != nil {
				out.err = err
			} else {
				out.val = val
			}
			ch <- &out
		}(i, f, v)
	}

	for i := 0; i < len(q.values); i++ {
		out := <-ch
		if out.err != nil {
			r.err = out.err
			return
		}
		r.values[out.index] = out.val
	}
	return
}

// AnyWith determines whether the query source contains any elements satisfying
// the provided predicate function.
func (q ParallelQuery) AnyWith(f func(T) (bool, error)) (exists bool, err error) {
	if q.err != nil {
		err = q.err
		return
	}
	if f == nil {
		err = ErrNilFunc
		return
	}

	ch := make(chan parallelBinaryResult)
	for _, v := range q.values {
		go func(f func(T) (bool, error), value T) {
			out := parallelBinaryResult{}
			ok, e := f(value)
			out.ok = ok
			out.err = e
			ch <- out
		}(f, v)
	}

	for i := 0; i < len(q.values); i++ {
		out := <-ch
		if out.err != nil {
			err = out.err
			return
		}
		if out.ok {
			exists = true
			return
		}
	}
	return
}

// All determines whether all elements of the query source satisfy the provided
// predicate function by executing the function for each element in parallel.
//
// Returns early if one element does not meet the conditions provided.
func (q ParallelQuery) All(f func(T) (bool, error)) (all bool, err error) {
	if q.err != nil {
		err = q.err
		return
	}
	if f == nil {
		err = ErrNilFunc
		return
	}

	ch := make(chan parallelBinaryResult)
	for v := range q.values {
		go func(f func(T) (bool, error), value T) {
			ok, e := f(value)
			ch <- parallelBinaryResult{ok: ok, err: e}
		}(f, v)
	}

	for i := 0; i < len(q.values); i++ {
		out := <-ch
		if out.err != nil {
			err = out.err
			return
		}
		if !out.ok {
			return false, nil
		}
	}
	return true, nil
}
<|endoftext|>


<commit_before>package vmx

import (
	"errors"
	"fmt"
	"log"
	"time"

	"github.com/mitchellh/multistep"
	vmwcommon "github.com/mitchellh/packer/builder/vmware/common"
	"github.com/mitchellh/packer/common"
	"github.com/mitchellh/packer/packer"
)

// Builder implements packer.Builder and builds the actual VirtualBox
// images.
type Builder struct {
	config *Config
	runner multistep.Runner
}

// Prepare processes the build configuration parameters.
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
	c, warnings, errs := NewConfig(raws...)
	if errs != nil {
		return warnings, errs
	}
	b.config = c

	return warnings, nil
}

// Run executes a Packer build and returns a packer.Artifact representing
// a VirtualBox appliance.
func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
	driver, err := vmwcommon.NewDriver(&b.config.SSHConfig)
	if err != nil {
		return nil, fmt.Errorf("Failed creating VMware driver: %s", err)
	}

	// Setup the directory
	dir := new(vmwcommon.LocalOutputDir)
	dir.SetOutputDir(b.config.OutputDir)

	// Set up the state.
	state := new(multistep.BasicStateBag)
	state.Put("config", b.config)
	state.Put("dir", dir)
	state.Put("driver", driver)
	state.Put("hook", hook)
	state.Put("ui", ui)

	// Build the steps.
	steps := []multistep.Step{
		&vmwcommon.StepOutputDir{
			Force: b.config.PackerForce,
		},
		&StepCloneVMX{
			OutputDir: b.config.OutputDir,
			Path:      b.config.SourcePath,
			VMName:    b.config.VMName,
		},
		&vmwcommon.StepConfigureVMX{
			CustomData: b.config.VMXData,
		},
		&vmwcommon.StepSuppressMessages{},
		&vmwcommon.StepRun{
			BootWait:           b.config.BootWait,
			DurationBeforeStop: 5 * time.Second,
			Headless:           b.config.Headless,
		},
	}

	// Run the steps.
	if b.config.PackerDebug {
		b.runner = &multistep.DebugRunner{
			Steps:   steps,
			PauseFn: common.MultistepDebugFn(ui),
		}
	} else {
		b.runner = &multistep.BasicRunner{Steps: steps}
	}
	b.runner.Run(state)

	// Report any errors.
	if rawErr, ok := state.GetOk("error"); ok {
		return nil, rawErr.(error)
	}

	// If we were interrupted or cancelled, then just exit.
	if _, ok := state.GetOk(multistep.StateCancelled); ok {
		return nil, errors.New("Build was cancelled.")
	}

	if _, ok := state.GetOk(multistep.StateHalted); ok {
		return nil, errors.New("Build was halted.")
	}

	return nil, nil
}

// Cancel.
func (b *Builder) Cancel() {
	if b.runner != nil {
		log.Println("Cancelling the step runner...")
		b.runner.Cancel()
	}
}
<commit_msg>builder/vmware/vmx: step connect SSH<commit_after>package vmx

import (
	"errors"
	"fmt"
	"log"
	"time"

	"github.com/mitchellh/multistep"
	vmwcommon "github.com/mitchellh/packer/builder/vmware/common"
	"github.com/mitchellh/packer/common"
	"github.com/mitchellh/packer/packer"
)

// Builder implements packer.Builder and builds the actual VirtualBox
// images.
type Builder struct {
	config *Config
	runner multistep.Runner
}

// Prepare processes the build configuration parameters.
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
	c, warnings, errs := NewConfig(raws...)
	if errs != nil {
		return warnings, errs
	}
	b.config = c

	return warnings, nil
}

// Run executes a Packer build and returns a packer.Artifact representing
// a VirtualBox appliance.
func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
	driver, err := vmwcommon.NewDriver(&b.config.SSHConfig)
	if err != nil {
		return nil, fmt.Errorf("Failed creating VMware driver: %s", err)
	}

	// Setup the directory
	dir := new(vmwcommon.LocalOutputDir)
	dir.SetOutputDir(b.config.OutputDir)

	// Set up the state.
	state := new(multistep.BasicStateBag)
	state.Put("config", b.config)
	state.Put("dir", dir)
	state.Put("driver", driver)
	state.Put("hook", hook)
	state.Put("ui", ui)

	// Build the steps.
	steps := []multistep.Step{
		&vmwcommon.StepOutputDir{
			Force: b.config.PackerForce,
		},
		&StepCloneVMX{
			OutputDir: b.config.OutputDir,
			Path:      b.config.SourcePath,
			VMName:    b.config.VMName,
		},
		&vmwcommon.StepConfigureVMX{
			CustomData: b.config.VMXData,
		},
		&vmwcommon.StepSuppressMessages{},
		&vmwcommon.StepRun{
			BootWait:           b.config.BootWait,
			DurationBeforeStop: 5 * time.Second,
			Headless:           b.config.Headless,
		},
		&common.StepConnectSSH{
			SSHAddress:     driver.SSHAddress,
			SSHConfig:      vmwcommon.SSHConfigFunc(&b.config.SSHConfig),
			SSHWaitTimeout: b.config.SSHWaitTimeout,
			NoPty:          b.config.SSHSkipRequestPty,
		},
		&common.StepProvision{},
	}

	// Run the steps.
	if b.config.PackerDebug {
		b.runner = &multistep.DebugRunner{
			Steps:   steps,
			PauseFn: common.MultistepDebugFn(ui),
		}
	} else {
		b.runner = &multistep.BasicRunner{Steps: steps}
	}
	b.runner.Run(state)

	// Report any errors.
	if rawErr, ok := state.GetOk("error"); ok {
		return nil, rawErr.(error)
	}

	// If we were interrupted or cancelled, then just exit.
	if _, ok := state.GetOk(multistep.StateCancelled); ok {
		return nil, errors.New("Build was cancelled.")
	}

	if _, ok := state.GetOk(multistep.StateHalted); ok {
		return nil, errors.New("Build was halted.")
	}

	return nil, nil
}

// Cancel.
func (b *Builder) Cancel() {
	if b.runner != nil {
		log.Println("Cancelling the step runner...")
		b.runner.Cancel()
	}
}
<|endoftext|>


<commit_before>// Copyright 2011 The Walk 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 main

import (
	"fmt"
	"os"
	"path"
	"time"
)

import "walk"

type MainWindow struct {
	*walk.MainWindow
	treeView   *walk.TreeView
	selTvwItem *walk.TreeViewItem
	listView   *walk.ListView
	preview    *walk.WebView
}

func (mw *MainWindow) showError(err os.Error) {
	walk.MsgBox(mw, "Error", err.String(), walk.MsgBoxOK|walk.MsgBoxIconError)
}

func (mw *MainWindow) populateTreeViewItem(parent *walk.TreeViewItem) {
	mw.treeView.SetSuspended(true)
	defer mw.treeView.SetSuspended(false)

	// Remove dummy child
	parent.Children().Clear()

	dirPath := pathForTreeViewItem(parent)

	dir, err := os.Open(dirPath)
	if err != nil {
		mw.showError(err)
		return
	}
	defer dir.Close()

	names, err := dir.Readdirnames(-1)
	panicIfErr(err)

	for _, name := range names {
		fi, err := os.Stat(path.Join(dirPath, name))
		panicIfErr(err)

		if !excludePath(name) && fi.IsDirectory() {
			child := newTreeViewItem(name)

			parent.Children().Add(child)
		}
	}
}

func (mw *MainWindow) populateListView(dirPath string) {
	mw.listView.SetSuspended(true)
	defer mw.listView.SetSuspended(false)

	mw.listView.Items().Clear()

	dir, err := os.Open(dirPath)
	if err != nil {
		mw.showError(err)
		return
	}
	defer dir.Close()

	names, err := dir.Readdirnames(-1)
	panicIfErr(err)

	for _, name := range names {
		if !excludePath(name) {
			fullPath := path.Join(dirPath, name)

			fi, err := os.Stat(fullPath)
			if err != nil {
				mw.showError(err)
				continue
			}

			var size string
			if !fi.IsDirectory() {
				size = fmt.Sprintf("%d", fi.Size)
			}
			lastMod := time.SecondsToLocalTime(fi.Mtime_ns / 10e8).Format("2006-01-02 15:04:05")

			item := walk.NewListViewItem()
			texts := []string{name, size, lastMod}
			item.SetTexts(texts)

			mw.listView.Items().Add(item)
		}
	}
}

func panicIfErr(err os.Error) {
	if err != nil {
		panic(err)
	}
}

func pathForTreeViewItem(item *walk.TreeViewItem) string {
	var parts []string
	for item != nil {
		parts = append([]string{item.Text()}, parts...)
		item = item.Parent()
	}

	return path.Join(parts...)
}

func excludePath(path string) bool {
	if path == "System Volume Information" {
		return true
	}

	return false
}

func newTreeViewItem(text string) *walk.TreeViewItem {
	item := walk.NewTreeViewItem()
	item.SetText(text)

	// For now, we add a dummy child to make the item expandable.
	item.Children().Add(walk.NewTreeViewItem())

	return item
}

func main() {
	walk.Initialize(walk.InitParams{PanicOnError: true})
	defer walk.Shutdown()

	mainWnd, _ := walk.NewMainWindow()

	mw := &MainWindow{MainWindow: mainWnd}
	mw.SetTitle("Walk File Browser Example")
	mw.SetLayout(walk.NewHBoxLayout())

	fileMenu, _ := walk.NewMenu()
	fileMenuAction, _ := mw.Menu().Actions().AddMenu(fileMenu)
	fileMenuAction.SetText("&File")

	exitAction := walk.NewAction()
	exitAction.SetText("E&xit")
	exitAction.Triggered().Attach(func() { walk.App().Exit(0) })
	fileMenu.Actions().Add(exitAction)

	helpMenu, _ := walk.NewMenu()
	helpMenuAction, _ := mw.Menu().Actions().AddMenu(helpMenu)
	helpMenuAction.SetText("&Help")

	aboutAction := walk.NewAction()
	aboutAction.SetText("&About")
	aboutAction.Triggered().Attach(func() {
		walk.MsgBox(mw, "About", "Walk File Browser Example", walk.MsgBoxOK|walk.MsgBoxIconInformation)
	})
	helpMenu.Actions().Add(aboutAction)

	splitter, _ := walk.NewSplitter(mw)

	mw.treeView, _ = walk.NewTreeView(splitter)

	mw.treeView.ItemExpanded().Attach(func(item *walk.TreeViewItem) {
		children := item.Children()
		if children.Len() == 1 && children.At(0).Text() == "" {
			mw.populateTreeViewItem(item)
		}
	})

	mw.treeView.SelectionChanged().Attach(func(old, new *walk.TreeViewItem) {
		mw.selTvwItem = new
		mw.populateListView(pathForTreeViewItem(new))
	})

	drives, _ := walk.DriveNames()

	mw.treeView.SetSuspended(true)
	for _, drive := range drives {
		driveItem := newTreeViewItem(drive[:2])
		mw.treeView.Items().Add(driveItem)
	}
	mw.treeView.SetSuspended(false)

	mw.listView, _ = walk.NewListView(splitter)
	mw.listView.SetSingleItemSelection(true)

	mw.listView.CurrentIndexChanged().Attach(func() {
		index := mw.listView.CurrentIndex()
		var url string
		if index > -1 {
			item := mw.listView.Items().At(index)

			url = path.Join(pathForTreeViewItem(mw.selTvwItem), item.Texts()[0])
		}

		mw.preview.SetURL(url)
	})

	nameCol := walk.NewListViewColumn()
	nameCol.SetTitle("Name")
	nameCol.SetWidth(200)
	mw.listView.Columns().Add(nameCol)

	sizeCol := walk.NewListViewColumn()
	sizeCol.SetTitle("Size")
	sizeCol.SetWidth(80)
	sizeCol.SetAlignment(walk.AlignFar)
	mw.listView.Columns().Add(sizeCol)

	modCol := walk.NewListViewColumn()
	modCol.SetTitle("Modified")
	modCol.SetWidth(120)
	mw.listView.Columns().Add(modCol)

	mw.preview, _ = walk.NewWebView(splitter)

	mw.SetMinMaxSize(walk.Size{600, 400}, walk.Size{})
	mw.SetSize(walk.Size{800, 600})
	mw.Show()

	mw.Run()
}
<commit_msg>Change filebrowser example to use TableView instead of ListView.<commit_after>// Copyright 2011 The Walk 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 main

import (
	"os"
	"path"
	"time"
)

import "walk"

type FileInfo struct {
	Name     string
	Size     int64
	Modified int64
}

type FileInfoModel struct {
	items               []*FileInfo
	rowsResetPublisher  walk.EventPublisher
	rowChangedPublisher walk.IntEventPublisher
}

func (m *FileInfoModel) Columns() []walk.TableColumn {
	return []walk.TableColumn{
		{Title: "Name", Width: 200},
		{Title: "Size", Format: "%d", Alignment: walk.AlignFar, Width: 80},
		{Title: "Modified", Format: "2006-01-02 15:04:05", Width: 120},
	}
}

func (m *FileInfoModel) RowCount() int {
	return len(m.items)
}

func (m *FileInfoModel) Value(row, col int) interface{} {
	item := m.items[row]

	switch col {
	case 0:
		return item.Name

	case 1:
		return item.Size

	case 2:
		return time.SecondsToLocalTime(item.Modified)
	}

	panic("unexpected col")
}

func (m *FileInfoModel) RowsReset() *walk.Event {
	return m.rowsResetPublisher.Event()
}

func (m *FileInfoModel) RowChanged() *walk.IntEvent {
	return m.rowChangedPublisher.Event()
}

func (m *FileInfoModel) ResetRows(dirPath string) os.Error {
	dir, err := os.Open(dirPath)
	if err != nil {
		return err
	}
	defer dir.Close()

	names, err := dir.Readdirnames(-1)
	if err != nil {
		return err
	}

	m.items = make([]*FileInfo, 0, len(names))

	for _, name := range names {
		if !excludePath(name) {
			fullPath := path.Join(dirPath, name)

			fi, err := os.Stat(fullPath)
			if err != nil {
				continue
			}

			item := &FileInfo{
				Name:     name,
				Size:     fi.Size,
				Modified: fi.Mtime_ns / 1e9,
			}

			m.items = append(m.items, item)
		}
	}

	m.rowsResetPublisher.Publish()

	return nil
}

type MainWindow struct {
	*walk.MainWindow
	fileInfoModel *FileInfoModel
	treeView      *walk.TreeView
	selTvwItem    *walk.TreeViewItem
	tableView     *walk.TableView
	preview       *walk.WebView
}

func (mw *MainWindow) showError(err os.Error) {
	if err == nil {
		return
	}

	walk.MsgBox(mw, "Error", err.String(), walk.MsgBoxOK|walk.MsgBoxIconError)
}

func (mw *MainWindow) populateTreeViewItem(parent *walk.TreeViewItem) {
	mw.treeView.SetSuspended(true)
	defer mw.treeView.SetSuspended(false)

	// Remove dummy child
	parent.Children().Clear()

	dirPath := pathForTreeViewItem(parent)

	dir, err := os.Open(dirPath)
	if err != nil {
		mw.showError(err)
		return
	}
	defer dir.Close()

	names, err := dir.Readdirnames(-1)
	panicIfErr(err)

	for _, name := range names {
		fi, err := os.Stat(path.Join(dirPath, name))
		panicIfErr(err)

		if !excludePath(name) && fi.IsDirectory() {
			child := newTreeViewItem(name)

			parent.Children().Add(child)
		}
	}
}

func panicIfErr(err os.Error) {
	if err != nil {
		panic(err)
	}
}

func pathForTreeViewItem(item *walk.TreeViewItem) string {
	var parts []string
	for item != nil {
		parts = append([]string{item.Text()}, parts...)
		item = item.Parent()
	}

	return path.Join(parts...)
}

func excludePath(path string) bool {
	if path == "System Volume Information" {
		return true
	}

	return false
}

func newTreeViewItem(text string) *walk.TreeViewItem {
	item := walk.NewTreeViewItem()
	item.SetText(text)

	// For now, we add a dummy child to make the item expandable.
	item.Children().Add(walk.NewTreeViewItem())

	return item
}

func main() {
	walk.Initialize(walk.InitParams{PanicOnError: true})
	defer walk.Shutdown()

	mainWnd, _ := walk.NewMainWindow()

	mw := &MainWindow{
		MainWindow:    mainWnd,
		fileInfoModel: &FileInfoModel{},
	}

	mw.SetTitle("Walk File Browser Example")
	mw.SetLayout(walk.NewHBoxLayout())

	fileMenu, _ := walk.NewMenu()
	fileMenuAction, _ := mw.Menu().Actions().AddMenu(fileMenu)
	fileMenuAction.SetText("&File")

	exitAction := walk.NewAction()
	exitAction.SetText("E&xit")
	exitAction.Triggered().Attach(func() { walk.App().Exit(0) })
	fileMenu.Actions().Add(exitAction)

	helpMenu, _ := walk.NewMenu()
	helpMenuAction, _ := mw.Menu().Actions().AddMenu(helpMenu)
	helpMenuAction.SetText("&Help")

	aboutAction := walk.NewAction()
	aboutAction.SetText("&About")
	aboutAction.Triggered().Attach(func() {
		walk.MsgBox(mw, "About", "Walk File Browser Example", walk.MsgBoxOK|walk.MsgBoxIconInformation)
	})
	helpMenu.Actions().Add(aboutAction)

	splitter, _ := walk.NewSplitter(mw)

	mw.treeView, _ = walk.NewTreeView(splitter)

	mw.treeView.ItemExpanded().Attach(func(item *walk.TreeViewItem) {
		children := item.Children()
		if children.Len() == 1 && children.At(0).Text() == "" {
			mw.populateTreeViewItem(item)
		}
	})

	mw.treeView.SelectionChanged().Attach(func(old, new *walk.TreeViewItem) {
		mw.selTvwItem = new
		mw.showError(mw.fileInfoModel.ResetRows(pathForTreeViewItem(new)))
	})

	drives, _ := walk.DriveNames()

	mw.treeView.SetSuspended(true)
	for _, drive := range drives {
		driveItem := newTreeViewItem(drive[:2])
		mw.treeView.Items().Add(driveItem)
	}
	mw.treeView.SetSuspended(false)

	mw.tableView, _ = walk.NewTableView(splitter)
	mw.tableView.SetModel(mw.fileInfoModel)
	mw.tableView.SetSingleItemSelection(true)

	mw.tableView.CurrentIndexChanged().Attach(func() {
		var url string

		index := mw.tableView.CurrentIndex()
		if index > -1 {
			name := mw.fileInfoModel.items[index].Name
			url = path.Join(pathForTreeViewItem(mw.selTvwItem), name)
		}

		mw.preview.SetURL(url)
	})

	mw.preview, _ = walk.NewWebView(splitter)

	mw.SetMinMaxSize(walk.Size{600, 400}, walk.Size{})
	mw.SetSize(walk.Size{800, 600})
	mw.Show()

	mw.Run()
}
<|endoftext|>


<commit_before>package gen

import (
	"reflect"

	"github.com/leanovate/gopter"
)

// SliceOf generates an arbitrary slice of generated elements
// genParams.MaxSize sets an (exclusive) upper limit on the size of the slice
// genParams.MinSize sets an (inclusive) lower limit on the size of the slice
func SliceOf(elementGen gopter.Gen) gopter.Gen {
	return func(genParams *gopter.GenParameters) *gopter.GenResult {
		len := 0
		if genParams.MaxSize > 0 || genParams.MinSize > 0 {
			len = genParams.Rng.Intn(genParams.MaxSize-genParams.MinSize) + genParams.MinSize
		}
		result, elementSieve, elementShrinker := genSlice(elementGen, genParams, len)

		genResult := gopter.NewGenResult(result.Interface(), SliceShrinker(elementShrinker))
		if elementSieve != nil {
			genResult.Sieve = forAllSieve(elementSieve)
		}
		return genResult
	}
}

// SliceOfN generates a slice of generated elements with definied length
func SliceOfN(len int, elementGen gopter.Gen) gopter.Gen {
	return func(genParams *gopter.GenParameters) *gopter.GenResult {
		result, elementSieve, elementShrinker := genSlice(elementGen, genParams, len)

		genResult := gopter.NewGenResult(result.Interface(), SliceShrinkerOne(elementShrinker))
		if elementSieve != nil {
			genResult.Sieve = func(v interface{}) bool {
				rv := reflect.ValueOf(v)
				return rv.Len() == len && forAllSieve(elementSieve)(v)
			}
		} else {
			genResult.Sieve = func(v interface{}) bool {
				return reflect.ValueOf(v).Len() == len
			}
		}
		return genResult
	}
}

func genSlice(elementGen gopter.Gen, genParams *gopter.GenParameters, len int) (reflect.Value, func(interface{}) bool, gopter.Shrinker) {
	element := elementGen(genParams)
	elementSieve := element.Sieve
	elementShrinker := element.Shrinker

	result := reflect.MakeSlice(reflect.SliceOf(element.ResultType), 0, len)

	for i := 0; i < len; i++ {
		value, ok := element.Retrieve()

		if ok {
			if value == nil {
				result = reflect.Append(result, reflect.Zero(element.ResultType))
			} else {
				result = reflect.Append(result, reflect.ValueOf(value))
			}
		}
		element = elementGen(genParams)
	}

	return result, elementSieve, elementShrinker
}

func forAllSieve(elementSieve func(interface{}) bool) func(interface{}) bool {
	return func(v interface{}) bool {
		rv := reflect.ValueOf(v)
		for i := rv.Len() - 1; i >= 0; i-- {
			if !elementSieve(rv.Index(i).Interface()) {
				return false
			}
		}
		return true
	}
}
<commit_msg>Add panic on invalid MinSize MaxSize combination<commit_after>package gen

import (
	"reflect"

	"github.com/leanovate/gopter"
)

// SliceOf generates an arbitrary slice of generated elements
// genParams.MaxSize sets an (exclusive) upper limit on the size of the slice
// genParams.MinSize sets an (inclusive) lower limit on the size of the slice
func SliceOf(elementGen gopter.Gen) gopter.Gen {
	return func(genParams *gopter.GenParameters) *gopter.GenResult {
		len := 0
		if genParams.MaxSize > 0 || genParams.MinSize > 0 {
			if genParams.MinSize > genParams.MaxSize {
				panic("GenParameters.MinSize must be <= GenParameters.MaxSize")
			}

			len = genParams.Rng.Intn(genParams.MaxSize-genParams.MinSize) + genParams.MinSize
		}
		result, elementSieve, elementShrinker := genSlice(elementGen, genParams, len)

		genResult := gopter.NewGenResult(result.Interface(), SliceShrinker(elementShrinker))
		if elementSieve != nil {
			genResult.Sieve = forAllSieve(elementSieve)
		}
		return genResult
	}
}

// SliceOfN generates a slice of generated elements with definied length
func SliceOfN(len int, elementGen gopter.Gen) gopter.Gen {
	return func(genParams *gopter.GenParameters) *gopter.GenResult {
		result, elementSieve, elementShrinker := genSlice(elementGen, genParams, len)

		genResult := gopter.NewGenResult(result.Interface(), SliceShrinkerOne(elementShrinker))
		if elementSieve != nil {
			genResult.Sieve = func(v interface{}) bool {
				rv := reflect.ValueOf(v)
				return rv.Len() == len && forAllSieve(elementSieve)(v)
			}
		} else {
			genResult.Sieve = func(v interface{}) bool {
				return reflect.ValueOf(v).Len() == len
			}
		}
		return genResult
	}
}

func genSlice(elementGen gopter.Gen, genParams *gopter.GenParameters, len int) (reflect.Value, func(interface{}) bool, gopter.Shrinker) {
	element := elementGen(genParams)
	elementSieve := element.Sieve
	elementShrinker := element.Shrinker

	result := reflect.MakeSlice(reflect.SliceOf(element.ResultType), 0, len)

	for i := 0; i < len; i++ {
		value, ok := element.Retrieve()

		if ok {
			if value == nil {
				result = reflect.Append(result, reflect.Zero(element.ResultType))
			} else {
				result = reflect.Append(result, reflect.ValueOf(value))
			}
		}
		element = elementGen(genParams)
	}

	return result, elementSieve, elementShrinker
}

func forAllSieve(elementSieve func(interface{}) bool) func(interface{}) bool {
	return func(v interface{}) bool {
		rv := reflect.ValueOf(v)
		for i := rv.Len() - 1; i >= 0; i-- {
			if !elementSieve(rv.Index(i).Interface()) {
				return false
			}
		}
		return true
	}
}
<|endoftext|>


<commit_before>package config

import (
	"fmt"
	"time"

	"github.com/hashicorp/vault/api"
)

const (
	// DefaultVaultGrace is the default grace period before which to read a new
	// secret from Vault. If a lease is due to expire in 15 seconds, Consul
	// Template will read a new secret at that time minus this value.
	DefaultVaultGrace = 15 * time.Second

	// DefaultVaultRenewToken is the default value for if the Vault token should
	// be renewed.
	DefaultVaultRenewToken = true

	// DefaultVaultUnwrapToken is the default value for if the Vault token should
	// be unwrapped.
	DefaultVaultUnwrapToken = false

	// DefaultVaultRetryBase is the default value for the base time to use for
	// exponential backoff.
	DefaultVaultRetryBase = 250 * time.Millisecond

	// DefaultVaultRetryMaxAttempts is the default maximum number of attempts to
	// retry before quitting.
	DefaultVaultRetryMaxAttempts = 5
)

// VaultConfig is the configuration for connecting to a vault server.
type VaultConfig struct {
	// Address is the URI to the Vault server.
	Address *string `mapstructure:"address"`

	// Enabled controls whether the Vault integration is active.
	Enabled *bool `mapstructure:"enabled"`

	// Grace is the amount of time before a lease is about to expire to force a
	// new secret to be read.
	Grace *time.Duration `mapstructure:"grace"`

	// Namespace is the Vault namespace to use for reading/writing secrets. This can
	// also be set via the VAULT_NAMESPACE environment variable.
	Namespace *string `mapstructure:"namespace"`

	// RenewToken renews the Vault token.
	RenewToken *bool `mapstructure:"renew_token"`

	// Retry is the configuration for specifying how to behave on failure.
	Retry *RetryConfig `mapstructure:"retry"`

	// SSL indicates we should use a secure connection while talking to Vault.
	SSL *SSLConfig `mapstructure:"ssl"`

	// Token is the Vault token to communicate with for requests. It may be
	// a wrapped token or a real token. This can also be set via the VAULT_TOKEN
	// environment variable, or via the VaultAgentTokenFile.
	Token *string `mapstructure:"token" json:"-"`

	// VaultAgentTokenFile is the path of file that contains a Vault Agent token.
	// If vault_agent_token_file is specified:
	//   - Consul Template will not try to renew the Vault token.
	//   - Consul Template will periodically stat the file and update the token if it has
	// changed.
	VaultAgentTokenFile *string `mapstructure:"vault_agent_token_file" json:"-"`

	// Transport configures the low-level network connection details.
	Transport *TransportConfig `mapstructure:"transport"`

	// UnwrapToken unwraps the provided Vault token as a wrapped token.
	UnwrapToken *bool `mapstructure:"unwrap_token"`
}

// DefaultVaultConfig returns a configuration that is populated with the
// default values.
func DefaultVaultConfig() *VaultConfig {
	v := &VaultConfig{
		Retry:     DefaultRetryConfig(),
		SSL:       DefaultSSLConfig(),
		Transport: DefaultTransportConfig(),
	}

	// Force SSL when communicating with Vault.
	v.SSL.Enabled = Bool(true)

	return v
}

// Copy returns a deep copy of this configuration.
func (c *VaultConfig) Copy() *VaultConfig {
	if c == nil {
		return nil
	}

	var o VaultConfig
	o.Address = c.Address

	o.Enabled = c.Enabled

	o.Grace = c.Grace

	o.Namespace = c.Namespace

	o.RenewToken = c.RenewToken

	if c.Retry != nil {
		o.Retry = c.Retry.Copy()
	}

	if c.SSL != nil {
		o.SSL = c.SSL.Copy()
	}

	o.Token = c.Token

	o.VaultAgentTokenFile = c.VaultAgentTokenFile

	if c.Transport != nil {
		o.Transport = c.Transport.Copy()
	}

	o.UnwrapToken = c.UnwrapToken

	return &o
}

// Merge combines all values in this configuration with the values in the other
// configuration, with values in the other configuration taking precedence.
// Maps and slices are merged, most other values are overwritten. Complex
// structs define their own merge functionality.
func (c *VaultConfig) Merge(o *VaultConfig) *VaultConfig {
	if c == nil {
		if o == nil {
			return nil
		}
		return o.Copy()
	}

	if o == nil {
		return c.Copy()
	}

	r := c.Copy()

	if o.Address != nil {
		r.Address = o.Address
	}

	if o.Enabled != nil {
		r.Enabled = o.Enabled
	}

	if o.Grace != nil {
		r.Grace = o.Grace
	}

	if o.Namespace != nil {
		r.Namespace = o.Namespace
	}

	if o.RenewToken != nil {
		r.RenewToken = o.RenewToken
	}

	if o.Retry != nil {
		r.Retry = r.Retry.Merge(o.Retry)
	}

	if o.SSL != nil {
		r.SSL = r.SSL.Merge(o.SSL)
	}

	if o.Token != nil {
		r.Token = o.Token
	}

	if o.VaultAgentTokenFile != nil {
		r.VaultAgentTokenFile = o.VaultAgentTokenFile
	}

	if o.Transport != nil {
		r.Transport = r.Transport.Merge(o.Transport)
	}

	if o.UnwrapToken != nil {
		r.UnwrapToken = o.UnwrapToken
	}

	return r
}

// Finalize ensures there no nil pointers.
func (c *VaultConfig) Finalize() {
	if c.Address == nil {
		c.Address = stringFromEnv([]string{
			api.EnvVaultAddress,
		}, "")
	}

	if c.Grace == nil {
		c.Grace = TimeDuration(DefaultVaultGrace)
	}

	if c.Namespace == nil {
		c.Namespace = stringFromEnv([]string{"VAULT_NAMESPACE"}, "")
	}

	if c.RenewToken == nil {
		default_renew := DefaultVaultRenewToken
		if c.VaultAgentTokenFile != nil {
			default_renew = false
		}
		c.RenewToken = boolFromEnv([]string{
			"VAULT_RENEW_TOKEN",
		}, default_renew)
	}

	if c.Retry == nil {
		c.Retry = DefaultRetryConfig()
	}
	c.Retry.Finalize()

	// Vault has custom SSL settings
	if c.SSL == nil {
		c.SSL = DefaultSSLConfig()
	}
	if c.SSL.Enabled == nil {
		c.SSL.Enabled = Bool(true)
	}
	if c.SSL.CaCert == nil {
		c.SSL.CaCert = stringFromEnv([]string{api.EnvVaultCACert}, "")
	}
	if c.SSL.CaPath == nil {
		c.SSL.CaPath = stringFromEnv([]string{api.EnvVaultCAPath}, "")
	}
	if c.SSL.Cert == nil {
		c.SSL.Cert = stringFromEnv([]string{api.EnvVaultClientCert}, "")
	}
	if c.SSL.Key == nil {
		c.SSL.Key = stringFromEnv([]string{api.EnvVaultClientKey}, "")
	}
	if c.SSL.ServerName == nil {
		c.SSL.ServerName = stringFromEnv([]string{api.EnvVaultTLSServerName}, "")
	}
	if c.SSL.Verify == nil {
		c.SSL.Verify = antiboolFromEnv([]string{api.EnvVaultInsecure}, true)
	}
	c.SSL.Finalize()

	// Order of precedence
	// 1. `vault_agent_token_file` configuration value
	// 2. `token` configuration value`
	// 3. `VAULT_TOKEN` environment variable
	if c.Token == nil {
		c.Token = stringFromEnv([]string{
			"VAULT_TOKEN",
		}, "")
	}

	if c.VaultAgentTokenFile == nil {
		if StringVal(c.Token) == "" {
			if homePath != "" {
				c.Token = stringFromFile([]string{
					homePath + "/.vault-token",
				}, "")
			}
		}
	} else {
		c.Token = stringFromFile([]string{*c.VaultAgentTokenFile}, "")
	}

	if c.Transport == nil {
		c.Transport = DefaultTransportConfig()
	}
	c.Transport.Finalize()

	if c.UnwrapToken == nil {
		c.UnwrapToken = boolFromEnv([]string{
			"VAULT_UNWRAP_TOKEN",
		}, DefaultVaultUnwrapToken)
	}

	if c.Enabled == nil {
		c.Enabled = Bool(StringPresent(c.Address))
	}
}

// GoString defines the printable version of this struct.
func (c *VaultConfig) GoString() string {
	if c == nil {
		return "(*VaultConfig)(nil)"
	}

	return fmt.Sprintf("&VaultConfig{"+
		"Address:%s, "+
		"Enabled:%s, "+
		"Grace:%s, "+
		"Namespace:%s,"+
		"RenewToken:%s, "+
		"Retry:%#v, "+
		"SSL:%#v, "+
		"Token:%t, "+
		"VaultAgentTokenFile:%t, "+
		"Transport:%#v, "+
		"UnwrapToken:%s"+
		"}",
		StringGoString(c.Address),
		BoolGoString(c.Enabled),
		TimeDurationGoString(c.Grace),
		StringGoString(c.Namespace),
		BoolGoString(c.RenewToken),
		c.Retry,
		c.SSL,
		StringPresent(c.Token),
		StringPresent(c.VaultAgentTokenFile),
		c.Transport,
		BoolGoString(c.UnwrapToken),
	)
}
<commit_msg>forward compatibility with vault env name change<commit_after>package config

import (
	"fmt"
	"time"

	"github.com/hashicorp/vault/api"
)

const (
	// XXX Change use to api.EnvVaultSkipVerify once we've updated vendored
	// vault to version 1.1.0 or newer.
	EnvVaultSkipVerify = "VAULT_SKIP_VERIFY"

	// DefaultVaultGrace is the default grace period before which to read a new
	// secret from Vault. If a lease is due to expire in 15 seconds, Consul
	// Template will read a new secret at that time minus this value.
	DefaultVaultGrace = 15 * time.Second

	// DefaultVaultRenewToken is the default value for if the Vault token should
	// be renewed.
	DefaultVaultRenewToken = true

	// DefaultVaultUnwrapToken is the default value for if the Vault token should
	// be unwrapped.
	DefaultVaultUnwrapToken = false

	// DefaultVaultRetryBase is the default value for the base time to use for
	// exponential backoff.
	DefaultVaultRetryBase = 250 * time.Millisecond

	// DefaultVaultRetryMaxAttempts is the default maximum number of attempts to
	// retry before quitting.
	DefaultVaultRetryMaxAttempts = 5
)

// VaultConfig is the configuration for connecting to a vault server.
type VaultConfig struct {
	// Address is the URI to the Vault server.
	Address *string `mapstructure:"address"`

	// Enabled controls whether the Vault integration is active.
	Enabled *bool `mapstructure:"enabled"`

	// Grace is the amount of time before a lease is about to expire to force a
	// new secret to be read.
	Grace *time.Duration `mapstructure:"grace"`

	// Namespace is the Vault namespace to use for reading/writing secrets. This can
	// also be set via the VAULT_NAMESPACE environment variable.
	Namespace *string `mapstructure:"namespace"`

	// RenewToken renews the Vault token.
	RenewToken *bool `mapstructure:"renew_token"`

	// Retry is the configuration for specifying how to behave on failure.
	Retry *RetryConfig `mapstructure:"retry"`

	// SSL indicates we should use a secure connection while talking to Vault.
	SSL *SSLConfig `mapstructure:"ssl"`

	// Token is the Vault token to communicate with for requests. It may be
	// a wrapped token or a real token. This can also be set via the VAULT_TOKEN
	// environment variable, or via the VaultAgentTokenFile.
	Token *string `mapstructure:"token" json:"-"`

	// VaultAgentTokenFile is the path of file that contains a Vault Agent token.
	// If vault_agent_token_file is specified:
	//   - Consul Template will not try to renew the Vault token.
	//   - Consul Template will periodically stat the file and update the token if it has
	// changed.
	VaultAgentTokenFile *string `mapstructure:"vault_agent_token_file" json:"-"`

	// Transport configures the low-level network connection details.
	Transport *TransportConfig `mapstructure:"transport"`

	// UnwrapToken unwraps the provided Vault token as a wrapped token.
	UnwrapToken *bool `mapstructure:"unwrap_token"`
}

// DefaultVaultConfig returns a configuration that is populated with the
// default values.
func DefaultVaultConfig() *VaultConfig {
	v := &VaultConfig{
		Retry:     DefaultRetryConfig(),
		SSL:       DefaultSSLConfig(),
		Transport: DefaultTransportConfig(),
	}

	// Force SSL when communicating with Vault.
	v.SSL.Enabled = Bool(true)

	return v
}

// Copy returns a deep copy of this configuration.
func (c *VaultConfig) Copy() *VaultConfig {
	if c == nil {
		return nil
	}

	var o VaultConfig
	o.Address = c.Address

	o.Enabled = c.Enabled

	o.Grace = c.Grace

	o.Namespace = c.Namespace

	o.RenewToken = c.RenewToken

	if c.Retry != nil {
		o.Retry = c.Retry.Copy()
	}

	if c.SSL != nil {
		o.SSL = c.SSL.Copy()
	}

	o.Token = c.Token

	o.VaultAgentTokenFile = c.VaultAgentTokenFile

	if c.Transport != nil {
		o.Transport = c.Transport.Copy()
	}

	o.UnwrapToken = c.UnwrapToken

	return &o
}

// Merge combines all values in this configuration with the values in the other
// configuration, with values in the other configuration taking precedence.
// Maps and slices are merged, most other values are overwritten. Complex
// structs define their own merge functionality.
func (c *VaultConfig) Merge(o *VaultConfig) *VaultConfig {
	if c == nil {
		if o == nil {
			return nil
		}
		return o.Copy()
	}

	if o == nil {
		return c.Copy()
	}

	r := c.Copy()

	if o.Address != nil {
		r.Address = o.Address
	}

	if o.Enabled != nil {
		r.Enabled = o.Enabled
	}

	if o.Grace != nil {
		r.Grace = o.Grace
	}

	if o.Namespace != nil {
		r.Namespace = o.Namespace
	}

	if o.RenewToken != nil {
		r.RenewToken = o.RenewToken
	}

	if o.Retry != nil {
		r.Retry = r.Retry.Merge(o.Retry)
	}

	if o.SSL != nil {
		r.SSL = r.SSL.Merge(o.SSL)
	}

	if o.Token != nil {
		r.Token = o.Token
	}

	if o.VaultAgentTokenFile != nil {
		r.VaultAgentTokenFile = o.VaultAgentTokenFile
	}

	if o.Transport != nil {
		r.Transport = r.Transport.Merge(o.Transport)
	}

	if o.UnwrapToken != nil {
		r.UnwrapToken = o.UnwrapToken
	}

	return r
}

// Finalize ensures there no nil pointers.
func (c *VaultConfig) Finalize() {
	if c.Address == nil {
		c.Address = stringFromEnv([]string{
			api.EnvVaultAddress,
		}, "")
	}

	if c.Grace == nil {
		c.Grace = TimeDuration(DefaultVaultGrace)
	}

	if c.Namespace == nil {
		c.Namespace = stringFromEnv([]string{"VAULT_NAMESPACE"}, "")
	}

	if c.RenewToken == nil {
		default_renew := DefaultVaultRenewToken
		if c.VaultAgentTokenFile != nil {
			default_renew = false
		}
		c.RenewToken = boolFromEnv([]string{
			"VAULT_RENEW_TOKEN",
		}, default_renew)
	}

	if c.Retry == nil {
		c.Retry = DefaultRetryConfig()
	}
	c.Retry.Finalize()

	// Vault has custom SSL settings
	if c.SSL == nil {
		c.SSL = DefaultSSLConfig()
	}
	if c.SSL.Enabled == nil {
		c.SSL.Enabled = Bool(true)
	}
	if c.SSL.CaCert == nil {
		c.SSL.CaCert = stringFromEnv([]string{api.EnvVaultCACert}, "")
	}
	if c.SSL.CaPath == nil {
		c.SSL.CaPath = stringFromEnv([]string{api.EnvVaultCAPath}, "")
	}
	if c.SSL.Cert == nil {
		c.SSL.Cert = stringFromEnv([]string{api.EnvVaultClientCert}, "")
	}
	if c.SSL.Key == nil {
		c.SSL.Key = stringFromEnv([]string{api.EnvVaultClientKey}, "")
	}
	if c.SSL.ServerName == nil {
		c.SSL.ServerName = stringFromEnv([]string{api.EnvVaultTLSServerName}, "")
	}
	if c.SSL.Verify == nil {
		c.SSL.Verify = antiboolFromEnv([]string{
			EnvVaultSkipVerify, api.EnvVaultInsecure}, true)
	}
	c.SSL.Finalize()

	// Order of precedence
	// 1. `vault_agent_token_file` configuration value
	// 2. `token` configuration value`
	// 3. `VAULT_TOKEN` environment variable
	if c.Token == nil {
		c.Token = stringFromEnv([]string{
			"VAULT_TOKEN",
		}, "")
	}

	if c.VaultAgentTokenFile == nil {
		if StringVal(c.Token) == "" {
			if homePath != "" {
				c.Token = stringFromFile([]string{
					homePath + "/.vault-token",
				}, "")
			}
		}
	} else {
		c.Token = stringFromFile([]string{*c.VaultAgentTokenFile}, "")
	}

	if c.Transport == nil {
		c.Transport = DefaultTransportConfig()
	}
	c.Transport.Finalize()

	if c.UnwrapToken == nil {
		c.UnwrapToken = boolFromEnv([]string{
			"VAULT_UNWRAP_TOKEN",
		}, DefaultVaultUnwrapToken)
	}

	if c.Enabled == nil {
		c.Enabled = Bool(StringPresent(c.Address))
	}
}

// GoString defines the printable version of this struct.
func (c *VaultConfig) GoString() string {
	if c == nil {
		return "(*VaultConfig)(nil)"
	}

	return fmt.Sprintf("&VaultConfig{"+
		"Address:%s, "+
		"Enabled:%s, "+
		"Grace:%s, "+
		"Namespace:%s,"+
		"RenewToken:%s, "+
		"Retry:%#v, "+
		"SSL:%#v, "+
		"Token:%t, "+
		"VaultAgentTokenFile:%t, "+
		"Transport:%#v, "+
		"UnwrapToken:%s"+
		"}",
		StringGoString(c.Address),
		BoolGoString(c.Enabled),
		TimeDurationGoString(c.Grace),
		StringGoString(c.Namespace),
		BoolGoString(c.RenewToken),
		c.Retry,
		c.SSL,
		StringPresent(c.Token),
		StringPresent(c.VaultAgentTokenFile),
		c.Transport,
		BoolGoString(c.UnwrapToken),
	)
}
<|endoftext|>


<commit_before>package list

import (
	"reflect"
	"strconv"
	"testing"
)

type StructTest struct {
	a int
	b string
}

func TestParse(t *testing.T) {
	def := []StructTest{
		StructTest{1, "Lucas"},
		StructTest{2, "Diego"},
	}

	l := Generic{}
	l.Add(StructTest{1, "Lucas"})
	l.Add(StructTest{2, "Diego"})

	list := l.Me()
	correctList := []StructTest{}

	for k := range list {
		correctList = append(correctList, list[k].(StructTest))
	}

	if !reflect.DeepEqual(def, correctList) {
		t.Error("expect equal lists")
	}
}

func TestReverse(t *testing.T) {
	l := Generic{}
	l.Add("1")
	l.Add("2")
	l.Add("3")
	l.Reverse()
	ls := l.ToSliceString()

	if ls[0] != "3" && ls[1] != "2" && ls[2] != "1" {
		t.Errorf("expect 3, 2 ,1. got: %s, %s, %s", ls[0], ls[1], ls[2])
	}
}

func TestAdd(t *testing.T) {
	l := Generic{}
	l.Add("1")
	l.Add("2")
	ls := l.ToSliceString()

	if ls[0] != "1" {
		t.Errorf("expect %s to be %s", ls[0], "1")
	}

	if ls[1] != "2" {
		t.Errorf("expect %s to be %s", ls[1], "2")
	}
}

func TestAddRange(t *testing.T) {
	l := Generic{}
	var rang []interface{}

	for i := 1; i < 3; i++ {
		rang = append(rang, strconv.Itoa(i))
	}

	l.AddRange(rang)

	ls := l.ToSliceString()

	if ls[0] != "1" {
		t.Errorf("expect %s to be %s", ls[0], "1")
	}

	if ls[1] != "2" {
		t.Errorf("expect %s to be %s", ls[1], "2")
	}
}

func TestInsertRangeAt(t *testing.T) {
	l := Generic{}
	var rang []interface{}

	l.InsertLast("a")
	l.InsertLast("b")
	l.InsertLast("e")
	l.InsertLast("f")

	rang = append(rang, "c")
	rang = append(rang, "d")

	l.InsertRangeAt(2, rang)

	ls := l.ToSliceString()

	if ls[0] != "a" && ls[1] != "b" && ls[2] != "c" && ls[3] != "d" && ls[4] != "e" && ls[5] != "f" {
		t.Errorf("expect a, b, c, d, e, f. got : %s, %s, %s, %s, %s, %s", ls[0], ls[1], ls[2], ls[3], ls[4], ls[5])
	}
}

func TestInsertAt(t *testing.T) {
	l := Generic{}

	l.InsertLast("a")
	l.InsertLast("b")
	l.InsertLast("d")

	l.InsertAt(2, "c")

	ls := l.ToSliceString()

	if ls[0] != "a" && ls[1] != "b" && ls[2] != "c" && ls[3] != "d" {
		t.Errorf("expect a, b, c, d. got : %s, %s, %s, %s", ls[0], ls[1], ls[2], ls[3])
	}
}

func TestInsertLast(t *testing.T) {
	l := Generic{}
	l.InsertLast(1.5)
	l.InsertLast(2.5)
	ls := l.ToSliceFloat64()

	if ls[0] != 1.5 {
		t.Errorf("expect %f to be %s", ls[0], "1.5")
	}

	if ls[1] != 2.5 {
		t.Errorf("expect %f to be %s", ls[1], "2.5")
	}
}

func TestGet(t *testing.T) {
	l := Generic{}
	l.Add("1")
	l.Add("2")
	l.Add("3")
	l.Add("4")
	l.Add("5")

	if l.GetFirst().(string) != "1" {
		t.Errorf("expect %s to be %s", l.GetFirst().(string), "1")
	}

	if l.GetAt(1).(string) != "2" {
		t.Errorf("expect %s to be %s", l.GetAt(1).(string), "2")
	}

	if l.GetLast().(string) != "5" {
		t.Errorf("expect %s to be %s", l.GetLast().(string), "5")
	}

	rang := l.GetRange(1, 3)

	if rang[0].(string) != "2" {
		t.Errorf("expect %s to be %s", rang[0], "2")
	}

	if rang[1].(string) != "3" {
		t.Errorf("expect %s to be %s", rang[1], "3")
	}

	if rang[2].(string) != "4" {
		t.Errorf("expect %s to be %s", rang[2], "4")
	}
}

func TestRemove(t *testing.T) {
	l := Generic{}
	l.Add("1")
	l.Add("2")
	l.Add("3")

	l.RemoveFirst()
	c1 := l.Count()
	ls1 := l.ToSliceString()
	if ls1[0] != "2" && c1 != 2 {
		t.Errorf("expect %s to be %s", ls1, "2")
		t.Errorf("expect count %d to be %d", c1, 2)
	}

	l.Add("6")
	l.RemoveLast()
	c2 := l.Count()
	ls2 := l.ToSliceString()
	if ls2[1] != "3" && c2 != 2 {
		t.Errorf("expect %s to be %s", ls2, "3")
		t.Errorf("expect count %d to be %d", c2, 2)
	}

	l.Add("9")
	l.RemoveAt(1)
	c3 := l.Count()
	ls3 := l.ToSliceString()
	if ls3[1] != "9" && c3 != 2 {
		t.Errorf("expect %s to be %s", ls3, "9")
		t.Errorf("expect count %d to be %d", c3, 2)
	}
}

func TestCount(t *testing.T) {
	l := Generic{}
	l.Add("1")
	l.Add("2")

	if l.Count() != 2 {
		t.Errorf("expect %d to be %d", l.Count(), 2)
	}
}

func TestClear(t *testing.T) {
	l := Generic{}
	l.Add("1")
	l.Add("2")
	l.Clear()

	emptySlice := make([]interface{}, 0)

	if !reflect.DeepEqual(l.Me(), emptySlice) {
		t.Error("expect equal lists")
	}
}

func filter(val interface{}) bool {
	num := val.(int)
	return num%10 == 0
}

func TestFilter(t *testing.T) {
	l := Generic{}
	l.Add(5)
	l.Add(10)
	l.Add(15)
	l.Add(20)

	list := l.Filter(filter)
	l.Clear()
	l.AddRange(list)

	listInt := l.ToSliceInt()

	if listInt[0] != 10 {
		t.Errorf("expect %d to be %d", listInt[0], 10)
	}

	if listInt[1] != 20 {
		t.Errorf("expect %d to be %d", listInt[1], 20)
	}
}

func TestFindAll(t *testing.T) {
	l := Generic{}
	l.Add(5)
	l.Add(10)
	l.Add(15)
	l.Add(20)

	list := l.FindAll(filter)
	l.Clear()
	l.AddRange(list)

	listInt := l.ToSliceInt()

	if listInt[0] != 10 {
		t.Errorf("expect %d to be %d", listInt[0], 10)
	}

	if listInt[1] != 20 {
		t.Errorf("expect %d to be %d", listInt[1], 20)
	}
}

func TestExists(t *testing.T) {
	l1 := Generic{}
	l1.Add(5)
	l1.Add(10)
	l1.Add(15)

	b1 := l1.Exists(filter)

	l2 := Generic{}
	l2.Add(1)
	l2.Add(2)
	l2.Add(3)

	b2 := l2.Exists(filter)

	if b1 != true {
		t.Errorf("expect %s to be true", b1)
	}

	if b2 != false {
		t.Errorf("expect %s to be false", b2)
	}
}

func TestFind(t *testing.T) {
	l1 := Generic{}
	l1.Add(5)
	l1.Add(10)
	l1.Add(15)

	b1 := l1.Find(filter)

	l2 := Generic{}
	l2.Add(80)
	l2.Add(2)
	l2.Add(3)

	b2 := l2.Find(filter)

	l3 := Generic{}
	l3.Add(1)
	l3.Add(2)
	l3.Add(3)

	b3 := l3.Find(filter)

	if b1.(int) != 10 {
		t.Errorf("expect %s to be 10", b1)
	}

	if b2.(int) != 80 {
		t.Errorf("expect %s to be 80", b2)
	}

	if b3 != nil {
		t.Errorf("expect %s to be nil", b3)
	}
}

func TestFindLast(t *testing.T) {
	l1 := Generic{}
	l1.Add(5)
	l1.Add(10)
	l1.Add(15)
	l1.Add(20)

	b1 := l1.FindLast(filter)

	l2 := Generic{}
	l2.Add(1)
	l2.Add(2)
	l2.Add(3)

	b2 := l2.FindLast(filter)

	if b1.(int) != 20 {
		t.Errorf("expect %s to be 10", b1)
	}

	if b2 != nil {
		t.Errorf("expect %s to be nil", b2)
	}
}

func TestFindIndex(t *testing.T) {
	l1 := Generic{}
	l1.Add(5)
	l1.Add(10)
	l1.Add(15)

	b1 := l1.FindIndex(filter)

	l2 := Generic{}
	l2.Add(80)
	l2.Add(2)
	l2.Add(3)

	b2 := l2.FindIndex(filter)

	if b1 != 1 {
		t.Errorf("expect %s to be 1", b1)
	}

	if b2 != 0 {
		t.Errorf("expect %s to be 0", b2)
	}
}

func TestFindLastIndex(t *testing.T) {
	l1 := Generic{}
	l1.Add(5)
	l1.Add(10)
	l1.Add(15)
	l1.Add(20)

	b1 := l1.FindLastIndex(filter)

	if b1 != 3 {
		t.Errorf("expect %s to be 3", b1)
	}
}

func TestFindTrueForAll(t *testing.T) {
	l1 := Generic{}
	l1.Add(10)
	l1.Add(20)
	l1.Add(30)

	b1 := l1.TrueForAll(filter)

	l2 := Generic{}
	l2.Add(10)
	l2.Add(20)
	l2.Add(30)
	l2.Add(35)

	b2 := l2.TrueForAll(filter)

	if b1 != true {
		t.Errorf("expect %s to be true", b1)
	}

	if b2 != false {
		t.Errorf("expect %s to be true", b2)
	}
}
<commit_msg>primeiro bench<commit_after>package list

import (
	"reflect"
	"strconv"
	"testing"
)

type StructTest struct {
	a int
	b string
}

func TestParse(t *testing.T) {
	def := []StructTest{
		StructTest{1, "Lucas"},
		StructTest{2, "Diego"},
	}

	l := Generic{}
	l.Add(StructTest{1, "Lucas"})
	l.Add(StructTest{2, "Diego"})

	list := l.Me()
	correctList := []StructTest{}

	for k := range list {
		correctList = append(correctList, list[k].(StructTest))
	}

	if !reflect.DeepEqual(def, correctList) {
		t.Error("expect equal lists")
	}
}

func TestReverse(t *testing.T) {
	l := Generic{}
	l.Add("1")
	l.Add("2")
	l.Add("3")
	l.Reverse()
	ls := l.ToSliceString()

	if ls[0] != "3" && ls[1] != "2" && ls[2] != "1" {
		t.Errorf("expect 3, 2 ,1. got: %s, %s, %s", ls[0], ls[1], ls[2])
	}
}

func TestAdd(t *testing.T) {
	l := Generic{}
	l.Add("1")
	l.Add("2")
	ls := l.ToSliceString()

	if ls[0] != "1" {
		t.Errorf("expect %s to be %s", ls[0], "1")
	}

	if ls[1] != "2" {
		t.Errorf("expect %s to be %s", ls[1], "2")
	}
}

func TestAddRange(t *testing.T) {
	l := Generic{}
	var rang []interface{}

	for i := 1; i < 3; i++ {
		rang = append(rang, strconv.Itoa(i))
	}

	l.AddRange(rang)

	ls := l.ToSliceString()

	if ls[0] != "1" {
		t.Errorf("expect %s to be %s", ls[0], "1")
	}

	if ls[1] != "2" {
		t.Errorf("expect %s to be %s", ls[1], "2")
	}
}

func TestInsertRangeAt(t *testing.T) {
	l := Generic{}
	var rang []interface{}

	l.InsertLast("a")
	l.InsertLast("b")
	l.InsertLast("e")
	l.InsertLast("f")

	rang = append(rang, "c")
	rang = append(rang, "d")

	l.InsertRangeAt(2, rang)

	ls := l.ToSliceString()

	if ls[0] != "a" && ls[1] != "b" && ls[2] != "c" && ls[3] != "d" && ls[4] != "e" && ls[5] != "f" {
		t.Errorf("expect a, b, c, d, e, f. got : %s, %s, %s, %s, %s, %s", ls[0], ls[1], ls[2], ls[3], ls[4], ls[5])
	}
}

func TestInsertAt(t *testing.T) {
	l := Generic{}

	l.InsertLast("a")
	l.InsertLast("b")
	l.InsertLast("d")

	l.InsertAt(2, "c")

	ls := l.ToSliceString()

	if ls[0] != "a" && ls[1] != "b" && ls[2] != "c" && ls[3] != "d" {
		t.Errorf("expect a, b, c, d. got : %s, %s, %s, %s", ls[0], ls[1], ls[2], ls[3])
	}
}

func TestInsertLast(t *testing.T) {
	l := Generic{}
	l.InsertLast(1.5)
	l.InsertLast(2.5)
	ls := l.ToSliceFloat64()

	if ls[0] != 1.5 {
		t.Errorf("expect %f to be %s", ls[0], "1.5")
	}

	if ls[1] != 2.5 {
		t.Errorf("expect %f to be %s", ls[1], "2.5")
	}
}

func TestGet(t *testing.T) {
	l := Generic{}
	l.Add("1")
	l.Add("2")
	l.Add("3")
	l.Add("4")
	l.Add("5")

	if l.GetFirst().(string) != "1" {
		t.Errorf("expect %s to be %s", l.GetFirst().(string), "1")
	}

	if l.GetAt(1).(string) != "2" {
		t.Errorf("expect %s to be %s", l.GetAt(1).(string), "2")
	}

	if l.GetLast().(string) != "5" {
		t.Errorf("expect %s to be %s", l.GetLast().(string), "5")
	}

	rang := l.GetRange(1, 3)

	if rang[0].(string) != "2" {
		t.Errorf("expect %s to be %s", rang[0], "2")
	}

	if rang[1].(string) != "3" {
		t.Errorf("expect %s to be %s", rang[1], "3")
	}

	if rang[2].(string) != "4" {
		t.Errorf("expect %s to be %s", rang[2], "4")
	}
}

func TestRemove(t *testing.T) {
	l := Generic{}
	l.Add("1")
	l.Add("2")
	l.Add("3")

	l.RemoveFirst()
	c1 := l.Count()
	ls1 := l.ToSliceString()
	if ls1[0] != "2" && c1 != 2 {
		t.Errorf("expect %s to be %s", ls1, "2")
		t.Errorf("expect count %d to be %d", c1, 2)
	}

	l.Add("6")
	l.RemoveLast()
	c2 := l.Count()
	ls2 := l.ToSliceString()
	if ls2[1] != "3" && c2 != 2 {
		t.Errorf("expect %s to be %s", ls2, "3")
		t.Errorf("expect count %d to be %d", c2, 2)
	}

	l.Add("9")
	l.RemoveAt(1)
	c3 := l.Count()
	ls3 := l.ToSliceString()
	if ls3[1] != "9" && c3 != 2 {
		t.Errorf("expect %s to be %s", ls3, "9")
		t.Errorf("expect count %d to be %d", c3, 2)
	}
}

func TestCount(t *testing.T) {
	l := Generic{}
	l.Add("1")
	l.Add("2")

	if l.Count() != 2 {
		t.Errorf("expect %d to be %d", l.Count(), 2)
	}
}

func TestClear(t *testing.T) {
	l := Generic{}
	l.Add("1")
	l.Add("2")
	l.Clear()

	emptySlice := make([]interface{}, 0)

	if !reflect.DeepEqual(l.Me(), emptySlice) {
		t.Error("expect equal lists")
	}
}

func filter(val interface{}) bool {
	num := val.(int)
	return num%10 == 0
}

func TestFilter(t *testing.T) {
	l := Generic{}
	l.Add(5)
	l.Add(10)
	l.Add(15)
	l.Add(20)

	list := l.Filter(filter)
	l.Clear()
	l.AddRange(list)

	listInt := l.ToSliceInt()

	if listInt[0] != 10 {
		t.Errorf("expect %d to be %d", listInt[0], 10)
	}

	if listInt[1] != 20 {
		t.Errorf("expect %d to be %d", listInt[1], 20)
	}
}

func TestFindAll(t *testing.T) {
	l := Generic{}
	l.Add(5)
	l.Add(10)
	l.Add(15)
	l.Add(20)

	list := l.FindAll(filter)
	l.Clear()
	l.AddRange(list)

	listInt := l.ToSliceInt()

	if listInt[0] != 10 {
		t.Errorf("expect %d to be %d", listInt[0], 10)
	}

	if listInt[1] != 20 {
		t.Errorf("expect %d to be %d", listInt[1], 20)
	}
}

func TestExists(t *testing.T) {
	l1 := Generic{}
	l1.Add(5)
	l1.Add(10)
	l1.Add(15)

	b1 := l1.Exists(filter)

	l2 := Generic{}
	l2.Add(1)
	l2.Add(2)
	l2.Add(3)

	b2 := l2.Exists(filter)

	if b1 != true {
		t.Errorf("expect %s to be true", b1)
	}

	if b2 != false {
		t.Errorf("expect %s to be false", b2)
	}
}

func TestFind(t *testing.T) {
	l1 := Generic{}
	l1.Add(5)
	l1.Add(10)
	l1.Add(15)

	b1 := l1.Find(filter)

	l2 := Generic{}
	l2.Add(80)
	l2.Add(2)
	l2.Add(3)

	b2 := l2.Find(filter)

	l3 := Generic{}
	l3.Add(1)
	l3.Add(2)
	l3.Add(3)

	b3 := l3.Find(filter)

	if b1.(int) != 10 {
		t.Errorf("expect %s to be 10", b1)
	}

	if b2.(int) != 80 {
		t.Errorf("expect %s to be 80", b2)
	}

	if b3 != nil {
		t.Errorf("expect %s to be nil", b3)
	}
}

func TestFindLast(t *testing.T) {
	l1 := Generic{}
	l1.Add(5)
	l1.Add(10)
	l1.Add(15)
	l1.Add(20)

	b1 := l1.FindLast(filter)

	l2 := Generic{}
	l2.Add(1)
	l2.Add(2)
	l2.Add(3)

	b2 := l2.FindLast(filter)

	if b1.(int) != 20 {
		t.Errorf("expect %s to be 10", b1)
	}

	if b2 != nil {
		t.Errorf("expect %s to be nil", b2)
	}
}

func TestFindIndex(t *testing.T) {
	l1 := Generic{}
	l1.Add(5)
	l1.Add(10)
	l1.Add(15)

	b1 := l1.FindIndex(filter)

	l2 := Generic{}
	l2.Add(80)
	l2.Add(2)
	l2.Add(3)

	b2 := l2.FindIndex(filter)

	if b1 != 1 {
		t.Errorf("expect %s to be 1", b1)
	}

	if b2 != 0 {
		t.Errorf("expect %s to be 0", b2)
	}
}

func TestFindLastIndex(t *testing.T) {
	l1 := Generic{}
	l1.Add(5)
	l1.Add(10)
	l1.Add(15)
	l1.Add(20)

	b1 := l1.FindLastIndex(filter)

	if b1 != 3 {
		t.Errorf("expect %s to be 3", b1)
	}
}

func TestFindTrueForAll(t *testing.T) {
	l1 := Generic{}
	l1.Add(10)
	l1.Add(20)
	l1.Add(30)

	b1 := l1.TrueForAll(filter)

	l2 := Generic{}
	l2.Add(10)
	l2.Add(20)
	l2.Add(30)
	l2.Add(35)

	b2 := l2.TrueForAll(filter)

	if b1 != true {
		t.Errorf("expect %s to be true", b1)
	}

	if b2 != false {
		t.Errorf("expect %s to be true", b2)
	}
}

func BenchmarkAddAndGetPure(b *testing.B) {
	for n := 0; n < b.N; n++ {
		var list []int

		for i := 0; i < 1000000; i++ {
			list = append(list, i)
		}

		// list[0] + list[500000]
	}
}

func BenchmarkAddAndGet(b *testing.B) {

	for n := 0; n < b.N; n++ {
		list := Generic{}
		for i := 0; i < 1000000; i++ {
			list.Add(1)
		}

		// list.GetAt(500000)
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2016 Laurent Moussault. All rights reserved.
// Licensed under a simplified BSD license (see LICENSE file).

package gfx

//------------------------------------------------------------------------------

import (
	"errors"
	"fmt"
	"unsafe"

	"github.com/drakmaniso/glam/color"
)

/*
#include <stdlib.h>
#include "glad.h"

GLuint NewPipeline() {
	GLuint p;
	glCreateProgramPipelines(1, &p);
	return p;
}

GLuint CreateVAO() {
	GLuint vao;
	glCreateVertexArrays(1, &vao);
	return vao;
}

char* PipelineLinkError(GLuint pr) {
    GLint ok = GL_TRUE;
    glGetProgramiv (pr, GL_LINK_STATUS, &ok);
    if (ok != GL_TRUE)
    {
        GLint l = 0;
        glGetProgramiv (pr, GL_INFO_LOG_LENGTH, &l);
        char *m = calloc(l + 1, sizeof(char));
        glGetProgramInfoLog (pr, l, &l, m);
        return m;
    }

	return NULL;
}

void PipelineUseShader(GLuint p, GLenum stages, GLuint shader) {
	glUseProgramStages(p, stages, shader);
}

void ClosePipeline(GLuint p, GLuint vao) {
	glDeleteVertexArrays(1, &vao);
	glDeleteProgramPipelines(1, &p);
}

static inline void BindPipeline(GLuint p, GLuint vao) {

    glEnable (GL_DEPTH_TEST);
    glDepthFunc (GL_LEQUAL);

    glEnable (GL_CULL_FACE);
    glCullFace (GL_BACK);

    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glEnable(GL_FRAMEBUFFER_SRGB);
	glBindProgramPipeline(p);
	glBindVertexArray(vao);
}

static inline void ClearColorBuffer(GLfloat *c) {
	glClearBufferfv(GL_COLOR, 0, c);
}

static inline void ClearDepthBuffer(GLfloat d) {
	glClearBufferfv(GL_DEPTH, 0, &d);
}

static inline void ClearStencilBuffer(GLint m) {
	glClearBufferiv(GL_STENCIL, 0, &m);
}
*/
import "C"

//------------------------------------------------------------------------------

// A Pipeline consists of shaders and state for the GPU.
type Pipeline struct {
	object     C.GLuint
	vao        C.GLuint
	clearColor [4]float32
}

//------------------------------------------------------------------------------

// A PipelineOption represents a configuration option used when creating a new
// pipeline.
type PipelineOption func(*Pipeline)

//------------------------------------------------------------------------------

// NewPipeline returns a pipeline with created from a specific set of shaders.
func NewPipeline(o ...PipelineOption) Pipeline {
	var p Pipeline
	p.object = C.NewPipeline() //TODO: Error Handling
	p.vao = C.CreateVAO()      //TODO: Error Handling
	for _, f := range o {
		f(&p)
	}
	return p
}

func (p *Pipeline) useShader(s shader) {
	C.PipelineUseShader(p.object, s.stages, s.shader)
	if errm := C.PipelineLinkError(p.object); errm != nil {
		defer C.free(unsafe.Pointer(errm))
		setErr(
			fmt.Errorf("shader link error:\n    %s", errors.New(C.GoString(errm))),
		)
	}
	return
}

//------------------------------------------------------------------------------

// ClearColorBuffer clears the color buffer with c.
func ClearColorBuffer(c color.RGBA) {
	C.ClearColorBuffer((*C.GLfloat)(unsafe.Pointer(&c)))
}

// ClearDepthBuffer clears the depth buffer with d.
func ClearDepthBuffer(d float32) {
	C.ClearDepthBuffer((C.GLfloat)(d))
}

// ClearStencilBuffer clears the stencil buffer with m.
func ClearStencilBuffer(m int32) {
	C.ClearStencilBuffer((C.GLint)(m))
}

//------------------------------------------------------------------------------

// Bind the pipeline for use by the GPU in all following draw commands.
func (p *Pipeline) Bind() {
	C.BindPipeline(
		p.object,
		p.vao,
	)
}

//------------------------------------------------------------------------------

// Close the pipeline.
func (p *Pipeline) Close() {
	C.ClosePipeline(p.object, p.vao)
}

//------------------------------------------------------------------------------
<commit_msg>Remove unused state in pipeline struct<commit_after>// Copyright (c) 2013-2016 Laurent Moussault. All rights reserved.
// Licensed under a simplified BSD license (see LICENSE file).

package gfx

//------------------------------------------------------------------------------

import (
	"errors"
	"fmt"
	"unsafe"

	"github.com/drakmaniso/glam/color"
)

/*
#include <stdlib.h>
#include "glad.h"

GLuint NewPipeline() {
	GLuint p;
	glCreateProgramPipelines(1, &p);
	return p;
}

GLuint CreateVAO() {
	GLuint vao;
	glCreateVertexArrays(1, &vao);
	return vao;
}

char* PipelineLinkError(GLuint pr) {
    GLint ok = GL_TRUE;
    glGetProgramiv (pr, GL_LINK_STATUS, &ok);
    if (ok != GL_TRUE)
    {
        GLint l = 0;
        glGetProgramiv (pr, GL_INFO_LOG_LENGTH, &l);
        char *m = calloc(l + 1, sizeof(char));
        glGetProgramInfoLog (pr, l, &l, m);
        return m;
    }

	return NULL;
}

void PipelineUseShader(GLuint p, GLenum stages, GLuint shader) {
	glUseProgramStages(p, stages, shader);
}

void ClosePipeline(GLuint p, GLuint vao) {
	glDeleteVertexArrays(1, &vao);
	glDeleteProgramPipelines(1, &p);
}

static inline void BindPipeline(GLuint p, GLuint vao) {

    glEnable (GL_DEPTH_TEST);
    glDepthFunc (GL_LEQUAL);

    glEnable (GL_CULL_FACE);
    glCullFace (GL_BACK);

    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glEnable(GL_FRAMEBUFFER_SRGB);
	glBindProgramPipeline(p);
	glBindVertexArray(vao);
}

static inline void ClearColorBuffer(GLfloat *c) {
	glClearBufferfv(GL_COLOR, 0, c);
}

static inline void ClearDepthBuffer(GLfloat d) {
	glClearBufferfv(GL_DEPTH, 0, &d);
}

static inline void ClearStencilBuffer(GLint m) {
	glClearBufferiv(GL_STENCIL, 0, &m);
}
*/
import "C"

//------------------------------------------------------------------------------

// A Pipeline consists of shaders and state for the GPU.
type Pipeline struct {
	object C.GLuint
	vao    C.GLuint
}

//------------------------------------------------------------------------------

// A PipelineOption represents a configuration option used when creating a new
// pipeline.
type PipelineOption func(*Pipeline)

//------------------------------------------------------------------------------

// NewPipeline returns a pipeline with created from a specific set of shaders.
func NewPipeline(o ...PipelineOption) Pipeline {
	var p Pipeline
	p.object = C.NewPipeline() //TODO: Error Handling
	p.vao = C.CreateVAO()      //TODO: Error Handling
	for _, f := range o {
		f(&p)
	}
	return p
}

func (p *Pipeline) useShader(s shader) {
	C.PipelineUseShader(p.object, s.stages, s.shader)
	if errm := C.PipelineLinkError(p.object); errm != nil {
		defer C.free(unsafe.Pointer(errm))
		setErr(
			fmt.Errorf("shader link error:\n    %s", errors.New(C.GoString(errm))),
		)
	}
	return
}

//------------------------------------------------------------------------------

// ClearColorBuffer clears the color buffer with c.
func ClearColorBuffer(c color.RGBA) {
	C.ClearColorBuffer((*C.GLfloat)(unsafe.Pointer(&c)))
}

// ClearDepthBuffer clears the depth buffer with d.
func ClearDepthBuffer(d float32) {
	C.ClearDepthBuffer((C.GLfloat)(d))
}

// ClearStencilBuffer clears the stencil buffer with m.
func ClearStencilBuffer(m int32) {
	C.ClearStencilBuffer((C.GLint)(m))
}

//------------------------------------------------------------------------------

// Bind the pipeline for use by the GPU in all following draw commands.
func (p *Pipeline) Bind() {
	C.BindPipeline(
		p.object,
		p.vao,
	)
}

//------------------------------------------------------------------------------

// Close the pipeline.
func (p *Pipeline) Close() {
	C.ClosePipeline(p.object, p.vao)
}

//------------------------------------------------------------------------------
<|endoftext|>


<commit_before>// Needs correcting on timing code
// Docs here: https://golang.org/pkg/time/#Time.UnixNano
// Testpad here: http://tour.golang.org/basics/13

package main

import (
	"fmt"
	"os"
	"strconv"
	"time"
)

func main() {
	var i int
	var x float64

	var num_steps int
	var err error

	if len(os.Args) > 1 {
		fmt.Println("beep")
		num_steps, err = strconv.Atoi(os.Args[1])
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error parsing argument as step count: %s\n", err)
			os.Exit(1)
		}
	} else {
		fmt.Println("boop")
		num_steps = 1000000000
	}

	fmt.Printf("Calculating PI using:\n  %v slices\n  1 process\n", num_steps)

	var sum float64 = 0
	step := 1.0 / float64(num_steps)

	var start time.Time = time.Now()

	for i = 0; i < num_steps; i++ {
		x = (float64(i) + 0.5) * step
		sum += 4.0 / (1.0 + x*x)
	}

	var stop time.Time = time.Now()

	var pi = sum * step

	timeTaken := (float64(stop.Sub(start)) * 0.000000001) // Durations come in ns

	fmt.Printf("Obtained value for PI: %.16g\n Time taken: %v s\n", pi, timeTaken)
}

//  const f = "%T(%v)\n"
<commit_msg>Removed debug bit accidentally left in golang version<commit_after>// Needs correcting on timing code
// Docs here: https://golang.org/pkg/time/#Time.UnixNano
// Testpad here: http://tour.golang.org/basics/13

package main

import (
	"fmt"
	"os"
	"strconv"
	"time"
)

func main() {
	var i int
	var x float64

	var num_steps int
	var err error

	if len(os.Args) > 1 {
		num_steps, err = strconv.Atoi(os.Args[1])
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error parsing argument as step count: %s\n", err)
			os.Exit(1)
		}
	} else {
		num_steps = 1000000000
	}

	fmt.Printf("Calculating PI using:\n  %v slices\n  1 process\n", num_steps)

	var sum float64 = 0
	step := 1.0 / float64(num_steps)

	var start time.Time = time.Now()

	for i = 0; i < num_steps; i++ {
		x = (float64(i) + 0.5) * step
		sum += 4.0 / (1.0 + x*x)
	}

	var stop time.Time = time.Now()

	var pi = sum * step

	timeTaken := (float64(stop.Sub(start)) * 0.000000001) // Durations come in ns

	fmt.Printf("Obtained value for PI: %.16g\n Time taken: %v s\n", pi, timeTaken)
}

//  const f = "%T(%v)\n"
<|endoftext|>