<commit_before>package yaml_test

import (
	"bytes"
	"fmt"
	"math"
	"testing"

	"github.com/goccy/go-yaml"
)

func TestEncoder(t *testing.T) {
	tests := []struct {
		source string
		value  interface{}
	}{
		{
			"null\n",
			(*struct{})(nil),
		},
		{
			"v: hi\n",
			map[string]string{"v": "hi"},
		},
		{
			"v: \"true\"\n",
			map[string]string{"v": "true"},
		},
		{
			"v: \"false\"\n",
			map[string]string{"v": "false"},
		},
		{
			"v: true\n",
			map[string]interface{}{"v": true},
		},
		{
			"v: false\n",
			map[string]bool{"v": false},
		},
		{
			"v: 10\n",
			map[string]int{"v": 10},
		},
		{
			"v: -10\n",
			map[string]int{"v": -10},
		},
		{
			"v: 4294967296\n",
			map[string]int{"v": 4294967296},
		},
		{
			"v: 0.1\n",
			map[string]interface{}{"v": 0.1},
		},
		{
			"v: 0.99\n",
			map[string]float32{"v": 0.99},
		},
		{
			"v: -0.1\n",
			map[string]float64{"v": -0.1},
		},
		{
			"v: 1.0\n",
			map[string]float64{"v": 1.0},
		},
		{
			"v: .inf\n",
			map[string]interface{}{"v": math.Inf(0)},
		},
		{
			"v: -.inf\n",
			map[string]interface{}{"v": math.Inf(-1)},
		},
		{
			"v: .nan\n",
			map[string]interface{}{"v": math.NaN()},
		},
		{
			"v: null\n",
			map[string]interface{}{"v": nil},
		},
		{
			"v: \"\"\n",
			map[string]string{"v": ""},
		},
		{
			"v:\n- A\n- B\n",
			map[string][]string{"v": {"A", "B"}},
		},
		{
			"a: -\n",
			map[string]string{"a": "-"},
		},
		{
			"123\n",
			123,
		},
		{
			"hello: world\n",
			map[string]string{"hello": "world"},
		},
		{
			"v:\n- A\n- 1\n- B:\n  - 2\n  - 3\n",
			map[string]interface{}{
				"v": []interface{}{
					"A",
					1,
					map[string][]int{
						"B": {2, 3},
					},
				},
			},
		},
		{
			"a:\n  b: c\n",
			map[string]interface{}{
				"a": map[string]string{
					"b": "c",
				},
			},
		},
		{
			"t2: 2018-01-09T10:40:47Z\nt4: 2098-01-09T10:40:47Z\n",
			map[string]string{
				"t2": "2018-01-09T10:40:47Z",
				"t4": "2098-01-09T10:40:47Z",
			},
		},
		{
			"a:\n  b: c\n  d: e\n",
			map[string]interface{}{
				"a": map[string]string{
					"b": "c",
					"d": "e",
				},
			},
		},
		{
			"a: 3s\n",
			map[string]string{
				"a": "3s",
			},
		},
		{
			"a: <foo>\n",
			map[string]string{"a": "<foo>"},
		},
		{
			"a: \"1:1\"\n",
			map[string]string{"a": "1:1"},
		},
		{
			"a: 1.2.3.4\n",
			map[string]string{"a": "1.2.3.4"},
		},
		{
			"a: \"b: c\"\n",
			map[string]string{"a": "b: c"},
		},
		{
			"a: \"Hello #comment\"\n",
			map[string]string{"a": "Hello #comment"},
		},
		{
			"a: 100.5\n",
			map[string]interface{}{
				"a": 100.5,
			},
		},
		{
			"a: \"\\\\0\"\n",
			map[string]string{"a": "\\0"},
		},
		{
			"a: 1\nb: 2\nc: 3\nd: 4\nsub:\n  e: 5\n",
			map[string]interface{}{
				"a": 1,
				"b": 2,
				"c": 3,
				"d": 4,
				"sub": map[string]int{
					"e": 5,
				},
			},
		},

		{
			"a: b\nc: d\n",
			struct {
				A string
				C string `yaml:"c"`
			}{
				"b", "d",
			},
		},
		{
			"a: 1\n",
			struct {
				A int
				B int `yaml:"-"`
			}{
				1, 0,
			},
		},
	}
	for _, test := range tests {
		var buf bytes.Buffer
		enc := yaml.NewEncoder(&buf)
		if err := enc.Encode(test.value); err != nil {
			t.Fatalf("%+v", err)
		}
		if test.source != buf.String() {
			t.Fatalf("expect = [%s], actual = [%s]", test.source, buf.String())
		}
	}
}

func TestEncodeWithAnchorAndAlias(t *testing.T) {
	var buf bytes.Buffer
	enc := yaml.NewEncoder(&buf)
	type T struct {
		A int
		B string
	}
	var v struct {
		A *T `yaml:"a,anchor=c"`
		B *T `yaml:"b,alias=c"`
	}
	v.A = &T{A: 1, B: "hello"}
	v.B = v.A
	if err := enc.Encode(v); err != nil {
		t.Fatalf("%+v", err)
	}
	expect := "a: &c\n  a: 1\n  b: hello\nb: *c\n"
	if expect != buf.String() {
		t.Fatalf("expect = [%s], actual = [%s]", expect, buf.String())
	}
}

func TestEncodeWithAutoAlias(t *testing.T) {
	var buf bytes.Buffer
	enc := yaml.NewEncoder(&buf)
	type T struct {
		I int
		S string
	}
	var v struct {
		A *T `yaml:"a,anchor=a"`
		B *T `yaml:"b,anchor=b"`
		C *T `yaml:"c,alias"`
		D *T `yaml:"d,alias"`
	}
	v.A = &T{I: 1, S: "hello"}
	v.B = &T{I: 2, S: "world"}
	v.C = v.A
	v.D = v.B
	if err := enc.Encode(v); err != nil {
		t.Fatalf("%+v", err)
	}
	expect := `a: &a
  i: 1
  s: hello
b: &b
  i: 2
  s: world
c: *a
d: *b
`
	if expect != buf.String() {
		t.Fatalf("expect = [%s], actual = [%s]", expect, buf.String())
	}
}

func TestEncodeWithImplicitAnchorAndAlias(t *testing.T) {
	var buf bytes.Buffer
	enc := yaml.NewEncoder(&buf)
	type T struct {
		I int
		S string
	}
	var v struct {
		A *T `yaml:"a,anchor"`
		B *T `yaml:"b,anchor"`
		C *T `yaml:"c,alias"`
		D *T `yaml:"d,alias"`
	}
	v.A = &T{I: 1, S: "hello"}
	v.B = &T{I: 2, S: "world"}
	v.C = v.A
	v.D = v.B
	if err := enc.Encode(v); err != nil {
		t.Fatalf("%+v", err)
	}
	expect := `a: &a
  i: 1
  s: hello
b: &b
  i: 2
  s: world
c: *a
d: *b
`
	if expect != buf.String() {
		t.Fatalf("expect = [%s], actual = [%s]", expect, buf.String())
	}
}

func TestEncodeWithMerge(t *testing.T) {
	type Person struct {
		*Person `yaml:",omitempty,inline,alias"`
		Name    string `yaml:",omitempty"`
		Age     int    `yaml:",omitempty"`
	}
	defaultPerson := &Person{
		Name: "John Smith",
		Age:  20,
	}
	people := []*Person{
		{
			Person: defaultPerson,
			Name:   "Ken",
			Age:    10,
		},
		{
			Person: defaultPerson,
		},
	}
	var doc struct {
		Default *Person   `yaml:"default,anchor"`
		People  []*Person `yaml:"people"`
	}
	doc.Default = defaultPerson
	doc.People = people
	var buf bytes.Buffer
	enc := yaml.NewEncoder(&buf)
	if err := enc.Encode(doc); err != nil {
		t.Fatalf("%+v", err)
	}
	expect := `default: &default
  name: John Smith
  age: 20
people:
- <<: *default
  name: Ken
  age: 10
- <<: *default
`
	if expect != buf.String() {
		t.Fatalf("expect = [%s], actual = [%s]", expect, buf.String())
	}
}

func Example_Marshal_ExplicitAnchorAlias() {
	type T struct {
		A int
		B string
	}
	var v struct {
		C *T `yaml:"c,anchor=x"`
		D *T `yaml:"d,alias=x"`
	}
	v.C = &T{A: 1, B: "hello"}
	v.D = v.C
	bytes, err := yaml.Marshal(v)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(bytes))
	// OUTPUT:
	//c: &x
	//   a: 1
	//   b: hello
	//d: *x
}

func Example_Marshal_ImplicitAnchorAlias() {
	type T struct {
		I int
		S string
	}
	var v struct {
		A *T `yaml:"a,anchor"`
		B *T `yaml:"b,anchor"`
		C *T `yaml:"c,alias"`
		D *T `yaml:"d,alias"`
	}
	v.A = &T{I: 1, S: "hello"}
	v.B = &T{I: 2, S: "world"}
	v.C = v.A // C has same pointer address to A
	v.D = v.B // D has same pointer address to B
	bytes, err := yaml.Marshal(v)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(bytes))
	// OUTPUT:
}
<commit_msg>oops, fix the output<commit_after>package yaml_test

import (
	"bytes"
	"fmt"
	"math"
	"testing"

	"github.com/goccy/go-yaml"
)

func TestEncoder(t *testing.T) {
	tests := []struct {
		source string
		value  interface{}
	}{
		{
			"null\n",
			(*struct{})(nil),
		},
		{
			"v: hi\n",
			map[string]string{"v": "hi"},
		},
		{
			"v: \"true\"\n",
			map[string]string{"v": "true"},
		},
		{
			"v: \"false\"\n",
			map[string]string{"v": "false"},
		},
		{
			"v: true\n",
			map[string]interface{}{"v": true},
		},
		{
			"v: false\n",
			map[string]bool{"v": false},
		},
		{
			"v: 10\n",
			map[string]int{"v": 10},
		},
		{
			"v: -10\n",
			map[string]int{"v": -10},
		},
		{
			"v: 4294967296\n",
			map[string]int{"v": 4294967296},
		},
		{
			"v: 0.1\n",
			map[string]interface{}{"v": 0.1},
		},
		{
			"v: 0.99\n",
			map[string]float32{"v": 0.99},
		},
		{
			"v: -0.1\n",
			map[string]float64{"v": -0.1},
		},
		{
			"v: 1.0\n",
			map[string]float64{"v": 1.0},
		},
		{
			"v: .inf\n",
			map[string]interface{}{"v": math.Inf(0)},
		},
		{
			"v: -.inf\n",
			map[string]interface{}{"v": math.Inf(-1)},
		},
		{
			"v: .nan\n",
			map[string]interface{}{"v": math.NaN()},
		},
		{
			"v: null\n",
			map[string]interface{}{"v": nil},
		},
		{
			"v: \"\"\n",
			map[string]string{"v": ""},
		},
		{
			"v:\n- A\n- B\n",
			map[string][]string{"v": {"A", "B"}},
		},
		{
			"a: -\n",
			map[string]string{"a": "-"},
		},
		{
			"123\n",
			123,
		},
		{
			"hello: world\n",
			map[string]string{"hello": "world"},
		},
		{
			"v:\n- A\n- 1\n- B:\n  - 2\n  - 3\n",
			map[string]interface{}{
				"v": []interface{}{
					"A",
					1,
					map[string][]int{
						"B": {2, 3},
					},
				},
			},
		},
		{
			"a:\n  b: c\n",
			map[string]interface{}{
				"a": map[string]string{
					"b": "c",
				},
			},
		},
		{
			"t2: 2018-01-09T10:40:47Z\nt4: 2098-01-09T10:40:47Z\n",
			map[string]string{
				"t2": "2018-01-09T10:40:47Z",
				"t4": "2098-01-09T10:40:47Z",
			},
		},
		{
			"a:\n  b: c\n  d: e\n",
			map[string]interface{}{
				"a": map[string]string{
					"b": "c",
					"d": "e",
				},
			},
		},
		{
			"a: 3s\n",
			map[string]string{
				"a": "3s",
			},
		},
		{
			"a: <foo>\n",
			map[string]string{"a": "<foo>"},
		},
		{
			"a: \"1:1\"\n",
			map[string]string{"a": "1:1"},
		},
		{
			"a: 1.2.3.4\n",
			map[string]string{"a": "1.2.3.4"},
		},
		{
			"a: \"b: c\"\n",
			map[string]string{"a": "b: c"},
		},
		{
			"a: \"Hello #comment\"\n",
			map[string]string{"a": "Hello #comment"},
		},
		{
			"a: 100.5\n",
			map[string]interface{}{
				"a": 100.5,
			},
		},
		{
			"a: \"\\\\0\"\n",
			map[string]string{"a": "\\0"},
		},
		{
			"a: 1\nb: 2\nc: 3\nd: 4\nsub:\n  e: 5\n",
			map[string]interface{}{
				"a": 1,
				"b": 2,
				"c": 3,
				"d": 4,
				"sub": map[string]int{
					"e": 5,
				},
			},
		},

		{
			"a: b\nc: d\n",
			struct {
				A string
				C string `yaml:"c"`
			}{
				"b", "d",
			},
		},
		{
			"a: 1\n",
			struct {
				A int
				B int `yaml:"-"`
			}{
				1, 0,
			},
		},
	}
	for _, test := range tests {
		var buf bytes.Buffer
		enc := yaml.NewEncoder(&buf)
		if err := enc.Encode(test.value); err != nil {
			t.Fatalf("%+v", err)
		}
		if test.source != buf.String() {
			t.Fatalf("expect = [%s], actual = [%s]", test.source, buf.String())
		}
	}
}

func TestEncodeWithAnchorAndAlias(t *testing.T) {
	var buf bytes.Buffer
	enc := yaml.NewEncoder(&buf)
	type T struct {
		A int
		B string
	}
	var v struct {
		A *T `yaml:"a,anchor=c"`
		B *T `yaml:"b,alias=c"`
	}
	v.A = &T{A: 1, B: "hello"}
	v.B = v.A
	if err := enc.Encode(v); err != nil {
		t.Fatalf("%+v", err)
	}
	expect := "a: &c\n  a: 1\n  b: hello\nb: *c\n"
	if expect != buf.String() {
		t.Fatalf("expect = [%s], actual = [%s]", expect, buf.String())
	}
}

