<commit_before>// Copyright (c) 2015, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package interfacer

import (
	"bytes"
	"flag"
	"fmt"
	"go/build"
	"go/parser"
	"go/token"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strings"
	"testing"
)

const testdata = "testdata"

var (
	name     = flag.String("name", "", "name of the test to run")
	warnsRe  = regexp.MustCompile(`^WARN (.*)\n?$`)
	singleRe = regexp.MustCompile(`([^ ]*) can be ([^ ]*)`)
)

func goFiles(p string) ([]string, error) {
	if strings.HasSuffix(p, ".go") {
		return []string{p}, nil
	}
	dirs, err := recurse(p)
	if err != nil {
		return nil, err
	}
	var paths []string
	for _, dir := range dirs {
		files, err := ioutil.ReadDir(dir)
		if err != nil {
			return nil, err
		}
		for _, file := range files {
			if file.IsDir() {
				continue
			}
			paths = append(paths, filepath.Join(dir, file.Name()))
		}
	}
	return paths, nil
}

func wantedWarnings(t *testing.T, p string) []Warn {
	paths, err := goFiles(p)
	if err != nil {
		t.Fatal(err)
	}
	fset := token.NewFileSet()
	var warns []Warn
	for _, path := range paths {
		src, err := os.Open(path)
		if err != nil {
			t.Fatal(err)
		}
		defer src.Close()
		f, err := parser.ParseFile(fset, path, src, parser.ParseComments)
		if err != nil {
			t.Fatal(err)
		}
		for _, group := range f.Comments {
			m := warnsRe.FindStringSubmatch(group.Text())
			if m == nil {
				continue
			}
			for _, m := range singleRe.FindAllStringSubmatch(m[1], -1) {
				warns = append(warns, Warn{
					Pos: token.Position{
						Filename: path,
					},
					Name: m[1],
					Type: m[2],
				})
			}
		}
	}
	return warns
}

func doTest(t *testing.T, p string) {
	warns := wantedWarnings(t, p)
	doTestWarns(t, p, warns, p)
}

func warnsEqual(got, want []Warn) bool {
	if len(got) != len(want) {
		return false
	}
	for i, w1 := range got {
		w2 := want[i]
		if w1.Name != w2.Name {
			return false
		}
		if w1.Type != w2.Type {
			return false
		}
	}
	return true
}

func warnsJoin(warns []Warn) string {
	var b bytes.Buffer
	for _, warn := range warns {
		fmt.Fprintln(&b, warn.String())
	}
	return b.String()
}

func doTestWarns(t *testing.T, name string, exp []Warn, args ...string) {
	got, err := CheckArgsList(args)
	if err != nil {
		t.Fatalf("Did not want error in %s:\n%v", name, err)
	}
	if !warnsEqual(exp, got) {
		t.Fatalf("Output mismatch in %s:\nExpected:\n%sGot:\n%s",
			name, warnsJoin(exp), warnsJoin(got))
	}
}

func endNewline(s string) string {
	if strings.HasSuffix(s, "\n") {
		return s
	}
	return s + "\n"
}

func doTestString(t *testing.T, name, exp string, args ...string) {
	var b bytes.Buffer
	switch len(args) {
	case 0:
		args = []string{name}
	case 1:
		if args[0] == "" {
			args = nil
		}
	}
	err := CheckArgsOutput(args, &b, true)
	if err != nil {
		t.Fatalf("Did not want error in %s:\n%v", name, err)
	}
	exp = endNewline(exp)
	got := b.String()
	if exp != got {
		t.Fatalf("Output mismatch in %s:\nExpected:\n%sGot:\n%s",
			name, exp, got)
	}
}

func inputPaths(t *testing.T, glob string) []string {
	all, err := filepath.Glob(glob)
	if err != nil {
		t.Fatal(err)
	}
	return all
}

func chdirUndo(t *testing.T, d string) func() {
	wd, err := os.Getwd()
	if err != nil {
		t.Fatal(err)
	}
	if err := os.Chdir(d); err != nil {
		t.Fatal(err)
	}
	return func() {
		if err := os.Chdir(wd); err != nil {
			t.Fatal(err)
		}
	}
}

func runFileTests(t *testing.T, paths ...string) {
	defer chdirUndo(t, "files")()
	if len(paths) == 0 {
		paths = inputPaths(t, "*")
	}
	for _, p := range paths {
		doTest(t, p)
	}
}

func runLocalTests(t *testing.T, paths ...string) {
	defer chdirUndo(t, "local")()
	if len(paths) == 0 {
		for _, p := range inputPaths(t, "*") {
			paths = append(paths, "./"+p+"/...")
		}
		// non-recursive
		paths = append(paths, "./single")
	}
	for _, p := range paths {
		doTest(t, p)
	}
	doTestString(t, "no-args", ".", "")
}

func runNonlocalTests(t *testing.T, paths ...string) {
	defer chdirUndo(t, "src")()
	if len(paths) > 0 {
		for _, p := range paths {
			doTest(t, p)
		}
		return
	}
	paths = inputPaths(t, "*")
	for _, p := range paths {
		doTest(t, p+"/...")
	}
	// local recursive
	doTest(t, "./nested/...")
	// non-recursive
	doTest(t, "single")
	// make sure we don't miss a package's imports
	doTestString(t, "grab-import", "grab-import\ngrab-import/use.go:27:15: s can be def2.Fooer")
	defer chdirUndo(t, "nested/pkg")()
	// relative paths
	doTestString(t, "rel-path", "nested/pkg\nsimple.go:12:17: rc can be Closer", "./...")
}

func TestMain(m *testing.M) {
	flag.Parse()
	if err := os.Chdir(testdata); err != nil {
		panic(err)
	}
	wd, err := os.Getwd()
	if err != nil {
		panic(err)
	}
	build.Default.GOPATH = wd
	os.Exit(m.Run())
}

func TestCheckWarnings(t *testing.T) {
	switch {
	case *name == "":
	case strings.HasSuffix(*name, ".go"):
		runFileTests(t, *name)
		return
	case strings.HasPrefix(*name, "./"):
		runLocalTests(t, *name)
		return
	default:
		runNonlocalTests(t, *name)
		return
	}
	runFileTests(t)
	runLocalTests(t)
	runNonlocalTests(t)
}

func doTestError(t *testing.T, name, exp string, args ...string) {
	switch len(args) {
	case 0:
		args = []string{name}
	case 1:
		if args[0] == "" {
			args = nil
		}
	}
	err := CheckArgsOutput(args, ioutil.Discard, false)
	if err == nil {
		t.Fatalf("Wanted error in %s, but none found.", name)
	}
	got := err.Error()
	if exp != got {
		t.Fatalf("Error mismatch in %s:\nExpected:\n%sGot:\n%s",
			name, exp, got)
	}
}

func TestErrors(t *testing.T) {
	// non-existent Go file
	doTestError(t, "missing.go", "open missing.go: no such file or directory")
	// local non-existent non-recursive
	doTestError(t, "./missing", "no initial packages were loaded")
	// non-local non-existent non-recursive
	doTestError(t, "missing", "no initial packages were loaded")
	// local non-existent recursive
	doTestError(t, "./missing-rec/...", "lstat ./missing-rec: no such file or directory")
	// Mixing Go files and dirs
	doTestError(t, "wrong-args", "named files must be .go files: bar", "foo.go", "bar")
}

func TestExtraArg(t *testing.T) {
	err := CheckArgsOutput([]string{"single", "--", "foo", "bar"}, ioutil.Discard, false)
	got := err.Error()
	want := "unwanted extra args: [foo bar]"
	if got != want {
		t.Fatalf("Error mismatch:\nExpected:\n%sGot:\n%s", want, got)
	}
}
<commit_msg>test: simplify goFiles<commit_after>// Copyright (c) 2015, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package interfacer

import (
	"bytes"
	"flag"
	"fmt"
	"go/build"
	"go/parser"
	"go/token"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strings"
	"testing"
)

const testdata = "testdata"

var (
	name     = flag.String("name", "", "name of the test to run")
	warnsRe  = regexp.MustCompile(`^WARN (.*)\n?$`)
	singleRe = regexp.MustCompile(`([^ ]*) can be ([^ ]*)`)
)

func goFiles(t *testing.T, p string) []string {
	if strings.HasSuffix(p, ".go") {
		return []string{p}
	}
	dirs, err := recurse(p)
	if err != nil {
		t.Fatal(err)
	}
	var paths []string
	for _, dir := range dirs {
		files, err := ioutil.ReadDir(dir)
		if err != nil {
			t.Fatal(err)
		}
		for _, file := range files {
			if file.IsDir() {
				continue
			}
			paths = append(paths, filepath.Join(dir, file.Name()))
		}
	}
	return paths
}

func wantedWarnings(t *testing.T, p string) []Warn {
	fset := token.NewFileSet()
	var warns []Warn
	for _, path := range goFiles(t, p) {
		src, err := os.Open(path)
		if err != nil {
			t.Fatal(err)
		}
		defer src.Close()
		f, err := parser.ParseFile(fset, path, src, parser.ParseComments)
		if err != nil {
			t.Fatal(err)
		}
		for _, group := range f.Comments {
			m := warnsRe.FindStringSubmatch(group.Text())
			if m == nil {
				continue
			}
			for _, m := range singleRe.FindAllStringSubmatch(m[1], -1) {
				warns = append(warns, Warn{
					Pos: token.Position{
						Filename: path,
					},
					Name: m[1],
					Type: m[2],
				})
			}
		}
	}
	return warns
}

func doTest(t *testing.T, p string) {
	warns := wantedWarnings(t, p)
	doTestWarns(t, p, warns, p)
}

func warnsEqual(got, want []Warn) bool {
	if len(got) != len(want) {
		return false
	}
	for i, w1 := range got {
		w2 := want[i]
		if w1.Name != w2.Name {
			return false
		}
		if w1.Type != w2.Type {
			return false
		}
	}
	return true
}

func warnsJoin(warns []Warn) string {
	var b bytes.Buffer
	for _, warn := range warns {
		fmt.Fprintln(&b, warn.String())
	}
	return b.String()
}

func doTestWarns(t *testing.T, name string, exp []Warn, args ...string) {
	got, err := CheckArgsList(args)
	if err != nil {
		t.Fatalf("Did not want error in %s:\n%v", name, err)
	}
	if !warnsEqual(exp, got) {
		t.Fatalf("Output mismatch in %s:\nExpected:\n%sGot:\n%s",
			name, warnsJoin(exp), warnsJoin(got))
	}
}

func endNewline(s string) string {
	if strings.HasSuffix(s, "\n") {
		return s
	}
	return s + "\n"
}

func doTestString(t *testing.T, name, exp string, args ...string) {
	var b bytes.Buffer
	switch len(args) {
	case 0:
		args = []string{name}
	case 1:
		if args[0] == "" {
			args = nil
		}
	}
	err := CheckArgsOutput(args, &b, true)
	if err != nil {
		t.Fatalf("Did not want error in %s:\n%v", name, err)
	}
	exp = endNewline(exp)
	got := b.String()
	if exp != got {
		t.Fatalf("Output mismatch in %s:\nExpected:\n%sGot:\n%s",
			name, exp, got)
	}
}

func inputPaths(t *testing.T, glob string) []string {
	all, err := filepath.Glob(glob)
	if err != nil {
		t.Fatal(err)
	}
	return all
}

func chdirUndo(t *testing.T, d string) func() {
	wd, err := os.Getwd()
	if err != nil {
		t.Fatal(err)
	}
	if err := os.Chdir(d); err != nil {
		t.Fatal(err)
	}
	return func() {
		if err := os.Chdir(wd); err != nil {
			t.Fatal(err)
		}
	}
}

func runFileTests(t *testing.T, paths ...string) {
	defer chdirUndo(t, "files")()
	if len(paths) == 0 {
		paths = inputPaths(t, "*")
	}
	for _, p := range paths {
		doTest(t, p)
	}
}

func runLocalTests(t *testing.T, paths ...string) {
	defer chdirUndo(t, "local")()
	if len(paths) == 0 {
		for _, p := range inputPaths(t, "*") {
			paths = append(paths, "./"+p+"/...")
		}
		// non-recursive
		paths = append(paths, "./single")
	}
	for _, p := range paths {
		doTest(t, p)
	}
	doTestString(t, "no-args", ".", "")
}

func runNonlocalTests(t *testing.T, paths ...string) {
	defer chdirUndo(t, "src")()
	if len(paths) > 0 {
		for _, p := range paths {
			doTest(t, p)
		}
		return
	}
	paths = inputPaths(t, "*")
	for _, p := range paths {
		doTest(t, p+"/...")
	}
	// local recursive
	doTest(t, "./nested/...")
	// non-recursive
	doTest(t, "single")
	// make sure we don't miss a package's imports
	doTestString(t, "grab-import", "grab-import\ngrab-import/use.go:27:15: s can be def2.Fooer")
	defer chdirUndo(t, "nested/pkg")()
	// relative paths
	doTestString(t, "rel-path", "nested/pkg\nsimple.go:12:17: rc can be Closer", "./...")
}

func TestMain(m *testing.M) {
	flag.Parse()
	if err := os.Chdir(testdata); err != nil {
		panic(err)
	}
	wd, err := os.Getwd()
	if err != nil {
		panic(err)
	}
	build.Default.GOPATH = wd
	os.Exit(m.Run())
}

