<commit_before>package persist

import (
	"flag"
	"fmt"
	"os"
	"testing"
	"time"

	"github.com/pachyderm/pachyderm/src/client/pfs"
	"github.com/pachyderm/pachyderm/src/client/pkg/require"
	"github.com/pachyderm/pachyderm/src/client/pkg/uuid"

	"github.com/dancannon/gorethink"
	"go.pedge.io/pb/go/google/protobuf"
)

const (
	RethinkAddress = "localhost:28015"
	RethinkTestDB  = "pachyderm_test"
)

func TestMain(m *testing.M) {
	flag.Parse()
	if err := InitDB(RethinkAddress, RethinkTestDB); err != nil {
		panic(err)
	}
	code := m.Run()
	if err := RemoveDB(RethinkAddress, RethinkTestDB); err != nil {
		panic(err)
	}
	os.Exit(code)
}

func timestampNow() *google_protobuf.Timestamp {
	return &google_protobuf.Timestamp{Seconds: time.Now().Unix()}
}

func persistCommitToPFSCommit(rawCommit *Commit) *pfs.Commit {
	return &pfs.Commit{
		Repo: &pfs.Repo{
			Name: rawCommit.Repo,
		},
		ID: rawCommit.ID,
	}
}

/*

CASES:

- start commit - no parent ID, branch name = master --> creates first commit on master
- do this and repeate start commit call pattern -> new commit should have first as parent
- start commit w parent ID
- when branch and parent nil, make a new branch

- check uniqueness -- see if creating branch w same id results in rethink error
*/

func TestStartCommit(t *testing.T) {
	d, err := NewDriver("localhost:1523", RethinkAddress, RethinkTestDB)
	require.NoError(t, err)
	fmt.Printf("got a driver")

	dbClient, err := dbConnect(RethinkAddress)
	require.NoError(t, err)

	commitID := uuid.NewWithoutDashes()
	err = d.StartCommit(
		&pfs.Repo{},
		commitID,
		"",
		"master",
		timestampNow(),
		make([]*pfs.Commit, 0),
		make(map[uint64]bool),
	)
	require.NoError(t, err)

	cursor, err := gorethink.DB(RethinkTestDB).Table(commitTable).Get(commitID).Default(gorethink.Error("value not found")).Run(dbClient)
	defer func() {
		require.NoError(t, cursor.Close())
	}()

	rawCommit := &Commit{}
	cursor.Next(rawCommit)
	require.NoError(t, cursor.Err())

	fmt.Printf("Commit info: %v\n", rawCommit)

	require.Equal(t, 1, len(rawCommit.BranchClocks))
	require.Equal(t, rawCommit.BranchClocks[0], &Clock{Branch: "master", Clock: 0})

	commit := persistCommitToPFSCommit(rawCommit)
	err = d.FinishCommit(commit, timestampNow(), false, make(map[uint64]bool))
	require.NoError(t, err)
}

func TestStartCommitJustByBranch(t *testing.T) {
	d, err := NewDriver("localhost:1523", RethinkAddress, RethinkTestDB)
	require.NoError(t, err)
	fmt.Printf("got a driver")

	dbClient, err := dbConnect(RethinkAddress)
	require.NoError(t, err)

	commitID := uuid.NewWithoutDashes()
	err = d.StartCommit(
		&pfs.Repo{},
		commitID,
		"",
		"master",
		timestampNow(),
		make([]*pfs.Commit, 0),
		make(map[uint64]bool),
	)
	require.NoError(t, err)

	cursor, err := gorethink.DB(RethinkTestDB).Table(commitTable).Get(commitID).Default(gorethink.Error("value not found")).Run(dbClient)
	defer func() {
		require.NoError(t, cursor.Close())
	}()

	rawCommit := &Commit{}
	cursor.Next(rawCommit)
	require.NoError(t, cursor.Err())

	fmt.Printf("Commit info: %v\n", rawCommit)

	require.Equal(t, 1, len(rawCommit.BranchClocks))
	require.Equal(t, rawCommit.BranchClocks[0], &Clock{Branch: "master", Clock: 0})

	commit := persistCommitToPFSCommit(rawCommit)
	err = d.FinishCommit(commit, timestampNow(), false, make(map[uint64]bool))
	require.NoError(t, err)

	commit2ID := uuid.NewWithoutDashes()
	err = d.StartCommit(
		&pfs.Repo{},
		commit2ID,
		"",
		"master",
		timestampNow(),
		make([]*pfs.Commit, 0),
		make(map[uint64]bool),
	)
	require.NoError(t, err)

	cursor, err = gorethink.DB(RethinkTestDB).Table(commitTable).Get(commitID).Default(gorethink.Error("value not found")).Run(dbClient)

	rawCommit2 := &Commit{}
	cursor.Next(rawCommit2)
	require.NoError(t, cursor.Err())

	fmt.Printf("Commit info: %v\n", rawCommit2)

	require.Equal(t, 2, len(rawCommit2.BranchClocks))
	require.Equal(t, rawCommit2.BranchClocks[0], &Clock{Branch: "master", Clock: 0})
	require.Equal(t, rawCommit2.BranchClocks[1], &Clock{Branch: "master", Clock: 1})

	commit2 := persistCommitToPFSCommit(rawCommit2)
	err = d.FinishCommit(commit2, timestampNow(), false, make(map[uint64]bool))
	require.NoError(t, err)

}
<commit_msg>More tests around commits and branches<commit_after>package persist

import (
	"flag"
	"fmt"
	"os"
	"testing"
	"time"

	"github.com/pachyderm/pachyderm/src/client/pfs"
	"github.com/pachyderm/pachyderm/src/client/pkg/require"
	"github.com/pachyderm/pachyderm/src/client/pkg/uuid"

	"github.com/dancannon/gorethink"
	"go.pedge.io/pb/go/google/protobuf"
)

const (
	RethinkAddress = "localhost:28015"
	RethinkTestDB  = "pachyderm_test"
)

func TestMain(m *testing.M) {
	flag.Parse()
	if err := InitDB(RethinkAddress, RethinkTestDB); err != nil {
		panic(err)
	}
	code := m.Run()
	if err := RemoveDB(RethinkAddress, RethinkTestDB); err != nil {
		panic(err)
	}
	os.Exit(code)
}

func timestampNow() *google_protobuf.Timestamp {
	return &google_protobuf.Timestamp{Seconds: time.Now().Unix()}
}

func persistCommitToPFSCommit(rawCommit *Commit) *pfs.Commit {
	return &pfs.Commit{
		Repo: &pfs.Repo{
			Name: rawCommit.Repo,
		},
		ID: rawCommit.ID,
	}
}

/*

CASES:

- start commit - no parent ID, branch name = master --> creates first commit on master
- do this and repeate start commit call pattern -> new commit should have first as parent
- start commit w parent ID
- when branch and parent nil, make a new branch

- check uniqueness -- see if creating branch w same id results in rethink error
*/

func TestStartCommit(t *testing.T) {
	d, err := NewDriver("localhost:1523", RethinkAddress, RethinkTestDB)
	require.NoError(t, err)
	fmt.Printf("got a driver")

	dbClient, err := dbConnect(RethinkAddress)
	require.NoError(t, err)

	commitID := uuid.NewWithoutDashes()
	err = d.StartCommit(
		&pfs.Repo{},
		commitID,
		"",
		"master",
		timestampNow(),
		make([]*pfs.Commit, 0),
		make(map[uint64]bool),
	)
	require.NoError(t, err)

	cursor, err := gorethink.DB(RethinkTestDB).Table(commitTable).Get(commitID).Default(gorethink.Error("value not found")).Run(dbClient)
	defer func() {
		require.NoError(t, cursor.Close())
	}()

	rawCommit := &Commit{}
	cursor.Next(rawCommit)
	require.NoError(t, cursor.Err())

	fmt.Printf("Commit info: %v\n", rawCommit)

	require.Equal(t, 1, len(rawCommit.BranchClocks))
	require.Equal(t, rawCommit.BranchClocks[0], &Clock{Branch: "master", Clock: 0})

	commit := persistCommitToPFSCommit(rawCommit)
	err = d.FinishCommit(commit, timestampNow(), false, make(map[uint64]bool))
	require.NoError(t, err)
}

func TestStartCommitJustByBranch(t *testing.T) {
	d, err := NewDriver("localhost:1523", RethinkAddress, RethinkTestDB)
	require.NoError(t, err)
	fmt.Printf("got a driver")

	dbClient, err := dbConnect(RethinkAddress)
	require.NoError(t, err)

	commitID := uuid.NewWithoutDashes()
	err = d.StartCommit(
		&pfs.Repo{},
		commitID,
		"",
		"master",
		timestampNow(),
		make([]*pfs.Commit, 0),
		make(map[uint64]bool),
	)
	require.NoError(t, err)

	cursor, err := gorethink.DB(RethinkTestDB).Table(commitTable).Get(commitID).Default(gorethink.Error("value not found")).Run(dbClient)
	defer func() {
		require.NoError(t, cursor.Close())
	}()

	rawCommit := &Commit{}
	cursor.Next(rawCommit)
	require.NoError(t, cursor.Err())

	fmt.Printf("Commit info: %v\n", rawCommit)

	require.Equal(t, 1, len(rawCommit.BranchClocks))
	require.Equal(t, rawCommit.BranchClocks[0], &Clock{Branch: "master", Clock: 0})

	commit := persistCommitToPFSCommit(rawCommit)
	err = d.FinishCommit(commit, timestampNow(), false, make(map[uint64]bool))
	require.NoError(t, err)

	commit2ID := uuid.NewWithoutDashes()
	err = d.StartCommit(
		&pfs.Repo{},
		commit2ID,
		"",
		"master",
		timestampNow(),
		make([]*pfs.Commit, 0),
		make(map[uint64]bool),
	)
	require.NoError(t, err)

	cursor, err = gorethink.DB(RethinkTestDB).Table(commitTable).Get(commitID).Default(gorethink.Error("value not found")).Run(dbClient)

	rawCommit2 := &Commit{}
	cursor.Next(rawCommit2)
	require.NoError(t, cursor.Err())

	fmt.Printf("Commit info: %v\n", rawCommit2)

	require.Equal(t, 2, len(rawCommit2.BranchClocks))
	require.Equal(t, rawCommit2.BranchClocks[0], &Clock{Branch: "master", Clock: 0})
	require.Equal(t, rawCommit2.BranchClocks[1], &Clock{Branch: "master", Clock: 1})

	commit2 := persistCommitToPFSCommit(rawCommit2)
	err = d.FinishCommit(commit2, timestampNow(), false, make(map[uint64]bool))
	require.NoError(t, err)

}

func TestStartCommitSpecifyParentAndBranch(t *testing.T) {
	d, err := NewDriver("localhost:1523", RethinkAddress, RethinkTestDB)
	require.NoError(t, err)
	fmt.Printf("got a driver")

	dbClient, err := dbConnect(RethinkAddress)
	require.NoError(t, err)

	commitID := uuid.NewWithoutDashes()
	err = d.StartCommit(
		&pfs.Repo{},
		commitID,
		"",
		"master",
		timestampNow(),
		make([]*pfs.Commit, 0),
		make(map[uint64]bool),
	)
	require.NoError(t, err)

	cursor, err := gorethink.DB(RethinkTestDB).Table(commitTable).Get(commitID).Default(gorethink.Error("value not found")).Run(dbClient)
	defer func() {
		require.NoError(t, cursor.Close())
	}()

	rawCommit := &Commit{}
	cursor.Next(rawCommit)
	require.NoError(t, cursor.Err())

	fmt.Printf("Commit info: %v\n", rawCommit)

	require.Equal(t, 1, len(rawCommit.BranchClocks))
	require.Equal(t, rawCommit.BranchClocks[0], &Clock{Branch: "master", Clock: 0})

	commit := persistCommitToPFSCommit(rawCommit)
	err = d.FinishCommit(commit, timestampNow(), false, make(map[uint64]bool))
	require.NoError(t, err)

	commit2ID := uuid.NewWithoutDashes()
	err = d.StartCommit(
		&pfs.Repo{},
		commit2ID,
		commitID,
		"master",
		timestampNow(),
		make([]*pfs.Commit, 0),
		make(map[uint64]bool),
	)
	require.NoError(t, err)

	cursor, err = gorethink.DB(RethinkTestDB).Table(commitTable).Get(commitID).Default(gorethink.Error("value not found")).Run(dbClient)

	rawCommit2 := &Commit{}
	cursor.Next(rawCommit2)
	require.NoError(t, cursor.Err())

	fmt.Printf("Commit info: %v\n", rawCommit2)

	require.Equal(t, 2, len(rawCommit2.BranchClocks))
	require.Equal(t, rawCommit2.BranchClocks[0], &Clock{Branch: "master", Clock: 0})
	require.Equal(t, rawCommit2.BranchClocks[1], &Clock{Branch: "master", Clock: 1})

	commit2 := persistCommitToPFSCommit(rawCommit2)
	err = d.FinishCommit(commit2, timestampNow(), false, make(map[uint64]bool))
	require.NoError(t, err)

}