func TestEncodeWithAutoAlias(t *testing.T) {
	var buf bytes.Buffer
	enc := yaml.NewEncoder(&buf)
	type T struct {
		I int
		S string
	}
	var v struct {
		A *T `yaml:"a,anchor=a"`
		B *T `yaml:"b,anchor=b"`
		C *T `yaml:"c,alias"`
		D *T `yaml:"d,alias"`
	}
	v.A = &T{I: 1, S: "hello"}
	v.B = &T{I: 2, S: "world"}
	v.C = v.A
	v.D = v.B
	if err := enc.Encode(v); err != nil {
		t.Fatalf("%+v", err)
	}
	expect := `a: &a
  i: 1
  s: hello
b: &b
  i: 2
  s: world
c: *a
d: *b
`
	if expect != buf.String() {
		t.Fatalf("expect = [%s], actual = [%s]", expect, buf.String())
	}
}

func TestEncodeWithImplicitAnchorAndAlias(t *testing.T) {
	var buf bytes.Buffer
	enc := yaml.NewEncoder(&buf)
	type T struct {
		I int
		S string
	}
	var v struct {
		A *T `yaml:"a,anchor"`
		B *T `yaml:"b,anchor"`
		C *T `yaml:"c,alias"`
		D *T `yaml:"d,alias"`
	}
	v.A = &T{I: 1, S: "hello"}
	v.B = &T{I: 2, S: "world"}
	v.C = v.A
	v.D = v.B
	if err := enc.Encode(v); err != nil {
		t.Fatalf("%+v", err)
	}
	expect := `a: &a
  i: 1
  s: hello
b: &b
  i: 2
  s: world
c: *a
d: *b
`
	if expect != buf.String() {
		t.Fatalf("expect = [%s], actual = [%s]", expect, buf.String())
	}
}

func TestEncodeWithMerge(t *testing.T) {
	type Person struct {
		*Person `yaml:",omitempty,inline,alias"`
		Name    string `yaml:",omitempty"`
		Age     int    `yaml:",omitempty"`
	}
	defaultPerson := &Person{
		Name: "John Smith",
		Age:  20,
	}
	people := []*Person{
		{
			Person: defaultPerson,
			Name:   "Ken",
			Age:    10,
		},
		{
			Person: defaultPerson,
		},
	}
	var doc struct {
		Default *Person   `yaml:"default,anchor"`
		People  []*Person `yaml:"people"`
	}
	doc.Default = defaultPerson
	doc.People = people
	var buf bytes.Buffer
	enc := yaml.NewEncoder(&buf)
	if err := enc.Encode(doc); err != nil {
		t.Fatalf("%+v", err)
	}
	expect := `default: &default
  name: John Smith
  age: 20
people:
- <<: *default
  name: Ken
  age: 10
- <<: *default
`
	if expect != buf.String() {
		t.Fatalf("expect = [%s], actual = [%s]", expect, buf.String())
	}
}

func Example_Marshal_ExplicitAnchorAlias() {
	type T struct {
		A int
		B string
	}
	var v struct {
		C *T `yaml:"c,anchor=x"`
		D *T `yaml:"d,alias=x"`
	}
	v.C = &T{A: 1, B: "hello"}
	v.D = v.C
	bytes, err := yaml.Marshal(v)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(bytes))
	// OUTPUT:
	//c: &x
	//   a: 1
	//   b: hello
	//d: *x
}

func Example_Marshal_ImplicitAnchorAlias() {
	type T struct {
		I int
		S string
	}
	var v struct {
		A *T `yaml:"a,anchor"`
		B *T `yaml:"b,anchor"`
		C *T `yaml:"c,alias"`
		D *T `yaml:"d,alias"`
	}
	v.A = &T{I: 1, S: "hello"}
	v.B = &T{I: 2, S: "world"}
	v.C = v.A // C has same pointer address to A
	v.D = v.B // D has same pointer address to B
	bytes, err := yaml.Marshal(v)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(bytes))
	// OUTPUT:
	// a: &a
	//   i: 1
	//   s: hello
	// b: &b
	//   i: 2
	//   s: world
	// c: *a
	// d: *b
}
<|endoftext|>


<commit_before>package main

import (
	"flag"

	"github.com/viant/endly"
	"log"
	_ "github.com/lib/pq"
	_ "github.com/mattn/go-sqlite3"
	_ "github.com/go-sql-driver/mysql"
	_ "github.com/viant/asc"
	_ "github.com/viant/bgc"
	"time"
)

var workflow = flag.String("workflow", "run.json", "path to workflow run request json file")

func main() {
	flag.Parse()
	runner := endly.NewCliRunner()
	err := runner.Run(*workflow)
	if err != nil {
		log.Fatal(err)
	}
	time.Sleep(time.Second)
}
<commit_msg>removed sqllite from import<commit_after>package main

import (
	"flag"

	"github.com/viant/endly"
	"log"
	_ "github.com/lib/pq"
	_ "github.com/go-sql-driver/mysql"
	_ "github.com/viant/asc"
	_ "github.com/viant/bgc"
	"time"
)

var workflow = flag.String("workflow", "run.json", "path to workflow run request json file")

func main() {
	flag.Parse()
	runner := endly.NewCliRunner()
	err := runner.Run(*workflow)
	if err != nil {
		log.Fatal(err)
	}
	time.Sleep(time.Second)
}
<|endoftext|>


<commit_before>package golang

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"

	"strings"

	"sourcegraph.com/sourcegraph/srcgraph/config"
	"sourcegraph.com/sourcegraph/srcgraph/container"
	"sourcegraph.com/sourcegraph/srcgraph/graph"
	"sourcegraph.com/sourcegraph/srcgraph/grapher2"
	"sourcegraph.com/sourcegraph/srcgraph/repo"
	"sourcegraph.com/sourcegraph/srcgraph/toolchain/golang/gog"
	"sourcegraph.com/sourcegraph/srcgraph/unit"
)

func init() {
	grapher2.Register(&Package{}, grapher2.DockerGrapher{defaultGoVersion})
}

func (v *goVersion) BuildGrapher(dir string, unit unit.SourceUnit, c *config.Repository) (*container.Command, error) {
	gogBinPath := filepath.Join(os.Getenv("GOBIN"), "gog")

	pkg := unit.(*Package)

	cont, err := v.containerForRepo(dir, unit, c)
	if err != nil {
		return nil, err
	}

	// Install VCS tools in Docker container.
	cont.Dockerfile = append(cont.Dockerfile, []byte("RUN apt-get -yq install git mercurial bzr subversion\n")...)

	cont.AddFiles = append(cont.AddFiles, [2]string{gogBinPath, "/usr/local/bin/gog"})
	cont.Cmd = []string{"bash", "-c", fmt.Sprintf("go get -v -t %s; gog %s", pkg.ImportPath, pkg.ImportPath)}

	cmd := container.Command{
		Container: *cont,
		Transform: func(in []byte) ([]byte, error) {
			var o gog.Output
			err := json.Unmarshal(in, &o)
			if err != nil {
				return nil, err
			}

			o2 := grapher2.Output{
				Symbols: make([]*graph.Symbol, len(o.Symbols)),
				Refs:    make([]*graph.Ref, len(o.Refs)),
				Docs:    make([]*graph.Doc, len(o.Docs)),
			}

			for i, gs := range o.Symbols {
				o2.Symbols[i], err = v.convertGoSymbol(gs, c)
				if err != nil {
					return nil, err
				}
			}
			for i, gr := range o.Refs {
				o2.Refs[i], err = v.convertGoRef(gr, c)
				if err != nil {
					return nil, err
				}
			}
			for i, gd := range o.Docs {
				o2.Docs[i], err = v.convertGoDoc(gd, c)
				if err != nil {
					return nil, err
				}
			}

			return json.Marshal(o2)
		},
	}

	return &cmd, nil
}

// SymbolData is extra Go-specific data about a symbol.
type SymbolData struct {
	gog.SymbolInfo

	// PackageImportPath is the import path of the package containing this
	// symbol (if this symbol is not a package). If this symbol is a package,
	// PackageImportPath is its own import path.
	PackageImportPath string `json:",omitempty"`
}

func (v *goVersion) convertGoSymbol(gs *gog.Symbol, c *config.Repository) (*graph.Symbol, error) {
	resolvedTarget, err := v.resolveGoImportDep(gs.SymbolKey.PackageImportPath, c)
	if err != nil {
		return nil, err
	}
	path := graph.SymbolPath(pathOrDot(strings.Join(gs.Path, "/")))
	treePath := graph.TreePath(path)
	if !treePath.IsValid() {
		return nil, fmt.Errorf("'%s' is not a valid tree-path")
	}

	sym := &graph.Symbol{
		SymbolKey: graph.SymbolKey{
			Unit:     resolvedTarget.ToUnit,
			UnitType: resolvedTarget.ToUnitType,
			Path:     path,
		},
		TreePath: treePath,

		Name: gs.Name,
		Kind: graph.SymbolKind(gog.GeneralKindMap[gs.Kind]),

		File:     gs.File,
		DefStart: gs.DeclSpan[0],
		DefEnd:   gs.DeclSpan[1],

		Exported: gs.SymbolInfo.Exported,
		Test:     strings.HasSuffix(gs.File, "_test.go"),
	}

	d := SymbolData{
		PackageImportPath: gs.SymbolKey.PackageImportPath,
		SymbolInfo:        gs.SymbolInfo,
	}
	sym.Data, err = json.Marshal(d)
	if err != nil {
		return nil, err
	}

	if sym.Kind == "func" {
		sym.Callable = true
	}

	return sym, nil
}

func (v *goVersion) convertGoRef(gr *gog.Ref, c *config.Repository) (*graph.Ref, error) {
	resolvedTarget, err := v.resolveGoImportDep(gr.Symbol.PackageImportPath, c)
	if err != nil {
		return nil, err
	}
	if resolvedTarget == nil {
		return nil, nil
	}

	return &graph.Ref{
		SymbolRepo:     uriOrEmpty(resolvedTarget.ToRepoCloneURL),
		SymbolPath:     graph.SymbolPath(pathOrDot(strings.Join(gr.Symbol.Path, "/"))),
		SymbolUnit:     resolvedTarget.ToUnit,
		SymbolUnitType: resolvedTarget.ToUnitType,
		Def:            gr.Def,
		File:           gr.File,
		Start:          gr.Span[0],
		End:            gr.Span[1],
	}, nil
}

func (v *goVersion) convertGoDoc(gd *gog.Doc, c *config.Repository) (*graph.Doc, error) {
	resolvedTarget, err := v.resolveGoImportDep(gd.PackageImportPath, c)
	if err != nil {
		return nil, err
	}
	return &graph.Doc{
		SymbolKey: graph.SymbolKey{
			Path:     graph.SymbolPath(pathOrDot(strings.Join(gd.Path, "/"))),
			Unit:     resolvedTarget.ToUnit,
			UnitType: resolvedTarget.ToUnitType,
		},
		Format: gd.Format,
		Data:   gd.Data,
		File:   gd.File,
		Start:  gd.Span[0],
		End:    gd.Span[1],
	}, nil
}

func uriOrEmpty(cloneURL string) repo.URI {
	if cloneURL == "" {
		return ""
	}
	return repo.MakeURI(cloneURL)
}

func pathOrDot(path string) string {
	if path == "" {
		return "."
	}
	return fmt.Sprintf("./%s", path)
}
<commit_msg>keep original go symbol path<commit_after>package golang

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"

	"strings"

	"sourcegraph.com/sourcegraph/srcgraph/config"
	"sourcegraph.com/sourcegraph/srcgraph/container"
	"sourcegraph.com/sourcegraph/srcgraph/graph"
	"sourcegraph.com/sourcegraph/srcgraph/grapher2"
	"sourcegraph.com/sourcegraph/srcgraph/repo"
	"sourcegraph.com/sourcegraph/srcgraph/toolchain/golang/gog"
	"sourcegraph.com/sourcegraph/srcgraph/unit"
)

func init() {
	grapher2.Register(&Package{}, grapher2.DockerGrapher{defaultGoVersion})
}

func (v *goVersion) BuildGrapher(dir string, unit unit.SourceUnit, c *config.Repository) (*container.Command, error) {
	gogBinPath := filepath.Join(os.Getenv("GOBIN"), "gog")

	pkg := unit.(*Package)

	cont, err := v.containerForRepo(dir, unit, c)
	if err != nil {
		return nil, err
	}

	// Install VCS tools in Docker container.
	cont.Dockerfile = append(cont.Dockerfile, []byte("RUN apt-get -yq install git mercurial bzr subversion\n")...)

	cont.AddFiles = append(cont.AddFiles, [2]string{gogBinPath, "/usr/local/bin/gog"})
	cont.Cmd = []string{"bash", "-c", fmt.Sprintf("go get -v -t %s; gog %s", pkg.ImportPath, pkg.ImportPath)}

	cmd := container.Command{
		Container: *cont,
		Transform: func(in []byte) ([]byte, error) {
			var o gog.Output
			err := json.Unmarshal(in, &o)
			if err != nil {
				return nil, err
			}

			o2 := grapher2.Output{
				Symbols: make([]*graph.Symbol, len(o.Symbols)),
				Refs:    make([]*graph.Ref, len(o.Refs)),
				Docs:    make([]*graph.Doc, len(o.Docs)),
			}

			for i, gs := range o.Symbols {
				o2.Symbols[i], err = v.convertGoSymbol(gs, c)
				if err != nil {
					return nil, err
				}
			}
			for i, gr := range o.Refs {
				o2.Refs[i], err = v.convertGoRef(gr, c)
				if err != nil {
					return nil, err
				}
			}
			for i, gd := range o.Docs {
				o2.Docs[i], err = v.convertGoDoc(gd, c)
				if err != nil {
					return nil, err
				}
			}

			return json.Marshal(o2)
		},
	}

	return &cmd, nil
}

