<commit_before>package glib

import (
	//"fmt"
	"github.com/nsf/termbox-go"
	"github.com/simulatedsimian/rect"
)

func printAt(b Buffer, x, y int, s string, fg, bg termbox.Attribute) {
	for _, r := range s {
		b.SetCell(x, y, r, fg, bg)
		x++
	}
}

type Buffer interface {
	SetCell(x, y int, ch rune, fg, bg termbox.Attribute)
	GetCell(x, y int) (rune, termbox.Attribute, termbox.Attribute)
	Size() (int, int)
}

type TermboxBufferType struct {
}

var TermboxBuffer TermboxBufferType

func (b TermboxBufferType) SetCell(x, y int, ch rune, fg, bg termbox.Attribute) {
	termbox.SetCell(x, y, ch, fg, bg)
}

func (b TermboxBufferType) GetCell(x, y int) (rune, termbox.Attribute, termbox.Attribute) {
	cells := termbox.CellBuffer()
	w, _ := termbox.Size()
	cell := &cells[y*w+x]
	return cell.Ch, cell.Fg, cell.Bg
}

func (b TermboxBufferType) Size() (int, int) {
	return termbox.Size()
}

type MemBuffer struct {
	w, h  int
	cells []termbox.Cell
}

func MakeMemBuffer(w, h int) *MemBuffer {
	return &MemBuffer{w, h, make([]termbox.Cell, w*h)}
}

func (b *MemBuffer) SetCell(x, y int, ch rune, fg, bg termbox.Attribute) {
	if x < 0 || x >= b.w {
		return
	}
	if y < 0 || y >= b.h {
		return
	}
	b.cells[y*b.w+x] = termbox.Cell{ch, fg, bg}
}

func (b *MemBuffer) GetCell(x, y int) (rune, termbox.Attribute, termbox.Attribute) {
	cell := &b.cells[y*b.w+x]
	return cell.Ch, cell.Fg, cell.Bg
}

func (b *MemBuffer) Size() (int, int) {
	return b.w, b.h
}

const (
	CHAR    = 1
	FG      = 2
	BG      = 4
	ALL     = CHAR | FG | BG
	ATTRIBS = FG | BG
)

func FillArea(dst Buffer, area rect.Rectangle, ch rune, fg, bg termbox.Attribute, filltype int) {
	area, ok := rect.Intersection(rect.WH(dst.Size()), area)

	if ok {
		for x := area.Min.X; x < area.Max.X; x++ {
			for y := area.Min.Y; y < area.Max.Y; y++ {
				if filltype == ALL {
					dst.SetCell(x, y, ch, fg, bg)
				} else {
					nch, nfg, nbg := dst.GetCell(x, y)
					if filltype&CHAR != 0 {
						nch = ch
					}
					if filltype&FG != 0 {
						nfg = fg
					}
					if filltype&BG != 0 {
						nbg = bg
					}
					dst.SetCell(x, y, nch, nfg, nbg)
				}
			}
		}
	}
}

func Fill(dst Buffer, ch rune, fg, bg termbox.Attribute, filltype int) {
	FillArea(dst, rect.WH(dst.Size()), ch, fg, bg, filltype)
}

func BlitBuffer(src, dst Buffer, xpos, ypos int) {
	srcSz := rect.WH(src.Size())
	srcSz.Translate(rect.Vec{xpos, ypos})

	dstSz := rect.WH(dst.Size())

	if intersect, ok := rect.Intersection(srcSz, dstSz); ok {
		for y := intersect.Min.Y; y < intersect.Max.Y; y++ {
			for x := intersect.Min.X; x < intersect.Max.X; x++ {
				nch, nfg, nbg := src.GetCell(x-xpos, y-ypos)
				dst.SetCell(x, y, nch, nfg, nbg)
			}
		}
	}
}
<commit_msg>added CellBuffer() to buffer interface<commit_after>package glib

import (
	//"fmt"
	"github.com/nsf/termbox-go"
	"github.com/simulatedsimian/rect"
)

func printAt(b Buffer, x, y int, s string, fg, bg termbox.Attribute) {
	for _, r := range s {
		b.SetCell(x, y, r, fg, bg)
		x++
	}
}

type Buffer interface {
	SetCell(x, y int, ch rune, fg, bg termbox.Attribute)
	GetCell(x, y int) (rune, termbox.Attribute, termbox.Attribute)
	Size() (int, int)
	CellBuffer() []termbox.Cell
}

type TermboxBufferType struct {
}

var TermboxBuffer TermboxBufferType

func (b TermboxBufferType) SetCell(x, y int, ch rune, fg, bg termbox.Attribute) {
	termbox.SetCell(x, y, ch, fg, bg)
}

func (b TermboxBufferType) GetCell(x, y int) (rune, termbox.Attribute, termbox.Attribute) {
	cells := termbox.CellBuffer()
	w, _ := termbox.Size()
	cell := &cells[y*w+x]
	return cell.Ch, cell.Fg, cell.Bg
}

func (b TermboxBufferType) Size() (int, int) {
	return termbox.Size()
}

func (b TermboxBufferType) CellBuffer() []termbox.Cell {
	return termbox.CellBuffer()
}

type MemBuffer struct {
	w, h  int
	cells []termbox.Cell
}

func MakeMemBuffer(w, h int) *MemBuffer {
	return &MemBuffer{w, h, make([]termbox.Cell, w*h)}
}

func (b *MemBuffer) SetCell(x, y int, ch rune, fg, bg termbox.Attribute) {
	if x < 0 || x >= b.w {
		return
	}
	if y < 0 || y >= b.h {
		return
	}
	b.cells[y*b.w+x] = termbox.Cell{ch, fg, bg}
}

func (b *MemBuffer) GetCell(x, y int) (rune, termbox.Attribute, termbox.Attribute) {
	cell := &b.cells[y*b.w+x]
	return cell.Ch, cell.Fg, cell.Bg
}

func (b *MemBuffer) Size() (int, int) {
	return b.w, b.h
}

func (b *MemBuffer) CellBuffer() []termbox.Cell {
	return b.cells
}

const (
	CHAR    = 1
	FG      = 2
	BG      = 4
	ALL     = CHAR | FG | BG
	ATTRIBS = FG | BG
)

func FillArea(dst Buffer, area rect.Rectangle, ch rune, fg, bg termbox.Attribute, filltype int) {
	area, ok := rect.Intersection(rect.WH(dst.Size()), area)

	if ok {
		for x := area.Min.X; x < area.Max.X; x++ {
			for y := area.Min.Y; y < area.Max.Y; y++ {
				if filltype == ALL {
					dst.SetCell(x, y, ch, fg, bg)
				} else {
					nch, nfg, nbg := dst.GetCell(x, y)
					if filltype&CHAR != 0 {
						nch = ch
					}
					if filltype&FG != 0 {
						nfg = fg
					}
					if filltype&BG != 0 {
						nbg = bg
					}
					dst.SetCell(x, y, nch, nfg, nbg)
				}
			}
		}
	}
}

func Fill(dst Buffer, ch rune, fg, bg termbox.Attribute, filltype int) {
	FillArea(dst, rect.WH(dst.Size()), ch, fg, bg, filltype)
}

func BlitBuffer(src, dst Buffer, xpos, ypos int) {
	srcSz := rect.WH(src.Size())
	srcSz.Translate(rect.Vec{xpos, ypos})

	dstSz := rect.WH(dst.Size())

	if intersect, ok := rect.Intersection(srcSz, dstSz); ok {
		for y := intersect.Min.Y; y < intersect.Max.Y; y++ {
			for x := intersect.Min.X; x < intersect.Max.X; x++ {
				nch, nfg, nbg := src.GetCell(x-xpos, y-ypos)
				dst.SetCell(x, y, nch, nfg, nbg)
			}
		}
	}
}
<|endoftext|>


<commit_before>/*
  Test Go's type system for inheritence and polymorphism.
*/
package main

import "fmt"

type Args struct {
  id uint
  check bool
  who string
}

type Args2 struct {
  // has to be anonymous and not a pointer
  // it really is best to think of these as nested structs, the language just
  // has convinience of seeing through all the nesting. e.g instead of needing
  // to type: Args2.Args.Id() you just type Args2.Id().... however Args2 is a
  // distinct type from Args, *no subclass relation has been established*.
  // e.g a function taking a Args argument won't accept an Args2 in its place.

  // This is kind of strange in that you inherit Args methods and fields but you
  // don't establish a type relation... I guess you do inherit the same subtype
  // relations as Args already has though. So if Args is a subtype of B & C
  // (through interfaces) then Args2 is also a subtype of B & C but has no
  // relation to Args. Its like a new type that uses Args as a starting point
  // but otherwise is not related to Args.
  Args
  CAS uint64
}

// interfaces are used for polymorphism.
// so Args & Args2 are distinct types still but Arg is a subtype of T and by
// inheriting from Args, Args2 is also a subtype of T... saying subtype is wrong
// in some ways as I don't think you can really have a hierachy. Its just flat.
// So field names can't be polymorphic though so need to use getter / setters
// still.
type T interface {
  Id() uint
  Check() bool
  Who() string
}

// implement T (note this implements T for Args2 as well!)
func (this *Args) Id() uint {
  return this.id
}

func (this *Args) Check() bool {
  return this.check
}

func (this *Args) Who() string {
  return this.who
}

func (this *Args) PolyFunc() {
  fmt.Println("Args is", this.Who())
}

func main() {
  a := &Args{0, true, "Args"}
  b := &Args2{Args{0, true, "Args2"}, 12}
  // Can compose
  c := &Args2{*a, 13}

  showArgs(a)
  // Can access anonymous struct by using its type
  // here the nesting is apparent!
  showArgs(&b.Args)
  showArgs(&c.Args)

  a.PolyFunc()
  b.PolyFunc()

  idT(a)
  idT(b)
  idT(c)
}

// Argument is Args, so not polymorphic sadly, Args2 won't be accepted
func showArgs(arg *Args) {
  fmt.Println("Args:", arg)
}

// Note argument is T! so polymorphic...!
func idT(t T) {
  fmt.Println("ID:", t.Id())
}

<commit_msg>more on Go sub classing<commit_after>/*
  Test Go's type system for inheritence and polymorphism.
*/
package main

import "fmt"

type Args struct {
  id uint
  check bool
  who string
}

type Args2 struct {
  // has to be anonymous and not a pointer
  // it really is best to think of these as nested structs, the language just
  // has convinience of seeing through all the nesting. e.g instead of needing
  // to type: Args2.Args.Id() you just type Args2.Id().... however Args2 is a
  // distinct type from Args, *no subclass relation has been established*.
  // e.g a function taking a Args argument won't accept an Args2 in its place.

  // This is kind of strange in that you inherit Args methods and fields but you
  // don't establish a type relation... I guess you do inherit the same subtype
  // relations as Args already has though. So if Args is a subtype of B & C
  // (through interfaces) then Args2 is also a subtype of B & C but has no
  // relation to Args. Its like a new type that uses Args as a starting point
  // but otherwise is not related to Args.
  Args
  CAS uint64
}

// So make Args3 a copy of Args but with Name and overriding the Id method...
type Args3 struct {
  Args
  Name string
}

func (this *Args3) Id() uint {
  return 666
}

// interfaces are used for polymorphism.
// so Args & Args2 are distinct types still but Arg is a subtype of T and by
// inheriting from Args, Args2 is also a subtype of T... saying subtype is wrong
// in some ways as I don't think you can really have a hierachy. Its just flat.
// So field names can't be polymorphic though so need to use getter / setters
// still.
type T interface {
  Id() uint
  Check() bool
  Who() string
}

// implement T (note this implements T for Args2 as well!)
func (this *Args) Id() uint {
  return this.id
}

func (this *Args) Check() bool {
  return this.check
}

func (this *Args) Who() string {
  return this.who
}

func (this *Args) PolyFunc() {
  fmt.Println("Args is", this.Who())
}

func main() {
  a := &Args{0, true, "Args"}
  b := &Args2{Args{1, true, "Args2"}, 12}
  // Can compose
  c := &Args2{*a, 13}
  d := &Args3{Args{2, true, "Args3"}, "Args3"}

  // DOESN'T COMPILE -- NOT SUBCLASSS
  // var d Args
  // d = *b

  // BUT ARGS2 inherits ARGS interfaces...
  fmt.Printf("a.Id() = %d\n", T.Id(a))
  fmt.Printf("b.Id() = %d\n", T.Id(b))

  // Wow -- can do selective overriding of Id for subclass.
  fmt.Printf("d.Id() = %d\n", T.Id(d))

  showArgs(a)
  // DOENS'T COMPILE
  // showArgs(b)
  // Can access anonymous struct by using its type
  // here the nesting is apparent!
  showArgs(&b.Args)
  showArgs(&c.Args)

  a.PolyFunc()
  // BUT, b has Args methods?
  b.PolyFunc()

  idT(a)
  idT(b)
  idT(c)
}

// Argument is Args, so not polymorphic sadly, Args2 won't be accepted
func showArgs(arg *Args) {
  fmt.Println("Args:", arg)
}

// Note argument is T! so polymorphic...!
func idT(t T) {
  fmt.Println("ID:", t.Id())
}

<|endoftext|>


<commit_before>package chat

import (
	"fmt"
	"strings"

	"github.com/keybase/client/go/chat/types"
	"github.com/keybase/client/go/chat/utils"
	"github.com/keybase/client/go/engine"
	"github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/protocol/chat1"
	"github.com/keybase/client/go/protocol/keybase1"
	"github.com/keybase/go-framed-msgpack-rpc/rpc"
	context "golang.org/x/net/context"
	"golang.org/x/sync/errgroup"
)

type KBFSTLFInfoSource struct {
	utils.DebugLabeler
	libkb.Contextified
}

func NewKBFSTLFInfoSource(g *libkb.GlobalContext) *KBFSTLFInfoSource {
	return &KBFSTLFInfoSource{
		DebugLabeler: utils.NewDebugLabeler(g, "KBFSTLFInfoSource", false),
		Contextified: libkb.NewContextified(g),
	}
}