func TestStartCommitSpecifyParentAndNewBranch(t *testing.T) {
	d, err := NewDriver("localhost:1523", RethinkAddress, RethinkTestDB)
	require.NoError(t, err)
	fmt.Printf("got a driver")

	dbClient, err := dbConnect(RethinkAddress)
	require.NoError(t, err)

	commitID := uuid.NewWithoutDashes()
	err = d.StartCommit(
		&pfs.Repo{},
		commitID,
		"",
		"master",
		timestampNow(),
		make([]*pfs.Commit, 0),
		make(map[uint64]bool),
	)
	require.NoError(t, err)

	cursor, err := gorethink.DB(RethinkTestDB).Table(commitTable).Get(commitID).Default(gorethink.Error("value not found")).Run(dbClient)
	defer func() {
		require.NoError(t, cursor.Close())
	}()

	rawCommit := &Commit{}
	cursor.Next(rawCommit)
	require.NoError(t, cursor.Err())

	fmt.Printf("Commit info: %v\n", rawCommit)

	require.Equal(t, 1, len(rawCommit.BranchClocks))
	require.Equal(t, rawCommit.BranchClocks[0], &Clock{Branch: "master", Clock: 0})

	commit := persistCommitToPFSCommit(rawCommit)
	err = d.FinishCommit(commit, timestampNow(), false, make(map[uint64]bool))
	require.NoError(t, err)

	commit2ID := uuid.NewWithoutDashes()
	err = d.StartCommit(
		&pfs.Repo{},
		commit2ID,
		commitID,
		"foo",
		timestampNow(),
		make([]*pfs.Commit, 0),
		make(map[uint64]bool),
	)
	require.NoError(t, err)

	cursor, err = gorethink.DB(RethinkTestDB).Table(commitTable).Get(commitID).Default(gorethink.Error("value not found")).Run(dbClient)

	rawCommit2 := &Commit{}
	cursor.Next(rawCommit2)
	require.NoError(t, cursor.Err())

	fmt.Printf("Commit info: %v\n", rawCommit2)

	require.Equal(t, 2, len(rawCommit2.BranchClocks))
	require.Equal(t, rawCommit2.BranchClocks[0], &Clock{Branch: "master", Clock: 0})
	require.Equal(t, rawCommit2.BranchClocks[1], &Clock{Branch: "foo", Clock: 0})

	commit2 := persistCommitToPFSCommit(rawCommit2)
	err = d.FinishCommit(commit2, timestampNow(), false, make(map[uint64]bool))
	require.NoError(t, err)

}

func TestStartCommitSpecifyParentAndNoBranch(t *testing.T) {
	d, err := NewDriver("localhost:1523", RethinkAddress, RethinkTestDB)
	require.NoError(t, err)
	fmt.Printf("got a driver")

	dbClient, err := dbConnect(RethinkAddress)
	require.NoError(t, err)

	commitID := uuid.NewWithoutDashes()
	err = d.StartCommit(
		&pfs.Repo{},
		commitID,
		"",
		"master",
		timestampNow(),
		make([]*pfs.Commit, 0),
		make(map[uint64]bool),
	)
	require.NoError(t, err)

	cursor, err := gorethink.DB(RethinkTestDB).Table(commitTable).Get(commitID).Default(gorethink.Error("value not found")).Run(dbClient)
	defer func() {
		require.NoError(t, cursor.Close())
	}()

	rawCommit := &Commit{}
	cursor.Next(rawCommit)
	require.NoError(t, cursor.Err())

	fmt.Printf("Commit info: %v\n", rawCommit)

	require.Equal(t, 1, len(rawCommit.BranchClocks))
	require.Equal(t, rawCommit.BranchClocks[0], &Clock{Branch: "master", Clock: 0})

	commit := persistCommitToPFSCommit(rawCommit)
	err = d.FinishCommit(commit, timestampNow(), false, make(map[uint64]bool))
	require.NoError(t, err)

	commit2ID := uuid.NewWithoutDashes()
	err = d.StartCommit(
		&pfs.Repo{},
		commit2ID,
		commitID,
		"",
		timestampNow(),
		make([]*pfs.Commit, 0),
		make(map[uint64]bool),
	)
	require.NoError(t, err)

	cursor, err = gorethink.DB(RethinkTestDB).Table(commitTable).Get(commitID).Default(gorethink.Error("value not found")).Run(dbClient)

	rawCommit2 := &Commit{}
	cursor.Next(rawCommit2)
	require.NoError(t, cursor.Err())

	fmt.Printf("Commit info: %v\n", rawCommit2)

	require.Equal(t, 2, len(rawCommit2.BranchClocks))
	require.Equal(t, rawCommit2.BranchClocks[0], &Clock{Branch: "master", Clock: 0})
	require.Matches(t, rawCommit2.BranchClocks[1].Branch)
	require.Equal(t, rawCommit2.BranchClocks[1].Clock, 0)

	commit2 := persistCommitToPFSCommit(rawCommit2)
	err = d.FinishCommit(commit2, timestampNow(), false, make(map[uint64]bool))
	require.NoError(t, err)

}
<|endoftext|>


<commit_before>// Copyright 2018 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.

package main

import (
	"io/ioutil"
	"os"
	"strings"
	"testing"
)

func TestMain(t *testing.T) {
	t.Skip("Need to set GOOGLE_CLOUD_PROJECT")
	oldStdout := os.Stdout
	r, w, _ := os.Pipe()
	os.Stdout = w

	main()

	w.Close()
	os.Stdout = oldStdout

	out, err := ioutil.ReadAll(r)
	if err != nil {
		t.Fatalf("Failed to read stdout: %v", err)
	}
	got := string(out)

	want := "Request ID"
	if !strings.Contains(got, want) {
		t.Errorf("stdout returned %s, wanted to contain %s", got, want)
	}
}
<commit_msg>jobs: enable quickstart test (#611)<commit_after>// Copyright 2018 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.

package main

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

	"github.com/GoogleCloudPlatform/golang-samples/internal/testutil"
	"golang.org/x/oauth2/google"
	talent "google.golang.org/api/jobs/v3"
)

func checkServiceAvailable(t *testing.T, projectID string) {
	client, err := google.DefaultClient(context.Background(), talent.CloudPlatformScope)
	if err != nil {
		t.Skipf("DefaultClient: %v", err)
	}

	service, err := talent.New(client)
	if err != nil {
		t.Skipf("createCTSService: service account likely in different project: %v", err)
	}
	if _, err := service.Projects.Companies.List("projects/" + projectID).Do(); err != nil {
		t.Skip("List: service account likely in different project")
	}
}

func TestMain(t *testing.T) {
	tc := testutil.SystemTest(t)
	checkServiceAvailable(t, tc.ProjectID)

	os.Setenv("GOOGLE_CLOUD_PROJECT", tc.ProjectID)

	oldStdout := os.Stdout
	r, w, _ := os.Pipe()
	os.Stdout = w

	main()

	w.Close()
	os.Stdout = oldStdout

	out, err := ioutil.ReadAll(r)
	if err != nil {
		t.Fatalf("Failed to read stdout: %v", err)
	}
	got := string(out)

	want := "Request ID"
	if !strings.Contains(got, want) {
		t.Errorf("stdout returned %s, wanted to contain %s", got, want)
	}
}
<|endoftext|>


<commit_before>package node

import (
	"fmt"
	"reflect"
	"testing"
	"time"

	"github.com/mosaicnetworks/babble/src/common"
	"github.com/mosaicnetworks/babble/src/crypto"
	"github.com/mosaicnetworks/babble/src/peers"
)

func TestJoinRequest(t *testing.T) {
	logger := common.NewTestLogger(t)
	keys, peerSet := initPeers(4)
	nodes := initNodes(keys, peerSet, 1000000, 1000, "inmem", logger, t)
	defer shutdownNodes(nodes)
	//defer drawGraphs(nodes, t)

	target := 30
	err := gossip(nodes, target, false, 3*time.Second)
	if err != nil {
		t.Fatal(err)
	}
	checkGossip(nodes, 0, t)

	key, _ := crypto.GenerateECDSAKey()
	peer := peers.NewPeer(
		fmt.Sprintf("0x%X", crypto.FromECDSAPub(&key.PublicKey)),
		fmt.Sprint("127.0.0.1:4242"),
	)
	newNode := newNode(peer, key, peerSet, 1000, 1000, "inmem", logger, t)
	defer newNode.Shutdown()

	err = newNode.join()
	if err != nil {
		t.Fatal(err)
	}

	//Gossip some more
	secondTarget := target + 30
	err = bombardAndWait(nodes, secondTarget, 6*time.Second)
	if err != nil {
		t.Fatal(err)
	}
	checkGossip(nodes, 0, t)
	checkPeerSets(nodes, t)
}

func TestJoinFull(t *testing.T) {
	logger := common.NewTestLogger(t)
	keys, peerSet := initPeers(4)
	initialNodes := initNodes(keys, peerSet, 1000000, 1000, "inmem", logger, t)
	defer shutdownNodes(initialNodes)

	target := 30
	err := gossip(initialNodes, target, false, 6*time.Second)
	if err != nil {
		t.Fatal(err)
	}
	checkGossip(initialNodes, 0, t)

	key, _ := crypto.GenerateECDSAKey()
	peer := peers.NewPeer(
		fmt.Sprintf("0x%X", crypto.FromECDSAPub(&key.PublicKey)),
		fmt.Sprint("127.0.0.1:4242"),
	)
	newNode := newNode(peer, key, peerSet, 1000000, 1000, "inmem", logger, t)
	defer newNode.Shutdown()

	//Run parallel routine to check newNode eventually reaches CatchingUp state.
	timeout := time.After(6 * time.Second)
	go func() {
		for {
			select {
			case <-timeout:
				t.Fatalf("Timeout waiting for newNode to enter CatchingUp state")
			default:
			}
			if newNode.getState() == CatchingUp {
				break
			}
		}
	}()

	newNode.RunAsync(true)

	nodes := append(initialNodes, newNode)

	//defer drawGraphs(nodes, t)

	//Gossip some more
	secondTarget := target + 50
	err = bombardAndWait(nodes, secondTarget, 6*time.Second)
	if err != nil {
		t.Fatal(err)
	}

	start := newNode.core.hg.FirstConsensusRound
	checkGossip(nodes, *start, t)
	checkPeerSets(nodes, t)
}

// func TestPullAfterJoin(t *testing.T) {
// 	logger := common.NewTestLogger(t)

// 	keys, peerSet := initPeers(3)
// 	nodes := initNodes(keys, peerSet, 1000000, 1000, "inmem", logger, t)

// 	defer shutdownNodes(nodes)
// 	defer drawGraphs(nodes, t)

// 	target := 50
// 	err := gossip(nodes, target, false, 3*time.Second)
// 	if err != nil {
// 		t.Fatal(err)
// 	}
// 	checkGossip(nodes, 0, t)

// 	key, _ := crypto.GenerateECDSAKey()
// 	peer := peers.NewPeer(
// 		fmt.Sprintf("0x%X", crypto.FromECDSAPub(&key.PublicKey)),
// 		fmt.Sprint("127.0.0.1:4242"),
// 	)
// 	newNode := newNode(peer, key, peerSet, 1000, 1000, "inmem", logger, t)

// 	err = newNode.join()
// 	if err != nil {
// 		t.Fatal(err)
// 	}

// 	err = newNode.fastForward()
// 	if err != nil {
// 		t.Fatal(err)
// 	}

// 	frameRound := newNode.core.hg.FirstConsensusRound

// 	frame, err := newNode.core.hg.Store.GetFrame(*frameRound)
// 	if err != nil {
// 		t.Fatal(err)
// 	}

// 	badRounds := false
// 	for _, ev := range frame.Events {
// 		realEv, err := nodes[0].core.hg.Store.GetEvent(ev.Hex())
// 		if err != nil {
// 			t.Fatal(err)
// 		}
// 		if *realEv.GetRound() != *ev.GetRound() {
// 			t.Logf("Event %s round should be %d, not %d", ev.Hex(), *realEv.GetRound(), *ev.GetRound())
// 			badRounds = true
// 		}
// 	}

// 	if badRounds {
// 		t.Fatalf("Bad Rounds")
// 	}
// }

// func TestPeerLeaveRequest(t *testing.T) {
// 	logger := common.NewTestLogger(t)

// 	keys, peerSet := initPeers(4)
// 	nodes := initNodes(keys, peerSet, 1000, 1000, "inmem", logger, t)

// 	runNodes(nodes, true)

// 	target := 50

// 	err := bombardAndWait(nodes, target, 3*time.Second)
// 	if err != nil {
// 		t.Fatal("Error bombarding: ", err)
// 	}

// 	nodes[1].Shutdown()
// 	nodes = append([]*Node{nodes[0]}, nodes[2:]...)

// 	target = 50

// 	err = bombardAndWait(nodes, target, 3*time.Second)
// 	if err != nil {
// 		t.Fatal("Error bombarding: ", err)
// 	}

// 	for i := range nodes {
// 		if nodes[i].core.peers.Len() != 3 {
// 			t.Errorf("Node %d should have %d peers, not %d", i, 3, nodes[i].core.peers.Len())
// 		}
// 	}
// }

func checkPeerSets(nodes []*Node, t *testing.T) {
	node0FP, err := nodes[0].core.hg.Store.GetFuturePeerSets(-1)
	if err != nil {
		t.Fatal(err)
	}
	for i := range nodes[1:] {
		nodeiFP, err := nodes[i].core.hg.Store.GetFuturePeerSets(-1)
		if err != nil {
			t.Fatal(err)
		}
		if !reflect.DeepEqual(node0FP, nodeiFP) {
			t.Logf("Node 0 FuturePeerSets: %v", node0FP)
			t.Logf("Node %d FuturePeerSets: %v", i, nodeiFP)
			t.Fatalf("FuturePeerSets defer")
		}
	}
}
<commit_msg>Increase timeout of JoinTest<commit_after>package node

import (
	"fmt"
	"reflect"
	"testing"
	"time"

	"github.com/mosaicnetworks/babble/src/common"
	"github.com/mosaicnetworks/babble/src/crypto"
	"github.com/mosaicnetworks/babble/src/peers"
)