// SymbolData is extra Go-specific data about a symbol.
type SymbolData struct {
	gog.SymbolInfo

	// PackageImportPath is the import path of the package containing this
	// symbol (if this symbol is not a package). If this symbol is a package,
	// PackageImportPath is its own import path.
	PackageImportPath string `json:",omitempty"`
}

func (v *goVersion) convertGoSymbol(gs *gog.Symbol, c *config.Repository) (*graph.Symbol, error) {
	resolvedTarget, err := v.resolveGoImportDep(gs.SymbolKey.PackageImportPath, c)
	if err != nil {
		return nil, err
	}
	path := graph.SymbolPath(pathOrDot(strings.Join(gs.Path, "/")))
	treePath := treePath(string(path))
	if !treePath.IsValid() {
		return nil, fmt.Errorf("'%s' is not a valid tree-path")
	}

	sym := &graph.Symbol{
		SymbolKey: graph.SymbolKey{
			Unit:     resolvedTarget.ToUnit,
			UnitType: resolvedTarget.ToUnitType,
			Path:     path,
		},
		TreePath: treePath,

		Name: gs.Name,
		Kind: graph.SymbolKind(gog.GeneralKindMap[gs.Kind]),

		File:     gs.File,
		DefStart: gs.DeclSpan[0],
		DefEnd:   gs.DeclSpan[1],

		Exported: gs.SymbolInfo.Exported,
		Test:     strings.HasSuffix(gs.File, "_test.go"),
	}

	d := SymbolData{
		PackageImportPath: gs.SymbolKey.PackageImportPath,
		SymbolInfo:        gs.SymbolInfo,
	}
	sym.Data, err = json.Marshal(d)
	if err != nil {
		return nil, err
	}

	if sym.Kind == "func" {
		sym.Callable = true
	}

	return sym, nil
}

func (v *goVersion) convertGoRef(gr *gog.Ref, c *config.Repository) (*graph.Ref, error) {
	resolvedTarget, err := v.resolveGoImportDep(gr.Symbol.PackageImportPath, c)
	if err != nil {
		return nil, err
	}
	if resolvedTarget == nil {
		return nil, nil
	}

	return &graph.Ref{
		SymbolRepo:     uriOrEmpty(resolvedTarget.ToRepoCloneURL),
		SymbolPath:     graph.SymbolPath(pathOrDot(strings.Join(gr.Symbol.Path, "/"))),
		SymbolUnit:     resolvedTarget.ToUnit,
		SymbolUnitType: resolvedTarget.ToUnitType,
		Def:            gr.Def,
		File:           gr.File,
		Start:          gr.Span[0],
		End:            gr.Span[1],
	}, nil
}

func (v *goVersion) convertGoDoc(gd *gog.Doc, c *config.Repository) (*graph.Doc, error) {
	resolvedTarget, err := v.resolveGoImportDep(gd.PackageImportPath, c)
	if err != nil {
		return nil, err
	}
	return &graph.Doc{
		SymbolKey: graph.SymbolKey{
			Path:     graph.SymbolPath(pathOrDot(strings.Join(gd.Path, "/"))),
			Unit:     resolvedTarget.ToUnit,
			UnitType: resolvedTarget.ToUnitType,
		},
		Format: gd.Format,
		Data:   gd.Data,
		File:   gd.File,
		Start:  gd.Span[0],
		End:    gd.Span[1],
	}, nil
}

func uriOrEmpty(cloneURL string) repo.URI {
	if cloneURL == "" {
		return ""
	}
	return repo.MakeURI(cloneURL)
}

func pathOrDot(path string) string {
	if path == "" {
		return "."
	}
	return path
}

func treePath(path string) graph.TreePath {
	if path == "" || path == "." {
		return graph.TreePath(".")
	}
	return graph.TreePath(fmt.Sprintf("./%s", path))
}
<|endoftext|>


<commit_before>package oci

import (
	"context"
	"errors"
	"fmt"
	"regexp"
	"time"

	core "github.com/oracle/oci-go-sdk/core"
)

// driverOCI implements the Driver interface and communicates with Oracle
// OCI.
type driverOCI struct {
	computeClient core.ComputeClient
	vcnClient     core.VirtualNetworkClient
	cfg           *Config
	context       context.Context
}

// NewDriverOCI Creates a new driverOCI with a connected compute client and a connected vcn client.
func NewDriverOCI(cfg *Config) (Driver, error) {
	coreClient, err := core.NewComputeClientWithConfigurationProvider(cfg.configProvider)
	if err != nil {
		return nil, err
	}

	vcnClient, err := core.NewVirtualNetworkClientWithConfigurationProvider(cfg.configProvider)
	if err != nil {
		return nil, err
	}

	return &driverOCI{
		computeClient: coreClient,
		vcnClient:     vcnClient,
		cfg:           cfg,
	}, nil
}

// CreateInstance creates a new compute instance.
func (d *driverOCI) CreateInstance(ctx context.Context, publicKey string) (string, error) {
	metadata := map[string]string{
		"ssh_authorized_keys": publicKey,
	}
	if d.cfg.Metadata != nil {
		for key, value := range d.cfg.Metadata {
			metadata[key] = value
		}
	}
	if d.cfg.UserData != "" {
		metadata["user_data"] = d.cfg.UserData
	}

	// Create VNIC details for instance
	CreateVnicDetails := core.CreateVnicDetails{
		AssignPublicIp:      d.cfg.CreateVnicDetails.AssignPublicIp,
		DisplayName:         d.cfg.CreateVnicDetails.DisplayName,
		HostnameLabel:       d.cfg.CreateVnicDetails.HostnameLabel,
		NsgIds:              d.cfg.CreateVnicDetails.NsgIds,
		PrivateIp:           d.cfg.CreateVnicDetails.PrivateIp,
		SkipSourceDestCheck: d.cfg.CreateVnicDetails.SkipSourceDestCheck,
		SubnetId:            d.cfg.CreateVnicDetails.SubnetId,
		DefinedTags:         d.cfg.CreateVnicDetails.DefinedTags,
		FreeformTags:        d.cfg.CreateVnicDetails.FreeformTags,
	}

	// Determine base image ID
	var imageId *string
	if d.cfg.BaseImageID != "" {
		imageId = &d.cfg.BaseImageID
	} else {
		// Pull images and determine which image ID to use, if BaseImageId not specified
		response, err := d.computeClient.ListImages(ctx, core.ListImagesRequest{
			CompartmentId:          d.cfg.BaseImageFilter.CompartmentId,
			DisplayName:            d.cfg.BaseImageFilter.DisplayName,
			OperatingSystem:        d.cfg.BaseImageFilter.OperatingSystem,
			OperatingSystemVersion: d.cfg.BaseImageFilter.OperatingSystemVersion,
			Shape:                  d.cfg.BaseImageFilter.Shape,
			LifecycleState:         "AVAILABLE",
			SortBy:                 "TIMECREATED",
			SortOrder:              "DESC",
		})
		if err != nil {
			return "", err
		}
		if len(response.Items) == 0 {
			return "", errors.New("base_image_filter returned no images")
		}
		if d.cfg.BaseImageFilter.DisplayNameSearch != nil {
			// Return most recent image that matches regex
			imageNameRegex, err := regexp.Compile(*d.cfg.BaseImageFilter.DisplayNameSearch)
			if err != nil {
				return "", err
			}
			for _, image := range response.Items {
				if imageNameRegex.MatchString(*image.DisplayName) {
					imageId = image.Id
					break
				}
			}
			if imageId == nil {
				return "", errors.New("No image matched display_name_search criteria")
			}
		} else {
			// If no regex provided, simply return most recent image pulled
			imageId = response.Items[0].Id
		}
	}

	// Create Source details which will be used to Launch Instance
	InstanceSourceDetails := core.InstanceSourceViaImageDetails{
		ImageId:             imageId,
		BootVolumeSizeInGBs: &d.cfg.BootVolumeSizeInGBs,
	}

	// Build instance details
	instanceDetails := core.LaunchInstanceDetails{
		AvailabilityDomain: &d.cfg.AvailabilityDomain,
		CompartmentId:      &d.cfg.CompartmentID,
		CreateVnicDetails:  &CreateVnicDetails,
		DefinedTags:        d.cfg.InstanceDefinedTags,
		DisplayName:        d.cfg.InstanceName,
		FreeformTags:       d.cfg.InstanceTags,
		Shape:              &d.cfg.Shape,
		SourceDetails:      InstanceSourceDetails,
		Metadata:           metadata,
	}

	instance, err := d.computeClient.LaunchInstance(context.TODO(), core.LaunchInstanceRequest{LaunchInstanceDetails: instanceDetails})

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

	return *instance.Id, nil
}

// CreateImage creates a new custom image.
func (d *driverOCI) CreateImage(ctx context.Context, id string) (core.Image, error) {
	res, err := d.computeClient.CreateImage(ctx, core.CreateImageRequest{CreateImageDetails: core.CreateImageDetails{
		CompartmentId: &d.cfg.ImageCompartmentID,
		InstanceId:    &id,
		DisplayName:   &d.cfg.ImageName,
		FreeformTags:  d.cfg.Tags,
		DefinedTags:   d.cfg.DefinedTags,
		LaunchMode:    core.CreateImageDetailsLaunchModeEnum(d.cfg.LaunchMode),
	}})

	if err != nil {
		return core.Image{}, err
	}

	return res.Image, nil
}

// DeleteImage deletes a custom image.
func (d *driverOCI) DeleteImage(ctx context.Context, id string) error {
	_, err := d.computeClient.DeleteImage(ctx, core.DeleteImageRequest{ImageId: &id})
	return err
}

// GetInstanceIP returns the public or private IP corresponding to the given instance id.
func (d *driverOCI) GetInstanceIP(ctx context.Context, id string) (string, error) {
	vnics, err := d.computeClient.ListVnicAttachments(ctx, core.ListVnicAttachmentsRequest{
		InstanceId:    &id,
		CompartmentId: &d.cfg.CompartmentID,
	})
	if err != nil {
		return "", err
	}

	if len(vnics.Items) == 0 {
		return "", errors.New("instance has zero VNICs")
	}

	vnic, err := d.vcnClient.GetVnic(ctx, core.GetVnicRequest{VnicId: vnics.Items[0].VnicId})
	if err != nil {
		return "", fmt.Errorf("Error getting VNIC details: %s", err)
	}

	if d.cfg.UsePrivateIP {
		return *vnic.PrivateIp, nil
	}

	if vnic.PublicIp == nil {
		return "", fmt.Errorf("Error getting VNIC Public Ip for: %s", id)
	}

	return *vnic.PublicIp, nil
}

func (d *driverOCI) GetInstanceInitialCredentials(ctx context.Context, id string) (string, string, error) {
	credentials, err := d.computeClient.GetWindowsInstanceInitialCredentials(ctx, core.GetWindowsInstanceInitialCredentialsRequest{
		InstanceId: &id,
	})
	if err != nil {
		return "", "", err
	}

	return *credentials.InstanceCredentials.Username, *credentials.InstanceCredentials.Password, err
}

// TerminateInstance terminates a compute instance.
func (d *driverOCI) TerminateInstance(ctx context.Context, id string) error {
	_, err := d.computeClient.TerminateInstance(ctx, core.TerminateInstanceRequest{
		InstanceId: &id,
	})
	return err
}

// WaitForImageCreation waits for a provisioning custom image to reach the
// "AVAILABLE" state.
func (d *driverOCI) WaitForImageCreation(ctx context.Context, id string) error {
	return waitForResourceToReachState(
		func(string) (string, error) {
			image, err := d.computeClient.GetImage(ctx, core.GetImageRequest{ImageId: &id})
			if err != nil {
				return "", err
			}
			return string(image.LifecycleState), nil
		},
		id,
		[]string{"PROVISIONING"},
		"AVAILABLE",
		0,             //Unlimited Retries
		5*time.Second, //5 second wait between retries
	)
}

// WaitForInstanceState waits for an instance to reach the a given terminal
// state.
func (d *driverOCI) WaitForInstanceState(ctx context.Context, id string, waitStates []string, terminalState string) error {
	return waitForResourceToReachState(
		func(string) (string, error) {
			instance, err := d.computeClient.GetInstance(ctx, core.GetInstanceRequest{InstanceId: &id})
			if err != nil {
				return "", err
			}
			return string(instance.LifecycleState), nil
		},
		id,
		waitStates,
		terminalState,
		0,             //Unlimited Retries
		5*time.Second, //5 second wait between retries
	)
}

// WaitForResourceToReachState checks the response of a request through a
// polled get and waits until the desired state or until the max retried has
// been reached.
func waitForResourceToReachState(getResourceState func(string) (string, error), id string, waitStates []string, terminalState string, maxRetries int, waitDuration time.Duration) error {
	for i := 0; maxRetries == 0 || i < maxRetries; i++ {
		state, err := getResourceState(id)
		if err != nil {
			return err
		}

		if stringSliceContains(waitStates, state) {
			time.Sleep(waitDuration)
			continue
		} else if state == terminalState {
			return nil
		}
		return fmt.Errorf("Unexpected resource state %q, expecting a waiting state %s or terminal state  %q ", state, waitStates, terminalState)
	}
	return fmt.Errorf("Maximum number of retries (%d) exceeded; resource did not reach state %q", maxRetries, terminalState)
}

// stringSliceContains loops through a slice of strings returning a boolean
// based on whether a given value is contained in the slice.
func stringSliceContains(slice []string, value string) bool {
	for _, elem := range slice {
		if elem == value {
			return true
		}
	}
	return false
}
<commit_msg>Add retry strategies to oci calls<commit_after>package oci

import (
	"context"
	"errors"
	"fmt"
	"regexp"
	"time"

	"github.com/oracle/oci-go-sdk/common"
	core "github.com/oracle/oci-go-sdk/core"
)

// driverOCI implements the Driver interface and communicates with Oracle
// OCI.
type driverOCI struct {
	computeClient core.ComputeClient
	vcnClient     core.VirtualNetworkClient
	cfg           *Config
	context       context.Context
}