func (t *KBFSTLFInfoSource) tlfKeysClient() (*keybase1.TlfKeysClient, error) {
	xp := t.G().ConnectionManager.LookupByClientType(keybase1.ClientType_KBFS)
	if xp == nil {
		return nil, fmt.Errorf("KBFS client wasn't found")
	}
	return &keybase1.TlfKeysClient{
		Cli: rpc.NewClient(
			xp, libkb.ErrorUnwrapper{}, libkb.LogTagsFromContext),
	}, nil
}

func (t *KBFSTLFInfoSource) Lookup(ctx context.Context, tlfName string,
	visibility chat1.TLFVisibility) (*types.TLFInfo, error) {
	res, err := CtxKeyFinder(ctx).Find(ctx, t, tlfName, visibility == chat1.TLFVisibility_PUBLIC)
	if err != nil {
		return nil, err
	}
	info := &types.TLFInfo{
		ID:               chat1.TLFID(res.NameIDBreaks.TlfID.ToBytes()),
		CanonicalName:    res.NameIDBreaks.CanonicalName.String(),
		IdentifyFailures: res.NameIDBreaks.Breaks.Breaks,
	}
	return info, nil
}

func (t *KBFSTLFInfoSource) CryptKeys(ctx context.Context, tlfName string) (res keybase1.GetTLFCryptKeysRes, ferr error) {
	identBehavior, breaks, ok := IdentifyMode(ctx)
	if !ok {
		return res, fmt.Errorf("invalid context with no chat metadata")
	}
	defer t.Trace(ctx, func() error { return ferr },
		fmt.Sprintf("CryptKeys(tlf=%s,mode=%v)", tlfName, identBehavior))()

	// call identifyTLF and GetTLFCryptKeys concurrently:
	group, ectx := errgroup.WithContext(BackgroundContext(ctx))

	var ib []keybase1.TLFIdentifyFailure
	group.Go(func() error {
		query := keybase1.TLFQuery{
			TlfName:          tlfName,
			IdentifyBehavior: identBehavior,
		}
		var err error
		ib, err = t.identifyTLF(ectx, query, true)
		return err
	})

	group.Go(func() error {
		tlfClient, err := t.tlfKeysClient()
		if err != nil {
			return err
		}

		// skip identify:
		query := keybase1.TLFQuery{
			TlfName:          tlfName,
			IdentifyBehavior: keybase1.TLFIdentifyBehavior_CHAT_SKIP,
		}

		res, err = tlfClient.GetTLFCryptKeys(ectx, query)
		return err
	})

	if err := group.Wait(); err != nil {
		return keybase1.GetTLFCryptKeysRes{}, err
	}

	// use id breaks calculated by identifyTLF
	res.NameIDBreaks.Breaks.Breaks = ib

	if in := CtxIdentifyNotifier(ctx); in != nil {
		in.Send(res.NameIDBreaks)
	}
	*breaks = appendBreaks(*breaks, res.NameIDBreaks.Breaks.Breaks)

	return res, nil
}

func (t *KBFSTLFInfoSource) PublicCanonicalTLFNameAndID(ctx context.Context, tlfName string) (res keybase1.CanonicalTLFNameAndIDWithBreaks, ferr error) {
	identBehavior, breaks, ok := IdentifyMode(ctx)
	if !ok {
		return res, fmt.Errorf("invalid context with no chat metadata")
	}
	defer t.Trace(ctx, func() error { return ferr },
		fmt.Sprintf("PublicCanonicalTLFNameAndID(tlf=%s,mode=%v)", tlfName, identBehavior))()

	// call identifyTLF and CanonicalTLFNameAndIDWithBreaks concurrently:
	group, ectx := errgroup.WithContext(BackgroundContext(ctx))

	var ib []keybase1.TLFIdentifyFailure
	group.Go(func() error {
		query := keybase1.TLFQuery{
			TlfName:          tlfName,
			IdentifyBehavior: identBehavior,
		}

		var err error
		ib, err = t.identifyTLF(ectx, query, false)
		return err
	})

	group.Go(func() error {
		tlfClient, err := t.tlfKeysClient()
		if err != nil {
			return err
		}

		// skip identify:
		query := keybase1.TLFQuery{
			TlfName:          tlfName,
			IdentifyBehavior: keybase1.TLFIdentifyBehavior_CHAT_SKIP,
		}

		res, err = tlfClient.GetPublicCanonicalTLFNameAndID(ectx, query)
		return err
	})

	if err := group.Wait(); err != nil {
		return keybase1.CanonicalTLFNameAndIDWithBreaks{}, err
	}

	// use id breaks calculated by identifyTLF
	res.Breaks.Breaks = ib

	if in := CtxIdentifyNotifier(ctx); in != nil {
		in.Send(res)
	}
	*breaks = appendBreaks(*breaks, res.Breaks.Breaks)

	return res, nil
}

func (t *KBFSTLFInfoSource) CompleteAndCanonicalizePrivateTlfName(ctx context.Context, tlfName string) (res keybase1.CanonicalTLFNameAndIDWithBreaks, err error) {
	username := t.G().Env.GetUsername()
	if len(username) == 0 {
		return keybase1.CanonicalTLFNameAndIDWithBreaks{}, libkb.LoginRequiredError{}
	}

	// Prepend username in case it's not present. We don't need to check if it
	// exists already since CryptKeys calls below transforms the TLF name into a
	// canonical one.
	//
	// This makes username a writer on this TLF, which might be unexpected.
	// TODO: We should think about how to handle read-only TLFs.
	tlfName = string(username) + "," + tlfName

	// TODO: do some caching so we don't end up calling this RPC
	// unnecessarily too often
	resp, err := t.CryptKeys(ctx, tlfName)
	if err != nil {
		return keybase1.CanonicalTLFNameAndIDWithBreaks{}, err
	}

	return resp.NameIDBreaks, nil
}

func (t *KBFSTLFInfoSource) identifyTLF(ctx context.Context, arg keybase1.TLFQuery, private bool) ([]keybase1.TLFIdentifyFailure, error) {
	// need new context as errgroup will cancel it.
	group, ectx := errgroup.WithContext(BackgroundContext(ctx))
	assertions := make(chan string)

	group.Go(func() error {
		defer close(assertions)
		pieces := strings.Split(strings.Fields(arg.TlfName)[0], ",")
		for _, p := range pieces {
			select {
			case assertions <- p:
			case <-ectx.Done():
				return ectx.Err()
			}
		}
		return nil
	})

	fails := make(chan keybase1.TLFIdentifyFailure)
	const numIdentifiers = 3
	for i := 0; i < numIdentifiers; i++ {
		group.Go(func() error {
			for assertion := range assertions {
				f, err := t.identifyUser(ectx, assertion, private, arg.IdentifyBehavior)
				if err != nil {
					return err
				}
				if f.Breaks == nil {
					continue
				}
				select {
				case fails <- f:
				case <-ectx.Done():
					return ectx.Err()
				}
			}
			return nil
		})
	}

	go func() {
		group.Wait()
		close(fails)
	}()

	var res []keybase1.TLFIdentifyFailure
	for f := range fails {
		res = append(res, f)
	}

	if err := group.Wait(); err != nil {
		return nil, err
	}
	return res, nil
}

func (t *KBFSTLFInfoSource) identifyUser(ctx context.Context, assertion string, private bool, idBehavior keybase1.TLFIdentifyBehavior) (keybase1.TLFIdentifyFailure, error) {
	reason := "You accessed a public conversation."
	if private {
		reason = fmt.Sprintf("You accessed a private conversation with %s.", assertion)
	}

	arg := keybase1.Identify2Arg{
		UserAssertion:    assertion,
		UseDelegateUI:    false,
		Reason:           keybase1.IdentifyReason{Reason: reason},
		CanSuppressUI:    true,
		IdentifyBehavior: idBehavior,
	}

	ectx := engine.Context{
		IdentifyUI: chatNullIdentifyUI{},
		NetContext: ctx,
	}

	eng := engine.NewResolveThenIdentify2(t.G(), &arg)
	err := engine.RunEngine(eng, &ectx)
	if err != nil {
		return keybase1.TLFIdentifyFailure{}, err
	}
	resp := eng.Result()

	var frep keybase1.TLFIdentifyFailure
	if resp != nil && resp.TrackBreaks != nil {
		frep.User = keybase1.User{
			Uid:      resp.Upk.Uid,
			Username: resp.Upk.Username,
		}
		frep.Breaks = resp.TrackBreaks
	}

	return frep, nil
}

func appendBreaks(l []keybase1.TLFIdentifyFailure, r []keybase1.TLFIdentifyFailure) []keybase1.TLFIdentifyFailure {
	m := make(map[string]bool)
	var res []keybase1.TLFIdentifyFailure
	for _, f := range l {
		m[f.User.Username] = true
		res = append(res, f)
	}
	for _, f := range r {
		if !m[f.User.Username] {
			res = append(res, f)
		}
	}
	return res
}
<commit_msg>Ignore libkb.ResolutionError<commit_after>package chat

import (
	"fmt"
	"strings"

	"github.com/keybase/client/go/chat/types"
	"github.com/keybase/client/go/chat/utils"
	"github.com/keybase/client/go/engine"
	"github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/protocol/chat1"
	"github.com/keybase/client/go/protocol/keybase1"
	"github.com/keybase/go-framed-msgpack-rpc/rpc"
	context "golang.org/x/net/context"
	"golang.org/x/sync/errgroup"
)

type KBFSTLFInfoSource struct {
	utils.DebugLabeler
	libkb.Contextified
}

func NewKBFSTLFInfoSource(g *libkb.GlobalContext) *KBFSTLFInfoSource {
	return &KBFSTLFInfoSource{
		DebugLabeler: utils.NewDebugLabeler(g, "KBFSTLFInfoSource", false),
		Contextified: libkb.NewContextified(g),
	}
}

func (t *KBFSTLFInfoSource) tlfKeysClient() (*keybase1.TlfKeysClient, error) {
	xp := t.G().ConnectionManager.LookupByClientType(keybase1.ClientType_KBFS)
	if xp == nil {
		return nil, fmt.Errorf("KBFS client wasn't found")
	}
	return &keybase1.TlfKeysClient{
		Cli: rpc.NewClient(
			xp, libkb.ErrorUnwrapper{}, libkb.LogTagsFromContext),
	}, nil
}

func (t *KBFSTLFInfoSource) Lookup(ctx context.Context, tlfName string,
	visibility chat1.TLFVisibility) (*types.TLFInfo, error) {
	res, err := CtxKeyFinder(ctx).Find(ctx, t, tlfName, visibility == chat1.TLFVisibility_PUBLIC)
	if err != nil {
		return nil, err
	}
	info := &types.TLFInfo{
		ID:               chat1.TLFID(res.NameIDBreaks.TlfID.ToBytes()),
		CanonicalName:    res.NameIDBreaks.CanonicalName.String(),
		IdentifyFailures: res.NameIDBreaks.Breaks.Breaks,
	}
	return info, nil
}

func (t *KBFSTLFInfoSource) CryptKeys(ctx context.Context, tlfName string) (res keybase1.GetTLFCryptKeysRes, ferr error) {
	identBehavior, breaks, ok := IdentifyMode(ctx)
	if !ok {
		return res, fmt.Errorf("invalid context with no chat metadata")
	}
	defer t.Trace(ctx, func() error { return ferr },
		fmt.Sprintf("CryptKeys(tlf=%s,mode=%v)", tlfName, identBehavior))()

	// call identifyTLF and GetTLFCryptKeys concurrently:
	group, ectx := errgroup.WithContext(BackgroundContext(ctx))

	var ib []keybase1.TLFIdentifyFailure
	group.Go(func() error {
		query := keybase1.TLFQuery{
			TlfName:          tlfName,
			IdentifyBehavior: identBehavior,
		}
		var err error
		ib, err = t.identifyTLF(ectx, query, true)
		return err
	})

	group.Go(func() error {
		tlfClient, err := t.tlfKeysClient()
		if err != nil {
			return err
		}

		// skip identify:
		query := keybase1.TLFQuery{
			TlfName:          tlfName,
			IdentifyBehavior: keybase1.TLFIdentifyBehavior_CHAT_SKIP,
		}

		res, err = tlfClient.GetTLFCryptKeys(ectx, query)
		return err
	})

	if err := group.Wait(); err != nil {
		return keybase1.GetTLFCryptKeysRes{}, err
	}

	// use id breaks calculated by identifyTLF
	res.NameIDBreaks.Breaks.Breaks = ib

	if in := CtxIdentifyNotifier(ctx); in != nil {
		in.Send(res.NameIDBreaks)
	}
	*breaks = appendBreaks(*breaks, res.NameIDBreaks.Breaks.Breaks)

	return res, nil
}

func (t *KBFSTLFInfoSource) PublicCanonicalTLFNameAndID(ctx context.Context, tlfName string) (res keybase1.CanonicalTLFNameAndIDWithBreaks, ferr error) {
	identBehavior, breaks, ok := IdentifyMode(ctx)
	if !ok {
		return res, fmt.Errorf("invalid context with no chat metadata")
	}
	defer t.Trace(ctx, func() error { return ferr },
		fmt.Sprintf("PublicCanonicalTLFNameAndID(tlf=%s,mode=%v)", tlfName, identBehavior))()

	// call identifyTLF and CanonicalTLFNameAndIDWithBreaks concurrently:
	group, ectx := errgroup.WithContext(BackgroundContext(ctx))

	var ib []keybase1.TLFIdentifyFailure
	group.Go(func() error {
		query := keybase1.TLFQuery{
			TlfName:          tlfName,
			IdentifyBehavior: identBehavior,
		}

		var err error
		ib, err = t.identifyTLF(ectx, query, false)
		return err
	})

	group.Go(func() error {
		tlfClient, err := t.tlfKeysClient()
		if err != nil {
			return err
		}

		// skip identify:
		query := keybase1.TLFQuery{
			TlfName:          tlfName,
			IdentifyBehavior: keybase1.TLFIdentifyBehavior_CHAT_SKIP,
		}

		res, err = tlfClient.GetPublicCanonicalTLFNameAndID(ectx, query)
		return err
	})

	if err := group.Wait(); err != nil {
		return keybase1.CanonicalTLFNameAndIDWithBreaks{}, err
	}

	// use id breaks calculated by identifyTLF
	res.Breaks.Breaks = ib

	if in := CtxIdentifyNotifier(ctx); in != nil {
		in.Send(res)
	}
	*breaks = appendBreaks(*breaks, res.Breaks.Breaks)

	return res, nil
}

