<commit_before>package conveyor_test

import (
	"bytes"
	"io"
	"os"
	"regexp"
	"testing"
	"time"

	"golang.org/x/net/context"

	"github.com/remind101/conveyor"
	"github.com/remind101/conveyor/builder"
	"github.com/remind101/conveyor/builder/docker"
	"github.com/stretchr/testify/assert"
)

// This is just a highlevel sanity test.
func TestConveyor(t *testing.T) {
	checkDocker(t)

	pr, pw := io.Pipe()
	c := newConveyor(t, io.MultiWriter(pw, os.Stdout))

	ctx := context.Background()
	err := c.Push(ctx, builder.BuildOptions{
		Repository: "remind101/acme-inc",
		Branch:     "master",
		Sha:        "827fecd2d36ebeaa2fd05aa8ef3eed1e56a8cd57",
	})
	assert.NoError(t, err)

	w := new(bytes.Buffer)
	_, err = io.Copy(w, pr)
	assert.NoError(t, err)

	if !regexp.MustCompile(`Successfully built`).MatchString(w.String()) {
		t.Log(w.String())
		t.Fatal("Expected image to be built")
	}
}

func TestConveyor_WithTimeout(t *testing.T) {
	checkDocker(t)

	w := new(bytes.Buffer)
	c := newConveyor(t, w)

	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()

	if err := c.Push(ctx, builder.BuildOptions{
		Repository: "remind101/acme-inc",
		Branch:     "master",
		Sha:        "827fecd2d36ebeaa2fd05aa8ef3eed1e56a8cd57",
	}); err != nil {
		if _, ok := err.(*builder.BuildCanceledError); !ok {
			t.Fatal("Expected build to be canceled")
		}
	}
}

func newConveyor(t *testing.T, w io.Writer) *conveyor.Conveyor {
	b, err := docker.NewBuilderFromEnv()
	if err != nil {
		t.Fatal(err)
	}
	b.DryRun = true

	return conveyor.New(conveyor.Options{
		LogFactory: func(builder.BuildOptions) (builder.Logger, error) {
			return builder.NewLogger(w), nil
		},
		Builder: b,
	})
}

func checkDocker(t testing.TB) {
	if testing.Short() {
		t.Skip("Skipping docker tests because they take a long time")
	}
}
<commit_msg>Fix integration tests.<commit_after>package conveyor_test

import (
	"bytes"
	"io"
	"regexp"
	"testing"
	"time"

	"golang.org/x/net/context"

	"github.com/remind101/conveyor"
	"github.com/remind101/conveyor/builder"
	"github.com/remind101/conveyor/builder/docker"
	"github.com/stretchr/testify/assert"
)

// This is just a highlevel sanity test.
func TestConveyor(t *testing.T) {
	checkDocker(t)

	w := newLogger()
	c := newConveyor(t, w)

	ctx := context.Background()
	err := c.Push(ctx, builder.BuildOptions{
		Repository: "remind101/acme-inc",
		Branch:     "master",
		Sha:        "827fecd2d36ebeaa2fd05aa8ef3eed1e56a8cd57",
	})
	assert.NoError(t, err)

	// Wait for logs to finish writing
	<-w.closed

	if !regexp.MustCompile(`Successfully built`).MatchString(w.String()) {
		t.Log(w.String())
		t.Fatal("Expected image to be built")
	}
}

func TestConveyor_WithTimeout(t *testing.T) {
	checkDocker(t)

	w := newLogger()
	c := newConveyor(t, w)

	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()

	if err := c.Push(ctx, builder.BuildOptions{
		Repository: "remind101/acme-inc",
		Branch:     "master",
		Sha:        "827fecd2d36ebeaa2fd05aa8ef3eed1e56a8cd57",
	}); err != nil {
		if _, ok := err.(*builder.BuildCanceledError); !ok {
			t.Fatal("Expected build to be canceled")
		}
	}
}

func newConveyor(t *testing.T, w io.Writer) *conveyor.Conveyor {
	b, err := docker.NewBuilderFromEnv()
	if err != nil {
		t.Fatal(err)
	}
	b.DryRun = true

	return conveyor.New(conveyor.Options{
		LogFactory: func(builder.BuildOptions) (builder.Logger, error) {
			return builder.NewLogger(w), nil
		},
		Builder: conveyor.NewBuilder(b),
	})
}

func checkDocker(t testing.TB) {
	if testing.Short() {
		t.Skip("Skipping docker tests because they take a long time")
	}
}

// logger implements the io.Closer interface on top of a bytes.Buffer. It sends
// on the closed channel when Close is called.
type logger struct {
	bytes.Buffer
	closed chan struct{}
}

func newLogger() *logger {
	return &logger{closed: make(chan struct{})}
}

func (l *logger) Close() error {
	close(l.closed)
	return nil
}
<|endoftext|>


<commit_before>package stacks

import (
	"errors"
	"fmt"
	"strings"
	"time"

	"github.com/daidokoro/qaz/bucket"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/cloudformation"
)

// Update - Update Cloudformation Stack
func (s *Stack) Update() error {

	err := s.DeployTimeParser()
	if err != nil {
		return err
	}

	done := make(chan bool)
	svc := cloudformation.New(s.Session, &aws.Config{Credentials: s.creds()})
	updateParams := &cloudformation.UpdateStackInput{
		StackName:    aws.String(s.Stackname),
		TemplateBody: aws.String(s.Template),
	}

	// NOTE: Add parameters and tags flag here if set
	if len(s.Parameters) > 0 {
		updateParams.Parameters = s.Parameters
	}

	if len(s.Tags) > 0 {
		updateParams.Tags = s.Tags
	}

	// If bucket - upload to s3
	if s.Bucket != "" {
		exists, err := bucket.Exists(s.Bucket, s.Session)
		if err != nil {
			Log.Warn("Received Error when checking if [%s] exists: %v", s.Bucket, err)
		}

		if !exists {
			Log.Info("Creating Bucket [%s]", s.Bucket)
			if err = bucket.Create(s.Bucket, s.Session); err != nil {
				return err
			}
		}
		t := time.Now()
		tStamp := fmt.Sprintf("%d-%d-%d_%d%d", t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute())
		url, err := bucket.S3write(s.Bucket, fmt.Sprintf("%s_%s.Template", s.Stackname, tStamp), s.Template, s.Session)
		if err != nil {
			return err
		}
		updateParams.TemplateURL = &url
	} else {
		updateParams.TemplateBody = &s.Template
	}

	// NOTE: Add parameters flag here if params set
	if len(s.Parameters) > 0 {
		updateParams.Parameters = s.Parameters
	}

	// If IAM is being touched, add Capabilities
	if strings.Contains(s.Template, "AWS::IAM") {
		updateParams.Capabilities = []*string{
			aws.String(cloudformation.CapabilityCapabilityIam),
			aws.String(cloudformation.CapabilityCapabilityNamedIam),
		}
	}

	if s.StackExists() {
		Log.Info("Stack exists, updating...")

		Log.Debug("calling [UpdateStack] with parameters: %s", updateParams)
		_, err := svc.UpdateStack(updateParams)

		if err != nil {
			return errors.New(fmt.Sprintln("Update failed: ", err))
		}

		go s.tail("UPDATE", done)

		describeStacksInput := &cloudformation.DescribeStacksInput{
			StackName: aws.String(s.Stackname),
		}
		Log.Debug("calling [WaitUntilStackUpdateComplete] with parameters: %s", describeStacksInput)
		if err := svc.WaitUntilStackUpdateComplete(describeStacksInput); err != nil {
			return err
		}

		Log.Info("stack update successful: [%s]", s.Stackname)

	}
	done <- true
	return nil
}
<commit_msg>added notification arns to stack update<commit_after>package stacks

import (
	"errors"
	"fmt"
	"strings"
	"time"

	"github.com/daidokoro/qaz/bucket"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/cloudformation"
)

// Update - Update Cloudformation Stack
func (s *Stack) Update() error {

	err := s.DeployTimeParser()
	if err != nil {
		return err
	}

	done := make(chan bool)
	svc := cloudformation.New(s.Session, &aws.Config{Credentials: s.creds()})
	updateParams := &cloudformation.UpdateStackInput{
		StackName:    aws.String(s.Stackname),
		TemplateBody: aws.String(s.Template),
	}

	// NOTE: Add parameters and tags flag here if set
	if len(s.Parameters) > 0 {
		updateParams.Parameters = s.Parameters
	}

	if len(s.Tags) > 0 {
		updateParams.Tags = s.Tags
	}

	if len(s.NotificationARNs) > 0 {
		updateParams.NotificationARNs = aws.StringSlice(s.NotificationARNs)
	}

	// If bucket - upload to s3
	if s.Bucket != "" {
		exists, err := bucket.Exists(s.Bucket, s.Session)
		if err != nil {
			Log.Warn("Received Error when checking if [%s] exists: %v", s.Bucket, err)
		}

		if !exists {
			Log.Info("Creating Bucket [%s]", s.Bucket)
			if err = bucket.Create(s.Bucket, s.Session); err != nil {
				return err
			}
		}
		t := time.Now()
		tStamp := fmt.Sprintf("%d-%d-%d_%d%d", t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute())
		url, err := bucket.S3write(s.Bucket, fmt.Sprintf("%s_%s.Template", s.Stackname, tStamp), s.Template, s.Session)
		if err != nil {
			return err
		}
		updateParams.TemplateURL = &url
	} else {
		updateParams.TemplateBody = &s.Template
	}

	// NOTE: Add parameters flag here if params set
	if len(s.Parameters) > 0 {
		updateParams.Parameters = s.Parameters
	}

	// If IAM is being touched, add Capabilities
	if strings.Contains(s.Template, "AWS::IAM") {
		updateParams.Capabilities = []*string{
			aws.String(cloudformation.CapabilityCapabilityIam),
			aws.String(cloudformation.CapabilityCapabilityNamedIam),
		}
	}

	if s.StackExists() {
		Log.Info("Stack exists, updating...")

		Log.Debug("calling [UpdateStack] with parameters: %s", updateParams)
		_, err := svc.UpdateStack(updateParams)

		if err != nil {
			return errors.New(fmt.Sprintln("Update failed: ", err))
		}

		go s.tail("UPDATE", done)

		describeStacksInput := &cloudformation.DescribeStacksInput{
			StackName: aws.String(s.Stackname),
		}
		Log.Debug("calling [WaitUntilStackUpdateComplete] with parameters: %s", describeStacksInput)
		if err := svc.WaitUntilStackUpdateComplete(describeStacksInput); err != nil {
			return err
		}

		Log.Info("stack update successful: [%s]", s.Stackname)

	}
	done <- true
	return nil
}
<|endoftext|>


<commit_before>package state

import (
	"encoding/gob"
	"fmt"
	"log"
	"math"
	"math/rand"
	"os"
	"os/signal"
	"time"
)

func (g *Game) write(fn string) {
	g.Lock()
	defer g.Unlock()

	new := fn + ".new"
	old := fn + ".old"
	f, err := os.Create(fn + ".new")
	if err != nil {
		log.Fatal(err)
	}
	err = gob.NewEncoder(f).Encode(&g.g)
	if err != nil {
		log.Fatal(err)
	}
	f.Sync()
	f.Close()

	os.Rename(fn, old)
	err = os.Rename(new, fn)
	if err != nil {
		log.Fatal(err)
	}
	os.Remove(old)
}

func nextTurn() <-chan time.Time {
	now := time.Now().UTC()
	tomorrow := now.Add(time.Hour * 23)
	for tomorrow.Day() == now.Day() {
		tomorrow = tomorrow.Add(time.Hour)
	}
	next := time.Date(tomorrow.Year(), tomorrow.Month(), tomorrow.Day(), 0, 0, 0, 0, time.UTC)
	return time.After(next.Sub(now))
}

func (g *Game) newDay() {
	const rounds = 15
	const (
		up = iota
		down
		dividend
	)

	before := g.g.Stock
	var divpaid [stockTypes]uint64
	news := make([]string, 0, stockTypes)

	for i := 0; i < rounds; i++ {
		adjust := uint64(math.Pow(rand.Float64()*.8+1.2, 5.0))
		stock := rand.Intn(stockTypes)
		switch rand.Intn(3) {
		case up:
			g.g.Stock[stock].Value += adjust
			if g.g.Stock[stock].Value >= splitValue {
				news = append(news, g.g.Stock[stock].Name+" split 2 for 1")
				g.g.Stock[stock].Value = (g.g.Stock[stock].Value + 1) / 2
				before[stock].Value = (before[stock].Value + 1) / 2
				for _, p := range g.g.Player {
					p.Shares[stock] *= 2
				}
			}
		case down:
			if g.g.Stock[stock].Value <= adjust {
				news = append(news, g.g.Stock[stock].Name+" went bankrupt, and was removed from the market")
				for _, p := range g.g.Player {
					p.Shares[stock] = 0
				}
				g.g.Stock[stock].Value = startingValue
				before[stock].Value = startingValue
				newname := g.g.pickName()
				news = append(news, newname+" was added to the market")
				g.g.Stock[stock].Name = newname
			} else {
				g.g.Stock[stock].Value -= adjust
			}
		case dividend:
			if g.g.Stock[stock].Value >= startingValue {
				divpaid[stock] += adjust
				for _, p := range g.g.Player {
					p.Cash += adjust * p.Shares[stock]
				}
			}
		}
	}

	for k, v := range g.g.Stock {
		var item string
		switch {
		case v.Value == before[k].Value:
			item = v.Name + " did not change price"
		case v.Value < before[k].Value:
			item = fmt.Sprintf("%s fell %.1f%%", v.Name, float64(before[k].Value-v.Value)/float64(before[k].Value)*100)
		default: // case v.Value > before[k].Value:
			item = fmt.Sprintf("%s rose %.1f%%", v.Name, float64(v.Value-before[k].Value)/float64(before[k].Value)*100)
		}
		if divpaid[k] > 0 {
			item = fmt.Sprintf("%s, and paid $%d in dividends", item, divpaid[k])
		}
		news = append(news, item)
	}
	g.g.News = news
}

