<commit_before>package main

import (
	"fmt"
	"time"
	"flag"
	"github.com/stealthycoin/evogo"
	"math/rand"
)

var (
	dummies *evogo.Population
	train_com = flag.Bool("t", false, "true to train computer")
)

// Genetic training stuff
type Gene struct {
	// 20 possible board states so we just map each to a number of pennies to remove
	state, choice int
}

func CreateGene(i int) evogo.Gene {
	return Gene{
		state: i,
		choice: rand.Intn(4) + 1,
	}
}

func MutateGene(g evogo.Gene) evogo.Gene {
	gene := g.(Gene)
	old := gene.choice
	for old == gene.choice {
		gene.choice = rand.Intn(4) + 1
	}
	return gene
}

func ShowGenes(i *evogo.Individual) {
	for _, g := range i.Genes() {
		gene := g.(Gene)
		fmt.Printf("%d ", gene.choice)
	}
}

func Fitness(indiv *evogo.Individual, others []*evogo.Individual) int {
	wins := 0
	// Battle other evolving members
	for i, enemy := range others {
		if indiv != enemy {
			if NewGame(NewComputer(indiv, false), NewComputer(others[i], false)).play() == 1 {
				wins++
			}
			if NewGame(NewComputer(others[i], false), NewComputer(indiv, false)).play() == 2 {
				wins++
			}
		}
	}

	// Battle dummies that don't evolve
	for _, enemy := range dummies.Individuals() {
		if NewGame(NewComputer(indiv, false), NewComputer(enemy, false)).play() == 1 {
			wins++
		}
		if NewGame(NewComputer(enemy, false), NewComputer(indiv, false)).play() == 2 {
			wins++
		}
	}

	return wins
}

func main() {
	flag.Parse()
	rand.Seed(time.Now().UTC().UnixNano())
	// Make the dummy population to train against
	dummies = evogo.NewPopulation(1000, 20, 20, CreateGene)

	var strongest *evogo.Individual
	if (*train_com) {
		pop := evogo.NewPopulation(100, 20, 20, CreateGene)
		pop.SetShowIndividual(ShowGenes)
		evogo.Train(pop, 2198, Fitness, MutateGene)
		strongest = pop.Individuals()[0] // Get strongest individual
	} else {
		strongest = dummies.Individuals()[0]
	}

	for {
		// Start games
		var a, b string
		var pa, pb player
		fmt.Print("Player 1 is human or computer (h, c, q to quit): ")
		fmt.Scanf("%v", &a)
		if a == "q" {
			return
		}
		fmt.Print("Player 2 is human or computer (h, c, q to quit): ")
		fmt.Scanf("%v", &b)
		if b == "q" {
			return
		}

		if a == "h" {
			pa = human{}
		} else {
			pa = NewComputer(strongest, true)
		}
		if b == "h" {
			pb = human{}
		} else {
			pb = NewComputer(strongest, true)
		}

		winner := NewGame(pa, pb).play()
		fmt.Println("The winner is player", winner, "\n\n")
	}
}
<commit_msg>STATE WAS OFF MAKING EVERYTHING BAD<commit_after>package main

import (
	"fmt"
	"time"
	"flag"
	"github.com/stealthycoin/evogo"
	"math/rand"
)

var (
	dummies *evogo.Population
	train_com = flag.Bool("t", false, "true to train computer")
)

// Genetic training stuff
type Gene struct {
	// 20 possible board states so we just map each to a number of pennies to remove
	state, choice int
}

func CreateGene(i int) evogo.Gene {
	return Gene{
		state: i+1,
		choice: rand.Intn(4) + 1,
	}
}

func MutateGene(g evogo.Gene) evogo.Gene {
	gene := g.(Gene)
	old := gene.choice
	for old == gene.choice {
		gene.choice = rand.Intn(4) + 1
	}
	return gene
}

func ShowGenes(i *evogo.Individual) {
	for _, g := range i.Genes() {
		gene := g.(Gene)
		fmt.Printf("%d ", gene.choice)
	}
}

func Fitness(indiv *evogo.Individual, others []*evogo.Individual) int {
	wins := 0
	// Battle other evolving members
	for i, enemy := range others {
		if indiv != enemy {
			if NewGame(NewComputer(indiv, false), NewComputer(others[i], false)).play() == 1 {
				wins++
			}
			if NewGame(NewComputer(others[i], false), NewComputer(indiv, false)).play() == 2 {
				wins++
			}
		}
	}

	// Battle dummies that don't evolve
	for _, enemy := range dummies.Individuals() {
		if NewGame(NewComputer(indiv, false), NewComputer(enemy, false)).play() == 1 {
			wins++
		}
		if NewGame(NewComputer(enemy, false), NewComputer(indiv, false)).play() == 2 {
			wins++
		}
	}

	return wins
}

func main() {
	flag.Parse()
	rand.Seed(time.Now().UTC().UnixNano())
	// Make the dummy population to train against
	dummies = evogo.NewPopulation(1000, 20, 20, CreateGene)

	var strongest *evogo.Individual
	if (*train_com) {
		pop := evogo.NewPopulation(100, 20, 20, CreateGene)
		pop.SetShowIndividual(ShowGenes)
		evogo.Train(pop, 2198, Fitness, MutateGene)
		strongest = pop.Individuals()[0] // Get strongest individual
	} else {
		strongest = dummies.Individuals()[0]
	}

	for {
		// Start games
		var a, b string
		var pa, pb player
		fmt.Print("Player 1 is human or computer (h, c, q to quit): ")
		fmt.Scanf("%v", &a)
		if a == "q" {
			return
		}
		fmt.Print("Player 2 is human or computer (h, c, q to quit): ")
		fmt.Scanf("%v", &b)
		if b == "q" {
			return
		}

		if a == "h" {
			pa = human{}
		} else {
			pa = NewComputer(strongest, true)
		}
		if b == "h" {
			pb = human{}
		} else {
			pb = NewComputer(strongest, true)
		}

		winner := NewGame(pa, pb).play()
		fmt.Println("The winner is player", winner, "\n\n")
	}
}
<|endoftext|>


<commit_before>package expr

import (
	"strconv"
	"testing"

	"github.com/grafana/metrictank/api/models"
)

func TestAliasByNodeZero(t *testing.T) {
	testAliasByNode("zero", []models.Series{}, []models.Series{}, t)
}
func TestAliasByNodeSingle(t *testing.T) {
	testAliasByNode(
		"single",
		[]models.Series{
			getQuerySeries("foo.bar.baz", a),
		},
		[]models.Series{
			getTargetSeries("foo", a),
		},
		t,
	)
}

func TestAliasByNodeMultiple(t *testing.T) {
	testAliasByNode(
		"multiple",
		[]models.Series{
			getQuerySeries("1.foo", a),
			getQuerySeries("2.foo", b),
		},
		[]models.Series{
			getTargetSeries("1", a),
			getTargetSeries("2", b),
		},
		t,
	)
}

func makeAliasByNode(in []models.Series, nodes []expr) GraphiteFunc {
	f := NewAliasByNode()
	abn := f.(*FuncAliasByNode)
	abn.nodes = nodes
	abn.in = NewMock(in)
	return f
}

func testAliasByNode(name string, in []models.Series, out []models.Series, t *testing.T) {
	f := makeAliasByNode(in, []expr{expr{etype: etInt, int: 0}})

	// Copy input to check that it is unchanged later
	inputCopy := make([]models.Series, len(in))
	copy(inputCopy, in)

	dataMap := DataMap(make(map[Req][]models.Series))

	got, err := f.Exec(dataMap)
	if err := equalOutput(out, got, nil, err); err != nil {
		t.Fatalf("Case %s: %s", name, err)
	}

	t.Run("DidNotModifyInput", func(t *testing.T) {
		if err := equalOutput(inputCopy, in, nil, nil); err != nil {
			t.Fatalf("Case %s: Input was modified, err = %s", name, err)
		}

	})

	t.Run("DoesNotDoubleReturnPoints", func(t *testing.T) {
		if err := dataMap.CheckForOverlappingPoints(); err != nil {
			t.Fatalf("Case %s: Point slices in datamap overlap, err = %s", name, err)
		}
	})
}

func BenchmarkAliasByNode_1(b *testing.B) {
	benchmarkAliasByNode(b, 1)
}
func BenchmarkAliasByNode_10(b *testing.B) {
	benchmarkAliasByNode(b, 10)
}
func BenchmarkAliasByNode_100(b *testing.B) {
	benchmarkAliasByNode(b, 100)
}
func BenchmarkAliasByNode_1000(b *testing.B) {
	benchmarkAliasByNode(b, 1000)
}

func benchmarkAliasByNode(b *testing.B, numSeries int) {
	var input []models.Series
	for i := 0; i < numSeries; i++ {
		series := models.Series{
			Target: strconv.Itoa(i),
		}
		input = append(input, series)
	}
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		f := NewAliasByNode()
		aliasbynode := f.(*FuncAliasByNode)
		aliasbynode.nodes = []expr{expr{etype: etInt, int: 0}}
		aliasbynode.in = NewMock(input)
		got, err := f.Exec(make(map[Req][]models.Series))
		if err != nil {
			b.Fatalf("%s", err)
		}
		results = got
	}
}
<commit_msg>gofmt<commit_after>package expr

import (
	"strconv"
	"testing"

	"github.com/grafana/metrictank/api/models"
)

func TestAliasByNodeZero(t *testing.T) {
	testAliasByNode("zero", []models.Series{}, []models.Series{}, t)
}
func TestAliasByNodeSingle(t *testing.T) {
	testAliasByNode(
		"single",
		[]models.Series{
			getQuerySeries("foo.bar.baz", a),
		},
		[]models.Series{
			getTargetSeries("foo", a),
		},
		t,
	)
}

func TestAliasByNodeMultiple(t *testing.T) {
	testAliasByNode(
		"multiple",
		[]models.Series{
			getQuerySeries("1.foo", a),
			getQuerySeries("2.foo", b),
		},
		[]models.Series{
			getTargetSeries("1", a),
			getTargetSeries("2", b),
		},
		t,
	)
}

func makeAliasByNode(in []models.Series, nodes []expr) GraphiteFunc {
	f := NewAliasByNode()
	abn := f.(*FuncAliasByNode)
	abn.nodes = nodes
	abn.in = NewMock(in)
	return f
}

func testAliasByNode(name string, in []models.Series, out []models.Series, t *testing.T) {
	f := makeAliasByNode(in, []expr{{etype: etInt, int: 0}})

	// Copy input to check that it is unchanged later
	inputCopy := make([]models.Series, len(in))
	copy(inputCopy, in)

	dataMap := DataMap(make(map[Req][]models.Series))

	got, err := f.Exec(dataMap)
	if err := equalOutput(out, got, nil, err); err != nil {
		t.Fatalf("Case %s: %s", name, err)
	}

	t.Run("DidNotModifyInput", func(t *testing.T) {
		if err := equalOutput(inputCopy, in, nil, nil); err != nil {
			t.Fatalf("Case %s: Input was modified, err = %s", name, err)
		}

	})

	t.Run("DoesNotDoubleReturnPoints", func(t *testing.T) {
		if err := dataMap.CheckForOverlappingPoints(); err != nil {
			t.Fatalf("Case %s: Point slices in datamap overlap, err = %s", name, err)
		}
	})
}

func BenchmarkAliasByNode_1(b *testing.B) {
	benchmarkAliasByNode(b, 1)
}
func BenchmarkAliasByNode_10(b *testing.B) {
	benchmarkAliasByNode(b, 10)
}
func BenchmarkAliasByNode_100(b *testing.B) {
	benchmarkAliasByNode(b, 100)
}
func BenchmarkAliasByNode_1000(b *testing.B) {
	benchmarkAliasByNode(b, 1000)
}

func benchmarkAliasByNode(b *testing.B, numSeries int) {
	var input []models.Series
	for i := 0; i < numSeries; i++ {
		series := models.Series{
			Target: strconv.Itoa(i),
		}
		input = append(input, series)
	}
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		f := NewAliasByNode()
		aliasbynode := f.(*FuncAliasByNode)
		aliasbynode.nodes = []expr{{etype: etInt, int: 0}}
		aliasbynode.in = NewMock(input)
		got, err := f.Exec(make(map[Req][]models.Series))
		if err != nil {
			b.Fatalf("%s", err)
		}
		results = got
	}
}
<|endoftext|>


<commit_before>package guard

import (
	"gopkg.in/workanator/go-floc.v2"
)

// Mock context which propagates all calls to the parent context
// but Done() returns mock channel.
type mockContext struct {
	floc.Context
	mock floc.Context
}