func (t *KBFSTLFInfoSource) CompleteAndCanonicalizePrivateTlfName(ctx context.Context, tlfName string) (res keybase1.CanonicalTLFNameAndIDWithBreaks, err error) {
	username := t.G().Env.GetUsername()
	if len(username) == 0 {
		return keybase1.CanonicalTLFNameAndIDWithBreaks{}, libkb.LoginRequiredError{}
	}

	// Prepend username in case it's not present. We don't need to check if it
	// exists already since CryptKeys calls below transforms the TLF name into a
	// canonical one.
	//
	// This makes username a writer on this TLF, which might be unexpected.
	// TODO: We should think about how to handle read-only TLFs.
	tlfName = string(username) + "," + tlfName

	// TODO: do some caching so we don't end up calling this RPC
	// unnecessarily too often
	resp, err := t.CryptKeys(ctx, tlfName)
	if err != nil {
		return keybase1.CanonicalTLFNameAndIDWithBreaks{}, err
	}

	return resp.NameIDBreaks, nil
}

func (t *KBFSTLFInfoSource) identifyTLF(ctx context.Context, arg keybase1.TLFQuery, private bool) ([]keybase1.TLFIdentifyFailure, error) {
	// need new context as errgroup will cancel it.
	group, ectx := errgroup.WithContext(BackgroundContext(ctx))
	assertions := make(chan string)

	group.Go(func() error {
		defer close(assertions)
		pieces := strings.Split(strings.Fields(arg.TlfName)[0], ",")
		for _, p := range pieces {
			select {
			case assertions <- p:
			case <-ectx.Done():
				return ectx.Err()
			}
		}
		return nil
	})

	fails := make(chan keybase1.TLFIdentifyFailure)
	const numIdentifiers = 3
	for i := 0; i < numIdentifiers; i++ {
		group.Go(func() error {
			for assertion := range assertions {
				f, err := t.identifyUser(ectx, assertion, private, arg.IdentifyBehavior)
				if err != nil {
					return err
				}
				if f.Breaks == nil {
					continue
				}
				select {
				case fails <- f:
				case <-ectx.Done():
					return ectx.Err()
				}
			}
			return nil
		})
	}

	go func() {
		group.Wait()
		close(fails)
	}()

	var res []keybase1.TLFIdentifyFailure
	for f := range fails {
		res = append(res, f)
	}

	if err := group.Wait(); err != nil {
		return nil, err
	}
	return res, nil
}

func (t *KBFSTLFInfoSource) identifyUser(ctx context.Context, assertion string, private bool, idBehavior keybase1.TLFIdentifyBehavior) (keybase1.TLFIdentifyFailure, error) {
	reason := "You accessed a public conversation."
	if private {
		reason = fmt.Sprintf("You accessed a private conversation with %s.", assertion)
	}

	arg := keybase1.Identify2Arg{
		UserAssertion:    assertion,
		UseDelegateUI:    false,
		Reason:           keybase1.IdentifyReason{Reason: reason},
		CanSuppressUI:    true,
		IdentifyBehavior: idBehavior,
	}

	ectx := engine.Context{
		IdentifyUI: chatNullIdentifyUI{},
		NetContext: ctx,
	}

	eng := engine.NewResolveThenIdentify2(t.G(), &arg)
	err := engine.RunEngine(eng, &ectx)
	if err != nil {
		if _, ok := err.(libkb.NotFoundError); ok {
			err = nil
		}
		if _, ok := err.(libkb.ResolutionError); ok {
			err = nil
		}
		return keybase1.TLFIdentifyFailure{}, err
	}
	resp := eng.Result()

	var frep keybase1.TLFIdentifyFailure
	if resp != nil && resp.TrackBreaks != nil {
		frep.User = keybase1.User{
			Uid:      resp.Upk.Uid,
			Username: resp.Upk.Username,
		}
		frep.Breaks = resp.TrackBreaks
	}

	return frep, nil
}

func appendBreaks(l []keybase1.TLFIdentifyFailure, r []keybase1.TLFIdentifyFailure) []keybase1.TLFIdentifyFailure {
	m := make(map[string]bool)
	var res []keybase1.TLFIdentifyFailure
	for _, f := range l {
		m[f.User.Username] = true
		res = append(res, f)
	}
	for _, f := range r {
		if !m[f.User.Username] {
			res = append(res, f)
		}
	}
	return res
}
<|endoftext|>


<commit_before>package mpwindowsprocessstats

import (
	"flag"
	"fmt"
	"os"
	"regexp"
	"sort"
	"strconv"

	"github.com/StackExchange/wmi"
	mp "github.com/mackerelio/go-mackerel-plugin-helper"
	"github.com/mackerelio/mackerel-agent/logging"
)

var logger = logging.GetLogger("metrics.plugin.windows-process-stats")

type Win32_PerfFormattedData_PerfProc_Process struct {
	ElapsedTime          uint64
	Name                 string
	IDProcess            uint32
	PercentProcessorTime uint64
	WorkingSet           uint64
}

type WindowsProcessStatsPlugin struct {
	Process     string
	MetricLabel string
}

func getProcesses(processName string) ([]Win32_PerfFormattedData_PerfProc_Process, error) {
	var procs []Win32_PerfFormattedData_PerfProc_Process

	q := wmi.CreateQuery(&procs, "WHERE Name like '"+processName+"%'")
	if err := wmi.Query(q, &procs); err != nil {
		return procs, err
	}

	sort.Slice(procs, func(i, j int) bool {
		return procs[i].IDProcess < procs[j].IDProcess
	})
	return procs, nil
}

// FetchMetrics interface for mackerelplugin
func (m WindowsProcessStatsPlugin) FetchMetrics() (map[string]interface{}, error) {
	procs, err := getProcesses(m.Process)
	if err != nil {
		return nil, err
	}
	stat := make(map[string]interface{})
	prefix := m.MetricLabel
	var re = regexp.MustCompile(`#[0-9]+$`)
	for k, v := range procs {
		name := re.ReplaceAllString(v.Name, "")
		processName := name + "_" + strconv.Itoa(k)
		metricNameCPU := prefix + "-windows-process-stats.cpu." + processName + ".cpu"
		metricNameMemory := prefix + "-windows-process-stats.memory." + processName + ".working_set"
		stat[metricNameCPU] = v.PercentProcessorTime //uint64(int(v.PercentProcessorTime) / int(runtime.NumCPU()))
		stat[metricNameMemory] = uint64(v.WorkingSet)
	}

	return stat, nil
}

// GraphDefinition interface for mackerelplugin
func (m WindowsProcessStatsPlugin) GraphDefinition() map[string](mp.Graphs) {
	prefix := m.MetricLabel
	return map[string](mp.Graphs){
		fmt.Sprintf("%s-windows-process-stats.cpu.#", prefix): mp.Graphs{
			Label: fmt.Sprintf("%s Windows Process Stats CPU", prefix),
			Unit:  "percentage",
			Metrics: []mp.Metrics{
				{Name: "cpu", Label: "cpu", Diff: false, Stacked: false},
			},
		},
		fmt.Sprintf("%s-windows-process-stats.memory.#", prefix): mp.Graphs{
			Label: fmt.Sprintf("%s Windows Process Stats Memory", prefix),
			Unit:  "bytes",
			Metrics: []mp.Metrics{
				{Name: "working_set", Label: "memory", Diff: false, Stacked: false},
			},
		},
	}
}

// Do the plugin
func Do() {
	optProcess := flag.String("process", "", "Process name")
	optMetricLabel := flag.String("label", "", "Metric Label Prefix")
	optTempfile := flag.String("tempfile", "", "Temp file name")
	flag.Parse()

	if *optProcess == "" {
		logger.Warningf("Process name is required")
		flag.PrintDefaults()
		os.Exit(1)
	}

	var plugin WindowsProcessStatsPlugin
	plugin.Process = *optProcess
	metricLabel := *optMetricLabel
	if metricLabel == "" {
		metricLabel = plugin.Process
	}
	plugin.MetricLabel = metricLabel

	helper := mp.NewMackerelPlugin(plugin)
	helper.Tempfile = *optTempfile
	helper.Run()
}
<commit_msg>remove unnecessary comments and type conversion<commit_after>package mpwindowsprocessstats

import (
	"flag"
	"fmt"
	"os"
	"regexp"
	"sort"
	"strconv"

	"github.com/StackExchange/wmi"
	mp "github.com/mackerelio/go-mackerel-plugin-helper"
	"github.com/mackerelio/mackerel-agent/logging"
)

var logger = logging.GetLogger("metrics.plugin.windows-process-stats")

type Win32_PerfFormattedData_PerfProc_Process struct {
	ElapsedTime          uint64
	Name                 string
	IDProcess            uint32
	PercentProcessorTime uint64
	WorkingSet           uint64
}

type WindowsProcessStatsPlugin struct {
	Process     string
	MetricLabel string
}

func getProcesses(processName string) ([]Win32_PerfFormattedData_PerfProc_Process, error) {
	var procs []Win32_PerfFormattedData_PerfProc_Process

	q := wmi.CreateQuery(&procs, "WHERE Name like '"+processName+"%'")
	if err := wmi.Query(q, &procs); err != nil {
		return procs, err
	}

	sort.Slice(procs, func(i, j int) bool {
		return procs[i].IDProcess < procs[j].IDProcess
	})
	return procs, nil
}

// FetchMetrics interface for mackerelplugin
func (m WindowsProcessStatsPlugin) FetchMetrics() (map[string]interface{}, error) {
	procs, err := getProcesses(m.Process)
	if err != nil {
		return nil, err
	}
	stat := make(map[string]interface{})
	prefix := m.MetricLabel
	var re = regexp.MustCompile(`#[0-9]+$`)
	for k, v := range procs {
		name := re.ReplaceAllString(v.Name, "")
		processName := name + "_" + strconv.Itoa(k)
		metricNameCPU := prefix + "-windows-process-stats.cpu." + processName + ".cpu"
		metricNameMemory := prefix + "-windows-process-stats.memory." + processName + ".working_set"
		stat[metricNameCPU] = v.PercentProcessorTime
		stat[metricNameMemory] = v.WorkingSet
	}

	return stat, nil
}

// GraphDefinition interface for mackerelplugin
func (m WindowsProcessStatsPlugin) GraphDefinition() map[string](mp.Graphs) {
	prefix := m.MetricLabel
	return map[string](mp.Graphs){
		fmt.Sprintf("%s-windows-process-stats.cpu.#", prefix): mp.Graphs{
			Label: fmt.Sprintf("%s Windows Process Stats CPU", prefix),
			Unit:  "percentage",
			Metrics: []mp.Metrics{
				{Name: "cpu", Label: "cpu", Diff: false, Stacked: false},
			},
		},
		fmt.Sprintf("%s-windows-process-stats.memory.#", prefix): mp.Graphs{
			Label: fmt.Sprintf("%s Windows Process Stats Memory", prefix),
			Unit:  "bytes",
			Metrics: []mp.Metrics{
				{Name: "working_set", Label: "memory", Diff: false, Stacked: false},
			},
		},
	}
}

// Do the plugin
func Do() {
	optProcess := flag.String("process", "", "Process name")
	optMetricLabel := flag.String("label", "", "Metric Label Prefix")
	optTempfile := flag.String("tempfile", "", "Temp file name")
	flag.Parse()

	if *optProcess == "" {
		logger.Warningf("Process name is required")
		flag.PrintDefaults()
		os.Exit(1)
	}

	var plugin WindowsProcessStatsPlugin
	plugin.Process = *optProcess
	metricLabel := *optMetricLabel
	if metricLabel == "" {
		metricLabel = plugin.Process
	}
	plugin.MetricLabel = metricLabel

	helper := mp.NewMackerelPlugin(plugin)
	helper.Tempfile = *optTempfile
	helper.Run()
}
<|endoftext|>


<commit_before>// +build windows
// Copyright 2013, Örjan Persson. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package logging

import (
	"bytes"
	"io"
	"log"
	"os"
	"syscall"
)

var (
	kernel32DLL                 = syscall.NewLazyDLL("kernel32.dll")
	setConsoleTextAttributeProc = kernel32DLL.NewProc("SetConsoleTextAttribute")
)

// TODO initialize here
var colors []WORD
var boldcolors []WORD

type color int
type WORD uint16

const (
	// Character attributes
	// Note:
	// -- The attributes are combined to produce various colors (e.g., Blue + Green will create Cyan).
	//    Clearing all foreground or background colors results in black; setting all creates white.
	// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms682088(v=vs.85).aspx#_win32_character_attributes.
	FOREGROUND_BLACK     WORD = 0x0000
	FOREGROUND_BLUE      WORD = 0x0001
	FOREGROUND_GREEN     WORD = 0x0002
	FOREGROUND_CYAN      WORD = 0x0003
	FOREGROUND_RED       WORD = 0x0004
	FOREGROUND_MAGENTA   WORD = 0x0005
	FOREGROUND_YELLOW    WORD = 0x0006
	FOREGROUND_WHITE     WORD = 0x0007
	FOREGROUND_INTENSITY WORD = 0x0008
	FOREGROUND_MASK      WORD = 0x000F
)

// LogBackend utilizes the standard log module.
type LogBackend struct {
	Logger *log.Logger
	Color  bool
	Handle uintptr
}

