<commit_before>package bolt

import (
	"context"

	"github.com/boltdb/bolt"
	"github.com/influxdata/chronograf"
	"github.com/influxdata/chronograf/bolt/internal"
)

// Ensure UsersStore implements chronograf.UsersStore.
var _ chronograf.UsersStore = &UsersStore{}

var UsersBucket = []byte("Users")

type UsersStore struct {
	client *Client
}

// get searches the UsersStore for user with name and returns the bolt representation
func (s *UsersStore) get(ctx context.Context, name string) (*internal.User, error) {
	found := false
	var user internal.User
	err := s.client.db.View(func(tx *bolt.Tx) error {
		err := tx.Bucket(UsersBucket).ForEach(func(k, v []byte) error {
			var u chronograf.User
			if err := internal.UnmarshalUser(v, &u); err != nil {
				return err
			} else if u.Name != name {
				return nil
			}
			found = true
			if err := internal.UnmarshalUserPB(v, &user); err != nil {
				return err
			}
			return nil
		})
		if err != nil {
			return err
		}
		if found == false {
			return chronograf.ErrUserNotFound
		}
		return nil
	})
	if err != nil {
		return nil, err
	}

	return &user, nil
}

// Get searches the UsersStore for user with name
func (s *UsersStore) Get(ctx context.Context, name string) (*chronograf.User, error) {
	u, err := s.get(ctx, name)
	if err != nil {
		return nil, err
	}
	return &chronograf.User{
		Name: u.Name,
	}, nil
}

// Create a new Users in the UsersStore.
func (s *UsersStore) Add(ctx context.Context, u *chronograf.User) (*chronograf.User, error) {
	if err := s.client.db.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket(UsersBucket)
		seq, err := b.NextSequence()
		if err != nil {
			return err
		}
		if v, err := internal.MarshalUser(u); err != nil {
			return err
		} else if err := b.Put(u64tob(seq), v); err != nil {
			return err
		}
		return nil
	}); err != nil {
		return nil, err
	}

	return u, nil
}

// Delete the users from the UsersStore
func (s *UsersStore) Delete(ctx context.Context, user *chronograf.User) error {
	u, err := s.get(ctx, user.Name)
	if err != nil {
		return err
	}
	if err := s.client.db.Update(func(tx *bolt.Tx) error {
		if err := tx.Bucket(UsersBucket).Delete(u64tob(u.ID)); err != nil {
			return err
		}
		return nil
	}); err != nil {
		return err
	}

	return nil
}

// Update a user
func (s *UsersStore) Update(ctx context.Context, usr *chronograf.User) error {
	u, err := s.get(ctx, usr.Name)
	if err != nil {
		return err
	}
	if err := s.client.db.Update(func(tx *bolt.Tx) error {
		u.Name = usr.Name
		if v, err := internal.MarshalUserPB(u); err != nil {
			return err
		} else if err := tx.Bucket(UsersBucket).Put(u64tob(u.ID), v); err != nil {
			return err
		}
		return nil
	}); err != nil {
		return err
	}

	return nil
}

// All returns all users
func (s *UsersStore) All(ctx context.Context) ([]chronograf.User, error) {
	var users []chronograf.User
	if err := s.client.db.View(func(tx *bolt.Tx) error {
		if err := tx.Bucket(UsersBucket).ForEach(func(k, v []byte) error {
			var user chronograf.User
			if err := internal.UnmarshalUser(v, &user); err != nil {
				return err
			}
			users = append(users, user)
			return nil
		}); err != nil {
			return err
		}
		return nil
	}); err != nil {
		return nil, err
	}

	return users, nil
}
<commit_msg>Update user bolt bucket to be different b/c schema change<commit_after>package bolt

import (
	"context"

	"github.com/boltdb/bolt"
	"github.com/influxdata/chronograf"
	"github.com/influxdata/chronograf/bolt/internal"
)

// Ensure UsersStore implements chronograf.UsersStore.
var _ chronograf.UsersStore = &UsersStore{}

var UsersBucket = []byte("UsersV1")

type UsersStore struct {
	client *Client
}

// get searches the UsersStore for user with name and returns the bolt representation
func (s *UsersStore) get(ctx context.Context, name string) (*internal.User, error) {
	found := false
	var user internal.User
	err := s.client.db.View(func(tx *bolt.Tx) error {
		err := tx.Bucket(UsersBucket).ForEach(func(k, v []byte) error {
			var u chronograf.User
			if err := internal.UnmarshalUser(v, &u); err != nil {
				return err
			} else if u.Name != name {
				return nil
			}
			found = true
			if err := internal.UnmarshalUserPB(v, &user); err != nil {
				return err
			}
			return nil
		})
		if err != nil {
			return err
		}
		if found == false {
			return chronograf.ErrUserNotFound
		}
		return nil
	})
	if err != nil {
		return nil, err
	}

	return &user, nil
}

// Get searches the UsersStore for user with name
func (s *UsersStore) Get(ctx context.Context, name string) (*chronograf.User, error) {
	u, err := s.get(ctx, name)
	if err != nil {
		return nil, err
	}
	return &chronograf.User{
		Name: u.Name,
	}, nil
}

// Create a new Users in the UsersStore.
func (s *UsersStore) Add(ctx context.Context, u *chronograf.User) (*chronograf.User, error) {
	if err := s.client.db.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket(UsersBucket)
		seq, err := b.NextSequence()
		if err != nil {
			return err
		}
		if v, err := internal.MarshalUser(u); err != nil {
			return err
		} else if err := b.Put(u64tob(seq), v); err != nil {
			return err
		}
		return nil
	}); err != nil {
		return nil, err
	}

	return u, nil
}

// Delete the users from the UsersStore
func (s *UsersStore) Delete(ctx context.Context, user *chronograf.User) error {
	u, err := s.get(ctx, user.Name)
	if err != nil {
		return err
	}
	if err := s.client.db.Update(func(tx *bolt.Tx) error {
		if err := tx.Bucket(UsersBucket).Delete(u64tob(u.ID)); err != nil {
			return err
		}
		return nil
	}); err != nil {
		return err
	}

	return nil
}

// Update a user
func (s *UsersStore) Update(ctx context.Context, usr *chronograf.User) error {
	u, err := s.get(ctx, usr.Name)
	if err != nil {
		return err
	}
	if err := s.client.db.Update(func(tx *bolt.Tx) error {
		u.Name = usr.Name
		if v, err := internal.MarshalUserPB(u); err != nil {
			return err
		} else if err := tx.Bucket(UsersBucket).Put(u64tob(u.ID), v); err != nil {
			return err
		}
		return nil
	}); err != nil {
		return err
	}

	return nil
}

// All returns all users
func (s *UsersStore) All(ctx context.Context) ([]chronograf.User, error) {
	var users []chronograf.User
	if err := s.client.db.View(func(tx *bolt.Tx) error {
		if err := tx.Bucket(UsersBucket).ForEach(func(k, v []byte) error {
			var user chronograf.User
			if err := internal.UnmarshalUser(v, &user); err != nil {
				return err
			}
			users = append(users, user)
			return nil
		}); err != nil {
			return err
		}
		return nil
	}); err != nil {
		return nil, err
	}

	return users, nil
}
<|endoftext|>


<commit_before>package main

import (
    "os"
    "testing"
)

func TestBasic(t *testing.T) {
    var conn, _ = initDb("./", "test.db")
    var bookCount = len(getBooks("", conn))
    if  bookCount != 0 {
        t.Errorf("Expected 0 books, found %v", bookCount)
    }

    var b = Book{}
    insert(&b, conn)

    bookCount = len(getBooks("", conn))
    if bookCount != 1 {
        t.Errorf("Expected 1 books, found %v", bookCount)
    }

    os.Remove("./test.db")
}
<commit_msg>More query tests<commit_after>package main

import (
    "code.google.com/p/gosqlite/sqlite"
    "os"
    "testing"
)

func queryAndExpect(query string, expected int, conn *sqlite.Conn, t *testing.T) {
    var bookCount = len(getBooks(query, conn))
    if bookCount != expected {
        t.Errorf("Expected %v books, found %v", expected, bookCount)
    }
}

func TestBasic(t *testing.T) {
    var conn, _ = initDb("./", "test.db")
    defer conn.Close()

    queryAndExpect("", 0, conn, t)

    var b = Book{}
    insert(&b, conn)

    queryAndExpect("", 1, conn, t)

    os.Remove("./test.db")
}

func TestQueries(t *testing.T) {
    var conn, _ = initDb("./", "test.db")
    defer conn.Close()

    var b1 = Book{ID:1, Title:"Foo", Author:"bar"}
    var b2 = Book{ID:2, Title:"Zebra", Author:"bar"}
    var b3 = Book{ID:3, Title:"Delta Spaces otherchars (subtitle goes here)", Author:"other"}
    insert(&b1, conn)
    insert(&b2, conn)
    insert(&b3, conn)

    queryAndExpect("", 3, conn, t)
    queryAndExpect("bar", 2, conn, t)
    queryAndExpect("other", 1, conn, t)
    queryAndExpect("a", 3, conn, t)
    queryAndExpect("NO such $tring", 0, conn, t)

    os.Remove("./test.db")
}
<|endoftext|>


<commit_before>package message

//import (
//	"reflect"
//
//	"github.com/pinfake/pes6go/data/block"
//)
//
//type CreateRoomResponse struct {
//	IpInfo []block.Piece
//}
//
//func (r CreateRoomResponse) GetBlocks() []*block.Block {
//	var blocks []*block.Block
//
//	blocks = append(blocks, block.GetBlocks(0x3087,
//		[]block.Piece{block.PlayerSettingsHeader{r.PlayerId}})...,
//	)
//	blocks = append(blocks, block.GetBlocks(0x3088, r.PlayerSettings)...)
//	blocks = append(blocks, block.GetBlocks(0x3089, []block.Piece{
//		block.Uint32{0},
//	})...)
//	return blocks
//}
//
//func NewPlayerSettingsMessage(playerId uint32, playerSettings block.PlayerSettings) PlayerSettings {
//	return PlayerSettings{
//		PlayerId:       playerId,
//		PlayerSettings: block.GetPieces(reflect.ValueOf(playerSettings)),
//	}
//}
<commit_msg>rooms, links wip... this is tough<commit_after>package message

import (
	"reflect"

	"github.com/pinfake/pes6go/data/block"
)

type CreateRoomResponse struct {
	RoomLinks []block.Piece
}

func (r CreateRoomResponse) GetBlocks() []*block.Block {
	var blocks []*block.Block

	blocks = append(blocks, block.GetBlocks(0x4311, []block.Piece{block.Uint32{0}})...)
	blocks = append(blocks, block.GetBlocks(0x4346, []block.Piece{block.Uint32{0}})...)
	blocks = append(blocks, block.GetBlocks(0x4347, r.RoomLinks)...)
	blocks = append(blocks, block.GetBlocks(0x4348, []block.Piece{block.Uint32{0}})...)
	return blocks
}

func NewCreateRoomResponse(playerId uint32, playerSettings block.PlayerSettings) PlayerSettings {
	return PlayerSettings{
		PlayerId:       playerId,
		PlayerSettings: block.GetPieces(reflect.ValueOf(playerSettings)),
	}
}
<|endoftext|>


<commit_before>// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package router

import (
	"fmt"
	"strings"
	"time"

	"github.com/ava-labs/avalanchego/ids"
	"github.com/ava-labs/avalanchego/snow/engine/common"
	"github.com/ava-labs/avalanchego/utils/constants"
)

type message struct {
	messageType  constants.MsgType
	validatorID  ids.ShortID
	requestID    uint32
	containerID  ids.ID
	container    []byte
	containers   [][]byte
	containerIDs []ids.ID
	notification common.Message
	received     time.Time // Time this message was received
	deadline     time.Time // Time this message must be responded to
}

// IsPeriodic returns true if this message is of a type that is sent on a
// periodic basis.
func (m message) IsPeriodic() bool {
	return m.requestID == constants.GossipMsgRequestID ||
		m.messageType == constants.GossipMsg
}