func watcher(g *Game, filename string, changed chan struct{}) {
	var tick <-chan time.Time
	tock := nextTurn()

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

	for {
		select {
		case <-changed:
			if tick == nil {
				tick = time.After(5 * time.Minute)
			}
		case <-tick:
			tick = nil
			g.write(filename)
		case <-tock:
			g.newDay()
			g.write(filename)
			tock = nextTurn()
		case <-sigint:
			if tick != nil {
				g.write(filename)
			}
			log.Println("Exiting")
			os.Exit(0)
		}
	}
}
<commit_msg>Create data file without global read permissions<commit_after>package state

import (
	"encoding/gob"
	"fmt"
	"log"
	"math"
	"math/rand"
	"os"
	"os/signal"
	"time"
)

func (g *Game) write(fn string) {
	g.Lock()
	defer g.Unlock()

	new := fn + ".new"
	old := fn + ".old"
	f, err := os.OpenFile(fn+".new", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		log.Fatal(err)
	}
	err = gob.NewEncoder(f).Encode(&g.g)
	if err != nil {
		log.Fatal(err)
	}
	f.Sync()
	f.Close()

	os.Rename(fn, old)
	err = os.Rename(new, fn)
	if err != nil {
		log.Fatal(err)
	}
	os.Remove(old)
}

func nextTurn() <-chan time.Time {
	now := time.Now().UTC()
	tomorrow := now.Add(time.Hour * 23)
	for tomorrow.Day() == now.Day() {
		tomorrow = tomorrow.Add(time.Hour)
	}
	next := time.Date(tomorrow.Year(), tomorrow.Month(), tomorrow.Day(), 0, 0, 0, 0, time.UTC)
	return time.After(next.Sub(now))
}

func (g *Game) newDay() {
	const rounds = 15
	const (
		up = iota
		down
		dividend
	)

	before := g.g.Stock
	var divpaid [stockTypes]uint64
	news := make([]string, 0, stockTypes)

	for i := 0; i < rounds; i++ {
		adjust := uint64(math.Pow(rand.Float64()*.8+1.2, 5.0))
		stock := rand.Intn(stockTypes)
		switch rand.Intn(3) {
		case up:
			g.g.Stock[stock].Value += adjust
			if g.g.Stock[stock].Value >= splitValue {
				news = append(news, g.g.Stock[stock].Name+" split 2 for 1")
				g.g.Stock[stock].Value = (g.g.Stock[stock].Value + 1) / 2
				before[stock].Value = (before[stock].Value + 1) / 2
				for _, p := range g.g.Player {
					p.Shares[stock] *= 2
				}
			}
		case down:
			if g.g.Stock[stock].Value <= adjust {
				news = append(news, g.g.Stock[stock].Name+" went bankrupt, and was removed from the market")
				for _, p := range g.g.Player {
					p.Shares[stock] = 0
				}
				g.g.Stock[stock].Value = startingValue
				before[stock].Value = startingValue
				newname := g.g.pickName()
				news = append(news, newname+" was added to the market")
				g.g.Stock[stock].Name = newname
			} else {
				g.g.Stock[stock].Value -= adjust
			}
		case dividend:
			if g.g.Stock[stock].Value >= startingValue {
				divpaid[stock] += adjust
				for _, p := range g.g.Player {
					p.Cash += adjust * p.Shares[stock]
				}
			}
		}
	}

	for k, v := range g.g.Stock {
		var item string
		switch {
		case v.Value == before[k].Value:
			item = v.Name + " did not change price"
		case v.Value < before[k].Value:
			item = fmt.Sprintf("%s fell %.1f%%", v.Name, float64(before[k].Value-v.Value)/float64(before[k].Value)*100)
		default: // case v.Value > before[k].Value:
			item = fmt.Sprintf("%s rose %.1f%%", v.Name, float64(v.Value-before[k].Value)/float64(before[k].Value)*100)
		}
		if divpaid[k] > 0 {
			item = fmt.Sprintf("%s, and paid $%d in dividends", item, divpaid[k])
		}
		news = append(news, item)
	}
	g.g.News = news
}

func watcher(g *Game, filename string, changed chan struct{}) {
	var tick <-chan time.Time
	tock := nextTurn()

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

	for {
		select {
		case <-changed:
			if tick == nil {
				tick = time.After(5 * time.Minute)
			}
		case <-tick:
			tick = nil
			g.write(filename)
		case <-tock:
			g.newDay()
			g.write(filename)
			tock = nextTurn()
		case <-sigint:
			if tick != nil {
				g.write(filename)
			}
			log.Println("Exiting")
			os.Exit(0)
		}
	}
}
<|endoftext|>


<commit_before>package vcs

import (
	"fmt"
	"testing"

	c "github.com/sahib/brig/catfs/core"
	"github.com/sahib/brig/catfs/db"
	ie "github.com/sahib/brig/catfs/errors"
	n "github.com/sahib/brig/catfs/nodes"
	h "github.com/sahib/brig/util/hashlib"
	"github.com/stretchr/testify/require"
)

func TestResetFile(t *testing.T) {
	c.WithDummyKv(t, func(kv db.Database) {
		lkr := c.NewLinker(kv)
		if err := lkr.MakeCommit(n.AuthorOfStage, "initial commit"); err != nil {
			t.Fatalf("Initial commit failed: %v", err)
		}

		initCmt, err := lkr.Head()
		if err != nil {
			t.Fatalf("Failed to get initial head")
		}

		root, err := lkr.Root()
		if err != nil {
			t.Fatalf("Getting root failed: %v", err)
		}

		file, err := n.NewEmptyFile(root, "cat.png", "u", 3)
		if err != nil {
			t.Fatalf("Failed to create cat.png: %v", err)
		}

		c.MustModify(t, lkr, file, 1)
		oldFileHash := file.TreeHash().Clone()

		if err := lkr.MakeCommit(n.AuthorOfStage, "second commit"); err != nil {
			t.Fatalf("Failed to make second commit: %v", err)
		}

		c.MustModify(t, lkr, file, 2)
		headFileHash := file.TreeHash().Clone()

		if err := lkr.MakeCommit(n.AuthorOfStage, "third commit"); err != nil {
			t.Fatalf("Failed to make third commit: %v", err)
		}

		head, err := lkr.Head()
		if err != nil {
			t.Fatalf("Failed to get HEAD: %v", err)
		}

		lastCommitNd, err := head.Parent(lkr)
		if err != nil {
			t.Fatalf("Failed to get second commit: %v", err)
		}

		lastCommit := lastCommitNd.(*n.Commit)

		if err := ResetNode(lkr, lastCommit, "/cat.png"); err != nil {
			t.Fatalf("Failed to checkout file before commit: %v", err)
		}

		lastVersion, err := lkr.LookupFile("/cat.png")
		if err != nil {
			t.Fatalf("Failed to lookup /cat.png post checkout")
		}

		if !lastVersion.TreeHash().Equal(oldFileHash) {
			t.Fatalf("Hash of checkout'd file is not from second commit")
		}

		if lastVersion.Size() != 1 {
			t.Fatalf("Size of checkout'd file is not from second commit")
		}

		if err := ResetNode(lkr, initCmt, "/cat.png"); err != nil {
			t.Fatalf("Failed to checkout file at init: %v", err)
		}

		_, err = lkr.LookupFile("/cat.png")
		if !ie.IsNoSuchFileError(err) {
			t.Fatalf("Different error: %v", err)
		}

		if err := ResetNode(lkr, head, "/cat.png"); err != nil {
			t.Fatalf("Failed to checkout file at head: %v", err)
		}

		headVersion, err := lkr.LookupFile("/cat.png")
		if err != nil {
			t.Fatalf("Failed to lookup /cat.png post checkout")
		}

		if !headVersion.TreeHash().Equal(headFileHash) {
			t.Fatalf(
				"Hash differs between new and head reset: %v != %v",
				headVersion.TreeHash(),
				headFileHash,
			)
		}
	})
}

func TestFindPathAt(t *testing.T) {
	c.WithDummyLinker(t, func(lkr *c.Linker) {
		nd := c.MustTouch(t, lkr, "/x", 1)
		c1 := c.MustCommit(t, lkr, "1")
		c.MustMove(t, lkr, nd, "/y")
		c.MustCommit(t, lkr, "2")

		oldPath, err := findPathAt(lkr, c1, "/y")
		require.Nil(t, err)
		fmt.Println("OLD PATH", oldPath)
	})
}

// Reset a file that was moved in earlier incarnations.
func TestResetMovedFile(t *testing.T) {
	c.WithDummyLinker(t, func(lkr *c.Linker) {
		sub := c.MustMkdir(t, lkr, "/sub")
		nd := c.MustTouch(t, lkr, "/sub/x", 1)
		c1 := c.MustCommit(t, lkr, "1")
		c.MustMove(t, lkr, nd, "/y")
		c.MustModify(t, lkr, nd, 2)
		c.MustCommit(t, lkr, "2")

		// This should reset /y to content=1.
		err := ResetNode(lkr, c1, "/y")
		require.Nil(t, err)

		root, err := lkr.Root()
		require.Nil(t, err)

		children, err := root.ChildrenSorted(lkr)
		require.Nil(t, err)
		require.Len(t, children, 2)
		require.Equal(t, children[0].Type(), n.NodeType(n.NodeTypeDirectory))
		require.Equal(t, children[0].Path(), "/sub")

		require.Equal(t, children[1].Type(), n.NodeType(n.NodeTypeFile))
		require.Equal(t, children[1].Path(), "/y")
		require.Equal(t, children[1].BackendHash(), h.TestDummy(t, 1))

		subChildren, err := sub.ChildrenSorted(lkr)
		require.Nil(t, err)
		require.Len(t, subChildren, 1)
		require.Equal(t, subChildren[0].Type(), n.NodeType(n.NodeTypeGhost))
		require.Equal(t, subChildren[0].Path(), "/sub/x")
	})
}
<commit_msg>fix compile error in test due to changed signature<commit_after>package vcs

import (
	"fmt"
	"testing"

	c "github.com/sahib/brig/catfs/core"
	"github.com/sahib/brig/catfs/db"
	ie "github.com/sahib/brig/catfs/errors"
	n "github.com/sahib/brig/catfs/nodes"
	h "github.com/sahib/brig/util/hashlib"
	"github.com/stretchr/testify/require"
)

func TestResetFile(t *testing.T) {
	c.WithDummyKv(t, func(kv db.Database) {
		lkr := c.NewLinker(kv)
		if err := lkr.MakeCommit(n.AuthorOfStage, "initial commit"); err != nil {
			t.Fatalf("Initial commit failed: %v", err)
		}

		initCmt, err := lkr.Head()
		if err != nil {
			t.Fatalf("Failed to get initial head")
		}

		root, err := lkr.Root()
		if err != nil {
			t.Fatalf("Getting root failed: %v", err)
		}

		file, err := n.NewEmptyFile(root, "cat.png", "u", 3)
		if err != nil {
			t.Fatalf("Failed to create cat.png: %v", err)
		}

		c.MustModify(t, lkr, file, 1)
		oldFileHash := file.TreeHash().Clone()

		if err := lkr.MakeCommit(n.AuthorOfStage, "second commit"); err != nil {
			t.Fatalf("Failed to make second commit: %v", err)
		}

		c.MustModify(t, lkr, file, 2)
		headFileHash := file.TreeHash().Clone()

		if err := lkr.MakeCommit(n.AuthorOfStage, "third commit"); err != nil {
			t.Fatalf("Failed to make third commit: %v", err)
		}

		head, err := lkr.Head()
		if err != nil {
			t.Fatalf("Failed to get HEAD: %v", err)
		}

		lastCommitNd, err := head.Parent(lkr)
		if err != nil {
			t.Fatalf("Failed to get second commit: %v", err)
		}

		lastCommit := lastCommitNd.(*n.Commit)

		if _, err := ResetNode(lkr, lastCommit, "/cat.png"); err != nil {
			t.Fatalf("Failed to checkout file before commit: %v", err)
		}

		lastVersion, err := lkr.LookupFile("/cat.png")
		if err != nil {
			t.Fatalf("Failed to lookup /cat.png post checkout")
		}

		if !lastVersion.TreeHash().Equal(oldFileHash) {
			t.Fatalf("Hash of checkout'd file is not from second commit")
		}

		if lastVersion.Size() != 1 {
			t.Fatalf("Size of checkout'd file is not from second commit")
		}

		if _, err := ResetNode(lkr, initCmt, "/cat.png"); err != nil {
			t.Fatalf("Failed to checkout file at init: %v", err)
		}

		_, err = lkr.LookupFile("/cat.png")
		if !ie.IsNoSuchFileError(err) {
			t.Fatalf("Different error: %v", err)
		}

		if _, err := ResetNode(lkr, head, "/cat.png"); err != nil {
			t.Fatalf("Failed to checkout file at head: %v", err)
		}

		headVersion, err := lkr.LookupFile("/cat.png")
		if err != nil {
			t.Fatalf("Failed to lookup /cat.png post checkout")
		}

		if !headVersion.TreeHash().Equal(headFileHash) {
			t.Fatalf(
				"Hash differs between new and head reset: %v != %v",
				headVersion.TreeHash(),
				headFileHash,
			)
		}
	})
}

func TestFindPathAt(t *testing.T) {
	c.WithDummyLinker(t, func(lkr *c.Linker) {
		nd := c.MustTouch(t, lkr, "/x", 1)
		c1 := c.MustCommit(t, lkr, "1")
		c.MustMove(t, lkr, nd, "/y")
		c.MustCommit(t, lkr, "2")

		oldPath, err := findPathAt(lkr, c1, "/y")
		require.Nil(t, err)
		fmt.Println("OLD PATH", oldPath)
	})
}