var retryPolicy = &common.RetryPolicy{
	MaximumNumberAttempts: 10,
	ShouldRetryOperation: func(res common.OCIOperationResponse) bool {
		if res.Error != nil {
			return true
		}
		return false
	},
	NextDuration: func(common.OCIOperationResponse) time.Duration {
		return 2 * time.Second
	},
}
var requestMetadata = common.RequestMetadata{
	RetryPolicy: retryPolicy,
}

// NewDriverOCI Creates a new driverOCI with a connected compute client and a connected vcn client.
func NewDriverOCI(cfg *Config) (Driver, error) {
	coreClient, err := core.NewComputeClientWithConfigurationProvider(cfg.configProvider)
	if err != nil {
		return nil, err
	}

	vcnClient, err := core.NewVirtualNetworkClientWithConfigurationProvider(cfg.configProvider)
	if err != nil {
		return nil, err
	}

	return &driverOCI{
		computeClient: coreClient,
		vcnClient:     vcnClient,
		cfg:           cfg,
	}, nil
}

// CreateInstance creates a new compute instance.
func (d *driverOCI) CreateInstance(ctx context.Context, publicKey string) (string, error) {
	metadata := map[string]string{
		"ssh_authorized_keys": publicKey,
	}
	if d.cfg.Metadata != nil {
		for key, value := range d.cfg.Metadata {
			metadata[key] = value
		}
	}
	if d.cfg.UserData != "" {
		metadata["user_data"] = d.cfg.UserData
	}

	// Create VNIC details for instance
	CreateVnicDetails := core.CreateVnicDetails{
		AssignPublicIp:      d.cfg.CreateVnicDetails.AssignPublicIp,
		DisplayName:         d.cfg.CreateVnicDetails.DisplayName,
		HostnameLabel:       d.cfg.CreateVnicDetails.HostnameLabel,
		NsgIds:              d.cfg.CreateVnicDetails.NsgIds,
		PrivateIp:           d.cfg.CreateVnicDetails.PrivateIp,
		SkipSourceDestCheck: d.cfg.CreateVnicDetails.SkipSourceDestCheck,
		SubnetId:            d.cfg.CreateVnicDetails.SubnetId,
		DefinedTags:         d.cfg.CreateVnicDetails.DefinedTags,
		FreeformTags:        d.cfg.CreateVnicDetails.FreeformTags,
	}

	// Determine base image ID
	var imageId *string
	if d.cfg.BaseImageID != "" {
		imageId = &d.cfg.BaseImageID
	} else {
		// Pull images and determine which image ID to use, if BaseImageId not specified
		response, err := d.computeClient.ListImages(ctx, core.ListImagesRequest{
			CompartmentId:          d.cfg.BaseImageFilter.CompartmentId,
			DisplayName:            d.cfg.BaseImageFilter.DisplayName,
			OperatingSystem:        d.cfg.BaseImageFilter.OperatingSystem,
			OperatingSystemVersion: d.cfg.BaseImageFilter.OperatingSystemVersion,
			Shape:                  d.cfg.BaseImageFilter.Shape,
			LifecycleState:         "AVAILABLE",
			SortBy:                 "TIMECREATED",
			SortOrder:              "DESC",
			RequestMetadata:        requestMetadata,
		})
		if err != nil {
			return "", err
		}
		if len(response.Items) == 0 {
			return "", errors.New("base_image_filter returned no images")
		}
		if d.cfg.BaseImageFilter.DisplayNameSearch != nil {
			// Return most recent image that matches regex
			imageNameRegex, err := regexp.Compile(*d.cfg.BaseImageFilter.DisplayNameSearch)
			if err != nil {
				return "", err
			}
			for _, image := range response.Items {
				if imageNameRegex.MatchString(*image.DisplayName) {
					imageId = image.Id
					break
				}
			}
			if imageId == nil {
				return "", errors.New("No image matched display_name_search criteria")
			}
		} else {
			// If no regex provided, simply return most recent image pulled
			imageId = response.Items[0].Id
		}
	}

	// Create Source details which will be used to Launch Instance
	InstanceSourceDetails := core.InstanceSourceViaImageDetails{
		ImageId:             imageId,
		BootVolumeSizeInGBs: &d.cfg.BootVolumeSizeInGBs,
	}

	// Build instance details
	instanceDetails := core.LaunchInstanceDetails{
		AvailabilityDomain: &d.cfg.AvailabilityDomain,
		CompartmentId:      &d.cfg.CompartmentID,
		CreateVnicDetails:  &CreateVnicDetails,
		DefinedTags:        d.cfg.InstanceDefinedTags,
		DisplayName:        d.cfg.InstanceName,
		FreeformTags:       d.cfg.InstanceTags,
		Shape:              &d.cfg.Shape,
		SourceDetails:      InstanceSourceDetails,
		Metadata:           metadata,
	}

	instance, err := d.computeClient.LaunchInstance(context.TODO(), core.LaunchInstanceRequest{
		LaunchInstanceDetails: instanceDetails,
		RequestMetadata:       requestMetadata,
	})

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

	return *instance.Id, nil
}

// CreateImage creates a new custom image.
func (d *driverOCI) CreateImage(ctx context.Context, id string) (core.Image, error) {
	res, err := d.computeClient.CreateImage(ctx, core.CreateImageRequest{CreateImageDetails: core.CreateImageDetails{
		CompartmentId: &d.cfg.ImageCompartmentID,
		InstanceId:    &id,
		DisplayName:   &d.cfg.ImageName,
		FreeformTags:  d.cfg.Tags,
		DefinedTags:   d.cfg.DefinedTags,
		LaunchMode:    core.CreateImageDetailsLaunchModeEnum(d.cfg.LaunchMode),
	},
		RequestMetadata: requestMetadata,
	})

	if err != nil {
		return core.Image{}, err
	}

	return res.Image, nil
}

// DeleteImage deletes a custom image.
func (d *driverOCI) DeleteImage(ctx context.Context, id string) error {
	_, err := d.computeClient.DeleteImage(ctx, core.DeleteImageRequest{
		ImageId:         &id,
		RequestMetadata: requestMetadata,
	})
	return err
}

// GetInstanceIP returns the public or private IP corresponding to the given instance id.
func (d *driverOCI) GetInstanceIP(ctx context.Context, id string) (string, error) {
	vnics, err := d.computeClient.ListVnicAttachments(ctx, core.ListVnicAttachmentsRequest{
		InstanceId:      &id,
		CompartmentId:   &d.cfg.CompartmentID,
		RequestMetadata: requestMetadata,
	})
	if err != nil {
		return "", err
	}

	if len(vnics.Items) == 0 {
		return "", errors.New("instance has zero VNICs")
	}

	vnic, err := d.vcnClient.GetVnic(ctx, core.GetVnicRequest{
		VnicId:          vnics.Items[0].VnicId,
		RequestMetadata: requestMetadata,
	})
	if err != nil {
		return "", fmt.Errorf("Error getting VNIC details: %s", err)
	}

	if d.cfg.UsePrivateIP {
		return *vnic.PrivateIp, nil
	}

	if vnic.PublicIp == nil {
		return "", fmt.Errorf("Error getting VNIC Public Ip for: %s", id)
	}

	return *vnic.PublicIp, nil
}

func (d *driverOCI) GetInstanceInitialCredentials(ctx context.Context, id string) (string, string, error) {
	credentials, err := d.computeClient.GetWindowsInstanceInitialCredentials(ctx, core.GetWindowsInstanceInitialCredentialsRequest{
		InstanceId:      &id,
		RequestMetadata: requestMetadata,
	})
	if err != nil {
		return "", "", err
	}

	return *credentials.InstanceCredentials.Username, *credentials.InstanceCredentials.Password, err
}

// TerminateInstance terminates a compute instance.
func (d *driverOCI) TerminateInstance(ctx context.Context, id string) error {
	_, err := d.computeClient.TerminateInstance(ctx, core.TerminateInstanceRequest{
		InstanceId:      &id,
		RequestMetadata: requestMetadata,
	})
	return err
}

// WaitForImageCreation waits for a provisioning custom image to reach the
// "AVAILABLE" state.
func (d *driverOCI) WaitForImageCreation(ctx context.Context, id string) error {
	return waitForResourceToReachState(
		func(string) (string, error) {
			image, err := d.computeClient.GetImage(ctx, core.GetImageRequest{
				ImageId:         &id,
				RequestMetadata: requestMetadata,
			})
			if err != nil {
				return "", err
			}
			return string(image.LifecycleState), nil
		},
		id,
		[]string{"PROVISIONING"},
		"AVAILABLE",
		0,             //Unlimited Retries
		5*time.Second, //5 second wait between retries
	)
}

// WaitForInstanceState waits for an instance to reach the a given terminal
// state.
func (d *driverOCI) WaitForInstanceState(ctx context.Context, id string, waitStates []string, terminalState string) error {
	return waitForResourceToReachState(
		func(string) (string, error) {
			instance, err := d.computeClient.GetInstance(ctx, core.GetInstanceRequest{
				InstanceId:      &id,
				RequestMetadata: requestMetadata,
			})
			if err != nil {
				return "", err
			}
			return string(instance.LifecycleState), nil
		},
		id,
		waitStates,
		terminalState,
		0,             //Unlimited Retries
		5*time.Second, //5 second wait between retries
	)
}

// WaitForResourceToReachState checks the response of a request through a
// polled get and waits until the desired state or until the max retried has
// been reached.
func waitForResourceToReachState(getResourceState func(string) (string, error), id string, waitStates []string, terminalState string, maxRetries int, waitDuration time.Duration) error {
	for i := 0; maxRetries == 0 || i < maxRetries; i++ {
		state, err := getResourceState(id)
		if err != nil {
			return err
		}

		if stringSliceContains(waitStates, state) {
			time.Sleep(waitDuration)
			continue
		} else if state == terminalState {
			return nil
		}
		return fmt.Errorf("Unexpected resource state %q, expecting a waiting state %s or terminal state  %q ", state, waitStates, terminalState)
	}
	return fmt.Errorf("Maximum number of retries (%d) exceeded; resource did not reach state %q", maxRetries, terminalState)
}

