<commit_before>package zwave

import (
	"bytes"
	"encoding/binary"
	"errors"
)

type FrameHeader uint8
type FrameType uint8

const (
	FrameHeaderData uint8 = 0x01
	FrameHeaderAck  uint8 = 0x06
	FrameHeaderNak  uint8 = 0x15
	FrameHeaderCan  uint8 = 0x18
)

const (
	FrameTypeReq uint8 = 0x00
	FrameTypeRes uint8 = 0x01
)

type ZFrame struct {

	// Header is one of FrameHeader*
	Header uint8

	// Length = byte length of all fields, excluding Header and Checksum
	Length uint8

	// Type is one of FrameType*
	Type uint8

	// Payload is the command id and command payload
	Payload []byte

	// Checksum = 0xff XOR Type XOR Length XOR payload[0] XOR [...payload[n]]
	Checksum uint8
}

func NewRequestFrame(payload []byte) *ZFrame {
	frame := ZFrame{
		Header:  FrameHeaderData,
		Type:    FrameTypeReq,
		Length:  uint8(len(payload) + 2), // payload length plus Type and Length
		Payload: payload,
	}

	frame.SetChecksum()

	return &frame
}

func NewNakFrame() *ZFrame {
	return &ZFrame{
		Header: FrameHeaderNak,
	}
}

func NewAckFrame() *ZFrame {
	return &ZFrame{
		Header: FrameHeaderAck,
	}
}

func NewCanFrame() *ZFrame {
	return &ZFrame{
		Header: FrameHeaderCan,
	}
}

func (z *ZFrame) IsRequest() bool {
	return z.Type == FrameTypeReq
}

func (z *ZFrame) IsResponse() bool {
	return z.Type == FrameTypeRes
}

func (z *ZFrame) IsAck() bool {
	return z.Header == FrameHeaderAck
}

// CalcChecksum calculates the checksum for this frame, given the current data.
// The Z-Wave checksum is calculated by taking 0xFF XOR Length XOR Type XOR Payload[0:n]
func (z *ZFrame) CalcChecksum() uint8 {
	var csum uint8 = 0xff
	csum ^= z.Length
	csum ^= z.Type

	for i := 0; i < len(z.Payload); i++ {
		csum ^= z.Payload[i]
	}

	return csum
}

// SetChecksum calculates the frame checksum and saves it into the frame
func (z *ZFrame) SetChecksum() {
	z.Checksum = z.CalcChecksum()
}

// VerifyChecksum calculates a checksum for the frame and compares it to the
// frame's checksum, returning an error if they do not agree
func (z *ZFrame) VerifyChecksum() error {
	if z.Header != FrameHeaderData {
		return nil
	}

	if z.Checksum != z.CalcChecksum() {
		return errors.New("Invalid checksum")
	}

	return nil
}

// Marshal this frame into a byte slice
func (z *ZFrame) Marshal() []byte {
	buf := new(bytes.Buffer)

	switch z.Header {
	case FrameHeaderData:
		// Data frames have the whole kit and caboodle
		binary.Write(buf, binary.BigEndian, uint8(z.Header))
		binary.Write(buf, binary.BigEndian, uint8(z.Length))
		binary.Write(buf, binary.BigEndian, uint8(z.Type))
		buf.Write(z.Payload)
		binary.Write(buf, binary.BigEndian, uint8(z.Checksum))
	default:
		// Non-data frames are just a single byte
		binary.Write(buf, binary.BigEndian, uint8(z.Header))
	}

	return buf.Bytes()
}

// UnmarshalFrame turns a byte slice into a ZFrame
func UnmarshalFrame(frame []byte) *ZFrame {
	if frame[0] != FrameHeaderData {
		return &ZFrame{
			Header: frame[0],
		}
	}

	return &ZFrame{
		Header:   frame[0],
		Length:   frame[1],
		Type:     frame[2],
		Payload:  frame[3 : len(frame)-2],
		Checksum: frame[len(frame)-1],
	}
}
<commit_msg>IsNak, IsCan, and IsData frame helper methods<commit_after>package zwave

import (
	"bytes"
	"encoding/binary"
	"errors"
)

type FrameHeader uint8
type FrameType uint8

const (
	FrameHeaderData uint8 = 0x01
	FrameHeaderAck  uint8 = 0x06
	FrameHeaderNak  uint8 = 0x15
	FrameHeaderCan  uint8 = 0x18
)

const (
	FrameTypeReq uint8 = 0x00
	FrameTypeRes uint8 = 0x01
)

type ZFrame struct {

	// Header is one of FrameHeader*
	Header uint8

	// Length = byte length of all fields, excluding Header and Checksum
	Length uint8

	// Type is one of FrameType*
	Type uint8

	// Payload is the command id and command payload
	Payload []byte

	// Checksum = 0xff XOR Type XOR Length XOR payload[0] XOR [...payload[n]]
	Checksum uint8
}

func NewRequestFrame(payload []byte) *ZFrame {
	frame := ZFrame{
		Header:  FrameHeaderData,
		Type:    FrameTypeReq,
		Length:  uint8(len(payload) + 2), // payload length plus Type and Length
		Payload: payload,
	}

	frame.SetChecksum()

	return &frame
}

func NewNakFrame() *ZFrame {
	return &ZFrame{
		Header: FrameHeaderNak,
	}
}

func NewAckFrame() *ZFrame {
	return &ZFrame{
		Header: FrameHeaderAck,
	}
}

func NewCanFrame() *ZFrame {
	return &ZFrame{
		Header: FrameHeaderCan,
	}
}

func (z *ZFrame) IsRequest() bool {
	return z.Type == FrameTypeReq
}

func (z *ZFrame) IsResponse() bool {
	return z.Type == FrameTypeRes
}

func (z *ZFrame) IsAck() bool {
	return z.Header == FrameHeaderAck
}

func (z *ZFrame) IsNak() bool {
	return z.Header == FrameHeaderNak
}

func (z *ZFrame) IsCan() bool {
	return z.Header == FrameHeaderCan
}

func (z *ZFrame) IsData() bool {
	return z.Header == FrameHeaderData
}

// CalcChecksum calculates the checksum for this frame, given the current data.
// The Z-Wave checksum is calculated by taking 0xFF XOR Length XOR Type XOR Payload[0:n]
func (z *ZFrame) CalcChecksum() uint8 {
	var csum uint8 = 0xff
	csum ^= z.Length
	csum ^= z.Type

	for i := 0; i < len(z.Payload); i++ {
		csum ^= z.Payload[i]
	}

	return csum
}

// SetChecksum calculates the frame checksum and saves it into the frame
func (z *ZFrame) SetChecksum() {
	z.Checksum = z.CalcChecksum()
}

// VerifyChecksum calculates a checksum for the frame and compares it to the
// frame's checksum, returning an error if they do not agree
func (z *ZFrame) VerifyChecksum() error {
	if z.Header != FrameHeaderData {
		return nil
	}

	if z.Checksum != z.CalcChecksum() {
		return errors.New("Invalid checksum")
	}

	return nil
}

// Marshal this frame into a byte slice
func (z *ZFrame) Marshal() []byte {
	buf := new(bytes.Buffer)

	switch z.Header {
	case FrameHeaderData:
		// Data frames have the whole kit and caboodle
		binary.Write(buf, binary.BigEndian, uint8(z.Header))
		binary.Write(buf, binary.BigEndian, uint8(z.Length))
		binary.Write(buf, binary.BigEndian, uint8(z.Type))
		buf.Write(z.Payload)
		binary.Write(buf, binary.BigEndian, uint8(z.Checksum))
	default:
		// Non-data frames are just a single byte
		binary.Write(buf, binary.BigEndian, uint8(z.Header))
	}

	return buf.Bytes()
}

// UnmarshalFrame turns a byte slice into a ZFrame
func UnmarshalFrame(frame []byte) *ZFrame {
	if frame[0] != FrameHeaderData {
		return &ZFrame{
			Header: frame[0],
		}
	}

	return &ZFrame{
		Header:   frame[0],
		Length:   frame[1],
		Type:     frame[2],
		Payload:  frame[3 : len(frame)-2],
		Checksum: frame[len(frame)-1],
	}
}
<|endoftext|>


<commit_before>// +build linux

package linux

import (
	"os"
	"testing"
)

func TestInterfaceGenerator(t *testing.T) {
	if _, err := os.Stat("/etc/fedora-release"); err == nil {
		t.Skip("The OS seems to be Fedora. Skipping interface test for now")
	}

	g := &InterfaceGenerator{1}
	values, err := g.Generate()
	if err != nil {
		t.Error("should not raise error")
	}

	metrics := []string{
		"rxBytes", "txBytes",
	}

	for _, metric := range metrics {
		if value, ok := values["interface.eth0."+metric+".delta"]; !ok {
			t.Errorf("Value for interface.eth0.%s.delta should be collected", metric)
		} else {
			t.Logf("Interface eth0 '%s' delta collected: %+v", metric, value)
		}
	}

	for _, metric := range metrics {
		if _, ok := values["interface.lo."+metric+".delta"]; ok {
			t.Errorf("Value for interface.lo.%s should NOT be collected", metric)
		} else {
			t.Logf("Interface lo '%s' NOT collected", metric)
		}
	}
}
<commit_msg>skip network test in travis for now<commit_after>// +build linux

package linux

import (
	"os"
	"testing"
)

func TestInterfaceGenerator(t *testing.T) {
	if _, err := os.Stat("/etc/fedora-release"); err == nil {
		t.Skip("The OS seems to be Fedora. Skipping interface test for now")
	}

	if os.Getenv("TRAVIS") != "" {
		t.Skip("Skip: in Travis, Skipping interface test for now")
	}

	g := &InterfaceGenerator{1}
	values, err := g.Generate()
	if err != nil {
		t.Error("should not raise error")
	}

	metrics := []string{
		"rxBytes", "txBytes",
	}

	for _, metric := range metrics {
		if value, ok := values["interface.eth0."+metric+".delta"]; !ok {
			t.Errorf("Value for interface.eth0.%s.delta should be collected", metric)
		} else {
			t.Logf("Interface eth0 '%s' delta collected: %+v", metric, value)
		}
	}

	for _, metric := range metrics {
		if _, ok := values["interface.lo."+metric+".delta"]; ok {
			t.Errorf("Value for interface.lo.%s should NOT be collected", metric)
		} else {
			t.Logf("Interface lo '%s' NOT collected", metric)
		}
	}
}
<|endoftext|>


<commit_before>package goose

import (
	"github.com/PuerkitoBio/goquery"
	"net/url"
	"regexp"
	"strconv"
	"strings"
)

type candidate struct {
	url     string
	surface int
	score   int
}

func (c *candidate) GetUrl() string {
	return c.url
}

var largebig = regexp.MustCompile("(large|big|full)")

var classRules = map[*regexp.Regexp]int{
	regexp.MustCompile("(promo|ads|banner)"): -1}

var rules = map[*regexp.Regexp]int{
	largebig:                                   1,
	regexp.MustCompile("upload"):               1,
	regexp.MustCompile("media"):                1,
	regexp.MustCompile("gravatar.com"):         -1,
	regexp.MustCompile("feeds.feedburner.com"): -1,
	regexp.MustCompile("(?i)icon"):             -1,
	regexp.MustCompile("(?i)logo"):             -1,
	regexp.MustCompile("(?i)spinner"):          -1,
	regexp.MustCompile("(?i)loading"):          -1,
	regexp.MustCompile("(?i)ads"):              -1,
	regexp.MustCompile("badge"):                -1,
	regexp.MustCompile("1x1"):                  -1,
	regexp.MustCompile("pixel"):                -1,
	regexp.MustCompile("thumbnail[s]*"):        -1,
	regexp.MustCompile(".html|" +
		".gif|" +
		".ico|" +
		"button|" +
		"twitter.jpg|" +
		"facebook.jpg|" +
		"ap_buy_photo|" +
		"digg.jpg|" +
		"digg.png|" +
		"delicious.png|" +
		"facebook.png|" +
		"reddit.jpg|" +
		"doubleclick|" +
		"diggthis|" +
		"diggThis|" +
		"adserver|" +
		"/(ads|promos|banners)/|" +
		"ec.atdmt.com|" +
		"mediaplex.com|" +
		"adsatt|" +
		"view.atdmt"): -1}

func getImageSrc(tag *goquery.Selection) string {
	src, _ := tag.Attr("src")
	// skip inline images
	if strings.Contains(src, "data:image/") {
		src = ""
	}
	if src == "" {
		src, _ = tag.Attr("data-src")
	}
	if src == "" {
		src, _ = tag.Attr("data-lazy-src")
	}
	return src
}

func score(tag *goquery.Selection) int {
	src := getImageSrc(tag)
	if src == "" {
		return -1
	}
	tagScore := 0
	for rule, score := range rules {
		if rule.MatchString(src) {
			tagScore += score
		}
	}

	alt, exists := tag.Attr("alt")
	if exists {
		if strings.Contains(alt, "thumbnail") {
			tagScore--
		}
	}

	id, exists := tag.Attr("id")
	if exists {
		if id == "fbPhotoImage" {
			tagScore++
		}
	}

	class, exists := tag.Attr("class")
	if exists {
		for rule, score := range classRules {
			if rule.MatchString(class) {
				tagScore += score
			}
		}
	}

	return tagScore
}