func (m message) String() string {
	sb := strings.Builder{}
	sb.WriteString(fmt.Sprintf("(%s, ValidatorID: %s, RequestID: %d", m.messageType, m.validatorID, m.requestID))
	if !m.received.IsZero() {
		sb.WriteString(fmt.Sprintf(", Received: %d", m.received.Unix()))
	}
	if !m.deadline.IsZero() {
		sb.WriteString(fmt.Sprintf(", Deadline: %d", m.deadline.Unix()))
	}
	switch m.messageType {
	case constants.GetAcceptedMsg, constants.AcceptedMsg, constants.ChitsMsg, constants.AcceptedFrontierMsg:
		sb.WriteString(fmt.Sprintf(", ContainerIDs: %s)", m.containerIDs))
	case constants.GetMsg, constants.GetAncestorsMsg, constants.PutMsg, constants.PushQueryMsg, constants.PullQueryMsg:
		sb.WriteString(fmt.Sprintf(", ContainerID: %s", m.containerID))
	case constants.MultiPutMsg:
		sb.WriteString(fmt.Sprintf(", NumContainers: %d)", len(m.containers)))
	case constants.NotifyMsg:
		sb.WriteString(fmt.Sprintf(", Notification: %s)", m.notification))
	default:
		sb.WriteString(")")
	}

	return sb.String()
}
<commit_msg>Add missing ) to msg stringer<commit_after>// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package router

import (
	"fmt"
	"strings"
	"time"

	"github.com/ava-labs/avalanchego/ids"
	"github.com/ava-labs/avalanchego/snow/engine/common"
	"github.com/ava-labs/avalanchego/utils/constants"
)

type message struct {
	messageType  constants.MsgType
	validatorID  ids.ShortID
	requestID    uint32
	containerID  ids.ID
	container    []byte
	containers   [][]byte
	containerIDs []ids.ID
	notification common.Message
	received     time.Time // Time this message was received
	deadline     time.Time // Time this message must be responded to
}

// IsPeriodic returns true if this message is of a type that is sent on a
// periodic basis.
func (m message) IsPeriodic() bool {
	return m.requestID == constants.GossipMsgRequestID ||
		m.messageType == constants.GossipMsg
}

func (m message) String() string {
	sb := strings.Builder{}
	sb.WriteString(fmt.Sprintf("(%s, ValidatorID: %s, RequestID: %d", m.messageType, m.validatorID, m.requestID))
	if !m.received.IsZero() {
		sb.WriteString(fmt.Sprintf(", Received: %d", m.received.Unix()))
	}
	if !m.deadline.IsZero() {
		sb.WriteString(fmt.Sprintf(", Deadline: %d", m.deadline.Unix()))
	}
	switch m.messageType {
	case constants.GetAcceptedMsg, constants.AcceptedMsg, constants.ChitsMsg, constants.AcceptedFrontierMsg:
		sb.WriteString(fmt.Sprintf(", ContainerIDs: %s)", m.containerIDs))
	case constants.GetMsg, constants.GetAncestorsMsg, constants.PutMsg, constants.PushQueryMsg, constants.PullQueryMsg:
		sb.WriteString(fmt.Sprintf(", ContainerID: %s)", m.containerID))
	case constants.MultiPutMsg:
		sb.WriteString(fmt.Sprintf(", NumContainers: %d)", len(m.containers)))
	case constants.NotifyMsg:
		sb.WriteString(fmt.Sprintf(", Notification: %s)", m.notification))
	default:
		sb.WriteString(")")
	}

	return sb.String()
}
<|endoftext|>


<commit_before>package formats

import (
	"fmt"
	"io"

	"github.com/ungerik/go3d/float64/vec3"
)

// Write outputs the buffer to the writer given. Returns an error if the
// operation fails.
func (b *objBuffer) Write(w io.Writer) error {
	var err error
	_, err = io.WriteString(w, "# Exported using RenderDB\n")
	if err != nil {
		return err
	}
	if b.mtllib != "" {
		_, err = io.WriteString(w, fmt.Sprintf("mtllib %s\n", b.mtllib))
		if err != nil {
			return err
		}
	}

	if err = b.writeVertices(w); err != nil {
		return err
	}
	if err = b.writeNormals(w); err != nil {
		return err
	}
	for _, g := range b.g {
		if err = b.writeGroup(w, g); err != nil {
			return err
		}
	}

	return nil
}

func (b *objBuffer) writeVertices(w io.Writer) error {
	return writeVectors(w, "v %g %g %g\n", b.v)
}

func (b *objBuffer) writeNormals(w io.Writer) error {
	return writeVectors(w, "vn %g %g %g\n", b.vn)
}

func writeFace(w io.Writer, f face) error {
	var err error

	_, err = io.WriteString(w, "f")
	if err != nil {
		return err
	}

	for _, c := range f.corners {
		if c.normalIndex != -1 {
			_, err := io.WriteString(w, fmt.Sprintf(" %d//%d", c.vertexIndex, c.normalIndex))
			if err != nil {
				return err
			}
		}
	}

	return nil
}

func writeVectors(w io.Writer, format string, vectors []vec3.T) error {
	for _, v := range vectors {
		_, err := io.WriteString(w, fmt.Sprintf(format, v[0], v[1], v[2]))
		if err != nil {
			return err
		}
	}
	return nil
}

func (b *objBuffer) writeGroup(w io.Writer, g group) error {
	var err error
	_, err = io.WriteString(w, fmt.Sprintf("g %s", g.name))
	if err != nil {
		return err
	}

	for i := g.firstFacesetIndex; i < g.firstFacesetIndex+g.facesetCount; i++ {
		fs := b.facesets[i]
		if err = b.writeFaceset(w, fs); err != nil {
			return err
		}
	}

	return nil
}

func (b *objBuffer) writeFaceset(w io.Writer, fs faceset) error {
	var err error
	if fs.material != "" {
		_, err = io.WriteString(w, fmt.Sprintf("usemtl %s\n", fs.material))
		if err != nil {
			return err
		}
	}

	for i := fs.firstFaceIndex; i < fs.firstFaceIndex+fs.faceCount; i++ {
		if err = writeFace(w, b.f[i]); err != nil {
			return err
		}
	}

	return nil
}
<commit_msg>Missing newline char after face entries.<commit_after>package formats

import (
	"fmt"
	"io"

	"github.com/ungerik/go3d/float64/vec3"
)

// Write outputs the buffer to the writer given. Returns an error if the
// operation fails.
func (b *objBuffer) Write(w io.Writer) error {
	var err error
	_, err = io.WriteString(w, "# Exported using RenderDB\n")
	if err != nil {
		return err
	}
	if b.mtllib != "" {
		_, err = io.WriteString(w, fmt.Sprintf("mtllib %s\n", b.mtllib))
		if err != nil {
			return err
		}
	}

	if err = b.writeVertices(w); err != nil {
		return err
	}
	if err = b.writeNormals(w); err != nil {
		return err
	}
	for _, g := range b.g {
		if err = b.writeGroup(w, g); err != nil {
			return err
		}
	}

	return nil
}

func (b *objBuffer) writeVertices(w io.Writer) error {
	return writeVectors(w, "v %g %g %g\n", b.v)
}

func (b *objBuffer) writeNormals(w io.Writer) error {
	return writeVectors(w, "vn %g %g %g\n", b.vn)
}

func writeFace(w io.Writer, f face) error {
	var err error

	_, err = io.WriteString(w, "f")
	if err != nil {
		return err
	}

	for _, c := range f.corners {
		if c.normalIndex != -1 {
			_, err = io.WriteString(w,
				fmt.Sprintf(" %d//%d", c.vertexIndex+1, c.normalIndex+1))
		} else {
			_, err = io.WriteString(w, fmt.Sprintf(" %d", c.vertexIndex+1))
		}
		if err != nil {
			return err
		}
	}
	_, err = io.WriteString(w, "\n")
	return err
}

func writeVectors(w io.Writer, format string, vectors []vec3.T) error {
	for _, v := range vectors {
		_, err := io.WriteString(w, fmt.Sprintf(format, v[0], v[1], v[2]))
		if err != nil {
			return err
		}
	}
	return nil
}

func (b *objBuffer) writeGroup(w io.Writer, g group) error {
	var err error
	_, err = io.WriteString(w, fmt.Sprintf("g %s", g.name))
	if err != nil {
		return err
	}

	for i := g.firstFacesetIndex; i < g.firstFacesetIndex+g.facesetCount; i++ {
		fs := b.facesets[i]
		if err = b.writeFaceset(w, fs); err != nil {
			return err
		}
	}

	return nil
}

