<commit_before>package att

import (
	"encoding/binary"
	"log"

	"github.com/currantlabs/ble"
)

// A DB is a contiguous range of attributes.
type DB struct {
	attrs []*attr
	base  uint16 // handle for first attr in attrs
}

const (
	tooSmall = -1
	tooLarge = -2
)

// idx returns the idx into attrs corresponding to attr a.
// If h is too small, idx returns tooSmall (-1).
// If h is too large, idx returns tooLarge (-2).
func (r *DB) idx(h int) int {
	if h < int(r.base) {
		return tooSmall
	}
	if int(h) >= int(r.base)+len(r.attrs) {
		return tooLarge
	}
	return h - int(r.base)
}

// at returns attr a.
func (r *DB) at(h uint16) (a *attr, ok bool) {
	i := r.idx(int(h))
	if i < 0 {
		return nil, false
	}
	return r.attrs[i], true
}

// subrange returns attributes in range [start, end]; it may return an empty slice.
// subrange does not panic for out-of-range start or end.
func (r *DB) subrange(start, end uint16) []*attr {
	startidx := r.idx(int(start))
	switch startidx {
	case tooSmall:
		startidx = 0
	case tooLarge:
		return []*attr{}
	}

	endidx := r.idx(int(end) + 1) // [start, end] includes its upper bound!
	switch endidx {
	case tooSmall:
		return []*attr{}
	case tooLarge:
		endidx = len(r.attrs)
	}
	return r.attrs[startidx:endidx]
}

// NewDB ...
func NewDB(ss []*ble.Service, base uint16) *DB {
	h := base
	var attrs []*attr
	var aa []*attr
	for i, s := range ss {
		h, aa = genSvcAttr(s, h)
		if i == len(ss)-1 {
			aa[0].endh = 0xFFFF
		}
		attrs = append(attrs, aa...)
	}
	DumpAttributes(attrs)
	return &DB{attrs: attrs, base: base}
}

func genSvcAttr(s *ble.Service, h uint16) (uint16, []*attr) {
	a := &attr{
		h:   h,
		typ: ble.PrimaryServiceUUID,
		v:   s.UUID,
	}
	h++
	attrs := []*attr{a}
	var aa []*attr

	for _, c := range s.Characteristics {
		h, aa = genCharAttr(c, h)
		attrs = append(attrs, aa...)
	}

	a.endh = h - 1
	return h, attrs
}

func genCharAttr(c *ble.Characteristic, h uint16) (uint16, []*attr) {
	vh := h + 1

	a := &attr{
		h:   h,
		typ: ble.CharacteristicUUID,
		v:   append([]byte{byte(c.Property), byte(vh), byte((vh) >> 8)}, c.UUID...),
	}

	va := &attr{
		h:   vh,
		typ: c.UUID,
		v:   c.Value,
		rh:  c.ReadHandler,
		wh:  c.WriteHandler,
	}

	c.Handle = h
	c.ValueHandle = vh
	if c.NotifyHandler != nil || c.IndicateHandler != nil {
		c.CCCD = newCCCD(c)
		c.Descriptors = append(c.Descriptors, c.CCCD)
	}

	h += 2

	attrs := []*attr{a, va}
	for _, d := range c.Descriptors {
		attrs = append(attrs, genDescAttr(d, h))
		h++
	}

	a.endh = h - 1
	return h, attrs
}

func genDescAttr(d *ble.Descriptor, h uint16) *attr {
	return &attr{
		h:   h,
		typ: d.UUID,
		v:   d.Value,
		rh:  d.ReadHandler,
		wh:  d.WriteHandler,
	}
}

// DumpAttributes ...
func DumpAttributes(aa []*attr) {
	log.Printf("Generating attribute table:")
	log.Printf("handle\tend\ttype\tvalue")
	for _, a := range aa {
		if a.v != nil {
			log.Printf("0x%04X\t0x%04X\t0x%s\t[ % X ]", a.h, a.endh, a.typ, a.v)
			continue
		}
		log.Printf("0x%04X\t0x%04X\t0x%s", a.h, a.endh, a.typ)
	}
}

const (
	cccNotify   = 0x0001
	cccIndicate = 0x0002
)

func newCCCD(c *ble.Characteristic) *ble.Descriptor {
	d := ble.NewDescriptor(ble.ClientCharacteristicConfigUUID)

	d.HandleRead(ble.ReadHandlerFunc(func(req ble.Request, rsp ble.ResponseWriter) {
		cccs := req.Conn().(*conn).cccs
		ccc := cccs[c.Handle]
		binary.Write(rsp, binary.LittleEndian, ccc)
	}))

	d.HandleWrite(ble.WriteHandlerFunc(func(req ble.Request, rsp ble.ResponseWriter) {
		cn := req.Conn().(*conn)
		old := cn.cccs[c.Handle]
		ccc := binary.LittleEndian.Uint16(req.Data())

		oldNotify := old&cccNotify != 0
		oldIndicate := old&cccIndicate != 0
		newNotify := ccc&cccNotify != 0
		newIndicate := ccc&cccIndicate != 0

		if newNotify && !oldNotify {
			if c.Property&ble.CharNotify == 0 {
				rsp.SetStatus(ble.ErrUnlikely)
				return
			}
			send := func(b []byte) (int, error) { return cn.svr.notify(c.ValueHandle, b) }
			cn.nn[c.Handle] = ble.NewNotifier(send)
			go c.NotifyHandler.ServeNotify(req, cn.nn[c.Handle])
		}
		if !newNotify && oldNotify {
			cn.nn[c.Handle].Close()
		}

		if newIndicate && !oldIndicate {
			if c.Property&ble.CharIndicate == 0 {
				rsp.SetStatus(ble.ErrUnlikely)
				return
			}
			send := func(b []byte) (int, error) { return cn.svr.indicate(c.ValueHandle, b) }
			cn.in[c.Handle] = ble.NewNotifier(send)
			go c.IndicateHandler.ServeNotify(req, cn.in[c.Handle])
		}
		if !newIndicate && oldIndicate {
			cn.in[c.Handle].Close()
		}
		cn.cccs[c.Handle] = ccc
	}))
	return d
}
<commit_msg>linux: use logxi for logging so we can turn it off by default<commit_after>package att

import (
	"encoding/binary"
	"fmt"

	"github.com/currantlabs/ble"
)

// A DB is a contiguous range of attributes.
type DB struct {
	attrs []*attr
	base  uint16 // handle for first attr in attrs
}

const (
	tooSmall = -1
	tooLarge = -2
)

// idx returns the idx into attrs corresponding to attr a.
// If h is too small, idx returns tooSmall (-1).
// If h is too large, idx returns tooLarge (-2).
func (r *DB) idx(h int) int {
	if h < int(r.base) {
		return tooSmall
	}
	if int(h) >= int(r.base)+len(r.attrs) {
		return tooLarge
	}
	return h - int(r.base)
}

// at returns attr a.
func (r *DB) at(h uint16) (a *attr, ok bool) {
	i := r.idx(int(h))
	if i < 0 {
		return nil, false
	}
	return r.attrs[i], true
}

// subrange returns attributes in range [start, end]; it may return an empty slice.
// subrange does not panic for out-of-range start or end.
func (r *DB) subrange(start, end uint16) []*attr {
	startidx := r.idx(int(start))
	switch startidx {
	case tooSmall:
		startidx = 0
	case tooLarge:
		return []*attr{}
	}

	endidx := r.idx(int(end) + 1) // [start, end] includes its upper bound!
	switch endidx {
	case tooSmall:
		return []*attr{}
	case tooLarge:
		endidx = len(r.attrs)
	}
	return r.attrs[startidx:endidx]
}

// NewDB ...
func NewDB(ss []*ble.Service, base uint16) *DB {
	h := base
	var attrs []*attr
	var aa []*attr
	for i, s := range ss {
		h, aa = genSvcAttr(s, h)
		if i == len(ss)-1 {
			aa[0].endh = 0xFFFF
		}
		attrs = append(attrs, aa...)
	}
	DumpAttributes(attrs)
	return &DB{attrs: attrs, base: base}
}

func genSvcAttr(s *ble.Service, h uint16) (uint16, []*attr) {
	a := &attr{
		h:   h,
		typ: ble.PrimaryServiceUUID,
		v:   s.UUID,
	}
	h++
	attrs := []*attr{a}
	var aa []*attr

	for _, c := range s.Characteristics {
		h, aa = genCharAttr(c, h)
		attrs = append(attrs, aa...)
	}

	a.endh = h - 1
	return h, attrs
}

func genCharAttr(c *ble.Characteristic, h uint16) (uint16, []*attr) {
	vh := h + 1

	a := &attr{
		h:   h,
		typ: ble.CharacteristicUUID,
		v:   append([]byte{byte(c.Property), byte(vh), byte((vh) >> 8)}, c.UUID...),
	}

	va := &attr{
		h:   vh,
		typ: c.UUID,
		v:   c.Value,
		rh:  c.ReadHandler,
		wh:  c.WriteHandler,
	}

	c.Handle = h
	c.ValueHandle = vh
	if c.NotifyHandler != nil || c.IndicateHandler != nil {
		c.CCCD = newCCCD(c)
		c.Descriptors = append(c.Descriptors, c.CCCD)
	}

	h += 2

	attrs := []*attr{a, va}
	for _, d := range c.Descriptors {
		attrs = append(attrs, genDescAttr(d, h))
		h++
	}

	a.endh = h - 1
	return h, attrs
}

func genDescAttr(d *ble.Descriptor, h uint16) *attr {
	return &attr{
		h:   h,
		typ: d.UUID,
		v:   d.Value,
		rh:  d.ReadHandler,
		wh:  d.WriteHandler,
	}
}

// DumpAttributes ...
func DumpAttributes(aa []*attr) {
	logger.Debug("server", "db", "Generating attribute table:")
	logger.Debug("server", "db", "handle   endh   type")
	for _, a := range aa {
		if a.v != nil {
			logger.Debug("server", "db", fmt.Sprintf("0x%04X 0x%04X 0x%s [% X]", a.h, a.endh, a.typ, a.v))
			continue
		}
		logger.Debug("server", "db", fmt.Sprintf("0x%04X 0x%04X 0x%s", a.h, a.endh, a.typ))
	}
}

const (
	cccNotify   = 0x0001
	cccIndicate = 0x0002
)

func newCCCD(c *ble.Characteristic) *ble.Descriptor {
	d := ble.NewDescriptor(ble.ClientCharacteristicConfigUUID)

	d.HandleRead(ble.ReadHandlerFunc(func(req ble.Request, rsp ble.ResponseWriter) {
		cccs := req.Conn().(*conn).cccs
		ccc := cccs[c.Handle]
		binary.Write(rsp, binary.LittleEndian, ccc)
	}))

	d.HandleWrite(ble.WriteHandlerFunc(func(req ble.Request, rsp ble.ResponseWriter) {
		cn := req.Conn().(*conn)
		old := cn.cccs[c.Handle]
		ccc := binary.LittleEndian.Uint16(req.Data())

		oldNotify := old&cccNotify != 0
		oldIndicate := old&cccIndicate != 0
		newNotify := ccc&cccNotify != 0
		newIndicate := ccc&cccIndicate != 0

		if newNotify && !oldNotify {
			if c.Property&ble.CharNotify == 0 {
				rsp.SetStatus(ble.ErrUnlikely)
				return
			}
			send := func(b []byte) (int, error) { return cn.svr.notify(c.ValueHandle, b) }
			cn.nn[c.Handle] = ble.NewNotifier(send)
			go c.NotifyHandler.ServeNotify(req, cn.nn[c.Handle])
		}
		if !newNotify && oldNotify {
			cn.nn[c.Handle].Close()
		}

		if newIndicate && !oldIndicate {
			if c.Property&ble.CharIndicate == 0 {
				rsp.SetStatus(ble.ErrUnlikely)
				return
			}
			send := func(b []byte) (int, error) { return cn.svr.indicate(c.ValueHandle, b) }
			cn.in[c.Handle] = ble.NewNotifier(send)
			go c.IndicateHandler.ServeNotify(req, cn.in[c.Handle])
		}
		if !newIndicate && oldIndicate {
			cn.in[c.Handle].Close()
		}
		cn.cccs[c.Handle] = ccc
	}))
	return d
}
<|endoftext|>


<commit_before>package ethpipe

import (
	"bytes"
	"encoding/json"
	"fmt"
	"sync/atomic"

	"github.com/ethereum/eth-go/ethchain"
	"github.com/ethereum/eth-go/ethcrypto"
	"github.com/ethereum/eth-go/ethreact"
	"github.com/ethereum/eth-go/ethstate"
	"github.com/ethereum/eth-go/ethutil"
)

type JSPipe struct {
	*Pipe
}

func NewJSPipe(eth ethchain.EthManager) *JSPipe {
	return &JSPipe{New(eth)}
}

func (self *JSPipe) BlockByHash(strHash string) *JSBlock {
	hash := ethutil.Hex2Bytes(strHash)
	block := self.obj.BlockChain().GetBlock(hash)

	return NewJSBlock(block)
}

func (self *JSPipe) GetBlockByNumber(num int32) *JSBlock {
	if num == -1 {
		return NewJSBlock(self.obj.BlockChain().CurrentBlock)
	}

	return NewJSBlock(self.obj.BlockChain().GetBlockByNumber(uint64(num)))
}

func (self *JSPipe) Key() *JSKey {
	return NewJSKey(self.obj.KeyManager().KeyPair())
}

func (self *JSPipe) StateObject(addr string) *JSObject {
	object := &Object{self.World().safeGet(ethutil.Hex2Bytes(addr))}

	return NewJSObject(object)
}

func (self *JSPipe) PeerCount() int {
	return self.obj.PeerCount()
}

func (self *JSPipe) Peers() []JSPeer {
	var peers []JSPeer
	for peer := self.obj.Peers().Front(); peer != nil; peer = peer.Next() {
		p := peer.Value.(ethchain.Peer)
		// we only want connected peers
		if atomic.LoadInt32(p.Connected()) != 0 {
			peers = append(peers, *NewJSPeer(p))
		}
	}

	return peers
}

func (self *JSPipe) IsMining() bool {
	return self.obj.IsMining()
}

func (self *JSPipe) IsListening() bool {
	return self.obj.IsListening()
}

func (self *JSPipe) CoinBase() string {
	return ethutil.Bytes2Hex(self.obj.KeyManager().Address())
}

func (self *JSPipe) BalanceAt(addr string) string {
	return self.World().SafeGet(ethutil.Hex2Bytes(addr)).Balance.String()
}

func (self *JSPipe) NumberToHuman(balance string) string {
	b := ethutil.Big(balance)

	return ethutil.CurrencyToString(b)
}

func (self *JSPipe) StorageAt(addr, storageAddr string) string {
	storage := self.World().SafeGet(ethutil.Hex2Bytes(addr)).Storage(ethutil.Hex2Bytes(storageAddr))
	return storage.BigInt().String()
}