// WebPageResolver fetches all candidate images from the HTML page
func WebPageImageResolver(doc *goquery.Document) ([]candidate, int) {
	imgs := doc.Find("img")

	var candidates []candidate
	significantSurface := 320 * 200
	significantSurfaceCount := 0
	src := ""
	imgs.Each(func(i int, tag *goquery.Selection) {
		var surface int
		src = getImageSrc(tag)
		if src == "" {
			return
		}

		width, _ := tag.Attr("width")
		height, _ := tag.Attr("height")
		if width != "" {
			w, _ := strconv.Atoi(width)
			if height != "" {
				h, _ := strconv.Atoi(height)
				surface = w * h
			} else {
				surface = w
			}
		} else {
			if height != "" {
				surface, _ = strconv.Atoi(height)
			} else {
				surface = 0
			}
		}

		if surface > significantSurface {
			significantSurfaceCount++
		}

		tagscore := score(tag)
		if tagscore >= 0 {
			c := candidate{
				url:     src,
				surface: surface,
				score:   score(tag),
			}
			candidates = append(candidates, c)
		}
	})

	if len(candidates) == 0 {
		return nil, 0
	}

	return candidates, significantSurfaceCount

}

// WebPageResolver fetches the main image from the HTML page
func WebPageResolver(article *Article) string {
	candidates, significantSurfaceCount := WebPageImageResolver(article.Doc)
	if candidates == nil {
		return ""
	}
	var bestCandidate candidate
	var topImage string
	if significantSurfaceCount > 0 {
		bestCandidate = findBestCandidateFromSurface(candidates)
	} else {
		bestCandidate = findBestCandidateFromScore(candidates)
	}

	topImage = bestCandidate.url
	a, err := url.Parse(topImage)
	if err != nil {
		return topImage
	}
	finalURL, err := url.Parse(article.FinalURL)
	if err != nil {
		return topImage
	}
	b := finalURL.ResolveReference(a)
	topImage = b.String()

	return topImage
}

func findBestCandidateFromSurface(candidates []candidate) candidate {
	max := 0
	var bestCandidate candidate
	for _, candidate := range candidates {
		surface := candidate.surface
		if surface >= max {
			max = surface
			bestCandidate = candidate
		}
	}

	return bestCandidate
}

func findBestCandidateFromScore(candidates []candidate) candidate {
	max := 0
	var bestCandidate candidate
	for _, candidate := range candidates {
		score := candidate.score
		if score >= max {
			max = score
			bestCandidate = candidate
		}
	}

	return bestCandidate
}

type ogTag struct {
	tpe       string
	attribute string
	name      string
	value     string
}

var ogTags = [4]ogTag{
	{
		tpe:       "facebook",
		attribute: "property",
		name:      "og:image",
		value:     "content",
	},
	{
		tpe:       "facebook",
		attribute: "rel",
		name:      "image_src",
		value:     "href",
	},
	{
		tpe:       "twitter",
		attribute: "name",
		name:      "twitter:image",
		value:     "value",
	},
	{
		tpe:       "twitter",
		attribute: "name",
		name:      "twitter:image",
		value:     "content",
	},
}

type ogImage struct {
	url   string
	tpe   string
	score int
}

// OpenGraphResolver return OpenGraph properties
func OpenGraphResolver(doc *goquery.Document) string {
	meta := doc.Find("meta")
	links := doc.Find("link")
	var topImage string
	meta = meta.Union(links)
	var ogImages []ogImage
	meta.Each(func(i int, tag *goquery.Selection) {
		for _, ogTag := range ogTags {
			attr, exist := tag.Attr(ogTag.attribute)
			value, vexist := tag.Attr(ogTag.value)
			if exist && attr == ogTag.name && vexist {
				ogImage := ogImage{
					url:   value,
					tpe:   ogTag.tpe,
					score: 0,
				}

				ogImages = append(ogImages, ogImage)
			}
		}
	})
	if len(ogImages) == 0 {
		return ""
	}
	if len(ogImages) == 1 {
		topImage = ogImages[0].url
		goto IMAGE_FINALIZE
	}
	for _, ogImage := range ogImages {
		if largebig.MatchString(ogImage.url) {
			ogImage.score++
		}
		if ogImage.tpe == "twitter" {
			ogImage.score++
		}
	}
	topImage = findBestImageFromScore(ogImages).url
IMAGE_FINALIZE:
	if !strings.HasPrefix(topImage, "http") {
		topImage = "http://" + topImage
	}

	return topImage
}

// assume that len(ogImages)>=2
func findBestImageFromScore(ogImages []ogImage) ogImage {
	max := 0
	bestOGImage := ogImages[0]
	for _, ogImage := range ogImages[1:] {
		score := ogImage.score
		if score > max {
			max = score
			bestOGImage = ogImage
		}
	}

	return bestOGImage
}
<commit_msg>Fix function comments based on best practices from Effective Go<commit_after>package goose

import (
	"github.com/PuerkitoBio/goquery"
	"net/url"
	"regexp"
	"strconv"
	"strings"
)

type candidate struct {
	url     string
	surface int
	score   int
}

func (c *candidate) GetUrl() string {
	return c.url
}

var largebig = regexp.MustCompile("(large|big|full)")

var classRules = map[*regexp.Regexp]int{
	regexp.MustCompile("(promo|ads|banner)"): -1}

var rules = map[*regexp.Regexp]int{
	largebig:                                   1,
	regexp.MustCompile("upload"):               1,
	regexp.MustCompile("media"):                1,
	regexp.MustCompile("gravatar.com"):         -1,
	regexp.MustCompile("feeds.feedburner.com"): -1,
	regexp.MustCompile("(?i)icon"):             -1,
	regexp.MustCompile("(?i)logo"):             -1,
	regexp.MustCompile("(?i)spinner"):          -1,
	regexp.MustCompile("(?i)loading"):          -1,
	regexp.MustCompile("(?i)ads"):              -1,
	regexp.MustCompile("badge"):                -1,
	regexp.MustCompile("1x1"):                  -1,
	regexp.MustCompile("pixel"):                -1,
	regexp.MustCompile("thumbnail[s]*"):        -1,
	regexp.MustCompile(".html|" +
		".gif|" +
		".ico|" +
		"button|" +
		"twitter.jpg|" +
		"facebook.jpg|" +
		"ap_buy_photo|" +
		"digg.jpg|" +
		"digg.png|" +
		"delicious.png|" +
		"facebook.png|" +
		"reddit.jpg|" +
		"doubleclick|" +
		"diggthis|" +
		"diggThis|" +
		"adserver|" +
		"/(ads|promos|banners)/|" +
		"ec.atdmt.com|" +
		"mediaplex.com|" +
		"adsatt|" +
		"view.atdmt"): -1}

func getImageSrc(tag *goquery.Selection) string {
	src, _ := tag.Attr("src")
	// skip inline images
	if strings.Contains(src, "data:image/") {
		src = ""
	}
	if src == "" {
		src, _ = tag.Attr("data-src")
	}
	if src == "" {
		src, _ = tag.Attr("data-lazy-src")
	}
	return src
}

func score(tag *goquery.Selection) int {
	src := getImageSrc(tag)
	if src == "" {
		return -1
	}
	tagScore := 0
	for rule, score := range rules {
		if rule.MatchString(src) {
			tagScore += score
		}
	}

	alt, exists := tag.Attr("alt")
	if exists {
		if strings.Contains(alt, "thumbnail") {
			tagScore--
		}
	}

	id, exists := tag.Attr("id")
	if exists {
		if id == "fbPhotoImage" {
			tagScore++
		}
	}

	class, exists := tag.Attr("class")
	if exists {
		for rule, score := range classRules {
			if rule.MatchString(class) {
				tagScore += score
			}
		}
	}

	return tagScore
}

// WebPageImageResolver fetches all candidate images from the HTML page
func WebPageImageResolver(doc *goquery.Document) ([]candidate, int) {
	imgs := doc.Find("img")

	var candidates []candidate
	significantSurface := 320 * 200
	significantSurfaceCount := 0
	src := ""
	imgs.Each(func(i int, tag *goquery.Selection) {
		var surface int
		src = getImageSrc(tag)
		if src == "" {
			return
		}

		width, _ := tag.Attr("width")
		height, _ := tag.Attr("height")
		if width != "" {
			w, _ := strconv.Atoi(width)
			if height != "" {
				h, _ := strconv.Atoi(height)
				surface = w * h
			} else {
				surface = w
			}
		} else {
			if height != "" {
				surface, _ = strconv.Atoi(height)
			} else {
				surface = 0
			}
		}

		if surface > significantSurface {
			significantSurfaceCount++
		}

		tagscore := score(tag)
		if tagscore >= 0 {
			c := candidate{
				url:     src,
				surface: surface,
				score:   score(tag),
			}
			candidates = append(candidates, c)
		}
	})

	if len(candidates) == 0 {
		return nil, 0
	}

	return candidates, significantSurfaceCount

}

// WebPageResolver fetches the main image from the HTML page
func WebPageResolver(article *Article) string {
	candidates, significantSurfaceCount := WebPageImageResolver(article.Doc)
	if candidates == nil {
		return ""
	}
	var bestCandidate candidate
	var topImage string
	if significantSurfaceCount > 0 {
		bestCandidate = findBestCandidateFromSurface(candidates)
	} else {
		bestCandidate = findBestCandidateFromScore(candidates)
	}

	topImage = bestCandidate.url
	a, err := url.Parse(topImage)
	if err != nil {
		return topImage
	}
	finalURL, err := url.Parse(article.FinalURL)
	if err != nil {
		return topImage
	}
	b := finalURL.ResolveReference(a)
	topImage = b.String()

	return topImage
}

func findBestCandidateFromSurface(candidates []candidate) candidate {
	max := 0
	var bestCandidate candidate
	for _, candidate := range candidates {
		surface := candidate.surface
		if surface >= max {
			max = surface
			bestCandidate = candidate
		}
	}

	return bestCandidate
}

func findBestCandidateFromScore(candidates []candidate) candidate {
	max := 0
	var bestCandidate candidate
	for _, candidate := range candidates {
		score := candidate.score
		if score >= max {
			max = score
			bestCandidate = candidate
		}
	}

	return bestCandidate
}

type ogTag struct {
	tpe       string
	attribute string
	name      string
	value     string
}

var ogTags = [4]ogTag{
	{
		tpe:       "facebook",
		attribute: "property",
		name:      "og:image",
		value:     "content",
	},
	{
		tpe:       "facebook",
		attribute: "rel",
		name:      "image_src",
		value:     "href",
	},
	{
		tpe:       "twitter",
		attribute: "name",
		name:      "twitter:image",
		value:     "value",
	},
	{
		tpe:       "twitter",
		attribute: "name",
		name:      "twitter:image",
		value:     "content",
	},
}

type ogImage struct {
	url   string
	tpe   string
	score int
}

// OpenGraphResolver return OpenGraph properties
func OpenGraphResolver(doc *goquery.Document) string {
	meta := doc.Find("meta")
	links := doc.Find("link")
	var topImage string
	meta = meta.Union(links)
	var ogImages []ogImage
	meta.Each(func(i int, tag *goquery.Selection) {
		for _, ogTag := range ogTags {
			attr, exist := tag.Attr(ogTag.attribute)
			value, vexist := tag.Attr(ogTag.value)
			if exist && attr == ogTag.name && vexist {
				ogImage := ogImage{
					url:   value,
					tpe:   ogTag.tpe,
					score: 0,
				}

				ogImages = append(ogImages, ogImage)
			}
		}
	})
	if len(ogImages) == 0 {
		return ""
	}
	if len(ogImages) == 1 {
		topImage = ogImages[0].url
		goto IMAGE_FINALIZE
	}
	for _, ogImage := range ogImages {
		if largebig.MatchString(ogImage.url) {
			ogImage.score++
		}
		if ogImage.tpe == "twitter" {
			ogImage.score++
		}
	}
	topImage = findBestImageFromScore(ogImages).url
IMAGE_FINALIZE:
	if !strings.HasPrefix(topImage, "http") {
		topImage = "http://" + topImage
	}

	return topImage
}

// assume that len(ogImages)>=2
func findBestImageFromScore(ogImages []ogImage) ogImage {
	max := 0
	bestOGImage := ogImages[0]
	for _, ogImage := range ogImages[1:] {
		score := ogImage.score
		if score > max {
			max = score
			bestOGImage = ogImage
		}
	}

	return bestOGImage
}
<|endoftext|>


<commit_before>package wellington

import (
	"bufio"
	"bytes"
	"errors"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/wellington/wellington/context"
)

type nopCloser struct {
	io.Reader
}

func (n nopCloser) Close() error { return nil }

// ImportPath accepts a directory and file path to find partials for importing.
// Returns the new pwd, string of the file contents, and error.
// File can contain a directory and should be evaluated if
// successfully found.
// Dir is used to provide relative context to the importee.  If no file is found
// pwd is echoed back.
//
// Paths are looked up in the following order:
// {includepath}/_file.scss
// {includePath}/_file.sass
// {includepath}/file.scss
// {includePath}/file.sass
// {Dir{dir+file}}/_{Base{file}}.scss
// {Dir{dir+file}}/_{Base{file}}.sass
// {Dir{dir+file}}/{Base{file}}.scss
// {Dir{dir+file}}/{Base{file}}.sass
func (p *Parser) ImportPath(dir, file string) (string, string, error) {
	var baseerr string
	// Attempt pwd
	r, fpath, err := importPath(dir, file)
	if err == nil {
		p.PartialMap.AddRelation(p.MainFile, fpath)
		contents, _ := ioutil.ReadAll(r)
		defer r.Close()
		return fpath, string(contents), nil
	}
	rel, _ := filepath.Rel(p.SassDir, fpath)
	if rel == "" {
		rel = "./"
	}
	baseerr += rel + "\n    "
	if os.IsNotExist(err) {
		// Look through the import path for the file
		for _, lib := range p.Includes {
			r, pwd, err := importPath(lib, file)
			defer r.Close()
			if err == nil {
				p.PartialMap.AddRelation(p.MainFile, fpath)
				bs, _ := ioutil.ReadAll(r)
				return pwd, string(bs), nil
			}
		}
	}
	// Ignore failures on compass
	re := regexp.MustCompile("compass\\/?")
	if re.Match([]byte(file)) {
		return filepath.Dir(fpath), "", nil //errors.New("compass")
	}
	if file == "images" {
		return filepath.Dir(fpath), "", nil
	}

	baseerr += strings.Join(p.Includes, "\n    ")
	return filepath.Dir(fpath), "",
		errors.New("Could not import: " + file + "\nTried:\n    " + baseerr)
}

