<commit_before>package commands

import (
	"fmt"

	cmds "github.com/jbenet/go-ipfs/commands"
	"github.com/jbenet/go-ipfs/core"
	"github.com/jbenet/go-ipfs/merkledag"
	u "github.com/jbenet/go-ipfs/util"
)

var pinCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Pin (and unpin) objects to local storage",
	},

	Subcommands: map[string]*cmds.Command{
		"add": addPinCmd,
		"rm":  rmPinCmd,
		"ls":  listPinCmd,
	},
}

var addPinCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Pins objects to local storage",
		ShortDescription: `
Retrieves the object named by <ipfs-path> and stores it locally
on disk.
`,
	},

	Arguments: []cmds.Argument{
		cmds.StringArg("ipfs-path", true, true, "Path to object(s) to be pinned"),
	},
	Options: []cmds.Option{
		cmds.BoolOption("recursive", "r", "Recursively pin the object linked to by the specified object(s)"),
	},
	Run: func(req cmds.Request) (interface{}, error) {
		n, err := req.Context().GetNode()
		if err != nil {
			return nil, err
		}

		// set recursive flag
		recursive, found, err := req.Option("recursive").Bool()
		if err != nil {
			return nil, err
		}
		if !found {
			recursive = false
		}

		_, err = pin(n, req.Arguments(), recursive)
		if err != nil {
			return nil, err
		}

		// TODO: create some output to show what got pinned
		return nil, nil
	},
}

var rmPinCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Unpin an object from local storage",
		ShortDescription: `
Removes the pin from the given object allowing it to be garbage
collected if needed.
`,
	},

	Arguments: []cmds.Argument{
		cmds.StringArg("ipfs-path", true, true, "Path to object(s) to be unpinned"),
	},
	Options: []cmds.Option{
		cmds.BoolOption("recursive", "r", "Recursively unpin the object linked to by the specified object(s)"),
	},
	Run: func(req cmds.Request) (interface{}, error) {
		n, err := req.Context().GetNode()
		if err != nil {
			return nil, err
		}

		// set recursive flag
		recursive, found, err := req.Option("recursive").Bool()
		if err != nil {
			return nil, err
		}
		if !found {
			recursive = false // default
		}

		_, err = unpin(n, req.Arguments(), recursive)
		if err != nil {
			return nil, err
		}

		// TODO: create some output to show what got unpinned
		return nil, nil
	},
}

var listPinCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "List objects pinned to local storage",
		ShortDescription: `
Returns a list of hashes of objects being pinned. Objects that are indirectly
or recursively pinned are not included in the list.
`,
		LongDescription: `
Returns a list of hashes of objects being pinned. Objects that are indirectly
or recursively pinned are not included in the list.

Use --type=<type> to specify the type of pinned keys to list. Valid values are:
    * "direct"
    * "indirect"
    * "recursive"
    * "all"
(Defaults to "direct")
`,
	},

	Options: []cmds.Option{
		cmds.StringOption("type", "t", "The type of pinned keys to list. Can be \"direct\", \"indirect\", \"recursive\", or \"all\". Defaults to \"direct\""),
	},
	Run: func(req cmds.Request) (interface{}, error) {
		n, err := req.Context().GetNode()
		if err != nil {
			return nil, err
		}

		typeStr, found, err := req.Option("type").String()
		if err != nil {
			return nil, err
		}
		if !found {
			typeStr = "direct"
		}

		if typeStr != "all" && typeStr != "direct" && typeStr != "indirect" && typeStr != "recursive" {
			return nil, cmds.ClientError("Invalid type '" + typeStr + "', must be \"direct\", \"indirect\", \"recursive\", or \"all\"")
		}

		keys := make([]u.Key, 0)
		if typeStr == "direct" || typeStr == "all" {
			keys = append(keys, n.Pinning.DirectKeys()...)
		}
		if typeStr == "indirect" || typeStr == "all" {
			keys = append(keys, n.Pinning.IndirectKeys()...)
		}
		if typeStr == "recursive" || typeStr == "all" {
			keys = append(keys, n.Pinning.RecursiveKeys()...)
		}

		return &KeyList{Keys: keys}, nil
	},
	Type: &KeyList{},
	Marshalers: cmds.MarshalerMap{
		cmds.Text: KeyListTextMarshaler,
	},
}

func pin(n *core.IpfsNode, paths []string, recursive bool) ([]*merkledag.Node, error) {

	dagnodes := make([]*merkledag.Node, 0)
	for _, path := range paths {
		dagnode, err := n.Resolver.ResolvePath(path)
		if err != nil {
			return nil, fmt.Errorf("pin error: %v", err)
		}
		dagnodes = append(dagnodes, dagnode)
	}

	for _, dagnode := range dagnodes {
		err := n.Pinning.Pin(dagnode, recursive)
		if err != nil {
			return nil, fmt.Errorf("pin: %v", err)
		}
	}

	err := n.Pinning.Flush()
	if err != nil {
		return nil, err
	}

	return dagnodes, nil
}

func unpin(n *core.IpfsNode, paths []string, recursive bool) ([]*merkledag.Node, error) {

	dagnodes := make([]*merkledag.Node, 0)
	for _, path := range paths {
		dagnode, err := n.Resolver.ResolvePath(path)
		if err != nil {
			return nil, err
		}
		dagnodes = append(dagnodes, dagnode)
	}

	for _, dagnode := range dagnodes {
		k, _ := dagnode.Key()
		err := n.Pinning.Unpin(k, recursive)
		if err != nil {
			return nil, err
		}
	}

	err := n.Pinning.Flush()
	if err != nil {
		return nil, err
	}
	return dagnodes, nil
}
<commit_msg>core/commands: Better syntax for 'pin ls' option value handling<commit_after>package commands

import (
	"fmt"

	cmds "github.com/jbenet/go-ipfs/commands"
	"github.com/jbenet/go-ipfs/core"
	"github.com/jbenet/go-ipfs/merkledag"
	u "github.com/jbenet/go-ipfs/util"
)

var pinCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Pin (and unpin) objects to local storage",
	},

	Subcommands: map[string]*cmds.Command{
		"add": addPinCmd,
		"rm":  rmPinCmd,
		"ls":  listPinCmd,
	},
}

var addPinCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Pins objects to local storage",
		ShortDescription: `
Retrieves the object named by <ipfs-path> and stores it locally
on disk.
`,
	},

	Arguments: []cmds.Argument{
		cmds.StringArg("ipfs-path", true, true, "Path to object(s) to be pinned"),
	},
	Options: []cmds.Option{
		cmds.BoolOption("recursive", "r", "Recursively pin the object linked to by the specified object(s)"),
	},
	Run: func(req cmds.Request) (interface{}, error) {
		n, err := req.Context().GetNode()
		if err != nil {
			return nil, err
		}

		// set recursive flag
		recursive, found, err := req.Option("recursive").Bool()
		if err != nil {
			return nil, err
		}
		if !found {
			recursive = false
		}

		_, err = pin(n, req.Arguments(), recursive)
		if err != nil {
			return nil, err
		}

		// TODO: create some output to show what got pinned
		return nil, nil
	},
}

var rmPinCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Unpin an object from local storage",
		ShortDescription: `
Removes the pin from the given object allowing it to be garbage
collected if needed.
`,
	},

	Arguments: []cmds.Argument{
		cmds.StringArg("ipfs-path", true, true, "Path to object(s) to be unpinned"),
	},
	Options: []cmds.Option{
		cmds.BoolOption("recursive", "r", "Recursively unpin the object linked to by the specified object(s)"),
	},
	Run: func(req cmds.Request) (interface{}, error) {
		n, err := req.Context().GetNode()
		if err != nil {
			return nil, err
		}

		// set recursive flag
		recursive, found, err := req.Option("recursive").Bool()
		if err != nil {
			return nil, err
		}
		if !found {
			recursive = false // default
		}

		_, err = unpin(n, req.Arguments(), recursive)
		if err != nil {
			return nil, err
		}

		// TODO: create some output to show what got unpinned
		return nil, nil
	},
}

var listPinCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "List objects pinned to local storage",
		ShortDescription: `
Returns a list of hashes of objects being pinned. Objects that are indirectly
or recursively pinned are not included in the list.
`,
		LongDescription: `
Returns a list of hashes of objects being pinned. Objects that are indirectly
or recursively pinned are not included in the list.

Use --type=<type> to specify the type of pinned keys to list. Valid values are:
    * "direct"
    * "indirect"
    * "recursive"
    * "all"
(Defaults to "direct")
`,
	},

	Options: []cmds.Option{
		cmds.StringOption("type", "t", "The type of pinned keys to list. Can be \"direct\", \"indirect\", \"recursive\", or \"all\". Defaults to \"direct\""),
	},
	Run: func(req cmds.Request) (interface{}, error) {
		n, err := req.Context().GetNode()
		if err != nil {
			return nil, err
		}

		typeStr, found, err := req.Option("type").String()
		if err != nil {
			return nil, err
		}
		if !found {
			typeStr = "direct"
		}

		switch typeStr {
		case "all", "direct", "indirect", "recursive":
		default:
			return nil, cmds.ClientError("Invalid type '" + typeStr + "', must be one of {direct, indirect, recursive, all}")
		}

		keys := make([]u.Key, 0)
		if typeStr == "direct" || typeStr == "all" {
			keys = append(keys, n.Pinning.DirectKeys()...)
		}
		if typeStr == "indirect" || typeStr == "all" {
			keys = append(keys, n.Pinning.IndirectKeys()...)
		}
		if typeStr == "recursive" || typeStr == "all" {
			keys = append(keys, n.Pinning.RecursiveKeys()...)
		}

		return &KeyList{Keys: keys}, nil
	},
	Type: &KeyList{},
	Marshalers: cmds.MarshalerMap{
		cmds.Text: KeyListTextMarshaler,
	},
}

func pin(n *core.IpfsNode, paths []string, recursive bool) ([]*merkledag.Node, error) {

	dagnodes := make([]*merkledag.Node, 0)
	for _, path := range paths {
		dagnode, err := n.Resolver.ResolvePath(path)
		if err != nil {
			return nil, fmt.Errorf("pin error: %v", err)
		}
		dagnodes = append(dagnodes, dagnode)
	}

	for _, dagnode := range dagnodes {
		err := n.Pinning.Pin(dagnode, recursive)
		if err != nil {
			return nil, fmt.Errorf("pin: %v", err)
		}
	}

	err := n.Pinning.Flush()
	if err != nil {
		return nil, err
	}

	return dagnodes, nil
}

func unpin(n *core.IpfsNode, paths []string, recursive bool) ([]*merkledag.Node, error) {

	dagnodes := make([]*merkledag.Node, 0)
	for _, path := range paths {
		dagnode, err := n.Resolver.ResolvePath(path)
		if err != nil {
			return nil, err
		}
		dagnodes = append(dagnodes, dagnode)
	}

	for _, dagnode := range dagnodes {
		k, _ := dagnode.Key()
		err := n.Pinning.Unpin(k, recursive)
		if err != nil {
			return nil, err
		}
	}

	err := n.Pinning.Flush()
	if err != nil {
		return nil, err
	}
	return dagnodes, nil
}
<|endoftext|>


<commit_before>package ledger

import (
	. "github.com/DNAProject/DNA/common"
	"github.com/DNAProject/DNA/common/serialization"
	"github.com/DNAProject/DNA/core/contract/program"
	tx "github.com/DNAProject/DNA/core/transaction"
	"github.com/DNAProject/DNA/crypto"
	. "github.com/DNAProject/DNA/errors"
	"io"
	"time"
	"github.com/DNAProject/DNA/vm"
	"github.com/DNAProject/DNA/common/log"
)

type Block struct {
	Blockdata    *Blockdata
	Transcations []*tx.Transaction

	hash *Uint256
}

func (b *Block) Serialize(w io.Writer) error {
	b.Blockdata.Serialize(w)
	err := serialization.WriteUint8(w, uint8(len(b.Transcations)))
	if err != nil {
		return NewDetailErr(err, ErrNoCode, "Block item Transcations length serialization failed.")
	}
	for _, transaction := range b.Transcations {
		temp := *transaction
		hash := temp.Hash()
		hash.Serialize(w)
	}
	return nil
}