func TestJoinRequest(t *testing.T) {
	logger := common.NewTestLogger(t)
	keys, peerSet := initPeers(4)
	nodes := initNodes(keys, peerSet, 1000000, 1000, "inmem", logger, t)
	defer shutdownNodes(nodes)
	//defer drawGraphs(nodes, t)

	target := 30
	err := gossip(nodes, target, false, 3*time.Second)
	if err != nil {
		t.Fatal(err)
	}
	checkGossip(nodes, 0, t)

	key, _ := crypto.GenerateECDSAKey()
	peer := peers.NewPeer(
		fmt.Sprintf("0x%X", crypto.FromECDSAPub(&key.PublicKey)),
		fmt.Sprint("127.0.0.1:4242"),
	)
	newNode := newNode(peer, key, peerSet, 1000, 1000, "inmem", logger, t)
	defer newNode.Shutdown()

	err = newNode.join()
	if err != nil {
		t.Fatal(err)
	}

	//Gossip some more
	secondTarget := target + 30
	err = bombardAndWait(nodes, secondTarget, 6*time.Second)
	if err != nil {
		t.Fatal(err)
	}
	checkGossip(nodes, 0, t)
	checkPeerSets(nodes, t)
}

func TestJoinFull(t *testing.T) {
	logger := common.NewTestLogger(t)
	keys, peerSet := initPeers(4)
	initialNodes := initNodes(keys, peerSet, 1000000, 1000, "inmem", logger, t)
	defer shutdownNodes(initialNodes)

	target := 30
	err := gossip(initialNodes, target, false, 6*time.Second)
	if err != nil {
		t.Fatal(err)
	}
	checkGossip(initialNodes, 0, t)

	key, _ := crypto.GenerateECDSAKey()
	peer := peers.NewPeer(
		fmt.Sprintf("0x%X", crypto.FromECDSAPub(&key.PublicKey)),
		fmt.Sprint("127.0.0.1:4242"),
	)
	newNode := newNode(peer, key, peerSet, 1000000, 1000, "inmem", logger, t)
	defer newNode.Shutdown()

	//Run parallel routine to check newNode eventually reaches CatchingUp state.
	timeout := time.After(6 * time.Second)
	go func() {
		for {
			select {
			case <-timeout:
				t.Fatalf("Timeout waiting for newNode to enter CatchingUp state")
			default:
			}
			if newNode.getState() == CatchingUp {
				break
			}
		}
	}()

	newNode.RunAsync(true)

	nodes := append(initialNodes, newNode)

	//defer drawGraphs(nodes, t)

	//Gossip some more
	secondTarget := target + 50
	err = bombardAndWait(nodes, secondTarget, 10*time.Second)
	if err != nil {
		t.Fatal(err)
	}

	start := newNode.core.hg.FirstConsensusRound
	checkGossip(nodes, *start, t)
	checkPeerSets(nodes, t)
}

// func TestPullAfterJoin(t *testing.T) {
// 	logger := common.NewTestLogger(t)

// 	keys, peerSet := initPeers(3)
// 	nodes := initNodes(keys, peerSet, 1000000, 1000, "inmem", logger, t)

// 	defer shutdownNodes(nodes)
// 	defer drawGraphs(nodes, t)

// 	target := 50
// 	err := gossip(nodes, target, false, 3*time.Second)
// 	if err != nil {
// 		t.Fatal(err)
// 	}
// 	checkGossip(nodes, 0, t)

// 	key, _ := crypto.GenerateECDSAKey()
// 	peer := peers.NewPeer(
// 		fmt.Sprintf("0x%X", crypto.FromECDSAPub(&key.PublicKey)),
// 		fmt.Sprint("127.0.0.1:4242"),
// 	)
// 	newNode := newNode(peer, key, peerSet, 1000, 1000, "inmem", logger, t)

// 	err = newNode.join()
// 	if err != nil {
// 		t.Fatal(err)
// 	}

// 	err = newNode.fastForward()
// 	if err != nil {
// 		t.Fatal(err)
// 	}

// 	frameRound := newNode.core.hg.FirstConsensusRound

// 	frame, err := newNode.core.hg.Store.GetFrame(*frameRound)
// 	if err != nil {
// 		t.Fatal(err)
// 	}

// 	badRounds := false
// 	for _, ev := range frame.Events {
// 		realEv, err := nodes[0].core.hg.Store.GetEvent(ev.Hex())
// 		if err != nil {
// 			t.Fatal(err)
// 		}
// 		if *realEv.GetRound() != *ev.GetRound() {
// 			t.Logf("Event %s round should be %d, not %d", ev.Hex(), *realEv.GetRound(), *ev.GetRound())
// 			badRounds = true
// 		}
// 	}

// 	if badRounds {
// 		t.Fatalf("Bad Rounds")
// 	}
// }

// func TestPeerLeaveRequest(t *testing.T) {
// 	logger := common.NewTestLogger(t)

// 	keys, peerSet := initPeers(4)
// 	nodes := initNodes(keys, peerSet, 1000, 1000, "inmem", logger, t)

// 	runNodes(nodes, true)

// 	target := 50

// 	err := bombardAndWait(nodes, target, 3*time.Second)
// 	if err != nil {
// 		t.Fatal("Error bombarding: ", err)
// 	}

// 	nodes[1].Shutdown()
// 	nodes = append([]*Node{nodes[0]}, nodes[2:]...)

// 	target = 50

// 	err = bombardAndWait(nodes, target, 3*time.Second)
// 	if err != nil {
// 		t.Fatal("Error bombarding: ", err)
// 	}

// 	for i := range nodes {
// 		if nodes[i].core.peers.Len() != 3 {
// 			t.Errorf("Node %d should have %d peers, not %d", i, 3, nodes[i].core.peers.Len())
// 		}
// 	}
// }

func checkPeerSets(nodes []*Node, t *testing.T) {
	node0FP, err := nodes[0].core.hg.Store.GetFuturePeerSets(-1)
	if err != nil {
		t.Fatal(err)
	}
	for i := range nodes[1:] {
		nodeiFP, err := nodes[i].core.hg.Store.GetFuturePeerSets(-1)
		if err != nil {
			t.Fatal(err)
		}
		if !reflect.DeepEqual(node0FP, nodeiFP) {
			t.Logf("Node 0 FuturePeerSets: %v", node0FP)
			t.Logf("Node %d FuturePeerSets: %v", i, nodeiFP)
			t.Fatalf("FuturePeerSets defer")
		}
	}
}
<|endoftext|>


<commit_before>package sqlite

import (
	"exp/sql"
	"os"
	"testing"
)

func TestOpen(t *testing.T) {
	db, err := sql.Open("sqlite3", "./foo.db")
	if err != nil {
		t.Errorf("Failed to open database:", err)
		return
	}
	defer os.Remove("./foo.db")

	_, err = db.Exec("drop table foo")
	_, err = db.Exec("create table foo (id integer)")
	if err != nil {
		t.Errorf("Failed to create table:", err)
		return
	}

	if stat, err := os.Stat("./foo.db"); err != nil || stat.IsDir() {
		t.Errorf("Failed to create ./foo.db")
	}
}

func TestInsert(t *testing.T) {
	db, err := sql.Open("sqlite3", "./foo.db")
	if err != nil {
		t.Errorf("Failed to open database:", err)
		return
	}
	defer os.Remove("./foo.db")

	_, err = db.Exec("drop table foo")
	_, err = db.Exec("create table foo (id integer)")
	if err != nil {
		t.Errorf("Failed to create table:", err)
		return
	}

	res, err := db.Exec("insert into foo(id) values(123)")
	if err != nil {
		t.Errorf("Failed to insert record:", err)
		return
	}
	affected, _ := res.RowsAffected()
	if affected != 1 {
		t.Errorf("Expected %d for affected rows, but %d:", 1, affected)
		return
	}

	rows, err := db.Query("select id from foo")
	if err != nil {
		t.Errorf("Failed to select records:", err)
		return
	}
	defer rows.Close()

	rows.Next()

	var result int
	rows.Scan(&result)
	if result != 123 {
		t.Errorf("Fetched %q; expected %q", 123, result)
	}
}

func TestUpdate(t *testing.T) {
	db, err := sql.Open("sqlite3", "./foo.db")
	if err != nil {
		t.Errorf("Failed to open database:", err)
		return
	}
	defer os.Remove("./foo.db")

	_, err = db.Exec("drop table foo")
	_, err = db.Exec("create table foo (id integer)")
	if err != nil {
		t.Errorf("Failed to create table:", err)
		return
	}

	res, err := db.Exec("insert into foo(id) values(123)")
	if err != nil {
		t.Errorf("Failed to insert record:", err)
		return
	}
	expected, err := res.LastInsertId()
	if err != nil {
		t.Errorf("Failed to get LastInsertId:", err)
		return
	}
	affected, _ := res.RowsAffected()
	if err != nil {
		t.Errorf("Failed to get RowsAffected:", err)
		return
	}
	if affected != 1 {
		t.Errorf("Expected %d for affected rows, but %d:", 1, affected)
		return
	}

	res, err = db.Exec("update foo set id = 234")
	if err != nil {
		t.Errorf("Failed to update record:", err)
		return
	}
	lastId, err := res.LastInsertId()
	if err != nil {
		t.Errorf("Failed to get LastInsertId:", err)
		return
	}
	if expected != lastId {
		t.Errorf("Expected %q for last Id, but %q:", expected, lastId)
	}
	affected, _ = res.RowsAffected()
	if err != nil {
		t.Errorf("Failed to get RowsAffected:", err)
		return
	}
	if affected != 1 {
		t.Errorf("Expected %d for affected rows, but %d:", 1, affected)
		return
	}

	rows, err := db.Query("select id from foo")
	if err != nil {
		t.Errorf("Failed to select records:", err)
		return
	}
	defer rows.Close()

	rows.Next()

	var result int
	rows.Scan(&result)
	if result != 234 {
		t.Errorf("Fetched %q; expected %q", 234, result)
	}
}

func TestDelete(t *testing.T) {
	db, err := sql.Open("sqlite3", "./foo.db")
	if err != nil {
		t.Errorf("Failed to select records:", err)
		return
	}
	defer os.Remove("./foo.db")

	_, err = db.Exec("drop table foo")
	_, err = db.Exec("create table foo (id integer)")
	if err != nil {
		t.Errorf("Failed to create table:", err)
		return
	}

	res, err := db.Exec("insert into foo(id) values(123)")
	if err != nil {
		t.Errorf("Failed to insert record:", err)
		return
	}
	expected, err := res.LastInsertId()
	if err != nil {
		t.Errorf("Failed to get LastInsertId:", err)
		return
	}
	affected, err := res.RowsAffected()
	if err != nil {
		t.Errorf("Failed to get RowsAffected:", err)
		return
	}
	if affected != 1 {
		t.Errorf("Expected %d for cout of affected rows, but %q:", 1, affected)
	}

	res, err = db.Exec("delete from foo where id = 123")
	if err != nil {
		t.Errorf("Failed to delete record:", err)
		return
	}
	lastId, err := res.LastInsertId()
	if err != nil {
		t.Errorf("Failed to get LastInsertId:", err)
		return
	}
	if expected != lastId {
		t.Errorf("Expected %q for last Id, but %q:", expected, lastId)
	}
	affected, err = res.RowsAffected()
	if err != nil {
		t.Errorf("Failed to get RowsAffected:", err)
		return
	}
	if affected != 1 {
		t.Errorf("Expected %d for cout of affected rows, but %q:", 1, affected)
	}

	rows, err := db.Query("select id from foo")
	if err != nil {
		t.Errorf("Failed to select records:", err)
		return
	}
	defer rows.Close()

	if rows.Next() {
		t.Errorf("Fetched row but expected not rows")
	}
}
<commit_msg>fixed package name.<commit_after>package sqlite

import (
	"database/sql"
	"os"
	"testing"
)

func TestOpen(t *testing.T) {
	db, err := sql.Open("sqlite3", "./foo.db")
	if err != nil {
		t.Errorf("Failed to open database:", err)
		return
	}
	defer os.Remove("./foo.db")

	_, err = db.Exec("drop table foo")
	_, err = db.Exec("create table foo (id integer)")
	if err != nil {
		t.Errorf("Failed to create table:", err)
		return
	}

	if stat, err := os.Stat("./foo.db"); err != nil || stat.IsDir() {
		t.Errorf("Failed to create ./foo.db")
	}
}

func TestInsert(t *testing.T) {
	db, err := sql.Open("sqlite3", "./foo.db")
	if err != nil {
		t.Errorf("Failed to open database:", err)
		return
	}
	defer os.Remove("./foo.db")

	_, err = db.Exec("drop table foo")
	_, err = db.Exec("create table foo (id integer)")
	if err != nil {
		t.Errorf("Failed to create table:", err)
		return
	}

	res, err := db.Exec("insert into foo(id) values(123)")
	if err != nil {
		t.Errorf("Failed to insert record:", err)
		return
	}
	affected, _ := res.RowsAffected()
	if affected != 1 {
		t.Errorf("Expected %d for affected rows, but %d:", 1, affected)
		return
	}

	rows, err := db.Query("select id from foo")
	if err != nil {
		t.Errorf("Failed to select records:", err)
		return
	}
	defer rows.Close()

	rows.Next()

	var result int
	rows.Scan(&result)
	if result != 123 {
		t.Errorf("Fetched %q; expected %q", 123, result)
	}
}