// Release releases the mock context.
func (ctx mockContext) Release() {
	ctx.mock.Release()
}

// Done returns the channel of the mock context.
func (ctx mockContext) Done() <-chan struct{} {
	return ctx.mock.Done()
}

// Resume resumes execution of the flow possibly canceled or completed by
// the job. If filter is empty or nil execution will be resumed regardless
// the reason it was finished. Otherwise execution will be resumed if the
// reason it finished with is in the filter result set.
func Resume(filter floc.ResultSet, job floc.Job) floc.Job {
	// If result filtering is omitted make the job simple with resuming always
	// happen.
	if len(filter) == 0 {
		return func(ctx floc.Context, ctrl floc.Control) error {
			mockCtx := floc.NewContext()
			defer mockCtx.Release()

			mockCtrl := floc.NewControl(mockCtx)
			defer mockCtrl.Release()

			return job(mockContext{ctx, mockCtx}, mockCtrl)
		}
	}

	// Make the job which is aware of the result.
	return func(ctx floc.Context, ctrl floc.Control) error {
		mockCtx := floc.NewContext()
		defer mockCtx.Release()

		mockCtrl := floc.NewControl(mockCtx)
		defer mockCtrl.Release()

		defer func() {
			// Test if execution finished first
			if mockCtrl.IsFinished() {
				res, data, err := mockCtrl.Result()
				if !filter.Contains(res) {
					// Propagate the result
					switch res {
					case floc.Canceled:
						mockCtrl.Cancel(data)
					case floc.Completed:
						mockCtrl.Complete(data)
					case floc.Failed:
						mockCtrl.Fail(data, err)
					}
				}
			}
		}()

		return job(mockContext{ctx, mockCtx}, mockCtrl)
	}
}
<commit_msg>Fix propagation bug<commit_after>package guard

import (
	"gopkg.in/workanator/go-floc.v2"
)

// Mock context which propagates all calls to the parent context
// but Done() returns mock channel.
type mockContext struct {
	floc.Context
	mock floc.Context
}

// Release releases the mock context.
func (ctx mockContext) Release() {
	ctx.mock.Release()
}

// Done returns the channel of the mock context.
func (ctx mockContext) Done() <-chan struct{} {
	return ctx.mock.Done()
}

