<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.

// This file contains tests for Eval.

package types_test

import (
	"go/ast"
	"go/parser"
	"go/token"
	"strings"
	"testing"

	_ "code.google.com/p/go.tools/go/gcimporter"
	. "code.google.com/p/go.tools/go/types"
)

func testEval(t *testing.T, pkg *Package, scope *Scope, str string, typ Type, typStr, valStr string) {
	gotTyp, gotVal, err := Eval(str, pkg, scope)
	if err != nil {
		t.Errorf("Eval(%q) failed: %s", str, err)
		return
	}
	if gotTyp == nil {
		t.Errorf("Eval(%q) got nil type but no error", str)
		return
	}

	// compare types
	if typ != nil {
		// we have a type, check identity
		if !IsIdentical(gotTyp, typ) {
			t.Errorf("Eval(%q) got type %s, want %s", str, gotTyp, typ)
			return
		}
	} else {
		// we have a string, compare type string
		gotStr := gotTyp.String()
		if gotStr != typStr {
			t.Errorf("Eval(%q) got type %s, want %s", str, gotStr, typStr)
			return
		}
	}

	// compare values
	gotStr := ""
	if gotVal != nil {
		gotStr = gotVal.String()
	}
	if gotStr != valStr {
		t.Errorf("Eval(%q) got value %s, want %s", str, gotStr, valStr)
	}
}

func TestEvalBasic(t *testing.T) {
	for _, typ := range Typ[Bool : String+1] {
		testEval(t, nil, nil, typ.Name(), typ, "", "")
	}
}

func TestEvalComposite(t *testing.T) {
	for _, test := range independentTestTypes {
		testEval(t, nil, nil, test.src, nil, test.str, "")
	}
}

func TestEvalArith(t *testing.T) {
	var tests = []string{
		`true`,
		`false == false`,
		`12345678 + 87654321 == 99999999`,
		`10 * 20 == 200`,
		`(1<<1000)*2 >> 100 == 2<<900`,
		`"foo" + "bar" == "foobar"`,
		`"abc" <= "bcd"`,
		`len([10]struct{}{}) == 2*5`,
	}
	for _, test := range tests {
		testEval(t, nil, nil, test, Typ[UntypedBool], "", "true")
	}
}

func TestEvalContext(t *testing.T) {
	src := `
package p
import "fmt"
import m "math"
const c = 3.0
type T []int
func f(a int, s string) float64 {
	fmt.Println("calling f")
	_ = m.Pi // use package math
	const d int = c + 1
	var x int
	x = a + len(s)
	return float64(x)
}
`
	fset := token.NewFileSet()
	file, err := parser.ParseFile(fset, "p", src, 0)
	if err != nil {
		t.Fatal(err)
	}

	pkg, err := Check("p", fset, []*ast.File{file})
	if err != nil {
		t.Fatal(err)
	}

	pkgScope := pkg.Scope()
	if n := pkgScope.NumChildren(); n != 1 {
		t.Fatalf("got %d file scopes, want 1", n)
	}

	fileScope := pkgScope.Child(0)
	if n := fileScope.NumChildren(); n != 1 {
		t.Fatalf("got %d functions scopes, want 1", n)
	}

	funcScope := fileScope.Child(0)

	var tests = []string{
		`true => true, untyped boolean`,
		`fmt.Println => , func(a·3 ...interface{}) (n·1 int, err·2 error)`,
		`c => 3, untyped float`,
		`T => , p.T`,
		`a => , int`,
		`s => , string`,
		`d => 4, int`,
		`x => , int`,
		`d/c => 1, int`,
		`c/2 => 3/2, untyped float`,
		`m.Pi < m.E => false, untyped boolean`,
	}
	for _, test := range tests {
		str, typ := split(test, ", ")
		str, val := split(str, "=>")
		testEval(t, pkg, funcScope, str, nil, typ, val)
	}
}

// split splits string s at the first occurrence of s.
func split(s, sep string) (string, string) {
	i := strings.Index(s, sep)
	return strings.TrimSpace(s[:i]), strings.TrimSpace(s[i+len(sep):])
}
<commit_msg>go.tools/go/types: submit missed file (fix build)<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.

// This file contains tests for Eval.

package types_test

import (
	"go/ast"
	"go/parser"
	"go/token"
	"strings"
	"testing"

	_ "code.google.com/p/go.tools/go/gcimporter"
	. "code.google.com/p/go.tools/go/types"
)

func testEval(t *testing.T, pkg *Package, scope *Scope, str string, typ Type, typStr, valStr string) {
	gotTyp, gotVal, err := Eval(str, pkg, scope)
	if err != nil {
		t.Errorf("Eval(%q) failed: %s", str, err)
		return
	}
	if gotTyp == nil {
		t.Errorf("Eval(%q) got nil type but no error", str)
		return
	}

	// compare types
	if typ != nil {
		// we have a type, check identity
		if !IsIdentical(gotTyp, typ) {
			t.Errorf("Eval(%q) got type %s, want %s", str, gotTyp, typ)
			return
		}
	} else {
		// we have a string, compare type string
		gotStr := gotTyp.String()
		if gotStr != typStr {
			t.Errorf("Eval(%q) got type %s, want %s", str, gotStr, typStr)
			return
		}
	}

	// compare values
	gotStr := ""
	if gotVal != nil {
		gotStr = gotVal.String()
	}
	if gotStr != valStr {
		t.Errorf("Eval(%q) got value %s, want %s", str, gotStr, valStr)
	}
}

func TestEvalBasic(t *testing.T) {
	for _, typ := range Typ[Bool : String+1] {
		testEval(t, nil, nil, typ.Name(), typ, "", "")
	}
}

func TestEvalComposite(t *testing.T) {
	for _, test := range independentTestTypes {
		testEval(t, nil, nil, test.src, nil, test.str, "")
	}
}

func TestEvalArith(t *testing.T) {
	var tests = []string{
		`true`,
		`false == false`,
		`12345678 + 87654321 == 99999999`,
		`10 * 20 == 200`,
		`(1<<1000)*2 >> 100 == 2<<900`,
		`"foo" + "bar" == "foobar"`,
		`"abc" <= "bcd"`,
		`len([10]struct{}{}) == 2*5`,
	}
	for _, test := range tests {
		testEval(t, nil, nil, test, Typ[UntypedBool], "", "true")
	}
}

func TestEvalContext(t *testing.T) {
	src := `
package p
import "fmt"
import m "math"
const c = 3.0
type T []int
func f(a int, s string) float64 {
	fmt.Println("calling f")
	_ = m.Pi // use package math
	const d int = c + 1
	var x int
	x = a + len(s)
	return float64(x)
}
`
	fset := token.NewFileSet()
	file, err := parser.ParseFile(fset, "p", src, 0)
	if err != nil {
		t.Fatal(err)
	}

	pkg, err := Check("p", fset, []*ast.File{file})
	if err != nil {
		t.Fatal(err)
	}

	pkgScope := pkg.Scope()
	if n := pkgScope.NumChildren(); n != 1 {
		t.Fatalf("got %d file scopes, want 1", n)
	}

	fileScope := pkgScope.Child(0)
	if n := fileScope.NumChildren(); n != 1 {
		t.Fatalf("got %d functions scopes, want 1", n)
	}

	funcScope := fileScope.Child(0)

	var tests = []string{
		`true => true, untyped boolean`,
		`fmt.Println => , func(a ...interface{}) (n int, err error)`,
		`c => 3, untyped float`,
		`T => , p.T`,
		`a => , int`,
		`s => , string`,
		`d => 4, int`,
		`x => , int`,
		`d/c => 1, int`,
		`c/2 => 3/2, untyped float`,
		`m.Pi < m.E => false, untyped boolean`,
	}
	for _, test := range tests {
		str, typ := split(test, ", ")
		str, val := split(str, "=>")
		testEval(t, pkg, funcScope, str, nil, typ, val)
	}
}

// split splits string s at the first occurrence of s.
func split(s, sep string) (string, string) {
	i := strings.Index(s, sep)
	return strings.TrimSpace(s[:i]), strings.TrimSpace(s[i+len(sep):])
}
<|endoftext|>


<commit_before>package main

import "fmt"

// I am using a programming skill call precomputation.
// It has a very good performance
const ans = `
  34
- 09
-----
  25
+ 86
-----
 111
=====

  36
- 09
-----
  27
+ 84
-----
 111
=====

  45
- 06
-----
  39
+ 72
-----
 111

=====
  52
- 09
-----
  43
+ 68
-----
 111
=====

  57
- 08
-----
  49
+ 62
-----
 111
=====

  57
- 09
-----
  48
+ 63
-----
 111
=====

  72
- 09
-----
  63
+ 48
-----
 111
=====

  84
- 05
-----
  79
+ 32
-----
 111
=====

  84
- 09
-----
  75
+ 36
-----
 111
=====

  85
- 06
-----
  79
+ 32
-----
 111
=====

  85
- 46
-----
  39
+ 72
-----
 111
=====

  86
- 54
-----
  32
+ 79
-----
 111
=====

  90
- 27
-----
  63
+ 48
-----
 111
=====

  90
- 63
-----
  27
+ 84
-----
 111
=====

  93
- 06
-----
  87
+ 24
-----
 111
=====

  93
- 07
-----
  86
+ 25
-----
 111
=====

  95
- 27
-----
  68
+ 43
-----
 111
=====
`

func main() {
    fmt.Println(ans)
}<commit_msg>Remove the solution start with zero<commit_after>package main

import "fmt"

// I am using a programming skill call precomputation.
// It has a very good performance
const ans = `
  85
- 46
-----
  39
+ 72
-----
 111
=====

  86
- 54
-----
  32
+ 79
-----
 111
=====

  90
- 27
-----
  63
+ 48
-----
 111
=====

  90
- 63
-----
  27
+ 84
-----
 111
=====

  95
- 27
-----
  68
+ 43
-----
 111
=====
`

func main() {
    fmt.Println(ans)
}<|endoftext|>


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

// Command generate updates settings.md from the UserOptions struct.
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"

	"golang.org/x/tools/internal/lsp/source"
)

func main() {
	if _, err := doMain(".", true); err != nil {
		fmt.Fprintf(os.Stderr, "Generation failed: %v\n", err)
		os.Exit(1)
	}
}

func doMain(baseDir string, write bool) (bool, error) {
	api := &source.APIJSON{}
	if err := json.Unmarshal([]byte(source.GeneratedAPIJSON), api); err != nil {
		return false, err
	}

	if ok, err := rewriteFile(filepath.Join(baseDir, "gopls/doc/settings.md"), api, write, rewriteSettings); !ok || err != nil {
		return ok, err
	}
	if ok, err := rewriteFile(filepath.Join(baseDir, "gopls/doc/commands.md"), api, write, rewriteCommands); !ok || err != nil {
		return ok, err
	}

	return true, nil
}

func rewriteFile(file string, api *source.APIJSON, write bool, rewrite func([]byte, *source.APIJSON) ([]byte, error)) (bool, error) {
	doc, err := ioutil.ReadFile(file)
	if err != nil {
		return false, err
	}

	content, err := rewrite(doc, api)
	if err != nil {
		return false, fmt.Errorf("rewriting %q: %v", file, err)
	}

	if !bytes.Equal(doc, content) && !write {
		return false, nil
	}

	if err := ioutil.WriteFile(file, content, 0); err != nil {
		return false, err
	}

	return true, nil
}

func rewriteSettings(doc []byte, api *source.APIJSON) ([]byte, error) {
	var result []byte
	for category, opts := range api.Options {
		section := bytes.NewBuffer(nil)
		for _, opt := range opts {
			var enumValues string
			if len(opt.EnumValues) > 0 {
				enumValues = "Must be one of:\n\n"
				for _, val := range opt.EnumValues {
					enumValues += fmt.Sprintf(" * `%v`\n", val)
				}
			}
			fmt.Fprintf(section, "### **%v** *%v*\n%v%v\n\nDefault: `%v`.\n", opt.Name, opt.Type, opt.Doc, enumValues, opt.Default)
		}
		var err error
		result, err = replaceSection(doc, category, section.Bytes())
		if err != nil {
			return nil, err
		}
	}

	section := bytes.NewBuffer(nil)
	for _, lens := range api.Lenses {
		fmt.Fprintf(section, "### **%v**\nIdentifier: `%v`\n\n%v\n\n", lens.Title, lens.Lens, lens.Doc)
	}
	return replaceSection(result, "Lenses", section.Bytes())
}

func rewriteCommands(doc []byte, api *source.APIJSON) ([]byte, error) {
	section := bytes.NewBuffer(nil)
	for _, command := range api.Commands {
		fmt.Fprintf(section, "### **%v**\nIdentifier: `%v`\n\n%v\n\n", command.Title, command.Command, command.Doc)
	}
	return replaceSection(doc, "Commands", section.Bytes())
}

func replaceSection(doc []byte, sectionName string, replacement []byte) ([]byte, error) {
	re := regexp.MustCompile(fmt.Sprintf(`(?s)<!-- BEGIN %v.* -->\n(.*?)<!-- END %v.* -->`, sectionName, sectionName))
	idx := re.FindSubmatchIndex(doc)
	if idx == nil {
		return nil, fmt.Errorf("could not find section %q", sectionName)
	}
	result := append([]byte(nil), doc[:idx[2]]...)
	result = append(result, replacement...)
	result = append(result, doc[idx[3]:]...)
	return result, nil
}
<commit_msg>gopls/doc: fix section rewriting<commit_after>// Copyright 2020 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.

// Command generate updates settings.md from the UserOptions struct.
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"

	"golang.org/x/tools/internal/lsp/source"
)

func main() {
	if _, err := doMain(".", true); err != nil {
		fmt.Fprintf(os.Stderr, "Generation failed: %v\n", err)
		os.Exit(1)
	}
}

func doMain(baseDir string, write bool) (bool, error) {
	api := &source.APIJSON{}
	if err := json.Unmarshal([]byte(source.GeneratedAPIJSON), api); err != nil {
		return false, err
	}

	if ok, err := rewriteFile(filepath.Join(baseDir, "gopls/doc/settings.md"), api, write, rewriteSettings); !ok || err != nil {
		return ok, err
	}
	if ok, err := rewriteFile(filepath.Join(baseDir, "gopls/doc/commands.md"), api, write, rewriteCommands); !ok || err != nil {
		return ok, err
	}

	return true, nil
}

func rewriteFile(file string, api *source.APIJSON, write bool, rewrite func([]byte, *source.APIJSON) ([]byte, error)) (bool, error) {
	doc, err := ioutil.ReadFile(file)
	if err != nil {
		return false, err
	}

	content, err := rewrite(doc, api)
	if err != nil {
		return false, fmt.Errorf("rewriting %q: %v", file, err)
	}

	if !bytes.Equal(doc, content) && !write {
		return false, nil
	}

	if err := ioutil.WriteFile(file, content, 0); err != nil {
		return false, err
	}

	return true, nil
}