// Reset a file that was moved in earlier incarnations.
func TestResetMovedFile(t *testing.T) {
	c.WithDummyLinker(t, func(lkr *c.Linker) {
		sub := c.MustMkdir(t, lkr, "/sub")
		nd := c.MustTouch(t, lkr, "/sub/x", 1)
		c1 := c.MustCommit(t, lkr, "1")
		c.MustMove(t, lkr, nd, "/y")
		c.MustModify(t, lkr, nd, 2)
		c.MustCommit(t, lkr, "2")

		// This should reset /y to content=1.
		_, err := ResetNode(lkr, c1, "/y")
		require.Nil(t, err)

		root, err := lkr.Root()
		require.Nil(t, err)

		children, err := root.ChildrenSorted(lkr)
		require.Nil(t, err)
		require.Len(t, children, 2)
		require.Equal(t, children[0].Type(), n.NodeType(n.NodeTypeDirectory))
		require.Equal(t, children[0].Path(), "/sub")

		require.Equal(t, children[1].Type(), n.NodeType(n.NodeTypeFile))
		require.Equal(t, children[1].Path(), "/y")
		require.Equal(t, children[1].BackendHash(), h.TestDummy(t, 1))

		subChildren, err := sub.ChildrenSorted(lkr)
		require.Nil(t, err)
		require.Len(t, subChildren, 1)
		require.Equal(t, subChildren[0].Type(), n.NodeType(n.NodeTypeGhost))
		require.Equal(t, subChildren[0].Path(), "/sub/x")
	})
}
<|endoftext|>


<commit_before>package devices_test

import (
	"fmt"
	"net"
	"os/exec"
	"strconv"
	"strings"

	"github.com/cloudfoundry-incubator/garden-linux/network/devices"
	"github.com/docker/libcontainer/netlink"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gexec"
)

var _ = Describe("Link Management", func() {
	var (
		l    devices.Link
		name string
		intf *net.Interface
	)

	BeforeEach(func() {
		cmd, err := gexec.Start(exec.Command("sh", "-c", "mount -n -t sysfs sysfs /sys ||true"), GinkgoWriter, GinkgoWriter)
		Expect(err).ToNot(HaveOccurred())
		Eventually(cmd).Should(gexec.Exit(0))

		name = fmt.Sprintf("gdn-test-%d", GinkgoParallelNode())
		Expect(netlink.NetworkLinkAdd(name, "dummy")).To(Succeed())
		intf, _ = net.InterfaceByName(name)
	})

	AfterEach(func() {
		cleanup(name)
	})

	Describe("AddIP", func() {
		Context("when the interface exists", func() {
			It("adds the IP succesffuly", func() {
				ip, subnet, _ := net.ParseCIDR("1.2.3.4/5")
				Expect(l.AddIP(intf, ip, subnet)).To(Succeed())

				intf, err := net.InterfaceByName(name)
				Expect(err).ToNot(HaveOccurred())
				addrs, err := intf.Addrs()
				Expect(err).ToNot(HaveOccurred())

				Expect(addrs).To(HaveLen(1))
				Expect(addrs[0].String()).To(Equal("1.2.3.4/5"))
			})
		})
	})

	Describe("SetUp", func() {
		Context("when the interface does not exist", func() {
			It("returns an error", func() {
				Expect(l.SetUp(&net.Interface{Name: "something"})).ToNot(Succeed())
			})
		})

		Context("when the interface exists", func() {
			Context("and it is down", func() {
				It("should bring the interface up", func() {
					Expect(l.SetUp(intf)).To(Succeed())

					intf, err := net.InterfaceByName(name)
					Expect(err).ToNot(HaveOccurred())
					Expect(intf.Flags & net.FlagUp).To(Equal(net.FlagUp))
				})
			})

			Context("and it is already up", func() {
				It("should still succeed", func() {
					Expect(l.SetUp(intf)).To(Succeed())
					Expect(l.SetUp(intf)).To(Succeed())

					intf, err := net.InterfaceByName(name)
					Expect(err).ToNot(HaveOccurred())
					Expect(intf.Flags & net.FlagUp).To(Equal(net.FlagUp))
				})
			})
		})
	})

	Describe("SetMTU", func() {
		Context("when the interface does not exist", func() {
			It("returns an error", func() {
				Expect(l.SetMTU(&net.Interface{Name: "something"}, 1234)).ToNot(Succeed())
			})
		})

		Context("when the interface exists", func() {
			It("sets the mtu", func() {
				Expect(l.SetMTU(intf, 1234)).To(Succeed())

				intf, err := net.InterfaceByName(name)
				Expect(err).ToNot(HaveOccurred())
				Expect(intf.MTU).To(Equal(1234))
			})
		})
	})

	Describe("SetNs", func() {
		BeforeEach(func() {
			cmd, err := gexec.Start(exec.Command("sh", "-c", "ip netns add gdnsetnstest"), GinkgoWriter, GinkgoWriter)
			Expect(err).ToNot(HaveOccurred())
			Eventually(cmd).Should(gexec.Exit(0))
		})

		AfterEach(func() {
			cmd, err := gexec.Start(exec.Command("sh", "-c", "ip netns delete gdnsetnstest"), GinkgoWriter, GinkgoWriter)
			Expect(err).ToNot(HaveOccurred())
			Eventually(cmd).Should(gexec.Exit(0))
		})

		It("moves the interface in to the given namespace by pid", func() {
			// look at this perfectly ordinary hat
			netns, err := gexec.Start(exec.Command("ip", "netns", "exec", "gdnsetnstest", "sleep", "6312736"), GinkgoWriter, GinkgoWriter)
			Expect(err).ToNot(HaveOccurred())
			defer netns.Kill()

			// (it has the following pid)
			ps, err := gexec.Start(exec.Command("sh", "-c", "ps -A -opid,command | grep 'sleep 6312736' | head -n 1 | awk '{print $1}'"), GinkgoWriter, GinkgoWriter) // look at my hat
			Expect(err).ToNot(HaveOccurred())
			Eventually(ps).Should(gexec.Exit(0))
			pid, err := strconv.Atoi(strings.TrimSuffix(string(ps.Out.Contents()), "\n"))
			Expect(err).ToNot(HaveOccurred())

			// I wave the magic wand
			Expect(l.SetNs(intf, pid)).To(Succeed())

			// the bunny has vanished! where is the bunny?
			intfs, _ := net.Interfaces()
			Expect(intfs).ToNot(ContainElement(intf))

			// oh my word it's in the hat!
			session, err := gexec.Start(exec.Command("sh", "-c", fmt.Sprintf("ip netns exec gdnsetnstest ifconfig %s", name)), GinkgoWriter, GinkgoWriter)
			Expect(err).ToNot(HaveOccurred())
			Eventually(session).Should(gexec.Exit(0))

		})
	})

	Describe("InterfaceByName", func() {
		Context("when the interface exists", func() {
			It("returns the interface with the given name, and true", func() {
				returnedIntf, found, err := l.InterfaceByName(name)
				Expect(err).ToNot(HaveOccurred())

				Expect(returnedIntf).To(Equal(intf))
				Expect(found).To(BeTrue())
			})
		})

		Context("when the interface does not exist", func() {
			It("does not return an error", func() {
				_, found, err := l.InterfaceByName("sandwich")
				Expect(err).ToNot(HaveOccurred())
				Expect(found).To(BeFalse())
			})
		})
	})

	Describe("List", func() {
		It("lists all the interfaces", func() {
			names, err := l.List()
			Expect(err).ToNot(HaveOccurred())

			Expect(names).To(ContainElement(name))
		})
	})

	Describe("GetStatistics", func() {

		Context("When the interface exist", func() {
			BeforeEach(func() {
				cmd, err := gexec.Start(exec.Command(
					"sh", "-c", `
					ip netns add netns1
					ip link add veth0 type veth peer name veth1
					ip link set veth1 netns netns1
					ip netns exec netns1 ifconfig veth1 10.1.1.1/24 up
					ifconfig veth0 10.1.1.2/24 up
					`,
				), GinkgoWriter, GinkgoWriter)
				Expect(err).ToNot(HaveOccurred())
				Eventually(cmd, "10s").Should(gexec.Exit(0))
			})

			AfterEach(func() {
				cmd, err := gexec.Start(exec.Command(
					"sh", "-c", `
					ip netns exec netns1 ip link del veth1
					ip netns delete netns1
					`,
				), GinkgoWriter, GinkgoWriter)
				Expect(err).ToNot(HaveOccurred())
				Eventually(cmd).Should(gexec.Exit(0))
			})

			It("Gets statistics from the interface", func() {
				link := devices.Link{Name: "veth0"}
				beforeStat, err := link.Statistics()
				Expect(err).ToNot(HaveOccurred())
				cmd, err := gexec.Start(exec.Command(
					"sh", "-c", `
					ping -c 10 -s 80 10.1.1.1
					`,
				), GinkgoWriter, GinkgoWriter)
				Expect(err).ToNot(HaveOccurred())
				Eventually(cmd, "15s").Should(gexec.Exit(0))

				afterStat, err := link.Statistics()
				Expect(err).ToNot(HaveOccurred())

				// size of ping packet is 42 + payload_size (80 bytes)
				// there could be additional arp messages transferred and recieved
				// so check for range instead of absolute values
				Expect(afterStat.TxBytes).To(BeNumerically(">=", beforeStat.TxBytes+(10*(42+80))))
				Expect(afterStat.TxBytes).To(BeNumerically("<", beforeStat.TxBytes+(10*(42+80))+1000))
				Expect(afterStat.RxBytes).To(BeNumerically(">=", beforeStat.RxBytes+(10*(42+80))))
				Expect(afterStat.RxBytes).To(BeNumerically("<", beforeStat.RxBytes+(10*(42+80))+1000))
			})
		})

		Context("when the interface does not exist", func() {
			It("Gets statistics return an error", func() {
				link := devices.Link{Name: "non-existent-intf"}
				_, err := link.Statistics()
				Expect(err).To(HaveOccurred())
			})
		})
	})
})
<commit_msg>improve link_linux_test<commit_after>package devices_test

import (
	"fmt"
	"net"
	"os/exec"
	"strconv"
	"strings"

	"github.com/cloudfoundry-incubator/garden-linux/network/devices"
	"github.com/docker/libcontainer/netlink"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gexec"
)

