<commit_before>package meta

import (
	"errors"
	"fmt"
	"math/rand"
	"net"
	"os"
	"path/filepath"
	"time"

	"github.com/hashicorp/raft"
	"github.com/hashicorp/raft-boltdb"
)

// raftState abstracts the interaction of the raft consensus layer
// across local or remote nodes.  It is a form of the state design pattern and allows
// the meta.Store to change its behavior with the raft layer at runtime.
type raftState interface {
	openRaft() error
	initialize() error
	leader() string
	isLeader() bool
	sync(index uint64, timeout time.Duration) error
	setPeers(addrs []string) error
	addPeer(addr string) error
	invalidate() error
	close() error
	lastIndex() uint64
	apply(b []byte) error
	snapshot() error
}

// localRaft is a consensus strategy that uses a local raft implementation for
// consensus operations.
type localRaft struct {
	store     *Store
	raft      *raft.Raft
	transport *raft.NetworkTransport
	peerStore raft.PeerStore
	raftStore *raftboltdb.BoltStore
	raftLayer *raftLayer
}

func (r *localRaft) invalidate() error {
	time.Sleep(time.Second)
	return nil
}

func (r *localRaft) openRaft() error {
	s := r.store
	// Setup raft configuration.
	config := raft.DefaultConfig()
	config.Logger = s.Logger
	config.HeartbeatTimeout = s.HeartbeatTimeout
	config.ElectionTimeout = s.ElectionTimeout
	config.LeaderLeaseTimeout = s.LeaderLeaseTimeout
	config.CommitTimeout = s.CommitTimeout

	// If no peers are set in the config then start as a single server.
	config.EnableSingleNode = (len(s.peers) == 0)

	// Ensure our addr is in the peer list
	if config.EnableSingleNode {
		s.peers = append(s.peers, s.Addr.String())
	}

	// Build raft layer to multiplex listener.
	r.raftLayer = newRaftLayer(s.RaftListener, s.Addr)

	// Create a transport layer
	r.transport = raft.NewNetworkTransport(r.raftLayer, 3, 10*time.Second, os.Stderr)

	// Create peer storage.
	r.peerStore = raft.NewJSONPeers(s.path, r.transport)

	// Create the log store and stable store.
	store, err := raftboltdb.NewBoltStore(filepath.Join(s.path, "raft.db"))
	if err != nil {
		return fmt.Errorf("new bolt store: %s", err)
	}
	r.raftStore = store

	// Create the snapshot store.
	snapshots, err := raft.NewFileSnapshotStore(s.path, raftSnapshotsRetained, os.Stderr)
	if err != nil {
		return fmt.Errorf("file snapshot store: %s", err)
	}

	// Create raft log.
	ra, err := raft.NewRaft(config, (*storeFSM)(s), store, store, snapshots, r.peerStore, r.transport)
	if err != nil {
		return fmt.Errorf("new raft: %s", err)
	}
	r.raft = ra

	return nil
}

func (r *localRaft) close() error {
	// Shutdown raft.
	if r.raft != nil {
		r.raft.Shutdown()
		r.raft = nil
	}
	if r.transport != nil {
		r.transport.Close()
		r.transport = nil
	}
	if r.raftStore != nil {
		r.raftStore.Close()
		r.raftStore = nil
	}

	return nil
}

func (r *localRaft) initialize() error {
	s := r.store
	// If we have committed entries then the store is already in the cluster.
	if index, err := r.raftStore.LastIndex(); err != nil {
		return fmt.Errorf("last index: %s", err)
	} else if index > 0 {
		return nil
	}

	// Force set peers.
	if err := r.setPeers(s.peers); err != nil {
		return fmt.Errorf("set raft peers: %s", err)
	}

	return nil
}

// apply applies a serialized command to the raft log.
func (r *localRaft) apply(b []byte) error {
	// Apply to raft log.
	f := r.raft.Apply(b, 0)
	if err := f.Error(); err != nil {
		return err
	}

	// Return response if it's an error.
	// No other non-nil objects should be returned.
	resp := f.Response()
	if err, ok := resp.(error); ok {
		return lookupError(err)
	}
	assert(resp == nil, "unexpected response: %#v", resp)

	return nil
}

func (r *localRaft) lastIndex() uint64 {
	return r.raft.LastIndex()
}

func (r *localRaft) sync(index uint64, timeout time.Duration) error {
	ticker := time.NewTicker(100 * time.Millisecond)
	defer ticker.Stop()

	timer := time.NewTimer(timeout)
	defer timer.Stop()

	for {
		// Wait for next tick or timeout.
		select {
		case <-ticker.C:
		case <-timer.C:
			return errors.New("timeout")
		}

		// Compare index against current metadata.
		r.store.mu.Lock()
		ok := (r.store.data.Index >= index)
		r.store.mu.Unlock()

		// Exit if we are at least at the given index.
		if ok {
			return nil
		}
	}
}

func (r *localRaft) snapshot() error {
	future := r.raft.Snapshot()
	return future.Error()
}

// addPeer adds addr to the list of peers in the cluster.
func (r *localRaft) addPeer(addr string) error {
	peers, err := r.peerStore.Peers()
	if err != nil {
		return err
	}

	if len(peers) >= 3 {
		return nil
	}

	if fut := r.raft.AddPeer(addr); fut.Error() != nil {
		return fut.Error()
	}
	return nil
}

// setPeers sets a list of peers in the cluster.
func (r *localRaft) setPeers(addrs []string) error {
	a := make([]string, len(addrs))
	for i, s := range addrs {
		addr, err := net.ResolveTCPAddr("tcp", s)
		if err != nil {
			return fmt.Errorf("cannot resolve addr: %s, err=%s", s, err)
		}
		a[i] = addr.String()
	}
	return r.raft.SetPeers(a).Error()
}

func (r *localRaft) leader() string {
	if r.raft == nil {
		return ""
	}

	return r.raft.Leader()
}

func (r *localRaft) isLeader() bool {
	r.store.mu.RLock()
	defer r.store.mu.RUnlock()
	if r.raft == nil {
		return false
	}
	return r.raft.State() == raft.Leader
}

// remoteRaft is a consensus strategy that uses a remote raft cluster for
// consensus operations.
type remoteRaft struct {
	store *Store
}

func (r *remoteRaft) updateMetaData(ms *Data) {
	if ms == nil {
		return
	}

	updated := false
	r.store.mu.RLock()
	if ms.Index > r.store.data.Index {
		updated = true
	}
	r.store.mu.RUnlock()

	if updated {
		r.store.Logger.Printf("Updating metastore to term=%v index=%v", ms.Term, ms.Index)
		r.store.mu.Lock()
		r.store.data = ms
		r.store.mu.Unlock()
	}
}

func (r *remoteRaft) invalidate() error {
	ms, err := r.store.rpc.fetchMetaData(false)
	if err != nil {
		return err
	}

	r.updateMetaData(ms)
	return nil
}

func (r *remoteRaft) setPeers(addrs []string) error {
	return nil
}

// addPeer adds addr to the list of peers in the cluster.
func (r *remoteRaft) addPeer(addr string) error {
	return fmt.Errorf("cannot add peer using remote raft")
}

func (r *remoteRaft) openRaft() error {
	go func() {
		for {
			select {
			case <-r.store.closing:
				return
			default:
			}

			ms, err := r.store.rpc.fetchMetaData(true)
			if err != nil {
				r.store.Logger.Printf("fetch metastore: %v", err)
				time.Sleep(time.Second)
				continue
			}
			r.updateMetaData(ms)
		}
	}()
	return nil
}

func (r *remoteRaft) close() error {
	return nil
}

// apply applies a serialized command to the raft log.
func (r *remoteRaft) apply(b []byte) error {
	return fmt.Errorf("cannot apply log while in remote raft state")
}

func (r *remoteRaft) initialize() error {
	return nil
}

func (r *remoteRaft) leader() string {
	if len(r.store.peers) == 0 {
		return ""
	}

	return r.store.peers[rand.Intn(len(r.store.peers))]
}

func (r *remoteRaft) isLeader() bool {
	return false
}

func (r *remoteRaft) lastIndex() uint64 {
	return r.store.cachedData().Index
}

func (r *remoteRaft) sync(index uint64, timeout time.Duration) error {
	//FIXME: jwilder: check index and timeout
	return r.store.invalidate()
}

func (r *remoteRaft) snapshot() error {
	return fmt.Errorf("cannot snapshot while in remote raft state")
}
<commit_msg>Invalidate raft member by fetching from leader<commit_after>package meta

import (
	"errors"
	"fmt"
	"math/rand"
	"net"
	"os"
	"path/filepath"
	"time"

	"github.com/hashicorp/raft"
	"github.com/hashicorp/raft-boltdb"
)

// raftState abstracts the interaction of the raft consensus layer
// across local or remote nodes.  It is a form of the state design pattern and allows
// the meta.Store to change its behavior with the raft layer at runtime.
type raftState interface {
	openRaft() error
	initialize() error
	leader() string
	isLeader() bool
	sync(index uint64, timeout time.Duration) error
	setPeers(addrs []string) error
	addPeer(addr string) error
	invalidate() error
	close() error
	lastIndex() uint64
	apply(b []byte) error
	snapshot() error
}

// localRaft is a consensus strategy that uses a local raft implementation for
// consensus operations.
type localRaft struct {
	store     *Store
	raft      *raft.Raft
	transport *raft.NetworkTransport
	peerStore raft.PeerStore
	raftStore *raftboltdb.BoltStore
	raftLayer *raftLayer
}

func (r *localRaft) updateMetaData(ms *Data) {
	if ms == nil {
		return
	}

	updated := false
	r.store.mu.RLock()
	if ms.Index > r.store.data.Index {
		updated = true
	}
	r.store.mu.RUnlock()

	if updated {
		r.store.Logger.Printf("Updating metastore to term=%v index=%v", ms.Term, ms.Index)
		r.store.mu.Lock()
		r.store.data = ms
		r.store.mu.Unlock()
	}
}

func (r *localRaft) invalidate() error {
	if r.store.IsLeader() {
		return nil
	}

	ms, err := r.store.rpc.fetchMetaData(false)
	if err != nil {
		return err
	}

	r.updateMetaData(ms)
	return nil
}

func (r *localRaft) openRaft() error {
	s := r.store
	// Setup raft configuration.
	config := raft.DefaultConfig()
	config.Logger = s.Logger
	config.HeartbeatTimeout = s.HeartbeatTimeout
	config.ElectionTimeout = s.ElectionTimeout
	config.LeaderLeaseTimeout = s.LeaderLeaseTimeout
	config.CommitTimeout = s.CommitTimeout

	// If no peers are set in the config then start as a single server.
	config.EnableSingleNode = (len(s.peers) == 0)

	// Ensure our addr is in the peer list
	if config.EnableSingleNode {
		s.peers = append(s.peers, s.Addr.String())
	}

	// Build raft layer to multiplex listener.
	r.raftLayer = newRaftLayer(s.RaftListener, s.Addr)

	// Create a transport layer
	r.transport = raft.NewNetworkTransport(r.raftLayer, 3, 10*time.Second, os.Stderr)

	// Create peer storage.
	r.peerStore = raft.NewJSONPeers(s.path, r.transport)

	// Create the log store and stable store.
	store, err := raftboltdb.NewBoltStore(filepath.Join(s.path, "raft.db"))
	if err != nil {
		return fmt.Errorf("new bolt store: %s", err)
	}
	r.raftStore = store

	// Create the snapshot store.
	snapshots, err := raft.NewFileSnapshotStore(s.path, raftSnapshotsRetained, os.Stderr)
	if err != nil {
		return fmt.Errorf("file snapshot store: %s", err)
	}

	// Create raft log.
	ra, err := raft.NewRaft(config, (*storeFSM)(s), store, store, snapshots, r.peerStore, r.transport)
	if err != nil {
		return fmt.Errorf("new raft: %s", err)
	}
	r.raft = ra

	return nil
}

func (r *localRaft) close() error {
	// Shutdown raft.
	if r.raft != nil {
		r.raft.Shutdown()
		r.raft = nil
	}
	if r.transport != nil {
		r.transport.Close()
		r.transport = nil
	}
	if r.raftStore != nil {
		r.raftStore.Close()
		r.raftStore = nil
	}

	return nil
}

func (r *localRaft) initialize() error {
	s := r.store
	// If we have committed entries then the store is already in the cluster.
	if index, err := r.raftStore.LastIndex(); err != nil {
		return fmt.Errorf("last index: %s", err)
	} else if index > 0 {
		return nil
	}

	// Force set peers.
	if err := r.setPeers(s.peers); err != nil {
		return fmt.Errorf("set raft peers: %s", err)
	}

	return nil
}