// Attempt _{}.scss, _{}.sass, {}.scss, {}.sass paths and return
// reader if found
// Returns the file contents, pwd, and error if any
func importPath(dir, file string) (io.ReadCloser, string, error) {
	var errs string
	spath, _ := filepath.Abs(filepath.Join(dir, file))
	pwd := filepath.Dir(spath)
	base := filepath.Base(spath)
	fpath := filepath.Join(pwd, "_"+base+".scss")
	if r, err := readSass(fpath); err == nil {
		return r, filepath.Dir(fpath), err
	} else {
		errs += "importPath:\n    " + err.Error()
	}

	fpath = filepath.Join(pwd, base+".scss")
	if r, err := readSass(fpath); err == nil {
		return r, filepath.Dir(fpath), err
	} else {
		errs += "\n    " + err.Error()
	}

	fpath = filepath.Join(pwd, "_"+base+".sass")
	if r, err := readSass(fpath); err == nil {
		return r, filepath.Dir(fpath), err
	} else {
		errs += "\n    " + err.Error()
	}

	fpath = filepath.Join(pwd, base+".sass")
	if r, err := readSass(fpath); err == nil {
		return r, filepath.Dir(fpath), err
	} else {
		errs += "\n    " + err.Error()
	}

	return nil, pwd, os.ErrNotExist
}

// readSassBytes converts readSass to []byte
func readSassBytes(path string) ([]byte, error) {
	reader, err := readSass(path)
	if err != nil {
		return nil, err
	}
	return ioutil.ReadAll(reader)
}

// readSass retrives a file from path. If found, it converts Sass
// to Scss or returns found Scss;
func readSass(path string) (io.ReadCloser, error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	return ToScssReader(file)
}

// ToScssReader ...
func ToScssReader(r io.Reader) (io.ReadCloser, error) {
	var (
		buf bytes.Buffer
	)

	tr := io.TeeReader(r, &buf)
	if IsSass(tr) {

		var ibuf bytes.Buffer
		context.ToScss(io.MultiReader(&buf, r), &ibuf)
		return nopCloser{&ibuf}, nil
	}
	mr := io.MultiReader(&buf, r)

	return nopCloser{mr}, nil
}

// IsSass determines if the given reader is Sass (not Scss).
// This is predicted by the presence of semicolons
func IsSass(r io.Reader) bool {
	scanner := bufio.NewScanner(r)
	for scanner.Scan() {
		text := strings.TrimSpace(scanner.Text())
		if strings.HasSuffix(text, "{") ||
			strings.HasSuffix(text, "}") {
			return false
		}
		if strings.HasSuffix(text, ";") {
			return false
		}
	}
	return true
}
<commit_msg>fix linting errors<commit_after>package wellington

import (
	"bufio"
	"bytes"
	"errors"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/wellington/wellington/context"
)

type nopCloser struct {
	io.Reader
}

func (n nopCloser) Close() error { return nil }

// ImportPath accepts a directory and file path to find partials for importing.
// Returns the new pwd, string of the file contents, and error.
// File can contain a directory and should be evaluated if
// successfully found.
// Dir is used to provide relative context to the importee.  If no file is found
// pwd is echoed back.
//
// Paths are looked up in the following order:
// {includepath}/_file.scss
// {includePath}/_file.sass
// {includepath}/file.scss
// {includePath}/file.sass
// {Dir{dir+file}}/_{Base{file}}.scss
// {Dir{dir+file}}/_{Base{file}}.sass
// {Dir{dir+file}}/{Base{file}}.scss
// {Dir{dir+file}}/{Base{file}}.sass
func (p *Parser) ImportPath(dir, file string) (string, string, error) {
	var baseerr string
	// Attempt pwd
	r, fpath, err := importPath(dir, file)
	if err == nil {
		p.PartialMap.AddRelation(p.MainFile, fpath)
		contents, _ := ioutil.ReadAll(r)
		defer r.Close()
		return fpath, string(contents), nil
	}
	rel, _ := filepath.Rel(p.SassDir, fpath)
	if rel == "" {
		rel = "./"
	}
	baseerr += rel + "\n    "
	if os.IsNotExist(err) {
		// Look through the import path for the file
		for _, lib := range p.Includes {
			r, pwd, err := importPath(lib, file)
			defer r.Close()
			if err == nil {
				p.PartialMap.AddRelation(p.MainFile, fpath)
				bs, _ := ioutil.ReadAll(r)
				return pwd, string(bs), nil
			}
		}
	}
	// Ignore failures on compass
	re := regexp.MustCompile("compass\\/?")
	if re.Match([]byte(file)) {
		return filepath.Dir(fpath), "", nil //errors.New("compass")
	}
	if file == "images" {
		return filepath.Dir(fpath), "", nil
	}

	baseerr += strings.Join(p.Includes, "\n    ")
	return filepath.Dir(fpath), "",
		errors.New("Could not import: " + file + "\nTried:\n    " + baseerr)
}

// Attempt _{}.scss, _{}.sass, {}.scss, {}.sass paths and return
// reader if found
// Returns the file contents, pwd, and error if any
func importPath(dir, file string) (io.ReadCloser, string, error) {
	var errs string
	spath, _ := filepath.Abs(filepath.Join(dir, file))
	pwd := filepath.Dir(spath)
	base := filepath.Base(spath)
	fpath := filepath.Join(pwd, "_"+base+".scss")
	r, err := readSass(fpath)
	if err == nil {
		return r, filepath.Dir(fpath), err
	}
	errs += "importPath:\n    " + err.Error()

	fpath = filepath.Join(pwd, base+".scss")
	r, err = readSass(fpath)
	if err == nil {
		return r, filepath.Dir(fpath), err
	}
	errs += "\n    " + err.Error()

	fpath = filepath.Join(pwd, "_"+base+".sass")
	r, err = readSass(fpath)
	if err == nil {
		return r, filepath.Dir(fpath), err
	}
	errs += "\n    " + err.Error()

	fpath = filepath.Join(pwd, base+".sass")
	r, err = readSass(fpath)
	if err == nil {
		return r, filepath.Dir(fpath), err
	}
	errs += "\n    " + err.Error()

	return nil, pwd, os.ErrNotExist
}

// readSassBytes converts readSass to []byte
func readSassBytes(path string) ([]byte, error) {
	reader, err := readSass(path)
	if err != nil {
		return nil, err
	}
	return ioutil.ReadAll(reader)
}

// readSass retrives a file from path. If found, it converts Sass
// to Scss or returns found Scss;
func readSass(path string) (io.ReadCloser, error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	return ToScssReader(file)
}

// ToScssReader ...
func ToScssReader(r io.Reader) (io.ReadCloser, error) {
	var (
		buf bytes.Buffer
	)

	tr := io.TeeReader(r, &buf)
	if IsSass(tr) {

		var ibuf bytes.Buffer
		context.ToScss(io.MultiReader(&buf, r), &ibuf)
		return nopCloser{&ibuf}, nil
	}
	mr := io.MultiReader(&buf, r)

	return nopCloser{mr}, nil
}

// IsSass determines if the given reader is Sass (not Scss).
// This is predicted by the presence of semicolons
func IsSass(r io.Reader) bool {
	scanner := bufio.NewScanner(r)
	for scanner.Scan() {
		text := strings.TrimSpace(scanner.Text())
		if strings.HasSuffix(text, "{") ||
			strings.HasSuffix(text, "}") {
			return false
		}
		if strings.HasSuffix(text, ";") {
			return false
		}
	}
	return true
}
<|endoftext|>


<commit_before>package telnet

import (
	"fmt"
)

// RFC 854: http://tools.ietf.org/html/rfc854, http://support.microsoft.com/kb/231866

var codeMap map[byte]int
var commandMap map[int]byte

const (
	NUL  = iota // NULL, no operation
	ECHO = iota // Echo
	SGA  = iota // Suppress go ahead
	ST   = iota // Status
	TM   = iota // Timing mark
	BEL  = iota // Bell
	BS   = iota // Backspace
	HT   = iota // Horizontal tab
	LF   = iota // Line feed
	FF   = iota // Form feed
	CR   = iota // Carriage return
	TT   = iota // Terminal type
	WS   = iota // Window size
	TS   = iota // Terminal speed
	RFC  = iota // Remote flow control
	LM   = iota // Line mode
	EV   = iota // Environment variables
	SE   = iota // End of subnegotiation parameters.
	NOP  = iota // No operation.
	DM   = iota // Data Mark. The data stream portion of a Synch. This should always be accompanied by a TCP Urgent notification.
	BRK  = iota // Break. NVT character BRK.
	IP   = iota // Interrupt Process
	AO   = iota // Abort output
	AYT  = iota // Are you there
	EC   = iota // Erase character
	EL   = iota // Erase line
	GA   = iota // Go ahead signal
	SB   = iota // Indicates that what follows is subnegotiation of the indicated option.
	WILL = iota // Indicates the desire to begin performing, or confirmation that you are now performing, the indicated option.
	WONT = iota // Indicates the refusal to perform, or continue performing, the indicated option.
	DO   = iota // Indicates the request that the other party perform, or confirmation that you are expecting the other party to perform, the indicated option.
	DONT = iota // Indicates the demand that the other party stop performing, or confirmation that you are no longer expecting the other party to perform, the indicated option.
	IAC  = iota // Interpret as command

	// Non-standard codes:
	CMP1 = iota // MCCP Compress
	CMP2 = iota // MCCP Compress2
	AARD = iota // Aardwolf MUD out of band communication, http://www.aardwolf.com/blog/2008/07/10/telnet-negotiation-control-mud-client-interaction/
	ATCP = iota // Achaea Telnet Client Protocol, http://www.ironrealms.com/rapture/manual/files/FeatATCP-txt.html
	GMCP = iota // Generic Mud Communication Protocol
)

func initLookups() {
	if codeMap != nil {
		return
	}

	codeMap = map[byte]int{}
	commandMap = map[int]byte{}

	commandMap[NUL] = '\x00'
	commandMap[ECHO] = '\x01'
	commandMap[SGA] = '\x03'
	commandMap[ST] = '\x05'
	commandMap[TM] = '\x06'
	commandMap[BEL] = '\x07'
	commandMap[BS] = '\x08'
	commandMap[HT] = '\x09'
	commandMap[LF] = '\x0a'
	commandMap[FF] = '\x0c'
	commandMap[CR] = '\x0d'
	commandMap[TT] = '\x18'
	commandMap[WS] = '\x1F'
	commandMap[TS] = '\x20'
	commandMap[RFC] = '\x21'
	commandMap[LM] = '\x22'
	commandMap[EV] = '\x24'
	commandMap[SE] = '\xf0'
	commandMap[NOP] = '\xf1'
	commandMap[DM] = '\xf2'
	commandMap[BRK] = '\xf3'
	commandMap[IP] = '\xf4'
	commandMap[AO] = '\xf5'
	commandMap[AYT] = '\xf6'
	commandMap[EC] = '\xf7'
	commandMap[EL] = '\xf8'
	commandMap[GA] = '\xf9'
	commandMap[SB] = '\xfa'
	commandMap[WILL] = '\xfb'
	commandMap[WONT] = '\xfc'
	commandMap[DO] = '\xfd'
	commandMap[DONT] = '\xfe'
	commandMap[IAC] = '\xff'

	commandMap[CMP1] = '\x55'
	commandMap[CMP2] = '\x56'
	commandMap[AARD] = '\x66'
	commandMap[ATCP] = '\xc8'
	commandMap[GMCP] = '\xc9'

	for enum, code := range commandMap {
		codeMap[code] = enum
	}
}

// Process strips telnet control codes from the given input, returning the resulting input string
func Process(bytes []byte) string {
	initLookups()

	type State int

	const (
		Base  State = iota
		InIAC State = iota
		InSB  State = iota
		CapSB State = iota
	)

	currentState := Base

	str := ""
	capturedBytes := []byte{}

	capture := func(b byte) {
		capturedBytes = append(capturedBytes, b)
	}

	dontCapture := func(b byte) {
		str = str + string(b)
	}

	for _, b := range bytes {
		code := codeMap[b]

		switch currentState {
		case Base:
			if code == IAC {
				currentState = InIAC
				capture(b)
			} else {
				dontCapture(b)
			}

		case InIAC:
			if code == WILL || code == WONT || code == DO || code == DONT {
				// Stay in this state
			} else if code == SB {
				currentState = InSB
			} else {
				currentState = Base
			}
			capture(b)

		case InSB:
			capture(b)
			currentState = CapSB

		case CapSB:
			capture(b)

			if code == IAC { // TODO: Handle escaped IAC sequences
				currentState = InIAC
			}
		}
	}

	if len(capturedBytes) > 0 {
		fmt.Println("Processed:", ToString(capturedBytes))
	}

	return str
}

func Code(enum int) byte {
	initLookups()
	return commandMap[enum]
}