// Resume resumes execution of the flow possibly canceled or completed by
// the job. If filter is empty or nil execution will be resumed regardless
// the reason it was finished. Otherwise execution will be resumed if the
// reason it finished with is in the filter result set.
func Resume(filter floc.ResultSet, job floc.Job) floc.Job {
	// If result filtering is omitted make the job simple with resuming always
	// happen.
	if len(filter) == 0 {
		return func(ctx floc.Context, ctrl floc.Control) error {
			mockCtx := floc.NewContext()
			defer mockCtx.Release()

			mockCtrl := floc.NewControl(mockCtx)
			defer mockCtrl.Release()

			return job(mockContext{ctx, mockCtx}, mockCtrl)
		}
	}

	// Make the job which is aware of the result.
	return func(ctx floc.Context, ctrl floc.Control) error {
		mockCtx := mockContext{
			Context: ctx,
			mock:    floc.NewContext(),
		}

		mockCtrl := floc.NewControl(mockCtx)

		defer func() {
			mockCtrl.Release()
			mockCtx.Release()

			// Test if execution finished first
			if mockCtrl.IsFinished() {
				res, data, err := mockCtrl.Result()
				if !filter.Contains(res) {
					// Propagate the result
					switch res {
					case floc.Canceled:
						ctrl.Cancel(data)
					case floc.Completed:
						ctrl.Complete(data)
					case floc.Failed:
						ctrl.Fail(data, err)
					}
				}
			}
		}()

		return job(mockCtx, mockCtrl)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"golang.org/x/net/icmp"
	"golang.org/x/net/ipv4"
	"io/ioutil"
	"log"
	"math"
	"math/rand"
	"net"
	"os"
	"strconv"
	"strings"
	"sync"
	"time"
)

type networkMessage struct {
	msg       []byte
	msgType   uint8
	queueable bool
	ts        time.Time
}

type networkConnection struct {
	Conn         *net.UDPConn
	Ip           string
	Port         uint32
	Capability   uint8
	messageQueue [][]byte // Device message queue.
	/*
		Sleep mode/throttle variables. "sleep mode" is actually now just a very reduced packet rate, since we don't know positively
		 when a client is ready to accept packets - we just assume so if we don't receive ICMP Unreachable packets in 5 secs.
	*/
	lastUnreachable time.Time // Last time the device sent an ICMP Unreachable packet.
	nextMessageTime time.Time // The next time that the device is "able" to receive a message.
	numOverflows    uint32    // Number of times the queue has overflowed - for calculating the amount to chop off from the queue.
}

var messageQueue chan networkMessage
var outSockets map[string]networkConnection
var dhcpLeases map[string]string
var netMutex *sync.Mutex

var totalNetworkMessagesSent uint32

var pingResponse map[string]time.Time // Last time an IP responded to an "echo" response.

const (
	NETWORK_GDL90_STANDARD = 1
	NETWORK_AHRS_FFSIM     = 2
	NETWORK_AHRS_GDL90     = 4
	dhcp_lease_file        = "/var/lib/dhcp/dhcpd.leases"
)

// Read the "dhcpd.leases" file and parse out IP/hostname.
func getDHCPLeases() (map[string]string, error) {
	dat, err := ioutil.ReadFile(dhcp_lease_file)
	ret := make(map[string]string)
	if err != nil {
		return ret, err
	}
	lines := strings.Split(string(dat), "\n")
	open_block := false
	block_ip := ""
	for _, line := range lines {
		spaced := strings.Split(line, " ")
		if len(spaced) > 2 && spaced[0] == "lease" {
			open_block = true
			block_ip = spaced[1]
		} else if open_block && len(spaced) >= 4 && spaced[2] == "client-hostname" {
			hostname := strings.TrimRight(strings.TrimLeft(strings.Join(spaced[3:], " "), "\""), "\";")
			ret[block_ip] = hostname
			open_block = false
		} else if open_block && strings.HasPrefix(spaced[0], "}") { // No hostname.
			open_block = false
			ret[block_ip] = ""
		}
	}
	return ret, nil
}

func isSleeping(k string) bool {
	ipAndPort := strings.Split(k, ":")
	lastPing, ok := pingResponse[ipAndPort[0]]
	// No ping response. Assume disconnected/sleeping device.
	if !ok || time.Since(lastPing) > (10*time.Second) {
		return true
	}
	if time.Since(outSockets[k].lastUnreachable) < (5 * time.Second) {
		return true
	}
	return false
}

// Throttle mode for testing port open and giving some start-up time to the app.
// Throttling is 0.1% data rate for first 15 seconds.
func isThrottled(k string) bool {
	return (rand.Int()%1000 != 0) && time.Since(outSockets[k].lastUnreachable) < (15*time.Second)
}

func sendToAllConnectedClients(msg networkMessage) {
	netMutex.Lock()
	defer netMutex.Unlock()
	for k, netconn := range outSockets {
		// Check if this port is able to accept the type of message we're sending.
		if (netconn.Capability & msg.msgType) == 0 {
			continue
		}
		// Send non-queueable messages immediately, or discard if the client is in sleep mode.
		if !msg.queueable {
			if !isSleeping(k) {
				netconn.Conn.Write(msg.msg) // Write immediately.
				totalNetworkMessagesSent++
			}
		} else {
			if !isSleeping(k) {
				netconn.numOverflows = 0 // Reset the overflow counter whenever the client is not sleeping so that we're not penalizing future sleepmodes.
			}
			// Queue the message if the message is "queueable".
			if len(netconn.messageQueue) >= maxUserMsgQueueSize { // Too many messages queued? Drop the oldest.
				log.Printf("%s:%d - message queue overflow.\n", netconn.Ip, netconn.Port)
				netconn.numOverflows++
				s := 2 * netconn.numOverflows // Double the amount we chop off on each overflow.
				if int(s) >= len(netconn.messageQueue) {
					netconn.messageQueue = make([][]byte, 0)
				} else {
					netconn.messageQueue = netconn.messageQueue[s:]
				}
			}
			netconn.messageQueue = append(netconn.messageQueue, msg.msg)
			outSockets[k] = netconn
		}
	}
}

// Just returns the number of DHCP leases for now.
func getNetworkStats() uint {
	ret := uint(len(dhcpLeases))
	globalStatus.Connected_Users = ret
	return ret
}

// See who has a DHCP lease and make a UDP connection to each of them.
func refreshConnectedClients() {
	netMutex.Lock()
	defer netMutex.Unlock()
	validConnections := make(map[string]bool)
	t, err := getDHCPLeases()
	if err != nil {
		log.Printf("getDHCPLeases(): %s\n", err.Error())
		return
	}
	dhcpLeases = t
	// Client connected that wasn't before.
	for ip, hostname := range dhcpLeases {
		for _, networkOutput := range globalSettings.NetworkOutputs {
			ipAndPort := ip + ":" + strconv.Itoa(int(networkOutput.Port))
			if _, ok := outSockets[ipAndPort]; !ok {
				log.Printf("client connected: %s:%d (%s).\n", ip, networkOutput.Port, hostname)
				addr, err := net.ResolveUDPAddr("udp", ipAndPort)
				if err != nil {
					log.Printf("ResolveUDPAddr(%s): %s\n", ipAndPort, err.Error())
					continue
				}
				outConn, err := net.DialUDP("udp", nil, addr)
				if err != nil {
					log.Printf("DialUDP(%s): %s\n", ipAndPort, err.Error())
					continue
				}
				newq := make([][]byte, 0)
				outSockets[ipAndPort] = networkConnection{Conn: outConn, Ip: ip, Port: networkOutput.Port, Capability: networkOutput.Capability, messageQueue: newq}
			}
			validConnections[ipAndPort] = true
		}
	}
	// Client that was connected before that isn't.
	for ipAndPort, conn := range outSockets {
		if _, ok := validConnections[ipAndPort]; !ok {
			log.Printf("removed connection %s.\n", ipAndPort)
			conn.Conn.Close()
			delete(outSockets, ipAndPort)
		}
	}
}

func messageQueueSender() {
	secondTimer := time.NewTicker(5 * time.Second)
	queueTimer := time.NewTicker(1 * time.Second)

	var lastQueueTimeChange time.Time // Reevaluate	send frequency every 5 seconds.
	for {
		select {
		case msg := <-messageQueue:
			sendToAllConnectedClients(msg)
		case <-queueTimer.C:
			netMutex.Lock()

			averageSendableQueueSize := float64(0.0)
			for k, netconn := range outSockets {
				if len(netconn.messageQueue) > 0 && !isSleeping(k) && !isThrottled(k) {
					averageSendableQueueSize += float64(len(netconn.messageQueue)) // Add num sendable messages.

					tmpConn := netconn
					tmpConn.Conn.Write(tmpConn.messageQueue[0])
					totalNetworkMessagesSent++
					tmpConn.messageQueue = tmpConn.messageQueue[1:]
					outSockets[k] = tmpConn
				}
			}

			if time.Since(lastQueueTimeChange) >= 5*time.Second {
				var pd float64
				if averageSendableQueueSize > 0.0 && len(outSockets) > 0 {
					averageSendableQueueSize = averageSendableQueueSize / float64(len(outSockets))  // It's a total, not an average, up until this point.
					pd = math.Max(float64(1.0/2500.0), float64(1.0/(4.0*averageSendableQueueSize))) // Say 250ms is enough to get through the whole queue.
				} else {
					pd = float64(1.0 / 2500.0)
				}
				queueTimer.Stop()
				queueTimer = time.NewTicker(time.Duration(pd*1000000000.0) * time.Nanosecond)
				lastQueueTimeChange = time.Now()
			}
			netMutex.Unlock()
		case <-secondTimer.C:
			getNetworkStats()
		}
	}
}

func sendMsg(msg []byte, msgType uint8, queueable bool) {
	messageQueue <- networkMessage{msg: msg, msgType: msgType, queueable: queueable, ts: time.Now()}
}

func sendGDL90(msg []byte, queueable bool) {
	sendMsg(msg, NETWORK_GDL90_STANDARD, queueable)
}

func monitorDHCPLeases() {
	//TODO: inotify or dhcp event hook.
	timer := time.NewTicker(30 * time.Second)
	for {
		select {
		case <-timer.C:
			refreshConnectedClients()
		}
	}
}

func icmpEchoSender(c *icmp.PacketConn) {
	timer := time.NewTicker(5 * time.Second)
	for {
		<-timer.C
		// Collect IPs.
		ips := make(map[string]bool)
		for k, _ := range outSockets {
			ipAndPort := strings.Split(k, ":")
			ips[ipAndPort[0]] = true
		}
		// Send to all IPs.
		for ip, _ := range ips {
			wm := icmp.Message{
				Type: ipv4.ICMPTypeEcho, Code: 0,
				Body: &icmp.Echo{
					ID: os.Getpid() & 0xffff, Seq: 1,
					Data: []byte("STRATUX"),
				},
			}
			wb, err := wm.Marshal(nil)
			if err != nil {
				log.Printf("couldn't send ICMP Echo: %s\n", err.Error())
				continue
			}
			if _, err := c.WriteTo(wb, &net.IPAddr{IP: net.ParseIP(ip)}); err != nil {
				log.Printf("couldn't send ICMP Echo: %s\n", err.Error())
				continue
			}
			totalNetworkMessagesSent++
		}
	}
}

// Monitor clients going in/out of sleep mode via ICMP unreachable packets.
func sleepMonitor() {
	c, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0")
	if err != nil {
		log.Printf("error listening for udp - sending data to all ports for all connected clients. err: %s", err)
		return
	}
	go icmpEchoSender(c)
	defer c.Close()
	for {
		buf := make([]byte, 1500)
		n, peer, err := c.ReadFrom(buf)
		if err != nil {
			log.Printf("%s\n", err.Error())
			continue
		}
		msg, err := icmp.ParseMessage(1, buf[:n])
		if err != nil {
			continue
		}

		ip := peer.String()

		// Look for echo replies, mark it as received.
		if msg.Type == ipv4.ICMPTypeEchoReply {
			pingResponse[ip] = time.Now()
			continue // No further processing needed.
		}

		// Only deal with ICMP Unreachable packets (since that's what iOS and Android seem to be sending whenever the apps are not available).
		if msg.Type != ipv4.ICMPTypeDestinationUnreachable {
			continue
		}
		// Packet parsing.
		mb, err := msg.Body.Marshal(1)
		if err != nil {
			continue
		}
		if len(mb) < 28 {
			continue
		}

		// The unreachable port.
		port := (uint16(mb[26]) << 8) | uint16(mb[27])
		ipAndPort := ip + ":" + strconv.Itoa(int(port))

		netMutex.Lock()
		p, ok := outSockets[ipAndPort]
		if !ok {
			// Can't do anything, the client isn't even technically connected.
			netMutex.Unlock()
			continue
		}
		p.lastUnreachable = time.Now()
		outSockets[ipAndPort] = p
		netMutex.Unlock()
	}
}

func initNetwork() {
	messageQueue = make(chan networkMessage, 1024) // Buffered channel, 1024 messages.
	outSockets = make(map[string]networkConnection)
	pingResponse = make(map[string]time.Time)
	netMutex = &sync.Mutex{}
	refreshConnectedClients()
	go monitorDHCPLeases()
	go messageQueueSender()
	go sleepMonitor()
}
<commit_msg>Save some cycles when message queues aren't that large.<commit_after>package main

import (
	"golang.org/x/net/icmp"
	"golang.org/x/net/ipv4"
	"io/ioutil"
	"log"
	"math"
	"math/rand"
	"net"
	"os"
	"strconv"
	"strings"
	"sync"
	"time"
)

type networkMessage struct {
	msg       []byte
	msgType   uint8
	queueable bool
	ts        time.Time
}

type networkConnection struct {
	Conn         *net.UDPConn
	Ip           string
	Port         uint32
	Capability   uint8
	messageQueue [][]byte // Device message queue.
	/*
		Sleep mode/throttle variables. "sleep mode" is actually now just a very reduced packet rate, since we don't know positively
		 when a client is ready to accept packets - we just assume so if we don't receive ICMP Unreachable packets in 5 secs.
	*/
	lastUnreachable time.Time // Last time the device sent an ICMP Unreachable packet.
	nextMessageTime time.Time // The next time that the device is "able" to receive a message.
	numOverflows    uint32    // Number of times the queue has overflowed - for calculating the amount to chop off from the queue.
}

var messageQueue chan networkMessage
var outSockets map[string]networkConnection
var dhcpLeases map[string]string
var netMutex *sync.Mutex

var totalNetworkMessagesSent uint32

var pingResponse map[string]time.Time // Last time an IP responded to an "echo" response.

const (
	NETWORK_GDL90_STANDARD = 1
	NETWORK_AHRS_FFSIM     = 2
	NETWORK_AHRS_GDL90     = 4
	dhcp_lease_file        = "/var/lib/dhcp/dhcpd.leases"
)

// Read the "dhcpd.leases" file and parse out IP/hostname.
func getDHCPLeases() (map[string]string, error) {
	dat, err := ioutil.ReadFile(dhcp_lease_file)
	ret := make(map[string]string)
	if err != nil {
		return ret, err
	}
	lines := strings.Split(string(dat), "\n")
	open_block := false
	block_ip := ""
	for _, line := range lines {
		spaced := strings.Split(line, " ")
		if len(spaced) > 2 && spaced[0] == "lease" {
			open_block = true
			block_ip = spaced[1]
		} else if open_block && len(spaced) >= 4 && spaced[2] == "client-hostname" {
			hostname := strings.TrimRight(strings.TrimLeft(strings.Join(spaced[3:], " "), "\""), "\";")
			ret[block_ip] = hostname
			open_block = false
		} else if open_block && strings.HasPrefix(spaced[0], "}") { // No hostname.
			open_block = false
			ret[block_ip] = ""
		}
	}
	return ret, nil
}

func isSleeping(k string) bool {
	ipAndPort := strings.Split(k, ":")
	lastPing, ok := pingResponse[ipAndPort[0]]
	// No ping response. Assume disconnected/sleeping device.
	if !ok || time.Since(lastPing) > (10*time.Second) {
		return true
	}
	if time.Since(outSockets[k].lastUnreachable) < (5 * time.Second) {
		return true
	}
	return false
}

// Throttle mode for testing port open and giving some start-up time to the app.
// Throttling is 0.1% data rate for first 15 seconds.
func isThrottled(k string) bool {
	return (rand.Int()%1000 != 0) && time.Since(outSockets[k].lastUnreachable) < (15*time.Second)
}

func sendToAllConnectedClients(msg networkMessage) {
	netMutex.Lock()
	defer netMutex.Unlock()
	for k, netconn := range outSockets {
		// Check if this port is able to accept the type of message we're sending.
		if (netconn.Capability & msg.msgType) == 0 {
			continue
		}
		// Send non-queueable messages immediately, or discard if the client is in sleep mode.
		if !msg.queueable {
			if !isSleeping(k) {
				netconn.Conn.Write(msg.msg) // Write immediately.
				totalNetworkMessagesSent++
			}
		} else {
			if !isSleeping(k) {
				netconn.numOverflows = 0 // Reset the overflow counter whenever the client is not sleeping so that we're not penalizing future sleepmodes.
			}
			// Queue the message if the message is "queueable".
			if len(netconn.messageQueue) >= maxUserMsgQueueSize { // Too many messages queued? Drop the oldest.
				log.Printf("%s:%d - message queue overflow.\n", netconn.Ip, netconn.Port)
				netconn.numOverflows++
				s := 2 * netconn.numOverflows // Double the amount we chop off on each overflow.
				if int(s) >= len(netconn.messageQueue) {
					netconn.messageQueue = make([][]byte, 0)
				} else {
					netconn.messageQueue = netconn.messageQueue[s:]
				}
			}
			netconn.messageQueue = append(netconn.messageQueue, msg.msg)
			outSockets[k] = netconn
		}
	}
}

// Just returns the number of DHCP leases for now.
func getNetworkStats() uint {
	ret := uint(len(dhcpLeases))
	globalStatus.Connected_Users = ret
	return ret
}

// See who has a DHCP lease and make a UDP connection to each of them.
func refreshConnectedClients() {
	netMutex.Lock()
	defer netMutex.Unlock()
	validConnections := make(map[string]bool)
	t, err := getDHCPLeases()
	if err != nil {
		log.Printf("getDHCPLeases(): %s\n", err.Error())
		return
	}
	dhcpLeases = t
	// Client connected that wasn't before.
	for ip, hostname := range dhcpLeases {
		for _, networkOutput := range globalSettings.NetworkOutputs {
			ipAndPort := ip + ":" + strconv.Itoa(int(networkOutput.Port))
			if _, ok := outSockets[ipAndPort]; !ok {
				log.Printf("client connected: %s:%d (%s).\n", ip, networkOutput.Port, hostname)
				addr, err := net.ResolveUDPAddr("udp", ipAndPort)
				if err != nil {
					log.Printf("ResolveUDPAddr(%s): %s\n", ipAndPort, err.Error())
					continue
				}
				outConn, err := net.DialUDP("udp", nil, addr)
				if err != nil {
					log.Printf("DialUDP(%s): %s\n", ipAndPort, err.Error())
					continue
				}
				newq := make([][]byte, 0)
				outSockets[ipAndPort] = networkConnection{Conn: outConn, Ip: ip, Port: networkOutput.Port, Capability: networkOutput.Capability, messageQueue: newq}
			}
			validConnections[ipAndPort] = true
		}
	}
	// Client that was connected before that isn't.
	for ipAndPort, conn := range outSockets {
		if _, ok := validConnections[ipAndPort]; !ok {
			log.Printf("removed connection %s.\n", ipAndPort)
			conn.Conn.Close()
			delete(outSockets, ipAndPort)
		}
	}
}

func messageQueueSender() {
	secondTimer := time.NewTicker(5 * time.Second)
	queueTimer := time.NewTicker(100 * time.Millisecond)

	var lastQueueTimeChange time.Time // Reevaluate	send frequency every 5 seconds.
	for {
		select {
		case msg := <-messageQueue:
			sendToAllConnectedClients(msg)
		case <-queueTimer.C:
			netMutex.Lock()

			averageSendableQueueSize := float64(0.0)
			for k, netconn := range outSockets {
				if len(netconn.messageQueue) > 0 && !isSleeping(k) && !isThrottled(k) {
					averageSendableQueueSize += float64(len(netconn.messageQueue)) // Add num sendable messages.

					tmpConn := netconn
					tmpConn.Conn.Write(tmpConn.messageQueue[0])
					totalNetworkMessagesSent++
					tmpConn.messageQueue = tmpConn.messageQueue[1:]
					outSockets[k] = tmpConn
				}
			}

			if time.Since(lastQueueTimeChange) >= 5*time.Second {
				var pd float64
				if averageSendableQueueSize > 0.0 && len(outSockets) > 0 {
					averageSendableQueueSize = averageSendableQueueSize / float64(len(outSockets))  // It's a total, not an average, up until this point.
					pd = math.Max(float64(1.0/2500.0), float64(1.0/(4.0*averageSendableQueueSize))) // Say 250ms is enough to get through the whole queue.
				} else {
					pd = float64(1.0 / 0.1) // 100ms.
				}
				queueTimer.Stop()
				queueTimer = time.NewTicker(time.Duration(pd*1000000000.0) * time.Nanosecond)
				lastQueueTimeChange = time.Now()
			}
			netMutex.Unlock()
		case <-secondTimer.C:
			getNetworkStats()
		}
	}
}

func sendMsg(msg []byte, msgType uint8, queueable bool) {
	messageQueue <- networkMessage{msg: msg, msgType: msgType, queueable: queueable, ts: time.Now()}
}

func sendGDL90(msg []byte, queueable bool) {
	sendMsg(msg, NETWORK_GDL90_STANDARD, queueable)
}

func monitorDHCPLeases() {
	//TODO: inotify or dhcp event hook.
	timer := time.NewTicker(30 * time.Second)
	for {
		select {
		case <-timer.C:
			refreshConnectedClients()
		}
	}
}

func icmpEchoSender(c *icmp.PacketConn) {
	timer := time.NewTicker(5 * time.Second)
	for {
		<-timer.C
		// Collect IPs.
		ips := make(map[string]bool)
		for k, _ := range outSockets {
			ipAndPort := strings.Split(k, ":")
			ips[ipAndPort[0]] = true
		}
		// Send to all IPs.
		for ip, _ := range ips {
			wm := icmp.Message{
				Type: ipv4.ICMPTypeEcho, Code: 0,
				Body: &icmp.Echo{
					ID: os.Getpid() & 0xffff, Seq: 1,
					Data: []byte("STRATUX"),
				},
			}
			wb, err := wm.Marshal(nil)
			if err != nil {
				log.Printf("couldn't send ICMP Echo: %s\n", err.Error())
				continue
			}
			if _, err := c.WriteTo(wb, &net.IPAddr{IP: net.ParseIP(ip)}); err != nil {
				log.Printf("couldn't send ICMP Echo: %s\n", err.Error())
				continue
			}
			totalNetworkMessagesSent++
		}
	}
}

// Monitor clients going in/out of sleep mode via ICMP unreachable packets.
func sleepMonitor() {
	c, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0")
	if err != nil {
		log.Printf("error listening for udp - sending data to all ports for all connected clients. err: %s", err)
		return
	}
	go icmpEchoSender(c)
	defer c.Close()
	for {
		buf := make([]byte, 1500)
		n, peer, err := c.ReadFrom(buf)
		if err != nil {
			log.Printf("%s\n", err.Error())
			continue
		}
		msg, err := icmp.ParseMessage(1, buf[:n])
		if err != nil {
			continue
		}

		ip := peer.String()

		// Look for echo replies, mark it as received.
		if msg.Type == ipv4.ICMPTypeEchoReply {
			pingResponse[ip] = time.Now()
			continue // No further processing needed.
		}

		// Only deal with ICMP Unreachable packets (since that's what iOS and Android seem to be sending whenever the apps are not available).
		if msg.Type != ipv4.ICMPTypeDestinationUnreachable {
			continue
		}
		// Packet parsing.
		mb, err := msg.Body.Marshal(1)
		if err != nil {
			continue
		}
		if len(mb) < 28 {
			continue
		}

		// The unreachable port.
		port := (uint16(mb[26]) << 8) | uint16(mb[27])
		ipAndPort := ip + ":" + strconv.Itoa(int(port))

		netMutex.Lock()
		p, ok := outSockets[ipAndPort]
		if !ok {
			// Can't do anything, the client isn't even technically connected.
			netMutex.Unlock()
			continue
		}
		p.lastUnreachable = time.Now()
		outSockets[ipAndPort] = p
		netMutex.Unlock()
	}
}

func initNetwork() {
	messageQueue = make(chan networkMessage, 1024) // Buffered channel, 1024 messages.
	outSockets = make(map[string]networkConnection)
	pingResponse = make(map[string]time.Time)
	netMutex = &sync.Mutex{}
	refreshConnectedClients()
	go monitorDHCPLeases()
	go messageQueueSender()
	go sleepMonitor()
}
<|endoftext|>


<commit_before>package script

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"strings"

	"gopkg.in/yaml.v1"

	"github.com/drone/drone/plugin/deploy"
	"github.com/drone/drone/plugin/notify"
	"github.com/drone/drone/plugin/publish"
	"github.com/drone/drone/shared/build/buildfile"
	"github.com/drone/drone/shared/build/git"
	"github.com/drone/drone/shared/build/repo"
)

