<commit_before>package main

import (
	"koding/db/mongodb/modelhelper"
	"math/rand"
	"socialapi/config"
	"socialapi/models"
	"socialapi/rest"
	"strconv"
	"testing"
	"time"

	"github.com/koding/bongo"
	"github.com/koding/runner"

	. "github.com/smartystreets/goconvey/convey"
)

func TestChannelParticipantOperations(t *testing.T) {
	r := runner.New("test")
	if err := r.Init(); err != nil {
		t.Fatalf("couldnt start bongo %s", err.Error())
	}
	defer r.Close()

	appConfig := config.MustRead(r.Conf.Path)
	modelhelper.Initialize(appConfig.Mongo)
	defer modelhelper.Close()

	Convey("while testing channel participants", t, func() {

		Convey("First Create Users and initiate conversation", func() {
			var err error
			ownerAccount := models.NewAccount()
			ownerAccount.OldId = AccountOldId.Hex()
			ownerAccount, err = rest.CreateAccount(ownerAccount)
			So(err, ShouldBeNil)
			So(ownerAccount, ShouldNotBeNil)

			secondAccount := models.NewAccount()
			secondAccount.OldId = AccountOldId2.Hex()
			secondAccount, err = rest.CreateAccount(secondAccount)
			So(err, ShouldBeNil)
			So(secondAccount, ShouldNotBeNil)

			thirdAccount := models.NewAccount()
			thirdAccount.OldId = AccountOldId3.Hex()
			thirdAccount, err = rest.CreateAccount(thirdAccount)
			So(err, ShouldBeNil)
			So(thirdAccount, ShouldNotBeNil)

			forthAccount := models.NewAccount()
			forthAccount.OldId = AccountOldId4.Hex()
			forthAccount, err = rest.CreateAccount(forthAccount)
			So(err, ShouldBeNil)
			So(forthAccount, ShouldNotBeNil)

			CreatePrivateChannelUser("devrim")

			groupName := "testgroup" + strconv.FormatInt(rand.Int63(), 10)

			pmr := models.PrivateChannelRequest{}

			pmr.AccountId = ownerAccount.Id

			pmr.Body = "new conversation"
			pmr.GroupName = groupName
			pmr.Recipients = []string{"devrim"}

			channelContainer, err := rest.SendPrivateChannelRequest(pmr)
			So(err, ShouldBeNil)
			So(channelContainer, ShouldNotBeNil)

			Convey("First user should be able to add second and third users to conversation", func() {
				_, err = rest.AddChannelParticipant(channelContainer.Channel.Id, ownerAccount.Id, secondAccount.Id, thirdAccount.Id)
				So(err, ShouldBeNil)
				participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerAccount.Id)
				So(err, ShouldBeNil)
				So(participants, ShouldNotBeNil)
				// it is four because first user is "devrim" here
				So(len(participants), ShouldEqual, 4)

				Convey("First user should not be able to re-add second participant", func() {
					_, err = rest.AddChannelParticipant(channelContainer.Channel.Id, ownerAccount.Id, secondAccount.Id)
					So(err, ShouldBeNil)

					participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerAccount.Id)
					So(err, ShouldBeNil)
					So(participants, ShouldNotBeNil)
					So(len(participants), ShouldEqual, 4)
				})

				Convey("Second user should be able to leave conversation", func() {
					_, err = rest.DeleteChannelParticipant(channelContainer.Channel.Id, secondAccount.Id, secondAccount.Id)
					So(err, ShouldBeNil)

					participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerAccount.Id)
					So(err, ShouldBeNil)
					So(participants, ShouldNotBeNil)
					So(len(participants), ShouldEqual, 3)

					Convey("A user who is not participant of a conversation should not be able to add another user to the conversation", func() {
						_, err = rest.AddChannelParticipant(channelContainer.Channel.Id, secondAccount.Id, forthAccount.Id)
						So(err, ShouldNotBeNil)

						participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerAccount.Id)
						So(err, ShouldBeNil)
						So(participants, ShouldNotBeNil)
						So(len(participants), ShouldEqual, 3)
					})
				})

				Convey("Channel owner should be able to kick another conversation participant", func() {
					_, err = rest.DeleteChannelParticipant(channelContainer.Channel.Id, ownerAccount.Id, secondAccount.Id)
					So(err, ShouldBeNil)

					participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerAccount.Id)
					So(err, ShouldBeNil)
					So(participants, ShouldNotBeNil)
					So(len(participants), ShouldEqual, 3)
				})

				Convey("Second user should not be able to kick another conversation participant", func() {
					_, err = rest.DeleteChannelParticipant(channelContainer.Channel.Id, secondAccount.Id, thirdAccount.Id)
					So(err, ShouldNotBeNil)
				})
			})

			// TODO Until we find a better way for handling async stuff, this test is skipped. Instead of sleep, we should use some
			// timeouts for testing these kind of stuff.
			SkipConvey("All private messages must be deleted when all participant users leave the channel", func() {
				account := models.NewAccount()
				err = account.ByNick("devrim")
				So(err, ShouldBeNil)

				_, err = rest.DeleteChannelParticipant(channelContainer.Channel.Id, account.Id, account.Id)
				So(err, ShouldBeNil)

				_, err = rest.DeleteChannelParticipant(channelContainer.Channel.Id, ownerAccount.Id, ownerAccount.Id)
				So(err, ShouldBeNil)

				time.Sleep(1 * time.Second)

				testChannel := models.NewChannel()
				err := testChannel.ById(channelContainer.Channel.Id)
				So(err, ShouldEqual, bongo.RecordNotFound)

				testChannelList := models.NewChannelMessageList()
				err = bongo.B.Unscoped().Where("channel_id = ?", channelContainer.Channel.Id).Find(testChannelList).Error
				So(err, ShouldEqual, bongo.RecordNotFound)

				testMessage := models.NewChannelMessage()
				err = bongo.B.Unscoped().Where("initial_channel_id = ?", channelContainer.Channel.Id).Find(testMessage).Error
				So(err, ShouldEqual, bongo.RecordNotFound)
			})
		})
	})
}
<commit_msg>Socialapi: added new test cases for channel participant blocking and unblocking<commit_after>package main

import (
	"koding/db/mongodb/modelhelper"
	"math/rand"
	"socialapi/config"
	"socialapi/models"
	"socialapi/rest"
	"strconv"
	"testing"
	"time"

	"github.com/koding/bongo"
	"github.com/koding/runner"

	. "github.com/smartystreets/goconvey/convey"
)

func TestChannelParticipantOperations(t *testing.T) {
	r := runner.New("test")
	if err := r.Init(); err != nil {
		t.Fatalf("couldnt start bongo %s", err.Error())
	}
	defer r.Close()

	appConfig := config.MustRead(r.Conf.Path)
	modelhelper.Initialize(appConfig.Mongo)
	defer modelhelper.Close()

	Convey("while testing channel participants", t, func() {

		Convey("First Create Users and initiate conversation", func() {
			var err error
			ownerAccount := models.NewAccount()
			ownerAccount.OldId = AccountOldId.Hex()
			ownerAccount, err = rest.CreateAccount(ownerAccount)
			So(err, ShouldBeNil)
			So(ownerAccount, ShouldNotBeNil)

			secondAccount := models.NewAccount()
			secondAccount.OldId = AccountOldId2.Hex()
			secondAccount, err = rest.CreateAccount(secondAccount)
			So(err, ShouldBeNil)
			So(secondAccount, ShouldNotBeNil)

			thirdAccount := models.NewAccount()
			thirdAccount.OldId = AccountOldId3.Hex()
			thirdAccount, err = rest.CreateAccount(thirdAccount)
			So(err, ShouldBeNil)
			So(thirdAccount, ShouldNotBeNil)

			forthAccount := models.NewAccount()
			forthAccount.OldId = AccountOldId4.Hex()
			forthAccount, err = rest.CreateAccount(forthAccount)
			So(err, ShouldBeNil)
			So(forthAccount, ShouldNotBeNil)

			CreatePrivateChannelUser("devrim")

			groupName := "testgroup" + strconv.FormatInt(rand.Int63(), 10)

			pmr := models.PrivateChannelRequest{}

			pmr.AccountId = ownerAccount.Id

			pmr.Body = "new conversation"
			pmr.GroupName = groupName
			pmr.Recipients = []string{"devrim"}

			channelContainer, err := rest.SendPrivateChannelRequest(pmr)
			So(err, ShouldBeNil)
			So(channelContainer, ShouldNotBeNil)

			Convey("First user should be able to add second and third users to conversation", func() {
				_, err = rest.AddChannelParticipant(channelContainer.Channel.Id, ownerAccount.Id, secondAccount.Id, thirdAccount.Id)
				So(err, ShouldBeNil)
				participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerAccount.Id)
				So(err, ShouldBeNil)
				So(participants, ShouldNotBeNil)
				// it is four because first user is "devrim" here
				So(len(participants), ShouldEqual, 4)

				Convey("First user should not be able to re-add second participant", func() {
					_, err = rest.AddChannelParticipant(channelContainer.Channel.Id, ownerAccount.Id, secondAccount.Id)
					So(err, ShouldBeNil)

					participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerAccount.Id)
					So(err, ShouldBeNil)
					So(participants, ShouldNotBeNil)
					So(len(participants), ShouldEqual, 4)
				})

				Convey("Second user should be able to leave conversation", func() {
					_, err = rest.DeleteChannelParticipant(channelContainer.Channel.Id, secondAccount.Id, secondAccount.Id)
					So(err, ShouldBeNil)

					participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerAccount.Id)
					So(err, ShouldBeNil)
					So(participants, ShouldNotBeNil)
					So(len(participants), ShouldEqual, 3)

					Convey("A user who is not participant of a conversation should not be able to add another user to the conversation", func() {
						_, err = rest.AddChannelParticipant(channelContainer.Channel.Id, secondAccount.Id, forthAccount.Id)
						So(err, ShouldNotBeNil)

						participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerAccount.Id)
						So(err, ShouldBeNil)
						So(participants, ShouldNotBeNil)
						So(len(participants), ShouldEqual, 3)
					})
				})

				Convey("Channel owner should be able to kick another conversation participant", func() {
					_, err = rest.DeleteChannelParticipant(channelContainer.Channel.Id, ownerAccount.Id, secondAccount.Id)
					So(err, ShouldBeNil)

					participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerAccount.Id)
					So(err, ShouldBeNil)
					So(participants, ShouldNotBeNil)
					So(len(participants), ShouldEqual, 3)
				})

				Convey("when a user is blocked", func() {
					_, err = rest.BlockChannelParticipant(channelContainer.Channel.Id, ownerAccount.Id, secondAccount.Id)
					So(err, ShouldBeNil)

					Convey("it should not be in channel participant list", func() {
						participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerAccount.Id)
						So(err, ShouldBeNil)
						So(participants, ShouldNotBeNil)
						So(len(participants), ShouldEqual, 3)
					})

					Convey("should not be able to add it back", func() {
						_, err = rest.AddChannelParticipant(channelContainer.Channel.Id, ownerAccount.Id, secondAccount.Id)
						So(err, ShouldNotBeNil)
					})

					Convey("should be able to unblock", func() {
						_, err = rest.UnblockChannelParticipant(channelContainer.Channel.Id, ownerAccount.Id, secondAccount.Id)
						So(err, ShouldBeNil)

						Convey("it should not be in channel participant list still", func() {
							participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerAccount.Id)
							So(err, ShouldBeNil)
							So(participants, ShouldNotBeNil)
							So(len(participants), ShouldEqual, 3)
						})

						Convey("when we add the same user as participant", func() {
							_, err = rest.AddChannelParticipant(channelContainer.Channel.Id, ownerAccount.Id, secondAccount.Id, thirdAccount.Id)
							So(err, ShouldBeNil)

							Convey("it should be in channel participant list", func() {
								participants, err := rest.ListChannelParticipants(channelContainer.Channel.Id, ownerAccount.Id)
								So(err, ShouldBeNil)
								So(participants, ShouldNotBeNil)
								So(len(participants), ShouldEqual, 4)
							})
						})
					})
				})

				Convey("Second user should not be able to kick another conversation participant", func() {
					_, err = rest.DeleteChannelParticipant(channelContainer.Channel.Id, secondAccount.Id, thirdAccount.Id)
					So(err, ShouldNotBeNil)
				})
			})

			// TODO Until we find a better way for handling async stuff, this test is skipped. Instead of sleep, we should use some
			// timeouts for testing these kind of stuff.
			SkipConvey("All private messages must be deleted when all participant users leave the channel", func() {
				account := models.NewAccount()
				err = account.ByNick("devrim")
				So(err, ShouldBeNil)

				_, err = rest.DeleteChannelParticipant(channelContainer.Channel.Id, account.Id, account.Id)
				So(err, ShouldBeNil)

				_, err = rest.DeleteChannelParticipant(channelContainer.Channel.Id, ownerAccount.Id, ownerAccount.Id)
				So(err, ShouldBeNil)

				time.Sleep(1 * time.Second)

				testChannel := models.NewChannel()
				err := testChannel.ById(channelContainer.Channel.Id)
				So(err, ShouldEqual, bongo.RecordNotFound)

				testChannelList := models.NewChannelMessageList()
				err = bongo.B.Unscoped().Where("channel_id = ?", channelContainer.Channel.Id).Find(testChannelList).Error
				So(err, ShouldEqual, bongo.RecordNotFound)

				testMessage := models.NewChannelMessage()
				err = bongo.B.Unscoped().Where("initial_channel_id = ?", channelContainer.Channel.Id).Find(testMessage).Error
				So(err, ShouldEqual, bongo.RecordNotFound)
			})
		})
	})
}
<|endoftext|>