func TestCheckWarnings(t *testing.T) {
	switch {
	case *name == "":
	case strings.HasSuffix(*name, ".go"):
		runFileTests(t, *name)
		return
	case strings.HasPrefix(*name, "./"):
		runLocalTests(t, *name)
		return
	default:
		runNonlocalTests(t, *name)
		return
	}
	runFileTests(t)
	runLocalTests(t)
	runNonlocalTests(t)
}

func doTestError(t *testing.T, name, exp string, args ...string) {
	switch len(args) {
	case 0:
		args = []string{name}
	case 1:
		if args[0] == "" {
			args = nil
		}
	}
	err := CheckArgsOutput(args, ioutil.Discard, false)
	if err == nil {
		t.Fatalf("Wanted error in %s, but none found.", name)
	}
	got := err.Error()
	if exp != got {
		t.Fatalf("Error mismatch in %s:\nExpected:\n%sGot:\n%s",
			name, exp, got)
	}
}

func TestErrors(t *testing.T) {
	// non-existent Go file
	doTestError(t, "missing.go", "open missing.go: no such file or directory")
	// local non-existent non-recursive
	doTestError(t, "./missing", "no initial packages were loaded")
	// non-local non-existent non-recursive
	doTestError(t, "missing", "no initial packages were loaded")
	// local non-existent recursive
	doTestError(t, "./missing-rec/...", "lstat ./missing-rec: no such file or directory")
	// Mixing Go files and dirs
	doTestError(t, "wrong-args", "named files must be .go files: bar", "foo.go", "bar")
}