// apply applies a serialized command to the raft log.
func (r *localRaft) apply(b []byte) error {
	// Apply to raft log.
	f := r.raft.Apply(b, 0)
	if err := f.Error(); err != nil {
		return err
	}

	// Return response if it's an error.
	// No other non-nil objects should be returned.
	resp := f.Response()
	if err, ok := resp.(error); ok {
		return lookupError(err)
	}
	assert(resp == nil, "unexpected response: %#v", resp)

	return nil
}

func (r *localRaft) lastIndex() uint64 {
	return r.raft.LastIndex()
}

func (r *localRaft) sync(index uint64, timeout time.Duration) error {
	ticker := time.NewTicker(100 * time.Millisecond)
	defer ticker.Stop()

	timer := time.NewTimer(timeout)
	defer timer.Stop()

	for {
		// Wait for next tick or timeout.
		select {
		case <-ticker.C:
		case <-timer.C:
			return errors.New("timeout")
		}

		// Compare index against current metadata.
		r.store.mu.Lock()
		ok := (r.store.data.Index >= index)
		r.store.mu.Unlock()

		// Exit if we are at least at the given index.
		if ok {
			return nil
		}
	}
}

func (r *localRaft) snapshot() error {
	future := r.raft.Snapshot()
	return future.Error()
}

// addPeer adds addr to the list of peers in the cluster.
func (r *localRaft) addPeer(addr string) error {
	peers, err := r.peerStore.Peers()
	if err != nil {
		return err
	}

	if len(peers) >= 3 {
		return nil
	}

	if fut := r.raft.AddPeer(addr); fut.Error() != nil {
		return fut.Error()
	}
	return nil
}

// setPeers sets a list of peers in the cluster.
func (r *localRaft) setPeers(addrs []string) error {
	a := make([]string, len(addrs))
	for i, s := range addrs {
		addr, err := net.ResolveTCPAddr("tcp", s)
		if err != nil {
			return fmt.Errorf("cannot resolve addr: %s, err=%s", s, err)
		}
		a[i] = addr.String()
	}
	return r.raft.SetPeers(a).Error()
}

func (r *localRaft) leader() string {
	if r.raft == nil {
		return ""
	}

	return r.raft.Leader()
}

func (r *localRaft) isLeader() bool {
	r.store.mu.RLock()
	defer r.store.mu.RUnlock()
	if r.raft == nil {
		return false
	}
	return r.raft.State() == raft.Leader
}

// remoteRaft is a consensus strategy that uses a remote raft cluster for
// consensus operations.
type remoteRaft struct {
	store *Store
}

func (r *remoteRaft) updateMetaData(ms *Data) {
	if ms == nil {
		return
	}

	updated := false
	r.store.mu.RLock()
	if ms.Index > r.store.data.Index {
		updated = true
	}
	r.store.mu.RUnlock()

	if updated {
		r.store.Logger.Printf("Updating metastore to term=%v index=%v", ms.Term, ms.Index)
		r.store.mu.Lock()
		r.store.data = ms
		r.store.mu.Unlock()
	}
}

func (r *remoteRaft) invalidate() error {
	ms, err := r.store.rpc.fetchMetaData(false)
	if err != nil {
		return err
	}

	r.updateMetaData(ms)
	return nil
}

func (r *remoteRaft) setPeers(addrs []string) error {
	return nil
}

// addPeer adds addr to the list of peers in the cluster.
func (r *remoteRaft) addPeer(addr string) error {
	return fmt.Errorf("cannot add peer using remote raft")
}

func (r *remoteRaft) openRaft() error {
	go func() {
		for {
			select {
			case <-r.store.closing:
				return
			default:
			}

			ms, err := r.store.rpc.fetchMetaData(true)
			if err != nil {
				r.store.Logger.Printf("fetch metastore: %v", err)
				time.Sleep(time.Second)
				continue
			}
			r.updateMetaData(ms)
		}
	}()
	return nil
}

func (r *remoteRaft) close() error {
	return nil
}

// apply applies a serialized command to the raft log.
func (r *remoteRaft) apply(b []byte) error {
	return fmt.Errorf("cannot apply log while in remote raft state")
}

func (r *remoteRaft) initialize() error {
	return nil
}

func (r *remoteRaft) leader() string {
	if len(r.store.peers) == 0 {
		return ""
	}

	return r.store.peers[rand.Intn(len(r.store.peers))]
}

func (r *remoteRaft) isLeader() bool {
	return false
}

func (r *remoteRaft) lastIndex() uint64 {
	return r.store.cachedData().Index
}

func (r *remoteRaft) sync(index uint64, timeout time.Duration) error {
	//FIXME: jwilder: check index and timeout
	return r.store.invalidate()
}

func (r *remoteRaft) snapshot() error {
	return fmt.Errorf("cannot snapshot while in remote raft state")
}
<|endoftext|>


<commit_before>package main

import (
	"net/http"
	"time"

	"github.com/dchest/uniuri"
	"github.com/raggaer/castro/app/models"
	"github.com/raggaer/castro/app/util"
	"github.com/ulule/limiter"
	"golang.org/x/net/context"
)

// microtimeHandler used to record all requests time spent
type microtimeHandler struct{}

// csrfHandler used to add a token to all requests
type csrfHandler struct{}

// sessionHandler used for application session
type sessionHandler struct{}

// securityHandler used to set some headers
type securityHandler struct{}

// rateLimitHandler used for rate-limiting
type rateLimitHandler struct {
	Limiter *limiter.Limiter
}

// newRateLimitHandler creates and returns a new rateLimitHandler instance
func newRateLimitHandler(limiter *limiter.Limiter) *rateLimitHandler {
	return &rateLimitHandler{limiter}
}

func (r *rateLimitHandler) ServeHTTP(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
	// Check if rate-limit is not enabled
	if !util.Config.Configuration.RateLimit.Enabled {
		next(w, req)
		return
	}

	// IP data holder
	ip := ""

	// Check if behind proxy
	if util.Config.Configuration.SSL.Proxy {

		// Get address from X-Forwarded-For
		ip = req.Header.Get("X-Forwarded-For")

	} else {

		// Get address from RemoteAddress
		ip = req.RemoteAddr
	}

	// Get rate-limit context
	ctx, err := r.Limiter.Get(ip)

	if err != nil {
		http.Error(w, "Cannot get rate-limit instance", 500)
		return
	}

	// Check for limit
	if ctx.Reached {
		http.Error(w, "Rate-limit reached", 500)
		return
	}

	// Execute next handler
	next(w, req)
}

// newSecurityHandler creates and returns a new securityHandler instance
func newSecurityHandler() *securityHandler {
	return &securityHandler{}
}

func (s *securityHandler) ServeHTTP(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
	// Retrieve nonce value from cache
	nonce, ok := util.Cache.Get("nonce")

	if !ok {

		// Create new nonce value
		nonce = uniuri.NewLen(3)

		// Save new nonce to cache
		util.Cache.Set("nonce", nonce, time.Minute*20)
	}

	// Set nonce header value
	util.Config.Configuration.Security.CSP.Script.Default = append(util.Config.Configuration.Security.CSP.Script.Default, "nonce-"+nonce.(string))

	// Create new context with cookie value
	ctx := context.WithValue(req.Context(), "nonce", nonce)

	// Set Strict-Transport-Security header if SSL
	if util.Config.Configuration.IsSSL() {

		// Set header
		w.Header().Set("Strict-Transport-Security", util.Config.Configuration.Security.STS)
	}

	// Set Engine header
	w.Header().Set("Engine", "Castro")

	// Set X-XSS-Protection header
	w.Header().Set("X-XSS-Protection", util.Config.Configuration.Security.XSS)

	// Set X-Frame-Options header
	w.Header().Set("X-Frame-Options", util.Config.Configuration.Security.Frame)

	// Set X-Content-Type-Options header
	w.Header().Set("X-Content-Type-Options", util.Config.Configuration.Security.ContentType)

	// Set Referrer-Policy header
	w.Header().Set("Referrer-Policy", util.Config.Configuration.Security.ReferrerPolicy)

	// Set X-Permitted-Cross-Domain-Policies header
	w.Header().Set("X-Permitted-Cross-Domain-Policies", util.Config.Configuration.Security.CrossDomainPolicy)

	if util.Config.Configuration.Security.CSP.Enabled {
		// Set Content-Security-Policy header
		w.Header().Set(
			"Content-Security-Policy",
			util.Config.Configuration.CSP(),
		)
	}

	// Run next handler
	next(w, req.WithContext(ctx))
}

// newSessionHandler creates and returns a new sessionHandler instance
func newSessionHandler() *sessionHandler {
	return &sessionHandler{}
}

func (s *sessionHandler) ServeHTTP(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
	// Get application cookie
	cookie, err := req.Cookie(util.Config.Configuration.Cookies.Name)

	if err != nil {

		// Cookie data
		v := make(map[string]interface{})

		// Set issuer field
		v["issuer"] = "Castro"

		// Encode cookie value
		encoded, err := util.SessionStore.Encode(util.Config.Configuration.Cookies.Name, v)

		if err != nil {
			util.Logger.Logger.Errorf("Cannot encode cookie value: %v", err)
			return
		}

		// Create cookie
		c := &http.Cookie{
			Name:     util.Config.Configuration.Cookies.Name,
			Value:    encoded,
			Path:     "/",
			MaxAge:   util.Config.Configuration.Cookies.MaxAge,
			Secure:   util.Config.Configuration.IsSSL(),
			HttpOnly: true,
		}

		// Set cookie
		http.SetCookie(w, c)

		// Create new context with cookie value
		ctx := context.WithValue(req.Context(), "session", v)

		// Run next handler
		next(w, req.WithContext(ctx))

		return
	}

	// Cookie data holder
	v := make(map[string]interface{})

	// Decode cookie
	if err := util.SessionStore.Decode(
		util.Config.Configuration.Cookies.Name,
		cookie.Value,
		&v,
	); err != nil {

		util.Logger.Logger.Errorf("Cannot decode cookie value: %v", err)
		return
	}

	// Get issuer
	issuer, ok := v["issuer"].(string)

	if !ok {
		return
	}

	// Check issuer
	if issuer != "Castro" {
		return
	}

	// Create new context with cookie value
	ctx := context.WithValue(req.Context(), "session", v)

	// Run next handler
	next(w, req.WithContext(ctx))
}

// newCsrfHandler creates and returns a new csrfHandler instance
func newCsrfHandler() *csrfHandler {
	return &csrfHandler{}
}

func (c *csrfHandler) ServeHTTP(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
	// Get session
	session, ok := req.Context().Value("session").(map[string]interface{})

	if !ok {
		return
	}

	// Get token
	token, ok := session["csrf-token"].(*models.CsrfToken)

	if !ok {

		// Check if request is valid
		if req.Method == http.MethodPost {
			return
		}

		// Create token
		tkn := models.CsrfToken{
			Token: uniuri.New(),
			At:    time.Now(),
		}

		// Set session value
		session["csrf-token"] = &tkn

		// Encode session
		encoded, err := util.SessionStore.Encode(util.Config.Configuration.Cookies.Name, session)

		if err != nil {
			util.Logger.Logger.Errorf("Cannot encode session: %v", err)
		}

		// Create cookie
		c := &http.Cookie{
			Name:     util.Config.Configuration.Cookies.Name,
			Value:    encoded,
			Path:     "/",
			MaxAge:   util.Config.Configuration.Cookies.MaxAge,
			Secure:   util.Config.Configuration.IsSSL(),
			HttpOnly: true,
		}

		// Set cookie
		http.SetCookie(w, c)

		// Create context
		ctx := context.WithValue(req.Context(), "csrf-token", &tkn)

		// Run next handler
		next(w, req.WithContext(ctx))

		return
	}

	// Check if valid token
	if req.Method == http.MethodPost && req.FormValue("_csrf") != token.Token {
		return
	}

	// Check if token  is old
	if time.Now().Before(token.At) {

		// Create new token
		token.Token = uniuri.New()
		token.At = time.Now()

		// Encode session
		encoded, err := util.SessionStore.Encode(util.Config.Configuration.Cookies.Name, session)

		if err != nil {
			util.Logger.Logger.Errorf("Cannot encode session: %v", err)
		}

		// Create cookie
		c := util.SessionCookie(encoded)

		// Set cookie
		http.SetCookie(w, c)
	}

	// Create context
	ctx := context.WithValue(req.Context(), "csrf-token", token)

	// Run next handler
	next(w, req.WithContext(ctx))
}

// newMicrotimeHandler creates and returns a new microtimeHandler instance
func newMicrotimeHandler() *microtimeHandler {
	return &microtimeHandler{}
}