func (b *Block) Deserialize(r io.Reader) error {
	if b.Blockdata == nil {
		b.Blockdata = new(Blockdata)
	}
	b.Blockdata.Deserialize(r)

	//Transactions
	var i uint8
	Len, err := serialization.ReadUint8(r)
	if err != nil {
		return err
	}
	var txhash Uint256
	var tharray []Uint256
	for i = 0; i < Len; i++ {
		txhash.Deserialize(r)
		transaction := new(tx.Transaction)
		transaction.SetHash(txhash)
		b.Transcations = append(b.Transcations, transaction)
		tharray = append(tharray, txhash)
	}

	b.Blockdata.TransactionsRoot, err = crypto.ComputeRoot(tharray)
	if err != nil {
		return NewDetailErr(err, ErrNoCode, "Block Deserialize merkleTree compute failed")
	}

	return nil
}

func (b *Block) GetMessage() []byte {
	return  sig.GetHashForSigning(b)
}

func (b *Block) GetProgramHashes() ([]Uint160, error) {

	return b.Blockdata.GetProgramHashes()
}

func (b *Block) SetPrograms(prog []*program.Program) {
	b.Blockdata.SetPrograms(prog)
	return
}

func (b *Block) GetPrograms() []*program.Program {
	return b.Blockdata.GetPrograms()
}

func (b *Block) Hash() Uint256 {
	if b.hash == nil {
		b.hash = new(Uint256)
		*b.hash = b.Blockdata.Hash()
	}
	return *b.hash
}

func (b *Block) Verify() error {
	log.Info("This function is expired.please use Validation/blockValidator to Verify Block.")
	return nil
}

func (b *Block) Type() InventoryType {
	return BLOCK
}

func GenesisBlockInit(miners []*crypto.PubKey) (*Block,error){
	genesisBlock := new(Block)
	//blockdata
	genesisBlockdata := new(Blockdata)
	genesisBlockdata.Version = uint32(0x00)
	genesisBlockdata.PrevBlockHash = Uint256{}
	genesisBlockdata.TransactionsRoot = Uint256{}
	tm:=time.Date(2017, time.February, 23, 0, 0, 0, 0, time.UTC)
	genesisBlockdata.Timestamp = uint32(tm.Unix())
	genesisBlockdata.Height = uint32(0)
	genesisBlockdata.ConsensusData = uint64(2083236893)
	nextMiner, err := GetMinerAddress(miners)
	if err != nil{
		return nil,NewDetailErr(err, ErrNoCode, "[Block],GenesisBlockInit err with GetMinerAddress")
	}
	genesisBlockdata.NextMiner = nextMiner

	pg := new(program.Program)
	pg.Code = []byte{'0'}
	pg.Parameter = []byte{byte(vm.OP_TRUE)}
	genesisBlockdata.Program = pg

	//transaction
	trans := new(tx.Transaction)
	{
		trans.TxType = tx.BookKeeping
		trans.PayloadVersion = byte(0)
		trans.Payload = nil
		trans.Nonce = uint64(0)
		trans.Attributes = nil
		trans.UTXOInputs = nil
		trans.BalanceInputs = nil
		trans.Outputs = nil
		{
			programHashes := []*program.Program{}
			pg := new(program.Program)
			pg.Code = []byte{'0'}
			pg.Parameter = []byte{byte(vm.OP_TRUE)}
			programHashes = append(programHashes, pg)
			trans.Programs = programHashes
		}
	}
	genesisBlock.Blockdata = genesisBlockdata

	genesisBlock.Transcations = append(genesisBlock.Transcations,trans)

	//hashx := genesisBlock.Hash()

	return genesisBlock,nil
}

func CreateGenesisBlock(miners []*crypto.PubKey) error {
	genesisBlock, err := GenesisBlockInit(miners)
	if err != nil {
		log.Error("Init Genesis Block Error")
		return err
	}
	err = genesisBlock.RebuildMerkleRoot()
	if err != nil {
		return err
	}
	hashx := genesisBlock.Hash()
	genesisBlock.hash = &hashx
	DefaultLedger.Store.InitLevelDBStoreWithGenesisBlock(genesisBlock)
	if err != nil {
		return err
	}
	return nil
}

func (b *Block)RebuildMerkleRoot()(error){
	txs := b.Transcations
	transactionHashes := []Uint256{}
	for _, tx :=  range txs{
		transactionHashes = append(transactionHashes,tx.Hash())
	}
	hash,err := crypto.ComputeRoot(transactionHashes)
	if err!=nil{
		return NewDetailErr(err, ErrNoCode, "[Block] , RebuildMerkleRoot ComputeRoot failed.")
	}
	b.Blockdata.TransactionsRoot =hash
	return nil

}

func (bd *Block) SerializeUnsigned(w io.Writer) error {
	/*
	* TODO Just Add for interface of signableDate.
	* 2017/2/27 luodanwg
	* */
	return nil
}
<commit_msg>Update block.go<commit_after>package ledger

import (
	. "github.com/DNAProject/DNA/common"
	"github.com/DNAProject/DNA/common/serialization"
	"github.com/DNAProject/DNA/core/contract/program"
	tx "github.com/DNAProject/DNA/core/transaction"
	sig "github.com/DNAProject/DNA/core/signature"
	"github.com/DNAProject/DNA/crypto"
	. "github.com/DNAProject/DNA/errors"
	"io"
	"time"
	"github.com/DNAProject/DNA/vm"
	"github.com/DNAProject/DNA/common/log"
)

type Block struct {
	Blockdata    *Blockdata
	Transcations []*tx.Transaction

	hash *Uint256
}

func (b *Block) Serialize(w io.Writer) error {
	b.Blockdata.Serialize(w)
	err := serialization.WriteUint8(w, uint8(len(b.Transcations)))
	if err != nil {
		return NewDetailErr(err, ErrNoCode, "Block item Transcations length serialization failed.")
	}
	for _, transaction := range b.Transcations {
		temp := *transaction
		hash := temp.Hash()
		hash.Serialize(w)
	}
	return nil
}

func (b *Block) Deserialize(r io.Reader) error {
	if b.Blockdata == nil {
		b.Blockdata = new(Blockdata)
	}
	b.Blockdata.Deserialize(r)

	//Transactions
	var i uint8
	Len, err := serialization.ReadUint8(r)
	if err != nil {
		return err
	}
	var txhash Uint256
	var tharray []Uint256
	for i = 0; i < Len; i++ {
		txhash.Deserialize(r)
		transaction := new(tx.Transaction)
		transaction.SetHash(txhash)
		b.Transcations = append(b.Transcations, transaction)
		tharray = append(tharray, txhash)
	}

	b.Blockdata.TransactionsRoot, err = crypto.ComputeRoot(tharray)
	if err != nil {
		return NewDetailErr(err, ErrNoCode, "Block Deserialize merkleTree compute failed")
	}

	return nil
}

func (b *Block) GetMessage() []byte {
	return  sig.GetHashForSigning(b)
}

func (b *Block) GetProgramHashes() ([]Uint160, error) {

	return b.Blockdata.GetProgramHashes()
}

func (b *Block) SetPrograms(prog []*program.Program) {
	b.Blockdata.SetPrograms(prog)
	return
}

func (b *Block) GetPrograms() []*program.Program {
	return b.Blockdata.GetPrograms()
}

func (b *Block) Hash() Uint256 {
	if b.hash == nil {
		b.hash = new(Uint256)
		*b.hash = b.Blockdata.Hash()
	}
	return *b.hash
}

func (b *Block) Verify() error {
	log.Info("This function is expired.please use Validation/blockValidator to Verify Block.")
	return nil
}

func (b *Block) Type() InventoryType {
	return BLOCK
}

func GenesisBlockInit(miners []*crypto.PubKey) (*Block,error){
	genesisBlock := new(Block)
	//blockdata
	genesisBlockdata := new(Blockdata)
	genesisBlockdata.Version = uint32(0x00)
	genesisBlockdata.PrevBlockHash = Uint256{}
	genesisBlockdata.TransactionsRoot = Uint256{}
	tm:=time.Date(2017, time.February, 23, 0, 0, 0, 0, time.UTC)
	genesisBlockdata.Timestamp = uint32(tm.Unix())
	genesisBlockdata.Height = uint32(0)
	genesisBlockdata.ConsensusData = uint64(2083236893)
	nextMiner, err := GetMinerAddress(miners)
	if err != nil{
		return nil,NewDetailErr(err, ErrNoCode, "[Block],GenesisBlockInit err with GetMinerAddress")
	}
	genesisBlockdata.NextMiner = nextMiner

	pg := new(program.Program)
	pg.Code = []byte{'0'}
	pg.Parameter = []byte{byte(vm.OP_TRUE)}
	genesisBlockdata.Program = pg

	//transaction
	trans := new(tx.Transaction)
	{
		trans.TxType = tx.BookKeeping
		trans.PayloadVersion = byte(0)
		trans.Payload = nil
		trans.Nonce = uint64(0)
		trans.Attributes = nil
		trans.UTXOInputs = nil
		trans.BalanceInputs = nil
		trans.Outputs = nil
		{
			programHashes := []*program.Program{}
			pg := new(program.Program)
			pg.Code = []byte{'0'}
			pg.Parameter = []byte{byte(vm.OP_TRUE)}
			programHashes = append(programHashes, pg)
			trans.Programs = programHashes
		}
	}
	genesisBlock.Blockdata = genesisBlockdata

	genesisBlock.Transcations = append(genesisBlock.Transcations,trans)

	//hashx := genesisBlock.Hash()

	return genesisBlock,nil
}

func CreateGenesisBlock(miners []*crypto.PubKey) error {
	genesisBlock, err := GenesisBlockInit(miners)
	if err != nil {
		log.Error("Init Genesis Block Error")
		return err
	}
	err = genesisBlock.RebuildMerkleRoot()
	if err != nil {
		return err
	}
	hashx := genesisBlock.Hash()
	genesisBlock.hash = &hashx
	DefaultLedger.Store.InitLevelDBStoreWithGenesisBlock(genesisBlock)
	if err != nil {
		return err
	}
	return nil
}

func (b *Block)RebuildMerkleRoot()(error){
	txs := b.Transcations
	transactionHashes := []Uint256{}
	for _, tx :=  range txs{
		transactionHashes = append(transactionHashes,tx.Hash())
	}
	hash,err := crypto.ComputeRoot(transactionHashes)
	if err!=nil{
		return NewDetailErr(err, ErrNoCode, "[Block] , RebuildMerkleRoot ComputeRoot failed.")
	}
	b.Blockdata.TransactionsRoot =hash
	return nil

}

func (bd *Block) SerializeUnsigned(w io.Writer) error {
	/*
	* TODO Just Add for interface of signableDate.
	* 2017/2/27 luodanwg
	* */
	return nil
}
<|endoftext|>


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

package core

import (
	"testing"
	"time"

	"github.com/trivago/tgo/ttesting"
)

func getMockMessage(data string) *Message {
	msg := &Message{
		prevStreamID: 2,
		source:       nil,
		timestamp:    time.Now(),
		sequence:     4,
	}

	msg.data.payload = []byte(data)
	msg.data.streamID = 1

	return msg
}

func TestMessageEnqueue(t *testing.T) {
	expect := ttesting.NewExpect(t)
	msgString := "Test for Enqueue()"
	msg := getMockMessage(msgString)
	buffer := NewMessageQueue(0)

	expect.Equal(MessageStateDiscard, buffer.Push(msg, -1))

	go func() {
		expect.Equal(MessageStateOk, buffer.Push(msg, 0))
	}()

	retMsg, _ := buffer.Pop()
	expect.Equal(msgString, retMsg.String())

	retStatus := buffer.Push(msg, 10*time.Millisecond)
	expect.Equal(MessageStateTimeout, retStatus)

	go func() {
		expect.Equal(MessageStateOk, buffer.Push(msg, 1*time.Second))
	}()

	retMsg, _ = buffer.Pop()
	expect.Equal(msgString, retMsg.String())
}

func TestMessageInstantiate(t *testing.T) {
	expect := ttesting.NewExpect(t)
	msgString := "Test for instantiate"

	msg := NewMessage(nil, []byte(msgString), 1, 1)

	expect.Equal(msgString, string(msg.data.payload))
	expect.Equal(MessageStreamID(1), msg.data.streamID)
	expect.Equal(msgString, string(msg.orig.payload))
	expect.Equal(MessageStreamID(1), msg.orig.streamID)
}