var _ = Describe("Link Management", func() {
	var (
		l    devices.Link
		name string
		intf *net.Interface
	)

	BeforeEach(func() {
		cmd, err := gexec.Start(exec.Command("sh", "-c", "mountpoint /sys || mount -t sysfs sysfs /sys"), GinkgoWriter, GinkgoWriter)
		Expect(err).ToNot(HaveOccurred())
		Eventually(cmd).Should(gexec.Exit(0))

		name = fmt.Sprintf("gdn-test-%d", GinkgoParallelNode())
		Expect(netlink.NetworkLinkAdd(name, "dummy")).To(Succeed())
		intf, _ = net.InterfaceByName(name)
	})

	AfterEach(func() {
		cleanup(name)
	})

	Describe("AddIP", func() {
		Context("when the interface exists", func() {
			It("adds the IP succesffuly", func() {
				ip, subnet, _ := net.ParseCIDR("1.2.3.4/5")
				Expect(l.AddIP(intf, ip, subnet)).To(Succeed())

				intf, err := net.InterfaceByName(name)
				Expect(err).ToNot(HaveOccurred())
				addrs, err := intf.Addrs()
				Expect(err).ToNot(HaveOccurred())

				Expect(addrs).To(HaveLen(1))
				Expect(addrs[0].String()).To(Equal("1.2.3.4/5"))
			})
		})
	})

	Describe("SetUp", func() {
		Context("when the interface does not exist", func() {
			It("returns an error", func() {
				Expect(l.SetUp(&net.Interface{Name: "something"})).ToNot(Succeed())
			})
		})

		Context("when the interface exists", func() {
			Context("and it is down", func() {
				It("should bring the interface up", func() {
					Expect(l.SetUp(intf)).To(Succeed())

					intf, err := net.InterfaceByName(name)
					Expect(err).ToNot(HaveOccurred())
					Expect(intf.Flags & net.FlagUp).To(Equal(net.FlagUp))
				})
			})

			Context("and it is already up", func() {
				It("should still succeed", func() {
					Expect(l.SetUp(intf)).To(Succeed())
					Expect(l.SetUp(intf)).To(Succeed())

					intf, err := net.InterfaceByName(name)
					Expect(err).ToNot(HaveOccurred())
					Expect(intf.Flags & net.FlagUp).To(Equal(net.FlagUp))
				})
			})
		})
	})

	Describe("SetMTU", func() {
		Context("when the interface does not exist", func() {
			It("returns an error", func() {
				Expect(l.SetMTU(&net.Interface{Name: "something"}, 1234)).ToNot(Succeed())
			})
		})

		Context("when the interface exists", func() {
			It("sets the mtu", func() {
				Expect(l.SetMTU(intf, 1234)).To(Succeed())

				intf, err := net.InterfaceByName(name)
				Expect(err).ToNot(HaveOccurred())
				Expect(intf.MTU).To(Equal(1234))
			})
		})
	})

	Describe("SetNs", func() {
		BeforeEach(func() {
			cmd, err := gexec.Start(exec.Command("sh", "-c", "ip netns add gdnsetnstest"), GinkgoWriter, GinkgoWriter)
			Expect(err).ToNot(HaveOccurred())
			Eventually(cmd).Should(gexec.Exit(0))
		})

		AfterEach(func() {
			cmd, err := gexec.Start(exec.Command("sh", "-c", "ip netns delete gdnsetnstest"), GinkgoWriter, GinkgoWriter)
			Expect(err).ToNot(HaveOccurred())
			Eventually(cmd).Should(gexec.Exit(0))
		})

		It("moves the interface in to the given namespace by pid", func() {
			// look at this perfectly ordinary hat
			netns, err := gexec.Start(exec.Command("ip", "netns", "exec", "gdnsetnstest", "sleep", "6312736"), GinkgoWriter, GinkgoWriter)
			Expect(err).ToNot(HaveOccurred())
			defer netns.Kill()

			// (it has the following pid)
			ps, err := gexec.Start(exec.Command("sh", "-c", "ps -A -opid,command | grep 'sleep 6312736' | head -n 1 | awk '{print $1}'"), GinkgoWriter, GinkgoWriter) // look at my hat
			Expect(err).ToNot(HaveOccurred())
			Eventually(ps).Should(gexec.Exit(0))
			pid, err := strconv.Atoi(strings.TrimSuffix(string(ps.Out.Contents()), "\n"))
			Expect(err).ToNot(HaveOccurred())

			// I wave the magic wand
			Expect(l.SetNs(intf, pid)).To(Succeed())

			// the bunny has vanished! where is the bunny?
			intfs, _ := net.Interfaces()
			Expect(intfs).ToNot(ContainElement(intf))

			// oh my word it's in the hat!
			session, err := gexec.Start(exec.Command("sh", "-c", fmt.Sprintf("ip netns exec gdnsetnstest ifconfig %s", name)), GinkgoWriter, GinkgoWriter)
			Expect(err).ToNot(HaveOccurred())
			Eventually(session).Should(gexec.Exit(0))

		})
	})

	Describe("InterfaceByName", func() {
		Context("when the interface exists", func() {
			It("returns the interface with the given name, and true", func() {
				returnedIntf, found, err := l.InterfaceByName(name)
				Expect(err).ToNot(HaveOccurred())

				Expect(returnedIntf).To(Equal(intf))
				Expect(found).To(BeTrue())
			})
		})

		Context("when the interface does not exist", func() {
			It("does not return an error", func() {
				_, found, err := l.InterfaceByName("sandwich")
				Expect(err).ToNot(HaveOccurred())
				Expect(found).To(BeFalse())
			})
		})
	})

	Describe("List", func() {
		It("lists all the interfaces", func() {
			names, err := l.List()
			Expect(err).ToNot(HaveOccurred())

			Expect(names).To(ContainElement(name))
		})
	})

	Describe("GetStatistics", func() {

		Context("When the interface exist", func() {
			BeforeEach(func() {
				cmd, err := gexec.Start(exec.Command(
					"sh", "-c", `
					ip netns add netns1
					ip link add veth0 type veth peer name veth1
					ip link set veth1 netns netns1
					ip netns exec netns1 ifconfig veth1 10.1.1.1/24 up
					ifconfig veth0 10.1.1.2/24 up
					`,
				), GinkgoWriter, GinkgoWriter)
				Expect(err).ToNot(HaveOccurred())
				Eventually(cmd, "10s").Should(gexec.Exit(0))
			})

			AfterEach(func() {
				cmd, err := gexec.Start(exec.Command(
					"sh", "-c", `
					ip netns exec netns1 ip link del veth1
					ip netns delete netns1
					`,
				), GinkgoWriter, GinkgoWriter)
				Expect(err).ToNot(HaveOccurred())
				Eventually(cmd).Should(gexec.Exit(0))
			})

			It("Gets statistics from the interface", func() {
				link := devices.Link{Name: "veth0"}
				beforeStat, err := link.Statistics()
				Expect(err).ToNot(HaveOccurred())
				cmd, err := gexec.Start(exec.Command(
					"sh", "-c", `
					ping -c 10 -s 80 10.1.1.1
					`,
				), GinkgoWriter, GinkgoWriter)
				Expect(err).ToNot(HaveOccurred())
				Eventually(cmd, "15s").Should(gexec.Exit(0))

				afterStat, err := link.Statistics()
				Expect(err).ToNot(HaveOccurred())

				// size of ping packet is 42 + payload_size (80 bytes)
				// there could be additional arp messages transferred and recieved
				// so check for range instead of absolute values
				Expect(afterStat.TxBytes).To(BeNumerically(">=", beforeStat.TxBytes+(10*(42+80))))
				Expect(afterStat.TxBytes).To(BeNumerically("<", beforeStat.TxBytes+(10*(42+80))+1000))
				Expect(afterStat.RxBytes).To(BeNumerically(">=", beforeStat.RxBytes+(10*(42+80))))
				Expect(afterStat.RxBytes).To(BeNumerically("<", beforeStat.RxBytes+(10*(42+80))+1000))
			})
		})

		Context("when the interface does not exist", func() {
			It("Gets statistics return an error", func() {
				link := devices.Link{Name: "non-existent-intf"}
				_, err := link.Statistics()
				Expect(err).To(HaveOccurred())
			})
		})
	})
})
<|endoftext|>


<commit_before>package koding

import (
	"encoding/json"
	"fmt"
	"koding/db/models"
	"koding/kites/kloud/protocol"
	"net/http"
	"net/url"
	"time"

	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
)

type SubscriptionsResponse struct {
	AccountId          string    `json:"accountId"`
	PlanTitle          string    `json:"planTitle"`
	PlanInterval       string    `json:"planInterval"`
	State              string    `json:"state"`
	CurrentPeriodStart time.Time `json:"currentPeriodStart"`
	CurrentPeriodEnd   time.Time `json:"currentPeriodEnd"`
	Description        string    `json:"description"`
	Error              string    `json:"error"`
}

func (p *Provider) Fetcher(endpoint string, m *protocol.Machine) (planResp Plan, planErr error) {
	defer func() {
		if planErr != nil {
			p.Log.Warning("[%s] username: %s could not fetch plan. Fallback to Free plan. err: %s",
				m.Username, m.Id, planErr)
			planResp = Free
			planErr = nil
		}
	}()

	userEndpoint, err := url.Parse(endpoint)
	if err != nil {
		return 0, err
	}

	var account *models.Account
	if err := p.Session.Run("jAccounts", func(c *mgo.Collection) error {
		return c.Find(bson.M{"profile.nickname": m.Username}).One(&account)
	}); err != nil {
		return 0, err
	}

	q := userEndpoint.Query()
	q.Set("account_id", account.Id.Hex())
	userEndpoint.RawQuery = q.Encode()

	p.Log.Debug("[%s] fetching plan via URL: '%s'", m.Id, userEndpoint.String())
	resp, err := http.Get(userEndpoint.String())
	if err != nil {
		return 0, err
	}
	defer resp.Body.Close()

	var subscription *SubscriptionsResponse
	e := json.NewDecoder(resp.Body)
	if err := e.Decode(&subscription); err != nil {
		return 0, err
	}

	// return an error back for a non 200 status
	if resp.StatusCode != 200 {
		if subscription.Error != "" {
			return 0, fmt.Errorf("[%s] could not fetch subscription. err: '%s'",
				m.Id, subscription.Description)
		}

		return 0, fmt.Errorf("[%s] could not fetch subscription. status code: %d",
			m.Id, resp.StatusCode)
	}

	plan, ok := plans[subscription.PlanTitle]
	if !ok {
		return 0, fmt.Errorf("[%s] could not find plan. There is no plan called '%s'",
			m.Id, subscription.PlanTitle)
	}

	p.Log.Debug("[%s] user has plan: %s", m.Id, plan)
	return plan, nil
}
<commit_msg>kloud/fetcher: add better logs<commit_after>package koding

import (
	"encoding/json"
	"fmt"
	"koding/db/models"
	"koding/kites/kloud/protocol"
	"net/http"
	"net/url"
	"time"

	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
)

type SubscriptionsResponse struct {
	AccountId          string    `json:"accountId"`
	PlanTitle          string    `json:"planTitle"`
	PlanInterval       string    `json:"planInterval"`
	State              string    `json:"state"`
	CurrentPeriodStart time.Time `json:"currentPeriodStart"`
	CurrentPeriodEnd   time.Time `json:"currentPeriodEnd"`
	Description        string    `json:"description"`
	Error              string    `json:"error"`
}

func (p *Provider) Fetcher(endpoint string, m *protocol.Machine) (planResp Plan, planErr error) {
	defer func() {
		if planErr != nil {
			p.Log.Warning("[%s] username: %s could not fetch plan. Fallback to Free plan. err: '%s'",
				m.Id, m.Username, planErr)
			planResp = Free
			planErr = nil
		}
	}()

	userEndpoint, err := url.Parse(endpoint)
	if err != nil {
		return 0, err
	}

	var account *models.Account
	if err := p.Session.Run("jAccounts", func(c *mgo.Collection) error {
		return c.Find(bson.M{"profile.nickname": m.Username}).One(&account)
	}); err != nil {
		return 0, err
	}

	q := userEndpoint.Query()
	q.Set("account_id", account.Id.Hex())
	userEndpoint.RawQuery = q.Encode()

	p.Log.Debug("[%s] fetching plan via URL: '%s'", m.Id, userEndpoint.String())
	resp, err := http.Get(userEndpoint.String())
	if err != nil {
		return 0, err
	}
	defer resp.Body.Close()

	var subscription *SubscriptionsResponse
	e := json.NewDecoder(resp.Body)
	if err := e.Decode(&subscription); err != nil {
		return 0, err
	}

	// return an error back for a non 200 status
	if resp.StatusCode != 200 {
		if subscription.Error != "" {
			return 0, fmt.Errorf("[%s] could not fetch subscription. err: '%s'",
				m.Id, subscription.Description)
		}

		return 0, fmt.Errorf("[%s] could not fetch subscription. status code: %d",
			m.Id, resp.StatusCode)
	}

	plan, ok := plans[subscription.PlanTitle]
	if !ok {
		return 0, fmt.Errorf("[%s] could not find plan. There is no plan called '%s'",
			m.Id, subscription.PlanTitle)
	}

	p.Log.Debug("[%s] user has plan: %s", m.Id, plan)
	return plan, nil
}
<|endoftext|>


<commit_before>
<commit_msg>Delete controller.go<commit_after><|endoftext|>


<commit_before>package main

import (
	"bytes"
	"errors"
	"io"
	"log"
	"net"
	"os"
	"os/exec"
	"strings"
	"time"

	"github.com/dropbox/godropbox/cinterop"
)

func reader(r io.Reader) {
	buf := make([]byte, 1024)
	for {
		n, err := r.Read(buf[:])
		if err != nil {
			return
		}
		println("Client got:", string(buf[0:n]))
	}
}

func main() {
	srv := exec.Command("./example")
	srvin, _ := srv.StdinPipe()
	srvout, _ := srv.StdoutPipe()
	srv.Stderr = os.Stderr
	srv.Start()

	filePathAndToken := make([]byte, 96)
	_, err := io.ReadFull(srvout, filePathAndToken)
	header := filePathAndToken[:32]
	if !bytes.Equal(header, []byte(cinterop.Header)) {
		panic(errors.New("CInterop header mismatch"))
	}
	filePath := filePathAndToken[32:64]
	token := filePathAndToken[64:]
	if err != nil {
		panic(err)
	}
	c, err := net.Dial("unix", strings.TrimRight(string(filePath), "\n"))
	if err != nil {
		panic(err)
	}
	defer c.Close()
	c.Write(token)
	go reader(c)
	for {
		_, err := c.Write([]byte("hi"))
		if err != nil {
			log.Fatal("write error:", err)
			break
		}
		time.Sleep(1e9)
	}
	srv.Wait()
	srvin.Close()
}
<commit_msg>delete minor unreachable code caused by log.Fatal<commit_after>package main

import (
	"bytes"
	"errors"
	"io"
	"log"
	"net"
	"os"
	"os/exec"
	"strings"
	"time"

	"github.com/dropbox/godropbox/cinterop"
)

func reader(r io.Reader) {
	buf := make([]byte, 1024)
	for {
		n, err := r.Read(buf[:])
		if err != nil {
			return
		}
		println("Client got:", string(buf[0:n]))
	}
}

func main() {
	srv := exec.Command("./example")
	srvin, _ := srv.StdinPipe()
	srvout, _ := srv.StdoutPipe()
	srv.Stderr = os.Stderr
	srv.Start()

	filePathAndToken := make([]byte, 96)
	_, err := io.ReadFull(srvout, filePathAndToken)
	header := filePathAndToken[:32]
	if !bytes.Equal(header, []byte(cinterop.Header)) {
		panic(errors.New("CInterop header mismatch"))
	}
	filePath := filePathAndToken[32:64]
	token := filePathAndToken[64:]
	if err != nil {
		panic(err)
	}
	c, err := net.Dial("unix", strings.TrimRight(string(filePath), "\n"))
	if err != nil {
		panic(err)
	}
	defer c.Close()
	c.Write(token)
	go reader(c)
	for {
		_, err := c.Write([]byte("hi"))
		if err != nil {
			log.Fatal("write error:", err)
		}
		time.Sleep(1e9)
	}
	srv.Wait()
	srvin.Close()
}
<|endoftext|>


<commit_before>package ssh

import (
	"fmt"
	"time"
)

// debug printing utilities

var verbose bool = true

func p(format string, a ...interface{}) {
	if verbose {
		tsPrintf(format, a...)
	}
}

// quiet: discard text
func q(format string, a ...interface{}) {}

func pp(format string, a ...interface{}) {
	tsPrintf(format, a...)
}

func ppp(format string, a ...interface{}) {
	fmt.Printf("\n"+format+"\n", a...)
}

// time-stamped printf
func tsPrintf(format string, a ...interface{}) {
	fmt.Printf("\n%s ", ts())
	fmt.Printf(format+"\n", a...)
}

// get timestamp for logging purposes
func ts() string {
	return time.Now().Format("2006-01-02 15:04:05.999 -0700 MST")
}
<commit_msg>quiet<commit_after>package ssh