// ServeHTTP makes microtimeHandler compatible with negroni
func (m *microtimeHandler) ServeHTTP(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
	// Set timestamp on the request context
	ctx := context.WithValue(req.Context(), "microtime", time.Now())

	// Execute next handler
	next(w, req.WithContext(ctx))
}
<commit_msg>Fix #75<commit_after>package main

import (
	"net/http"
	"strings"
	"time"

	"github.com/dchest/uniuri"
	"github.com/raggaer/castro/app/models"
	"github.com/raggaer/castro/app/util"
	"github.com/ulule/limiter"
	"golang.org/x/net/context"
)

// microtimeHandler used to record all requests time spent
type microtimeHandler struct{}

// csrfHandler used to add a token to all requests
type csrfHandler struct{}

// sessionHandler used for application session
type sessionHandler struct{}

// securityHandler used to set some headers
type securityHandler struct{}

// rateLimitHandler used for rate-limiting
type rateLimitHandler struct {
	Limiter *limiter.Limiter
}

// newRateLimitHandler creates and returns a new rateLimitHandler instance
func newRateLimitHandler(limiter *limiter.Limiter) *rateLimitHandler {
	return &rateLimitHandler{limiter}
}

func (r *rateLimitHandler) ServeHTTP(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
	// Check if rate-limit is not enabled
	if !util.Config.Configuration.RateLimit.Enabled {
		next(w, req)
		return
	}

	// IP data holder
	ip := ""

	// Check if behind proxy
	if util.Config.Configuration.SSL.Proxy {

		// Get address from X-Forwarded-For
		ip = req.Header.Get("X-Forwarded-For")

	} else {

		// Get address from RemoteAddress
		ip = req.RemoteAddr
	}

	// Get rate-limit context
	ctx, err := r.Limiter.Get(ip)

	if err != nil {
		http.Error(w, "Cannot get rate-limit instance", 500)
		return
	}

	// Check for limit
	if ctx.Reached {
		http.Error(w, "Rate-limit reached", 500)
		return
	}

	// Execute next handler
	next(w, req)
}

// newSecurityHandler creates and returns a new securityHandler instance
func newSecurityHandler() *securityHandler {
	return &securityHandler{}
}

func (s *securityHandler) ServeHTTP(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
	// Retrieve nonce value from cache
	nonce, ok := util.Cache.Get("nonce")

	if !ok {

		// Create new nonce value
		nonce = uniuri.NewLen(3)

		// Save new nonce to cache
		util.Cache.Set("nonce", nonce, time.Minute*20)
	}

	// Set nonce header value
	util.Config.Configuration.Security.CSP.Script.Default = append(util.Config.Configuration.Security.CSP.Script.Default, "nonce-"+nonce.(string))

	// Create new context with cookie value
	ctx := context.WithValue(req.Context(), "nonce", nonce)

	// Set Strict-Transport-Security header if SSL
	if util.Config.Configuration.IsSSL() {

		// Set header
		w.Header().Set("Strict-Transport-Security", util.Config.Configuration.Security.STS)
	}

	// Set Engine header
	w.Header().Set("Engine", "Castro")

	// Set X-XSS-Protection header
	w.Header().Set("X-XSS-Protection", util.Config.Configuration.Security.XSS)

	// Set X-Frame-Options header
	w.Header().Set("X-Frame-Options", util.Config.Configuration.Security.Frame)

	// Set X-Content-Type-Options header
	w.Header().Set("X-Content-Type-Options", util.Config.Configuration.Security.ContentType)

	// Set Referrer-Policy header
	w.Header().Set("Referrer-Policy", util.Config.Configuration.Security.ReferrerPolicy)

	// Set X-Permitted-Cross-Domain-Policies header
	w.Header().Set("X-Permitted-Cross-Domain-Policies", util.Config.Configuration.Security.CrossDomainPolicy)

	if util.Config.Configuration.Security.CSP.Enabled {
		// Set Content-Security-Policy header
		w.Header().Set(
			"Content-Security-Policy",
			util.Config.Configuration.CSP(),
		)
	}

	// Run next handler
	next(w, req.WithContext(ctx))
}

// newSessionHandler creates and returns a new sessionHandler instance
func newSessionHandler() *sessionHandler {
	return &sessionHandler{}
}

func (s *sessionHandler) ServeHTTP(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
	// Get application cookie
	cookie, err := req.Cookie(util.Config.Configuration.Cookies.Name)

	if err != nil {

		// Cookie data
		v := make(map[string]interface{})

		// Set issuer field
		v["issuer"] = "Castro"

		// Encode cookie value
		encoded, err := util.SessionStore.Encode(util.Config.Configuration.Cookies.Name, v)

		if err != nil {
			util.Logger.Logger.Errorf("Cannot encode cookie value: %v", err)
			return
		}

		// Create cookie
		c := &http.Cookie{
			Name:     util.Config.Configuration.Cookies.Name,
			Value:    encoded,
			Path:     "/",
			MaxAge:   util.Config.Configuration.Cookies.MaxAge,
			Secure:   util.Config.Configuration.IsSSL(),
			HttpOnly: true,
		}

		// Set cookie
		http.SetCookie(w, c)

		// Create new context with cookie value
		ctx := context.WithValue(req.Context(), "session", v)

		// Run next handler
		next(w, req.WithContext(ctx))

		return
	}

	// Cookie data holder
	v := make(map[string]interface{})

	// Decode cookie
	if err := util.SessionStore.Decode(
		util.Config.Configuration.Cookies.Name,
		cookie.Value,
		&v,
	); err != nil {

		util.Logger.Logger.Errorf("Cannot decode cookie value: %v", err)
		return
	}

	// Get issuer
	issuer, ok := v["issuer"].(string)

	if !ok {
		return
	}

	// Check issuer
	if issuer != "Castro" {
		return
	}

	// Create new context with cookie value
	ctx := context.WithValue(req.Context(), "session", v)

	// Run next handler
	next(w, req.WithContext(ctx))
}

// newCsrfHandler creates and returns a new csrfHandler instance
func newCsrfHandler() *csrfHandler {
	return &csrfHandler{}
}

func (c *csrfHandler) ServeHTTP(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
	// Skip nocsrf routes
	if strings.HasPrefix(req.URL.Path, "/nocsrf") {

		// Run next handler
		next(w, req)
		return
	}

	// Get session
	session, ok := req.Context().Value("session").(map[string]interface{})

	if !ok {
		return
	}

	// Get token
	token, ok := session["csrf-token"].(*models.CsrfToken)

	if !ok {

		// Check if request is valid
		if req.Method == http.MethodPost {
			return
		}

		// Create token
		tkn := models.CsrfToken{
			Token: uniuri.New(),
			At:    time.Now(),
		}

		// Set session value
		session["csrf-token"] = &tkn

		// Encode session
		encoded, err := util.SessionStore.Encode(util.Config.Configuration.Cookies.Name, session)

		if err != nil {
			util.Logger.Logger.Errorf("Cannot encode session: %v", err)
		}

		// Create cookie
		c := &http.Cookie{
			Name:     util.Config.Configuration.Cookies.Name,
			Value:    encoded,
			Path:     "/",
			MaxAge:   util.Config.Configuration.Cookies.MaxAge,
			Secure:   util.Config.Configuration.IsSSL(),
			HttpOnly: true,
		}

		// Set cookie
		http.SetCookie(w, c)

		// Create context
		ctx := context.WithValue(req.Context(), "csrf-token", &tkn)

		// Run next handler
		next(w, req.WithContext(ctx))

		return
	}

	// Check if valid token
	if req.Method == http.MethodPost && req.FormValue("_csrf") != token.Token {
		return
	}

	// Check if token  is old
	if time.Now().Before(token.At) {

		// Create new token
		token.Token = uniuri.New()
		token.At = time.Now()

		// Encode session
		encoded, err := util.SessionStore.Encode(util.Config.Configuration.Cookies.Name, session)

		if err != nil {
			util.Logger.Logger.Errorf("Cannot encode session: %v", err)
		}

		// Create cookie
		c := util.SessionCookie(encoded)

		// Set cookie
		http.SetCookie(w, c)
	}

	// Create context
	ctx := context.WithValue(req.Context(), "csrf-token", token)

	// Run next handler
	next(w, req.WithContext(ctx))
}

// newMicrotimeHandler creates and returns a new microtimeHandler instance
func newMicrotimeHandler() *microtimeHandler {
	return &microtimeHandler{}
}

// ServeHTTP makes microtimeHandler compatible with negroni
func (m *microtimeHandler) ServeHTTP(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
	// Set timestamp on the request context
	ctx := context.WithValue(req.Context(), "microtime", time.Now())

	// Execute next handler
	next(w, req.WithContext(ctx))
}
<|endoftext|>


<commit_before><commit_msg>gopï: fix typo<commit_after><|endoftext|>


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

package main

import (
	"fmt"
	"strings"

	"github.com/minio/cli"
	"github.com/minio/mc/pkg/client"
	"github.com/minio/minio-xl/pkg/probe"
)

type mirrorURLs struct {
	SourceContent  *client.Content
	TargetContents []*client.Content
	Error          *probe.Error `json:"-"`
}

func (m mirrorURLs) isEmpty() bool {
	if m.SourceContent == nil && len(m.TargetContents) == 0 && m.Error == nil {
		return true
	}
	if m.SourceContent.Size == 0 && len(m.TargetContents) == 0 && m.Error == nil {
		return true
	}
	return false
}

//
//   * MIRROR ARGS - VALID CASES
//   =========================
//   mirror(d1..., [](d2)) -> []mirror(d1/f, [](d2/d1/f))

// checkMirrorSyntax(URLs []string)
func checkMirrorSyntax(ctx *cli.Context) {
	if len(ctx.Args()) < 2 {
		cli.ShowCommandHelpAndExit(ctx, "mirror", 1) // last argument is exit code.
	}

	// Check if any of the arg is recursive type.
	for _, arg := range ctx.Args() {
		// Recursive URLs are not allowed in target.
		if isURLRecursive(arg) {
			fatalIf(errDummy().Trace(), fmt.Sprintf("Recursive option is not supported for target ‘%s’ argument.", arg))
		}
	}

	// extract URLs.
	URLs, err := args2URLs(ctx.Args())
	fatalIf(err.Trace(ctx.Args()...), "Unable to parse arguments.")

	srcURL := URLs[0]
	tgtURLs := URLs[1:]

	/****** Generic rules *******/
	// Recursive source URL.
	newSrcURL := stripRecursiveURL(srcURL)
	_, srcContent, err := url2Stat(newSrcURL)
	if err != nil && !prefixExists(newSrcURL) {
		fatalIf(err.Trace(srcURL), "Unable to stat source ‘"+newSrcURL+"’.")
	}

	if err == nil && !srcContent.Type.IsDir() {
		fatalIf(errInvalidArgument().Trace(srcContent.URL.String(), srcContent.Type.String()), fmt.Sprintf("Source ‘%s’ is not a folder. Only folders are supported by mirror command.", srcURL))
	}

	if len(tgtURLs) == 0 && tgtURLs == nil {
		fatalIf(errInvalidArgument().Trace(), "Invalid target arguments to mirror command.")
	}

	for _, tgtURL := range tgtURLs {
		url := client.NewURL(tgtURL)
		if url.Host != "" {
			if url.Path == string(url.Separator) {
				fatalIf(errInvalidArgument().Trace(), fmt.Sprintf("Target ‘%s’ does not contain bucket name.", tgtURL))
			}
		}
	}
}