func TestUpdate(t *testing.T) {
	db, err := sql.Open("sqlite3", "./foo.db")
	if err != nil {
		t.Errorf("Failed to open database:", err)
		return
	}
	defer os.Remove("./foo.db")

	_, err = db.Exec("drop table foo")
	_, err = db.Exec("create table foo (id integer)")
	if err != nil {
		t.Errorf("Failed to create table:", err)
		return
	}

	res, err := db.Exec("insert into foo(id) values(123)")
	if err != nil {
		t.Errorf("Failed to insert record:", err)
		return
	}
	expected, err := res.LastInsertId()
	if err != nil {
		t.Errorf("Failed to get LastInsertId:", err)
		return
	}
	affected, _ := res.RowsAffected()
	if err != nil {
		t.Errorf("Failed to get RowsAffected:", err)
		return
	}
	if affected != 1 {
		t.Errorf("Expected %d for affected rows, but %d:", 1, affected)
		return
	}

	res, err = db.Exec("update foo set id = 234")
	if err != nil {
		t.Errorf("Failed to update record:", err)
		return
	}
	lastId, err := res.LastInsertId()
	if err != nil {
		t.Errorf("Failed to get LastInsertId:", err)
		return
	}
	if expected != lastId {
		t.Errorf("Expected %q for last Id, but %q:", expected, lastId)
	}
	affected, _ = res.RowsAffected()
	if err != nil {
		t.Errorf("Failed to get RowsAffected:", err)
		return
	}
	if affected != 1 {
		t.Errorf("Expected %d for affected rows, but %d:", 1, affected)
		return
	}

	rows, err := db.Query("select id from foo")
	if err != nil {
		t.Errorf("Failed to select records:", err)
		return
	}
	defer rows.Close()

	rows.Next()

	var result int
	rows.Scan(&result)
	if result != 234 {
		t.Errorf("Fetched %q; expected %q", 234, result)
	}
}

func TestDelete(t *testing.T) {
	db, err := sql.Open("sqlite3", "./foo.db")
	if err != nil {
		t.Errorf("Failed to select records:", err)
		return
	}
	defer os.Remove("./foo.db")

	_, err = db.Exec("drop table foo")
	_, err = db.Exec("create table foo (id integer)")
	if err != nil {
		t.Errorf("Failed to create table:", err)
		return
	}

	res, err := db.Exec("insert into foo(id) values(123)")
	if err != nil {
		t.Errorf("Failed to insert record:", err)
		return
	}
	expected, err := res.LastInsertId()
	if err != nil {
		t.Errorf("Failed to get LastInsertId:", err)
		return
	}
	affected, err := res.RowsAffected()
	if err != nil {
		t.Errorf("Failed to get RowsAffected:", err)
		return
	}
	if affected != 1 {
		t.Errorf("Expected %d for cout of affected rows, but %q:", 1, affected)
	}

	res, err = db.Exec("delete from foo where id = 123")
	if err != nil {
		t.Errorf("Failed to delete record:", err)
		return
	}
	lastId, err := res.LastInsertId()
	if err != nil {
		t.Errorf("Failed to get LastInsertId:", err)
		return
	}
	if expected != lastId {
		t.Errorf("Expected %q for last Id, but %q:", expected, lastId)
	}
	affected, err = res.RowsAffected()
	if err != nil {
		t.Errorf("Failed to get RowsAffected:", err)
		return
	}
	if affected != 1 {
		t.Errorf("Expected %d for cout of affected rows, but %q:", 1, affected)
	}

	rows, err := db.Query("select id from foo")
	if err != nil {
		t.Errorf("Failed to select records:", err)
		return
	}
	defer rows.Close()

	if rows.Next() {
		t.Errorf("Fetched row but expected not rows")
	}
}
<|endoftext|>


<commit_before>package sqlite

import (
	"testing"
	"exp/sql"
	"os"
)

func TestOpen(t *testing.T) {
	db, err := sql.Open("sqlite3", "./foo.db")
	if err != nil {
		t.Errorf("Failed to open database:", err)
		return
	}
	defer os.Remove("./foo.db")

	_, err = db.Exec("drop table foo")
	_, err = db.Exec("create table foo (id integer)")
	if err != nil {
		t.Errorf("Failed to create table:", err)
		return
	}

	if stat, err := os.Stat("./foo.db"); err != nil || stat.IsDirectory() {
		t.Errorf("Failed to create ./foo.db")
	}
}

func TestInsert(t *testing.T) {
	db, err := sql.Open("sqlite3", "./foo.db")
	if err != nil {
		t.Errorf("Failed to open database:", err)
		return
	}
	defer os.Remove("./foo.db")

	_, err = db.Exec("drop table foo")
	_, err = db.Exec("create table foo (id integer)")
	if err != nil {
		t.Errorf("Failed to create table:", err)
		return
	}

	res, err := db.Exec("insert into foo(id) values(123)")
	if err != nil {
		t.Errorf("Failed to insert record:", err)
		return
	}
	affected, _ := res.RowsAffected()
	if affected != 1 {
		t.Errorf("Expected %d for affected rows, but %d:", 1, affected)
		return
	}

	rows, err := db.Query("select id from foo")
	if err != nil {
		t.Errorf("Failed to select records:", err)
		return
	}
	defer rows.Close()

	rows.Next()

	var result int
	rows.Scan(&result)
	if result != 123 {
		t.Errorf("Fetched %q; expected %q", 123, result)
	}
}

func TestUpdate(t *testing.T) {
	db, err := sql.Open("sqlite3", "./foo.db")
	if err != nil {
		t.Errorf("Failed to open database:", err)
		return
	}
	defer os.Remove("./foo.db")

	_, err = db.Exec("drop table foo")
	_, err = db.Exec("create table foo (id integer)")
	if err != nil {
		t.Errorf("Failed to create table:", err)
		return
	}

	res, err := db.Exec("insert into foo(id) values(123)")
	if err != nil {
		t.Errorf("Failed to insert record:", err)
		return
	}
	expected, err := res.LastInsertId()
	if err != nil {
		t.Errorf("Failed to get LastInsertId:", err)
		return
	}
	affected, _ := res.RowsAffected()
	if err != nil {
		t.Errorf("Failed to get RowsAffected:", err)
		return
	}
	if affected != 1 {
		t.Errorf("Expected %d for affected rows, but %d:", 1, affected)
		return
	}

	res, err = db.Exec("update foo set id = 234")
	if err != nil {
		t.Errorf("Failed to update record:", err)
		return
	}
	lastId, err := res.LastInsertId()
	if err != nil {
		t.Errorf("Failed to get LastInsertId:", err)
		return
	}
	if expected != lastId {
		t.Errorf("Expected %q for last Id, but %q:", expected, lastId)
	}
	affected, _ = res.RowsAffected()
	if err != nil {
		t.Errorf("Failed to get RowsAffected:", err)
		return
	}
	if affected != 1 {
		t.Errorf("Expected %d for affected rows, but %d:", 1, affected)
		return
	}

	rows, err := db.Query("select id from foo")
	if err != nil {
		t.Errorf("Failed to select records:", err)
		return
	}
	defer rows.Close()

	rows.Next()

	var result int
	rows.Scan(&result)
	if result != 234 {
		t.Errorf("Fetched %q; expected %q", 234, result)
	}
}

func TestDelete(t *testing.T) {
	db, err := sql.Open("sqlite3", "./foo.db")
	if err != nil {
		t.Errorf("Failed to select records:", err)
		return
	}
	defer os.Remove("./foo.db")

	_, err = db.Exec("drop table foo")
	_, err = db.Exec("create table foo (id integer)")
	if err != nil {
		t.Errorf("Failed to create table:", err)
		return
	}

	res, err := db.Exec("insert into foo(id) values(123)")
	if err != nil {
		t.Errorf("Failed to insert record:", err)
		return
	}
	expected, err := res.LastInsertId()
	if err != nil {
		t.Errorf("Failed to get LastInsertId:", err)
		return
	}
	affected, err := res.RowsAffected()
	if err != nil {
		t.Errorf("Failed to get RowsAffected:", err)
		return
	}
	if affected != 1 {
		t.Errorf("Expected %d for cout of affected rows, but %q:", 1, affected)
	}

	res, err = db.Exec("delete from foo where id = 123")
	if err != nil {
		t.Errorf("Failed to delete record:", err)
		return
	}
	lastId, err := res.LastInsertId()
	if err != nil {
		t.Errorf("Failed to get LastInsertId:", err)
		return
	}
	if expected != lastId {
		t.Errorf("Expected %q for last Id, but %q:", expected, lastId)
	}
	affected, err = res.RowsAffected()
	if err != nil {
		t.Errorf("Failed to get RowsAffected:", err)
		return
	}
	if affected != 1 {
		t.Errorf("Expected %d for cout of affected rows, but %q:", 1, affected)
	}

	rows, err := db.Query("select id from foo")
	if err != nil {
		t.Errorf("Failed to select records:", err)
		return
	}
	defer rows.Close()

	if rows.Next() {
		t.Errorf("Fetched row but expected not rows")
	}
}
<commit_msg>gofix.<commit_after>package sqlite

import (
	"exp/sql"
	"os"
	"testing"
)

func TestOpen(t *testing.T) {
	db, err := sql.Open("sqlite3", "./foo.db")
	if err != nil {
		t.Errorf("Failed to open database:", err)
		return
	}
	defer os.Remove("./foo.db")

	_, err = db.Exec("drop table foo")
	_, err = db.Exec("create table foo (id integer)")
	if err != nil {
		t.Errorf("Failed to create table:", err)
		return
	}

	if stat, err := os.Stat("./foo.db"); err != nil || stat.IsDir() {
		t.Errorf("Failed to create ./foo.db")
	}
}

func TestInsert(t *testing.T) {
	db, err := sql.Open("sqlite3", "./foo.db")
	if err != nil {
		t.Errorf("Failed to open database:", err)
		return
	}
	defer os.Remove("./foo.db")

	_, err = db.Exec("drop table foo")
	_, err = db.Exec("create table foo (id integer)")
	if err != nil {
		t.Errorf("Failed to create table:", err)
		return
	}

	res, err := db.Exec("insert into foo(id) values(123)")
	if err != nil {
		t.Errorf("Failed to insert record:", err)
		return
	}
	affected, _ := res.RowsAffected()
	if affected != 1 {
		t.Errorf("Expected %d for affected rows, but %d:", 1, affected)
		return
	}

	rows, err := db.Query("select id from foo")
	if err != nil {
		t.Errorf("Failed to select records:", err)
		return
	}
	defer rows.Close()

	rows.Next()

	var result int
	rows.Scan(&result)
	if result != 123 {
		t.Errorf("Fetched %q; expected %q", 123, result)
	}
}

func TestUpdate(t *testing.T) {
	db, err := sql.Open("sqlite3", "./foo.db")
	if err != nil {
		t.Errorf("Failed to open database:", err)
		return
	}
	defer os.Remove("./foo.db")

	_, err = db.Exec("drop table foo")
	_, err = db.Exec("create table foo (id integer)")
	if err != nil {
		t.Errorf("Failed to create table:", err)
		return
	}

	res, err := db.Exec("insert into foo(id) values(123)")
	if err != nil {
		t.Errorf("Failed to insert record:", err)
		return
	}
	expected, err := res.LastInsertId()
	if err != nil {
		t.Errorf("Failed to get LastInsertId:", err)
		return
	}
	affected, _ := res.RowsAffected()
	if err != nil {
		t.Errorf("Failed to get RowsAffected:", err)
		return
	}
	if affected != 1 {
		t.Errorf("Expected %d for affected rows, but %d:", 1, affected)
		return
	}

	res, err = db.Exec("update foo set id = 234")
	if err != nil {
		t.Errorf("Failed to update record:", err)
		return
	}
	lastId, err := res.LastInsertId()
	if err != nil {
		t.Errorf("Failed to get LastInsertId:", err)
		return
	}
	if expected != lastId {
		t.Errorf("Expected %q for last Id, but %q:", expected, lastId)
	}
	affected, _ = res.RowsAffected()
	if err != nil {
		t.Errorf("Failed to get RowsAffected:", err)
		return
	}
	if affected != 1 {
		t.Errorf("Expected %d for affected rows, but %d:", 1, affected)
		return
	}

	rows, err := db.Query("select id from foo")
	if err != nil {
		t.Errorf("Failed to select records:", err)
		return
	}
	defer rows.Close()

	rows.Next()

	var result int
	rows.Scan(&result)
	if result != 234 {
		t.Errorf("Fetched %q; expected %q", 234, result)
	}
}

func TestDelete(t *testing.T) {
	db, err := sql.Open("sqlite3", "./foo.db")
	if err != nil {
		t.Errorf("Failed to select records:", err)
		return
	}
	defer os.Remove("./foo.db")

	_, err = db.Exec("drop table foo")
	_, err = db.Exec("create table foo (id integer)")
	if err != nil {
		t.Errorf("Failed to create table:", err)
		return
	}

	res, err := db.Exec("insert into foo(id) values(123)")
	if err != nil {
		t.Errorf("Failed to insert record:", err)
		return
	}
	expected, err := res.LastInsertId()
	if err != nil {
		t.Errorf("Failed to get LastInsertId:", err)
		return
	}
	affected, err := res.RowsAffected()
	if err != nil {
		t.Errorf("Failed to get RowsAffected:", err)
		return
	}
	if affected != 1 {
		t.Errorf("Expected %d for cout of affected rows, but %q:", 1, affected)
	}

	res, err = db.Exec("delete from foo where id = 123")
	if err != nil {
		t.Errorf("Failed to delete record:", err)
		return
	}
	lastId, err := res.LastInsertId()
	if err != nil {
		t.Errorf("Failed to get LastInsertId:", err)
		return
	}
	if expected != lastId {
		t.Errorf("Expected %q for last Id, but %q:", expected, lastId)
	}
	affected, err = res.RowsAffected()
	if err != nil {
		t.Errorf("Failed to get RowsAffected:", err)
		return
	}
	if affected != 1 {
		t.Errorf("Expected %d for cout of affected rows, but %q:", 1, affected)
	}

	rows, err := db.Query("select id from foo")
	if err != nil {
		t.Errorf("Failed to select records:", err)
		return
	}
	defer rows.Close()

	if rows.Next() {
		t.Errorf("Fetched row but expected not rows")
	}
}
<|endoftext|>


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