func TestExtraArg(t *testing.T) {
	err := CheckArgsOutput([]string{"single", "--", "foo", "bar"}, ioutil.Discard, false)
	got := err.Error()
	want := "unwanted extra args: [foo bar]"
	if got != want {
		t.Fatalf("Error mismatch:\nExpected:\n%sGot:\n%s", want, got)
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package interfacer

import (
	"bytes"
	"flag"
	"fmt"
	"go/ast"
	"go/build"
	"go/parser"
	"go/token"
	"io/ioutil"
	"os"
	"path/filepath"
	"reflect"
	"regexp"
	"strings"
	"testing"
)

const testdata = "testdata"

var (
	name     = flag.String("name", "", "name of the test to run")
	warnsRe  = regexp.MustCompile(`^WARN (.*)\n?$`)
	singleRe = regexp.MustCompile(`([^ ]*) can be ([^ ]*)`)
)

func goFiles(t *testing.T, p string) []string {
	if strings.HasSuffix(p, ".go") {
		return []string{p}
	}
	dirs, err := recurse(p)
	if err != nil {
		t.Fatal(err)
	}
	var paths []string
	for _, dir := range dirs {
		files, err := ioutil.ReadDir(dir)
		if err != nil {
			t.Fatal(err)
		}
		for _, file := range files {
			if file.IsDir() {
				continue
			}
			paths = append(paths, filepath.Join(dir, file.Name()))
		}
	}
	return paths
}

type identVisitor struct {
	fset   *token.FileSet
	idents map[string]token.Position
}

func identKey(pos token.Position, name string) string {
	return fmt.Sprintf("%d %s", pos.Line, name)
}

func (v *identVisitor) Visit(n ast.Node) ast.Visitor {
	switch x := n.(type) {
	case *ast.Ident:
		pos := v.fset.Position(x.Pos())
		v.idents[identKey(pos, x.Name)] = pos
	}
	return v
}

func identPositions(fset *token.FileSet, f *ast.File) map[string]token.Position {
	v := &identVisitor{
		fset:   fset,
		idents: make(map[string]token.Position),
	}
	ast.Walk(v, f)
	return v.idents
}

func wantedWarnings(t *testing.T, p string) []Warn {
	fset := token.NewFileSet()
	var warns []Warn
	for _, path := range goFiles(t, p) {
		src, err := os.Open(path)
		if err != nil {
			t.Fatal(err)
		}
		defer src.Close()
		f, err := parser.ParseFile(fset, path, src, parser.ParseComments)
		if err != nil {
			t.Fatal(err)
		}
		identPos := identPositions(fset, f)
		for _, group := range f.Comments {
			cm := warnsRe.FindStringSubmatch(group.Text())
			if cm == nil {
				continue
			}
			for _, m := range singleRe.FindAllStringSubmatch(cm[1], -1) {
				vname, tname := m[1], m[2]
				comPos := fset.Position(group.Pos())
				warns = append(warns, Warn{
					Pos:  identPos[identKey(comPos, vname)],
					Name: vname,
					Type: tname,
				})
			}
		}
	}
	return warns
}

func doTest(t *testing.T, p string) {
	warns := wantedWarnings(t, p)
	doTestWarns(t, p, warns, p)
}

func warnsJoin(warns []Warn) string {
	var b bytes.Buffer
	for _, warn := range warns {
		fmt.Fprintln(&b, warn.String())
	}
	return b.String()
}

func doTestWarns(t *testing.T, name string, exp []Warn, args ...string) {
	got, err := CheckArgsList(args)
	if err != nil {
		t.Fatalf("Did not want error in %s:\n%v", name, err)
	}
	if !reflect.DeepEqual(exp, got) {
		t.Fatalf("Output mismatch in %s:\nExpected:\n%sGot:\n%s",
			name, warnsJoin(exp), warnsJoin(got))
	}
}

func endNewline(s string) string {
	if strings.HasSuffix(s, "\n") {
		return s
	}
	return s + "\n"
}

func doTestString(t *testing.T, name, exp string, args ...string) {
	var b bytes.Buffer
	switch len(args) {
	case 0:
		args = []string{name}
	case 1:
		if args[0] == "" {
			args = nil
		}
	}
	err := CheckArgsOutput(args, &b, true)
	if err != nil {
		t.Fatalf("Did not want error in %s:\n%v", name, err)
	}
	exp = endNewline(exp)
	got := b.String()
	if exp != got {
		t.Fatalf("Output mismatch in %s:\nExpected:\n%sGot:\n%s",
			name, exp, got)
	}
}

func inputPaths(t *testing.T, glob string) []string {
	all, err := filepath.Glob(glob)
	if err != nil {
		t.Fatal(err)
	}
	return all
}

func chdirUndo(t *testing.T, d string) func() {
	wd, err := os.Getwd()
	if err != nil {
		t.Fatal(err)
	}
	if err := os.Chdir(d); err != nil {
		t.Fatal(err)
	}
	return func() {
		if err := os.Chdir(wd); err != nil {
			t.Fatal(err)
		}
	}
}

func runFileTests(t *testing.T, paths ...string) {
	defer chdirUndo(t, "files")()
	if len(paths) == 0 {
		paths = inputPaths(t, "*")
	}
	for _, p := range paths {
		doTest(t, p)
	}
}

func runLocalTests(t *testing.T, paths ...string) {
	defer chdirUndo(t, "local")()
	if len(paths) == 0 {
		for _, p := range inputPaths(t, "*") {
			paths = append(paths, "./"+p+"/...")
		}
		// non-recursive
		paths = append(paths, "./single")
	}
	for _, p := range paths {
		doTest(t, p)
	}
	doTestString(t, "no-args", ".", "")
}

func runNonlocalTests(t *testing.T, paths ...string) {
	defer chdirUndo(t, "src")()
	if len(paths) > 0 {
		for _, p := range paths {
			doTest(t, p)
		}
		return
	}
	paths = inputPaths(t, "*")
	for _, p := range paths {
		doTest(t, p+"/...")
	}
	// local recursive
	doTest(t, "./nested/...")
	// non-recursive
	doTest(t, "single")
	// make sure we don't miss a package's imports
	doTestString(t, "grab-import", "grab-import\ngrab-import/use.go:27:15: s can be def2.Fooer")
	defer chdirUndo(t, "nested/pkg")()
	// relative paths
	doTestString(t, "rel-path", "nested/pkg\nsimple.go:12:17: rc can be Closer", "./...")
}

func TestMain(m *testing.M) {
	flag.Parse()
	if err := os.Chdir(testdata); err != nil {
		panic(err)
	}
	wd, err := os.Getwd()
	if err != nil {
		panic(err)
	}
	build.Default.GOPATH = wd
	os.Exit(m.Run())
}

func TestCheckWarnings(t *testing.T) {
	switch {
	case *name == "":
	case strings.HasSuffix(*name, ".go"):
		runFileTests(t, *name)
		return
	case strings.HasPrefix(*name, "./"):
		runLocalTests(t, *name)
		return
	default:
		runNonlocalTests(t, *name)
		return
	}
	runFileTests(t)
	runLocalTests(t)
	runNonlocalTests(t)
}

func doTestError(t *testing.T, name, exp string, args ...string) {
	switch len(args) {
	case 0:
		args = []string{name}
	case 1:
		if args[0] == "" {
			args = nil
		}
	}
	err := CheckArgsOutput(args, ioutil.Discard, false)
	if err == nil {
		t.Fatalf("Wanted error in %s, but none found.", name)
	}
	got := err.Error()
	if exp != got {
		t.Fatalf("Error mismatch in %s:\nExpected:\n%sGot:\n%s",
			name, exp, got)
	}
}

func TestErrors(t *testing.T) {
	// non-existent Go file
	doTestError(t, "missing.go", "open missing.go: no such file or directory")
	// local non-existent non-recursive
	doTestError(t, "./missing", "no initial packages were loaded")
	// non-local non-existent non-recursive
	doTestError(t, "missing", "no initial packages were loaded")
	// local non-existent recursive
	doTestError(t, "./missing-rec/...", "lstat ./missing-rec: no such file or directory")
	// Mixing Go files and dirs
	doTestError(t, "wrong-args", "named files must be .go files: bar", "foo.go", "bar")
}

func TestExtraArg(t *testing.T) {
	err := CheckArgsOutput([]string{"single", "--", "foo", "bar"}, ioutil.Discard, false)
	got := err.Error()
	want := "unwanted extra args: [foo bar]"
	if got != want {
		t.Fatalf("Error mismatch:\nExpected:\n%sGot:\n%s", want, got)
	}
}
<commit_msg>test: separate comment warnings with a comma<commit_after>// Copyright (c) 2015, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package interfacer

import (
	"bytes"
	"flag"
	"fmt"
	"go/ast"
	"go/build"
	"go/parser"
	"go/token"
	"io/ioutil"
	"os"
	"path/filepath"
	"reflect"
	"regexp"
	"strings"
	"testing"
)

const testdata = "testdata"

var (
	name     = flag.String("name", "", "name of the test to run")
	warnsRe  = regexp.MustCompile(`^WARN (.*)\n?$`)
	singleRe = regexp.MustCompile(`([^ ]*) can be ([^ ]*)(,|$)`)
)

func goFiles(t *testing.T, p string) []string {
	if strings.HasSuffix(p, ".go") {
		return []string{p}
	}
	dirs, err := recurse(p)
	if err != nil {
		t.Fatal(err)
	}
	var paths []string
	for _, dir := range dirs {
		files, err := ioutil.ReadDir(dir)
		if err != nil {
			t.Fatal(err)
		}
		for _, file := range files {
			if file.IsDir() {
				continue
			}
			paths = append(paths, filepath.Join(dir, file.Name()))
		}
	}
	return paths
}

type identVisitor struct {
	fset   *token.FileSet
	idents map[string]token.Position
}

func identKey(pos token.Position, name string) string {
	return fmt.Sprintf("%d %s", pos.Line, name)
}

func (v *identVisitor) Visit(n ast.Node) ast.Visitor {
	switch x := n.(type) {
	case *ast.Ident:
		pos := v.fset.Position(x.Pos())
		v.idents[identKey(pos, x.Name)] = pos
	}
	return v
}

func identPositions(fset *token.FileSet, f *ast.File) map[string]token.Position {
	v := &identVisitor{
		fset:   fset,
		idents: make(map[string]token.Position),
	}
	ast.Walk(v, f)
	return v.idents
}

func wantedWarnings(t *testing.T, p string) []Warn {
	fset := token.NewFileSet()
	var warns []Warn
	for _, path := range goFiles(t, p) {
		src, err := os.Open(path)
		if err != nil {
			t.Fatal(err)
		}
		defer src.Close()
		f, err := parser.ParseFile(fset, path, src, parser.ParseComments)
		if err != nil {
			t.Fatal(err)
		}
		identPos := identPositions(fset, f)
		for _, group := range f.Comments {
			cm := warnsRe.FindStringSubmatch(group.Text())
			if cm == nil {
				continue
			}
			for _, m := range singleRe.FindAllStringSubmatch(cm[1], -1) {
				vname, tname := m[1], m[2]
				comPos := fset.Position(group.Pos())
				warns = append(warns, Warn{
					Pos:  identPos[identKey(comPos, vname)],
					Name: vname,
					Type: tname,
				})
			}
		}
	}
	return warns
}

func doTest(t *testing.T, p string) {
	warns := wantedWarnings(t, p)
	doTestWarns(t, p, warns, p)
}

func warnsJoin(warns []Warn) string {
	var b bytes.Buffer
	for _, warn := range warns {
		fmt.Fprintln(&b, warn.String())
	}
	return b.String()
}

func doTestWarns(t *testing.T, name string, exp []Warn, args ...string) {
	got, err := CheckArgsList(args)
	if err != nil {
		t.Fatalf("Did not want error in %s:\n%v", name, err)
	}
	if !reflect.DeepEqual(exp, got) {
		t.Fatalf("Output mismatch in %s:\nExpected:\n%sGot:\n%s",
			name, warnsJoin(exp), warnsJoin(got))
	}
}

func endNewline(s string) string {
	if strings.HasSuffix(s, "\n") {
		return s
	}
	return s + "\n"
}

func doTestString(t *testing.T, name, exp string, args ...string) {
	var b bytes.Buffer
	switch len(args) {
	case 0:
		args = []string{name}
	case 1:
		if args[0] == "" {
			args = nil
		}
	}
	err := CheckArgsOutput(args, &b, true)
	if err != nil {
		t.Fatalf("Did not want error in %s:\n%v", name, err)
	}
	exp = endNewline(exp)
	got := b.String()
	if exp != got {
		t.Fatalf("Output mismatch in %s:\nExpected:\n%sGot:\n%s",
			name, exp, got)
	}
}

func inputPaths(t *testing.T, glob string) []string {
	all, err := filepath.Glob(glob)
	if err != nil {
		t.Fatal(err)
	}
	return all
}

func chdirUndo(t *testing.T, d string) func() {
	wd, err := os.Getwd()
	if err != nil {
		t.Fatal(err)
	}
	if err := os.Chdir(d); err != nil {
		t.Fatal(err)
	}
	return func() {
		if err := os.Chdir(wd); err != nil {
			t.Fatal(err)
		}
	}
}

func runFileTests(t *testing.T, paths ...string) {
	defer chdirUndo(t, "files")()
	if len(paths) == 0 {
		paths = inputPaths(t, "*")
	}
	for _, p := range paths {
		doTest(t, p)
	}
}

func runLocalTests(t *testing.T, paths ...string) {
	defer chdirUndo(t, "local")()
	if len(paths) == 0 {
		for _, p := range inputPaths(t, "*") {
			paths = append(paths, "./"+p+"/...")
		}
		// non-recursive
		paths = append(paths, "./single")
	}
	for _, p := range paths {
		doTest(t, p)
	}
	doTestString(t, "no-args", ".", "")
}

func runNonlocalTests(t *testing.T, paths ...string) {
	defer chdirUndo(t, "src")()
	if len(paths) > 0 {
		for _, p := range paths {
			doTest(t, p)
		}
		return
	}
	paths = inputPaths(t, "*")
	for _, p := range paths {
		doTest(t, p+"/...")
	}
	// local recursive
	doTest(t, "./nested/...")
	// non-recursive
	doTest(t, "single")
	// make sure we don't miss a package's imports
	doTestString(t, "grab-import", "grab-import\ngrab-import/use.go:27:15: s can be def2.Fooer")
	defer chdirUndo(t, "nested/pkg")()
	// relative paths
	doTestString(t, "rel-path", "nested/pkg\nsimple.go:12:17: rc can be Closer", "./...")
}

func TestMain(m *testing.M) {
	flag.Parse()
	if err := os.Chdir(testdata); err != nil {
		panic(err)
	}
	wd, err := os.Getwd()
	if err != nil {
		panic(err)
	}
	build.Default.GOPATH = wd
	os.Exit(m.Run())
}

func TestCheckWarnings(t *testing.T) {
	switch {
	case *name == "":
	case strings.HasSuffix(*name, ".go"):
		runFileTests(t, *name)
		return
	case strings.HasPrefix(*name, "./"):
		runLocalTests(t, *name)
		return
	default:
		runNonlocalTests(t, *name)
		return
	}
	runFileTests(t)
	runLocalTests(t)
	runNonlocalTests(t)
}

func doTestError(t *testing.T, name, exp string, args ...string) {
	switch len(args) {
	case 0:
		args = []string{name}
	case 1:
		if args[0] == "" {
			args = nil
		}
	}
	err := CheckArgsOutput(args, ioutil.Discard, false)
	if err == nil {
		t.Fatalf("Wanted error in %s, but none found.", name)
	}
	got := err.Error()
	if exp != got {
		t.Fatalf("Error mismatch in %s:\nExpected:\n%sGot:\n%s",
			name, exp, got)
	}
}

func TestErrors(t *testing.T) {
	// non-existent Go file
	doTestError(t, "missing.go", "open missing.go: no such file or directory")
	// local non-existent non-recursive
	doTestError(t, "./missing", "no initial packages were loaded")
	// non-local non-existent non-recursive
	doTestError(t, "missing", "no initial packages were loaded")
	// local non-existent recursive
	doTestError(t, "./missing-rec/...", "lstat ./missing-rec: no such file or directory")
	// Mixing Go files and dirs
	doTestError(t, "wrong-args", "named files must be .go files: bar", "foo.go", "bar")
}

func TestExtraArg(t *testing.T) {
	err := CheckArgsOutput([]string{"single", "--", "foo", "bar"}, ioutil.Discard, false)
	got := err.Error()
	want := "unwanted extra args: [foo bar]"
	if got != want {
		t.Fatalf("Error mismatch:\nExpected:\n%sGot:\n%s", want, got)
	}
}
<|endoftext|>


<commit_before>// Copyright 2013 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 ipv6

import (
	"net"
	"syscall"
	"unsafe"

	"golang.org/x/net/internal/iana"
)

type sysSockoptLen int32

var (
	ctlOpts = [ctlMax]ctlOpt{
		ctlHopLimit:   {sysIPV6_2292HOPLIMIT, 4, marshal2292HopLimit, parseHopLimit},
		ctlPacketInfo: {sysIPV6_2292PKTINFO, sysSizeofInet6Pktinfo, marshal2292PacketInfo, parsePacketInfo},
	}

	sockOpts = [ssoMax]sockOpt{
		ssoTrafficClass:       {iana.ProtocolIPv6, sysIPV6_TCLASS, ssoTypeInt},
		ssoHopLimit:           {iana.ProtocolIPv6, sysIPV6_UNICAST_HOPS, ssoTypeInt},
		ssoMulticastInterface: {iana.ProtocolIPv6, sysIPV6_MULTICAST_IF, ssoTypeInterface},
		ssoMulticastHopLimit:  {iana.ProtocolIPv6, sysIPV6_MULTICAST_HOPS, ssoTypeInt},
		ssoMulticastLoopback:  {iana.ProtocolIPv6, sysIPV6_MULTICAST_LOOP, ssoTypeInt},
		ssoReceiveHopLimit:    {iana.ProtocolIPv6, sysIPV6_2292HOPLIMIT, ssoTypeInt},
		ssoReceivePacketInfo:  {iana.ProtocolIPv6, sysIPV6_2292PKTINFO, ssoTypeInt},
		ssoChecksum:           {iana.ProtocolIPv6, sysIPV6_CHECKSUM, ssoTypeInt},
		ssoICMPFilter:         {iana.ProtocolIPv6ICMP, sysICMP6_FILTER, ssoTypeICMPFilter},
		ssoJoinGroup:          {iana.ProtocolIPv6, sysIPV6_JOIN_GROUP, ssoTypeIPMreq},
		ssoLeaveGroup:         {iana.ProtocolIPv6, sysIPV6_LEAVE_GROUP, ssoTypeIPMreq},
	}
)

func init() {
	// Seems like kern.osreldate is veiled on latest OS X. We use
	// kern.osrelease instead.
	osver, err := syscall.Sysctl("kern.osrelease")
	if err != nil {
		return
	}
	var i int
	for i = range osver {
		if osver[i] != '.' {
			continue
		}
	}
	// The IP_PKTINFO and protocol-independent multicast API were
	// introduced in OS X 10.7 (Darwin 11.0.0). But it looks like
	// those features require OS X 10.8 (Darwin 12.0.0) and above.
	// See http://support.apple.com/kb/HT1633.
	if i > 2 || i == 2 && osver[0] >= '1' && osver[1] >= '2' {
		ctlOpts[ctlTrafficClass].name = sysIPV6_TCLASS
		ctlOpts[ctlTrafficClass].length = 4
		ctlOpts[ctlTrafficClass].marshal = marshalTrafficClass
		ctlOpts[ctlTrafficClass].parse = parseTrafficClass
		ctlOpts[ctlHopLimit].name = sysIPV6_HOPLIMIT
		ctlOpts[ctlHopLimit].marshal = marshalHopLimit
		ctlOpts[ctlPacketInfo].name = sysIPV6_PKTINFO
		ctlOpts[ctlPacketInfo].marshal = marshalPacketInfo
		sockOpts[ssoReceiveTrafficClass].level = iana.ProtocolIPv6
		sockOpts[ssoReceiveTrafficClass].name = sysIPV6_RECVTCLASS
		sockOpts[ssoReceiveTrafficClass].typ = ssoTypeInt
		sockOpts[ssoReceiveHopLimit].name = sysIPV6_RECVHOPLIMIT
		sockOpts[ssoReceivePacketInfo].name = sysIPV6_RECVPKTINFO
		sockOpts[ssoReceivePathMTU].level = iana.ProtocolIPv6
		sockOpts[ssoReceivePathMTU].name = sysIPV6_RECVPATHMTU
		sockOpts[ssoReceivePathMTU].typ = ssoTypeInt
		sockOpts[ssoPathMTU].level = iana.ProtocolIPv6
		sockOpts[ssoPathMTU].name = sysIPV6_PATHMTU
		sockOpts[ssoPathMTU].typ = ssoTypeMTUInfo
		sockOpts[ssoJoinGroup].name = sysMCAST_JOIN_GROUP
		sockOpts[ssoJoinGroup].typ = ssoTypeGroupReq
		sockOpts[ssoLeaveGroup].name = sysMCAST_LEAVE_GROUP
		sockOpts[ssoLeaveGroup].typ = ssoTypeGroupReq
		sockOpts[ssoJoinSourceGroup].level = iana.ProtocolIPv6
		sockOpts[ssoJoinSourceGroup].name = sysMCAST_JOIN_SOURCE_GROUP
		sockOpts[ssoJoinSourceGroup].typ = ssoTypeGroupSourceReq
		sockOpts[ssoLeaveSourceGroup].level = iana.ProtocolIPv6
		sockOpts[ssoLeaveSourceGroup].name = sysMCAST_LEAVE_SOURCE_GROUP
		sockOpts[ssoLeaveSourceGroup].typ = ssoTypeGroupSourceReq
		sockOpts[ssoBlockSourceGroup].level = iana.ProtocolIPv6
		sockOpts[ssoBlockSourceGroup].name = sysMCAST_BLOCK_SOURCE
		sockOpts[ssoBlockSourceGroup].typ = ssoTypeGroupSourceReq
		sockOpts[ssoUnblockSourceGroup].level = iana.ProtocolIPv6
		sockOpts[ssoUnblockSourceGroup].name = sysMCAST_UNBLOCK_SOURCE
		sockOpts[ssoUnblockSourceGroup].typ = ssoTypeGroupSourceReq
	}
}

func (sa *sysSockaddrInet6) setSockaddr(ip net.IP, i int) {
	sa.Len = sysSizeofSockaddrInet6
	sa.Family = syscall.AF_INET6
	copy(sa.Addr[:], ip)
	sa.Scope_id = uint32(i)
}

func (pi *sysInet6Pktinfo) setIfindex(i int) {
	pi.Ifindex = uint32(i)
}

func (mreq *sysIPv6Mreq) setIfindex(i int) {
	mreq.Interface = uint32(i)
}

func (gr *sysGroupReq) setGroup(grp net.IP) {
	sa := (*sysSockaddrInet6)(unsafe.Pointer(&gr.Pad_cgo_0[0]))
	sa.Len = sysSizeofSockaddrInet6
	sa.Family = syscall.AF_INET6
	copy(sa.Addr[:], grp)
}

func (gsr *sysGroupSourceReq) setSourceGroup(grp, src net.IP) {
	sa := (*sysSockaddrInet6)(unsafe.Pointer(&gsr.Pad_cgo_0[0]))
	sa.Len = sysSizeofSockaddrInet6
	sa.Family = syscall.AF_INET6
	copy(sa.Addr[:], grp)
	sa = (*sysSockaddrInet6)(unsafe.Pointer(&gsr.Pad_cgo_1[0]))
	sa.Len = sysSizeofSockaddrInet6
	sa.Family = syscall.AF_INET6
	copy(sa.Addr[:], src)
}
<commit_msg>x/net/ipv6: fix build on older darwin kernels<commit_after>// Copyright 2013 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 ipv6

import (
	"net"
	"syscall"
	"unsafe"

	"golang.org/x/net/internal/iana"
)

type sysSockoptLen int32

var (
	ctlOpts = [ctlMax]ctlOpt{
		ctlHopLimit:   {sysIPV6_2292HOPLIMIT, 4, marshal2292HopLimit, parseHopLimit},
		ctlPacketInfo: {sysIPV6_2292PKTINFO, sysSizeofInet6Pktinfo, marshal2292PacketInfo, parsePacketInfo},
	}

	sockOpts = [ssoMax]sockOpt{
		ssoHopLimit:           {iana.ProtocolIPv6, sysIPV6_UNICAST_HOPS, ssoTypeInt},
		ssoMulticastInterface: {iana.ProtocolIPv6, sysIPV6_MULTICAST_IF, ssoTypeInterface},
		ssoMulticastHopLimit:  {iana.ProtocolIPv6, sysIPV6_MULTICAST_HOPS, ssoTypeInt},
		ssoMulticastLoopback:  {iana.ProtocolIPv6, sysIPV6_MULTICAST_LOOP, ssoTypeInt},
		ssoReceiveHopLimit:    {iana.ProtocolIPv6, sysIPV6_2292HOPLIMIT, ssoTypeInt},
		ssoReceivePacketInfo:  {iana.ProtocolIPv6, sysIPV6_2292PKTINFO, ssoTypeInt},
		ssoChecksum:           {iana.ProtocolIPv6, sysIPV6_CHECKSUM, ssoTypeInt},
		ssoICMPFilter:         {iana.ProtocolIPv6ICMP, sysICMP6_FILTER, ssoTypeICMPFilter},
		ssoJoinGroup:          {iana.ProtocolIPv6, sysIPV6_JOIN_GROUP, ssoTypeIPMreq},
		ssoLeaveGroup:         {iana.ProtocolIPv6, sysIPV6_LEAVE_GROUP, ssoTypeIPMreq},
	}
)

func init() {
	// Seems like kern.osreldate is veiled on latest OS X. We use
	// kern.osrelease instead.
	osver, err := syscall.Sysctl("kern.osrelease")
	if err != nil {
		return
	}
	var i int
	for i = range osver {
		if osver[i] == '.' {
			break
		}
	}
	// The IP_PKTINFO and protocol-independent multicast API were
	// introduced in OS X 10.7 (Darwin 11.0.0). But it looks like
	// those features require OS X 10.8 (Darwin 12.0.0) and above.
	// See http://support.apple.com/kb/HT1633.
	if i > 2 || i == 2 && osver[0] >= '1' && osver[1] >= '2' {
		ctlOpts[ctlTrafficClass].name = sysIPV6_TCLASS
		ctlOpts[ctlTrafficClass].length = 4
		ctlOpts[ctlTrafficClass].marshal = marshalTrafficClass
		ctlOpts[ctlTrafficClass].parse = parseTrafficClass
		ctlOpts[ctlHopLimit].name = sysIPV6_HOPLIMIT
		ctlOpts[ctlHopLimit].marshal = marshalHopLimit
		ctlOpts[ctlPacketInfo].name = sysIPV6_PKTINFO
		ctlOpts[ctlPacketInfo].marshal = marshalPacketInfo
		sockOpts[ssoTrafficClass].level = iana.ProtocolIPv6
		sockOpts[ssoTrafficClass].name = sysIPV6_TCLASS
		sockOpts[ssoTrafficClass].typ = ssoTypeInt
		sockOpts[ssoReceiveTrafficClass].level = iana.ProtocolIPv6
		sockOpts[ssoReceiveTrafficClass].name = sysIPV6_RECVTCLASS
		sockOpts[ssoReceiveTrafficClass].typ = ssoTypeInt
		sockOpts[ssoReceiveHopLimit].name = sysIPV6_RECVHOPLIMIT
		sockOpts[ssoReceivePacketInfo].name = sysIPV6_RECVPKTINFO
		sockOpts[ssoReceivePathMTU].level = iana.ProtocolIPv6
		sockOpts[ssoReceivePathMTU].name = sysIPV6_RECVPATHMTU
		sockOpts[ssoReceivePathMTU].typ = ssoTypeInt
		sockOpts[ssoPathMTU].level = iana.ProtocolIPv6
		sockOpts[ssoPathMTU].name = sysIPV6_PATHMTU
		sockOpts[ssoPathMTU].typ = ssoTypeMTUInfo
		sockOpts[ssoJoinGroup].name = sysMCAST_JOIN_GROUP
		sockOpts[ssoJoinGroup].typ = ssoTypeGroupReq
		sockOpts[ssoLeaveGroup].name = sysMCAST_LEAVE_GROUP
		sockOpts[ssoLeaveGroup].typ = ssoTypeGroupReq
		sockOpts[ssoJoinSourceGroup].level = iana.ProtocolIPv6
		sockOpts[ssoJoinSourceGroup].name = sysMCAST_JOIN_SOURCE_GROUP
		sockOpts[ssoJoinSourceGroup].typ = ssoTypeGroupSourceReq
		sockOpts[ssoLeaveSourceGroup].level = iana.ProtocolIPv6
		sockOpts[ssoLeaveSourceGroup].name = sysMCAST_LEAVE_SOURCE_GROUP
		sockOpts[ssoLeaveSourceGroup].typ = ssoTypeGroupSourceReq
		sockOpts[ssoBlockSourceGroup].level = iana.ProtocolIPv6
		sockOpts[ssoBlockSourceGroup].name = sysMCAST_BLOCK_SOURCE
		sockOpts[ssoBlockSourceGroup].typ = ssoTypeGroupSourceReq
		sockOpts[ssoUnblockSourceGroup].level = iana.ProtocolIPv6
		sockOpts[ssoUnblockSourceGroup].name = sysMCAST_UNBLOCK_SOURCE
		sockOpts[ssoUnblockSourceGroup].typ = ssoTypeGroupSourceReq
	}
}

func (sa *sysSockaddrInet6) setSockaddr(ip net.IP, i int) {
	sa.Len = sysSizeofSockaddrInet6
	sa.Family = syscall.AF_INET6
	copy(sa.Addr[:], ip)
	sa.Scope_id = uint32(i)
}

func (pi *sysInet6Pktinfo) setIfindex(i int) {
	pi.Ifindex = uint32(i)
}

func (mreq *sysIPv6Mreq) setIfindex(i int) {
	mreq.Interface = uint32(i)
}

func (gr *sysGroupReq) setGroup(grp net.IP) {
	sa := (*sysSockaddrInet6)(unsafe.Pointer(&gr.Pad_cgo_0[0]))
	sa.Len = sysSizeofSockaddrInet6
	sa.Family = syscall.AF_INET6
	copy(sa.Addr[:], grp)
}

func (gsr *sysGroupSourceReq) setSourceGroup(grp, src net.IP) {
	sa := (*sysSockaddrInet6)(unsafe.Pointer(&gsr.Pad_cgo_0[0]))
	sa.Len = sysSizeofSockaddrInet6
	sa.Family = syscall.AF_INET6
	copy(sa.Addr[:], grp)
	sa = (*sysSockaddrInet6)(unsafe.Pointer(&gsr.Pad_cgo_1[0]))
	sa.Len = sysSizeofSockaddrInet6
	sa.Family = syscall.AF_INET6
	copy(sa.Addr[:], src)
}
<|endoftext|>


<commit_before>package main

import (
	cwe "github.com/aws/aws-sdk-go/service/cloudwatchevents"
)

type Rules struct {
	Rules []Rule
}

type Rule struct {
	Description        string   `yaml:"description"`
	EventPattern       string   `yaml:"event_pattern"`
	Name               string   `yaml:"name"`
	RoleArn            string   `yaml:"role_arn"`
	ScheduleExpression string   `yaml:"schedule_expression"`
	State              string   `yaml:"state"`
	Targets            []Target `yaml:"targets"`
	ActualRule         cwe.Rule
	NeedUpdate         bool
	NeedDelete         bool
}

type Target struct {
	Arn          string `yaml:"arn"`
	Id           string `yaml:"id"`
	Input        string `yaml:"input"`
	InputPath    string `yaml:"input_path"`
	ActualTarget cwe.Target
	NeedUpdate   bool
	NeedDelete   bool
}

type LambdaPolicy struct {
	Version   string             `json:"Version"`
	Id        string             `json:"Id"`
	Statement *[]PolicyStatement `json:"Statement"`
}

type PolicyStatement struct {
	Resource    string           `json:"Resource"`
	Condition   *PolicyCondition `json:"Condition"`
	StatementId string           `json:"Sid"`
	Effect      string           `json:"Effect"`
	Principal   *PolicyPrincipal `json:"Principal"`
	Action      string           `json:"Action"`
}

type PolicyCondition struct {
	ArnLike *PolicyArnLike `json:"ArnLike"`
}

type PolicyArnLike struct {
	AwsSourceArn string `json:"AWS:SourceArn"`
}

type PolicyPrincipal struct {
	Service string `json:"Service"`
}
<commit_msg>Add comment to structs<commit_after>package main

import (
	cwe "github.com/aws/aws-sdk-go/service/cloudwatchevents"
)

// struct for store unmarshalized configuration yaml
type Rules struct {
	Rules []Rule
}

// struct for expression CloudWatch Events Rule
type Rule struct {
	Description        string   `yaml:"description"`
	EventPattern       string   `yaml:"event_pattern"`
	Name               string   `yaml:"name"`
	RoleArn            string   `yaml:"role_arn"`
	ScheduleExpression string   `yaml:"schedule_expression"`
	State              string   `yaml:"state"`
	Targets            []Target `yaml:"targets"`
	ActualRule         cwe.Rule
	NeedUpdate         bool
	NeedDelete         bool
}

// struct for expression CloudWatch Events Target
type Target struct {
	Arn          string `yaml:"arn"`
	Id           string `yaml:"id"`
	Input        string `yaml:"input"`
	InputPath    string `yaml:"input_path"`
	ActualTarget cwe.Target
	NeedUpdate   bool
	NeedDelete   bool
}

// struct for JSON that return from Lambda.GetPolicy
type LambdaPolicy struct {
	Version   string             `json:"Version"`
	Id        string             `json:"Id"`
	Statement *[]PolicyStatement `json:"Statement"`
}

// part of the LambdaPolicy
type PolicyStatement struct {
	Resource    string           `json:"Resource"`
	Condition   *PolicyCondition `json:"Condition"`
	StatementId string           `json:"Sid"`
	Effect      string           `json:"Effect"`
	Principal   *PolicyPrincipal `json:"Principal"`
	Action      string           `json:"Action"`
}

// part of the LambdaPolicy
type PolicyCondition struct {
	ArnLike *PolicyArnLike `json:"ArnLike"`
}

// part of the LambdaPolicy
type PolicyArnLike struct {
	AwsSourceArn string `json:"AWS:SourceArn"`
}

// part of the LambdaPolicy
type PolicyPrincipal struct {
	Service string `json:"Service"`
}
<|endoftext|>


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

package internal

import (
	"flag"

	"cloud.google.com/go/spanner"
	"golang.org/x/net/context"
	"google.golang.org/api/option"

	"go.chromium.org/luci/common/errors"
	"go.chromium.org/luci/server"
	"go.chromium.org/luci/server/auth"
	"go.chromium.org/luci/server/limiter"
	"go.chromium.org/luci/server/module"
	"go.chromium.org/luci/server/secrets"

	"go.chromium.org/luci/resultdb/internal/span"
)

const (
	// accessGroup is a CIA group that can access ResultDB.
	// TODO(crbug.com/1013316): remove in favor of realms.
	accessGroup = "luci-resultdb-access"
)

// Main runs a service.
//
// Registers -spanner-database flag and initializes a Spanner client.
func Main(init func(srv *server.Server) error) {
	modules := []module.Module{
		limiter.NewModuleFromFlags(),
		secrets.NewModuleFromFlags(),
	}

	spannerDB := flag.String("spanner-database", "", "Name of the spanner database to connect to")

	server.Main(nil, modules, func(srv *server.Server) error {
		var err error
		if srv.Context, err = withProdSpannerClient(srv.Context, *spannerDB); err != nil {
			return err
		}

		return init(srv)
	})
}

// TODO(vadimsh): Move to a module.Module.
func withProdSpannerClient(ctx context.Context, dbFlag string) (context.Context, error) {
	if dbFlag == "" {
		return ctx, errors.Reason("-spanner-database flag is required").Err()
	}

	// A token source with Cloud scope.
	ts, err := auth.GetTokenSource(ctx, auth.AsSelf, auth.WithScopes(auth.CloudOAuthScopes...))
	if err != nil {
		return ctx, errors.Annotate(err, "failed to get the token source").Err()
	}

	// Init a Spanner client.
	spannerClient, err := spanner.NewClient(ctx, dbFlag, option.WithTokenSource(ts))
	if err != nil {
		return ctx, err
	}

	// Run a "ping" query to verify the database exists and we can access it
	// before we actually serve any requests. On misconfiguration better to fail
	// early.
	iter := spannerClient.Single().Query(ctx, spanner.NewStatement("SELECT 1;"))
	if err := iter.Do(func(*spanner.Row) error { return nil }); err != nil {
		return ctx, errors.Annotate(err, "failed to ping Spanner").Err()
	}

	return span.WithClient(ctx, spannerClient), nil
}
<commit_msg>[resultdb] Enable Spanner session handle tracking<commit_after>// Copyright 2019 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package internal

import (
	"flag"

	"cloud.google.com/go/spanner"
	"golang.org/x/net/context"
	"google.golang.org/api/option"

	"go.chromium.org/luci/common/errors"
	"go.chromium.org/luci/server"
	"go.chromium.org/luci/server/auth"
	"go.chromium.org/luci/server/limiter"
	"go.chromium.org/luci/server/module"
	"go.chromium.org/luci/server/secrets"

	"go.chromium.org/luci/resultdb/internal/span"
)

const (
	// accessGroup is a CIA group that can access ResultDB.
	// TODO(crbug.com/1013316): remove in favor of realms.
	accessGroup = "luci-resultdb-access"
)

// Main runs a service.
//
// Registers -spanner-database flag and initializes a Spanner client.
func Main(init func(srv *server.Server) error) {
	modules := []module.Module{
		limiter.NewModuleFromFlags(),
		secrets.NewModuleFromFlags(),
	}

	spannerDB := flag.String("spanner-database", "", "Name of the spanner database to connect to")
	prodMode := flag.Bool("resultdb-prod", false, "Run ResultDB in production mode")

	server.Main(nil, modules, func(srv *server.Server) error {
		var err error
		if srv.Context, err = withProdSpannerClient(srv.Context, *spannerDB, !*prodMode); err != nil {
			return err
		}

		return init(srv)
	})
}

// TODO(vadimsh): Move to a module.Module.
func withProdSpannerClient(ctx context.Context, dbFlag string, trackSessionHandles bool) (context.Context, error) {
	if dbFlag == "" {
		return ctx, errors.Reason("-spanner-database flag is required").Err()
	}

	// A token source with Cloud scope.
	ts, err := auth.GetTokenSource(ctx, auth.AsSelf, auth.WithScopes(auth.CloudOAuthScopes...))
	if err != nil {
		return ctx, errors.Annotate(err, "failed to get the token source").Err()
	}

	// Init a Spanner client.
	cfg := spanner.ClientConfig{
		SessionPoolConfig: spanner.SessionPoolConfig{
			TrackSessionHandles: trackSessionHandles,
		},
	}
	spannerClient, err := spanner.NewClientWithConfig(ctx, dbFlag, cfg, option.WithTokenSource(ts))
	if err != nil {
		return ctx, err
	}

	// Run a "ping" query to verify the database exists and we can access it
	// before we actually serve any requests. On misconfiguration better to fail
	// early.
	iter := spannerClient.Single().Query(ctx, spanner.NewStatement("SELECT 1;"))
	if err := iter.Do(func(*spanner.Row) error { return nil }); err != nil {
		return ctx, errors.Annotate(err, "failed to ping Spanner").Err()
	}

	return span.WithClient(ctx, spannerClient), nil
}
<|endoftext|>


<commit_before>package hcsshim

import (
	"fmt"
	"syscall"
	"unsafe"

	"github.com/Sirupsen/logrus"
)

func GetLayerMountPath(info DriverInfo, id string) (string, error) {
	title := "hcsshim::GetLayerMountPath "
	logrus.Debugf(title+"Flavour %s ID %s", info.Flavour, id)

	// Load the DLL and get a handle to the procedure we need
	dll, proc, err := loadAndFind(procGetLayerMountPath)
	if dll != nil {
		defer dll.Release()
	}
	if err != nil {
		return "", err
	}

	// Convert id to uint16 pointer for calling the procedure
	idp, err := syscall.UTF16PtrFromString(id)
	if err != nil {
		err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err)
		logrus.Error(err)
		return "", err
	}

	// Convert info to API calling convention
	infop, err := convertDriverInfo(info)
	if err != nil {
		err = fmt.Errorf(title+" - Failed conversion info struct %s", err)
		logrus.Error(err)
		return "", err
	}

	var mountPathLength uint64
	mountPathLength = 0

	// Call the procedure itself.
	logrus.Debugf("Calling proc")
	r1, _, _ := proc.Call(
		uintptr(unsafe.Pointer(&infop)),
		uintptr(unsafe.Pointer(idp)),
		uintptr(unsafe.Pointer(&mountPathLength)),
		uintptr(unsafe.Pointer(nil)))

	use(unsafe.Pointer(&mountPathLength))
	use(unsafe.Pointer(&infop))
	use(unsafe.Pointer(idp))

	if r1 != 0 {
		err = fmt.Errorf(title+" - First Win32 API call returned error r1=%d err=%s id=%s flavour=%d",
			r1, syscall.Errno(r1), id, info.Flavour)
		logrus.Error(err)
		return "", err
	}

	// Allocate a mount path of the returned length.
	if mountPathLength == 0 {
		return "", nil
	}
	mountPathp := make([]uint16, mountPathLength)
	mountPathp[0] = 0

	// Call the procedure again
	r1, _, _ = proc.Call(
		uintptr(unsafe.Pointer(&infop)),
		uintptr(unsafe.Pointer(idp)),
		uintptr(unsafe.Pointer(&mountPathLength)),
		uintptr(unsafe.Pointer(&mountPathp[0])))

	if r1 != 0 {
		err = fmt.Errorf(title+" - Second Win32 API call returned error r1=%d errno=%d id=%s flavour=%d",
			r1, syscall.Errno(r1), id, info.Flavour)
		logrus.Error(err)
		return "", err
	}

	path := syscall.UTF16ToString(mountPathp[0:])
	logrus.Debugf(title+" - succeeded id=%s flavour=%d path=%s", id, info.Flavour, path)
	return path, nil
}
<commit_msg>Move use to avoid GC problem in GLMP<commit_after>package hcsshim

import (
	"fmt"
	"syscall"
	"unsafe"

	"github.com/Sirupsen/logrus"
)

func GetLayerMountPath(info DriverInfo, id string) (string, error) {
	title := "hcsshim::GetLayerMountPath "
	logrus.Debugf(title+"Flavour %s ID %s", info.Flavour, id)

	// Load the DLL and get a handle to the procedure we need
	dll, proc, err := loadAndFind(procGetLayerMountPath)
	if dll != nil {
		defer dll.Release()
	}
	if err != nil {
		return "", err
	}

	// Convert id to uint16 pointer for calling the procedure
	idp, err := syscall.UTF16PtrFromString(id)
	if err != nil {
		err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err)
		logrus.Error(err)
		return "", err
	}

	// Convert info to API calling convention
	infop, err := convertDriverInfo(info)
	if err != nil {
		err = fmt.Errorf(title+" - Failed conversion info struct %s", err)
		logrus.Error(err)
		return "", err
	}

	var mountPathLength uint64
	mountPathLength = 0

	// Call the procedure itself.
	logrus.Debugf("Calling proc (1)")
	r1, _, _ := proc.Call(
		uintptr(unsafe.Pointer(&infop)),
		uintptr(unsafe.Pointer(idp)),
		uintptr(unsafe.Pointer(&mountPathLength)),
		uintptr(unsafe.Pointer(nil)))

	if r1 != 0 {
		err = fmt.Errorf(title+" - First Win32 API call returned error r1=%d err=%s id=%s flavour=%d",
			r1, syscall.Errno(r1), id, info.Flavour)
		logrus.Error(err)
		return "", err
	}

	// Allocate a mount path of the returned length.
	if mountPathLength == 0 {
		return "", nil
	}
	mountPathp := make([]uint16, mountPathLength)
	mountPathp[0] = 0

	// Call the procedure again
	logrus.Debugf("Calling proc (2)")
	r1, _, _ = proc.Call(
		uintptr(unsafe.Pointer(&infop)),
		uintptr(unsafe.Pointer(idp)),
		uintptr(unsafe.Pointer(&mountPathLength)),
		uintptr(unsafe.Pointer(&mountPathp[0])))

	use(unsafe.Pointer(&mountPathLength))
	use(unsafe.Pointer(&infop))
	use(unsafe.Pointer(idp))

	if r1 != 0 {
		err = fmt.Errorf(title+" - Second Win32 API call returned error r1=%d errno=%d id=%s flavour=%d",
			r1, syscall.Errno(r1), id, info.Flavour)
		logrus.Error(err)
		return "", err
	}

	path := syscall.UTF16ToString(mountPathp[0:])
	logrus.Debugf(title+" - succeeded id=%s flavour=%d path=%s", id, info.Flavour, path)
	return path, nil
}
<|endoftext|>