import (
	"fmt"
	"time"
)

// debug printing utilities

var verbose bool = false

func p(format string, a ...interface{}) {
	if verbose {
		tsPrintf(format, a...)
	}
}

// quiet: discard text
func q(format string, a ...interface{}) {}

func pp(format string, a ...interface{}) {
	tsPrintf(format, a...)
}

func ppp(format string, a ...interface{}) {
	fmt.Printf("\n"+format+"\n", a...)
}

// time-stamped printf
func tsPrintf(format string, a ...interface{}) {
	fmt.Printf("\n%s ", ts())
	fmt.Printf(format+"\n", a...)
}

// get timestamp for logging purposes
func ts() string {
	return time.Now().Format("2006-01-02 15:04:05.999 -0700 MST")
}
<|endoftext|>


<commit_before>/*
   PulseHA - HA Cluster Daemon
   Copyright (C) 2017-2018  Andrew Zak <andrew@pulseha.com>

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published
   by the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Affero General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package server

import (
	"encoding/json"
	"errors"
	log "github.com/Sirupsen/logrus"
	p "github.com/Syleron/PulseHA/proto"
	"github.com/Syleron/PulseHA/src/client"
	"github.com/Syleron/PulseHA/src/utils"
	"google.golang.org/grpc/connectivity"
	"sync"
	"time"
	)

/**
 * MemberList struct type
 */
type MemberList struct {
	Members []*Member
	sync.Mutex
}

/**

 */
func (m *MemberList) Lock() {
	m.Mutex.Lock()
}

/**

 */
func (m *MemberList) Unlock() {
	m.Mutex.Unlock()
}

/**
 * Add a member to the client list
 */
func (m *MemberList) AddMember(hostname string, client *client.Client) {
	if !m.MemberExists(hostname) {
		log.Debug("MemberList:MemberAdd() " + hostname + " added to memberlist")
		m.Lock()
		newMember := &Member{}
		newMember.SetHostname(hostname)
		newMember.SetStatus(p.MemberStatus_UNAVAILABLE)
		newMember.SetClient(client)
		m.Members = append(m.Members, newMember)
		m.Unlock()
	} else {
		log.Debug("MemberList:MemberAdd() Member " + hostname + " already exists. Skipping.")
	}
}

/**
 * Remove a member from the client list by hostname
 */
func (m *MemberList) MemberRemoveByName(hostname string) {
	log.Debug("MemberList:MemberRemoveByName() " + hostname + " removed from the memberlist")
	m.Lock()
	defer m.Unlock()
	for i, member := range m.Members {
		if member.GetHostname() == hostname {
			m.Members = append(m.Members[:i], m.Members[i+1:]...)
		}
	}
}

/**
 * Return Member by hostname
 */
func (m *MemberList) GetMemberByHostname(hostname string) *Member {
	m.Lock()
	defer m.Unlock()
	if hostname == "" {
		log.Warning("MemberList:GetMemberByHostname() Unable to get get member by hostname as hostname is empty!")
	}
	for _, member := range m.Members {
		if member.GetHostname() == hostname {
			return member
		}
	}
	return nil
}

/**
 * Return true/false whether a member exists or not.
 */
func (m *MemberList) MemberExists(hostname string) bool {
	m.Lock()
	defer m.Unlock()
	for _, member := range m.Members {
		if member.GetHostname() == hostname {
			return true
		}
	}
	return false
}

/**
 * Attempt to broadcast a client function to other nodes (clients) within the memberlist
 */
func (m *MemberList) Broadcast(funcName client.ProtoFunction, data interface{}) {
	log.Debug("MemberList:Broadcast() Broadcasting " + funcName.String())
	m.Lock()
	defer m.Unlock()
	for _, member := range m.Members {
		// We don't want to broadcast to our self!
		hostname, err := utils.GetHostname()
		if err != nil {
			log.Error("cannot broadcast as unable to get local hostname")
			return
		}
		if member.GetHostname() == hostname {
			continue
		}
		log.Debugf("Broadcast: %s to member %s", funcName.String(), member.GetHostname())
		member.Connect()
		member.Send(funcName, data)
	}
}

/**
Setup process for the memberlist
*/
func (m *MemberList) Setup() {
	// Load members into our memberlist slice
	m.LoadMembers()
	// Check to see if we are in a cluster
	if DB.Config.ClusterCheck() {
		// Are we the only member in the cluster?
		if DB.Config.NodeCount() == 1 {
			// We are the only member in the cluster so
			// we are assume that we are now the active appliance.
			m.PromoteMember(DB.Config.GetLocalNode())
		} else {
			// come up passive and monitoring health checks
			localMember := m.GetMemberByHostname(DB.Config.GetLocalNode())
			localMember.SetLastHCResponse(time.Now())
			localMember.SetStatus(p.MemberStatus_PASSIVE)
			log.Debug("MemberList:Setup() starting the monitor received health checks scheduler")
			go utils.Scheduler(localMember.MonitorReceivedHCs, 2000*time.Millisecond)
		}
	}
}

/**
load the nodes in our config into our memberlist
*/
func (m *MemberList) LoadMembers() {
	for key := range DB.Config.Nodes {
		newClient := &client.Client{}
		m.AddMember(key, newClient)
	}
}

/**
Reload the memberlist
 */
func (m *MemberList) Reload() {
	log.Debug("MemberList:ReloadMembers() Reloading member nodes")
	// clear local members
	m.LoadMembers()
}

/**
Get status of a specific member by hostname
*/
func (m *MemberList) MemberGetStatus(hostname string) (p.MemberStatus_Status, error) {
	m.Lock()
	defer m.Unlock()
	for _, member := range m.Members {
		if member.GetHostname() == hostname {
			return member.GetStatus(), nil
		}
	}
	return p.MemberStatus_UNAVAILABLE, errors.New("unable to find member with hostname " + hostname)
}

/*
	Return the hostname of the active member
	or empty string if non are active
*/
func (m *MemberList) GetActiveMember() (string, *Member) {
	for _, member := range m.Members {
		if member.GetStatus() == p.MemberStatus_ACTIVE {
			return member.GetHostname(), member
		}
	}
	return "", nil
}

/**
Promote a member within the memberlist to become the active
node
*/
func (m *MemberList) PromoteMember(hostname string) error {
	log.Debug("MemberList:PromoteMember() MemberList promoting " + hostname + " as active member..")
	// Inform everyone in the cluster that a specific node is now the new active
	// Demote if old active is no longer active. promote if the passive is the new active.
	// get host is it active?
	// Make sure the hostname member exists
	member := m.GetMemberByHostname(hostname)
	if member == nil {
		log.Warningf("Unknown hostname %s give in call to promoteMember", hostname)
		return errors.New("the specified host does not exist in the configured cluster")
	}
	// if unavailable check it works or do nothing?
	switch member.GetStatus() {
	case p.MemberStatus_UNAVAILABLE:
		//If we are the only node and just configured we will be unavailable
		if DB.Config.NodeCount() > 1 {
			log.Warningf("Unable to promote member %s because it is unavailable", member.GetHostname())
			return errors.New("unable to promote member as it is unavailable")
		}
	case p.MemberStatus_ACTIVE:
		log.Warningf("Unable to promote member %s as it is active", member.GetHostname())
		return errors.New("unable to promote member as it is already active")
	}
	// get the current active member
	_, activeMember := m.GetActiveMember()
	// handle if we do not have an active member
	if activeMember != nil {
		// Make the current Active appliance passive
		success := activeMember.MakePassive()
		if !success {
			log.Warningf("Failed to make %s passive, continuing", activeMember.GetHostname())
		}
		// TODO: Note: Do we need this?
		// Update our local value for the active member
		activeMember.SetStatus(p.MemberStatus_PASSIVE)
	}
	// make the hostname the new active
	success := member.MakeActive()
	// make new node active
	if !success {
		log.Warningf("Failed to promote %s to active. Falling back to %s", member.GetHostname(), activeMember.GetHostname())
		// Somethings gone wrong.. attempt to make the previous active - active again.
		success := activeMember.MakeActive()
		if !success {
			log.Error("Failed to make reinstate the active node. Something is really wrong")
		}
		// Note: we don't need to update the active status as we should receive an updated memberlist from the active
	}
	return nil
}

/**
	Function is only to be run on the active appliance
	Note: THis is not the final function name.. or not sure if this is
          where this logic will stay.. just playing around at this point.
	monitors the connections states for each member
*/
func (m *MemberList) MonitorClientConns() bool {
	// make sure we are still the active appliance
	member, err := m.GetLocalMember()
	if err != nil {
		log.Debug("MemberList:monitorClientConns() Client monitoring has stopped as it seems we are no longer in a cluster")
		return true
	}
	if member.GetStatus() == p.MemberStatus_PASSIVE {
		log.Debug("MemberList:monitorClientConns() Client monitoring has stopped as we are no longer active")
		return true
	}
	for _, member := range m.Members {
		if member.GetHostname() == DB.Config.GetLocalNode() {
			continue
		}
		member.Connect()
		log.Debug("MemberList:MonitorClientConns() " + member.Hostname + " connection status is " + member.Connection.GetState().String())
		switch member.Connection.GetState() {
		case connectivity.Idle:
		case connectivity.Ready:
			member.SetStatus(p.MemberStatus_PASSIVE)
		default:
			member.SetStatus(p.MemberStatus_UNAVAILABLE)
		}
	}
	return false
}

/**
Send health checks to users who have a healthy connection
*/
func (m *MemberList) AddHealthCheckHandler() bool {
	// make sure we are still the active appliance
	member, err := m.GetLocalMember()
	if err != nil {
		log.Debug("MemberList:addHealthCheckhandler() Health check handler has stopped as it seems we are no longer in a cluster")
		return true
	}
	if member.GetStatus() == p.MemberStatus_PASSIVE {
		log.Debug("MemberList:addHealthCheckHandler() Health check handler has stopped as it seems we are no longer active")
		return true
	}
	for _, member := range m.Members {
		if member.GetHostname() == DB.Config.GetLocalNode() {
			continue
		}
		if !member.GetHCBusy() && member.GetStatus() == p.MemberStatus_PASSIVE {
			memberlist := new(p.PulseHealthCheck)
			for _, member := range m.Members {
				newMember := &p.MemberlistMember{
					Hostname:     member.GetHostname(),
					Status:       member.GetStatus(),
					Latency:      member.GetLatency(),
					LastReceived: member.GetLastHCResponse().Format(time.RFC1123),
				}
				memberlist.Memberlist = append(memberlist.Memberlist, newMember)
			}
			go member.RoutineHC(memberlist)
		}
	}
	return false
}

/**
Sync local config with each member in the cluster.
*/
func (m *MemberList) SyncConfig() error {
	log.Debug("MemberList:SyncConfig Syncing config with peers..")
	// Return with our new updated config
	buf, err := json.Marshal(DB.Config.GetConfig())
	// Handle failure to marshal config
	if err != nil {
		return errors.New("unable to sync config " + err.Error())
	}
	m.Broadcast(client.SendConfigSync, &p.PulseConfigSync{
		Replicated: true,
		Config:     buf,
	})
	return nil
}

/**
Update the local memberlist statuses based on the proto memberlist message
*/
func (m *MemberList) Update(memberlist []*p.MemberlistMember) {
	log.Debug("MemberList:update() Updating memberlist")
	m.Lock()
	defer m.Unlock()
	//do not update the memberlist if we are active
	for _, member := range memberlist {
		for _, localMember := range m.Members {
			if member.GetHostname() == localMember.GetHostname() {
				localMember.SetStatus(member.Status)
				localMember.SetLatency(member.Latency)
				// our local last received has priority
				if member.GetHostname() != DB.Config.GetLocalNode() {
					tym, _ := time.Parse(time.RFC1123, member.LastReceived)
					localMember.SetLastHCResponse(tym)
				}
				break
			}
		}
	}
}

/**
Calculate who's next to become active in the memberlist
*/
func (m *MemberList) GetNextActiveMember() (*Member, error) {
	for hostname, _ := range DB.Config.Nodes {
		member := m.GetMemberByHostname(hostname)
		if member == nil {
			panic("MemberList:getNextActiveMember() Cannot get member by hostname " + hostname)
		}
		if member.GetStatus() == p.MemberStatus_PASSIVE {
			log.Debug("MemberList:getNextActiveMember() " + member.GetHostname() + " is the new active appliance")
			return member, nil
		}
	}
	return &Member{}, errors.New("MemberList:getNextActiveMember() No new active member found")
}

/**

 */
func (m *MemberList) GetLocalMember() (*Member, error) {
	m.Lock()
	defer m.Unlock()
	for _, member := range m.Members {
		if member.GetHostname() == DB.Config.GetLocalNode() {
			return member, nil
		}
	}
	return &Member{}, errors.New("cannot get local member. Perhaps we are no longer in a cluster")
}

/**
Reset the memberlist when we are no longer in a cluster.
*/
func (m *MemberList) Reset() {
	m.Lock()
	defer m.Unlock()
	m.Members = []*Member{}
}
<commit_msg>Fixed not being able to promote after assign/unassign a FIP group<commit_after>/*
   PulseHA - HA Cluster Daemon
   Copyright (C) 2017-2018  Andrew Zak <andrew@pulseha.com>

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published
   by the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Affero General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package server

import (
	"encoding/json"
	"errors"
	log "github.com/Sirupsen/logrus"
	p "github.com/Syleron/PulseHA/proto"
	"github.com/Syleron/PulseHA/src/client"
	"github.com/Syleron/PulseHA/src/utils"
	"google.golang.org/grpc/connectivity"
	"sync"
	"time"
	)

/**
 * MemberList struct type
 */
type MemberList struct {
	Members []*Member
	sync.Mutex
}

/**

 */
func (m *MemberList) Lock() {
	m.Mutex.Lock()
}