func ParseBuild(data string, params map[string]string) (*Build, error) {
	build := Build{}

	// parse the build configuration file
	err := yaml.Unmarshal(injectParams([]byte(data), params), &build)
	return &build, err
}

func ParseBuildFile(filename string) (*Build, error) {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}

	return ParseBuild(string(data), nil)
}

// injectParams injects params into data.
func injectParams(data []byte, params map[string]string) []byte {
	for k, v := range params {
		data = bytes.Replace(data, []byte(fmt.Sprintf("{{%s}}", k)), []byte(v), -1)
	}
	return data
}

// Build stores the configuration details for
// building, testing and deploying code.
type Build struct {
	// Image specifies the Docker Image that will be
	// used to virtualize the Build process.
	Image string

	// Name specifies a user-defined label used
	// to identify the build.
	Name string

	// Script specifies the build and test commands.
	Script []string

	// Env specifies the environment of the build.
	Env []string

	// Hosts specifies the custom IP address and
	// hostname mappings.
	Hosts []string

	// Cache lists a set of directories that should
	// persisted between builds.
	Cache []string

	// Services specifies external services, such as
	// database or messaging queues, that should be
	// linked to the build environment.
	Services []string

	// White-list of Branches that are built.
	Branches []string

	Deploy        *deploy.Deploy       `yaml:"deploy,omitempty"`
	Publish       *publish.Publish     `yaml:"publish,omitempty"`
	Notifications *notify.Notification `yaml:"notify,omitempty"`

	// Git specified git-specific parameters, such as
	// the clone depth and path
	Git *git.Git `yaml:"git,omitempty"`
}

// Write adds all the steps to the build script, including
// build commands, deploy and publish commands.
func (b *Build) Write(f *buildfile.Buildfile, r *repo.Repo) {
	// append build commands
	b.WriteBuild(f)

	// write publish commands
	if b.Publish != nil {
		b.Publish.Write(f, r)
	}

	// write deployment commands
	if b.Deploy != nil {
		b.Deploy.Write(f)
	}

	// write exit value
	f.WriteCmd("exit 0")
}

// WriteBuild adds only the build steps to the build script,
// omitting publish and deploy steps. This is important for
// pull requests, where deployment would be undesirable.
func (b *Build) WriteBuild(f *buildfile.Buildfile) {
	// append environment variables
	for _, env := range b.Env {
		parts := strings.Split(env, "=")
		if len(parts) != 2 {
			continue
		}
		f.WriteEnv(parts[0], parts[1])
	}

	// append build commands
	for _, cmd := range b.Script {
		f.WriteCmd(cmd)
	}
}

func (b *Build) MatchBranch(branch string) bool {
	if len(b.Branches) == 0 {
		return true
	}
	for _, item := range b.Branches {
		if item == branch {
			return true
		}
	}
	return false
}

type Publish interface {
	Write(f *buildfile.Buildfile)
}

type Deployment interface {
	Write(f *buildfile.Buildfile)
}

type Notification interface {
	Set(c Context)
}

type Context interface {
	Host() string
	Owner() string
	Name() string

	Branch() string
	Hash() string
	Status() string
	Message() string
	Author() string
	Gravatar() string

	Duration() int64
	HumanDuration() string

	//Settings
}
<commit_msg>Update script.go<commit_after>package script

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"strings"

	"gopkg.in/yaml.v1"

	"github.com/drone/drone/plugin/deploy"
	"github.com/drone/drone/plugin/notify"
	"github.com/drone/drone/plugin/publish"
	"github.com/drone/drone/shared/build/buildfile"
	"github.com/drone/drone/shared/build/git"
	"github.com/drone/drone/shared/build/repo"
)

func ParseBuild(data string, params map[string]string) (*Build, error) {
	build := Build{}

	// parse the build configuration file
	err := yaml.Unmarshal(injectParams([]byte(data), params), &build)
	return &build, err
}

func ParseBuildFile(filename string) (*Build, error) {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}

	return ParseBuild(string(data), nil)
}

// injectParams injects params into data.
func injectParams(data []byte, params map[string]string) []byte {
	for k, v := range params {
		data = bytes.Replace(data, []byte(fmt.Sprintf("{{%s}}", k)), []byte(v), -1)
	}
	return data
}

// Build stores the configuration details for
// building, testing and deploying code.
type Build struct {
	// Image specifies the Docker Image that will be
	// used to virtualize the Build process.
	Image string

	// Name specifies a user-defined label used
	// to identify the build.
	Name string

	// Script specifies the build and test commands.
	Script []string

	// Env specifies the environment of the build.
	Env []string

	// Hosts specifies the custom IP address and
	// hostname mappings.
	Hosts []string

	// Cache lists a set of directories that should
	// persisted between builds.
	Cache []string

	// Services specifies external services, such as
	// database or messaging queues, that should be
	// linked to the build environment.
	Services []string

	// White-list of Branches that are built.
	Branches []string

	Deploy        *deploy.Deploy       `yaml:"deploy,omitempty"`
	Publish       *publish.Publish     `yaml:"publish,omitempty"`
	Notifications *notify.Notification `yaml:"notify"`

	// Git specified git-specific parameters, such as
	// the clone depth and path
	Git *git.Git `yaml:"git,omitempty"`
}

// Write adds all the steps to the build script, including
// build commands, deploy and publish commands.
func (b *Build) Write(f *buildfile.Buildfile, r *repo.Repo) {
	// append build commands
	b.WriteBuild(f)

	// write publish commands
	if b.Publish != nil {
		b.Publish.Write(f, r)
	}

	// write deployment commands
	if b.Deploy != nil {
		b.Deploy.Write(f)
	}

	// write exit value
	f.WriteCmd("exit 0")
}

// WriteBuild adds only the build steps to the build script,
// omitting publish and deploy steps. This is important for
// pull requests, where deployment would be undesirable.
func (b *Build) WriteBuild(f *buildfile.Buildfile) {
	// append environment variables
	for _, env := range b.Env {
		parts := strings.Split(env, "=")
		if len(parts) != 2 {
			continue
		}
		f.WriteEnv(parts[0], parts[1])
	}

	// append build commands
	for _, cmd := range b.Script {
		f.WriteCmd(cmd)
	}
}

func (b *Build) MatchBranch(branch string) bool {
	if len(b.Branches) == 0 {
		return true
	}
	for _, item := range b.Branches {
		if item == branch {
			return true
		}
	}
	return false
}

type Publish interface {
	Write(f *buildfile.Buildfile)
}

type Deployment interface {
	Write(f *buildfile.Buildfile)
}

type Notification interface {
	Set(c Context)
}

type Context interface {
	Host() string
	Owner() string
	Name() string

	Branch() string
	Hash() string
	Status() string
	Message() string
	Author() string
	Gravatar() string

	Duration() int64
	HumanDuration() string

	//Settings
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2017 Bitnami

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 main

import (
	"bytes"
	"encoding/json"
	"errors"
	"net/http"
	"net/http/httptest"
	"reflect"
	"testing"

	"github.com/kubeapps/ratesvc/testutil"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/mock"
	"github.com/stretchr/testify/require"
	"gopkg.in/mgo.v2/bson"
)

type body struct {
	Data []item `json:"data"`
}

var itemsList []*item

func TestGetStars(t *testing.T) {
	var m mock.Mock
	dbSession = testutil.NewMockSession(&m)
	currentUser := bson.NewObjectId()
	oldGetCurrentUserID := getCurrentUserID
	getCurrentUserID = func(_ *http.Request) (bson.ObjectId, error) { return currentUser, nil }
	defer func() { getCurrentUserID = oldGetCurrentUserID }()
	tests := []struct {
		name          string
		items         []*item
		starredByUser bool
	}{
		{"no stars", []*item{
			{ID: "stable/wordpress", Type: "chart", StargazersIDs: []bson.ObjectId{}},
		}, false},
		{"stars", []*item{
			{ID: "stable/wordpress", Type: "chart", StargazersIDs: []bson.ObjectId{bson.NewObjectId(), bson.NewObjectId()}},
			{ID: "stable/drupal", Type: "chart", StargazersIDs: []bson.ObjectId{bson.NewObjectId()}},
		}, false},
		{"starred by user", []*item{
			{ID: "stable/wordpress", Type: "chart", StargazersIDs: []bson.ObjectId{bson.NewObjectId(), currentUser}},
		}, true},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			m.On("All", &itemsList).Run(func(args mock.Arguments) {
				*args.Get(0).(*[]*item) = tt.items
			})

			w := httptest.NewRecorder()
			req := httptest.NewRequest("GET", "/v1/stars", nil)
			GetStars(w, req)
			assert.Equal(t, http.StatusOK, w.Code)
			var b body
			json.NewDecoder(w.Body).Decode(&b)
			require.Len(t, b.Data, len(tt.items))
			for i, it := range tt.items {
				assert.Equal(t, len(it.StargazersIDs), b.Data[i].StargazersCount, "%s stars", it.ID)
				if tt.starredByUser {
					assert.True(t, it.HasStarred)
				}
			}
		})
	}
}

func TestUpdateStar(t *testing.T) {
	var m mock.Mock
	m.On("One", &item{}).Return(nil).Run(func(args mock.Arguments) {
		*args.Get(0).(*item) = item{ID: "stable/wordpress"}
	})
	dbSession = testutil.NewMockSession(&m)
	currentUser := bson.NewObjectId()
	oldGetCurrentUserID := getCurrentUserID
	getCurrentUserID = func(_ *http.Request) (bson.ObjectId, error) { return currentUser, nil }
	defer func() { getCurrentUserID = oldGetCurrentUserID }()
	tests := []struct {
		name        string
		requestBody string
		wantCode    int
		unstar      bool
	}{
		{"invalid", `NOTJSON`, http.StatusBadRequest, false},
		{"no id", `{"has_starred": true}`, http.StatusBadRequest, false},
		{"valid", `{"id": "stable/wordpress", "has_starred": true}`, http.StatusCreated, false},
		{"valid unstar", `{"id": "stable/wordpress", "has_starred": false}`, http.StatusCreated, true},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if tt.wantCode == http.StatusCreated {
				op := "$push"
				if tt.unstar {
					op = "$pull"
				}
				m.On("UpdateId", "stable/wordpress", bson.M{op: bson.M{"stargazers_ids": currentUser}})
			}

			w := httptest.NewRecorder()
			req := httptest.NewRequest("PUT", "/v1/stars", bytes.NewBuffer([]byte(tt.requestBody)))
			UpdateStar(w, req)
			assert.Equal(t, tt.wantCode, w.Code)
		})
	}
}