<commit_before>package instana

import (
	"strconv"
	"strings"

	ot "github.com/opentracing/opentracing-go"
)

type textMapPropagator struct {
	tracer *tracerS
}

// Instana header constants
const (
	// FieldT Trace ID header
	FieldT = "x-instana-t"
	// FieldS Span ID header
	FieldS = "x-instana-s"
	// FieldL Level header
	FieldL = "x-instana-l"
	// FieldB OT Baggage header
	FieldB     = "x-instana-b-"
	fieldCount = 2
)

func (r *textMapPropagator) inject(spanContext ot.SpanContext, opaqueCarrier interface{}) error {
	sc, ok := spanContext.(SpanContext)
	if !ok {
		return ot.ErrInvalidSpanContext
	}

	roCarrier, ok := opaqueCarrier.(ot.TextMapReader)
	if !ok {
		return ot.ErrInvalidCarrier
	}

	// Handle pre-existing case-sensitive keys
	var (
		exstfieldT = FieldT
		exstfieldS = FieldS
		exstfieldL = FieldL
		exstfieldB = FieldB
	)

	roCarrier.ForeachKey(func(k, v string) error {
		switch strings.ToLower(k) {
		case FieldT:
			exstfieldT = k
		case FieldS:
			exstfieldS = k
		case FieldL:
			exstfieldL = k
		default:
			if strings.HasPrefix(strings.ToLower(k), FieldB) {
				exstfieldB = string([]rune(k)[0:len(FieldB)])
			}
		}

		return nil
	})

	carrier, ok := opaqueCarrier.(ot.TextMapWriter)
	if !ok {
		return ot.ErrInvalidCarrier
	}

	if instanaID, err := ID2Header(sc.TraceID); err == nil {
		carrier.Set(exstfieldT, instanaID)
	} else {
		log.debug(err)
	}
	if instanaID, err := ID2Header(sc.SpanID); err == nil {
		carrier.Set(exstfieldS, instanaID)
	} else {
		log.debug(err)
	}
	carrier.Set(exstfieldL, strconv.Itoa(1))

	for k, v := range sc.Baggage {
		carrier.Set(exstfieldB+k, v)
	}

	return nil
}

func (r *textMapPropagator) extract(opaqueCarrier interface{}) (ot.SpanContext, error) {
	carrier, ok := opaqueCarrier.(ot.TextMapReader)
	if !ok {
		return nil, ot.ErrInvalidCarrier
	}

	fieldCount := 0
	var traceID, spanID int64
	var err error
	baggage := make(map[string]string)
	err = carrier.ForeachKey(func(k, v string) error {
		switch strings.ToLower(k) {
		case FieldT:
			fieldCount++
			traceID, err = Header2ID(v)
			if err != nil {
				return ot.ErrSpanContextCorrupted
			}
		case FieldS:
			fieldCount++
			spanID, err = Header2ID(v)
			if err != nil {
				return ot.ErrSpanContextCorrupted
			}
		default:
			lk := strings.ToLower(k)

			if strings.HasPrefix(lk, FieldB) {
				baggage[strings.TrimPrefix(lk, FieldB)] = v
			}
		}

		return nil
	})

	return r.finishExtract(err, fieldCount, traceID, spanID, baggage)
}

func (r *textMapPropagator) finishExtract(err error,
	fieldCount int,
	traceID int64,
	spanID int64,
	baggage map[string]string) (ot.SpanContext, error) {
	if err != nil {
		return nil, err
	}

	if fieldCount < fieldCount {
		if fieldCount == 0 {
			return nil, ot.ErrSpanContextNotFound
		}

		return nil, ot.ErrSpanContextCorrupted
	}

	return SpanContext{
		TraceID: traceID,
		SpanID:  spanID,
		Sampled: false, //TODO: add configurable sampling strategy
		Baggage: baggage,
	}, nil
}
<commit_msg>Delete pre-existing header keys<commit_after>package instana

import (
	"net/http"
	"strconv"
	"strings"

	ot "github.com/opentracing/opentracing-go"
)

type textMapPropagator struct {
	tracer *tracerS
}

// Instana header constants
const (
	// FieldT Trace ID header
	FieldT = "x-instana-t"
	// FieldS Span ID header
	FieldS = "x-instana-s"
	// FieldL Level header
	FieldL = "x-instana-l"
	// FieldB OT Baggage header
	FieldB     = "x-instana-b-"
	fieldCount = 2
)

func (r *textMapPropagator) inject(spanContext ot.SpanContext, opaqueCarrier interface{}) error {
	sc, ok := spanContext.(SpanContext)
	if !ok {
		return ot.ErrInvalidSpanContext
	}

	roCarrier, ok := opaqueCarrier.(ot.TextMapReader)
	if !ok {
		return ot.ErrInvalidCarrier
	}

	// Handle pre-existing case-sensitive keys
	var (
		exstfieldT = FieldT
		exstfieldS = FieldS
		exstfieldL = FieldL
		exstfieldB = FieldB
	)

	roCarrier.ForeachKey(func(k, v string) error {
		switch strings.ToLower(k) {
		case FieldT:
			exstfieldT = k
		case FieldS:
			exstfieldS = k
		case FieldL:
			exstfieldL = k
		default:
			if strings.HasPrefix(strings.ToLower(k), FieldB) {
				exstfieldB = string([]rune(k)[0:len(FieldB)])
			}
		}
		return nil
	})

	carrier, ok := opaqueCarrier.(ot.TextMapWriter)
	if !ok {
		return ot.ErrInvalidCarrier
	}

	hhcarrier, ok := opaqueCarrier.(ot.HTTPHeadersCarrier)
	if ok {
		// If http.Headers has pre-existing keys, calling Set() like we do
		// below will just append to those existing values and break context
		// propagation.  So defend against that case, we delete any pre-existing
		// keys entirely first.
		y := http.Header(hhcarrier)
		y.Del(exstfieldT)
		y.Del(exstfieldS)
		y.Del(exstfieldL)

		for key := range y {
			if strings.HasPrefix(strings.ToLower(key), FieldB) {
				y.Del(key)
			}
		}
	}

	if instanaTID, err := ID2Header(sc.TraceID); err == nil {
		carrier.Set(exstfieldT, instanaTID)
	} else {
		log.debug(err)
	}
	if instanaSID, err := ID2Header(sc.SpanID); err == nil {
		carrier.Set(exstfieldS, instanaSID)
	} else {
		log.debug(err)
	}
	carrier.Set(exstfieldL, strconv.Itoa(1))

	for k, v := range sc.Baggage {
		carrier.Set(exstfieldB+k, v)
	}
	return nil
}

func (r *textMapPropagator) extract(opaqueCarrier interface{}) (ot.SpanContext, error) {
	carrier, ok := opaqueCarrier.(ot.TextMapReader)
	if !ok {
		return nil, ot.ErrInvalidCarrier
	}

	fieldCount := 0
	var traceID, spanID int64
	var err error
	baggage := make(map[string]string)
	err = carrier.ForeachKey(func(k, v string) error {
		switch strings.ToLower(k) {
		case FieldT:
			fieldCount++
			traceID, err = Header2ID(v)
			if err != nil {
				return ot.ErrSpanContextCorrupted
			}
		case FieldS:
			fieldCount++
			spanID, err = Header2ID(v)
			if err != nil {
				return ot.ErrSpanContextCorrupted
			}
		default:
			lk := strings.ToLower(k)

			if strings.HasPrefix(lk, FieldB) {
				baggage[strings.TrimPrefix(lk, FieldB)] = v
			}
		}

		return nil
	})

	return r.finishExtract(err, fieldCount, traceID, spanID, baggage)
}

func (r *textMapPropagator) finishExtract(err error,
	fieldCount int,
	traceID int64,
	spanID int64,
	baggage map[string]string) (ot.SpanContext, error) {
	if err != nil {
		return nil, err
	}

	if fieldCount < 2 {
		if fieldCount == 0 {
			return nil, ot.ErrSpanContextNotFound
		}

		return nil, ot.ErrSpanContextCorrupted
	}

	return SpanContext{
		TraceID: traceID,
		SpanID:  spanID,
		Sampled: false,
		Baggage: baggage,
	}, nil
}
<|endoftext|>


<commit_before>package proxy

import (
	"encoding/binary"
	"fmt"
	"io"
	"net"
	"os"

	"github.com/DimShadoWWW/power-pg/common"
)

var (
	connid = uint64(0)
)

// Start function
func Start(localHost, remoteHost *string, powerCallback common.Callback) {
	fmt.Printf("Proxying from %v to %v\n", localHost, remoteHost)

	localAddr, remoteAddr := getResolvedAddresses(localHost, remoteHost)
	listener := getListener(localAddr)

	for {
		conn, err := listener.AcceptTCP()
		if err != nil {
			fmt.Printf("Failed to accept connection '%s'\n", err)
			continue
		}
		connid++

		p := &proxy{
			lconn:  *conn,
			laddr:  localAddr,
			raddr:  remoteAddr,
			erred:  false,
			errsig: make(chan bool),
			prefix: fmt.Sprintf("Connection #%03d ", connid),
		}
		go p.start(powerCallback)
	}
}

func getResolvedAddresses(localHost, remoteHost *string) (*net.TCPAddr, *net.TCPAddr) {
	laddr, err := net.ResolveTCPAddr("tcp", *localHost)
	check(err)
	raddr, err := net.ResolveTCPAddr("tcp", *remoteHost)
	check(err)
	return laddr, raddr
}

func getListener(addr *net.TCPAddr) *net.TCPListener {
	listener, err := net.ListenTCP("tcp", addr)
	check(err)
	return listener
}

type proxy struct {
	sentBytes     uint64
	receivedBytes uint64
	laddr, raddr  *net.TCPAddr
	lconn, rconn  net.TCPConn
	erred         bool
	errsig        chan bool
	prefix        string
}

func (p *proxy) err(s string, err error) {
	if p.erred {
		return
	}
	if err != io.EOF {
		warn(p.prefix+s, err)
	}
	p.errsig <- true
	p.erred = true
}

func (p *proxy) start(powerCallback common.Callback) {
	// defer p.lconn.conn.Close()
	//connect to remote
	rconn, err := net.DialTCP("tcp", nil, p.raddr)
	if err != nil {
		p.err("Remote connection failed: %s", err)
		return
	}
	p.rconn = *rconn
	// p.rconn.alive = true
	// defer p.rconn.conn.Close()
	//bidirectional copy
	go p.pipe(p.lconn, p.rconn, powerCallback)
	go p.pipe(p.rconn, p.lconn, nil)
	//wait for close...
	<-p.errsig
}

func (p *proxy) pipe(src, dst net.TCPConn, powerCallback common.Callback) {
	//data direction
	islocal := src == p.lconn
	//directional copy (64k buffer)
	buff := make(readBuf, 0xffff)
	newPacket := true
	var msg string
	remainingBytes := 0
	if islocal {
		for {
			var r readBuf
			n, err := src.Read(buff)
			if err != nil {
				p.err("Read failed '%s'\n", err)
				return
			}
			fmt.Printf("Readed bytes: %d\n", n)
			b := buff[:n]
			//write out result
			n, err = dst.Write(b)
			if err != nil {
				p.err("Write failed '%s'\n", err)
				return
			}

			r = buff[:n]
			// fmt.Printf("%#v", string(buff[:n]))
			fmt.Printf("Remaining bytes: %d\n", remainingBytes)
			if remainingBytes > 0 {
				if remainingBytes <= n {
					newPacket = true
					msg = msg + string(r.next(remainingBytes))
					remainingBytes = n - remainingBytes
					fmt.Println("msg: ", string(msg))
				} else {
					newPacket = false
					msg = msg + string(r.next(remainingBytes))
					remainingBytes = remainingBytes - n
				}
			}
		NewP:
			if newPacket {
				remainingBytes = 0
				newPacket = false
				msg = ""
				t := r.byte()
				n = n - 1
				fmt.Println("t: ", t)
				switch t {
				case query:
					// c.rxReadyForQuery(r)
					remainingBytes = r.int32()
					remainingBytes = remainingBytes - 4
					if remainingBytes > 0 {
						if remainingBytes <= n {
							newPacket = true
							msg = msg + string(r.next(remainingBytes))
							remainingBytes = n - remainingBytes
							fmt.Println(msg)
							goto NewP
						} else {
							newPacket = false
							msg = msg + string(r.next(remainingBytes))
							remainingBytes = remainingBytes - n
						}
						fmt.Printf("Remaining bytes: %d\n", remainingBytes)
					}
				// case rowDescription:
				// case dataRow:
				// case bindComplete:
				// case commandComplete:
				// 	commandTag = CommandTag(r.readCString())
				default:
					// if e := c.processContextFreeMsg(t, r); e != nil && softErr == nil {
					// 	softErr = e
					// }
				}
			}
			// r = append(r, buff[:]...)

			// fmt.Println("a")
			// c := src
			// c.reader = bufio.NewReader(src.conn)
			// c.mr.reader = c.reader
			//
			// var t byte
			// var r *msgReader
			// fmt.Println("b")
			// t, r, err := c.rxMsg()
			// fmt.Println("c")
			// if err != nil {
			// 	fmt.Println(err)
			// 	return
			// }
			// fmt.Println("d")
			//
			// fmt.Printf("t: %#v\n", t)

			// n, err := src.Read(buff)
			// if err != nil {
			// 	p.err("Read failed '%s'\n", err)
			// 	return
			// }
			// b := buff[:n]
			// //show output
			//
			//
			// b = getModifiedBuffer(b, powerCallback)
			// n, err = dst.Write(b)
			// //
			// //write out result
			// n, err = dst.Write(b)
			// if err != nil {
			// 	p.err("Write failed '%s'\n", err)
			// 	return
			// }
		}
	} else {
		for {
			n, err := src.Read(buff)
			if err != nil {
				p.err("Read failed '%s'\n", err)
				return
			}
			b := buff[:n]
			//write out result
			n, err = dst.Write(b)
			if err != nil {
				p.err("Write failed '%s'\n", err)
				return
			}
			if err != nil {
				p.err("Write failed '%s'\n", err)
				return
			}
		}
	}
}