<commit_before>package testing

import (
	"fmt"
	"time"
	"errors"
	"reflect"
	"io/ioutil"
	"encoding/json"
	//
	"github.com/fatih/color"
	//
	"github.com/golangdaddy/tarantula/httpclient"
	"github.com/golangdaddy/tarantula/router/common"
	"github.com/golangdaddy/tarantula/router/testing/manifest"
)

func Execute(m *manifest.Manifest, endpoints ...*manifest.Endpoint) error {

	app := &App{
		GetHandlers(m.Spec),
		m,
		httpclient.NewClient(),
	}

	for _, e := range endpoints {

		time.Sleep(time.Duration(int64(time.Millisecond) * 1000 * int64(e.DelayAfter)))

		err := app.startExecution(e)
		if err != nil {
			return err
		}

		time.Sleep(time.Duration(int64(time.Millisecond) * 1000 * int64(e.DelayAfter)))

	}

	m.AddEndpoints(endpoints...)

	b, err := json.Marshal(m)
	if err != nil {
		panic(err)
	}

	err = ioutil.WriteFile("manifest.latest.json", b, 0666)
	if err != nil {
		panic(err)
	}

	return nil
}

func (app *App) startExecution(endpoint *manifest.Endpoint) error {

	pathArgs := map[string]interface{}{}
	for k, v := range endpoint.PathArgs {
		x := app.Manifest.Variables[v]
		if x == nil {
			return errors.New("PATH PARAM REFERENCE NOT FOUND: "+v)
		}
		pathArgs[k] = x
	}

	bodyArgs := map[string]interface{}{}
	for k, v := range endpoint.BodyArgs {
		x := app.Manifest.Variables[v]
		if x == nil {
			return errors.New("BODY PARAM REFERENCE NOT FOUND: "+v)
		}
		bodyArgs[k] = x
	}
	for k, v := range endpoint.BodyLiterals {
		bodyArgs[k] = v
	}

	endpoint.Spec = app.GetHandler(
		endpoint.Method,
		endpoint.Endpoint,
		pathArgs,
		bodyArgs,
	)
	if endpoint.Spec == nil {
		fmt.Println(endpoint)
		return errors.New("FAILED TO EXECUTE NIL SPEC")
	}

	obj, err := app.execute(endpoint.Spec)
	if err != nil {
		return err
	}

	if obj == nil {
		return nil
	}

	if object, ok := obj.(map[string]interface{}); !ok {
		if object, ok := obj.([]interface{}); !ok {
			return errors.New("TYPE ASSERTION FAILED: "+reflect.TypeOf(obj).String())
		} else {
			app.Manifest.Variables["array"] = object
		}
	} else {
		for used, as := range endpoint.Use {
			value, ok := object[used].(string)
			if !ok {
				fmt.Println(object)
				panic("TYPE ASSERT FAILED")
			}
			fmt.Println("USING VARIABLE " + used + " AS " + as)
			app.Manifest.Variables[as] = value
		}
	}

	return nil
}