func rewriteSettings(doc []byte, api *source.APIJSON) ([]byte, error) {
	result := doc
	for category, opts := range api.Options {
		section := bytes.NewBuffer(nil)
		for _, opt := range opts {
			var enumValues string
			if len(opt.EnumValues) > 0 {
				enumValues = "Must be one of:\n\n"
				for _, val := range opt.EnumValues {
					enumValues += fmt.Sprintf(" * `%v`\n", val)
				}
			}
			fmt.Fprintf(section, "### **%v** *%v*\n%v%v\n\nDefault: `%v`.\n", opt.Name, opt.Type, opt.Doc, enumValues, opt.Default)
		}
		var err error
		result, err = replaceSection(result, category, section.Bytes())
		if err != nil {
			return nil, err
		}
	}

	section := bytes.NewBuffer(nil)
	for _, lens := range api.Lenses {
		fmt.Fprintf(section, "### **%v**\nIdentifier: `%v`\n\n%v\n\n", lens.Title, lens.Lens, lens.Doc)
	}
	return replaceSection(result, "Lenses", section.Bytes())
}

func rewriteCommands(doc []byte, api *source.APIJSON) ([]byte, error) {
	section := bytes.NewBuffer(nil)
	for _, command := range api.Commands {
		fmt.Fprintf(section, "### **%v**\nIdentifier: `%v`\n\n%v\n\n", command.Title, command.Command, command.Doc)
	}
	return replaceSection(doc, "Commands", section.Bytes())
}

func replaceSection(doc []byte, sectionName string, replacement []byte) ([]byte, error) {
	re := regexp.MustCompile(fmt.Sprintf(`(?s)<!-- BEGIN %v.* -->\n(.*?)<!-- END %v.* -->`, sectionName, sectionName))
	idx := re.FindSubmatchIndex(doc)
	if idx == nil {
		return nil, fmt.Errorf("could not find section %q", sectionName)
	}
	result := append([]byte(nil), doc[:idx[2]]...)
	result = append(result, replacement...)
	result = append(result, doc[idx[3]:]...)
	return result, nil
}
<|endoftext|>


<commit_before>// +build linux

// Package g25 contains GPIO drivers for the Acme Systems Aria G25
//
// The Aria G25 contains up to 60 GPIO pins. This package implements all GPIO
// operations such as getting/setting the value, setting the direction and
// changing the active low. The package provides a mapping between the
// pinnumber, the atmel ID and the kernel ID.
// https://www.acmesystems.it/aria
package g25

import (
	"fmt"
	"io/ioutil"
	"strconv"

	"github.com/advancedclimatesystems/io/gpio"
)

var w gpio.Watcher

// NewPin creates a new pin with a kernel ID based on the pin name found
// here: https://www.acmesystems.it/aria. It assumes the kernel has version 3.1x
// if this is not the case, use the NewPinV26 instead.
func NewPin(id string) (gpio.GPIO, error) {
	k, err := getKernelVersion()
	if err != nil {
		return nil, err
	}

	kernelID, err := getkernelID(k, id)
	if err != nil {
		return nil, err
	}

	if err := setupWatcher(); err != nil {
		return nil, err
	}

	// The file created by export is always called pio, followed by ic pin ID,
	// but without the fist character. So exporting N2 gives an file called pioC0.
	gpio := gpio.NewPin(kernelID, fmt.Sprintf("pio%v", g25Id[id].icPin[1:]), w)
	if err := gpio.Export(); err != nil {
		return nil, err
	}
	return gpio, nil
}

// setupWatcher creates a new watcher and starts it, if its not already running.
func setupWatcher() error {
	// A Watcher only needs to be setup once, but an error can't be handled in an
	// init function.
	var err error
	if w == nil {
		w, err = gpio.NewWatcher()
		if err != nil {
			return err
		}
		go func() {
			err = w.Watch()
			defer w.Close()
		}()
	}
	return err
}

// getKernelID returns the corrent kernel ID, based on the kernel version and id.
func getkernelID(k int, id string) (int, error) {
	pinID, ok := g25Id[id]
	if !ok {
		return 0, fmt.Errorf("id %v not known", id)
	}

	var kernelID int
	if k < 3 {
		kernelID = pinID.kernelID26
	} else {
		kernelID = pinID.kernelID31
	}
	return kernelID, nil
}

// getkernelVersion get s the kernel version from /proc/version
func getKernelVersion() (int, error) {
	data, err := ioutil.ReadFile("/proc/version")
	if err != nil || len(data) < 15 {
		return 0, err
	}
	// The 14th byte should be the major version, which is what we are loooking for.
	return strconv.Atoi(string(data[14]))
}

// g25Id provides a mapping between the "pin name" and all other indentifiers
// of a pin.
var g25Id = map[string]struct {
	// Names such as N2, N3, E10, E6
	pinName string
	// Names such as PC0, PC1, PC30, PC26. These are used to figure out the
	// name of the file created by exporting the pin.
	icPin string
	// Kernel ID for version 2.6.
	kernelID26 int
	// Kernel ID for version 3.1.
	kernelID31 int
}{
	"N2":  {"N2", "PC0", 96, 64},
	"N3":  {"N3", "PC1", 97, 65},
	"N4":  {"N4", "PC2", 98, 66},
	"N5":  {"N5", "PC3", 99, 67},
	"N6":  {"N6", "PC4", 100, 68},
	"N7":  {"N7", "PC5", 101, 69},
	"N8":  {"N8", "PC6", 102, 70},
	"N9":  {"N9", "PC7", 103, 71},
	"N10": {"N10", "PC8", 104, 72},
	"N11": {"N11", "PC9", 105, 73},
	"N12": {"N12", "PC10", 106, 74},
	"N13": {"N13", "PC11", 107, 75},
	"N14": {"N14", "PC12", 108, 76},
	"N15": {"N15", "PC13", 109, 77},
	"N16": {"N16", "PC14", 110, 78},
	"N17": {"N17", "PC15", 111, 79},
	"N18": {"N18", "PC16", 112, 80},
	"N19": {"N19", "PC17", 113, 81},
	"N20": {"N20", "PC18", 114, 82},
	"N21": {"N21", "PC19", 115, 83},
	"N22": {"N22", "PC20", 116, 84},
	"N23": {"N23", "PC21", 117, 85},

	"E2":  {"E2", "PC22", 118, 86},
	"E3":  {"E3", "PC23", 119, 87},
	"E4":  {"E4", "PC24", 120, 88},
	"E5":  {"E5", "PC25", 121, 89},
	"E6":  {"E6", "PC26", 122, 90},
	"E7":  {"E7", "PC27", 123, 91},
	"E8":  {"E8", "PC28", 124, 92},
	"E9":  {"E9", "PC29", 125, 93},
	"E10": {"E10", "PC30", 126, 94},
	"E11": {"E11", "PC31", 127, 95},

	"S2":  {"S2", "PA21", 53, 21},
	"S9":  {"S9", "PA14", 46, 14},
	"S10": {"S10", "PA13", 45, 13},
	"S11": {"S11", "PA12", 44, 12},
	"S12": {"S12", "PA11", 43, 11},
	"S15": {"S15", "PA8", 40, 8},
	"S16": {"S16", "PA7", 39, 7},
	"S17": {"S17", "PA6", 38, 6},
	"S18": {"S18", "PA5", 37, 5},
	"S20": {"S20", "PA3", 35, 3},
	"S21": {"S21", "PA2", 34, 2},
	"S22": {"S22", "PA1", 33, 1},
	"S23": {"S23", "PA0", 32, 0},

	"W9":  {"W9", "PA22", 54, 22},
	"W10": {"W10", "PA23", 55, 23},
	"W11": {"W11", "PA24", 56, 24},
	"W12": {"W12", "PA25", 57, 25},
	"W13": {"W13", "PA26", 58, 26},
	"W14": {"W14", "PA27", 59, 27},
	"W15": {"W15", "PA28", 60, 28},
	"W16": {"W16", "PA29", 61, 29},
	"W17": {"W17", "PA30", 62, 30},
	"W18": {"W18", "PA31", 63, 31},
	"W20": {"W20", "PB11", 75, 43},
	"W21": {"W21", "PB12", 76, 44},
	"W22": {"W22", "PB13", 77, 45},
	"W23": {"W23", "PB14", 78, 46},
}
<commit_msg>adds missing gpio pins<commit_after>// +build linux

// Package g25 contains GPIO drivers for the Acme Systems Aria G25
//
// The Aria G25 contains up to 60 GPIO pins. This package implements all GPIO
// operations such as getting/setting the value, setting the direction and
// changing the active low. The package provides a mapping between the
// pinnumber, the atmel ID and the kernel ID.
// https://www.acmesystems.it/aria
package g25

import (
	"fmt"
	"io/ioutil"
	"strconv"

	"github.com/advancedclimatesystems/io/gpio"
)

var w gpio.Watcher

// NewPin creates a new pin with a kernel ID based on the pin name found
// here: https://www.acmesystems.it/aria. It assumes the kernel has version 3.1x
// if this is not the case, use the NewPinV26 instead.
func NewPin(id string) (gpio.GPIO, error) {
	k, err := getKernelVersion()
	if err != nil {
		return nil, err
	}

	kernelID, err := getkernelID(k, id)
	if err != nil {
		return nil, err
	}

	if err := setupWatcher(); err != nil {
		return nil, err
	}

	// The file created by export is always called pio, followed by ic pin ID,
	// but without the fist character. So exporting N2 gives an file called pioC0.
	gpio := gpio.NewPin(kernelID, fmt.Sprintf("pio%v", g25Id[id].icPin[1:]), w)
	if err := gpio.Export(); err != nil {
		return nil, err
	}
	return gpio, nil
}

// setupWatcher creates a new watcher and starts it, if its not already running.
func setupWatcher() error {
	// A Watcher only needs to be setup once, but an error can't be handled in an
	// init function.
	var err error
	if w == nil {
		w, err = gpio.NewWatcher()
		if err != nil {
			return err
		}
		go func() {
			err = w.Watch()
			defer w.Close()
		}()
	}
	return err
}

// getKernelID returns the corrent kernel ID, based on the kernel version and id.
func getkernelID(k int, id string) (int, error) {
	pinID, ok := g25Id[id]
	if !ok {
		return 0, fmt.Errorf("id %v not known", id)
	}

	var kernelID int
	if k < 3 {
		kernelID = pinID.kernelID26
	} else {
		kernelID = pinID.kernelID31
	}
	return kernelID, nil
}

// getkernelVersion get s the kernel version from /proc/version
func getKernelVersion() (int, error) {
	data, err := ioutil.ReadFile("/proc/version")
	if err != nil || len(data) < 15 {
		return 0, err
	}
	// The 14th byte should be the major version, which is what we are loooking for.
	return strconv.Atoi(string(data[14]))
}

// g25Id provides a mapping between the "pin name" and all other indentifiers
// of a pin.
var g25Id = map[string]struct {
	// Names such as N2, N3, E10, E6
	pinName string
	// Names such as PC0, PC1, PC30, PC26. These are used to figure out the
	// name of the file created by exporting the pin.
	icPin string
	// Kernel ID for version 2.6.
	kernelID26 int
	// Kernel ID for version 3.1.
	kernelID31 int
}{
	"N2":  {"N2", "PC0", 96, 64},
	"N3":  {"N3", "PC1", 97, 65},
	"N4":  {"N4", "PC2", 98, 66},
	"N5":  {"N5", "PC3", 99, 67},
	"N6":  {"N6", "PC4", 100, 68},
	"N7":  {"N7", "PC5", 101, 69},
	"N8":  {"N8", "PC6", 102, 70},
	"N9":  {"N9", "PC7", 103, 71},
	"N10": {"N10", "PC8", 104, 72},
	"N11": {"N11", "PC9", 105, 73},
	"N12": {"N12", "PC10", 106, 74},
	"N13": {"N13", "PC11", 107, 75},
	"N14": {"N14", "PC12", 108, 76},
	"N15": {"N15", "PC13", 109, 77},
	"N16": {"N16", "PC14", 110, 78},
	"N17": {"N17", "PC15", 111, 79},
	"N18": {"N18", "PC16", 112, 80},
	"N19": {"N19", "PC17", 113, 81},
	"N20": {"N20", "PC18", 114, 82},
	"N21": {"N21", "PC19", 115, 83},
	"N22": {"N22", "PC20", 116, 84},
	"N23": {"N23", "PC21", 117, 85},

	"E2":  {"E2", "PC22", 118, 86},
	"E3":  {"E3", "PC23", 119, 87},
	"E4":  {"E4", "PC24", 120, 88},
	"E5":  {"E5", "PC25", 121, 89},
	"E6":  {"E6", "PC26", 122, 90},
	"E7":  {"E7", "PC27", 123, 91},
	"E8":  {"E8", "PC28", 124, 92},
	"E9":  {"E9", "PC29", 125, 93},
	"E10": {"E10", "PC30", 126, 94},
	"E11": {"E11", "PC31", 127, 95},

	"S2":  {"S2", "PA21", 53, 21},
	"S3":  {"S3", "PA20", 52, 20},
	"S4":  {"S4", "PA19", 51, 19},
	"S5":  {"S5", "PA18", 50, 18},
	"S6":  {"S6", "PA17", 49, 17},
	"S7":  {"S7", "PA16", 48, 16},
	"S8":  {"S8", "PA15", 47, 15},
	"S9":  {"S9", "PA14", 46, 14},
	"S10": {"S10", "PA13", 45, 13},
	"S11": {"S11", "PA12", 44, 12},
	"S12": {"S12", "PA11", 43, 11},
	"S15": {"S15", "PA8", 40, 8},
	"S16": {"S16", "PA7", 39, 7},
	"S17": {"S17", "PA6", 38, 6},
	"S18": {"S18", "PA5", 37, 5},
	"S19": {"S19", "PA4", 36, 4},
	"S20": {"S20", "PA3", 35, 3},
	"S21": {"S21", "PA2", 34, 2},
	"S22": {"S22", "PA1", 33, 1},
	"S23": {"S23", "PA0", 32, 0},

	"W9":  {"W9", "PA22", 54, 22},
	"W10": {"W10", "PA23", 55, 23},
	"W11": {"W11", "PA24", 56, 24},
	"W12": {"W12", "PA25", 57, 25},
	"W13": {"W13", "PA26", 58, 26},
	"W14": {"W14", "PA27", 59, 27},
	"W15": {"W15", "PA28", 60, 28},
	"W16": {"W16", "PA29", 61, 29},
	"W17": {"W17", "PA30", 62, 30},
	"W18": {"W18", "PA31", 63, 31},
	"W20": {"W20", "PB11", 75, 43},
	"W21": {"W21", "PB12", 76, 44},
	"W22": {"W22", "PB13", 77, 45},
	"W23": {"W23", "PB14", 78, 46},
}
<|endoftext|>