func ToString(bytes []byte) string {
	initLookups()

	str := ""
	for _, b := range bytes {
		enum, found := codeMap[b]
		result := ""

		if found {
			switch enum {
			case NUL:
				result = "NUL"
			case ECHO:
				result = "ECHO"
			case SGA:
				result = "SGA"
			case ST:
				result = "ST"
			case TM:
				result = "TM"
			case BEL:
				result = "BEL"
			case BS:
				result = "BS"
			case HT:
				result = "HT"
			case LF:
				result = "LF"
			case FF:
				result = "FF"
			case CR:
				result = "CR"
			case TT:
				result = "TT"
			case WS:
				result = "WS"
			case TS:
				result = "TS"
			case RFC:
				result = "RFC"
			case LM:
				result = "LM"
			case EV:
				result = "EV"
			case SE:
				result = "SE"
			case NOP:
				result = "NOP"
			case DM:
				result = "DM"
			case BRK:
				result = "BRK"
			case IP:
				result = "IP"
			case AO:
				result = "AO"
			case AYT:
				result = "AYT"
			case EC:
				result = "EC"
			case EL:
				result = "EL"
			case GA:
				result = "GA"
			case SB:
				result = "SB"
			case WILL:
				result = "WILL"
			case WONT:
				result = "WONT"
			case DO:
				result = "DO"
			case DONT:
				result = "DONT"
			case IAC:
				result = "IAC"
			case CMP1:
				result = "CMP1"
			case CMP2:
				result = "CMP2"
			case AARD:
				result = "AARD"
			case ATCP:
				result = "ATCP"
			case GMCP:
				result = "GMCP"
			}
		} else {
			result = "???"
		}

		if str != "" {
			str = str + " "
		}
		str = str + result
	}

	return str
}

func buildCommand(length int) []byte {
	command := make([]byte, length)
	command[0] = commandMap[IAC]
	return command
}

func WillEcho() []byte {
	command := buildCommand(3)
	command[1] = commandMap[WILL]
	command[2] = commandMap[ECHO]
	return command
}

func WontEcho() []byte {
	command := buildCommand(3)
	command[1] = commandMap[WONT]
	command[2] = commandMap[ECHO]
	return command
}

// vim: nocindent
<commit_msg>Improved type safety, cleaner way to build commands<commit_after>package telnet

import (
	"fmt"
)

// RFC 854: http://tools.ietf.org/html/rfc854, http://support.microsoft.com/kb/231866

var codeMap map[byte]TelnetCode
var commandMap map[TelnetCode]byte

type TelnetCode int

const (
	NUL  TelnetCode = iota // NULL, no operation
	ECHO TelnetCode = iota // Echo
	SGA  TelnetCode = iota // Suppress go ahead
	ST   TelnetCode = iota // Status
	TM   TelnetCode = iota // Timing mark
	BEL  TelnetCode = iota // Bell
	BS   TelnetCode = iota // Backspace
	HT   TelnetCode = iota // Horizontal tab
	LF   TelnetCode = iota // Line feed
	FF   TelnetCode = iota // Form feed
	CR   TelnetCode = iota // Carriage return
	TT   TelnetCode = iota // Terminal type
	WS   TelnetCode = iota // Window size
	TS   TelnetCode = iota // Terminal speed
	RFC  TelnetCode = iota // Remote flow control
	LM   TelnetCode = iota // Line mode
	EV   TelnetCode = iota // Environment variables
	SE   TelnetCode = iota // End of subnegotiation parameters.
	NOP  TelnetCode = iota // No operation.
	DM   TelnetCode = iota // Data Mark. The data stream portion of a Synch. This should always be accompanied by a TCP Urgent notification.
	BRK  TelnetCode = iota // Break. NVT character BRK.
	IP   TelnetCode = iota // Interrupt Process
	AO   TelnetCode = iota // Abort output
	AYT  TelnetCode = iota // Are you there
	EC   TelnetCode = iota // Erase character
	EL   TelnetCode = iota // Erase line
	GA   TelnetCode = iota // Go ahead signal
	SB   TelnetCode = iota // Indicates that what follows is subnegotiation of the indicated option.
	WILL TelnetCode = iota // Indicates the desire to begin performing, or confirmation that you are now performing, the indicated option.
	WONT TelnetCode = iota // Indicates the refusal to perform, or continue performing, the indicated option.
	DO   TelnetCode = iota // Indicates the request that the other party perform, or confirmation that you are expecting the other party to perform, the indicated option.
	DONT TelnetCode = iota // Indicates the demand that the other party stop performing, or confirmation that you are no longer expecting the other party to perform, the indicated option.
	IAC  TelnetCode = iota // Interpret as command

	// Non-standard codes:
	CMP1 TelnetCode = iota // MCCP Compress
	CMP2 TelnetCode = iota // MCCP Compress2
	AARD TelnetCode = iota // Aardwolf MUD out of band communication, http://www.aardwolf.com/blog/2008/07/10/telnet-negotiation-control-mud-client-interaction/
	ATCP TelnetCode = iota // Achaea Telnet Client Protocol, http://www.ironrealms.com/rapture/manual/files/FeatATCP-txt.html
	GMCP TelnetCode = iota // Generic Mud Communication Protocol
)

func initLookups() {
	if codeMap != nil {
		return
	}

	codeMap = map[byte]TelnetCode{}
	commandMap = map[TelnetCode]byte{}

	commandMap[NUL] = '\x00'
	commandMap[ECHO] = '\x01'
	commandMap[SGA] = '\x03'
	commandMap[ST] = '\x05'
	commandMap[TM] = '\x06'
	commandMap[BEL] = '\x07'
	commandMap[BS] = '\x08'
	commandMap[HT] = '\x09'
	commandMap[LF] = '\x0a'
	commandMap[FF] = '\x0c'
	commandMap[CR] = '\x0d'
	commandMap[TT] = '\x18'
	commandMap[WS] = '\x1F'
	commandMap[TS] = '\x20'
	commandMap[RFC] = '\x21'
	commandMap[LM] = '\x22'
	commandMap[EV] = '\x24'
	commandMap[SE] = '\xf0'
	commandMap[NOP] = '\xf1'
	commandMap[DM] = '\xf2'
	commandMap[BRK] = '\xf3'
	commandMap[IP] = '\xf4'
	commandMap[AO] = '\xf5'
	commandMap[AYT] = '\xf6'
	commandMap[EC] = '\xf7'
	commandMap[EL] = '\xf8'
	commandMap[GA] = '\xf9'
	commandMap[SB] = '\xfa'
	commandMap[WILL] = '\xfb'
	commandMap[WONT] = '\xfc'
	commandMap[DO] = '\xfd'
	commandMap[DONT] = '\xfe'
	commandMap[IAC] = '\xff'

	commandMap[CMP1] = '\x55'
	commandMap[CMP2] = '\x56'
	commandMap[AARD] = '\x66'
	commandMap[ATCP] = '\xc8'
	commandMap[GMCP] = '\xc9'

	for enum, code := range commandMap {
		codeMap[code] = enum
	}
}

// Process strips telnet control codes from the given input, returning the resulting input string
func Process(bytes []byte) string {
	initLookups()

	type State int

	const (
		Base  State = iota
		InIAC State = iota
		InSB  State = iota
		CapSB State = iota
	)

	currentState := Base

	str := ""
	capturedBytes := []byte{}

	capture := func(b byte) {
		capturedBytes = append(capturedBytes, b)
	}

	dontCapture := func(b byte) {
		str = str + string(b)
	}

	for _, b := range bytes {
		code := codeMap[b]

		switch currentState {
		case Base:
			if code == IAC {
				currentState = InIAC
				capture(b)
			} else {
				dontCapture(b)
			}

		case InIAC:
			if code == WILL || code == WONT || code == DO || code == DONT {
				// Stay in this state
			} else if code == SB {
				currentState = InSB
			} else {
				currentState = Base
			}
			capture(b)

		case InSB:
			capture(b)
			currentState = CapSB

		case CapSB:
			capture(b)

			if code == IAC { // TODO: Handle escaped IAC sequences
				currentState = InIAC
			}
		}
	}

	if len(capturedBytes) > 0 {
		fmt.Println("Processed:", ToString(capturedBytes))
	}

	return str
}

func ToString(bytes []byte) string {
	initLookups()

	str := ""
	for _, b := range bytes {
		enum, found := codeMap[b]
		result := ""

		if found {
			switch enum {
			case NUL:
				result = "NUL"
			case ECHO:
				result = "ECHO"
			case SGA:
				result = "SGA"
			case ST:
				result = "ST"
			case TM:
				result = "TM"
			case BEL:
				result = "BEL"
			case BS:
				result = "BS"
			case HT:
				result = "HT"
			case LF:
				result = "LF"
			case FF:
				result = "FF"
			case CR:
				result = "CR"
			case TT:
				result = "TT"
			case WS:
				result = "WS"
			case TS:
				result = "TS"
			case RFC:
				result = "RFC"
			case LM:
				result = "LM"
			case EV:
				result = "EV"
			case SE:
				result = "SE"
			case NOP:
				result = "NOP"
			case DM:
				result = "DM"
			case BRK:
				result = "BRK"
			case IP:
				result = "IP"
			case AO:
				result = "AO"
			case AYT:
				result = "AYT"
			case EC:
				result = "EC"
			case EL:
				result = "EL"
			case GA:
				result = "GA"
			case SB:
				result = "SB"
			case WILL:
				result = "WILL"
			case WONT:
				result = "WONT"
			case DO:
				result = "DO"
			case DONT:
				result = "DONT"
			case IAC:
				result = "IAC"
			case CMP1:
				result = "CMP1"
			case CMP2:
				result = "CMP2"
			case AARD:
				result = "AARD"
			case ATCP:
				result = "ATCP"
			case GMCP:
				result = "GMCP"
			}
		} else {
			result = "???"
		}

		if str != "" {
			str = str + " "
		}
		str = str + result
	}

	return str
}

func buildCommand(codes ...TelnetCode) []byte {
	command := make([]byte, len(codes)+1)
	command[0] = commandMap[IAC]

	for i, code := range codes {
		command[i+1] = commandMap[code]
	}

	return command
}

func WillEcho() []byte {
	return buildCommand(WILL, ECHO)
}

func WontEcho() []byte {
	return buildCommand(WONT, ECHO)
}

func DoWindowSize() []byte {
	return buildCommand(DO, WS)
}

// vim: nocindent
<|endoftext|>


<commit_before>package structs

import (
	"errors"
	"fmt"
	"reflect"
)

var (
	errNotExported = errors.New("field is not exported")
	errNotSettable = errors.New("field is not settable")
)

// Field represents a single struct field that encapsulates high level
// functions around the field.
type Field struct {
	value      reflect.Value
	field      reflect.StructField
	defaultTag string
}

// Tag returns the value associated with key in the tag string. If there is no
// such key in the tag, Tag returns the empty string.
func (f *Field) Tag(key string) string {
	return f.field.Tag.Get(key)
}

// Value returns the underlying value of of the field. It panics if the field
// is not exported.
func (f *Field) Value() interface{} {
	return f.value.Interface()
}

// IsEmbedded returns true if the given field is an anonymous field (embedded)
func (f *Field) IsEmbedded() bool {
	return f.field.Anonymous
}

// IsExported returns true if the given field is exported.
func (f *Field) IsExported() bool {
	return f.field.PkgPath == ""
}

// IsZero returns true if the given field is not initalized (has a zero value).
// It panics if the field is not exported.
func (f *Field) IsZero() bool {
	zero := reflect.Zero(f.value.Type()).Interface()
	current := f.Value()

	return reflect.DeepEqual(current, zero)
}

// Name returns the name of the given field
func (f *Field) Name() string {
	return f.field.Name
}

// Kind returns the fields kind, such as "string", "map", "bool", etc ..
func (f *Field) Kind() reflect.Kind {
	return f.value.Kind()
}

// Set sets the field to given value v. It retuns an error if the field is not
// settable (not addresable or not exported) or if the given value's type
// doesn't match the fields type.
func (f *Field) Set(val interface{}) error {
	// we can't set unexported fields, so be sure this field is exported
	if !f.IsExported() {
		return errNotExported
	}

	// do we get here? not sure...
	if !f.value.CanSet() {
		return errNotSettable
	}

	given := reflect.ValueOf(val)

	if f.value.Kind() != given.Kind() {
		return fmt.Errorf("wrong kind. got: %s want: %s", given.Kind(), f.value.Kind())
	}

	f.value.Set(given)
	return nil
}

// Zero sets the field to its zero value. It returns an error if the field is not
// settable (not addressable or not exported).
func (f *Field) Zero() error {
	zero := reflect.Zero(f.value.Type()).Interface()
	return f.Set(zero)
}

// Fields returns a slice of Fields. This is particular handy to get the fields
// of a nested struct . A struct tag with the content of "-" ignores the
// checking of that particular field. Example:
//
//   // Field is ignored by this package.
//   Field *http.Request `structs:"-"`
//
// It panics if field is not exported or if field's kind is not struct
func (f *Field) Fields() []*Field {
	return getFields(f.value, f.defaultTag)
}

// Field returns the field from a nested struct. It panics if the nested struct
// is not exported or if the field was not found.
func (f *Field) Field(name string) *Field {
	field, ok := f.FieldOk(name)
	if !ok {
		panic("field not found")
	}

	return field
}

// Field returns the field from a nested struct. The boolean returns true if
// the field was found. It panics if the nested struct is not exported or if
// the field was not found.
func (f *Field) FieldOk(name string) (*Field, bool) {
	v := strctVal(f.value.Interface())
	t := v.Type()

	field, ok := t.FieldByName(name)
	if !ok {
		return nil, false
	}

	return &Field{
		field: field,
		value: v.FieldByName(name),
	}, true
}
<commit_msg>fix typos<commit_after>package structs

import (
	"errors"
	"fmt"
	"reflect"
)