func (self *JSPipe) TxCountAt(address string) int {
	return int(self.World().SafeGet(ethutil.Hex2Bytes(address)).Nonce)
}

func (self *JSPipe) IsContract(address string) bool {
	return len(self.World().SafeGet(ethutil.Hex2Bytes(address)).Code) > 0
}

func (self *JSPipe) SecretToAddress(key string) string {
	pair, err := ethcrypto.NewKeyPairFromSec(ethutil.Hex2Bytes(key))
	if err != nil {
		return ""
	}

	return ethutil.Bytes2Hex(pair.Address())
}

type KeyVal struct {
	Key   string `json:"key"`
	Value string `json:"value"`
}

func (self *JSPipe) EachStorage(addr string) string {
	var values []KeyVal
	object := self.World().SafeGet(ethutil.Hex2Bytes(addr))
	object.EachStorage(func(name string, value *ethutil.Value) {
		value.Decode()
		values = append(values, KeyVal{ethutil.Bytes2Hex([]byte(name)), ethutil.Bytes2Hex(value.Bytes())})
	})

	valuesJson, err := json.Marshal(values)
	if err != nil {
		return ""
	}

	return string(valuesJson)
}

func (self *JSPipe) ToAscii(str string) string {
	padded := ethutil.RightPadBytes([]byte(str), 32)

	return "0x" + ethutil.Bytes2Hex(padded)
}

func (self *JSPipe) FromAscii(str string) string {
	if ethutil.IsHex(str) {
		str = str[2:]
	}

	return string(bytes.Trim(ethutil.Hex2Bytes(str), "\x00"))
}

func (self *JSPipe) FromNumber(str string) string {
	if ethutil.IsHex(str) {
		str = str[2:]
	}

	return ethutil.BigD(ethutil.Hex2Bytes(str)).String()
}

func (self *JSPipe) Transact(key, toStr, valueStr, gasStr, gasPriceStr, codeStr string) (*JSReceipt, error) {
	var hash []byte
	var contractCreation bool
	if len(toStr) == 0 {
		contractCreation = true
	} else {
		// Check if an address is stored by this address
		addr := self.World().Config().Get("NameReg").StorageString(toStr).Bytes()
		if len(addr) > 0 {
			hash = addr
		} else {
			hash = ethutil.Hex2Bytes(toStr)
		}
	}

	var keyPair *ethcrypto.KeyPair
	var err error
	if ethutil.IsHex(key) {
		keyPair, err = ethcrypto.NewKeyPairFromSec([]byte(ethutil.Hex2Bytes(key[2:])))
	} else {
		keyPair, err = ethcrypto.NewKeyPairFromSec([]byte(ethutil.Hex2Bytes(key)))
	}

	if err != nil {
		return nil, err
	}

	var (
		value    = ethutil.Big(valueStr)
		gas      = ethutil.Big(gasStr)
		gasPrice = ethutil.Big(gasPriceStr)
		data     []byte
		tx       *ethchain.Transaction
	)

	if ethutil.IsHex(codeStr) {
		data = ethutil.Hex2Bytes(codeStr[2:])
	} else {
		data = ethutil.Hex2Bytes(codeStr)
	}

	if contractCreation {
		tx = ethchain.NewContractCreationTx(value, gas, gasPrice, data)
	} else {
		tx = ethchain.NewTransactionMessage(hash, value, gas, gasPrice, data)
	}

	acc := self.obj.StateManager().TransState().GetOrNewStateObject(keyPair.Address())
	tx.Nonce = acc.Nonce
	acc.Nonce += 1
	self.obj.StateManager().TransState().UpdateStateObject(acc)

	tx.Sign(keyPair.PrivateKey)
	self.obj.TxPool().QueueTransaction(tx)

	if contractCreation {
		logger.Infof("Contract addr %x", tx.CreationAddress())
	}

	return NewJSReciept(contractCreation, tx.CreationAddress(), tx.Hash(), keyPair.Address()), nil
}

func (self *JSPipe) CompileMutan(code string) string {
	data, err := self.Pipe.CompileMutan(code)
	if err != nil {
		return err.Error()
	}

	return ethutil.Bytes2Hex(data)
}

func (self *JSPipe) Watch(object map[string]interface{}) *JSFilter {
	return NewJSFilterFromMap(object, self.Pipe.obj)
	/*} else if str, ok := object.(string); ok {
	println("str")
	return NewJSFilterFromString(str, self.Pipe.obj)
	*/
}

func (self *JSPipe) Messages(object map[string]interface{}) string {
	filter := self.Watch(object)
	filter.Uninstall()

	return filter.Messages()

}

type JSFilter struct {
	eth ethchain.EthManager
	*ethchain.Filter
	quit chan bool

	BlockCallback   func(*ethchain.Block)
	MessageCallback func(ethstate.Messages)
}

func NewJSFilterFromMap(object map[string]interface{}, eth ethchain.EthManager) *JSFilter {
	filter := &JSFilter{eth, ethchain.NewFilterFromMap(object, eth), make(chan bool), nil, nil}

	go filter.mainLoop()

	return filter
}

func NewJSFilterFromString(str string, eth ethchain.EthManager) *JSFilter {
	return nil
}

func (self *JSFilter) MessagesToJson(messages ethstate.Messages) string {
	var msgs []JSMessage
	for _, m := range messages {
		msgs = append(msgs, NewJSMessage(m))
	}

	b, err := json.Marshal(msgs)
	if err != nil {
		return "{\"error\":" + err.Error() + "}"
	}

	return string(b)
}

func (self *JSFilter) Messages() string {
	return self.MessagesToJson(self.Find())
}

func (self *JSFilter) mainLoop() {
	blockChan := make(chan ethreact.Event, 5)
	messageChan := make(chan ethreact.Event, 5)
	// Subscribe to events
	reactor := self.eth.Reactor()
	reactor.Subscribe("newBlock", blockChan)
	reactor.Subscribe("messages", messageChan)
out:
	for {
		select {
		case <-self.quit:
			break out
		case block := <-blockChan:
			if block, ok := block.Resource.(*ethchain.Block); ok {
				if self.BlockCallback != nil {
					self.BlockCallback(block)
				}
			}
		case msg := <-messageChan:
			if messages, ok := msg.Resource.(ethstate.Messages); ok {
				if self.MessageCallback != nil {
					println("messages!")
					msgs := self.FilterMessages(messages)
					if len(msgs) > 0 {
						self.MessageCallback(msgs)
					}
				}
			}
		}
	}
}

func (self *JSFilter) Changed(object interface{}) {
	fmt.Printf("%T\n", object)
}

func (self *JSFilter) Uninstall() {
	self.quit <- true
}
<commit_msg>Added block by hash or number<commit_after>package ethpipe

import (
	"bytes"
	"encoding/json"
	"fmt"
	"sync/atomic"

	"github.com/ethereum/eth-go/ethchain"
	"github.com/ethereum/eth-go/ethcrypto"
	"github.com/ethereum/eth-go/ethreact"
	"github.com/ethereum/eth-go/ethstate"
	"github.com/ethereum/eth-go/ethutil"
)

type JSPipe struct {
	*Pipe
}

func NewJSPipe(eth ethchain.EthManager) *JSPipe {
	return &JSPipe{New(eth)}
}

func (self *JSPipe) BlockByHash(strHash string) *JSBlock {
	hash := ethutil.Hex2Bytes(strHash)
	block := self.obj.BlockChain().GetBlock(hash)

	return NewJSBlock(block)
}

func (self *JSPipe) BlockByNumber(num int32) *JSBlock {
	if num == -1 {
		return NewJSBlock(self.obj.BlockChain().CurrentBlock)
	}

	return NewJSBlock(self.obj.BlockChain().GetBlockByNumber(uint64(num)))
}

func (self *JSPipe) Block(v interface{}) *JSBlock {
	if n, ok := v.(int32); ok {
		return self.BlockByNumber(n)
	} else if str, ok := v.(string); ok {
		return self.BlockByHash(str)
	} else if f, ok := v.(float64); ok { // Don't ask ...
		return self.BlockByNumber(int32(f))
	}

	return nil
}

func (self *JSPipe) Key() *JSKey {
	return NewJSKey(self.obj.KeyManager().KeyPair())
}

func (self *JSPipe) StateObject(addr string) *JSObject {
	object := &Object{self.World().safeGet(ethutil.Hex2Bytes(addr))}

	return NewJSObject(object)
}

func (self *JSPipe) PeerCount() int {
	return self.obj.PeerCount()
}

func (self *JSPipe) Peers() []JSPeer {
	var peers []JSPeer
	for peer := self.obj.Peers().Front(); peer != nil; peer = peer.Next() {
		p := peer.Value.(ethchain.Peer)
		// we only want connected peers
		if atomic.LoadInt32(p.Connected()) != 0 {
			peers = append(peers, *NewJSPeer(p))
		}
	}

	return peers
}

func (self *JSPipe) IsMining() bool {
	return self.obj.IsMining()
}

func (self *JSPipe) IsListening() bool {
	return self.obj.IsListening()
}

func (self *JSPipe) CoinBase() string {
	return ethutil.Bytes2Hex(self.obj.KeyManager().Address())
}

func (self *JSPipe) BalanceAt(addr string) string {
	return self.World().SafeGet(ethutil.Hex2Bytes(addr)).Balance.String()
}

func (self *JSPipe) NumberToHuman(balance string) string {
	b := ethutil.Big(balance)

	return ethutil.CurrencyToString(b)
}

func (self *JSPipe) StorageAt(addr, storageAddr string) string {
	storage := self.World().SafeGet(ethutil.Hex2Bytes(addr)).Storage(ethutil.Hex2Bytes(storageAddr))
	return storage.BigInt().String()
}

func (self *JSPipe) TxCountAt(address string) int {
	return int(self.World().SafeGet(ethutil.Hex2Bytes(address)).Nonce)
}

func (self *JSPipe) IsContract(address string) bool {
	return len(self.World().SafeGet(ethutil.Hex2Bytes(address)).Code) > 0
}

func (self *JSPipe) SecretToAddress(key string) string {
	pair, err := ethcrypto.NewKeyPairFromSec(ethutil.Hex2Bytes(key))
	if err != nil {
		return ""
	}

	return ethutil.Bytes2Hex(pair.Address())
}

type KeyVal struct {
	Key   string `json:"key"`
	Value string `json:"value"`
}

func (self *JSPipe) EachStorage(addr string) string {
	var values []KeyVal
	object := self.World().SafeGet(ethutil.Hex2Bytes(addr))
	object.EachStorage(func(name string, value *ethutil.Value) {
		value.Decode()
		values = append(values, KeyVal{ethutil.Bytes2Hex([]byte(name)), ethutil.Bytes2Hex(value.Bytes())})
	})

	valuesJson, err := json.Marshal(values)
	if err != nil {
		return ""
	}

	return string(valuesJson)
}

func (self *JSPipe) ToAscii(str string) string {
	padded := ethutil.RightPadBytes([]byte(str), 32)

	return "0x" + ethutil.Bytes2Hex(padded)
}

func (self *JSPipe) FromAscii(str string) string {
	if ethutil.IsHex(str) {
		str = str[2:]
	}

	return string(bytes.Trim(ethutil.Hex2Bytes(str), "\x00"))
}

func (self *JSPipe) FromNumber(str string) string {
	if ethutil.IsHex(str) {
		str = str[2:]
	}

	return ethutil.BigD(ethutil.Hex2Bytes(str)).String()
}

func (self *JSPipe) Transact(key, toStr, valueStr, gasStr, gasPriceStr, codeStr string) (*JSReceipt, error) {
	var hash []byte
	var contractCreation bool
	if len(toStr) == 0 {
		contractCreation = true
	} else {
		// Check if an address is stored by this address
		addr := self.World().Config().Get("NameReg").StorageString(toStr).Bytes()
		if len(addr) > 0 {
			hash = addr
		} else {
			hash = ethutil.Hex2Bytes(toStr)
		}
	}

	var keyPair *ethcrypto.KeyPair
	var err error
	if ethutil.IsHex(key) {
		keyPair, err = ethcrypto.NewKeyPairFromSec([]byte(ethutil.Hex2Bytes(key[2:])))
	} else {
		keyPair, err = ethcrypto.NewKeyPairFromSec([]byte(ethutil.Hex2Bytes(key)))
	}

	if err != nil {
		return nil, err
	}

	var (
		value    = ethutil.Big(valueStr)
		gas      = ethutil.Big(gasStr)
		gasPrice = ethutil.Big(gasPriceStr)
		data     []byte
		tx       *ethchain.Transaction
	)

	if ethutil.IsHex(codeStr) {
		data = ethutil.Hex2Bytes(codeStr[2:])
	} else {
		data = ethutil.Hex2Bytes(codeStr)
	}

	if contractCreation {
		tx = ethchain.NewContractCreationTx(value, gas, gasPrice, data)
	} else {
		tx = ethchain.NewTransactionMessage(hash, value, gas, gasPrice, data)
	}

	acc := self.obj.StateManager().TransState().GetOrNewStateObject(keyPair.Address())
	tx.Nonce = acc.Nonce
	acc.Nonce += 1
	self.obj.StateManager().TransState().UpdateStateObject(acc)

	tx.Sign(keyPair.PrivateKey)
	self.obj.TxPool().QueueTransaction(tx)

	if contractCreation {
		logger.Infof("Contract addr %x", tx.CreationAddress())
	}

	return NewJSReciept(contractCreation, tx.CreationAddress(), tx.Hash(), keyPair.Address()), nil
}

func (self *JSPipe) CompileMutan(code string) string {
	data, err := self.Pipe.CompileMutan(code)
	if err != nil {
		return err.Error()
	}

	return ethutil.Bytes2Hex(data)
}

func (self *JSPipe) Watch(object map[string]interface{}) *JSFilter {
	return NewJSFilterFromMap(object, self.Pipe.obj)
	/*} else if str, ok := object.(string); ok {
	println("str")
	return NewJSFilterFromString(str, self.Pipe.obj)
	*/
}

func (self *JSPipe) Messages(object map[string]interface{}) string {
	filter := self.Watch(object)
	filter.Uninstall()

	return filter.Messages()

}

type JSFilter struct {
	eth ethchain.EthManager
	*ethchain.Filter
	quit chan bool

	BlockCallback   func(*ethchain.Block)
	MessageCallback func(ethstate.Messages)
}

func NewJSFilterFromMap(object map[string]interface{}, eth ethchain.EthManager) *JSFilter {
	filter := &JSFilter{eth, ethchain.NewFilterFromMap(object, eth), make(chan bool), nil, nil}

	go filter.mainLoop()

	return filter
}

func NewJSFilterFromString(str string, eth ethchain.EthManager) *JSFilter {
	return nil
}