func getModifiedBuffer(buffer []byte, powerCallback common.Callback) []byte {
	if powerCallback == nil || len(buffer) < 1 || string(buffer[0]) != "Q" || string(buffer[5:11]) != "power:" {
		return buffer
	}
	query := powerCallback(string(buffer[5:]))
	return makeMessage(query)
}

func makeMessage(query string) []byte {
	queryArray := make([]byte, 0, 6+len(query))
	queryArray = append(queryArray, 'Q', 0, 0, 0, 0)
	queryArray = append(queryArray, query...)
	queryArray = append(queryArray, 0)
	binary.BigEndian.PutUint32(queryArray[1:], uint32(len(queryArray)-1))
	return queryArray

}

func check(err error) {
	if err != nil {
		warn(err.Error())
		os.Exit(1)
	}
}

func warn(f string, args ...interface{}) {
	fmt.Printf(f+"\n", args...)
}
<commit_msg>Update<commit_after>package proxy

import (
	"encoding/binary"
	"fmt"
	"io"
	"net"
	"os"

	"github.com/DimShadoWWW/power-pg/common"
)

var (
	connid = uint64(0)
)

// Start function
func Start(localHost, remoteHost *string, powerCallback common.Callback) {
	fmt.Printf("Proxying from %v to %v\n", localHost, remoteHost)

	localAddr, remoteAddr := getResolvedAddresses(localHost, remoteHost)
	listener := getListener(localAddr)

	for {
		conn, err := listener.AcceptTCP()
		if err != nil {
			fmt.Printf("Failed to accept connection '%s'\n", err)
			continue
		}
		connid++

		p := &proxy{
			lconn:  *conn,
			laddr:  localAddr,
			raddr:  remoteAddr,
			erred:  false,
			errsig: make(chan bool),
			prefix: fmt.Sprintf("Connection #%03d ", connid),
		}
		go p.start(powerCallback)
	}
}

func getResolvedAddresses(localHost, remoteHost *string) (*net.TCPAddr, *net.TCPAddr) {
	laddr, err := net.ResolveTCPAddr("tcp", *localHost)
	check(err)
	raddr, err := net.ResolveTCPAddr("tcp", *remoteHost)
	check(err)
	return laddr, raddr
}

func getListener(addr *net.TCPAddr) *net.TCPListener {
	listener, err := net.ListenTCP("tcp", addr)
	check(err)
	return listener
}

type proxy struct {
	sentBytes     uint64
	receivedBytes uint64
	laddr, raddr  *net.TCPAddr
	lconn, rconn  net.TCPConn
	erred         bool
	errsig        chan bool
	prefix        string
}

func (p *proxy) err(s string, err error) {
	if p.erred {
		return
	}
	if err != io.EOF {
		warn(p.prefix+s, err)
	}
	p.errsig <- true
	p.erred = true
}

func (p *proxy) start(powerCallback common.Callback) {
	// defer p.lconn.conn.Close()
	//connect to remote
	rconn, err := net.DialTCP("tcp", nil, p.raddr)
	if err != nil {
		p.err("Remote connection failed: %s", err)
		return
	}
	p.rconn = *rconn
	// p.rconn.alive = true
	// defer p.rconn.conn.Close()
	//bidirectional copy
	go p.pipe(p.lconn, p.rconn, powerCallback)
	go p.pipe(p.rconn, p.lconn, nil)
	//wait for close...
	<-p.errsig
}

func (p *proxy) pipe(src, dst net.TCPConn, powerCallback common.Callback) {
	//data direction
	islocal := src == p.lconn
	//directional copy (64k buffer)
	buff := make(readBuf, 0xffff)
	newPacket := true
	var msg string
	remainingBytes := 0
	if islocal {
		for {
			var r readBuf
			n, err := src.Read(buff)
			if err != nil {
				p.err("Read failed '%s'\n", err)
				return
			}
			fmt.Printf("Readed bytes: %d\n", n)
			b := buff[:n]
			//write out result
			n, err = dst.Write(b)
			if err != nil {
				p.err("Write failed '%s'\n", err)
				return
			}

			r = buff[:n]
			// fmt.Printf("%#v", string(buff[:n]))
			fmt.Printf("Remaining bytes: %d\n", remainingBytes)
			if remainingBytes > 0 {
				if remainingBytes <= n {
					fmt.Println("1")
					newPacket = true
					msg = msg + string(r.next(remainingBytes))
					remainingBytes = n - remainingBytes
					fmt.Println("msg: ", string(msg))
				} else {
					fmt.Println("2")
					newPacket = false
					msg = msg + string(r.next(remainingBytes))
					remainingBytes = remainingBytes - n
				}
			}
			fmt.Println("3")
		NewP:
			fmt.Println("4")
			if newPacket {
				fmt.Println("5")
				remainingBytes = 0
				newPacket = false
				msg = ""
				t := r.byte()
				n = n - 1
				fmt.Println("t: ", t)
				switch t {
				case query:
					// c.rxReadyForQuery(r)
					remainingBytes = r.int32()
					remainingBytes = remainingBytes - 4
					if remainingBytes > 0 {
						if remainingBytes <= n {
							newPacket = true
							msg = msg + string(r.next(remainingBytes))
							remainingBytes = n - remainingBytes
							fmt.Println(msg)
							goto NewP
						} else {
							newPacket = false
							msg = msg + string(r.next(remainingBytes))
							remainingBytes = remainingBytes - n
						}
						fmt.Printf("Remaining bytes: %d\n", remainingBytes)
					}
				// case rowDescription:
				// case dataRow:
				// case bindComplete:
				// case commandComplete:
				// 	commandTag = CommandTag(r.readCString())
				default:
					// if e := c.processContextFreeMsg(t, r); e != nil && softErr == nil {
					// 	softErr = e
					// }
				}
			}
			// r = append(r, buff[:]...)

			// fmt.Println("a")
			// c := src
			// c.reader = bufio.NewReader(src.conn)
			// c.mr.reader = c.reader
			//
			// var t byte
			// var r *msgReader
			// fmt.Println("b")
			// t, r, err := c.rxMsg()
			// fmt.Println("c")
			// if err != nil {
			// 	fmt.Println(err)
			// 	return
			// }
			// fmt.Println("d")
			//
			// fmt.Printf("t: %#v\n", t)

			// n, err := src.Read(buff)
			// if err != nil {
			// 	p.err("Read failed '%s'\n", err)
			// 	return
			// }
			// b := buff[:n]
			// //show output
			//
			//
			// b = getModifiedBuffer(b, powerCallback)
			// n, err = dst.Write(b)
			// //
			// //write out result
			// n, err = dst.Write(b)
			// if err != nil {
			// 	p.err("Write failed '%s'\n", err)
			// 	return
			// }
		}
	} else {
		for {
			n, err := src.Read(buff)
			if err != nil {
				p.err("Read failed '%s'\n", err)
				return
			}
			b := buff[:n]
			//write out result
			n, err = dst.Write(b)
			if err != nil {
				p.err("Write failed '%s'\n", err)
				return
			}
			if err != nil {
				p.err("Write failed '%s'\n", err)
				return
			}
		}
	}
}

func getModifiedBuffer(buffer []byte, powerCallback common.Callback) []byte {
	if powerCallback == nil || len(buffer) < 1 || string(buffer[0]) != "Q" || string(buffer[5:11]) != "power:" {
		return buffer
	}
	query := powerCallback(string(buffer[5:]))
	return makeMessage(query)
}

func makeMessage(query string) []byte {
	queryArray := make([]byte, 0, 6+len(query))
	queryArray = append(queryArray, 'Q', 0, 0, 0, 0)
	queryArray = append(queryArray, query...)
	queryArray = append(queryArray, 0)
	binary.BigEndian.PutUint32(queryArray[1:], uint32(len(queryArray)-1))
	return queryArray

}

func check(err error) {
	if err != nil {
		warn(err.Error())
		os.Exit(1)
	}
}

func warn(f string, args ...interface{}) {
	fmt.Printf(f+"\n", args...)
}
<|endoftext|>


<commit_before>package proxy

import (
	"strings"

	log "github.com/Sirupsen/logrus"
)

// Proxy defines proxy rules for a route
type Proxy struct {
	PreserveHostHeader          bool     `bson:"preserve_host_header" json:"preserve_host_header"`
	ListenPath                  string   `bson:"listen_path" json:"listen_path" valid:"required"`
	TargetURL                   string   `bson:"target_url" json:"target_url" valid:"url,required"`
	StripListenPath             bool     `bson:"strip_listen_path" json:"strip_listen_path"`
	EnableLoadBalancing         bool     `bson:"enable_load_balancing" json:"enable_load_balancing"`
	TargetList                  []string `bson:"target_list" json:"target_list"`
	CheckHostAgainstUptimeTests bool     `bson:"check_host_against_uptime_tests" json:"check_host_against_uptime_tests"`
	Methods                     []string `bson:"methods" json:"methods"`
}

//Validate validates proxy data
func Validate(proxy Proxy) bool {
	if proxy.ListenPath == "" {
		log.Error("Listen path is empty")
		return false
	}

	if strings.Contains(proxy.ListenPath, " ") {
		log.Error("Listen path contains spaces, is invalid")
		return false
	}

	return true
}
<commit_msg>Added append listen path to the proxy definition<commit_after>package proxy

import (
	"strings"

	log "github.com/Sirupsen/logrus"
)

// Proxy defines proxy rules for a route
type Proxy struct {
	PreserveHostHeader          bool     `bson:"preserve_host_header" json:"preserve_host_header"`
	ListenPath                  string   `bson:"listen_path" json:"listen_path" valid:"required"`
	TargetURL                   string   `bson:"target_url" json:"target_url" valid:"url,required"`
	StripListenPath             bool     `bson:"strip_listen_path" json:"strip_listen_path"`
	AppendListenPath            bool     `bson:"append_listen_path" json:"append_listen_path"`
	EnableLoadBalancing         bool     `bson:"enable_load_balancing" json:"enable_load_balancing"`
	TargetList                  []string `bson:"target_list" json:"target_list"`
	CheckHostAgainstUptimeTests bool     `bson:"check_host_against_uptime_tests" json:"check_host_against_uptime_tests"`
	Methods                     []string `bson:"methods" json:"methods"`
}

//Validate validates proxy data
func Validate(proxy Proxy) bool {
	if proxy.ListenPath == "" {
		log.Error("Listen path is empty")
		return false
	}

	if strings.Contains(proxy.ListenPath, " ") {
		log.Error("Listen path contains spaces, is invalid")
		return false
	}

	return true
}
<|endoftext|>


<commit_before>// Package assert provides type-safe assertions with clean error messages.
package assert

import (
	"bytes"
	"fmt"
	"reflect"
	"strconv"
	"strings"
	"testing"

	"github.com/alecthomas/repr"
	"github.com/hexops/gotextdiff"
	"github.com/hexops/gotextdiff/myers"
)

func objectsAreEqual(expected, actual interface{}) bool {
	if expected == nil || actual == nil {
		return expected == actual
	}

	exp, ok := expected.([]byte)
	if !ok {
		return reflect.DeepEqual(expected, actual)
	}

	act, ok := actual.([]byte)
	if !ok {
		return false
	}
	if exp == nil || act == nil {
		return exp == nil && act == nil
	}
	return bytes.Equal(exp, act)
}

// Compare two values for equality and return true or false.
func Compare[T any](t testing.TB, x, y T) bool {
	return objectsAreEqual(x, y)
}

// Equal asserts that "expected" and "actual" are equal.
//
// If they are not, a diff of the Go representation of the values will be displayed.
func Equal[T any](t testing.TB, expected, actual T, msgAndArgs ...interface{}) {
	if objectsAreEqual(expected, actual) {
		return
	}
	t.Helper()
	msg := formatMsgAndArgs("Expected values to be equal:", msgAndArgs...)
	t.Fatalf("%s\n%s", msg, diff(expected, actual))
}

// NotEqual asserts that "expected" is not equal to "actual".
//
// If they are equal the expected value will be displayed.
func NotEqual[T any](t testing.TB, expected, actual T, msgAndArgs ...interface{}) {
	if !objectsAreEqual(expected, actual) {
		return
	}
	t.Helper()
	msg := formatMsgAndArgs("Expected values to not be equal but both were:", msgAndArgs...)
	t.Fatalf("%s\n%s", msg, repr.String(expected, repr.Indent("  ")))
}

// Contains asserts that "haystack" contains "needle".
func Contains(t testing.TB, haystack string, needle string, msgAndArgs ...interface{}) {
	if strings.Contains(haystack, needle) {
		return
	}
	t.Helper()
	msg := formatMsgAndArgs("Haystack does not contain needle.", msgAndArgs...)
	t.Fatalf("%s\nNeedle: %q\nHaystack: %q\n", msg, needle, haystack)
}