// NewLogBackend creates a new LogBackend.
func NewLogBackend(out *os.File, prefix string, flag int) *LogBackend {
	return &LogBackend{Logger: log.New(out, prefix, flag), Handle: out.Fd()}
}

func (b *LogBackend) Log(level Level, calldepth int, rec *Record) error {
	if b.Color {
		buf := &bytes.Buffer{}
		setConsoleTextAttribute(b.Handle, colors[level])
		buf.Write([]byte(rec.Formatted(calldepth + 1)))
		// For some reason, the Go logger arbitrarily decided "2" was the correct
		// call depth...
		err := b.Logger.Output(calldepth+2, buf.String())
		setConsoleTextAttribute(b.Handle, FOREGROUND_WHITE)
		return err
	} else {
		return b.Logger.Output(calldepth+2, rec.Formatted(calldepth+1))
	}
}

func init() {
	colors = []WORD{
		INFO:     FOREGROUND_WHITE,
		CRITICAL: FOREGROUND_MAGENTA,
		ERROR:    FOREGROUND_RED,
		WARNING:  FOREGROUND_YELLOW,
		NOTICE:   FOREGROUND_GREEN,
		DEBUG:    FOREGROUND_CYAN,
	}
	boldcolors = []WORD{
		INFO:     FOREGROUND_WHITE | FOREGROUND_INTENSITY,
		CRITICAL: FOREGROUND_MAGENTA | FOREGROUND_INTENSITY,
		ERROR:    FOREGROUND_RED | FOREGROUND_INTENSITY,
		WARNING:  FOREGROUND_YELLOW | FOREGROUND_INTENSITY,
		NOTICE:   FOREGROUND_GREEN | FOREGROUND_INTENSITY,
		DEBUG:    FOREGROUND_CYAN | FOREGROUND_INTENSITY,
	}
}

// setConsoleTextAttribute sets the attributes of characters written to the
// console screen buffer by the WriteFile or WriteConsole function.
// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms686047(v=vs.85).aspx.
func setConsoleTextAttribute(handle uintptr, attribute WORD) error {
	r1, r2, err := setConsoleTextAttributeProc.Call(handle, uintptr(attribute), 0)
	use(attribute)
	return checkError(r1, r2, err)
}

// checkError evaluates the results of a Windows API call and returns the error if it failed.
func checkError(r1, r2 uintptr, err error) error {
	// Windows APIs return non-zero to indicate success
	if r1 != 0 {
		return nil
	}

	// Return the error if provided, otherwise default to EINVAL
	if err != nil {
		return err
	}
	return syscall.EINVAL
}

// use is a no-op, but the compiler cannot see that it is.
// Calling use(p) ensures that p is kept live until that point.
func use(p interface{}) {}

func doFmtVerbLevelColor(layout string, level Level, output io.Writer) {
	// no-op for now. We need the file descriptor to do colors.
}
<commit_msg>Do not expose windows colors<commit_after>// +build windows
// Copyright 2013, Örjan Persson. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package logging

import (
	"bytes"
	"io"
	"log"
	"os"
	"syscall"
)

var (
	kernel32DLL                 = syscall.NewLazyDLL("kernel32.dll")
	setConsoleTextAttributeProc = kernel32DLL.NewProc("SetConsoleTextAttribute")
)

// TODO initialize here
var colors []WORD
var boldcolors []WORD

type color int
type WORD uint16

const (
	// Character attributes
	// Note:
	// -- The attributes are combined to produce various colors (e.g., Blue + Green will create Cyan).
	//    Clearing all foreground or background colors results in black; setting all creates white.
	// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms682088(v=vs.85).aspx#_win32_character_attributes.
	fgBlack     WORD = 0x0000
	fgBlue      WORD = 0x0001
	fgGreen     WORD = 0x0002
	fgCyan      WORD = 0x0003
	fgRed       WORD = 0x0004
	fgMagenta   WORD = 0x0005
	fgYellow    WORD = 0x0006
	fgWhite     WORD = 0x0007
	fgIntensity WORD = 0x0008
	fgMask      WORD = 0x000F
)

// LogBackend utilizes the standard log module.
type LogBackend struct {
	Logger *log.Logger
	Color  bool
	Handle uintptr
}

// NewLogBackend creates a new LogBackend.
func NewLogBackend(out *os.File, prefix string, flag int) *LogBackend {
	return &LogBackend{Logger: log.New(out, prefix, flag), Handle: out.Fd()}
}

func (b *LogBackend) Log(level Level, calldepth int, rec *Record) error {
	if b.Color {
		buf := &bytes.Buffer{}
		setConsoleTextAttribute(b.Handle, colors[level])
		buf.Write([]byte(rec.Formatted(calldepth + 1)))
		// For some reason, the Go logger arbitrarily decided "2" was the correct
		// call depth...
		err := b.Logger.Output(calldepth+2, buf.String())
		setConsoleTextAttribute(b.Handle, fgWhite)
		return err
	}
	return b.Logger.Output(calldepth+2, rec.Formatted(calldepth+1))
}

func init() {
	colors = []WORD{
		INFO:     fgWhite,
		CRITICAL: fgMagenta,
		ERROR:    fgRed,
		WARNING:  fgYellow,
		NOTICE:   fgGreen,
		DEBUG:    fgCyan,
	}
	boldcolors = []WORD{
		INFO:     fgWhite | fgIntensity,
		CRITICAL: fgMagenta | fgIntensity,
		ERROR:    fgRed | fgIntensity,
		WARNING:  fgYellow | fgIntensity,
		NOTICE:   fgGreen | fgIntensity,
		DEBUG:    fgCyan | fgIntensity,
	}
}

// setConsoleTextAttribute sets the attributes of characters written to the
// console screen buffer by the WriteFile or WriteConsole function.
// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms686047(v=vs.85).aspx.
func setConsoleTextAttribute(handle uintptr, attribute WORD) error {
	r1, r2, err := setConsoleTextAttributeProc.Call(handle, uintptr(attribute), 0)
	use(attribute)
	return checkError(r1, r2, err)
}

// checkError evaluates the results of a Windows API call and returns the error if it failed.
func checkError(r1, r2 uintptr, err error) error {
	// Windows APIs return non-zero to indicate success
	if r1 != 0 {
		return nil
	}

	// Return the error if provided, otherwise default to EINVAL
	if err != nil {
		return err
	}
	return syscall.EINVAL
}

// use is a no-op, but the compiler cannot see that it is.
// Calling use(p) ensures that p is kept live until that point.
func use(p interface{}) {}

func doFmtVerbLevelColor(layout string, level Level, output io.Writer) {
	// no-op for now. We need the file descriptor to do colors.
}
<|endoftext|>


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

package gomock

import (
	"fmt"
	"reflect"
	"strconv"
	"strings"
)

// Call represents an expected call to a mock.
type Call struct {
	t TestReporter // for triggering test failures on invalid call setup

	receiver   interface{}   // the receiver of the method call
	method     string        // the name of the method
	methodType reflect.Type  // the type of the method
	args       []Matcher     // the args
	rets       []interface{} // the return values (if any)
	origin     string        // file and line number of call setup

	preReqs []*Call // prerequisite calls

	// Expectations
	minCalls, maxCalls int

	numCalls int // actual number made

	// Actions
	doFunc  reflect.Value
	setArgs map[int]reflect.Value
}

// AnyTimes allows the expectation to be called 0 or more times
func (c *Call) AnyTimes() *Call {
	c.minCalls, c.maxCalls = 0, 1e8 // close enough to infinity
	return c
}

// MinTimes requires the call to occur at least n times. If AnyTimes or MaxTimes have not been called, MinTimes also
// sets the maximum number of calls to infinity.
func (c *Call) MinTimes(n int) *Call {
	c.minCalls = n
	if c.maxCalls == 1 {
		c.maxCalls = 1e8
	}
	return c
}

// MaxTimes limits the number of calls to n times. If AnyTimes or MinTimes have not been called, MaxTimes also
// sets the minimum number of calls to 0.
func (c *Call) MaxTimes(n int) *Call {
	c.maxCalls = n
	if c.minCalls == 1 {
		c.minCalls = 0
	}
	return c
}

// Do declares the action to run when the call is matched.
// It takes an interface{} argument to support n-arity functions.
func (c *Call) Do(f interface{}) *Call {
	// TODO: Check arity and types here, rather than dying badly elsewhere.
	c.doFunc = reflect.ValueOf(f)
	return c
}

func (c *Call) Return(rets ...interface{}) *Call {
	mt := c.methodType
	if len(rets) != mt.NumOut() {
		c.t.Fatalf("wrong number of arguments to Return for %T.%v: got %d, want %d [%s]",
			c.receiver, c.method, len(rets), mt.NumOut(), c.origin)
	}
	for i, ret := range rets {
		if got, want := reflect.TypeOf(ret), mt.Out(i); got == want {
			// Identical types; nothing to do.
		} else if got == nil {
			// Nil needs special handling.
			switch want.Kind() {
			case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
				// ok
			default:
				c.t.Fatalf("argument %d to Return for %T.%v is nil, but %v is not nillable [%s]",
					i, c.receiver, c.method, want, c.origin)
			}
		} else if got.AssignableTo(want) {
			// Assignable type relation. Make the assignment now so that the generated code
			// can return the values with a type assertion.
			v := reflect.New(want).Elem()
			v.Set(reflect.ValueOf(ret))
			rets[i] = v.Interface()
		} else {
			c.t.Fatalf("wrong type of argument %d to Return for %T.%v: %v is not assignable to %v [%s]",
				i, c.receiver, c.method, got, want, c.origin)
		}
	}

	c.rets = rets
	return c
}

func (c *Call) Times(n int) *Call {
	c.minCalls, c.maxCalls = n, n
	return c
}

// SetArg declares an action that will set the nth argument's value,
// indirected through a pointer. Or, in the case of a slice, SetArg
// will copy value's elements into the nth argument.
func (c *Call) SetArg(n int, value interface{}) *Call {
	if c.setArgs == nil {
		c.setArgs = make(map[int]reflect.Value)
	}
	mt := c.methodType
	// TODO: This will break on variadic methods.
	// We will need to check those at invocation time.
	if n < 0 || n >= mt.NumIn() {
		c.t.Fatalf("SetArg(%d, ...) called for a method with %d args [%s]",
			n, mt.NumIn(), c.origin)
	}
	// Permit setting argument through an interface.
	// In the interface case, we don't (nay, can't) check the type here.
	at := mt.In(n)
	switch at.Kind() {
	case reflect.Ptr:
		dt := at.Elem()
		if vt := reflect.TypeOf(value); !vt.AssignableTo(dt) {
			c.t.Fatalf("SetArg(%d, ...) argument is a %v, not assignable to %v [%s]",
				n, vt, dt, c.origin)
		}
	case reflect.Interface:
		// nothing to do
	case reflect.Slice:
		// nothing to do
	default:
		c.t.Fatalf("SetArg(%d, ...) referring to argument of non-pointer non-interface non-slice type %v",
			n, at, c.origin)
	}
	c.setArgs[n] = reflect.ValueOf(value)
	return c
}

// isPreReq returns true if other is a direct or indirect prerequisite to c.
func (c *Call) isPreReq(other *Call) bool {
	for _, preReq := range c.preReqs {
		if other == preReq || preReq.isPreReq(other) {
			return true
		}
	}
	return false
}

// After declares that the call may only match after preReq has been exhausted.
func (c *Call) After(preReq *Call) *Call {
	if c == preReq {
		c.t.Fatalf("A call isn't allowed to be its own prerequisite")
	}
	if preReq.isPreReq(c) {
		c.t.Fatalf("Loop in call order: %v is a prerequisite to %v (possibly indirectly).", c, preReq)
	}

	c.preReqs = append(c.preReqs, preReq)
	return c
}

// Returns true if the minimum number of calls have been made.
func (c *Call) satisfied() bool {
	return c.numCalls >= c.minCalls
}

// Returns true iff the maximum number of calls have been made.
func (c *Call) exhausted() bool {
	return c.numCalls >= c.maxCalls
}

func (c *Call) String() string {
	args := make([]string, len(c.args))
	for i, arg := range c.args {
		args[i] = arg.String()
	}
	arguments := strings.Join(args, ", ")
	return fmt.Sprintf("%T.%v(%s) %s", c.receiver, c.method, arguments, c.origin)
}

// Tests if the given call matches the expected call.
// If yes, returns nil. If no, returns error with message explaining why it does not match.
func (c *Call) matches(args []interface{}) error {
	if c.methodType.IsVariadic() {
		if len(c.args) < c.methodType.NumIn()-1 {
			return fmt.Errorf("matcher count is not enough at %s. Got: %d, want: greater than or equal to %d",
				c.origin, len(c.args), c.methodType.NumIn()-1)
		}
		if len(c.args) != c.methodType.NumIn() && len(args) != len(c.args) {
			return fmt.Errorf("Expected call at %s has the wrong number of arguments. Got: %d, want: %d",
				c.origin, len(args), len(c.args))
		}
		if len(args) < len(c.args)-1 {
			return fmt.Errorf("Expected call at %s has the wrong number of arguments. Got: %d, want: greater than or equal to %d",
				c.origin, len(args), len(c.args)-1)
		}
	} else {
		if len(args) != len(c.args) {
			return fmt.Errorf("Expected call at %s has the wrong number of arguments. Got: %d, want: %d",
				c.origin, len(args), len(c.args))
		}
	}

	for i, m := range c.args {
		if i == len(c.args)-1 && c.methodType.IsVariadic() {
			if !c.args[i].Matches(args[i:]) && !(len(c.args) == len(args) && c.args[i].Matches(args[i])) {
				return fmt.Errorf("Expected call at %s doesn't match the argument at index %s.\nGot: %v\nWant: %v\n",
					c.origin, strconv.Itoa(i), args[i:], c.args[i])
			}
			break
		}
		if !m.Matches(args[i]) {
			return fmt.Errorf("Expected call at %s doesn't match the argument at index %s.\nGot: %v\nWant: %v\n",
				c.origin, strconv.Itoa(i), args[i], m)
		}
	}

	// Check that all prerequisite calls have been satisfied.
	for _, preReqCall := range c.preReqs {
		if !preReqCall.satisfied() {
			return fmt.Errorf("Expected call at %s doesn't have a prerequisite call satisfied:\n%v\nshould be called before:\n%v",
				c.origin, preReqCall, c)
		}
	}

	return nil
}