// stringSliceContains loops through a slice of strings returning a boolean
// based on whether a given value is contained in the slice.
func stringSliceContains(slice []string, value string) bool {
	for _, elem := range slice {
		if elem == value {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"errors"
	"net"
	"net/url"
	"time"

	"github.com/centrifugal/centrifugo/logger"

	"github.com/garyburd/redigo/redis"
	"github.com/mitchellh/mapstructure"
)

// redisEngine uses Redis datastructures and PUB/SUB to manage Centrifuge logic.
// This engine allows to scale Centrifuge - you can run several Centrifuge instances
// connected to the same Redis and load balance clients between instances.
type redisEngine struct {
	app      *application
	pool     *redis.Pool
	psc      redis.PubSubConn
	api      bool
	inPubSub bool
	inApi    bool
}

func newRedisEngine(app *application, host, port, password, db, redisUrl string, api bool) *redisEngine {
	if redisUrl != "" {
		u, err := url.Parse(redisUrl)
		if err != nil {
			panic(err)
		}
		if u.User != nil {
			var ok bool
			password, ok = u.User.Password()
			if !ok {
				password = ""
			}
		}
		host, port, err = net.SplitHostPort(u.Host)
		if err != nil {
			panic(err)
		}
		path := u.Path
		if path != "" {
			db = path[1:]
		}
		if db == "" {
			db = "0"
		}
	}
	server := host + ":" + port
	pool := newPool(server, password, db)
	return &redisEngine{
		app:  app,
		pool: pool,
		api:  api,
	}
}

func newPool(server, password, db string) *redis.Pool {
	return &redis.Pool{
		MaxIdle:     3,
		IdleTimeout: 240 * time.Second,
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial("tcp", server)
			if err != nil {
				logger.CRITICAL.Println(err)
				return nil, err
			}
			if password != "" {
				if _, err := c.Do("AUTH", password); err != nil {
					c.Close()
					logger.CRITICAL.Println(err)
					return nil, err
				}
			}
			if _, err := c.Do("SELECT", db); err != nil {
				c.Close()
				logger.CRITICAL.Println(err)
				return nil, err
			}
			return c, err
		},
		TestOnBorrow: func(c redis.Conn, t time.Time) error {
			_, err := c.Do("PING")
			return err
		},
	}
}

func (e *redisEngine) getName() string {
	return "Redis"
}

func (e *redisEngine) initialize() error {
	go e.initializePubSub()
	if e.api {
		go e.initializeApi()
	}
	go e.checkConnectionStatus()
	return nil
}

func (e *redisEngine) checkConnectionStatus() {
	for {
		time.Sleep(time.Second)
		if !e.inPubSub {
			go e.initializePubSub()
		}
		if e.api && !e.inApi {
			go e.initializeApi()
		}
	}
}

type redisApiRequest struct {
	Project string
	Data    []map[string]interface{}
}

func (e *redisEngine) initializeApi() {
	e.inApi = true
	conn := e.pool.Get()
	defer conn.Close()
	defer func() {
		e.inApi = false
	}()
	apiKey := e.app.channelPrefix + "." + "api"
	for {
		reply, err := conn.Do("BLPOP", apiKey, 0)
		if err != nil {
			logger.ERROR.Println(err)
			return
		}
		a, err := mapStringInterface(reply, nil)
		if err != nil {
			logger.ERROR.Println(err)
			continue
		}
		body, ok := a[apiKey]
		if !ok {
			continue
		}
		var request redisApiRequest
		err = mapstructure.Decode(body, &request)
		if err != nil {
			logger.ERROR.Println(err)
			continue
		}
		project, exists := e.app.getProjectByKey(request.Project)
		if !exists {
			logger.ERROR.Println("no project found with key", request.Project)
			continue
		}

		var commands []apiCommand
		err = mapstructure.Decode(request.Data, &commands)
		if err != nil {
			logger.ERROR.Println(err)
			continue
		}
		for _, command := range commands {
			_, err := e.app.handleApiCommand(project, command)
			if err != nil {
				logger.ERROR.Println(err)
			}
		}
	}
}

func (e *redisEngine) initializePubSub() {
	e.inPubSub = true
	e.psc = redis.PubSubConn{e.pool.Get()}
	defer e.psc.Close()
	defer func() {
		e.inPubSub = false
	}()
	err := e.psc.Subscribe(e.app.adminChannel)
	if err != nil {
		e.psc.Close()
		return
	}
	err = e.psc.Subscribe(e.app.controlChannel)
	if err != nil {
		e.psc.Close()
		return
	}
	for _, channel := range e.app.clientSubscriptionHub.getChannels() {
		err = e.psc.Subscribe(channel)
		if err != nil {
			e.psc.Close()
			return
		}
	}
	for {
		switch n := e.psc.Receive().(type) {
		case redis.Message:
			e.app.handleMessage(n.Channel, n.Data)
		case redis.Subscription:
		case error:
			logger.ERROR.Printf("error: %v\n", n)
			e.psc.Close()
			return
		}
	}
}

func (e *redisEngine) publish(channel string, message []byte) error {
	conn := e.pool.Get()
	defer conn.Close()
	_, err := conn.Do("PUBLISH", channel, message)
	return err
}

func (e *redisEngine) subscribe(channel string) error {
	return e.psc.Subscribe(channel)
}

func (e *redisEngine) unsubscribe(channel string) error {
	return e.psc.Unsubscribe(channel)
}

func (e *redisEngine) getHashKey(channel string) string {
	return e.app.channelPrefix + ".presence.hash." + channel
}

func (e *redisEngine) getSetKey(channel string) string {
	return e.app.channelPrefix + ".presence.set." + channel
}

func (e *redisEngine) getHistoryKey(channel string) string {
	return e.app.channelPrefix + ".history.list." + channel
}

func (e *redisEngine) addPresence(channel, uid string, info interface{}) error {
	conn := e.pool.Get()
	defer conn.Close()
	infoJson, err := json.Marshal(info)
	if err != nil {
		return err
	}
	expireAt := time.Now().Unix() + e.app.presenceExpireInterval
	hashKey := e.getHashKey(channel)
	setKey := e.getSetKey(channel)
	conn.Send("MULTI")
	conn.Send("ZADD", setKey, expireAt, uid)
	conn.Send("HSET", hashKey, uid, infoJson)
	_, err = conn.Do("EXEC")
	return err
}

func (e *redisEngine) removePresence(channel, uid string) error {
	conn := e.pool.Get()
	defer conn.Close()
	hashKey := e.getHashKey(channel)
	setKey := e.getSetKey(channel)
	conn.Send("MULTI")
	conn.Send("HDEL", hashKey, uid)
	conn.Send("ZREM", setKey, uid)
	_, err := conn.Do("EXEC")
	return err
}

func mapStringInterface(result interface{}, err error) (map[string]interface{}, error) {
	values, err := redis.Values(result, err)
	if err != nil {
		return nil, err
	}
	if len(values)%2 != 0 {
		return nil, errors.New("mapStringInterface expects even number of values result")
	}
	m := make(map[string]interface{}, len(values)/2)
	for i := 0; i < len(values); i += 2 {
		key, okKey := values[i].([]byte)
		value, okValue := values[i+1].([]byte)
		if !okKey || !okValue {
			return nil, errors.New("ScanMap key not a bulk string value")
		}
		var f interface{}
		err = json.Unmarshal(value, &f)
		if err != nil {
			return nil, errors.New("can not unmarshal value to interface")
		}
		m[string(key)] = f
	}
	return m, nil
}

func (e *redisEngine) getPresence(channel string) (map[string]interface{}, error) {
	conn := e.pool.Get()
	defer conn.Close()
	now := time.Now().Unix()
	hashKey := e.getHashKey(channel)
	setKey := e.getSetKey(channel)
	reply, err := conn.Do("ZRANGEBYSCORE", setKey, 0, now)
	if err != nil {
		return nil, err
	}
	expiredKeys, err := redis.Strings(reply, nil)
	if err != nil {
		return nil, err
	}
	if len(expiredKeys) > 0 {
		conn.Send("MULTI")
		conn.Send("ZREMRANGEBYSCORE", setKey, 0, now)
		for _, key := range expiredKeys {
			conn.Send("HDEL", hashKey, key)
		}
		_, err = conn.Do("EXEC")
		if err != nil {
			return nil, err
		}
	}
	reply, err = conn.Do("HGETALL", hashKey)
	if err != nil {
		return nil, err
	}
	presence, err := mapStringInterface(reply, nil)
	return presence, err
}

func (e *redisEngine) addHistoryMessage(channel string, message interface{}, size, lifetime int64) error {
	conn := e.pool.Get()
	defer conn.Close()
	if size <= 0 {
		return nil
	}
	historyKey := e.getHistoryKey(channel)
	messageJson, err := json.Marshal(message)
	if err != nil {
		return err
	}
	conn.Send("MULTI")
	conn.Send("LPUSH", historyKey, messageJson)
	conn.Send("LTRIM", historyKey, 0, size-1)
	if lifetime <= 0 {
		conn.Send("PERSIST", historyKey)
	} else {
		conn.Send("EXPIRE", historyKey, lifetime)
	}
	_, err = conn.Do("EXEC")
	return err
}

func (e *redisEngine) getHistory(channel string) ([]interface{}, error) {
	conn := e.pool.Get()
	defer conn.Close()
	historyKey := e.getHistoryKey(channel)
	values, err := redis.Values(conn.Do("LRANGE", historyKey, 0, -1))
	return values, err
}
<commit_msg>redis url fix<commit_after>package main

import (
	"encoding/json"
	"errors"
	"net"
	"net/url"
	"time"

	"github.com/centrifugal/centrifugo/logger"

	"github.com/garyburd/redigo/redis"
	"github.com/mitchellh/mapstructure"
)

// redisEngine uses Redis datastructures and PUB/SUB to manage Centrifuge logic.
// This engine allows to scale Centrifuge - you can run several Centrifuge instances
// connected to the same Redis and load balance clients between instances.
type redisEngine struct {
	app      *application
	pool     *redis.Pool
	psc      redis.PubSubConn
	api      bool
	inPubSub bool
	inApi    bool
}

func newRedisEngine(app *application, host, port, password, db, redisUrl string, api bool) *redisEngine {
	if redisUrl != "" {
		u, err := url.Parse(redisUrl)
		if err != nil {
			panic(err)
		}
		if u.User != nil {
			var ok bool
			password, ok = u.User.Password()
			if !ok {
				password = ""
			}
		}
		host, port, err = net.SplitHostPort(u.Host)
		if err != nil {
			panic(err)
		}
		path := u.Path
		if path != "" {
			db = path[1:]
		}
	}
	if db == "" {
		db = "0"
	}
	server := host + ":" + port
	pool := newPool(server, password, db)
	return &redisEngine{
		app:  app,
		pool: pool,
		api:  api,
	}
}

func newPool(server, password, db string) *redis.Pool {
	return &redis.Pool{
		MaxIdle:     3,
		IdleTimeout: 240 * time.Second,
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial("tcp", server)
			if err != nil {
				logger.CRITICAL.Println(err)
				return nil, err
			}
			if password != "" {
				if _, err := c.Do("AUTH", password); err != nil {
					c.Close()
					logger.CRITICAL.Println(err)
					return nil, err
				}
			}
			if _, err := c.Do("SELECT", db); err != nil {
				c.Close()
				logger.CRITICAL.Println(err)
				return nil, err
			}
			return c, err
		},
		TestOnBorrow: func(c redis.Conn, t time.Time) error {
			_, err := c.Do("PING")
			return err
		},
	}
}

func (e *redisEngine) getName() string {
	return "Redis"
}

func (e *redisEngine) initialize() error {
	go e.initializePubSub()
	if e.api {
		go e.initializeApi()
	}
	go e.checkConnectionStatus()
	return nil
}

func (e *redisEngine) checkConnectionStatus() {
	for {
		time.Sleep(time.Second)
		if !e.inPubSub {
			go e.initializePubSub()
		}
		if e.api && !e.inApi {
			go e.initializeApi()
		}
	}
}

type redisApiRequest struct {
	Project string
	Data    []map[string]interface{}
}

func (e *redisEngine) initializeApi() {
	e.inApi = true
	conn := e.pool.Get()
	defer conn.Close()
	defer func() {
		e.inApi = false
	}()
	apiKey := e.app.channelPrefix + "." + "api"
	for {
		reply, err := conn.Do("BLPOP", apiKey, 0)
		if err != nil {
			logger.ERROR.Println(err)
			return
		}
		a, err := mapStringInterface(reply, nil)
		if err != nil {
			logger.ERROR.Println(err)
			continue
		}
		body, ok := a[apiKey]
		if !ok {
			continue
		}
		var request redisApiRequest
		err = mapstructure.Decode(body, &request)
		if err != nil {
			logger.ERROR.Println(err)
			continue
		}
		project, exists := e.app.getProjectByKey(request.Project)
		if !exists {
			logger.ERROR.Println("no project found with key", request.Project)
			continue
		}

		var commands []apiCommand
		err = mapstructure.Decode(request.Data, &commands)
		if err != nil {
			logger.ERROR.Println(err)
			continue
		}
		for _, command := range commands {
			_, err := e.app.handleApiCommand(project, command)
			if err != nil {
				logger.ERROR.Println(err)
			}
		}
	}
}

func (e *redisEngine) initializePubSub() {
	e.inPubSub = true
	e.psc = redis.PubSubConn{e.pool.Get()}
	defer e.psc.Close()
	defer func() {
		e.inPubSub = false
	}()
	err := e.psc.Subscribe(e.app.adminChannel)
	if err != nil {
		e.psc.Close()
		return
	}
	err = e.psc.Subscribe(e.app.controlChannel)
	if err != nil {
		e.psc.Close()
		return
	}
	for _, channel := range e.app.clientSubscriptionHub.getChannels() {
		err = e.psc.Subscribe(channel)
		if err != nil {
			e.psc.Close()
			return
		}
	}
	for {
		switch n := e.psc.Receive().(type) {
		case redis.Message:
			e.app.handleMessage(n.Channel, n.Data)
		case redis.Subscription:
		case error:
			logger.ERROR.Printf("error: %v\n", n)
			e.psc.Close()
			return
		}
	}
}

func (e *redisEngine) publish(channel string, message []byte) error {
	conn := e.pool.Get()
	defer conn.Close()
	_, err := conn.Do("PUBLISH", channel, message)
	return err
}

func (e *redisEngine) subscribe(channel string) error {
	return e.psc.Subscribe(channel)
}

func (e *redisEngine) unsubscribe(channel string) error {
	return e.psc.Unsubscribe(channel)
}

func (e *redisEngine) getHashKey(channel string) string {
	return e.app.channelPrefix + ".presence.hash." + channel
}

func (e *redisEngine) getSetKey(channel string) string {
	return e.app.channelPrefix + ".presence.set." + channel
}

func (e *redisEngine) getHistoryKey(channel string) string {
	return e.app.channelPrefix + ".history.list." + channel
}

func (e *redisEngine) addPresence(channel, uid string, info interface{}) error {
	conn := e.pool.Get()
	defer conn.Close()
	infoJson, err := json.Marshal(info)
	if err != nil {
		return err
	}
	expireAt := time.Now().Unix() + e.app.presenceExpireInterval
	hashKey := e.getHashKey(channel)
	setKey := e.getSetKey(channel)
	conn.Send("MULTI")
	conn.Send("ZADD", setKey, expireAt, uid)
	conn.Send("HSET", hashKey, uid, infoJson)
	_, err = conn.Do("EXEC")
	return err
}

func (e *redisEngine) removePresence(channel, uid string) error {
	conn := e.pool.Get()
	defer conn.Close()
	hashKey := e.getHashKey(channel)
	setKey := e.getSetKey(channel)
	conn.Send("MULTI")
	conn.Send("HDEL", hashKey, uid)
	conn.Send("ZREM", setKey, uid)
	_, err := conn.Do("EXEC")
	return err
}

func mapStringInterface(result interface{}, err error) (map[string]interface{}, error) {
	values, err := redis.Values(result, err)
	if err != nil {
		return nil, err
	}
	if len(values)%2 != 0 {
		return nil, errors.New("mapStringInterface expects even number of values result")
	}
	m := make(map[string]interface{}, len(values)/2)
	for i := 0; i < len(values); i += 2 {
		key, okKey := values[i].([]byte)
		value, okValue := values[i+1].([]byte)
		if !okKey || !okValue {
			return nil, errors.New("ScanMap key not a bulk string value")
		}
		var f interface{}
		err = json.Unmarshal(value, &f)
		if err != nil {
			return nil, errors.New("can not unmarshal value to interface")
		}
		m[string(key)] = f
	}
	return m, nil
}

func (e *redisEngine) getPresence(channel string) (map[string]interface{}, error) {
	conn := e.pool.Get()
	defer conn.Close()
	now := time.Now().Unix()
	hashKey := e.getHashKey(channel)
	setKey := e.getSetKey(channel)
	reply, err := conn.Do("ZRANGEBYSCORE", setKey, 0, now)
	if err != nil {
		return nil, err
	}
	expiredKeys, err := redis.Strings(reply, nil)
	if err != nil {
		return nil, err
	}
	if len(expiredKeys) > 0 {
		conn.Send("MULTI")
		conn.Send("ZREMRANGEBYSCORE", setKey, 0, now)
		for _, key := range expiredKeys {
			conn.Send("HDEL", hashKey, key)
		}
		_, err = conn.Do("EXEC")
		if err != nil {
			return nil, err
		}
	}
	reply, err = conn.Do("HGETALL", hashKey)
	if err != nil {
		return nil, err
	}
	presence, err := mapStringInterface(reply, nil)
	return presence, err
}

func (e *redisEngine) addHistoryMessage(channel string, message interface{}, size, lifetime int64) error {
	conn := e.pool.Get()
	defer conn.Close()
	if size <= 0 {
		return nil
	}
	historyKey := e.getHistoryKey(channel)
	messageJson, err := json.Marshal(message)
	if err != nil {
		return err
	}
	conn.Send("MULTI")
	conn.Send("LPUSH", historyKey, messageJson)
	conn.Send("LTRIM", historyKey, 0, size-1)
	if lifetime <= 0 {
		conn.Send("PERSIST", historyKey)
	} else {
		conn.Send("EXPIRE", historyKey, lifetime)
	}
	_, err = conn.Do("EXEC")
	return err
}