// NotContains asserts that "haystack" does not contain "needle".
func NotContains(t testing.TB, haystack string, needle string, msgAndArgs ...interface{}) {
	if !strings.Contains(haystack, needle) {
		return
	}
	t.Helper()
	msg := formatMsgAndArgs("Haystack should not contain needle.", msgAndArgs...)
	quotedHaystack, quotedNeedle, positions := needlePosition(haystack, needle)
	t.Fatalf("%s\nNeedle: %s\nHaystack: %s\n          %s\n", msg, quotedNeedle, quotedHaystack, positions)
}

// Zero asserts that a value is its zero value.
func Zero[T any](t testing.TB, value T, msgAndArgs ...interface{}) {
	var zero T
	if objectsAreEqual(value, zero) {
		return
	}
	val := reflect.ValueOf(value)
	if (val.Kind() == reflect.Slice || val.Kind() == reflect.Map || val.Kind() == reflect.Array) && val.Len() == 0 {
		return
	}
	t.Helper()
	msg := formatMsgAndArgs("Expected a zero value but got:", msgAndArgs...)
	t.Fatalf("%s\n%s", msg, repr.String(value, repr.Indent("  ")))
}

// NotZero asserts that a value is not its zero value.
func NotZero[T any](t testing.TB, value T, msgAndArgs ...interface{}) {
	var zero T
	if !objectsAreEqual(value, zero) {
		val := reflect.ValueOf(value)
		if !((val.Kind() == reflect.Slice || val.Kind() == reflect.Map || val.Kind() == reflect.Array) && val.Len() == 0) {
			return
		}
	}
	t.Helper()
	msg := formatMsgAndArgs("Did not expect the zero value:", msgAndArgs...)
	t.Fatalf("%s\n%s", msg, repr.String(value))
}

// EqualError asserts that either an error is non-nil and that its message is what is expected,
// or that error is nil if the expected message is empty.
func EqualError(t testing.TB, err error, errString string, msgAndArgs ...interface{}) {
	if err == nil && errString == "" {
		return
	}
	t.Helper()
	if err == nil {
		t.Fatal(formatMsgAndArgs("Expected an error", msgAndArgs...))
	}
	if err.Error() != errString {
		msg := formatMsgAndArgs("Error message not as expected:", msgAndArgs...)
		t.Fatalf("%s\n%s", msg, diff(errString, err.Error()))
	}
}

// Error asserts that an error is not nil.
func Error(t testing.TB, err error, msgAndArgs ...interface{}) {
	if err != nil {
		return
	}
	t.Helper()
	t.Fatal(formatMsgAndArgs("Expected an error", msgAndArgs...))
}

// NoError asserts that an error is nil.
func NoError(t testing.TB, err error, msgAndArgs ...interface{}) {
	if err == nil {
		return
	}
	t.Helper()
	msg := formatMsgAndArgs("Did not expect an error but got:", msgAndArgs...)
	t.Fatalf("%s\n%s", msg, err)
}

// True asserts that an expression is true.
func True(t testing.TB, ok bool, msgAndArgs ...interface{}) {
	if ok {
		return
	}
	t.Helper()
	t.Fatal("Expected expression to be true")
}

// False asserts that an expression is false.
func False(t testing.TB, ok bool, msgAndArgs ...interface{}) {
	if !ok {
		return
	}
	t.Helper()
	t.Fatal("Expected expression to be false")
}

// Panics asserts that the given function panics.
func Panics(t testing.TB, fn func(), msgAndArgs ...interface{}) {
	t.Helper()
	defer func() {
		if recover() == nil {
			msg := formatMsgAndArgs("Expected function to panic", msgAndArgs...)
			t.Fatal(msg)
		}
	}()
	fn()
}

// NotPanics asserts that the given function does not panic.
func NotPanics(t testing.TB, fn func(), msgAndArgs ...interface{}) {
	t.Helper()
	defer func() {
		if err := recover(); err != nil {
			msg := formatMsgAndArgs("Expected function not to panic", msgAndArgs...)
			t.Fatalf("%s\nPanic: %v", msg, err)
		}
	}()
	fn()
}

func diff[T any](lhs, rhs T) string {
	var lhss, rhss string
	// Special case strings so we get nice diffs.
	if l, ok := any(lhs).(string); ok {
		lhss = l
		rhss = any(rhs).(string)
	} else {
		lhss = repr.String(lhs, repr.Indent("  ")) + "\n"
		rhss = repr.String(rhs, repr.Indent("  ")) + "\n"
	}
	edits := myers.ComputeEdits("a.txt", lhss, rhss)
	lines := strings.Split(fmt.Sprint(gotextdiff.ToUnified("expected.txt", "actual.txt", lhss, edits)), "\n")
	if len(lines) < 3 {
		return ""
	}
	return strings.Join(lines[3:], "\n")
}

func formatMsgAndArgs(dflt string, msgAndArgs ...interface{}) string {
	if len(msgAndArgs) == 0 {
		return dflt
	}
	return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...)
}

func needlePosition(haystack, needle string) (quotedHaystack, quotedNeedle, positions string) {
	quotedNeedle = strconv.Quote(needle)
	quotedNeedle = quotedNeedle[1 : len(quotedNeedle)-1]
	quotedHaystack = strconv.Quote(haystack)
	rawPositions := strings.ReplaceAll(quotedHaystack, quotedNeedle, strings.Repeat("^", len(quotedNeedle)))
	for _, rn := range rawPositions {
		if rn != '^' {
			positions += " "
		} else {
			positions += "^"
		}
	}
	return
}
<commit_msg>Log the given arguments when asserting true or false #5<commit_after>// Package assert provides type-safe assertions with clean error messages.
package assert

import (
	"bytes"
	"fmt"
	"reflect"
	"strconv"
	"strings"
	"testing"

	"github.com/alecthomas/repr"
	"github.com/hexops/gotextdiff"
	"github.com/hexops/gotextdiff/myers"
)

func objectsAreEqual(expected, actual interface{}) bool {
	if expected == nil || actual == nil {
		return expected == actual
	}

	exp, ok := expected.([]byte)
	if !ok {
		return reflect.DeepEqual(expected, actual)
	}

	act, ok := actual.([]byte)
	if !ok {
		return false
	}
	if exp == nil || act == nil {
		return exp == nil && act == nil
	}
	return bytes.Equal(exp, act)
}

// Compare two values for equality and return true or false.
func Compare[T any](t testing.TB, x, y T) bool {
	return objectsAreEqual(x, y)
}

// Equal asserts that "expected" and "actual" are equal.
//
// If they are not, a diff of the Go representation of the values will be displayed.
func Equal[T any](t testing.TB, expected, actual T, msgAndArgs ...interface{}) {
	if objectsAreEqual(expected, actual) {
		return
	}
	t.Helper()
	msg := formatMsgAndArgs("Expected values to be equal:", msgAndArgs...)
	t.Fatalf("%s\n%s", msg, diff(expected, actual))
}

// NotEqual asserts that "expected" is not equal to "actual".
//
// If they are equal the expected value will be displayed.
func NotEqual[T any](t testing.TB, expected, actual T, msgAndArgs ...interface{}) {
	if !objectsAreEqual(expected, actual) {
		return
	}
	t.Helper()
	msg := formatMsgAndArgs("Expected values to not be equal but both were:", msgAndArgs...)
	t.Fatalf("%s\n%s", msg, repr.String(expected, repr.Indent("  ")))
}

// Contains asserts that "haystack" contains "needle".
func Contains(t testing.TB, haystack string, needle string, msgAndArgs ...interface{}) {
	if strings.Contains(haystack, needle) {
		return
	}
	t.Helper()
	msg := formatMsgAndArgs("Haystack does not contain needle.", msgAndArgs...)
	t.Fatalf("%s\nNeedle: %q\nHaystack: %q\n", msg, needle, haystack)
}

// NotContains asserts that "haystack" does not contain "needle".
func NotContains(t testing.TB, haystack string, needle string, msgAndArgs ...interface{}) {
	if !strings.Contains(haystack, needle) {
		return
	}
	t.Helper()
	msg := formatMsgAndArgs("Haystack should not contain needle.", msgAndArgs...)
	quotedHaystack, quotedNeedle, positions := needlePosition(haystack, needle)
	t.Fatalf("%s\nNeedle: %s\nHaystack: %s\n          %s\n", msg, quotedNeedle, quotedHaystack, positions)
}

// Zero asserts that a value is its zero value.
func Zero[T any](t testing.TB, value T, msgAndArgs ...interface{}) {
	var zero T
	if objectsAreEqual(value, zero) {
		return
	}
	val := reflect.ValueOf(value)
	if (val.Kind() == reflect.Slice || val.Kind() == reflect.Map || val.Kind() == reflect.Array) && val.Len() == 0 {
		return
	}
	t.Helper()
	msg := formatMsgAndArgs("Expected a zero value but got:", msgAndArgs...)
	t.Fatalf("%s\n%s", msg, repr.String(value, repr.Indent("  ")))
}

// NotZero asserts that a value is not its zero value.
func NotZero[T any](t testing.TB, value T, msgAndArgs ...interface{}) {
	var zero T
	if !objectsAreEqual(value, zero) {
		val := reflect.ValueOf(value)
		if !((val.Kind() == reflect.Slice || val.Kind() == reflect.Map || val.Kind() == reflect.Array) && val.Len() == 0) {
			return
		}
	}
	t.Helper()
	msg := formatMsgAndArgs("Did not expect the zero value:", msgAndArgs...)
	t.Fatalf("%s\n%s", msg, repr.String(value))
}

// EqualError asserts that either an error is non-nil and that its message is what is expected,
// or that error is nil if the expected message is empty.
func EqualError(t testing.TB, err error, errString string, msgAndArgs ...interface{}) {
	if err == nil && errString == "" {
		return
	}
	t.Helper()
	if err == nil {
		t.Fatal(formatMsgAndArgs("Expected an error", msgAndArgs...))
	}
	if err.Error() != errString {
		msg := formatMsgAndArgs("Error message not as expected:", msgAndArgs...)
		t.Fatalf("%s\n%s", msg, diff(errString, err.Error()))
	}
}

// Error asserts that an error is not nil.
func Error(t testing.TB, err error, msgAndArgs ...interface{}) {
	if err != nil {
		return
	}
	t.Helper()
	t.Fatal(formatMsgAndArgs("Expected an error", msgAndArgs...))
}

// NoError asserts that an error is nil.
func NoError(t testing.TB, err error, msgAndArgs ...interface{}) {
	if err == nil {
		return
	}
	t.Helper()
	msg := formatMsgAndArgs("Did not expect an error but got:", msgAndArgs...)
	t.Fatalf("%s\n%s", msg, err)
}

// True asserts that an expression is true.
func True(t testing.TB, ok bool, msgAndArgs ...interface{}) {
	if ok {
		return
	}
	t.Helper()
	t.Fatal(formatMsgAndArgs("Expected expression to be true", msgAndArgs...))
}

// False asserts that an expression is false.
func False(t testing.TB, ok bool, msgAndArgs ...interface{}) {
	if !ok {
		return
	}
	t.Helper()
	t.Fatal(formatMsgAndArgs("Expected expression to be false", msgAndArgs...))
}

// Panics asserts that the given function panics.
func Panics(t testing.TB, fn func(), msgAndArgs ...interface{}) {
	t.Helper()
	defer func() {
		if recover() == nil {
			msg := formatMsgAndArgs("Expected function to panic", msgAndArgs...)
			t.Fatal(msg)
		}
	}()
	fn()
}

// NotPanics asserts that the given function does not panic.
func NotPanics(t testing.TB, fn func(), msgAndArgs ...interface{}) {
	t.Helper()
	defer func() {
		if err := recover(); err != nil {
			msg := formatMsgAndArgs("Expected function not to panic", msgAndArgs...)
			t.Fatalf("%s\nPanic: %v", msg, err)
		}
	}()
	fn()
}

func diff[T any](lhs, rhs T) string {
	var lhss, rhss string
	// Special case strings so we get nice diffs.
	if l, ok := any(lhs).(string); ok {
		lhss = l
		rhss = any(rhs).(string)
	} else {
		lhss = repr.String(lhs, repr.Indent("  ")) + "\n"
		rhss = repr.String(rhs, repr.Indent("  ")) + "\n"
	}
	edits := myers.ComputeEdits("a.txt", lhss, rhss)
	lines := strings.Split(fmt.Sprint(gotextdiff.ToUnified("expected.txt", "actual.txt", lhss, edits)), "\n")
	if len(lines) < 3 {
		return ""
	}
	return strings.Join(lines[3:], "\n")
}

func formatMsgAndArgs(dflt string, msgAndArgs ...interface{}) string {
	if len(msgAndArgs) == 0 {
		return dflt
	}
	return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...)
}

func needlePosition(haystack, needle string) (quotedHaystack, quotedNeedle, positions string) {
	quotedNeedle = strconv.Quote(needle)
	quotedNeedle = quotedNeedle[1 : len(quotedNeedle)-1]
	quotedHaystack = strconv.Quote(haystack)
	rawPositions := strings.ReplaceAll(quotedHaystack, quotedNeedle, strings.Repeat("^", len(quotedNeedle)))
	for _, rn := range rawPositions {
		if rn != '^' {
			positions += " "
		} else {
			positions += "^"
		}
	}
	return
}
<|endoftext|>


<commit_before>//
// Copyright © 2011-2014 Guy M. Allard
//
// 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 stompngo

import (
	"testing"
)

type supdata struct {
	v string
	s bool
}

var suptests = []supdata{
	{SPL_10, true},
	{SPL_11, true},
	{SPL_12, true},
	{"1.3", false},
	{"2.0", false},
	{"2.1", false},
}