func (b *objBuffer) writeFaceset(w io.Writer, fs faceset) error {
	var err error
	if fs.material != "" {
		_, err = io.WriteString(w, fmt.Sprintf("usemtl %s\n", fs.material))
		if err != nil {
			return err
		}
	}

	for i := fs.firstFaceIndex; i < fs.firstFaceIndex+fs.faceCount; i++ {
		if err = writeFace(w, b.f[i]); err != nil {
			return err
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package node

import (
	. "DNA/common/config"
	"DNA/common/log"
	"DNA/events"
	msg "DNA/net/message"
	. "DNA/net/protocol"
	"crypto/tls"
	"crypto/x509"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"os"
	"strconv"
	"strings"
	"time"
)

type link struct {
	//Todo Add lock here
	addr  string    // The address of the node
	conn  net.Conn  // Connect socket with the peer node
	port  uint16    // The server port of the node
	time  time.Time // The latest time the node activity
	rxBuf struct {  // The RX buffer of this node to solve mutliple packets problem
		p   []byte
		len int
	}
	connCnt uint64 // The connection count
}

// Shrinking the buf to the exactly reading in byte length
//@Return @1 the start header of next message, the left length of the next message
func unpackNodeBuf(node *node, buf []byte) {
	var msgLen int
	var msgBuf []byte

	if len(buf) == 0 {
		return
	}

	if node.rxBuf.len == 0 {
		length := MSGHDRLEN - len(node.rxBuf.p)
		if length > len(buf) {
			length = len(buf)
			node.rxBuf.p = append(node.rxBuf.p, buf[0:length]...)
			return
		}

		node.rxBuf.p = append(node.rxBuf.p, buf[0:length]...)
		if msg.ValidMsgHdr(node.rxBuf.p) == false {
			node.rxBuf.p = nil
			node.rxBuf.len = 0
			log.Warn("Get error message header, TODO: relocate the msg header")
			// TODO Relocate the message header
			return
		}

		node.rxBuf.len = msg.PayloadLen(node.rxBuf.p)
		buf = buf[length:]
	}

	msgLen = node.rxBuf.len
	if len(buf) == msgLen {
		msgBuf = append(node.rxBuf.p, buf[:]...)
		go msg.HandleNodeMsg(node, msgBuf, len(msgBuf))
		node.rxBuf.p = nil
		node.rxBuf.len = 0
	} else if len(buf) < msgLen {
		node.rxBuf.p = append(node.rxBuf.p, buf[:]...)
		node.rxBuf.len = msgLen - len(buf)
	} else {
		msgBuf = append(node.rxBuf.p, buf[0:msgLen]...)
		go msg.HandleNodeMsg(node, msgBuf, len(msgBuf))
		node.rxBuf.p = nil
		node.rxBuf.len = 0

		unpackNodeBuf(node, buf[msgLen:])
	}
}

func (node *node) rx() {
	conn := node.getConn()
	buf := make([]byte, MAXBUFLEN)
	for {
		len, err := conn.Read(buf[0:(MAXBUFLEN - 1)])
		buf[MAXBUFLEN-1] = 0 //Prevent overflow
		switch err {
		case nil:
			t := time.Now()
			node.UpdateRXTime(t)
			unpackNodeBuf(node, buf[0:len])
		case io.EOF:
			log.Error("Rx io.EOF: ", err, ", node id is ", node.GetID())
			goto DISCONNECT
		default:
			log.Error("Read connection error ", err)
			goto DISCONNECT
		}
	}

DISCONNECT:
	node.local.eventQueue.GetEvent("disconnect").Notify(events.EventNodeDisconnect, node)
}

func printIPAddr() {
	host, _ := os.Hostname()
	addrs, _ := net.LookupIP(host)
	for _, addr := range addrs {
		if ipv4 := addr.To4(); ipv4 != nil {
			log.Info("IPv4: ", ipv4)
		}
	}
}

func (link *link) CloseConn() {
	link.conn.Close()
}

func (n *node) initConnection() {
	isTls := Parameters.IsTLS
	var listener net.Listener
	var err error
	if isTls {
		listener, err = initTlsListen()
		if err != nil {
			log.Error("TLS listen failed")
			return
		}
	} else {
		listener, err = initNonTlsListen()
		if err != nil {
			log.Error("non TLS listen failed")
			return
		}
	}
	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Error("Error accepting ", err.Error())
			return
		}
		log.Info("Remote node connect with ", conn.RemoteAddr(), conn.LocalAddr())

		n.link.connCnt++

		node := NewNode()
		node.addr, err = parseIPaddr(conn.RemoteAddr().String())
		node.local = n
		node.conn = conn
		go node.rx()
	}
	//TODO Release the net listen resouce
}

func initNonTlsListen() (net.Listener, error) {
	log.Debug()
	listener, err := net.Listen("tcp", ":"+strconv.Itoa(Parameters.NodePort))
	if err != nil {
		log.Error("Error listening\n", err.Error())
		return nil, err
	}
	return listener, nil
}

func initTlsListen() (net.Listener, error) {
	CertPath := Parameters.CertPath
	KeyPath := Parameters.KeyPath
	CAPath := Parameters.CAPath

	// load cert
	cert, err := tls.LoadX509KeyPair(CertPath, KeyPath)
	if err != nil {
		log.Error("load keys fail", err)
		return nil, err
	}
	// load root ca
	caData, err := ioutil.ReadFile(CAPath)
	if err != nil {
		log.Error("read ca fail", err)
		return nil, err
	}
	pool := x509.NewCertPool()
	ret := pool.AppendCertsFromPEM(caData)
	if !ret {
		return nil, errors.New("failed to parse root certificate")
	}

	tlsConfig := &tls.Config{
		Certificates: []tls.Certificate{cert},
		RootCAs:      pool,
		ClientAuth:   tls.RequireAndVerifyClientCert,
		ClientCAs:    pool,
	}

	log.Info("TLS listen port is ", strconv.Itoa(Parameters.NodePort))
	listener, err := tls.Listen("tcp", ":"+strconv.Itoa(Parameters.NodePort), tlsConfig)
	if err != nil {
		log.Error(err)
		return nil, err
	}
	return listener, nil
}

func parseIPaddr(s string) (string, error) {
	i := strings.Index(s, ":")
	if i < 0 {
		log.Warn("Split IP address&port error")
		return s, errors.New("Split IP address&port error")
	}
	return s[:i], nil
}

func (node *node) Connect(nodeAddr string) error {
	log.Debug()

	if node.IsAddrInNbrList(nodeAddr) == true {
		return nil
	}
	if added := node.SetAddrInConnectingList(nodeAddr); added == false {
		return errors.New("node exist in connecting list, cancel")
	}

	isTls := Parameters.IsTLS
	var conn net.Conn
	var err error

	if isTls {
		conn, err = TLSDial(nodeAddr)
		if err != nil {
			node.RemoveAddrInConnectingList(nodeAddr)
			log.Error("TLS connect failed: ", err)
			return err
		}
	} else {
		conn, err = NonTLSDial(nodeAddr)
		if err != nil {
			node.RemoveAddrInConnectingList(nodeAddr)
			log.Error("non TLS connect failed: ", err)
			return err
		}
	}
	node.link.connCnt++
	n := NewNode()
	n.conn = conn
	n.addr, err = parseIPaddr(conn.RemoteAddr().String())
	n.local = node

	log.Info(fmt.Sprintf("Connect node %s connect with %s with %s",
		conn.LocalAddr().String(), conn.RemoteAddr().String(),
		conn.RemoteAddr().Network()))
	go n.rx()

	n.SetState(HAND)
	buf, _ := msg.NewVersion(node)
	n.Tx(buf)

	return nil
}

func NonTLSDial(nodeAddr string) (net.Conn, error) {
	log.Debug()
	conn, err := net.DialTimeout("tcp", nodeAddr, time.Second*DIALTIMEOUT)
	if err != nil {
		return nil, err
	}
	return conn, nil
}

func TLSDial(nodeAddr string) (net.Conn, error) {
	CertPath := Parameters.CertPath
	KeyPath := Parameters.KeyPath
	CAPath := Parameters.CAPath

	clientCertPool := x509.NewCertPool()

	cacert, err := ioutil.ReadFile(CAPath)
	cert, err := tls.LoadX509KeyPair(CertPath, KeyPath)
	if err != nil {
		return nil, err
	}

	ret := clientCertPool.AppendCertsFromPEM(cacert)
	if !ret {
		return nil, errors.New("failed to parse root certificate")
	}

	conf := &tls.Config{
		RootCAs:      clientCertPool,
		Certificates: []tls.Certificate{cert},
	}

	var dialer net.Dialer
	dialer.Timeout = time.Second * DIALTIMEOUT
	conn, err := tls.DialWithDialer(&dialer, "tcp", nodeAddr, conf)
	if err != nil {
		return nil, err
	}
	return conn, nil
}

func (node *node) Tx(buf []byte) {
	log.Debugf("TX buf length: %d\n%x", len(buf), buf)

	_, err := node.conn.Write(buf)
	if err != nil {
		log.Error("Error sending messge to peer node ", err.Error())
	}
}
<commit_msg>If node state is INACTIVITY, return Tx directly<commit_after>package node

import (
	. "DNA/common/config"
	"DNA/common/log"
	"DNA/events"
	msg "DNA/net/message"
	. "DNA/net/protocol"
	"crypto/tls"
	"crypto/x509"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"os"
	"strconv"
	"strings"
	"time"
)

type link struct {
	//Todo Add lock here
	addr  string    // The address of the node
	conn  net.Conn  // Connect socket with the peer node
	port  uint16    // The server port of the node
	time  time.Time // The latest time the node activity
	rxBuf struct {  // The RX buffer of this node to solve mutliple packets problem
		p   []byte
		len int
	}
	connCnt uint64 // The connection count
}

// Shrinking the buf to the exactly reading in byte length
//@Return @1 the start header of next message, the left length of the next message
func unpackNodeBuf(node *node, buf []byte) {
	var msgLen int
	var msgBuf []byte

	if len(buf) == 0 {
		return
	}

	if node.rxBuf.len == 0 {
		length := MSGHDRLEN - len(node.rxBuf.p)
		if length > len(buf) {
			length = len(buf)
			node.rxBuf.p = append(node.rxBuf.p, buf[0:length]...)
			return
		}

		node.rxBuf.p = append(node.rxBuf.p, buf[0:length]...)
		if msg.ValidMsgHdr(node.rxBuf.p) == false {
			node.rxBuf.p = nil
			node.rxBuf.len = 0
			log.Warn("Get error message header, TODO: relocate the msg header")
			// TODO Relocate the message header
			return
		}

		node.rxBuf.len = msg.PayloadLen(node.rxBuf.p)
		buf = buf[length:]
	}

	msgLen = node.rxBuf.len
	if len(buf) == msgLen {
		msgBuf = append(node.rxBuf.p, buf[:]...)
		go msg.HandleNodeMsg(node, msgBuf, len(msgBuf))
		node.rxBuf.p = nil
		node.rxBuf.len = 0
	} else if len(buf) < msgLen {
		node.rxBuf.p = append(node.rxBuf.p, buf[:]...)
		node.rxBuf.len = msgLen - len(buf)
	} else {
		msgBuf = append(node.rxBuf.p, buf[0:msgLen]...)
		go msg.HandleNodeMsg(node, msgBuf, len(msgBuf))
		node.rxBuf.p = nil
		node.rxBuf.len = 0

		unpackNodeBuf(node, buf[msgLen:])
	}
}

func (node *node) rx() {
	conn := node.getConn()
	buf := make([]byte, MAXBUFLEN)
	for {
		len, err := conn.Read(buf[0:(MAXBUFLEN - 1)])
		buf[MAXBUFLEN-1] = 0 //Prevent overflow
		switch err {
		case nil:
			t := time.Now()
			node.UpdateRXTime(t)
			unpackNodeBuf(node, buf[0:len])
		case io.EOF:
			log.Error("Rx io.EOF: ", err, ", node id is ", node.GetID())
			goto DISCONNECT
		default:
			log.Error("Read connection error ", err)
			goto DISCONNECT
		}
	}

DISCONNECT:
	node.local.eventQueue.GetEvent("disconnect").Notify(events.EventNodeDisconnect, node)
}

func printIPAddr() {
	host, _ := os.Hostname()
	addrs, _ := net.LookupIP(host)
	for _, addr := range addrs {
		if ipv4 := addr.To4(); ipv4 != nil {
			log.Info("IPv4: ", ipv4)
		}
	}
}

func (link *link) CloseConn() {
	link.conn.Close()
}

func (n *node) initConnection() {
	isTls := Parameters.IsTLS
	var listener net.Listener
	var err error
	if isTls {
		listener, err = initTlsListen()
		if err != nil {
			log.Error("TLS listen failed")
			return
		}
	} else {
		listener, err = initNonTlsListen()
		if err != nil {
			log.Error("non TLS listen failed")
			return
		}
	}
	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Error("Error accepting ", err.Error())
			return
		}
		log.Info("Remote node connect with ", conn.RemoteAddr(), conn.LocalAddr())

		n.link.connCnt++

		node := NewNode()
		node.addr, err = parseIPaddr(conn.RemoteAddr().String())
		node.local = n
		node.conn = conn
		go node.rx()
	}
	//TODO Release the net listen resouce
}

func initNonTlsListen() (net.Listener, error) {
	log.Debug()
	listener, err := net.Listen("tcp", ":"+strconv.Itoa(Parameters.NodePort))
	if err != nil {
		log.Error("Error listening\n", err.Error())
		return nil, err
	}
	return listener, nil
}

func initTlsListen() (net.Listener, error) {
	CertPath := Parameters.CertPath
	KeyPath := Parameters.KeyPath
	CAPath := Parameters.CAPath

	// load cert
	cert, err := tls.LoadX509KeyPair(CertPath, KeyPath)
	if err != nil {
		log.Error("load keys fail", err)
		return nil, err
	}
	// load root ca
	caData, err := ioutil.ReadFile(CAPath)
	if err != nil {
		log.Error("read ca fail", err)
		return nil, err
	}
	pool := x509.NewCertPool()
	ret := pool.AppendCertsFromPEM(caData)
	if !ret {
		return nil, errors.New("failed to parse root certificate")
	}

	tlsConfig := &tls.Config{
		Certificates: []tls.Certificate{cert},
		RootCAs:      pool,
		ClientAuth:   tls.RequireAndVerifyClientCert,
		ClientCAs:    pool,
	}

	log.Info("TLS listen port is ", strconv.Itoa(Parameters.NodePort))
	listener, err := tls.Listen("tcp", ":"+strconv.Itoa(Parameters.NodePort), tlsConfig)
	if err != nil {
		log.Error(err)
		return nil, err
	}
	return listener, nil
}

func parseIPaddr(s string) (string, error) {
	i := strings.Index(s, ":")
	if i < 0 {
		log.Warn("Split IP address&port error")
		return s, errors.New("Split IP address&port error")
	}
	return s[:i], nil
}

func (node *node) Connect(nodeAddr string) error {
	log.Debug()

	if node.IsAddrInNbrList(nodeAddr) == true {
		return nil
	}
	if added := node.SetAddrInConnectingList(nodeAddr); added == false {
		return errors.New("node exist in connecting list, cancel")
	}

	isTls := Parameters.IsTLS
	var conn net.Conn
	var err error

	if isTls {
		conn, err = TLSDial(nodeAddr)
		if err != nil {
			node.RemoveAddrInConnectingList(nodeAddr)
			log.Error("TLS connect failed: ", err)
			return err
		}
	} else {
		conn, err = NonTLSDial(nodeAddr)
		if err != nil {
			node.RemoveAddrInConnectingList(nodeAddr)
			log.Error("non TLS connect failed: ", err)
			return err
		}
	}
	node.link.connCnt++
	n := NewNode()
	n.conn = conn
	n.addr, err = parseIPaddr(conn.RemoteAddr().String())
	n.local = node

	log.Info(fmt.Sprintf("Connect node %s connect with %s with %s",
		conn.LocalAddr().String(), conn.RemoteAddr().String(),
		conn.RemoteAddr().Network()))
	go n.rx()

	n.SetState(HAND)
	buf, _ := msg.NewVersion(node)
	n.Tx(buf)

	return nil
}

func NonTLSDial(nodeAddr string) (net.Conn, error) {
	log.Debug()
	conn, err := net.DialTimeout("tcp", nodeAddr, time.Second*DIALTIMEOUT)
	if err != nil {
		return nil, err
	}
	return conn, nil
}

func TLSDial(nodeAddr string) (net.Conn, error) {
	CertPath := Parameters.CertPath
	KeyPath := Parameters.KeyPath
	CAPath := Parameters.CAPath

	clientCertPool := x509.NewCertPool()

	cacert, err := ioutil.ReadFile(CAPath)
	cert, err := tls.LoadX509KeyPair(CertPath, KeyPath)
	if err != nil {
		return nil, err
	}

	ret := clientCertPool.AppendCertsFromPEM(cacert)
	if !ret {
		return nil, errors.New("failed to parse root certificate")
	}

	conf := &tls.Config{
		RootCAs:      clientCertPool,
		Certificates: []tls.Certificate{cert},
	}

	var dialer net.Dialer
	dialer.Timeout = time.Second * DIALTIMEOUT
	conn, err := tls.DialWithDialer(&dialer, "tcp", nodeAddr, conf)
	if err != nil {
		return nil, err
	}
	return conn, nil
}