func (e *redisEngine) getHistory(channel string) ([]interface{}, error) {
	conn := e.pool.Get()
	defer conn.Close()
	historyKey := e.getHistoryKey(channel)
	values, err := redis.Values(conn.Do("LRANGE", historyKey, 0, -1))
	return values, err
}
<|endoftext|>


<commit_before>package epochs

import (
	"testing"
	"time"
)

var MixedTests = []struct {
	f   func(int64) time.Time
	num int64
	exp time.Time
}{
	{
		Chrome,
		12879041490000000,
		time.Date(2009, time.February, 13, 23, 31, 30, 0, time.UTC),
	},
	{
		Chrome,
		12912187816559001,
		time.Date(2010, time.March, 4, 14, 50, 16, 559001000, time.UTC),
	},
	{
		Cocoa,
		256260690,
		time.Date(2009, time.February, 13, 23, 31, 30, 0, time.UTC),
	},
	{
		Cocoa,
		314238233,
		time.Date(2010, time.December, 17, 0, 23, 53, 0, time.UTC),
	},
	{
		Java,
		1234567890000,
		time.Date(2009, time.February, 13, 23, 31, 30, 0, time.UTC),
	},
	{
		Java,
		1283002533751,
		time.Date(2010, time.August, 28, 13, 35, 33, 751000000, time.UTC),
	},
	{
		Mozilla,
		1234567890000000,
		time.Date(2009, time.February, 13, 23, 31, 30, 0, time.UTC),
	},
	{
		Symbian,
		63401787090000000,
		time.Date(2009, time.February, 13, 23, 31, 30, 0, time.UTC),
	},
	{
		Unix,
		1234567890,
		time.Date(2009, time.February, 13, 23, 31, 30, 0, time.UTC),
	},
	{
		Unix,
		-1234567890,
		time.Date(1930, time.November, 18, 0, 28, 30, 0, time.UTC),
	},
	{
		UUIDv1,
		134538606900000000,
		time.Date(2009, time.February, 13, 23, 31, 30, 0, time.UTC),
	},
	{
		UUIDv1,
		0x1dc7711a73088f5,
		time.Date(2007, time.October, 10, 9, 17, 41, 739749300, time.UTC),
	},
	{
		WindowsDate,
		633701646900000000,
		time.Date(2009, time.February, 13, 23, 31, 30, 0, time.UTC),
	},
	{
		WindowsDate,
		634496538123456789,
		time.Date(2011, time.August, 22, 23, 50, 12, 345678900, time.UTC),
	},
	{
		WindowsFile,
		128790414900000000,
		time.Date(2009, time.February, 13, 23, 31, 30, 0, time.UTC),
	},
	{
		WindowsFile,
		0x1cabbaa00ca9000,
		time.Date(2010, time.March, 4, 14, 50, 16, 559001600, time.UTC),
	},
}

func TestMixed(t *testing.T) {
	for _, tt := range MixedTests {

		obs := tt.f(tt.num)
		if obs != tt.exp {
			t.Errorf("%q(%q) => %q, want %q", tt.f, tt.num, obs, tt.exp)
		}
	}
}

var ICQTests = []struct {
	f   func(float64) time.Time
	num float64
	exp time.Time
}{
	{
		ICQ,
		0,
		time.Date(1899, time.December, 30, 0, 0, 0, 0, time.UTC),
	},
	{
		ICQ,
		41000,
		time.Date(2012, time.April, 1, 0, 0, 0, 0, time.UTC),
	},
	{
		ICQ,
		41056.2752083333,
		time.Date(2012, time.May, 27, 6, 36, 17, 999997418, time.UTC),
	},
	{
		ICQ,
		41056.2967361111,
		time.Date(2012, time.May, 27, 7, 7, 17, 999999080, time.UTC),
	},
}

func TestICQ(t *testing.T) {
	for _, tt := range ICQTests {

		obs := tt.f(tt.num)
		if obs != tt.exp {
			t.Errorf("%q(%q) => %q, want %q", tt.f, tt.num, obs, tt.exp)
		}
	}
}

var OLETests = []struct {
	f   func(string) time.Time
	num string
	exp time.Time
}{
	{
		OLE,
		"dedddd5d3f76e340",
		time.Date(2009, time.February, 13, 23, 31, 30, 83, time.UTC),
	},
	{
		OLE,
		"8ad371b4bcd2e340",
		time.Date(2011, time.February, 23, 21, 31, 43, 127000061, time.UTC),
	},
}

func TestOLE(t *testing.T) {
	for _, tt := range OLETests {

		obs := tt.f(tt.num)
		if obs != tt.exp {
			t.Errorf("%q(%q) => %q, want %q", tt.f, tt.num, obs, tt.exp)
		}
	}
}
<commit_msg>add tests for GoogleCalendar<commit_after>package epochs

import (
	"testing"
	"time"
)

var MixedTests = []struct {
	f   func(int64) time.Time
	num int64
	exp time.Time
}{
	{
		Chrome,
		12879041490000000,
		time.Date(2009, time.February, 13, 23, 31, 30, 0, time.UTC),
	},
	{
		Chrome,
		12912187816559001,
		time.Date(2010, time.March, 4, 14, 50, 16, 559001000, time.UTC),
	},
	{
		Cocoa,
		256260690,
		time.Date(2009, time.February, 13, 23, 31, 30, 0, time.UTC),
	},
	{
		Cocoa,
		314238233,
		time.Date(2010, time.December, 17, 0, 23, 53, 0, time.UTC),
	},
	{
		GoogleCalendar,
		1297899090,
		time.Date(2009, time.February, 13, 23, 31, 30, 0, time.UTC),
	},
	{
		GoogleCalendar,
		1234567890,
		time.Date(2007, time.March, 16, 23, 31, 30, 0, time.UTC),
	},
	{
		Java,
		1234567890000,
		time.Date(2009, time.February, 13, 23, 31, 30, 0, time.UTC),
	},
	{
		Java,
		1283002533751,
		time.Date(2010, time.August, 28, 13, 35, 33, 751000000, time.UTC),
	},
	{
		Mozilla,
		1234567890000000,
		time.Date(2009, time.February, 13, 23, 31, 30, 0, time.UTC),
	},
	{
		Symbian,
		63401787090000000,
		time.Date(2009, time.February, 13, 23, 31, 30, 0, time.UTC),
	},
	{
		Unix,
		1234567890,
		time.Date(2009, time.February, 13, 23, 31, 30, 0, time.UTC),
	},
	{
		Unix,
		-1234567890,
		time.Date(1930, time.November, 18, 0, 28, 30, 0, time.UTC),
	},
	{
		UUIDv1,
		134538606900000000,
		time.Date(2009, time.February, 13, 23, 31, 30, 0, time.UTC),
	},
	{
		UUIDv1,
		0x1dc7711a73088f5,
		time.Date(2007, time.October, 10, 9, 17, 41, 739749300, time.UTC),
	},
	{
		WindowsDate,
		633701646900000000,
		time.Date(2009, time.February, 13, 23, 31, 30, 0, time.UTC),
	},
	{
		WindowsDate,
		634496538123456789,
		time.Date(2011, time.August, 22, 23, 50, 12, 345678900, time.UTC),
	},
	{
		WindowsFile,
		128790414900000000,
		time.Date(2009, time.February, 13, 23, 31, 30, 0, time.UTC),
	},
	{
		WindowsFile,
		0x1cabbaa00ca9000,
		time.Date(2010, time.March, 4, 14, 50, 16, 559001600, time.UTC),
	},
}

func TestMixed(t *testing.T) {
	for _, tt := range MixedTests {

		obs := tt.f(tt.num)
		if obs != tt.exp {
			t.Errorf("%q(%q) => %q, want %q", tt.f, tt.num, obs, tt.exp)
		}
	}
}

var ICQTests = []struct {
	f   func(float64) time.Time
	num float64
	exp time.Time
}{
	{
		ICQ,
		0,
		time.Date(1899, time.December, 30, 0, 0, 0, 0, time.UTC),
	},
	{
		ICQ,
		41000,
		time.Date(2012, time.April, 1, 0, 0, 0, 0, time.UTC),
	},
	{
		ICQ,
		41056.2752083333,
		time.Date(2012, time.May, 27, 6, 36, 17, 999997418, time.UTC),
	},
	{
		ICQ,
		41056.2967361111,
		time.Date(2012, time.May, 27, 7, 7, 17, 999999080, time.UTC),
	},
}

func TestICQ(t *testing.T) {
	for _, tt := range ICQTests {

		obs := tt.f(tt.num)
		if obs != tt.exp {
			t.Errorf("%q(%q) => %q, want %q", tt.f, tt.num, obs, tt.exp)
		}
	}
}

var OLETests = []struct {
	f   func(string) time.Time
	num string
	exp time.Time
}{
	{
		OLE,
		"dedddd5d3f76e340",
		time.Date(2009, time.February, 13, 23, 31, 30, 83, time.UTC),
	},
	{
		OLE,
		"8ad371b4bcd2e340",
		time.Date(2011, time.February, 23, 21, 31, 43, 127000061, time.UTC),
	},
}

func TestOLE(t *testing.T) {
	for _, tt := range OLETests {

		obs := tt.f(tt.num)
		if obs != tt.exp {
			t.Errorf("%q(%q) => %q, want %q", tt.f, tt.num, obs, tt.exp)
		}
	}
}
<|endoftext|>


<commit_before>/*

errors is a package that implements FriendlyError. FriendlyError implements
the error interface, but also has a FriendlyError() method that returns a
message that is reasonable to show to end-users.

Every method that returns a FriendlyError also accepts 0 to n Fields objects
may be provided and they will be combined into a single Fields, with later
values overwriting newer ones.

FriendlyErrors also have With* methods that return a copy of the error with
the given changes. This allows a pattern where a method defines a default
FriendlyError with the friendly error message to use and then when it needs to
return an error uses WithError() to add the specific error message.

*/
package errors

const DefaultFriendlyError = "An error occurred"

type Fields map[string]interface{}

type Friendly struct {
	msg         string
	friendlyMsg string
	secureMsg   string
	fields      Fields
}

//New creates a new errors.Friendly with the given msg.
func New(msg string, fields ...Fields) *Friendly {
	return &Friendly{
		msg:    msg,
		fields: combineFields(fields...),
	}
}

//NewFriendly returns a new errors.Friendly with the given FriendlyError.
func NewFriendly(friendlyMsg string, fields ...Fields) *Friendly {
	return &Friendly{
		friendlyMsg: friendlyMsg,
		fields:      combineFields(fields...),
	}
}

//NewSecure returns a new errors.Friendly with the given SecureError.
func NewSecure(secureMsg string, fields ...Fields) *Friendly {
	return &Friendly{
		secureMsg: secureMsg,
		fields:    combineFields(fields...),
	}
}

//NewWrapped takes a generic error. It returns either a new error with that
//message or, if nil, returns nil. Returns a generic error so if it returns
//nil it will no be a nil interface value to a *Friendly.
func NewWrapped(err error, fields ...Fields) error {
	if err == nil {
		return nil
	}
	return New(err.Error(), fields...)
}

func combineFields(fields ...Fields) Fields {
	var result = make(Fields)
	for _, field := range fields {
		for key, val := range field {
			result[key] = val
		}
	}
	return result
}

//SecureError returns the error message that should only be shown in secure
//contexts, because it may include secret information. If no SecureError
//message has been provided, will return Error()
func (f *Friendly) SecureError() string {
	if f.secureMsg == "" {
		return f.Error()
	}
	return f.secureMsg
}

//Error returns the error message, implementing the error interface. If no
//specific message has been provided, will fall back on FriendlyError(). The
//Error() value is OK to show in insecure contexts (i.e. on the client) but it
//just might be confusing to users.
func (f *Friendly) Error() string {
	if f.msg == "" {
		return f.FriendlyError()
	}
	return f.msg
}

//FriendlyError is the error string that is OK to show in insecure contexts to
//end-users. It is generally a much simplified version of the message. If no
//specific FriendlyMessage has been provided, will return DefaultFriendlyError.
func (f *Friendly) FriendlyError() string {
	if f.friendlyMsg == "" {
		return DefaultFriendlyError
	}
	return f.friendlyMsg
}

//Fields returns the Fields object for this error. Fields should only be used
//in secure contexts (e.g. logging on a server) because they may contain
//private information.
func (f *Friendly) Fields() Fields {
	return f.fields
}

//Extend returns a new FriendlyError where the Error() message is prepended
//with this new message and a delimiter. If err is an *errors.Friendly then
//the secure message, friendly message, and fields will all be included
//unchanged.
func Extend(err error, msg string, fields ...Fields) *Friendly {

	var base *Friendly

	if f, ok := err.(*Friendly); ok {
		base = f
	}

	if base == nil {
		base = New(err.Error())
	}

	return &Friendly{
		secureMsg:   base.secureMsg,
		friendlyMsg: base.friendlyMsg,
		msg:         msg + " : " + base.Error(),
		fields:      combineFields(append([]Fields{base.fields}, fields...)...),
	}
}

//WithFriendly returns a copy of err where the friendlyMsg is set to friendlyMsg
func (f *Friendly) WithFriendly(friendlyMsg string, fields ...Fields) *Friendly {
	return &Friendly{
		secureMsg:   f.secureMsg,
		msg:         f.msg,
		friendlyMsg: friendlyMsg,
		fields:      combineFields(append([]Fields{f.fields}, fields...)...),
	}
}

//WithError returns a copy of err where the Error() is set to msg. See a;so
//Extend, which prepends a new message to the front of the existing message.
func (f *Friendly) WithError(msg string, fields ...Fields) *Friendly {
	return &Friendly{
		secureMsg:   f.secureMsg,
		msg:         msg,
		friendlyMsg: f.friendlyMsg,
		fields:      combineFields(append([]Fields{f.fields}, fields...)...),
	}
}