/**

 */
func (m *MemberList) Unlock() {
	m.Mutex.Unlock()
}

/**
 * Add a member to the client list
 */
func (m *MemberList) AddMember(hostname string, client *client.Client) {
	if !m.MemberExists(hostname) {
		log.Debug("MemberList:MemberAdd() " + hostname + " added to memberlist")
		m.Lock()
		newMember := &Member{}
		newMember.SetHostname(hostname)
		newMember.SetStatus(p.MemberStatus_UNAVAILABLE)
		newMember.SetClient(client)
		m.Members = append(m.Members, newMember)
		m.Unlock()
	} else {
		log.Debug("MemberList:MemberAdd() Member " + hostname + " already exists. Skipping.")
	}
}

/**
 * Remove a member from the client list by hostname
 */
func (m *MemberList) MemberRemoveByName(hostname string) {
	log.Debug("MemberList:MemberRemoveByName() " + hostname + " removed from the memberlist")
	m.Lock()
	defer m.Unlock()
	for i, member := range m.Members {
		if member.GetHostname() == hostname {
			m.Members = append(m.Members[:i], m.Members[i+1:]...)
		}
	}
}

/**
 * Return Member by hostname
 */
func (m *MemberList) GetMemberByHostname(hostname string) *Member {
	m.Lock()
	defer m.Unlock()
	if hostname == "" {
		log.Warning("MemberList:GetMemberByHostname() Unable to get get member by hostname as hostname is empty!")
	}
	for _, member := range m.Members {
		if member.GetHostname() == hostname {
			return member
		}
	}
	return nil
}

/**
 * Return true/false whether a member exists or not.
 */
func (m *MemberList) MemberExists(hostname string) bool {
	m.Lock()
	defer m.Unlock()
	for _, member := range m.Members {
		if member.GetHostname() == hostname {
			return true
		}
	}
	return false
}

/**
 * Attempt to broadcast a client function to other nodes (clients) within the memberlist
 */
func (m *MemberList) Broadcast(funcName client.ProtoFunction, data interface{}) {
	log.Debug("MemberList:Broadcast() Broadcasting " + funcName.String())
	m.Lock()
	defer m.Unlock()
	for _, member := range m.Members {
		// We don't want to broadcast to our self!
		hostname, err := utils.GetHostname()
		if err != nil {
			log.Error("cannot broadcast as unable to get local hostname")
			return
		}
		if member.GetHostname() == hostname {
			continue
		}
		log.Debugf("Broadcast: %s to member %s", funcName.String(), member.GetHostname())
		member.Connect()
		member.Send(funcName, data)
	}
}

/**
Setup process for the memberlist
*/
func (m *MemberList) Setup() {
	// Load members into our memberlist slice
	m.LoadMembers()
	// Check to see if we are in a cluster
	if DB.Config.ClusterCheck() {
		// Are we the only member in the cluster?
		if DB.Config.NodeCount() == 1 {
			// We are the only member in the cluster so
			// we are assume that we are now the active appliance.
			m.PromoteMember(DB.Config.GetLocalNode())
		} else {
			// come up passive and monitoring health checks
			localMember := m.GetMemberByHostname(DB.Config.GetLocalNode())
			localMember.SetLastHCResponse(time.Now())
			localMember.SetStatus(p.MemberStatus_PASSIVE)
			log.Debug("MemberList:Setup() starting the monitor received health checks scheduler")
			go utils.Scheduler(localMember.MonitorReceivedHCs, 2000*time.Millisecond)
		}
	}
}

/**
load the nodes in our config into our memberlist
*/
func (m *MemberList) LoadMembers() {
	for key := range DB.Config.Nodes {
		newClient := &client.Client{}
		m.AddMember(key, newClient)
	}
}

/**
Reload the memberlist
 */
func (m *MemberList) Reload() {
	log.Debug("MemberList:ReloadMembers() Reloading member nodes")
	// Reload our config
	DB.Config.Reload()
	// clear local members
	m.LoadMembers()
}

/**
Get status of a specific member by hostname
*/
func (m *MemberList) MemberGetStatus(hostname string) (p.MemberStatus_Status, error) {
	m.Lock()
	defer m.Unlock()
	for _, member := range m.Members {
		if member.GetHostname() == hostname {
			return member.GetStatus(), nil
		}
	}
	return p.MemberStatus_UNAVAILABLE, errors.New("unable to find member with hostname " + hostname)
}

/*
	Return the hostname of the active member
	or empty string if non are active
*/
func (m *MemberList) GetActiveMember() (string, *Member) {
	for _, member := range m.Members {
		if member.GetStatus() == p.MemberStatus_ACTIVE {
			return member.GetHostname(), member
		}
	}
	return "", nil
}

/**
Promote a member within the memberlist to become the active
node
*/
func (m *MemberList) PromoteMember(hostname string) error {
	log.Debug("MemberList:PromoteMember() MemberList promoting " + hostname + " as active member..")
	// Inform everyone in the cluster that a specific node is now the new active
	// Demote if old active is no longer active. promote if the passive is the new active.
	// get host is it active?
	// Make sure the hostname member exists
	member := m.GetMemberByHostname(hostname)
	if member == nil {
		log.Warningf("Unknown hostname %s give in call to promoteMember", hostname)
		return errors.New("the specified host does not exist in the configured cluster")
	}
	// if unavailable check it works or do nothing?
	switch member.GetStatus() {
	case p.MemberStatus_UNAVAILABLE:
		//If we are the only node and just configured we will be unavailable
		if DB.Config.NodeCount() > 1 {
			log.Warningf("Unable to promote member %s because it is unavailable", member.GetHostname())
			return errors.New("unable to promote member as it is unavailable")
		}
	case p.MemberStatus_ACTIVE:
		log.Warningf("Unable to promote member %s as it is active", member.GetHostname())
		return errors.New("unable to promote member as it is already active")
	}
	// get the current active member
	_, activeMember := m.GetActiveMember()
	// handle if we do not have an active member
	if activeMember != nil {
		// Make the current Active appliance passive
		success := activeMember.MakePassive()
		if !success {
			log.Warningf("Failed to make %s passive, continuing", activeMember.GetHostname())
		}
		// TODO: Note: Do we need this?
		// Update our local value for the active member
		activeMember.SetStatus(p.MemberStatus_PASSIVE)
	}
	// make the hostname the new active
	success := member.MakeActive()
	// make new node active
	if !success {
		log.Warningf("Failed to promote %s to active. Falling back to %s", member.GetHostname(), activeMember.GetHostname())
		// Somethings gone wrong.. attempt to make the previous active - active again.
		success := activeMember.MakeActive()
		if !success {
			log.Error("Failed to make reinstate the active node. Something is really wrong")
		}
		// Note: we don't need to update the active status as we should receive an updated memberlist from the active
	}
	return nil
}

/**
	Function is only to be run on the active appliance
	Note: THis is not the final function name.. or not sure if this is
          where this logic will stay.. just playing around at this point.
	monitors the connections states for each member
*/
func (m *MemberList) MonitorClientConns() bool {
	// make sure we are still the active appliance
	member, err := m.GetLocalMember()
	if err != nil {
		log.Debug("MemberList:monitorClientConns() Client monitoring has stopped as it seems we are no longer in a cluster")
		return true
	}
	if member.GetStatus() == p.MemberStatus_PASSIVE {
		log.Debug("MemberList:monitorClientConns() Client monitoring has stopped as we are no longer active")
		return true
	}
	for _, member := range m.Members {
		if member.GetHostname() == DB.Config.GetLocalNode() {
			continue
		}
		member.Connect()
		log.Debug("MemberList:MonitorClientConns() " + member.Hostname + " connection status is " + member.Connection.GetState().String())
		switch member.Connection.GetState() {
		case connectivity.Idle:
		case connectivity.Ready:
			member.SetStatus(p.MemberStatus_PASSIVE)
		default:
			member.SetStatus(p.MemberStatus_UNAVAILABLE)
		}
	}
	return false
}

/**
Send health checks to users who have a healthy connection
*/
func (m *MemberList) AddHealthCheckHandler() bool {
	// make sure we are still the active appliance
	member, err := m.GetLocalMember()
	if err != nil {
		log.Debug("MemberList:addHealthCheckhandler() Health check handler has stopped as it seems we are no longer in a cluster")
		return true
	}
	if member.GetStatus() == p.MemberStatus_PASSIVE {
		log.Debug("MemberList:addHealthCheckHandler() Health check handler has stopped as it seems we are no longer active")
		return true
	}
	for _, member := range m.Members {
		if member.GetHostname() == DB.Config.GetLocalNode() {
			continue
		}
		if !member.GetHCBusy() && member.GetStatus() == p.MemberStatus_PASSIVE {
			memberlist := new(p.PulseHealthCheck)
			for _, member := range m.Members {
				newMember := &p.MemberlistMember{
					Hostname:     member.GetHostname(),
					Status:       member.GetStatus(),
					Latency:      member.GetLatency(),
					LastReceived: member.GetLastHCResponse().Format(time.RFC1123),
				}
				memberlist.Memberlist = append(memberlist.Memberlist, newMember)
			}
			go member.RoutineHC(memberlist)
		}
	}
	return false
}

/**
Sync local config with each member in the cluster.
*/
func (m *MemberList) SyncConfig() error {
	log.Debug("MemberList:SyncConfig() Syncing config with peers..")
	// Return with our new updated config
	buf, err := json.Marshal(DB.Config.GetConfig())
	// Handle failure to marshal config
	if err != nil {
		return errors.New("unable to sync config " + err.Error())
	}
	m.Broadcast(client.SendConfigSync, &p.PulseConfigSync{
		Replicated: true,
		Config:     buf,
	})
	return nil
}

/**
Update the local memberlist statuses based on the proto memberlist message
*/
func (m *MemberList) Update(memberlist []*p.MemberlistMember) {
	log.Debug("MemberList:update() Updating memberlist")
	m.Lock()
	defer m.Unlock()
	//do not update the memberlist if we are active
	for _, member := range memberlist {
		for _, localMember := range m.Members {
			if member.GetHostname() == localMember.GetHostname() {
				localMember.SetStatus(member.Status)
				localMember.SetLatency(member.Latency)
				// our local last received has priority
				if member.GetHostname() != DB.Config.GetLocalNode() {
					tym, _ := time.Parse(time.RFC1123, member.LastReceived)
					localMember.SetLastHCResponse(tym)
				}
				break
			}
		}
	}
}

/**
Calculate who's next to become active in the memberlist
*/
func (m *MemberList) GetNextActiveMember() (*Member, error) {
	for hostname, _ := range DB.Config.Nodes {
		member := m.GetMemberByHostname(hostname)
		if member == nil {
			panic("MemberList:getNextActiveMember() Cannot get member by hostname " + hostname)
		}
		if member.GetStatus() == p.MemberStatus_PASSIVE {
			log.Debug("MemberList:getNextActiveMember() " + member.GetHostname() + " is the new active appliance")
			return member, nil
		}
	}
	return &Member{}, errors.New("MemberList:getNextActiveMember() No new active member found")
}

/**

 */
func (m *MemberList) GetLocalMember() (*Member, error) {
	m.Lock()
	defer m.Unlock()
	for _, member := range m.Members {
		if member.GetHostname() == DB.Config.GetLocalNode() {
			return member, nil
		}
	}
	return &Member{}, errors.New("cannot get local member. Perhaps we are no longer in a cluster")
}

/**
Reset the memberlist when we are no longer in a cluster.
*/
func (m *MemberList) Reset() {
	m.Lock()
	defer m.Unlock()
	m.Members = []*Member{}
}
<|endoftext|>


<commit_before>package log

import (
	"encoding/json"
	"fmt"
	"runtime"
	"strings"
	"sync"
	"time"

	"github.com/fatih/camelcase"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/sirupsen/logrus"
)

const (
	bucketFactor = 2.0
	bucketCount  = 20 // Which makes the max bucket 2^20 seconds or ~12 days in size
)

// This needs to be a global var, not a field on the logger, because multiple servers
// create new loggers, and the prometheus registration uses a global namespace
var reportMetricGauge prometheus.Gauge
var reportMetricsOnce sync.Once

// Logger is a helper for emitting our grpc API logs
type Logger interface {
	Log(request interface{}, response interface{}, err error, duration time.Duration)
	LogAtLevelFromDepth(request interface{}, response interface{}, err error, duration time.Duration, level logrus.Level, depth int)
}

type logger struct {
	*logrus.Entry
	histogram   map[string]*prometheus.HistogramVec
	counter     map[string]prometheus.Counter
	mutex       *sync.Mutex
	exportStats bool
}

// NewLogger creates a new logger
func NewLogger(service string) Logger {
	return newLogger(service, true)
}

// NewLocalLogger creates a new logger for local testing (which does not report prometheus metrics)
func NewLocalLogger(service string) Logger {
	return newLogger(service, false)
}

func newLogger(service string, exportStats bool) Logger {
	l := logrus.New()
	l.Formatter = new(prettyFormatter)
	newLogger := &logger{
		l.WithFields(logrus.Fields{"service": service}),
		make(map[string]*prometheus.HistogramVec),
		make(map[string]prometheus.Counter),
		&sync.Mutex{},
		exportStats,
	}
	if exportStats {
		reportMetricsOnce.Do(func() {
			newReportMetricGauge := prometheus.NewGauge(
				prometheus.GaugeOpts{
					Namespace: "pachyderm",
					Subsystem: "pachd",
					Name:      "report_metric",
					Help:      "gauge of number of calls to ReportMetric()",
				},
			)
			if err := prometheus.Register(newReportMetricGauge); err != nil {
				entry := newLogger.WithFields(logrus.Fields{"method": "NewLogger"})
				newLogger.LogAtLevel(entry, logrus.WarnLevel, "error registering prometheus metric: %v", err)
			} else {
				reportMetricGauge = newReportMetricGauge
			}
		})
	}
	return newLogger
}