package time_test

import (
	"testing"
	. "time"
)

func TestTicker(t *testing.T) {
	const Count = 10
	Delta := 100 * Millisecond
	ticker := NewTicker(Delta)
	t0 := Now()
	for i := 0; i < Count; i++ {
		<-ticker.C
	}
	ticker.Stop()
	t1 := Now()
	dt := t1.Sub(t0)
	target := Delta * Count
	slop := target * 2 / 10
	if dt < target-slop || dt > target+slop {
		t.Fatalf("%d %s ticks took %s, expected [%s,%s]", Count, Delta, dt, target-slop, target+slop)
	}
	// Now test that the ticker stopped
	Sleep(2 * Delta)
	select {
	case <-ticker.C:
		t.Fatal("Ticker did not shut down")
	default:
		// ok
	}
}

// Test that a bug tearing down a ticker has been fixed.  This routine should not deadlock.
func TestTeardown(t *testing.T) {
	Delta := 100 * Millisecond
	if testing.Short() {
		Delta = 20 * Millisecond
	}
	for i := 0; i < 3; i++ {
		ticker := NewTicker(Delta)
		<-ticker.C
		ticker.Stop()
	}
}

func BenchmarkTicker(b *testing.B) {
	ticker := NewTicker(1)
	b.ResetTimer()
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		<-ticker.C
	}
	b.StopTimer()
	ticker.Stop()
}
<commit_msg>time: during short test, do not bother tickers take longer than expected<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package time_test

import (
	"testing"
	. "time"
)

func TestTicker(t *testing.T) {
	const Count = 10
	Delta := 100 * Millisecond
	ticker := NewTicker(Delta)
	t0 := Now()
	for i := 0; i < Count; i++ {
		<-ticker.C
	}
	ticker.Stop()
	t1 := Now()
	dt := t1.Sub(t0)
	target := Delta * Count
	slop := target * 2 / 10
	if dt < target-slop || (!testing.Short() && dt > target+slop) {
		t.Fatalf("%d %s ticks took %s, expected [%s,%s]", Count, Delta, dt, target-slop, target+slop)
	}
	// Now test that the ticker stopped
	Sleep(2 * Delta)
	select {
	case <-ticker.C:
		t.Fatal("Ticker did not shut down")
	default:
		// ok
	}
}

// Test that a bug tearing down a ticker has been fixed.  This routine should not deadlock.
func TestTeardown(t *testing.T) {
	Delta := 100 * Millisecond
	if testing.Short() {
		Delta = 20 * Millisecond
	}
	for i := 0; i < 3; i++ {
		ticker := NewTicker(Delta)
		<-ticker.C
		ticker.Stop()
	}
}

func BenchmarkTicker(b *testing.B) {
	ticker := NewTicker(1)
	b.ResetTimer()
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		<-ticker.C
	}
	b.StopTimer()
	ticker.Stop()
}
<|endoftext|>


<commit_before>// Copyright 2011 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.

// +build appengine

package build

import (
	"bytes"
	"encoding/gob"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"regexp"
	"runtime"
	"sort"
	"text/template"

	"appengine"
	"appengine/datastore"
	"appengine/delay"
	"appengine/mail"
	"appengine/urlfetch"
)

const (
	mailFrom   = "builder@golang.org" // use this for sending any mail
	failMailTo = "golang-dev@googlegroups.com"
	domain     = "build.golang.org"
	gobotBase  = "http://research.swtch.com/gobot_codereview"
)

// ignoreFailure is a set of builders that we don't email about because
// they are not yet production-ready.
var ignoreFailure = map[string]bool{
	"dragonfly-386":           true,
	"dragonfly-amd64":         true,
	"netbsd-amd64-bsiegert":   true,
	"netbsd-arm-rpi":          true,
	"solaris-amd64-smartos":   true,
	"solaris-amd64-solaris11": true,
	"plan9-amd64-aram":        true,
}

// notifyOnFailure checks whether the supplied Commit or the subsequent
// Commit (if present) breaks the build for this builder.
// If either of those commits break the build an email notification is sent
// from a delayed task. (We use a task because this way the mail won't be
// sent if the enclosing datastore transaction fails.)
//
// This must be run in a datastore transaction, and the provided *Commit must
// have been retrieved from the datastore within that transaction.
func notifyOnFailure(c appengine.Context, com *Commit, builder string) error {
	if ignoreFailure[builder] {
		return nil
	}

	// TODO(adg): implement notifications for packages
	if com.PackagePath != "" {
		return nil
	}

	p := &Package{Path: com.PackagePath}
	var broken *Commit
	cr := com.Result(builder, "")
	if cr == nil {
		return fmt.Errorf("no result for %s/%s", com.Hash, builder)
	}
	q := datastore.NewQuery("Commit").Ancestor(p.Key(c))
	if cr.OK {
		// This commit is OK. Notify if next Commit is broken.
		next := new(Commit)
		q = q.Filter("ParentHash=", com.Hash)
		if err := firstMatch(c, q, next); err != nil {
			if err == datastore.ErrNoSuchEntity {
				// OK at tip, no notification necessary.
				return nil
			}
			return err
		}
		if nr := next.Result(builder, ""); nr != nil && !nr.OK {
			c.Debugf("commit ok: %#v\nresult: %#v", com, cr)
			c.Debugf("next commit broken: %#v\nnext result:%#v", next, nr)
			broken = next
		}
	} else {
		// This commit is broken. Notify if the previous Commit is OK.
		prev := new(Commit)
		q = q.Filter("Hash=", com.ParentHash)
		if err := firstMatch(c, q, prev); err != nil {
			if err == datastore.ErrNoSuchEntity {
				// No previous result, let the backfill of
				// this result trigger the notification.
				return nil
			}
			return err
		}
		if pr := prev.Result(builder, ""); pr != nil && pr.OK {
			c.Debugf("commit broken: %#v\nresult: %#v", com, cr)
			c.Debugf("previous commit ok: %#v\nprevious result:%#v", prev, pr)
			broken = com
		}
	}
	if broken == nil {
		return nil
	}
	r := broken.Result(builder, "")
	if r == nil {
		return fmt.Errorf("finding result for %q: %+v", builder, com)
	}
	return commonNotify(c, broken, builder, r.LogHash)
}

// firstMatch executes the query q and loads the first entity into v.
func firstMatch(c appengine.Context, q *datastore.Query, v interface{}) error {
	t := q.Limit(1).Run(c)
	_, err := t.Next(v)
	if err == datastore.Done {
		err = datastore.ErrNoSuchEntity
	}
	return err
}

var notifyLater = delay.Func("notify", notify)

// notify tries to update the CL for the given Commit with a failure message.
// If it doesn't succeed, it sends a failure email to golang-dev.
func notify(c appengine.Context, com *Commit, builder, logHash string) {
	v := url.Values{"brokebuild": {builder}, "log": {logHash}}
	if !updateCL(c, com, v) {
		// Send a mail notification if the CL can't be found.
		sendFailMail(c, com, builder, logHash)
	}
}

// updateCL tells gobot to update the CL for the given Commit with
// the provided query values.
func updateCL(c appengine.Context, com *Commit, v url.Values) bool {
	cl, err := lookupCL(c, com)
	if err != nil {
		c.Errorf("could not find CL for %v: %v", com.Hash, err)
		return false
	}
	u := fmt.Sprintf("%v?cl=%v&%s", gobotBase, cl, v.Encode())
	r, err := urlfetch.Client(c).Post(u, "text/plain", nil)
	if err != nil {
		c.Errorf("could not update CL %v: %v", cl, err)
		return false
	}
	r.Body.Close()
	if r.StatusCode != http.StatusOK {
		c.Errorf("could not update CL %v: %v", cl, r.Status)
		return false
	}
	return true
}

var clURL = regexp.MustCompile(`https://codereview.appspot.com/([0-9]+)`)

// lookupCL consults code.google.com for the full change description for the
// provided Commit, and returns the relevant CL number.
func lookupCL(c appengine.Context, com *Commit) (string, error) {
	url := "https://code.google.com/p/go/source/detail?r=" + com.Hash
	r, err := urlfetch.Client(c).Get(url)
	if err != nil {
		return "", err
	}
	defer r.Body.Close()
	if r.StatusCode != http.StatusOK {
		return "", fmt.Errorf("retrieving %v: %v", url, r.Status)
	}
	b, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return "", err
	}
	m := clURL.FindAllSubmatch(b, -1)
	if m == nil {
		return "", errors.New("no CL URL found on changeset page")
	}
	// Return the last visible codereview URL on the page,
	// in case the change description refers to another CL.
	return string(m[len(m)-1][1]), nil
}

var sendFailMailTmpl = template.Must(template.New("notify.txt").
	Funcs(template.FuncMap(tmplFuncs)).
	ParseFiles("build/notify.txt"))

func init() {
	gob.Register(&Commit{}) // for delay
}

var (
	sendPerfMailLater = delay.Func("sendPerfMail", sendPerfMailFunc)
	sendPerfMailTmpl  = template.Must(
		template.New("perf_notify.txt").
			Funcs(template.FuncMap(tmplFuncs)).
			ParseFiles("build/perf_notify.txt"),
	)
)

func sendPerfFailMail(c appengine.Context, builder string, res *PerfResult) error {
	com := &Commit{Hash: res.CommitHash}
	logHash := ""
	parsed := res.ParseData()
	for _, data := range parsed[builder] {
		if !data.OK {
			logHash = data.Artifacts["log"]
			break
		}
	}
	if logHash == "" {
		return fmt.Errorf("can not find failed result for commit %v on builder %v", com.Hash, builder)
	}
	return commonNotify(c, com, builder, logHash)
}

func commonNotify(c appengine.Context, com *Commit, builder, logHash string) error {
	if com.Num == 0 || com.Desc == "" {
		stk := make([]byte, 10000)
		n := runtime.Stack(stk, false)
		stk = stk[:n]
		c.Errorf("refusing to notify with com=%+v\n%s", *com, string(stk))
		return fmt.Errorf("misuse of commonNotify")
	}
	if com.FailNotificationSent {
		return nil
	}
	c.Infof("%s is broken commit; notifying", com.Hash)
	notifyLater.Call(c, com, builder, logHash) // add task to queue
	com.FailNotificationSent = true
	return putCommit(c, com)
}

// sendFailMail sends a mail notification that the build failed on the
// provided commit and builder.
func sendFailMail(c appengine.Context, com *Commit, builder, logHash string) {
	// get Log
	k := datastore.NewKey(c, "Log", logHash, 0, nil)
	l := new(Log)
	if err := datastore.Get(c, k, l); err != nil {
		c.Errorf("finding Log record %v: %v", logHash, err)
		return
	}
	logText, err := l.Text()
	if err != nil {
		c.Errorf("unpacking Log record %v: %v", logHash, err)
		return
	}

	// prepare mail message
	var body bytes.Buffer
	err = sendFailMailTmpl.Execute(&body, map[string]interface{}{
		"Builder": builder, "Commit": com, "LogHash": logHash, "LogText": logText,
		"Hostname": domain,
	})
	if err != nil {
		c.Errorf("rendering mail template: %v", err)
		return
	}
	subject := fmt.Sprintf("%s broken by %s", builder, shortDesc(com.Desc))
	msg := &mail.Message{
		Sender:  mailFrom,
		To:      []string{failMailTo},
		ReplyTo: failMailTo,
		Subject: subject,
		Body:    body.String(),
	}

	// send mail
	if err := mail.Send(c, msg); err != nil {
		c.Errorf("sending mail: %v", err)
	}
}

type PerfChangeBenchmark struct {
	Name    string
	Metrics []*PerfChangeMetric
}

type PerfChangeMetric struct {
	Name  string
	Old   uint64
	New   uint64
	Delta float64
}

type PerfChangeBenchmarkSlice []*PerfChangeBenchmark

func (l PerfChangeBenchmarkSlice) Len() int      { return len(l) }
func (l PerfChangeBenchmarkSlice) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
func (l PerfChangeBenchmarkSlice) Less(i, j int) bool {
	b1, p1 := splitBench(l[i].Name)
	b2, p2 := splitBench(l[j].Name)
	if b1 != b2 {
		return b1 < b2
	}
	return p1 < p2
}

type PerfChangeMetricSlice []*PerfChangeMetric

func (l PerfChangeMetricSlice) Len() int           { return len(l) }
func (l PerfChangeMetricSlice) Swap(i, j int)      { l[i], l[j] = l[j], l[i] }
func (l PerfChangeMetricSlice) Less(i, j int) bool { return l[i].Name < l[j].Name }