func (node *node) Tx(buf []byte) {
	log.Debugf("TX buf length: %d\n%x", len(buf), buf)

	if node.GetState() == INACTIVITY {
		return
	}
	_, err := node.conn.Write(buf)
	if err != nil {
		log.Error("Error sending messge to peer node ", err.Error())
		node.local.eventQueue.GetEvent("disconnect").Notify(events.EventNodeDisconnect, node)
	}
}
<|endoftext|>


<commit_before>package charm

import (
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"launchpad.net/juju/go/log"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"
)

// InfoResponse is sent by the charm store in response to charm-info requests.
type InfoResponse struct {
	Revision int      `json:"revision"` // Zero is valid. Can't omitempty.
	Sha256   string   `json:"sha256,omitempty"`
	Errors   []string `json:"errors,omitempty"`
	Warnings []string `json:"warnings,omitempty"`
}

// Repository respresents a collection of charms.
type Repository interface {
	Get(curl *URL) (Charm, error)
	Latest(curl *URL) (int, error)
}

// store is a Repository that talks to the juju charm server (in ../store).
type store struct {
	baseURL   string
	cachePath string
}

const (
	storeURL  = "https://store.juju.ubuntu.com"
	cachePath = "$HOME/.juju/cache"
)

// Store returns a Repository that provides access to the juju charm store.
func Store() Repository {
	return &store{storeURL, os.ExpandEnv(cachePath)}
}