// Helper function used to log requests and responses from our GRPC method
// implementations
func (l *logger) Log(request interface{}, response interface{}, err error, duration time.Duration) {
	if err != nil {
		l.LogAtLevelFromDepth(request, response, err, duration, logrus.ErrorLevel, 4)
	} else {
		l.LogAtLevelFromDepth(request, response, err, duration, logrus.InfoLevel, 4)
	}
	// We have to grab the method's name here before we
	// enter the goro's stack
	go l.ReportMetric(getMethodName(), duration, err)
}

func getMethodName() string {
	depth := 4
	pc := make([]uintptr, depth)
	runtime.Callers(depth, pc)
	split := strings.Split(runtime.FuncForPC(pc[0]).Name(), ".")
	return split[len(split)-1]
}

func (l *logger) ReportMetric(method string, duration time.Duration, err error) {
	if !l.exportStats {
		return
	}
	// Count the number of ReportMetric() goros in case we start to leak them
	if reportMetricGauge != nil {
		reportMetricGauge.Inc()
	}
	defer func() {
		if reportMetricGauge != nil {
			reportMetricGauge.Dec()
		}
	}()
	l.mutex.Lock() // for conccurent map access (histogram,counter)
	defer l.mutex.Unlock()
	state := "started"
	if err != nil {
		state = "errored"
	} else {
		if duration.Seconds() > 0 {
			state = "finished"
		}
	}
	entry := l.WithFields(logrus.Fields{"method": method})

	var tokens []string
	for _, token := range camelcase.Split(method) {
		tokens = append(tokens, strings.ToLower(token))
	}
	rootStatName := strings.Join(tokens, "_")

	// Recording the distribution of started times is meaningless
	if state != "started" {
		runTimeName := fmt.Sprintf("%v_time", rootStatName)
		runTime, ok := l.histogram[runTimeName]
		if !ok {
			runTime = prometheus.NewHistogramVec(
				prometheus.HistogramOpts{
					Namespace: "pachyderm",
					Subsystem: "pachd",
					Name:      runTimeName,
					Help:      fmt.Sprintf("Run time of %v", method),
					Buckets:   prometheus.ExponentialBuckets(1.0, bucketFactor, bucketCount),
				},
				[]string{
					"state", // Since both finished and errored API calls can have run times
				},
			)
			if err := prometheus.Register(runTime); err != nil {
				l.LogAtLevel(entry, logrus.WarnLevel, "error registering prometheus metric: %v", err)
			} else {
				l.histogram[runTimeName] = runTime
			}
		}
		if hist, err := runTime.GetMetricWithLabelValues(state); err != nil {
			l.LogAtLevel(entry, logrus.WarnLevel, "failed to get histogram w labels: state (%v) with error %v", state, err)
		} else {
			hist.Observe(duration.Seconds())
		}
	}

	secondsCountName := fmt.Sprintf("%v_seconds_count", rootStatName)
	secondsCount, ok := l.counter[secondsCountName]
	if !ok {
		secondsCount = prometheus.NewCounter(
			prometheus.CounterOpts{
				Namespace: "pachyderm",
				Subsystem: "pachd",
				Name:      secondsCountName,
				Help:      fmt.Sprintf("cumulative number of seconds spent in %v", method),
			},
		)
		if err := prometheus.Register(secondsCount); err != nil {
			l.LogAtLevel(entry, logrus.WarnLevel, "error registering prometheus metric: %v", err)
		} else {
			l.counter[secondsCountName] = secondsCount
		}
	}
	secondsCount.Add(duration.Seconds())

}

func (l *logger) LogAtLevel(entry *logrus.Entry, level logrus.Level, args ...interface{}) {
	switch level {
	case logrus.PanicLevel:
		entry.Panic(args)
	case logrus.FatalLevel:
		entry.Fatal(args)
	case logrus.ErrorLevel:
		entry.Error(args)
	case logrus.WarnLevel:
		entry.Warn(args)
	case logrus.InfoLevel:
		entry.Info(args)
	case logrus.DebugLevel:
		entry.Debug(args)
	}
}

func (l *logger) LogAtLevelFromDepth(request interface{}, response interface{}, err error, duration time.Duration, level logrus.Level, depth int) {
	pc := make([]uintptr, depth)
	runtime.Callers(depth, pc)
	split := strings.Split(runtime.FuncForPC(pc[0]).Name(), ".")
	method := split[len(split)-1]

	fields := logrus.Fields{
		"method":  method,
		"request": request,
	}
	if response != nil {
		fields["response"] = response
	}
	if err != nil {
		// "err" itself might be a code or even an empty struct
		fields["error"] = err.Error()
	}
	if duration > 0 {
		fields["duration"] = duration
	}
	l.LogAtLevel(l.WithFields(fields), level)
}

type prettyFormatter struct{}

func (f *prettyFormatter) Format(entry *logrus.Entry) ([]byte, error) {
	serialized := []byte(
		fmt.Sprintf(
			"%v %v ",
			entry.Time.Format(logrus.DefaultTimestampFormat),
			strings.ToUpper(entry.Level.String()),
		),
	)
	if entry.Data["service"] != nil {
		serialized = append(serialized, []byte(fmt.Sprintf("%v.%v ", entry.Data["service"], entry.Data["method"]))...)
	}
	if len(entry.Data) > 2 {
		delete(entry.Data, "service")
		delete(entry.Data, "method")
		if entry.Data["duration"] != nil {
			entry.Data["duration"] = entry.Data["duration"].(time.Duration).Seconds()
		}
		data, err := json.Marshal(entry.Data)
		if err != nil {
			return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
		}
		serialized = append(serialized, []byte(string(data))...)
		serialized = append(serialized, ' ')
	}

	serialized = append(serialized, []byte(entry.Message)...)
	serialized = append(serialized, '\n')
	return serialized, nil
}
<commit_msg>Fix metric warnings<commit_after>package log

import (
	"encoding/json"
	"fmt"
	"runtime"
	"strings"
	"sync"
	"time"

	"github.com/fatih/camelcase"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/sirupsen/logrus"
)

const (
	bucketFactor = 2.0
	bucketCount  = 20 // Which makes the max bucket 2^20 seconds or ~12 days in size
)

// This needs to be a global var, not a field on the logger, because multiple servers
// create new loggers, and the prometheus registration uses a global namespace
var reportMetricGauge prometheus.Gauge
var reportMetricsOnce sync.Once

// Logger is a helper for emitting our grpc API logs
type Logger interface {
	Log(request interface{}, response interface{}, err error, duration time.Duration)
	LogAtLevelFromDepth(request interface{}, response interface{}, err error, duration time.Duration, level logrus.Level, depth int)
}

type logger struct {
	*logrus.Entry
	histogram   map[string]*prometheus.HistogramVec
	counter     map[string]prometheus.Counter
	mutex       *sync.Mutex
	exportStats bool
}

// NewLogger creates a new logger
func NewLogger(service string) Logger {
	return newLogger(service, true)
}

// NewLocalLogger creates a new logger for local testing (which does not report prometheus metrics)
func NewLocalLogger(service string) Logger {
	return newLogger(service, false)
}

func newLogger(service string, exportStats bool) Logger {
	l := logrus.New()
	l.Formatter = new(prettyFormatter)
	newLogger := &logger{
		l.WithFields(logrus.Fields{"service": service}),
		make(map[string]*prometheus.HistogramVec),
		make(map[string]prometheus.Counter),
		&sync.Mutex{},
		exportStats,
	}
	if exportStats {
		reportMetricsOnce.Do(func() {
			newReportMetricGauge := prometheus.NewGauge(
				prometheus.GaugeOpts{
					Namespace: "pachyderm",
					Subsystem: "pachd",
					Name:      "report_metric",
					Help:      "gauge of number of calls to ReportMetric()",
				},
			)
			if err := prometheus.Register(newReportMetricGauge); err != nil {
				entry := newLogger.WithFields(logrus.Fields{"method": "NewLogger"})
				newLogger.LogAtLevel(entry, logrus.WarnLevel, fmt.Sprintf("error registering prometheus metric: %v", newReportMetricGauge), err)
			} else {
				reportMetricGauge = newReportMetricGauge
			}
		})
	}
	return newLogger
}

// Helper function used to log requests and responses from our GRPC method
// implementations
func (l *logger) Log(request interface{}, response interface{}, err error, duration time.Duration) {
	if err != nil {
		l.LogAtLevelFromDepth(request, response, err, duration, logrus.ErrorLevel, 4)
	} else {
		l.LogAtLevelFromDepth(request, response, err, duration, logrus.InfoLevel, 4)
	}
	// We have to grab the method's name here before we
	// enter the goro's stack
	go l.ReportMetric(getMethodName(), duration, err)
}

func getMethodName() string {
	depth := 4
	pc := make([]uintptr, depth)
	runtime.Callers(depth, pc)
	split := strings.Split(runtime.FuncForPC(pc[0]).Name(), ".")
	return split[len(split)-1]
}

func (l *logger) ReportMetric(method string, duration time.Duration, err error) {
	if !l.exportStats {
		return
	}
	// Count the number of ReportMetric() goros in case we start to leak them
	if reportMetricGauge != nil {
		reportMetricGauge.Inc()
	}
	defer func() {
		if reportMetricGauge != nil {
			reportMetricGauge.Dec()
		}
	}()
	l.mutex.Lock() // for conccurent map access (histogram,counter)
	defer l.mutex.Unlock()
	state := "started"
	if err != nil {
		state = "errored"
	} else {
		if duration.Seconds() > 0 {
			state = "finished"
		}
	}
	entry := l.WithFields(logrus.Fields{"method": method})

	var tokens []string
	for _, token := range camelcase.Split(method) {
		tokens = append(tokens, strings.ToLower(token))
	}
	rootStatName := strings.Join(tokens, "_")

	// Recording the distribution of started times is meaningless
	if state != "started" {
		runTimeName := fmt.Sprintf("%v_time", rootStatName)
		runTime, ok := l.histogram[runTimeName]
		if !ok {
			runTime = prometheus.NewHistogramVec(
				prometheus.HistogramOpts{
					Namespace: "pachyderm",
					Subsystem: "pachd",
					Name:      runTimeName,
					Help:      fmt.Sprintf("Run time of %v", method),
					Buckets:   prometheus.ExponentialBuckets(1.0, bucketFactor, bucketCount),
				},
				[]string{
					"state", // Since both finished and errored API calls can have run times
				},
			)
			if err := prometheus.Register(runTime); err != nil {
				newLogger.LogAtLevel(entry, logrus.WarnLevel, fmt.Sprintf("error registering prometheus metric: %v", newReportMetricGauge), err)
			} else {
				l.histogram[runTimeName] = runTime
			}
		}
		if hist, err := runTime.GetMetricWithLabelValues(state); err != nil {
			l.LogAtLevel(entry, logrus.WarnLevel, "failed to get histogram w labels: state (%v) with error %v", state, err)
		} else {
			hist.Observe(duration.Seconds())
		}
	}

	secondsCountName := fmt.Sprintf("%v_seconds_count", rootStatName)
	secondsCount, ok := l.counter[secondsCountName]
	if !ok {
		secondsCount = prometheus.NewCounter(
			prometheus.CounterOpts{
				Namespace: "pachyderm",
				Subsystem: "pachd",
				Name:      secondsCountName,
				Help:      fmt.Sprintf("cumulative number of seconds spent in %v", method),
			},
		)
		if err := prometheus.Register(secondsCount); err != nil {
			newLogger.LogAtLevel(entry, logrus.WarnLevel, fmt.Sprintf("error registering prometheus metric: %v", newReportMetricGauge), err)
		} else {
			l.counter[secondsCountName] = secondsCount
		}
	}
	secondsCount.Add(duration.Seconds())

}

func (l *logger) LogAtLevel(entry *logrus.Entry, level logrus.Level, args ...interface{}) {
	switch level {
	case logrus.PanicLevel:
		entry.Panic(args)
	case logrus.FatalLevel:
		entry.Fatal(args)
	case logrus.ErrorLevel:
		entry.Error(args)
	case logrus.WarnLevel:
		entry.Warn(args)
	case logrus.InfoLevel:
		entry.Info(args)
	case logrus.DebugLevel:
		entry.Debug(args)
	}
}

func (l *logger) LogAtLevelFromDepth(request interface{}, response interface{}, err error, duration time.Duration, level logrus.Level, depth int) {
	pc := make([]uintptr, depth)
	runtime.Callers(depth, pc)
	split := strings.Split(runtime.FuncForPC(pc[0]).Name(), ".")
	method := split[len(split)-1]

	fields := logrus.Fields{
		"method":  method,
		"request": request,
	}
	if response != nil {
		fields["response"] = response
	}
	if err != nil {
		// "err" itself might be a code or even an empty struct
		fields["error"] = err.Error()
	}
	if duration > 0 {
		fields["duration"] = duration
	}
	l.LogAtLevel(l.WithFields(fields), level)
}

type prettyFormatter struct{}

func (f *prettyFormatter) Format(entry *logrus.Entry) ([]byte, error) {
	serialized := []byte(
		fmt.Sprintf(
			"%v %v ",
			entry.Time.Format(logrus.DefaultTimestampFormat),
			strings.ToUpper(entry.Level.String()),
		),
	)
	if entry.Data["service"] != nil {
		serialized = append(serialized, []byte(fmt.Sprintf("%v.%v ", entry.Data["service"], entry.Data["method"]))...)
	}
	if len(entry.Data) > 2 {
		delete(entry.Data, "service")
		delete(entry.Data, "method")
		if entry.Data["duration"] != nil {
			entry.Data["duration"] = entry.Data["duration"].(time.Duration).Seconds()
		}
		data, err := json.Marshal(entry.Data)
		if err != nil {
			return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
		}
		serialized = append(serialized, []byte(string(data))...)
		serialized = append(serialized, ' ')
	}

	serialized = append(serialized, []byte(entry.Message)...)
	serialized = append(serialized, '\n')
	return serialized, nil
}
<|endoftext|>