func sendPerfMailFunc(c appengine.Context, com *Commit, prevCommitHash, builder string, changes []*PerfChange) {
	// Sort the changes into the right order.
	var benchmarks []*PerfChangeBenchmark
	for _, ch := range changes {
		// Find the benchmark.
		var b *PerfChangeBenchmark
		for _, b1 := range benchmarks {
			if b1.Name == ch.Bench {
				b = b1
				break
			}
		}
		if b == nil {
			b = &PerfChangeBenchmark{Name: ch.Bench}
			benchmarks = append(benchmarks, b)
		}
		b.Metrics = append(b.Metrics, &PerfChangeMetric{Name: ch.Metric, Old: ch.Old, New: ch.New, Delta: ch.Diff})
	}
	for _, b := range benchmarks {
		sort.Sort(PerfChangeMetricSlice(b.Metrics))
	}
	sort.Sort(PerfChangeBenchmarkSlice(benchmarks))

	u := fmt.Sprintf("http://%v/perfdetail?commit=%v&commit0=%v&kind=builder&builder=%v", domain, com.Hash, prevCommitHash, builder)

	// Prepare mail message (without Commit, for updateCL).
	var body bytes.Buffer
	err := sendPerfMailTmpl.Execute(&body, map[string]interface{}{
		"Builder": builder, "Hostname": domain, "Url": u, "Benchmarks": benchmarks,
	})
	if err != nil {
		c.Errorf("rendering perf mail template: %v", err)
		return
	}

	// First, try to update the CL.
	v := url.Values{"textmsg": {body.String()}}
	if updateCL(c, com, v) {
		return
	}

	// Otherwise, send mail (with Commit, for independent mail message).
	body.Reset()
	err = sendPerfMailTmpl.Execute(&body, map[string]interface{}{
		"Builder": builder, "Commit": com, "Hostname": domain, "Url": u, "Benchmarks": benchmarks,
	})
	if err != nil {
		c.Errorf("rendering perf mail template: %v", err)
		return
	}
	subject := fmt.Sprintf("Perf changes on %s by %s", builder, shortDesc(com.Desc))
	msg := &mail.Message{
		Sender:  mailFrom,
		To:      []string{failMailTo},
		ReplyTo: failMailTo,
		Subject: subject,
		Body:    body.String(),
	}

	// send mail
	if err := mail.Send(c, msg); err != nil {
		c.Errorf("sending mail: %v", err)
	}
}
<commit_msg>go.tools/dashboard: remove Solaris builders from flaky builders list<commit_after>// Copyright 2011 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.

// +build appengine

package build

import (
	"bytes"
	"encoding/gob"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"regexp"
	"runtime"
	"sort"
	"text/template"

	"appengine"
	"appengine/datastore"
	"appengine/delay"
	"appengine/mail"
	"appengine/urlfetch"
)

const (
	mailFrom   = "builder@golang.org" // use this for sending any mail
	failMailTo = "golang-dev@googlegroups.com"
	domain     = "build.golang.org"
	gobotBase  = "http://research.swtch.com/gobot_codereview"
)

// ignoreFailure is a set of builders that we don't email about because
// they are not yet production-ready.
var ignoreFailure = map[string]bool{
	"dragonfly-386":         true,
	"dragonfly-amd64":       true,
	"netbsd-amd64-bsiegert": true,
	"netbsd-arm-rpi":        true,
	"plan9-amd64-aram":      true,
}

// notifyOnFailure checks whether the supplied Commit or the subsequent
// Commit (if present) breaks the build for this builder.
// If either of those commits break the build an email notification is sent
// from a delayed task. (We use a task because this way the mail won't be
// sent if the enclosing datastore transaction fails.)
//
// This must be run in a datastore transaction, and the provided *Commit must
// have been retrieved from the datastore within that transaction.
func notifyOnFailure(c appengine.Context, com *Commit, builder string) error {
	if ignoreFailure[builder] {
		return nil
	}

	// TODO(adg): implement notifications for packages
	if com.PackagePath != "" {
		return nil
	}

	p := &Package{Path: com.PackagePath}
	var broken *Commit
	cr := com.Result(builder, "")
	if cr == nil {
		return fmt.Errorf("no result for %s/%s", com.Hash, builder)
	}
	q := datastore.NewQuery("Commit").Ancestor(p.Key(c))
	if cr.OK {
		// This commit is OK. Notify if next Commit is broken.
		next := new(Commit)
		q = q.Filter("ParentHash=", com.Hash)
		if err := firstMatch(c, q, next); err != nil {
			if err == datastore.ErrNoSuchEntity {
				// OK at tip, no notification necessary.
				return nil
			}
			return err
		}
		if nr := next.Result(builder, ""); nr != nil && !nr.OK {
			c.Debugf("commit ok: %#v\nresult: %#v", com, cr)
			c.Debugf("next commit broken: %#v\nnext result:%#v", next, nr)
			broken = next
		}
	} else {
		// This commit is broken. Notify if the previous Commit is OK.
		prev := new(Commit)
		q = q.Filter("Hash=", com.ParentHash)
		if err := firstMatch(c, q, prev); err != nil {
			if err == datastore.ErrNoSuchEntity {
				// No previous result, let the backfill of
				// this result trigger the notification.
				return nil
			}
			return err
		}
		if pr := prev.Result(builder, ""); pr != nil && pr.OK {
			c.Debugf("commit broken: %#v\nresult: %#v", com, cr)
			c.Debugf("previous commit ok: %#v\nprevious result:%#v", prev, pr)
			broken = com
		}
	}
	if broken == nil {
		return nil
	}
	r := broken.Result(builder, "")
	if r == nil {
		return fmt.Errorf("finding result for %q: %+v", builder, com)
	}
	return commonNotify(c, broken, builder, r.LogHash)
}

// firstMatch executes the query q and loads the first entity into v.
func firstMatch(c appengine.Context, q *datastore.Query, v interface{}) error {
	t := q.Limit(1).Run(c)
	_, err := t.Next(v)
	if err == datastore.Done {
		err = datastore.ErrNoSuchEntity
	}
	return err
}

var notifyLater = delay.Func("notify", notify)

// notify tries to update the CL for the given Commit with a failure message.
// If it doesn't succeed, it sends a failure email to golang-dev.
func notify(c appengine.Context, com *Commit, builder, logHash string) {
	v := url.Values{"brokebuild": {builder}, "log": {logHash}}
	if !updateCL(c, com, v) {
		// Send a mail notification if the CL can't be found.
		sendFailMail(c, com, builder, logHash)
	}
}

// updateCL tells gobot to update the CL for the given Commit with
// the provided query values.
func updateCL(c appengine.Context, com *Commit, v url.Values) bool {
	cl, err := lookupCL(c, com)
	if err != nil {
		c.Errorf("could not find CL for %v: %v", com.Hash, err)
		return false
	}
	u := fmt.Sprintf("%v?cl=%v&%s", gobotBase, cl, v.Encode())
	r, err := urlfetch.Client(c).Post(u, "text/plain", nil)
	if err != nil {
		c.Errorf("could not update CL %v: %v", cl, err)
		return false
	}
	r.Body.Close()
	if r.StatusCode != http.StatusOK {
		c.Errorf("could not update CL %v: %v", cl, r.Status)
		return false
	}
	return true
}

var clURL = regexp.MustCompile(`https://codereview.appspot.com/([0-9]+)`)

// lookupCL consults code.google.com for the full change description for the
// provided Commit, and returns the relevant CL number.
func lookupCL(c appengine.Context, com *Commit) (string, error) {
	url := "https://code.google.com/p/go/source/detail?r=" + com.Hash
	r, err := urlfetch.Client(c).Get(url)
	if err != nil {
		return "", err
	}
	defer r.Body.Close()
	if r.StatusCode != http.StatusOK {
		return "", fmt.Errorf("retrieving %v: %v", url, r.Status)
	}
	b, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return "", err
	}
	m := clURL.FindAllSubmatch(b, -1)
	if m == nil {
		return "", errors.New("no CL URL found on changeset page")
	}
	// Return the last visible codereview URL on the page,
	// in case the change description refers to another CL.
	return string(m[len(m)-1][1]), nil
}

var sendFailMailTmpl = template.Must(template.New("notify.txt").
	Funcs(template.FuncMap(tmplFuncs)).
	ParseFiles("build/notify.txt"))

func init() {
	gob.Register(&Commit{}) // for delay
}

var (
	sendPerfMailLater = delay.Func("sendPerfMail", sendPerfMailFunc)
	sendPerfMailTmpl  = template.Must(
		template.New("perf_notify.txt").
			Funcs(template.FuncMap(tmplFuncs)).
			ParseFiles("build/perf_notify.txt"),
	)
)

func sendPerfFailMail(c appengine.Context, builder string, res *PerfResult) error {
	com := &Commit{Hash: res.CommitHash}
	logHash := ""
	parsed := res.ParseData()
	for _, data := range parsed[builder] {
		if !data.OK {
			logHash = data.Artifacts["log"]
			break
		}
	}
	if logHash == "" {
		return fmt.Errorf("can not find failed result for commit %v on builder %v", com.Hash, builder)
	}
	return commonNotify(c, com, builder, logHash)
}

func commonNotify(c appengine.Context, com *Commit, builder, logHash string) error {
	if com.Num == 0 || com.Desc == "" {
		stk := make([]byte, 10000)
		n := runtime.Stack(stk, false)
		stk = stk[:n]
		c.Errorf("refusing to notify with com=%+v\n%s", *com, string(stk))
		return fmt.Errorf("misuse of commonNotify")
	}
	if com.FailNotificationSent {
		return nil
	}
	c.Infof("%s is broken commit; notifying", com.Hash)
	notifyLater.Call(c, com, builder, logHash) // add task to queue
	com.FailNotificationSent = true
	return putCommit(c, com)
}

// sendFailMail sends a mail notification that the build failed on the
// provided commit and builder.
func sendFailMail(c appengine.Context, com *Commit, builder, logHash string) {
	// get Log
	k := datastore.NewKey(c, "Log", logHash, 0, nil)
	l := new(Log)
	if err := datastore.Get(c, k, l); err != nil {
		c.Errorf("finding Log record %v: %v", logHash, err)
		return
	}
	logText, err := l.Text()
	if err != nil {
		c.Errorf("unpacking Log record %v: %v", logHash, err)
		return
	}

	// prepare mail message
	var body bytes.Buffer
	err = sendFailMailTmpl.Execute(&body, map[string]interface{}{
		"Builder": builder, "Commit": com, "LogHash": logHash, "LogText": logText,
		"Hostname": domain,
	})
	if err != nil {
		c.Errorf("rendering mail template: %v", err)
		return
	}
	subject := fmt.Sprintf("%s broken by %s", builder, shortDesc(com.Desc))
	msg := &mail.Message{
		Sender:  mailFrom,
		To:      []string{failMailTo},
		ReplyTo: failMailTo,
		Subject: subject,
		Body:    body.String(),
	}

	// send mail
	if err := mail.Send(c, msg); err != nil {
		c.Errorf("sending mail: %v", err)
	}
}

type PerfChangeBenchmark struct {
	Name    string
	Metrics []*PerfChangeMetric
}

type PerfChangeMetric struct {
	Name  string
	Old   uint64
	New   uint64
	Delta float64
}

type PerfChangeBenchmarkSlice []*PerfChangeBenchmark

func (l PerfChangeBenchmarkSlice) Len() int      { return len(l) }
func (l PerfChangeBenchmarkSlice) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
func (l PerfChangeBenchmarkSlice) Less(i, j int) bool {
	b1, p1 := splitBench(l[i].Name)
	b2, p2 := splitBench(l[j].Name)
	if b1 != b2 {
		return b1 < b2
	}
	return p1 < p2
}

type PerfChangeMetricSlice []*PerfChangeMetric

func (l PerfChangeMetricSlice) Len() int           { return len(l) }
func (l PerfChangeMetricSlice) Swap(i, j int)      { l[i], l[j] = l[j], l[i] }
func (l PerfChangeMetricSlice) Less(i, j int) bool { return l[i].Name < l[j].Name }

func sendPerfMailFunc(c appengine.Context, com *Commit, prevCommitHash, builder string, changes []*PerfChange) {
	// Sort the changes into the right order.
	var benchmarks []*PerfChangeBenchmark
	for _, ch := range changes {
		// Find the benchmark.
		var b *PerfChangeBenchmark
		for _, b1 := range benchmarks {
			if b1.Name == ch.Bench {
				b = b1
				break
			}
		}
		if b == nil {
			b = &PerfChangeBenchmark{Name: ch.Bench}
			benchmarks = append(benchmarks, b)
		}
		b.Metrics = append(b.Metrics, &PerfChangeMetric{Name: ch.Metric, Old: ch.Old, New: ch.New, Delta: ch.Diff})
	}
	for _, b := range benchmarks {
		sort.Sort(PerfChangeMetricSlice(b.Metrics))
	}
	sort.Sort(PerfChangeBenchmarkSlice(benchmarks))

	u := fmt.Sprintf("http://%v/perfdetail?commit=%v&commit0=%v&kind=builder&builder=%v", domain, com.Hash, prevCommitHash, builder)

	// Prepare mail message (without Commit, for updateCL).
	var body bytes.Buffer
	err := sendPerfMailTmpl.Execute(&body, map[string]interface{}{
		"Builder": builder, "Hostname": domain, "Url": u, "Benchmarks": benchmarks,
	})
	if err != nil {
		c.Errorf("rendering perf mail template: %v", err)
		return
	}

	// First, try to update the CL.
	v := url.Values{"textmsg": {body.String()}}
	if updateCL(c, com, v) {
		return
	}

	// Otherwise, send mail (with Commit, for independent mail message).
	body.Reset()
	err = sendPerfMailTmpl.Execute(&body, map[string]interface{}{
		"Builder": builder, "Commit": com, "Hostname": domain, "Url": u, "Benchmarks": benchmarks,
	})
	if err != nil {
		c.Errorf("rendering perf mail template: %v", err)
		return
	}
	subject := fmt.Sprintf("Perf changes on %s by %s", builder, shortDesc(com.Desc))
	msg := &mail.Message{
		Sender:  mailFrom,
		To:      []string{failMailTo},
		ReplyTo: failMailTo,
		Subject: subject,
		Body:    body.String(),
	}

	// send mail
	if err := mail.Send(c, msg); err != nil {
		c.Errorf("sending mail: %v", err)
	}
}
<|endoftext|>


<commit_before>// Copyright 2011 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.

// +build appengine

package build

import (
	"encoding/json"
	"fmt"
	"net/http"

	"appengine"
	"appengine/datastore"
)

func init() {
	http.HandleFunc("/updatebenchmark", updateBenchmark)
}