func deltaSourceTargets(sourceURL string, targetURLs []string, mirrorURLsCh chan<- mirrorURLs) {
	defer close(mirrorURLsCh)

	// source and targets are always directories
	sourceSeparator := string(client.NewURL(sourceURL).Separator)
	if !strings.HasSuffix(sourceURL, sourceSeparator) {
		sourceURL = sourceURL + sourceSeparator
	}
	for i, url := range targetURLs {
		targetSeparator := string(client.NewURL(url).Separator)
		if !strings.HasSuffix(url, targetSeparator) {
			targetURLs[i] = url + targetSeparator
		}
	}

	// array of objectDifference functions corresponding to their targetURL
	objectDifferenceArray := make([]objectDifference, len(targetURLs))

	for i := range targetURLs {
		var err *probe.Error
		objectDifferenceArray[i], err = objectDifferenceFactory(targetURLs[i])
		if err != nil {
			mirrorURLsCh <- mirrorURLs{Error: err.Trace()}
			return
		}
	}

	sourceClient, err := url2Client(sourceURL)
	if err != nil {
		mirrorURLsCh <- mirrorURLs{Error: err.Trace(sourceURL)}
		return
	}

	for sourceContent := range sourceClient.List(true, false) {
		if sourceContent.Err != nil {
			mirrorURLsCh <- mirrorURLs{Error: sourceContent.Err.Trace()}
			continue
		}
		if sourceContent.Type.IsDir() {
			continue
		}
		suffix := strings.TrimPrefix(sourceContent.URL.String(), sourceURL)
		targetContents := []*client.Content{}
		for i, difference := range objectDifferenceArray {
			differ, err := difference(suffix, sourceContent.Type, sourceContent.Size)
			if err != nil {
				mirrorURLsCh <- mirrorURLs{Error: err.Trace()}
				continue
			}
			if differ == differNone {
				// no difference, continue
				continue
			}
			if differ == differType {
				mirrorURLsCh <- mirrorURLs{Error: errInvalidTarget(suffix)}
				continue
			}
			if differ == differSize && !mirrorIsForce {
				// size differs and force not set
				mirrorURLsCh <- mirrorURLs{Error: errOverWriteNotAllowed(sourceContent.URL.String())}
				continue
			}
			// either available only in source or size differs and force is set
			targetPath := urlJoinPath(targetURLs[i], suffix)
			targetContent := client.Content{URL: *client.NewURL(targetPath)}
			targetContents = append(targetContents, &targetContent)
		}
		if len(targetContents) > 0 {
			mirrorURLsCh <- mirrorURLs{
				SourceContent:  sourceContent,
				TargetContents: targetContents,
			}
		}
	}
}

func prepareMirrorURLs(sourceURL string, targetURLs []string) <-chan mirrorURLs {
	mirrorURLsCh := make(chan mirrorURLs)
	go deltaSourceTargets(sourceURL, targetURLs, mirrorURLsCh)
	return mirrorURLsCh
}
<commit_msg>detect invalid bucketname for mirror #1404<commit_after>/*
 * Minio Client (C) 2015 Minio, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package main

import (
	"fmt"
	"strings"

	"github.com/minio/cli"
	"github.com/minio/mc/pkg/client"
	"github.com/minio/minio-xl/pkg/probe"
)

type mirrorURLs struct {
	SourceContent  *client.Content
	TargetContents []*client.Content
	Error          *probe.Error `json:"-"`
}

func (m mirrorURLs) isEmpty() bool {
	if m.SourceContent == nil && len(m.TargetContents) == 0 && m.Error == nil {
		return true
	}
	if m.SourceContent.Size == 0 && len(m.TargetContents) == 0 && m.Error == nil {
		return true
	}
	return false
}

//
//   * MIRROR ARGS - VALID CASES
//   =========================
//   mirror(d1..., [](d2)) -> []mirror(d1/f, [](d2/d1/f))

// checkMirrorSyntax(URLs []string)
func checkMirrorSyntax(ctx *cli.Context) {
	if len(ctx.Args()) < 2 {
		cli.ShowCommandHelpAndExit(ctx, "mirror", 1) // last argument is exit code.
	}

	// Check if any of the arg is recursive type.
	for _, arg := range ctx.Args() {
		// Recursive URLs are not allowed in target.
		if isURLRecursive(arg) {
			fatalIf(errDummy().Trace(), fmt.Sprintf("Recursive option is not supported for target ‘%s’ argument.", arg))
		}
	}

	// extract URLs.
	URLs, err := args2URLs(ctx.Args())
	fatalIf(err.Trace(ctx.Args()...), "Unable to parse arguments.")

	srcURL := URLs[0]
	tgtURLs := URLs[1:]

	/****** Generic rules *******/
	// Recursive source URL.
	newSrcURL := stripRecursiveURL(srcURL)
	_, srcContent, err := url2Stat(newSrcURL)
	if err != nil && !prefixExists(newSrcURL) {
		fatalIf(err.Trace(srcURL), "Unable to stat source ‘"+newSrcURL+"’.")
	}

	if err == nil && !srcContent.Type.IsDir() {
		fatalIf(errInvalidArgument().Trace(srcContent.URL.String(), srcContent.Type.String()), fmt.Sprintf("Source ‘%s’ is not a folder. Only folders are supported by mirror command.", srcURL))
	}

	if len(tgtURLs) == 0 && tgtURLs == nil {
		fatalIf(errInvalidArgument().Trace(), "Invalid target arguments to mirror command.")
	}

	for _, tgtURL := range tgtURLs {
		url := client.NewURL(tgtURL)
		if url.Host != "" {
			if url.Path == string(url.Separator) {
				fatalIf(errInvalidArgument().Trace(), fmt.Sprintf("Target ‘%s’ does not contain bucket name.", tgtURL))
			}
		}
		_, _, err = url2Stat(tgtURL)
		// we die on any error other than client.PathNotFound - destination directory need not exist.
		if _, ok := err.ToGoError().(client.PathNotFound); !ok {
			fatalIf(err.Trace(), fmt.Sprintf("Unable to stat %s", tgtURL))
		}
	}
}

func deltaSourceTargets(sourceURL string, targetURLs []string, mirrorURLsCh chan<- mirrorURLs) {
	defer close(mirrorURLsCh)

	// source and targets are always directories
	sourceSeparator := string(client.NewURL(sourceURL).Separator)
	if !strings.HasSuffix(sourceURL, sourceSeparator) {
		sourceURL = sourceURL + sourceSeparator
	}
	for i, url := range targetURLs {
		targetSeparator := string(client.NewURL(url).Separator)
		if !strings.HasSuffix(url, targetSeparator) {
			targetURLs[i] = url + targetSeparator
		}
	}

	// array of objectDifference functions corresponding to their targetURL
	objectDifferenceArray := make([]objectDifference, len(targetURLs))

	for i := range targetURLs {
		var err *probe.Error
		objectDifferenceArray[i], err = objectDifferenceFactory(targetURLs[i])
		if err != nil {
			mirrorURLsCh <- mirrorURLs{Error: err.Trace()}
			return
		}
	}

	sourceClient, err := url2Client(sourceURL)
	if err != nil {
		mirrorURLsCh <- mirrorURLs{Error: err.Trace(sourceURL)}
		return
	}

	for sourceContent := range sourceClient.List(true, false) {
		if sourceContent.Err != nil {
			mirrorURLsCh <- mirrorURLs{Error: sourceContent.Err.Trace()}
			continue
		}
		if sourceContent.Type.IsDir() {
			continue
		}
		suffix := strings.TrimPrefix(sourceContent.URL.String(), sourceURL)
		targetContents := []*client.Content{}
		for i, difference := range objectDifferenceArray {
			differ, err := difference(suffix, sourceContent.Type, sourceContent.Size)
			if err != nil {
				mirrorURLsCh <- mirrorURLs{Error: err.Trace()}
				continue
			}
			if differ == differNone {
				// no difference, continue
				continue
			}
			if differ == differType {
				mirrorURLsCh <- mirrorURLs{Error: errInvalidTarget(suffix)}
				continue
			}
			if differ == differSize && !mirrorIsForce {
				// size differs and force not set
				mirrorURLsCh <- mirrorURLs{Error: errOverWriteNotAllowed(sourceContent.URL.String())}
				continue
			}
			// either available only in source or size differs and force is set
			targetPath := urlJoinPath(targetURLs[i], suffix)
			targetContent := client.Content{URL: *client.NewURL(targetPath)}
			targetContents = append(targetContents, &targetContent)
		}
		if len(targetContents) > 0 {
			mirrorURLsCh <- mirrorURLs{
				SourceContent:  sourceContent,
				TargetContents: targetContents,
			}
		}
	}
}

func prepareMirrorURLs(sourceURL string, targetURLs []string) <-chan mirrorURLs {
	mirrorURLsCh := make(chan mirrorURLs)
	go deltaSourceTargets(sourceURL, targetURLs, mirrorURLsCh)
	return mirrorURLsCh
}
<|endoftext|>


<commit_before>package misc

import (
	"fmt"
	"github.com/kr/pretty"
	"log"
	"reflect"
)

type Service struct {
	Name string  `yaml:"name"`
	Ints []*Item `yaml:"ints"`
}

type Item struct {
	Name string `yaml:"name"`
}

func main() {
	log.SetFlags(log.Lshortfile)
	s := &Service{Name: "s", Ints: []*Item{
		{
			Name: "i1",
		},
		{
			Name: "i2",
		},
	}}
	// Original
	pretty.Println(s)
	fmt.Printf("%p\n", s.Ints[0])
	// Add a new item
	addItem(s)
	pretty.Println(s)
	// Address of 1st Item are unchanged
	fmt.Printf("%p\n", s.Ints[0])
	fmt.Printf("%p\n", s.Ints[2])
	// Remove an item
	removeItem(s)
	pretty.Println(s)
	// Address of 1st Item are unchanged
	fmt.Printf("%p\n", s.Ints[0])
	fmt.Printf("%p\n", s.Ints[1])
}

func addItem(s *Service) {
	val := reflect.ValueOf(s)
	if val.Kind() == reflect.Ptr {
		val = val.Elem()
	}
	slice := val.FieldByName("Ints")
	sliceType := slice.Type()
	// get item's type in slice
	itemType := sliceType.Elem()
	if itemType.Kind() == reflect.Ptr {
		itemType = itemType.Elem()
	}
	newItem := reflect.New(itemType)
	newItem.Elem().FieldByName("Name").SetString("HAHAHA")
	slice.Set(reflect.Append(slice, newItem))
}

func removeItem(s *Service) {
	val := reflect.ValueOf(s)
	if val.Kind() == reflect.Ptr {
		val = val.Elem()
	}
	slice := val.FieldByName("Ints")
	// remove 2nd item
	i := 1
	resultSlice := reflect.AppendSlice(slice.Slice(0, i), slice.Slice(i+1, slice.Len()))
	slice.Set(resultSlice)
}
<commit_msg>fix package name<commit_after>package main

import (
	"fmt"
	"github.com/kr/pretty"
	"log"
	"reflect"
)

type Service struct {
	Name string  `yaml:"name"`
	Ints []*Item `yaml:"ints"`
}

type Item struct {
	Name string `yaml:"name"`
}

func main() {
	log.SetFlags(log.Lshortfile)
	s := &Service{Name: "s", Ints: []*Item{
		{
			Name: "i1",
		},
		{
			Name: "i2",
		},
	}}
	// Original
	pretty.Println(s)
	fmt.Printf("%p\n", s.Ints[0])
	// Add a new item
	addItem(s)
	pretty.Println(s)
	// Address of 1st Item are unchanged
	fmt.Printf("%p\n", s.Ints[0])
	fmt.Printf("%p\n", s.Ints[2])
	// Remove an item
	removeItem(s)
	pretty.Println(s)
	// Address of 1st Item are unchanged
	fmt.Printf("%p\n", s.Ints[0])
	fmt.Printf("%p\n", s.Ints[1])
}

func addItem(s *Service) {
	val := reflect.ValueOf(s)
	if val.Kind() == reflect.Ptr {
		val = val.Elem()
	}
	slice := val.FieldByName("Ints")
	sliceType := slice.Type()
	// get item's type in slice
	itemType := sliceType.Elem()
	if itemType.Kind() == reflect.Ptr {
		itemType = itemType.Elem()
	}
	newItem := reflect.New(itemType)
	newItem.Elem().FieldByName("Name").SetString("HAHAHA")
	slice.Set(reflect.Append(slice, newItem))
}

func removeItem(s *Service) {
	val := reflect.ValueOf(s)
	if val.Kind() == reflect.Ptr {
		val = val.Elem()
	}
	slice := val.FieldByName("Ints")
	// remove 2nd item
	i := 1
	resultSlice := reflect.AppendSlice(slice.Slice(0, i), slice.Slice(i+1, slice.Len()))
	slice.Set(resultSlice)
}
<|endoftext|>


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

package time

import (
	"testing";
	"time";
)

export func TestTick(t *testing.T) {
	const (
		Delta uint64 = 100*1e6;
		Count uint64 = 10;
	);
	c := Tick(Delta);
	t0 := Nanoseconds();
	for i := 0; i < Count; i++ {
		<-c;
	}
	t1 := Nanoseconds();
	ns := t1 - t0;
	target := int64(Delta*Count);
	slop := target*2/10;
	if ns < target - slop || ns > target + slop {
		t.Fatalf("%d ticks of %g ns took %g ns, expected %g", Count, float64(Delta), float64(ns), float64(target));
	}
}
<commit_msg>Remove types from constants, since they didn't match what Tick() expected.<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package time

import (
	"testing";
	"time";
)