var (
	errNotExported = errors.New("field is not exported")
	errNotSettable = errors.New("field is not settable")
)

// Field represents a single struct field that encapsulates high level
// functions around the field.
type Field struct {
	value      reflect.Value
	field      reflect.StructField
	defaultTag string
}

// Tag returns the value associated with key in the tag string. If there is no
// such key in the tag, Tag returns the empty string.
func (f *Field) Tag(key string) string {
	return f.field.Tag.Get(key)
}

// Value returns the underlying value of of the field. It panics if the field
// is not exported.
func (f *Field) Value() interface{} {
	return f.value.Interface()
}

// IsEmbedded returns true if the given field is an anonymous field (embedded)
func (f *Field) IsEmbedded() bool {
	return f.field.Anonymous
}

// IsExported returns true if the given field is exported.
func (f *Field) IsExported() bool {
	return f.field.PkgPath == ""
}

// IsZero returns true if the given field is not initialized (has a zero value).
// It panics if the field is not exported.
func (f *Field) IsZero() bool {
	zero := reflect.Zero(f.value.Type()).Interface()
	current := f.Value()

	return reflect.DeepEqual(current, zero)
}

// Name returns the name of the given field
func (f *Field) Name() string {
	return f.field.Name
}

// Kind returns the fields kind, such as "string", "map", "bool", etc ..
func (f *Field) Kind() reflect.Kind {
	return f.value.Kind()
}

// Set sets the field to given value v. It retuns an error if the field is not
// settable (not addressable or not exported) or if the given value's type
// doesn't match the fields type.
func (f *Field) Set(val interface{}) error {
	// we can't set unexported fields, so be sure this field is exported
	if !f.IsExported() {
		return errNotExported
	}

	// do we get here? not sure...
	if !f.value.CanSet() {
		return errNotSettable
	}

	given := reflect.ValueOf(val)

	if f.value.Kind() != given.Kind() {
		return fmt.Errorf("wrong kind. got: %s want: %s", given.Kind(), f.value.Kind())
	}

	f.value.Set(given)
	return nil
}

// Zero sets the field to its zero value. It returns an error if the field is not
// settable (not addressable or not exported).
func (f *Field) Zero() error {
	zero := reflect.Zero(f.value.Type()).Interface()
	return f.Set(zero)
}

// Fields returns a slice of Fields. This is particular handy to get the fields
// of a nested struct . A struct tag with the content of "-" ignores the
// checking of that particular field. Example:
//
//   // Field is ignored by this package.
//   Field *http.Request `structs:"-"`
//
// It panics if field is not exported or if field's kind is not struct
func (f *Field) Fields() []*Field {
	return getFields(f.value, f.defaultTag)
}

// Field returns the field from a nested struct. It panics if the nested struct
// is not exported or if the field was not found.
func (f *Field) Field(name string) *Field {
	field, ok := f.FieldOk(name)
	if !ok {
		panic("field not found")
	}

	return field
}

// Field returns the field from a nested struct. The boolean returns true if
// the field was found. It panics if the nested struct is not exported or if
// the field was not found.
func (f *Field) FieldOk(name string) (*Field, bool) {
	v := strctVal(f.value.Interface())
	t := v.Type()

	field, ok := t.FieldByName(name)
	if !ok {
		return nil, false
	}

	return &Field{
		field: field,
		value: v.FieldByName(name),
	}, true
}
<|endoftext|>


<commit_before>package gzip

import (
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"testing"
	"time"
)

// Per golang.org/issue/14939, check that every .gz file
// in the tree has a zero mtime.
func TestGZIPFilesHaveZeroMTimes(t *testing.T) {
	var files []string
	err := filepath.Walk(runtime.GOROOT(), func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if !info.IsDir() && strings.HasSuffix(path, ".gz") {
			files = append(files, path)
		}
		return nil
	})
	if err != nil {
		t.Fatal("error collecting list of .gz files in GOROOT: ", err)
	}
	if len(files) == 0 {
		t.Fatal("expected to find some .gz files under GOROOT")
	}
	for _, path := range files {
		checkZeroMTime(t, path)
	}
}

func checkZeroMTime(t *testing.T, path string) {
	f, err := os.Open(path)
	if err != nil {
		t.Error(err)
		return
	}
	defer f.Close()
	gz, err := NewReader(f)
	if err != nil {
		t.Errorf("cannot read gzip file %s: %s", path, err)
		return
	}
	defer gz.Close()
	if !gz.ModTime.Equal(time.Unix(0, 0)) {
		t.Errorf("gzip file %s has non-zero mtime (%s)", path, gz.ModTime)
	}
}
<commit_msg>compress/gzip: skip mtime test when GOROOT doesn't exist<commit_after>package gzip

import (
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"testing"
	"time"
)

// Per golang.org/issue/14939, check that every .gz file
// in the tree has a zero mtime.
func TestGZIPFilesHaveZeroMTimes(t *testing.T) {
	var files []string
	err := filepath.Walk(runtime.GOROOT(), func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if !info.IsDir() && strings.HasSuffix(path, ".gz") {
			files = append(files, path)
		}
		return nil
	})
	if err != nil {
		if os.IsNotExist(err) {
			t.Skipf("skipping: GOROOT directory not found: %s", runtime.GOROOT())
		}
		t.Fatal("error collecting list of .gz files in GOROOT: ", err)
	}
	if len(files) == 0 {
		t.Fatal("expected to find some .gz files under GOROOT")
	}
	for _, path := range files {
		checkZeroMTime(t, path)
	}
}

func checkZeroMTime(t *testing.T, path string) {
	f, err := os.Open(path)
	if err != nil {
		t.Error(err)
		return
	}
	defer f.Close()
	gz, err := NewReader(f)
	if err != nil {
		t.Errorf("cannot read gzip file %s: %s", path, err)
		return
	}
	defer gz.Close()
	if !gz.ModTime.Equal(time.Unix(0, 0)) {
		t.Errorf("gzip file %s has non-zero mtime (%s)", path, gz.ModTime)
	}
}
<|endoftext|>


<commit_before>package commands_test

import (
	/*	"cf"*/
	/*	"cf/api"*/
	. "cf/commands"
	"github.com/stretchr/testify/assert"
	"testhelpers"
	"testing"
)

func TestCreateOrgFailsWithUsage(t *testing.T) {
	orgRepo := &testhelpers.FakeOrgRepository{}
	reqFactory := &testhelpers.FakeReqFactory{LoginSuccess: true}

	fakeUI := callCreateOrganization([]string{}, reqFactory, orgRepo)
	assert.True(t, fakeUI.FailedWithUsage)

	fakeUI = callCreateOrganization([]string{"my-org"}, reqFactory, orgRepo)
	assert.False(t, fakeUI.FailedWithUsage)
}

func TestCreateOrgRequirements(t *testing.T) {
	orgRepo := &testhelpers.FakeOrgRepository{}

	reqFactory := &testhelpers.FakeReqFactory{LoginSuccess: true}
	callCreateOrganization([]string{"my-org"}, reqFactory, orgRepo)
	assert.True(t, testhelpers.CommandDidPassRequirements)

	reqFactory = &testhelpers.FakeReqFactory{LoginSuccess: false}
	callCreateOrganization([]string{"my-org"}, reqFactory, orgRepo)
	assert.False(t, testhelpers.CommandDidPassRequirements)
}

func TestCreateOrganization(t *testing.T) {
	orgRepo := &testhelpers.FakeOrgRepository{}
	reqFactory := &testhelpers.FakeReqFactory{LoginSuccess: true}
	fakeUI := callCreateOrganization([]string{"my-org"}, reqFactory, orgRepo)

	assert.Contains(t, fakeUI.Outputs[0], "Creating organization")
	assert.Contains(t, fakeUI.Outputs[0], "my-org")
	assert.Equal(t, orgRepo.CreateName, "my-org")
	assert.Contains(t, fakeUI.Outputs[1], "OK")
}

func TestCreateOrganizationWhenAlreadyExists(t *testing.T){
	orgRepo := &testhelpers.FakeOrgRepository{CreateOrgExists: true}
	reqFactory := &testhelpers.FakeReqFactory{LoginSuccess: true}
	fakeUI := callCreateOrganization([]string{"my-org"}, reqFactory, orgRepo)

	println(fakeUI.DumpOutputs())
	assert.Contains(t, fakeUI.Outputs[0], "Creating organization")
	assert.Contains(t, fakeUI.Outputs[0], "my-org")
	assert.Contains(t, fakeUI.Outputs[1], "OK")
	assert.Contains(t, fakeUI.Outputs[2], "my-org")
	assert.Contains(t, fakeUI.Outputs[2], "already exists.")
}

func callCreateOrganization(args []string, reqFactory *testhelpers.FakeReqFactory, orgRepo *testhelpers.FakeOrgRepository) (fakeUI *testhelpers.FakeUI) {
	fakeUI = new(testhelpers.FakeUI)
	ctxt := testhelpers.NewContext("create-org", args)
	cmd := NewCreateOrganization(fakeUI, orgRepo)

	testhelpers.RunCommand(cmd, ctxt, reqFactory)
	return
}
<commit_msg>Get rid of stray println.<commit_after>package commands_test

import (
	/*	"cf"*/
	/*	"cf/api"*/
	. "cf/commands"
	"github.com/stretchr/testify/assert"
	"testhelpers"
	"testing"
)

func TestCreateOrgFailsWithUsage(t *testing.T) {
	orgRepo := &testhelpers.FakeOrgRepository{}
	reqFactory := &testhelpers.FakeReqFactory{LoginSuccess: true}

	fakeUI := callCreateOrganization([]string{}, reqFactory, orgRepo)
	assert.True(t, fakeUI.FailedWithUsage)

	fakeUI = callCreateOrganization([]string{"my-org"}, reqFactory, orgRepo)
	assert.False(t, fakeUI.FailedWithUsage)
}

func TestCreateOrgRequirements(t *testing.T) {
	orgRepo := &testhelpers.FakeOrgRepository{}

	reqFactory := &testhelpers.FakeReqFactory{LoginSuccess: true}
	callCreateOrganization([]string{"my-org"}, reqFactory, orgRepo)
	assert.True(t, testhelpers.CommandDidPassRequirements)

	reqFactory = &testhelpers.FakeReqFactory{LoginSuccess: false}
	callCreateOrganization([]string{"my-org"}, reqFactory, orgRepo)
	assert.False(t, testhelpers.CommandDidPassRequirements)
}

func TestCreateOrganization(t *testing.T) {
	orgRepo := &testhelpers.FakeOrgRepository{}
	reqFactory := &testhelpers.FakeReqFactory{LoginSuccess: true}
	fakeUI := callCreateOrganization([]string{"my-org"}, reqFactory, orgRepo)

	assert.Contains(t, fakeUI.Outputs[0], "Creating organization")
	assert.Contains(t, fakeUI.Outputs[0], "my-org")
	assert.Equal(t, orgRepo.CreateName, "my-org")
	assert.Contains(t, fakeUI.Outputs[1], "OK")
}

func TestCreateOrganizationWhenAlreadyExists(t *testing.T){
	orgRepo := &testhelpers.FakeOrgRepository{CreateOrgExists: true}
	reqFactory := &testhelpers.FakeReqFactory{LoginSuccess: true}
	fakeUI := callCreateOrganization([]string{"my-org"}, reqFactory, orgRepo)

	assert.Contains(t, fakeUI.Outputs[0], "Creating organization")
	assert.Contains(t, fakeUI.Outputs[0], "my-org")
	assert.Contains(t, fakeUI.Outputs[1], "OK")
	assert.Contains(t, fakeUI.Outputs[2], "my-org")
	assert.Contains(t, fakeUI.Outputs[2], "already exists.")
}

func callCreateOrganization(args []string, reqFactory *testhelpers.FakeReqFactory, orgRepo *testhelpers.FakeOrgRepository) (fakeUI *testhelpers.FakeUI) {
	fakeUI = new(testhelpers.FakeUI)
	ctxt := testhelpers.NewContext("create-org", args)
	cmd := NewCreateOrganization(fakeUI, orgRepo)

	testhelpers.RunCommand(cmd, ctxt, reqFactory)
	return
}
<|endoftext|>


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

package trace

import (
	"cmd/internal/traceviewer"
	"context"
	"encoding/json"
	"errors"
	"os"
	"strings"
	"sync/atomic"
	"time"
)

// Constants used in event fields.
// See https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU
// for more details.
const (
	phaseDurationBegin = "B"
	phaseDurationEnd   = "E"
	phaseFlowStart     = "s"
	phaseFlowEnd       = "f"

	bindEnclosingSlice = "e"
)

var traceStarted int32

func getTraceContext(ctx context.Context) (traceContext, bool) {
	if atomic.LoadInt32(&traceStarted) == 0 {
		return traceContext{}, false
	}
	v := ctx.Value(traceKey{})
	if v == nil {
		return traceContext{}, false
	}
	return v.(traceContext), true
}

// StartSpan starts a trace event with the given name. The Span ends when its Done method is called.
func StartSpan(ctx context.Context, name string) (context.Context, *Span) {
	tc, ok := getTraceContext(ctx)
	if !ok {
		return ctx, nil
	}
	childSpan := &Span{t: tc.t, name: name, tid: tc.tid, start: time.Now()}
	tc.t.writeEvent(&traceviewer.Event{
		Name:  childSpan.name,
		Time:  float64(childSpan.start.UnixNano()) / float64(time.Microsecond),
		TID:   childSpan.tid,
		Phase: phaseDurationBegin,
	})
	ctx = context.WithValue(ctx, traceKey{}, traceContext{tc.t, tc.tid})
	return ctx, childSpan
}