func (app *App) execute(spec *common.HandlerSpec) (interface{}, error) {

	var dst interface{}
	b, err := json.Marshal(spec)
	color.Blue("TESTING SPEC: "+string(b))

	responseSchema, _ := json.Marshal(spec.ResponseSchema)
	switch string(responseSchema[0]) {

		case "{":

			obj := map[string]interface{}{}
			dst = &obj

		case "[":

			array := []interface{}{}
			dst = &array

		default:

	}

	authHeader := map[string]string{
		"Authorization": "Bearer "+app.Manifest.Token,
	}

	switch spec.Method {

		case "GET":

			_, err = app.Get(app.Manifest.Host + spec.MockEndpoint, dst, authHeader)

		case "POST":

			_, err = app.Post(app.Manifest.Host + spec.MockEndpoint, spec.MockPayload, dst, authHeader)

		case "DELETE":

			_, err = app.Delete(app.Manifest.Host + spec.MockEndpoint, nil, authHeader)

	}
	if err != nil {
		return nil, err
	}

	if dst == nil {
		return nil, nil
	}

	b, _ = json.Marshal(dst)
	color.Green(string(b))

	output, ok := dst.(*[]interface{})
	if ok {
		return *output, nil
	}

	return *((dst).(*map[string]interface{})), nil
}
<commit_msg>add post payload log<commit_after>package testing

import (
	"fmt"
	"time"
	"errors"
	"reflect"
	"io/ioutil"
	"encoding/json"
	//
	"github.com/fatih/color"
	//
	"github.com/golangdaddy/tarantula/httpclient"
	"github.com/golangdaddy/tarantula/router/common"
	"github.com/golangdaddy/tarantula/router/testing/manifest"
)

func Execute(m *manifest.Manifest, endpoints ...*manifest.Endpoint) error {

	app := &App{
		GetHandlers(m.Spec),
		m,
		httpclient.NewClient(),
	}

	for _, e := range endpoints {

		time.Sleep(time.Duration(int64(time.Millisecond) * 1000 * int64(e.DelayAfter)))

		err := app.startExecution(e)
		if err != nil {
			return err
		}

		time.Sleep(time.Duration(int64(time.Millisecond) * 1000 * int64(e.DelayAfter)))

	}

	m.AddEndpoints(endpoints...)

	b, err := json.Marshal(m)
	if err != nil {
		panic(err)
	}

	err = ioutil.WriteFile("manifest.latest.json", b, 0666)
	if err != nil {
		panic(err)
	}

	return nil
}