func TestMessageOriginalDataIntegrity(t *testing.T) {
	expect := ttesting.NewExpect(t)
	msgString := "Test for original data integrity"
	msgUpdateString := "Test for original data integrity - UPDATE"

	msg := NewMessage(nil, []byte(msgString), 1, 1)

	msg.SetStreamID(MessageStreamID(10))
	msg.Store([]byte(msgUpdateString))

	expect.Equal(msgUpdateString, string(msg.data.payload))
	expect.Equal(MessageStreamID(10), msg.data.streamID)
	expect.Equal(msgString, string(msg.orig.payload))
	expect.Equal(MessageStreamID(1), msg.orig.streamID)
	expect.Equal(MessageStreamID(1), msg.prevStreamID)
}

func TestMessageClone(t *testing.T) {
	expect := ttesting.NewExpect(t)
	msgString := "Test for clone"
	msgUpdateString := "Test for clone - UPDATE"

	msg := NewMessage(nil, []byte(msgString), 1, 1)
	msg.SetStreamID(MessageStreamID(10))
	msg.Store([]byte(msgUpdateString))

	msgClone := msg.Clone()

	expect.Equal(msgUpdateString, string(msgClone.data.payload))
	expect.Equal(MessageStreamID(10), msgClone.data.streamID)
	expect.Equal(msgString, string(msgClone.orig.payload))
	expect.Equal(MessageStreamID(1), msgClone.orig.streamID)
}

func TestMessageCloneOriginal(t *testing.T) {
	expect := ttesting.NewExpect(t)
	msgString := "Test for clone original"
	msgUpdateString := "Test for clone original - UPDATE"

	msg := NewMessage(nil, []byte(msgString), 1, 1)
	msg.SetStreamID(MessageStreamID(10))
	msg.Store([]byte(msgUpdateString))

	msgClone := msg.CloneOriginal()

	expect.Equal(msgString, string(msgClone.data.payload))
	expect.Equal(MessageStreamID(1), msgClone.data.streamID)
	expect.Equal(msgString, string(msgClone.orig.payload))
	expect.Equal(MessageStreamID(1), msgClone.orig.streamID)
}

func TestMessageMetaData(t *testing.T) {
	expect := ttesting.NewExpect(t)

	msg := NewMessage(nil, []byte("message payload"), 1, 1)
	value1 := []byte("value string")
	value2 := []byte("100")

	msg.MetaData().SetValue("key1", value1)
	msg.MetaData().SetValue("key2", value2)

	result1 := msg.MetaData().GetValue("key1")
	result2 := msg.MetaData().GetValue("key2")

	expect.Equal("value string", string(result1))
	expect.Equal("100", string(result2))
}

func TestMessageMetaDataReset(t *testing.T) {
	expect := ttesting.NewExpect(t)

	msg := NewMessage(nil, []byte("message payload"), 1, 1)
	value := []byte("value string")

	msg.MetaData().SetValue("key1", value)

	result1 := msg.MetaData().GetValue("key1")

	msg.MetaData().ResetValue("key1")
	result2 := msg.MetaData().GetValue("key1")

	expect.Equal("value string", string(result1))
	expect.Equal([]byte{}, result2)
}
<commit_msg>Added additional message unit tests<commit_after>// Copyright 2015-2017 trivago GmbH
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package core

import (
	"testing"
	"time"

	"github.com/trivago/tgo/ttesting"
)

func getMockMessage(data string) *Message {
	msg := &Message{
		prevStreamID: 2,
		source:       nil,
		timestamp:    time.Now(),
		sequence:     4,
	}

	msg.data.payload = []byte(data)
	msg.data.streamID = 1

	return msg
}

func TestMessageEnqueue(t *testing.T) {
	expect := ttesting.NewExpect(t)
	msgString := "Test for Enqueue()"
	msg := getMockMessage(msgString)
	buffer := NewMessageQueue(0)

	expect.Equal(MessageStateDiscard, buffer.Push(msg, -1))

	go func() {
		expect.Equal(MessageStateOk, buffer.Push(msg, 0))
	}()

	retMsg, _ := buffer.Pop()
	expect.Equal(msgString, retMsg.String())

	retStatus := buffer.Push(msg, 10*time.Millisecond)
	expect.Equal(MessageStateTimeout, retStatus)

	go func() {
		expect.Equal(MessageStateOk, buffer.Push(msg, 1*time.Second))
	}()

	retMsg, _ = buffer.Pop()
	expect.Equal(msgString, retMsg.String())
}

func TestMessageInstantiate(t *testing.T) {
	expect := ttesting.NewExpect(t)
	msgString := "Test for instantiate"

	msg := NewMessage(nil, []byte(msgString), 1, 1)

	expect.Equal(msgString, string(msg.data.payload))
	expect.Equal(MessageStreamID(1), msg.data.streamID)
	expect.Equal(msgString, string(msg.orig.payload))
	expect.Equal(MessageStreamID(1), msg.orig.streamID)
}

func TestMessageOriginalDataIntegrity(t *testing.T) {
	expect := ttesting.NewExpect(t)
	msgString := "Test for original data integrity"
	msgUpdateString := "Test for original data integrity - UPDATE"

	msg := NewMessage(nil, []byte(msgString), 1, 1)

	msg.SetStreamID(MessageStreamID(10))
	msg.Store([]byte(msgUpdateString))

	expect.Equal(msgUpdateString, string(msg.data.payload))
	expect.Equal(MessageStreamID(10), msg.data.streamID)
	expect.Equal(msgString, string(msg.orig.payload))
	expect.Equal(MessageStreamID(1), msg.orig.streamID)
	expect.Equal(MessageStreamID(1), msg.prevStreamID)
}

func TestMessageClone(t *testing.T) {
	expect := ttesting.NewExpect(t)
	msgString := "Test for clone"
	msgUpdateString := "Test for clone - UPDATE"

	msg := NewMessage(nil, []byte(msgString), 1, 1)
	msg.SetStreamID(MessageStreamID(10))
	msg.Store([]byte(msgUpdateString))

	msgClone := msg.Clone()

	expect.Equal(msgUpdateString, string(msgClone.data.payload))
	expect.Equal(MessageStreamID(10), msgClone.data.streamID)
	expect.Equal(msgString, string(msgClone.orig.payload))
	expect.Equal(MessageStreamID(1), msgClone.orig.streamID)
}

func TestMessageCloneMetaData(t *testing.T) {
	expect := ttesting.NewExpect(t)
	msgString := "Test for clone"
	msgUpdateString := "Test for clone - UPDATE"

	msg := NewMessage(nil, []byte(msgString), 1, 1)
	msg.SetStreamID(MessageStreamID(10))
	msg.Store([]byte(msgUpdateString))
	msg.MetaData().SetValue("foo", []byte("bar"))

	msg.Clone()

	expect.Equal("bar", msg.MetaData().GetValueString("foo"))
}

func TestMessageCloneOriginal(t *testing.T) {
	expect := ttesting.NewExpect(t)
	msgString := "Test for clone original"
	msgUpdateString := "Test for clone original - UPDATE"

	msg := NewMessage(nil, []byte(msgString), 1, 1)
	msg.SetStreamID(MessageStreamID(10))
	msg.Store([]byte(msgUpdateString))

	msgClone := msg.CloneOriginal()

	expect.Equal(msgString, string(msgClone.data.payload))
	expect.Equal(MessageStreamID(1), msgClone.data.streamID)
	expect.Equal(msgString, string(msgClone.orig.payload))
	expect.Equal(MessageStreamID(1), msgClone.orig.streamID)
}

func TestMessageCloneOriginalMetaData(t *testing.T) {
	expect := ttesting.NewExpect(t)
	msgString := "Test for clone original"
	msgUpdateString := "Test for clone original - UPDATE"

	msg := NewMessage(nil, []byte(msgString), 1, 1)
	msg.SetStreamID(MessageStreamID(10))
	msg.Store([]byte(msgUpdateString))
	msg.MetaData().SetValue("foo", []byte("bar"))

	msg.CloneOriginal()

	expect.Equal("bar", msg.MetaData().GetValueString("foo"))
}

func TestMessageMetaData(t *testing.T) {
	expect := ttesting.NewExpect(t)

	msg := NewMessage(nil, []byte("message payload"), 1, 1)
	value1 := []byte("value string")
	value2 := []byte("100")

	msg.MetaData().SetValue("key1", value1)
	msg.MetaData().SetValue("key2", value2)

	result1 := msg.MetaData().GetValue("key1")
	result2 := msg.MetaData().GetValue("key2")

	expect.Equal("value string", string(result1))
	expect.Equal("100", string(result2))
}

func TestMessageMetaDataReset(t *testing.T) {
	expect := ttesting.NewExpect(t)

	msg := NewMessage(nil, []byte("message payload"), 1, 1)
	value := []byte("value string")

	msg.MetaData().SetValue("key1", value)

	result1 := msg.MetaData().GetValue("key1")

	msg.MetaData().ResetValue("key1")
	result2 := msg.MetaData().GetValue("key1")

	expect.Equal("value string", string(result1))
	expect.Equal([]byte{}, result2)
}
<|endoftext|>


<commit_before>// This packages contains an interface for accessing other processes' memory.
package memaccess

import "fmt"

// Creates a new ProcessMemoryReader for a given process.
func NewProcessMemoryReader(pid uint) (reader ProcessMemoryReader, harderror error, softerrors []error) {
	return newProcessMemoryReaderImpl(pid)
}

// This interface is used to access a process memory. For getting an instance
// of a type implementing it you must call NewProcessMemoryReader function.
type ProcessMemoryReader interface {
	// Frees the resources attached to this interface.
	Close() (harderror error, softerrors []error)

	// Returns a memory region containing address, or the next readable region
	// after address in case addresss is not in a readable region.
	//
	// If there aren't more regions available the special value
	// NoRegionAvailable is returned.
	NextReadableMemoryRegion(address uintptr) (region MemoryRegion, harderror error, softerrors []error)

	// Fills the entire buffer with memory from the process starting in address (in the process address space).
	// If there is not enough memory to read it returns a hard error. Note that this is not the only hard error it may
	// return though.
	CopyMemory(address uintptr, buffer []byte) (harderror error, softerrors []error)
}

// This struct represents a region of readable contiguos memory of a process.
//
// No readable memory can be available right next to this region, it's maximal
// in its upper bound.
//
// Note that this region is not necessary equivalent to the OS's region, if any.
type MemoryRegion struct {
	Address uintptr
	Size    uint
}

func (m MemoryRegion) String() string {
	return fmt.Sprintf("MemoryRegion[%x-%x)", m.Address, m.Address+uintptr(m.Size))
}

// A centinel value indicating that there is no more regions available.
var NoRegionAvailable MemoryRegion

// This type represents a function used for walking through the memory, see
// WalkMemory for more details.
type WalkFunc func(address uintptr, buf []byte) (keepSearching bool)

// WalkMemory reads all the memory of a process starting at a given address
// reading upto bufSize bytes into a buffer, and calling walkFn with the buffer
// and the start address of the memory in the buffer. If walkFn returns false
// WalkMemory stop reading the memory.
// It can call to walkFn with a smaller buffer when reading the last part of
// a memory region.
func WalkMemory(reader ProcessMemoryReader, startAddress uintptr, bufSize uint, walkFn WalkFunc) (harderror error,
	softerrors []error) {

	var region MemoryRegion
	region, harderror, softerrors = reader.NextReadableMemoryRegion(startAddress)
	if harderror != nil {
		return
	}

	const max_retries int = 5

	buf := make([]byte, bufSize)
	retries := max_retries

	for region != NoRegionAvailable {

		keepWalking, addr, err, serrs := walkRegion(reader, region, buf, walkFn)
		softerrors = append(softerrors, serrs...)

		if err != nil && retries > 0 {
			// An error occurred: retry using the nearest region to the address that failed.
			retries--
			region, harderror, serrs = reader.NextReadableMemoryRegion(addr)
			softerrors = append(softerrors, serrs...)
			if harderror != nil {
				return
			}

			// if some chunk of this new region was already read we don't want to read it again.
			if region.Address < addr {
				region.Address = addr
			}

			continue
		} else if err != nil {
			// we have exceeded our retries, mark the error as soft error and keep going.
			softerrors = append(softerrors, fmt.Errorf("Retries exceeded on reading %d bytes starting at %x: %s",
				len(buf), addr, err.Error()))
		} else if !keepWalking {
			return
		}

		region, harderror, serrs = reader.NextReadableMemoryRegion(region.Address + uintptr(region.Size))
		softerrors = append(softerrors, serrs...)
		if harderror != nil {
			return
		}
		retries = max_retries
	}
	return
}