func updateBenchmark(w http.ResponseWriter, r *http.Request) {
	if !appengine.IsDevAppServer() {
		fmt.Fprint(w, "Update must not run on real server.")
		return
	}

	if r.Method != "POST" {
		fmt.Fprintf(w, "bad request method")
		return
	}

	c := contextForRequest(r)
	if !validKey(c, r.FormValue("key"), r.FormValue("builder")) {
		fmt.Fprintf(w, "bad builder/key")
		return
	}

	defer r.Body.Close()
	var hashes []string
	if err := json.NewDecoder(r.Body).Decode(&hashes); err != nil {
		fmt.Fprintf(w, "failed to decode request: %v", err)
		return
	}

	ncommit := 0
	nrun := 0
	tx := func(c appengine.Context) error {
		var cr *CommitRun
		for _, hash := range hashes {
			// Update Commit.
			com := &Commit{Hash: hash}
			err := datastore.Get(c, com.Key(c), com)
			if err != nil && err != datastore.ErrNoSuchEntity {
				return fmt.Errorf("fetching Commit: %v", err)
			}
			if err == datastore.ErrNoSuchEntity {
				continue
			}
			com.NeedsBenchmarking = true
			com.ResultData = nil
			if err := putCommit(c, com); err != nil {
				return err
			}
			ncommit++

			// create PerfResult
			res := &PerfResult{CommitHash: com.Hash, CommitNum: com.Num}
			err = datastore.Get(c, res.Key(c), res)
			if err != nil && err != datastore.ErrNoSuchEntity {
				return fmt.Errorf("fetching PerfResult: %v", err)
			}
			if err == datastore.ErrNoSuchEntity {
				if _, err := datastore.Put(c, res.Key(c), res); err != nil {
					return fmt.Errorf("putting PerfResult: %v", err)
				}
			}

			// Update CommitRun.
			if cr != nil && cr.StartCommitNum != com.Num/PerfRunLength*PerfRunLength {
				if _, err := datastore.Put(c, cr.Key(c), cr); err != nil {
					return fmt.Errorf("putting CommitRun: %v", err)
				}
				nrun++
				cr = nil
			}
			if cr == nil {
				var err error
				cr, err = GetCommitRun(c, com.Num)
				if err != nil {
					return fmt.Errorf("getting CommitRun: %v", err)
				}
			}
			if com.Num < cr.StartCommitNum || com.Num >= cr.StartCommitNum+PerfRunLength {
				return fmt.Errorf("commit num %v out of range [%v, %v)", com.Num, cr.StartCommitNum, cr.StartCommitNum+PerfRunLength)
			}
			idx := com.Num - cr.StartCommitNum
			cr.Hash[idx] = com.Hash
			cr.User[idx] = shortDesc(com.User)
			cr.Desc[idx] = shortDesc(com.Desc)
			cr.Time[idx] = com.Time
			cr.NeedsBenchmarking[idx] = com.NeedsBenchmarking
		}
		if cr != nil {
			if _, err := datastore.Put(c, cr.Key(c), cr); err != nil {
				return fmt.Errorf("putting CommitRun: %v", err)
			}
			nrun++
		}
		return nil
	}
	if err := datastore.RunInTransaction(c, tx, nil); err != nil {
		fmt.Fprintf(w, "failed to execute tx: %v", err)
		return
	}
	fmt.Fprintf(w, "OK (updated %v commits and %v commit runs)", ncommit, nrun)
}
<commit_msg>dashboard: fix update script It needs to remove perf results rather than build results.<commit_after>// Copyright 2011 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.

// +build appengine

package build

import (
	"encoding/json"
	"fmt"
	"net/http"

	"appengine"
	"appengine/datastore"
)

func init() {
	http.HandleFunc("/updatebenchmark", updateBenchmark)
}

func updateBenchmark(w http.ResponseWriter, r *http.Request) {
	if !appengine.IsDevAppServer() {
		fmt.Fprint(w, "Update must not run on real server.")
		return
	}

	if r.Method != "POST" {
		fmt.Fprintf(w, "bad request method")
		return
	}

	c := contextForRequest(r)
	if !validKey(c, r.FormValue("key"), r.FormValue("builder")) {
		fmt.Fprintf(w, "bad builder/key")
		return
	}

	defer r.Body.Close()
	var hashes []string
	if err := json.NewDecoder(r.Body).Decode(&hashes); err != nil {
		fmt.Fprintf(w, "failed to decode request: %v", err)
		return
	}

	ncommit := 0
	nrun := 0
	tx := func(c appengine.Context) error {
		var cr *CommitRun
		for _, hash := range hashes {
			// Update Commit.
			com := &Commit{Hash: hash}
			err := datastore.Get(c, com.Key(c), com)
			if err != nil && err != datastore.ErrNoSuchEntity {
				return fmt.Errorf("fetching Commit: %v", err)
			}
			if err == datastore.ErrNoSuchEntity {
				continue
			}
			com.NeedsBenchmarking = true
			com.PerfResults = nil
			if err := putCommit(c, com); err != nil {
				return err
			}
			ncommit++

			// create PerfResult
			res := &PerfResult{CommitHash: com.Hash, CommitNum: com.Num}
			err = datastore.Get(c, res.Key(c), res)
			if err != nil && err != datastore.ErrNoSuchEntity {
				return fmt.Errorf("fetching PerfResult: %v", err)
			}
			if err == datastore.ErrNoSuchEntity {
				if _, err := datastore.Put(c, res.Key(c), res); err != nil {
					return fmt.Errorf("putting PerfResult: %v", err)
				}
			}

			// Update CommitRun.
			if cr != nil && cr.StartCommitNum != com.Num/PerfRunLength*PerfRunLength {
				if _, err := datastore.Put(c, cr.Key(c), cr); err != nil {
					return fmt.Errorf("putting CommitRun: %v", err)
				}
				nrun++
				cr = nil
			}
			if cr == nil {
				var err error
				cr, err = GetCommitRun(c, com.Num)
				if err != nil {
					return fmt.Errorf("getting CommitRun: %v", err)
				}
			}
			if com.Num < cr.StartCommitNum || com.Num >= cr.StartCommitNum+PerfRunLength {
				return fmt.Errorf("commit num %v out of range [%v, %v)", com.Num, cr.StartCommitNum, cr.StartCommitNum+PerfRunLength)
			}
			idx := com.Num - cr.StartCommitNum
			cr.Hash[idx] = com.Hash
			cr.User[idx] = shortDesc(com.User)
			cr.Desc[idx] = shortDesc(com.Desc)
			cr.Time[idx] = com.Time
			cr.NeedsBenchmarking[idx] = com.NeedsBenchmarking
		}
		if cr != nil {
			if _, err := datastore.Put(c, cr.Key(c), cr); err != nil {
				return fmt.Errorf("putting CommitRun: %v", err)
			}
			nrun++
		}
		return nil
	}
	if err := datastore.RunInTransaction(c, tx, nil); err != nil {
		fmt.Fprintf(w, "failed to execute tx: %v", err)
		return
	}
	fmt.Fprintf(w, "OK (updated %v commits and %v commit runs)", ncommit, nrun)
}
<|endoftext|>


<commit_before>package datakit

import (
	"bytes"
	"io"
	"log"
	"net"
	"sync"

	p9p "github.com/docker/go-p9p"
	"context"
)

type Client struct {
	conn     net.Conn
	session  p9p.Session
	m        *sync.Mutex
	c        *sync.Cond
	usedFids map[p9p.Fid]bool
	freeFids []p9p.Fid
	root     p9p.Fid
}

var badFid = p9p.Fid(0)

var rwx = p9p.DMREAD | p9p.DMWRITE | p9p.DMEXEC
var rx = p9p.DMREAD | p9p.DMEXEC
var rw = p9p.DMREAD | p9p.DMWRITE
var r = p9p.DMREAD
var dirperm = uint32(rwx<<6 | rx<<3 | rx | p9p.DMDIR)
var fileperm = uint32(rw<<6 | r<<3 | r)

// Dial opens a connection to a 9P server
func Dial(ctx context.Context, network, address string) (*Client, error) {
	log.Println("Dialling", network, address)
	conn, err := net.Dial(network, address)
	if err != nil {
		return nil, err
	}
	return NewClient(ctx, conn)
}

// NewClient creates opens a connection with the p9p server
func NewClient(ctx context.Context, conn net.Conn) (*Client, error) {
	session, err := p9p.NewSession(ctx, conn)
	if err != nil {
		log.Println("Failed to establish 9P session to", err)
		return nil, err
	}
	root := p9p.Fid(1)
	if _, err := session.Attach(ctx, root, p9p.NOFID, "anyone", "/"); err != nil {
		log.Println("Failed to Attach to filesystem", err)
		return nil, err
	}
	usedFids := make(map[p9p.Fid]bool, 0)
	freeFids := make([]p9p.Fid, 0)
	for i := 0; i < 128; i++ {
		fid := p9p.Fid(i)
		if fid == root {
			usedFids[fid] = true
		} else {
			freeFids = append(freeFids, fid)
			usedFids[fid] = false
		}
	}
	var m sync.Mutex
	c := sync.NewCond(&m)
	return &Client{conn, session, &m, c, usedFids, freeFids, root}, nil
}

func (c *Client) Close(ctx context.Context) {
	if err := c.session.Clunk(ctx, c.root); err != nil {
		log.Println("Failed to Clunk root fid", err)
	} else {
		c.usedFids[c.root] = false
	}
	c.m.Lock()
	defer c.m.Unlock()
	for fid, inuse := range c.usedFids {
		if inuse {
			log.Println("I don't know how to flush: leaking", fid)
		}
	}
	c.conn.Close()
}

// allocFid returns a fresh fid, bound to a clone of from
func (c *Client) allocFid(ctx context.Context, from p9p.Fid) (p9p.Fid, error) {
	c.m.Lock()
	defer c.m.Unlock()
	for len(c.freeFids) == 0 {
		c.c.Wait()
	}
	fid := c.freeFids[len(c.freeFids)-1]
	c.freeFids = c.freeFids[0 : len(c.freeFids)-1]
	c.usedFids[fid] = true
	_, err := c.session.Walk(ctx, from, fid)
	if err != nil {
		log.Println("Failed to clone root fid", err)
		return badFid, err
	}
	return fid, nil
}

// freeFid removes resources associated with the given fid
func (c *Client) freeFid(ctx context.Context, fid p9p.Fid) {
	c.m.Lock()
	defer c.m.Unlock()
	c.freeFids = append(c.freeFids, fid)
	c.usedFids[fid] = false
	if err := c.session.Clunk(ctx, fid); err != nil {
		log.Println("Failed to clunk fid", fid)
	}
	c.c.Signal()
}

// Mkdir acts like 'mkdir -p'
func (c *Client) Mkdir(ctx context.Context, path ...string) error {
	fid, err := c.allocFid(ctx, c.root)
	if err != nil {
		return nil
	}
	defer c.freeFid(ctx, fid)
	// mkdir -p
	for _, dir := range path {
		dirfid, err := c.allocFid(ctx, fid)
		if err != nil {
			return err
		}
		// dir may or may not exist
		_, _, _ = c.session.Create(ctx, dirfid, dir, dirperm, p9p.OREAD)
		c.freeFid(ctx, dirfid)
		// dir should definitely exist
		if _, err := c.session.Walk(ctx, fid, fid, dir); err != nil {
			log.Println("Failed to Walk to", dir, err)
			return err
		}
	}
	return nil
}

var enoent = p9p.MessageRerror{Ename: "No such file or directory"}
var enotdir = p9p.MessageRerror{Ename: "Can't walk from a file"}

// Remove acts like 'rm -f'
func (c *Client) Remove(ctx context.Context, path ...string) error {
	fid, err := c.allocFid(ctx, c.root)
	if err != nil {
		return err
	}
	defer c.freeFid(ctx, fid)
	if _, err := c.session.Walk(ctx, fid, fid, path...); err != nil {
		if err == enoent || err == enotdir {
			return nil
		}
		log.Println("Failed to walk to", path, err)
		return err
	}
	if err := c.session.Remove(ctx, fid); err != nil {
		if err == enoent {
			return nil
		}
		log.Println("Failed to Remove", path, err)
		return err
	}
	return nil
}

type File struct {
	fid  p9p.Fid
	c    *Client
	m    *sync.Mutex
	open bool
}

// Create creates a file
func (c *Client) Create(ctx context.Context, path ...string) (*File, error) {
	fid, err := c.allocFid(ctx, c.root)
	if err != nil {
		return nil, err
	}
	dir := path[0 : len(path)-1]
	_, err = c.session.Walk(ctx, fid, fid, dir...)
	if err != nil {
		if err != enoent {
			// This is a common error
			log.Println("Failed to Walk to", path, err)
		}
		c.freeFid(ctx, fid)
		return nil, err
	}
	_, _, err = c.session.Create(ctx, fid, path[len(path)-1], fileperm, p9p.ORDWR)
	if err != nil {
		log.Println("Failed to Create", path, err)
		return nil, err
	}
	var m sync.Mutex
	return &File{fid: fid, c: c, m: &m, open: true}, nil
}

// Open opens a file
func (c *Client) Open(ctx context.Context, mode p9p.Flag, path ...string) (*File, error) {
	fid, err := c.allocFid(ctx, c.root)
	if err != nil {
		return nil, err
	}
	_, err = c.session.Walk(ctx, fid, fid, path...)
	if err != nil {
		if err != enoent {
			// This is a common error
			log.Println("Failed to Walk to", path, err)
		}
		c.freeFid(ctx, fid)
		return nil, err
	}
	_, _, err = c.session.Open(ctx, fid, mode)
	if err != nil {
		log.Println("Failed to Open", path, err)
		c.freeFid(ctx, fid)
		return nil, err
	}
	var m sync.Mutex
	return &File{fid: fid, c: c, m: &m, open: true}, nil
}