func (self *JSFilter) MessagesToJson(messages ethstate.Messages) string {
	var msgs []JSMessage
	for _, m := range messages {
		msgs = append(msgs, NewJSMessage(m))
	}

	b, err := json.Marshal(msgs)
	if err != nil {
		return "{\"error\":" + err.Error() + "}"
	}

	return string(b)
}

func (self *JSFilter) Messages() string {
	return self.MessagesToJson(self.Find())
}

func (self *JSFilter) mainLoop() {
	blockChan := make(chan ethreact.Event, 5)
	messageChan := make(chan ethreact.Event, 5)
	// Subscribe to events
	reactor := self.eth.Reactor()
	reactor.Subscribe("newBlock", blockChan)
	reactor.Subscribe("messages", messageChan)
out:
	for {
		select {
		case <-self.quit:
			break out
		case block := <-blockChan:
			if block, ok := block.Resource.(*ethchain.Block); ok {
				if self.BlockCallback != nil {
					self.BlockCallback(block)
				}
			}
		case msg := <-messageChan:
			if messages, ok := msg.Resource.(ethstate.Messages); ok {
				if self.MessageCallback != nil {
					println("messages!")
					msgs := self.FilterMessages(messages)
					if len(msgs) > 0 {
						self.MessageCallback(msgs)
					}
				}
			}
		}
	}
}

func (self *JSFilter) Changed(object interface{}) {
	fmt.Printf("%T\n", object)
}

func (self *JSFilter) Uninstall() {
	self.quit <- true
}
<|endoftext|>


<commit_before>package config

import (
	"bytes"
	"sync"
	"time"

	"github.com/micro/go-micro/v2/config/loader"
	"github.com/micro/go-micro/v2/config/loader/memory"
	"github.com/micro/go-micro/v2/config/reader"
	"github.com/micro/go-micro/v2/config/reader/json"
	"github.com/micro/go-micro/v2/config/source"
)

type config struct {
	exit chan bool
	opts Options

	sync.RWMutex
	// the current snapshot
	snap *loader.Snapshot
	// the current values
	vals reader.Values
}

type watcher struct {
	lw    loader.Watcher
	rd    reader.Reader
	path  []string
	value reader.Value
}

func newConfig(opts ...Option) (Config, error) {
	var c config

	c.Init(opts...)
	go c.run()

	return &c, nil
}

func (c *config) Init(opts ...Option) error {
	c.opts = Options{
		Reader: json.NewReader(),
	}
	c.exit = make(chan bool)
	for _, o := range opts {
		o(&c.opts)
	}

	// default loader uses the configured reader
	if c.opts.Loader == nil {
		c.opts.Loader = memory.NewLoader(memory.WithReader(c.opts.Reader))
	}

	err := c.opts.Loader.Load(c.opts.Source...)
	if err != nil {
		return err
	}

	c.snap, err = c.opts.Loader.Snapshot()
	if err != nil {
		return err
	}

	c.vals, err = c.opts.Reader.Values(c.snap.ChangeSet)
	if err != nil {
		return err
	}

	return nil
}

func (c *config) Options() Options {
	return c.opts
}

func (c *config) run() {
	watch := func(w loader.Watcher) error {
		for {
			// get changeset
			snap, err := w.Next()
			if err != nil {
				return err
			}

			c.Lock()

			if c.snap.Version >= snap.Version {
				c.Unlock()
				continue
			}

			// save
			c.snap = snap

			// set values
			c.vals, _ = c.opts.Reader.Values(snap.ChangeSet)

			c.Unlock()
		}
	}

	for {
		w, err := c.opts.Loader.Watch()
		if err != nil {
			time.Sleep(time.Second)
			continue
		}

		done := make(chan bool)

		// the stop watch func
		go func() {
			select {
			case <-done:
			case <-c.exit:
			}
			w.Stop()
		}()

		// block watch
		if err := watch(w); err != nil {
			// do something better
			time.Sleep(time.Second)
		}

		// close done chan
		close(done)

		// if the config is closed exit
		select {
		case <-c.exit:
			return
		default:
		}
	}
}

func (c *config) Map() map[string]interface{} {
	c.RLock()
	defer c.RUnlock()
	return c.vals.Map()
}

func (c *config) Scan(v interface{}) error {
	c.RLock()
	defer c.RUnlock()
	return c.vals.Scan(v)
}

// sync loads all the sources, calls the parser and updates the config
func (c *config) Sync() error {
	if err := c.opts.Loader.Sync(); err != nil {
		return err
	}

	snap, err := c.opts.Loader.Snapshot()
	if err != nil {
		return err
	}

	c.Lock()
	defer c.Unlock()

	c.snap = snap
	vals, err := c.opts.Reader.Values(snap.ChangeSet)
	if err != nil {
		return err
	}
	c.vals = vals

	return nil
}

func (c *config) Close() error {
	select {
	case <-c.exit:
		return nil
	default:
		close(c.exit)
	}
	return nil
}

func (c *config) Get(path ...string) reader.Value {
	c.RLock()
	defer c.RUnlock()

	// did sync actually work?
	if c.vals != nil {
		return c.vals.Get(path...)
	}

	// no value
	return newValue()
}

func (c *config) Set(val interface{}, path ...string) {
	c.Lock()
	defer c.Unlock()

	if c.vals != nil {
		c.vals.Set(val, path...)
	}

	return
}

func (c *config) Del(path ...string) {
	c.Lock()
	defer c.Unlock()

	if c.vals != nil {
		c.vals.Del(path...)
	}

	return
}

func (c *config) Bytes() []byte {
	c.RLock()
	defer c.RUnlock()

	if c.vals == nil {
		return []byte{}
	}

	return c.vals.Bytes()
}

func (c *config) Load(sources ...source.Source) error {
	if err := c.opts.Loader.Load(sources...); err != nil {
		return err
	}

	snap, err := c.opts.Loader.Snapshot()
	if err != nil {
		return err
	}

	c.Lock()
	defer c.Unlock()

	c.snap = snap
	vals, err := c.opts.Reader.Values(snap.ChangeSet)
	if err != nil {
		return err
	}
	c.vals = vals

	return nil
}

func (c *config) Watch(path ...string) (Watcher, error) {
	value := c.Get(path...)

	w, err := c.opts.Loader.Watch(path...)
	if err != nil {
		return nil, err
	}

	return &watcher{
		lw:    w,
		rd:    c.opts.Reader,
		path:  path,
		value: value,
	}, nil
}

func (c *config) String() string {
	return "config"
}

func (w *watcher) Next() (reader.Value, error) {
	for {
		s, err := w.lw.Next()
		if err != nil {
			return nil, err
		}

		// only process changes
		if bytes.Equal(w.value.Bytes(), s.ChangeSet.Data) {
			continue
		}

		v, err := w.rd.Values(s.ChangeSet)
		if err != nil {
			return nil, err
		}

		w.value = v.Get()
		return w.value, nil
	}
}