// This function walks through a single memory region calling walkFunc with a given buffer. It always fills as much of
// the buffer as possible before calling walkFunc, but it never calls it with overlaped memory sections.
//
// If the buffer cannot be filled a hard error is returned with the starting address of the chunk of memory that could
// not be read. If no harderror is returned errorAddress must be ignored.
//
// If any of the calls to walkFn returns false, this function inmediatly returns, with keepWalking set to false and no
// hard error.
func walkRegion(reader ProcessMemoryReader, region MemoryRegion, buf []byte, walkFn WalkFunc) (keepWalking bool,
	errorAddress uintptr, harderror error, softerrors []error) {
	softerrors = make([]error, 0)
	keepWalking = true

	remaningBytes := uintptr(region.Size)
	for addr := region.Address; remaningBytes > 0; {
		err, serrs := reader.CopyMemory(addr, buf)
		softerrors = append(softerrors, serrs...)

		if err != nil {
			harderror = err
			errorAddress = addr
			return
		}

		keepWalking = walkFn(addr, buf)
		if !keepWalking {
			return
		}

		addr += uintptr(len(buf))
		remaningBytes -= uintptr(len(buf))
		if remaningBytes < uintptr(len(buf)) {
			buf = buf[:remaningBytes]
		}
	}

	return
}
<commit_msg>[memaccess] Fix bug in walkRegion<commit_after>// This packages contains an interface for accessing other processes' memory.
package memaccess

import "fmt"

// Creates a new ProcessMemoryReader for a given process.
func NewProcessMemoryReader(pid uint) (reader ProcessMemoryReader, harderror error, softerrors []error) {
	return newProcessMemoryReaderImpl(pid)
}

// This interface is used to access a process memory. For getting an instance
// of a type implementing it you must call NewProcessMemoryReader function.
type ProcessMemoryReader interface {
	// Frees the resources attached to this interface.
	Close() (harderror error, softerrors []error)

	// Returns a memory region containing address, or the next readable region
	// after address in case addresss is not in a readable region.
	//
	// If there aren't more regions available the special value
	// NoRegionAvailable is returned.
	NextReadableMemoryRegion(address uintptr) (region MemoryRegion, harderror error, softerrors []error)

	// Fills the entire buffer with memory from the process starting in address (in the process address space).
	// If there is not enough memory to read it returns a hard error. Note that this is not the only hard error it may
	// return though.
	CopyMemory(address uintptr, buffer []byte) (harderror error, softerrors []error)
}

// This struct represents a region of readable contiguos memory of a process.
//
// No readable memory can be available right next to this region, it's maximal
// in its upper bound.
//
// Note that this region is not necessary equivalent to the OS's region, if any.
type MemoryRegion struct {
	Address uintptr
	Size    uint
}

func (m MemoryRegion) String() string {
	return fmt.Sprintf("MemoryRegion[%x-%x)", m.Address, m.Address+uintptr(m.Size))
}

// A centinel value indicating that there is no more regions available.
var NoRegionAvailable MemoryRegion

// This type represents a function used for walking through the memory, see
// WalkMemory for more details.
type WalkFunc func(address uintptr, buf []byte) (keepSearching bool)

// WalkMemory reads all the memory of a process starting at a given address
// reading upto bufSize bytes into a buffer, and calling walkFn with the buffer
// and the start address of the memory in the buffer. If walkFn returns false
// WalkMemory stop reading the memory.
// It can call to walkFn with a smaller buffer when reading the last part of
// a memory region.
func WalkMemory(reader ProcessMemoryReader, startAddress uintptr, bufSize uint, walkFn WalkFunc) (harderror error,
	softerrors []error) {

	var region MemoryRegion
	region, harderror, softerrors = reader.NextReadableMemoryRegion(startAddress)
	if harderror != nil {
		return
	}

	const max_retries int = 5

	buf := make([]byte, bufSize)
	retries := max_retries

	for region != NoRegionAvailable {

		keepWalking, addr, err, serrs := walkRegion(reader, region, buf, walkFn)
		softerrors = append(softerrors, serrs...)

		if err != nil && retries > 0 {
			// An error occurred: retry using the nearest region to the address that failed.
			retries--
			region, harderror, serrs = reader.NextReadableMemoryRegion(addr)
			softerrors = append(softerrors, serrs...)
			if harderror != nil {
				return
			}

			// if some chunk of this new region was already read we don't want to read it again.
			if region.Address < addr {
				region.Address = addr
			}

			continue
		} else if err != nil {
			// we have exceeded our retries, mark the error as soft error and keep going.
			softerrors = append(softerrors, fmt.Errorf("Retries exceeded on reading %d bytes starting at %x: %s",
				len(buf), addr, err.Error()))
		} else if !keepWalking {
			return
		}

		region, harderror, serrs = reader.NextReadableMemoryRegion(region.Address + uintptr(region.Size))
		softerrors = append(softerrors, serrs...)
		if harderror != nil {
			return
		}
		retries = max_retries
	}
	return
}

// This function walks through a single memory region calling walkFunc with a given buffer. It always fills as much of
// the buffer as possible before calling walkFunc, but it never calls it with overlaped memory sections.
//
// If the buffer cannot be filled a hard error is returned with the starting address of the chunk of memory that could
// not be read. If no harderror is returned errorAddress must be ignored.
//
// If any of the calls to walkFn returns false, this function inmediatly returns, with keepWalking set to false and no
// hard error.
func walkRegion(reader ProcessMemoryReader, region MemoryRegion, buf []byte, walkFn WalkFunc) (keepWalking bool,
	errorAddress uintptr, harderror error, softerrors []error) {
	softerrors = make([]error, 0)
	keepWalking = true
	remainingBytes := uintptr(region.Size)
	for addr := region.Address; remainingBytes > 0; {
		if remainingBytes < uintptr(len(buf)) {
			buf = buf[:remainingBytes]
		}

		err, serrs := reader.CopyMemory(addr, buf)
		softerrors = append(softerrors, serrs...)

		if err != nil {
			harderror = err
			errorAddress = addr
			return
		}

		keepWalking = walkFn(addr, buf)
		if !keepWalking {
			return
		}

		addr += uintptr(len(buf))
		remainingBytes -= uintptr(len(buf))
	}

	return
}
	}

	return
}
<|endoftext|>


<commit_before>package memcache

import (
	"runtime"
	"strings"
	"sync"
	"testing"
)

func benchmarkSetGet(b *testing.B, item *Item) {
	cmd, c := newUnixServer(b)
	key := item.Key
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		if err := c.Set(item); err != nil {
			b.Fatal(err)
		}
		if _, err := c.Get(key); err != nil {
			b.Fatal(err)
		}
	}
	b.StopTimer()
	cmd.Process.Kill()
	cmd.Wait()
}

func largeItem() *Item {
	key := strings.Repeat("f", 240)
	value := make([]byte, 1024)
	return &Item{Key: key, Value: value}
}

func smallItem() *Item {
	return &Item{Key: "foo", Value: []byte("bar")}
}

func BenchmarkSetGet(b *testing.B) {
	benchmarkSetGet(b, smallItem())
}

func BenchmarkSetGetLarge(b *testing.B) {
	benchmarkSetGet(b, largeItem())
}

func benchmarkConcurrentSetGet(b *testing.B, item *Item, count int, opcount int) {
	mp := runtime.GOMAXPROCS(0)
	defer runtime.GOMAXPROCS(mp)
	runtime.GOMAXPROCS(count)
	cmd, c := newUnixServer(b)
	c = New("localhost:11211")
	// Items are not thread safe
	items := make([]*Item, count)
	for ii := range items {
		items[ii] = &Item{Key: item.Key, Value: item.Value}
	}
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		var wg sync.WaitGroup
		wg.Add(count)
		for j := 0; j < count; j++ {
			it := items[j]
			key := it.Key
			go func() {
				defer wg.Done()
				for k := 0; k < opcount; k++ {
					if err := c.Set(it); err != nil {
						b.Fatal(err)
					}
					if _, err := c.Get(key); err != nil {
						b.Fatal(err)
					}
				}
			}()
		}
		wg.Wait()
	}
	b.StopTimer()
	cmd.Process.Kill()
	cmd.Wait()
}

func BenchmarkConcurrentSetGetSmall10_100(b *testing.B) {
	benchmarkConcurrentSetGet(b, smallItem(), 10, 100)
}

func BenchmarkConcurrentSetGetLarge10_100(b *testing.B) {
	benchmarkConcurrentSetGet(b, largeItem(), 10, 100)
}

func BenchmarkConcurrentSetGetLarge50(b *testing.B) {
	benchmarkConcurrentSetGet(b, largeItem(), 50, 1000)
}
<commit_msg>Remove benchmark with 50 threads, add a couple with 20 threads<commit_after>package memcache

import (
	"runtime"
	"strings"
	"sync"
	"testing"
)

func benchmarkSetGet(b *testing.B, item *Item) {
	cmd, c := newUnixServer(b)
	key := item.Key
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		if err := c.Set(item); err != nil {
			b.Fatal(err)
		}
		if _, err := c.Get(key); err != nil {
			b.Fatal(err)
		}
	}
	b.StopTimer()
	cmd.Process.Kill()
	cmd.Wait()
}

func largeItem() *Item {
	key := strings.Repeat("f", 240)
	value := make([]byte, 1024)
	return &Item{Key: key, Value: value}
}

func smallItem() *Item {
	return &Item{Key: "foo", Value: []byte("bar")}
}

func BenchmarkSetGet(b *testing.B) {
	benchmarkSetGet(b, smallItem())
}

func BenchmarkSetGetLarge(b *testing.B) {
	benchmarkSetGet(b, largeItem())
}

func benchmarkConcurrentSetGet(b *testing.B, item *Item, count int, opcount int) {
	mp := runtime.GOMAXPROCS(0)
	defer runtime.GOMAXPROCS(mp)
	runtime.GOMAXPROCS(count)
	cmd, c := newUnixServer(b)
	c = New("localhost:11211")
	// Items are not thread safe
	items := make([]*Item, count)
	for ii := range items {
		items[ii] = &Item{Key: item.Key, Value: item.Value}
	}
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		var wg sync.WaitGroup
		wg.Add(count)
		for j := 0; j < count; j++ {
			it := items[j]
			key := it.Key
			go func() {
				defer wg.Done()
				for k := 0; k < opcount; k++ {
					if err := c.Set(it); err != nil {
						b.Fatal(err)
					}
					if _, err := c.Get(key); err != nil {
						b.Fatal(err)
					}
				}
			}()
		}
		wg.Wait()
	}
	b.StopTimer()
	cmd.Process.Kill()
	cmd.Wait()
}

func BenchmarkConcurrentSetGetSmall10_100(b *testing.B) {
	benchmarkConcurrentSetGet(b, smallItem(), 10, 100)
}

func BenchmarkConcurrentSetGetLarge10_100(b *testing.B) {
	benchmarkConcurrentSetGet(b, largeItem(), 10, 100)
}

func BenchmarkConcurrentSetGetSmall20_100(b *testing.B) {
	benchmarkConcurrentSetGet(b, smallItem(), 20, 100)
}

func BenchmarkConcurrentSetGetLarge20_100(b *testing.B) {
	benchmarkConcurrentSetGet(b, largeItem(), 20, 100)
}
<|endoftext|>


<commit_before>// Copyright 2015 Hari haran. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

// Package memory provides different memory related data.
package memory

import (
	"bufio"
	"os"
	"strings"
)

// Data represents the memory data.
type Data map[string]interface{}