// StartGoroutine associates the context with a new Thread ID. The Chrome trace viewer associates each
// trace event with a thread, and doesn't expect events with the same thread id to happen at the
// same time.
func StartGoroutine(ctx context.Context) context.Context {
	tc, ok := getTraceContext(ctx)
	if !ok {
		return ctx
	}
	return context.WithValue(ctx, traceKey{}, traceContext{tc.t, tc.t.getNextTID()})
}

// Flow marks a flow indicating that the 'to' span depends on the 'from' span.
// Flow should be called while the 'to' span is in progress.
func Flow(ctx context.Context, from *Span, to *Span) {
	tc, ok := getTraceContext(ctx)
	if !ok || from == nil || to == nil {
		return
	}

	id := tc.t.getNextFlowID()
	tc.t.writeEvent(&traceviewer.Event{
		Name:     from.name + " -> " + to.name,
		Category: "flow",
		ID:       id,
		Time:     float64(from.end.UnixNano()) / float64(time.Microsecond),
		Phase:    phaseFlowStart,
		TID:      from.tid,
	})
	tc.t.writeEvent(&traceviewer.Event{
		Name:      from.name + " -> " + to.name,
		Category:  "flow", // TODO(matloob): Add Category to Flow?
		ID:        id,
		Time:      float64(to.start.UnixNano()) / float64(time.Microsecond),
		Phase:     phaseFlowEnd,
		TID:       to.tid,
		BindPoint: bindEnclosingSlice,
	})
}

type Span struct {
	t *tracer

	name  string
	tid   uint64
	start time.Time
	end   time.Time
}

func (s *Span) Done() {
	if s == nil {
		return
	}
	s.end = time.Now()
	s.t.writeEvent(&traceviewer.Event{
		Name:  s.name,
		Time:  float64(s.end.UnixNano()) / float64(time.Microsecond),
		TID:   s.tid,
		Phase: phaseDurationEnd,
	})
}

type tracer struct {
	file chan traceFile // 1-buffered

	nextTID    uint64
	nextFlowID uint64
}

func (t *tracer) writeEvent(ev *traceviewer.Event) error {
	f := <-t.file
	defer func() { t.file <- f }()
	var err error
	if f.entries == 0 {
		_, err = f.sb.WriteString("[\n")
	} else {
		_, err = f.sb.WriteString(",")
	}
	f.entries++
	if err != nil {
		return nil
	}

	if err := f.enc.Encode(ev); err != nil {
		return err
	}

	// Write event string to output file.
	_, err = f.f.WriteString(f.sb.String())
	f.sb.Reset()
	return err
}

func (t *tracer) Close() error {
	f := <-t.file
	defer func() { t.file <- f }()

	_, firstErr := f.f.WriteString("]")
	if err := f.f.Close(); firstErr == nil {
		firstErr = err
	}
	return firstErr
}

func (t *tracer) getNextTID() uint64 {
	return atomic.AddUint64(&t.nextTID, 1)
}

func (t *tracer) getNextFlowID() uint64 {
	return atomic.AddUint64(&t.nextFlowID, 1)
}

// traceKey is the context key for tracing information. It is unexported to prevent collisions with context keys defined in
// other packages.
type traceKey struct{}

type traceContext struct {
	t   *tracer
	tid uint64
}

// Start starts a trace which writes to the given file.
func Start(ctx context.Context, file string) (context.Context, func() error, error) {
	atomic.StoreInt32(&traceStarted, 1)
	if file == "" {
		return nil, nil, errors.New("no trace file supplied")
	}
	f, err := os.Create(file)
	if err != nil {
		return nil, nil, err
	}
	t := &tracer{file: make(chan traceFile, 1)}
	sb := new(strings.Builder)
	t.file <- traceFile{
		f:   f,
		sb:  sb,
		enc: json.NewEncoder(sb),
	}
	ctx = context.WithValue(ctx, traceKey{}, traceContext{t: t})
	return ctx, t.Close, nil
}

type traceFile struct {
	f       *os.File
	sb      *strings.Builder
	enc     *json.Encoder
	entries int64
}
<commit_msg>cmd/go/internal/trace: convert traceStarted to atomic type<commit_after>// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package trace

import (
	"cmd/internal/traceviewer"
	"context"
	"encoding/json"
	"errors"
	"os"
	"strings"
	"sync/atomic"
	"time"
)

// Constants used in event fields.
// See https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU
// for more details.
const (
	phaseDurationBegin = "B"
	phaseDurationEnd   = "E"
	phaseFlowStart     = "s"
	phaseFlowEnd       = "f"

	bindEnclosingSlice = "e"
)

var traceStarted atomic.Bool

func getTraceContext(ctx context.Context) (traceContext, bool) {
	if !traceStarted.Load() {
		return traceContext{}, false
	}
	v := ctx.Value(traceKey{})
	if v == nil {
		return traceContext{}, false
	}
	return v.(traceContext), true
}

// StartSpan starts a trace event with the given name. The Span ends when its Done method is called.
func StartSpan(ctx context.Context, name string) (context.Context, *Span) {
	tc, ok := getTraceContext(ctx)
	if !ok {
		return ctx, nil
	}
	childSpan := &Span{t: tc.t, name: name, tid: tc.tid, start: time.Now()}
	tc.t.writeEvent(&traceviewer.Event{
		Name:  childSpan.name,
		Time:  float64(childSpan.start.UnixNano()) / float64(time.Microsecond),
		TID:   childSpan.tid,
		Phase: phaseDurationBegin,
	})
	ctx = context.WithValue(ctx, traceKey{}, traceContext{tc.t, tc.tid})
	return ctx, childSpan
}

// StartGoroutine associates the context with a new Thread ID. The Chrome trace viewer associates each
// trace event with a thread, and doesn't expect events with the same thread id to happen at the
// same time.
func StartGoroutine(ctx context.Context) context.Context {
	tc, ok := getTraceContext(ctx)
	if !ok {
		return ctx
	}
	return context.WithValue(ctx, traceKey{}, traceContext{tc.t, tc.t.getNextTID()})
}

// Flow marks a flow indicating that the 'to' span depends on the 'from' span.
// Flow should be called while the 'to' span is in progress.
func Flow(ctx context.Context, from *Span, to *Span) {
	tc, ok := getTraceContext(ctx)
	if !ok || from == nil || to == nil {
		return
	}

	id := tc.t.getNextFlowID()
	tc.t.writeEvent(&traceviewer.Event{
		Name:     from.name + " -> " + to.name,
		Category: "flow",
		ID:       id,
		Time:     float64(from.end.UnixNano()) / float64(time.Microsecond),
		Phase:    phaseFlowStart,
		TID:      from.tid,
	})
	tc.t.writeEvent(&traceviewer.Event{
		Name:      from.name + " -> " + to.name,
		Category:  "flow", // TODO(matloob): Add Category to Flow?
		ID:        id,
		Time:      float64(to.start.UnixNano()) / float64(time.Microsecond),
		Phase:     phaseFlowEnd,
		TID:       to.tid,
		BindPoint: bindEnclosingSlice,
	})
}

type Span struct {
	t *tracer

	name  string
	tid   uint64
	start time.Time
	end   time.Time
}

func (s *Span) Done() {
	if s == nil {
		return
	}
	s.end = time.Now()
	s.t.writeEvent(&traceviewer.Event{
		Name:  s.name,
		Time:  float64(s.end.UnixNano()) / float64(time.Microsecond),
		TID:   s.tid,
		Phase: phaseDurationEnd,
	})
}

type tracer struct {
	file chan traceFile // 1-buffered

	nextTID    uint64
	nextFlowID uint64
}

func (t *tracer) writeEvent(ev *traceviewer.Event) error {
	f := <-t.file
	defer func() { t.file <- f }()
	var err error
	if f.entries == 0 {
		_, err = f.sb.WriteString("[\n")
	} else {
		_, err = f.sb.WriteString(",")
	}
	f.entries++
	if err != nil {
		return nil
	}

	if err := f.enc.Encode(ev); err != nil {
		return err
	}

	// Write event string to output file.
	_, err = f.f.WriteString(f.sb.String())
	f.sb.Reset()
	return err
}

func (t *tracer) Close() error {
	f := <-t.file
	defer func() { t.file <- f }()

	_, firstErr := f.f.WriteString("]")
	if err := f.f.Close(); firstErr == nil {
		firstErr = err
	}
	return firstErr
}

func (t *tracer) getNextTID() uint64 {
	return atomic.AddUint64(&t.nextTID, 1)
}

func (t *tracer) getNextFlowID() uint64 {
	return atomic.AddUint64(&t.nextFlowID, 1)
}

// traceKey is the context key for tracing information. It is unexported to prevent collisions with context keys defined in
// other packages.
type traceKey struct{}

type traceContext struct {
	t   *tracer
	tid uint64
}

// Start starts a trace which writes to the given file.
func Start(ctx context.Context, file string) (context.Context, func() error, error) {
	traceStarted.Store(true)
	if file == "" {
		return nil, nil, errors.New("no trace file supplied")
	}
	f, err := os.Create(file)
	if err != nil {
		return nil, nil, err
	}
	t := &tracer{file: make(chan traceFile, 1)}
	sb := new(strings.Builder)
	t.file <- traceFile{
		f:   f,
		sb:  sb,
		enc: json.NewEncoder(sb),
	}
	ctx = context.WithValue(ctx, traceKey{}, traceContext{t: t})
	return ctx, t.Close, nil
}

type traceFile struct {
	f       *os.File
	sb      *strings.Builder
	enc     *json.Encoder
	entries int64
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// 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
//
// 	https://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 safehttp_test

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"github.com/google/go-safeweb/safehttp"
	"github.com/google/safehtml"
)

func TestRegisteredHandler(t *testing.T) {
	mb := safehttp.NewServeMuxConfig(nil)

	mb.Handle("/abc", safehttp.MethodGet, safehttp.HandlerFunc(func(w safehttp.ResponseWriter, r *safehttp.IncomingRequest) safehttp.Result {
		return w.Write(safehtml.HTMLEscaped("Welcome!"))
	}))
	mb.Handle("/abc", safehttp.MethodPost, safehttp.HandlerFunc(func(w safehttp.ResponseWriter, r *safehttp.IncomingRequest) safehttp.Result {
		f, err := r.PostForm()
		if err != nil {
			return w.WriteError(safehttp.StatusBadRequest)
		}
		animal := f.String("animal", "")
		if animal == "" {
			return w.WriteError(safehttp.StatusBadRequest)
		}
		return w.Write(safehtml.HTMLEscaped(fmt.Sprintf("Added %s.", animal)))
	}))
	mb.Handle("/def", safehttp.MethodGet, safehttp.HandlerFunc(func(w safehttp.ResponseWriter, r *safehttp.IncomingRequest) safehttp.Result {
		return w.Write(safehtml.HTMLEscaped("Bye!"))
	}))

	safeMux := mb.Mux()

	mux := http.NewServeMux()
	mux.Handle("/abc", safehttp.RegisteredHandler(safeMux, "/abc"))
	mux.Handle("/def", safehttp.RegisteredHandler(safeMux, "/def"))

	var tests = []struct {
		name       string
		req        *http.Request
		wantStatus safehttp.StatusCode
		wantBody   string
	}{
		{
			name:       "Valid GET Request",
			req:        httptest.NewRequest(safehttp.MethodGet, "http://foo.com/abc", nil),
			wantStatus: safehttp.StatusOK,
			wantBody:   "Welcome!",
		},
		{
			name: "Valid POST Request",
			req: func() *http.Request {
				req := httptest.NewRequest(safehttp.MethodPost, "http://foo.com/abc", strings.NewReader("animal=cat"))
				req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
				return req
			}(),
			wantStatus: safehttp.StatusOK,
			wantBody:   "Added cat.",
		},
		{
			name:       "Different handler",
			req:        httptest.NewRequest(safehttp.MethodGet, "http://foo.com/def", nil),
			wantStatus: safehttp.StatusOK,
			wantBody:   "Bye!",
		},
		{
			name:       "Invalid Method",
			req:        httptest.NewRequest(safehttp.MethodHead, "http://foo.com/abc", nil),
			wantStatus: safehttp.StatusMethodNotAllowed,
			wantBody:   "Method Not Allowed\n",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			rw := httptest.NewRecorder()

			mux.ServeHTTP(rw, tt.req)

			if rw.Code != int(tt.wantStatus) {
				t.Errorf("rw.Code: got %v want %v", rw.Code, tt.wantStatus)
			}

			if got := rw.Body.String(); got != tt.wantBody {
				t.Errorf("response body: got %q want %q", got, tt.wantBody)
			}
		})
	}
}
<commit_msg>More tests for RegisteredHandler.<commit_after>// Copyright 2020 Google LLC
//
// 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
//
// 	https://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 safehttp_test

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"github.com/google/go-safeweb/safehttp"
	"github.com/google/safehtml"
)