func (app *App) startExecution(endpoint *manifest.Endpoint) error {

	pathArgs := map[string]interface{}{}
	for k, v := range endpoint.PathArgs {
		x := app.Manifest.Variables[v]
		if x == nil {
			return errors.New("PATH PARAM REFERENCE NOT FOUND: "+v)
		}
		pathArgs[k] = x
	}

	bodyArgs := map[string]interface{}{}
	for k, v := range endpoint.BodyArgs {
		x := app.Manifest.Variables[v]
		if x == nil {
			return errors.New("BODY PARAM REFERENCE NOT FOUND: "+v)
		}
		bodyArgs[k] = x
	}
	for k, v := range endpoint.BodyLiterals {
		bodyArgs[k] = v
	}

	endpoint.Spec = app.GetHandler(
		endpoint.Method,
		endpoint.Endpoint,
		pathArgs,
		bodyArgs,
	)
	if endpoint.Spec == nil {
		fmt.Println(endpoint)
		return errors.New("FAILED TO EXECUTE NIL SPEC")
	}

	obj, err := app.execute(endpoint.Spec)
	if err != nil {
		return err
	}

	if obj == nil {
		return nil
	}

	if object, ok := obj.(map[string]interface{}); !ok {
		if object, ok := obj.([]interface{}); !ok {
			return errors.New("TYPE ASSERTION FAILED: "+reflect.TypeOf(obj).String())
		} else {
			app.Manifest.Variables["array"] = object
		}
	} else {
		for used, as := range endpoint.Use {
			value, ok := object[used].(string)
			if !ok {
				fmt.Println(object)
				panic("TYPE ASSERT FAILED")
			}
			fmt.Println("USING VARIABLE " + used + " AS " + as)
			app.Manifest.Variables[as] = value
		}
	}

	return nil
}