/*
	Data Test: Frame Basic.
*/
func TestDataFrameBasic(t *testing.T) {
	t.Parallel()
	c := CONNECT
	h := Headers{"keya", "valuea"}
	s := "The Message Body"
	f := &Frame{Command: c, Headers: h, Body: []byte(s)}
	//
	if c != f.Command {
		t.Errorf("Command, expected: [%v], got [%v]\n", c, f.Command)
	}
	if !h.Compare(f.Headers) {
		t.Errorf("Headers, expected: [true], got [false], for [%v] [%v]\n", h, f.Headers)
	}
	if s != string(f.Body) {
		t.Errorf("Body string, expected: [%v], got [%v]\n", s, string(f.Body))
	}
}

/*
	Data Test: Message Basic.
*/
func TestDataMessageBasic(t *testing.T) {
	t.Parallel()
	f := CONNECT
	h := Headers{"keya", "valuea"}
	s := "The Message Body"
	m := &Message{Command: f, Headers: h, Body: []byte(s)}
	//
	if f != m.Command {
		t.Errorf("Command, expected: [%v], got [%v]\n", f, m.Command)
	}
	if !h.Compare(m.Headers) {
		t.Errorf("Headers, expected: [true], got [false], for [%v] [%v]\n", h, m.Headers)
	}
	if s != m.BodyString() {
		t.Errorf("Body string, expected: [%v], got [%v]\n", s, m.BodyString())
	}
}

/*
	Data Test: protocols.
*/
func TestDataprotocols(t *testing.T) {
	t.Parallel()
	l := SPL_10
	if !Supported(l) {
		t.Errorf("Expected: [true], got: [false] for protocol level %v\n", l)
	}
	l = SPL_11
	if !Supported(l) {
		t.Errorf("Expected: [true], got: [false] for protocol level %v\n", l)
	}
	l = SPL_12
	if !Supported(l) {
		t.Errorf("Expected: [true], got: [false] for protocol level %v\n", l)
	}
	l = "9.9"
	if Supported(l) {
		t.Errorf("Expected: [false], got: [true] for protocol level %v\n", l)
	}
	//
	for _, v := range suptests {
		b := Supported(v.v)
		if b != v.s {
			t.Errorf("Expected: [%v] for protocol level [%v]\n", v.s, v.v)
		}
	}
}

/*
	Data test: Protocols.
*/
func TestDataProtocols(t *testing.T) {
	t.Parallel()
	s := Protocols()
	for i, p := range s {
		if supported[i] != p {
			t.Errorf("Expected [%v], got [%v]\n", supported[i], p)
		}
	}
}

/*
	Data test: Error.
*/
func TestDataError(t *testing.T) {
	t.Parallel()
	s := "An error string"
	e := Error(s)
	if s != e.Error() {
		t.Errorf("Expected [%v], got [%v]\n", s, e.Error())
	}
}

/*
	Data Test: Message Size.
*/
func TestDataMessageSize(t *testing.T) {
	t.Parallel()
	f := CONNECT
	h := Headers{"keya", "valuea"}
	s := "The Message Body"
	m := &Message{Command: f, Headers: h, Body: []byte(s)}
	e := false
	//
	var w int64 = int64(len(CONNECT)) + 1 + h.Size(e) + 1 + int64(len(s)) + 1
	r := m.Size(e)
	if w != r {
		t.Errorf("Message size, expected: [%d], got [%d]\n", w, r)
	}
}

/*
  Data Test: Broker Command Validity.
*/
func TestBrokerCmdVal(t *testing.T) {
	t.Parallel()
	var tData = map[string]bool{MESSAGE: true, ERROR: true, RECEIPT: true,
		CONNECT: false, DISCONNECT: false, SUBSCRIBE: false, BEGIN: false,
		STOMP: false, COMMIT: false, ABORT: false, UNSUBSCRIBE: false,
		SEND: false, ACK: false, NACK: false, CONNECTED: false,
		"JUNK": false}
	for k, v := range tData {
		if v != validCmds[k] {
			t.Errorf("Command Validity, expected: [%d], got [%d] for key [%s]\n", v,
				validCmds[k], k)
		}
	}
}

func BenchmarkHeaderAdd(b *testing.B) {
	h := Headers{"k1", "v1"}
	for n := 0; n < b.N; n++ {
		_ = h.Add("akey", "avalue")
	}
}

func BenchmarkHeaderAppend(b *testing.B) {
	h := []string{"k1", "v1"}
	for n := 0; n < b.N; n++ {
		_ = append(h, "akey", "avalue")
	}
}
<commit_msg>Minor changes per 'vet'.<commit_after>//
// Copyright © 2011-2014 Guy M. Allard
//
// 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 stompngo

import (
	"testing"
)

type supdata struct {
	v string
	s bool
}

var suptests = []supdata{
	{SPL_10, true},
	{SPL_11, true},
	{SPL_12, true},
	{"1.3", false},
	{"2.0", false},
	{"2.1", false},
}

/*
	Data Test: Frame Basic.
*/
func TestDataFrameBasic(t *testing.T) {
	t.Parallel()
	c := CONNECT
	h := Headers{"keya", "valuea"}
	s := "The Message Body"
	f := &Frame{Command: c, Headers: h, Body: []byte(s)}
	//
	if c != f.Command {
		t.Errorf("Command, expected: [%v], got [%v]\n", c, f.Command)
	}
	if !h.Compare(f.Headers) {
		t.Errorf("Headers, expected: [true], got [false], for [%v] [%v]\n", h, f.Headers)
	}
	if s != string(f.Body) {
		t.Errorf("Body string, expected: [%v], got [%v]\n", s, string(f.Body))
	}
}

/*
	Data Test: Message Basic.
*/
func TestDataMessageBasic(t *testing.T) {
	t.Parallel()
	f := CONNECT
	h := Headers{"keya", "valuea"}
	s := "The Message Body"
	m := &Message{Command: f, Headers: h, Body: []byte(s)}
	//
	if f != m.Command {
		t.Errorf("Command, expected: [%v], got [%v]\n", f, m.Command)
	}
	if !h.Compare(m.Headers) {
		t.Errorf("Headers, expected: [true], got [false], for [%v] [%v]\n", h, m.Headers)
	}
	if s != m.BodyString() {
		t.Errorf("Body string, expected: [%v], got [%v]\n", s, m.BodyString())
	}
}

/*
	Data Test: protocols.
*/
func TestDataprotocols(t *testing.T) {
	t.Parallel()
	l := SPL_10
	if !Supported(l) {
		t.Errorf("Expected: [true], got: [false] for protocol level %v\n", l)
	}
	l = SPL_11
	if !Supported(l) {
		t.Errorf("Expected: [true], got: [false] for protocol level %v\n", l)
	}
	l = SPL_12
	if !Supported(l) {
		t.Errorf("Expected: [true], got: [false] for protocol level %v\n", l)
	}
	l = "9.9"
	if Supported(l) {
		t.Errorf("Expected: [false], got: [true] for protocol level %v\n", l)
	}
	//
	for _, v := range suptests {
		b := Supported(v.v)
		if b != v.s {
			t.Errorf("Expected: [%v] for protocol level [%v]\n", v.s, v.v)
		}
	}
}

/*
	Data test: Protocols.
*/
func TestDataProtocols(t *testing.T) {
	t.Parallel()
	s := Protocols()
	for i, p := range s {
		if supported[i] != p {
			t.Errorf("Expected [%v], got [%v]\n", supported[i], p)
		}
	}
}

/*
	Data test: Error.
*/
func TestDataError(t *testing.T) {
	t.Parallel()
	s := "An error string"
	e := Error(s)
	if s != e.Error() {
		t.Errorf("Expected [%v], got [%v]\n", s, e.Error())
	}
}

/*
	Data Test: Message Size.
*/
func TestDataMessageSize(t *testing.T) {
	t.Parallel()
	f := CONNECT
	h := Headers{"keya", "valuea"}
	s := "The Message Body"
	m := &Message{Command: f, Headers: h, Body: []byte(s)}
	e := false
	//
	var w int64 = int64(len(CONNECT)) + 1 + h.Size(e) + 1 + int64(len(s)) + 1
	r := m.Size(e)
	if w != r {
		t.Errorf("Message size, expected: [%d], got [%d]\n", w, r)
	}
}

/*
  Data Test: Broker Command Validity.
*/
func TestBrokerCmdVal(t *testing.T) {
	t.Parallel()
	var tData = map[string]bool{MESSAGE: true, ERROR: true, RECEIPT: true,
		CONNECT: false, DISCONNECT: false, SUBSCRIBE: false, BEGIN: false,
		STOMP: false, COMMIT: false, ABORT: false, UNSUBSCRIBE: false,
		SEND: false, ACK: false, NACK: false, CONNECTED: false,
		"JUNK": false}
	for k, v := range tData {
		if v != validCmds[k] {
			t.Errorf("Command Validity, expected: [%t], got [%t] for key [%s]\n", v,
				validCmds[k], k)
		}
	}
}

func BenchmarkHeaderAdd(b *testing.B) {
	h := Headers{"k1", "v1"}
	for n := 0; n < b.N; n++ {
		_ = h.Add("akey", "avalue")
	}
}

func BenchmarkHeaderAppend(b *testing.B) {
	h := []string{"k1", "v1"}
	for n := 0; n < b.N; n++ {
		_ = append(h, "akey", "avalue")
	}
}
<|endoftext|>


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

package autocmd

import (
	"context"

	"github.com/neovim/go-client/nvim/plugin"
	"golang.org/x/sync/syncmap"

	"github.com/zchee/nvim-go/pkg/buildctxt"
	"github.com/zchee/nvim-go/pkg/command"
	"github.com/zchee/nvim-go/pkg/logger"
)

// Register registers autocmd to Neovim.
func Register(pctx context.Context, cancel func(), p *plugin.Plugin, buildContext *buildctxt.Context, cmd *command.Command) {
	ctx := logger.NewContext(pctx, logger.FromContext(pctx).Named("autocmd"))

	autocmd := &Autocmd{
		ctx:              ctx,
		cancel:           cancel,
		Nvim:             p.Nvim,
		buildContext:     buildContext,
		cmd:              cmd,
		bufWritePreChan:  make(chan interface{}),
		bufWritePostChan: make(chan error),
		errs:             new(syncmap.Map),
	}

	// Handle the initial start Neovim process.
	// Note that does not run the 'VimEnter' handler if open the *not* go file. Because 'VimEnter' handler already run the other file or directory.
	// TODO(zchee): consider Pattern to '*' instead of '*.go' with get '&filetype' and early return
	// p.HandleAutocmd(&plugin.AutocmdOptions{Event: "VimEnter", Pattern: "*", Group: "nvim-go", Eval: "*"}, autocmd.VimEnter)

	// Handle the open the file.
	// If open the file at first, run the 'BufEnter' -> 'VimEnter'.
	p.HandleAutocmd(&plugin.AutocmdOptions{Event: "BufEnter", Pattern: "*.go", Group: "nvim-go", Eval: "*"}, autocmd.BufEnter)

	// BufNewFile: Handle create the new file.
	// BufReadPre: Handle the before the read to file.
	// If create the new file, does not run the 'BufReadPre', Instead of 'BufNewFile'.
	p.HandleAutocmd(&plugin.AutocmdOptions{Event: "BufNewFile,BufReadPre", Group: "nvim-go-autocmd", Pattern: "*.go", Eval: "*"}, autocmd.BufReadPre)

	// p.HandleAutocmd(&plugin.AutocmdOptions{Event: "WinEnter", Group: "nvim-go-autocmd", Pattern: "*.go", Eval: "*"}, autocmd.WinEnter)

	// Handle the before the write to file.
	p.HandleAutocmd(&plugin.AutocmdOptions{Event: "BufWritePre", Pattern: "*.go", Group: "nvim-go", Eval: "*"}, autocmd.BufWritePre)

	// Handle the after the write to file.
	p.HandleAutocmd(&plugin.AutocmdOptions{Event: "BufWritePost", Pattern: "*.go", Group: "nvim-go", Eval: "*"}, autocmd.bufWritePost)

	p.HandleAutocmd(&plugin.AutocmdOptions{Event: "VimLeavePre", Pattern: "*.go", Group: "nvim-go"}, autocmd.VimLeavePre)
}
<commit_msg>pkg/autocmd: add handle `NvimGo` method event<commit_after>// Copyright 2018 The nvim-go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package autocmd

import (
	"context"

	"github.com/neovim/go-client/nvim/plugin"
	"go.uber.org/zap"
	"golang.org/x/exp/errors/fmt"
	"golang.org/x/sync/syncmap"

	"github.com/zchee/nvim-go/pkg/buildctxt"
	"github.com/zchee/nvim-go/pkg/command"
	"github.com/zchee/nvim-go/pkg/logger"
	"github.com/zchee/nvim-go/pkg/nvimctx"
)