func TestUpdateStarDoesNotDuplicate(t *testing.T) {
	var m mock.Mock
	currentUser := bson.NewObjectId()
	m.On("One", &item{}).Return(nil).Run(func(args mock.Arguments) {
		*args.Get(0).(*item) = item{ID: "stable/wordpress", StargazersIDs: []bson.ObjectId{currentUser}}
	})
	dbSession = testutil.NewMockSession(&m)
	oldGetCurrentUserID := getCurrentUserID
	getCurrentUserID = func(_ *http.Request) (bson.ObjectId, error) { return currentUser, nil }
	defer func() { getCurrentUserID = oldGetCurrentUserID }()
	tests := []struct {
		name        string
		requestBody string
		wantCode    int
	}{
		{"noop", `{"id": "stable/wordpress", "has_starred": true}`, http.StatusOK},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			m.AssertNotCalled(t, "UpdateId")

			w := httptest.NewRecorder()
			req := httptest.NewRequest("PUT", "/v1/stars", bytes.NewBuffer([]byte(tt.requestBody)))
			UpdateStar(w, req)
			assert.Equal(t, tt.wantCode, w.Code)
		})
	}
}

func TestUpdateStarInsertsInexistantItem(t *testing.T) {
	var m mock.Mock
	m.On("One", &item{}).Return(errors.New("not found"))
	dbSession = testutil.NewMockSession(&m)
	currentUser := bson.NewObjectId()
	oldGetCurrentUserID := getCurrentUserID
	getCurrentUserID = func(_ *http.Request) (bson.ObjectId, error) { return currentUser, nil }
	defer func() { getCurrentUserID = oldGetCurrentUserID }()
	tests := []struct {
		name        string
		requestBody string
		unstar      bool
	}{
		{"valid", `{"id": "stable/wordpress", "has_starred": true}`, false},
		{"valid unstar", `{"id": "stable/wordpress", "has_starred": false}`, true},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			toInsert := item{ID: "stable/wordpress", Type: "chart", HasStarred: !tt.unstar}
			if !tt.unstar {
				toInsert.StargazersIDs = []bson.ObjectId{currentUser}
			}
			m.On("Insert", toInsert)

			w := httptest.NewRecorder()
			req := httptest.NewRequest("PUT", "/v1/stars", bytes.NewBuffer([]byte(tt.requestBody)))
			UpdateStar(w, req)
			assert.Equal(t, http.StatusCreated, w.Code)
		})
	}
}

func TestUpdateStarUnauthorized(t *testing.T) {
	var m mock.Mock
	dbSession = testutil.NewMockSession(&m)
	w := httptest.NewRecorder()
	req := httptest.NewRequest("PUT", "/v1/stars", nil)
	UpdateStar(w, req)
	assert.Equal(t, http.StatusUnauthorized, w.Code)
}

func TestGetComments(t *testing.T) {
	type args struct {
		w   http.ResponseWriter
		req *http.Request
	}
	tests := []struct {
		name string
		args args
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			GetComments(tt.args.w, tt.args.req)
		})
	}
}

func TestCreateComment(t *testing.T) {
	type args struct {
		w   http.ResponseWriter
		req *http.Request
	}
	tests := []struct {
		name string
		args args
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			CreateComment(tt.args.w, tt.args.req)
		})
	}
}