// info returns the revision and SHA256 digest of the charm referenced by curl.
func (s *store) info(curl *URL) (rev int, digest string, err error) {
	key := curl.String()
	resp, err := http.Get(s.baseURL + "/charm-info?charms=" + url.QueryEscape(key))
	if err != nil {
		return
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	infos := make(map[string]*InfoResponse)
	if err = json.Unmarshal(body, &infos); err != nil {
		return
	}
	info, found := infos[key]
	if !found {
		err = fmt.Errorf("charm: charm store returned response without charm %q", key)
		return
	}
	for _, w := range info.Warnings {
		log.Printf("WARNING: charm store reports for %q: %s", key, w)
	}
	if info.Errors != nil {
		err = fmt.Errorf(
			"charm info errors for %q: %s", key, strings.Join(info.Errors, "; "),
		)
		return
	}
	return info.Revision, info.Sha256, nil
}

// Latest returns the latest revision of the charm referenced by curl, regardless
// of the revision set on curl itself.
func (s *store) Latest(curl *URL) (int, error) {
	rev, _, err := s.info(curl.WithRevision(-1))
	return rev, err
}

// verify returns an error unless a file exists at path with a hex-encoded
// SHA256 matching digest.
func verify(path, digest string) error {
	b, err := ioutil.ReadFile(path)
	if err != nil {
		return err
	}
	h := sha256.New()
	h.Write(b)
	if hex.EncodeToString(h.Sum(nil)) != digest {
		return fmt.Errorf("bad SHA256 of %q", path)
	}
	return nil
}

// Get returns the charm referenced by curl.
func (s *store) Get(curl *URL) (Charm, error) {
	if err := os.MkdirAll(s.cachePath, 0755); err != nil {
		return nil, err
	}
	rev, digest, err := s.info(curl)
	if err != nil {
		return nil, err
	}
	if curl.Revision == -1 {
		curl = curl.WithRevision(rev)
	} else if curl.Revision != rev {
		return nil, fmt.Errorf("charm: store returned charm with wrong revision for %q", curl.String())
	}
	path := filepath.Join(s.cachePath, Quote(curl.String())+".charm")
	if verify(path, digest) != nil {
		resp, err := http.Get(s.baseURL + "/charm/" + url.QueryEscape(curl.Path()))
		if err != nil {
			return nil, err
		}
		defer resp.Body.Close()
		f, err := ioutil.TempFile(s.cachePath, "charm-download")
		if err != nil {
			return nil, err
		}
		dlPath := f.Name()
		_, err = io.Copy(f, resp.Body)
		if cerr := f.Close(); err == nil {
			err = cerr
		}
		if err != nil {
			os.Remove(dlPath)
			return nil, err
		}
		if err := os.Rename(dlPath, path); err != nil {
			return nil, err
		}
	}
	if err := verify(path, digest); err != nil {
		return nil, err
	}
	return ReadBundle(path)
}

// LocalRepository represents a local directory containing subdirectories
// named after an Ubuntu series, each of which contains charms targeted for
// that series.
type LocalRepository struct {
	Path string
}

// Latest returns the latest revision of the charm referenced by curl, regardless
// of the revision set on curl itself.
func (r *LocalRepository) Latest(curl *URL) (int, error) {
	ch, err := r.Get(curl.WithRevision(-1))
	if err != nil {
		return 0, err
	}
	return ch.Revision(), nil
}

func repoNotFound(path string) error {
	return fmt.Errorf("no repository found at %q", path)
}

func charmNotFound(curl *URL) error {
	return fmt.Errorf("no charms found matching %q", curl)
}

func mightBeCharm(info os.FileInfo) bool {
	if info.IsDir() {
		return !strings.HasPrefix(info.Name(), ".")
	}
	return strings.HasSuffix(info.Name(), ".charm")
}

// Get returns a charm matching curl, if one exists. If curl has a revision of
// -1, it returns the latest charm that matches curl. If multiple candidates
// satisfy the foregoing, the first one encountered will be returned.
func (r *LocalRepository) Get(curl *URL) (Charm, error) {
	if curl.Schema != "local" {
		return nil, fmt.Errorf("charm: local repository got URL with non-local schema: %q", curl)
	}
	info, err := os.Stat(r.Path)
	if err != nil {
		if os.IsNotExist(err) {
			err = repoNotFound(r.Path)
		}
		return nil, err
	}
	if !info.IsDir() {
		return nil, repoNotFound(r.Path)
	}
	path := filepath.Join(r.Path, curl.Series)
	infos, err := ioutil.ReadDir(path)
	if err != nil {
		return nil, charmNotFound(curl)
	}
	var latest Charm
	for _, info := range infos {
		if !mightBeCharm(info) {
			continue
		}
		chPath := filepath.Join(path, info.Name())
		if ch, err := Read(chPath); err != nil {
			log.Printf("WARNING: failed to load charm at %q: %s", chPath, err)
		} else if ch.Meta().Name == curl.Name {
			if ch.Revision() == curl.Revision {
				return ch, nil
			}
			if latest == nil || ch.Revision() > latest.Revision() {
				latest = ch
			}
		}
	}
	if curl.Revision == -1 && latest != nil {
		return latest, nil
	}
	return nil, charmNotFound(curl)
}
<commit_msg>address final review points<commit_after>package charm

import (
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"launchpad.net/juju/go/log"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"
)

// InfoResponse is sent by the charm store in response to charm-info requests.
type InfoResponse struct {
	Revision int      `json:"revision"` // Zero is valid. Can't omitempty.
	Sha256   string   `json:"sha256,omitempty"`
	Errors   []string `json:"errors,omitempty"`
	Warnings []string `json:"warnings,omitempty"`
}

// Repository respresents a collection of charms.
type Repository interface {
	Get(curl *URL) (Charm, error)
	Latest(curl *URL) (int, error)
}

// store is a Repository that talks to the juju charm server (in ../store).
type store struct {
	baseURL   string
	cachePath string
}

const (
	storeURL  = "https://store.juju.ubuntu.com"
	cachePath = "$HOME/.juju/cache"
)

// Store returns a Repository that provides access to the juju charm store.
func Store() Repository {
	return &store{storeURL, os.ExpandEnv(cachePath)}
}

// info returns the revision and SHA256 digest of the charm referenced by curl.
func (s *store) info(curl *URL) (rev int, digest string, err error) {
	key := curl.String()
	resp, err := http.Get(s.baseURL + "/charm-info?charms=" + url.QueryEscape(key))
	if err != nil {
		return
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	infos := make(map[string]*InfoResponse)
	if err = json.Unmarshal(body, &infos); err != nil {
		return
	}
	info, found := infos[key]
	if !found {
		err = fmt.Errorf("charm: charm store returned response without charm %q", key)
		return
	}
	for _, w := range info.Warnings {
		log.Printf("WARNING: charm store reports for %q: %s", key, w)
	}
	if info.Errors != nil {
		err = fmt.Errorf(
			"charm info errors for %q: %s", key, strings.Join(info.Errors, "; "),
		)
		return
	}
	return info.Revision, info.Sha256, nil
}

// Latest returns the latest revision of the charm referenced by curl, regardless
// of the revision set on curl itself.
func (s *store) Latest(curl *URL) (int, error) {
	rev, _, err := s.info(curl.WithRevision(-1))
	return rev, err
}

// verify returns an error unless a file exists at path with a hex-encoded
// SHA256 matching digest.
func verify(path, digest string) error {
	b, err := ioutil.ReadFile(path)
	if err != nil {
		return err
	}
	h := sha256.New()
	h.Write(b)
	if hex.EncodeToString(h.Sum(nil)) != digest {
		return fmt.Errorf("bad SHA256 of %q", path)
	}
	return nil
}

// Get returns the charm referenced by curl.
func (s *store) Get(curl *URL) (Charm, error) {
	if err := os.MkdirAll(s.cachePath, 0755); err != nil {
		return nil, err
	}
	rev, digest, err := s.info(curl)
	if err != nil {
		return nil, err
	}
	if curl.Revision == -1 {
		curl = curl.WithRevision(rev)
	} else if curl.Revision != rev {
		return nil, fmt.Errorf("charm: store returned charm with wrong revision for %q", curl.String())
	}
	path := filepath.Join(s.cachePath, Quote(curl.String())+".charm")
	if verify(path, digest) != nil {
		resp, err := http.Get(s.baseURL + "/charm/" + url.QueryEscape(curl.Path()))
		if err != nil {
			return nil, err
		}
		defer resp.Body.Close()
		f, err := ioutil.TempFile(s.cachePath, "charm-download")
		if err != nil {
			return nil, err
		}
		dlPath := f.Name()
		_, err = io.Copy(f, resp.Body)
		if cerr := f.Close(); err == nil {
			err = cerr
		}
		if err != nil {
			os.Remove(dlPath)
			return nil, err
		}
		if err := os.Rename(dlPath, path); err != nil {
			return nil, err
		}
	}
	if err := verify(path, digest); err != nil {
		return nil, err
	}
	return ReadBundle(path)
}

// LocalRepository represents a local directory containing subdirectories
// named after an Ubuntu series, each of which contains charms targeted for
// that series. For example:
//
//   /path/to/repository/oneiric/mongodb/
//   /path/to/repository/precise/mongodb.charm
//   /path/to/repository/precise/wordpress/
type LocalRepository struct {
	Path string
}

// Latest returns the latest revision of the charm referenced by curl, regardless
// of the revision set on curl itself.
func (r *LocalRepository) Latest(curl *URL) (int, error) {
	ch, err := r.Get(curl.WithRevision(-1))
	if err != nil {
		return 0, err
	}
	return ch.Revision(), nil
}

func repoNotFound(path string) error {
	return fmt.Errorf("no repository found at %q", path)
}

func charmNotFound(curl *URL) error {
	return fmt.Errorf("no charms found matching %q", curl)
}

func mightBeCharm(info os.FileInfo) bool {
	if info.IsDir() {
		return !strings.HasPrefix(info.Name(), ".")
	}
	return strings.HasSuffix(info.Name(), ".charm")
}

// Get returns a charm matching curl, if one exists. If curl has a revision of
// -1, it returns the latest charm that matches curl. If multiple candidates
// satisfy the foregoing, the first one encountered will be returned.
func (r *LocalRepository) Get(curl *URL) (Charm, error) {
	if curl.Schema != "local" {
		return nil, fmt.Errorf("local repository got URL with non-local schema: %q", curl)
	}
	info, err := os.Stat(r.Path)
	if err != nil {
		if os.IsNotExist(err) {
			err = repoNotFound(r.Path)
		}
		return nil, err
	}
	if !info.IsDir() {
		return nil, repoNotFound(r.Path)
	}
	path := filepath.Join(r.Path, curl.Series)
	infos, err := ioutil.ReadDir(path)
	if err != nil {
		return nil, charmNotFound(curl)
	}
	var latest Charm
	for _, info := range infos {
		if !mightBeCharm(info) {
			continue
		}
		chPath := filepath.Join(path, info.Name())
		if ch, err := Read(chPath); err != nil {
			log.Printf("WARNING: failed to load charm at %q: %s", chPath, err)
		} else if ch.Meta().Name == curl.Name {
			if ch.Revision() == curl.Revision {
				return ch, nil
			}
			if latest == nil || ch.Revision() > latest.Revision() {
				latest = ch
			}
		}
	}
	if curl.Revision == -1 && latest != nil {
		return latest, nil
	}
	return nil, charmNotFound(curl)
}
<|endoftext|>


<commit_before>package mtree

import (
	"bytes"
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"
	"time"
)

// simple walk of current directory, and imediately check it.
// may not be parallelizable.
func TestCheck(t *testing.T) {
	dh, err := Walk(".", nil, append(DefaultKeywords, "sha1"), nil)
	if err != nil {
		t.Fatal(err)
	}

	res, err := Check(".", dh, nil, nil)
	if err != nil {
		t.Fatal(err)
	}

	if len(res) > 0 {
		t.Errorf("%#v", res)
	}
}

// make a directory, walk it, check it, modify the timestamp and ensure it fails.
// only check again for size and sha1, and ignore time, and ensure it passes
func TestCheckKeywords(t *testing.T) {
	content := []byte("I know half of you half as well as I ought to")
	dir, err := ioutil.TempDir("", "test-check-keywords")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(dir) // clean up

	tmpfn := filepath.Join(dir, "tmpfile")
	if err := ioutil.WriteFile(tmpfn, content, 0666); err != nil {
		t.Fatal(err)
	}

	// Walk this tempdir
	dh, err := Walk(dir, nil, append(DefaultKeywords, "sha1"), nil)
	if err != nil {
		t.Fatal(err)
	}

	// Check for sanity. This ought to pass.
	res, err := Check(dir, dh, nil, nil)
	if err != nil {
		t.Fatal(err)
	}
	if len(res) > 0 {
		t.Errorf("%#v", res)
	}

	// Touch a file, so the mtime changes.
	now := time.Now()
	if err := os.Chtimes(tmpfn, now, now); err != nil {
		t.Fatal(err)
	}

	// Check again. This ought to fail.
	res, err = Check(dir, dh, nil, nil)
	if err != nil {
		t.Fatal(err)
	}
	if len(res) != 1 {
		t.Fatal("expected to get 1 delta on changed mtimes, but did not")
	}
	if res[0].Type() != Modified {
		t.Errorf("expected to get modified delta on changed mtimes, but did not")
	}

	// Check again, but only sha1 and mode. This ought to pass.
	res, err = Check(dir, dh, []Keyword{"sha1", "mode"}, nil)
	if err != nil {
		t.Fatal(err)
	}
	if len(res) > 0 {
		t.Errorf("%#v", res)
	}
}

func ExampleCheck() {
	dh, err := Walk(".", nil, append(DefaultKeywords, "sha1"), nil)
	if err != nil {
		// handle error ...
	}

	res, err := Check(".", dh, nil, nil)
	if err != nil {
		// handle error ...
	}
	if len(res) > 0 {
		// handle failed validity ...
	}
}

// Tests default action for evaluating a symlink, which is just to compare the
// link itself, not to follow it
func TestDefaultBrokenLink(t *testing.T) {
	dh, err := Walk("./testdata/dirwithbrokenlink", nil, append(DefaultKeywords, "sha1"), nil)
	if err != nil {
		t.Fatal(err)
	}
	res, err := Check("./testdata/dirwithbrokenlink", dh, nil, nil)
	if err != nil {
		t.Fatal(err)
	}
	if len(res) > 0 {
		for _, delta := range res {
			t.Error(delta)
		}
	}
}

// https://github.com/vbatts/go-mtree/issues/8
func TestTimeComparison(t *testing.T) {
	dir, err := ioutil.TempDir("", "test-time.")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(dir)

	// This is the format of time from FreeBSD
	spec := `
/set type=file time=5.000000000
.               type=dir
    file       time=5.000000000
..
`

	fh, err := os.Create(filepath.Join(dir, "file"))
	if err != nil {
		t.Fatal(err)
	}
	// This is what mode we're checking for. Round integer of epoch seconds
	epoch := time.Unix(5, 0)
	if err := os.Chtimes(fh.Name(), epoch, epoch); err != nil {
		t.Fatal(err)
	}
	if err := os.Chtimes(dir, epoch, epoch); err != nil {
		t.Fatal(err)
	}
	if err := fh.Close(); err != nil {
		t.Error(err)
	}

	dh, err := ParseSpec(bytes.NewBufferString(spec))
	if err != nil {
		t.Fatal(err)
	}

	res, err := Check(dir, dh, nil, nil)
	if err != nil {
		t.Error(err)
	}
	if len(res) > 0 {
		t.Fatal(res)
	}
}

func TestTarTime(t *testing.T) {
	dir, err := ioutil.TempDir("", "test-tar-time.")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(dir)

	// This is the format of time from FreeBSD
	spec := `
/set type=file time=5.454353132
.               type=dir time=5.123456789
    file       time=5.911134111
..
`

	fh, err := os.Create(filepath.Join(dir, "file"))
	if err != nil {
		t.Fatal(err)
	}
	// This is what mode we're checking for. Round integer of epoch seconds
	epoch := time.Unix(5, 0)
	if err := os.Chtimes(fh.Name(), epoch, epoch); err != nil {
		t.Fatal(err)
	}
	if err := os.Chtimes(dir, epoch, epoch); err != nil {
		t.Fatal(err)
	}
	if err := fh.Close(); err != nil {
		t.Error(err)
	}

	dh, err := ParseSpec(bytes.NewBufferString(spec))
	if err != nil {
		t.Fatal(err)
	}

	keywords := dh.UsedKeywords()

	// make sure "time" keyword works
	_, err = Check(dir, dh, keywords, nil)
	if err != nil {
		t.Error(err)
	}

	// make sure tar_time wins
	res, err := Check(dir, dh, append(keywords, "tar_time"), nil)
	if err != nil {
		t.Error(err)
	}
	if len(res) > 0 {
		t.Fatal(res)
	}
}

func TestIgnoreComments(t *testing.T) {
	dir, err := ioutil.TempDir("", "test-comments.")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(dir)

	// This is the format of time from FreeBSD
	spec := `
/set type=file time=5.000000000
.               type=dir
    file1       time=5.000000000
..
`

	fh, err := os.Create(filepath.Join(dir, "file1"))
	if err != nil {
		t.Fatal(err)
	}
	// This is what mode we're checking for. Round integer of epoch seconds
	epoch := time.Unix(5, 0)
	if err := os.Chtimes(fh.Name(), epoch, epoch); err != nil {
		t.Fatal(err)
	}
	if err := os.Chtimes(dir, epoch, epoch); err != nil {
		t.Fatal(err)
	}
	if err := fh.Close(); err != nil {
		t.Error(err)
	}

	dh, err := ParseSpec(bytes.NewBufferString(spec))
	if err != nil {
		t.Fatal(err)
	}

	res, err := Check(dir, dh, nil, nil)
	if err != nil {
		t.Error(err)
	}

	if len(res) > 0 {
		t.Fatal(res)
	}

	// now change the spec to a comment that looks like an actual Entry but has
	// whitespace in front of it
	spec = `
/set type=file time=5.000000000
.               type=dir
    file1       time=5.000000000
	#file2 		time=5.000000000
..
`
	dh, err = ParseSpec(bytes.NewBufferString(spec))

	res, err = Check(dir, dh, nil, nil)
	if err != nil {
		t.Error(err)
	}

	if len(res) > 0 {
		t.Fatal(res)
	}
}

func TestCheckNeedsEncoding(t *testing.T) {
	dir, err := ioutil.TempDir("", "test-needs-encoding")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(dir)

	fh, err := os.Create(filepath.Join(dir, "file[ "))
	if err != nil {
		t.Fatal(err)
	}
	if err := fh.Close(); err != nil {
		t.Error(err)
	}
	fh, err = os.Create(filepath.Join(dir, "    , should work"))
	if err != nil {
		t.Fatal(err)
	}
	if err := fh.Close(); err != nil {
		t.Error(err)
	}

	dh, err := Walk(dir, nil, DefaultKeywords, nil)
	if err != nil {
		t.Fatal(err)
	}
	res, err := Check(dir, dh, nil, nil)
	if err != nil {
		t.Fatal(err)
	}
	if len(res) > 0 {
		t.Fatal(res)
	}
}
<commit_msg>check: test times weren't different enough<commit_after>package mtree

import (
	"bytes"
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"
	"time"
)

// simple walk of current directory, and imediately check it.
// may not be parallelizable.
func TestCheck(t *testing.T) {
	dh, err := Walk(".", nil, append(DefaultKeywords, "sha1"), nil)
	if err != nil {
		t.Fatal(err)
	}

	res, err := Check(".", dh, nil, nil)
	if err != nil {
		t.Fatal(err)
	}

	if len(res) > 0 {
		t.Errorf("%#v", res)
	}
}

// make a directory, walk it, check it, modify the timestamp and ensure it fails.
// only check again for size and sha1, and ignore time, and ensure it passes
func TestCheckKeywords(t *testing.T) {
	content := []byte("I know half of you half as well as I ought to")
	dir, err := ioutil.TempDir("", "test-check-keywords")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(dir) // clean up

	tmpfn := filepath.Join(dir, "tmpfile")
	if err := ioutil.WriteFile(tmpfn, content, 0666); err != nil {
		t.Fatal(err)
	}

	// Walk this tempdir
	dh, err := Walk(dir, nil, append(DefaultKeywords, "sha1"), nil)
	if err != nil {
		t.Fatal(err)
	}

	// Check for sanity. This ought to pass.
	res, err := Check(dir, dh, nil, nil)
	if err != nil {
		t.Fatal(err)
	}
	if len(res) > 0 {
		t.Errorf("%#v", res)
	}

	// Touch a file, so the mtime changes.
	newtime := time.Date(2006, time.February, 1, 3, 4, 5, 0, time.UTC)
	if err := os.Chtimes(tmpfn, newtime, newtime); err != nil {
		t.Fatal(err)
	}

	// Check again. This ought to fail.
	res, err = Check(dir, dh, nil, nil)
	if err != nil {
		t.Fatal(err)
	}
	if len(res) != 1 {
		t.Fatal("expected to get 1 delta on changed mtimes, but did not")
	}
	if res[0].Type() != Modified {
		t.Errorf("expected to get modified delta on changed mtimes, but did not")
	}

	// Check again, but only sha1 and mode. This ought to pass.
	res, err = Check(dir, dh, []Keyword{"sha1", "mode"}, nil)
	if err != nil {
		t.Fatal(err)
	}
	if len(res) > 0 {
		t.Errorf("%#v", res)
	}
}

func ExampleCheck() {
	dh, err := Walk(".", nil, append(DefaultKeywords, "sha1"), nil)
	if err != nil {
		// handle error ...
	}

	res, err := Check(".", dh, nil, nil)
	if err != nil {
		// handle error ...
	}
	if len(res) > 0 {
		// handle failed validity ...
	}
}

// Tests default action for evaluating a symlink, which is just to compare the
// link itself, not to follow it
func TestDefaultBrokenLink(t *testing.T) {
	dh, err := Walk("./testdata/dirwithbrokenlink", nil, append(DefaultKeywords, "sha1"), nil)
	if err != nil {
		t.Fatal(err)
	}
	res, err := Check("./testdata/dirwithbrokenlink", dh, nil, nil)
	if err != nil {
		t.Fatal(err)
	}
	if len(res) > 0 {
		for _, delta := range res {
			t.Error(delta)
		}
	}
}

// https://github.com/vbatts/go-mtree/issues/8
func TestTimeComparison(t *testing.T) {
	dir, err := ioutil.TempDir("", "test-time.")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(dir)

	// This is the format of time from FreeBSD
	spec := `
/set type=file time=5.000000000
.               type=dir
    file       time=5.000000000
..
`

	fh, err := os.Create(filepath.Join(dir, "file"))
	if err != nil {
		t.Fatal(err)
	}
	// This is what mode we're checking for. Round integer of epoch seconds
	epoch := time.Unix(5, 0)
	if err := os.Chtimes(fh.Name(), epoch, epoch); err != nil {
		t.Fatal(err)
	}
	if err := os.Chtimes(dir, epoch, epoch); err != nil {
		t.Fatal(err)
	}
	if err := fh.Close(); err != nil {
		t.Error(err)
	}

	dh, err := ParseSpec(bytes.NewBufferString(spec))
	if err != nil {
		t.Fatal(err)
	}

	res, err := Check(dir, dh, nil, nil)
	if err != nil {
		t.Error(err)
	}
	if len(res) > 0 {
		t.Fatal(res)
	}
}

func TestTarTime(t *testing.T) {
	dir, err := ioutil.TempDir("", "test-tar-time.")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(dir)

	// This is the format of time from FreeBSD
	spec := `
/set type=file time=5.454353132
.               type=dir time=5.123456789
    file       time=5.911134111
..
`

	fh, err := os.Create(filepath.Join(dir, "file"))
	if err != nil {
		t.Fatal(err)
	}
	// This is what mode we're checking for. Round integer of epoch seconds
	epoch := time.Unix(5, 0)
	if err := os.Chtimes(fh.Name(), epoch, epoch); err != nil {
		t.Fatal(err)
	}
	if err := os.Chtimes(dir, epoch, epoch); err != nil {
		t.Fatal(err)
	}
	if err := fh.Close(); err != nil {
		t.Error(err)
	}

	dh, err := ParseSpec(bytes.NewBufferString(spec))
	if err != nil {
		t.Fatal(err)
	}

	keywords := dh.UsedKeywords()

	// make sure "time" keyword works
	_, err = Check(dir, dh, keywords, nil)
	if err != nil {
		t.Error(err)
	}

	// make sure tar_time wins
	res, err := Check(dir, dh, append(keywords, "tar_time"), nil)
	if err != nil {
		t.Error(err)
	}
	if len(res) > 0 {
		t.Fatal(res)
	}
}

func TestIgnoreComments(t *testing.T) {
	dir, err := ioutil.TempDir("", "test-comments.")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(dir)

	// This is the format of time from FreeBSD
	spec := `
/set type=file time=5.000000000
.               type=dir
    file1       time=5.000000000
..
`

	fh, err := os.Create(filepath.Join(dir, "file1"))
	if err != nil {
		t.Fatal(err)
	}
	// This is what mode we're checking for. Round integer of epoch seconds
	epoch := time.Unix(5, 0)
	if err := os.Chtimes(fh.Name(), epoch, epoch); err != nil {
		t.Fatal(err)
	}
	if err := os.Chtimes(dir, epoch, epoch); err != nil {
		t.Fatal(err)
	}
	if err := fh.Close(); err != nil {
		t.Error(err)
	}

	dh, err := ParseSpec(bytes.NewBufferString(spec))
	if err != nil {
		t.Fatal(err)
	}

	res, err := Check(dir, dh, nil, nil)
	if err != nil {
		t.Error(err)
	}

	if len(res) > 0 {
		t.Fatal(res)
	}

	// now change the spec to a comment that looks like an actual Entry but has
	// whitespace in front of it
	spec = `
/set type=file time=5.000000000
.               type=dir
    file1       time=5.000000000
	#file2 		time=5.000000000
..
`
	dh, err = ParseSpec(bytes.NewBufferString(spec))

	res, err = Check(dir, dh, nil, nil)
	if err != nil {
		t.Error(err)
	}

	if len(res) > 0 {
		t.Fatal(res)
	}
}

func TestCheckNeedsEncoding(t *testing.T) {
	dir, err := ioutil.TempDir("", "test-needs-encoding")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(dir)

	fh, err := os.Create(filepath.Join(dir, "file[ "))
	if err != nil {
		t.Fatal(err)
	}
	if err := fh.Close(); err != nil {
		t.Error(err)
	}
	fh, err = os.Create(filepath.Join(dir, "    , should work"))
	if err != nil {
		t.Fatal(err)
	}
	if err := fh.Close(); err != nil {
		t.Error(err)
	}

	dh, err := Walk(dir, nil, DefaultKeywords, nil)
	if err != nil {
		t.Fatal(err)
	}
	res, err := Check(dir, dh, nil, nil)
	if err != nil {
		t.Fatal(err)
	}
	if len(res) > 0 {
		t.Fatal(res)
	}
}
<|endoftext|>


<commit_before>package xsdgen

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"
)

func glob(dir ...string) []string {
	files, err := filepath.Glob(filepath.Join(dir...))
	if err != nil {
		panic("error in glob util function: " + err.Error())
	}
	return files
}

type testLogger testing.T

func (t *testLogger) Printf(format string, v ...interface{}) {
	t.Logf(format, v...)
}

func TestLibrarySchema(t *testing.T) {
	testGen(t, "http://dyomedea.com/ns/library", "testdata/library.xsd")
}
func TestPurchasOrderSchema(t *testing.T) {
	testGen(t, "http://www.example.com/PO1", "testdata/po1.xsd")
}
func TestUSTreasureSDN(t *testing.T) {
	testGen(t, "http://tempuri.org/sdnList.xsd", "testdata/sdn.xsd")
}
func TestSoap(t *testing.T) {
	testGen(t, "http://schemas.xmlsoap.org/soap/encoding/", "testdata/soap11.xsd")
}

func testGen(t *testing.T, ns string, files ...string) {
	file, err := ioutil.TempFile("", "xsdgen")
	if err != nil {
		t.Fatal(err)
	}
	defer os.Remove(file.Name())

	var cfg Config
	cfg.Option(DefaultOptions...)
	cfg.Option(LogOutput((*testLogger)(t)))

	args := []string{"-v", "-o", file.Name(), "-ns", ns}
	err = cfg.GenCLI(append(args, files...)...)
	if err != nil {
		t.Error(err)
	}
	if data, err := ioutil.ReadFile(file.Name()); err != nil {
		t.Error(err)
	} else {
		t.Logf("\n%s\n", data)
	}
}
<commit_msg>removed unused function<commit_after>package xsdgen

import (
	"io/ioutil"
	"os"
	"testing"
)

type testLogger testing.T

func (t *testLogger) Printf(format string, v ...interface{}) {
	t.Logf(format, v...)
}

func TestLibrarySchema(t *testing.T) {
	testGen(t, "http://dyomedea.com/ns/library", "testdata/library.xsd")
}
func TestPurchasOrderSchema(t *testing.T) {
	testGen(t, "http://www.example.com/PO1", "testdata/po1.xsd")
}
func TestUSTreasureSDN(t *testing.T) {
	testGen(t, "http://tempuri.org/sdnList.xsd", "testdata/sdn.xsd")
}
func TestSoap(t *testing.T) {
	testGen(t, "http://schemas.xmlsoap.org/soap/encoding/", "testdata/soap11.xsd")
}

func testGen(t *testing.T, ns string, files ...string) {
	file, err := ioutil.TempFile("", "xsdgen")
	if err != nil {
		t.Fatal(err)
	}
	defer os.Remove(file.Name())

	var cfg Config
	cfg.Option(DefaultOptions...)
	cfg.Option(LogOutput((*testLogger)(t)))

	args := []string{"-v", "-o", file.Name(), "-ns", ns}
	err = cfg.GenCLI(append(args, files...)...)
	if err != nil {
		t.Error(err)
	}
	if data, err := ioutil.ReadFile(file.Name()); err != nil {
		t.Error(err)
	} else {
		t.Logf("\n%s\n", data)
	}
}
<|endoftext|>


<commit_before>// Package redis implements a Gondola cache backend using redis.
package redis

import (
	"github.com/vmihailenco/redis"
	"gondola/cache/driver"
	"fmt"
	"strconv"
)

type redisDriver struct {
	*redis.Client
}

func (r *redisDriver) Set(key string, b []byte, timeout int) error {
	var req *redis.StatusReq
	if timeout == 0 {
		req = r.Client.Set(key, string(b))
	} else {
		req = r.Client.SetEx(key, int64(timeout), string(b))
	}
	return req.Err()
}

func (r *redisDriver) Get(key string) ([]byte, error) {
	req := r.Client.Get(key)
	if err := req.Err(); err != nil {
		if err == redis.Nil {
			return nil, nil
		}
		return nil, err
	}
	return []byte(req.Val()), nil
}

func (r *redisDriver) GetMulti(keys []string) (map[string][]byte, error) {
	req := r.Client.MGet(keys...)
	if err := req.Err(); err != nil {
		return nil, err
	}
	value := make(map[string][]byte, len(keys))
	for ii, v := range req.Val() {
		if v != nil {
			s := v.(string)
			value[keys[ii]] = []byte(s)
		}
	}
	return value, nil
}

func (r *redisDriver) Delete(key string) error {
	req := r.Client.Del(key)
	return req.Err()
}

func (r *redisDriver) Connection() interface{} {
	return r.Client
}

func redisOpener(value string, o driver.Options) (driver.Driver, error) {
	password := o.Get("password")
	db := int64(-1)
	if d := o.Get("db"); d != "" {
		val, err := strconv.ParseInt(d, 0, 64)
		if err != nil {
		    return nil, fmt.Errorf("invalid db %q, must be an integer", d)
		}
		db = val
	}
	conn := driver.DefaultPort(value, 6379)
	client := redis.NewTCPClient(conn, password, db)
	return &redisDriver{Client: client}, nil
}

func init() {
	driver.Register("redis", redisOpener)
}
<commit_msg>Fix redis driver<commit_after>// Package redis implements a Gondola cache backend using redis.
package redis

import (
	"fmt"
	"github.com/vmihailenco/redis"
	"gondola/cache/driver"
	"strconv"
)

type redisDriver struct {
	*redis.Client
}

func (r *redisDriver) Set(key string, b []byte, timeout int) error {
	var req *redis.StatusReq
	if timeout == 0 {
		req = r.Client.Set(key, string(b))
	} else {
		req = r.Client.SetEx(key, int64(timeout), string(b))
	}
	return req.Err()
}

func (r *redisDriver) Get(key string) ([]byte, error) {
	req := r.Client.Get(key)
	if err := req.Err(); err != nil {
		if err == redis.Nil {
			return nil, nil
		}
		return nil, err
	}
	return []byte(req.Val()), nil
}

func (r *redisDriver) GetMulti(keys []string) (map[string][]byte, error) {
	req := r.Client.MGet(keys...)
	if err := req.Err(); err != nil {
		return nil, err
	}
	value := make(map[string][]byte, len(keys))
	for ii, v := range req.Val() {
		if v != nil {
			s := v.(string)
			value[keys[ii]] = []byte(s)
		}
	}
	return value, nil
}

func (r *redisDriver) Delete(key string) error {
	req := r.Client.Del(key)
	return req.Err()
}

func (r *redisDriver) Connection() interface{} {
	return r.Client
}

func redisOpener(value string, o driver.Options) (driver.Driver, error) {
	password := o.Get("password")
	db := int64(-1)
	if d := o.Get("db"); d != "" {
		val, err := strconv.ParseInt(d, 0, 64)
		if err != nil {
			return nil, fmt.Errorf("invalid db %q, must be an integer", d)
		}
		db = val
	}
	conn := driver.DefaultPort(value, 6379)
	client := redis.NewTCPClient(conn, password, db)
	return &redisDriver{Client: client}, nil
}

func init() {
	driver.Register("redis", redisOpener)
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"fmt"
	"jiacrontab/client/store"
	"jiacrontab/libs"
	"jiacrontab/libs/proto"
	"log"
	"strings"
	"sync"
	"sync/atomic"
	"time"
)

func newCrontab(taskChanSize int) *crontab {
	return &crontab{
		taskChan:     make(chan *proto.TaskArgs, taskChanSize),
		delTaskChan:  make(chan *proto.TaskArgs, taskChanSize),
		killTaskChan: make(chan *proto.TaskArgs, taskChanSize),
		handleMap:    make(map[string]*handle),
	}
}

type handle struct {
	cancel         context.CancelFunc
	cancelCmdArray []context.CancelFunc
	clockChan      chan time.Time
	timeout        int64
}

type crontab struct {
	taskChan     chan *proto.TaskArgs
	delTaskChan  chan *proto.TaskArgs
	killTaskChan chan *proto.TaskArgs
	handleMap    map[string]*handle
	lock         sync.RWMutex
}

func (c *crontab) add(t *proto.TaskArgs) {
	c.taskChan <- t
	log.Printf("add task %+v", *t)
}

func (c *crontab) quickStart(t *proto.TaskArgs, content *[]byte) {
	start := time.Now().Unix()
	args := strings.Split(t.Args, " ")
	t.LastExecTime = start
	var timeout int64
	if t.Timeout == 0 {
		timeout = 60
	}

	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second)
	err := execScript(ctx, fmt.Sprintf("%s-%s.log", t.Name, t.Id), t.Command, globalConfig.logPath, content, args...)
	cancel()

	if err != nil {
		*content = append(*content, []byte(err.Error())...)
	}

	t.LastCostTime = time.Now().Unix() - start
	globalStore.Sync()

	log.Printf("%s:  quic start end costTime %ds %v", t.Name, t.LastCostTime, err)

}