// CollectData collects the data and returns an error if any.
func CollectData() (Data, error) {

	// allocate memory
	d := make(Data)
	d["swap"] = make(map[string]string)

	// cast interface{} to a map
	swap := d["swap"].(map[string]string)

	f, err := os.Open("/proc/meminfo")
	if err != nil {
		return d, err
	}
	defer f.Close()
	s := bufio.NewScanner(f)
	for s.Scan() {
		l := strings.Split(s.Text(), ":")
		k, v := l[0], strings.TrimSpace(l[1])
		switch k {
		case "MemTotal":
			d["total"] = v
		case "MemFree":
			d["free"] = v
		case "MemAvailable":
			d["available"] = v
		case "Buffers":
			d["buffers"] = v
		case "Cached":
			d["cached"] = v
		case "SwapCached":
			swap["cached"] = v
		case "Active":
			d["active"] = v
		case "Inactive":
			d["inactive"] = v
		case "SwapTotal":
			swap["total"] = v
		case "SwapFree":
			swap["free"] = v
		case "Dirty":
			d["dirty"] = v
		case "Writeback":
			d["writeback"] = v
		case "AnonPages":
			d["anon_pages"] = v
		case "Mapped":
			d["mapped"] = v
		case "Slab":
			d["slab"] = v
		case "SReclaimable":
			d["slab_reclaimable"] = v
		case "SUnreclaim":
			d["slab_unreclaim"] = v
		case "PageTables":
			d["page_tables"] = v
		case "NFS_Unstable":
			d["nfs_unstable"] = v
		case "Bounce":
			d["bounce"] = v
		case "CommitLimit":
			d["commit_limit"] = v
		case "Committed_AS":
			d["committed_as"] = v
		case "VmallocTotal":
			d["vmalloc_total"] = v
		case "VmallocUsed":
			d["vmalloc_used"] = v
		case "VmallocChunk":
			d["vmalloc_chunk"] = v
		}
	}
	if err := s.Err(); err != nil {
		return d, err
	}
	return d, nil
}
<commit_msg>Add length check for slice to avoid runtime panic<commit_after>// Copyright 2015 Hari haran. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

// Package memory provides different memory related data.
package memory

import (
	"bufio"
	"os"
	"strings"
)

// Data represents the memory data.
type Data map[string]interface{}

// CollectData collects the data and returns an error if any.
func CollectData() (Data, error) {

	// allocate memory
	d := make(Data)
	d["swap"] = make(map[string]string)

	// cast interface{} to a map
	swap := d["swap"].(map[string]string)

	f, err := os.Open("/proc/meminfo")
	if err != nil {
		return d, err
	}
	defer f.Close()
	s := bufio.NewScanner(f)
	for s.Scan() {
		l := strings.Split(s.Text(), ":")
		if len(l) == 2 {
			k, v := l[0], strings.TrimSpace(l[1])
			switch k {
			case "MemTotal":
				d["total"] = v
			case "MemFree":
				d["free"] = v
			case "MemAvailable":
				d["available"] = v
			case "Buffers":
				d["buffers"] = v
			case "Cached":
				d["cached"] = v
			case "SwapCached":
				swap["cached"] = v
			case "Active":
				d["active"] = v
			case "Inactive":
				d["inactive"] = v
			case "SwapTotal":
				swap["total"] = v
			case "SwapFree":
				swap["free"] = v
			case "Dirty":
				d["dirty"] = v
			case "Writeback":
				d["writeback"] = v
			case "AnonPages":
				d["anon_pages"] = v
			case "Mapped":
				d["mapped"] = v
			case "Slab":
				d["slab"] = v
			case "SReclaimable":
				d["slab_reclaimable"] = v
			case "SUnreclaim":
				d["slab_unreclaim"] = v
			case "PageTables":
				d["page_tables"] = v
			case "NFS_Unstable":
				d["nfs_unstable"] = v
			case "Bounce":
				d["bounce"] = v
			case "CommitLimit":
				d["commit_limit"] = v
			case "Committed_AS":
				d["committed_as"] = v
			case "VmallocTotal":
				d["vmalloc_total"] = v
			case "VmallocUsed":
				d["vmalloc_used"] = v
			case "VmallocChunk":
				d["vmalloc_chunk"] = v
			}
		}
	}
	if err := s.Err(); err != nil {
		return d, err
	}
	return d, nil
}
<|endoftext|>


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

// Process plain text into HTML.
//	- h2's are made from lines followed by a line "----\n"
//	- tab-indented blocks become
 blocks
//	- blank lines become
 marks
//	- "quoted strings" become quoted strings

package main

import (
	"bufio";
	"bytes";
	"log";
	"os";
)