func (w *watcher) Stop() error {
	return w.lw.Stop()
}
<commit_msg>do not compare snapshot unless non nil (#1830)<commit_after>package config

import (
	"bytes"
	"sync"
	"time"

	"github.com/micro/go-micro/v2/config/loader"
	"github.com/micro/go-micro/v2/config/loader/memory"
	"github.com/micro/go-micro/v2/config/reader"
	"github.com/micro/go-micro/v2/config/reader/json"
	"github.com/micro/go-micro/v2/config/source"
)

type config struct {
	exit chan bool
	opts Options

	sync.RWMutex
	// the current snapshot
	snap *loader.Snapshot
	// the current values
	vals reader.Values
}

type watcher struct {
	lw    loader.Watcher
	rd    reader.Reader
	path  []string
	value reader.Value
}

func newConfig(opts ...Option) (Config, error) {
	var c config

	c.Init(opts...)
	go c.run()

	return &c, nil
}

func (c *config) Init(opts ...Option) error {
	c.opts = Options{
		Reader: json.NewReader(),
	}
	c.exit = make(chan bool)
	for _, o := range opts {
		o(&c.opts)
	}

	// default loader uses the configured reader
	if c.opts.Loader == nil {
		c.opts.Loader = memory.NewLoader(memory.WithReader(c.opts.Reader))
	}

	err := c.opts.Loader.Load(c.opts.Source...)
	if err != nil {
		return err
	}

	c.snap, err = c.opts.Loader.Snapshot()
	if err != nil {
		return err
	}

	c.vals, err = c.opts.Reader.Values(c.snap.ChangeSet)
	if err != nil {
		return err
	}

	return nil
}

func (c *config) Options() Options {
	return c.opts
}

func (c *config) run() {
	watch := func(w loader.Watcher) error {
		for {
			// get changeset
			snap, err := w.Next()
			if err != nil {
				return err
			}

			c.Lock()

			if c.snap != nil && c.snap.Version >= snap.Version {
				c.Unlock()
				continue
			}

			// save
			c.snap = snap

			// set values
			c.vals, _ = c.opts.Reader.Values(snap.ChangeSet)

			c.Unlock()
		}
	}

	for {
		w, err := c.opts.Loader.Watch()
		if err != nil {
			time.Sleep(time.Second)
			continue
		}

		done := make(chan bool)

		// the stop watch func
		go func() {
			select {
			case <-done:
			case <-c.exit:
			}
			w.Stop()
		}()

		// block watch
		if err := watch(w); err != nil {
			// do something better
			time.Sleep(time.Second)
		}

		// close done chan
		close(done)

		// if the config is closed exit
		select {
		case <-c.exit:
			return
		default:
		}
	}
}

func (c *config) Map() map[string]interface{} {
	c.RLock()
	defer c.RUnlock()
	return c.vals.Map()
}

func (c *config) Scan(v interface{}) error {
	c.RLock()
	defer c.RUnlock()
	return c.vals.Scan(v)
}

// sync loads all the sources, calls the parser and updates the config
func (c *config) Sync() error {
	if err := c.opts.Loader.Sync(); err != nil {
		return err
	}

	snap, err := c.opts.Loader.Snapshot()
	if err != nil {
		return err
	}

	c.Lock()
	defer c.Unlock()

	c.snap = snap
	vals, err := c.opts.Reader.Values(snap.ChangeSet)
	if err != nil {
		return err
	}
	c.vals = vals

	return nil
}

func (c *config) Close() error {
	select {
	case <-c.exit:
		return nil
	default:
		close(c.exit)
	}
	return nil
}

func (c *config) Get(path ...string) reader.Value {
	c.RLock()
	defer c.RUnlock()

	// did sync actually work?
	if c.vals != nil {
		return c.vals.Get(path...)
	}

	// no value
	return newValue()
}

func (c *config) Set(val interface{}, path ...string) {
	c.Lock()
	defer c.Unlock()

	if c.vals != nil {
		c.vals.Set(val, path...)
	}

	return
}

func (c *config) Del(path ...string) {
	c.Lock()
	defer c.Unlock()

	if c.vals != nil {
		c.vals.Del(path...)
	}

	return
}

func (c *config) Bytes() []byte {
	c.RLock()
	defer c.RUnlock()

	if c.vals == nil {
		return []byte{}
	}

	return c.vals.Bytes()
}

func (c *config) Load(sources ...source.Source) error {
	if err := c.opts.Loader.Load(sources...); err != nil {
		return err
	}

	snap, err := c.opts.Loader.Snapshot()
	if err != nil {
		return err
	}

	c.Lock()
	defer c.Unlock()

	c.snap = snap
	vals, err := c.opts.Reader.Values(snap.ChangeSet)
	if err != nil {
		return err
	}
	c.vals = vals

	return nil
}

func (c *config) Watch(path ...string) (Watcher, error) {
	value := c.Get(path...)

	w, err := c.opts.Loader.Watch(path...)
	if err != nil {
		return nil, err
	}

	return &watcher{
		lw:    w,
		rd:    c.opts.Reader,
		path:  path,
		value: value,
	}, nil
}

func (c *config) String() string {
	return "config"
}

func (w *watcher) Next() (reader.Value, error) {
	for {
		s, err := w.lw.Next()
		if err != nil {
			return nil, err
		}

		// only process changes
		if bytes.Equal(w.value.Bytes(), s.ChangeSet.Data) {
			continue
		}

		v, err := w.rd.Values(s.ChangeSet)
		if err != nil {
			return nil, err
		}

		w.value = v.Get()
		return w.value, nil
	}
}

func (w *watcher) Stop() error {
	return w.lw.Stop()
}
<|endoftext|>


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

// Package state manages the meta-data required by consensus for an avalanche
// dag.
package state

import (
	"errors"
	"fmt"

	"github.com/ava-labs/avalanchego/cache"
	"github.com/ava-labs/avalanchego/database"
	"github.com/ava-labs/avalanchego/database/versiondb"
	"github.com/ava-labs/avalanchego/ids"
	"github.com/ava-labs/avalanchego/snow"
	"github.com/ava-labs/avalanchego/snow/choices"
	"github.com/ava-labs/avalanchego/snow/consensus/avalanche"
	"github.com/ava-labs/avalanchego/snow/consensus/snowstorm"
	"github.com/ava-labs/avalanchego/snow/engine/avalanche/vertex"
	"github.com/ava-labs/avalanchego/utils/hashing"
	"github.com/ava-labs/avalanchego/utils/math"
)

const (
	dbCacheSize = 10000
	idCacheSize = 1000
)

var (
	errUnknownVertex = errors.New("unknown vertex")
	errWrongChainID  = errors.New("wrong ChainID in vertex")
)

// Serializer manages the state of multiple vertices
type Serializer struct {
	ctx   *snow.Context
	vm    vertex.DAGVM
	state *prefixedState
	db    *versiondb.Database
	edge  ids.Set
}

// Initialize implements the avalanche.State interface
func (s *Serializer) Initialize(ctx *snow.Context, vm vertex.DAGVM, db database.Database) {
	s.ctx = ctx
	s.vm = vm

	vdb := versiondb.New(db)
	dbCache := &cache.LRU{Size: dbCacheSize}
	rawState := &state{
		serializer: s,
		dbCache:    dbCache,
		db:         vdb,
	}
	s.state = newPrefixedState(rawState, idCacheSize)
	s.db = vdb

	s.edge.Add(s.state.Edge()...)
}

// ParseVertex implements the avalanche.State interface
func (s *Serializer) ParseVertex(b []byte) (avalanche.Vertex, error) {
	return newUniqueVertex(s, b)
}

// BuildVertex implements the avalanche.State interface
func (s *Serializer) BuildVertex(parentIDs []ids.ID, txs []snowstorm.Tx) (avalanche.Vertex, error) {
	if len(txs) == 0 {
		return nil, errNoTxs
	} else if l := len(txs); l > maxTxsPerVtx {
		return nil, fmt.Errorf("number of txs (%d) exceeds max (%d)", l, maxTxsPerVtx)
	} else if l := parentSet.Len(); l > maxNumParents {
		return nil, fmt.Errorf("number of parents (%d) exceeds max (%d)", l, maxNumParents)
	}

	ids.SortIDs(parentIDs)
	sortTxs(txs)

	height := uint64(0)
	for _, parentID := range parentIDs {
		parent, err := s.getVertex(parentID)
		if err != nil {
			return nil, err
		}
		height = math.Max64(height, parent.v.vtx.height)
	}

	vtx := &innerVertex{
		chainID:   s.ctx.ChainID,
		height:    height + 1,
		parentIDs: parentIDs,
		txs:       txs,
	}

	bytes, err := vtx.Marshal()
	if err != nil {
		return nil, err
	}
	vtx.bytes = bytes
	vtx.id = ids.NewID(hashing.ComputeHash256Array(vtx.bytes))

	uVtx := &uniqueVertex{
		serializer: s,
		vtxID:      vtx.ID(),
	}
	// setVertex handles the case where this vertex already exists even
	// though we just made it
	return uVtx, uVtx.setVertex(vtx)
}

// GetVertex implements the avalanche.State interface
func (s *Serializer) GetVertex(vtxID ids.ID) (avalanche.Vertex, error) { return s.getVertex(vtxID) }

// Edge implements the avalanche.State interface
func (s *Serializer) Edge() []ids.ID { return s.edge.List() }

func (s *Serializer) parseVertex(b []byte) (*innerVertex, error) {
	vtx := &innerVertex{}
	if err := vtx.Unmarshal(b, s.vm); err != nil {
		return nil, err
	} else if !vtx.chainID.Equals(s.ctx.ChainID) {
		return nil, errWrongChainID
	}
	return vtx, nil
}

func (s *Serializer) getVertex(vtxID ids.ID) (*uniqueVertex, error) {
	vtx := &uniqueVertex{
		serializer: s,
		vtxID:      vtxID,
	}
	if vtx.Status() == choices.Unknown {
		return nil, errUnknownVertex
	}
	return vtx, nil
}
<commit_msg>fixed merge error<commit_after>// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

// Package state manages the meta-data required by consensus for an avalanche
// dag.
package state

import (
	"errors"
	"fmt"

	"github.com/ava-labs/avalanchego/cache"
	"github.com/ava-labs/avalanchego/database"
	"github.com/ava-labs/avalanchego/database/versiondb"
	"github.com/ava-labs/avalanchego/ids"
	"github.com/ava-labs/avalanchego/snow"
	"github.com/ava-labs/avalanchego/snow/choices"
	"github.com/ava-labs/avalanchego/snow/consensus/avalanche"
	"github.com/ava-labs/avalanchego/snow/consensus/snowstorm"
	"github.com/ava-labs/avalanchego/snow/engine/avalanche/vertex"
	"github.com/ava-labs/avalanchego/utils/hashing"
	"github.com/ava-labs/avalanchego/utils/math"
)

const (
	dbCacheSize = 10000
	idCacheSize = 1000
)

var (
	errUnknownVertex = errors.New("unknown vertex")
	errWrongChainID  = errors.New("wrong ChainID in vertex")
)

// Serializer manages the state of multiple vertices
type Serializer struct {
	ctx   *snow.Context
	vm    vertex.DAGVM
	state *prefixedState
	db    *versiondb.Database
	edge  ids.Set
}

// Initialize implements the avalanche.State interface
func (s *Serializer) Initialize(ctx *snow.Context, vm vertex.DAGVM, db database.Database) {
	s.ctx = ctx
	s.vm = vm

	vdb := versiondb.New(db)
	dbCache := &cache.LRU{Size: dbCacheSize}
	rawState := &state{
		serializer: s,
		dbCache:    dbCache,
		db:         vdb,
	}
	s.state = newPrefixedState(rawState, idCacheSize)
	s.db = vdb

	s.edge.Add(s.state.Edge()...)
}

// ParseVertex implements the avalanche.State interface
func (s *Serializer) ParseVertex(b []byte) (avalanche.Vertex, error) {
	return newUniqueVertex(s, b)
}

// BuildVertex implements the avalanche.State interface
func (s *Serializer) BuildVertex(parentIDs []ids.ID, txs []snowstorm.Tx) (avalanche.Vertex, error) {
	if len(txs) == 0 {
		return nil, errNoTxs
	} else if l := len(txs); l > maxTxsPerVtx {
		return nil, fmt.Errorf("number of txs (%d) exceeds max (%d)", l, maxTxsPerVtx)
	} else if l := len(parentIDs); l > maxNumParents {
		return nil, fmt.Errorf("number of parents (%d) exceeds max (%d)", l, maxNumParents)
	}

	ids.SortIDs(parentIDs)
	sortTxs(txs)

	height := uint64(0)
	for _, parentID := range parentIDs {
		parent, err := s.getVertex(parentID)
		if err != nil {
			return nil, err
		}
		height = math.Max64(height, parent.v.vtx.height)
	}

	vtx := &innerVertex{
		chainID:   s.ctx.ChainID,
		height:    height + 1,
		parentIDs: parentIDs,
		txs:       txs,
	}

	bytes, err := vtx.Marshal()
	if err != nil {
		return nil, err
	}
	vtx.bytes = bytes
	vtx.id = ids.NewID(hashing.ComputeHash256Array(vtx.bytes))

	uVtx := &uniqueVertex{
		serializer: s,
		vtxID:      vtx.ID(),
	}
	// setVertex handles the case where this vertex already exists even
	// though we just made it
	return uVtx, uVtx.setVertex(vtx)
}

// GetVertex implements the avalanche.State interface
func (s *Serializer) GetVertex(vtxID ids.ID) (avalanche.Vertex, error) { return s.getVertex(vtxID) }

// Edge implements the avalanche.State interface
func (s *Serializer) Edge() []ids.ID { return s.edge.List() }

func (s *Serializer) parseVertex(b []byte) (*innerVertex, error) {
	vtx := &innerVertex{}
	if err := vtx.Unmarshal(b, s.vm); err != nil {
		return nil, err
	} else if !vtx.chainID.Equals(s.ctx.ChainID) {
		return nil, errWrongChainID
	}
	return vtx, nil
}

func (s *Serializer) getVertex(vtxID ids.ID) (*uniqueVertex, error) {
	vtx := &uniqueVertex{
		serializer: s,
		vtxID:      vtxID,
	}
	if vtx.Status() == choices.Unknown {
		return nil, errUnknownVertex
	}
	return vtx, nil
}
<|endoftext|>


<commit_before>package engine

import (
	"fmt"

	"github.com/keybase/client/go/libkb"
)

// Identify is an engine to identify a user.
type Identify struct {
	arg       *IdentifyArg
	user      *libkb.User
	me        *libkb.User
	userExpr  libkb.AssertionExpression
	outcome   *libkb.IdentifyOutcome
	trackInst *libkb.TrackInstructions
}

type IdentifyArg struct {
	TargetUsername string // The user being identified, leave blank to identify self
	WithTracking   bool   // true if want tracking statement for logged in user on TargetUsername

	// When tracking is being performed, the identify engine is used with a tracking ui.
	// These options are sent to the ui based on command line options.
	// For normal identify, safe to leave these in their default zero state.
	TrackOptions TrackOptions
}

func NewIdentifyArg(targetUsername string, withTracking bool) *IdentifyArg {
	return &IdentifyArg{
		TargetUsername: targetUsername,
		WithTracking:   withTracking,
	}
}

func NewIdentifyTrackArg(targetUsername string, withTracking bool, options TrackOptions) *IdentifyArg {
	return &IdentifyArg{
		TargetUsername: targetUsername,
		WithTracking:   withTracking,
		TrackOptions:   options,
	}
}

func (ia *IdentifyArg) SelfID() bool {
	return len(ia.TargetUsername) == 0
}

// NewIdentify creates a Identify engine.
func NewIdentify(arg *IdentifyArg) *Identify {
	return &Identify{arg: arg}
}

// Name is the unique engine name.
func (e *Identify) Name() string {
	return "Identify"
}

// GetPrereqs returns the engine prereqs.
func (e *Identify) GetPrereqs() EnginePrereqs {
	// if WithTracking is on, we need to be logged in
	return EnginePrereqs{Session: e.arg.WithTracking}
}

// RequiredUIs returns the required UIs.
func (e *Identify) RequiredUIs() []libkb.UIKind {
	return []libkb.UIKind{
		libkb.IdentifyUIKind,
	}
}

// SubConsumers returns the other UI consumers for this engine.
func (e *Identify) SubConsumers() []libkb.UIConsumer {
	return nil
}

// Run starts the engine.
func (e *Identify) Run(ctx *Context) error {
	if err := e.loadUser(); err != nil {
		return err
	}

	ok, err := IsLoggedIn()
	if err != nil {
		return err
	}
	if ok {
		e.me, err = libkb.LoadMe(libkb.LoadUserArg{})
		if err != nil {
			return err
		}

		if e.user.Equal(*e.me) {
			e.arg.WithTracking = false
		} else {
			e.arg.WithTracking = true
		}
	}

	ctx.IdentifyUI.Start(e.user.GetName())

	e.outcome, err = e.run(ctx)
	if err != nil {
		return err
	}

	// set the flags in the outcome with the track options to
	// inform the ui what to do with the remote tracking prompt:
	e.outcome.LocalOnly = e.arg.TrackOptions.TrackLocalOnly
	e.outcome.ApproveRemote = e.arg.TrackOptions.TrackApprove

	tmp, err := ctx.IdentifyUI.FinishAndPrompt(e.outcome.Export())
	if err != nil {
		return err
	}
	fpr := libkb.ImportFinishAndPromptRes(tmp)
	e.trackInst = &fpr

	return nil
}

func (e *Identify) User() *libkb.User {
	return e.user
}

func (e *Identify) Outcome() *libkb.IdentifyOutcome {
	return e.outcome
}

func (e *Identify) TrackInstructions() *libkb.TrackInstructions {
	return e.trackInst
}

func (e *Identify) run(ctx *Context) (*libkb.IdentifyOutcome, error) {
	res := libkb.NewIdentifyOutcome(e.arg.WithTracking)
	is := libkb.NewIdentifyState(res, e.user)

	if e.arg.WithTracking {
		if e.user.Equal(*e.me) {
			return nil, libkb.SelfTrackError{}
		}

		tlink, err := e.me.GetTrackingStatementFor(e.user.GetName(), e.user.GetUid())
		if err != nil {
			return nil, err
		}
		if tlink != nil {
			is.Track = libkb.NewTrackLookup(tlink)
			res.TrackUsed = is.Track
		}
	}

	ctx.IdentifyUI.ReportLastTrack(libkb.ExportTrackSummary(is.Track))

	G.Log.Debug("+ Identify(%s)", e.user.GetName())

	for _, bundle := range e.user.GetActivePgpKeys(true) {
		fokid := libkb.GenericKeyToFOKID(bundle)
		var diff libkb.TrackDiff
		if is.Track != nil {
			diff = is.Track.ComputeKeyDiff(&fokid)
			// XXX this is probably a bug now that there are multiple pgp keys
			res.KeyDiff = diff
		}
		ctx.IdentifyUI.DisplayKey(fokid.Export(), libkb.ExportTrackDiff(diff))
	}

	is.InitResultList()
	is.ComputeTrackDiffs()
	is.ComputeDeletedProofs()

	ctx.IdentifyUI.LaunchNetworkChecks(res.ExportToUncheckedIdentity(), e.user.Export())
	e.user.IdTable.Identify(is, ctx.IdentifyUI)

	if !e.userExpr.MatchSet(*e.user.ToOkProofSet()) {
		return nil, fmt.Errorf("User %s didn't match given assertion", e.user.GetName())
	}

	G.Log.Debug("- Identify(%s)", e.user.GetName())

	return res, nil
}

func (e *Identify) loadUser() error {
	arg, err := e.loadUserArg()
	if err != nil {
		return err
	}

	u, err := libkb.LoadUser(*arg)
	if err != nil {
		return err
	}
	e.user = u

	if arg.Self {
		// if this was a self load, need to load an assertion expression
		// now that we have the username
		if err := e.loadExpr(e.user.GetName()); err != nil {
			return err
		}
	}

	return nil
}

func (e *Identify) loadUserArg() (*libkb.LoadUserArg, error) {
	if e.arg.SelfID() {
		// loading self
		return &libkb.LoadUserArg{Self: true}, nil
	}

	// Use assertions for everything:
	if err := e.loadExpr(e.arg.TargetUsername); err != nil {
		return nil, err
	}

	// Next, pop off the 'best' assertion and load the user by it.
	// That is, it might be the keybase assertion (if there), or otherwise,
	// something that's unique like Twitter or Github, and lastly,
	// something like DNS that is more likely ambiguous...
	b := e.findBestComponent(e.userExpr)
	if len(b) == 0 {
		return nil, fmt.Errorf("Cannot lookup user with %q", e.arg.TargetUsername)
	}

	return &libkb.LoadUserArg{Name: b}, nil
}

func (e *Identify) loadExpr(assertion string) error {
	// Parse assertion but don't allow OR operators, only AND operators
	expr, err := libkb.AssertionParseAndOnly(assertion)
	if err != nil {
		return fmt.Errorf("assertion parse error: %s", err)
	}
	e.userExpr = expr
	return nil
}

func (e *Identify) findBestComponent(expr libkb.AssertionExpression) string {
	urls := make([]libkb.AssertionUrl, 0, 1)
	urls = expr.CollectUrls(urls)
	if len(urls) == 0 {
		return ""
	}

	var uid, kb, soc, fp libkb.AssertionUrl

	for _, u := range urls {
		if u.IsUid() {
			uid = u
			break
		} else if u.IsKeybase() {
			kb = u
		} else if u.IsFingerprint() && fp == nil {
			fp = u
		} else if u.IsSocial() && soc == nil {
			soc = u
		}
	}

	order := []libkb.AssertionUrl{uid, kb, fp, soc, urls[0]}
	for _, p := range order {
		if p != nil {
			return p.String()
		}
	}
	return ""
}
<commit_msg>Close #298<commit_after>package engine

import (
	"fmt"

	"github.com/keybase/client/go/libkb"
)

// Identify is an engine to identify a user.
type Identify struct {
	arg       *IdentifyArg
	user      *libkb.User
	me        *libkb.User
	userExpr  libkb.AssertionExpression
	outcome   *libkb.IdentifyOutcome
	trackInst *libkb.TrackInstructions
}

type IdentifyArg struct {
	TargetUsername string // The user being identified, leave blank to identify self
	WithTracking   bool   // true if want tracking statement for logged in user on TargetUsername
	AllowSelf      bool   // if we're allowed to id/track ourself

	// When tracking is being performed, the identify engine is used with a tracking ui.
	// These options are sent to the ui based on command line options.
	// For normal identify, safe to leave these in their default zero state.
	TrackOptions TrackOptions
}

func NewIdentifyArg(targetUsername string, withTracking bool) *IdentifyArg {
	return &IdentifyArg{
		TargetUsername: targetUsername,
		WithTracking:   withTracking,
		AllowSelf:      true,
	}
}

func NewIdentifyTrackArg(targetUsername string, withTracking bool, options TrackOptions) *IdentifyArg {
	return &IdentifyArg{
		TargetUsername: targetUsername,
		WithTracking:   withTracking,
		TrackOptions:   options,
		AllowSelf:      false,
	}
}

func (ia *IdentifyArg) SelfID() bool {
	return len(ia.TargetUsername) == 0
}

// NewIdentify creates a Identify engine.
func NewIdentify(arg *IdentifyArg) *Identify {
	return &Identify{arg: arg}
}

// Name is the unique engine name.
func (e *Identify) Name() string {
	return "Identify"
}

// GetPrereqs returns the engine prereqs.
func (e *Identify) GetPrereqs() EnginePrereqs {
	// if WithTracking is on, we need to be logged in
	return EnginePrereqs{Session: e.arg.WithTracking}
}

// RequiredUIs returns the required UIs.
func (e *Identify) RequiredUIs() []libkb.UIKind {
	return []libkb.UIKind{
		libkb.IdentifyUIKind,
	}
}

// SubConsumers returns the other UI consumers for this engine.
func (e *Identify) SubConsumers() []libkb.UIConsumer {
	return nil
}

// Run starts the engine.
func (e *Identify) Run(ctx *Context) error {
	if err := e.loadUser(); err != nil {
		return err
	}

	ok, err := IsLoggedIn()
	if err != nil {
		return err
	}
	if ok {
		e.me, err = libkb.LoadMe(libkb.LoadUserArg{})
		if err != nil {
			return err
		}

		if e.user.Equal(*e.me) {
			e.arg.WithTracking = false
		} else {
			e.arg.WithTracking = true
		}
	}

	ctx.IdentifyUI.Start(e.user.GetName())

	e.outcome, err = e.run(ctx)
	if err != nil {
		return err
	}

	// set the flags in the outcome with the track options to
	// inform the ui what to do with the remote tracking prompt:
	e.outcome.LocalOnly = e.arg.TrackOptions.TrackLocalOnly
	e.outcome.ApproveRemote = e.arg.TrackOptions.TrackApprove

	tmp, err := ctx.IdentifyUI.FinishAndPrompt(e.outcome.Export())
	if err != nil {
		return err
	}
	fpr := libkb.ImportFinishAndPromptRes(tmp)
	e.trackInst = &fpr

	return nil
}

func (e *Identify) User() *libkb.User {
	return e.user
}

func (e *Identify) Outcome() *libkb.IdentifyOutcome {
	return e.outcome
}

func (e *Identify) TrackInstructions() *libkb.TrackInstructions {
	return e.trackInst
}

func (e *Identify) run(ctx *Context) (*libkb.IdentifyOutcome, error) {
	res := libkb.NewIdentifyOutcome(e.arg.WithTracking)
	is := libkb.NewIdentifyState(res, e.user)

	if e.me != nil && e.user.Equal(*e.me) && !e.arg.AllowSelf {
		return nil, libkb.SelfTrackError{}
	}

	if e.arg.WithTracking {

		tlink, err := e.me.GetTrackingStatementFor(e.user.GetName(), e.user.GetUid())
		if err != nil {
			return nil, err
		}
		if tlink != nil {
			is.Track = libkb.NewTrackLookup(tlink)
			res.TrackUsed = is.Track
		}
	}

	ctx.IdentifyUI.ReportLastTrack(libkb.ExportTrackSummary(is.Track))

	G.Log.Debug("+ Identify(%s)", e.user.GetName())

	for _, bundle := range e.user.GetActivePgpKeys(true) {
		fokid := libkb.GenericKeyToFOKID(bundle)
		var diff libkb.TrackDiff
		if is.Track != nil {
			diff = is.Track.ComputeKeyDiff(&fokid)
			// XXX this is probably a bug now that there are multiple pgp keys
			res.KeyDiff = diff
		}
		ctx.IdentifyUI.DisplayKey(fokid.Export(), libkb.ExportTrackDiff(diff))
	}

	is.InitResultList()
	is.ComputeTrackDiffs()
	is.ComputeDeletedProofs()

	ctx.IdentifyUI.LaunchNetworkChecks(res.ExportToUncheckedIdentity(), e.user.Export())
	e.user.IdTable.Identify(is, ctx.IdentifyUI)

	if !e.userExpr.MatchSet(*e.user.ToOkProofSet()) {
		return nil, fmt.Errorf("User %s didn't match given assertion", e.user.GetName())
	}

	G.Log.Debug("- Identify(%s)", e.user.GetName())

	return res, nil
}

func (e *Identify) loadUser() error {
	arg, err := e.loadUserArg()
	if err != nil {
		return err
	}

	u, err := libkb.LoadUser(*arg)
	if err != nil {
		return err
	}
	e.user = u

	if arg.Self {
		// if this was a self load, need to load an assertion expression
		// now that we have the username
		if err := e.loadExpr(e.user.GetName()); err != nil {
			return err
		}
	}

	return nil
}

func (e *Identify) loadUserArg() (*libkb.LoadUserArg, error) {
	if e.arg.SelfID() {
		// loading self
		return &libkb.LoadUserArg{Self: true}, nil
	}

	// Use assertions for everything:
	if err := e.loadExpr(e.arg.TargetUsername); err != nil {
		return nil, err
	}

	// Next, pop off the 'best' assertion and load the user by it.
	// That is, it might be the keybase assertion (if there), or otherwise,
	// something that's unique like Twitter or Github, and lastly,
	// something like DNS that is more likely ambiguous...
	b := e.findBestComponent(e.userExpr)
	if len(b) == 0 {
		return nil, fmt.Errorf("Cannot lookup user with %q", e.arg.TargetUsername)
	}

	return &libkb.LoadUserArg{Name: b}, nil
}

func (e *Identify) loadExpr(assertion string) error {
	// Parse assertion but don't allow OR operators, only AND operators
	expr, err := libkb.AssertionParseAndOnly(assertion)
	if err != nil {
		return fmt.Errorf("assertion parse error: %s", err)
	}
	e.userExpr = expr
	return nil
}

func (e *Identify) findBestComponent(expr libkb.AssertionExpression) string {
	urls := make([]libkb.AssertionUrl, 0, 1)
	urls = expr.CollectUrls(urls)
	if len(urls) == 0 {
		return ""
	}

	var uid, kb, soc, fp libkb.AssertionUrl

	for _, u := range urls {
		if u.IsUid() {
			uid = u
			break
		} else if u.IsKeybase() {
			kb = u
		} else if u.IsFingerprint() && fp == nil {
			fp = u
		} else if u.IsSocial() && soc == nil {
			soc = u
		}
	}

	order := []libkb.AssertionUrl{uid, kb, fp, soc, urls[0]}
	for _, p := range order {
		if p != nil {
			return p.String()
		}
	}
	return ""
}
<|endoftext|>


<commit_before>package index

import (
	"archive/tar"
	"bytes"
	"context"
	"io"

	"github.com/gogo/protobuf/proto"
	"github.com/pachyderm/pachyderm/src/server/pkg/storage/chunk"
)

const (
	indexType        = 'i'
	rangeType        = 'r'
	defaultRangeSize = int64(chunk.MB)
)

// Header is a wrapper for a tar header and index.
type Header struct {
	Hdr *tar.Header
	Idx *Index
}

type levelWriter struct {
	cw *chunk.Writer
	tw *tar.Writer
}

// Writer is used for creating a multi-level index into a serialized FileSet.
// Each index level consists of compressed tar stream chunks.
// Each index tar entry has the full index in the content section.
type Writer struct {
	ctx       context.Context
	chunks    *chunk.Storage
	root      *Header
	levels    []*levelWriter
	rangeSize int64
	closed    bool
	lastPath  string
}

// NewWriter create a new Writer.
func NewWriter(ctx context.Context, chunks *chunk.Storage, rangeSize ...int64) *Writer {
	rSize := defaultRangeSize
	if len(rangeSize) > 0 {
		rSize = rangeSize[0]
	}
	return &Writer{
		ctx:       ctx,
		chunks:    chunks,
		rangeSize: rSize,
	}
}

// WriteHeader writes a Header to the index.
func (w *Writer) WriteHeader(hdr *Header) error {
	// Sets up the root header and first level.
	if w.root == nil {
		w.root = hdr
		cw := w.chunks.NewWriter(w.ctx)
		cw.StartRange(w.callback(hdr, 0))
		w.levels = append(w.levels, &levelWriter{
			cw: cw,
			tw: tar.NewWriter(cw),
		})
	}
	w.lastPath = hdr.Hdr.Name
	if hdr.Idx == nil {
		hdr.Idx = &Index{}
	}
	hdr.Hdr.Typeflag = indexType
	return w.writeHeader(hdr, 0)
}

func (w *Writer) writeHeader(hdr *Header, level int) error {
	l := w.levels[level]
	// Start new range if past range size, and propagate first header up index levels.
	if l.cw.RangeSize() > w.rangeSize {
		l.cw.StartRange(w.callback(hdr, level))
	}
	return w.serialize(l.tw, hdr, level)
}

func (w *Writer) serialize(tw *tar.Writer, hdr *Header, level int) error {
	// Create file range if above lowest index level.
	if level > 0 {
		hdr.Idx.Range = &Range{}
		hdr.Idx.Range.LastPath = w.lastPath
	}
	// Serialize and write additional metadata.
	idx, err := proto.Marshal(hdr.Idx)
	if err != nil {
		return err
	}
	hdr.Hdr.Size = int64(len(idx))
	if err := tw.WriteHeader(hdr.Hdr); err != nil {
		return err
	}
	if _, err = tw.Write(idx); err != nil {
		return err
	}
	return tw.Flush()
}

func (w *Writer) callback(hdr *Header, level int) func([]*chunk.DataRef) error {
	return func(dataRefs []*chunk.DataRef) error {
		hdr.Hdr.Typeflag = rangeType
		// Used to communicate data refs for final index level to Close function.
		if w.closed && w.levels[level].cw.RangeCount() == 1 {
			w.root.Idx.DataOp = &DataOp{DataRefs: dataRefs}
			return nil
		}
		// Create next index level if it does not exist.
		if level == len(w.levels)-1 {
			cw := w.chunks.NewWriter(w.ctx)
			cw.StartRange(w.callback(hdr, level+1))
			w.levels = append(w.levels, &levelWriter{
				cw: cw,
				tw: tar.NewWriter(cw),
			})
		}
		// Write index entry in next level index.
		hdr.Idx.DataOp = &DataOp{DataRefs: dataRefs}
		return w.writeHeader(hdr, level+1)
	}
}

// Close finishes the index, and returns the serialized top level index.
func (w *Writer) Close() (r io.Reader, retErr error) {
	w.closed = true
	// Note: new levels can be created while closing, so the number of iterations
	// necessary can increase as the levels are being closed. The number of ranges
	// will decrease per level as long as the range size is in general larger than
	// a serialized header. Levels stop getting created when the top level chunk
	// writer has been closed and the number of ranges it has is one.
	for i := 0; i < len(w.levels); i++ {
		l := w.levels[i]
		if err := l.tw.Close(); err != nil {
			return nil, err
		}
		if err := l.cw.Close(); err != nil {
			return nil, err
		}
	}
	// Write the final index level that will be readable
	// by the caller.
	buf := &bytes.Buffer{}
	tw := tar.NewWriter(buf)
	defer func() {
		if err := tw.Close(); err != nil && retErr != nil {
			retErr = err
		}
	}()
	if err := w.serialize(tw, w.root, len(w.levels)); err != nil {
		return nil, err
	}
	return buf, nil
}
<commit_msg>Add clarification comment about range size parameter to index writer<commit_after>package index

import (
	"archive/tar"
	"bytes"
	"context"
	"io"

	"github.com/gogo/protobuf/proto"
	"github.com/pachyderm/pachyderm/src/server/pkg/storage/chunk"
)

const (
	indexType        = 'i'
	rangeType        = 'r'
	defaultRangeSize = int64(chunk.MB)
)

// Header is a wrapper for a tar header and index.
type Header struct {
	Hdr *tar.Header
	Idx *Index
}

type levelWriter struct {
	cw *chunk.Writer
	tw *tar.Writer
}

// Writer is used for creating a multi-level index into a serialized FileSet.
// Each index level consists of compressed tar stream chunks.
// Each index tar entry has the full index in the content section.
type Writer struct {
	ctx       context.Context
	chunks    *chunk.Storage
	root      *Header
	levels    []*levelWriter
	rangeSize int64
	closed    bool
	lastPath  string
}

// NewWriter create a new Writer.
// rangeSize should not be used except for testing purposes, the defaultRangeSize will
// be used in a real deployment.
func NewWriter(ctx context.Context, chunks *chunk.Storage, rangeSize ...int64) *Writer {
	rSize := defaultRangeSize
	if len(rangeSize) > 0 {
		rSize = rangeSize[0]
	}
	return &Writer{
		ctx:       ctx,
		chunks:    chunks,
		rangeSize: rSize,
	}
}

// WriteHeader writes a Header to the index.
func (w *Writer) WriteHeader(hdr *Header) error {
	// Sets up the root header and first level.
	if w.root == nil {
		w.root = hdr
		cw := w.chunks.NewWriter(w.ctx)
		cw.StartRange(w.callback(hdr, 0))
		w.levels = append(w.levels, &levelWriter{
			cw: cw,
			tw: tar.NewWriter(cw),
		})
	}
	w.lastPath = hdr.Hdr.Name
	if hdr.Idx == nil {
		hdr.Idx = &Index{}
	}
	hdr.Hdr.Typeflag = indexType
	return w.writeHeader(hdr, 0)
}

func (w *Writer) writeHeader(hdr *Header, level int) error {
	l := w.levels[level]
	// Start new range if past range size, and propagate first header up index levels.
	if l.cw.RangeSize() > w.rangeSize {
		l.cw.StartRange(w.callback(hdr, level))
	}
	return w.serialize(l.tw, hdr, level)
}

func (w *Writer) serialize(tw *tar.Writer, hdr *Header, level int) error {
	// Create file range if above lowest index level.
	if level > 0 {
		hdr.Idx.Range = &Range{}
		hdr.Idx.Range.LastPath = w.lastPath
	}
	// Serialize and write additional metadata.
	idx, err := proto.Marshal(hdr.Idx)
	if err != nil {
		return err
	}
	hdr.Hdr.Size = int64(len(idx))
	if err := tw.WriteHeader(hdr.Hdr); err != nil {
		return err
	}
	if _, err = tw.Write(idx); err != nil {
		return err
	}
	return tw.Flush()
}

func (w *Writer) callback(hdr *Header, level int) func([]*chunk.DataRef) error {
	return func(dataRefs []*chunk.DataRef) error {
		hdr.Hdr.Typeflag = rangeType
		// Used to communicate data refs for final index level to Close function.
		if w.closed && w.levels[level].cw.RangeCount() == 1 {
			w.root.Idx.DataOp = &DataOp{DataRefs: dataRefs}
			return nil
		}
		// Create next index level if it does not exist.
		if level == len(w.levels)-1 {
			cw := w.chunks.NewWriter(w.ctx)
			cw.StartRange(w.callback(hdr, level+1))
			w.levels = append(w.levels, &levelWriter{
				cw: cw,
				tw: tar.NewWriter(cw),
			})
		}
		// Write index entry in next level index.
		hdr.Idx.DataOp = &DataOp{DataRefs: dataRefs}
		return w.writeHeader(hdr, level+1)
	}
}

// Close finishes the index, and returns the serialized top level index.
func (w *Writer) Close() (r io.Reader, retErr error) {
	w.closed = true
	// Note: new levels can be created while closing, so the number of iterations
	// necessary can increase as the levels are being closed. The number of ranges
	// will decrease per level as long as the range size is in general larger than
	// a serialized header. Levels stop getting created when the top level chunk
	// writer has been closed and the number of ranges it has is one.
	for i := 0; i < len(w.levels); i++ {
		l := w.levels[i]
		if err := l.tw.Close(); err != nil {
			return nil, err
		}
		if err := l.cw.Close(); err != nil {
			return nil, err
		}
	}
	// Write the final index level that will be readable
	// by the caller.
	buf := &bytes.Buffer{}
	tw := tar.NewWriter(buf)
	defer func() {
		if err := tw.Close(); err != nil && retErr != nil {
			retErr = err
		}
	}()
	if err := w.serialize(tw, w.root, len(w.levels)); err != nil {
		return nil, err
	}
	return buf, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Kubernetes Authors All rights reserved.

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 collector

import (
	"fmt"
	"testing"

	v1 "k8s.io/api/core/v1"
)

func TestIsHugePageSizeFromResourceName(t *testing.T) {
	testCases := []struct {
		resourceName v1.ResourceName
		expectVal    bool
	}{
		{
			resourceName: "pod.alpha.kubernetes.io/opaque-int-resource-foo",
			expectVal:    false,
		},
		{
			resourceName: "hugepages-100m",
			expectVal:    true,
		},
		{
			resourceName: "",
			expectVal:    false,
		},
	}

	for _, tc := range testCases {
		t.Run(fmt.Sprintf("resourceName input=%s, expected value=%v", tc.resourceName, tc.expectVal), func(t *testing.T) {
			v := isHugePageResourceName(tc.resourceName)
			if v != tc.expectVal {
				t.Errorf("Got %v but expected %v", v, tc.expectVal)
			}
		})
	}
}

func TestIsAttachableVolumeResourceName(t *testing.T) {
	testCases := []struct {
		resourceName v1.ResourceName
		expectVal    bool
	}{
		{
			resourceName: "pod.alpha.kubernetes.io/opaque-int-resource-foo",
			expectVal:    false,
		},
		{
			resourceName: "attachable-volumes-100m",
			expectVal:    true,
		},
		{
			resourceName: "",
			expectVal:    false,
		},
	}

	for _, tc := range testCases {
		t.Run(fmt.Sprintf("resourceName input=%s, expected value=%v", tc.resourceName, tc.expectVal), func(t *testing.T) {
			v := isAttachableVolumeResourceName(tc.resourceName)
			if v != tc.expectVal {
				t.Errorf("Got %v but expected %v", v, tc.expectVal)
			}
		})
	}
}

func TestIsExtendedResourceName(t *testing.T) {
	testCases := []struct {
		resourceName v1.ResourceName
		expectVal    bool
	}{
		{
			resourceName: "pod.alpha.kubernetes.io/opaque-int-resource-foo",
			expectVal:    false,
		},
		{
			resourceName: "kubernetes.io/resource-foo",
			expectVal:    false,
		},
		{
			resourceName: "foo",
			expectVal:    false,
		},
		{
			resourceName: "a/b",
			expectVal:    true,
		},
		{
			resourceName: "requests.foobar",
			expectVal:    false,
		},
		{
			resourceName: "c/d/",
			expectVal:    false,
		},
		{
			resourceName: "",
			expectVal:    false,
		},
	}

	for _, tc := range testCases {
		t.Run(fmt.Sprintf("resourceName input=%s, expected value=%v", tc.resourceName, tc.expectVal), func(t *testing.T) {
			v := isExtendedResourceName(tc.resourceName)
			if v != tc.expectVal {
				t.Errorf("Got %v but expected %v", v, tc.expectVal)
			}
		})
	}
}

func TestKubeLabelsToPrometheusLabels(t *testing.T) {
	testCases := []struct {
		kubeLabels   map[string]string
		expectKeys   []string
		expectValues []string
	}{
		{
			kubeLabels: map[string]string{
				"app1": "normal",
			},
			expectKeys:   []string{"label_app1"},
			expectValues: []string{"normal"},
		},
		{
			kubeLabels: map[string]string{
				"0_app3": "starts_with_digit",
			},
			expectKeys:   []string{"label_0_app3"},
			expectValues: []string{"starts_with_digit"},
		},
		{
			kubeLabels: map[string]string{
				"": "empty",
			},
			expectKeys:   []string{"label_"},
			expectValues: []string{"empty"},
		},
		{
			kubeLabels: map[string]string{
				"$app4": "special_char",
			},
			expectKeys:   []string{"label__app4"},
			expectValues: []string{"special_char"},
		},
		{
			kubeLabels: map[string]string{
				"_app5": "starts_with_underscore",
			},
			expectKeys:   []string{"label__app5"},
			expectValues: []string{"starts_with_underscore"},
		},
	}

	for _, tc := range testCases {
		t.Run(fmt.Sprintf("kubelabels input=%v , expected prometheus keys=%v, expected prometheus values=%v", tc.kubeLabels, tc.expectKeys, tc.expectValues), func(t *testing.T) {
			labelKeys, labelValues := kubeLabelsToPrometheusLabels(tc.kubeLabels)
			if len(labelKeys) != len(tc.expectKeys) {
				t.Errorf("Got Prometheus label keys with len %d but expected %d", len(labelKeys), len(tc.expectKeys))
			}

			if len(labelValues) != len(tc.expectValues) {
				t.Errorf("Got Prometheus label values with len %d but expected %d", len(labelValues), len(tc.expectValues))
			}

			for i := range tc.expectKeys {
				if !(tc.expectKeys[i] == labelKeys[i] && tc.expectValues[i] == labelValues[i]) {
					t.Errorf("Got Prometheus label %q: %q but expected %q: %q", labelKeys[i], labelValues[i], tc.expectKeys[i], tc.expectValues[i])
				}
			}
		})
	}

}

func TestKubeAnnotationsToPrometheusAnootations(t *testing.T) {
	testCases := []struct {
		kubeAnnotations map[string]string
		expectKeys      []string
		expectValues    []string
	}{
		{
			kubeAnnotations: map[string]string{
				"app1": "normal",
			},
			expectKeys:   []string{"annotation_app1"},
			expectValues: []string{"normal"},
		},
		{
			kubeAnnotations: map[string]string{
				"0_app3": "starts_with_digit",
			},
			expectKeys:   []string{"annotation_0_app3"},
			expectValues: []string{"starts_with_digit"},
		},
		{
			kubeAnnotations: map[string]string{
				"": "empty",
			},
			expectKeys:   []string{"annotation_"},
			expectValues: []string{"empty"},
		},
		{
			kubeAnnotations: map[string]string{
				"$app4": "special_char",
			},
			expectKeys:   []string{"annotation__app4"},
			expectValues: []string{"special_char"},
		},
		{
			kubeAnnotations: map[string]string{
				"_app5": "starts_with_underscore",
			},
			expectKeys:   []string{"annotation__app5"},
			expectValues: []string{"starts_with_underscore"},
		},
	}

	for _, tc := range testCases {
		t.Run(fmt.Sprintf("kubeannotations input=%v , expected prometheus keys=%v, expected prometheus values=%v", tc.kubeAnnotations, tc.expectKeys, tc.expectValues), func(t *testing.T) {
			annotationKeys, annotationValues := kubeLabelsToPrometheusLabels(tc.kubeAnnotations)
			if len(annotationKeys) != len(tc.expectKeys) {
				t.Errorf("Got Prometheus label keys with len %d but expected %d", len(annotationKeys), len(tc.expectKeys))
			}

			if len(annotationValues) != len(tc.expectValues) {
				t.Errorf("Got Prometheus label values with len %d but expected %d", len(annotationValues), len(tc.expectValues))
			}

			for i := range tc.expectKeys {
				if !(tc.expectKeys[i] == annotationKeys[i] && tc.expectValues[i] == annotationValues[i]) {
					t.Errorf("Got Prometheus label %q: %q but expected %q: %q", annotationKeys[i], annotationValues[i], tc.expectKeys[i], tc.expectValues[i])
				}
			}
		})
	}

}
<commit_msg>fixing test failure<commit_after>/*
Copyright 2019 The Kubernetes Authors All rights reserved.

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 collector

import (
	"fmt"
	"testing"

	v1 "k8s.io/api/core/v1"
)

func TestIsHugePageSizeFromResourceName(t *testing.T) {
	testCases := []struct {
		resourceName v1.ResourceName
		expectVal    bool
	}{
		{
			resourceName: "pod.alpha.kubernetes.io/opaque-int-resource-foo",
			expectVal:    false,
		},
		{
			resourceName: "hugepages-100m",
			expectVal:    true,
		},
		{
			resourceName: "",
			expectVal:    false,
		},
	}

	for _, tc := range testCases {
		t.Run(fmt.Sprintf("resourceName input=%s, expected value=%v", tc.resourceName, tc.expectVal), func(t *testing.T) {
			v := isHugePageResourceName(tc.resourceName)
			if v != tc.expectVal {
				t.Errorf("Got %v but expected %v", v, tc.expectVal)
			}
		})
	}
}

func TestIsAttachableVolumeResourceName(t *testing.T) {
	testCases := []struct {
		resourceName v1.ResourceName
		expectVal    bool
	}{
		{
			resourceName: "pod.alpha.kubernetes.io/opaque-int-resource-foo",
			expectVal:    false,
		},
		{
			resourceName: "attachable-volumes-100m",
			expectVal:    true,
		},
		{
			resourceName: "",
			expectVal:    false,
		},
	}

	for _, tc := range testCases {
		t.Run(fmt.Sprintf("resourceName input=%s, expected value=%v", tc.resourceName, tc.expectVal), func(t *testing.T) {
			v := isAttachableVolumeResourceName(tc.resourceName)
			if v != tc.expectVal {
				t.Errorf("Got %v but expected %v", v, tc.expectVal)
			}
		})
	}
}

func TestIsExtendedResourceName(t *testing.T) {
	testCases := []struct {
		resourceName v1.ResourceName
		expectVal    bool
	}{
		{
			resourceName: "pod.alpha.kubernetes.io/opaque-int-resource-foo",
			expectVal:    false,
		},
		{
			resourceName: "kubernetes.io/resource-foo",
			expectVal:    false,
		},
		{
			resourceName: "foo",
			expectVal:    false,
		},
		{
			resourceName: "a/b",
			expectVal:    true,
		},
		{
			resourceName: "requests.foobar",
			expectVal:    false,
		},
		{
			resourceName: "c/d/",
			expectVal:    false,
		},
		{
			resourceName: "",
			expectVal:    false,
		},
	}

	for _, tc := range testCases {
		t.Run(fmt.Sprintf("resourceName input=%s, expected value=%v", tc.resourceName, tc.expectVal), func(t *testing.T) {
			v := isExtendedResourceName(tc.resourceName)
			if v != tc.expectVal {
				t.Errorf("Got %v but expected %v", v, tc.expectVal)
			}
		})
	}
}

func TestKubeLabelsToPrometheusLabels(t *testing.T) {
	testCases := []struct {
		kubeLabels   map[string]string
		expectKeys   []string
		expectValues []string
	}{
		{
			kubeLabels: map[string]string{
				"app1": "normal",
			},
			expectKeys:   []string{"label_app1"},
			expectValues: []string{"normal"},
		},
		{
			kubeLabels: map[string]string{
				"0_app3": "starts_with_digit",
			},
			expectKeys:   []string{"label_0_app3"},
			expectValues: []string{"starts_with_digit"},
		},
		{
			kubeLabels: map[string]string{
				"": "empty",
			},
			expectKeys:   []string{"label_"},
			expectValues: []string{"empty"},
		},
		{
			kubeLabels: map[string]string{
				"$app4": "special_char",
			},
			expectKeys:   []string{"label__app4"},
			expectValues: []string{"special_char"},
		},
		{
			kubeLabels: map[string]string{
				"_app5": "starts_with_underscore",
			},
			expectKeys:   []string{"label__app5"},
			expectValues: []string{"starts_with_underscore"},
		},
	}

	for _, tc := range testCases {
		t.Run(fmt.Sprintf("kubelabels input=%v , expected prometheus keys=%v, expected prometheus values=%v", tc.kubeLabels, tc.expectKeys, tc.expectValues), func(t *testing.T) {
			labelKeys, labelValues := kubeLabelsToPrometheusLabels(tc.kubeLabels)
			if len(labelKeys) != len(tc.expectKeys) {
				t.Errorf("Got Prometheus label keys with len %d but expected %d", len(labelKeys), len(tc.expectKeys))
			}

			if len(labelValues) != len(tc.expectValues) {
				t.Errorf("Got Prometheus label values with len %d but expected %d", len(labelValues), len(tc.expectValues))
			}

			for i := range tc.expectKeys {
				if !(tc.expectKeys[i] == labelKeys[i] && tc.expectValues[i] == labelValues[i]) {
					t.Errorf("Got Prometheus label %q: %q but expected %q: %q", labelKeys[i], labelValues[i], tc.expectKeys[i], tc.expectValues[i])
				}
			}
		})
	}

}

func TestKubeAnnotationsToPrometheusAnnotations(t *testing.T) {
	testCases := []struct {
		kubeAnnotations map[string]string
		expectKeys      []string
		expectValues    []string
	}{
		{
			kubeAnnotations: map[string]string{
				"app1": "normal",
			},
			expectKeys:   []string{"annotation_app1"},
			expectValues: []string{"normal"},
		},
		{
			kubeAnnotations: map[string]string{
				"0_app3": "starts_with_digit",
			},
			expectKeys:   []string{"annotation_0_app3"},
			expectValues: []string{"starts_with_digit"},
		},
		{
			kubeAnnotations: map[string]string{
				"": "empty",
			},
			expectKeys:   []string{"annotation_"},
			expectValues: []string{"empty"},
		},
		{
			kubeAnnotations: map[string]string{
				"$app4": "special_char",
			},
			expectKeys:   []string{"annotation__app4"},
			expectValues: []string{"special_char"},
		},
		{
			kubeAnnotations: map[string]string{
				"_app5": "starts_with_underscore",
			},
			expectKeys:   []string{"annotation__app5"},
			expectValues: []string{"starts_with_underscore"},
		},
	}

	for _, tc := range testCases {
		t.Run(fmt.Sprintf("kubeannotations input=%v , expected prometheus keys=%v, expected prometheus values=%v", tc.kubeAnnotations, tc.expectKeys, tc.expectValues), func(t *testing.T) {
			annotationKeys, annotationValues := kubeAnnotationsToPrometheusAnnotations(tc.kubeAnnotations)
			if len(annotationKeys) != len(tc.expectKeys) {
				t.Errorf("Got Prometheus label keys with len %d but expected %d", len(annotationKeys), len(tc.expectKeys))
			}

			if len(annotationValues) != len(tc.expectValues) {
				t.Errorf("Got Prometheus label values with len %d but expected %d", len(annotationValues), len(tc.expectValues))
			}

			for i := range tc.expectKeys {
				if !(tc.expectKeys[i] == annotationKeys[i] && tc.expectValues[i] == annotationValues[i]) {
					t.Errorf("Got Prometheus label %q: %q but expected %q: %q", annotationKeys[i], annotationValues[i], tc.expectKeys[i], tc.expectValues[i])
				}
			}
		})
	}

}
<|endoftext|>


<commit_before>// Copyright 2015 ikawaha
//
// 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 lattice

import (
	"bytes"
	"testing"
	"unicode/utf8"

	"github.com/ikawaha/kagome/internal/dic"
)

func TestLatticeBuild01(t *testing.T) {
	la := New(dic.SysDic(), nil)
	if la == nil {
		t.Error("cannot new a lattice")
	}
	defer la.Free()

	inp := ""
	la.Build(inp)
	if la.Input != inp {
		t.Errorf("got %v, expected %v", la.Input, inp)
	}
	boseos := node{ID: -1}
	if len(la.list) != 2 {
		t.Errorf("lattice initialize error: got %v, expected has 2 eos/bos nodes", la.list)
	} else if len(la.list[0]) != 1 || *la.list[0][0] != boseos {
		t.Errorf("lattice initialize error: got %v, expected %v", *la.list[0][0], boseos)
	} else if len(la.list[1]) != 1 || *la.list[1][0] != boseos {
		t.Errorf("lattice initialize error: got %v, expected %v", *la.list[1][0], boseos)
	}
	if len(la.Output) != 0 {
		t.Errorf("lattice initialize error: got %v, expected empty", la.Output)
	}

	if la.dic == nil {
		t.Errorf("lattice initialize error: dic is nil")
	}
	if la.udic != nil {
		t.Errorf("lattice initialize error: got %v, expected empty", la.udic)
	}
}

func TestLatticeBuild02(t *testing.T) {
	la := New(dic.SysDic(), nil)
	if la == nil {
		t.Fatal("cannot new a lattice")
	}
	defer la.Free()

	inp := "あ"
	la.Build(inp)
	if la.Input != inp {
		t.Errorf("got %v, expected %v", la.Input, inp)
	}
	bos := node{ID: -1}
	eos := node{ID: -1, Start: 1}
	if len(la.list) != 3 {
		t.Errorf("lattice initialize error: got %v, expected has 2 eos/bos nodes", la.list)
	} else if len(la.list[0]) != 1 || *la.list[0][0] != bos {
		t.Errorf("lattice initialize error: got %v, expected %v", *la.list[0][0], bos)
	} else if len(la.list[2]) != 1 || *la.list[2][0] != eos {
		t.Errorf("lattice initialize error: got %v, expected %v", *la.list[2][0], eos)
	}

	expected := 4
	if len(la.list[1]) != expected {
		t.Errorf("lattice initialize error: got %v, expected %v", len(la.list[1]), expected)
	} else {
		l := la.list[1]
		callAndResponse := []struct {
			in  int
			out node
		}{
			{in: 0, out: node{122, 0, KNOWN, 0, 3, 3, 5549, "あ", nil}},
			{in: 1, out: node{123, 0, KNOWN, 0, 776, 776, 6690, "あ", nil}},
			{in: 2, out: node{124, 0, KNOWN, 0, 2, 2, 4262, "あ", nil}},
			{in: 3, out: node{125, 0, KNOWN, 0, 1118, 1118, 9035, "あ", nil}},
		}
		for _, cr := range callAndResponse {
			if *l[cr.in] != cr.out {
				t.Errorf("lattice initialize error: got %v, expected %v", l[cr.in], cr.out)
			}
		}
	}
	if len(la.Output) != 0 {
		t.Errorf("lattice initialize error: got %v, expected empty", la.Output)
	}
	if la.dic == nil {
		t.Errorf("lattice initialize error: dic is nil")
	}
	if la.udic != nil {
		t.Errorf("lattice initialize error: got %v, expected empty", la.udic)
	}
}

func TestLatticeBuild03(t *testing.T) {

	const udicPath = "../../_sample/userdic.txt"

	udic, e := dic.NewUserDic(udicPath)
	if e != nil {
		t.Fatalf("unexpected error: cannot load user dic, %v", e)
	}
	la := New(dic.SysDic(), udic)
	if la == nil {
		t.Fatal("cannot new a lattice")
	}
	defer la.Free()

	inp := "朝青龍"
	la.Build(inp)
	if la.Input != inp {
		t.Errorf("got %v, expected %v", la.Input, inp)
	}

	if la.list[3][0].Class != USER {
		t.Errorf("%+v", la)
	}

	if len(la.Output) != 0 {
		t.Errorf("lattice initialize error: got %v, expected empty", la.Output)
	}
	if la.dic == nil {
		t.Errorf("lattice initialize error: dic is nil")
	}
	if la.udic == nil {
		t.Errorf("lattice initialize error: got %v, expected not empty", la.udic)
	}
}

func TestLatticeBuild04(t *testing.T) {
	la := New(dic.SysDic(), nil)
	if la == nil {
		t.Fatal("cannot new a lattice")
	}
	defer la.Free()

	inp := "ポポピ"
	la.Build(inp)
	if la.Input != inp {
		t.Errorf("got %v, expected %v", la.Input, inp)
	}
	bos := node{ID: -1}
	eos := node{ID: -1, Start: 3}
	if len(la.list) != 5 {
		t.Errorf("lattice initialize error: got %v, expected has 2 eos/bos nodes", la.list)
	} else if len(la.list[0]) != 1 || *la.list[0][0] != bos {
		t.Errorf("lattice initialize error: got %v, expected %v", *la.list[0][0], bos)
	} else if len(la.list[len(la.list)-1]) != 1 || *la.list[len(la.list)-1][0] != eos {
		t.Errorf("lattice initialize error: got %v, expected %v", *la.list[len(la.list)-1][0], eos)
	}

	expected := 7
	if len(la.list[1]) != expected {
		t.Errorf("lattice initialize error: got %v, expected %v", len(la.list[1]), expected)
	} else {
		l := la.list[1]
		callAndResponse := []struct {
			in  int
			out node
		}{
			{in: 0, out: node{98477, 0, KNOWN, 0, 1285, 1285, 4279, "ポ", nil}},
			{in: 1, out: node{31, 0, UNKNOWN, 0, 1289, 1289, 13581, "ポ", nil}},
			{in: 2, out: node{32, 0, UNKNOWN, 0, 1285, 1285, 9461, "ポ", nil}},
			{in: 3, out: node{33, 0, UNKNOWN, 0, 1293, 1293, 13661, "ポ", nil}},
			{in: 4, out: node{34, 0, UNKNOWN, 0, 1292, 1292, 10922, "ポ", nil}},
			{in: 5, out: node{35, 0, UNKNOWN, 0, 1288, 1288, 10521, "ポ", nil}},
			{in: 6, out: node{36, 0, UNKNOWN, 0, 3, 3, 14138, "ポ", nil}},
		}
		for _, cr := range callAndResponse {
			if *l[cr.in] != cr.out {
				t.Errorf("lattice initialize error: got %v, expected %v", l[cr.in], cr.out)
			}
		}
	}
	if len(la.Output) != 0 {
		t.Errorf("lattice initialize error: got %v, expected empty", la.Output)
	}
	if la.dic == nil {
		t.Errorf("lattice initialize error: dic is nil")
	}
	if la.udic != nil {
		t.Errorf("lattice initialize error: got %v, expected empty", la.udic)
	}
}

func TestLatticeBuild05(t *testing.T) {

	la := New(dic.SysDic(), nil)
	if la == nil {
		t.Fatal("cannot new a lattice")
	}
	defer la.Free()

	inp := "ポポピポンポコナーノ"
	var b bytes.Buffer
	for i, step := 0, utf8.RuneCountInString(inp); i < maximumUnknownWordLength; i = i + step {
		if _, e := b.WriteString(inp); e != nil {
			t.Fatalf("unexpected error: create the test input, %v", b.String())
		}
	}
	la.Build(b.String())
	for i := range la.list {
		for j := range la.list[i] {
			l := utf8.RuneCountInString(la.list[i][j].Surface)
			if l > maximumUnknownWordLength {
				t.Errorf("too long unknown word, %v", l)
			}
		}
	}
}

func TestKanjiOnly01(t *testing.T) {
	callAndResponse := []struct {
		in  string
		out bool
	}{
		{in: "ひらがな", out: false},
		{in: "カタカナ", out: false},
		{in: "漢字", out: true},
		{in: "かな漢字交じり", out: false},
		{in: "123", out: false},
		{in: "#$%", out: false},
		{in: "", out: false},
	}
	for _, cr := range callAndResponse {
		if rsp := kanjiOnly(cr.in); rsp != cr.out {
			t.Errorf("in: %v, got %v, expected: %v", cr.in, rsp, cr.out)
		}
	}
}

func TestLatticeString(t *testing.T) {
	la := New(dic.SysDic(), nil)
	if la == nil {
		t.Fatal("cannot new a lattice")
	}
	defer la.Free()

	expected := ""
	str := la.String()
	if str != expected {
		t.Errorf("got %v, expected: %v", str, expected)
	}

	la.Build("わたしまけましたわ")
	str = la.String()
	if str == "" {
		t.Errorf("got empty string")
	}
}

func TestLatticeDot(t *testing.T) {
	la := New(dic.SysDic(), nil)
	if la == nil {
		t.Fatal("cannot new a lattice")
	}
	defer la.Free()

	expected := "graph lattice {\n\tdpi=48;\n\tgraph [style=filled, rankdir=LR]\n}\n"
	var b bytes.Buffer
	la.Dot(&b)
	if b.String() != expected {
		t.Errorf("got %v, expected: %v", b.String(), expected)
	}
	b.Reset()
	la.Build("わたしまけましたわ")
	la.Dot(&b)
	if b.String() == "" {
		t.Errorf("got empty string")
	}
}

func TestLatticeNewAndFree(t *testing.T) {
	for i := 0; i < 100; i++ {
		la := New(dic.SysDic(), nil)
		if la == nil {
			t.Fatal("unexpected error: cannot new a lattice")
		}
		if la.Input != "" {
			t.Fatalf("unexpected error: lattice input initialize error, %+v", la.Input)
		}
		if len(la.Output) != 0 {
			t.Fatalf("unexpected error: lattice output initialize error, %+v", la.Output)
		}
		if len(la.list) != 0 {
			t.Fatalf("unexpected error: lattice list initialize error, %+v", la.list)
		}
		la.Build("すべては科学する心に宿るのだ")
		la.Free()

		// renew
		la = New(dic.SysDic(), nil)
		if la == nil {
			t.Fatal("unexpected error: cannot new a lattice")
		}
		if la.Input != "" {
			t.Fatalf("unexpected error: lattice input initialize error, %+v", la.Input)
		}
		if len(la.Output) != 0 {
			t.Fatalf("unexpected error: lattice output initialize error, %+v", la.Output)
		}
		if len(la.list) != 0 {
			t.Fatalf("unexpected error: lattice list initialize error, %+v", la.list)
		}
		la.Free()
	}
}

func TestForward(t *testing.T) {
	la := New(dic.SysDic(), nil)
	if la == nil {
		t.Fatal("unexpected error: cannot new a lattice")
	}

	la.Forward(Normal)
	la.Forward(Search)
	la.Forward(Extended)

	for _, m := range []TokenizeMode{Normal, Search, Extended} {
		la.Build("わたしまけましたわ．関西国際空港．ポポポポポポポポポポ")
		la.Forward(m)
	}
}

func TestBackward01(t *testing.T) {
	la := New(dic.SysDic(), nil)
	if la == nil {
		t.Fatal("unexpected error: cannot new a lattice")
	}

	// only run
	la.Backward(Normal)
	la.Backward(Search)
	la.Backward(Extended)

	for _, m := range []TokenizeMode{Normal, Search, Extended} {
		la.Build("わたしまけましたわ．ポポピ")
		la.Forward(m)
		la.Backward(m)
	}
}
<commit_msg>Fix a test<commit_after>// Copyright 2015 ikawaha
//
// 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 lattice

import (
	"bytes"
	"testing"
	"unicode/utf8"

	"github.com/ikawaha/kagome/internal/dic"
)

func TestLatticeBuild01(t *testing.T) {
	la := New(dic.SysDic(), nil)
	if la == nil {
		t.Error("cannot new a lattice")
	}
	defer la.Free()

	inp := ""
	la.Build(inp)
	if la.Input != inp {
		t.Errorf("got %v, expected %v", la.Input, inp)
	}
	boseos := node{ID: -1}
	if len(la.list) != 2 {
		t.Errorf("lattice initialize error: got %v, expected has 2 eos/bos nodes", la.list)
	} else if len(la.list[0]) != 1 || *la.list[0][0] != boseos {
		t.Errorf("lattice initialize error: got %v, expected %v", *la.list[0][0], boseos)
	} else if len(la.list[1]) != 1 || *la.list[1][0] != boseos {
		t.Errorf("lattice initialize error: got %v, expected %v", *la.list[1][0], boseos)
	}
	if len(la.Output) != 0 {
		t.Errorf("lattice initialize error: got %v, expected empty", la.Output)
	}

	if la.dic == nil {
		t.Errorf("lattice initialize error: dic is nil")
	}
	if la.udic != nil {
		t.Errorf("lattice initialize error: got %v, expected empty", la.udic)
	}
}

func TestLatticeBuild02(t *testing.T) {
	la := New(dic.SysDic(), nil)
	if la == nil {
		t.Fatal("cannot new a lattice")
	}
	defer la.Free()

	inp := "あ"
	la.Build(inp)
	if la.Input != inp {
		t.Errorf("got %v, expected %v", la.Input, inp)
	}
	bos := node{ID: -1}
	eos := node{ID: -1, Start: 1}
	if len(la.list) != 3 {
		t.Errorf("lattice initialize error: got %v, expected has 2 eos/bos nodes", la.list)
	} else if len(la.list[0]) != 1 || *la.list[0][0] != bos {
		t.Errorf("lattice initialize error: got %v, expected %v", *la.list[0][0], bos)
	} else if len(la.list[2]) != 1 || *la.list[2][0] != eos {
		t.Errorf("lattice initialize error: got %v, expected %v", *la.list[2][0], eos)
	}

	expected := 4
	if len(la.list[1]) != expected {
		t.Errorf("lattice initialize error: got %v, expected %v", len(la.list[1]), expected)
	} else {
		l := la.list[1]
		callAndResponse := []struct {
			in  int
			out node
		}{
			{in: 0, out: node{122, 0, KNOWN, 0, 3, 3, 5549, "あ", nil}},
			{in: 1, out: node{123, 0, KNOWN, 0, 776, 776, 6690, "あ", nil}},
			{in: 2, out: node{124, 0, KNOWN, 0, 2, 2, 4262, "あ", nil}},
			{in: 3, out: node{125, 0, KNOWN, 0, 1118, 1118, 9035, "あ", nil}},
		}
		for _, cr := range callAndResponse {
			if *l[cr.in] != cr.out {
				t.Errorf("lattice initialize error: got %v, expected %v", l[cr.in], cr.out)
			}
		}
	}
	if len(la.Output) != 0 {
		t.Errorf("lattice initialize error: got %v, expected empty", la.Output)
	}
	if la.dic == nil {
		t.Errorf("lattice initialize error: dic is nil")
	}
	if la.udic != nil {
		t.Errorf("lattice initialize error: got %v, expected empty", la.udic)
	}
}

func TestLatticeBuild03(t *testing.T) {

	const udicPath = "../../_sample/userdic.txt"

	udic, e := dic.NewUserDic(udicPath)
	if e != nil {
		t.Fatalf("unexpected error: cannot load user dic, %v", e)
	}
	la := New(dic.SysDic(), udic)
	if la == nil {
		t.Fatal("cannot new a lattice")
	}
	defer la.Free()

	inp := "朝青龍"
	la.Build(inp)
	if la.Input != inp {
		t.Errorf("got %v, expected %v", la.Input, inp)
	}

	if la.list[3][0].Class != USER {
		t.Errorf("%+v", la)
	}

	if len(la.Output) != 0 {
		t.Errorf("lattice initialize error: got %v, expected empty", la.Output)
	}
	if la.dic == nil {
		t.Errorf("lattice initialize error: dic is nil")
	}
	if la.udic == nil {
		t.Errorf("lattice initialize error: got %v, expected not empty", la.udic)
	}
}

func TestLatticeBuild04(t *testing.T) {
	la := New(dic.SysDic(), nil)
	if la == nil {
		t.Fatal("cannot new a lattice")
	}
	defer la.Free()

	inp := "ポポピ"
	la.Build(inp)
	if la.Input != inp {
		t.Errorf("got %v, expected %v", la.Input, inp)
	}
	bos := node{ID: -1}
	eos := node{ID: -1, Start: 3}
	if len(la.list) != 5 {
		t.Errorf("lattice initialize error: got %v, expected has 2 eos/bos nodes", la.list)
	} else if len(la.list[0]) != 1 || *la.list[0][0] != bos {
		t.Errorf("lattice initialize error: got %v, expected %v", *la.list[0][0], bos)
	} else if len(la.list[len(la.list)-1]) != 1 || *la.list[len(la.list)-1][0] != eos {
		t.Errorf("lattice initialize error: got %v, expected %v", *la.list[len(la.list)-1][0], eos)
	}

	expected := 7
	if len(la.list[1]) != expected {
		t.Errorf("lattice initialize error: got %v, expected %v", len(la.list[1]), expected)
	} else {
		l := la.list[1]
		callAndResponse := []struct {
			in  int
			out node
		}{
			{in: 0, out: node{98477, 0, KNOWN, 0, 1285, 1285, 4279, "ポ", nil}},
			{in: 1, out: node{31, 0, UNKNOWN, 0, 1289, 1289, 13581, "ポ", nil}},
			{in: 2, out: node{32, 0, UNKNOWN, 0, 1285, 1285, 9461, "ポ", nil}},
			{in: 3, out: node{33, 0, UNKNOWN, 0, 1293, 1293, 13661, "ポ", nil}},
			{in: 4, out: node{34, 0, UNKNOWN, 0, 1292, 1292, 10922, "ポ", nil}},
			{in: 5, out: node{35, 0, UNKNOWN, 0, 1288, 1288, 10521, "ポ", nil}},
			{in: 6, out: node{36, 0, UNKNOWN, 0, 3, 3, 14138, "ポ", nil}},
		}
		for _, cr := range callAndResponse {
			if *l[cr.in] != cr.out {
				t.Errorf("lattice initialize error: got %v, expected %v", l[cr.in], cr.out)
			}
		}
	}
	if len(la.Output) != 0 {
		t.Errorf("lattice initialize error: got %v, expected empty", la.Output)
	}
	if la.dic == nil {
		t.Errorf("lattice initialize error: dic is nil")
	}
	if la.udic != nil {
		t.Errorf("lattice initialize error: got %v, expected empty", la.udic)
	}
}

func TestLatticeBuild05(t *testing.T) {

	la := New(dic.SysDic(), nil)
	if la == nil {
		t.Fatal("cannot new a lattice")
	}
	defer la.Free()

	inp := "ポポピポンポコナーノ"
	var b bytes.Buffer
	for i, step := 0, utf8.RuneCountInString(inp); i < maximumUnknownWordLength; i = i + step {
		if _, e := b.WriteString(inp); e != nil {
			t.Fatalf("unexpected error: create the test input, %v", b.String())
		}
	}
	la.Build(b.String())
	for i := range la.list {
		for j := range la.list[i] {
			l := utf8.RuneCountInString(la.list[i][j].Surface)
			if l > maximumUnknownWordLength {
				t.Errorf("too long unknown word, %v", l)
			}
		}
	}
}

func TestKanjiOnly01(t *testing.T) {
	callAndResponse := []struct {
		in  string
		out bool
	}{
		{in: "ひらがな", out: false},
		{in: "カタカナ", out: false},
		{in: "漢字", out: true},
		{in: "かな漢字交じり", out: false},
		{in: "123", out: false},
		{in: "#$%", out: false},
		{in: "", out: false},
	}
	for _, cr := range callAndResponse {
		if rsp := kanjiOnly(cr.in); rsp != cr.out {
			t.Errorf("in: %v, got %v, expected: %v", cr.in, rsp, cr.out)
		}
	}
}

func TestLatticeString(t *testing.T) {
	la := New(dic.SysDic(), nil)
	if la == nil {
		t.Fatal("cannot new a lattice")
	}
	defer la.Free()

	expected := ""
	str := la.String()
	if str != expected {
		t.Errorf("got %v, expected: %v", str, expected)
	}

	la.Build("わたしまけましたわ")
	str = la.String()
	if str == "" {
		t.Errorf("got empty string")
	}
}

func TestLatticeDot(t *testing.T) {
	la := New(dic.SysDic(), nil)
	if la == nil {
		t.Fatal("cannot new a lattice")
	}
	defer la.Free()

	expected := "graph lattice {\n\tdpi=48;\n\tgraph [style=filled, rankdir=LR]\n}\n"
	var b bytes.Buffer
	la.Dot(&b)
	if b.String() != expected {
		t.Errorf("got %v, expected: %v", b.String(), expected)
	}
	b.Reset()
	la.Build("わたしまけましたわ")
	la.Dot(&b)
	if b.String() == "" {
		t.Errorf("got empty string")
	}
}

func TestLatticeNewAndFree(t *testing.T) {
	for i := 0; i < 100; i++ {
		la := New(dic.SysDic(), nil)
		if la == nil {
			t.Fatal("unexpected error: cannot new a lattice")
		}
		if la.Input != "" {
			t.Fatalf("unexpected error: lattice input initialize error, %+v", la.Input)
		}
		if len(la.Output) != 0 {
			t.Fatalf("unexpected error: lattice output initialize error, %+v", la.Output)
		}
		if len(la.list) != 0 {
			t.Fatalf("unexpected error: lattice list initialize error, %+v", la.list)
		}
		la.Build("すべては科学する心に宿るのだ")
		la.Free()

		// renew
		la = New(dic.SysDic(), nil)
		if la == nil {
			t.Fatal("unexpected error: cannot new a lattice")
		}
		if la.Input != "" {
			t.Fatalf("unexpected error: lattice input initialize error, %+v", la.Input)
		}
		if len(la.Output) != 0 {
			t.Fatalf("unexpected error: lattice output initialize error, %+v", la.Output)
		}
		if len(la.list) != 0 {
			t.Fatalf("unexpected error: lattice list initialize error, %+v", la.list)
		}
		la.Free()
	}
}

func TestForward(t *testing.T) {
	la := New(dic.SysDic(), nil)
	if la == nil {
		t.Fatal("unexpected error: cannot new a lattice")
	}

	la.Forward(Normal)
	la.Forward(Search)
	la.Forward(Extended)

	for _, m := range []TokenizeMode{Normal, Search, Extended} {
		la.Build("わたしまけましたわ．関西国際空港．ポポポポポポポポポポ．\U0001f363\U0001f363\U0001f363\U0001f363\U0001f363\U0001f363\U0001f363\U0001f363\U0001f363\U0001f363")
		la.Forward(m)
	}
}

func TestBackward01(t *testing.T) {
	la := New(dic.SysDic(), nil)
	if la == nil {
		t.Fatal("unexpected error: cannot new a lattice")
	}

	// only run
	la.Backward(Normal)
	la.Backward(Search)
	la.Backward(Extended)

	for _, m := range []TokenizeMode{Normal, Search, Extended} {
		la.Build("わたしまけましたわ．ポポピ")
		la.Forward(m)
		la.Backward(m)
	}
}
<|endoftext|>


<commit_before>package ca

import (
	"encoding/json"
	"errors"
	"fmt"

	"github.com/cloudflare/cfssl/config"
	"github.com/cloudflare/cfssl/csr"
)

// Config stores configuration information for the CA.
type Config struct {
	CN         string
	Name       csr.Name             `json:"name"`
	KeyRequest *csr.BasicKeyRequest `json:"key"`

	Usage        []string            `json:"usages"`
	ExpiryString string              `json:"expiry"`
	CAConstraint config.CAConstraint `json:"ca_constraint"`
}

// DefaultConfig defines the default configuration for a CA.
var DefaultConfig = &Config{
	KeyRequest:   &csr.BasicKeyRequest{"rsa", 4096},
	Usage:        []string{"cert sign", "crl sign"},
	ExpiryString: "43800h",
}

// LoadConfig attempts to load the configuration from a byte slice. On
// error, it returns nil.
func LoadConfig(data []byte) (*Config, error) {
	var cfg = &Config{}
	err := json.Unmarshal(data, &cfg)
	if err != nil {
		return nil, fmt.Errorf("failed to unmarshal configuration: %s", err.Error())
	}

	if cfg.CN == "" {
		return nil, errors.New("empty common name in CA config")
	}
	if cfg.KeyRequest == nil {
		cfg.KeyRequest = DefaultConfig.KeyRequest
	}
	if len(cfg.Usage) > 0 {
		cfg.Usage = DefaultConfig.Usage
	}
	if cfg.ExpiryString == "" {
		cfg.ExpiryString = DefaultConfig.ExpiryString
	}

	return cfg, nil
}

// Signing returns a CFSSL signing policy derived from the Config.
func (cfg *Config) Signing() (*config.Signing, error) {
	cfsslConfig := &config.Config{
		Signing: &config.Signing{
			Default: &config.SigningProfile{
				Usage:        cfg.Usage,
				ExpiryString: cfg.ExpiryString,
				CAConstraint: cfg.CAConstraint,
			},
		},
	}

	// CFSSL config.LoadConfig will call the private function populate()
	// for each signing profile.
	buf, err := json.Marshal(cfsslConfig)
	if err != nil {
		return nil, err
	}
	cfsslConfig, err = config.LoadConfig(buf)
	if err != nil {
		return nil, err
	}

	return cfsslConfig.Signing, nil
}

// CertificateRequest returns a CFSSL certificate request for the CA.
func (cfg *Config) CertificateRequest() *csr.CertificateRequest {
	return &csr.CertificateRequest{
		CN:         cfg.CN,
		Names:      []csr.Name{cfg.Name},
		KeyRequest: cfg.KeyRequest,
	}
}
<commit_msg>Fix bug in applying default usage for ca.Config<commit_after>package ca

import (
	"encoding/json"
	"errors"
	"fmt"

	"github.com/cloudflare/cfssl/config"
	"github.com/cloudflare/cfssl/csr"
)

// Config stores configuration information for the CA.
type Config struct {
	CN         string
	Name       csr.Name             `json:"name"`
	KeyRequest *csr.BasicKeyRequest `json:"key"`

	Usage        []string            `json:"usages"`
	ExpiryString string              `json:"expiry"`
	CAConstraint config.CAConstraint `json:"ca_constraint"`
}

// DefaultConfig defines the default configuration for a CA.
var DefaultConfig = &Config{
	KeyRequest:   &csr.BasicKeyRequest{"rsa", 4096},
	Usage:        []string{"cert sign", "crl sign"},
	ExpiryString: "43800h",
}

// LoadConfig attempts to load the configuration from a byte slice. On
// error, it returns nil.
func LoadConfig(data []byte) (*Config, error) {
	var cfg = &Config{}
	err := json.Unmarshal(data, &cfg)
	if err != nil {
		return nil, fmt.Errorf("failed to unmarshal configuration: %s", err.Error())
	}

	if cfg.CN == "" {
		return nil, errors.New("empty common name in CA config")
	}
	if cfg.KeyRequest == nil {
		cfg.KeyRequest = DefaultConfig.KeyRequest
	}
	if len(cfg.Usage) == 0 {
		cfg.Usage = DefaultConfig.Usage
	}
	if cfg.ExpiryString == "" {
		cfg.ExpiryString = DefaultConfig.ExpiryString
	}

	return cfg, nil
}

// Signing returns a CFSSL signing policy derived from the Config.
func (cfg *Config) Signing() (*config.Signing, error) {
	cfsslConfig := &config.Config{
		Signing: &config.Signing{
			Default: &config.SigningProfile{
				Usage:        cfg.Usage,
				ExpiryString: cfg.ExpiryString,
				CAConstraint: cfg.CAConstraint,
			},
		},
	}

	// CFSSL config.LoadConfig will call the private function populate()
	// for each signing profile.
	buf, err := json.Marshal(cfsslConfig)
	if err != nil {
		return nil, err
	}
	cfsslConfig, err = config.LoadConfig(buf)
	if err != nil {
		return nil, err
	}

	return cfsslConfig.Signing, nil
}

// CertificateRequest returns a CFSSL certificate request for the CA.
func (cfg *Config) CertificateRequest() *csr.CertificateRequest {
	return &csr.CertificateRequest{
		CN:         cfg.CN,
		Names:      []csr.Name{cfg.Name},
		KeyRequest: cfg.KeyRequest,
	}
}
<|endoftext|>