// dropPrereqs tells the expected Call to not re-check prerequisite calls any
// longer, and to return its current set.
func (c *Call) dropPrereqs() (preReqs []*Call) {
	preReqs = c.preReqs
	c.preReqs = nil
	return
}

func (c *Call) call(args []interface{}) (rets []interface{}, action func()) {
	c.numCalls++

	// Actions
	if c.doFunc.IsValid() {
		doArgs := make([]reflect.Value, len(args))
		ft := c.doFunc.Type()
		for i := 0; i < len(args); i++ {
			if args[i] != nil {
				doArgs[i] = reflect.ValueOf(args[i])
			} else {
				// Use the zero value for the arg.
				doArgs[i] = reflect.Zero(ft.In(i))
			}
		}
		action = func() { c.doFunc.Call(doArgs) }
	}
	for n, v := range c.setArgs {
		switch reflect.TypeOf(args[n]).Kind() {
		case reflect.Slice:
			setSlice(args[n], v)
		default:
			reflect.ValueOf(args[n]).Elem().Set(v)
		}
	}

	rets = c.rets
	if rets == nil {
		// Synthesize the zero value for each of the return args' types.
		mt := c.methodType
		rets = make([]interface{}, mt.NumOut())
		for i := 0; i < mt.NumOut(); i++ {
			rets[i] = reflect.Zero(mt.Out(i)).Interface()
		}
	}

	return
}

// InOrder declares that the given calls should occur in order.
func InOrder(calls ...*Call) {
	for i := 1; i < len(calls); i++ {
		calls[i].After(calls[i-1])
	}
}

func setSlice(arg interface{}, v reflect.Value) {
	va := reflect.ValueOf(arg)
	for i := 0; i < v.Len(); i++ {
		va.Index(i).Set(v.Index(i))
	}
}
<commit_msg>refactor messages<commit_after>// Copyright 2010 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package gomock

import (
	"fmt"
	"reflect"
	"strconv"
	"strings"
)

// Call represents an expected call to a mock.
type Call struct {
	t TestReporter // for triggering test failures on invalid call setup

	receiver   interface{}   // the receiver of the method call
	method     string        // the name of the method
	methodType reflect.Type  // the type of the method
	args       []Matcher     // the args
	rets       []interface{} // the return values (if any)
	origin     string        // file and line number of call setup

	preReqs []*Call // prerequisite calls

	// Expectations
	minCalls, maxCalls int

	numCalls int // actual number made

	// Actions
	doFunc  reflect.Value
	setArgs map[int]reflect.Value
}

// AnyTimes allows the expectation to be called 0 or more times
func (c *Call) AnyTimes() *Call {
	c.minCalls, c.maxCalls = 0, 1e8 // close enough to infinity
	return c
}

// MinTimes requires the call to occur at least n times. If AnyTimes or MaxTimes have not been called, MinTimes also
// sets the maximum number of calls to infinity.
func (c *Call) MinTimes(n int) *Call {
	c.minCalls = n
	if c.maxCalls == 1 {
		c.maxCalls = 1e8
	}
	return c
}

// MaxTimes limits the number of calls to n times. If AnyTimes or MinTimes have not been called, MaxTimes also
// sets the minimum number of calls to 0.
func (c *Call) MaxTimes(n int) *Call {
	c.maxCalls = n
	if c.minCalls == 1 {
		c.minCalls = 0
	}
	return c
}

// Do declares the action to run when the call is matched.
// It takes an interface{} argument to support n-arity functions.
func (c *Call) Do(f interface{}) *Call {
	// TODO: Check arity and types here, rather than dying badly elsewhere.
	c.doFunc = reflect.ValueOf(f)
	return c
}

func (c *Call) Return(rets ...interface{}) *Call {
	mt := c.methodType
	if len(rets) != mt.NumOut() {
		c.t.Fatalf("wrong number of arguments to Return for %T.%v: got %d, want %d [%s]",
			c.receiver, c.method, len(rets), mt.NumOut(), c.origin)
	}
	for i, ret := range rets {
		if got, want := reflect.TypeOf(ret), mt.Out(i); got == want {
			// Identical types; nothing to do.
		} else if got == nil {
			// Nil needs special handling.
			switch want.Kind() {
			case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
				// ok
			default:
				c.t.Fatalf("argument %d to Return for %T.%v is nil, but %v is not nillable [%s]",
					i, c.receiver, c.method, want, c.origin)
			}
		} else if got.AssignableTo(want) {
			// Assignable type relation. Make the assignment now so that the generated code
			// can return the values with a type assertion.
			v := reflect.New(want).Elem()
			v.Set(reflect.ValueOf(ret))
			rets[i] = v.Interface()
		} else {
			c.t.Fatalf("wrong type of argument %d to Return for %T.%v: %v is not assignable to %v [%s]",
				i, c.receiver, c.method, got, want, c.origin)
		}
	}

	c.rets = rets
	return c
}

func (c *Call) Times(n int) *Call {
	c.minCalls, c.maxCalls = n, n
	return c
}

// SetArg declares an action that will set the nth argument's value,
// indirected through a pointer. Or, in the case of a slice, SetArg
// will copy value's elements into the nth argument.
func (c *Call) SetArg(n int, value interface{}) *Call {
	if c.setArgs == nil {
		c.setArgs = make(map[int]reflect.Value)
	}
	mt := c.methodType
	// TODO: This will break on variadic methods.
	// We will need to check those at invocation time.
	if n < 0 || n >= mt.NumIn() {
		c.t.Fatalf("SetArg(%d, ...) called for a method with %d args [%s]",
			n, mt.NumIn(), c.origin)
	}
	// Permit setting argument through an interface.
	// In the interface case, we don't (nay, can't) check the type here.
	at := mt.In(n)
	switch at.Kind() {
	case reflect.Ptr:
		dt := at.Elem()
		if vt := reflect.TypeOf(value); !vt.AssignableTo(dt) {
			c.t.Fatalf("SetArg(%d, ...) argument is a %v, not assignable to %v [%s]",
				n, vt, dt, c.origin)
		}
	case reflect.Interface:
		// nothing to do
	case reflect.Slice:
		// nothing to do
	default:
		c.t.Fatalf("SetArg(%d, ...) referring to argument of non-pointer non-interface non-slice type %v",
			n, at, c.origin)
	}
	c.setArgs[n] = reflect.ValueOf(value)
	return c
}

// isPreReq returns true if other is a direct or indirect prerequisite to c.
func (c *Call) isPreReq(other *Call) bool {
	for _, preReq := range c.preReqs {
		if other == preReq || preReq.isPreReq(other) {
			return true
		}
	}
	return false
}

// After declares that the call may only match after preReq has been exhausted.
func (c *Call) After(preReq *Call) *Call {
	if c == preReq {
		c.t.Fatalf("A call isn't allowed to be its own prerequisite")
	}
	if preReq.isPreReq(c) {
		c.t.Fatalf("Loop in call order: %v is a prerequisite to %v (possibly indirectly).", c, preReq)
	}

	c.preReqs = append(c.preReqs, preReq)
	return c
}

// Returns true if the minimum number of calls have been made.
func (c *Call) satisfied() bool {
	return c.numCalls >= c.minCalls
}

// Returns true iff the maximum number of calls have been made.
func (c *Call) exhausted() bool {
	return c.numCalls >= c.maxCalls
}

func (c *Call) String() string {
	args := make([]string, len(c.args))
	for i, arg := range c.args {
		args[i] = arg.String()
	}
	arguments := strings.Join(args, ", ")
	return fmt.Sprintf("%T.%v(%s) %s", c.receiver, c.method, arguments, c.origin)
}

// Tests if the given call matches the expected call.
// If yes, returns nil. If no, returns error with message explaining why it does not match.
func (c *Call) matches(args []interface{}) error {
	if !c.methodType.IsVariadic() {
		if len(args) != len(c.args) {
			return fmt.Errorf("Expected call at %s has the wrong number of arguments. Got: %d, want: %d",
				c.origin, len(args), len(c.args))
		}

		for i, m := range c.args {
			if !m.Matches(args[i]) {
				return fmt.Errorf("Expected call at %s doesn't match the argument at index %s.\nGot: %v\nWant: %v\n",
					c.origin, strconv.Itoa(i), args[i], m)
			}
		}
	} else {
		if len(c.args) < c.methodType.NumIn()-1 {
			return fmt.Errorf("Expected call at %s has the wrong number of matchers. Got: %d, want: %d",
				c.origin, len(c.args), c.methodType.NumIn()-1)
		}
		if len(c.args) != c.methodType.NumIn() && len(args) != len(c.args) {
			return fmt.Errorf("Expected call at %s has the wrong number of arguments. Got: %d, want: %d",
				c.origin, len(args), len(c.args))
		}
		if len(args) < len(c.args)-1 {
			return fmt.Errorf("Expected call at %s has the wrong number of arguments. Got: %d, want: greater than or equal to %d",
				c.origin, len(args), len(c.args)-1)
		}

		for i, m := range c.args {
			if i == len(c.args)-1 {
				// The last arg has a possibility of a variadic argument, so let it branch

				// sample: Foo(a int, b int, c ...int)

				if len(c.args) == len(args) {
					if c.args[i].Matches(args[i]) {
						// Got Foo(a, b, c) want Foo(matcherA, matcherB, gomock.Any())
						// Got Foo(a, b, c) want Foo(matcherA, matcherB, someSliceMatcher)
						// Got Foo(a, b, c) want Foo(matcherA, matcherB, matcherC)
						// Got Foo(a, b) want Foo(matcherA, matcherB)
						// Got Foo(a, b, c, d) want Foo(matcherA, matcherB, matcherC, matcherD)
						break
					}
				} else if c.args[i].Matches(args[i:]) {
					// Got Foo(a, b, c, d, e) want Foo(matcherA, matcherB, gomock.Any())
					// Got Foo(a, b, c, d, e) want Foo(matcherA, matcherB, someSliceMatcher)
					// Got Foo(a, b) want Foo(matcherA, matcherB, gomock.Any())
					// Got Foo(a, b) want Foo(matcherA, matcherB, someEmptySliceMatcher)
					break
				}
				// Wrong number of matchers or not match. Fail.
				// Got Foo(a, b) want Foo(matcherA, matcherB, matcherC, matcherD)
				// Got Foo(a, b, c) want Foo(matcherA, matcherB, matcherC, matcherD)
				// Got Foo(a, b, c, d) want Foo(matcherA, matcherB, matcherC, matcherD, matcherE)
				// Got Foo(a, b, c, d, e) want Foo(matcherA, matcherB, matcherC, matcherD)
				// Got Foo(a, b, c) want Foo(matcherA, matcherB)
				return fmt.Errorf("Expected call at %s doesn't match the argument at index %s.\nGot: %v\nWant: %v\n",
					c.origin, strconv.Itoa(i), args[i:], c.args[i])
			}

			if !m.Matches(args[i]) {
				return fmt.Errorf("Expected call at %s doesn't match the argument at index %s.\nGot: %v\nWant: %v\n",
					c.origin, strconv.Itoa(i), args[i], m)
			}
		}
	}

	// Check that all prerequisite calls have been satisfied.
	for _, preReqCall := range c.preReqs {
		if !preReqCall.satisfied() {
			return fmt.Errorf("Expected call at %s doesn't have a prerequisite call satisfied:\n%v\nshould be called before:\n%v",
				c.origin, preReqCall, c)
		}
	}

	return nil
}

// dropPrereqs tells the expected Call to not re-check prerequisite calls any
// longer, and to return its current set.
func (c *Call) dropPrereqs() (preReqs []*Call) {
	preReqs = c.preReqs
	c.preReqs = nil
	return
}

func (c *Call) call(args []interface{}) (rets []interface{}, action func()) {
	c.numCalls++

	// Actions
	if c.doFunc.IsValid() {
		doArgs := make([]reflect.Value, len(args))
		ft := c.doFunc.Type()
		for i := 0; i < len(args); i++ {
			if args[i] != nil {
				doArgs[i] = reflect.ValueOf(args[i])
			} else {
				// Use the zero value for the arg.
				doArgs[i] = reflect.Zero(ft.In(i))
			}
		}
		action = func() { c.doFunc.Call(doArgs) }
	}
	for n, v := range c.setArgs {
		switch reflect.TypeOf(args[n]).Kind() {
		case reflect.Slice:
			setSlice(args[n], v)
		default:
			reflect.ValueOf(args[n]).Elem().Set(v)
		}
	}

	rets = c.rets
	if rets == nil {
		// Synthesize the zero value for each of the return args' types.
		mt := c.methodType
		rets = make([]interface{}, mt.NumOut())
		for i := 0; i < mt.NumOut(); i++ {
			rets[i] = reflect.Zero(mt.Out(i)).Interface()
		}
	}

	return
}

// InOrder declares that the given calls should occur in order.
func InOrder(calls ...*Call) {
	for i := 1; i < len(calls); i++ {
		calls[i].After(calls[i-1])
	}
}

func setSlice(arg interface{}, v reflect.Value) {
	va := reflect.ValueOf(arg)
	for i := 0; i < v.Len(); i++ {
		va.Index(i).Set(v.Index(i))
	}
}
<|endoftext|>


<commit_before>package gorocheck

import (
	"bufio"
	"bytes"
	"fmt"
	"reflect"
	"runtime"
	"strings"
)

var pkgName string

func init() {
	t := reflect.TypeOf(Goroutine{})
	parts := strings.Split(t.PkgPath(), "/")

	pkgName = parts[len(parts)-1]
}