func TestRegisteredHandler(t *testing.T) {
	mb := safehttp.NewServeMuxConfig(nil)

	mb.Handle("/abc", safehttp.MethodGet, safehttp.HandlerFunc(func(w safehttp.ResponseWriter, r *safehttp.IncomingRequest) safehttp.Result {
		return w.Write(safehtml.HTMLEscaped("Welcome!"))
	}))
	mb.Handle("/abc", safehttp.MethodPost, safehttp.HandlerFunc(func(w safehttp.ResponseWriter, r *safehttp.IncomingRequest) safehttp.Result {
		f, err := r.PostForm()
		if err != nil {
			return w.WriteError(safehttp.StatusBadRequest)
		}
		animal := f.String("animal", "")
		if animal == "" {
			return w.WriteError(safehttp.StatusBadRequest)
		}
		return w.Write(safehtml.HTMLEscaped(fmt.Sprintf("Added %s.", animal)))
	}))
	mb.Handle("/def", safehttp.MethodGet, safehttp.HandlerFunc(func(w safehttp.ResponseWriter, r *safehttp.IncomingRequest) safehttp.Result {
		return w.Write(safehtml.HTMLEscaped("Bye!"))
	}))

	safeMux := mb.Mux()

	mux := http.NewServeMux()
	mux.Handle("/abc", safehttp.RegisteredHandler(safeMux, "/abc"))
	mux.Handle("/def", safehttp.RegisteredHandler(safeMux, "/def"))

	var tests = []struct {
		name       string
		req        *http.Request
		wantStatus safehttp.StatusCode
		wantBody   string
	}{
		{
			name:       "Valid GET Request",
			req:        httptest.NewRequest(safehttp.MethodGet, "http://foo.com/abc", nil),
			wantStatus: safehttp.StatusOK,
			wantBody:   "Welcome!",
		},
		{
			name: "Valid POST Request",
			req: func() *http.Request {
				req := httptest.NewRequest(safehttp.MethodPost, "http://foo.com/abc", strings.NewReader("animal=cat"))
				req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
				return req
			}(),
			wantStatus: safehttp.StatusOK,
			wantBody:   "Added cat.",
		},
		{
			name:       "Different handler",
			req:        httptest.NewRequest(safehttp.MethodGet, "http://foo.com/def", nil),
			wantStatus: safehttp.StatusOK,
			wantBody:   "Bye!",
		},
		{
			name:       "Invalid Method",
			req:        httptest.NewRequest(safehttp.MethodHead, "http://foo.com/abc", nil),
			wantStatus: safehttp.StatusMethodNotAllowed,
			wantBody:   "Method Not Allowed\n",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			rw := httptest.NewRecorder()

			mux.ServeHTTP(rw, tt.req)

			if rw.Code != int(tt.wantStatus) {
				t.Errorf("rw.Code: got %v want %v", rw.Code, tt.wantStatus)
			}

			if got := rw.Body.String(); got != tt.wantBody {
				t.Errorf("response body: got %q want %q", got, tt.wantBody)
			}
		})
	}
}

func TestRegisteredHandler_StrictPatterns(t *testing.T) {
	mb := safehttp.NewServeMuxConfig(nil)

	mb.Handle("/foo/", safehttp.MethodGet, safehttp.HandlerFunc(func(w safehttp.ResponseWriter, r *safehttp.IncomingRequest) safehttp.Result {
		return w.Write(safehtml.HTMLEscaped("Homepage!"))
	}))
	safeMux := mb.Mux()

	if safehttp.RegisteredHandler(safeMux, "/foo/") == nil {
		t.Error(`RegisteredHandler(_, "/foo/") got nil, want non-nil`)
	}
	if safehttp.RegisteredHandler(safeMux, "/foo/subpath") != nil {
		t.Error(`RegisteredHandler(_, "/foo/subpath") got non-nil, want nil`)
	}
}
<|endoftext|>


<commit_before>package testutil

import (
	"fmt"
	"os"
	"time"

	"github.com/hashicorp/nomad/nomad/structs"
	"github.com/kr/pretty"
	testing "github.com/mitchellh/go-testing-interface"
	"github.com/stretchr/testify/require"
)

type testFn func() (bool, error)
type errorFn func(error)

func WaitForResult(test testFn, error errorFn) {
	WaitForResultRetries(500*TestMultiplier(), test, error)
}

func WaitForResultRetries(retries int64, test testFn, error errorFn) {
	for retries > 0 {
		time.Sleep(10 * time.Millisecond)
		retries--

		success, err := test()
		if success {
			return
		}

		if retries == 0 {
			error(err)
		}
	}
}

// AssertUntil asserts the test function passes throughout the given duration.
// Otherwise error is called on failure.
func AssertUntil(until time.Duration, test testFn, error errorFn) {
	deadline := time.Now().Add(until)
	for time.Now().Before(deadline) {
		success, err := test()
		if !success {
			error(err)
			return
		}
		// Sleep some arbitrary fraction of the deadline
		time.Sleep(until / 30)
	}
}

// TestMultiplier returns a multiplier for retries and waits given environment
// the tests are being run under.
func TestMultiplier() int64 {
	if IsCI() {
		return 4
	}

	return 1
}

// Timeout takes the desired timeout and increases it if running in Travis
func Timeout(original time.Duration) time.Duration {
	return original * time.Duration(TestMultiplier())
}

func IsCI() bool {
	_, ok := os.LookupEnv("CI")
	return ok
}

func IsTravis() bool {
	_, ok := os.LookupEnv("TRAVIS")
	return ok
}

func IsAppVeyor() bool {
	_, ok := os.LookupEnv("APPVEYOR")
	return ok
}

type rpcFn func(string, interface{}, interface{}) error

// WaitForLeader blocks until a leader is elected.
func WaitForLeader(t testing.T, rpc rpcFn) {
	WaitForResult(func() (bool, error) {
		args := &structs.GenericRequest{}
		args.AllowStale = true
		var leader string
		err := rpc("Status.Leader", args, &leader)
		return leader != "", err
	}, func(err error) {
		t.Fatalf("failed to find leader: %v", err)
	})
}

// WaitForVotingMembers blocks until autopilot promotes all server peers
// to be voting members.
//
// Useful for tests that change cluster topology (e.g. kill a node)
// that should wait until cluster is stable.
func WaitForVotingMembers(t testing.T, rpc rpcFn, nPeers int) {
	WaitForResult(func() (bool, error) {
		args := &structs.GenericRequest{}
		args.AllowStale = true
		args.Region = "global"
		args.Namespace = structs.DefaultNamespace
		resp := structs.RaftConfigurationResponse{}
		err := rpc("Operator.RaftGetConfiguration", args, &resp)
		if err != nil {
			return false, fmt.Errorf("failed to query raft: %v", err)
		}

		if len(resp.Servers) != nPeers {
			return false, fmt.Errorf("expected %d peers found %d", nPeers, len(resp.Servers))
		}

		for _, s := range resp.Servers {
			if !s.Voter {
				return false, fmt.Errorf("found nonvoting server: %v", s)
			}
		}

		return true, nil
	}, func(err error) {
		t.Fatalf("failed to wait until voting members: %v", err)
	})
}

// RegisterJobWithToken registers a job and uses the job's Region and Namespace.
func RegisterJobWithToken(t testing.T, rpc rpcFn, job *structs.Job, token string) {
	WaitForResult(func() (bool, error) {
		args := &structs.JobRegisterRequest{}
		args.Job = job
		args.WriteRequest.Region = job.Region
		args.AuthToken = token
		args.Namespace = job.Namespace
		var jobResp structs.JobRegisterResponse
		err := rpc("Job.Register", args, &jobResp)
		return err == nil, fmt.Errorf("Job.Register error: %v", err)
	}, func(err error) {
		t.Fatalf("error registering job: %v", err)
	})

	t.Logf("Job %q registered", job.ID)
}

func RegisterJob(t testing.T, rpc rpcFn, job *structs.Job) {
	RegisterJobWithToken(t, rpc, job, "")
}

func WaitForRunningWithToken(t testing.T, rpc rpcFn, job *structs.Job, token string) []*structs.AllocListStub {
	RegisterJobWithToken(t, rpc, job, token)

	var resp structs.JobAllocationsResponse

	WaitForResult(func() (bool, error) {
		args := &structs.JobSpecificRequest{}
		args.JobID = job.ID
		args.QueryOptions.Region = job.Region
		args.AuthToken = token
		args.Namespace = job.Namespace
		err := rpc("Job.Allocations", args, &resp)
		if err != nil {
			return false, fmt.Errorf("Job.Allocations error: %v", err)
		}

		if len(resp.Allocations) == 0 {
			evals := structs.JobEvaluationsResponse{}
			require.NoError(t, rpc("Job.Evaluations", args, &evals), "error looking up evals")
			return false, fmt.Errorf("0 allocations; evals: %s", pretty.Sprint(evals.Evaluations))
		}

		for _, alloc := range resp.Allocations {
			if alloc.ClientStatus == structs.AllocClientStatusPending {
				return false, fmt.Errorf("alloc not running: id=%v tg=%v status=%v",
					alloc.ID, alloc.TaskGroup, alloc.ClientStatus)
			}
		}

		return true, nil
	}, func(err error) {
		require.NoError(t, err)
	})

	return resp.Allocations
}

// WaitForRunning runs a job and blocks until all allocs are out of pending.
func WaitForRunning(t testing.T, rpc rpcFn, job *structs.Job) []*structs.AllocListStub {
	return WaitForRunningWithToken(t, rpc, job, "")
}
<commit_msg>tests: wait until leadership loop finishes<commit_after>package testutil

import (
	"fmt"
	"os"
	"time"

	"github.com/hashicorp/nomad/nomad/structs"
	"github.com/kr/pretty"
	testing "github.com/mitchellh/go-testing-interface"
	"github.com/stretchr/testify/require"
)

type testFn func() (bool, error)
type errorFn func(error)

func WaitForResult(test testFn, error errorFn) {
	WaitForResultRetries(500*TestMultiplier(), test, error)
}

func WaitForResultRetries(retries int64, test testFn, error errorFn) {
	for retries > 0 {
		time.Sleep(10 * time.Millisecond)
		retries--

		success, err := test()
		if success {
			return
		}

		if retries == 0 {
			error(err)
		}
	}
}

// AssertUntil asserts the test function passes throughout the given duration.
// Otherwise error is called on failure.
func AssertUntil(until time.Duration, test testFn, error errorFn) {
	deadline := time.Now().Add(until)
	for time.Now().Before(deadline) {
		success, err := test()
		if !success {
			error(err)
			return
		}
		// Sleep some arbitrary fraction of the deadline
		time.Sleep(until / 30)
	}
}

// TestMultiplier returns a multiplier for retries and waits given environment
// the tests are being run under.
func TestMultiplier() int64 {
	if IsCI() {
		return 4
	}

	return 1
}

// Timeout takes the desired timeout and increases it if running in Travis
func Timeout(original time.Duration) time.Duration {
	return original * time.Duration(TestMultiplier())
}

func IsCI() bool {
	_, ok := os.LookupEnv("CI")
	return ok
}

func IsTravis() bool {
	_, ok := os.LookupEnv("TRAVIS")
	return ok
}

func IsAppVeyor() bool {
	_, ok := os.LookupEnv("APPVEYOR")
	return ok
}

type rpcFn func(string, interface{}, interface{}) error

// WaitForLeader blocks until a leader is elected.
func WaitForLeader(t testing.T, rpc rpcFn) {
	t.Helper()
	WaitForResult(func() (bool, error) {
		args := &structs.GenericRequest{}
		var leader string
		err := rpc("Status.Leader", args, &leader)
		return leader != "", err
	}, func(err error) {
		t.Fatalf("failed to find leader: %v", err)
	})
}

// WaitForVotingMembers blocks until autopilot promotes all server peers
// to be voting members.
//
// Useful for tests that change cluster topology (e.g. kill a node)
// that should wait until cluster is stable.
func WaitForVotingMembers(t testing.T, rpc rpcFn, nPeers int) {
	WaitForResult(func() (bool, error) {
		args := &structs.GenericRequest{}
		args.AllowStale = true
		args.Region = "global"
		args.Namespace = structs.DefaultNamespace
		resp := structs.RaftConfigurationResponse{}
		err := rpc("Operator.RaftGetConfiguration", args, &resp)
		if err != nil {
			return false, fmt.Errorf("failed to query raft: %v", err)
		}

		if len(resp.Servers) != nPeers {
			return false, fmt.Errorf("expected %d peers found %d", nPeers, len(resp.Servers))
		}

		for _, s := range resp.Servers {
			if !s.Voter {
				return false, fmt.Errorf("found nonvoting server: %v", s)
			}
		}

		return true, nil
	}, func(err error) {
		t.Fatalf("failed to wait until voting members: %v", err)
	})
}

// RegisterJobWithToken registers a job and uses the job's Region and Namespace.
func RegisterJobWithToken(t testing.T, rpc rpcFn, job *structs.Job, token string) {
	WaitForResult(func() (bool, error) {
		args := &structs.JobRegisterRequest{}
		args.Job = job
		args.WriteRequest.Region = job.Region
		args.AuthToken = token
		args.Namespace = job.Namespace
		var jobResp structs.JobRegisterResponse
		err := rpc("Job.Register", args, &jobResp)
		return err == nil, fmt.Errorf("Job.Register error: %v", err)
	}, func(err error) {
		t.Fatalf("error registering job: %v", err)
	})

	t.Logf("Job %q registered", job.ID)
}

func RegisterJob(t testing.T, rpc rpcFn, job *structs.Job) {
	RegisterJobWithToken(t, rpc, job, "")
}

func WaitForRunningWithToken(t testing.T, rpc rpcFn, job *structs.Job, token string) []*structs.AllocListStub {
	RegisterJobWithToken(t, rpc, job, token)

	var resp structs.JobAllocationsResponse

	WaitForResult(func() (bool, error) {
		args := &structs.JobSpecificRequest{}
		args.JobID = job.ID
		args.QueryOptions.Region = job.Region
		args.AuthToken = token
		args.Namespace = job.Namespace
		err := rpc("Job.Allocations", args, &resp)
		if err != nil {
			return false, fmt.Errorf("Job.Allocations error: %v", err)
		}

		if len(resp.Allocations) == 0 {
			evals := structs.JobEvaluationsResponse{}
			require.NoError(t, rpc("Job.Evaluations", args, &evals), "error looking up evals")
			return false, fmt.Errorf("0 allocations; evals: %s", pretty.Sprint(evals.Evaluations))
		}

		for _, alloc := range resp.Allocations {
			if alloc.ClientStatus == structs.AllocClientStatusPending {
				return false, fmt.Errorf("alloc not running: id=%v tg=%v status=%v",
					alloc.ID, alloc.TaskGroup, alloc.ClientStatus)
			}
		}

		return true, nil
	}, func(err error) {
		require.NoError(t, err)
	})

	return resp.Allocations
}