// Register registers autocmd to Neovim.
//
//  :help rpcrequest()
//  :help rpcnotify()
func Register(pctx context.Context, cancel func(), p *plugin.Plugin, buildContext *buildctxt.Context, cmd *command.Command) {
	log := logger.FromContext(pctx).Named("autocmd")
	ctx := logger.NewContext(pctx, log)

	autocmd := &Autocmd{
		ctx:              ctx,
		cancel:           cancel,
		Nvim:             p.Nvim,
		buildContext:     buildContext,
		cmd:              cmd,
		bufWritePreChan:  make(chan interface{}),
		bufWritePostChan: make(chan error),
		errs:             new(syncmap.Map),
	}

	// Handle the initial start Neovim process.
	// Note that does not run the 'VimEnter' handler if open the *not* go file. Because 'VimEnter' handler already run the other file or directory.
	// TODO(zchee): consider Pattern to '*' instead of '*.go' with get '&filetype' and early return
	// p.HandleAutocmd(&plugin.AutocmdOptions{Event: "VimEnter", Pattern: "*", Group: "nvim-go", Eval: "*"}, autocmd.VimEnter)

	p.Handle(nvimctx.Method, func(event ...interface{}) {
		log.Debug(fmt.Sprintf("handles %s", nvimctx.Method), zap.Any("event", event))
	})

	// Handle the open the file.
	// If open the file at first, run the 'BufEnter' -> 'VimEnter'.
	p.HandleAutocmd(&plugin.AutocmdOptions{Event: "BufEnter", Pattern: "*.go", Group: "nvim-go", Eval: "*"}, autocmd.BufEnter)

	// BufNewFile: Handle create the new file.
	// BufReadPre: Handle the before the read to file.
	// If create the new file, does not run the 'BufReadPre', Instead of 'BufNewFile'.
	p.HandleAutocmd(&plugin.AutocmdOptions{Event: "BufNewFile,BufReadPre", Group: "nvim-go-autocmd", Pattern: "*.go", Eval: "*"}, autocmd.BufReadPre)

	// p.HandleAutocmd(&plugin.AutocmdOptions{Event: "WinEnter", Group: "nvim-go-autocmd", Pattern: "*.go", Eval: "*"}, autocmd.WinEnter)

	// Handle the before the write to file.
	p.HandleAutocmd(&plugin.AutocmdOptions{Event: "BufWritePre", Pattern: "*.go", Group: "nvim-go", Eval: "*"}, autocmd.BufWritePre)

	// Handle the after the write to file.
	p.HandleAutocmd(&plugin.AutocmdOptions{Event: "BufWritePost", Pattern: "*.go", Group: "nvim-go", Eval: "*"}, autocmd.bufWritePost)

	p.HandleAutocmd(&plugin.AutocmdOptions{Event: "VimLeavePre", Pattern: "*.go", Group: "nvim-go"}, autocmd.VimLeavePre)
}
<|endoftext|>


<commit_before>package k8s

import (
	"testing"
	"time"
)

const (
	delay = 10 * time.Second
)

func (w *Watcher) fetch(resource, qname string) (result Resource) {
	go func() {
		time.Sleep(delay)
		w.Stop()
	}()

	err := w.Watch(resource, func(w *Watcher) {
		for _, r := range w.List(resource) {
			if r.QName() == qname {
				result = r
				w.Stop()
			}
		}
	})

	if err != nil {
		panic(err)
	}

	w.Wait()
	return result
}

func TestUpdateStatus(t *testing.T) {
	w := NewClient(nil).Watcher()

	svc := w.fetch("services", "kubernetes.default")
	svc.Status()["loadBalancer"].(map[string]interface{})["ingress"] = []map[string]interface{}{{"hostname": "foo", "ip": "1.2.3.4"}}
	result, err := w.UpdateStatus(svc)
	if err != nil {
		t.Error(err)
		return
	} else {
		t.Logf("updated %s status, result: %v\n", svc.QName(), result.ResourceVersion())
	}

	svc = NewClient(nil).Watcher().fetch("services", "kubernetes.default")
	ingresses := svc.Status()["loadBalancer"].(map[string]interface{})["ingress"].([]interface{})
	ingress := ingresses[0].(map[string]interface{})
	if ingress["hostname"] != "foo" {
		t.Error("expected foo")
	}

	if ingress["ip"] != "1.2.3.4" {
		t.Error("expected 1.2.3.4")
	}
}

func TestWatchCustom(t *testing.T) {
	w := NewClient(nil).Watcher()

	// XXX: we can only watch custom resources... k8s doesn't
	// support status for CRDs until 1.12
	xmas := w.fetch("customs", "xmas.default")
	if xmas == nil {
		t.Error("couldn't find xmas")
	} else {
		spec := xmas.Spec()
		if spec["deck"] != "the halls" {
			t.Errorf("expected the halls, got %v", spec["deck"])
		}
	}
}
<commit_msg>fix hang in watcher test<commit_after>package k8s

import (
	"testing"
	"time"
)

const (
	delay = 10 * time.Second
)

func (w *Watcher) fetch(resource, qname string) (result Resource) {
	go func() {
		time.Sleep(delay)
		w.Stop()
	}()

	err := w.Watch(resource, func(w *Watcher) {
		for _, r := range w.List(resource) {
			if r.QName() == qname {
				result = r
				w.Stop()
			}
		}
	})

	if err != nil {
		panic(err)
	}

	w.Start()
	w.Wait()
	return result
}

func TestUpdateStatus(t *testing.T) {
	w := NewClient(nil).Watcher()

	svc := w.fetch("services", "kubernetes.default")
	svc.Status()["loadBalancer"].(map[string]interface{})["ingress"] = []map[string]interface{}{{"hostname": "foo", "ip": "1.2.3.4"}}
	result, err := w.UpdateStatus(svc)
	if err != nil {
		t.Error(err)
		return
	} else {
		t.Logf("updated %s status, result: %v\n", svc.QName(), result.ResourceVersion())
	}

	svc = NewClient(nil).Watcher().fetch("services", "kubernetes.default")
	ingresses := svc.Status()["loadBalancer"].(map[string]interface{})["ingress"].([]interface{})
	ingress := ingresses[0].(map[string]interface{})
	if ingress["hostname"] != "foo" {
		t.Error("expected foo")
	}

	if ingress["ip"] != "1.2.3.4" {
		t.Error("expected 1.2.3.4")
	}
}

func TestWatchCustom(t *testing.T) {
	w := NewClient(nil).Watcher()

	// XXX: we can only watch custom resources... k8s doesn't
	// support status for CRDs until 1.12
	xmas := w.fetch("customs", "xmas.default")
	if xmas == nil {
		t.Error("couldn't find xmas")
	} else {
		spec := xmas.Spec()
		if spec["deck"] != "the halls" {
			t.Errorf("expected the halls, got %v", spec["deck"])
		}
	}
}
<|endoftext|>


<commit_before>package landscaper

import (
	"errors"
	"os"
	"path/filepath"
	"strings"

	"github.com/Sirupsen/logrus"

	"k8s.io/helm/cmd/helm/downloader"
	"k8s.io/helm/cmd/helm/helmpath"
	"k8s.io/helm/pkg/chartutil"
	"k8s.io/helm/pkg/proto/hapi/chart"
)

// ChartLoader allows one to load Charts by name
type ChartLoader interface {
	Load(chartRef string) (*chart.Chart, string, error)
}

// LocalCharts allows one to load Charts from a local path
type LocalCharts struct {
	HomePath string
}

// NewLocalCharts creates a LocalCharts ChartLoader
func NewLocalCharts(homePath string) *LocalCharts {
	return &LocalCharts{HomePath: homePath}
}

// ErrChartNotFound is thrown when an unknown chart is trying to be loaded
var ErrChartNotFound = errors.New("chart not found")

// Load locates, and potentially downloads, a chart to the local repository
func (c *LocalCharts) Load(chartRef string) (*chart.Chart, string, error) {
	logrus.WithFields(logrus.Fields{"chartRef": chartRef}).Debug("Load Chart")

	chartPath, err := locateChartPath(c.HomePath, chartRef)
	if err != nil {
		return nil, "", err
	}

	chart, err := chartutil.Load(chartPath)
	if err != nil {
		return nil, "", err
	}

	logrus.WithFields(logrus.Fields{"chartRef": chartRef}).Debug("Loaded Chart successfully")
	return chart, chartPath, nil
}

// locateChartPath searches for a chart in homePath, downloads it otherwise and if that fails and possibly returns an ErrChartNotFound
func locateChartPath(homePath, chartRef string) (string, error) {
	logrus.WithFields(logrus.Fields{"chartRef": chartRef, "homePath": homePath}).Debug("locateChartPath")
	name, version := parseChartRef(chartRef)

	chartFile := filepath.Join(helmpath.Home(homePath).Repository(), name)
	if _, err := os.Stat(chartFile); err == nil {
		return filepath.Abs(chartFile)
	}

	dl := downloader.ChartDownloader{
		HelmHome: helmpath.Home(homePath),
		Out:      os.Stdout,
	}

	logrus.WithFields(logrus.Fields{"name": name, "version": version, "homePath": homePath}).Debug("Download Chart")
	chartFile, _, err := dl.DownloadTo(name, version, helmpath.Home(homePath).Repository())
	if err == nil {
		chartFile, err = filepath.Abs(chartFile)
		if err != nil {
			return "", err
		}

		repoName := ""
		info := strings.Split(name, "/")
		if len(info) == 2 {
			repoName = info[0]
		}

		// Extract the chart for easier reference the next time
		chartutil.ExpandFile(filepath.Join(helmpath.Home(homePath).Repository(), repoName), chartFile)

		logrus.WithFields(logrus.Fields{"chartFile": chartFile}).Debug("Downloaded Chart")
		return chartFile, nil
	}

	logrus.WithFields(logrus.Fields{"name": name, "version": version, "homePath": homePath, "err": err}).Error("Failed to download Chart")
	return "", ErrChartNotFound
}

// parseChartRef splits a name:version into a name and an (optional) version
func parseChartRef(ref string) (string, string) {
	chartInfo := strings.Split(ref, ":")
	chartName, chartVersion := chartInfo[0], ""
	if len(chartInfo) == 2 {
		chartVersion = chartInfo[1]
	}

	return strings.TrimSpace(chartName), strings.TrimSpace(chartVersion)
}
<commit_msg>Include versioning in downloaded chart file; fix #25<commit_after>package landscaper

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/Sirupsen/logrus"

	"k8s.io/helm/cmd/helm/downloader"
	"k8s.io/helm/cmd/helm/helmpath"
	"k8s.io/helm/pkg/chartutil"
	"k8s.io/helm/pkg/proto/hapi/chart"
)

// ChartLoader allows one to load Charts by name
type ChartLoader interface {
	Load(chartRef string) (*chart.Chart, string, error)
}

// LocalCharts allows one to load Charts from a local path
type LocalCharts struct {
	HomePath string
}

// NewLocalCharts creates a LocalCharts ChartLoader
func NewLocalCharts(homePath string) *LocalCharts {
	return &LocalCharts{HomePath: homePath}
}

// Load locates, and potentially downloads, a chart to the local repository
func (c *LocalCharts) Load(chartRef string) (*chart.Chart, string, error) {
	logrus.WithFields(logrus.Fields{"chartRef": chartRef}).Debug("Load Chart")

	chartPath, err := locateChartPath(c.HomePath, chartRef)
	if err != nil {
		return nil, "", err
	}

	chart, err := chartutil.Load(chartPath)
	if err != nil {
		return nil, "", err
	}

	logrus.WithFields(logrus.Fields{"chartRef": chartRef}).Debug("Loaded Chart successfully")
	return chart, chartPath, nil
}

// locateChartPath downloads charts by reference. It stores the resulting tgzs in a temporary directory.
func locateChartPath(homePath, chartRef string) (string, error) {
	name, version := parseChartRef(chartRef)
	logrus.WithFields(logrus.Fields{"chartRef": chartRef, "homePath": homePath, "name": name, "version": version}).Debug("locateChartPath")

	repoName := ""
	info := strings.Split(name, "/")
	if len(info) != 2 {
		return "", fmt.Errorf("expect repo/name instead of `%s`", name)
	}
	repoName = info[0]

	dl := downloader.ChartDownloader{
		HelmHome: helmpath.Home(homePath),
		Out:      os.Stdout,
	}

	// ResolveChartVersion provides us through the repo index an url from which we can obtain the filename chart.tgz
	url, err := dl.ResolveChartVersion(name, version)
	if err != nil {
		return "", fmt.Errorf("cannot resolve chartversion: %s", err)
	}

	_, chartFile := filepath.Split(url.Path)

	repoDir := filepath.Join(os.TempDir(), "landscaper", repoName)
	if err := os.MkdirAll(repoDir, 0755); err != nil {
		return "", fmt.Errorf("cannot create work directory `%s`", repoDir)
	}

	chartPath, err := filepath.Abs(filepath.Join(repoDir, chartFile))
	if err != nil {
		return "", err
	}

	logrus.WithFields(logrus.Fields{"chartPath": chartPath}).Debug("Look for cached local package")

	if _, err := os.Stat(chartPath); err == nil {
		return chartPath, nil
	}

	logrus.WithFields(logrus.Fields{"name": name, "version": version, "repoDir": repoDir}).Debug("Download")
	chartFile, _, err = dl.DownloadTo(name, version, repoDir)
	if err != nil {
		return "", fmt.Errorf("failed to download `%s`: %s", chartRef, err)
	}

	return chartPath, nil
}

// parseChartRef splits a name:version into a name and an (optional) version
func parseChartRef(ref string) (string, string) {
	chartInfo := strings.Split(ref, ":")
	chartName, chartVersion := chartInfo[0], ""
	if len(chartInfo) == 2 {
		chartVersion = chartInfo[1]
	}

	return strings.TrimSpace(chartName), strings.TrimSpace(chartVersion)
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/codingsince1985/checksum/md5"
	"github.com/codingsince1985/util"
	"strings"
)

func main() {
	root := "/home/jerry/Downloads/Go/"
	fileList, err := util.GetFiles(root)
	if err != nil {
		panic(err)
	}

	files := []util.File{}
	for _, file := range fileList {
		md5sum, err := md5.MD5sum(file)
		if err != nil {
			panic(err)
		}
		files = append(files, util.File{file[strings.Index(file, root)+len(root):], md5sum})
	}
	folder := util.Folder{root, "md5", files}

	folder.Write("/home/jerry/Downloads/Go.json")
}
<commit_msg>read folder and checksum filename from command line<commit_after>package main