export func TestTick(t *testing.T) {
	const (
		Delta = 100*1e6;
		Count = 10;
	);
	c := Tick(Delta);
	t0 := Nanoseconds();
	for i := 0; i < Count; i++ {
		<-c;
	}
	t1 := Nanoseconds();
	ns := t1 - t0;
	target := int64(Delta*Count);
	slop := target*2/10;
	if ns < target - slop || ns > target + slop {
		t.Fatalf("%d ticks of %g ns took %g ns, expected %g", Count, float64(Delta), float64(ns), float64(target));
	}
}
<|endoftext|>


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

package runtime

import "unsafe"

// sigtrampPC is the PC at the beginning of the jmpdefer assembly function.
// The traceback needs to recognize it on link register architectures.
var sigtrampPC uintptr

var sigtramp struct{} // assembly function

func init() {
	sigtrampPC = funcPC(sigtramp)
	systraceback = traceback_windows
}

func traceback_windows(f *_func, frame *stkframe, gp *g, printing bool, callback func(*stkframe, unsafe.Pointer) bool, v unsafe.Pointer) (changed, aborted bool) {
	// The main traceback thinks it has found a function. Check this.

	// Windows exception handlers run on the actual g stack (there is room
	// dedicated to this below the usual "bottom of stack"), not on a separate
	// stack. As a result, we have to be able to unwind past the exception
	// handler when called to unwind during stack growth inside the handler.
	// Recognize the frame at the call to sighandler in sigtramp and unwind
	// using the context argument passed to the call. This is awful.
	if f != nil && f.entry == sigtrampPC && frame.pc > f.entry {
		var r *context
		// Invoke callback so that stack copier sees an uncopyable frame.
		if callback != nil {
			frame.continpc = frame.pc
			frame.argp = 0
			frame.arglen = 0
			if !callback(frame, v) {
				aborted = true
				return
			}
		}
		r = (*context)(unsafe.Pointer(frame.sp + ptrSize))
		frame.pc = contextPC(r)
		frame.sp = contextSP(r)
		frame.lr = 0
		frame.fp = 0
		frame.fn = nil
		if printing && showframe(nil, gp) {
			print("----- exception handler -----\n")
		}
		f = findfunc(frame.pc)
		if f == nil {
			print("runtime: unknown pc ", hex(frame.pc), " after exception handler\n")
			if callback != nil {
				gothrow("unknown pc")
			}
		}
		frame.fn = f
		changed = true
		return
	}

	return
}
<commit_msg>runtime: fix sigtrampPC on Windows<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package runtime

import "unsafe"

// sigtrampPC is the PC at the beginning of the jmpdefer assembly function.
// The traceback needs to recognize it on link register architectures.
var sigtrampPC uintptr

func sigtramp()

func init() {
	sigtrampPC = funcPC(sigtramp)
	systraceback = traceback_windows
}

func traceback_windows(f *_func, frame *stkframe, gp *g, printing bool, callback func(*stkframe, unsafe.Pointer) bool, v unsafe.Pointer) (changed, aborted bool) {
	// The main traceback thinks it has found a function. Check this.

	// Windows exception handlers run on the actual g stack (there is room
	// dedicated to this below the usual "bottom of stack"), not on a separate
	// stack. As a result, we have to be able to unwind past the exception
	// handler when called to unwind during stack growth inside the handler.
	// Recognize the frame at the call to sighandler in sigtramp and unwind
	// using the context argument passed to the call. This is awful.
	if f != nil && f.entry == sigtrampPC && frame.pc > f.entry {
		var r *context
		// Invoke callback so that stack copier sees an uncopyable frame.
		if callback != nil {
			frame.continpc = frame.pc
			frame.argp = 0
			frame.arglen = 0
			if !callback(frame, v) {
				aborted = true
				return
			}
		}
		r = (*context)(unsafe.Pointer(frame.sp + ptrSize))
		frame.pc = contextPC(r)
		frame.sp = contextSP(r)
		frame.lr = 0
		frame.fp = 0
		frame.fn = nil
		if printing && showframe(nil, gp) {
			print("----- exception handler -----\n")
		}
		f = findfunc(frame.pc)
		if f == nil {
			print("runtime: unknown pc ", hex(frame.pc), " after exception handler\n")
			if callback != nil {
				gothrow("unknown pc")
			}
		}
		frame.fn = f
		changed = true
		return
	}

	return
}
<|endoftext|>


<commit_before>package pipelineserver

import (
	"errors"
	"fmt"
	"sync"
	"time"

	"github.com/pachyderm/pachyderm/src/pfs"
	"github.com/pachyderm/pachyderm/src/pps"
	"github.com/pachyderm/pachyderm/src/pps/persist"
	"go.pedge.io/google-protobuf"
	"go.pedge.io/proto/rpclog"
	"go.pedge.io/protolog"
	"golang.org/x/net/context"
)

type apiServer struct {
	protorpclog.Logger
	pfsAPIClient     pfs.APIClient
	jobAPIClient     pps.JobAPIClient
	persistAPIClient persist.APIClient

	started                          bool
	pipelineNameToPipelineController map[string]*pipelineController
	lock                             *sync.Mutex
}

func newAPIServer(
	pfsAPIClient pfs.APIClient,
	jobAPIClient pps.JobAPIClient,
	persistAPIClient persist.APIClient,
) *apiServer {
	return &apiServer{
		protorpclog.NewLogger("pachyderm.pps.PipelineAPI"),
		pfsAPIClient,
		jobAPIClient,
		persistAPIClient,
		false,
		make(map[string]*pipelineController),
		&sync.Mutex{},
	}
}

func (a *apiServer) Start() error {
	a.lock.Lock()
	defer a.lock.Unlock()
	// TODO: volatile bool?
	if a.started {
		// TODO: abstract error to public variable
		return errors.New("pachyderm.pps.pipelineserver: already started")
	}
	a.started = true
	pipelineInfos, err := a.ListPipeline(context.Background(), &pps.ListPipelineRequest{})
	if err != nil {
		return err
	}
	for _, pipelineInfo := range pipelineInfos.PipelineInfo {
		if err := a.addPipelineController(pipelineInfo); err != nil {
			return err
		}
	}
	return nil
}

func (a *apiServer) CreatePipeline(ctx context.Context, request *pps.CreatePipelineRequest) (response *google_protobuf.Empty, err error) {
	defer func(start time.Time) { a.Log(request, response, err, time.Since(start)) }(time.Now())
	persistPipelineInfo := &persist.PipelineInfo{
		PipelineName: request.Pipeline.Name,
		Transform:    request.Transform,
		Input:        request.Input,
		Output:       request.Output,
	}
	if _, err := a.persistAPIClient.CreatePipelineInfo(ctx, persistPipelineInfo); err != nil {
		return nil, err
	}
	a.lock.Lock()
	defer a.lock.Unlock()
	if err := a.addPipelineController(persistPipelineInfoToPipelineInfo(persistPipelineInfo)); err != nil {
		// TODO: proper create/rollback (do not commit transaction with create)
		if _, rollbackErr := a.persistAPIClient.DeletePipelineInfo(ctx, request.Pipeline); rollbackErr != nil {
			return nil, fmt.Errorf("%v-%v", err, rollbackErr)
		}
		return nil, err
	}
	return google_protobuf.EmptyInstance, nil
}

func (a *apiServer) InspectPipeline(ctx context.Context, request *pps.InspectPipelineRequest) (response *pps.PipelineInfo, err error) {
	defer func(start time.Time) { a.Log(request, response, err, time.Since(start)) }(time.Now())
	persistPipelineInfo, err := a.persistAPIClient.GetPipelineInfo(ctx, request.Pipeline)
	if err != nil {
		return nil, err
	}
	return persistPipelineInfoToPipelineInfo(persistPipelineInfo), nil
}

func (a *apiServer) ListPipeline(ctx context.Context, request *pps.ListPipelineRequest) (response *pps.PipelineInfos, err error) {
	defer func(start time.Time) { a.Log(request, response, err, time.Since(start)) }(time.Now())
	persistPipelineInfos, err := a.persistAPIClient.ListPipelineInfos(ctx, google_protobuf.EmptyInstance)
	if err != nil {
		return nil, err
	}
	pipelineInfos := make([]*pps.PipelineInfo, len(persistPipelineInfos.PipelineInfo))
	for i, persistPipelineInfo := range persistPipelineInfos.PipelineInfo {
		pipelineInfos[i] = persistPipelineInfoToPipelineInfo(persistPipelineInfo)
	}
	return &pps.PipelineInfos{
		PipelineInfo: pipelineInfos,
	}, nil
}

func (a *apiServer) DeletePipeline(ctx context.Context, request *pps.DeletePipelineRequest) (response *google_protobuf.Empty, err error) {
	if _, err := a.persistAPIClient.DeletePipelineInfo(ctx, request.Pipeline); err != nil {
		return nil, err
	}
	a.lock.Lock()
	defer a.lock.Unlock()
	if err := a.removePipelineController(request.Pipeline.Name); err != nil {
		return nil, err
	}
	return google_protobuf.EmptyInstance, nil
}

func persistPipelineInfoToPipelineInfo(persistPipelineInfo *persist.PipelineInfo) *pps.PipelineInfo {
	return &pps.PipelineInfo{
		Pipeline: &pps.Pipeline{
			Name: persistPipelineInfo.PipelineName,
		},
		Transform: persistPipelineInfo.Transform,
		Input:     persistPipelineInfo.Input,
		Output:    persistPipelineInfo.Output,
	}
}

func (a *apiServer) addPipelineController(pipelineInfo *pps.PipelineInfo) error {
	if _, ok := a.pipelineNameToPipelineController[pipelineInfo.Pipeline.Name]; ok {
		protolog.Warnf("pachyderm.pps.pipelineserver: had a create change event for an existing pipeline: %v", pipelineInfo)
		if err := a.removePipelineController(pipelineInfo.Pipeline.Name); err != nil {
			return err
		}
	}
	pipelineController := newPipelineController(
		a.pfsAPIClient,
		a.jobAPIClient,
		pps.NewLocalPipelineAPIClient(a),
		pipelineInfo,
	)
	a.pipelineNameToPipelineController[pipelineInfo.Pipeline.Name] = pipelineController
	return pipelineController.Start()
}

func (a *apiServer) removePipelineController(name string) error {
	pipelineController, ok := a.pipelineNameToPipelineController[name]
	if ok {
		delete(a.pipelineNameToPipelineController, name)
		return pipelineController.Cancel()
	}
	protolog.Warnf("pachyderm.pps.pipelineserver: no pipeline registered for name: %s", name)
	return nil
}
<commit_msg>Stop using pipelineController.<commit_after>package pipelineserver

import (
	"sync"
	"time"

	"github.com/pachyderm/pachyderm/src/pfs"
	"github.com/pachyderm/pachyderm/src/pps"
	"github.com/pachyderm/pachyderm/src/pps/persist"
	"go.pedge.io/google-protobuf"
	"go.pedge.io/proto/rpclog"
	"go.pedge.io/protolog"
	"golang.org/x/net/context"
)

type apiServer struct {
	protorpclog.Logger
	pfsAPIClient     pfs.APIClient
	jobAPIClient     pps.JobAPIClient
	persistAPIClient persist.APIClient

	cancelFuncs map[pps.Pipeline]func()
	lock        sync.Mutex
}

func newAPIServer(
	pfsAPIClient pfs.APIClient,
	jobAPIClient pps.JobAPIClient,
	persistAPIClient persist.APIClient,
) *apiServer {
	return &apiServer{
		protorpclog.NewLogger("pachyderm.pps.PipelineAPI"),
		pfsAPIClient,
		jobAPIClient,
		persistAPIClient,
		make(map[pps.Pipeline]func()),
		sync.Mutex{},
	}
}

func (a *apiServer) Start() error {
	pipelineInfos, err := a.ListPipeline(context.Background(), &pps.ListPipelineRequest{})
	if err != nil {
		return err
	}
	for _, pipelineInfo := range pipelineInfos.PipelineInfo {
		go func() {
			if err := a.runPipeline(pipelineInfo); err != nil {
				protolog.Printf("pipeline errored: %s", err.Error())
			}
		}()
	}
	return nil
}

func (a *apiServer) CreatePipeline(ctx context.Context, request *pps.CreatePipelineRequest) (response *google_protobuf.Empty, err error) {
	defer func(start time.Time) { a.Log(request, response, err, time.Since(start)) }(time.Now())
	persistPipelineInfo := &persist.PipelineInfo{
		PipelineName: request.Pipeline.Name,
		Transform:    request.Transform,
		Input:        request.Input,
		Output:       request.Output,
	}
	if _, err := a.persistAPIClient.CreatePipelineInfo(ctx, persistPipelineInfo); err != nil {
		return nil, err
	}
	go func() {
		if err := a.runPipeline(persistPipelineInfoToPipelineInfo(persistPipelineInfo)); err != nil {
			protolog.Printf("pipeline errored: %s", err.Error())
		}
	}()
	return google_protobuf.EmptyInstance, nil
}