func Test_getCurrentUserID(t *testing.T) {
	type args struct {
		req *http.Request
	}
	tests := []struct {
		name    string
		args    args
		want    bson.ObjectId
		wantErr bool
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := getCurrentUserID(tt.args.req)
			if (err != nil) != tt.wantErr {
				t.Errorf("getCurrentUserID() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if !reflect.DeepEqual(got, tt.want) {
				t.Errorf("getCurrentUserID() = %v, want %v", got, tt.want)
			}
		})
	}
}
<commit_msg>clean up the test<commit_after>/*
Copyright (c) 2017 Bitnami

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 main

import (
	"bytes"
	"encoding/json"
	"errors"
	"net/http"
	"net/http/httptest"
	"reflect"
	"testing"

	"github.com/kubeapps/ratesvc/testutil"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/mock"
	"github.com/stretchr/testify/require"
	"gopkg.in/mgo.v2/bson"
)

type body struct {
	Data []item `json:"data"`
}

var itemsList []*item

func TestGetStars(t *testing.T) {
	var m mock.Mock
	dbSession = testutil.NewMockSession(&m)
	currentUser := bson.NewObjectId()
	oldGetCurrentUserID := getCurrentUserID
	getCurrentUserID = func(_ *http.Request) (bson.ObjectId, error) { return currentUser, nil }
	defer func() { getCurrentUserID = oldGetCurrentUserID }()
	tests := []struct {
		name          string
		items         []*item
		starredByUser bool
	}{
		{"no stars", []*item{
			{ID: "stable/wordpress", Type: "chart", StargazersIDs: []bson.ObjectId{}},
		}, false},
		{"stars", []*item{
			{ID: "stable/wordpress", Type: "chart", StargazersIDs: []bson.ObjectId{bson.NewObjectId(), bson.NewObjectId()}},
			{ID: "stable/drupal", Type: "chart", StargazersIDs: []bson.ObjectId{bson.NewObjectId()}},
		}, false},
		{"starred by user", []*item{
			{ID: "stable/wordpress", Type: "chart", StargazersIDs: []bson.ObjectId{bson.NewObjectId(), currentUser}},
		}, true},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			m.On("All", &itemsList).Run(func(args mock.Arguments) {
				*args.Get(0).(*[]*item) = tt.items
			})

			w := httptest.NewRecorder()
			req := httptest.NewRequest("GET", "/v1/stars", nil)
			GetStars(w, req)
			assert.Equal(t, http.StatusOK, w.Code)
			var b body
			json.NewDecoder(w.Body).Decode(&b)
			require.Len(t, b.Data, len(tt.items))
			for i, it := range tt.items {
				assert.Equal(t, len(it.StargazersIDs), b.Data[i].StargazersCount, "%s stars", it.ID)
				if tt.starredByUser {
					assert.True(t, it.HasStarred)
				}
			}
		})
	}
}

func TestUpdateStar(t *testing.T) {
	var m mock.Mock
	m.On("One", &item{}).Return(nil).Run(func(args mock.Arguments) {
		*args.Get(0).(*item) = item{ID: "stable/wordpress"}
	})
	dbSession = testutil.NewMockSession(&m)
	currentUser := bson.NewObjectId()
	oldGetCurrentUserID := getCurrentUserID
	getCurrentUserID = func(_ *http.Request) (bson.ObjectId, error) { return currentUser, nil }
	defer func() { getCurrentUserID = oldGetCurrentUserID }()
	tests := []struct {
		name        string
		requestBody string
		wantCode    int
		unstar      bool
	}{
		{"invalid", `NOTJSON`, http.StatusBadRequest, false},
		{"no id", `{"has_starred": true}`, http.StatusBadRequest, false},
		{"valid", `{"id": "stable/wordpress", "has_starred": true}`, http.StatusCreated, false},
		{"valid unstar", `{"id": "stable/wordpress", "has_starred": false}`, http.StatusCreated, true},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if tt.wantCode == http.StatusCreated {
				op := "$push"
				if tt.unstar {
					op = "$pull"
				}
				m.On("UpdateId", "stable/wordpress", bson.M{op: bson.M{"stargazers_ids": currentUser}})
			}

			w := httptest.NewRecorder()
			req := httptest.NewRequest("PUT", "/v1/stars", bytes.NewBuffer([]byte(tt.requestBody)))
			UpdateStar(w, req)
			assert.Equal(t, tt.wantCode, w.Code)
		})
	}
}

func TestUpdateStarDoesNotDuplicate(t *testing.T) {
	var m mock.Mock
	currentUser := bson.NewObjectId()
	m.On("One", &item{}).Return(nil).Run(func(args mock.Arguments) {
		*args.Get(0).(*item) = item{ID: "stable/wordpress", StargazersIDs: []bson.ObjectId{currentUser}}
	})
	dbSession = testutil.NewMockSession(&m)
	oldGetCurrentUserID := getCurrentUserID
	getCurrentUserID = func(_ *http.Request) (bson.ObjectId, error) { return currentUser, nil }
	defer func() { getCurrentUserID = oldGetCurrentUserID }()

	m.AssertNotCalled(t, "UpdateId")
	w := httptest.NewRecorder()
	requestBody := `{"id": "stable/wordpress", "has_starred": true}`
	req := httptest.NewRequest("PUT", "/v1/stars", bytes.NewBuffer([]byte(requestBody)))
	UpdateStar(w, req)
	assert.Equal(t, http.StatusOK, w.Code)
}

func TestUpdateStarInsertsInexistantItem(t *testing.T) {
	var m mock.Mock
	m.On("One", &item{}).Return(errors.New("not found"))
	dbSession = testutil.NewMockSession(&m)
	currentUser := bson.NewObjectId()
	oldGetCurrentUserID := getCurrentUserID
	getCurrentUserID = func(_ *http.Request) (bson.ObjectId, error) { return currentUser, nil }
	defer func() { getCurrentUserID = oldGetCurrentUserID }()
	tests := []struct {
		name        string
		requestBody string
		unstar      bool
	}{
		{"valid", `{"id": "stable/wordpress", "has_starred": true}`, false},
		{"valid unstar", `{"id": "stable/wordpress", "has_starred": false}`, true},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			toInsert := item{ID: "stable/wordpress", Type: "chart", HasStarred: !tt.unstar}
			if !tt.unstar {
				toInsert.StargazersIDs = []bson.ObjectId{currentUser}
			}
			m.On("Insert", toInsert)

			w := httptest.NewRecorder()
			req := httptest.NewRequest("PUT", "/v1/stars", bytes.NewBuffer([]byte(tt.requestBody)))
			UpdateStar(w, req)
			assert.Equal(t, http.StatusCreated, w.Code)
		})
	}
}

func TestUpdateStarUnauthorized(t *testing.T) {
	var m mock.Mock
	dbSession = testutil.NewMockSession(&m)
	w := httptest.NewRecorder()
	req := httptest.NewRequest("PUT", "/v1/stars", nil)
	UpdateStar(w, req)
	assert.Equal(t, http.StatusUnauthorized, w.Code)
}

func TestGetComments(t *testing.T) {
	type args struct {
		w   http.ResponseWriter
		req *http.Request
	}
	tests := []struct {
		name string
		args args
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			GetComments(tt.args.w, tt.args.req)
		})
	}
}

func TestCreateComment(t *testing.T) {
	type args struct {
		w   http.ResponseWriter
		req *http.Request
	}
	tests := []struct {
		name string
		args args
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			CreateComment(tt.args.w, tt.args.req)
		})
	}
}

func Test_getCurrentUserID(t *testing.T) {
	type args struct {
		req *http.Request
	}
	tests := []struct {
		name    string
		args    args
		want    bson.ObjectId
		wantErr bool
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := getCurrentUserID(tt.args.req)
			if (err != nil) != tt.wantErr {
				t.Errorf("getCurrentUserID() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if !reflect.DeepEqual(got, tt.want) {
				t.Errorf("getCurrentUserID() = %v, want %v", got, tt.want)
			}
		})
	}
}
<|endoftext|>


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

package hashmap

import "testing"

type Integer int;

func (self Integer) Hash() uint { return uint(self*self) }
func (self Integer) Equal(other Hashable) bool { return self == other.(Integer) }

func TestZeroLen(t *testing.T) {
	a := New()
	if a.Len() != 0 {
		t.Errorf("expected 0, got %d", a.Len())
	}
}

func TestZeroLookup(t *testing.T) {
	const Len = 10000
	a := New()
	for i := 0; i < Len; i++ {
		if a.Has(Integer(i)) {
			t.Errorf("found %d in empty hashmap", i)
		}
	}
}

func TestInsert(t *testing.T) {
	const Len = 10000
	a := New()
	for i := 0; i < Len; i++ {
		a.Insert(Integer(i), i)
	}
	for i := 0; i < Len; i++ {
		if !a.Has(Integer(i)) {
			t.Errorf("inserted %d not found", i)
		}
	}
}

func TestRemove(t *testing.T) {
	const Len = 10000
	a := New()
	for i := 0; i < Len; i++ {
		a.Insert(Integer(i), i)
	}
	for i := 0; i < Len; i++ {
		a.Remove(Integer(i))
	}
	for i := 0; i < Len; i++ {
		if a.Has(Integer(i)) {
			t.Errorf("removed %d was found", i)
		}
	}
}

func TestIter(t *testing.T) {
	const Len = 100
	x := New()
	for i := 0; i < Len; i++ {
		x.Insert(Integer(i), i*i)
	}
	i := 0
	for v := range x.Iter() {
		p := v.(HashPair)
		key := p.key.(Integer)
		val := p.value.(int)
		if key*key != Integer(val) {
			t.Error("Iter expected", key*key, "got", val)
		}
		i++
	}
	if i != Len {
		t.Error("Iter stopped at", i, "not", Len)
	}
}

func BenchmarkLen(b *testing.B) {
	b.StopTimer()
	m := New()
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		m.Len()
	}
}

func BenchmarkInsert(b *testing.B) {
	b.StopTimer()
	m := New()
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		m.Insert(Integer(i), true);
	}
}

func BenchmarkRemove(b *testing.B) {
	b.StopTimer()
	m := New()
	for i := 0; i < b.N; i++ {
		m.Insert(Integer(i), true);
	}
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		m.Remove(Integer(i));
	}
}

func BenchmarkAt(b *testing.B) {
	b.StopTimer()
	m := New()
	for i := 0; i < b.N; i++ {
		m.Insert(Integer(i), true);
	}
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		m.At(Integer(i));
	}
}

func BenchmarkSet(b *testing.B) {
	b.StopTimer()
	m := New()
	for i := 0; i < b.N; i++ {
		m.Insert(Integer(i), true);
	}
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		m.Set(Integer(i), "Yah");
	}
}

func BenchmarkSuccessfulLookup(b *testing.B) {
	b.StopTimer()
	m := New()
	for i := 0; i < b.N; i++ {
		m.Insert(Integer(i), true);
	}
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		m.Has(Integer(i));
	}
}

func BenchmarkFailedLookup(b *testing.B) {
	b.StopTimer()
	m := New()
	for i := 0; i < b.N; i++ {
		m.Insert(Integer(i), true);
	}
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		m.Has(Integer(-1));
	}
}
<commit_msg>Benchmarking failed lookups is fair now.<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package hashmap

import "testing"

type Integer int;

func (self Integer) Hash() uint { return uint(self*self) }
func (self Integer) Equal(other Hashable) bool { return self == other.(Integer) }

func TestZeroLen(t *testing.T) {
	a := New()
	if a.Len() != 0 {
		t.Errorf("expected 0, got %d", a.Len())
	}
}

func TestZeroLookup(t *testing.T) {
	const Len = 10000
	a := New()
	for i := 0; i < Len; i++ {
		if a.Has(Integer(i)) {
			t.Errorf("found %d in empty hashmap", i)
		}
	}
}

func TestInsert(t *testing.T) {
	const Len = 10000
	a := New()
	for i := 0; i < Len; i++ {
		a.Insert(Integer(i), i)
	}
	for i := 0; i < Len; i++ {
		if !a.Has(Integer(i)) {
			t.Errorf("inserted %d not found", i)
		}
	}
}

func TestRemove(t *testing.T) {
	const Len = 10000
	a := New()
	for i := 0; i < Len; i++ {
		a.Insert(Integer(i), i)
	}
	for i := 0; i < Len; i++ {
		a.Remove(Integer(i))
	}
	for i := 0; i < Len; i++ {
		if a.Has(Integer(i)) {
			t.Errorf("removed %d was found", i)
		}
	}
}

func TestIter(t *testing.T) {
	const Len = 100
	x := New()
	for i := 0; i < Len; i++ {
		x.Insert(Integer(i), i*i)
	}
	i := 0
	for v := range x.Iter() {
		p := v.(HashPair)
		key := p.key.(Integer)
		val := p.value.(int)
		if key*key != Integer(val) {
			t.Error("Iter expected", key*key, "got", val)
		}
		i++
	}
	if i != Len {
		t.Error("Iter stopped at", i, "not", Len)
	}
}

func BenchmarkLen(b *testing.B) {
	b.StopTimer()
	m := New()
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		m.Len()
	}
}

func BenchmarkInsert(b *testing.B) {
	b.StopTimer()
	m := New()
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		m.Insert(Integer(i), true);
	}
}

func BenchmarkRemove(b *testing.B) {
	b.StopTimer()
	m := New()
	for i := 0; i < b.N; i++ {
		m.Insert(Integer(i), true);
	}
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		m.Remove(Integer(i));
	}
}

func BenchmarkAt(b *testing.B) {
	b.StopTimer()
	m := New()
	for i := 0; i < b.N; i++ {
		m.Insert(Integer(i), true);
	}
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		m.At(Integer(i));
	}
}

func BenchmarkSet(b *testing.B) {
	b.StopTimer()
	m := New()
	for i := 0; i < b.N; i++ {
		m.Insert(Integer(i), true);
	}
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		m.Set(Integer(i), "Yah");
	}
}

func BenchmarkSuccessfulLookup(b *testing.B) {
	b.StopTimer()
	m := New()
	for i := 0; i < b.N; i++ {
		m.Insert(Integer(i), true);
	}
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		m.Has(Integer(i));
	}
}

func BenchmarkFailedLookup(b *testing.B) {
	b.StopTimer()
	m := New()
	for i := 0; i < b.N; i++ {
		m.Insert(Integer(i), true);
	}
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		m.Has(Integer(-i));
	}
}
<|endoftext|>


<commit_before>package hashmap

import (
	"fmt"
	"strconv"
	"sync/atomic"
	"testing"
	"unsafe"
)

type Animal struct {
	name string
}

func TestMapCreation(t *testing.T) {
	m := &HashMap{}
	if m.Len() != 0 {
		t.Error("new map should be empty.")
	}
}

func TestOverwrite(t *testing.T) {
	m := &HashMap{}

	elephant := "elephant"
	monkey := "monkey"

	m.Set(1, unsafe.Pointer(&elephant))
	m.Set(1, unsafe.Pointer(&monkey))

	if m.Len() != 1 {
		t.Error("map should contain exactly one element.")
	}

	tmp, ok := m.Get(1) // Retrieve inserted element.
	if !ok {
		t.Error("ok should be true for item stored within the map.")
	}

	item := (*string)(tmp) // Type assertion.
	if *item != "monkey" {
		t.Error("wrong item returned.")
	}
}

func TestInsert(t *testing.T) {
	m := &HashMap{}
	c := uintptr(16)
	ok := m.Insert(uintptr(128), unsafe.Pointer(&c))
	if !ok {
		t.Error("insert did not succeed.")
	}
	ok = m.Insert(uintptr(128), unsafe.Pointer(&c))
	if ok {
		t.Error("insert on existing item did succeed.")
	}
	_, ok = m.GetUintKey(128)
	if !ok {
		t.Error("ok should be true for item stored within the map.")
	}
	if m.Len() != 1 {
		t.Error("map should contain exactly 1 element.")
	}
}

func TestSet(t *testing.T) {
	m := New(4)
	elephant := "elephant"
	monkey := "monkey"

	m.Set(4, unsafe.Pointer(&elephant))
	m.Set(3, unsafe.Pointer(&elephant))
	m.Set(2, unsafe.Pointer(&monkey))
	m.Set(1, unsafe.Pointer(&monkey))

	if m.Len() != 4 {
		t.Error("map should contain exactly 4 elements.")
	}
}

func TestGet(t *testing.T) {
	m := &HashMap{}
	elephant := "elephant"

	val, ok := m.Get("animal") // Get a missing element.
	if ok {
		t.Error("ok should be false when item is missing from map.")
	}
	if val != nil {
		t.Error("Missing values should return as nil.")
	}

	m.Set("animal", unsafe.Pointer(&elephant))

	_, ok = m.Get("human") // Get a missing element.
	if ok {
		t.Error("ok should be false when item is missing from map.")
	}

	val, ok = m.Get("animal") // Retrieve inserted element.
	if !ok {
		t.Error("ok should be true for item stored within the map.")
	}

	animal := (*string)(val)
	if *animal != elephant {
		t.Error("item was modified.")
	}
}

func TestResize(t *testing.T) {
	m := New(2)
	itemCount := 50

	for i := 0; i < itemCount; i++ {
		m.Set(uintptr(i), unsafe.Pointer(&Animal{strconv.Itoa(i)}))
	}

	if m.Len() != itemCount {
		t.Error("Expected element count did not match.")
	}

	if m.Fillrate() < 30 {
		t.Error("Expecting >= 30 percent fillrate.")
	}

	for i := 0; i < itemCount; i++ {
		_, ok := m.Get(uintptr(i))
		if !ok {
			t.Error("Getting inserted item failed.")
		}
	}
}

func TestStringer(t *testing.T) {
	m := &HashMap{}
	elephant := &Animal{"elephant"}
	monkey := &Animal{"monkey"}

	s := m.String()
	if s != "[]" {
		t.Error("empty map as string does not match.")
	}

	m.Set(0, unsafe.Pointer(elephant))
	s = m.String()
	if s != "[9257401834698437112]" {
		t.Error("1 item map as string does not match:", s)
	}

	m.Set(1, unsafe.Pointer(monkey))
	s = m.String()
	if s != "[1754102016959854353,9257401834698437112]" {
		t.Error("2 item map as string does not match:", s)
	}
}

func TestDelete(t *testing.T) {
	m := &HashMap{}
	m.Del(0)

	elephant := &Animal{"elephant"}
	monkey := &Animal{"monkey"}
	m.Set(1, unsafe.Pointer(elephant))
	m.Set(2, unsafe.Pointer(monkey))
	m.Del(0)
	m.Del(3)
	if m.Len() != 2 {
		t.Error("map should contain exactly two elements.")
	}

	m.Del(1)
	m.Del(1)
	m.Del(2)
	if m.Len() != 0 {
		t.Error("map should be empty.")
	}

	val, ok := m.Get(1) // Get a missing element.
	if ok {
		t.Error("ok should be false when item is missing from map.")
	}
	if val != nil {
		t.Error("Missing values should return as nil.")
	}

	m.Set(1, unsafe.Pointer(elephant))
}

func TestIterator(t *testing.T) {
	m := &HashMap{}
	itemCount := 16

	for i := itemCount; i > 0; i-- {
		m.Set(uintptr(i), unsafe.Pointer(&Animal{strconv.Itoa(i)}))
	}

	counter := 0
	for item := range m.Iter() {
		val := item.Value
		if val == nil {
			t.Error("Expecting an object.")
		}
		counter++
	}

	if counter != itemCount {
		t.Error("Returned item count did not match.")
	}
}

func TestHashedKey(t *testing.T) {
	m := &HashMap{}
	itemCount := 16
	log := log2(uintptr(itemCount))

	for i := 0; i < itemCount; i++ {
		m.SetHashedKey(uintptr(i)<<(strconv.IntSize-log), unsafe.Pointer(&Animal{strconv.Itoa(i)}))
	}

	if m.Len() != itemCount {
		t.Error("Expected element count did not match.")
	}

	for i := 0; i < itemCount; i++ {
		_, ok := m.GetHashedKey(uintptr(i) << (strconv.IntSize - log))
		if !ok {
			t.Error("Getting inserted item failed.")
		}
	}

	for i := 0; i < itemCount; i++ {
		m.DelHashedKey(uintptr(i) << (strconv.IntSize - log))
	}

	if m.Len() != 0 {
		t.Error("Map is not empty.")
	}
}

func TestCompareAndSwapHashedKey(t *testing.T) {
	m := &HashMap{}
	elephant := &Animal{"elephant"}
	monkey := &Animal{"monkey"}

	m.SetHashedKey(1<<62, unsafe.Pointer(elephant))
	if m.Len() != 1 {
		t.Error("map should contain exactly one element.")
	}
	if !m.CasHashedKey(1<<62, unsafe.Pointer(elephant), unsafe.Pointer(monkey)) {
		t.Error("Cas should success if expectation met")
	}
	if m.CasHashedKey(1<<62, unsafe.Pointer(elephant), unsafe.Pointer(monkey)) {
		t.Error("Cas should fail if expectation didn't meet")
	}
	tmp, ok := m.GetHashedKey(1 << 62)
	if !ok {
		t.Error("ok should be true for item stored within the map.")
	}
	item := (*Animal)(tmp)
	if item != monkey {
		t.Error("wrong item returned.")
	}
}

func TestCompareAndSwap(t *testing.T) {
	m := &HashMap{}
	elephant := &Animal{"elephant"}
	monkey := &Animal{"monkey"}

	m.Set("animal", unsafe.Pointer(elephant))
	if m.Len() != 1 {
		t.Error("map should contain exactly one element.")
	}
	if !m.Cas("animal", unsafe.Pointer(elephant), unsafe.Pointer(monkey)) {
		t.Error("Cas should success if expectation met")
	}
	if m.Cas("animal", unsafe.Pointer(elephant), unsafe.Pointer(monkey)) {
		t.Error("Cas should fail if expectation didn't meet")
	}
	tmp, ok := m.Get("animal")
	if !ok {
		t.Error("ok should be true for item stored within the map.")
	}
	item := (*Animal)(tmp)
	if item != monkey {
		t.Error("wrong item returned.")
	}
}

// TestAPICounter shows how to use the hashmap to count REST server API calls
func TestAPICounter(t *testing.T) {
	m := &HashMap{}

	for i := 0; i < 100; i++ {
		s := fmt.Sprintf("/api%d/", i%4)

		for {
			val, ok := m.GetStringKey(s)
			if !ok { // item does not exist yet
				c := uintptr(1)
				if !m.Insert(s, unsafe.Pointer(&c)) {
					continue // item was inserted concurrently, try to read it again
				}
				break
			}

			c := (*uintptr)(val)
			atomic.AddUintptr(c, 1)
			break
		}
	}

	s := fmt.Sprintf("/api%d/", 0)
	val, _ := m.GetStringKey(s)
	c := (*uintptr)(val)
	if *c != 25 {
		t.Error("wrong API call count.")
	}
}

func TestExample(t *testing.T) {
	m := &HashMap{}
	i := 123
	m.Set("amount", unsafe.Pointer(&i))

	val, ok := m.Get("amount")
	if !ok {
		t.Fail()
	}

	j := *(*int)(val)
	if i != j {
		t.Fail()
	}
}

func TestGetOrInsert(t *testing.T) {
	m := &HashMap{}

	var i, j uintptr
	actual, loaded := m.GetOrInsert("api1", unsafe.Pointer(&i))
	if loaded {
		t.Error("item should have been inserted.")
	}

	counter := (*uintptr)(actual)
	if *counter != 0 {
		t.Error("item should be 0.")
	}

	atomic.AddUintptr(counter, 1) // increase counter

	actual, loaded = m.GetOrInsert("api1", unsafe.Pointer(&j))
	if !loaded {
		t.Error("item should have been loaded.")
	}

	counter = (*uintptr)(actual)
	if *counter != 1 {
		t.Error("item should be 1.")
	}
}
<commit_msg>Fixed shift constant for 32 bit<commit_after>package hashmap

import (
	"fmt"
	"strconv"
	"sync/atomic"
	"testing"
	"unsafe"
)

type Animal struct {
	name string
}

func TestMapCreation(t *testing.T) {
	m := &HashMap{}
	if m.Len() != 0 {
		t.Error("new map should be empty.")
	}
}

func TestOverwrite(t *testing.T) {
	m := &HashMap{}

	elephant := "elephant"
	monkey := "monkey"

	m.Set(1, unsafe.Pointer(&elephant))
	m.Set(1, unsafe.Pointer(&monkey))

	if m.Len() != 1 {
		t.Error("map should contain exactly one element.")
	}

	tmp, ok := m.Get(1) // Retrieve inserted element.
	if !ok {
		t.Error("ok should be true for item stored within the map.")
	}

	item := (*string)(tmp) // Type assertion.
	if *item != "monkey" {
		t.Error("wrong item returned.")
	}
}

func TestInsert(t *testing.T) {
	m := &HashMap{}
	c := uintptr(16)
	ok := m.Insert(uintptr(128), unsafe.Pointer(&c))
	if !ok {
		t.Error("insert did not succeed.")
	}
	ok = m.Insert(uintptr(128), unsafe.Pointer(&c))
	if ok {
		t.Error("insert on existing item did succeed.")
	}
	_, ok = m.GetUintKey(128)
	if !ok {
		t.Error("ok should be true for item stored within the map.")
	}
	if m.Len() != 1 {
		t.Error("map should contain exactly 1 element.")
	}
}

func TestSet(t *testing.T) {
	m := New(4)
	elephant := "elephant"
	monkey := "monkey"

	m.Set(4, unsafe.Pointer(&elephant))
	m.Set(3, unsafe.Pointer(&elephant))
	m.Set(2, unsafe.Pointer(&monkey))
	m.Set(1, unsafe.Pointer(&monkey))

	if m.Len() != 4 {
		t.Error("map should contain exactly 4 elements.")
	}
}

func TestGet(t *testing.T) {
	m := &HashMap{}
	elephant := "elephant"

	val, ok := m.Get("animal") // Get a missing element.
	if ok {
		t.Error("ok should be false when item is missing from map.")
	}
	if val != nil {
		t.Error("Missing values should return as nil.")
	}

	m.Set("animal", unsafe.Pointer(&elephant))

	_, ok = m.Get("human") // Get a missing element.
	if ok {
		t.Error("ok should be false when item is missing from map.")
	}

	val, ok = m.Get("animal") // Retrieve inserted element.
	if !ok {
		t.Error("ok should be true for item stored within the map.")
	}

	animal := (*string)(val)
	if *animal != elephant {
		t.Error("item was modified.")
	}
}

func TestResize(t *testing.T) {
	m := New(2)
	itemCount := 50

	for i := 0; i < itemCount; i++ {
		m.Set(uintptr(i), unsafe.Pointer(&Animal{strconv.Itoa(i)}))
	}

	if m.Len() != itemCount {
		t.Error("Expected element count did not match.")
	}

	if m.Fillrate() < 30 {
		t.Error("Expecting >= 30 percent fillrate.")
	}

	for i := 0; i < itemCount; i++ {
		_, ok := m.Get(uintptr(i))
		if !ok {
			t.Error("Getting inserted item failed.")
		}
	}
}

func TestStringer(t *testing.T) {
	m := &HashMap{}
	elephant := &Animal{"elephant"}
	monkey := &Animal{"monkey"}

	s := m.String()
	if s != "[]" {
		t.Error("empty map as string does not match.")
	}

	m.Set(0, unsafe.Pointer(elephant))
	s = m.String()
	if s != "[9257401834698437112]" {
		t.Error("1 item map as string does not match:", s)
	}

	m.Set(1, unsafe.Pointer(monkey))
	s = m.String()
	if s != "[1754102016959854353,9257401834698437112]" {
		t.Error("2 item map as string does not match:", s)
	}
}

func TestDelete(t *testing.T) {
	m := &HashMap{}
	m.Del(0)

	elephant := &Animal{"elephant"}
	monkey := &Animal{"monkey"}
	m.Set(1, unsafe.Pointer(elephant))
	m.Set(2, unsafe.Pointer(monkey))
	m.Del(0)
	m.Del(3)
	if m.Len() != 2 {
		t.Error("map should contain exactly two elements.")
	}

	m.Del(1)
	m.Del(1)
	m.Del(2)
	if m.Len() != 0 {
		t.Error("map should be empty.")
	}

	val, ok := m.Get(1) // Get a missing element.
	if ok {
		t.Error("ok should be false when item is missing from map.")
	}
	if val != nil {
		t.Error("Missing values should return as nil.")
	}

	m.Set(1, unsafe.Pointer(elephant))
}

func TestIterator(t *testing.T) {
	m := &HashMap{}
	itemCount := 16

	for i := itemCount; i > 0; i-- {
		m.Set(uintptr(i), unsafe.Pointer(&Animal{strconv.Itoa(i)}))
	}

	counter := 0
	for item := range m.Iter() {
		val := item.Value
		if val == nil {
			t.Error("Expecting an object.")
		}
		counter++
	}

	if counter != itemCount {
		t.Error("Returned item count did not match.")
	}
}

func TestHashedKey(t *testing.T) {
	m := &HashMap{}
	itemCount := 16
	log := log2(uintptr(itemCount))

	for i := 0; i < itemCount; i++ {
		m.SetHashedKey(uintptr(i)<<(strconv.IntSize-log), unsafe.Pointer(&Animal{strconv.Itoa(i)}))
	}

	if m.Len() != itemCount {
		t.Error("Expected element count did not match.")
	}

	for i := 0; i < itemCount; i++ {
		_, ok := m.GetHashedKey(uintptr(i) << (strconv.IntSize - log))
		if !ok {
			t.Error("Getting inserted item failed.")
		}
	}

	for i := 0; i < itemCount; i++ {
		m.DelHashedKey(uintptr(i) << (strconv.IntSize - log))
	}

	if m.Len() != 0 {
		t.Error("Map is not empty.")
	}
}

func TestCompareAndSwapHashedKey(t *testing.T) {
	m := &HashMap{}
	elephant := &Animal{"elephant"}
	monkey := &Animal{"monkey"}

	m.SetHashedKey(1<<(strconv.IntSize-2), unsafe.Pointer(elephant))
	if m.Len() != 1 {
		t.Error("map should contain exactly one element.")
	}
	if !m.CasHashedKey(1<<(strconv.IntSize-2), unsafe.Pointer(elephant), unsafe.Pointer(monkey)) {
		t.Error("Cas should success if expectation met")
	}
	if m.CasHashedKey(1<<(strconv.IntSize-2), unsafe.Pointer(elephant), unsafe.Pointer(monkey)) {
		t.Error("Cas should fail if expectation didn't meet")
	}
	tmp, ok := m.GetHashedKey(1 << (strconv.IntSize - 2))
	if !ok {
		t.Error("ok should be true for item stored within the map.")
	}
	item := (*Animal)(tmp)
	if item != monkey {
		t.Error("wrong item returned.")
	}
}

func TestCompareAndSwap(t *testing.T) {
	m := &HashMap{}
	elephant := &Animal{"elephant"}
	monkey := &Animal{"monkey"}

	m.Set("animal", unsafe.Pointer(elephant))
	if m.Len() != 1 {
		t.Error("map should contain exactly one element.")
	}
	if !m.Cas("animal", unsafe.Pointer(elephant), unsafe.Pointer(monkey)) {
		t.Error("Cas should success if expectation met")
	}
	if m.Cas("animal", unsafe.Pointer(elephant), unsafe.Pointer(monkey)) {
		t.Error("Cas should fail if expectation didn't meet")
	}
	tmp, ok := m.Get("animal")
	if !ok {
		t.Error("ok should be true for item stored within the map.")
	}
	item := (*Animal)(tmp)
	if item != monkey {
		t.Error("wrong item returned.")
	}
}

// TestAPICounter shows how to use the hashmap to count REST server API calls
func TestAPICounter(t *testing.T) {
	m := &HashMap{}

	for i := 0; i < 100; i++ {
		s := fmt.Sprintf("/api%d/", i%4)

		for {
			val, ok := m.GetStringKey(s)
			if !ok { // item does not exist yet
				c := uintptr(1)
				if !m.Insert(s, unsafe.Pointer(&c)) {
					continue // item was inserted concurrently, try to read it again
				}
				break
			}

			c := (*uintptr)(val)
			atomic.AddUintptr(c, 1)
			break
		}
	}

	s := fmt.Sprintf("/api%d/", 0)
	val, _ := m.GetStringKey(s)
	c := (*uintptr)(val)
	if *c != 25 {
		t.Error("wrong API call count.")
	}
}

func TestExample(t *testing.T) {
	m := &HashMap{}
	i := 123
	m.Set("amount", unsafe.Pointer(&i))

	val, ok := m.Get("amount")
	if !ok {
		t.Fail()
	}

	j := *(*int)(val)
	if i != j {
		t.Fail()
	}
}

func TestGetOrInsert(t *testing.T) {
	m := &HashMap{}

	var i, j uintptr
	actual, loaded := m.GetOrInsert("api1", unsafe.Pointer(&i))
	if loaded {
		t.Error("item should have been inserted.")
	}

	counter := (*uintptr)(actual)
	if *counter != 0 {
		t.Error("item should be 0.")
	}

	atomic.AddUintptr(counter, 1) // increase counter

	actual, loaded = m.GetOrInsert("api1", unsafe.Pointer(&j))
	if !loaded {
		t.Error("item should have been loaded.")
	}

	counter = (*uintptr)(actual)
	if *counter != 1 {
		t.Error("item should be 1.")
	}
}
<|endoftext|>


<commit_before>package out_test

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"

	"github.com/onsi/gomega/ghttp"

	"github.com/concourse/tracker-resource/out"
)

var _ = Describe("In", func() {
	var tmpdir string

	var outCmd *exec.Cmd

	BeforeEach(func() {
		var err error

		tmpdir, err = ioutil.TempDir("", "out-tmp")
		Ω(err).ShouldNot(HaveOccurred())
		err = os.MkdirAll(tmpdir, 0755)
		Ω(err).ShouldNot(HaveOccurred())

		setupTestEnvironment(tmpdir)

		outCmd = exec.Command(outPath, tmpdir)
	})

	AfterEach(func() {
		os.RemoveAll(tmpdir)
	})

	Context("when executed", func() {
		var request out.OutRequest
		var response out.OutResponse

		var server *ghttp.Server

		BeforeEach(func() {
			server = ghttp.NewServer()

			request = out.OutRequest{
				Source: out.Source{
					Token:      "abc",
					TrackerURL: server.URL(),
					ProjectID:  "1234",
				},
				Params: out.Params{
					Repos: []string{
						"git",
						"middle/git2",
					},
				},
			}
			response = out.OutResponse{}
		})

		AfterEach(func() {
			server.Close()
		})

		It("finds finished stories that are mentioned in recent git commits", func() {
			server.AppendHandlers(
				ghttp.CombineHandlers(
					ghttp.VerifyRequest("GET", "/services/v5/projects/1234/stories"),
					ghttp.VerifyHeaderKV("X-TrackerToken", "abc"),
					ghttp.RespondWith(http.StatusOK, Fixture("stories.json")),
				),
				ghttp.CombineHandlers(
					ghttp.VerifyRequest("PUT", "/services/v5/projects/1234/stories/123456"),
					ghttp.VerifyHeaderKV("X-TrackerToken", "abc"),
					ghttp.VerifyJSON(`{"current_state":"delivered"}`),
				),
				ghttp.CombineHandlers(
					ghttp.VerifyRequest("PUT", "/services/v5/projects/1234/stories/123457"),
					ghttp.VerifyHeaderKV("X-TrackerToken", "abc"),
					ghttp.VerifyJSON(`{"current_state":"delivered"}`),
				),
			)

			stdin, err := outCmd.StdinPipe()
			Ω(err).ShouldNot(HaveOccurred())

			session, err := Start(outCmd, GinkgoWriter, GinkgoWriter)
			Ω(err).ShouldNot(HaveOccurred())
			err = json.NewEncoder(stdin).Encode(request)
			Ω(err).ShouldNot(HaveOccurred())
			Eventually(session).Should(Exit(0))

			// does not output credentials
			Ω(session.Err).ShouldNot(Say("abc"))

			Ω(session.Err).Should(Say("Checking for finished story: .*#565"))
			Ω(session.Err).Should(Say("git.*... .*SKIPPING"))
			Ω(session.Err).Should(Say("middle/git2.*... .*SKIPPING"))

			Ω(session.Err).Should(Say("Checking for finished story: .*#123456"))
			Ω(session.Err).Should(Say("git.*... .*DELIVERING"))
			Ω(session.Err).Should(Say("middle/git2.*... .*SKIPPING"))

			Ω(session.Err).Should(Say("Checking for finished story: .*#123457"))
			Ω(session.Err).Should(Say("git.*... .*SKIPPING"))
			Ω(session.Err).Should(Say("middle/git2.*... .*DELIVERING"))

			// Output
			err = json.Unmarshal(session.Out.Contents(), &response)
			Ω(err).ShouldNot(HaveOccurred())
			Ω(response.Version.Time).Should(BeTemporally("~", time.Now(), time.Second))
		})
	})
})

func setupTestEnvironment(path string) {
	cmd := exec.Command(filepath.Join("scripts/setup.sh"), path)
	cmd.Stdout = GinkgoWriter
	cmd.Stderr = GinkgoWriter

	err := cmd.Run()
	Ω(err).ShouldNot(HaveOccurred())
}
<commit_msg>make tests beautiful<commit_after>package out_test

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"

	"github.com/onsi/gomega/ghttp"

	"github.com/concourse/tracker-resource/out"
)

var _ = Describe("In", func() {
	var tmpdir string

	var outCmd *exec.Cmd

	BeforeEach(func() {
		var err error

		tmpdir, err = ioutil.TempDir("", "out-tmp")
		Ω(err).ShouldNot(HaveOccurred())
		err = os.MkdirAll(tmpdir, 0755)
		Ω(err).ShouldNot(HaveOccurred())

		setupTestEnvironment(tmpdir)

		outCmd = exec.Command(outPath, tmpdir)
	})

	AfterEach(func() {
		os.RemoveAll(tmpdir)
	})

	Context("when executed", func() {
		var request out.OutRequest
		var response out.OutResponse

		var server *ghttp.Server

		trackerToken := "abc"
		projectId := "1234"

		BeforeEach(func() {
			server = ghttp.NewServer()

			request = out.OutRequest{
				Source: out.Source{
					Token:      trackerToken,
					TrackerURL: server.URL(),
					ProjectID:  projectId,
				},
				Params: out.Params{
					Repos: []string{
						"git",
						"middle/git2",
					},
				},
			}
			response = out.OutResponse{}

			server.AppendHandlers(
				listStoriesHandler(),
				deliverStoryHandler(trackerToken, projectId, 123456),
				deliverStoryHandler(trackerToken, projectId, 123457),
			)
		})

		AfterEach(func() {
			server.Close()
		})

		It("does not output credentials", func() {
			session := runCommand(outCmd, request)

			Ω(session.Err).ShouldNot(Say(trackerToken))
		})

		It("finds finished stories that are mentioned in recent git commits", func() {
			session := runCommand(outCmd, request)

			Ω(session.Err).Should(Say("Checking for finished story: .*#565"))
			Ω(session.Err).Should(Say("git.*... .*SKIPPING"))
			Ω(session.Err).Should(Say("middle/git2.*... .*SKIPPING"))

			Ω(session.Err).Should(Say("Checking for finished story: .*#123456"))
			Ω(session.Err).Should(Say("git.*... .*DELIVERING"))
			Ω(session.Err).Should(Say("middle/git2.*... .*SKIPPING"))

			Ω(session.Err).Should(Say("Checking for finished story: .*#123457"))
			Ω(session.Err).Should(Say("git.*... .*SKIPPING"))
			Ω(session.Err).Should(Say("middle/git2.*... .*DELIVERING"))
		})

		It("outputs the current time", func() {
			session := runCommand(outCmd, request)

			err := json.Unmarshal(session.Out.Contents(), &response)
			Ω(err).ShouldNot(HaveOccurred())
			Ω(response.Version.Time).Should(BeTemporally("~", time.Now(), time.Second))
		})
	})
})

func runCommand(outCmd *exec.Cmd, request out.OutRequest) *Session {
	stdin, err := outCmd.StdinPipe()
	Ω(err).ShouldNot(HaveOccurred())

	session, err := Start(outCmd, GinkgoWriter, GinkgoWriter)
	Ω(err).ShouldNot(HaveOccurred())
	err = json.NewEncoder(stdin).Encode(request)
	Ω(err).ShouldNot(HaveOccurred())
	Eventually(session).Should(Exit(0))

	return session
}

func listStoriesHandler() http.HandlerFunc {
	return ghttp.CombineHandlers(
		ghttp.VerifyRequest("GET", "/services/v5/projects/1234/stories"),
		ghttp.VerifyHeaderKV("X-TrackerToken", "abc"),
		ghttp.RespondWith(http.StatusOK, Fixture("stories.json")),
	)
}

func deliverStoryHandler(token string, projectId string, storyId int) http.HandlerFunc {
	return ghttp.CombineHandlers(
		ghttp.VerifyRequest("PUT", fmt.Sprintf("/services/v5/projects/%s/stories/%d", projectId, storyId)),
		ghttp.VerifyHeaderKV("X-TrackerToken", token),
		ghttp.VerifyJSON(`{"current_state":"delivered"}`),
	)
}

func setupTestEnvironment(path string) {
	cmd := exec.Command(filepath.Join("scripts/setup.sh"), path)
	cmd.Stdout = GinkgoWriter
	cmd.Stderr = GinkgoWriter

	err := cmd.Run()
	Ω(err).ShouldNot(HaveOccurred())
}
<|endoftext|>


<commit_before>package outputs

import (
	"github.com/karlseguin/thirdlaw/core"
	"gopkg.in/karlseguin/typed.v1"
	"log"
	"os"
)

type File struct {
	path     string
	truncate bool
}

func (o File) Process(results *core.Results) {
	f, err := os.OpenFile(o.path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600)
	if err != nil {
		log.Println("failed to open output file", o.path, err)
		return
	}
	defer f.Close()
	writeTo(results, f, false)
}

func NewFile(t typed.Typed) *File {
	return &File{
		path: t.StringOr("path", "failures.log"),
	}
}
<commit_msg>file output supports truncate, or not<commit_after>package outputs

import (
	"github.com/karlseguin/thirdlaw/core"
	"gopkg.in/karlseguin/typed.v1"
	"log"
	"os"
)

type File struct {
	path     string
	flags    int
}

func (o File) Process(results *core.Results) {
	f, err := os.OpenFile(o.path, o.flags, 0600)
	if err != nil {
		log.Println("failed to open output file", o.path, err)
		return
	}
	defer f.Close()
	writeTo(results, f, true)
}

func NewFile(t typed.Typed) *File {
	flags := os.O_CREATE | os.O_WRONLY
	if t := t.BoolOr("truncate", false); t {
		flags |= os.O_TRUNC
	} else {
		flags |= os.O_APPEND
	}

	return &File{
		flags: flags,
		path: t.StringOr("path", "failures.log"),
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/42wim/matterbridge/bridge/config"
	"github.com/42wim/matterbridge/gateway"
	log "github.com/Sirupsen/logrus"
	"github.com/google/gops/agent"
	"os"
	"strings"
)

var (
	version = "1.7.0"
	githash string
)

func init() {
	log.SetFormatter(&log.TextFormatter{FullTimestamp: true})
}

func main() {
	flagConfig := flag.String("conf", "matterbridge.toml", "config file")
	flagDebug := flag.Bool("debug", false, "enable debug")
	flagVersion := flag.Bool("version", false, "show version")
	flagGops := flag.Bool("gops", false, "enable gops agent")
	flag.Parse()
	if *flagGops {
		agent.Listen(&agent.Options{})
		defer agent.Close()
	}
	if *flagVersion {
		fmt.Printf("version: %s %s\n", version, githash)
		return
	}
	if *flagDebug || os.Getenv("DEBUG") == "1" {
		log.Info("Enabling debug")
		log.SetLevel(log.DebugLevel)
	}
	log.Printf("Running version %s %s", version, githash)
	if strings.Contains(version, "-dev") {
		log.Println("WARNING: THIS IS A DEVELOPMENT VERSION. Things may break.")
	}
	cfg := config.NewConfig(*flagConfig)
	cfg.General.Debug = *flagDebug
	r, err := gateway.NewRouter(cfg)
	if err != nil {
		log.Fatalf("Starting gateway failed: %s", err)
	}
	err = r.Start()
	if err != nil {
		log.Fatalf("Starting gateway failed: %s", err)
	}
	log.Printf("Gateway(s) started succesfully. Now relaying messages")
	select {}
}
<commit_msg>Bump version<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/42wim/matterbridge/bridge/config"
	"github.com/42wim/matterbridge/gateway"
	log "github.com/Sirupsen/logrus"
	"github.com/google/gops/agent"
	"os"
	"strings"
)

var (
	version = "1.7.1-dev"
	githash string
)

func init() {
	log.SetFormatter(&log.TextFormatter{FullTimestamp: true})
}

func main() {
	flagConfig := flag.String("conf", "matterbridge.toml", "config file")
	flagDebug := flag.Bool("debug", false, "enable debug")
	flagVersion := flag.Bool("version", false, "show version")
	flagGops := flag.Bool("gops", false, "enable gops agent")
	flag.Parse()
	if *flagGops {
		agent.Listen(&agent.Options{})
		defer agent.Close()
	}
	if *flagVersion {
		fmt.Printf("version: %s %s\n", version, githash)
		return
	}
	if *flagDebug || os.Getenv("DEBUG") == "1" {
		log.Info("Enabling debug")
		log.SetLevel(log.DebugLevel)
	}
	log.Printf("Running version %s %s", version, githash)
	if strings.Contains(version, "-dev") {
		log.Println("WARNING: THIS IS A DEVELOPMENT VERSION. Things may break.")
	}
	cfg := config.NewConfig(*flagConfig)
	cfg.General.Debug = *flagDebug
	r, err := gateway.NewRouter(cfg)
	if err != nil {
		log.Fatalf("Starting gateway failed: %s", err)
	}
	err = r.Start()
	if err != nil {
		log.Fatalf("Starting gateway failed: %s", err)
	}
	log.Printf("Gateway(s) started succesfully. Now relaying messages")
	select {}
}
<|endoftext|>