func (app *App) execute(spec *common.HandlerSpec) (interface{}, error) {

	var dst interface{}
	b, err := json.Marshal(spec)
	color.Blue("TESTING SPEC: "+string(b))

	responseSchema, _ := json.Marshal(spec.ResponseSchema)
	switch string(responseSchema[0]) {

		case "{":

			obj := map[string]interface{}{}
			dst = &obj

		case "[":

			array := []interface{}{}
			dst = &array

		default:

	}

	authHeader := map[string]string{
		"Authorization": "Bearer "+app.Manifest.Token,
	}

	switch spec.Method {

		case "GET":

			_, err = app.Get(app.Manifest.Host + spec.MockEndpoint, dst, authHeader)

		case "POST":

			b, _ := json.Marshal(spec.MockPayload)
			color.Yellow(string(b))

			_, err = app.Post(app.Manifest.Host + spec.MockEndpoint, spec.MockPayload, dst, authHeader)

		case "DELETE":

			_, err = app.Delete(app.Manifest.Host + spec.MockEndpoint, nil, authHeader)

	}
	if err != nil {
		return nil, err
	}

	if dst == nil {
		return nil, nil
	}

	b, _ = json.Marshal(dst)
	color.Green(string(b))

	output, ok := dst.(*[]interface{})
	if ok {
		return *output, nil
	}

	return *((dst).(*map[string]interface{})), nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2012-2016 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.

package antlr

import (
	"bytes"
	"errors"
	"fmt"
	"hash/fnv"
	"sort"
	"strconv"
	"strings"
)

func intMin(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func intMax(a, b int) int {
	if a > b {
		return a
	}
	return b
}

// A simple integer stack

type IntStack []int

var ErrEmptyStack = errors.New("Stack is empty")

func (s *IntStack) Pop() (int, error) {
	l := len(*s) - 1
	if l < 0 {
		return 0, ErrEmptyStack
	}
	v := (*s)[l]
	*s = (*s)[0:l]
	return v, nil
}

func (s *IntStack) Push(e int) {
	*s = append(*s, e)
}

type Set struct {
	data             map[int][]interface{}
	hashcodeFunction func(interface{}) int
	equalsFunction   func(interface{}, interface{}) bool
}

func NewSet(
	hashcodeFunction func(interface{}) int,
	equalsFunction func(interface{}, interface{}) bool) *Set {

	s := new(Set)

	s.data = make(map[int][]interface{})

	if hashcodeFunction != nil {
		s.hashcodeFunction = hashcodeFunction
	} else {
		s.hashcodeFunction = standardHashFunction
	}

	if equalsFunction == nil {
		s.equalsFunction = standardEqualsFunction
	} else {
		s.equalsFunction = equalsFunction
	}

	return s
}

func standardEqualsFunction(a interface{}, b interface{}) bool {

	ac, oka := a.(Comparable)
	bc, okb := b.(Comparable)

	if !oka || !okb {
		panic("Not Comparable")
	}

	return ac.equals(bc)
}

func standardHashFunction(a interface{}) int {
	if h, ok := a.(HashCoder); ok {
		return h.HashCode()
	}

	if h, ok := a.(Hasher); ok {
		s := h.Hash()
		ha := fnv.New32a()
		ha.Write([]byte((s)))
		return int(ha.Sum32())
	}

	panic("Not Hasher")
}

type Hasher interface {
	Hash() string
}

type HashCoder interface {
	HashCode() int
}

func (s *Set) length() int {
	return len(s.data)
}

func (s *Set) add(value interface{}) interface{} {

	key := s.hashcodeFunction(value)

	values := s.data[key]

	if s.data[key] != nil {
		for i := 0; i < len(values); i++ {
			if s.equalsFunction(value, values[i]) {
				return values[i]
			}
		}

		s.data[key] = append(s.data[key], value)
		return value
	}

	v := make([]interface{}, 1, 10)
	v[0] = value
	s.data[key] = v

	return value
}

func (s *Set) contains(value interface{}) bool {

	key := s.hashcodeFunction(value)

	values := s.data[key]

	if s.data[key] != nil {
		for i := 0; i < len(values); i++ {
			if s.equalsFunction(value, values[i]) {
				return true
			}
		}
	}
	return false
}

func (s *Set) values() []interface{} {
	var l []interface{}

	for _, v := range s.data {
		l = append(l, v...)
	}

	return l
}

func (s *Set) String() string {
	r := ""

	for _, av := range s.data {
		for _, v := range av {
			r += fmt.Sprint(v)
		}
	}

	return r
}

type BitSet struct {
	data map[int]bool
}

func NewBitSet() *BitSet {
	b := new(BitSet)
	b.data = make(map[int]bool)
	return b
}

func (b *BitSet) add(value int) {
	b.data[value] = true
}

func (b *BitSet) clear(index int) {
	delete(b.data, index)
}

func (b *BitSet) or(set *BitSet) {
	for k := range set.data {
		b.add(k)
	}
}

func (b *BitSet) remove(value int) {
	delete(b.data, value)
}

func (b *BitSet) contains(value int) bool {
	return b.data[value]
}

func (b *BitSet) values() []int {
	ks := make([]int, len(b.data))
	i := 0
	for k := range b.data {
		ks[i] = k
		i++
	}
	sort.Ints(ks)
	return ks
}

func (b *BitSet) minValue() int {
	min := 2147483647

	for k := range b.data {
		if k < min {
			min = k
		}
	}

	return min
}

func (b *BitSet) equals(other interface{}) bool {
	otherBitSet, ok := other.(*BitSet)
	if !ok {
		return false
	}

	if len(b.data) != len(otherBitSet.data) {
		return false
	}

	for k, v := range b.data {
		if otherBitSet.data[k] != v {
			return false
		}
	}

	return true
}

func (b *BitSet) length() int {
	return len(b.data)
}

func (b *BitSet) String() string {
	vals := b.values()
	valsS := make([]string, len(vals))

	for i, val := range vals {
		valsS[i] = strconv.Itoa(val)
	}
	return "{" + strings.Join(valsS, ", ") + "}"
}

type AltDict struct {
	data map[string]interface{}
}

func NewAltDict() *AltDict {
	d := new(AltDict)
	d.data = make(map[string]interface{})
	return d
}

func (a *AltDict) Get(key string) interface{} {
	key = "k-" + key
	return a.data[key]
}

func (a *AltDict) put(key string, value interface{}) {
	key = "k-" + key
	a.data[key] = value
}

func (a *AltDict) values() []interface{} {
	vs := make([]interface{}, len(a.data))
	i := 0
	for _, v := range a.data {
		vs[i] = v
		i++
	}
	return vs
}

type DoubleDict struct {
	data map[string]map[string]interface{}
}

func NewDoubleDict() *DoubleDict {
	dd := new(DoubleDict)
	dd.data = make(map[string]map[string]interface{})
	return dd
}

func (d *DoubleDict) Get(a string, b string) interface{} {
	data := d.data[a]

	if data == nil {
		return nil
	}

	return data[b]
}

func (d *DoubleDict) set(a, b string, o interface{}) {
	data := d.data[a]

	if data == nil {
		data = make(map[string]interface{})
		d.data[a] = data
	}

	data[b] = o
}

func EscapeWhitespace(s string, escapeSpaces bool) string {

	s = strings.Replace(s, "\t", "\\t", -1)
	s = strings.Replace(s, "\n", "\\n", -1)
	s = strings.Replace(s, "\r", "\\r", -1)
	if escapeSpaces {
		s = strings.Replace(s, " ", "\u00B7", -1)
	}
	return s
}

func TerminalNodeToStringArray(sa []TerminalNode) []string {
	st := make([]string, len(sa))

	for i, s := range sa {
		st[i] = fmt.Sprintf("%v", s)
	}

	return st
}

func PrintArrayJavaStyle(sa []string) string {
	var buffer bytes.Buffer

	buffer.WriteString("[")

	for i, s := range sa {
		buffer.WriteString(s)
		if i != len(sa)-1 {
			buffer.WriteString(", ")
		}
	}

	buffer.WriteString("]")

	return buffer.String()
}

// murmur hash
const (
	c1_32 = 0xCC9E2D51
	c2_32 = 0x1B873593
	n1_32 = 0xE6546B64
)

func initHash(seed int) int {
	return seed
}

func update(h1 int, k1 int) int {
	k1 *= c1_32
	k1 = (k1 << 15) | (k1 >> 17) // rotl32(k1, 15)
	k1 *= c2_32

	h1 ^= k1
	h1 = (h1 << 13) | (h1 >> 19) // rotl32(h1, 13)
	h1 = h1*5 + 0xe6546b64
	return h1
}

func finish(h1 int, numberOfWords int) int {
	h1 ^= (numberOfWords * 4)
	h1 ^= h1 >> 16
	h1 *= 0x85ebca6b
	h1 ^= h1 >> 13
	h1 *= 0xc2b2ae35
	h1 ^= h1 >> 16

	return h1
}
<commit_msg>Change DoubleDict to use int<commit_after>// Copyright (c) 2012-2016 The ANTLR Project. All rights reserved.
// Use of this file is governed by the BSD 3-clause license that
// can be found in the LICENSE.txt file in the project root.

package antlr

import (
	"bytes"
	"errors"
	"fmt"
	"hash/fnv"
	"sort"
	"strconv"
	"strings"
)

func intMin(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func intMax(a, b int) int {
	if a > b {
		return a
	}
	return b
}

// A simple integer stack

type IntStack []int

var ErrEmptyStack = errors.New("Stack is empty")

func (s *IntStack) Pop() (int, error) {
	l := len(*s) - 1
	if l < 0 {
		return 0, ErrEmptyStack
	}
	v := (*s)[l]
	*s = (*s)[0:l]
	return v, nil
}

func (s *IntStack) Push(e int) {
	*s = append(*s, e)
}

type Set struct {
	data             map[int][]interface{}
	hashcodeFunction func(interface{}) int
	equalsFunction   func(interface{}, interface{}) bool
}

func NewSet(
	hashcodeFunction func(interface{}) int,
	equalsFunction func(interface{}, interface{}) bool) *Set {

	s := new(Set)

	s.data = make(map[int][]interface{})

	if hashcodeFunction != nil {
		s.hashcodeFunction = hashcodeFunction
	} else {
		s.hashcodeFunction = standardHashFunction
	}

	if equalsFunction == nil {
		s.equalsFunction = standardEqualsFunction
	} else {
		s.equalsFunction = equalsFunction
	}

	return s
}

func standardEqualsFunction(a interface{}, b interface{}) bool {

	ac, oka := a.(Comparable)
	bc, okb := b.(Comparable)

	if !oka || !okb {
		panic("Not Comparable")
	}

	return ac.equals(bc)
}

func standardHashFunction(a interface{}) int {
	if h, ok := a.(HashCoder); ok {
		return h.HashCode()
	}

	if h, ok := a.(Hasher); ok {
		s := h.Hash()
		ha := fnv.New32a()
		ha.Write([]byte((s)))
		return int(ha.Sum32())
	}

	panic("Not Hasher")
}

type Hasher interface {
	Hash() string
}

type HashCoder interface {
	HashCode() int
}

func (s *Set) length() int {
	return len(s.data)
}

func (s *Set) add(value interface{}) interface{} {

	key := s.hashcodeFunction(value)

	values := s.data[key]

	if s.data[key] != nil {
		for i := 0; i < len(values); i++ {
			if s.equalsFunction(value, values[i]) {
				return values[i]
			}
		}

		s.data[key] = append(s.data[key], value)
		return value
	}

	v := make([]interface{}, 1, 10)
	v[0] = value
	s.data[key] = v

	return value
}

func (s *Set) contains(value interface{}) bool {

	key := s.hashcodeFunction(value)

	values := s.data[key]

	if s.data[key] != nil {
		for i := 0; i < len(values); i++ {
			if s.equalsFunction(value, values[i]) {
				return true
			}
		}
	}
	return false
}

func (s *Set) values() []interface{} {
	var l []interface{}

	for _, v := range s.data {
		l = append(l, v...)
	}

	return l
}

func (s *Set) String() string {
	r := ""

	for _, av := range s.data {
		for _, v := range av {
			r += fmt.Sprint(v)
		}
	}

	return r
}

type BitSet struct {
	data map[int]bool
}

func NewBitSet() *BitSet {
	b := new(BitSet)
	b.data = make(map[int]bool)
	return b
}

func (b *BitSet) add(value int) {
	b.data[value] = true
}

func (b *BitSet) clear(index int) {
	delete(b.data, index)
}

func (b *BitSet) or(set *BitSet) {
	for k := range set.data {
		b.add(k)
	}
}

func (b *BitSet) remove(value int) {
	delete(b.data, value)
}

func (b *BitSet) contains(value int) bool {
	return b.data[value]
}

func (b *BitSet) values() []int {
	ks := make([]int, len(b.data))
	i := 0
	for k := range b.data {
		ks[i] = k
		i++
	}
	sort.Ints(ks)
	return ks
}

func (b *BitSet) minValue() int {
	min := 2147483647

	for k := range b.data {
		if k < min {
			min = k
		}
	}

	return min
}

func (b *BitSet) equals(other interface{}) bool {
	otherBitSet, ok := other.(*BitSet)
	if !ok {
		return false
	}

	if len(b.data) != len(otherBitSet.data) {
		return false
	}

	for k, v := range b.data {
		if otherBitSet.data[k] != v {
			return false
		}
	}

	return true
}

func (b *BitSet) length() int {
	return len(b.data)
}

func (b *BitSet) String() string {
	vals := b.values()
	valsS := make([]string, len(vals))

	for i, val := range vals {
		valsS[i] = strconv.Itoa(val)
	}
	return "{" + strings.Join(valsS, ", ") + "}"
}

type AltDict struct {
	data map[string]interface{}
}

func NewAltDict() *AltDict {
	d := new(AltDict)
	d.data = make(map[string]interface{})
	return d
}

func (a *AltDict) Get(key string) interface{} {
	key = "k-" + key
	return a.data[key]
}

func (a *AltDict) put(key string, value interface{}) {
	key = "k-" + key
	a.data[key] = value
}

func (a *AltDict) values() []interface{} {
	vs := make([]interface{}, len(a.data))
	i := 0
	for _, v := range a.data {
		vs[i] = v
		i++
	}
	return vs
}

type DoubleDict struct {
	data map[int]map[int]interface{}
}

func NewDoubleDict() *DoubleDict {
	dd := new(DoubleDict)
	dd.data = make(map[int]map[int]interface{})
	return dd
}

func (d *DoubleDict) Get(a, b int) interface{} {
	data := d.data[a]

	if data == nil {
		return nil
	}

	return data[b]
}

func (d *DoubleDict) set(a, b int, o interface{}) {
	data := d.data[a]

	if data == nil {
		data = make(map[int]interface{})
		d.data[a] = data
	}

	data[b] = o
}

func EscapeWhitespace(s string, escapeSpaces bool) string {

	s = strings.Replace(s, "\t", "\\t", -1)
	s = strings.Replace(s, "\n", "\\n", -1)
	s = strings.Replace(s, "\r", "\\r", -1)
	if escapeSpaces {
		s = strings.Replace(s, " ", "\u00B7", -1)
	}
	return s
}

func TerminalNodeToStringArray(sa []TerminalNode) []string {
	st := make([]string, len(sa))

	for i, s := range sa {
		st[i] = fmt.Sprintf("%v", s)
	}

	return st
}

func PrintArrayJavaStyle(sa []string) string {
	var buffer bytes.Buffer

	buffer.WriteString("[")

	for i, s := range sa {
		buffer.WriteString(s)
		if i != len(sa)-1 {
			buffer.WriteString(", ")
		}
	}

	buffer.WriteString("]")

	return buffer.String()
}

// murmur hash
const (
	c1_32 = 0xCC9E2D51
	c2_32 = 0x1B873593
	n1_32 = 0xE6546B64
)

func initHash(seed int) int {
	return seed
}

func update(h1 int, k1 int) int {
	k1 *= c1_32
	k1 = (k1 << 15) | (k1 >> 17) // rotl32(k1, 15)
	k1 *= c2_32

	h1 ^= k1
	h1 = (h1 << 13) | (h1 >> 19) // rotl32(h1, 13)
	h1 = h1*5 + 0xe6546b64
	return h1
}

func finish(h1 int, numberOfWords int) int {
	h1 ^= (numberOfWords * 4)
	h1 ^= h1 >> 16
	h1 *= 0x85ebca6b
	h1 ^= h1 >> 13
	h1 *= 0xc2b2ae35
	h1 ^= h1 >> 16

	return h1
}
<|endoftext|>


<commit_before>package tag

import (
	"errors"
	"sort"
	"strings"
)

// Tag aggregates tag-related information: tag name, image digest etc
type Tag struct {
	name    string
	digest  string
	imageID string
	state   string
}

// SortKey returns a sort key
func (tg *Tag) SortKey() string {
	return tg.name
}

// GetName gets tag name
func (tg *Tag) GetName() string {
	return tg.name
}

// GetDigest gets tagged image's digest
func (tg *Tag) GetDigest() string {
	return tg.digest
}

func calculateImageID(s string) string {
	fields := strings.Split(s, ":")

	if len(fields) < 2 {
		return s
	}

	if len(fields[1]) > 12 {
		return fields[1][0:12]
	}

	return fields[1]
}

// SetImageID sets local Docker image ID
func (tg *Tag) SetImageID(s string) {
	tg.imageID = calculateImageID(s)
}

// GetImageID gets local Docker image ID
func (tg *Tag) GetImageID() string {
	return tg.imageID
}

// SetState sets repo tag state
func (tg *Tag) SetState(state string) {
	tg.state = state
}

// GetState gets repo tag state
func (tg *Tag) GetState() string {
	return tg.state
}

// New creates a new instance of Tag
func New(name, digest string) (*Tag, error) {
	if name == "" {
		return nil, errors.New("Empty tag name not allowed")
	}

	if digest == "" {
		return nil, errors.New("Empty image digest not allowed")
	}

	return &Tag{
			name:   name,
			digest: digest,
		},
		nil
}

// Join joins local tags with ones from registry, performs state processing and returns:
// * sorted slice of sort keys
// * joined map of *tag.Tag
func Join(registryTags, localTags map[string]*Tag) ([]string, map[string]*Tag) {
	sortedKeys := make([]string, 0)
	joinedTags := make(map[string]*Tag)

	for sortKey := range registryTags {
		sortedKeys = append(sortedKeys, sortKey)
		joinedTags[sortKey] = registryTags[sortKey]

		ltg, defined := localTags[sortKey]
		if defined {
			joinedTags[sortKey].SetImageID(ltg.GetImageID())
		} else {
			joinedTags[sortKey].SetImageID("n/a")
		}
	}

	for sortKey := range localTags {
		_, defined := registryTags[sortKey]
		if !defined {
			sortedKeys = append(sortedKeys, sortKey)
			joinedTags[sortKey] = localTags[sortKey]
		}
	}

	for sortKey, jtg := range joinedTags {
		jtg.SetState(
			calculateState(
				sortKey,
				registryTags,
				localTags,
			),
		)
	}

	sort.Strings(sortedKeys)

	return sortedKeys, joinedTags
}

func calculateState(sortKey string, registryTags, localTags map[string]*Tag) string {
	r, definedInRegistry := registryTags[sortKey]
	l, definedLocally := localTags[sortKey]

	if definedInRegistry && !definedLocally {
		return "ABSENT"
	}

	if !definedInRegistry && definedLocally {
		return "LOCAL-ONLY"
	}

	if definedInRegistry && definedLocally {
		if r.GetDigest() == l.GetDigest() {
			return "PRESENT"
		}

		return "CHANGED"
	}

	return "UNKNOWN"
}
<commit_msg>Move function LOL<commit_after>package tag

import (
	"errors"
	"sort"
	"strings"
)

// Tag aggregates tag-related information: tag name, image digest etc
type Tag struct {
	name    string
	digest  string
	imageID string
	state   string
}

// SortKey returns a sort key
func (tg *Tag) SortKey() string {
	return tg.name
}

// GetName gets tag name
func (tg *Tag) GetName() string {
	return tg.name
}

// GetDigest gets tagged image's digest
func (tg *Tag) GetDigest() string {
	return tg.digest
}

func calculateImageID(s string) string {
	fields := strings.Split(s, ":")

	if len(fields) < 2 {
		return s
	}

	if len(fields[1]) > 12 {
		return fields[1][0:12]
	}

	return fields[1]
}

// SetImageID sets local Docker image ID
func (tg *Tag) SetImageID(s string) {
	tg.imageID = calculateImageID(s)
}

// GetImageID gets local Docker image ID
func (tg *Tag) GetImageID() string {
	return tg.imageID
}

// SetState sets repo tag state
func (tg *Tag) SetState(state string) {
	tg.state = state
}

// GetState gets repo tag state
func (tg *Tag) GetState() string {
	return tg.state
}

// New creates a new instance of Tag
func New(name, digest string) (*Tag, error) {
	if name == "" {
		return nil, errors.New("Empty tag name not allowed")
	}

	if digest == "" {
		return nil, errors.New("Empty image digest not allowed")
	}

	return &Tag{
			name:   name,
			digest: digest,
		},
		nil
}

func calculateState(sortKey string, registryTags, localTags map[string]*Tag) string {
	r, definedInRegistry := registryTags[sortKey]
	l, definedLocally := localTags[sortKey]

	if definedInRegistry && !definedLocally {
		return "ABSENT"
	}

	if !definedInRegistry && definedLocally {
		return "LOCAL-ONLY"
	}

	if definedInRegistry && definedLocally {
		if r.GetDigest() == l.GetDigest() {
			return "PRESENT"
		}

		return "CHANGED"
	}

	return "UNKNOWN"
}

// Join joins local tags with ones from registry, performs state processing and returns:
// * sorted slice of sort keys
// * joined map of *tag.Tag
func Join(registryTags, localTags map[string]*Tag) ([]string, map[string]*Tag) {
	sortedKeys := make([]string, 0)
	joinedTags := make(map[string]*Tag)

	for sortKey := range registryTags {
		sortedKeys = append(sortedKeys, sortKey)
		joinedTags[sortKey] = registryTags[sortKey]

		ltg, defined := localTags[sortKey]
		if defined {
			joinedTags[sortKey].SetImageID(ltg.GetImageID())
		} else {
			joinedTags[sortKey].SetImageID("n/a")
		}
	}

	for sortKey := range localTags {
		_, defined := registryTags[sortKey]
		if !defined {
			sortedKeys = append(sortedKeys, sortKey)
			joinedTags[sortKey] = localTags[sortKey]
		}
	}

	for sortKey, jtg := range joinedTags {
		jtg.SetState(
			calculateState(
				sortKey,
				registryTags,
				localTags,
			),
		)
	}

	sort.Strings(sortedKeys)

	return sortedKeys, joinedTags
}
<|endoftext|>


<commit_before>package app

// farm - is the node management data and functions

import (
	"errors"
	"log"
)

// the maximum number of nodes in the cluster
// Arbitrarily set to the same number of flocks in the two character flocking system
const MAX_NODES = 1296

// Each flock can have at most 10 replicas
const MAX_REPLICAS = 10

// The set of allowable characters in any key
const KEY_CHARS = "01234567890abcdefghijklmnopqrstuvwxyz"

type nodeIndex uint16 // 65535 nodes maximum (2 per flock)

type NodeStatus struct {
	Url string
	Up  bool
}

// node nodeIndex to string lookup
type nodeLookup []NodeStatus

// node string uri (which will almost certainly be a url as well) to nodeIndex lookup
type nodeNameMap map[string]nodeIndex

// for a particular flock what does the Node (givien by the node index) care
type FlockStatus struct {
	// an index into nodeLookup so our nodemap does not contain strings - just integer references space++
	Node nodeIndex
	// does the Node want to herd this flock
	Herder bool
	// is if herding - if this is false and Herder is true, then the Node has not got a copy of the flock data yet
	Herding bool
}

// array (rather than linked list as modes rarely added or removed)
type nodeList []FlockStatus

// The nodeMap contains the
type nodeMap struct {
	MyUri string
	// the nodeIndex to node Uri mapping thing
	NodeUris nodeLookup
	NodeIds  nodeNameMap
	// a farm is a map of all our flocks
	Farm map[string]nodeList
}

// return the uri for this node
func Farm() *nodeMap {
	return &farm
}

// return the uri for this node
func MyUri() string {
	return farm.MyUri
}

// this is the flock key algorithm - default simply the first two characters of the bucket key
func getFlockKey(bucketKey string) string {
	return bucketKey[0:2]
}

// for a given bucket return whether the current node is herding it and a list of other node urls that are herding it as well
// flag to rule out those that are not actually fully herding yet
func getHerdersForBucket(bucketKey string, allowPartialHerding bool) (bool, []string) {
	flockKey := getFlockKey(bucketKey)
	iCare := false
	herders := make([]string, 0, MAX_REPLICAS)
	for _, fs := range farm.Farm[flockKey] {
		if fs.Node == 0 {
			iCare = fs.Herding || (allowPartialHerding && fs.Herder)
		} else if fs.Herder {
			if allowPartialHerding || fs.Herding {
				nodeStatus, err := LookupNode(fs.Node)
				if err != nil {
					log.Println("Error - inconsistant farm")
				} else if !nodeStatus.Up {
					log.Println("Warning - wanted to send stuff to a downed node")
				} else {
					herders = append(herders, nodeStatus.Url)
				}
			}
		}
	}
	return iCare, herders
}

// Register that a Node with given uri is herding / or not a particular flock
func AddNodeToFlock(uri string, flockKey string, herder bool) error {
	// check the Node exists in our list
	index, in := farm.NodeIds[uri]
	if !in {
		return errors.New("Tried to add an unknown node " + uri + " to flock: " + flockKey)
	}

	flock := FlockStatus{
		Node:   index,
		Herder: herder,
	}

	nl, in := farm.Farm[flockKey]
	if !in {
		nl = make(nodeList, 0, MAX_REPLICAS)
	}

	// check if this node index is already in
	for _, f := range nl {
		if f.Node == flock.Node {
			// is this error needed really - any harm trying to add the same node?
			return errors.New("this node has allready been added to that flock")
		}
	}

	if len(nl) >= MAX_REPLICAS {
		return errors.New("Too many nodes for this flock")
	}
	nl = append(nl, flock)
	farm.Farm[flockKey] = nl
	return nil
}

// Add a node uri to the node lookups
// returns the index for the node, and if it is new
func AddNode(uri string) (nodeIndex, bool, error) {

	// got this one already
	id, in := farm.NodeIds[uri]
	if in {
		return id, false, nil
	}

	if len(farm.NodeUris) >= MAX_NODES {
		return 0, false, errors.New("Too many nodes for the world")
	}

	// otherwise ad it to the list
	farm.NodeUris = append(farm.NodeUris, NodeStatus{uri, true})
	id = nodeIndex(len(farm.NodeUris) - 1)

	// and our index lookup
	farm.NodeIds[uri] = id
	return id, true, nil
}

// Return the node uri for a given internal node index
func LookupNode(id nodeIndex) (NodeStatus, error) {
	if id >= nodeIndex(len(farm.NodeUris)) {
		return NodeStatus{}, errors.New("that node id does not exist in our node list")
	}
	return farm.NodeUris[id], nil
}

func addExternalFarm(url string, newfarm *SingleNodeFarm) {
	for k, f := range newfarm.Flocks {
		AddNodeToFlock(url, k, f.Herder)
	}
}

// for any nodes found in the recently acquired nodelist if they are new then get that nodes farm status as well
func addExternalNodes(newNodes *NodeList) {
	for _, f := range newNodes.Nodes {
		ind, isNew, err := AddNode(f.Url)
		if err == nil {
			farm.NodeUris[ind].Up = f.Up
			// any new nodes go and get the farm status
			if isNew {
				tellFarm(f.Url)
			}
		}
	}
}

// report a node as down when we cant get a connection to it
func markNodeUpOrDown(url string, upOrDown bool) {
	index, in := farm.NodeIds[url]
	if in {
		farm.NodeUris[index].Up = upOrDown

	}
}

// load the farm with all possible flocks using the first two chars of the key method
func SetupDefaultFlocks() {
	for _, c1 := range KEY_CHARS {
		for _, c2 := range KEY_CHARS {
			herd := true
			AddNodeToFlock(MyUri(), string(c1)+string(c2), herd, false)
		}
	}
}
<commit_msg>fixing the redundant caching flag<commit_after>package app

// farm - is the node management data and functions

import (
	"errors"
	"log"
)

// the maximum number of nodes in the cluster
// Arbitrarily set to the same number of flocks in the two character flocking system
const MAX_NODES = 1296

// Each flock can have at most 10 replicas
const MAX_REPLICAS = 10

// The set of allowable characters in any key
const KEY_CHARS = "01234567890abcdefghijklmnopqrstuvwxyz"

type nodeIndex uint16 // 65535 nodes maximum (2 per flock)

type NodeStatus struct {
	Url string
	Up  bool
}

// node nodeIndex to string lookup
type nodeLookup []NodeStatus

// node string uri (which will almost certainly be a url as well) to nodeIndex lookup
type nodeNameMap map[string]nodeIndex

// for a particular flock what does the Node (givien by the node index) care
type FlockStatus struct {
	// an index into nodeLookup so our nodemap does not contain strings - just integer references space++
	Node nodeIndex
	// does the Node want to herd this flock
	Herder bool
	// is if herding - if this is false and Herder is true, then the Node has not got a copy of the flock data yet
	Herding bool
}

// array (rather than linked list as modes rarely added or removed)
type nodeList []FlockStatus

// The nodeMap contains the
type nodeMap struct {
	MyUri string
	// the nodeIndex to node Uri mapping thing
	NodeUris nodeLookup
	NodeIds  nodeNameMap
	// a farm is a map of all our flocks
	Farm map[string]nodeList
}

// return the uri for this node
func Farm() *nodeMap {
	return &farm
}

// return the uri for this node
func MyUri() string {
	return farm.MyUri
}

// this is the flock key algorithm - default simply the first two characters of the bucket key
func getFlockKey(bucketKey string) string {
	return bucketKey[0:2]
}

// for a given bucket return whether the current node is herding it and a list of other node urls that are herding it as well
// flag to rule out those that are not actually fully herding yet
func getHerdersForBucket(bucketKey string, allowPartialHerding bool) (bool, []string) {
	flockKey := getFlockKey(bucketKey)
	iCare := false
	herders := make([]string, 0, MAX_REPLICAS)
	for _, fs := range farm.Farm[flockKey] {
		if fs.Node == 0 {
			iCare = fs.Herding || (allowPartialHerding && fs.Herder)
		} else if fs.Herder {
			if allowPartialHerding || fs.Herding {
				nodeStatus, err := LookupNode(fs.Node)
				if err != nil {
					log.Println("Error - inconsistant farm")
				} else if !nodeStatus.Up {
					log.Println("Warning - wanted to send stuff to a downed node")
				} else {
					herders = append(herders, nodeStatus.Url)
				}
			}
		}
	}
	return iCare, herders
}

// Register that a Node with given uri is herding / or not a particular flock
func AddNodeToFlock(uri string, flockKey string, herder bool) error {
	// check the Node exists in our list
	index, in := farm.NodeIds[uri]
	if !in {
		return errors.New("Tried to add an unknown node " + uri + " to flock: " + flockKey)
	}

	flock := FlockStatus{
		Node:   index,
		Herder: herder,
	}

	nl, in := farm.Farm[flockKey]
	if !in {
		nl = make(nodeList, 0, MAX_REPLICAS)
	}

	// check if this node index is already in
	for _, f := range nl {
		if f.Node == flock.Node {
			// is this error needed really - any harm trying to add the same node?
			return errors.New("this node has allready been added to that flock")
		}
	}

	if len(nl) >= MAX_REPLICAS {
		return errors.New("Too many nodes for this flock")
	}
	nl = append(nl, flock)
	farm.Farm[flockKey] = nl
	return nil
}

// Add a node uri to the node lookups
// returns the index for the node, and if it is new
func AddNode(uri string) (nodeIndex, bool, error) {

	// got this one already
	id, in := farm.NodeIds[uri]
	if in {
		return id, false, nil
	}

	if len(farm.NodeUris) >= MAX_NODES {
		return 0, false, errors.New("Too many nodes for the world")
	}

	// otherwise ad it to the list
	farm.NodeUris = append(farm.NodeUris, NodeStatus{uri, true})
	id = nodeIndex(len(farm.NodeUris) - 1)

	// and our index lookup
	farm.NodeIds[uri] = id
	return id, true, nil
}

// Return the node uri for a given internal node index
func LookupNode(id nodeIndex) (NodeStatus, error) {
	if id >= nodeIndex(len(farm.NodeUris)) {
		return NodeStatus{}, errors.New("that node id does not exist in our node list")
	}
	return farm.NodeUris[id], nil
}

func addExternalFarm(url string, newfarm *SingleNodeFarm) {
	for k, f := range newfarm.Flocks {
		AddNodeToFlock(url, k, f.Herder)
	}
}

// for any nodes found in the recently acquired nodelist if they are new then get that nodes farm status as well
func addExternalNodes(newNodes *NodeList) {
	for _, f := range newNodes.Nodes {
		ind, isNew, err := AddNode(f.Url)
		if err == nil {
			farm.NodeUris[ind].Up = f.Up
			// any new nodes go and get the farm status
			if isNew {
				tellFarm(f.Url)
			}
		}
	}
}

// report a node as down when we cant get a connection to it
func markNodeUpOrDown(url string, upOrDown bool) {
	index, in := farm.NodeIds[url]
	if in {
		farm.NodeUris[index].Up = upOrDown

	}
}

// load the farm with all possible flocks using the first two chars of the key method
func SetupDefaultFlocks() {
	for _, c1 := range KEY_CHARS {
		for _, c2 := range KEY_CHARS {
			herd := true
			AddNodeToFlock(MyUri(), string(c1)+string(c2), herd)
		}
	}
}
<|endoftext|>


<commit_before>package app

import (
	"chant/app/repository"

	"github.com/revel/revel"
)

func init() {
	// Filters is the default set of global filters.
	revel.Filters = []revel.Filter{
		revel.PanicFilter,             // Recover from panics and display an error page instead.
		revel.RouterFilter,            // Use the routing table to select the right Action
		revel.FilterConfiguringFilter, // A hook for adding or removing per-Action filters.
		revel.ParamsFilter,            // Parse parameters into Controller.Params.
		revel.SessionFilter,           // Restore and write the session cookie.
		revel.FlashFilter,             // Restore and write the flash cookie.
		revel.ValidationFilter,        // Restore kept validation errors and save new ones from cookie.
		revel.I18nFilter,              // Resolve the requested language
		HeaderFilter,                  // Add some security based headers
		revel.InterceptorFilter,       // Run interceptors around the action.
		revel.CompressFilter,          // Compress the result.
		revel.ActionInvoker,           // Invoke the action.
	}

	// register startup functions with OnAppStart
	// ( order dependent )
	revel.OnAppStart(InitRepository)
	// revel.OnAppStart(FillCache)
}

// TODO turn this into revel.HeaderFilter
// should probably also have a filter for CSRF
// not sure if it can go in the same filter or not
var HeaderFilter = func(c *revel.Controller, fc []revel.Filter) {
	// Add some common security headers
	c.Response.Out.Header().Add("X-Frame-Options", "SAMEORIGIN")
	c.Response.Out.Header().Add("X-XSS-Protection", "1; mode=block")
	c.Response.Out.Header().Add("X-Content-Type-Options", "nosniff")

	fc[0](c, fc[1:]) // Execute the next filter stage.
}

// InitRepository ...
func InitRepository() {
	// Init Messages repo
	initRepository("messages")
	// Init Stamps repo
	initRepository("stamps")
}

func initRepository(key string) {
	if revel.Config.BoolDefault("persistent."+key, false) {
		repo := repository.NewRedisRepository(
			revel.Config.StringDefault("redis.host", "localhost"),
			revel.Config.StringDefault("redis.port", "6379"),
		)
		repository.SetRepository(key, repo)
	}
}
<commit_msg>Fix cache expire<commit_after>package app

import (
	"chant/app/repository"
	"time"

	"github.com/otiai10/cachely"
	"github.com/revel/revel"
)

func init() {
	// Filters is the default set of global filters.
	revel.Filters = []revel.Filter{
		revel.PanicFilter,             // Recover from panics and display an error page instead.
		revel.RouterFilter,            // Use the routing table to select the right Action
		revel.FilterConfiguringFilter, // A hook for adding or removing per-Action filters.
		revel.ParamsFilter,            // Parse parameters into Controller.Params.
		revel.SessionFilter,           // Restore and write the session cookie.
		revel.FlashFilter,             // Restore and write the flash cookie.
		revel.ValidationFilter,        // Restore kept validation errors and save new ones from cookie.
		revel.I18nFilter,              // Resolve the requested language
		HeaderFilter,                  // Add some security based headers
		revel.InterceptorFilter,       // Run interceptors around the action.
		revel.CompressFilter,          // Compress the result.
		revel.ActionInvoker,           // Invoke the action.
	}

	// register startup functions with OnAppStart
	// ( order dependent )
	revel.OnAppStart(InitRepository)
	// revel.OnAppStart(FillCache)

	cachely.Expires(5 * time.Minute)
}

// TODO turn this into revel.HeaderFilter
// should probably also have a filter for CSRF
// not sure if it can go in the same filter or not
var HeaderFilter = func(c *revel.Controller, fc []revel.Filter) {
	// Add some common security headers
	c.Response.Out.Header().Add("X-Frame-Options", "SAMEORIGIN")
	c.Response.Out.Header().Add("X-XSS-Protection", "1; mode=block")
	c.Response.Out.Header().Add("X-Content-Type-Options", "nosniff")

	fc[0](c, fc[1:]) // Execute the next filter stage.
}

// InitRepository ...
func InitRepository() {
	// Init Messages repo
	initRepository("messages")
	// Init Stamps repo
	initRepository("stamps")
}

func initRepository(key string) {
	if revel.Config.BoolDefault("persistent."+key, false) {
		repo := repository.NewRedisRepository(
			revel.Config.StringDefault("redis.host", "localhost"),
			revel.Config.StringDefault("redis.port", "6379"),
		)
		repository.SetRepository(key, repo)
	}
}
<|endoftext|>