func (a *apiServer) InspectPipeline(ctx context.Context, request *pps.InspectPipelineRequest) (response *pps.PipelineInfo, err error) {
	defer func(start time.Time) { a.Log(request, response, err, time.Since(start)) }(time.Now())
	persistPipelineInfo, err := a.persistAPIClient.GetPipelineInfo(ctx, request.Pipeline)
	if err != nil {
		return nil, err
	}
	return persistPipelineInfoToPipelineInfo(persistPipelineInfo), nil
}

func (a *apiServer) ListPipeline(ctx context.Context, request *pps.ListPipelineRequest) (response *pps.PipelineInfos, err error) {
	defer func(start time.Time) { a.Log(request, response, err, time.Since(start)) }(time.Now())
	persistPipelineInfos, err := a.persistAPIClient.ListPipelineInfos(ctx, google_protobuf.EmptyInstance)
	if err != nil {
		return nil, err
	}
	pipelineInfos := make([]*pps.PipelineInfo, len(persistPipelineInfos.PipelineInfo))
	for i, persistPipelineInfo := range persistPipelineInfos.PipelineInfo {
		pipelineInfos[i] = persistPipelineInfoToPipelineInfo(persistPipelineInfo)
	}
	return &pps.PipelineInfos{
		PipelineInfo: pipelineInfos,
	}, nil
}

func (a *apiServer) DeletePipeline(ctx context.Context, request *pps.DeletePipelineRequest) (response *google_protobuf.Empty, err error) {
	if _, err := a.persistAPIClient.DeletePipelineInfo(ctx, request.Pipeline); err != nil {
		return nil, err
	}
	a.lock.Lock()
	defer a.lock.Unlock()
	a.cancelFuncs[*request.Pipeline]()
	delete(a.cancelFuncs, *request.Pipeline)
	return google_protobuf.EmptyInstance, nil
}

func persistPipelineInfoToPipelineInfo(persistPipelineInfo *persist.PipelineInfo) *pps.PipelineInfo {
	return &pps.PipelineInfo{
		Pipeline: &pps.Pipeline{
			Name: persistPipelineInfo.PipelineName,
		},
		Transform: persistPipelineInfo.Transform,
		Input:     persistPipelineInfo.Input,
		Output:    persistPipelineInfo.Output,
	}
}

func (a *apiServer) runPipeline(pipelineInfo *pps.PipelineInfo) error {
	ctx, cancel := context.WithCancel(context.Background())
	a.lock.Lock()
	a.cancelFuncs[*pipelineInfo.Pipeline] = cancel
	a.lock.Unlock()
	for {
		var lastCommit *pfs.Commit
		listCommitRequest := &pfs.ListCommitRequest{
			Repo:       pipelineInfo.Input,
			CommitType: pfs.CommitType_COMMIT_TYPE_READ,
			From:       lastCommit,
			Block:      true,
		}
		commitInfos, err := a.pfsAPIClient.ListCommit(ctx, listCommitRequest)
		if err != nil {
			return err
		}
		for _, commitInfo := range commitInfos.CommitInfo {
			outParentCommit, err := a.bestParent(pipelineInfo, commitInfo)
			if err != nil {
				return err
			}
			_, err = a.jobAPIClient.CreateJob(
				context.Background(),
				&pps.CreateJobRequest{
					Spec: &pps.CreateJobRequest_Pipeline{
						Pipeline: pipelineInfo.Pipeline,
					},
					Input:        commitInfo.Commit,
					OutputParent: outParentCommit,
				},
			)
		}
	}
	return nil
}

func (a *apiServer) bestParent(pipelineInfo *pps.PipelineInfo, inputCommitInfo *pfs.CommitInfo) (*pfs.Commit, error) {
	for {
		jobInfos, err := a.jobAPIClient.ListJob(
			context.Background(),
			&pps.ListJobRequest{
				Pipeline: pipelineInfo.Pipeline,
				Input:    inputCommitInfo.Commit,
			},
		)
		if err != nil {
			return nil, err
		}
		// newest to oldest assumed
		for _, jobInfo := range jobInfos.JobInfo {
			if jobInfo.Output != nil {
				outputCommitInfo, err := a.pfsAPIClient.InspectCommit(context.TODO(), &pfs.InspectCommitRequest{Commit: jobInfo.Output})
				if err != nil {
					return nil, err
				}
				if outputCommitInfo.CommitType == pfs.CommitType_COMMIT_TYPE_READ {
					return outputCommitInfo.Commit, nil
				}
			}
		}
		if inputCommitInfo.ParentCommit.Id == pfs.InitialCommitID {
			return &pfs.Commit{
				Repo: inputCommitInfo.Commit.Repo,
				Id:   pfs.InitialCommitID,
			}, nil
		}
		inputCommitInfo, err = a.pfsAPIClient.InspectCommit(context.TODO(), &pfs.InspectCommitRequest{Commit: inputCommitInfo.ParentCommit})
		if err != nil {
			return nil, err
		}
	}
}
<|endoftext|>


<commit_before>package models

import (
  "fmt"
  "github.com/spacedock-io/registry/db"
)

type Tag struct {
  Id         int64
  Tag        string `sql:"not null"`
  ImageId    int64
  Repo       string `sql:"not null"`
  Namespace  string `sql:"not null"`
}

func CreateTag(namespace string, repo string, tag string, uuid string) error {
  fmt.Printf("CreateTag uuid: %+v\n", uuid)

  image, err := GetImage(uuid)
  if err != nil {
    return err
  }

  t := Tag{
    Tag: tag,
    Repo: repo,
    Namespace: namespace,
  }
  image.Tags = append(image.Tags, t)
  return image.Save()
}

func GetTags(namespace string, repo string) ([]Tag, error) {
  var t []Tag
  q := db.DB.Where("Namespace = ? and Repo = ?", namespace, repo).Find(&t)
  if q.Error != nil {
    return nil, q.Error
  }
  return t, nil
}

func GetTag(namespace string, repo string, tag string) (*Tag, error) {
  t := &Tag{}
  q := db.DB.Where("Namespace = ? and Repo = ?", namespace, repo).Find(t)
  if q.Error != nil {
    return nil, q.Error
  }
  return t, nil
}

func (tag *Tag) Save() error {
  q := db.DB.Save(tag)
  if q.Error != nil {
    return TagSaveErr
  }
  return nil
}

func (tag *Tag) Create() error {
  return tag.Save()
}
<commit_msg>Remove debug statements<commit_after>package models

import (
  "github.com/spacedock-io/registry/db"
)

type Tag struct {
  Id         int64
  Tag        string `sql:"not null"`
  ImageId    int64
  Repo       string `sql:"not null"`
  Namespace  string `sql:"not null"`
}

func CreateTag(namespace string, repo string, tag string, uuid string) error {
  image, err := GetImage(uuid)
  if err != nil {
    return err
  }

  t := Tag{
    Tag: tag,
    Repo: repo,
    Namespace: namespace,
  }
  image.Tags = append(image.Tags, t)
  return image.Save()
}

func GetTags(namespace string, repo string) ([]Tag, error) {
  var t []Tag
  q := db.DB.Where("Namespace = ? and Repo = ?", namespace, repo).Find(&t)
  if q.Error != nil {
    return nil, q.Error
  }
  return t, nil
}

func GetTag(namespace string, repo string, tag string) (*Tag, error) {
  t := &Tag{}
  q := db.DB.Where("Namespace = ? and Repo = ?", namespace, repo).Find(t)
  if q.Error != nil {
    return nil, q.Error
  }
  return t, nil
}

func (tag *Tag) Save() error {
  q := db.DB.Save(tag)
  if q.Error != nil {
    return TagSaveErr
  }
  return nil
}

func (tag *Tag) Create() error {
  return tag.Save()
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"github.com/bwmarrin/discordgo"
	"github.com/jonas747/dca"
	"github.com/rylio/ytdl"
	"io"
)

func msgYoutube(s *discordgo.Session, m *discordgo.MessageCreate, msglist []string) {
	switch msglist[1] {
	case "play":
		addToQueue(s, m, msglist[2:])
	case "stop":
		stop(s, m, msglist[2:])
	}
}

func addToQueue(s *discordgo.Session, m *discordgo.MessageCreate, msglist []string) {
	guild, err := guildDetails(m.ChannelID, s)
	if err != nil {
		errorLog.Println(err)
		return
	}

	srvr := sMap.Server[guild.ID]
	srvr.VoiceInst.Done = make(chan error)

	// TODO error messages boolean logic end of func
	for _, vs := range guild.VoiceStates {
		if vs.UserID == m.Author.ID {
			if (vs.ChannelID == srvr.VoiceInst.ChannelID) || !srvr.VoiceInst.Playing {
				vc, err := s.ChannelVoiceJoin(guild.ID, vs.ChannelID, false, true)
				if err != nil {
					errorLog.Println(err)
					return
				}

				srvr.VoiceInst.Queue = append(srvr.VoiceInst.Queue, song{
					URL: msglist[0],
				})

				vid, err := ytdl.GetVideoInfo(srvr.VoiceInst.Queue[0].URL)
				if err != nil {
					errorLog.Println("1", err)
					return
				}

				s.ChannelMessageSend(m.ChannelID, "Added "+vid.Title+" to the queue!")

				if !srvr.VoiceInst.Playing {
					go play(s, m, sMap.Server[guild.ID], vc)
				}
				return
			}

			if vs.ChannelID != srvr.VoiceInst.ChannelID {
				s.ChannelMessageSend(m.ChannelID, "Already playing in a different voice channel :(")
			}
		}
	}

	s.ChannelMessageSend(m.ChannelID, "Need to be in a voice channel!")
}

func play(s *discordgo.Session, m *discordgo.MessageCreate, srvr *server, vc *discordgo.VoiceConnection) {
	if len(srvr.VoiceInst.Queue) == 0 {
		vc.Disconnect()
		srvr.VoiceInst.ChannelID = ""
		srvr.VoiceInst.Playing = false
		s.ChannelMessageSend(m.ChannelID, "🔇 Done queue!")
		return
	}

	vid, err := ytdl.GetVideoInfo(srvr.VoiceInst.Queue[0].URL)
	if err != nil {
		errorLog.Println("1", err)
		return
	}

	format := vid.Formats.Extremes(ytdl.FormatAudioBitrateKey, true)[0]
	videoURL, err := vid.GetDownloadURL(format)
	if err != nil {
		errorLog.Println("2", err)
		return
	}

	options := dca.StdEncodeOptions
	options.RawOutput = true
	options.Bitrate = 96
	options.Application = "lowdelay"
	options.Volume = 200

	encSesh, err := dca.EncodeFile(videoURL.String(), options)
	if err != nil {
		errorLog.Println("3", err)
		return
	}
	defer encSesh.Cleanup()

	dca.NewStream(encSesh, vc, srvr.VoiceInst.Done)
	s.ChannelMessageSend(m.ChannelID, "🔊 Playing: "+vid.Title)

	srvr.VoiceInst.Playing = true
	srvr.VoiceInst.ChannelID = vc.ChannelID

	for {
		err = <-srvr.VoiceInst.Done
		if err != nil && err != io.EOF && err.Error() != "stop" {
			errorLog.Println("Music stream error", err)
		}
		break
	}

	srvr.VoiceInst.Queue = srvr.VoiceInst.Queue[1:]
	go play(s, m, srvr, vc)

	return
}

func stop(s *discordgo.Session, m *discordgo.MessageCreate, msglist []string) {
	guild, err := guildDetails(m.ChannelID, s)
	if err != nil {
		errorLog.Println("Guild details error", err)
		return
	}

	voiceInst := &(sMap.Server[guild.ID].VoiceInst)
	voiceInst.Done <- errors.New("stop")
}
<commit_msg>gofmt and removed fmt import<commit_after>package main

import (
	"errors"
	"github.com/bwmarrin/discordgo"
	"github.com/jonas747/dca"
	"github.com/rylio/ytdl"
	"io"
)

func msgYoutube(s *discordgo.Session, m *discordgo.MessageCreate, msglist []string) {
	switch msglist[1] {
	case "play":
		addToQueue(s, m, msglist[2:])
	case "stop":
		stop(s, m, msglist[2:])
	}
}