import (
	"github.com/codingsince1985/checksum/md5"
	"github.com/codingsince1985/util"
	"os"
)

func main() {
	args := os.Args
	if len(args) == 4 {
		switch args[1] {
		case "--create":
			createChecksumFile(args[2], args[3])
		}
	}
}

func createChecksumFile(root, file string) {
	fileList, err := util.GetFiles(root)
	if err != nil {
		panic(err)
	}

	files := []util.File{}
	for _, file := range fileList {
		md5sum, err := md5.MD5sum(file)
		if err != nil {
			panic(err)
		}
		files = append(files, util.File{file[len(root):], md5sum})
	}
	folder := util.Folder{root, "md5", files}

	folder.Write(file)
}
<|endoftext|>


<commit_before>package runner

import (
	"net/url"
	"os"

	"golang.org/x/net/context"

	"github.com/fsouza/go-dockerclient"
	"google.golang.org/appengine"
	"google.golang.org/appengine/log"
)

var compute *url.URL

var dc *docker.Client

func init() {
	var err error
	if appengine.IsDevAppServer() {
		dc, err = docker.NewClientFromEnv()
		if err != nil {
			panic(err)
		}
	}
}

func prepareImage(ctx context.Context, name string) error {
	_, err := dc.InspectImage(name)

	if err != nil {
		return nil
	}

	if err != docker.ErrNoSuchImage {
		return err
	}

	log.Warningf(ctx, "Missing image %s will be pulled. Expect severe delay!", name)

	err = dc.PullImage(docker.PullImageOptions{
		Repository:   name,
		OutputStream: os.Stderr,
	}, docker.AuthConfiguration{})

	if err != nil {
		log.Warningf(ctx, "Failed pulling image %s because of: %s", name, err)
	}

	return err
}

// newImage returns the correct docker image name for a
// specific language.
func newImage(language string) string {
	const imagePattern string = "coduno/fingerprint-"
	return imagePattern + language
}

func createDockerVolume(name string) (*docker.Volume, error) {
	return dc.CreateVolume(docker.CreateVolumeOptions{
		Driver: "gcs",
		Name:   name,
	})
}
<commit_msg>hack: Add Docker endpoint for GAE<commit_after>package runner

import (
	"net/url"
	"os"

	"golang.org/x/net/context"

	"github.com/fsouza/go-dockerclient"
	"google.golang.org/appengine"
	"google.golang.org/appengine/log"
)

var compute *url.URL

var dc *docker.Client

func init() {
	var err error
	if appengine.IsDevAppServer() {
		dc, err = docker.NewClientFromEnv()
	} else {
		// FIXME(flowlo)
		dc, err = docker.NewClient("tcp://10.240.10.141:2375")
	}
	if err != nil {
		panic(err)
	}
}

func prepareImage(ctx context.Context, name string) error {
	_, err := dc.InspectImage(name)

	if err != nil {
		return nil
	}

	if err != docker.ErrNoSuchImage {
		return err
	}

	log.Warningf(ctx, "Missing image %s will be pulled. Expect severe delay!", name)

	err = dc.PullImage(docker.PullImageOptions{
		Repository:   name,
		OutputStream: os.Stderr,
	}, docker.AuthConfiguration{})

	if err != nil {
		log.Warningf(ctx, "Failed pulling image %s because of: %s", name, err)
	}

	return err
}

// newImage returns the correct docker image name for a
// specific language.
func newImage(language string) string {
	const imagePattern string = "coduno/fingerprint-"
	return imagePattern + language
}

func createDockerVolume(name string) (*docker.Volume, error) {
	return dc.CreateVolume(docker.CreateVolumeOptions{
		Driver: "gcs",
		Name:   name,
	})
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"os"
	"os/signal"
	"time"

	"github.com/kid0m4n/go-rpi/controller/pca9685"
	"github.com/kid0m4n/go-rpi/i2c"
	"github.com/kid0m4n/go-rpi/motion/servo"
)

func main() {
	bus, err := i2c.NewBus(1)
	if err != nil {
		log.Panic(err)
	}

	pwm := pca9685.New(bus, 0x42, 50)
	defer pwm.Close()

	servo := servo.New(pwm, 50, 0, 1, 2.5)

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill)

	turnTimer := time.Tick(500 * time.Millisecond)
	left := true

	servo.SetAngle(90)
	defer func() {
		servo.SetAngle(90)
	}()

	for {
		select {
		case <-turnTimer:
			left = !left
			switch left {
			case true:
				servo.SetAngle(70)
			case false:
				servo.SetAngle(110)
			}
		case <-c:
			return
		}
	}
}
<commit_msg>servo: sample debug turned<commit_after>package main

import (
	"log"
	"os"
	"os/signal"
	"time"

	"github.com/kid0m4n/go-rpi/controller/pca9685"
	"github.com/kid0m4n/go-rpi/i2c"
	"github.com/kid0m4n/go-rpi/motion/servo"
)

func main() {
	bus, err := i2c.NewBus(1)
	if err != nil {
		log.Panic(err)
	}

	pwm := pca9685.New(bus, 0x41, 50)
	pwm.Debug = true
	defer pwm.Close()

	servo := servo.New(pwm, 50, 15, 1, 2.5)
	servo.Debug = true

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill)

	turnTimer := time.Tick(500 * time.Millisecond)
	left := true

	servo.SetAngle(90)
	defer func() {
		servo.SetAngle(90)
	}()

	for {
		select {
		case <-turnTimer:
			left = !left
			switch left {
			case true:
				servo.SetAngle(70)
			case false:
				servo.SetAngle(110)
			}
		case <-c:
			return
		}
	}
}
<|endoftext|>


<commit_before>package scanner

const (
	version           = "0.1.0"
	DefaultHostname   = "example.com"
	DefaultMaxProcs   = 1
	DefaultMaxMin     = 5
	DefaultMaxWorkers = 4
)
<commit_msg>version up<commit_after>package scanner

const (
	version           = "0.1.1-alpha"
	DefaultHostname   = "example.com"
	DefaultMaxProcs   = 1
	DefaultMaxMin     = 5
	DefaultMaxWorkers = 4
)
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"time"
)

type Params struct {
	Customers      int
	Seats          int
	Customer_delay float64
	Barber_delay   float64
}

func barber(customer_ready chan int) {
	fmt.Printf("I am a Barber.\n")
	for {
		customer_id := <-customer_ready
		fmt.Printf("BARBER: Customer %d served.\n", customer_id)
	}
}

func customer(id int, customer_ready chan int) {
	fmt.Printf("I am a Customer #%d.\n", id)
	customer_ready <- id

}

func read_params() *Params {
	var params *Params = new(Params)
	flag.IntVar(&params.Customers, "customers", 10, "number of customers to come to barber shop")
	flag.IntVar(&params.Seats, "seats", 3, "number of seats in barber shop")
	flag.Float64Var(&params.Customer_delay, "customers_delay", 100, "mean value of time of customers incoming to shop")
	flag.Float64Var(&params.Barber_delay, "barber_delay", 150, "mean value of time of barbers work on customer")

	flag.Parse()
	return params
}

func main() {
	params := read_params()

	customer_ready := make(chan int)

	go barber(customer_ready)
	for id := 0; id < params.Customers; id++ {
		go customer(id, customer_ready)
	}

	time.Sleep(250 * time.Millisecond)
}
<commit_msg>Customers are leaving when the barber shop is full<commit_after>package main

import (
	"flag"
	"fmt"
	"time"
)

type Params struct {
	Customers      int
	Seats          int
	Customer_delay int
	Barber_delay   int
}

func barber(params Params, seats chan int) {
	for {
		customer_id := <-seats
		time.Sleep(time.Duration(params.Barber_delay) * time.Millisecond)
		fmt.Printf("BARBER: Customer %d served.\n", customer_id)
	}
}

func customer(id int, seats chan int) {
	select {
	case seats <- id:
		fmt.Printf("CUSTOMER %d: Leaving barber shop happy.\n", id)
	default:
		fmt.Printf("CUSTOMER %d: Leaving barber shop unserviced.\n", id)
	}
}

func read_params() *Params {
	var params *Params = new(Params)
	flag.IntVar(&params.Customers, "customers", 10, "number of customers to come to barber shop")
	flag.IntVar(&params.Seats, "seats", 3, "number of seats in barber shop")
	flag.IntVar(&params.Customer_delay, "customers_delay", 5, "mean value of time of customers incoming to shop")
	flag.IntVar(&params.Barber_delay, "barber_delay", 15, "mean value of time of barbers work on customer")

	flag.Parse()
	return params
}

func main() {
	var params *Params = read_params()

	seats := make(chan int, params.Seats)

	go barber(*params, seats)
	for id := 0; id < params.Customers; id++ {
		go customer(id, seats)
		time.Sleep(time.Duration(params.Customer_delay) * time.Millisecond)
	}

	time.Sleep(500 * time.Millisecond)
}
<|endoftext|>


<commit_before>package main

import (
	"code.google.com/p/go-html-transform/h5"
	"fmt"
	"os"
	"path/filepath"
	"regexp"
)

func runDatTests(ps []string) {
	//for _, p := range ps {
	//}
}

func runTestTests(ps []string) {
	//for _, p := range ps {
	//}
}

func runHtmlTests(ps []string) {
	for _, p := range ps {
		fmt.Println("Attempting to parse file: ", p)
		f, err := os.Open(p)
		if err != nil {
			fmt.Println("Error opening file: ", err)
		}
		parse := h5.NewParser(f)
		err = parse.Parse()
		if err != nil {
			fmt.Println("Error parsing file: ", err)
		} else {
			fmt.Println("Success!!!")
		}
	}
}

type grepSpec map[*regexp.Regexp][]string

func grep(path string, spec grepSpec) error {
	return filepath.Walk(path, func(p string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if !info.IsDir() {
			for re, _ := range spec {
				if re.MatchString(p) {
					spec[re] = append(spec[re], p)
				}
			}
		}
		return nil
	})
}

func main() {
	datRe := regexp.MustCompile("dat$")
	testRe := regexp.MustCompile("test$")
	htmlRe := regexp.MustCompile("html?$")
	spec := make(map[*regexp.Regexp][]string)
	spec[datRe] = []string{}
	spec[testRe] = []string{}
	spec[htmlRe] = []string{}
	err := grep("./", spec)
	if err != nil {
		fmt.Println("Error while grepping: ", err)
	}
	runDatTests(spec[datRe])
	runTestTests(spec[testRe])
	runHtmlTests(spec[htmlRe])
}<commit_msg>Add todo about timing the parsing algorithms.<commit_after>package main

import (
	"code.google.com/p/go-html-transform/h5"
	"fmt"
	"os"
	"path/filepath"
	"regexp"
)

func runDatTests(ps []string) {
	//for _, p := range ps {
	//}
}

func runTestTests(ps []string) {
	//for _, p := range ps {
	//}
}

func runHtmlTests(ps []string) {
	// TODO(jwall): with timings?
	for _, p := range ps {
		fmt.Println("Attempting to parse file: ", p)
		f, err := os.Open(p)
		if err != nil {
			fmt.Println("Error opening file: ", err)
		}
		parse := h5.NewParser(f)
		err = parse.Parse()
		if err != nil {
			fmt.Println("Error parsing file: ", err)
		} else {
			fmt.Println("Success!!!")
		}
	}
}

type grepSpec map[*regexp.Regexp][]string

func grep(path string, spec grepSpec) error {
	return filepath.Walk(path, func(p string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if !info.IsDir() {
			for re, _ := range spec {
				if re.MatchString(p) {
					spec[re] = append(spec[re], p)
				}
			}
		}
		return nil
	})
}

func main() {
	datRe := regexp.MustCompile("dat$")
	testRe := regexp.MustCompile("test$")
	htmlRe := regexp.MustCompile("html?$")
	spec := make(map[*regexp.Regexp][]string)
	spec[datRe] = []string{}
	spec[testRe] = []string{}
	spec[htmlRe] = []string{}
	err := grep("./", spec)
	if err != nil {
		fmt.Println("Error while grepping: ", err)
	}
	runDatTests(spec[datRe])
	runTestTests(spec[testRe])
	runHtmlTests(spec[htmlRe])
}<|endoftext|>


<commit_before>package main

import (
	"encoding/binary"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"github.com/jessevdk/go-flags"
	"hash/crc32"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
)

const (
	name                 = "bitrot"
	version              = "0.0.1"
	manifestDirName      = ".bitrot"
	manifestNameTemplate = "manifest-%s-%s.json"
	// RFC3339 minus punctuation characters, better for filenames
	manifestNameTimeFormat = "20060102T150405Z07:00"
)

// go-flags requires us to wrap positional args in a struct
type PathArguments struct {
	Path flags.Filename `positional-arg-name:"PATH" description:"Path to directory."`
}

// Options/arguments for the `generate` command
type Generate struct {
	Exclude   []string      `short:"e" long:"exclude" description:"File/directory names to exclude. Repeat option to exclude multiple names."`
	Pretty    bool          `short:"p" long:"pretty" description:"Make a \"pretty\" (indented) JSON file."`
	Arguments PathArguments `required:"true" positional-args:"true"`
	logger    *log.Logger
}

type ManifestFile struct {
	Manifest  *Manifest
	JSONBytes []byte
	Filename  string
}