type Goroutine struct {
	Function string
	Number   int
	Action   string
	Stack    []string
}

func funcNameFromStackLine(s string) string {
	parts := strings.Split(s, "(")
	s = parts[0]
	parts = strings.Split(s, "/")
	return parts[len(parts)-1]
}

func parseStack() []*Goroutine {
	stkbuf := make([]byte, 1000000)
	n := runtime.Stack(stkbuf, true)
	stkbuf = stkbuf[:n]

	var out []*Goroutine
	var cur *Goroutine
	scan := bufio.NewScanner(bytes.NewReader(stkbuf))
	for scan.Scan() {
		if strings.HasPrefix(scan.Text(), "goroutine") {
			parts := strings.Split(scan.Text(), " ")

			var num int
			fmt.Sscanf(parts[1], "%d", &num)

			if !scan.Scan() {
				panic("bad format")
			}

			fname := funcNameFromStackLine(scan.Text())

			g := &Goroutine{
				Number:   num,
				Function: fname,
				Stack:    []string{scan.Text()},
			}
			out = append(out, g)
			cur = g
		} else if cur != nil {
			cur.Stack = append(cur.Stack, scan.Text())
		}
	}
	return out
}

func filterSystemRoutines(gs []*Goroutine) []*Goroutine {
	sys := map[string]struct{}{
		"testing.RunTests":      struct{}{},
		pkgName + ".parseStack": struct{}{},
		"signal.loop":           struct{}{},
		"signal.signal_recv":    struct{}{},
		"runtime.goexit":        struct{}{},
	}

	var out []*Goroutine
	for _, g := range gs {
		if _, found := sys[g.Function]; !found {
			out = append(out, g)
		} else {
			fmt.Println("skipped ", g)
		}
	}
	return out
}

func CheckForLeaks(filter func(*Goroutine) bool) error {
	goros := filterSystemRoutines(parseStack())
	var gorosFiltered []*Goroutine
	if filter != nil {
		for _, g := range goros {
			if !filter(g) {
				gorosFiltered = append(gorosFiltered, g)
			}
		}
	}
	goros = gorosFiltered
	if len(goros) > 0 {
		return fmt.Errorf("had %d goroutines still running. First on list: %s", len(goros), goros[0].Stack)
	}
	return nil
}
<commit_msg>remove debug statements<commit_after>package gorocheck

import (
	"bufio"
	"bytes"
	"fmt"
	"reflect"
	"runtime"
	"strings"
)

var pkgName string

func init() {
	t := reflect.TypeOf(Goroutine{})
	parts := strings.Split(t.PkgPath(), "/")

	pkgName = parts[len(parts)-1]
}

type Goroutine struct {
	Function string
	Number   int
	Action   string
	Stack    []string
}

func funcNameFromStackLine(s string) string {
	parts := strings.Split(s, "(")
	s = parts[0]
	parts = strings.Split(s, "/")
	return parts[len(parts)-1]
}

func parseStack() []*Goroutine {
	stkbuf := make([]byte, 1000000)
	n := runtime.Stack(stkbuf, true)
	stkbuf = stkbuf[:n]

	var out []*Goroutine
	var cur *Goroutine
	scan := bufio.NewScanner(bytes.NewReader(stkbuf))
	for scan.Scan() {
		if strings.HasPrefix(scan.Text(), "goroutine") {
			parts := strings.Split(scan.Text(), " ")

			var num int
			fmt.Sscanf(parts[1], "%d", &num)

			if !scan.Scan() {
				panic("bad format")
			}

			fname := funcNameFromStackLine(scan.Text())

			g := &Goroutine{
				Number:   num,
				Function: fname,
				Stack:    []string{scan.Text()},
			}
			out = append(out, g)
			cur = g
		} else if cur != nil {
			cur.Stack = append(cur.Stack, scan.Text())
		}
	}
	return out
}

func filterSystemRoutines(gs []*Goroutine) []*Goroutine {
	sys := map[string]struct{}{
		"testing.RunTests":      struct{}{},
		pkgName + ".parseStack": struct{}{},
		"signal.loop":           struct{}{},
		"signal.signal_recv":    struct{}{},
		"runtime.goexit":        struct{}{},
	}

	var out []*Goroutine
	for _, g := range gs {
		if _, found := sys[g.Function]; !found {
			out = append(out, g)
		}
	}
	return out
}

func CheckForLeaks(filter func(*Goroutine) bool) error {
	goros := filterSystemRoutines(parseStack())
	var gorosFiltered []*Goroutine
	if filter != nil {
		for _, g := range goros {
			if !filter(g) {
				gorosFiltered = append(gorosFiltered, g)
			}
		}
	}
	goros = gorosFiltered
	if len(goros) > 0 {
		return fmt.Errorf("had %d goroutines still running. First on list: %s", len(goros), goros[0].Stack)
	}
	return nil
}
<|endoftext|>


<commit_before>package logrus

import (
	"bytes"
	"encoding/json"
	"io/ioutil"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
)

func LogAndAssertJSON(t *testing.T, log func(*Logger), assertions func(fields Fields)) {
	var buffer bytes.Buffer
	var fields Fields

	logger := New()
	logger.Out = &buffer
	logger.Formatter = new(JSONFormatter)

	log(logger)

	err := json.Unmarshal(buffer.Bytes(), &fields)
	assert.Nil(t, err)

	assertions(fields)
}

func TestPrint(t *testing.T) {
	LogAndAssertJSON(t, func(log *Logger) {
		log.Print("test")
	}, func(fields Fields) {
		assert.Equal(t, fields["msg"], "test")
		assert.Equal(t, fields["level"], "info")
	})
}

func TestInfo(t *testing.T) {
	LogAndAssertJSON(t, func(log *Logger) {
		log.Info("test")
	}, func(fields Fields) {
		assert.Equal(t, fields["msg"], "test")
		assert.Equal(t, fields["level"], "info")
	})
}

func TestWarn(t *testing.T) {
	LogAndAssertJSON(t, func(log *Logger) {
		log.Warn("test")
	}, func(fields Fields) {
		assert.Equal(t, fields["msg"], "test")
		assert.Equal(t, fields["level"], "warning")
	})
}

func TestInfolnShouldAddSpacesBetweenStrings(t *testing.T) {
	LogAndAssertJSON(t, func(log *Logger) {
		log.Infoln("test", "test")
	}, func(fields Fields) {
		assert.Equal(t, fields["msg"], "test test")
	})
}

func TestInfolnShouldAddSpacesBetweenStringAndNonstring(t *testing.T) {
	LogAndAssertJSON(t, func(log *Logger) {
		log.Infoln("test", 10)
	}, func(fields Fields) {
		assert.Equal(t, fields["msg"], "test 10")
	})
}

func TestInfolnShouldAddSpacesBetweenTwoNonStrings(t *testing.T) {
	LogAndAssertJSON(t, func(log *Logger) {
		log.Infoln(10, 10)
	}, func(fields Fields) {
		assert.Equal(t, fields["msg"], "10 10")
	})
}

func TestInfoShouldAddSpacesBetweenTwoNonStrings(t *testing.T) {
	LogAndAssertJSON(t, func(log *Logger) {
		log.Infoln(10, 10)
	}, func(fields Fields) {
		assert.Equal(t, fields["msg"], "10 10")
	})
}

func TestInfoShouldNotAddSpacesBetweenStringAndNonstring(t *testing.T) {
	LogAndAssertJSON(t, func(log *Logger) {
		log.Info("test", 10)
	}, func(fields Fields) {
		assert.Equal(t, fields["msg"], "test10")
	})
}

func TestInfoShouldNotAddSpacesBetweenStrings(t *testing.T) {
	LogAndAssertJSON(t, func(log *Logger) {
		log.Info("test", "test")
	}, func(fields Fields) {
		assert.Equal(t, fields["msg"], "testtest")
	})
}

type SlowString string

func (s SlowString) String() string {
	time.Sleep(time.Millisecond)
	return string(s)
}

func getLogAtLevel(l Level) *Logger {
	log := New()
	log.Level = l
	log.Out = ioutil.Discard
	return log
}

func BenchmarkLevelDisplayed(b *testing.B) {
	log := getLogAtLevel(Info)
	for i := 0; i < b.N; i++ {
		log.Info(SlowString("foo"))
	}
}

func BenchmarkLevelHidden(b *testing.B) {
	log := getLogAtLevel(Info)
	for i := 0; i < b.N; i++ {
		log.Debug(SlowString("foo"))
	}
}

func BenchmarkLevelfDisplayed(b *testing.B) {
	log := getLogAtLevel(Info)
	for i := 0; i < b.N; i++ {
		log.Infof("%s", SlowString("foo"))
	}
}

func BenchmarkLevelfHidden(b *testing.B) {
	log := getLogAtLevel(Info)
	for i := 0; i < b.N; i++ {
		log.Debugf("%s", SlowString("foo"))
	}
}

func BenchmarkLevellnDisplayed(b *testing.B) {
	log := getLogAtLevel(Info)
	for i := 0; i < b.N; i++ {
		log.Infoln(SlowString("foo"))
	}
}

func BenchmarkLevellnHidden(b *testing.B) {
	log := getLogAtLevel(Info)
	for i := 0; i < b.N; i++ {
		log.Debugln(SlowString("foo"))
	}
}
<commit_msg>test: remove temporary benchmarks<commit_after>package logrus

import (
	"bytes"
	"encoding/json"
	"testing"

	"github.com/stretchr/testify/assert"
)

func LogAndAssertJSON(t *testing.T, log func(*Logger), assertions func(fields Fields)) {
	var buffer bytes.Buffer
	var fields Fields

	logger := New()
	logger.Out = &buffer
	logger.Formatter = new(JSONFormatter)

	log(logger)

	err := json.Unmarshal(buffer.Bytes(), &fields)
	assert.Nil(t, err)

	assertions(fields)
}

func TestPrint(t *testing.T) {
	LogAndAssertJSON(t, func(log *Logger) {
		log.Print("test")
	}, func(fields Fields) {
		assert.Equal(t, fields["msg"], "test")
		assert.Equal(t, fields["level"], "info")
	})
}

func TestInfo(t *testing.T) {
	LogAndAssertJSON(t, func(log *Logger) {
		log.Info("test")
	}, func(fields Fields) {
		assert.Equal(t, fields["msg"], "test")
		assert.Equal(t, fields["level"], "info")
	})
}

func TestWarn(t *testing.T) {
	LogAndAssertJSON(t, func(log *Logger) {
		log.Warn("test")
	}, func(fields Fields) {
		assert.Equal(t, fields["msg"], "test")
		assert.Equal(t, fields["level"], "warning")
	})
}

func TestInfolnShouldAddSpacesBetweenStrings(t *testing.T) {
	LogAndAssertJSON(t, func(log *Logger) {
		log.Infoln("test", "test")
	}, func(fields Fields) {
		assert.Equal(t, fields["msg"], "test test")
	})
}

func TestInfolnShouldAddSpacesBetweenStringAndNonstring(t *testing.T) {
	LogAndAssertJSON(t, func(log *Logger) {
		log.Infoln("test", 10)
	}, func(fields Fields) {
		assert.Equal(t, fields["msg"], "test 10")
	})
}

func TestInfolnShouldAddSpacesBetweenTwoNonStrings(t *testing.T) {
	LogAndAssertJSON(t, func(log *Logger) {
		log.Infoln(10, 10)
	}, func(fields Fields) {
		assert.Equal(t, fields["msg"], "10 10")
	})
}

func TestInfoShouldAddSpacesBetweenTwoNonStrings(t *testing.T) {
	LogAndAssertJSON(t, func(log *Logger) {
		log.Infoln(10, 10)
	}, func(fields Fields) {
		assert.Equal(t, fields["msg"], "10 10")
	})
}

func TestInfoShouldNotAddSpacesBetweenStringAndNonstring(t *testing.T) {
	LogAndAssertJSON(t, func(log *Logger) {
		log.Info("test", 10)
	}, func(fields Fields) {
		assert.Equal(t, fields["msg"], "test10")
	})
}

func TestInfoShouldNotAddSpacesBetweenStrings(t *testing.T) {
	LogAndAssertJSON(t, func(log *Logger) {
		log.Info("test", "test")
	}, func(fields Fields) {
		assert.Equal(t, fields["msg"], "testtest")
	})
}
<|endoftext|>


<commit_before>package logs

import (
	"context"
	"fmt"
	"github.com/ivankorobkov/go-blink/strs"
	"strings"
)

const (
	DefaultMessageFormat = "\t${Level}\t${Log}\t${Message}\t${Context}"
	DefaultTimeFormat    = "2006-01-02 15:04:05"
)

// format formats a Record into a human readable UTF-8 string using named ${Level} placeholders.
type format struct {
	formatter   *strs.Formatter
	timeFormat  string
	contextKeys []string
}

func newFormat(messageFormat string, timeFormat string, contextKeys []string) *format {
	if messageFormat == "" {
		messageFormat = DefaultMessageFormat
	}
	if timeFormat == "" {
		timeFormat = DefaultTimeFormat
	}

	return &format{
		formatter:   strs.NewFormatter(messageFormat),
		timeFormat:  timeFormat,
		contextKeys: contextKeys,
	}
}

func (f *format) format(ctx context.Context, record Record) string {
	r := struct {
		Log     string
		Time    string
		Level   Level
		Message string
		Context string
	}{
		Log:     record.Log,
		Time:    record.Time.Format(f.timeFormat),
		Level:   record.Level,
		Message: f.formatMessage(ctx, record),
		Context: f.formatContext(ctx),
	}

	return f.formatter.FormatStruct(r)
}

func (f *format) formatMessage(ctx context.Context, record Record) string {
	if record.Message != "" {
		return fmt.Sprintf(record.Message, record.Args...)
	}
	return fmt.Sprint(record.Args...)
}