func addToQueue(s *discordgo.Session, m *discordgo.MessageCreate, msglist []string) {
	guild, err := guildDetails(m.ChannelID, s)
	if err != nil {
		errorLog.Println(err)
		return
	}

	srvr := sMap.Server[guild.ID]
	srvr.VoiceInst.Done = make(chan error)

	// TODO error messages boolean logic end of func
	for _, vs := range guild.VoiceStates {
		if vs.UserID == m.Author.ID {
			if (vs.ChannelID == srvr.VoiceInst.ChannelID) || !srvr.VoiceInst.Playing {
				vc, err := s.ChannelVoiceJoin(guild.ID, vs.ChannelID, false, true)
				if err != nil {
					errorLog.Println(err)
					return
				}

				srvr.VoiceInst.Queue = append(srvr.VoiceInst.Queue, song{
					URL: msglist[0],
				})

				vid, err := ytdl.GetVideoInfo(srvr.VoiceInst.Queue[0].URL)
				if err != nil {
					errorLog.Println("1", err)
					return
				}

				s.ChannelMessageSend(m.ChannelID, "Added "+vid.Title+" to the queue!")

				if !srvr.VoiceInst.Playing {
					go play(s, m, sMap.Server[guild.ID], vc)
				}
				return
			}

			if vs.ChannelID != srvr.VoiceInst.ChannelID {
				s.ChannelMessageSend(m.ChannelID, "Already playing in a different voice channel :(")
			}
		}
	}

	s.ChannelMessageSend(m.ChannelID, "Need to be in a voice channel!")
}

func play(s *discordgo.Session, m *discordgo.MessageCreate, srvr *server, vc *discordgo.VoiceConnection) {
	if len(srvr.VoiceInst.Queue) == 0 {
		vc.Disconnect()
		srvr.VoiceInst.ChannelID = ""
		srvr.VoiceInst.Playing = false
		s.ChannelMessageSend(m.ChannelID, "🔇 Done queue!")
		return
	}

	vid, err := ytdl.GetVideoInfo(srvr.VoiceInst.Queue[0].URL)
	if err != nil {
		errorLog.Println("1", err)
		return
	}

	format := vid.Formats.Extremes(ytdl.FormatAudioBitrateKey, true)[0]
	videoURL, err := vid.GetDownloadURL(format)
	if err != nil {
		errorLog.Println("2", err)
		return
	}

	options := dca.StdEncodeOptions
	options.RawOutput = true
	options.Bitrate = 96
	options.Application = "lowdelay"
	options.Volume = 200

	encSesh, err := dca.EncodeFile(videoURL.String(), options)
	if err != nil {
		errorLog.Println("3", err)
		return
	}
	defer encSesh.Cleanup()

	dca.NewStream(encSesh, vc, srvr.VoiceInst.Done)
	s.ChannelMessageSend(m.ChannelID, "🔊 Playing: "+vid.Title)

	srvr.VoiceInst.Playing = true
	srvr.VoiceInst.ChannelID = vc.ChannelID

	for {
		err = <-srvr.VoiceInst.Done
		if err != nil && err != io.EOF && err.Error() != "stop" {
			errorLog.Println("Music stream error", err)
		}
		break
	}

	srvr.VoiceInst.Queue = srvr.VoiceInst.Queue[1:]
	go play(s, m, srvr, vc)

	return
}

func stop(s *discordgo.Session, m *discordgo.MessageCreate, msglist []string) {
	guild, err := guildDetails(m.ChannelID, s)
	if err != nil {
		errorLog.Println("Guild details error", err)
		return
	}

	voiceInst := &(sMap.Server[guild.ID].VoiceInst)
	voiceInst.Done <- errors.New("stop")
}
<|endoftext|>


<commit_before>package tips

// Reflection in Go:
// https://golang.org/pkg/reflect/

import (
	"reflect"
	"strings"
	"testing"
)

func TestReflectInt(t *testing.T) {
	i := 123
	ti := reflect.TypeOf(i)
	if ti.Kind() != reflect.Int {
		t.Errorf("Expected reflect.Int but got %v", ti.Kind())
		return
	}
	v := reflect.ValueOf(i)
	if v.Type() != ti {
		t.Errorf("Expected %v but got %v", ti, v.Type())
		return
	}
	// Retrieve the actual value.
	var ri int64 = v.Int()
	if ri != int64(i) {
		t.Errorf("Expected %d but got %d", i, ri)
	}
	// Interestingly, this does not panic :)
	if v.String() != "<int Value>" {
		t.Errorf("Expected an empty string but got %q", v.String())
	}
	// This panics! (using unaddressable value)
	// v.SetInt(456)
}

func TestReflectIntPointer(t *testing.T) {
	i := 123
	var p interface{} = &i
	ty := reflect.TypeOf(p)
	if ty.Kind() != reflect.Ptr {
		t.Errorf("Expected reflect.Ptr but got %v", ty.Kind())
		return
	}
	v := reflect.ValueOf(p)
	if v.Type() != ty {
		t.Errorf("Expected %v but got %v", ty, v.Type())
		return
	}
	var ev reflect.Value = v.Elem()
	if ev.Type().Kind() != reflect.Int {
		t.Errorf("Expected reflect.Int but got %v", ev.Type().Kind())
	}
	if ev.Kind() != reflect.Int {
		t.Errorf("Expected reflect.Int but got %v", ev.Kind())
	}
	if !ev.CanSet() {
		t.Error("CanSet must return true.")
	}
	// Set value!
	v.Elem().SetInt(456)
	if i != 456 {
		t.Errorf("Expected value: %d", i)
	}
}

func TestReflectStruct(t *testing.T) {
	type entry struct {
		name string
		Age  int `myattr:"myvalue"`
	}
	e := entry{name: "Alice", Age: 13}

	ty := reflect.TypeOf(e)
	if ty.Kind() != reflect.Struct {
		t.Errorf("Unexpected kind: %v", ty.Kind())
		return
	}
	if ty.NumField() != 2 {
		t.Errorf("Unexpected NumField(): %d", ty.NumField())
		return
	}
	var f0 reflect.StructField = ty.Field(0)
	if f0.Name != "name" || f0.Type.Kind() != reflect.String {
		t.Errorf("Unexpected field attrs: name = %q, type = %s", f0.Name, f0.Type)
	}
	f1 := ty.Field(1)
	if f1.Name != "Age" || f1.Type.Kind() != reflect.Int {
		t.Errorf("Unexpected field attrs: name = %q, type = %s", f1.Name, f1.Type)
	}
	// How to retrieve struct field tags.
	// https://golang.org/pkg/reflect/#StructTag
	if f1.Tag.Get("myattr") != "myvalue" {
		t.Errorf("Unexpected tag value: %q", f1.Tag.Get("myattr"))
	}

	// Value of struct.
	v := reflect.ValueOf(e)
	if v.Type() != ty {
		t.Errorf("Expected %v but got %v", ty, v.Type())
	}
	if v.NumField() != 2 {
		t.Errorf("Unexpected NumField(): %d", v.NumField())
		return
	}
	var vf0 reflect.Value = v.Field(0)
	if vf0.Type().Kind() != reflect.String {
		t.Errorf("Unexpected type for vf0: %v", vf0.Type())
	}
	if vf0.String() != "Alice" {
		t.Errorf("Unexpected value: %q", vf0.String())
	}
	vf1 := v.Field(1)
	if vf1.Type().Kind() != reflect.Int {
		t.Errorf("Unexpected type for vf1: %v", vf1.Type())
	}
	if vf0.String() != "Alice" {
		t.Errorf("Unexpected value: %q", vf0.String())
	}
	if vf1.Int() != 13 {
		t.Errorf("Unexpected value: %d", vf1.Int())
	}
	// fields of struct are not settable.
	if vf0.CanSet() || vf1.CanSet() {
		t.Error("CanSet of all fields must return false")
	}

	// This panics "using value obtained using unexported field".
	// vf0.SetString("hello")
	//
	// This panics with "using unaddressable value".
	// vf1.SetInt(20)
}

func TestReflectStructPointer(t *testing.T) {
	type entry struct {
		name string
		Age  int `myattr:"myvalue"`
	}
	p := &entry{name: "Alice", Age: 13}
	ty := reflect.TypeOf(p)
	if ty.Kind() != reflect.Ptr {
		t.Errorf("Unexpected kind: %v", ty.Kind())
		return
	}
	// Set field values.
	v := reflect.ValueOf(p)
	v.Elem().Field(1).SetInt(24)
	if p.Age != 24 {
		t.Errorf("Unexpected value: %v", p.Age)
	}
	// This panics "using value obtained using unexported field".
	// v.Elem().Field(0).SetString("Bob")
}

func TestRelectEmbed(t *testing.T) {
	type embed struct {
		str string
		Str string
	}
	type Embed struct {
		Int     int
		integer int
	}
	type entry struct {
		F float32
		embed
		Embed
		float64
	}
	e := entry{
		F: 3.14,
		embed: embed{
			str: "hello",
			Str: "World",
		},
		Embed: Embed{
			Int:     100,
			integer: 10,
		},
		float64: 12.34,
	}
	ty := reflect.TypeOf(e)
	// Embeded struct are treated as fields as you may expect.
	if ty.NumField() != 4 {
		t.Errorf("Unexpected NumField() = %d", ty.NumField())
		return
	}
	f := ty.Field(0)
	if !(f.Name == "F" && !f.Anonymous) {
		t.Errorf("Unexpected: %#v", f)
	}
	f = ty.Field(1)
	// Anonymous is true if the field is an embedded field.
	if !(f.Name == "embed" && f.Anonymous) {
		t.Errorf("Unexpected: %#v", f)
	}
	f = ty.Field(2)
	// Anonymous is true if the field is an embedded field.
	if !(f.Name == "Embed" && f.Anonymous) {
		t.Errorf("Unexpected: %#v", f)
	}
	f = ty.Field(3)
	// Anonymous is true if the field is an embedded field.
	if !(f.Name == "float64" && f.Anonymous) {
		t.Errorf("Unexpected: %#v", f)
	}

	// TODO: Investigate Value.
}

func TestReflectFunc(t *testing.T) {
	sum := func(x int, y int32) float32 {
		return float32(x + int(y))
	}
	var inter interface{} = sum
	ty := reflect.TypeOf(inter)
	if ty.Kind() != reflect.Func {
		t.Errorf("Unexpected kind: %v", ty.Kind())
		return
	}
	// Types of arguments and return values.
	if ty.NumIn() != 2 {
		t.Errorf("Unexpected NumIn() = %v", ty.NumIn())
	}
	if ty.NumOut() != 1 {
		t.Errorf("Unexpected NumOut() = %v", ty.NumOut())
	}
	if ty.In(0).Kind() != reflect.Int {
		t.Errorf("Unexpected first arg type: %v", ty.In(0).Kind())
	}
	if ty.Out(0).Kind() != reflect.Float32 {
		t.Errorf("Unexpected first arg type: %v", ty.Out(0).Kind())
	}

	// Invoke
	v := reflect.ValueOf(inter)
	returns := v.Call([]reflect.Value{
		reflect.ValueOf(12),
		reflect.ValueOf(int32(34)),
	})
	if len(returns) != 1 {
		t.Errorf("Unexpected size of slice was returned: %d", len(returns))
		return
	}
	f := returns[0].Float()
	if f != 46.0 {
		t.Errorf("Unexpected return value: %f", f)
	}

	// Call panics if arguments are invalid.
	// v.Call([]reflect.Value{})
}

func TestReflectSlice(t *testing.T) {
	slicePtr := reflect.New(reflect.SliceOf(reflect.TypeOf(int(0))))
	for i := 0; i < 10; i++ {
		slicePtr.Elem().Set(reflect.Append(slicePtr.Elem(), reflect.ValueOf(i*i)))
	}
	s := slicePtr.Elem().Interface().([]int)
	expected := []int{0, 1, 4, 9, 16, 25, 36, 49, 64, 81}
	if !reflect.DeepEqual(s, expected) {
		t.Errorf("Expected %v but got %v", expected, s)
	}
}

func TestInterfaceToInterface(t *testing.T) {
	var err error
	var i interface{} = err
	if i != nil {
		t.Error("An interface from a nil interface must be nil too in Go.")
	}
	v := reflect.ValueOf(i)
	if v.IsValid() {
		t.Error("The value of nil must not be valid")
	}
	func() {
		defer func() {
			if recover() == nil {
				t.Error("v.IsNil() below must panic.")
			}
		}()
		// Wow, this panics!
		v.IsNil()
	}()
	func() {
		defer func() {
			p := recover()
			if p == nil {
				t.Error("The code must panic.")
				return
			}
			err := p.(error)
			if !strings.Contains(err.Error(), "interface is nil, not error") {
				t.Errorf("Unexpected error: %v", err)
			}
		}()
		err = i.(error)
	}()
}
<commit_msg>Learn how to handle nil with reflect.Value.Call.<commit_after>package tips