<commit_before>// Copyright 2015 The Serulian 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 srg

import (
	"fmt"
	"strings"

	"github.com/serulian/compiler/compilercommon"
	"github.com/serulian/compiler/compilergraph"
	"github.com/serulian/compiler/compilerutil"
	"github.com/serulian/compiler/parser"
)

// SRGTypeRef represents a type reference defined in the SRG.
type SRGTypeRef struct {
	compilergraph.GraphNode
	srg *SRG // The parent SRG.
}

type TypeRefKind int

const (
	TypeRefNullable TypeRefKind = iota // A nullable type.
	TypeRefStream                      // A stream type.
	TypeRefPath                        // A normal path type. May have generics.
)

// Location returns the source location for this type ref.
func (t SRGTypeRef) Location() compilercommon.SourceAndLocation {
	return salForNode(t.GraphNode)
}

// ResolveType attempts to resolve the type path referenced by this type ref.
// Panics if this is not a RefKind of TypeRefPath.
func (t SRGTypeRef) ResolveType() (SRGType, bool) {
	compilerutil.DCHECK(func() bool { return t.RefKind() == TypeRefPath }, "Expected type ref path")

	var resolvePathPieces = make([]string, 0)
	var currentPath compilergraph.GraphNode = t.GraphNode.
		GetNode(parser.NodeTypeReferencePath).
		GetNode(parser.NodeIdentifierPathRoot)

	for {
		// Add the path piece to the array.
		name := currentPath.Get(parser.NodeIdentifierAccessName)
		resolvePathPieces = append([]string{name}, resolvePathPieces...)

		// If there is a source, continue searching.
		source, found := currentPath.TryGetNode(parser.NodeIdentifierAccessSource)
		if !found {
			break
		}

		currentPath = source
	}

	// Find the parent module.
	srgModule, found := t.srg.FindModuleBySource(t.Location().Source())
	if !found {
		panic(fmt.Sprintf("Unknown parent module: %s", t.Location().Source()))
	}

	// Resolve the type path under the module.
	resolvePath := strings.Join(resolvePathPieces, ".")
	return srgModule.ResolveType(resolvePath)
}

// InnerReference returns the inner type reference, if this is a nullable or stream.
func (t SRGTypeRef) InnerReference() SRGTypeRef {
	compilerutil.DCHECK(func() bool { return t.RefKind() != TypeRefPath }, "Expected non-path")
	return SRGTypeRef{t.GraphNode.GetNode(parser.NodeTypeReferenceInnerType), t.srg}
}

// Generics returns the generics defined on this type ref.
// Panics if this is not a RefKind of TypeRefPath.
func (t SRGTypeRef) Generics() []SRGTypeRef {
	compilerutil.DCHECK(func() bool { return t.RefKind() == TypeRefPath }, "Expected type ref path")
	return t.subReferences(parser.NodeTypeReferenceGeneric)
}

// subReferences returns the subreferences found off of the given predicate, if any.
func (t SRGTypeRef) subReferences(predicate string) []SRGTypeRef {
	subRefs := make([]SRGTypeRef, 0)
	it := t.GraphNode.StartQuery().Out(predicate).BuildNodeIterator()
	for it.Next() {
		subRefs = append(subRefs, SRGTypeRef{it.Node, t.srg})
	}
	return subRefs
}

// RefKind returns the kind of this type reference.
func (t SRGTypeRef) RefKind() TypeRefKind {
	nodeKind := t.GraphNode.Kind.(parser.NodeType)
	switch nodeKind {
	case parser.NodeTypeStream:
		return TypeRefStream

	case parser.NodeTypeNullable:
		return TypeRefNullable

	case parser.NodeTypeTypeReference:
		return TypeRefPath

	default:
		panic(fmt.Sprintf("Unknown kind of type reference node %v", nodeKind))
	}
}
<commit_msg>Make module lookup faster in type ref resolution<commit_after>// Copyright 2015 The Serulian 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 srg

import (
	"fmt"
	"strings"

	"github.com/serulian/compiler/compilercommon"
	"github.com/serulian/compiler/compilergraph"
	"github.com/serulian/compiler/compilerutil"
	"github.com/serulian/compiler/parser"
)

// SRGTypeRef represents a type reference defined in the SRG.
type SRGTypeRef struct {
	compilergraph.GraphNode
	srg *SRG // The parent SRG.
}

type TypeRefKind int

const (
	TypeRefNullable TypeRefKind = iota // A nullable type.
	TypeRefStream                      // A stream type.
	TypeRefPath                        // A normal path type. May have generics.
)

// Location returns the source location for this type ref.
func (t SRGTypeRef) Location() compilercommon.SourceAndLocation {
	return salForNode(t.GraphNode)
}

// ResolveType attempts to resolve the type path referenced by this type ref.
// Panics if this is not a RefKind of TypeRefPath.
func (t SRGTypeRef) ResolveType() (SRGType, bool) {
	compilerutil.DCHECK(func() bool { return t.RefKind() == TypeRefPath }, "Expected type ref path")

	var resolvePathPieces = make([]string, 0)
	var currentPath compilergraph.GraphNode = t.GraphNode.
		GetNode(parser.NodeTypeReferencePath).
		GetNode(parser.NodeIdentifierPathRoot)

	for {
		// Add the path piece to the array.
		name := currentPath.Get(parser.NodeIdentifierAccessName)
		resolvePathPieces = append([]string{name}, resolvePathPieces...)

		// If there is a source, continue searching.
		source, found := currentPath.TryGetNode(parser.NodeIdentifierAccessSource)
		if !found {
			break
		}

		currentPath = source
	}

	// Find the parent module.
	source := compilercommon.InputSource(t.GraphNode.Get(parser.NodePredicateSource))
	srgModule, found := t.srg.FindModuleBySource(source)
	if !found {
		panic(fmt.Sprintf("Unknown parent module: %s", source))
	}

	// Resolve the type path under the module.
	resolvePath := strings.Join(resolvePathPieces, ".")
	return srgModule.ResolveType(resolvePath)
}

// InnerReference returns the inner type reference, if this is a nullable or stream.
func (t SRGTypeRef) InnerReference() SRGTypeRef {
	compilerutil.DCHECK(func() bool { return t.RefKind() != TypeRefPath }, "Expected non-path")
	return SRGTypeRef{t.GraphNode.GetNode(parser.NodeTypeReferenceInnerType), t.srg}
}

// Generics returns the generics defined on this type ref.
// Panics if this is not a RefKind of TypeRefPath.
func (t SRGTypeRef) Generics() []SRGTypeRef {
	compilerutil.DCHECK(func() bool { return t.RefKind() == TypeRefPath }, "Expected type ref path")
	return t.subReferences(parser.NodeTypeReferenceGeneric)
}

// subReferences returns the subreferences found off of the given predicate, if any.
func (t SRGTypeRef) subReferences(predicate string) []SRGTypeRef {
	subRefs := make([]SRGTypeRef, 0)
	it := t.GraphNode.StartQuery().Out(predicate).BuildNodeIterator()
	for it.Next() {
		subRefs = append(subRefs, SRGTypeRef{it.Node, t.srg})
	}
	return subRefs
}

// RefKind returns the kind of this type reference.
func (t SRGTypeRef) RefKind() TypeRefKind {
	nodeKind := t.GraphNode.Kind.(parser.NodeType)
	switch nodeKind {
	case parser.NodeTypeStream:
		return TypeRefStream

	case parser.NodeTypeNullable:
		return TypeRefNullable

	case parser.NodeTypeTypeReference:
		return TypeRefPath

	default:
		panic(fmt.Sprintf("Unknown kind of type reference node %v", nodeKind))
	}
}
<|endoftext|>


<commit_before>package git

import (
	"context"
	"fmt"
	"io"
	"io/ioutil"

	. "github.com/polydawn/go-errcat"
	"gopkg.in/src-d/go-git.v4/plumbing/filemode"
	"gopkg.in/src-d/go-git.v4/plumbing/object"

	"go.polydawn.net/go-timeless-api"
	"go.polydawn.net/go-timeless-api/rio"
	"go.polydawn.net/go-timeless-api/util"
	"go.polydawn.net/rio/config"
	"go.polydawn.net/rio/fs"
	"go.polydawn.net/rio/fs/osfs"
	"go.polydawn.net/rio/fsOp"
	"go.polydawn.net/rio/transmat/mixins/cache"
	"go.polydawn.net/rio/transmat/mixins/filters"
	"go.polydawn.net/rio/transmat/mixins/fshash"
	gitWarehouse "go.polydawn.net/rio/warehouse/impl/git"
)

var (
	_ rio.UnpackFunc = Unpack
)

func Unpack(
	ctx context.Context, // Long-running call.  Cancellable.
	wareID api.WareID, // What wareID to fetch for unpacking.
	path string, // Where to unpack the fileset (absolute path).
	filt api.FilesetFilters, // Optionally: filters we should apply while unpacking.
	placementMode rio.PlacementMode, // Optionally: a placement mode (default is "copy").
	warehouses []api.WarehouseAddr, // Warehouses we can try to fetch from.
	mon rio.Monitor, // Optionally: callbacks for progress monitoring.
) (_ api.WareID, err error) {
	if mon.Chan != nil {
		defer close(mon.Chan)
	}
	defer RequireErrorHasCategory(&err, rio.ErrorCategory(""))

	// Sanitize arguments.
	if wareID.Type != PackType {
		return api.WareID{}, Errorf(rio.ErrUsage, "this transmat implementation only supports packtype %q (not %q)", PackType, wareID.Type)
	}
	if placementMode == "" {
		placementMode = rio.Placement_Copy
	}
	// Wrap the direct unpack func with cache behavior; call that.
	return cache.Lrn2Cache(
		osfs.New(config.GetCacheBasePath()),
		unpack,
	)(ctx, wareID, path, filt, placementMode, warehouses, mon)
}

func unpack(
	ctx context.Context,
	wareID api.WareID,
	path string,
	filt api.FilesetFilters,
	placementMode rio.PlacementMode,
	warehouses []api.WarehouseAddr,
	mon rio.Monitor,
) (_ api.WareID, err error) {
	defer RequireErrorHasCategory(&err, rio.ErrorCategory(""))

	// Sanitize arguments.
	path2 := fs.MustAbsolutePath(path)
	filt2, err := apiutil.ProcessFilters(filt, apiutil.FilterPurposeUnpack)
	if err != nil {
		return api.WareID{}, Errorf(rio.ErrUsage, "invalid filter specification: %s", err)
	}

	// Pick a warehouse and get a reader.
	//  This is a *very* expensive operation for git.  It's less
	//  of "pick a warehouse" and more "download the whole thing and hope we
	//  get what we wanted" (which is very ironic for a system that has
	//  a CAS system on its inside, yes).
	whCtrl, err := pick(ctx,
		wareID,
		warehouses,
		osfs.New(config.GetCacheBasePath().Join(fs.MustRelPath("git/objs"))),
		mon,
	)
	if err != nil {
		return api.WareID{}, err
	}

	// Get submodule config.  Fetch them all.
	submodules, err := whCtrl.Submodules(wareID.Hash)
	if err != nil {
		return api.WareID{}, err
	}
	// We'll organize them by path now; only thing that's useful.
	submoduleCtrls := map[string]*gitWarehouse.Controller{}
	for _, submCfg := range submodules {
		// TODO it would be dreamy to parallelize this.
		whCtrl, err := pick(ctx,
			api.WareID{"git", submCfg.Hash},
			[]api.WarehouseAddr{api.WarehouseAddr(submCfg.URL)},
			osfs.New(config.GetCacheBasePath().Join(fs.MustRelPath("git/objs"))),
			mon,
		)
		if err != nil {
			return api.WareID{}, err
		}
		submoduleCtrls[submCfg.Path] = whCtrl
	}

	// Open a tree to walk in the main repo.
	//  We'll do submodule checkouts somewhere deep in the middle of this.
	tr, err := whCtrl.GetTree(wareID.Hash)
	if err != nil {
		panic(err)
	}

	// Construct filesystem wrapper to use for all our ops.
	afs := osfs.New(path2)

	// Walk.
	if err := unpackOneRepo(ctx, tr, afs, true, filt2, submoduleCtrls, mon); err != nil {
		return api.WareID{}, err
	}

	// That's it.  Checkout should have already checked the hash, so we just return it.
	return wareID, nil
}