<commit_before>// skip

// Copyright 2010 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.

// Generate test of index and slice bounds checks.
// The actual tests are index0.go, index1.go, index2.go.

package main

import (
	"bufio"
	"fmt"
	"os"
	"runtime"
)

const prolog = `

package main

import (
	"runtime"
)

type quad struct { x, y, z, w int }

const (
	cj = 100011
	ci int = 100012
	ci8 int8 = 115
	ci16 int16 = 10016
	ci32 int32 = 100013
	ci64 int64 = 100014
	ci64big int64 = 1<<31
	ci64bigger int64 = 1<<32
	chuge = 1<<100

	cnj = -2
	cni int = -3
	cni8 int8 = -6
	cni16 int16 = -7
	cni32 int32 = -4
	cni64 int64 = -5
	cni64big int64 = -1<<31
	cni64bigger int64 = -1<<32
	cnhuge = -1<<100
)

var j int = 100020
var i int = 100021
var i8 int8 = 126
var i16 int16 = 10025
var i32 int32 = 100022
var i64 int64 = 100023
var i64big int64 = 1<<31
var i64bigger int64 = 1<<32
var huge uint64 = 1<<64 - 1

var nj int = -10
var ni int = -11
var ni8 int8 = -14
var ni16 int16 = -15
var ni32 int32 = -12
var ni64 int64 = -13
var ni64big int64 = -1<<31
var ni64bigger int64 = -1<<32
var nhuge int64 = -1<<63

var si []int = make([]int, 10)
var ai [10]int
var pai *[10]int = &ai

var sq []quad = make([]quad, 10)
var aq [10]quad
var paq *[10]quad = &aq

var sib []int = make([]int, 100000)
var aib [100000]int
var paib *[100000]int = &aib

var sqb []quad = make([]quad, 100000)
var aqb [100000]quad
var paqb *[100000]quad = &aqb

type T struct {
	si []int
	ai [10]int
	pai *[10]int
	sq []quad
	aq [10]quad
	paq *[10]quad

	sib []int
	aib [100000]int
	paib *[100000]int
	sqb []quad
	aqb [100000]quad
	paqb *[100000]quad
}

var t = T{si, ai, pai, sq, aq, paq, sib, aib, paib, sqb, aqb, paqb}

var pt = &T{si, ai, pai, sq, aq, paq, sib, aib, paib, sqb, aqb, paqb}

// test that f panics
func test(f func(), s string) {
	defer func() {
		if err := recover(); err == nil {
			_, file, line, _ := runtime.Caller(2)
			bug()
			print(file, ":", line, ": ", s, " did not panic\n")
		} else if !contains(err.(error).Error(), "out of range") {
			_, file, line, _ := runtime.Caller(2)
			bug()
			print(file, ":", line, ": ", s, " unexpected panic: ", err.(error).Error(), "\n")
		}
	}()
	f()
}

func contains(x, y string) bool {
	for i := 0; i+len(y) <= len(x); i++ {
		if x[i:i+len(y)] == y {
			return true
		}
	}
	return false
}

var X interface{}
func use(y interface{}) {
	X = y
}

var didBug = false

func bug() {
	if !didBug {
		didBug = true
		println("BUG")
	}
}

func main() {
`

// pass variable set in index[012].go
//	0 - dynamic checks
//	1 - static checks of invalid constants (cannot assign to types)
//	2 - static checks of array bounds

func testExpr(b *bufio.Writer, expr string) {
	if pass == 0 {
		fmt.Fprintf(b, "\ttest(func(){use(%s)}, %q)\n", expr, expr)
	} else {
		fmt.Fprintf(b, "\tuse(%s)  // ERROR \"index|overflow\"\n", expr)
	}
}

func main() {
	b := bufio.NewWriter(os.Stdout)

	if pass == 0 {
		fmt.Fprint(b, "// run\n\n")
	} else {
		fmt.Fprint(b, "// errorcheck\n\n")
	}
	fmt.Fprint(b, prolog)

	var choices = [][]string{
		// Direct value, fetch from struct, fetch from struct pointer.
		// The last two cases get us to oindex_const_sudo in gsubr.c.
		[]string{"", "t.", "pt."},

		// Array, pointer to array, slice.
		[]string{"a", "pa", "s"},

		// Element is int, element is quad (struct).
		// This controls whether we end up in gsubr.c (i) or cgen.c (q).
		[]string{"i", "q"},

		// Small or big len.
		[]string{"", "b"},

		// Variable or constant.
		[]string{"", "c"},

		// Positive or negative.
		[]string{"", "n"},

		// Size of index.
		[]string{"j", "i", "i8", "i16", "i32", "i64", "i64big", "i64bigger", "huge"},
	}

	forall(choices, func(x []string) {
		p, a, e, big, c, n, i := x[0], x[1], x[2], x[3], x[4], x[5], x[6]

		// Pass: dynamic=0, static=1, 2.
		// Which cases should be caught statically?
		// Only constants, obviously.
		// Beyond that, must be one of these:
		//	indexing into array or pointer to array
		//	negative constant
		//	large constant
		thisPass := 0
		if c == "c" && (a == "a" || a == "pa" || n == "n" || i == "i64big" || i == "i64bigger" || i == "huge") {
			if i == "huge" {
				// Due to a detail of 6g's internals,
				// the huge constant errors happen in an
				// earlier pass than the others and inhibits
				// the next pass from running.
				// So run it as a separate check.
				thisPass = 1
			} else if a == "s" && n == "" && (i == "i64big" || i == "i64bigger") && runtime.GOARCH == "amd64" {
				// On amd64, these huge numbers do fit in an int, so they are not
				// rejected at compile time.
				thisPass = 0
			} else {
				thisPass = 2
			}
		}

		// If we're using the big-len data, positive int8 and int16 cannot overflow.
		if big == "b" && n == "" && (i == "i8" || i == "i16") {
			return
		}

		// Only print the test case if it is appropriate for this pass.
		if thisPass == pass {
			pae := p+a+e+big
			cni := c+n+i

			// Index operation
			testExpr(b, pae + "[" + cni + "]")

			// Slice operation.
			// Low index 0 is a special case in ggen.c
			// so test both 0 and 1.
			testExpr(b, pae + "[0:" + cni + "]")
			testExpr(b, pae + "[1:" + cni + "]")
			testExpr(b, pae + "[" + cni + ":]")
			testExpr(b, pae + "[" + cni + ":" + cni + "]")
		}
	})

	fmt.Fprintln(b, "}")
	b.Flush()
}

func forall(choices [][]string, f func([]string)) {
	x := make([]string, len(choices))

	var recurse func(d int)
	recurse = func(d int) {
		if d >= len(choices) {
			f(x)
			return
		}
		for _, x[d] = range choices[d] {
			recurse(d+1)
		}
	}
	recurse(0)
}
<commit_msg>test: change index.go to test size of int, not GOARCH == "amd64"<commit_after>// skip

// Copyright 2010 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.

// Generate test of index and slice bounds checks.
// The actual tests are index0.go, index1.go, index2.go.

package main

import (
	"bufio"
	"fmt"
	"os"
	"unsafe"
)

const prolog = `

package main

import (
	"runtime"
)

type quad struct { x, y, z, w int }

const (
	cj = 100011
	ci int = 100012
	ci8 int8 = 115
	ci16 int16 = 10016
	ci32 int32 = 100013
	ci64 int64 = 100014
	ci64big int64 = 1<<31
	ci64bigger int64 = 1<<32
	chuge = 1<<100

	cnj = -2
	cni int = -3
	cni8 int8 = -6
	cni16 int16 = -7
	cni32 int32 = -4
	cni64 int64 = -5
	cni64big int64 = -1<<31
	cni64bigger int64 = -1<<32
	cnhuge = -1<<100
)

var j int = 100020
var i int = 100021
var i8 int8 = 126
var i16 int16 = 10025
var i32 int32 = 100022
var i64 int64 = 100023
var i64big int64 = 1<<31
var i64bigger int64 = 1<<32
var huge uint64 = 1<<64 - 1

var nj int = -10
var ni int = -11
var ni8 int8 = -14
var ni16 int16 = -15
var ni32 int32 = -12
var ni64 int64 = -13
var ni64big int64 = -1<<31
var ni64bigger int64 = -1<<32
var nhuge int64 = -1<<63

var si []int = make([]int, 10)
var ai [10]int
var pai *[10]int = &ai

var sq []quad = make([]quad, 10)
var aq [10]quad
var paq *[10]quad = &aq

var sib []int = make([]int, 100000)
var aib [100000]int
var paib *[100000]int = &aib

var sqb []quad = make([]quad, 100000)
var aqb [100000]quad
var paqb *[100000]quad = &aqb

type T struct {
	si []int
	ai [10]int
	pai *[10]int
	sq []quad
	aq [10]quad
	paq *[10]quad

	sib []int
	aib [100000]int
	paib *[100000]int
	sqb []quad
	aqb [100000]quad
	paqb *[100000]quad
}

var t = T{si, ai, pai, sq, aq, paq, sib, aib, paib, sqb, aqb, paqb}

var pt = &T{si, ai, pai, sq, aq, paq, sib, aib, paib, sqb, aqb, paqb}

// test that f panics
func test(f func(), s string) {
	defer func() {
		if err := recover(); err == nil {
			_, file, line, _ := runtime.Caller(2)
			bug()
			print(file, ":", line, ": ", s, " did not panic\n")
		} else if !contains(err.(error).Error(), "out of range") {
			_, file, line, _ := runtime.Caller(2)
			bug()
			print(file, ":", line, ": ", s, " unexpected panic: ", err.(error).Error(), "\n")
		}
	}()
	f()
}

func contains(x, y string) bool {
	for i := 0; i+len(y) <= len(x); i++ {
		if x[i:i+len(y)] == y {
			return true
		}
	}
	return false
}

var X interface{}
func use(y interface{}) {
	X = y
}

var didBug = false

func bug() {
	if !didBug {
		didBug = true
		println("BUG")
	}
}

func main() {
`

// pass variable set in index[012].go
//	0 - dynamic checks
//	1 - static checks of invalid constants (cannot assign to types)
//	2 - static checks of array bounds

func testExpr(b *bufio.Writer, expr string) {
	if pass == 0 {
		fmt.Fprintf(b, "\ttest(func(){use(%s)}, %q)\n", expr, expr)
	} else {
		fmt.Fprintf(b, "\tuse(%s)  // ERROR \"index|overflow\"\n", expr)
	}
}

func main() {
	b := bufio.NewWriter(os.Stdout)

	if pass == 0 {
		fmt.Fprint(b, "// run\n\n")
	} else {
		fmt.Fprint(b, "// errorcheck\n\n")
	}
	fmt.Fprint(b, prolog)

	var choices = [][]string{
		// Direct value, fetch from struct, fetch from struct pointer.
		// The last two cases get us to oindex_const_sudo in gsubr.c.
		[]string{"", "t.", "pt."},

		// Array, pointer to array, slice.
		[]string{"a", "pa", "s"},

		// Element is int, element is quad (struct).
		// This controls whether we end up in gsubr.c (i) or cgen.c (q).
		[]string{"i", "q"},

		// Small or big len.
		[]string{"", "b"},

		// Variable or constant.
		[]string{"", "c"},

		// Positive or negative.
		[]string{"", "n"},

		// Size of index.
		[]string{"j", "i", "i8", "i16", "i32", "i64", "i64big", "i64bigger", "huge"},
	}

	forall(choices, func(x []string) {
		p, a, e, big, c, n, i := x[0], x[1], x[2], x[3], x[4], x[5], x[6]

		// Pass: dynamic=0, static=1, 2.
		// Which cases should be caught statically?
		// Only constants, obviously.
		// Beyond that, must be one of these:
		//	indexing into array or pointer to array
		//	negative constant
		//	large constant
		thisPass := 0
		if c == "c" && (a == "a" || a == "pa" || n == "n" || i == "i64big" || i == "i64bigger" || i == "huge") {
			if i == "huge" {
				// Due to a detail of 6g's internals,
				// the huge constant errors happen in an
				// earlier pass than the others and inhibits
				// the next pass from running.
				// So run it as a separate check.
				thisPass = 1
			} else if a == "s" && n == "" && (i == "i64big" || i == "i64bigger") && unsafe.Sizeof(int(0)) > 4 {
				// If int is 64 bits, these huge
				// numbers do fit in an int, so they
				// are not rejected at compile time.
				thisPass = 0
			} else {
				thisPass = 2
			}
		}

		// If we're using the big-len data, positive int8 and int16 cannot overflow.
		if big == "b" && n == "" && (i == "i8" || i == "i16") {
			return
		}

		// Only print the test case if it is appropriate for this pass.
		if thisPass == pass {
			pae := p+a+e+big
			cni := c+n+i

			// Index operation
			testExpr(b, pae + "[" + cni + "]")

			// Slice operation.
			// Low index 0 is a special case in ggen.c
			// so test both 0 and 1.
			testExpr(b, pae + "[0:" + cni + "]")
			testExpr(b, pae + "[1:" + cni + "]")
			testExpr(b, pae + "[" + cni + ":]")
			testExpr(b, pae + "[" + cni + ":" + cni + "]")
		}
	})

	fmt.Fprintln(b, "}")
	b.Flush()
}

func forall(choices [][]string, f func([]string)) {
	x := make([]string, len(choices))

	var recurse func(d int)
	recurse = func(d int) {
		if d >= len(choices) {
			f(x)
			return
		}
		for _, x[d] = range choices[d] {
			recurse(d+1)
		}
	}
	recurse(0)
}
<|endoftext|>