// Reflection in Go:
// https://golang.org/pkg/reflect/

import (
	"reflect"
	"strings"
	"testing"
)

func TestReflectInt(t *testing.T) {
	i := 123
	ti := reflect.TypeOf(i)
	if ti.Kind() != reflect.Int {
		t.Errorf("Expected reflect.Int but got %v", ti.Kind())
		return
	}
	v := reflect.ValueOf(i)
	if v.Type() != ti {
		t.Errorf("Expected %v but got %v", ti, v.Type())
		return
	}
	// Retrieve the actual value.
	var ri int64 = v.Int()
	if ri != int64(i) {
		t.Errorf("Expected %d but got %d", i, ri)
	}
	// Interestingly, this does not panic :)
	if v.String() != "<int Value>" {
		t.Errorf("Expected an empty string but got %q", v.String())
	}
	// This panics! (using unaddressable value)
	// v.SetInt(456)
}

func TestReflectIntPointer(t *testing.T) {
	i := 123
	var p interface{} = &i
	ty := reflect.TypeOf(p)
	if ty.Kind() != reflect.Ptr {
		t.Errorf("Expected reflect.Ptr but got %v", ty.Kind())
		return
	}
	v := reflect.ValueOf(p)
	if v.Type() != ty {
		t.Errorf("Expected %v but got %v", ty, v.Type())
		return
	}
	var ev reflect.Value = v.Elem()
	if ev.Type().Kind() != reflect.Int {
		t.Errorf("Expected reflect.Int but got %v", ev.Type().Kind())
	}
	if ev.Kind() != reflect.Int {
		t.Errorf("Expected reflect.Int but got %v", ev.Kind())
	}
	if !ev.CanSet() {
		t.Error("CanSet must return true.")
	}
	// Set value!
	v.Elem().SetInt(456)
	if i != 456 {
		t.Errorf("Expected value: %d", i)
	}
}

func TestReflectStruct(t *testing.T) {
	type entry struct {
		name string
		Age  int `myattr:"myvalue"`
	}
	e := entry{name: "Alice", Age: 13}

	ty := reflect.TypeOf(e)
	if ty.Kind() != reflect.Struct {
		t.Errorf("Unexpected kind: %v", ty.Kind())
		return
	}
	if ty.NumField() != 2 {
		t.Errorf("Unexpected NumField(): %d", ty.NumField())
		return
	}
	var f0 reflect.StructField = ty.Field(0)
	if f0.Name != "name" || f0.Type.Kind() != reflect.String {
		t.Errorf("Unexpected field attrs: name = %q, type = %s", f0.Name, f0.Type)
	}
	f1 := ty.Field(1)
	if f1.Name != "Age" || f1.Type.Kind() != reflect.Int {
		t.Errorf("Unexpected field attrs: name = %q, type = %s", f1.Name, f1.Type)
	}
	// How to retrieve struct field tags.
	// https://golang.org/pkg/reflect/#StructTag
	if f1.Tag.Get("myattr") != "myvalue" {
		t.Errorf("Unexpected tag value: %q", f1.Tag.Get("myattr"))
	}

	// Value of struct.
	v := reflect.ValueOf(e)
	if v.Type() != ty {
		t.Errorf("Expected %v but got %v", ty, v.Type())
	}
	if v.NumField() != 2 {
		t.Errorf("Unexpected NumField(): %d", v.NumField())
		return
	}
	var vf0 reflect.Value = v.Field(0)
	if vf0.Type().Kind() != reflect.String {
		t.Errorf("Unexpected type for vf0: %v", vf0.Type())
	}
	if vf0.String() != "Alice" {
		t.Errorf("Unexpected value: %q", vf0.String())
	}
	vf1 := v.Field(1)
	if vf1.Type().Kind() != reflect.Int {
		t.Errorf("Unexpected type for vf1: %v", vf1.Type())
	}
	if vf0.String() != "Alice" {
		t.Errorf("Unexpected value: %q", vf0.String())
	}
	if vf1.Int() != 13 {
		t.Errorf("Unexpected value: %d", vf1.Int())
	}
	// fields of struct are not settable.
	if vf0.CanSet() || vf1.CanSet() {
		t.Error("CanSet of all fields must return false")
	}

	// This panics "using value obtained using unexported field".
	// vf0.SetString("hello")
	//
	// This panics with "using unaddressable value".
	// vf1.SetInt(20)
}

func TestReflectStructPointer(t *testing.T) {
	type entry struct {
		name string
		Age  int `myattr:"myvalue"`
	}
	p := &entry{name: "Alice", Age: 13}
	ty := reflect.TypeOf(p)
	if ty.Kind() != reflect.Ptr {
		t.Errorf("Unexpected kind: %v", ty.Kind())
		return
	}
	// Set field values.
	v := reflect.ValueOf(p)
	v.Elem().Field(1).SetInt(24)
	if p.Age != 24 {
		t.Errorf("Unexpected value: %v", p.Age)
	}
	// This panics "using value obtained using unexported field".
	// v.Elem().Field(0).SetString("Bob")
}

func TestRelectEmbed(t *testing.T) {
	type embed struct {
		str string
		Str string
	}
	type Embed struct {
		Int     int
		integer int
	}
	type entry struct {
		F float32
		embed
		Embed
		float64
	}
	e := entry{
		F: 3.14,
		embed: embed{
			str: "hello",
			Str: "World",
		},
		Embed: Embed{
			Int:     100,
			integer: 10,
		},
		float64: 12.34,
	}
	ty := reflect.TypeOf(e)
	// Embeded struct are treated as fields as you may expect.
	if ty.NumField() != 4 {
		t.Errorf("Unexpected NumField() = %d", ty.NumField())
		return
	}
	f := ty.Field(0)
	if !(f.Name == "F" && !f.Anonymous) {
		t.Errorf("Unexpected: %#v", f)
	}
	f = ty.Field(1)
	// Anonymous is true if the field is an embedded field.
	if !(f.Name == "embed" && f.Anonymous) {
		t.Errorf("Unexpected: %#v", f)
	}
	f = ty.Field(2)
	// Anonymous is true if the field is an embedded field.
	if !(f.Name == "Embed" && f.Anonymous) {
		t.Errorf("Unexpected: %#v", f)
	}
	f = ty.Field(3)
	// Anonymous is true if the field is an embedded field.
	if !(f.Name == "float64" && f.Anonymous) {
		t.Errorf("Unexpected: %#v", f)
	}

	// TODO: Investigate Value.
}

func TestReflectFunc(t *testing.T) {
	sum := func(x int, y int32) float32 {
		return float32(x + int(y))
	}
	var inter interface{} = sum
	ty := reflect.TypeOf(inter)
	if ty.Kind() != reflect.Func {
		t.Errorf("Unexpected kind: %v", ty.Kind())
		return
	}
	// Types of arguments and return values.
	if ty.NumIn() != 2 {
		t.Errorf("Unexpected NumIn() = %v", ty.NumIn())
	}
	if ty.NumOut() != 1 {
		t.Errorf("Unexpected NumOut() = %v", ty.NumOut())
	}
	if ty.In(0).Kind() != reflect.Int {
		t.Errorf("Unexpected first arg type: %v", ty.In(0).Kind())
	}
	if ty.Out(0).Kind() != reflect.Float32 {
		t.Errorf("Unexpected first arg type: %v", ty.Out(0).Kind())
	}

	// Invoke
	v := reflect.ValueOf(inter)
	returns := v.Call([]reflect.Value{
		reflect.ValueOf(12),
		reflect.ValueOf(int32(34)),
	})
	if len(returns) != 1 {
		t.Errorf("Unexpected size of slice was returned: %d", len(returns))
		return
	}
	f := returns[0].Float()
	if f != 46.0 {
		t.Errorf("Unexpected return value: %f", f)
	}

	// Call panics if arguments are invalid.
	// v.Call([]reflect.Value{})
}

func TestReflectSlice(t *testing.T) {
	slicePtr := reflect.New(reflect.SliceOf(reflect.TypeOf(int(0))))
	for i := 0; i < 10; i++ {
		slicePtr.Elem().Set(reflect.Append(slicePtr.Elem(), reflect.ValueOf(i*i)))
	}
	s := slicePtr.Elem().Interface().([]int)
	expected := []int{0, 1, 4, 9, 16, 25, 36, 49, 64, 81}
	if !reflect.DeepEqual(s, expected) {
		t.Errorf("Expected %v but got %v", expected, s)
	}
}

func TestInterfaceToInterface(t *testing.T) {
	var err error
	var i interface{} = err
	if i != nil {
		t.Error("An interface from a nil interface must be nil too in Go.")
	}
	v := reflect.ValueOf(i)
	if v.IsValid() {
		t.Error("The value of nil must not be valid")
	}
	func() {
		defer func() {
			if recover() == nil {
				t.Error("v.IsNil() below must panic.")
			}
		}()
		// Wow, this panics!
		v.IsNil()
	}()
	func() {
		defer func() {
			p := recover()
			if p == nil {
				t.Error("The code must panic.")
				return
			}
			err := p.(error)
			if !strings.Contains(err.Error(), "interface is nil, not error") {
				t.Errorf("Unexpected error: %v", err)
			}
		}()
		err = i.(error)
	}()
}

func TestNilAndCall(t *testing.T) {
	errorType := reflect.TypeOf((*error)(nil)).Elem()
	if errorType.Name() != "error" {
		t.Errorf("Unexpected errorType: %v", errorType)
	}

	fn := func(e error) error {
		if e != nil {
			panic("Call this function with nil!")
		}
		return nil
	}
	v := reflect.ValueOf(fn)

	// NG
	// arg := reflect.ValueOf(nil)
	arg := reflect.New(errorType).Elem()
	rets := v.Call([]reflect.Value{arg})
	if len(rets) != 1 {
		t.Errorf("Unexpected len(ret): %d", len(rets))
		return
	}
	ret := rets[0]
	// Unlike the test above, a nil interface in the return values is not invalid and has a type.
	if !ret.IsValid() {
		t.Error("ret is invalid unexpectedly")
	}
	if !ret.IsNil() {
		t.Error("ret.IsNil() returned false unexpectedly")
	}
	if ret.Type() != errorType {
		t.Errorf("Unexpected type: %v", ret.Type())
	}
}
<|endoftext|>


<commit_before>package chunkymonkey

import (
    "testing"
)

type CoordDivModTest struct {
    expected_div, expected_mod int32
    num, denom int32
}

var CoordDivModTests = []CoordDivModTest{
    // Simple +ve numerator cases
    CoordDivModTest{0, 0, 0, 16},
    CoordDivModTest{0, 1, 1, 16},
    CoordDivModTest{0, 15, 15, 16},
    CoordDivModTest{1, 0, 16, 16},
    CoordDivModTest{1, 15, 31, 16},

    // -ve numerator cases
    CoordDivModTest{-1, 15, -1, 16},
    CoordDivModTest{-1, 0, -16, 16},
    CoordDivModTest{-2, 15, -17, 16},
    CoordDivModTest{-2, 0, -32, 16},
}

func TestCoordDivMod(t *testing.T) {
    for _, r := range CoordDivModTests {
        div, mod := coordDivMod(r.num, r.denom)
        if r.expected_div != div || r.expected_mod != mod {
            t.Errorf("coordDivMod(%d, %d) expected (%d, %d) got (%d, %d)",
                r.num, r.denom, r.expected_div, r.expected_mod, div, mod)
        }
    }
}
<commit_msg>gofmt run.<commit_after>package chunkymonkey

import (
    "testing"
)

type CoordDivModTest struct {
    expected_div, expected_mod int32
    num, denom                 int32
}

var CoordDivModTests = []CoordDivModTest{
    // Simple +ve numerator cases
    CoordDivModTest{0, 0, 0, 16},
    CoordDivModTest{0, 1, 1, 16},
    CoordDivModTest{0, 15, 15, 16},
    CoordDivModTest{1, 0, 16, 16},
    CoordDivModTest{1, 15, 31, 16},

    // -ve numerator cases
    CoordDivModTest{-1, 15, -1, 16},
    CoordDivModTest{-1, 0, -16, 16},
    CoordDivModTest{-2, 15, -17, 16},
    CoordDivModTest{-2, 0, -32, 16},
}

func TestCoordDivMod(t *testing.T) {
    for _, r := range CoordDivModTests {
        div, mod := coordDivMod(r.num, r.denom)
        if r.expected_div != div || r.expected_mod != mod {
            t.Errorf("coordDivMod(%d, %d) expected (%d, %d) got (%d, %d)",
                r.num, r.denom, r.expected_div, r.expected_mod, div, mod)
        }
    }
}
<|endoftext|>