func unpackOneRepo(
	ctx context.Context,
	tr *object.Tree,
	afs fs.FS,
	isRoot bool, // if true, will recurse for submodules (with this set to false).
	filt apiutil.FilesetFilters,
	submoduleCtrls map[string]*gitWarehouse.Controller,
	mon rio.Monitor,
) (err error) {
	tw := object.NewTreeWalker(tr, true, nil)

	// Make the root dir.  Git doesn't have metadata for the tree root.
	conjuredFmeta := fshash.DefaultDirMetadata()
	filters.Apply(filt, &conjuredFmeta)
	if err := fsOp.PlaceFile(afs, conjuredFmeta, nil, filt.SkipChown); err != nil {
		return Errorf(rio.ErrInoperablePath, "error while unpacking: %s", err)
	}

	// Extract.
	// Iterate over each entry, mutating filesystem as we go.
	dirs := make([]fs.RelPath, 1, 200) // Keep for dir time repair at end.
	dirs[0] = fs.RelPath{}
	for {
		fmeta := fs.Metadata{}
		name, te, err := tw.Next()

		// Check for done.
		if err == io.EOF {
			break // sucess!  end of archive.
		}
		if err != nil {
			return Errorf(rio.ErrWareCorrupt, "corrupt git tree: %s", err)
		}
		if ctx.Err() != nil {
			return Errorf(rio.ErrCancelled, "cancelled")
		}
		//fmt.Fprintf(os.Stderr, "walking git tree %s -- %#v\n", name, te)

		// Reshuffle metainfo to our default format.
		fmeta.Name = fs.MustRelPath(name)
		fmeta.Uid = 1000
		fmeta.Gid = 1000
		switch te.Mode {
		case filemode.Dir:
			fmeta.Type = fs.Type_Dir
			fmeta.Perms = 0755
			dirs = append(dirs, fmeta.Name)
		case filemode.Regular:
			fmeta.Type = fs.Type_File
			fmeta.Perms = 0644
		case filemode.Executable:
			fmeta.Type = fs.Type_File
			fmeta.Perms = 0755
		case filemode.Symlink:
			fmeta.Type = fs.Type_Symlink
			fmeta.Perms = 0644
			// Hang on, extracting a symlink is actually rough.
			tf, err := tr.TreeEntryFile(&te)
			if err != nil {
				return Errorf(rio.ErrWareCorrupt, "corrupt git tree: %s", err)
			}
			reader, err := tf.Blob.Reader()
			if err != nil {
				return Errorf(rio.ErrWareCorrupt, "corrupt git tree: %s", err)
			}
			blob, err := ioutil.ReadAll(reader)
			if err != nil {
				return Errorf(rio.ErrWareCorrupt, "corrupt git tree: %s", err)
			}
			fmeta.Linkname = string(blob)
		case filemode.Submodule:
			// Ooowee!  Recurse time!
			submCtrl, ok := submoduleCtrls[name]
			if !ok {
				return Errorf(rio.ErrWareCorrupt, "gitlink found at path %q but no matching config in .gitmodules", name)
			}
			submTr, err := submCtrl.GetTree(te.Hash.String())
			if err != nil {
				panic(err)
			}
			submFs := osfs.New(afs.BasePath().Join(fmeta.Name))
			if err := unpackOneRepo(ctx, submTr, submFs, false, filt, nil, mon); err != nil {
				return err
			}
			continue
		case filemode.Empty:
			fallthrough
		case filemode.Deprecated:
			fallthrough
		default:
			panic(fmt.Errorf("unknown git filemode %#v", te.Mode))
		}
		fmeta.Mtime = apiutil.DefaultMtime // git doesn't have time info

		// Apply filters.
		filters.Apply(filt, &fmeta)

		// Place the file.
		switch fmeta.Type {
		case fs.Type_File:
			tf, err := tr.TreeEntryFile(&te)
			if err != nil {
				return Errorf(rio.ErrWareCorrupt, "corrupt git tree: %s", err)
			}
			reader, err := tf.Blob.Reader()
			if err != nil {
				return Errorf(rio.ErrWareCorrupt, "corrupt git tree: %s", err)
			}
			if err := fsOp.PlaceFile(afs, fmeta, reader, filt.SkipChown); err != nil {
				return Errorf(rio.ErrInoperablePath, "error while unpacking: %s", err)
			}
			reader.Close()
		default:
			if err := fsOp.PlaceFile(afs, fmeta, nil, filt.SkipChown); err != nil {
				return Errorf(rio.ErrInoperablePath, "error while unpacking: %s", err)
			}
		}
	}

	// Cleanup dir times with a post-order traversal over the bucket.
	//  Files and dirs placed inside dirs cause the parent's mtime to update, so we have to re-pave them.
	for i := len(dirs) - 1; i >= 0; i-- {
		if err := afs.SetTimesNano(dirs[i], fs.DefaultAtime, fs.DefaultAtime); err != nil {
			return Errorf(rio.ErrInoperablePath, "error while unpacking: %s", err)
		}
	}

	return nil
}
<commit_msg>git: don't deep recurse for submodules.<commit_after>package git

import (
	"context"
	"fmt"
	"io"
	"io/ioutil"

	. "github.com/polydawn/go-errcat"
	"gopkg.in/src-d/go-git.v4/plumbing/filemode"
	"gopkg.in/src-d/go-git.v4/plumbing/object"

	"go.polydawn.net/go-timeless-api"
	"go.polydawn.net/go-timeless-api/rio"
	"go.polydawn.net/go-timeless-api/util"
	"go.polydawn.net/rio/config"
	"go.polydawn.net/rio/fs"
	"go.polydawn.net/rio/fs/osfs"
	"go.polydawn.net/rio/fsOp"
	"go.polydawn.net/rio/transmat/mixins/cache"
	"go.polydawn.net/rio/transmat/mixins/filters"
	"go.polydawn.net/rio/transmat/mixins/fshash"
	gitWarehouse "go.polydawn.net/rio/warehouse/impl/git"
)

var (
	_ rio.UnpackFunc = Unpack
)

func Unpack(
	ctx context.Context, // Long-running call.  Cancellable.
	wareID api.WareID, // What wareID to fetch for unpacking.
	path string, // Where to unpack the fileset (absolute path).
	filt api.FilesetFilters, // Optionally: filters we should apply while unpacking.
	placementMode rio.PlacementMode, // Optionally: a placement mode (default is "copy").
	warehouses []api.WarehouseAddr, // Warehouses we can try to fetch from.
	mon rio.Monitor, // Optionally: callbacks for progress monitoring.
) (_ api.WareID, err error) {
	if mon.Chan != nil {
		defer close(mon.Chan)
	}
	defer RequireErrorHasCategory(&err, rio.ErrorCategory(""))

	// Sanitize arguments.
	if wareID.Type != PackType {
		return api.WareID{}, Errorf(rio.ErrUsage, "this transmat implementation only supports packtype %q (not %q)", PackType, wareID.Type)
	}
	if placementMode == "" {
		placementMode = rio.Placement_Copy
	}
	// Wrap the direct unpack func with cache behavior; call that.
	return cache.Lrn2Cache(
		osfs.New(config.GetCacheBasePath()),
		unpack,
	)(ctx, wareID, path, filt, placementMode, warehouses, mon)
}

func unpack(
	ctx context.Context,
	wareID api.WareID,
	path string,
	filt api.FilesetFilters,
	placementMode rio.PlacementMode,
	warehouses []api.WarehouseAddr,
	mon rio.Monitor,
) (_ api.WareID, err error) {
	defer RequireErrorHasCategory(&err, rio.ErrorCategory(""))

	// Sanitize arguments.
	path2 := fs.MustAbsolutePath(path)
	filt2, err := apiutil.ProcessFilters(filt, apiutil.FilterPurposeUnpack)
	if err != nil {
		return api.WareID{}, Errorf(rio.ErrUsage, "invalid filter specification: %s", err)
	}

	// Pick a warehouse and get a reader.
	//  This is a *very* expensive operation for git.  It's less
	//  of "pick a warehouse" and more "download the whole thing and hope we
	//  get what we wanted" (which is very ironic for a system that has
	//  a CAS system on its inside, yes).
	whCtrl, err := pick(ctx,
		wareID,
		warehouses,
		osfs.New(config.GetCacheBasePath().Join(fs.MustRelPath("git/objs"))),
		mon,
	)
	if err != nil {
		return api.WareID{}, err
	}

	// Get submodule config.  Fetch them all.
	submodules, err := whCtrl.Submodules(wareID.Hash)
	if err != nil {
		return api.WareID{}, err
	}
	// We'll organize them by path now; only thing that's useful.
	submoduleCtrls := map[string]*gitWarehouse.Controller{}
	for _, submCfg := range submodules {
		// TODO it would be dreamy to parallelize this.
		whCtrl, err := pick(ctx,
			api.WareID{"git", submCfg.Hash},
			[]api.WarehouseAddr{api.WarehouseAddr(submCfg.URL)},
			osfs.New(config.GetCacheBasePath().Join(fs.MustRelPath("git/objs"))),
			mon,
		)
		if err != nil {
			return api.WareID{}, err
		}
		submoduleCtrls[submCfg.Path] = whCtrl
	}

	// Open a tree to walk in the main repo.
	//  We'll do submodule checkouts somewhere deep in the middle of this.
	tr, err := whCtrl.GetTree(wareID.Hash)
	if err != nil {
		panic(err)
	}

	// Construct filesystem wrapper to use for all our ops.
	afs := osfs.New(path2)

	// Walk.
	if err := unpackOneRepo(ctx, tr, afs, true, filt2, submoduleCtrls, mon); err != nil {
		return api.WareID{}, err
	}

	// That's it.  Checkout should have already checked the hash, so we just return it.
	return wareID, nil
}