var (
	lines = make([][]byte, 0, 10000);	// assume big enough
	linebuf = make([]byte, 10000);		// assume big enough

	empty = []byte("");
	newline = []byte("\n");
	tab = []byte("\t");
	quote = []byte(`"`);

	sectionMarker = []byte("----\n");
	preStart = []byte("
");
	preEnd = []byte("
\n");
	pp = []byte("
\n");
);

func main() {
	read();
	headings();
	paragraphs();
	coalesce(preStart, foldPre);
	coalesce(tab, foldTabs);
	quotes();
	write();
}

func read() {
	b := bufio.NewReader(os.Stdin);
	for {
		line, err := b.ReadBytes('\n');
		if err == os.EOF {
			break;
		}
		if err != nil {
			log.Exit(err)
		}
		n := len(lines);
		lines = lines[0:n+1];
		lines[n] = line;
	}
}

func write() {
	b := bufio.NewWriter(os.Stdout);
	for _, line := range lines {
		b.Write(expandTabs(line));
	}
	b.Flush();
}

// each time prefix is found on a line, call fold and replace
// line with return value from fold.
func coalesce(prefix []byte, fold func(i int) (n int, line []byte)) {
	j := 0;	// output line number; goes up by one each loop
	for i := 0; i < len(lines); {
		if bytes.HasPrefix(lines[i], prefix) {
			nlines, block := fold(i);
			lines[j] = block;
			i += nlines;
		} else {
			lines[j] = lines[i];
			i++;
		}
		j++;
	}
	lines = lines[0:j];
}

// return the
 block as a single slice
func foldPre(i int) (n int, line []byte) {
	buf := new(bytes.Buffer);
	for i < len(lines) {
		buf.Write(lines[i]);
		n++;
		if bytes.Equal(lines[i], preEnd) {
			break
		}
		i++;
	}
	return n, buf.Bytes();
}

// return the tab-indented block as a single
-bounded slice
func foldTabs(i int) (n int, line []byte) {
	buf := new(bytes.Buffer);
	buf.WriteString("
\n");
	for i < len(lines) {
		if !bytes.HasPrefix(lines[i], tab) {
			break;
		}
		buf.Write(lines[i]);
		n++;
		i++;
	}
	buf.WriteString("
\n");
	return n, buf.Bytes();
}

func headings() {
	b := bufio.NewWriter(os.Stdout);
	for i, l := range lines {
		if i > 0 && bytes.Equal(l, sectionMarker) {
			lines[i-1] = []byte("
" + string(trim(lines[i-1])) + "
\n");
			lines[i] = empty;
		}
	}
	b.Flush();
}

func paragraphs() {
	for i, l := range lines {
		if bytes.Equal(l, newline) {
			lines[i] = pp;
		}
	}
}

func quotes() {
	for i, l := range lines {
		lines[i] = codeQuotes(l);
	}
}

func codeQuotes(l []byte) []byte {
	if bytes.HasPrefix(l, preStart) {
		return l
	}
	n := bytes.Index(l, quote);
	if n < 0 {
		return l
	}
	buf := new(bytes.Buffer);
	inQuote := false;
	for _, c := range l {
		if c == '"' {
			if inQuote {
				buf.WriteString("")
			} else {
				buf.WriteString("")
			}
			inQuote = !inQuote
		} else {
			buf.WriteByte(c)
		}
	}
	return buf.Bytes();
}

// drop trailing newline
func trim(l []byte) []byte {
	n := len(l);
	if n > 0 && l[n-1] == '\n' {
		return l[0:n-1]
	}
	return l
}

// expand tabs to 4 spaces. don't worry about columns.
func expandTabs(l []byte) []byte {
	j := 0;	// position in linebuf.
	for _, c := range l {
		if c == '\t' {
			for k := 0; k < 4; k++ {
				linebuf[j] = ' ';
				j++;
			}
		} else {
			linebuf[j] = c;
			j++;
		}
	}
	return linebuf[0:j];
}
<commit_msg>doc/htmlgen.go: remove unnecessary semicolons<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Process plain text into HTML.
//	- h2's are made from lines followed by a line "----\n"
//	- tab-indented blocks become
 blocks
//	- blank lines become
 marks
//	- "quoted strings" become quoted strings

package main

import (
	"bufio"
	"bytes"
	"log"
	"os"
)

var (
	lines   = make([][]byte, 0, 10000) // assume big enough
	linebuf = make([]byte, 10000)      // assume big enough

	empty   = []byte("")
	newline = []byte("\n")
	tab     = []byte("\t")
	quote   = []byte(`"`)

	sectionMarker = []byte("----\n")
	preStart      = []byte("
")
	preEnd        = []byte("
\n")
	pp            = []byte("
\n")
)

func main() {
	read()
	headings()
	paragraphs()
	coalesce(preStart, foldPre)
	coalesce(tab, foldTabs)
	quotes()
	write()
}

func read() {
	b := bufio.NewReader(os.Stdin)
	for {
		line, err := b.ReadBytes('\n')
		if err == os.EOF {
			break
		}
		if err != nil {
			log.Exit(err)
		}
		n := len(lines)
		lines = lines[0 : n+1]
		lines[n] = line
	}
}

func write() {
	b := bufio.NewWriter(os.Stdout)
	for _, line := range lines {
		b.Write(expandTabs(line))
	}
	b.Flush()
}

// each time prefix is found on a line, call fold and replace
// line with return value from fold.
func coalesce(prefix []byte, fold func(i int) (n int, line []byte)) {
	j := 0 // output line number goes up by one each loop
	for i := 0; i < len(lines); {
		if bytes.HasPrefix(lines[i], prefix) {
			nlines, block := fold(i)
			lines[j] = block
			i += nlines
		} else {
			lines[j] = lines[i]
			i++
		}
		j++
	}
	lines = lines[0:j]
}

// return the
 block as a single slice
func foldPre(i int) (n int, line []byte) {
	buf := new(bytes.Buffer)
	for i < len(lines) {
		buf.Write(lines[i])
		n++
		if bytes.Equal(lines[i], preEnd) {
			break
		}
		i++
	}
	return n, buf.Bytes()
}

// return the tab-indented block as a single
-bounded slice
func foldTabs(i int) (n int, line []byte) {
	buf := new(bytes.Buffer)
	buf.WriteString("
\n")
	for i < len(lines) {
		if !bytes.HasPrefix(lines[i], tab) {
			break
		}
		buf.Write(lines[i])
		n++
		i++
	}
	buf.WriteString("
\n")
	return n, buf.Bytes()
}

func headings() {
	b := bufio.NewWriter(os.Stdout)
	for i, l := range lines {
		if i > 0 && bytes.Equal(l, sectionMarker) {
			lines[i-1] = []byte("
" + string(trim(lines[i-1])) + "
\n")
			lines[i] = empty
		}
	}
	b.Flush()
}

func paragraphs() {
	for i, l := range lines {
		if bytes.Equal(l, newline) {
			lines[i] = pp
		}
	}
}

func quotes() {
	for i, l := range lines {
		lines[i] = codeQuotes(l)
	}
}

func codeQuotes(l []byte) []byte {
	if bytes.HasPrefix(l, preStart) {
		return l
	}
	n := bytes.Index(l, quote)
	if n < 0 {
		return l
	}
	buf := new(bytes.Buffer)
	inQuote := false
	for _, c := range l {
		if c == '"' {
			if inQuote {
				buf.WriteString("")
			} else {
				buf.WriteString("")
			}
			inQuote = !inQuote
		} else {
			buf.WriteByte(c)
		}
	}
	return buf.Bytes()
}

// drop trailing newline
func trim(l []byte) []byte {
	n := len(l)
	if n > 0 && l[n-1] == '\n' {
		return l[0 : n-1]
	}
	return l
}

// expand tabs to 4 spaces. don't worry about columns.
func expandTabs(l []byte) []byte {
	j := 0 // position in linebuf.
	for _, c := range l {
		if c == '\t' {
			for k := 0; k < 4; k++ {
				linebuf[j] = ' '
				j++
			}
		} else {
			linebuf[j] = c
			j++
		}
	}
	return linebuf[0:j]
}
<|endoftext|>


<commit_before>// Copyright (C) 2017, 2018 Damon Revoe. All rights reserved.
// Use of this source code is governed by the MIT
// license, which can be found in the LICENSE file.

package main

import (
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strings"

	"github.com/spf13/cobra"
)

// configureEnv is a cache of environment variables that is
// reused when configuring multiple packages.
type configureEnv struct {
	envSansPkgConfigPath []string
	origPkgConfigPath    string // original value of PKG_CONFIG_PATH
	buildDir             string
	pkgBuildDir          map[string]string
}

const pkgConfigPathVarName = "PKG_CONFIG_PATH"

func dropEnvVar(env []string, i int) []string {
	if i < len(env)-1 {
		env[i] = env[len(env)-1]
	}
	return env[:len(env)-1]
}

func prepareConfigureEnv(buildDir string) *configureEnv {
	ce := &configureEnv{
		os.Environ(),
		"",
		buildDir,
		map[string]string{}}

	for i, v := range ce.envSansPkgConfigPath {
		if strings.HasPrefix(v, pkgConfigPathVarName+"=") {
			ce.envSansPkgConfigPath = dropEnvVar(
				ce.envSansPkgConfigPath, i)
			ce.origPkgConfigPath = strings.SplitN(v, "=", 2)[1]
			break
		}
	}

	return ce
}

func (ce *configureEnv) addPackageBuildDir(pkgName string) {
	ce.pkgBuildDir[pkgName] = path.Join(ce.buildDir, pkgName)
}

func (ce *configureEnv) makeEnv(pd *packageDefinition) []string {
	var configuredPackagePathames []string

	for _, dep := range pd.allRequired {
		depBuildDir, found := ce.pkgBuildDir[dep.PackageName]
		if found {
			configuredPackagePathames = append(
				configuredPackagePathames, depBuildDir)
		}
	}

	pkgConfigPath := strings.Join(configuredPackagePathames, ":")

	if len(pkgConfigPath) == 0 {
		if len(ce.origPkgConfigPath) == 0 {
			return ce.envSansPkgConfigPath
		}
		pkgConfigPath = ce.origPkgConfigPath
	} else if len(ce.origPkgConfigPath) > 0 {
		pkgConfigPath += ":"
		pkgConfigPath += ce.origPkgConfigPath
	}

	return append(ce.envSansPkgConfigPath,
		pkgConfigPathVarName+"="+pkgConfigPath)
}

func configurePackage(workspaceDir, pkgRootDir string, pd *packageDefinition,
	cfgEnv *configureEnv, conftab *Conftab) error {
	fmt.Println("[configure] " + pd.PackageName)

	pkgBuildDir := path.Join(cfgEnv.buildDir, pd.PackageName)

	configurePathname, err := filepath.Rel(pkgBuildDir,
		path.Join(pkgRootDir, pd.PackageName, "configure"))
	if err != nil {
		return err
	}

	err = os.MkdirAll(pkgBuildDir, os.FileMode(0775))
	if err != nil {
		return nil
	}

	configureArgs := conftab.getConfigureArgs(pd.PackageName)

	installDir := flags.installDir
	if installDir == "" {
		installDir = workspaceDir
	}

	configureArgs = append(configureArgs, "--quiet", "--prefix="+installDir)

	configureCmd := exec.Command(configurePathname, configureArgs...)
	configureCmd.Dir = pkgBuildDir
	configureCmd.Stdout = os.Stdout
	configureCmd.Stderr = os.Stderr
	configureCmd.Env = cfgEnv.makeEnv(pd)
	if err := configureCmd.Run(); err != nil {
		return errors.New(configurePathname + ": " + err.Error())
	}

	return nil
}

func configurePackages(args []string) error {
	ws, err := loadWorkspace()
	if err != nil {
		return err
	}

	pi, err := readPackageDefinitions(ws.wp)
	if err != nil {
		return err
	}

	buildDir := ws.buildDir()

	configuredPackageDirs, err := ioutil.ReadDir(buildDir)
	if err != nil {
		return err
	}

	cfgEnv := prepareConfigureEnv(buildDir)

	// Register packages that already exist in the build directory.
	for _, dir := range configuredPackageDirs {
		cfgEnv.addPackageBuildDir(dir.Name())
	}

	var selection packageDefinitionList

	if len(args) > 0 {
		selection, err = packageRangesToFlatSelection(pi, args)
	} else {
		selection, err = readPackageSelection(pi, ws.absPrivateDir)
	}
	if err != nil {
		return err
	}

	for _, pd := range selection {
		cfgEnv.addPackageBuildDir(pd.PackageName)
	}

	conftab, err := readConftab(path.Join(ws.absPrivateDir, conftabFilename))
	if err != nil {
		return err
	}

	pkgRootDir := ws.generatedPkgRootDir()

	for _, pd := range selection {
		err := configurePackage(ws.absDir, pkgRootDir, pd,
			cfgEnv, conftab)
		if err != nil {
			return err
		}
	}

	return nil
}

// configureCmd represents the configure command
var configureCmd = &cobra.Command{
	Use: "configure [package_range...]",
	Short: "Configure all selected packages " +
		"or the specified package range",
	Run: func(_ *cobra.Command, args []string) {
		if err := configurePackages(args); err != nil {
			log.Fatal(err)
		}
	},
}

func init() {
	rootCmd.AddCommand(configureCmd)

	configureCmd.Flags().SortFlags = false
	addQuietFlag(configureCmd)
	addWorkspaceDirFlag(configureCmd)
}
<commit_msg>Fix a bug in configurecmd<commit_after>// Copyright (C) 2017, 2018 Damon Revoe. All rights reserved.
// Use of this source code is governed by the MIT
// license, which can be found in the LICENSE file.

package main

import (
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strings"

	"github.com/spf13/cobra"
)

// configureEnv is a cache of environment variables that is
// reused when configuring multiple packages.
type configureEnv struct {
	envSansPkgConfigPath []string
	origPkgConfigPath    string // original value of PKG_CONFIG_PATH
	buildDir             string
	pkgBuildDir          map[string]string
}

const pkgConfigPathVarName = "PKG_CONFIG_PATH"

func dropEnvVar(env []string, i int) []string {
	if i < len(env)-1 {
		env[i] = env[len(env)-1]
	}
	return env[:len(env)-1]
}

func prepareConfigureEnv(buildDir string) *configureEnv {
	ce := &configureEnv{
		os.Environ(),
		"",
		buildDir,
		map[string]string{}}

	for i, v := range ce.envSansPkgConfigPath {
		if strings.HasPrefix(v, pkgConfigPathVarName+"=") {
			ce.envSansPkgConfigPath = dropEnvVar(
				ce.envSansPkgConfigPath, i)
			ce.origPkgConfigPath = strings.SplitN(v, "=", 2)[1]
			break
		}
	}

	return ce
}

func (ce *configureEnv) addPackageBuildDir(pkgName string) {
	ce.pkgBuildDir[pkgName] = path.Join(ce.buildDir, pkgName)
}

func (ce *configureEnv) makeEnv(pd *packageDefinition) []string {
	var configuredPackagePathames []string

	for _, dep := range pd.allRequired {
		depBuildDir, found := ce.pkgBuildDir[dep.PackageName]
		if found {
			configuredPackagePathames = append(
				configuredPackagePathames, depBuildDir)
		}
	}

	pkgConfigPath := strings.Join(configuredPackagePathames, ":")

	if len(pkgConfigPath) == 0 {
		if len(ce.origPkgConfigPath) == 0 {
			return ce.envSansPkgConfigPath
		}
		pkgConfigPath = ce.origPkgConfigPath
	} else if len(ce.origPkgConfigPath) > 0 {
		pkgConfigPath += ":"
		pkgConfigPath += ce.origPkgConfigPath
	}

	return append(ce.envSansPkgConfigPath,
		pkgConfigPathVarName+"="+pkgConfigPath)
}

func configurePackage(workspaceDir, pkgRootDir string, pd *packageDefinition,
	cfgEnv *configureEnv, conftab *Conftab) error {
	fmt.Println("[configure] " + pd.PackageName)

	pkgBuildDir := path.Join(cfgEnv.buildDir, pd.PackageName)

	configurePathname, err := filepath.Rel(pkgBuildDir,
		path.Join(pkgRootDir, pd.PackageName, "configure"))
	if err != nil {
		return err
	}

	err = os.MkdirAll(pkgBuildDir, os.FileMode(0775))
	if err != nil {
		return nil
	}

	configureArgs := conftab.getConfigureArgs(pd.PackageName)

	installDir := flags.installDir
	if installDir == "" {
		installDir = workspaceDir
	}

	configureArgs = append(configureArgs, "--quiet", "--prefix="+installDir)

	configureCmd := exec.Command(configurePathname, configureArgs...)
	configureCmd.Dir = pkgBuildDir
	configureCmd.Stdout = os.Stdout
	configureCmd.Stderr = os.Stderr
	configureCmd.Env = cfgEnv.makeEnv(pd)
	if err := configureCmd.Run(); err != nil {
		return errors.New(configurePathname + ": " + err.Error())
	}

	return nil
}

func configurePackages(args []string) error {
	ws, err := loadWorkspace()
	if err != nil {
		return err
	}

	pi, err := readPackageDefinitions(ws.wp)
	if err != nil {
		return err
	}

	buildDir := ws.buildDir()

	cfgEnv := prepareConfigureEnv(buildDir)

	if configuredPackageDirs, err := ioutil.ReadDir(buildDir); err == nil {
		// Register packages that already exist
		// in the build directory.
		for _, dir := range configuredPackageDirs {
			cfgEnv.addPackageBuildDir(dir.Name())
		}
	}

	var selection packageDefinitionList

	if len(args) > 0 {
		selection, err = packageRangesToFlatSelection(pi, args)
	} else {
		selection, err = readPackageSelection(pi, ws.absPrivateDir)
	}
	if err != nil {
		return err
	}

	for _, pd := range selection {
		cfgEnv.addPackageBuildDir(pd.PackageName)
	}

	conftab, err := readConftab(
		path.Join(ws.absPrivateDir, conftabFilename))
	if err != nil {
		return err
	}

	pkgRootDir := ws.generatedPkgRootDir()

	for _, pd := range selection {
		err := configurePackage(ws.absDir, pkgRootDir, pd,
			cfgEnv, conftab)
		if err != nil {
			return err
		}
	}

	return nil
}

// configureCmd represents the configure command
var configureCmd = &cobra.Command{
	Use: "configure [package_range...]",
	Short: "Configure all selected packages " +
		"or the specified package range",
	Run: func(_ *cobra.Command, args []string) {
		if err := configurePackages(args); err != nil {
			log.Fatal(err)
		}
	},
}

func init() {
	rootCmd.AddCommand(configureCmd)

	configureCmd.Flags().SortFlags = false
	addQuietFlag(configureCmd)
	addWorkspaceDirFlag(configureCmd)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math/rand"
	"strings"
	"time"
)

func mesosTestProvider(taskId string) (RunningTask, error) {
	parts := strings.Split(taskId, ".")
	if len(parts) == 2 && parts[0] != "" {
		return RunningTask{
			Id: taskId,
			Name: parts[0],
			StartTime: time.Now(),
		}, nil
	} else {
		return RunningTask{
			Id: fmt.Sprintf("%s.%d", parts[0], rand.Int()),
			Name: parts[0],
			StartTime: time.Now(),
		}, nil
	}
}
<commit_msg>Fix test provider, go fmt<commit_after>package main

import (
	"fmt"
	"math/rand"
	"strings"
	"time"
)

func mesosTestProvider(taskId string) (RunningTask, error) {
	parts := strings.Split(taskId, ".")
	if len(parts) == 2 && parts[1] != "" {
		return RunningTask{
			Id:        taskId,
			Name:      parts[0],
			StartTime: time.Now(),
		}, nil
	} else {
		return RunningTask{
			Id:        fmt.Sprintf("%s.%d", parts[0], rand.Int()),
			Name:      parts[0],
			StartTime: time.Now(),
		}, nil
	}
}
<|endoftext|>


<commit_before>package libusb

// #cgo pkg-config: libusb-1.0
// #include <libusb.h>
// int libusbHotplugCallback (libusb_context *ctx, libusb_device *device, libusb_hotplug_event event, void *user_data);
// typedef struct libusb_device_descriptor libusb_device_descriptor_struct;
// static int libusb_hotplug_register_callback_wrapper (
//	libusb_context *ctx,
//	int events, int flags,
//	int vendor_id, int product_id, int dev_class,
//	libusb_hotplug_callback_fn cb_fn, void *user_data,
//	libusb_hotplug_callback_handle *callback_handle)
//	{
// 		return libusb_hotplug_register_callback(ctx, events, flags, vendor_id, product_id, dev_class, cb_fn, user_data, callback_handle);
// }
import "C"
import (
	"fmt"
	"log"
	"unsafe"
)

/*
	rc := C.libusb_hotplug_register_callback(
		ctx.libusbContext,
		event,
		C.LIBUSB_HOTPLUG_NO_FLAGS,
		vID,
		pID,
		C.LIBUSB_HOTPLUG_MATCH_ANY,
		C.libusb_hotplug_callback_fn(unsafe.Pointer(C.libusbHotplugCallback)),
		nil,
		&cbHandle,
	)
*/

// HotPlugEventType ...
type HotPlugEventType uint8

// HotPlugCbFunc callback
type HotPlugCbFunc func(vID, pID uint16, eventType HotPlugEventType)

// HotPlug Event Types
const (
	HotplugUndefined HotPlugEventType = iota
	HotplugArrived
	HotplugLeft
)

// HotPlugEvent callback message
type HotPlugEvent struct {
	VendorID  uint16
	ProductID uint16
	Event     HotPlugEventType
}

type hotplugCallback struct {
	handler *C.libusb_hotplug_callback_handle
	fn      HotPlugCbFunc
}

// HotplugCallbackStorage ...
type HotplugCallbackStorage struct {
	callbackMap map[uint32]hotplugCallback
	done        chan struct{}
}

var hotplugCallbackStorage HotplugCallbackStorage

func (ctx *Context) newHotPlugHandler() {
	hotplugCallbackStorage.callbackMap = make(map[uint32]hotplugCallback)
	hotplugCallbackStorage.done = make(chan struct{})

	go hotplugCallbackStorage.handleEvents(ctx.libusbContext)
}

func (s HotplugCallbackStorage) isEmpty() bool {
	return s.callbackMap == nil
}

// HotplugRegisterCallbackEvent ...
func (ctx *Context) HotplugRegisterCallbackEvent(vendorID, productID uint16, eventType HotPlugEventType, cb HotPlugCbFunc) error {
	if hotplugCallbackStorage.isEmpty() {
		ctx.newHotPlugHandler()
	}

	var event C.int
	switch eventType {
	case HotplugArrived:
		event = C.LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED
	case HotplugLeft:
		event = C.LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT
	default:
		event = C.LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | C.LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT
	}

	var vID C.int = C.LIBUSB_HOTPLUG_MATCH_ANY
	var pID C.int = C.LIBUSB_HOTPLUG_MATCH_ANY

	if vendorID != 0 {
		vID = C.int(vendorID)
	}
	if productID != 0 {
		pID = C.int(productID)
	}

	var cbHandle C.libusb_hotplug_callback_handle

	rc := C.libusb_hotplug_register_callback_wrapper(
		ctx.libusbContext,
		event,
		C.LIBUSB_HOTPLUG_NO_FLAGS,
		vID,
		pID,
		C.LIBUSB_HOTPLUG_MATCH_ANY,
		C.libusb_hotplug_callback_fn(unsafe.Pointer(C.libusbHotplugCallback)),
		nil,
		&cbHandle,
	)
	if rc != C.LIBUSB_SUCCESS {
		return fmt.Errorf("libusb_hotplug_register_callback error: %s", ErrorCode(rc))
	}

	hotplugCallbackStorage.callbackMap[vidPidToUint32(vendorID, productID)] = hotplugCallback{
		handler: &cbHandle,
		fn:      cb,
	}

	return nil
}

// HotplugDeregisterCallback ...
func (ctx *Context) HotplugDeregisterCallback(vendorID, productID uint16) error {
	if hotplugCallbackStorage.isEmpty() {
		return nil
	}

	key := vidPidToUint32(vendorID, productID)

	cb, ok := hotplugCallbackStorage.callbackMap[key]
	if !ok {
		return nil
	}

	C.libusb_hotplug_deregister_callback(ctx.libusbContext, *cb.handler)

	delete(hotplugCallbackStorage.callbackMap, key)

	if len(hotplugCallbackStorage.callbackMap) == 0 {
		ctx.hotplugHandleEventsCompleteAll()
	}
	return nil
}

// HotplugDeregisterAllCallbacks ...
func (ctx *Context) HotplugDeregisterAllCallbacks() error {
	if hotplugCallbackStorage.callbackMap != nil {
		for _, cb := range hotplugCallbackStorage.callbackMap {
			C.libusb_hotplug_deregister_callback(ctx.libusbContext, *cb.handler)
		}
	}

	ctx.hotplugHandleEventsCompleteAll()

	return nil
}

func (ctx *Context) hotplugHandleEventsCompleteAll() {
	if hotplugCallbackStorage.isEmpty() {
		return
	}
	hotplugCallbackStorage.done <- struct{}{}

	hotplugCallbackStorage.callbackMap = nil
	close(hotplugCallbackStorage.done)
}

func (storage *HotplugCallbackStorage) handleEvents(libCtx *C.libusb_context) {
	tv := C.struct_timeval{tv_usec: 100000}
	for {
		select {
		case <-storage.done:
			return
		default:
		}
		if errno := C.libusb_handle_events_timeout_completed(libCtx, &tv, nil); errno < 0 {
			log.Printf("handle_events error: %s", ErrorCode(errno))
		}
	}
}

//export libusbHotplugCallback
func libusbHotplugCallback(ctx *C.libusb_context, dev *C.libusb_device, event C.libusb_hotplug_event, p unsafe.Pointer) C.int {
	var desc C.libusb_device_descriptor_struct
	rc := C.libusb_get_device_descriptor(dev, &desc)
	if rc != C.LIBUSB_SUCCESS {
		return rc
	}

	var vendorID = uint16(desc.idVendor)
	var productID = uint16(desc.idProduct)

	var e HotPlugEventType
	switch event {
	case C.LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED:
		e = HotplugArrived
	case C.LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT:
		e = HotplugLeft
	default:
		e = HotplugUndefined
	}

	cb, ok := hotplugCallbackStorage.callbackMap[vidPidToUint32(vendorID, productID)]
	if ok {
		cb.fn(vendorID, productID, e)
	}

	// for all
	cb, ok = hotplugCallbackStorage.callbackMap[0]
	if ok {
		cb.fn(vendorID, productID, e)
	}

	return C.LIBUSB_SUCCESS
}

func vidPidToUint32(vID, pID uint16) uint32 {
	return (uint32(vID) << 16) | (uint32(pID))
}
<commit_msg>del comment<commit_after>package libusb

// #cgo pkg-config: libusb-1.0
// #include <libusb.h>
// int libusbHotplugCallback (libusb_context *ctx, libusb_device *device, libusb_hotplug_event event, void *user_data);
// typedef struct libusb_device_descriptor libusb_device_descriptor_struct;
// static int libusb_hotplug_register_callback_wrapper (
//	libusb_context *ctx,
//	int events, int flags,
//	int vendor_id, int product_id, int dev_class,
//	libusb_hotplug_callback_fn cb_fn, void *user_data,
//	libusb_hotplug_callback_handle *callback_handle)
//	{
// 		return libusb_hotplug_register_callback(ctx, events, flags, vendor_id, product_id, dev_class, cb_fn, user_data, callback_handle);
// }
import "C"
import (
	"fmt"
	"log"
	"unsafe"
)

// HotPlugEventType ...
type HotPlugEventType uint8

// HotPlugCbFunc callback
type HotPlugCbFunc func(vID, pID uint16, eventType HotPlugEventType)

// HotPlug Event Types
const (
	HotplugUndefined HotPlugEventType = iota
	HotplugArrived
	HotplugLeft
)

// HotPlugEvent callback message
type HotPlugEvent struct {
	VendorID  uint16
	ProductID uint16
	Event     HotPlugEventType
}

type hotplugCallback struct {
	handler *C.libusb_hotplug_callback_handle
	fn      HotPlugCbFunc
}

// HotplugCallbackStorage ...
type HotplugCallbackStorage struct {
	callbackMap map[uint32]hotplugCallback
	done        chan struct{}
}

var hotplugCallbackStorage HotplugCallbackStorage

func (ctx *Context) newHotPlugHandler() {
	hotplugCallbackStorage.callbackMap = make(map[uint32]hotplugCallback)
	hotplugCallbackStorage.done = make(chan struct{})

	go hotplugCallbackStorage.handleEvents(ctx.libusbContext)
}

func (s HotplugCallbackStorage) isEmpty() bool {
	return s.callbackMap == nil
}

// HotplugRegisterCallbackEvent ...
func (ctx *Context) HotplugRegisterCallbackEvent(vendorID, productID uint16, eventType HotPlugEventType, cb HotPlugCbFunc) error {
	if hotplugCallbackStorage.isEmpty() {
		ctx.newHotPlugHandler()
	}

	var event C.int
	switch eventType {
	case HotplugArrived:
		event = C.LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED
	case HotplugLeft:
		event = C.LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT
	default:
		event = C.LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | C.LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT
	}

	var vID C.int = C.LIBUSB_HOTPLUG_MATCH_ANY
	var pID C.int = C.LIBUSB_HOTPLUG_MATCH_ANY

	if vendorID != 0 {
		vID = C.int(vendorID)
	}
	if productID != 0 {
		pID = C.int(productID)
	}

	var cbHandle C.libusb_hotplug_callback_handle

	rc := C.libusb_hotplug_register_callback_wrapper(
		ctx.libusbContext,
		event,
		C.LIBUSB_HOTPLUG_NO_FLAGS,
		vID,
		pID,
		C.LIBUSB_HOTPLUG_MATCH_ANY,
		C.libusb_hotplug_callback_fn(unsafe.Pointer(C.libusbHotplugCallback)),
		nil,
		&cbHandle,
	)
	if rc != C.LIBUSB_SUCCESS {
		return fmt.Errorf("libusb_hotplug_register_callback error: %s", ErrorCode(rc))
	}

	hotplugCallbackStorage.callbackMap[vidPidToUint32(vendorID, productID)] = hotplugCallback{
		handler: &cbHandle,
		fn:      cb,
	}

	return nil
}

// HotplugDeregisterCallback ...
func (ctx *Context) HotplugDeregisterCallback(vendorID, productID uint16) error {
	if hotplugCallbackStorage.isEmpty() {
		return nil
	}

	key := vidPidToUint32(vendorID, productID)

	cb, ok := hotplugCallbackStorage.callbackMap[key]
	if !ok {
		return nil
	}

	C.libusb_hotplug_deregister_callback(ctx.libusbContext, *cb.handler)

	delete(hotplugCallbackStorage.callbackMap, key)

	if len(hotplugCallbackStorage.callbackMap) == 0 {
		ctx.hotplugHandleEventsCompleteAll()
	}
	return nil
}

// HotplugDeregisterAllCallbacks ...
func (ctx *Context) HotplugDeregisterAllCallbacks() error {
	if hotplugCallbackStorage.callbackMap != nil {
		for _, cb := range hotplugCallbackStorage.callbackMap {
			C.libusb_hotplug_deregister_callback(ctx.libusbContext, *cb.handler)
		}
	}

	ctx.hotplugHandleEventsCompleteAll()

	return nil
}

func (ctx *Context) hotplugHandleEventsCompleteAll() {
	if hotplugCallbackStorage.isEmpty() {
		return
	}
	hotplugCallbackStorage.done <- struct{}{}

	hotplugCallbackStorage.callbackMap = nil
	close(hotplugCallbackStorage.done)
}

func (storage *HotplugCallbackStorage) handleEvents(libCtx *C.libusb_context) {
	tv := C.struct_timeval{tv_usec: 100000}
	for {
		select {
		case <-storage.done:
			return
		default:
		}
		if errno := C.libusb_handle_events_timeout_completed(libCtx, &tv, nil); errno < 0 {
			log.Printf("handle_events error: %s", ErrorCode(errno))
		}
	}
}

//export libusbHotplugCallback
func libusbHotplugCallback(ctx *C.libusb_context, dev *C.libusb_device, event C.libusb_hotplug_event, p unsafe.Pointer) C.int {
	var desc C.libusb_device_descriptor_struct
	rc := C.libusb_get_device_descriptor(dev, &desc)
	if rc != C.LIBUSB_SUCCESS {
		return rc
	}

	var vendorID = uint16(desc.idVendor)
	var productID = uint16(desc.idProduct)

	var e HotPlugEventType
	switch event {
	case C.LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED:
		e = HotplugArrived
	case C.LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT:
		e = HotplugLeft
	default:
		e = HotplugUndefined
	}

	cb, ok := hotplugCallbackStorage.callbackMap[vidPidToUint32(vendorID, productID)]
	if ok {
		cb.fn(vendorID, productID, e)
	}

	// for all
	cb, ok = hotplugCallbackStorage.callbackMap[0]
	if ok {
		cb.fn(vendorID, productID, e)
	}

	return C.LIBUSB_SUCCESS
}

func vidPidToUint32(vID, pID uint16) uint32 {
	return (uint32(vID) << 16) | (uint32(pID))
}
<|endoftext|>


<commit_before>// Package testdata provides test images
package testdata

import (
	"fmt"
	"io/ioutil"
	"path/filepath"
	"runtime"

	"github.com/pierrre/imageserver"
)

var (
	// Images contains all images by filename
	Images = make(map[string]*imageserver.Image)

	// Small is a small Image
	Small = loadImage("small.jpg", "jpeg")
	// Medium is a medium Image
	Medium = loadImage("medium.jpg", "jpeg")
	// Large is a large image
	Large = loadImage("large.jpg", "jpeg")
	// Huge is a huge image
	Huge = loadImage("huge.jpg", "jpeg")
	// Animated is an animated GIF Image
	Animated = loadImage("animated.gif", "gif")

	// Provider is an Image Provider that uses filename as source
	Provider = new(testDataProvider)
)

func GetDir() string {
	_, currentFile, _, _ := runtime.Caller(0)
	return filepath.Dir(currentFile)
}

type testDataProvider struct{}

func (provider *testDataProvider) Get(source interface{}, parameters imageserver.Parameters) (*imageserver.Image, error) {
	name, ok := source.(string)
	if !ok {
		return nil, imageserver.NewError(fmt.Sprintf("source is not a string: %#v", source))
	}

	image, ok := Images[name]
	if !ok {
		return nil, imageserver.NewError(fmt.Sprintf("source is unknown: %s", name))
	}

	return image, nil
}

func loadImage(filename string, format string) *imageserver.Image {
	filePath := filepath.Join(GetDir(), filename)

	data, err := ioutil.ReadFile(filePath)
	if err != nil {
		panic(err)
	}

	image := &imageserver.Image{
		Format: format,
		Data:   data,
	}

	Images[filename] = image

	return image
}
<commit_msg>refactor testdata<commit_after>// Package testdata provides test images
package testdata

import (
	"fmt"
	"io/ioutil"
	"path/filepath"
	"runtime"

	"github.com/pierrre/imageserver"
)

var (
	Dir = initDir()

	// Images contains all images by filename
	Images = make(map[string]*imageserver.Image)

	// Small is a small Image
	SmallFileName = "small.jpg"
	Small         = loadImage(SmallFileName, "jpeg")
	// Medium is a medium Image
	MediumFileName = "medium.jpg"
	Medium         = loadImage(MediumFileName, "jpeg")
	// Large is a large image
	LargeFileName = "large.jpg"
	Large         = loadImage(LargeFileName, "jpeg")
	// Huge is a huge image
	HugeFileName = "huge.jpg"
	Huge         = loadImage(HugeFileName, "jpeg")
	// Animated is an animated GIF Image
	AnimatedFileName = "animated.gif"
	Animated         = loadImage(AnimatedFileName, "gif")

	// Provider is an Image Provider that uses filename as source
	Provider = new(testDataProvider)
)

func initDir() string {
	_, currentFile, _, _ := runtime.Caller(0)
	return filepath.Dir(currentFile)
}

type testDataProvider struct{}

func (provider *testDataProvider) Get(source interface{}, parameters imageserver.Parameters) (*imageserver.Image, error) {
	name, ok := source.(string)
	if !ok {
		return nil, imageserver.NewError(fmt.Sprintf("source is not a string: %#v", source))
	}

	image, ok := Images[name]
	if !ok {
		return nil, imageserver.NewError(fmt.Sprintf("source is unknown: %s", name))
	}

	return image, nil
}

func loadImage(filename string, format string) *imageserver.Image {
	filePath := filepath.Join(Dir, filename)

	data, err := ioutil.ReadFile(filePath)
	if err != nil {
		panic(err)
	}

	image := &imageserver.Image{
		Format: format,
		Data:   data,
	}

	Images[filename] = image

	return image
}
<|endoftext|>


<commit_before><commit_msg>adding session management<commit_after>package middlewares

import (
	"github.com/labstack/echo"
	"github.com/nu7hatch/gouuid"
	"goappuser/database"
	"goappuser/user"
)

type SessionManagerUnvailable error

var (
	manager SessionManager = nil
)

type SessionManager struct {
	isSecure bool
	duration int
	db       dbm.DatabaseQuerier
}

func NewSessionManager(isSecure bool, duration int, db dbm.DatabaseQuerier) SessionManager {
	manager = SessionManager{IsSecure: isSecure, duration: duration, db: db}
	return manager
}

type Session struct {
	id uuid.UUID

	User   *user.User
	Values map[string]interface{}
}

func NewSession(c echo.Context, user *user.User, db dbm.DatabaseQuerier) (error, *Session) {
	if manager == nil {
		return SessionManagerUnvailable, nil
	}

	s := &Session{id: uuid.NewV5(uuid.NamespaceURL, []byte(user.Email)),
		config: SessionConfig{IsSecure: true, duration: time.Now().Add(24 * time.Hour), db: db},
		User:   user,
		Values: make(map[string]interface{})}
	s.writeCookie(c)
	return nil, s
}

func (s *Session) writeCookie(c echo.Context) {
	cookie := new(echo.Cookie)
	cookie.SetName("sessionId")
	cookie.SetValue(s.id.String())
	cookie.SetExpires(manager.duration)
	c.SetCookie(cookie)
}

func readSessionCookie(c echo.Context) (uuid.UUID, error) {
	cookie, err := c.Cookie("sessionId")
	if err != nil {
		return nil, err
	}
	return cookie.Value(), nil
}

func SessionMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
	return func(c echo.Context) error {
		if manager == nil {
			return SessionManagerUnvailable
		}
		sessionId, err := readSessionCookie(c)
		if err != nil {
			return err
		}
		s := &Session{}
		if errDB := manager.db.GetOneModel(dbm.M{"sessionId": sessionId.String()}, s); errDB != nil {
			return errDB
		}
		c.Set("Session", s)
		next(c)
	}
}
<|endoftext|>


<commit_before>// Copyright 2014 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

package context

import (
	"net/http"
	"testing"

	"github.com/issue9/assert"
)

func TestContext(t *testing.T) {
	a := assert.New(t)

	// 测试request为nil的情况
	a.Panic(func() {
		Get(nil)
	})

	req1, err := http.NewRequest("GET", "/abc/", nil)
	a.NotError(err).NotNil(req1)
	req2, err := http.NewRequest("GET", "/abc/", nil)
	a.NotError(err).NotNil(req2)

	ctx1 := Get(req1)
	ctx2 := Get(req2)

	// ctx1.Add()
	ok := ctx1.Add("key", "val")
	a.Equal(1, len(ctx1.items)).Equal(0, len(ctx2.items)) // 不影响ctx2
	a.True(ok).Equal(ctx1.MustGet("key", "default").(string), "val")
	a.Equal(ctx2.MustGet("key", "default").(string), "default")

	// 添加一个相同的值，失败
	a.False(ctx1.Add("key", "val1"))
	a.Equal(len(ctx1.items), 1)

	// 测试set
	ctx1.Set("key2", "val")
	ctx1.Set("key2", "val2")
	v, found := ctx1.Get("key2")
	a.True(found).Equal(v, "val2")

	// 同一个Request，应该是相同的值
	newCtx1 := Get(req1)
	a.Equal(newCtx1.MustGet("key", "default").(string), "val")

	// Free(nil)，应该不会释放任何内容
	Free(nil)
	a.Equal(2, len(ctx1.items)).Equal(0, len(ctx2.items))

	Free(req1)
	Free(req2)
	ctx1 = Get(req1)
	a.Equal(0, len(ctx1.items)).Equal(0, len(ctx2.items))
}

// BenchmarkGetFree	 3000000	       509 ns/op
func BenchmarkGetFree(b *testing.B) {
	a := assert.New(b)
	req, err := http.NewRequest("GET", "/api", nil)
	a.NotError(err).NotNil(req)

	for i := 0; i < b.N; i++ {
		c := Get(req)
		if c != nil {
			Free(req)
		}
	}
}

// BenchmarkContext	 1000000	      1210 ns/op
func BenchmarkContext(b *testing.B) {
	ctx := &Context{
		items: make(map[interface{}]interface{}, 0),
	}

	for i := 0; i < b.N; i++ {
		ctx.Set(i, i)
		_, found := ctx.Get(i)
		if !found {
			b.Error("!found")
		}
	}
}
<commit_msg>改进BenchmarkContext<commit_after>// Copyright 2014 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

package context

import (
	"net/http"
	"testing"

	"github.com/issue9/assert"
)

func TestContext(t *testing.T) {
	a := assert.New(t)

	// 测试request为nil的情况
	a.Panic(func() {
		Get(nil)
	})

	req1, err := http.NewRequest("GET", "/abc/", nil)
	a.NotError(err).NotNil(req1)
	req2, err := http.NewRequest("GET", "/abc/", nil)
	a.NotError(err).NotNil(req2)

	ctx1 := Get(req1)
	ctx2 := Get(req2)

	// ctx1.Add()
	ok := ctx1.Add("key", "val")
	a.Equal(1, len(ctx1.items)).Equal(0, len(ctx2.items)) // 不影响ctx2
	a.True(ok).Equal(ctx1.MustGet("key", "default").(string), "val")
	a.Equal(ctx2.MustGet("key", "default").(string), "default")

	// 添加一个相同的值，失败
	a.False(ctx1.Add("key", "val1"))
	a.Equal(len(ctx1.items), 1)

	// 测试set
	ctx1.Set("key2", "val")
	ctx1.Set("key2", "val2")
	v, found := ctx1.Get("key2")
	a.True(found).Equal(v, "val2")

	// 同一个Request，应该是相同的值
	newCtx1 := Get(req1)
	a.Equal(newCtx1.MustGet("key", "default").(string), "val")

	// Free(nil)，应该不会释放任何内容
	Free(nil)
	a.Equal(2, len(ctx1.items)).Equal(0, len(ctx2.items))

	Free(req1)
	Free(req2)
	ctx1 = Get(req1)
	a.Equal(0, len(ctx1.items)).Equal(0, len(ctx2.items))
}

// BenchmarkGetFree	 3000000	       509 ns/op
func BenchmarkGetFree(b *testing.B) {
	a := assert.New(b)
	req, err := http.NewRequest("GET", "/api", nil)
	a.NotError(err).NotNil(req)

	for i := 0; i < b.N; i++ {
		c := Get(req)
		if c != nil {
			Free(req)
		}
	}
}

// BenchmarkContext	 1000000	      1675 ns/op
func BenchmarkContext(b *testing.B) {
	ctx := &Context{
		items: make(map[interface{}]interface{}, 0),
	}

	for i := 0; i < b.N; i++ {
		ctx.Set(i, i)
		// 应该是读多于写
		_, found := ctx.Get(i)
		_, found = ctx.Get(i)
		_, found = ctx.Get(i)
		if !found {
			b.Error("!found")
		}
	}
}
<|endoftext|>