//WithSecure returns a copy of err where the SecureError() is set to secureMsg.
func (f *Friendly) WithSecure(secureMsg string, fields ...Fields) *Friendly {
	return &Friendly{
		secureMsg:   secureMsg,
		msg:         f.msg,
		friendlyMsg: f.friendlyMsg,
		fields:      combineFields(append([]Fields{f.fields}, fields...)...),
	}
}
<commit_msg>Fixed lint warnings for errors pkg. Part of #552.<commit_after>/*

Package errors is a package that implements FriendlyError. FriendlyError
implements the error interface, but also has a FriendlyError() method that
returns a message that is reasonable to show to end-users.

Every method that returns a FriendlyError also accepts 0 to n Fields objects may
be provided and they will be combined into a single Fields, with later values
overwriting newer ones.

FriendlyErrors also have With* methods that return a copy of the error with the
given changes. This allows a pattern where a method defines a default
FriendlyError with the friendly error message to use and then when it needs to
return an error uses WithError() to add the specific error message.

*/
package errors

//DefaultFriendlyError is the message that will be shown by default unless a
//more specific friendly value is returned.
const DefaultFriendlyError = "An error occurred"

//Fields is the place we store extra field/value information on an error.
type Fields map[string]interface{}

//Friendly is the core type of the error, representing an error that knows how
//to render a default string and a "friendly" string, appropriate for showing to
//end users.
type Friendly struct {
	msg         string
	friendlyMsg string
	secureMsg   string
	fields      Fields
}

//New creates a new errors.Friendly with the given msg.
func New(msg string, fields ...Fields) *Friendly {
	return &Friendly{
		msg:    msg,
		fields: combineFields(fields...),
	}
}

//NewFriendly returns a new errors.Friendly with the given FriendlyError.
func NewFriendly(friendlyMsg string, fields ...Fields) *Friendly {
	return &Friendly{
		friendlyMsg: friendlyMsg,
		fields:      combineFields(fields...),
	}
}

//NewSecure returns a new errors.Friendly with the given SecureError.
func NewSecure(secureMsg string, fields ...Fields) *Friendly {
	return &Friendly{
		secureMsg: secureMsg,
		fields:    combineFields(fields...),
	}
}

//NewWrapped takes a generic error. It returns either a new error with that
//message or, if nil, returns nil. Returns a generic error so if it returns
//nil it will no be a nil interface value to a *Friendly.
func NewWrapped(err error, fields ...Fields) error {
	if err == nil {
		return nil
	}
	return New(err.Error(), fields...)
}

func combineFields(fields ...Fields) Fields {
	var result = make(Fields)
	for _, field := range fields {
		for key, val := range field {
			result[key] = val
		}
	}
	return result
}

//SecureError returns the error message that should only be shown in secure
//contexts, because it may include secret information. If no SecureError
//message has been provided, will return Error()
func (f *Friendly) SecureError() string {
	if f.secureMsg == "" {
		return f.Error()
	}
	return f.secureMsg
}

//Error returns the error message, implementing the error interface. If no
//specific message has been provided, will fall back on FriendlyError(). The
//Error() value is OK to show in insecure contexts (i.e. on the client) but it
//just might be confusing to users.
func (f *Friendly) Error() string {
	if f.msg == "" {
		return f.FriendlyError()
	}
	return f.msg
}

//FriendlyError is the error string that is OK to show in insecure contexts to
//end-users. It is generally a much simplified version of the message. If no
//specific FriendlyMessage has been provided, will return DefaultFriendlyError.
func (f *Friendly) FriendlyError() string {
	if f.friendlyMsg == "" {
		return DefaultFriendlyError
	}
	return f.friendlyMsg
}

//Fields returns the Fields object for this error. Fields should only be used
//in secure contexts (e.g. logging on a server) because they may contain
//private information.
func (f *Friendly) Fields() Fields {
	return f.fields
}

//Extend returns a new FriendlyError where the Error() message is prepended
//with this new message and a delimiter. If err is an *errors.Friendly then
//the secure message, friendly message, and fields will all be included
//unchanged.
func Extend(err error, msg string, fields ...Fields) *Friendly {

	var base *Friendly

	if f, ok := err.(*Friendly); ok {
		base = f
	}

	if base == nil {
		base = New(err.Error())
	}

	return &Friendly{
		secureMsg:   base.secureMsg,
		friendlyMsg: base.friendlyMsg,
		msg:         msg + " : " + base.Error(),
		fields:      combineFields(append([]Fields{base.fields}, fields...)...),
	}
}

//WithFriendly returns a copy of err where the friendlyMsg is set to friendlyMsg
func (f *Friendly) WithFriendly(friendlyMsg string, fields ...Fields) *Friendly {
	return &Friendly{
		secureMsg:   f.secureMsg,
		msg:         f.msg,
		friendlyMsg: friendlyMsg,
		fields:      combineFields(append([]Fields{f.fields}, fields...)...),
	}
}

//WithError returns a copy of err where the Error() is set to msg. See a;so
//Extend, which prepends a new message to the front of the existing message.
func (f *Friendly) WithError(msg string, fields ...Fields) *Friendly {
	return &Friendly{
		secureMsg:   f.secureMsg,
		msg:         msg,
		friendlyMsg: f.friendlyMsg,
		fields:      combineFields(append([]Fields{f.fields}, fields...)...),
	}
}

//WithSecure returns a copy of err where the SecureError() is set to secureMsg.
func (f *Friendly) WithSecure(secureMsg string, fields ...Fields) *Friendly {
	return &Friendly{
		secureMsg:   secureMsg,
		msg:         f.msg,
		friendlyMsg: f.friendlyMsg,
		fields:      combineFields(append([]Fields{f.fields}, fields...)...),
	}
}
<|endoftext|>


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

import (
	"appengine"
	"appengine/datastore"
	"encoding/json"
	"net/http"
	"time"

	"github.com/mjibson/appstats"
)

type listing struct {
	Name       string `json:"name"`       // Resource name
	Location   string `json:"location"`   // URL
	Expiration int64  `json:"expiration"` // UNIX time in seconds
}

func init() {
	http.Handle("/", appstats.NewHandler(register))
	http.Handle("/clean", appstats.NewHandler(clean))
}

func register(c appengine.Context, w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	switch r.Method {
	case "GET":
		getDirectory(c, w, r)
		return
	case "PUT":
		putListing(c, w, r)
	default:
		c.Errorf("Method %v not expected.", r.Method)
		w.WriteHeader(http.StatusBadRequest)
		w.Write(nil)
	}
}

func getDirectory(c appengine.Context, w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	q := datastore.NewQuery("listing")
	var listings []listing
	_, err := q.GetAll(c, &listings)
	if err != nil {
		c.Errorf("getDirectory GetAll query failed %v", err)
	}
	b, err := json.Marshal(listings)
	if err != nil {
		c.Errorf("getDirectory Marshal failed %v", err)
	}
	_, err = w.Write(b)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		w.Write([]byte(err.Error()))
		c.Errorf("getDirectory %v", err)
	}
}

func putListing(c appengine.Context, w http.ResponseWriter, r *http.Request) {
	newListing := listing{}
	requestData := make([]byte, 100)
	n, err := r.Body.Read(requestData)
	if err != nil {
		c.Errorf("addListing read body %v", err)
	}
	err = json.Unmarshal(requestData[:n], &newListing)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		c.Errorf("addListing Unmarshal %v", err)
		return
	}

	now := time.Now()
	newListing.Expiration = now.Add(time.Minute).Unix()

	key, err := datastore.Put(c, datastore.NewIncompleteKey(c, "listing", nil), &newListing)
	if err != nil {
		c.Errorf("addListing datastore.Put %v", err)
	}
	c.Infof("addListing key %v", key)

	b, err := json.Marshal(newListing)
	if err != nil {
		c.Errorf("addListing Marshal %v", err)
	}
	_, err = w.Write(b)
	if err != nil {
		c.Errorf("addListing Write %v", err)
	}
}

func clean(c appengine.Context, w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	switch r.Method {
	case "DELETE":
		deleteOldListings(c, w, r)
		return
	default:
		c.Errorf("Method %v not expected.", r.Method)
		w.WriteHeader(http.StatusBadRequest)
		w.Write(nil)
	}
}

func deleteOldListings(c appengine.Context, w http.ResponseWriter, r *http.Request) {
	q := datastore.NewQuery("listing")
	var listings []listing
	keys, err := q.GetAll(c, &listings)
	if err != nil {
		c.Errorf("getDirectory GetAll query failed %v", err)
	}

	for index, element := range listings {
		if time.Now().Unix() > element.Expiration {
			key := keys[index]
			datastore.Delete(c, key)
		}
	}

	b, err := json.Marshal(listings)
	if err != nil {
		c.Errorf("getDirectory Marshal failed %v", err)
	}
	_, err = w.Write(b)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		w.Write([]byte(err.Error()))
		c.Errorf("getDirectory %v", err)
	}
}
<commit_msg>Refactor code to get all listings into a function.<commit_after>/*
 * Copyright 2015 Chris Cartland
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package server

import (
	"appengine"
	"appengine/datastore"
	"encoding/json"
	"net/http"
	"time"

	"github.com/mjibson/appstats"
)

type listing struct {
	Name       string `json:"name"`       // Resource name
	Location   string `json:"location"`   // URL
	Expiration int64  `json:"expiration"` // UNIX time in seconds
}

func init() {
	http.Handle("/", appstats.NewHandler(register))
	http.Handle("/clean", appstats.NewHandler(clean))
}

func register(c appengine.Context, w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	switch r.Method {
	case "GET":
		getDirectory(c, w, r)
		return
	case "PUT":
		putListing(c, w, r)
	default:
		c.Errorf("Method %v not expected.", r.Method)
		w.WriteHeader(http.StatusBadRequest)
		w.Write(nil)
	}
}

func getDirectory(c appengine.Context, w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	listings, err := getAllListings(c)
	if err != nil {
		c.Errorf("listings GetAll query failed %v", err)
	}
	b, err := json.Marshal(listings)
	if err != nil {
		c.Errorf("getDirectory Marshal failed %v", err)
	}
	_, err = w.Write(b)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		w.Write([]byte(err.Error()))
		c.Errorf("getDirectory %v", err)
	}
}

func getAllListings(c appengine.Context) ([]listing, error) {
	q := datastore.NewQuery("listing")
	var listings []listing
	_, err := q.GetAll(c, &listings)
	return listings, err
}

func putListing(c appengine.Context, w http.ResponseWriter, r *http.Request) {
	newListing := listing{}
	requestData := make([]byte, 100)
	n, err := r.Body.Read(requestData)
	if err != nil {
		c.Errorf("addListing read body %v", err)
	}
	err = json.Unmarshal(requestData[:n], &newListing)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		c.Errorf("addListing Unmarshal %v", err)
		return
	}

	now := time.Now()
	newListing.Expiration = now.Add(time.Minute).Unix()

	key, err := datastore.Put(c, datastore.NewIncompleteKey(c, "listing", nil), &newListing)
	if err != nil {
		c.Errorf("addListing datastore.Put %v", err)
	}
	c.Infof("addListing key %v", key)

	b, err := json.Marshal(newListing)
	if err != nil {
		c.Errorf("addListing Marshal %v", err)
	}
	_, err = w.Write(b)
	if err != nil {
		c.Errorf("addListing Write %v", err)
	}
}

func clean(c appengine.Context, w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	switch r.Method {
	case "DELETE":
		deleteOldListings(c, w, r)
		return
	default:
		c.Errorf("Method %v not expected.", r.Method)
		w.WriteHeader(http.StatusBadRequest)
		w.Write(nil)
	}
}

func deleteOldListings(c appengine.Context, w http.ResponseWriter, r *http.Request) {
	q := datastore.NewQuery("listing")
	var listings []listing
	keys, err := q.GetAll(c, &listings)
	if err != nil {
		c.Errorf("getDirectory GetAll query failed %v", err)
	}

	for index, element := range listings {
		if time.Now().Unix() > element.Expiration {
			key := keys[index]
			datastore.Delete(c, key)
		}
	}

	b, err := json.Marshal(listings)
	if err != nil {
		c.Errorf("getDirectory Marshal failed %v", err)
	}
	_, err = w.Write(b)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		w.Write([]byte(err.Error()))
		c.Errorf("getDirectory %v", err)
	}
}
<|endoftext|>


<commit_before>/** Author: Charney Kaye */

package main

// typedef unsigned char Uint16;
// void AudioCallback(void *userdata, Uint16 *stream, int len);
import "C"
import (
	log "github.com/Sirupsen/logrus"
	"github.com/outrightmental/go-atomix"
	"github.com/veandco/go-sdl2/sdl"
	"os"
	"time"
)

const (
	sampleHz   = 44100
	numSamples = 4096
)

func main() {
	if err := sdl.Init(sdl.INIT_AUDIO); err != nil {
		log.WithFields(log.Fields{
			"error": err,
		}).Fatal("Cannot init SDL")
		return
	}
	defer func() {
		if r := recover(); r != nil {
			log.WithFields(log.Fields{
				"recover": r,
			}).Warn("Player Recovered")
		}
		sdl.PauseAudio(true)
		atomix.Teardown()
		sdl.Quit()
	}()

	var (
		bpm   = 120
		step  = time.Minute / time.Duration(bpm*4)
		loops = 16
	)

	var (
		prefix  = "assets/sounds/percussion/808/"
		kick1   = "kick1.wav"
		kick2   = "kick2.wav"
		marac   = "maracas.wav"
		snare   = "snare.wav"
		hitom   = "hightom.wav"
		clhat   = "cl_hihat.wav"
		pattern = []string{
			kick2,
			marac,
			clhat,
			marac,
			snare,
			marac,
			clhat,
			kick2,
			marac,
			marac,
			hitom,
			marac,
			snare,
			kick1,
			clhat,
			marac,
		}
	)

	atomix.Debug(true)
	atomix.Configure(sdl.AudioSpec{
		Freq:     sampleHz,
		Format:   sdl.AUDIO_F32,
		Channels: 1,
		Samples:  numSamples,
	})
	atomix.SetSoundsPath(prefix)
	atomix.StartAt(time.Now().Add(1 * time.Second))

	t := 1 * time.Second // padding before music
	for n := 0; n < loops; n++ {
		for s := 0; s < len(pattern); s++ {
			atomix.SetFire(pattern[s], t+time.Duration(s)*step, 0, 1.0, 0)
		}
		t += time.Duration(len(pattern)) * step
	}

	spec := atomix.Spec()
	sdl.OpenAudio(spec, nil)
	sdl.PauseAudio(false)
	log.WithFields(log.Fields{
		"pid":  os.Getpid(),
		"spec": spec,
	}).Info("SDL OpenAudio > Atomix")

	time.Sleep(t + 1*time.Second) // padding after music
}
<commit_msg>simplify example<commit_after>/** Author: Charney Kaye */