// WaitForRunning runs a job and blocks until all allocs are out of pending.
func WaitForRunning(t testing.T, rpc rpcFn, job *structs.Job) []*structs.AllocListStub {
	return WaitForRunningWithToken(t, rpc, job, "")
}
<|endoftext|>


<commit_before>package asset

import (
	"context"
	"io/ioutil"
	"os"
	"reflect"
	"strings"
	"testing"

	dbm "github.com/tendermint/tmlibs/db"

	"github.com/bytom/consensus"
	"github.com/bytom/crypto/ed25519/chainkd"
	"github.com/bytom/database/leveldb"
	"github.com/bytom/protocol"
	"github.com/bytom/testutil"
)

func TestDefineAssetWithLowercase(t *testing.T) {
	reg := mockNewRegistry(t)
	alias := "lower"
	asset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, alias, nil)
	if err != nil {
		t.Fatal(err)
	}
	if *asset.Alias != strings.ToUpper(alias) {
		t.Fatal("created asset alias should be uppercase")
	}
}

func TestDefineAssetWithSpaceTrimed(t *testing.T) {
	reg := mockNewRegistry(t)
	alias := " WITH SPACE "
	asset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, alias, nil)
	if err != nil {
		t.Fatal(err)
	}
	if *asset.Alias != strings.TrimSpace(alias) {
		t.Fatal("created asset alias should be uppercase")
	}
}

func TestDefineAsset(t *testing.T) {
	ctx := context.Background()
	reg := mockNewRegistry(t)
	asset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, "asset-alias", nil)
	if err != nil {
		testutil.FatalErr(t, err)
	}

	found, err := reg.FindByID(ctx, &asset.AssetID)
	if err != nil {
		t.Errorf("unexpected error %v", err)
	}

	if !testutil.DeepEqual(asset, found) {
		t.Errorf("expected asset %v to be recorded as %v", asset, found)
	}
}

func TestDefineBtmAsset(t *testing.T) {
	reg := mockNewRegistry(t)
	_, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, consensus.BTMAlias, nil)
	if err == nil {
		testutil.FatalErr(t, err)
	}
}

func TestFindAssetByID(t *testing.T) {
	ctx := context.Background()
	reg := mockNewRegistry(t)
	keys := []chainkd.XPub{testutil.TestXPub}
	asset, err := reg.Define(keys, 1, nil, "", nil)
	if err != nil {
		testutil.FatalErr(t, err)

	}
	found, err := reg.FindByID(ctx, &asset.AssetID)
	if err != nil {
		testutil.FatalErr(t, err)
	}

	if !testutil.DeepEqual(asset, found) {
		t.Errorf("expected %v and %v to match", asset, found)
	}
}

func TestUpdateAssetTags(t *testing.T) {
	dirPath, err := ioutil.TempDir(".", "")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(dirPath)

	testDB := dbm.NewDB("testdb", "leveldb", "temp")
	defer os.RemoveAll("temp")

	store := leveldb.NewStore(testDB)
	txPool := protocol.NewTxPool()
	chain, err := protocol.NewChain(store, txPool)
	if err != nil {
		t.Fatal(err)
	}

	reg := NewRegistry(testDB, chain)
	ctx := context.Background()

	asset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, "asset-alias",
		map[string]interface{}{
			"test_tag": "v0",
		})
	if err != nil {
		testutil.FatalErr(t, err)
	}

	// Update by ID
	wantTags := map[string]interface{}{
		"test_tag": "v1",
	}

	if reg.UpdateTags(ctx, asset.AssetID.String(), wantTags) != nil {
		testutil.FatalErr(t, err)
	}

	asset1, err := reg.FindByAlias(ctx, *asset.Alias)
	if err != nil {
		testutil.FatalErr(t, err)
	}

	gotTags := asset1.Tags
	if !reflect.DeepEqual(gotTags, wantTags) {
		t.Fatalf("tags:\ngot:  %v\nwant: %v", gotTags, wantTags)
	}

	// Update by alias
	wantTags = map[string]interface{}{
		"test_tag": "v2",
	}

	if reg.UpdateTags(ctx, *asset.Alias, wantTags) != nil {
		testutil.FatalErr(t, err)
	}

	asset2, err := reg.FindByAlias(ctx, *asset.Alias)
	if err != nil {
		testutil.FatalErr(t, err)
	}

	gotTags = asset2.Tags
	if !reflect.DeepEqual(gotTags, wantTags) {
		t.Fatalf("tags:\ngot:  %v\nwant: %v", gotTags, wantTags)
	}
}

func TestUpdateAssetAlias(t *testing.T) {
	ctx := context.Background()
	reg := mockNewRegistry(t)

	oldAlias := "OLD_ALIAS"
	newAlias := "NEW_ALIAS"

	_, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, oldAlias, nil)
	if err != nil {
		testutil.FatalErr(t, err)
	}

	if reg.UpdateAssetAlias(oldAlias, newAlias) != nil {
		testutil.FatalErr(t, err)
	}

	asset1, err := reg.FindByAlias(ctx, newAlias)
	if err != nil {
		testutil.FatalErr(t, err)
	}

	gotAlias := *asset1.Alias
	if !reflect.DeepEqual(gotAlias, newAlias) {
		t.Fatalf("alias:\ngot:  %v\nwant: %v", gotAlias, newAlias)
	}
}

func TestListAssets(t *testing.T) {
	reg := mockNewRegistry(t)

	firstAlias := "FIRST_ALIAS"
	secondAlias := "SECOND_ALIAS"

	firstAsset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, firstAlias, nil)
	if err != nil {
		testutil.FatalErr(t, err)
	}

	secondAsset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, secondAlias, nil)
	if err != nil {
		testutil.FatalErr(t, err)
	}

	wantAssets := []*Asset{DefaultNativeAsset, secondAsset, firstAsset}

	gotAssets, err := reg.ListAssets("")
	if err != nil {
		testutil.FatalErr(t, err)
	}

	if !testutil.DeepEqual(gotAssets, wantAssets) {
		t.Fatalf("got:\ngot:  %v\nwant: %v", gotAssets, wantAssets)
	}
}

func mockChain(testDB dbm.DB) (*protocol.Chain, error) {
	store := leveldb.NewStore(testDB)
	txPool := protocol.NewTxPool()
	chain, err := protocol.NewChain(store, txPool)
	if err != nil {
		return nil, err
	}
	return chain, nil
}

func mockNewRegistry(t *testing.T) *Registry {
	dirPath, err := ioutil.TempDir(".", "")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(dirPath)

	testDB := dbm.NewDB("testdb", "leveldb", "temp")
	defer os.RemoveAll("temp")

	chain, err := mockChain(testDB)
	if err != nil {
		t.Fatal(err)
	}

	return NewRegistry(testDB, chain)
}
<commit_msg>fix unit test<commit_after>package asset

import (
	"context"
	"io/ioutil"
	"os"
	"reflect"
	"strings"
	"testing"

	dbm "github.com/tendermint/tmlibs/db"

	"github.com/bytom/consensus"
	"github.com/bytom/crypto/ed25519/chainkd"
	"github.com/bytom/database/leveldb"
	"github.com/bytom/protocol"
	"github.com/bytom/testutil"
)

func TestDefineAssetWithLowercase(t *testing.T) {
	reg := mockNewRegistry(t)
	alias := "lower"
	asset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, alias, nil)
	if err != nil {
		t.Fatal(err)
	}
	if *asset.Alias != strings.ToUpper(alias) {
		t.Fatal("created asset alias should be uppercase")
	}
}

func TestDefineAssetWithSpaceTrimed(t *testing.T) {
	reg := mockNewRegistry(t)
	alias := " WITH SPACE "
	asset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, alias, nil)
	if err != nil {
		t.Fatal(err)
	}
	if *asset.Alias != strings.TrimSpace(alias) {
		t.Fatal("created asset alias should be uppercase")
	}
}

func TestDefineAsset(t *testing.T) {
	ctx := context.Background()
	reg := mockNewRegistry(t)
	asset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, "asset-alias", nil)
	if err != nil {
		testutil.FatalErr(t, err)
	}

	found, err := reg.FindByID(ctx, &asset.AssetID)
	if err != nil {
		t.Errorf("unexpected error %v", err)
	}

	if !testutil.DeepEqual(asset, found) {
		t.Errorf("expected asset %v to be recorded as %v", asset, found)
	}
}

func TestDefineBtmAsset(t *testing.T) {
	reg := mockNewRegistry(t)
	_, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, consensus.BTMAlias, nil)
	if err == nil {
		testutil.FatalErr(t, err)
	}
}

func TestFindAssetByID(t *testing.T) {
	ctx := context.Background()
	reg := mockNewRegistry(t)
	keys := []chainkd.XPub{testutil.TestXPub}
	asset, err := reg.Define(keys, 1, nil, "", nil)
	if err != nil {
		testutil.FatalErr(t, err)

	}
	found, err := reg.FindByID(ctx, &asset.AssetID)
	if err != nil {
		testutil.FatalErr(t, err)
	}

	if !testutil.DeepEqual(asset, found) {
		t.Errorf("expected %v and %v to match", asset, found)
	}
}

func TestUpdateAssetTags(t *testing.T) {
	dirPath, err := ioutil.TempDir(".", "")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(dirPath)

	testDB := dbm.NewDB("testdb", "leveldb", "temp")
	defer os.RemoveAll("temp")

	store := leveldb.NewStore(testDB)
	txPool := protocol.NewTxPool()
	chain, err := protocol.NewChain(store, txPool)
	if err != nil {
		t.Fatal(err)
	}

	reg := NewRegistry(testDB, chain)
	ctx := context.Background()

	asset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, "asset-alias",
		map[string]interface{}{
			"test_tag": "v0",
		})
	if err != nil {
		testutil.FatalErr(t, err)
	}

	// Update by ID
	wantTags := map[string]interface{}{
		"test_tag": "v1",
	}

	if reg.UpdateTags(ctx, asset.AssetID.String(), wantTags) != nil {
		testutil.FatalErr(t, err)
	}

	asset1, err := reg.FindByAlias(ctx, *asset.Alias)
	if err != nil {
		testutil.FatalErr(t, err)
	}

	gotTags := asset1.Tags
	if !reflect.DeepEqual(gotTags, wantTags) {
		t.Fatalf("tags:\ngot:  %v\nwant: %v", gotTags, wantTags)
	}

	// Update by alias
	wantTags = map[string]interface{}{
		"test_tag": "v2",
	}

	if reg.UpdateTags(ctx, *asset.Alias, wantTags) != nil {
		testutil.FatalErr(t, err)
	}

	asset2, err := reg.FindByAlias(ctx, *asset.Alias)
	if err != nil {
		testutil.FatalErr(t, err)
	}

	gotTags = asset2.Tags
	if !reflect.DeepEqual(gotTags, wantTags) {
		t.Fatalf("tags:\ngot:  %v\nwant: %v", gotTags, wantTags)
	}
}

func TestUpdateAssetAlias(t *testing.T) {
	ctx := context.Background()
	reg := mockNewRegistry(t)

	oldAlias := "OLD_ALIAS"
	newAlias := "NEW_ALIAS"

	_, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, oldAlias, nil)
	if err != nil {
		testutil.FatalErr(t, err)
	}

	if reg.UpdateAssetAlias(oldAlias, newAlias) != nil {
		testutil.FatalErr(t, err)
	}

	asset1, err := reg.FindByAlias(ctx, newAlias)
	if err != nil {
		testutil.FatalErr(t, err)
	}

	gotAlias := *asset1.Alias
	if !reflect.DeepEqual(gotAlias, newAlias) {
		t.Fatalf("alias:\ngot:  %v\nwant: %v", gotAlias, newAlias)
	}
}

func TestListAssets(t *testing.T) {
	reg := mockNewRegistry(t)

	firstAlias := "FIRST_ALIAS"
	secondAlias := "SECOND_ALIAS"

	firstAsset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, firstAlias, nil)
	if err != nil {
		testutil.FatalErr(t, err)
	}

	secondAsset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, secondAlias, nil)
	if err != nil {
		testutil.FatalErr(t, err)
	}

	wantAssets := []*Asset{DefaultNativeAsset, firstAsset, secondAsset}

	gotAssets, err := reg.ListAssets("")
	if err != nil {
		testutil.FatalErr(t, err)
	}

	if !testutil.DeepEqual(gotAssets, wantAssets) {
		t.Fatalf("got:\ngot:  %v\nwant: %v", gotAssets, wantAssets)
	}
}

func mockChain(testDB dbm.DB) (*protocol.Chain, error) {
	store := leveldb.NewStore(testDB)
	txPool := protocol.NewTxPool()
	chain, err := protocol.NewChain(store, txPool)
	if err != nil {
		return nil, err
	}
	return chain, nil
}

func mockNewRegistry(t *testing.T) *Registry {
	dirPath, err := ioutil.TempDir(".", "")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(dirPath)

	testDB := dbm.NewDB("testdb", "leveldb", "temp")
	defer os.RemoveAll("temp")

	chain, err := mockChain(testDB)
	if err != nil {
		t.Fatal(err)
	}

	return NewRegistry(testDB, chain)
}
<|endoftext|>