func (c *crontab) stop(t *proto.TaskArgs) {
	c.kill(t)
	c.delTaskChan <- t
	log.Println("stop", t.Name, t.Id)
}

func (c *crontab) kill(t *proto.TaskArgs) {
	c.killTaskChan <- t
	log.Println("kill", t.Name, t.Id)
}

func (c *crontab) delete(t *proto.TaskArgs) {
	globalStore.Update(func(s *store.Store) {
		delete(s.TaskList, t.Id)
	})
	c.kill(t)
	c.delTaskChan <- t
	log.Println("delete", t.Name, t.Id)
}

func (c *crontab) ids() []string {
	var sli []string
	c.lock.Lock()
	for k, _ := range c.handleMap {
		sli = append(sli, k)
	}

	c.lock.Unlock()
	return sli
}

func (c *crontab) run() {
	// initialize
	go func() {
		globalStore.Update(func(s *store.Store) {
			for _, v := range s.TaskList {
				if v.State != 0 {

					c.add(v)
				}
			}
		}).Sync()

	}()
	// global clock
	go func() {
		t := time.Tick(1 * time.Minute)
		for {
			now := <-t

			// broadcast
			c.lock.Lock()
			for _, v := range c.handleMap {
				v.clockChan <- now
			}
			c.lock.Unlock()
		}
	}()

	// add task
	go func() {
		for {
			select {
			case task := <-c.taskChan:
				ctx, cancel := context.WithCancel(context.Background())
				task.State = 1
				c.lock.Lock()
				c.handleMap[task.Id] = &handle{
					cancel:    cancel,
					clockChan: make(chan time.Time),
				}
				c.lock.Unlock()

				go c.deal(task, ctx)
			}
		}
	}()
	// remove task
	go func() {
		for {
			select {
			case task := <-c.delTaskChan:
				c.lock.Lock()
				if handle, ok := c.handleMap[task.Id]; ok {
					handle.cancel()
				}
				c.lock.Unlock()
				task.State = 0
			}
		}
	}()

	// kill task
	go func() {
		for {
			select {
			case task := <-c.killTaskChan:
				c.lock.Lock()
				if handle, ok := c.handleMap[task.Id]; ok {
					if handle.cancelCmdArray != nil {
						for _, cancel := range handle.cancelCmdArray {
							cancel()
						}
						handle.cancelCmdArray = make([]context.CancelFunc, 0)
						c.lock.Unlock()
						task.State = 1
						globalStore.Sync()
					} else {
						c.lock.Unlock()
					}
				} else {
					c.lock.Unlock()
				}
			}
		}
	}()

}