func (f *format) formatContext(ctx context.Context) string {
	if len(f.contextKeys) == 0 {
		return ""
	}

	s := []string{}
	for _, key := range f.contextKeys {
		val := ctx.Value(key)
		if val == nil {
			continue
		}

		s = append(s, fmt.Sprintf("%s=%v", key, val))
	}
	if len(s) == 0 {
		return ""
	}

	return "{" + strings.Join(s, ", ") + "}"
}
<commit_msg>logs: Fixed context format NPE.<commit_after>package logs

import (
	"context"
	"fmt"
	"github.com/ivankorobkov/go-blink/strs"
	"strings"
)

const (
	DefaultMessageFormat = "\t${Level}\t${Log}\t${Message}\t${Context}"
	DefaultTimeFormat    = "2006-01-02 15:04:05"
)

// format formats a Record into a human readable UTF-8 string using named ${Level} placeholders.
type format struct {
	formatter   *strs.Formatter
	timeFormat  string
	contextKeys []string
}

func newFormat(messageFormat string, timeFormat string, contextKeys []string) *format {
	if messageFormat == "" {
		messageFormat = DefaultMessageFormat
	}
	if timeFormat == "" {
		timeFormat = DefaultTimeFormat
	}

	return &format{
		formatter:   strs.NewFormatter(messageFormat),
		timeFormat:  timeFormat,
		contextKeys: contextKeys,
	}
}

func (f *format) format(ctx context.Context, record Record) string {
	r := struct {
		Log     string
		Time    string
		Level   Level
		Message string
		Context string
	}{
		Log:     record.Log,
		Time:    record.Time.Format(f.timeFormat),
		Level:   record.Level,
		Message: f.formatMessage(ctx, record),
		Context: f.formatContext(ctx),
	}

	return f.formatter.FormatStruct(r)
}

func (f *format) formatMessage(ctx context.Context, record Record) string {
	if record.Message != "" {
		return fmt.Sprintf(record.Message, record.Args...)
	}
	return fmt.Sprint(record.Args...)
}

func (f *format) formatContext(ctx context.Context) string {
	if ctx == nil || len(f.contextKeys) == 0 {
		return ""
	}

	s := []string{}
	for _, key := range f.contextKeys {
		val := ctx.Value(key)
		if val == nil {
			continue
		}

		s = append(s, fmt.Sprintf("%s=%v", key, val))
	}
	if len(s) == 0 {
		return ""
	}

	return "{" + strings.Join(s, ", ") + "}"
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"syscall"

	"github.com/lxc/lxd/shared"

	log "gopkg.in/inconshreveable/log15.v2"
)

/* Some interesting filesystems */
const (
	filesystemSuperMagicTmpfs = 0x01021994
	filesystemSuperMagicExt4  = 0xEF53
	filesystemSuperMagicXfs   = 0x58465342
	filesystemSuperMagicNfs   = 0x6969
	filesystemSuperMagicZfs   = 0x2fc12fc1
)

/*
 * filesystemDetect returns the filesystem on which
 * the passed-in path sits
 */
func filesystemDetect(path string) (string, error) {
	fs := syscall.Statfs_t{}

	err := syscall.Statfs(path, &fs)
	if err != nil {
		return "", err
	}

	switch fs.Type {
	case filesystemSuperMagicBtrfs:
		return "btrfs", nil
	case filesystemSuperMagicZfs:
		return "zfs", nil
	case filesystemSuperMagicTmpfs:
		return "tmpfs", nil
	case filesystemSuperMagicExt4:
		return "ext4", nil
	case filesystemSuperMagicXfs:
		return "xfs", nil
	case filesystemSuperMagicNfs:
		return "nfs", nil
	default:
		shared.Debugf("Unknown backing filesystem type: 0x%x", fs.Type)
		return string(fs.Type), nil
	}
}

// storageRsyncCopy copies a directory using rsync (with the --devices option).
func storageRsyncCopy(source string, dest string) (string, error) {
	if err := os.MkdirAll(dest, 0755); err != nil {
		return "", err
	}

	rsyncVerbosity := "-q"
	if *debug {
		rsyncVerbosity = "-vi"
	}

	output, err := exec.Command(
		"rsync",
		"-a",
		"-HAX",
		"--devices",
		"--delete",
		"--checksum",
		rsyncVerbosity,
		shared.AddSlash(source),
		dest).CombinedOutput()

	return string(output), err
}

func storageUnprivUserAclSet(c container, dpath string) error {
	idmapset := c.IdmapSetGet()

	if idmapset == nil {
		return nil
	}
	uid, _ := idmapset.ShiftIntoNs(0, 0)
	switch uid {
	case -1:
		shared.Debugf("No root id mapping")
		return nil
	case 0:
		return nil
	}
	acl := fmt.Sprintf("%d:rx", uid)
	output, err := exec.Command("setfacl", "-m", acl, dpath).CombinedOutput()
	if err != nil {
		shared.Debugf("Setfacl failed:\n%s", string(output))
	}
	return err
}

// storageType defines the type of a storage
type storageType int

const (
	storageTypeBtrfs storageType = iota
	storageTypeZfs
	storageTypeLvm
	storageTypeDir
	storageTypeMock
)

func storageTypeToString(sType storageType) string {
	switch sType {
	case storageTypeBtrfs:
		return "btrfs"
	case storageTypeZfs:
		return "zfs"
	case storageTypeLvm:
		return "lvm"
	case storageTypeMock:
		return "mock"
	}

	return "dir"
}

type storage interface {
	Init(config map[string]interface{}) (storage, error)

	GetStorageType() storageType
	GetStorageTypeName() string
	GetStorageTypeVersion() string

	// ContainerCreate creates an empty container (no rootfs/metadata.yaml)
	ContainerCreate(container container) error

	// ContainerCreateFromImage creates a container from a image.
	ContainerCreateFromImage(container container, imageFingerprint string) error

	ContainerDelete(container container) error
	ContainerCopy(container container, sourceContainer container) error
	ContainerStart(container container) error
	ContainerStop(container container) error
	ContainerRename(container container, newName string) error
	ContainerRestore(container container, sourceContainer container) error

	ContainerSnapshotCreate(
		snapshotContainer container, sourceContainer container) error
	ContainerSnapshotDelete(snapshotContainer container) error
	ContainerSnapshotRename(snapshotContainer container, newName string) error

	ImageCreate(fingerprint string) error
	ImageDelete(fingerprint string) error
}

func newStorage(d *Daemon, sType storageType) (storage, error) {
	var nilmap map[string]interface{}
	return newStorageWithConfig(d, sType, nilmap)
}

func newStorageWithConfig(d *Daemon, sType storageType, config map[string]interface{}) (storage, error) {
	if d.IsMock {
		return d.Storage, nil
	}

	var s storage

	switch sType {
	case storageTypeBtrfs:
		if d.Storage != nil && d.Storage.GetStorageType() == storageTypeBtrfs {
			return d.Storage, nil
		}

		s = &storageLogWrapper{w: &storageBtrfs{d: d}}
	case storageTypeZfs:
		if d.Storage != nil && d.Storage.GetStorageType() == storageTypeZfs {
			return d.Storage, nil
		}

		s = &storageLogWrapper{w: &storageZfs{d: d}}
	case storageTypeLvm:
		if d.Storage != nil && d.Storage.GetStorageType() == storageTypeLvm {
			return d.Storage, nil
		}

		s = &storageLogWrapper{w: &storageLvm{d: d}}
	default:
		if d.Storage != nil && d.Storage.GetStorageType() == storageTypeDir {
			return d.Storage, nil
		}

		s = &storageLogWrapper{w: &storageDir{d: d}}
	}

	return s.Init(config)
}

func storageForFilename(d *Daemon, filename string) (storage, error) {
	config := make(map[string]interface{})
	storageType := storageTypeDir

	if shared.PathExists(filename + ".lv") {
		storageType = storageTypeLvm
		lvPath, err := os.Readlink(filename + ".lv")
		if err != nil {
			return nil, fmt.Errorf("couldn't read link dest for '%s': %v", filename+".lv", err)
		}
		vgname := filepath.Base(filepath.Dir(lvPath))
		config["vgName"] = vgname
	} else if shared.PathExists(filename + ".btrfs") {
		storageType = storageTypeBtrfs
	} else if shared.PathExists(filename + ".zfs") {
		storageType = storageTypeZfs
	}

	return newStorageWithConfig(d, storageType, config)
}

func storageForImage(d *Daemon, imgInfo *shared.ImageBaseInfo) (storage, error) {
	imageFilename := shared.VarPath("images", imgInfo.Fingerprint)
	return storageForFilename(d, imageFilename)
}

type storageShared struct {
	sType        storageType
	sTypeName    string
	sTypeVersion string

	log log.Logger
}

func (ss *storageShared) initShared() error {
	ss.log = shared.Log.New(
		log.Ctx{"driver": fmt.Sprintf("storage/%s", ss.sTypeName)},
	)
	return nil
}

func (ss *storageShared) GetStorageType() storageType {
	return ss.sType
}

func (ss *storageShared) GetStorageTypeName() string {
	return ss.sTypeName
}

func (ss *storageShared) GetStorageTypeVersion() string {
	return ss.sTypeVersion
}

func (ss *storageShared) shiftRootfs(c container) error {
	dpath := c.PathGet("")
	rpath := c.RootfsPathGet()

	shared.Log.Debug("Shifting root filesystem",
		log.Ctx{"container": c.NameGet(), "rootfs": rpath})

	idmapset := c.IdmapSetGet()

	if idmapset == nil {
		return fmt.Errorf("IdmapSet of container '%s' is nil", c.NameGet())
	}

	err := idmapset.ShiftRootfs(rpath)
	if err != nil {
		shared.Debugf("Shift of rootfs %s failed: %s", rpath, err)
		return err
	}

	/* Set an acl so the container root can descend the container dir */
	// TODO: i changed this so it calls ss.setUnprivUserAcl, which does
	// the acl change only if the container is not privileged, think thats right.
	return ss.setUnprivUserAcl(c, dpath)
}

func (ss *storageShared) setUnprivUserAcl(c container, destPath string) error {
	if !c.IsPrivileged() {
		err := storageUnprivUserAclSet(c, destPath)
		if err != nil {
			ss.log.Error(
				"Adding acl for container root: falling back to chmod",
				log.Ctx{"destPath": destPath})

			output, err := exec.Command(
				"chmod", "+x", destPath).CombinedOutput()

			if err != nil {
				ss.log.Error(
					"chmoding the container root",
					log.Ctx{
						"destPath": destPath,
						"output":   string(output)})

				return err
			}
		}
	}

	return nil
}

type storageLogWrapper struct {
	w   storage
	log log.Logger
}

func (lw *storageLogWrapper) Init(config map[string]interface{}) (storage, error) {
	_, err := lw.w.Init(config)
	lw.log = shared.Log.New(
		log.Ctx{"driver": fmt.Sprintf("storage/%s", lw.w.GetStorageTypeName())},
	)

	lw.log.Info("Init")
	return lw, err
}

func (lw *storageLogWrapper) GetStorageType() storageType {
	return lw.w.GetStorageType()
}

func (lw *storageLogWrapper) GetStorageTypeName() string {
	return lw.w.GetStorageTypeName()
}

func (lw *storageLogWrapper) GetStorageTypeVersion() string {
	return lw.w.GetStorageTypeVersion()
}

func (lw *storageLogWrapper) ContainerCreate(container container) error {
	lw.log.Debug(
		"ContainerCreate",
		log.Ctx{
			"name":         container.NameGet(),
			"isPrivileged": container.IsPrivileged()})
	return lw.w.ContainerCreate(container)
}

func (lw *storageLogWrapper) ContainerCreateFromImage(
	container container, imageFingerprint string) error {

	lw.log.Debug(
		"ContainerCreateFromImage",
		log.Ctx{
			"imageFingerprint": imageFingerprint,
			"name":             container.NameGet(),
			"isPrivileged":     container.IsPrivileged()})
	return lw.w.ContainerCreateFromImage(container, imageFingerprint)
}

func (lw *storageLogWrapper) ContainerDelete(container container) error {
	lw.log.Debug("ContainerDelete", log.Ctx{"container": container.NameGet()})
	return lw.w.ContainerDelete(container)
}

func (lw *storageLogWrapper) ContainerCopy(
	container container, sourceContainer container) error {

	lw.log.Debug(
		"ContainerCopy",
		log.Ctx{
			"container": container.NameGet(),
			"source":    sourceContainer.NameGet()})
	return lw.w.ContainerCopy(container, sourceContainer)
}

func (lw *storageLogWrapper) ContainerStart(container container) error {
	lw.log.Debug("ContainerStart", log.Ctx{"container": container.NameGet()})
	return lw.w.ContainerStart(container)
}

func (lw *storageLogWrapper) ContainerStop(container container) error {
	lw.log.Debug("ContainerStop", log.Ctx{"container": container.NameGet()})
	return lw.w.ContainerStop(container)
}

func (lw *storageLogWrapper) ContainerRename(
	container container, newName string) error {

	lw.log.Debug(
		"ContainerRename",
		log.Ctx{
			"container": container.NameGet(),
			"newName":   newName})
	return lw.w.ContainerRename(container, newName)
}

func (lw *storageLogWrapper) ContainerRestore(
	container container, sourceContainer container) error {

	lw.log.Debug(
		"ContainerRestore",
		log.Ctx{
			"container": container.NameGet(),
			"source":    sourceContainer.NameGet()})
	return lw.w.ContainerRestore(container, sourceContainer)
}

func (lw *storageLogWrapper) ContainerSnapshotCreate(
	snapshotContainer container, sourceContainer container) error {

	lw.log.Debug("ContainerSnapshotCreate",
		log.Ctx{
			"snapshotContainer": snapshotContainer.NameGet(),
			"sourceContainer":   sourceContainer.NameGet()})

	return lw.w.ContainerSnapshotCreate(snapshotContainer, sourceContainer)
}
func (lw *storageLogWrapper) ContainerSnapshotDelete(
	snapshotContainer container) error {

	lw.log.Debug("ContainerSnapshotDelete",
		log.Ctx{"snapshotContainer": snapshotContainer.NameGet()})
	return lw.w.ContainerSnapshotDelete(snapshotContainer)
}