func unpackOneRepo(
	ctx context.Context,
	tr *object.Tree,
	afs fs.FS,
	isRoot bool, // if true, will recurse for submodules (with this set to false).
	filt apiutil.FilesetFilters,
	submoduleCtrls map[string]*gitWarehouse.Controller,
	mon rio.Monitor,
) (err error) {
	tw := object.NewTreeWalker(tr, true, nil)

	// Make the root dir.  Git doesn't have metadata for the tree root.
	conjuredFmeta := fshash.DefaultDirMetadata()
	filters.Apply(filt, &conjuredFmeta)
	if err := fsOp.PlaceFile(afs, conjuredFmeta, nil, filt.SkipChown); err != nil {
		return Errorf(rio.ErrInoperablePath, "error while unpacking: %s", err)
	}

	// Extract.
	// Iterate over each entry, mutating filesystem as we go.
	dirs := make([]fs.RelPath, 1, 200) // Keep for dir time repair at end.
	dirs[0] = fs.RelPath{}
	for {
		fmeta := fs.Metadata{}
		name, te, err := tw.Next()

		// Check for done.
		if err == io.EOF {
			break // sucess!  end of archive.
		}
		if err != nil {
			return Errorf(rio.ErrWareCorrupt, "corrupt git tree: %s", err)
		}
		if ctx.Err() != nil {
			return Errorf(rio.ErrCancelled, "cancelled")
		}
		//fmt.Fprintf(os.Stderr, "walking git tree %s -- %#v\n", name, te)

		// Reshuffle metainfo to our default format.
		fmeta.Name = fs.MustRelPath(name)
		fmeta.Uid = 1000
		fmeta.Gid = 1000
		switch te.Mode {
		case filemode.Dir:
			fmeta.Type = fs.Type_Dir
			fmeta.Perms = 0755
			dirs = append(dirs, fmeta.Name)
		case filemode.Regular:
			fmeta.Type = fs.Type_File
			fmeta.Perms = 0644
		case filemode.Executable:
			fmeta.Type = fs.Type_File
			fmeta.Perms = 0755
		case filemode.Symlink:
			fmeta.Type = fs.Type_Symlink
			fmeta.Perms = 0644
			// Hang on, extracting a symlink is actually rough.
			tf, err := tr.TreeEntryFile(&te)
			if err != nil {
				return Errorf(rio.ErrWareCorrupt, "corrupt git tree: %s", err)
			}
			reader, err := tf.Blob.Reader()
			if err != nil {
				return Errorf(rio.ErrWareCorrupt, "corrupt git tree: %s", err)
			}
			blob, err := ioutil.ReadAll(reader)
			if err != nil {
				return Errorf(rio.ErrWareCorrupt, "corrupt git tree: %s", err)
			}
			fmeta.Linkname = string(blob)
		case filemode.Submodule:
			// Ooowee!  Recurse time!
			if !isRoot {
				// Except of course if we're already a submodule, in which case no.
				// Like git, we will make the empty dir, though.
				fmeta.Type = fs.Type_Dir
				fmeta.Perms = 0755
				dirs = append(dirs, fmeta.Name)
				break
			}
			submCtrl, ok := submoduleCtrls[name]
			if !ok {
				return Errorf(rio.ErrWareCorrupt, "gitlink found at path %q but no matching config in .gitmodules", name)
			}
			submTr, err := submCtrl.GetTree(te.Hash.String())
			if err != nil {
				panic(err)
			}
			submFs := osfs.New(afs.BasePath().Join(fmeta.Name))
			if err := unpackOneRepo(ctx, submTr, submFs, false, filt, nil, mon); err != nil {
				return err
			}
			continue
		case filemode.Empty:
			fallthrough
		case filemode.Deprecated:
			fallthrough
		default:
			panic(fmt.Errorf("unknown git filemode %#v", te.Mode))
		}
		fmeta.Mtime = apiutil.DefaultMtime // git doesn't have time info

		// Apply filters.
		filters.Apply(filt, &fmeta)

		// Place the file.
		switch fmeta.Type {
		case fs.Type_File:
			tf, err := tr.TreeEntryFile(&te)
			if err != nil {
				return Errorf(rio.ErrWareCorrupt, "corrupt git tree: %s", err)
			}
			reader, err := tf.Blob.Reader()
			if err != nil {
				return Errorf(rio.ErrWareCorrupt, "corrupt git tree: %s", err)
			}
			if err := fsOp.PlaceFile(afs, fmeta, reader, filt.SkipChown); err != nil {
				return Errorf(rio.ErrInoperablePath, "error while unpacking: %s", err)
			}
			reader.Close()
		default:
			if err := fsOp.PlaceFile(afs, fmeta, nil, filt.SkipChown); err != nil {
				return Errorf(rio.ErrInoperablePath, "error while unpacking: %s", err)
			}
		}
	}

	// Cleanup dir times with a post-order traversal over the bucket.
	//  Files and dirs placed inside dirs cause the parent's mtime to update, so we have to re-pave them.
	for i := len(dirs) - 1; i >= 0; i-- {
		if err := afs.SetTimesNano(dirs[i], fs.DefaultAtime, fs.DefaultAtime); err != nil {
			return Errorf(rio.ErrInoperablePath, "error while unpacking: %s", err)
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package git

import (
	"context"
	"fmt"
	"io"

	. "github.com/polydawn/go-errcat"
	"gopkg.in/src-d/go-git.v4/plumbing/filemode"
	"gopkg.in/src-d/go-git.v4/plumbing/object"

	"go.polydawn.net/go-timeless-api"
	"go.polydawn.net/go-timeless-api/rio"
	"go.polydawn.net/go-timeless-api/util"
	"go.polydawn.net/rio/config"
	"go.polydawn.net/rio/fs"
	"go.polydawn.net/rio/fs/osfs"
	"go.polydawn.net/rio/fsOp"
	"go.polydawn.net/rio/transmat/mixins/cache"
	"go.polydawn.net/rio/transmat/mixins/filters"
	"go.polydawn.net/rio/transmat/mixins/fshash"
)

var (
	_ rio.UnpackFunc = Unpack
)

func Unpack(
	ctx context.Context, // Long-running call.  Cancellable.
	wareID api.WareID, // What wareID to fetch for unpacking.
	path string, // Where to unpack the fileset (absolute path).
	filt api.FilesetFilters, // Optionally: filters we should apply while unpacking.
	placementMode rio.PlacementMode, // Optionally: a placement mode (default is "copy").
	warehouses []api.WarehouseAddr, // Warehouses we can try to fetch from.
	mon rio.Monitor, // Optionally: callbacks for progress monitoring.
) (_ api.WareID, err error) {
	if mon.Chan != nil {
		defer close(mon.Chan)
	}
	defer RequireErrorHasCategory(&err, rio.ErrorCategory(""))

	// Sanitize arguments.
	if wareID.Type != PackType {
		return api.WareID{}, Errorf(rio.ErrUsage, "this transmat implementation only supports packtype %q (not %q)", PackType, wareID.Type)
	}
	if placementMode == "" {
		placementMode = rio.Placement_Copy
	}
	// Wrap the direct unpack func with cache behavior; call that.
	return cache.Lrn2Cache(
		osfs.New(config.GetCacheBasePath()),
		unpack,
	)(ctx, wareID, path, filt, placementMode, warehouses, mon)
}

func unpack(
	ctx context.Context,
	wareID api.WareID,
	path string,
	filt api.FilesetFilters,
	placementMode rio.PlacementMode,
	warehouses []api.WarehouseAddr,
	mon rio.Monitor,
) (_ api.WareID, err error) {
	defer RequireErrorHasCategory(&err, rio.ErrorCategory(""))

	// Sanitize arguments.
	path2 := fs.MustAbsolutePath(path)
	filt2, err := apiutil.ProcessFilters(filt, apiutil.FilterPurposeUnpack)
	if err != nil {
		return api.WareID{}, Errorf(rio.ErrUsage, "invalid filter specification: %s", err)
	}

	// Pick a warehouse and get a reader.
	//  This is a *very* expensive operation for git.  It's less
	//  of "pick a warehouse" and more "download the whole thing and hope we
	//  get what we wanted" (which is very ironic for a system that has
	//  a CAS system on its inside, yes).
	whCtrl, err := pick(ctx,
		wareID,
		warehouses,
		osfs.New(config.GetCacheBasePath().Join(fs.MustRelPath("git/objs"))),
		mon,
	)
	if err != nil {
		return api.WareID{}, err
	}
	tr, err := whCtrl.GetTree(wareID.Hash)
	if err != nil {
		panic(err)
	}
	tw := object.NewTreeWalker(tr, true, nil)

	// Construct filesystem wrapper to use for all our ops.
	afs := osfs.New(path2)

	// Make the root dir.  Git doesn't have metadata for the tree root.
	conjuredFmeta := fshash.DefaultDirMetadata()
	filters.Apply(filt2, &conjuredFmeta)
	if err := fsOp.PlaceFile(afs, conjuredFmeta, nil, filt2.SkipChown); err != nil {
		return api.WareID{}, Errorf(rio.ErrInoperablePath, "error while unpacking: %s", err)
	}

	// Extract.
	// Iterate over each entry, mutating filesystem as we go.
	for {
		fmeta := fs.Metadata{}
		name, te, err := tw.Next()

		// Check for done.
		if err == io.EOF {
			break // sucess!  end of archive.
		}
		if err != nil {
			return api.WareID{}, Errorf(rio.ErrWareCorrupt, "corrupt git tree: %s", err)
		}
		if ctx.Err() != nil {
			return api.WareID{}, Errorf(rio.ErrCancelled, "cancelled")
		}
		//fmt.Fprintf(os.Stderr, "walking git tree %s -- %#v\n", name, te)

		// Reshuffle metainfo to our default format.
		fmeta.Name = fs.MustRelPath(name)
		switch te.Mode {
		case filemode.Dir:
			fmeta.Type = fs.Type_Dir
			fmeta.Perms = 0644
		case filemode.Regular:
			fmeta.Type = fs.Type_File
			fmeta.Perms = 0644
		case filemode.Executable:
			fmeta.Type = fs.Type_File
			fmeta.Perms = 0755
		case filemode.Symlink:
			fmeta.Type = fs.Type_Symlink
			fmeta.Perms = 0644
			fmeta.Linkname = "TODO" // TODO ?!?!
		case filemode.Submodule:
			// TODO
			continue
		case filemode.Empty:
			fallthrough
		case filemode.Deprecated:
			fallthrough
		default:
			panic(fmt.Errorf("unknown git filemode %#v", te.Mode))
		}
		fmeta.Mtime = apiutil.DefaultMtime // git doesn't have time info

		// Apply filters.
		filters.Apply(filt2, &fmeta)

		// Place the file.
		switch fmeta.Type {
		case fs.Type_File:
			tf, err := tr.TreeEntryFile(&te)
			if err != nil {
				return api.WareID{}, Errorf(rio.ErrWareCorrupt, "corrupt git tree: %s", err)
			}
			reader, err := tf.Blob.Reader()
			if err != nil {
				return api.WareID{}, Errorf(rio.ErrWareCorrupt, "corrupt git tree: %s", err)
			}
			if err := fsOp.PlaceFile(afs, fmeta, reader, filt2.SkipChown); err != nil {
				return api.WareID{}, Errorf(rio.ErrInoperablePath, "error while unpacking: %s", err)
			}
			reader.Close()
		default:
			if err := fsOp.PlaceFile(afs, fmeta, nil, filt2.SkipChown); err != nil {
				return api.WareID{}, Errorf(rio.ErrInoperablePath, "error while unpacking: %s", err)
			}
		}
	}

	// Cleanup dir times with a post-order traversal over the bucket.
	//  Files and dirs placed inside dirs cause the parent's mtime to update, so we have to re-pave them.
	// TODO we don't have the state kept for this

	// That's it.  Checkout should have already checked the hash, so we just return it.
	return wareID, nil
}
<commit_msg>git: support checkout of symlinks.<commit_after>package git

import (
	"context"
	"fmt"
	"io"
	"io/ioutil"

	. "github.com/polydawn/go-errcat"
	"gopkg.in/src-d/go-git.v4/plumbing/filemode"
	"gopkg.in/src-d/go-git.v4/plumbing/object"

	"go.polydawn.net/go-timeless-api"
	"go.polydawn.net/go-timeless-api/rio"
	"go.polydawn.net/go-timeless-api/util"
	"go.polydawn.net/rio/config"
	"go.polydawn.net/rio/fs"
	"go.polydawn.net/rio/fs/osfs"
	"go.polydawn.net/rio/fsOp"
	"go.polydawn.net/rio/transmat/mixins/cache"
	"go.polydawn.net/rio/transmat/mixins/filters"
	"go.polydawn.net/rio/transmat/mixins/fshash"
)

var (
	_ rio.UnpackFunc = Unpack
)

func Unpack(
	ctx context.Context, // Long-running call.  Cancellable.
	wareID api.WareID, // What wareID to fetch for unpacking.
	path string, // Where to unpack the fileset (absolute path).
	filt api.FilesetFilters, // Optionally: filters we should apply while unpacking.
	placementMode rio.PlacementMode, // Optionally: a placement mode (default is "copy").
	warehouses []api.WarehouseAddr, // Warehouses we can try to fetch from.
	mon rio.Monitor, // Optionally: callbacks for progress monitoring.
) (_ api.WareID, err error) {
	if mon.Chan != nil {
		defer close(mon.Chan)
	}
	defer RequireErrorHasCategory(&err, rio.ErrorCategory(""))

	// Sanitize arguments.
	if wareID.Type != PackType {
		return api.WareID{}, Errorf(rio.ErrUsage, "this transmat implementation only supports packtype %q (not %q)", PackType, wareID.Type)
	}
	if placementMode == "" {
		placementMode = rio.Placement_Copy
	}
	// Wrap the direct unpack func with cache behavior; call that.
	return cache.Lrn2Cache(
		osfs.New(config.GetCacheBasePath()),
		unpack,
	)(ctx, wareID, path, filt, placementMode, warehouses, mon)
}

func unpack(
	ctx context.Context,
	wareID api.WareID,
	path string,
	filt api.FilesetFilters,
	placementMode rio.PlacementMode,
	warehouses []api.WarehouseAddr,
	mon rio.Monitor,
) (_ api.WareID, err error) {
	defer RequireErrorHasCategory(&err, rio.ErrorCategory(""))

	// Sanitize arguments.
	path2 := fs.MustAbsolutePath(path)
	filt2, err := apiutil.ProcessFilters(filt, apiutil.FilterPurposeUnpack)
	if err != nil {
		return api.WareID{}, Errorf(rio.ErrUsage, "invalid filter specification: %s", err)
	}

	// Pick a warehouse and get a reader.
	//  This is a *very* expensive operation for git.  It's less
	//  of "pick a warehouse" and more "download the whole thing and hope we
	//  get what we wanted" (which is very ironic for a system that has
	//  a CAS system on its inside, yes).
	whCtrl, err := pick(ctx,
		wareID,
		warehouses,
		osfs.New(config.GetCacheBasePath().Join(fs.MustRelPath("git/objs"))),
		mon,
	)
	if err != nil {
		return api.WareID{}, err
	}
	tr, err := whCtrl.GetTree(wareID.Hash)
	if err != nil {
		panic(err)
	}
	tw := object.NewTreeWalker(tr, true, nil)

	// Construct filesystem wrapper to use for all our ops.
	afs := osfs.New(path2)

	// Make the root dir.  Git doesn't have metadata for the tree root.
	conjuredFmeta := fshash.DefaultDirMetadata()
	filters.Apply(filt2, &conjuredFmeta)
	if err := fsOp.PlaceFile(afs, conjuredFmeta, nil, filt2.SkipChown); err != nil {
		return api.WareID{}, Errorf(rio.ErrInoperablePath, "error while unpacking: %s", err)
	}

	// Extract.
	// Iterate over each entry, mutating filesystem as we go.
	for {
		fmeta := fs.Metadata{}
		name, te, err := tw.Next()

		// Check for done.
		if err == io.EOF {
			break // sucess!  end of archive.
		}
		if err != nil {
			return api.WareID{}, Errorf(rio.ErrWareCorrupt, "corrupt git tree: %s", err)
		}
		if ctx.Err() != nil {
			return api.WareID{}, Errorf(rio.ErrCancelled, "cancelled")
		}
		//fmt.Fprintf(os.Stderr, "walking git tree %s -- %#v\n", name, te)

		// Reshuffle metainfo to our default format.
		fmeta.Name = fs.MustRelPath(name)
		switch te.Mode {
		case filemode.Dir:
			fmeta.Type = fs.Type_Dir
			fmeta.Perms = 0644
		case filemode.Regular:
			fmeta.Type = fs.Type_File
			fmeta.Perms = 0644
		case filemode.Executable:
			fmeta.Type = fs.Type_File
			fmeta.Perms = 0755
		case filemode.Symlink:
			fmeta.Type = fs.Type_Symlink
			fmeta.Perms = 0644
			// Hang on, extracting a symlink is actually rough.
			tf, err := tr.TreeEntryFile(&te)
			if err != nil {
				return api.WareID{}, Errorf(rio.ErrWareCorrupt, "corrupt git tree: %s", err)
			}
			reader, err := tf.Blob.Reader()
			if err != nil {
				return api.WareID{}, Errorf(rio.ErrWareCorrupt, "corrupt git tree: %s", err)
			}
			blob, err := ioutil.ReadAll(reader)
			if err != nil {
				return api.WareID{}, Errorf(rio.ErrWareCorrupt, "corrupt git tree: %s", err)
			}
			fmeta.Linkname = string(blob)
		case filemode.Submodule:
			// TODO
			continue
		case filemode.Empty:
			fallthrough
		case filemode.Deprecated:
			fallthrough
		default:
			panic(fmt.Errorf("unknown git filemode %#v", te.Mode))
		}
		fmeta.Mtime = apiutil.DefaultMtime // git doesn't have time info

		// Apply filters.
		filters.Apply(filt2, &fmeta)

		// Place the file.
		switch fmeta.Type {
		case fs.Type_File:
			tf, err := tr.TreeEntryFile(&te)
			if err != nil {
				return api.WareID{}, Errorf(rio.ErrWareCorrupt, "corrupt git tree: %s", err)
			}
			reader, err := tf.Blob.Reader()
			if err != nil {
				return api.WareID{}, Errorf(rio.ErrWareCorrupt, "corrupt git tree: %s", err)
			}
			if err := fsOp.PlaceFile(afs, fmeta, reader, filt2.SkipChown); err != nil {
				return api.WareID{}, Errorf(rio.ErrInoperablePath, "error while unpacking: %s", err)
			}
			reader.Close()
		default:
			if err := fsOp.PlaceFile(afs, fmeta, nil, filt2.SkipChown); err != nil {
				return api.WareID{}, Errorf(rio.ErrInoperablePath, "error while unpacking: %s", err)
			}
		}
	}

	// Cleanup dir times with a post-order traversal over the bucket.
	//  Files and dirs placed inside dirs cause the parent's mtime to update, so we have to re-pave them.
	// TODO we don't have the state kept for this

	// That's it.  Checkout should have already checked the hash, so we just return it.
	return wareID, nil
}
<|endoftext|>


<commit_before>package tartrans

import (
	"context"
	"fmt"
	"io"

	. "github.com/polydawn/go-errcat"

	"go.polydawn.net/go-timeless-api"
	"go.polydawn.net/go-timeless-api/rio"
	"go.polydawn.net/go-timeless-api/util"
	"go.polydawn.net/rio/fs/nilfs"
	"go.polydawn.net/rio/transmat/mixins/log"
)

var (
	_ rio.MirrorFunc = Mirror
)

func Mirror(
	ctx context.Context, // Long-running call.  Cancellable.
	wareID api.WareID, // What wareID to mirror.
	target api.WarehouseAddr, // Warehouse to ensure the ware is mirrored into.
	sources []api.WarehouseAddr, // Warehouses we can try to fetch from.
	mon rio.Monitor, // Optionally: callbacks for progress monitoring.
) (_ api.WareID, err error) {
	defer RequireErrorHasCategory(&err, rio.ErrorCategory(""))
	if mon.Chan != nil {
		defer close(mon.Chan)
	}

	// Try to read the ware from the target first; if successfull, no-op out.
	//  We don't fully re-verify the content, because that requires a time
	//  committment, and we want this command to be fast when run repeatedly.
	reader, err := PickReader(wareID, []api.WarehouseAddr{target}, false, mon)
	if err == nil {
		log.MirrorNoop(mon, target, wareID)
		reader.Close()
		return wareID, nil
	}

	// Connect to target warehouse, and get write controller opened.
	//  During mirroring, unlike unpacking, we actually *do* know the hash
	//  of what we'll be uploading... but there's nothing dramatically better
	//  we can do with that knowledge.
	wc, err := OpenWriteController(target, wareID.Type, mon)
	if err != nil {
		return api.WareID{}, err
	}
	defer wc.Close()

	// Pick a source warehouse and get a reader.
	reader, err = PickReader(wareID, sources, false, mon)
	if err != nil {
		return api.WareID{}, err
	}
	defer reader.Close()

	// Prepare to scan this as we process.
	//  It would be unfortunate to accidentally foist corrupted or
	//  wrongly identified content onto a mirror.
	reader = flippingReader{reader, wc}
	afs := nilFS.New()

	// "unpack", scanningly.  This drives the copy.
	filt, _ := apiutil.ProcessFilters(api.Filter_NoMutation, apiutil.FilterPurposeUnpack)
	gotWare, err := unpackTar(ctx, afs, filt, reader)
	if err != nil {
		// If errors at this stage: still return a blank wareID, because
		//  we haven't finished *uploading* it.
		return api.WareID{}, err
	}

	// Check for hash mismatch; abort if detected.
	//  Again, return a blank wareID, because we haven't *uploaded* it.
	//  You'll have no choice but to inspect the error details if you need the value.
	if gotWare != wareID {
		return api.WareID{}, ErrorDetailed(
			rio.ErrWareHashMismatch,
			fmt.Sprintf("hash mismatch: expected %q, got %q", wareID, gotWare),
			map[string]string{
				"expected": wareID.String(),
				"actual":   gotWare.String(),
			},
		)
	}

	// All's quiet: flush and commit.
	return gotWare, wc.Commit(wareID)
}

// Proxy read calls, also copying each buffer into another write.
type flippingReader struct {
	read io.ReadCloser
	dup  io.Writer
}

func (fr flippingReader) Read(b []byte) (int, error) {
	n, err := fr.read.Read(b)
	if err == nil || err == io.EOF {
		n2, err2 := fr.dup.Write(b)
		if n2 < n {
			return n, io.ErrShortWrite
		}
		if err2 != nil {
			return n, err2
		}
	}
	return n, err
}

func (fr flippingReader) Close() error {
	return fr.read.Close()
}
<commit_msg>transmat/tar: fix mirror byte buffer copying.<commit_after>package tartrans

import (
	"context"
	"fmt"
	"io"

	. "github.com/polydawn/go-errcat"

	"go.polydawn.net/go-timeless-api"
	"go.polydawn.net/go-timeless-api/rio"
	"go.polydawn.net/go-timeless-api/util"
	"go.polydawn.net/rio/fs/nilfs"
	"go.polydawn.net/rio/transmat/mixins/log"
)

var (
	_ rio.MirrorFunc = Mirror
)

func Mirror(
	ctx context.Context, // Long-running call.  Cancellable.
	wareID api.WareID, // What wareID to mirror.
	target api.WarehouseAddr, // Warehouse to ensure the ware is mirrored into.
	sources []api.WarehouseAddr, // Warehouses we can try to fetch from.
	mon rio.Monitor, // Optionally: callbacks for progress monitoring.
) (_ api.WareID, err error) {
	defer RequireErrorHasCategory(&err, rio.ErrorCategory(""))
	if mon.Chan != nil {
		defer close(mon.Chan)
	}

	// Try to read the ware from the target first; if successfull, no-op out.
	//  We don't fully re-verify the content, because that requires a time
	//  committment, and we want this command to be fast when run repeatedly.
	reader, err := PickReader(wareID, []api.WarehouseAddr{target}, false, mon)
	if err == nil {
		log.MirrorNoop(mon, target, wareID)
		reader.Close()
		return wareID, nil
	}

	// Connect to target warehouse, and get write controller opened.
	//  During mirroring, unlike unpacking, we actually *do* know the hash
	//  of what we'll be uploading... but there's nothing dramatically better
	//  we can do with that knowledge.
	wc, err := OpenWriteController(target, wareID.Type, mon)
	if err != nil {
		return api.WareID{}, err
	}
	defer wc.Close()

	// Pick a source warehouse and get a reader.
	reader, err = PickReader(wareID, sources, false, mon)
	if err != nil {
		return api.WareID{}, err
	}
	defer reader.Close()

	// Prepare to scan this as we process.
	//  It would be unfortunate to accidentally foist corrupted or
	//  wrongly identified content onto a mirror.
	reader = flippingReader{reader, wc}
	afs := nilFS.New()

	// "unpack", scanningly.  This drives the copy.
	filt, _ := apiutil.ProcessFilters(api.Filter_NoMutation, apiutil.FilterPurposeUnpack)
	gotWare, err := unpackTar(ctx, afs, filt, reader)
	if err != nil {
		// If errors at this stage: still return a blank wareID, because
		//  we haven't finished *uploading* it.
		return api.WareID{}, err
	}

	// Check for hash mismatch; abort if detected.
	//  Again, return a blank wareID, because we haven't *uploaded* it.
	//  You'll have no choice but to inspect the error details if you need the value.
	if gotWare != wareID {
		return api.WareID{}, ErrorDetailed(
			rio.ErrWareHashMismatch,
			fmt.Sprintf("hash mismatch: expected %q, got %q", wareID, gotWare),
			map[string]string{
				"expected": wareID.String(),
				"actual":   gotWare.String(),
			},
		)
	}

	// All's quiet: flush and commit.
	return gotWare, wc.Commit(wareID)
}

// Proxy read calls, also copying each buffer into another write.
type flippingReader struct {
	read io.ReadCloser
	dup  io.Writer
}

func (fr flippingReader) Read(b []byte) (int, error) {
	n, err := fr.read.Read(b)
	if err == nil || err == io.EOF {
		n2, err2 := fr.dup.Write(b[:n])
		if n2 < n {
			return n, io.ErrShortWrite
		}
		if err2 != nil {
			return n, err2
		}
	}
	return n, err
}

func (fr flippingReader) Close() error {
	return fr.read.Close()
}
<|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 leaktest provides tools to detect leaked goroutines in tests.
// To use it, call "defer leaktest.AfterTest(t)" at the beginning of each
// test that may use goroutines, and add a TestMain function for the package
// which calls leaktest.TestMainWithLeakCheck.
package leaktest

import (
	"fmt"
	"net/http"
	"os"
	"runtime"
	"sort"
	"strings"
	"sync/atomic"
	"testing"
	"time"
)

var hasFailed int32 // updated atomially (though not necessary in normal usage)

// TestMainWithLeakCheck is an implementation of TestMain which verifies that
// there are no leaked goroutines at the end of the run (except those created
// by the system which are on a whitelist). Usage:
//
//
// // Adjust the relative path as needed.
// //go:generate ../util/leaktest/add-leaktest.sh *_test.go
//
// func TestMain(m *testing.M) {
//   leaktest.TestMainWithLeakCheck(m)
// }
func TestMainWithLeakCheck(m *testing.M) {
	v := m.Run()
	if v == 0 && goroutineLeaked() {
		os.Exit(1)
	}
	os.Exit(v)
}

func interestingGoroutines() (gs []string) {
	buf := make([]byte, 2<<20)
	buf = buf[:runtime.Stack(buf, true)]
	for _, g := range strings.Split(string(buf), "\n\n") {
		sl := strings.SplitN(g, "\n", 2)
		if len(sl) != 2 {
			continue
		}
		stack := strings.TrimSpace(sl[1])
		if stack == "" ||
			strings.Contains(stack, "created by net.startServer") ||
			strings.Contains(stack, "created by testing.RunTests") ||
			strings.Contains(stack, "closeWriteAndWait") ||
			strings.Contains(stack, "testing.Main(") ||
			// These only show up with GOTRACEBACK=2; Issue 5005 (comment 28)
			strings.Contains(stack, "runtime.goexit") ||
			strings.Contains(stack, "created by runtime.gc") ||
			strings.Contains(stack, "github.com/cockroachdb/cockroach/util/leaktest.interestingGoroutines") ||
			strings.Contains(stack, "runtime.MHeap_Scavenger") ||
			strings.Contains(stack, "github.com/cockroachdb/cockroach/util/log.init") ||
			strings.Contains(stack, "os/signal.loop") {
			continue
		}
		gs = append(gs, stack)
	}
	sort.Strings(gs)
	return
}

// Verify the other tests didn't leave any goroutines running.
func goroutineLeaked() bool {
	if testing.Short() {
		// not counting goroutines for leakage in -short mode
		return false
	}

	var stackCount map[string]int
	for i := 0; i < 8; i++ {
		n := 0
		stackCount = make(map[string]int)
		gs := interestingGoroutines()
		for _, g := range gs {
			stackCount[g]++
			n++
		}
		if n == 0 {
			return false
		}
		// Wait for goroutines to schedule and die off:
		time.Sleep(10 * time.Millisecond)
	}
	fmt.Fprintf(os.Stderr, "Too many goroutines running after test(s).\n")
	for stack, count := range stackCount {
		fmt.Fprintf(os.Stderr, "%d instances of:\n%s\n", count, stack)
	}
	return true
}

// AfterTest should be called (generally with "defer leaktest.AfterTest(t)")
// from each test which uses goroutines. This waits for all goroutines
// on a blacklist to terminate and provides more precise error reporting
// than TestMainWithLeakCheck alone.
// If a previous test's check has already failed, this is a noop (to avoid
// failing unrelated tests).
func AfterTest(t testing.TB) {
	if atomic.LoadInt32(&hasFailed) > 0 {
		t.Log("prior leak detected, leaktest disabled")
		return
	}
	if r := recover(); r != nil {
		// Don't bother with leaktest if we're recovering from a panic.
		panic(r)
	}
	http.DefaultTransport.(*http.Transport).CloseIdleConnections()
	if testing.Short() || t.Failed() {
		// If a test has failed, chances are it hasn't shut down cleanly, so
		// stop checking for leaks in this run altogether.
		atomic.StoreInt32(&hasFailed, 1)
		return
	}
	if r := recover(); r != nil {
		panic(r)
	}
	var bad string
	badSubstring := map[string]string{
		").readLoop(":                                  "a Transport",
		").writeLoop(":                                 "a Transport",
		"created by net/http/httptest.(*Server).Start": "an httptest.Server",
		"timeoutHandler":                               "a TimeoutHandler",
		"net.(*netFD).connect(":                        "a timing out dial",
		").noteClientGone(":                            "a closenotifier sender",
		"created by net/rpc.NewClientWithCodec":        "an rpc client",
		"created by net/rpc.(*Server.ServeCodec)":      "an rpc server connection",
		"(*Store).Start":                               "a store",
		"(*Range).Send":                                "a range command",
	}
	var stacks string
	for i := 0; i < 8; i++ {
		bad = ""
		stacks = strings.Join(interestingGoroutines(), "\n\n")
		for substr, what := range badSubstring {
			if strings.Contains(stacks, substr) {
				bad = what
			}
		}
		if bad == "" {
			return
		}
		// Bad stuff found, but goroutines might just still be
		// shutting down, so give it some time.
		time.Sleep(10 * time.Millisecond)
	}
	atomic.StoreInt32(&hasFailed, 1)
	t.Errorf("Test appears to have leaked %s:\n%s", bad, stacks)
}
<commit_msg>leaktest: simplify our customizations<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 leaktest provides tools to detect leaked goroutines in tests.
// To use it, call "defer leaktest.AfterTest(t)" at the beginning of each
// test that may use goroutines, and add a TestMain function for the package
// which calls leaktest.TestMainWithLeakCheck.
package leaktest

import (
	"fmt"
	"net/http"
	"os"
	"runtime"
	"sort"
	"strings"
	"sync/atomic"
	"testing"
	"time"
)

var hasLeaked int32 // updated atomically (though not necessary in normal usage)

// TestMainWithLeakCheck is an implementation of TestMain which verifies that
// there are no leaked goroutines at the end of the run (except those created
// by the system which are on a whitelist). Usage:
//
//
// // Adjust the relative path as needed.
// //go:generate ../util/leaktest/add-leaktest.sh *_test.go
//
// func TestMain(m *testing.M) {
//   leaktest.TestMainWithLeakCheck(m)
// }
func TestMainWithLeakCheck(m *testing.M) {
	v := m.Run()
	if v == 0 && goroutineLeaked() {
		os.Exit(1)
	}
	os.Exit(v)
}

func interestingGoroutines() (gs []string) {
	buf := make([]byte, 2<<20)
	buf = buf[:runtime.Stack(buf, true)]
	for _, g := range strings.Split(string(buf), "\n\n") {
		sl := strings.SplitN(g, "\n", 2)
		if len(sl) != 2 {
			continue
		}
		stack := strings.TrimSpace(sl[1])
		if stack == "" ||
			strings.Contains(stack, "created by net.startServer") ||
			strings.Contains(stack, "created by testing.RunTests") ||
			strings.Contains(stack, "closeWriteAndWait") ||
			strings.Contains(stack, "testing.Main(") ||
			// These only show up with GOTRACEBACK=2; Issue 5005 (comment 28)
			strings.Contains(stack, "runtime.goexit") ||
			strings.Contains(stack, "created by runtime.gc") ||
			strings.Contains(stack, "github.com/cockroachdb/cockroach/util/leaktest.interestingGoroutines") ||
			strings.Contains(stack, "runtime.MHeap_Scavenger") ||
			strings.Contains(stack, "github.com/cockroachdb/cockroach/util/log.init") ||
			strings.Contains(stack, "os/signal.loop") {
			continue
		}
		gs = append(gs, stack)
	}
	sort.Strings(gs)
	return
}

// Verify the other tests didn't leave any goroutines running.
func goroutineLeaked() bool {
	if testing.Short() {
		// not counting goroutines for leakage in -short mode
		return false
	}

	var stackCount map[string]int
	for i := 0; i < 8; i++ {
		n := 0
		stackCount = make(map[string]int)
		gs := interestingGoroutines()
		for _, g := range gs {
			stackCount[g]++
			n++
		}
		if n == 0 {
			return false
		}
		// Wait for goroutines to schedule and die off:
		time.Sleep(10 * time.Millisecond)
	}
	fmt.Fprintf(os.Stderr, "Too many goroutines running after test(s).\n")
	for stack, count := range stackCount {
		fmt.Fprintf(os.Stderr, "%d instances of:\n%s\n", count, stack)
	}
	return true
}

// AfterTest should be called (generally with "defer leaktest.AfterTest(t)")
// from each test which uses goroutines. This waits for all goroutines
// on a blacklist to terminate and provides more precise error reporting
// than TestMainWithLeakCheck alone.
// If a previous test's check has already failed, this is a noop (to avoid
// failing unrelated tests).
func AfterTest(t testing.TB) {
	http.DefaultTransport.(*http.Transport).CloseIdleConnections()
	if testing.Short() {
		return
	}
	if atomic.LoadInt32(&hasLeaked) > 0 {
		t.Log("prior leak detected, leaktest disabled")
		return
	}
	var bad string
	badSubstring := map[string]string{
		").readLoop(":                                  "a Transport",
		").writeLoop(":                                 "a Transport",
		"created by net/http/httptest.(*Server).Start": "an httptest.Server",
		"timeoutHandler":                               "a TimeoutHandler",
		"net.(*netFD).connect(":                        "a timing out dial",
		").noteClientGone(":                            "a closenotifier sender",
		"created by net/rpc.NewClientWithCodec":        "an rpc client",
		"created by net/rpc.(*Server.ServeCodec)":      "an rpc server connection",
		"(*Store).Start":                               "a store",
		"(*Range).Send":                                "a range command",
	}
	var stacks string
	for i := 0; i < 8; i++ {
		bad = ""
		stacks = strings.Join(interestingGoroutines(), "\n\n")
		for substr, what := range badSubstring {
			if strings.Contains(stacks, substr) {
				bad = what
			}
		}
		if bad == "" {
			return
		}
		// Bad stuff found, but goroutines might just still be
		// shutting down, so give it some time.
		time.Sleep(10 * time.Millisecond)
	}
	// If a test has leaked, all subsequent tests will suffer from the same leak,
	// so stop checking for leaks in this run altogether.
	atomic.StoreInt32(&hasLeaked, 1)
	t.Errorf("Test appears to have leaked %s:\n%s", bad, stacks)
}
<|endoftext|>


<commit_before>package profiler

import (
	"github.com/pkg/profile"
	"github.com/urfave/cli"
)

func Attach(app *cli.App) {
	app.Flags = append(app.Flags,
		cli.StringFlag{
			Name:   "profile-cpu",
			Hidden: true,
		},
		cli.StringFlag{
			Name:   "profile-memory",
			Hidden: true,
		},
		cli.IntFlag{
			Name:   "profile-memoryrate",
			Value:  512 * 1024,
			Hidden: true,
		},
		cli.StringFlag{
			Name:   "profile-block",
			Hidden: true,
		},
		cli.StringFlag{
			Name:   "profile-mutex",
			Hidden: true,
		},
		cli.StringFlag{
			Name:   "profile-trace",
			Hidden: true,
		},
	)

	var stoppers = []interface {
		Stop()
	}{}

	before := app.Before
	app.Before = func(clicontext *cli.Context) error {
		if before != nil {
			if err := before(clicontext); err != nil {
				return err
			}
		}

		if cpuProfile := clicontext.String("profile-cpu"); cpuProfile != "" {
			stoppers = append(stoppers, profile.Start(profile.CPUProfile, profile.ProfilePath(cpuProfile)))
		}

		if memProfile := clicontext.String("profile-memory"); memProfile != "" {
			stoppers = append(stoppers, profile.Start(profile.MemProfile, profile.ProfilePath(memProfile), profile.MemProfileRate(clicontext.Int("profile-memoryrate"))))
		}

		if blockProfile := clicontext.String("profile-block"); blockProfile != "" {
			stoppers = append(stoppers, profile.Start(profile.BlockProfile, profile.ProfilePath(blockProfile)))
		}

		if mutexProfile := clicontext.String("profile-mutex"); mutexProfile != "" {
			stoppers = append(stoppers, profile.Start(profile.MutexProfile, profile.ProfilePath(mutexProfile)))
		}

		if traceProfile := clicontext.String("profile-trace"); traceProfile != "" {
			stoppers = append(stoppers, profile.Start(profile.TraceProfile, profile.ProfilePath(traceProfile)))
		}
		return nil
	}

	after := app.After
	app.After = func(clicontext *cli.Context) error {
		if after != nil {
			if err := after(clicontext); err != nil {
				return err
			}
		}

		for _, stopper := range stoppers {
			stopper.Stop()
		}
		return nil
	}
}
<commit_msg>profiler: add noshutdown hooks<commit_after>package profiler

import (
	"github.com/pkg/profile"
	"github.com/urfave/cli"
)

func Attach(app *cli.App) {
	app.Flags = append(app.Flags,
		cli.StringFlag{
			Name:   "profile-cpu",
			Hidden: true,
		},
		cli.StringFlag{
			Name:   "profile-memory",
			Hidden: true,
		},
		cli.IntFlag{
			Name:   "profile-memoryrate",
			Value:  512 * 1024,
			Hidden: true,
		},
		cli.StringFlag{
			Name:   "profile-block",
			Hidden: true,
		},
		cli.StringFlag{
			Name:   "profile-mutex",
			Hidden: true,
		},
		cli.StringFlag{
			Name:   "profile-trace",
			Hidden: true,
		},
	)

	var stoppers = []interface {
		Stop()
	}{}

	before := app.Before
	app.Before = func(clicontext *cli.Context) error {
		if before != nil {
			if err := before(clicontext); err != nil {
				return err
			}
		}

		if cpuProfile := clicontext.String("profile-cpu"); cpuProfile != "" {
			stoppers = append(stoppers, profile.Start(profile.CPUProfile, profile.ProfilePath(cpuProfile), profile.NoShutdownHook))
		}

		if memProfile := clicontext.String("profile-memory"); memProfile != "" {
			stoppers = append(stoppers, profile.Start(profile.MemProfile, profile.ProfilePath(memProfile), profile.NoShutdownHook, profile.MemProfileRate(clicontext.Int("profile-memoryrate"))))
		}

		if blockProfile := clicontext.String("profile-block"); blockProfile != "" {
			stoppers = append(stoppers, profile.Start(profile.BlockProfile, profile.ProfilePath(blockProfile), profile.NoShutdownHook))
		}

		if mutexProfile := clicontext.String("profile-mutex"); mutexProfile != "" {
			stoppers = append(stoppers, profile.Start(profile.MutexProfile, profile.ProfilePath(mutexProfile), profile.NoShutdownHook))
		}

		if traceProfile := clicontext.String("profile-trace"); traceProfile != "" {
			stoppers = append(stoppers, profile.Start(profile.TraceProfile, profile.ProfilePath(traceProfile), profile.NoShutdownHook))
		}
		return nil
	}

	after := app.After
	app.After = func(clicontext *cli.Context) error {
		if after != nil {
			if err := after(clicontext); err != nil {
				return err
			}
		}

		for _, stopper := range stoppers {
			stopper.Stop()
		}
		return nil
	}
}
<|endoftext|>


<commit_before>package kcp

import (
	"crypto/sha1"
	"fmt"
	"log"
	"net"
	"net/http"
	_ "net/http/pprof"
	"sync"
	"testing"
	"time"

	"golang.org/x/crypto/pbkdf2"
)

const port = "127.0.0.1:9999"
const salt = "kcptest"

var key = []byte("testkey")
var fec = 4
var pass = pbkdf2.Key(key, []byte(salt), 4096, 32, sha1.New)

func init() {
	go func() {
		log.Println(http.ListenAndServe("localhost:6060", nil))
	}()

	go server()
}

func DialTest() (*UDPSession, error) {
	block, _ := NewNoneBlockCrypt(pass)
	//block, _ := NewSimpleXORBlockCrypt(pass)
	//block, _ := NewTEABlockCrypt(pass[:16])
	//block, _ := NewAESBlockCrypt(pass)
	sess, err := DialWithOptions(port, block, 10, 3)
	if err != nil {
		panic(err)
	}

	sess.SetStreamMode(true)
	sess.SetWindowSize(1024, 1024)
	sess.SetReadBuffer(4 * 1024 * 1024)
	sess.SetWriteBuffer(4 * 1024 * 1024)
	sess.SetStreamMode(true)
	sess.SetNoDelay(1, 20, 2, 1)
	sess.SetACKNoDelay(true)
	sess.SetDeadline(time.Now().Add(time.Minute))
	return sess, err
}

func ListenTest() (net.Listener, error) {
	block, _ := NewNoneBlockCrypt(pass)
	//block, _ := NewSimpleXORBlockCrypt(pass)
	//block, _ := NewTEABlockCrypt(pass[:16])
	//block, _ := NewAESBlockCrypt(pass)
	return ListenWithOptions(port, block, 10, 3)
}

func server() {
	l, err := ListenTest()
	if err != nil {
		panic(err)
	}

	go func() {
		kcplistener := l.(*Listener)
		kcplistener.SetReadBuffer(4 * 1024 * 1024)
		kcplistener.SetWriteBuffer(4 * 1024 * 1024)
		kcplistener.SetDSCP(46)
		for {
			s, err := l.Accept()
			if err != nil {
				return
			}

			// coverage test
			s.(*UDPSession).SetReadBuffer(4 * 1024 * 1024)
			s.(*UDPSession).SetWriteBuffer(4 * 1024 * 1024)
			s.(*UDPSession).SetKeepAlive(1)
			go handleClient(s.(*UDPSession))
		}
	}()
}

func handleClient(conn *UDPSession) {
	conn.SetStreamMode(true)
	conn.SetWindowSize(1024, 1024)
	conn.SetNoDelay(1, 20, 2, 1)
	conn.SetDSCP(46)
	conn.SetMtu(1450)
	conn.SetACKNoDelay(false)
	conn.SetReadDeadline(time.Now().Add(time.Hour))
	conn.SetWriteDeadline(time.Now().Add(time.Hour))
	buf := make([]byte, 65536)
	for {
		n, err := conn.Read(buf)
		if err != nil {
			panic(err)
		}
		conn.Write(buf[:n])
	}
}

func TestTimeout(t *testing.T) {
	cli, err := DialTest()
	if err != nil {
		panic(err)
	}
	buf := make([]byte, 10)

	//timeout
	cli.SetDeadline(time.Now().Add(time.Second))
	<-time.After(2 * time.Second)
	n, err := cli.Read(buf)
	if n != 0 || err == nil {
		t.Fail()
	}
	n, err = cli.Write(buf)
	if n != 0 || err == nil {
		t.Fail()
	}
	cli.Close()
}

func TestSendRecv(t *testing.T) {
	cli, err := DialTest()
	if err != nil {
		panic(err)
	}
	const N = 100
	buf := make([]byte, 10)
	for i := 0; i < N; i++ {
		msg := fmt.Sprintf("hello%v", i)
		cli.Write([]byte(msg))
		if n, err := cli.Read(buf); err == nil {
			if string(buf[:n]) != msg {
				t.Fail()
			}
		} else {
			panic(err)
		}
	}
	cli.Close()
}

func TestClose(t *testing.T) {
	cli, err := DialTest()
	if err != nil {
		panic(err)
	}
	buf := make([]byte, 10)

	cli.Close()
	if cli.Close() == nil {
		t.Fail()
	}
	n, err := cli.Write(buf)
	if n != 0 || err == nil {
		t.Fail()
	}
	n, err = cli.Read(buf)
	if n != 0 || err == nil {
		t.Fail()
	}
	cli.Close()
}

func TestParallel1024CLIENT_64BMSG_64CNT(t *testing.T) {
	var wg sync.WaitGroup
	wg.Add(1024)
	for i := 0; i < 1024; i++ {
		go parallel_client(&wg)
	}
	wg.Wait()
}

func parallel_client(wg *sync.WaitGroup) {
	cli, err := DialTest()
	if err != nil {
		panic(err)
	}

	echo_tester(cli, 64, 64)
	wg.Done()
}

func BenchmarkSpeed4K(b *testing.B) {
	for i := 0; i < b.N; i++ {
		speedclient(b, 4096)
	}
}

func BenchmarkSpeed64K(b *testing.B) {
	for i := 0; i < b.N; i++ {
		speedclient(b, 65536)
	}
}

func BenchmarkSpeed512K(b *testing.B) {
	for i := 0; i < b.N; i++ {
		speedclient(b, 524288)
	}
}

func BenchmarkSpeed1M(b *testing.B) {
	for i := 0; i < b.N; i++ {
		speedclient(b, 1048576)
	}
}

func speedclient(b *testing.B, nbytes int) {
	cli, err := DialTest()
	if err != nil {
		panic(err)
	}

	echo_tester(cli, nbytes, 1)
	b.SetBytes(int64(nbytes) * 4)
}

func TestSNMP(t *testing.T) {
	t.Log(DefaultSnmp.Copy())
	t.Log(DefaultSnmp.Header())
	t.Log(DefaultSnmp.ToSlice())
	DefaultSnmp.Reset()
	t.Log(DefaultSnmp.ToSlice())
}

func echo_tester(cli net.Conn, msglen, msgcount int) {
	total := msglen * msgcount

	var wg sync.WaitGroup

	// sender
	wg.Add(2)
	go func() {
		buf := make([]byte, msglen)
		for i := 0; i < msgcount; i++ {
			cli.Write(buf)
		}
		wg.Done()
	}()

	// receiver
	go func() {
		buf := make([]byte, msglen)
		nrecv := 0
		for {
			n, err := cli.Read(buf)
			if err != nil {
				log.Println(err)
				break
			} else {
				nrecv += n
				if nrecv == total {
					break
				}
			}
		}
		wg.Done()
	}()
	wg.Wait()
}
<commit_msg>update tests<commit_after>package kcp

import (
	"crypto/sha1"
	"fmt"
	"log"
	"net"
	"net/http"
	_ "net/http/pprof"
	"sync"
	"testing"
	"time"

	"golang.org/x/crypto/pbkdf2"
)

const port = "127.0.0.1:9999"
const salt = "kcptest"

var key = []byte("testkey")
var fec = 4
var pass = pbkdf2.Key(key, []byte(salt), 4096, 32, sha1.New)

func init() {
	go func() {
		log.Println(http.ListenAndServe("localhost:6060", nil))
	}()

	go server()
}

func DialTest() (*UDPSession, error) {
	block, _ := NewNoneBlockCrypt(pass)
	//block, _ := NewSimpleXORBlockCrypt(pass)
	//block, _ := NewTEABlockCrypt(pass[:16])
	//block, _ := NewAESBlockCrypt(pass)
	sess, err := DialWithOptions(port, block, 10, 3)
	if err != nil {
		panic(err)
	}

	sess.SetStreamMode(true)
	sess.SetWindowSize(4096, 4096)
	sess.SetReadBuffer(4 * 1024 * 1024)
	sess.SetWriteBuffer(4 * 1024 * 1024)
	sess.SetStreamMode(true)
	sess.SetNoDelay(1, 10, 2, 1)
	sess.SetMtu(1400)
	sess.SetACKNoDelay(true)
	sess.SetDeadline(time.Now().Add(time.Minute))
	return sess, err
}

func ListenTest() (net.Listener, error) {
	block, _ := NewNoneBlockCrypt(pass)
	//block, _ := NewSimpleXORBlockCrypt(pass)
	//block, _ := NewTEABlockCrypt(pass[:16])
	//block, _ := NewAESBlockCrypt(pass)
	return ListenWithOptions(port, block, 10, 3)
}

func server() {
	l, err := ListenTest()
	if err != nil {
		panic(err)
	}

	go func() {
		kcplistener := l.(*Listener)
		kcplistener.SetReadBuffer(4 * 1024 * 1024)
		kcplistener.SetWriteBuffer(4 * 1024 * 1024)
		kcplistener.SetDSCP(46)
		for {
			s, err := l.Accept()
			if err != nil {
				return
			}

			// coverage test
			s.(*UDPSession).SetReadBuffer(4 * 1024 * 1024)
			s.(*UDPSession).SetWriteBuffer(4 * 1024 * 1024)
			s.(*UDPSession).SetKeepAlive(1)
			go handleClient(s.(*UDPSession))
		}
	}()
}

func handleClient(conn *UDPSession) {
	conn.SetStreamMode(true)
	conn.SetWindowSize(4096, 4096)
	conn.SetNoDelay(1, 10, 2, 1)
	conn.SetDSCP(46)
	conn.SetMtu(1400)
	conn.SetACKNoDelay(false)
	conn.SetReadDeadline(time.Now().Add(time.Hour))
	conn.SetWriteDeadline(time.Now().Add(time.Hour))
	buf := make([]byte, 65536)
	for {
		n, err := conn.Read(buf)
		if err != nil {
			panic(err)
		}
		conn.Write(buf[:n])
	}
}

func TestTimeout(t *testing.T) {
	cli, err := DialTest()
	if err != nil {
		panic(err)
	}
	buf := make([]byte, 10)

	//timeout
	cli.SetDeadline(time.Now().Add(time.Second))
	<-time.After(2 * time.Second)
	n, err := cli.Read(buf)
	if n != 0 || err == nil {
		t.Fail()
	}
	n, err = cli.Write(buf)
	if n != 0 || err == nil {
		t.Fail()
	}
	cli.Close()
}

func TestSendRecv(t *testing.T) {
	cli, err := DialTest()
	if err != nil {
		panic(err)
	}
	const N = 100
	buf := make([]byte, 10)
	for i := 0; i < N; i++ {
		msg := fmt.Sprintf("hello%v", i)
		cli.Write([]byte(msg))
		if n, err := cli.Read(buf); err == nil {
			if string(buf[:n]) != msg {
				t.Fail()
			}
		} else {
			panic(err)
		}
	}
	cli.Close()
}

func TestClose(t *testing.T) {
	cli, err := DialTest()
	if err != nil {
		panic(err)
	}
	buf := make([]byte, 10)

	cli.Close()
	if cli.Close() == nil {
		t.Fail()
	}
	n, err := cli.Write(buf)
	if n != 0 || err == nil {
		t.Fail()
	}
	n, err = cli.Read(buf)
	if n != 0 || err == nil {
		t.Fail()
	}
	cli.Close()
}

func TestParallel1024CLIENT_64BMSG_64CNT(t *testing.T) {
	var wg sync.WaitGroup
	wg.Add(1024)
	for i := 0; i < 1024; i++ {
		go parallel_client(&wg)
	}
	wg.Wait()
}

func parallel_client(wg *sync.WaitGroup) {
	cli, err := DialTest()
	if err != nil {
		panic(err)
	}

	echo_tester(cli, 64, 64)
	wg.Done()
}

func BenchmarkEchoSpeed4K(b *testing.B) {
	for i := 0; i < b.N; i++ {
		speedclient(b, 4096)
	}
}

func BenchmarkEchoSpeed64K(b *testing.B) {
	for i := 0; i < b.N; i++ {
		speedclient(b, 65536)
	}
}

func BenchmarkEchoSpeed512K(b *testing.B) {
	for i := 0; i < b.N; i++ {
		speedclient(b, 524288)
	}
}

func BenchmarkEchoSpeed1M(b *testing.B) {
	for i := 0; i < b.N; i++ {
		speedclient(b, 1048576)
	}
}

func speedclient(b *testing.B, nbytes int) {
	cli, err := DialTest()
	if err != nil {
		panic(err)
	}

	echo_tester(cli, nbytes, 1)
	b.SetBytes(int64(nbytes))
}

func TestSNMP(t *testing.T) {
	t.Log(DefaultSnmp.Copy())
	t.Log(DefaultSnmp.Header())
	t.Log(DefaultSnmp.ToSlice())
	DefaultSnmp.Reset()
	t.Log(DefaultSnmp.ToSlice())
}

func echo_tester(cli net.Conn, msglen, msgcount int) {
	total := msglen * msgcount

	var wg sync.WaitGroup

	// sender
	wg.Add(2)
	go func() {
		buf := make([]byte, msglen)
		for i := 0; i < msgcount; i++ {
			cli.Write(buf)
		}
		wg.Done()
	}()

	// receiver
	go func() {
		buf := make([]byte, msglen)
		nrecv := 0
		for {
			n, err := cli.Read(buf)
			if err != nil {
				log.Println(err)
				break
			} else {
				nrecv += n
				if nrecv == total {
					break
				}
			}
		}
		wg.Done()
	}()
	wg.Wait()
}
<|endoftext|>


<commit_before>// A set of comprehensive testing tools for use with the normal Go testing system.
//
// Example Usage
//
// The following is a complete example using assert in a standard test function:
//    import (
//      "testing"
//      "github.com/stretchr/testify/assert"
//    )
//
//    func TestSomething(t *testing.T) {
//
//      var a string = "Hello"
//      var b string = "Hello"
//
//      assert.Equal(t, a, b, "The two words should be the same.")
//
//    }
//
// if you assert many times, use the below:
//
//    import (
//      "testing"
//      "github.com/stretchr/testify/assert"
//    )
//
//    func TestSomething(t *testing.T) {
//      assert := assert.New(t)
//
//      var a string = "Hello"
//      var b string = "Hello"
//
//      assert.Equal(a, b, "The two words should be the same.")
//    }
//
// Assertions
//
// Assertions allow you to easily write test code, and are global funcs in the `assert` package.
// All assertion functions take, as the first argument, the `*testing.T` object provided by the
// testing framework. This allows the assertion funcs to write the failings and other details to
// the correct place.
//
// Every assertion function also takes an optional string message as the final argument,
// allowing custom error messages to be appended to the message the assertion method outputs.
//
// Here is an overview of the assert functions:
//
//    assert.Equal(t, expected, actual [, message [, format-args])
//
//    assert.NotEqual(t, notExpected, actual [, message [, format-args]])
//
//    assert.True(t, actualBool [, message [, format-args]])
//
//    assert.False(t, actualBool [, message [, format-args]])
//
//    assert.Nil(t, actualObject [, message [, format-args]])
//
//    assert.NotNil(t, actualObject [, message [, format-args]])
//
//    assert.Empty(t, actualObject [, message [, format-args]])
//
//    assert.NotEmpty(t, actualObject [, message [, format-args]])
//
//    assert.Error(t, errorObject [, message [, format-args]])
//
//    assert.NoError(t, errorObject [, message [, format-args]])
//
//    assert.Implements(t, (*MyInterface)(nil), new(MyObject) [,message [, format-args]])
//
//    assert.IsType(t, expectedObject, actualObject [, message [, format-args]])
//
//    assert.Contains(t, string, substring [, message [, format-args]])
//
//    assert.NotContains(t, string, substring [, message [, format-args]])
//
//    assert.Panics(t, func(){
//
//	    // call code that should panic
//
//    } [, message [, format-args]])
//
//    assert.NotPanics(t, func(){
//
//	    // call code that should not panic
//
//    } [, message [, format-args]])
//
//    assert.WithinDuration(t, timeA, timeB, deltaTime, [, message [, format-args]])
//
// assert package contains Assertions object. it has assertion methods.
//
// Here is an overview of the assert functions:
//    assert.Equal(expected, actual [, message [, format-args])
//
//    assert.NotEqual(notExpected, actual [, message [, format-args]])
//
//    assert.True(actualBool [, message [, format-args]])
//
//    assert.False(actualBool [, message [, format-args]])
//
//    assert.Nil(actualObject [, message [, format-args]])
//
//    assert.NotNil(actualObject [, message [, format-args]])
//
//    assert.Empty(actualObject [, message [, format-args]])
//
//    assert.NotEmpty(actualObject [, message [, format-args]])
//
//    assert.Error(errorObject [, message [, format-args]])
//
//    assert.NoError(errorObject [, message [, format-args]])
//
//    assert.Implements((*MyInterface)(nil), new(MyObject) [,message [, format-args]])
//
//    assert.IsType(expectedObject, actualObject [, message [, format-args]])
//
//    assert.Contains(string, substring [, message [, format-args]])
//
//    assert.NotContains(string, substring [, message [, format-args]])
//
//    assert.Panics(func(){
//
//	    // call code that should panic
//
//    } [, message [, format-args]])
//
//    assert.NotPanics(func(){
//
//	    // call code that should not panic
//
//    } [, message [, format-args]])
//
//    assert.WithinDuration(timeA, timeB, deltaTime, [, message [, format-args]])
package assert
<commit_msg>add `EqualError` to doc.go<commit_after>// A set of comprehensive testing tools for use with the normal Go testing system.
//
// Example Usage
//
// The following is a complete example using assert in a standard test function:
//    import (
//      "testing"
//      "github.com/stretchr/testify/assert"
//    )
//
//    func TestSomething(t *testing.T) {
//
//      var a string = "Hello"
//      var b string = "Hello"
//
//      assert.Equal(t, a, b, "The two words should be the same.")
//
//    }
//
// if you assert many times, use the below:
//
//    import (
//      "testing"
//      "github.com/stretchr/testify/assert"
//    )
//
//    func TestSomething(t *testing.T) {
//      assert := assert.New(t)
//
//      var a string = "Hello"
//      var b string = "Hello"
//
//      assert.Equal(a, b, "The two words should be the same.")
//    }
//
// Assertions
//
// Assertions allow you to easily write test code, and are global funcs in the `assert` package.
// All assertion functions take, as the first argument, the `*testing.T` object provided by the
// testing framework. This allows the assertion funcs to write the failings and other details to
// the correct place.
//
// Every assertion function also takes an optional string message as the final argument,
// allowing custom error messages to be appended to the message the assertion method outputs.
//
// Here is an overview of the assert functions:
//
//    assert.Equal(t, expected, actual [, message [, format-args])
//
//    assert.NotEqual(t, notExpected, actual [, message [, format-args]])
//
//    assert.True(t, actualBool [, message [, format-args]])
//
//    assert.False(t, actualBool [, message [, format-args]])
//
//    assert.Nil(t, actualObject [, message [, format-args]])
//
//    assert.NotNil(t, actualObject [, message [, format-args]])
//
//    assert.Empty(t, actualObject [, message [, format-args]])
//
//    assert.NotEmpty(t, actualObject [, message [, format-args]])
//
//    assert.Error(t, errorObject [, message [, format-args]])
//
//    assert.NoError(t, errorObject [, message [, format-args]])
//
//    assert.EqualError(t, theError, errString [, message [, format-args]])
//
//    assert.Implements(t, (*MyInterface)(nil), new(MyObject) [,message [, format-args]])
//
//    assert.IsType(t, expectedObject, actualObject [, message [, format-args]])
//
//    assert.Contains(t, string, substring [, message [, format-args]])
//
//    assert.NotContains(t, string, substring [, message [, format-args]])
//
//    assert.Panics(t, func(){
//
//	    // call code that should panic
//
//    } [, message [, format-args]])
//
//    assert.NotPanics(t, func(){
//
//	    // call code that should not panic
//
//    } [, message [, format-args]])
//
//    assert.WithinDuration(t, timeA, timeB, deltaTime, [, message [, format-args]])
//
// assert package contains Assertions object. it has assertion methods.
//
// Here is an overview of the assert functions:
//    assert.Equal(expected, actual [, message [, format-args])
//
//    assert.NotEqual(notExpected, actual [, message [, format-args]])
//
//    assert.True(actualBool [, message [, format-args]])
//
//    assert.False(actualBool [, message [, format-args]])
//
//    assert.Nil(actualObject [, message [, format-args]])
//
//    assert.NotNil(actualObject [, message [, format-args]])
//
//    assert.Empty(actualObject [, message [, format-args]])
//
//    assert.NotEmpty(actualObject [, message [, format-args]])
//
//    assert.Error(errorObject [, message [, format-args]])
//
//    assert.NoError(errorObject [, message [, format-args]])
//
//    assert.EqualError(theError, errString [, message [, format-args]])
//
//    assert.Implements((*MyInterface)(nil), new(MyObject) [,message [, format-args]])
//
//    assert.IsType(expectedObject, actualObject [, message [, format-args]])
//
//    assert.Contains(string, substring [, message [, format-args]])
//
//    assert.NotContains(string, substring [, message [, format-args]])
//
//    assert.Panics(func(){
//
//	    // call code that should panic
//
//    } [, message [, format-args]])
//
//    assert.NotPanics(func(){
//
//	    // call code that should not panic
//
//    } [, message [, format-args]])
//
//    assert.WithinDuration(timeA, timeB, deltaTime, [, message [, format-args]])
package assert
<|endoftext|>


<commit_before>package coreos

import (
	"github.com/bernardolins/clustereasy/scope"
	"github.com/bernardolins/clustereasy/service/etcd"
	"github.com/bernardolins/clustereasy/service/flannel"
	"github.com/bernardolins/clustereasy/service/fleet"
	"github.com/bernardolins/clustereasy/setup/types"
	"github.com/bernardolins/clustereasy/unit"
	"github.com/bernardolins/clustereasy/unit/default/coreos"
)

func CreateScope(node types.Node, cluster types.Cluster) *scope.Scope {
	etcd2 := etcd2.New()
	etcd2.Configure(node, cluster)

	fleet := fleet.New()
	fleet.Configure(node, cluster)

	flannel := flannel.New()
	flannel.Configure(node, cluster)

	coreos := scope.New("coreos")

	coreos.AddService(*etcd2)
	coreos.AddService(*fleet)
	coreos.AddService(*flannel)

	configureUnits(coreos, cluster)

	return coreos
}

func configureUnits(scope *scope.Scope, cluster types.Cluster) {
	for _, u := range cluster.GetUnits() {
		unit := unit.New(u.UnitName(), u.UnitCommand())
		scope.AddUnit(*unit)
	}

	for _, u := range unitdef.DefaultUnits() {
		scope.AddUnit(u)
	}
}
<commit_msg>Fix error of unitdef package import after changing it's name<commit_after>package coreos

import (
	"github.com/bernardolins/clustereasy/scope"
	"github.com/bernardolins/clustereasy/service/etcd"
	"github.com/bernardolins/clustereasy/service/flannel"
	"github.com/bernardolins/clustereasy/service/fleet"
	"github.com/bernardolins/clustereasy/setup/types"
	"github.com/bernardolins/clustereasy/unit"
	"github.com/bernardolins/clustereasy/unit/default"
)

func CreateScope(node types.Node, cluster types.Cluster) *scope.Scope {
	etcd2 := etcd2.New()
	etcd2.Configure(node, cluster)

	fleet := fleet.New()
	fleet.Configure(node, cluster)

	flannel := flannel.New()
	flannel.Configure(node, cluster)

	coreos := scope.New("coreos")

	coreos.AddService(*etcd2)
	coreos.AddService(*fleet)
	coreos.AddService(*flannel)

	configureUnits(coreos, cluster)

	return coreos
}

func configureUnits(scope *scope.Scope, cluster types.Cluster) {
	for _, u := range cluster.GetUnits() {
		unit := unit.New(u.UnitName(), u.UnitCommand())
		scope.AddUnit(unit)
	}

	for _, u := range unitdef.DefaultUnits() {
		scope.AddUnit(u)
	}
}
<|endoftext|>