func (c *crontab) deal(task *proto.TaskArgs, ctx context.Context) {
	var wgroup sync.WaitGroup
	for {
		c.lock.Lock()
		h := c.handleMap[task.Id]
		c.lock.Unlock()
		select {
		case now := <-h.clockChan:
			wgroup.Add(1)
			go func() {
				defer func() {
					libs.MRecover()
					wgroup.Done()
				}()

				check := task.C
				if checkMonth(check, now.Month()) &&
					checkWeekday(check, now.Weekday()) &&
					checkDay(check, now.Day()) &&
					checkHour(check, now.Hour()) &&
					checkMinute(check, now.Minute()) {

					var content []byte
					var hdl *handle

					now2 := time.Now()
					start := now2.UnixNano()
					args := strings.Split(task.Args, " ")
					task.LastExecTime = now2.Unix()
					flag := true
					task.State = 2
					ctx, cancel := context.WithCancel(context.Background())

					c.lock.Lock()
					hdl = c.handleMap[task.Id]
					if len(hdl.cancelCmdArray) >= task.MaxConcurrent {
						hdl.cancelCmdArray[0]()
						hdl.cancelCmdArray = hdl.cancelCmdArray[1:]
					}
					hdl.cancelCmdArray = append(hdl.cancelCmdArray, cancel)

					c.lock.Unlock()

					if task.Timeout != 0 {
						time.AfterFunc(time.Duration(task.Timeout)*time.Second, func() {
							if flag {
								switch task.OpTimeout {
								case "email":
									sendMail(task.MailTo, globalConfig.addr+"提醒脚本执行超时", fmt.Sprintf(
										"任务名：%s\n详情：%s %v\n开始时间：%s\n超时：%ds",
										task.Name, task.Command, task.Args, now2.Format("2006-01-02 15:04:05"), task.Timeout))
								case "kill":
									cancel()

								case "email_and_kill":
									cancel()
									sendMail(task.MailTo, globalConfig.addr+"提醒脚本执行超时", fmt.Sprintf(
										"任务名：%s\n详情：%s %v\n开始时间：%s\n超时：%ds",
										task.Name, task.Command, task.Args, now2.Format("2006-01-02 15:04:05"), task.Timeout))
								case "ignore":
								default:
								}
							}

						})
					}
					atomic.AddInt32(&task.NumberProcess, 1)
					err := execScript(ctx, fmt.Sprintf("%s-%s.log", task.Name, task.Id), task.Command, globalConfig.logPath, &content, args...)
					flag = false
					task.LastCostTime = time.Now().UnixNano() - start

					atomic.AddInt32(&task.NumberProcess, -1)
					if task.NumberProcess == 0 {
						task.State = 1
					} else {
						task.State = 2
					}
					globalStore.Sync()

					log.Printf("%s:%s %v %s %.3fs %v", task.Name, task.Command, task.Args, task.OpTimeout, float64(task.LastCostTime)/1000000000, err)

				}
			}()
		case <-ctx.Done():
			// 等待所有的计划任务执行完毕
			wgroup.Wait()
			task.State = 0
			c.lock.Lock()
			close(c.handleMap[task.Id].clockChan)
			delete(c.handleMap, task.Id)
			c.lock.Unlock()
			globalStore.Sync()
			return
		}

	}

}
<commit_msg>fix quick start<commit_after>package main

import (
	"context"
	"fmt"
	"jiacrontab/client/store"
	"jiacrontab/libs"
	"jiacrontab/libs/proto"
	"log"
	"strings"
	"sync"
	"sync/atomic"
	"time"
)

func newCrontab(taskChanSize int) *crontab {
	return &crontab{
		taskChan:     make(chan *proto.TaskArgs, taskChanSize),
		delTaskChan:  make(chan *proto.TaskArgs, taskChanSize),
		killTaskChan: make(chan *proto.TaskArgs, taskChanSize),
		handleMap:    make(map[string]*handle),
	}
}

type handle struct {
	cancel         context.CancelFunc
	cancelCmdArray []context.CancelFunc
	clockChan      chan time.Time
	timeout        int64
}

type crontab struct {
	taskChan     chan *proto.TaskArgs
	delTaskChan  chan *proto.TaskArgs
	killTaskChan chan *proto.TaskArgs
	handleMap    map[string]*handle
	lock         sync.RWMutex
}

func (c *crontab) add(t *proto.TaskArgs) {
	c.taskChan <- t
	log.Printf("add task %+v", *t)
}

func (c *crontab) quickStart(t *proto.TaskArgs, content *[]byte) {
	start := time.Now().Unix()
	args := strings.Split(t.Args, " ")
	t.LastExecTime = start
	var timeout int64
	if t.Timeout == 0 {
		timeout = 60
	} else {
		timeout = t.Timeout
	}

	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second)
	err := execScript(ctx, fmt.Sprintf("%s-%s.log", t.Name, t.Id), t.Command, globalConfig.logPath, content, args...)
	cancel()

	if err != nil {
		*content = append(*content, []byte(err.Error())...)
	}

	t.LastCostTime = time.Now().Unix() - start
	globalStore.Sync()

	log.Printf("%s:  quic start end costTime %ds %v", t.Name, t.LastCostTime, err)

}

func (c *crontab) stop(t *proto.TaskArgs) {
	c.kill(t)
	c.delTaskChan <- t
	log.Println("stop", t.Name, t.Id)
}

func (c *crontab) kill(t *proto.TaskArgs) {
	c.killTaskChan <- t
	log.Println("kill", t.Name, t.Id)
}

func (c *crontab) delete(t *proto.TaskArgs) {
	globalStore.Update(func(s *store.Store) {
		delete(s.TaskList, t.Id)
	})
	c.kill(t)
	c.delTaskChan <- t
	log.Println("delete", t.Name, t.Id)
}

func (c *crontab) ids() []string {
	var sli []string
	c.lock.Lock()
	for k, _ := range c.handleMap {
		sli = append(sli, k)
	}

	c.lock.Unlock()
	return sli
}

func (c *crontab) run() {
	// initialize
	go func() {
		globalStore.Update(func(s *store.Store) {
			for _, v := range s.TaskList {
				if v.State != 0 {

					c.add(v)
				}
			}
		}).Sync()

	}()
	// global clock
	go func() {
		t := time.Tick(1 * time.Minute)
		for {
			now := <-t

			// broadcast
			c.lock.Lock()
			for _, v := range c.handleMap {
				v.clockChan <- now
			}
			c.lock.Unlock()
		}
	}()

	// add task
	go func() {
		for {
			select {
			case task := <-c.taskChan:
				ctx, cancel := context.WithCancel(context.Background())
				task.State = 1
				c.lock.Lock()
				c.handleMap[task.Id] = &handle{
					cancel:    cancel,
					clockChan: make(chan time.Time),
				}
				c.lock.Unlock()

				go c.deal(task, ctx)
			}
		}
	}()
	// remove task
	go func() {
		for {
			select {
			case task := <-c.delTaskChan:
				c.lock.Lock()
				if handle, ok := c.handleMap[task.Id]; ok {
					handle.cancel()
				}
				c.lock.Unlock()
				task.State = 0
			}
		}
	}()

	// kill task
	go func() {
		for {
			select {
			case task := <-c.killTaskChan:
				c.lock.Lock()
				if handle, ok := c.handleMap[task.Id]; ok {
					if handle.cancelCmdArray != nil {
						for _, cancel := range handle.cancelCmdArray {
							cancel()
						}
						handle.cancelCmdArray = make([]context.CancelFunc, 0)
						c.lock.Unlock()
						task.State = 1
						globalStore.Sync()
					} else {
						c.lock.Unlock()
					}
				} else {
					c.lock.Unlock()
				}
			}
		}
	}()

}

func (c *crontab) deal(task *proto.TaskArgs, ctx context.Context) {
	var wgroup sync.WaitGroup
	for {
		c.lock.Lock()
		h := c.handleMap[task.Id]
		c.lock.Unlock()
		select {
		case now := <-h.clockChan:
			wgroup.Add(1)
			go func() {
				defer func() {
					libs.MRecover()
					wgroup.Done()
				}()

				check := task.C
				if checkMonth(check, now.Month()) &&
					checkWeekday(check, now.Weekday()) &&
					checkDay(check, now.Day()) &&
					checkHour(check, now.Hour()) &&
					checkMinute(check, now.Minute()) {

					var content []byte
					var hdl *handle

					now2 := time.Now()
					start := now2.UnixNano()
					args := strings.Split(task.Args, " ")
					task.LastExecTime = now2.Unix()
					flag := true
					task.State = 2
					ctx, cancel := context.WithCancel(context.Background())

					c.lock.Lock()
					hdl = c.handleMap[task.Id]
					if len(hdl.cancelCmdArray) >= task.MaxConcurrent {
						hdl.cancelCmdArray[0]()
						hdl.cancelCmdArray = hdl.cancelCmdArray[1:]
					}
					hdl.cancelCmdArray = append(hdl.cancelCmdArray, cancel)

					c.lock.Unlock()

					if task.Timeout != 0 {
						time.AfterFunc(time.Duration(task.Timeout)*time.Second, func() {
							if flag {
								switch task.OpTimeout {
								case "email":
									sendMail(task.MailTo, globalConfig.addr+"提醒脚本执行超时", fmt.Sprintf(
										"任务名：%s\n详情：%s %v\n开始时间：%s\n超时：%ds",
										task.Name, task.Command, task.Args, now2.Format("2006-01-02 15:04:05"), task.Timeout))
								case "kill":
									cancel()

								case "email_and_kill":
									cancel()
									sendMail(task.MailTo, globalConfig.addr+"提醒脚本执行超时", fmt.Sprintf(
										"任务名：%s\n详情：%s %v\n开始时间：%s\n超时：%ds",
										task.Name, task.Command, task.Args, now2.Format("2006-01-02 15:04:05"), task.Timeout))
								case "ignore":
								default:
								}
							}

						})
					}
					atomic.AddInt32(&task.NumberProcess, 1)
					err := execScript(ctx, fmt.Sprintf("%s-%s.log", task.Name, task.Id), task.Command, globalConfig.logPath, &content, args...)
					flag = false
					task.LastCostTime = time.Now().UnixNano() - start

					atomic.AddInt32(&task.NumberProcess, -1)
					if task.NumberProcess == 0 {
						task.State = 1
					} else {
						task.State = 2
					}
					globalStore.Sync()

					log.Printf("%s:%s %v %s %.3fs %v", task.Name, task.Command, task.Args, task.OpTimeout, float64(task.LastCostTime)/1000000000, err)

				}
			}()
		case <-ctx.Done():
			// 等待所有的计划任务执行完毕
			wgroup.Wait()
			task.State = 0
			c.lock.Lock()
			close(c.handleMap[task.Id].clockChan)
			delete(c.handleMap, task.Id)
			c.lock.Unlock()
			globalStore.Sync()
			return
		}

	}

}
<|endoftext|>