package main

// typedef unsigned char Uint16;
// void AudioCallback(void *userdata, Uint16 *stream, int len);
import "C"
import (
	"fmt"
	"github.com/outrightmental/go-atomix"
	"github.com/veandco/go-sdl2/sdl"
	"os"
	"time"
)

var (
	sampleHz   = int32(44100)
	numSamples = uint16(4096)
	bpm        = 120
	step       = time.Minute / time.Duration(bpm*4)
	loops      = 16
	prefix     = "assets/sounds/percussion/808/"
	kick1      = "kick1.wav"
	kick2      = "kick2.wav"
	marac      = "maracas.wav"
	snare      = "snare.wav"
	hitom      = "hightom.wav"
	clhat      = "cl_hihat.wav"
	pattern    = []string{
		kick2,
		marac,
		clhat,
		marac,
		snare,
		marac,
		clhat,
		kick2,
		marac,
		marac,
		hitom,
		marac,
		snare,
		kick1,
		clhat,
		marac,
	}
)

func main() {
	if err := sdl.Init(sdl.INIT_AUDIO); err != nil {
		fmt.Printf("Cannot init SDL. Error: %v\n", err)
		return
	}
	defer func() {
		if r := recover(); r != nil {
			fmt.Printf("Player Recovered: %v\n", r)
		}
		sdl.PauseAudio(true)
		atomix.Teardown()
		sdl.Quit()
	}()

	atomix.Debug(true)
	atomix.Configure(sdl.AudioSpec{
		Freq:     sampleHz,
		Format:   sdl.AUDIO_F32,
		Channels: 1,
		Samples:  numSamples,
	})
	atomix.SetSoundsPath(prefix)
	atomix.StartAt(time.Now().Add(1 * time.Second))

	t := 1 * time.Second // padding before music
	for n := 0; n < loops; n++ {
		for s := 0; s < len(pattern); s++ {
			atomix.SetFire(pattern[s], t+time.Duration(s)*step, 0, 1.0, 0)
		}
		t += time.Duration(len(pattern)) * step
	}

	spec := atomix.Spec()
	sdl.OpenAudio(spec, nil)
	sdl.PauseAudio(false)

	fmt.Printf("SDL OpenAudio > Atomix, pid:%v, spec:%v\n", os.Getpid(), spec)
	time.Sleep(t + 1*time.Second) // padding after music
}
<|endoftext|>


<commit_before>// Copyright 2017 The go-interpreter 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 exec

import (
	"errors"
	"math"
)

// ErrOutOfBoundsMemoryAccess is the error value used while trapping the VM
// when it detects an out of bounds access to the linear memory.
var ErrOutOfBoundsMemoryAccess = errors.New("exec: out of bounds memory access")

func (vm *VM) fetchBaseAddr() int {
	return int(vm.fetchUint32() + uint32(vm.popInt32()))
}

// inBounds returns true when the next vm.fetchBaseAddr() + offset
// indices are in bounds accesses to the linear memory.
func (vm *VM) inBounds(offset int) bool {
	addr := endianess.Uint32(vm.ctx.code[vm.ctx.pc:]) + uint32(vm.ctx.stack[len(vm.ctx.stack)-1])
	return int(addr)+offset < len(vm.memory)
}

// curMem returns a slice to the memeory segment pointed to by
// the current base address on the bytecode stream.
func (vm *VM) curMem() []byte {
	return vm.memory[vm.fetchBaseAddr():]
}

func (vm *VM) i32Load() {
	if !vm.inBounds(3) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.pushUint32(endianess.Uint32(vm.curMem()))
}

func (vm *VM) i32Load8s() {
	if !vm.inBounds(0) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.pushInt32(int32(int8(vm.memory[vm.fetchBaseAddr()])))
}

func (vm *VM) i32Load8u() {
	if !vm.inBounds(0) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.pushUint32(uint32(uint8(vm.memory[vm.fetchBaseAddr()])))
}

func (vm *VM) i32Load16s() {
	if !vm.inBounds(1) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.pushInt32(int32(int16(endianess.Uint16(vm.curMem()))))
}

func (vm *VM) i32Load16u() {
	if !vm.inBounds(1) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.pushUint32(uint32(endianess.Uint16(vm.curMem())))
}

func (vm *VM) i64Load() {
	if !vm.inBounds(7) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.pushUint64(endianess.Uint64(vm.curMem()))
}

func (vm *VM) i64Load8s() {
	if !vm.inBounds(0) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.pushInt64(int64(int8(vm.memory[vm.fetchBaseAddr()])))
}

func (vm *VM) i64Load8u() {
	if !vm.inBounds(0) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.pushUint64(uint64(uint8(vm.memory[vm.fetchBaseAddr()])))
}

func (vm *VM) i64Load16s() {
	if !vm.inBounds(1) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.pushInt64(int64(int16(endianess.Uint16(vm.curMem()))))
}

func (vm *VM) i64Load16u() {
	if !vm.inBounds(1) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.pushUint64(uint64(endianess.Uint16(vm.curMem())))
}

func (vm *VM) i64Load32s() {
	if !vm.inBounds(3) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.pushInt64(int64(int32(endianess.Uint32(vm.curMem()))))
}

func (vm *VM) i64Load32u() {
	if !vm.inBounds(3) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.pushUint64(uint64(endianess.Uint32(vm.curMem())))
}

func (vm *VM) f32Store() {
	v := math.Float32bits(vm.popFloat32())
	if !vm.inBounds(3) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	endianess.PutUint32(vm.curMem(), v)
}

func (vm *VM) f32Load() {
	if !vm.inBounds(3) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.pushFloat32(math.Float32frombits(endianess.Uint32(vm.curMem())))
}

func (vm *VM) f64Store() {
	v := math.Float64bits(vm.popFloat64())
	if !vm.inBounds(7) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	endianess.PutUint64(vm.curMem(), v)
}

func (vm *VM) f64Load() {
	if !vm.inBounds(7) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.pushFloat64(math.Float64frombits(endianess.Uint64(vm.curMem())))
}

func (vm *VM) i32Store() {
	v := vm.popUint32()
	if !vm.inBounds(3) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	endianess.PutUint32(vm.curMem(), v)
}

func (vm *VM) i32Store8() {
	v := byte(uint8(vm.popUint32()))
	if !vm.inBounds(0) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.memory[vm.fetchBaseAddr()] = v
}

func (vm *VM) i32Store16() {
	v := uint16(vm.popUint32())
	if !vm.inBounds(1) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	endianess.PutUint16(vm.curMem(), v)
}

func (vm *VM) i64Store() {
	v := vm.popUint64()
	if !vm.inBounds(7) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	endianess.PutUint64(vm.curMem(), v)
}

func (vm *VM) i64Store8() {
	v := byte(uint8(vm.popUint64()))
	if !vm.inBounds(0) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.memory[vm.fetchBaseAddr()] = v
}

func (vm *VM) i64Store16() {
	v := uint16(vm.popUint64())
	if !vm.inBounds(1) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	endianess.PutUint16(vm.curMem(), v)
}

func (vm *VM) i64Store32() {
	v := uint32(vm.popUint64())
	if !vm.inBounds(3) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	endianess.PutUint32(vm.curMem(), v)
}

func (vm *VM) currentMemory() {
	_ = vm.fetchInt8() // reserved (https://github.com/WebAssembly/design/blob/27ac254c854994103c24834a994be16f74f54186/BinaryEncoding.md#memory-related-operators-described-here)
	vm.pushInt32(int32(len(vm.memory) / wasmPageSize))
}

func (vm *VM) growMemory() {
	curLen := len(vm.memory) / wasmPageSize
	n := vm.popInt32()
	vm.memory = append(vm.memory, make([]byte, n*wasmPageSize)...)
	vm.pushInt32(int32(curLen))
}
<commit_msg>exec: Fetch reserved integer in grow_memory<commit_after>// Copyright 2017 The go-interpreter 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 exec

import (
	"errors"
	"math"
)

// ErrOutOfBoundsMemoryAccess is the error value used while trapping the VM
// when it detects an out of bounds access to the linear memory.
var ErrOutOfBoundsMemoryAccess = errors.New("exec: out of bounds memory access")

func (vm *VM) fetchBaseAddr() int {
	return int(vm.fetchUint32() + uint32(vm.popInt32()))
}

// inBounds returns true when the next vm.fetchBaseAddr() + offset
// indices are in bounds accesses to the linear memory.
func (vm *VM) inBounds(offset int) bool {
	addr := endianess.Uint32(vm.ctx.code[vm.ctx.pc:]) + uint32(vm.ctx.stack[len(vm.ctx.stack)-1])
	return int(addr)+offset < len(vm.memory)
}

// curMem returns a slice to the memeory segment pointed to by
// the current base address on the bytecode stream.
func (vm *VM) curMem() []byte {
	return vm.memory[vm.fetchBaseAddr():]
}

func (vm *VM) i32Load() {
	if !vm.inBounds(3) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.pushUint32(endianess.Uint32(vm.curMem()))
}

func (vm *VM) i32Load8s() {
	if !vm.inBounds(0) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.pushInt32(int32(int8(vm.memory[vm.fetchBaseAddr()])))
}

func (vm *VM) i32Load8u() {
	if !vm.inBounds(0) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.pushUint32(uint32(uint8(vm.memory[vm.fetchBaseAddr()])))
}

func (vm *VM) i32Load16s() {
	if !vm.inBounds(1) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.pushInt32(int32(int16(endianess.Uint16(vm.curMem()))))
}

func (vm *VM) i32Load16u() {
	if !vm.inBounds(1) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.pushUint32(uint32(endianess.Uint16(vm.curMem())))
}

func (vm *VM) i64Load() {
	if !vm.inBounds(7) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.pushUint64(endianess.Uint64(vm.curMem()))
}

func (vm *VM) i64Load8s() {
	if !vm.inBounds(0) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.pushInt64(int64(int8(vm.memory[vm.fetchBaseAddr()])))
}

func (vm *VM) i64Load8u() {
	if !vm.inBounds(0) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.pushUint64(uint64(uint8(vm.memory[vm.fetchBaseAddr()])))
}

func (vm *VM) i64Load16s() {
	if !vm.inBounds(1) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.pushInt64(int64(int16(endianess.Uint16(vm.curMem()))))
}

func (vm *VM) i64Load16u() {
	if !vm.inBounds(1) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.pushUint64(uint64(endianess.Uint16(vm.curMem())))
}

func (vm *VM) i64Load32s() {
	if !vm.inBounds(3) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.pushInt64(int64(int32(endianess.Uint32(vm.curMem()))))
}

func (vm *VM) i64Load32u() {
	if !vm.inBounds(3) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.pushUint64(uint64(endianess.Uint32(vm.curMem())))
}

func (vm *VM) f32Store() {
	v := math.Float32bits(vm.popFloat32())
	if !vm.inBounds(3) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	endianess.PutUint32(vm.curMem(), v)
}

func (vm *VM) f32Load() {
	if !vm.inBounds(3) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.pushFloat32(math.Float32frombits(endianess.Uint32(vm.curMem())))
}

func (vm *VM) f64Store() {
	v := math.Float64bits(vm.popFloat64())
	if !vm.inBounds(7) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	endianess.PutUint64(vm.curMem(), v)
}

func (vm *VM) f64Load() {
	if !vm.inBounds(7) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.pushFloat64(math.Float64frombits(endianess.Uint64(vm.curMem())))
}

func (vm *VM) i32Store() {
	v := vm.popUint32()
	if !vm.inBounds(3) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	endianess.PutUint32(vm.curMem(), v)
}

func (vm *VM) i32Store8() {
	v := byte(uint8(vm.popUint32()))
	if !vm.inBounds(0) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.memory[vm.fetchBaseAddr()] = v
}

func (vm *VM) i32Store16() {
	v := uint16(vm.popUint32())
	if !vm.inBounds(1) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	endianess.PutUint16(vm.curMem(), v)
}

func (vm *VM) i64Store() {
	v := vm.popUint64()
	if !vm.inBounds(7) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	endianess.PutUint64(vm.curMem(), v)
}

func (vm *VM) i64Store8() {
	v := byte(uint8(vm.popUint64()))
	if !vm.inBounds(0) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	vm.memory[vm.fetchBaseAddr()] = v
}

func (vm *VM) i64Store16() {
	v := uint16(vm.popUint64())
	if !vm.inBounds(1) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	endianess.PutUint16(vm.curMem(), v)
}

func (vm *VM) i64Store32() {
	v := uint32(vm.popUint64())
	if !vm.inBounds(3) {
		panic(ErrOutOfBoundsMemoryAccess)
	}
	endianess.PutUint32(vm.curMem(), v)
}

func (vm *VM) currentMemory() {
	_ = vm.fetchInt8() // reserved (https://github.com/WebAssembly/design/blob/27ac254c854994103c24834a994be16f74f54186/BinaryEncoding.md#memory-related-operators-described-here)
	vm.pushInt32(int32(len(vm.memory) / wasmPageSize))
}

func (vm *VM) growMemory() {
	_ = vm.fetchInt8() // reserved (https://github.com/WebAssembly/design/blob/27ac254c854994103c24834a994be16f74f54186/BinaryEncoding.md#memory-related-operators-described-here)
	curLen := len(vm.memory) / wasmPageSize
	n := vm.popInt32()
	vm.memory = append(vm.memory, make([]byte, n*wasmPageSize)...)
	vm.pushInt32(int32(curLen))
}
<|endoftext|>