func (lw *storageLogWrapper) ContainerSnapshotRename(
	snapshotContainer container, newName string) error {

	lw.log.Debug("ContainerSnapshotRename",
		log.Ctx{
			"snapshotContainer": snapshotContainer.NameGet(),
			"newName":           newName})
	return lw.w.ContainerSnapshotRename(snapshotContainer, newName)
}

func (lw *storageLogWrapper) ImageCreate(fingerprint string) error {
	lw.log.Debug(
		"ImageCreate",
		log.Ctx{"fingerprint": fingerprint})
	return lw.w.ImageCreate(fingerprint)
}

func (lw *storageLogWrapper) ImageDelete(fingerprint string) error {
	lw.log.Debug("ImageDelete", log.Ctx{"fingerprint": fingerprint})
	return lw.w.ImageDelete(fingerprint)

}
<commit_msg>Fix btrfs detection code<commit_after>package main

import (
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"syscall"

	"github.com/lxc/lxd/shared"

	log "gopkg.in/inconshreveable/log15.v2"
)

/* Some interesting filesystems */
const (
	filesystemSuperMagicTmpfs = 0x01021994
	filesystemSuperMagicExt4  = 0xEF53
	filesystemSuperMagicXfs   = 0x58465342
	filesystemSuperMagicNfs   = 0x6969
	filesystemSuperMagicZfs   = 0x2fc12fc1
)

/*
 * filesystemDetect returns the filesystem on which
 * the passed-in path sits
 */
func filesystemDetect(path string) (string, error) {
	fs := syscall.Statfs_t{}

	err := syscall.Statfs(path, &fs)
	if err != nil {
		return "", err
	}

	switch fs.Type {
	case filesystemSuperMagicBtrfs:
		return "btrfs", nil
	case filesystemSuperMagicZfs:
		return "zfs", nil
	case filesystemSuperMagicTmpfs:
		return "tmpfs", nil
	case filesystemSuperMagicExt4:
		return "ext4", nil
	case filesystemSuperMagicXfs:
		return "xfs", nil
	case filesystemSuperMagicNfs:
		return "nfs", nil
	default:
		shared.Debugf("Unknown backing filesystem type: 0x%x", fs.Type)
		return string(fs.Type), nil
	}
}

// storageRsyncCopy copies a directory using rsync (with the --devices option).
func storageRsyncCopy(source string, dest string) (string, error) {
	if err := os.MkdirAll(dest, 0755); err != nil {
		return "", err
	}

	rsyncVerbosity := "-q"
	if *debug {
		rsyncVerbosity = "-vi"
	}

	output, err := exec.Command(
		"rsync",
		"-a",
		"-HAX",
		"--devices",
		"--delete",
		"--checksum",
		rsyncVerbosity,
		shared.AddSlash(source),
		dest).CombinedOutput()

	return string(output), err
}

func storageUnprivUserAclSet(c container, dpath string) error {
	idmapset := c.IdmapSetGet()

	if idmapset == nil {
		return nil
	}
	uid, _ := idmapset.ShiftIntoNs(0, 0)
	switch uid {
	case -1:
		shared.Debugf("No root id mapping")
		return nil
	case 0:
		return nil
	}
	acl := fmt.Sprintf("%d:rx", uid)
	output, err := exec.Command("setfacl", "-m", acl, dpath).CombinedOutput()
	if err != nil {
		shared.Debugf("Setfacl failed:\n%s", string(output))
	}
	return err
}

// storageType defines the type of a storage
type storageType int

const (
	storageTypeBtrfs storageType = iota
	storageTypeZfs
	storageTypeLvm
	storageTypeDir
	storageTypeMock
)

func storageTypeToString(sType storageType) string {
	switch sType {
	case storageTypeBtrfs:
		return "btrfs"
	case storageTypeZfs:
		return "zfs"
	case storageTypeLvm:
		return "lvm"
	case storageTypeMock:
		return "mock"
	}

	return "dir"
}

type storage interface {
	Init(config map[string]interface{}) (storage, error)

	GetStorageType() storageType
	GetStorageTypeName() string
	GetStorageTypeVersion() string

	// ContainerCreate creates an empty container (no rootfs/metadata.yaml)
	ContainerCreate(container container) error

	// ContainerCreateFromImage creates a container from a image.
	ContainerCreateFromImage(container container, imageFingerprint string) error

	ContainerDelete(container container) error
	ContainerCopy(container container, sourceContainer container) error
	ContainerStart(container container) error
	ContainerStop(container container) error
	ContainerRename(container container, newName string) error
	ContainerRestore(container container, sourceContainer container) error

	ContainerSnapshotCreate(
		snapshotContainer container, sourceContainer container) error
	ContainerSnapshotDelete(snapshotContainer container) error
	ContainerSnapshotRename(snapshotContainer container, newName string) error

	ImageCreate(fingerprint string) error
	ImageDelete(fingerprint string) error
}

func newStorage(d *Daemon, sType storageType) (storage, error) {
	var nilmap map[string]interface{}
	return newStorageWithConfig(d, sType, nilmap)
}

func newStorageWithConfig(d *Daemon, sType storageType, config map[string]interface{}) (storage, error) {
	if d.IsMock {
		return d.Storage, nil
	}

	var s storage

	switch sType {
	case storageTypeBtrfs:
		if d.Storage != nil && d.Storage.GetStorageType() == storageTypeBtrfs {
			return d.Storage, nil
		}

		s = &storageLogWrapper{w: &storageBtrfs{d: d}}
	case storageTypeZfs:
		if d.Storage != nil && d.Storage.GetStorageType() == storageTypeZfs {
			return d.Storage, nil
		}

		s = &storageLogWrapper{w: &storageZfs{d: d}}
	case storageTypeLvm:
		if d.Storage != nil && d.Storage.GetStorageType() == storageTypeLvm {
			return d.Storage, nil
		}

		s = &storageLogWrapper{w: &storageLvm{d: d}}
	default:
		if d.Storage != nil && d.Storage.GetStorageType() == storageTypeDir {
			return d.Storage, nil
		}

		s = &storageLogWrapper{w: &storageDir{d: d}}
	}

	return s.Init(config)
}

func storageForFilename(d *Daemon, filename string) (storage, error) {
	config := make(map[string]interface{})
	storageType := storageTypeDir

	filesystem, err := filesystemDetect(filename)
	if err != nil {
		return nil, fmt.Errorf("couldn't detect filesystem for '%s': %v", filename, err)
	}

	if shared.PathExists(filename + ".lv") {
		storageType = storageTypeLvm
		lvPath, err := os.Readlink(filename + ".lv")
		if err != nil {
			return nil, fmt.Errorf("couldn't read link dest for '%s': %v", filename+".lv", err)
		}
		vgname := filepath.Base(filepath.Dir(lvPath))
		config["vgName"] = vgname
	} else if shared.PathExists(filename+".btrfs") || filesystem == "btrfs" {
		storageType = storageTypeBtrfs
	} else if shared.PathExists(filename + ".zfs") {
		storageType = storageTypeZfs
	}

	return newStorageWithConfig(d, storageType, config)
}

func storageForImage(d *Daemon, imgInfo *shared.ImageBaseInfo) (storage, error) {
	imageFilename := shared.VarPath("images", imgInfo.Fingerprint)
	return storageForFilename(d, imageFilename)
}

type storageShared struct {
	sType        storageType
	sTypeName    string
	sTypeVersion string

	log log.Logger
}

func (ss *storageShared) initShared() error {
	ss.log = shared.Log.New(
		log.Ctx{"driver": fmt.Sprintf("storage/%s", ss.sTypeName)},
	)
	return nil
}

func (ss *storageShared) GetStorageType() storageType {
	return ss.sType
}

func (ss *storageShared) GetStorageTypeName() string {
	return ss.sTypeName
}

func (ss *storageShared) GetStorageTypeVersion() string {
	return ss.sTypeVersion
}

func (ss *storageShared) shiftRootfs(c container) error {
	dpath := c.PathGet("")
	rpath := c.RootfsPathGet()

	shared.Log.Debug("Shifting root filesystem",
		log.Ctx{"container": c.NameGet(), "rootfs": rpath})

	idmapset := c.IdmapSetGet()

	if idmapset == nil {
		return fmt.Errorf("IdmapSet of container '%s' is nil", c.NameGet())
	}

	err := idmapset.ShiftRootfs(rpath)
	if err != nil {
		shared.Debugf("Shift of rootfs %s failed: %s", rpath, err)
		return err
	}

	/* Set an acl so the container root can descend the container dir */
	// TODO: i changed this so it calls ss.setUnprivUserAcl, which does
	// the acl change only if the container is not privileged, think thats right.
	return ss.setUnprivUserAcl(c, dpath)
}

func (ss *storageShared) setUnprivUserAcl(c container, destPath string) error {
	if !c.IsPrivileged() {
		err := storageUnprivUserAclSet(c, destPath)
		if err != nil {
			ss.log.Error(
				"Adding acl for container root: falling back to chmod",
				log.Ctx{"destPath": destPath})

			output, err := exec.Command(
				"chmod", "+x", destPath).CombinedOutput()

			if err != nil {
				ss.log.Error(
					"chmoding the container root",
					log.Ctx{
						"destPath": destPath,
						"output":   string(output)})

				return err
			}
		}
	}

	return nil
}

type storageLogWrapper struct {
	w   storage
	log log.Logger
}

func (lw *storageLogWrapper) Init(config map[string]interface{}) (storage, error) {
	_, err := lw.w.Init(config)
	lw.log = shared.Log.New(
		log.Ctx{"driver": fmt.Sprintf("storage/%s", lw.w.GetStorageTypeName())},
	)

	lw.log.Info("Init")
	return lw, err
}

func (lw *storageLogWrapper) GetStorageType() storageType {
	return lw.w.GetStorageType()
}

func (lw *storageLogWrapper) GetStorageTypeName() string {
	return lw.w.GetStorageTypeName()
}

func (lw *storageLogWrapper) GetStorageTypeVersion() string {
	return lw.w.GetStorageTypeVersion()
}

func (lw *storageLogWrapper) ContainerCreate(container container) error {
	lw.log.Debug(
		"ContainerCreate",
		log.Ctx{
			"name":         container.NameGet(),
			"isPrivileged": container.IsPrivileged()})
	return lw.w.ContainerCreate(container)
}

func (lw *storageLogWrapper) ContainerCreateFromImage(
	container container, imageFingerprint string) error {

	lw.log.Debug(
		"ContainerCreateFromImage",
		log.Ctx{
			"imageFingerprint": imageFingerprint,
			"name":             container.NameGet(),
			"isPrivileged":     container.IsPrivileged()})
	return lw.w.ContainerCreateFromImage(container, imageFingerprint)
}

func (lw *storageLogWrapper) ContainerDelete(container container) error {
	lw.log.Debug("ContainerDelete", log.Ctx{"container": container.NameGet()})
	return lw.w.ContainerDelete(container)
}

func (lw *storageLogWrapper) ContainerCopy(
	container container, sourceContainer container) error {

	lw.log.Debug(
		"ContainerCopy",
		log.Ctx{
			"container": container.NameGet(),
			"source":    sourceContainer.NameGet()})
	return lw.w.ContainerCopy(container, sourceContainer)
}

func (lw *storageLogWrapper) ContainerStart(container container) error {
	lw.log.Debug("ContainerStart", log.Ctx{"container": container.NameGet()})
	return lw.w.ContainerStart(container)
}

func (lw *storageLogWrapper) ContainerStop(container container) error {
	lw.log.Debug("ContainerStop", log.Ctx{"container": container.NameGet()})
	return lw.w.ContainerStop(container)
}

func (lw *storageLogWrapper) ContainerRename(
	container container, newName string) error {

	lw.log.Debug(
		"ContainerRename",
		log.Ctx{
			"container": container.NameGet(),
			"newName":   newName})
	return lw.w.ContainerRename(container, newName)
}

func (lw *storageLogWrapper) ContainerRestore(
	container container, sourceContainer container) error {

	lw.log.Debug(
		"ContainerRestore",
		log.Ctx{
			"container": container.NameGet(),
			"source":    sourceContainer.NameGet()})
	return lw.w.ContainerRestore(container, sourceContainer)
}

func (lw *storageLogWrapper) ContainerSnapshotCreate(
	snapshotContainer container, sourceContainer container) error {

	lw.log.Debug("ContainerSnapshotCreate",
		log.Ctx{
			"snapshotContainer": snapshotContainer.NameGet(),
			"sourceContainer":   sourceContainer.NameGet()})

	return lw.w.ContainerSnapshotCreate(snapshotContainer, sourceContainer)
}
func (lw *storageLogWrapper) ContainerSnapshotDelete(
	snapshotContainer container) error {

	lw.log.Debug("ContainerSnapshotDelete",
		log.Ctx{"snapshotContainer": snapshotContainer.NameGet()})
	return lw.w.ContainerSnapshotDelete(snapshotContainer)
}

func (lw *storageLogWrapper) ContainerSnapshotRename(
	snapshotContainer container, newName string) error {

	lw.log.Debug("ContainerSnapshotRename",
		log.Ctx{
			"snapshotContainer": snapshotContainer.NameGet(),
			"newName":           newName})
	return lw.w.ContainerSnapshotRename(snapshotContainer, newName)
}

func (lw *storageLogWrapper) ImageCreate(fingerprint string) error {
	lw.log.Debug(
		"ImageCreate",
		log.Ctx{"fingerprint": fingerprint})
	return lw.w.ImageCreate(fingerprint)
}

func (lw *storageLogWrapper) ImageDelete(fingerprint string) error {
	lw.log.Debug("ImageDelete", log.Ctx{"fingerprint": fingerprint})
	return lw.w.ImageDelete(fingerprint)

}
<|endoftext|>