<commit_before>package templates

import (
	"bytes"
	"net/http"
	"testing"
)

// testWriter implements the net/http ResponseWriter interface
// Write is implemented by the embedded bytes.Buffer
type testWriter struct {
	*bytes.Buffer
}

// Header returns a new header everytime
func (tw *testWriter) Header() http.Header {
	return http.Header{}
}

// WriteHeader does nothing with the code
func (tw *testWriter) WriteHeader(code int) {}

func newTestWriter() *testWriter {
	var b bytes.Buffer
	return &testWriter{&b}
}

// Check that testWriter implements the http.ResponseWriter
var _ http.ResponseWriter = newTestWriter()

func TestEmpty(t *testing.T) {
	empty := Empty()
	if err := empty.Add("{{fsfd"); err == nil {
		t.Errorf("templates: Add failed to error when given a bad template")
	}
	if err := empty.Add(`{{ define "whatever" }}{{ .Whatever }}{{ end }}`); err != nil {
		t.Errorf("templates: Add returned an error when given a proper template")
	}
}

func TestTemplates(t *testing.T) {
	// Parse the test_fixtures directory with a local variable
	parsed := New("./test_fixtures/pass", Attrs{"Greeting": "Yo"})

	// Overwrite a local variable
	if err := parsed.SetAttr("Greeting", "Hello"); err == nil {
		t.Errorf("failed to warn of overwritten local attributes")
	}

	// Create a testWriter for testing output
	w := newTestWriter()

	// Render the template with an additional Name attribute
	parsed.Execute(w, "parent", Attrs{"Name": "Lebowski"})

	// Test the output versus expected. If you've modified the test_fixtures
	// templates watch out for newlines - they matter!
	expected := `Parent is named Lebowski
Child says Hello`
	if w.String() != expected {
		t.Errorf("unexpected template execution output: %s", w.String())
	}

	// Test alternate delims
	parsed = NewWithDelims(
		"./test_fixtures/delims",
		`<%`,
		`%>`,
		Attrs{"Greeting": "Yo"},
	)
	w = newTestWriter()
	parsed.Execute(w, "delims")
	expected = `The template says Yo`
	if w.String() != expected {
		t.Errorf("unexpected delim template execution output: %s", w.String())
	}

	// Call a template that doesn't exist
	// Execute the test in an anon block (in case we want more defers)
	func() {
		var panicked interface{}
		defer func() {
			panicked = recover()
		}()
		w = newTestWriter()
		parsed.Execute(w, "dne")
		if panicked == nil {
			t.Fatalf("failed to panic when given a name that does not exist")
		}
	}()

	// Cause an error in filepath.Walk by providing a dir that does not exist
	func() {
		var panicked interface{}
		defer func() {
			panicked = recover()
		}()
		New("./test_fixtures/dne")
		if panicked == nil {
			t.Fatalf("failed to panic when given a dir that does not exist")
		}
	}()

	// Parse a bad template
	func() {
		var panicked interface{}
		defer func() {
			panicked = recover()
		}()
		New("./test_fixtures/fail")
		if panicked == nil {
			t.Fatalf("failed to panic when a bad template is given")
		}
	}()
}
<commit_msg>The added template should be available through Execute<commit_after>package templates

import (
	"bytes"
	"net/http"
	"testing"
)

// testWriter implements the net/http ResponseWriter interface
// Write is implemented by the embedded bytes.Buffer
type testWriter struct {
	*bytes.Buffer
}

// Header returns a new header everytime
func (tw *testWriter) Header() http.Header {
	return http.Header{}
}

// WriteHeader does nothing with the code
func (tw *testWriter) WriteHeader(code int) {}

func newTestWriter() *testWriter {
	var b bytes.Buffer
	return &testWriter{&b}
}

// Check that testWriter implements the http.ResponseWriter
var _ http.ResponseWriter = newTestWriter()

func TestEmpty(t *testing.T) {
	empty := Empty()
	if err := empty.Add("{{fsfd"); err == nil {
		t.Errorf("templates: Add failed to error when given a bad template")
	}
	if err := empty.Add(`{{ define "whatever" }}{{ .Whatever }}{{ end }}`); err != nil {
		t.Errorf("templates: Add returned an error when given a proper template")
	}

	// The whatever template should be added to the templates
	var b []byte
	buffer := bytes.NewBuffer(b)
	empty.Execute(buffer, "whatever")
}

func TestTemplates(t *testing.T) {
	// Parse the test_fixtures directory with a local variable
	parsed := New("./test_fixtures/pass", Attrs{"Greeting": "Yo"})

	// Overwrite a local variable
	if err := parsed.SetAttr("Greeting", "Hello"); err == nil {
		t.Errorf("failed to warn of overwritten local attributes")
	}

	// Create a testWriter for testing output
	w := newTestWriter()

	// Render the template with an additional Name attribute
	parsed.Execute(w, "parent", Attrs{"Name": "Lebowski"})

	// Test the output versus expected. If you've modified the test_fixtures
	// templates watch out for newlines - they matter!
	expected := `Parent is named Lebowski
Child says Hello`
	if w.String() != expected {
		t.Errorf("unexpected template execution output: %s", w.String())
	}

	// Test alternate delims
	parsed = NewWithDelims(
		"./test_fixtures/delims",
		`<%`,
		`%>`,
		Attrs{"Greeting": "Yo"},
	)
	w = newTestWriter()
	parsed.Execute(w, "delims")
	expected = `The template says Yo`
	if w.String() != expected {
		t.Errorf("unexpected delim template execution output: %s", w.String())
	}

	// Call a template that doesn't exist
	// Execute the test in an anon block (in case we want more defers)
	func() {
		var panicked interface{}
		defer func() {
			panicked = recover()
		}()
		w = newTestWriter()
		parsed.Execute(w, "dne")
		if panicked == nil {
			t.Fatalf("failed to panic when given a name that does not exist")
		}
	}()

	// Cause an error in filepath.Walk by providing a dir that does not exist
	func() {
		var panicked interface{}
		defer func() {
			panicked = recover()
		}()
		New("./test_fixtures/dne")
		if panicked == nil {
			t.Fatalf("failed to panic when given a dir that does not exist")
		}
	}()

	// Parse a bad template
	func() {
		var panicked interface{}
		defer func() {
			panicked = recover()
		}()
		New("./test_fixtures/fail")
		if panicked == nil {
			t.Fatalf("failed to panic when a bad template is given")
		}
	}()
}
<|endoftext|>


<commit_before>package kiwi

/*
Copyright (c) 2016-2018, Alexander I.Grafov <grafov@gmail.com>
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 kvlog 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 HOLDER 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.

ॐ तारे तुत्तारे तुरे स्व

All tests consists of three parts:

- arrange structures and initialize objects for use in tests
- act on testing object
- check and assert on results

These parts separated by empty lines in each test function.
*/

import (
	"bytes"
	"strings"
	"testing"
	"time"
)

// Test of non default value of FloatFormat global var.
// It should format the value accordingly with selected format ('f' in this test).
func TestConvertor_NonDefaultFloatFormatPass_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	original := FloatFormat
	FloatFormat = 'f'
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("key", 3.14159265)

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `key=3.14159265` {
		println(output.String())
		t.Fail()
	}
	FloatFormat = original
}

// Test of non default value of TimeLayout global var.
// It should format the value accordingly with selected format.
func TestConvertor_NonDefaultTimeLayoutPass_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	original := TimeLayout
	TimeLayout = time.RFC822
	now := time.Now()
	nowString := now.Format(time.RFC822)
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("key", now)

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `key=`+nowString {
		println(output.String())
		t.Fail()
	}
	TimeLayout = original
}

func TestConvertor_LogByteType_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("the key", []byte("the sample byte sequence..."))

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `"the key"="the sample byte sequence..."` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogBoolType_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("true", false)

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `true=false` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogInt8Type_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("1", int8(2))

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `1=2` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogInt16Type_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("1", int16(2))

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `1=2` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogInt32Type_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("1", int32(2))

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `1=2` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogIntType_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("1", 2)

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `1=2` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogInt64Type_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("1", int64(2))

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `1=2` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogUint8Type_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("1", uint8(2))

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `1=2` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogUint16Type_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("1", uint16(2))

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `1=2` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogUint32Type_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("1", uint32(2))

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `1=2` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogUintType_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("1", uint(2))

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `1=2` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogUint64Type_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("1", uint64(2))

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `1=2` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogFloat32Type_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("pi", float32(3.14159265))

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `pi=3.1415927e+00` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogFloat64Type_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("pi", 3.14159265359)

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `pi=3.14159265359e+00` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogNil(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("key", nil)

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `key="<nil>"` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogEmpty(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("empty")

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `empty="<nil>"` {
		println(output.String())
		t.Fail()
	}
}
<commit_msg>Fix test accordingly with API change<commit_after>package kiwi

/*
Copyright (c) 2016-2018, Alexander I.Grafov <grafov@gmail.com>
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 kvlog 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 HOLDER 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.

ॐ तारे तुत्तारे तुरे स्व

All tests consists of three parts:

- arrange structures and initialize objects for use in tests
- act on testing object
- check and assert on results

These parts separated by empty lines in each test function.
*/

import (
	"bytes"
	"strings"
	"testing"
	"time"
)

// Test of non default value of FloatFormat global var.
// It should format the value accordingly with selected format ('f' in this test).
func TestConvertor_NonDefaultFloatFormatPass_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	original := FloatFormat
	FloatFormat = 'f'
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("key", 3.14159265)

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `key=3.14159265` {
		println(output.String())
		t.Fail()
	}
	FloatFormat = original
}

// Test of non default value of TimeLayout global var.
// It should format the value accordingly with selected format.
func TestConvertor_NonDefaultTimeLayoutPass_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	original := TimeLayout
	TimeLayout = time.RFC822
	now := time.Now()
	nowString := now.Format(time.RFC822)
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("key", now)

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `key=`+nowString {
		println(output.String())
		t.Fail()
	}
	TimeLayout = original
}

func TestConvertor_LogByteType_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("the key", []byte("the sample byte sequence..."))

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `"the key"="the sample byte sequence..."` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogBoolType_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("true", false)

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `true=false` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogInt8Type_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("1", int8(2))

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `1=2` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogInt16Type_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("1", int16(2))

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `1=2` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogInt32Type_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("1", int32(2))

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `1=2` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogIntType_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("1", 2)

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `1=2` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogInt64Type_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("1", int64(2))

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `1=2` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogUint8Type_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("1", uint8(2))

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `1=2` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogUint16Type_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("1", uint16(2))

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `1=2` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogUint32Type_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("1", uint32(2))

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `1=2` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogUintType_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("1", uint(2))

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `1=2` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogUint64Type_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("1", uint64(2))

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `1=2` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogFloat32Type_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("pi", float32(3.14159265))

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `pi=3.1415927e+00` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogFloat64Type_Logfmt(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("pi", 3.14159265359)

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `pi=3.14159265359e+00` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogNil(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("key", nil)

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `key="<nil>"` {
		println(output.String())
		t.Fail()
	}
}

func TestConvertor_LogValueWithoutKey(t *testing.T) {
	output := bytes.NewBufferString("")
	log := New()
	out := SinkTo(output, UseLogfmt()).Start()

	log.Log("just a single value")

	out.Flush().Close()
	if strings.TrimSpace(output.String()) != `message="just a single value"` {
		println(output.String())
		t.Fail()
	}
}
<|endoftext|>