// TODO break this func down a bit and unit test?
func NewManifestFile(manifest *Manifest, pretty bool) *ManifestFile {
	var jsonBytes []byte
	var err error
	if pretty {
		jsonBytes, err = json.MarshalIndent(manifest, "", "  ")
	} else {
		jsonBytes, err = json.Marshal(manifest)
	}
	check(err)
	manifestName := fmt.Sprintf(
		manifestNameTemplate,
		manifest.CreatedAt.Format(manifestNameTimeFormat),
		shortChecksum(&jsonBytes),
	)
	return &ManifestFile{
		Manifest:  manifest,
		JSONBytes: jsonBytes,
		Filename:  manifestName,
	}
}

// Extracts string path from wrapper and converts it to an absolute path
func (args *PathArguments) PathString() string {
	path, err := filepath.Abs(string(args.Path))
	check(err)
	return path
}

func (cmd *Generate) Execute(args []string) (err error) {
	config := DefaultConfig()
	if len(cmd.Exclude) > 0 {
		config.ExcludedFiles = cmd.Exclude
	}
	assertNoExtraArgs(&args, cmd.logger)
	path := cmd.Arguments.PathString()

	cmd.logger.Printf("Generating manifest for %s...\n", path)

	// Prepare manifest file destination
	manifestDir := filepath.Join(path, manifestDirName)
	err = os.Mkdir(manifestDir, 0755)
	check(err)

	manifest := NewManifest(path, config)
	manifestFile := NewManifestFile(manifest, cmd.Pretty)

	manifestPath := filepath.Join(manifestDir, manifestFile.Filename)
	if _, err := os.Stat(manifestPath); os.IsNotExist(err) {
		err = ioutil.WriteFile(manifestPath, manifestFile.JSONBytes, 0644)
		check(err)

		cmd.logger.Printf("Wrote manifest to %s\n", manifestPath)
	} else {
		cmd.logger.Fatalf("Manifest file already exists! Path: %s\n", manifestPath)
	}

	return nil
}

func assertNoExtraArgs(args *[]string, logger *log.Logger) {
	if len(*args) > 0 {
		logger.Fatalf("Unrecognized arguments: %s\n", strings.Join(*args, " "))
	}
}

// Short checksum suitable for a quick check on the manifest files
func shortChecksum(data *[]byte) string {
	checksum := crc32.ChecksumIEEE(*data)
	checksumBytes := [4]byte{}
	binary.BigEndian.PutUint32(checksumBytes[:], checksum)
	return hex.EncodeToString(checksumBytes[:])
}

// General helper functions
func check(e error) {
	if e != nil {
		panic(e)
	}
}

func main() {
	logger := log.New(os.Stderr, "", 0)
	var AppOpts struct {
		Version func() `long:"version" short:"v"`
	}
	AppOpts.Version = func() {
		log.Printf("%s version %s\n", name, version)
		os.Exit(0)
	}
	var parser = flags.NewParser(&AppOpts, flags.Default)
	generate := Generate{logger: logger}
	var err error
	_, err = parser.AddCommand("generate", "Generate manifest", "Generate manifest for directory", &generate)
	check(err)
	_, err = parser.AddCommand("validate", "Validate manifest", "Validate manifest for directory", &generate)
	check(err)
	parser.Parse()
}
<commit_msg>Use MkdirAll in Generate to avoid error<commit_after>package main

import (
	"encoding/binary"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"github.com/jessevdk/go-flags"
	"hash/crc32"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
)

const (
	name                 = "bitrot"
	version              = "0.0.1"
	manifestDirName      = ".bitrot"
	manifestNameTemplate = "manifest-%s-%s.json"
	// RFC3339 minus punctuation characters, better for filenames
	manifestNameTimeFormat = "20060102T150405Z07:00"
)

// go-flags requires us to wrap positional args in a struct
type PathArguments struct {
	Path flags.Filename `positional-arg-name:"PATH" description:"Path to directory."`
}

// Options/arguments for the `generate` command
type Generate struct {
	Exclude   []string      `short:"e" long:"exclude" description:"File/directory names to exclude. Repeat option to exclude multiple names."`
	Pretty    bool          `short:"p" long:"pretty" description:"Make a \"pretty\" (indented) JSON file."`
	Arguments PathArguments `required:"true" positional-args:"true"`
	logger    *log.Logger
}

type ManifestFile struct {
	Manifest  *Manifest
	JSONBytes []byte
	Filename  string
}

// TODO break this func down a bit and unit test?
func NewManifestFile(manifest *Manifest, pretty bool) *ManifestFile {
	var jsonBytes []byte
	var err error
	if pretty {
		jsonBytes, err = json.MarshalIndent(manifest, "", "  ")
	} else {
		jsonBytes, err = json.Marshal(manifest)
	}
	check(err)
	manifestName := fmt.Sprintf(
		manifestNameTemplate,
		manifest.CreatedAt.Format(manifestNameTimeFormat),
		shortChecksum(&jsonBytes),
	)
	return &ManifestFile{
		Manifest:  manifest,
		JSONBytes: jsonBytes,
		Filename:  manifestName,
	}
}

// Extracts string path from wrapper and converts it to an absolute path
func (args *PathArguments) PathString() string {
	path, err := filepath.Abs(string(args.Path))
	check(err)
	return path
}

func (cmd *Generate) Execute(args []string) (err error) {
	config := DefaultConfig()
	if len(cmd.Exclude) > 0 {
		config.ExcludedFiles = cmd.Exclude
	}
	assertNoExtraArgs(&args, cmd.logger)
	path := cmd.Arguments.PathString()

	cmd.logger.Printf("Generating manifest for %s...\n", path)

	// Prepare manifest file destination
	manifestDir := filepath.Join(path, manifestDirName)
	// Using MkdirAll because it doesn't return an error when the path is already a directory
	err = os.MkdirAll(manifestDir, 0755)
	check(err)

	manifest := NewManifest(path, config)
	manifestFile := NewManifestFile(manifest, cmd.Pretty)

	manifestPath := filepath.Join(manifestDir, manifestFile.Filename)
	if _, err := os.Stat(manifestPath); os.IsNotExist(err) {
		err = ioutil.WriteFile(manifestPath, manifestFile.JSONBytes, 0644)
		check(err)

		cmd.logger.Printf("Wrote manifest to %s\n", manifestPath)
	} else {
		cmd.logger.Fatalf("Manifest file already exists! Path: %s\n", manifestPath)
	}

	return nil
}

func assertNoExtraArgs(args *[]string, logger *log.Logger) {
	if len(*args) > 0 {
		logger.Fatalf("Unrecognized arguments: %s\n", strings.Join(*args, " "))
	}
}

// Short checksum suitable for a quick check on the manifest files
func shortChecksum(data *[]byte) string {
	checksum := crc32.ChecksumIEEE(*data)
	checksumBytes := [4]byte{}
	binary.BigEndian.PutUint32(checksumBytes[:], checksum)
	return hex.EncodeToString(checksumBytes[:])
}

// General helper functions
func check(e error) {
	if e != nil {
		panic(e)
	}
}

func main() {
	logger := log.New(os.Stderr, "", 0)
	var AppOpts struct {
		Version func() `long:"version" short:"v"`
	}
	AppOpts.Version = func() {
		log.Printf("%s version %s\n", name, version)
		os.Exit(0)
	}
	var parser = flags.NewParser(&AppOpts, flags.Default)
	generate := Generate{logger: logger}
	var err error
	_, err = parser.AddCommand("generate", "Generate manifest", "Generate manifest for directory", &generate)
	check(err)
	_, err = parser.AddCommand("validate", "Validate manifest", "Validate manifest for directory", &generate)
	check(err)
	parser.Parse()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"

	"github.com/boltdb/bolt"
	"github.com/codegangsta/cli"
	"github.com/olekukonko/tablewriter"
)

func main() {
	var file string
	var bucket string
	i := impl{}

	cli.AppHelpTemplate = `NAME:
  {{.Name}} - {{.Usage}}

VERSION:
  {{.Version}}

USAGE:
  {{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}

GLOBAL OPTIONS:
  {{range .VisibleFlags}}{{.}}
  {{end}}
AUTHOR:
  {{range .Authors}}{{ . }}{{end}}
`
	app := cli.NewApp()
	app.Name = "bolter"
	app.Usage = "view boltdb file in your terminal"
	app.Version = "1.0.0"
	app.Author = "Hasit Mistry"
	app.Email = "hasitnm@gmail.com"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:        "file, f",
			Usage:       "boltdb `FILE` to view",
			Destination: &file,
		},
		cli.StringFlag{
			Name:        "bucket, b",
			Usage:       "boltdb `BUCKET` to view",
			Destination: &bucket,
		},
	}
	app.Action = func(c *cli.Context) error {
		if file != "" {
			if _, err := os.Stat(file); os.IsNotExist(err) {
				log.Fatal(err)
				return err
			}
			i.initDB(file)
			defer i.DB.Close()
			if bucket != "" {
				i.listBucketItems(bucket)
			} else {
				i.listBuckets()
			}
		} else {
			cli.ShowAppHelp(c)
		}
		return nil
	}
	app.Run(os.Args)
}

type impl struct {
	DB *bolt.DB
}

type item struct {
	Key   string `json:"Key"`
	Value string `json:"Value"`
}

type bucket struct {
	Name string `json:"Name"`
}

func (i *impl) initDB(file string) {
	var err error
	// Read-only permission
	i.DB, err = bolt.Open(file, 0400, nil)
	if err != nil {
		log.Fatal(err)
	}
}

func (i *impl) listBucketItems(bucket string) {
	items := []item{}
	err := i.DB.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(bucket))
		c := b.Cursor()
		for k, v := c.First(); k != nil; k, v = c.Next() {
			items = append(items, item{Key: string(k), Value: string(v)})
		}
		return nil
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Bucket: %s\n", bucket)
	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"Key", "Value"})
	for _, item := range items {
		row := []string{item.Key, item.Value}
		table.Append(row)
	}
	table.Render()
}

func (i *impl) listBuckets() {
	buckets := []bucket{}
	err := i.DB.View(func(tx *bolt.Tx) error {
		return tx.ForEach(func(bucketname []byte, _ *bolt.Bucket) error {
			buckets = append(buckets, bucket{Name: string(bucketname)})
			return nil
		})
	})
	if err != nil {
		log.Fatal(err)
	}
	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"Buckets"})
	for _, b := range buckets {
		row := []string{b.Name}
		table.Append(row)
	}
	table.Render()
}
<commit_msg>It is now possible to list nested buckets.<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"strings"

	"github.com/boltdb/bolt"
	"github.com/codegangsta/cli"
	"github.com/olekukonko/tablewriter"
)

func main() {
	var file string
	var bucket string
	i := impl{}

	cli.AppHelpTemplate = `NAME:
  {{.Name}} - {{.Usage}}

VERSION:
  {{.Version}}

USAGE:
  {{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}

GLOBAL OPTIONS:
  {{range .VisibleFlags}}{{.}}
  {{end}}
AUTHOR:
  {{range .Authors}}{{ . }}{{end}}
`
	app := cli.NewApp()
	app.Name = "bolter"
	app.Usage = "view boltdb file in your terminal"
	app.Version = "1.0.0"
	app.Author = "Hasit Mistry"
	app.Email = "hasitnm@gmail.com"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:        "file, f",
			Usage:       "boltdb `FILE` to view",
			Destination: &file,
		},
		cli.StringFlag{
			Name:        "bucket, b",
			Usage:       "boltdb `BUCKET` to view",
			Destination: &bucket,
		},
	}
	app.Action = func(c *cli.Context) error {
		if file != "" {
			if _, err := os.Stat(file); os.IsNotExist(err) {
				log.Fatal(err)
				return err
			}
			i.initDB(file)
			defer i.DB.Close()
			if bucket != "" {
				i.listBucketItems(bucket)
			} else {
				i.listBuckets()
			}
		} else {
			cli.ShowAppHelp(c)
		}
		return nil
	}
	app.Run(os.Args)
}

type impl struct {
	DB *bolt.DB
}

type item struct {
	Key   string `json:"Key"`
	Value string `json:"Value"`
}

type bucket struct {
	Name string `json:"Name"`
}

func (i *impl) initDB(file string) {
	var err error
	// Read-only permission
	i.DB, err = bolt.Open(file, 0400, nil)
	if err != nil {
		log.Fatal(err)
	}
}

func (i *impl) listBucketItems(bucket string) {
	items := []item{}
	err := i.DB.View(func(tx *bolt.Tx) error {
		nbs := strings.Split(bucket, ".")
		b := tx.Bucket([]byte(nbs[0]))
		if b == nil {
			return nil
		}
		for _, nb := range nbs[1:] {
			b = b.Bucket([]byte(nb))
			if b == nil {
				return nil
			}
		}
		c := b.Cursor()
		for k, v := c.First(); k != nil; k, v = c.Next() {
			items = append(items, item{Key: string(k), Value: string(v)})
		}
		return nil
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Bucket: %s\n", bucket)
	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"Key", "Value"})
	for _, item := range items {
		row := []string{item.Key, item.Value}
		table.Append(row)
	}
	table.Render()
}

func (i *impl) listBuckets() {
	buckets := []bucket{}
	err := i.DB.View(func(tx *bolt.Tx) error {
		return tx.ForEach(func(bucketname []byte, _ *bolt.Bucket) error {
			buckets = append(buckets, bucket{Name: string(bucketname)})
			return nil
		})
	})
	if err != nil {
		log.Fatal(err)
	}
	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"Buckets"})
	for _, b := range buckets {
		row := []string{b.Name}
		table.Append(row)
	}
	table.Render()
}
<|endoftext|>