// List a directory
func (c *Client) List(ctx context.Context, path []string) ([]string, error) {
	file, err := c.Open(ctx, p9p.OREAD, path...)
	if err != nil {
		return nil, err
	}
	defer file.Close(ctx)

	msize, _ := c.session.Version()
	iounit := uint32(msize - 24) // size of message max minus fcall io header (Rread)

	p := make([]byte, iounit)

	n, err := c.session.Read(ctx, file.fid, p, 0)
	if err != nil {
		return nil, err
	}

	files := []string{}

	rd := bytes.NewReader(p[:n])
	codec := p9p.NewCodec() // TODO(stevvooe): Need way to resolve codec based on session.
	for {
		var d p9p.Dir
		if err := p9p.DecodeDir(codec, rd, &d); err != nil {
			if err == io.EOF {
				break
			}
			return files, err
		}
		files = append(files, d.Name)
	}
	return files, nil
}

// Close closes a file
func (f *File) Close(ctx context.Context) {
	f.m.Lock()
	defer f.m.Unlock()
	if f.open {
		f.c.freeFid(ctx, f.fid)
	}
	f.open = false
}

// Read reads a value
func (f *File) Read(ctx context.Context, p []byte, offset int64) (int, error) {
	f.m.Lock()
	defer f.m.Unlock()
	if !f.open {
		return 0, io.EOF
	}
	return f.c.session.Read(ctx, f.fid, p, offset)
}

// Write writes a value
func (f *File) Write(ctx context.Context, p []byte, offset int64) (int, error) {
	f.m.Lock()
	defer f.m.Unlock()
	if !f.open {
		return 0, io.EOF
	}
	return f.c.session.Write(ctx, f.fid, p, offset)
}

type FileReader struct {
	file   *File
	offset int64
	ctx    context.Context
}

func (f *File) NewFileReader(ctx context.Context) *FileReader {
	offset := int64(0)
	return &FileReader{file: f, offset: offset, ctx: ctx}
}

func (f *FileReader) Read(p []byte) (int, error) {
	n, err := f.file.Read(f.ctx, p, f.offset)
	f.offset = f.offset + int64(n)
	if n == 0 {
		return 0, io.EOF
	}
	return n, err
}

type ioFileReaderWriter struct {
	f      *File
	ctx    context.Context
	offset int64
}

// NewIOReader creates a standard io.Reader at a given position in the file
func (f *File) NewIOReader(ctx context.Context, offset int64) io.Reader {
	return &ioFileReaderWriter{f, ctx, offset}
}

// NewIOWriter creates a standard io.Writer at a given position in the file
func (f *File) NewIOWriter(ctx context.Context, offset int64) io.Writer {
	return &ioFileReaderWriter{f, ctx, offset}
}

func (r *ioFileReaderWriter) Read(p []byte) (n int, err error) {

	r.f.m.Lock()
	defer r.f.m.Unlock()
	n, err = r.f.c.session.Read(r.ctx, r.f.fid, p, r.offset)

	r.offset += int64(n)
	return n, err
}
func (w *ioFileReaderWriter) Write(p []byte) (n int, err error) {
	w.f.m.Lock()
	defer w.f.m.Unlock()
	for err == nil || err == io.ErrShortWrite {
		var written int
		written, err = w.f.c.session.Write(w.ctx, w.f.fid, p, w.offset)
		p = p[written:]
		w.offset += int64(written)
		n += written
		if len(p) == 0 {
			break
		}
	}
	return
}
<commit_msg>go: Remove will clunk fid even on failure<commit_after>package datakit

import (
	"bytes"
	"io"
	"log"
	"net"
	"sync"

	p9p "github.com/docker/go-p9p"
	"context"
)

type Client struct {
	conn     net.Conn
	session  p9p.Session
	m        *sync.Mutex
	c        *sync.Cond
	usedFids map[p9p.Fid]bool
	freeFids []p9p.Fid
	root     p9p.Fid
}

var badFid = p9p.Fid(0)

var rwx = p9p.DMREAD | p9p.DMWRITE | p9p.DMEXEC
var rx = p9p.DMREAD | p9p.DMEXEC
var rw = p9p.DMREAD | p9p.DMWRITE
var r = p9p.DMREAD
var dirperm = uint32(rwx<<6 | rx<<3 | rx | p9p.DMDIR)
var fileperm = uint32(rw<<6 | r<<3 | r)

// Dial opens a connection to a 9P server
func Dial(ctx context.Context, network, address string) (*Client, error) {
	log.Println("Dialling", network, address)
	conn, err := net.Dial(network, address)
	if err != nil {
		return nil, err
	}
	return NewClient(ctx, conn)
}

// NewClient creates opens a connection with the p9p server
func NewClient(ctx context.Context, conn net.Conn) (*Client, error) {
	session, err := p9p.NewSession(ctx, conn)
	if err != nil {
		log.Println("Failed to establish 9P session to", err)
		return nil, err
	}
	root := p9p.Fid(1)
	if _, err := session.Attach(ctx, root, p9p.NOFID, "anyone", "/"); err != nil {
		log.Println("Failed to Attach to filesystem", err)
		return nil, err
	}
	usedFids := make(map[p9p.Fid]bool, 0)
	freeFids := make([]p9p.Fid, 0)
	for i := 0; i < 128; i++ {
		fid := p9p.Fid(i)
		if fid == root {
			usedFids[fid] = true
		} else {
			freeFids = append(freeFids, fid)
			usedFids[fid] = false
		}
	}
	var m sync.Mutex
	c := sync.NewCond(&m)
	return &Client{conn, session, &m, c, usedFids, freeFids, root}, nil
}

func (c *Client) Close(ctx context.Context) {
	if err := c.session.Clunk(ctx, c.root); err != nil {
		log.Println("Failed to Clunk root fid", err)
	} else {
		c.usedFids[c.root] = false
	}
	c.m.Lock()
	defer c.m.Unlock()
	for fid, inuse := range c.usedFids {
		if inuse {
			log.Println("I don't know how to flush: leaking", fid)
		}
	}
	c.conn.Close()
}

// allocFid returns a fresh fid, bound to a clone of from
func (c *Client) allocFid(ctx context.Context, from p9p.Fid) (p9p.Fid, error) {
	c.m.Lock()
	defer c.m.Unlock()
	for len(c.freeFids) == 0 {
		c.c.Wait()
	}
	fid := c.freeFids[len(c.freeFids)-1]
	c.freeFids = c.freeFids[0 : len(c.freeFids)-1]
	c.usedFids[fid] = true
	_, err := c.session.Walk(ctx, from, fid)
	if err != nil {
		log.Println("Failed to clone root fid", err)
		return badFid, err
	}
	return fid, nil
}

// freeFid removes resources associated with the given fid
func (c *Client) freeFid(ctx context.Context, fid p9p.Fid) {
	c.m.Lock()
	defer c.m.Unlock()
	c.freeFids = append(c.freeFids, fid)
	c.usedFids[fid] = false
	if err := c.session.Clunk(ctx, fid); err != nil {
		log.Println("Failed to clunk fid", fid)
	}
	c.c.Signal()
}

// Mkdir acts like 'mkdir -p'
func (c *Client) Mkdir(ctx context.Context, path ...string) error {
	fid, err := c.allocFid(ctx, c.root)
	if err != nil {
		return nil
	}
	defer c.freeFid(ctx, fid)
	// mkdir -p
	for _, dir := range path {
		dirfid, err := c.allocFid(ctx, fid)
		if err != nil {
			return err
		}
		// dir may or may not exist
		_, _, _ = c.session.Create(ctx, dirfid, dir, dirperm, p9p.OREAD)
		c.freeFid(ctx, dirfid)
		// dir should definitely exist
		if _, err := c.session.Walk(ctx, fid, fid, dir); err != nil {
			log.Println("Failed to Walk to", dir, err)
			return err
		}
	}
	return nil
}

var enoent = p9p.MessageRerror{Ename: "No such file or directory"}
var enotdir = p9p.MessageRerror{Ename: "Can't walk from a file"}

// Remove acts like 'rm -f'
func (c *Client) Remove(ctx context.Context, path ...string) error {
	fid, err := c.allocFid(ctx, c.root)
	if err != nil {
		return err
	}
	if _, err := c.session.Walk(ctx, fid, fid, path...); err != nil {
		if err == enoent || err == enotdir {
			c.freeFid(ctx, fid)
			return nil
		}
		log.Println("Failed to walk to", path, err)
		c.freeFid(ctx, fid)
		return err
	}
	// Remove will cluck the fid, even if it fails
	if err := c.session.Remove(ctx, fid); err != nil {
		if err == enoent {
			return nil
		}
		log.Println("Failed to Remove", path, err)
		return err
	}
	return nil
}

type File struct {
	fid  p9p.Fid
	c    *Client
	m    *sync.Mutex
	open bool
}

// Create creates a file
func (c *Client) Create(ctx context.Context, path ...string) (*File, error) {
	fid, err := c.allocFid(ctx, c.root)
	if err != nil {
		return nil, err
	}
	dir := path[0 : len(path)-1]
	_, err = c.session.Walk(ctx, fid, fid, dir...)
	if err != nil {
		if err != enoent {
			// This is a common error
			log.Println("Failed to Walk to", path, err)
		}
		c.freeFid(ctx, fid)
		return nil, err
	}
	_, _, err = c.session.Create(ctx, fid, path[len(path)-1], fileperm, p9p.ORDWR)
	if err != nil {
		log.Println("Failed to Create", path, err)
		return nil, err
	}
	var m sync.Mutex
	return &File{fid: fid, c: c, m: &m, open: true}, nil
}

// Open opens a file
func (c *Client) Open(ctx context.Context, mode p9p.Flag, path ...string) (*File, error) {
	fid, err := c.allocFid(ctx, c.root)
	if err != nil {
		return nil, err
	}
	_, err = c.session.Walk(ctx, fid, fid, path...)
	if err != nil {
		if err != enoent {
			// This is a common error
			log.Println("Failed to Walk to", path, err)
		}
		c.freeFid(ctx, fid)
		return nil, err
	}
	_, _, err = c.session.Open(ctx, fid, mode)
	if err != nil {
		log.Println("Failed to Open", path, err)
		c.freeFid(ctx, fid)
		return nil, err
	}
	var m sync.Mutex
	return &File{fid: fid, c: c, m: &m, open: true}, nil
}

// List a directory
func (c *Client) List(ctx context.Context, path []string) ([]string, error) {
	file, err := c.Open(ctx, p9p.OREAD, path...)
	if err != nil {
		return nil, err
	}
	defer file.Close(ctx)

	msize, _ := c.session.Version()
	iounit := uint32(msize - 24) // size of message max minus fcall io header (Rread)

	p := make([]byte, iounit)

	n, err := c.session.Read(ctx, file.fid, p, 0)
	if err != nil {
		return nil, err
	}

	files := []string{}

	rd := bytes.NewReader(p[:n])
	codec := p9p.NewCodec() // TODO(stevvooe): Need way to resolve codec based on session.
	for {
		var d p9p.Dir
		if err := p9p.DecodeDir(codec, rd, &d); err != nil {
			if err == io.EOF {
				break
			}
			return files, err
		}
		files = append(files, d.Name)
	}
	return files, nil
}

// Close closes a file
func (f *File) Close(ctx context.Context) {
	f.m.Lock()
	defer f.m.Unlock()
	if f.open {
		f.c.freeFid(ctx, f.fid)
	}
	f.open = false
}

// Read reads a value
func (f *File) Read(ctx context.Context, p []byte, offset int64) (int, error) {
	f.m.Lock()
	defer f.m.Unlock()
	if !f.open {
		return 0, io.EOF
	}
	return f.c.session.Read(ctx, f.fid, p, offset)
}

// Write writes a value
func (f *File) Write(ctx context.Context, p []byte, offset int64) (int, error) {
	f.m.Lock()
	defer f.m.Unlock()
	if !f.open {
		return 0, io.EOF
	}
	return f.c.session.Write(ctx, f.fid, p, offset)
}

type FileReader struct {
	file   *File
	offset int64
	ctx    context.Context
}

func (f *File) NewFileReader(ctx context.Context) *FileReader {
	offset := int64(0)
	return &FileReader{file: f, offset: offset, ctx: ctx}
}

func (f *FileReader) Read(p []byte) (int, error) {
	n, err := f.file.Read(f.ctx, p, f.offset)
	f.offset = f.offset + int64(n)
	if n == 0 {
		return 0, io.EOF
	}
	return n, err
}

type ioFileReaderWriter struct {
	f      *File
	ctx    context.Context
	offset int64
}

// NewIOReader creates a standard io.Reader at a given position in the file
func (f *File) NewIOReader(ctx context.Context, offset int64) io.Reader {
	return &ioFileReaderWriter{f, ctx, offset}
}

// NewIOWriter creates a standard io.Writer at a given position in the file
func (f *File) NewIOWriter(ctx context.Context, offset int64) io.Writer {
	return &ioFileReaderWriter{f, ctx, offset}
}

func (r *ioFileReaderWriter) Read(p []byte) (n int, err error) {

	r.f.m.Lock()
	defer r.f.m.Unlock()
	n, err = r.f.c.session.Read(r.ctx, r.f.fid, p, r.offset)

	r.offset += int64(n)
	return n, err
}
func (w *ioFileReaderWriter) Write(p []byte) (n int, err error) {
	w.f.m.Lock()
	defer w.f.m.Unlock()
	for err == nil || err == io.ErrShortWrite {
		var written int
		written, err = w.f.c.session.Write(w.ctx, w.f.fid, p, w.offset)
		p = p[written:]
		w.offset += int64(written)
		n += written
		if len(p) == 0 {
			break
		}
	}
	return
}
<|endoftext|>