<commit_before>// Copyright 2011 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 oglemock_test

import (
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/oglemock"
	. "github.com/jacobsa/ogletest"
)

////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////

type errorReport struct {
	fileName string
	lineNumber int
	err error
}

type fakeErrorReporter struct {
	errorsReported []errorReport
}

func (r *fakeErrorReporter) ReportError(fileName string, lineNumber int, err error) {
	report := errorReport{fileName, lineNumber, err}
	r.errorsReported = append(r.errorsReported, report)
}

type trivialMockObject struct {
	id uintptr
	desc string
}

func (o *trivialMockObject) Oglemock_Id() uintptr {
	return o.id
}

func (o *trivialMockObject) Oglemock_Description() string {
	return o.desc
}

// Method being mocked
func (o *trivialMockObject) StringToInt(s string) int {
	return 0
}

// Method being mocked
func (o *trivialMockObject) TwoIntsToString(i, j int) string {
	return ""
}

type ControllerTest struct {
	reporter fakeErrorReporter
	controller Controller

	mock1 MockObject
	mock2 MockObject
}

func (t *ControllerTest) SetUp() {
	t.reporter.errorsReported = make([]errorReport, 0)
	t.controller = NewController(&t.reporter)

	t.mock1 = &trivialMockObject{17, "taco"}
	t.mock2 = &trivialMockObject{19, "burrito"}
}

func init() { RegisterTestSuite(&ControllerTest{}) }

////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////

func (t *ControllerTest) FinishWithoutAnyEvents() {
	t.controller.Finish()
	ExpectThat(len(t.reporter.errorsReported), Equals(0))
}

func (t *ControllerTest) HandleCallForUnknownObject() {
	p := []byte{255}
	t.controller.HandleMethodCall(
		t.mock1,
		"StringToInt",
		"taco.go",
		112,
		[]interface{}{p})

	// The error should be reported immediately.
	ExpectThat(len(t.reporter.errorsReported), Equals(1))
	ExpectThat(t.reporter.errorsReported[0].fileName, Equals("taco.go"))
	ExpectThat(t.reporter.errorsReported[0].lineNumber, Equals(112))
	ExpectThat(t.reporter.errorsReported[0].err, Error(HasSubstr("Unexpected")))
	ExpectThat(t.reporter.errorsReported[0].err, Error(HasSubstr("Read")))
	ExpectThat(t.reporter.errorsReported[0].err, Error(HasSubstr("[255]")))

	// Finish should change nothing.
	t.controller.Finish()
	ExpectThat(len(t.reporter.errorsReported), Equals(1))
}

func (t *ControllerTest) ExpectCallForUnknownMethod() {
	ExpectThat(
		func() {
			t.controller.ExpectCall(t.mock1, "Frobnicate")
		},
		Panics(HasSubstr("Unknown method: Frobnicate")))
}

func (t *ControllerTest) PartialExpectationGivenWrongNumberOfArgs() {
	ExpectThat(
		func() {
			t.controller.ExpectCall(t.mock1, "TwoIntsToString")(17, 19, 23)
		},
		Panics(HasSubstr("arguments: expected 2, got 3")))
}

func (t *ControllerTest) PartialExpectationCalledTwice() {
	ExpectThat(
		func() {
			partial := t.controller.ExpectCall(t.mock1, "StringToInt")
			partial("taco")
			partial("taco")
		},
		Panics(HasSubstr("called more than once")))
}

func (t *ControllerTest) ExpectThenNonMatchingCall() {
	p := []byte{255}
	t.controller.ExpectCall(t.mock1, "TwoIntsToString")(LessThan(10), Equals(2))
	t.controller.HandleMethodCall(
		t.mock1,
		"TwoIntsToString",
		"taco.go",
		112,
		[]interface{}{8, 1})

	// The error should be reported immediately.
	ExpectThat(len(t.reporter.errorsReported), Equals(1))
	ExpectThat(t.reporter.errorsReported[0].fileName, Equals("taco.go"))
	ExpectThat(t.reporter.errorsReported[0].lineNumber, Equals(112))
	ExpectThat(t.reporter.errorsReported[0].err, Error(HasSubstr("Unexpected")))
	ExpectThat(t.reporter.errorsReported[0].err, Error(HasSubstr("Tried")))
	ExpectThat(t.reporter.errorsReported[0].err, Error(HasSubstr("burrito.go:117")))
	ExpectThat(t.reporter.errorsReported[0].err, Error(HasSubstr("arg 1")))
	ExpectThat(t.reporter.errorsReported[0].err, Error(HasSubstr("Expected: 2")))
	ExpectThat(t.reporter.errorsReported[0].err, Error(HasSubstr("Actual:   1")))

	// Finish should change nothing.
	t.controller.Finish()
	ExpectThat(len(t.reporter.errorsReported), Equals(1))
}

func (t *ControllerTest) ExplicitCardinalityNotSatisfied() {
}

func (t *ControllerTest) ImplicitOneTimeActionCountNotSatisfied() {
}

func (t *ControllerTest) ImplicitOneTimeActionLowerBoundNotSatisfied() {
}

func (t *ControllerTest) ImplicitCardinalityOfOneNotSatisfied() {
}

func (t *ControllerTest) ExplicitCardinalitySatisfied() {
}

func (t *ControllerTest) ImplicitOneTimeActionCountSatisfied() {
}

func (t *ControllerTest) ImplicitOneTimeActionLowerBoundSatisfied() {
}

func (t *ControllerTest) FallbackActionConfiguredWithZeroCalls() {
}

func (t *ControllerTest) FallbackActionConfiguredWithMultipleCalls() {
}

func (t *ControllerTest) ImplicitCardinalityOfOneSatisfied() {
}

func (t *ControllerTest) InvokesOneTimeActions() {
}

func (t *ControllerTest) InvokesFallbackActions() {
}

func (t *ControllerTest) InvokesImplicitActions() {
}

func (t *ControllerTest) ExpectationsAreMatchedLastToFirst() {
}

func (t *ControllerTest) ExpectationsAreSegregatedByMockObject() {
}

func (t *ControllerTest) ExpectationsAreSegregatedByMethodName() {
}
<commit_msg>Fixed some errors.<commit_after>// Copyright 2011 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 oglemock_test

import (
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/oglemock"
	. "github.com/jacobsa/ogletest"
)

////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////

type errorReport struct {
	fileName string
	lineNumber int
	err error
}

type fakeErrorReporter struct {
	errorsReported []errorReport
}

func (r *fakeErrorReporter) ReportError(fileName string, lineNumber int, err error) {
	report := errorReport{fileName, lineNumber, err}
	r.errorsReported = append(r.errorsReported, report)
}

type trivialMockObject struct {
	id uintptr
	desc string
}

func (o *trivialMockObject) Oglemock_Id() uintptr {
	return o.id
}

func (o *trivialMockObject) Oglemock_Description() string {
	return o.desc
}

// Method being mocked
func (o *trivialMockObject) StringToInt(s string) int {
	return 0
}

// Method being mocked
func (o *trivialMockObject) TwoIntsToString(i, j int) string {
	return ""
}

type ControllerTest struct {
	reporter fakeErrorReporter
	controller Controller

	mock1 MockObject
	mock2 MockObject
}

func (t *ControllerTest) SetUp() {
	t.reporter.errorsReported = make([]errorReport, 0)
	t.controller = NewController(&t.reporter)

	t.mock1 = &trivialMockObject{17, "taco"}
	t.mock2 = &trivialMockObject{19, "burrito"}
}

func init() { RegisterTestSuite(&ControllerTest{}) }

////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////

func (t *ControllerTest) FinishWithoutAnyEvents() {
	t.controller.Finish()
	ExpectThat(len(t.reporter.errorsReported), Equals(0))
}

func (t *ControllerTest) HandleCallForUnknownObject() {
	p := []byte{255}
	t.controller.HandleMethodCall(
		t.mock1,
		"StringToInt",
		"taco.go",
		112,
		[]interface{}{p})

	// The error should be reported immediately.
	ExpectThat(len(t.reporter.errorsReported), Equals(1))
	ExpectThat(t.reporter.errorsReported[0].fileName, Equals("taco.go"))
	ExpectThat(t.reporter.errorsReported[0].lineNumber, Equals(112))
	ExpectThat(t.reporter.errorsReported[0].err, Error(HasSubstr("Unexpected")))
	ExpectThat(t.reporter.errorsReported[0].err, Error(HasSubstr("Read")))
	ExpectThat(t.reporter.errorsReported[0].err, Error(HasSubstr("[255]")))

	// Finish should change nothing.
	t.controller.Finish()
	ExpectThat(len(t.reporter.errorsReported), Equals(1))
}

func (t *ControllerTest) ExpectCallForUnknownMethod() {
	ExpectThat(
		func() {
			t.controller.ExpectCall(t.mock1, "Frobnicate", "", 0)
		},
		Panics(HasSubstr("Unknown method: Frobnicate")))
}

func (t *ControllerTest) PartialExpectationGivenWrongNumberOfArgs() {
	ExpectThat(
		func() {
			t.controller.ExpectCall(t.mock1, "TwoIntsToString", "", 0)(17, 19, 23)
		},
		Panics(HasSubstr("arguments: expected 2, got 3")))
}

func (t *ControllerTest) PartialExpectationCalledTwice() {
	ExpectThat(
		func() {
			partial := t.controller.ExpectCall(t.mock1, "StringToInt", "", 0)
			partial("taco")
			partial("taco")
		},
		Panics(HasSubstr("called more than once")))
}

func (t *ControllerTest) ExpectThenNonMatchingCall() {
	// Expectation
	partial := t.controller.ExpectCall(
		t.mock1,
		"TwoIntsToString",
		"burrito.go",
		117)

	partial(LessThan(10), Equals(2))

	// Call
	t.controller.HandleMethodCall(
		t.mock1,
		"TwoIntsToString",
		"taco.go",
		112,
		[]interface{}{8, 1})

	// The error should be reported immediately.
	ExpectThat(len(t.reporter.errorsReported), Equals(1))
	ExpectThat(t.reporter.errorsReported[0].fileName, Equals("taco.go"))
	ExpectThat(t.reporter.errorsReported[0].lineNumber, Equals(112))
	ExpectThat(t.reporter.errorsReported[0].err, Error(HasSubstr("Unexpected")))
	ExpectThat(t.reporter.errorsReported[0].err, Error(HasSubstr("Tried")))
	ExpectThat(t.reporter.errorsReported[0].err, Error(HasSubstr("burrito.go:117")))
	ExpectThat(t.reporter.errorsReported[0].err, Error(HasSubstr("arg 1")))
	ExpectThat(t.reporter.errorsReported[0].err, Error(HasSubstr("Expected: 2")))
	ExpectThat(t.reporter.errorsReported[0].err, Error(HasSubstr("Actual:   1")))

	// Finish should change nothing.
	t.controller.Finish()
	ExpectThat(len(t.reporter.errorsReported), Equals(1))
}

func (t *ControllerTest) ExplicitCardinalityNotSatisfied() {
}

func (t *ControllerTest) ImplicitOneTimeActionCountNotSatisfied() {
}

func (t *ControllerTest) ImplicitOneTimeActionLowerBoundNotSatisfied() {
}

func (t *ControllerTest) ImplicitCardinalityOfOneNotSatisfied() {
}

func (t *ControllerTest) ExplicitCardinalitySatisfied() {
}

func (t *ControllerTest) ImplicitOneTimeActionCountSatisfied() {
}

func (t *ControllerTest) ImplicitOneTimeActionLowerBoundSatisfied() {
}

func (t *ControllerTest) FallbackActionConfiguredWithZeroCalls() {
}

func (t *ControllerTest) FallbackActionConfiguredWithMultipleCalls() {
}

func (t *ControllerTest) ImplicitCardinalityOfOneSatisfied() {
}

func (t *ControllerTest) InvokesOneTimeActions() {
}

func (t *ControllerTest) InvokesFallbackActions() {
}

func (t *ControllerTest) InvokesImplicitActions() {
}

func (t *ControllerTest) ExpectationsAreMatchedLastToFirst() {
}

func (t *ControllerTest) ExpectationsAreSegregatedByMockObject() {
}

func (t *ControllerTest) ExpectationsAreSegregatedByMethodName() {
}
<|endoftext|>


<commit_before>// Copyright 2011 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 oglemock_test

import (
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/oglemock"
	. "github.com/jacobsa/ogletest"
)

////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////

type errorReport struct {
	fileName string
	lineNumber int
	err error
}

type fakeErrorReporter struct {
	errorsReported []errorReport
}

func (r *fakeErrorReporter) ReportError(fileName string, lineNumber int, err error) {
	report := errorReport{fileName, lineNumber, err}
	r.errorsReported = append(r.errorsReported, report)
}

type trivialMockObject struct {
	id uintptr
	desc string
}

func (o *trivialMockObject) Oglemock_Id() uintptr {
	return o.id
}

func (o *trivialMockObject) Oglemock_Description() string {
	return o.desc
}

type ControllerTest struct {
	reporter fakeErrorReporter
	controller Controller

	mock1 MockObject
	mock2 MockObject
}

func (t *ControllerTest) SetUp() {
	t.reporter.errorsReported = make([]errorReport, 0)
	t.controller = NewController(&t.reporter)

	t.mock1 = &trivialMockObject{17, "taco"}
	t.mock2 = &trivialMockObject{19, "burrito"}
}

func init() { RegisterTestSuite(&ControllerTest{}) }

////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////

func (t *ControllerTest) FinishWithoutAnyEvents() {
	t.controller.Finish()
	ExpectThat(len(t.reporter.errorsReported), Equals(0))
}

func (t *ControllerTest) HandleCallForUnknownObject() {
	p := []byte{255}
	t.controller.HandleMethodCall(
		t.mock1,
		"Read",
		"taco.go",
		112,
		[]interface{}{p})

	// The error should be reported immediately.
	ExpectThat(len(t.reporter.errorsReported), Equals(1))
	ExpectThat(t.reporter.errorsReported[0].fileName, Equals("taco.go"))
	ExpectThat(t.reporter.errorsReported[0].lineNumber, Equals(112))
	ExpectThat(t.reporter.errorsReported[0].err, Error(HasSubstr("Unexpected")))
	ExpectThat(t.reporter.errorsReported[0].err, Error(HasSubstr("Read")))
	ExpectThat(t.reporter.errorsReported[0].err, Error(HasSubstr("[255]")))
}

func (t *ControllerTest) ExpectCallForUnknownMethod() {
	ExpectThat(
		func() {
			t.controller.ExpectCall(t.mock1, "Frobnicate")
		},
		Panics(HasSubstr("Unknown method: Frobnicate")))
}

func (t *ControllerTest) PartialExpectationGivenWrongNumberOfArgs() {
}

func (t *ControllerTest) PartialExpectationCalledTwice() {
}

func (t *ControllerTest) ExpectThenNonMatchingCall() {
}

func (t *ControllerTest) ExplicitCardinalityNotSatisfied() {
}

func (t *ControllerTest) ImplicitOneTimeActionCountNotSatisfied() {
}

func (t *ControllerTest) ImplicitOneTimeActionLowerBoundNotSatisfied() {
}

func (t *ControllerTest) ImplicitCardinalityOfOneNotSatisfied() {
}

func (t *ControllerTest) ExplicitCardinalitySatisfied() {
}

func (t *ControllerTest) ImplicitOneTimeActionCountSatisfied() {
}

func (t *ControllerTest) ImplicitOneTimeActionLowerBoundSatisfied() {
}

func (t *ControllerTest) FallbackActionConfiguredWithZeroCalls() {
}

func (t *ControllerTest) FallbackActionConfiguredWithMultipleCalls() {
}

func (t *ControllerTest) ImplicitCardinalityOfOneSatisfied() {
}

func (t *ControllerTest) InvokesOneTimeActions() {
}

func (t *ControllerTest) InvokesFallbackActions() {
}

func (t *ControllerTest) InvokesImplicitActions() {
}

func (t *ControllerTest) ExpectationsAreMatchedLastToFirst() {
}

func (t *ControllerTest) ExpectationsAreSegregatedByMockObject() {
}

func (t *ControllerTest) ExpectationsAreSegregatedByMethodName() {
}
<commit_msg>Added methods being mocked.<commit_after>// Copyright 2011 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 oglemock_test

import (
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/oglemock"
	. "github.com/jacobsa/ogletest"
)

////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////

type errorReport struct {
	fileName string
	lineNumber int
	err error
}

type fakeErrorReporter struct {
	errorsReported []errorReport
}

func (r *fakeErrorReporter) ReportError(fileName string, lineNumber int, err error) {
	report := errorReport{fileName, lineNumber, err}
	r.errorsReported = append(r.errorsReported, report)
}

type trivialMockObject struct {
	id uintptr
	desc string
}

func (o *trivialMockObject) Oglemock_Id() uintptr {
	return o.id
}

func (o *trivialMockObject) Oglemock_Description() string {
	return o.desc
}

// Method being mocked
func (o *trivialMockObject) StringToInt(s string) int {
	return 0
}

// Method being mocked
func (o *trivialMockObject) TwoIntsToString(i, j int) string {
	return ""
}

type ControllerTest struct {
	reporter fakeErrorReporter
	controller Controller

	mock1 MockObject
	mock2 MockObject
}

func (t *ControllerTest) SetUp() {
	t.reporter.errorsReported = make([]errorReport, 0)
	t.controller = NewController(&t.reporter)

	t.mock1 = &trivialMockObject{17, "taco"}
	t.mock2 = &trivialMockObject{19, "burrito"}
}

func init() { RegisterTestSuite(&ControllerTest{}) }

////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////

func (t *ControllerTest) FinishWithoutAnyEvents() {
	t.controller.Finish()
	ExpectThat(len(t.reporter.errorsReported), Equals(0))
}

func (t *ControllerTest) HandleCallForUnknownObject() {
	p := []byte{255}
	t.controller.HandleMethodCall(
		t.mock1,
		"StringToInt",
		"taco.go",
		112,
		[]interface{}{p})

	// The error should be reported immediately.
	ExpectThat(len(t.reporter.errorsReported), Equals(1))
	ExpectThat(t.reporter.errorsReported[0].fileName, Equals("taco.go"))
	ExpectThat(t.reporter.errorsReported[0].lineNumber, Equals(112))
	ExpectThat(t.reporter.errorsReported[0].err, Error(HasSubstr("Unexpected")))
	ExpectThat(t.reporter.errorsReported[0].err, Error(HasSubstr("Read")))
	ExpectThat(t.reporter.errorsReported[0].err, Error(HasSubstr("[255]")))
}

func (t *ControllerTest) ExpectCallForUnknownMethod() {
	ExpectThat(
		func() {
			t.controller.ExpectCall(t.mock1, "Frobnicate")
		},
		Panics(HasSubstr("Unknown method: Frobnicate")))
}

func (t *ControllerTest) PartialExpectationGivenWrongNumberOfArgs() {
}

func (t *ControllerTest) PartialExpectationCalledTwice() {
}

func (t *ControllerTest) ExpectThenNonMatchingCall() {
}

func (t *ControllerTest) ExplicitCardinalityNotSatisfied() {
}

func (t *ControllerTest) ImplicitOneTimeActionCountNotSatisfied() {
}

func (t *ControllerTest) ImplicitOneTimeActionLowerBoundNotSatisfied() {
}

func (t *ControllerTest) ImplicitCardinalityOfOneNotSatisfied() {
}

func (t *ControllerTest) ExplicitCardinalitySatisfied() {
}

func (t *ControllerTest) ImplicitOneTimeActionCountSatisfied() {
}

func (t *ControllerTest) ImplicitOneTimeActionLowerBoundSatisfied() {
}

func (t *ControllerTest) FallbackActionConfiguredWithZeroCalls() {
}

func (t *ControllerTest) FallbackActionConfiguredWithMultipleCalls() {
}

func (t *ControllerTest) ImplicitCardinalityOfOneSatisfied() {
}

func (t *ControllerTest) InvokesOneTimeActions() {
}

func (t *ControllerTest) InvokesFallbackActions() {
}

func (t *ControllerTest) InvokesImplicitActions() {
}

func (t *ControllerTest) ExpectationsAreMatchedLastToFirst() {
}

func (t *ControllerTest) ExpectationsAreSegregatedByMockObject() {
}

func (t *ControllerTest) ExpectationsAreSegregatedByMethodName() {
}
<|endoftext|>


<commit_before>package freetree

import "sort"

// -----------------------------------------------------------------------------

// SimpleTree implements a simple binary search tree.
type SimpleTree struct {
	root  *simpleNode
	nodes uint
}

// NewSimpleTree returns an empty SimpleTree.
func NewSimpleTree() *SimpleTree {
	return &SimpleTree{}
}

// Insert inserts the given Comparables in the tree.
// It does not rebalance the tree, use Rebalance() for that.
//
// If the tree is currently empty and the passed-in Comparable are already
// sorted in increasing order, the tree will be perfectly balanced.
// This means you don't have to Rebalance() the tree if you've inserted all
// your pre-sorted data in one Insert() call.
func (st *SimpleTree) Insert(cs ...Comparable) {
	st.insert(cs)
}

// InsertArray is a helper to use Insert() with a ComparableArray.
func (st *SimpleTree) InsertArray(cs ComparableArray) {
	st.insert(cs)
	st.nodes += uint(len(cs))
}

func (st *SimpleTree) insert(cs ComparableArray) {
	l := len(cs)
	if l == 0 {
		return
	}

	st.root = st.root.insert(cs[l/2])

	if l > 1 {
		st.insert(cs[:l/2])
		st.insert(cs[l/2+1:])
	}
}

// Ascend returns the first element in the tree that is >= `pivot`.
func (st SimpleTree) Ascend(pivot Comparable) Comparable {
	return st.ascend(pivot)
}

func (st SimpleTree) ascend(pivot Comparable) Comparable {
	return st.root.ascend(pivot)
}

// Rebalance rebalances the tree to guarantee O(log(n)) search complexity.
//
// Rebalancing is implemented as straightforwardly as possible: it's dumb.
// I strongly suggest running the garbage collector once it's done.
//   runtime.GC()
//   debug.FreeOSMemory()
func (st *SimpleTree) Rebalance() {
	flat := st.flatten()
	sort.Sort(flat)

	st.root = nil
	st.insert(flat)
}

// Flatten returns the content of the tree as a ComparableArray.
func (st SimpleTree) Flatten() ComparableArray {
	return st.flatten()
}

func (st SimpleTree) flatten() ComparableArray {
	ca := make(ComparableArray, 0, st.nodes)
	return st.root.flatten(ca)
}

// -----------------------------------------------------------------------------

type simpleNode struct {
	left, right *simpleNode
	data        Comparable
}

func (sn *simpleNode) insert(c Comparable) *simpleNode {
	if sn == nil {
		return &simpleNode{data: c}
	}

	if c.Less(sn.data) {
		sn.left = sn.left.insert(c)
	} else {
		sn.right = sn.right.insert(c)
	}

	return sn
}

func (sn *simpleNode) ascend(pivot Comparable) Comparable {
	if sn == nil {
		return nil
	}

	if pivot.Less(sn.data) {
		return sn.data
	} else {
		return sn.right.ascend(pivot)
	}
}

func (sn *simpleNode) flatten(ca ComparableArray) ComparableArray {
	if sn == nil {
		return ca
	}

	ca = sn.left.flatten(ca)
	ca = sn.right.flatten(ca)

	return append(ca, sn.data)
}
<commit_msg>fixed SimpleTree ascending<commit_after>package freetree

import "sort"

// -----------------------------------------------------------------------------

// SimpleTree implements a simple binary search tree.
type SimpleTree struct {
	root  *simpleNode
	nodes uint
}

// NewSimpleTree returns an empty SimpleTree.
func NewSimpleTree() *SimpleTree {
	return &SimpleTree{}
}

// Insert inserts the given Comparables in the tree.
// It does not rebalance the tree, use Rebalance() for that.
//
// If the tree is currently empty and the passed-in Comparable are already
// sorted in increasing order, the tree will be perfectly balanced.
// This means you don't have to Rebalance() the tree if you've inserted all
// your pre-sorted data in one Insert() call.
func (st *SimpleTree) Insert(cs ...Comparable) {
	st.insert(cs)
}

// InsertArray is a helper to use Insert() with a ComparableArray.
func (st *SimpleTree) InsertArray(cs ComparableArray) {
	st.insert(cs)
	st.nodes += uint(len(cs))
}

func (st *SimpleTree) insert(cs ComparableArray) {
	l := len(cs)
	if l == 0 {
		return
	}

	st.root = st.root.insert(cs[l/2])

	if l > 1 {
		st.insert(cs[:l/2])
		st.insert(cs[l/2+1:])
	}
}

// Ascend returns the first element in the tree that is >= `pivot`.
func (st SimpleTree) Ascend(pivot Comparable) Comparable {
	return st.ascend(pivot)
}

func (st SimpleTree) ascend(pivot Comparable) Comparable {
	return st.root.ascend(pivot)
}

// Rebalance rebalances the tree to guarantee O(log(n)) search complexity.
//
// Rebalancing is implemented as straightforwardly as possible: it's dumb.
// I strongly suggest running the garbage collector once it's done.
//   runtime.GC()
//   debug.FreeOSMemory()
func (st *SimpleTree) Rebalance() {
	flat := st.flatten()
	sort.Sort(flat)

	st.root = nil
	st.insert(flat)
}

// Flatten returns the content of the tree as a ComparableArray.
func (st SimpleTree) Flatten() ComparableArray {
	return st.flatten()
}

func (st SimpleTree) flatten() ComparableArray {
	ca := make(ComparableArray, 0, st.nodes)
	return st.root.flatten(ca)
}

// -----------------------------------------------------------------------------

type simpleNode struct {
	left, right *simpleNode
	data        Comparable
}

func (sn *simpleNode) insert(c Comparable) *simpleNode {
	if sn == nil {
		return &simpleNode{data: c}
	}

	if c.Less(sn.data) {
		sn.left = sn.left.insert(c)
	} else {
		sn.right = sn.right.insert(c)
	}

	return sn
}

func (sn *simpleNode) ascend(pivot Comparable) Comparable {
	if sn == nil {
		return nil
	}

	if pivot.Less(sn.data) {
		return sn.left.ascend(pivot)
	} else if sn.data.Less(pivot) {
		return sn.right.ascend(pivot)
	}

	return sn.data
}

func (sn *simpleNode) flatten(ca ComparableArray) ComparableArray {
	if sn == nil {
		return ca
	}

	ca = sn.left.flatten(ca)
	ca = sn.right.flatten(ca)

	return append(ca, sn.data)
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/index0h/go-tracker/modules/event"
	"github.com/index0h/go-tracker/modules/flash"
	"github.com/index0h/go-tracker/modules/track"
	"github.com/index0h/go-tracker/modules/visit"

	eventDummy "github.com/index0h/go-tracker/modules/event/dao/dummy"
	flashDummy "github.com/index0h/go-tracker/modules/flash/dao/dummy"
	visitDummy "github.com/index0h/go-tracker/modules/visit/dao/dummy"

	eventElastic "github.com/index0h/go-tracker/modules/event/dao/elastic"
	flashElastic "github.com/index0h/go-tracker/modules/flash/dao/elastic"
	visitElastic "github.com/index0h/go-tracker/modules/visit/dao/elastic"

	eventMemory "github.com/index0h/go-tracker/modules/event/dao/memory"
	visitMemory "github.com/index0h/go-tracker/modules/visit/dao/memory"

	"github.com/index0h/go-tracker/app/generated"
	"github.com/index0h/go-tracker/app/handlers"
	"github.com/index0h/go-tracker/share/uuid"

	"git.apache.org/thrift.git/lib/go/thrift"
	"github.com/Sirupsen/logrus"
	"github.com/olivere/elastic"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"

	"fmt"
	"os"
	"strconv"
)

const Version = "0.0.1"

type Config struct {
	Port     uint
	Host     string
	LogLevel string

	ElasticConnections struct {
		Host       string
		MaxRetries int
	}

	Visit struct {
		Elastic bool
		Memory  struct {
			Use       bool
			CacheSize int
		}
	}

	Event struct {
		Elastic bool
		Memory  struct {
			Use bool
		}
	}

	Flash struct {
		Elastic bool
	}
}

func main() {
	var (
		config     Config
		configPath string
		err        error
	)

	logger := logrus.New()
	logger.Formatter = &logrus.JSONFormatter{}

	configLoader := viper.New()
	configLoader.SetConfigType("yml")
	configLoader.SetConfigName("tracker")

	runCommand := &cobra.Command{
		Use:   "run",
		Short: "Run tracker service",
		Run: func(cmd *cobra.Command, args []string) {
			if err := configLoader.ReadInConfig(); err != nil {
				logger.Fatal(err)
			}

			if err := configLoader.Marshal(&config); err != nil {
				logger.Fatal(err)
			}

			if logger.Level, err = logrus.ParseLevel(config.LogLevel); err != nil {
				logger.Panic(err)
			}

			Run(&config, logger)
		},
	}

	runCommand.Flags().StringVarP(&configPath, "config", "c", "", "alternative config path")
	if configPath != "" {
		configLoader.AddConfigPath(configPath)
	} else {
		currentPath, err := os.Getwd()
		if err != nil {
			logger.Fatal(err)
		}

		configLoader.AddConfigPath(currentPath)
		configLoader.AddConfigPath("/etc/tracker/")
		configLoader.AddConfigPath("$HOME/.tracker")
	}

	runCommand.Flags().StringVarP(&config.LogLevel, "log", "l", "warning", "log level")
	viper.BindPFlag("Log", runCommand.Flags().Lookup("log"))

	runCommand.Flags().StringVar(&config.Host, "host", "localhost", "tracker service host")
	viper.BindPFlag("Host", runCommand.Flags().Lookup("host"))

	runCommand.Flags().UintVarP(&config.Port, "port", "p", 9898, "tracker service port")
	viper.BindPFlag("Port", runCommand.Flags().Lookup("port"))

	versionCommand := &cobra.Command{
		Use:   "version",
		Short: "Print tracker version",
		Run: func(cmd *cobra.Command, args []string) {
			fmt.Println(Version)
		},
	}

	rootCommand := &cobra.Command{Use: "app"}
	rootCommand.AddCommand(runCommand, versionCommand)
	rootCommand.Execute()
}

func Run(config *Config, logger *logrus.Logger) {
	var (
		visitRepository visit.RepositoryInterface
		eventRepository event.RepositoryInterface
		flashRepository flash.RepositoryInterface
		elasticClient   *elastic.Client
		err             error
	)

	uuid := uuid.New()

	if config.ElasticConnections.Host != "" {
		logger.Info("create elastic client")

		elasticClient, err = elastic.NewClient(
			elastic.SetURL(config.ElasticConnections.Host),
			elastic.SetMaxRetries(config.ElasticConnections.MaxRetries),
		)
		if err != nil {
			logger.Fatal(err)
		}
	}

	visitRepository = visitDummy.NewRepository()

	if config.Visit.Elastic {
		logger.Info("create elastic visit repository")

		visitRepository, err = visitElastic.NewRepository(elasticClient, uuid)
		if err != nil {
			logger.Fatal(err)
		}
	}

	if config.Visit.Memory.Use {
		logger.Info("create memory visit repository")

		visitRepository, err = visitMemory.NewRepository(visitRepository, config.Visit.Memory.CacheSize)
		if err != nil {
			logger.Fatal(err)
		}
	}

	visitManager := visit.NewManager(visitRepository, uuid, logger.WithField("service", "VisitManager"))

	eventRepository = eventDummy.NewRepository()

	if config.Event.Elastic {
		logger.Info("create elastic event repository")

		eventRepository, err = eventElastic.NewRepository(elasticClient, uuid)
		if err != nil {
			logger.Fatal(err)
		}
	}

	if config.Event.Memory.Use {
		logger.Info("create memory event repository")

		eventRepository, err = eventMemory.NewRepository(eventRepository)
		if err != nil {
			logger.Fatal(err)
		}
	}

	eventManager := event.NewManager(eventRepository, uuid, logger.WithField("service", "EventManager"))

	flashRepository = flashDummy.NewRepository()

	if config.Flash.Elastic {
		logger.Info("create elastic flash repository")

		flashRepository, err = flashElastic.NewRepository(elasticClient, uuid)
		if err != nil {
			logger.Fatal(err)
		}
	}

	flashManager := flash.NewManager(flashRepository, uuid, logger.WithField("service", "FlashManager"))

	trackLogger := logger.WithField("service", "TrackManager")
	trackManager := track.NewManager(visitManager, eventManager, flashManager, nil, uuid, trackLogger)

	logger.Info("init thrift")

	processor := thrift.NewTMultiplexedProcessor()

	visitHandler := handlers.NewVisitHandler(visitManager, uuid)
	eventHandler := handlers.NewEventHandler(eventManager, uuid)
	flashHandler := handlers.NewFlashHandler(flashManager, uuid)
	trackHandler := handlers.NewTrackHandler(trackManager, uuid)

	processor.RegisterProcessor("visit", generated.NewVisitServiceProcessor(visitHandler))
	processor.RegisterProcessor("event", generated.NewEventServiceProcessor(eventHandler))
	processor.RegisterProcessor("flash", generated.NewFlashServiceProcessor(flashHandler))
	processor.RegisterProcessor("track", generated.NewTrackServiceProcessor(trackHandler))

	transport, err := thrift.NewTServerSocket(config.Host + ":" + strconv.Itoa(int(config.Port)))
	if err != nil {
		logger.Fatal(err)
	}

	transportFactory := thrift.NewTBufferedTransportFactory(8192)

	protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()

	server := thrift.NewTSimpleServer4(processor, transport, transportFactory, protocolFactory)

	logger.Info("run server on: tcp://" + config.Host + ":" + strconv.Itoa(int(config.Port)))

	server.Serve()
}
<commit_msg>fix logger interface<commit_after>package main

import (
	"github.com/index0h/go-tracker/modules/event"
	"github.com/index0h/go-tracker/modules/flash"
	"github.com/index0h/go-tracker/modules/track"
	"github.com/index0h/go-tracker/modules/visit"

	eventDummy "github.com/index0h/go-tracker/modules/event/dao/dummy"
	flashDummy "github.com/index0h/go-tracker/modules/flash/dao/dummy"
	visitDummy "github.com/index0h/go-tracker/modules/visit/dao/dummy"

	eventElastic "github.com/index0h/go-tracker/modules/event/dao/elastic"
	flashElastic "github.com/index0h/go-tracker/modules/flash/dao/elastic"
	visitElastic "github.com/index0h/go-tracker/modules/visit/dao/elastic"

	eventMemory "github.com/index0h/go-tracker/modules/event/dao/memory"
	visitMemory "github.com/index0h/go-tracker/modules/visit/dao/memory"

	"github.com/index0h/go-tracker/app/generated"
	"github.com/index0h/go-tracker/app/handlers"
	"github.com/index0h/go-tracker/share/uuid"

	"git.apache.org/thrift.git/lib/go/thrift"
	"github.com/Sirupsen/logrus"
	"github.com/olivere/elastic"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"

	"fmt"
	"os"
	"strconv"
)

const Version = "0.0.1"

type Config struct {
	Port     uint
	Host     string
	LogLevel string

	ElasticConnections struct {
		Host       string
		MaxRetries int
	}

	Visit struct {
		Elastic bool
		Memory  struct {
			Use       bool
			CacheSize int
		}
	}

	Event struct {
		Elastic bool
		Memory  struct {
			Use bool
		}
	}

	Flash struct {
		Elastic bool
	}
}

func main() {
	var (
		config     Config
		configPath string
		err        error
	)

	logger := logrus.New()
	logger.Formatter = &logrus.JSONFormatter{}

	configLoader := viper.New()
	configLoader.SetConfigType("yml")
	configLoader.SetConfigName("tracker")

	runCommand := &cobra.Command{
		Use:   "run",
		Short: "Run tracker service",
		Run: func(cmd *cobra.Command, args []string) {
			if err := configLoader.ReadInConfig(); err != nil {
				logger.Fatal(err)
			}

			if err := configLoader.Marshal(&config); err != nil {
				logger.Fatal(err)
			}

			if logger.Level, err = logrus.ParseLevel(config.LogLevel); err != nil {
				logger.Panic(err)
			}

			Run(&config, logger)
		},
	}

	runCommand.Flags().StringVarP(&configPath, "config", "c", "", "alternative config path")
	if configPath != "" {
		configLoader.AddConfigPath(configPath)
	} else {
		currentPath, err := os.Getwd()
		if err != nil {
			logger.Fatal(err)
		}

		configLoader.AddConfigPath(currentPath)
		configLoader.AddConfigPath("/etc/tracker/")
		configLoader.AddConfigPath("$HOME/.tracker")
	}

	runCommand.Flags().StringVarP(&config.LogLevel, "log", "l", "warning", "log level")
	viper.BindPFlag("Log", runCommand.Flags().Lookup("log"))

	runCommand.Flags().StringVar(&config.Host, "host", "localhost", "tracker service host")
	viper.BindPFlag("Host", runCommand.Flags().Lookup("host"))

	runCommand.Flags().UintVarP(&config.Port, "port", "p", 9898, "tracker service port")
	viper.BindPFlag("Port", runCommand.Flags().Lookup("port"))

	versionCommand := &cobra.Command{
		Use:   "version",
		Short: "Print tracker version",
		Run: func(cmd *cobra.Command, args []string) {
			fmt.Println(Version)
		},
	}

	rootCommand := &cobra.Command{Use: "app"}
	rootCommand.AddCommand(runCommand, versionCommand)
	rootCommand.Execute()
}

func Run(config *Config, logger *logrus.Logger) {
	var (
		visitRepository visit.RepositoryInterface
		eventRepository event.RepositoryInterface
		flashRepository flash.RepositoryInterface
		elasticClient   *elastic.Client
		err             error
	)

	uuid := uuid.New()

	if config.ElasticConnections.Host != "" {
		logger.Info("create elastic client")

		elasticClient, err = elastic.NewClient(
			elastic.SetURL(config.ElasticConnections.Host),
			elastic.SetMaxRetries(config.ElasticConnections.MaxRetries),
		)
		if err != nil {
			logger.Fatal(err)
		}
	}

	visitRepository = visitDummy.NewRepository()

	if config.Visit.Elastic {
		logger.Info("create elastic visit repository")

		visitRepository, err = visitElastic.NewRepository(elasticClient, uuid)
		if err != nil {
			logger.Fatal(err)
		}
	}

	if config.Visit.Memory.Use {
		logger.Info("create memory visit repository")

		visitRepository, err = visitMemory.NewRepository(visitRepository, config.Visit.Memory.CacheSize)
		if err != nil {
			logger.Fatal(err)
		}
	}

	visitManager := visit.NewManager(visitRepository, uuid, logger)

	eventRepository = eventDummy.NewRepository()

	if config.Event.Elastic {
		logger.Info("create elastic event repository")

		eventRepository, err = eventElastic.NewRepository(elasticClient, uuid)
		if err != nil {
			logger.Fatal(err)
		}
	}

	if config.Event.Memory.Use {
		logger.Info("create memory event repository")

		eventRepository, err = eventMemory.NewRepository(eventRepository)
		if err != nil {
			logger.Fatal(err)
		}
	}

	eventManager := event.NewManager(eventRepository, uuid, logger)

	flashRepository = flashDummy.NewRepository()

	if config.Flash.Elastic {
		logger.Info("create elastic flash repository")

		flashRepository, err = flashElastic.NewRepository(elasticClient, uuid)
		if err != nil {
			logger.Fatal(err)
		}
	}

	flashManager := flash.NewManager(flashRepository, uuid, logger)

	trackManager := track.NewManager(visitManager, eventManager, flashManager, nil, uuid, logger)

	logger.Info("init thrift")

	processor := thrift.NewTMultiplexedProcessor()

	visitHandler := handlers.NewVisitHandler(visitManager, uuid)
	eventHandler := handlers.NewEventHandler(eventManager, uuid)
	flashHandler := handlers.NewFlashHandler(flashManager, uuid)
	trackHandler := handlers.NewTrackHandler(trackManager, uuid)

	processor.RegisterProcessor("visit", generated.NewVisitServiceProcessor(visitHandler))
	processor.RegisterProcessor("event", generated.NewEventServiceProcessor(eventHandler))
	processor.RegisterProcessor("flash", generated.NewFlashServiceProcessor(flashHandler))
	processor.RegisterProcessor("track", generated.NewTrackServiceProcessor(trackHandler))

	transport, err := thrift.NewTServerSocket(config.Host + ":" + strconv.Itoa(int(config.Port)))
	if err != nil {
		logger.Fatal(err)
	}

	transportFactory := thrift.NewTBufferedTransportFactory(8192)

	protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()

	server := thrift.NewTSimpleServer4(processor, transport, transportFactory, protocolFactory)

	logger.Info("run server on: tcp://" + config.Host + ":" + strconv.Itoa(int(config.Port)))

	server.Serve()
}
<|endoftext|>


<commit_before>// Errors and error handling

package fs

import (
	"fmt"
	"io"
	"net/http"
	"reflect"
	"strings"

	"github.com/pkg/errors"
)

// Retrier is an optional interface for error as to whether the
// operation should be retried at a high level.
//
// This should be returned from Update or Put methods as required
type Retrier interface {
	error
	Retry() bool
}

// retryError is a type of error
type retryError string

// Error interface
func (r retryError) Error() string {
	return string(r)
}

// Retry interface
func (r retryError) Retry() bool {
	return true
}

// Check interface
var _ Retrier = retryError("")

// RetryErrorf makes an error which indicates it would like to be retried
func RetryErrorf(format string, a ...interface{}) error {
	return retryError(fmt.Sprintf(format, a...))
}

// wrappedRetryError is an error wrapped so it will satisfy the
// Retrier interface and return true
type wrappedRetryError struct {
	error
}

// Retry interface
func (err wrappedRetryError) Retry() bool {
	return true
}

// Check interface
var _ Retrier = wrappedRetryError{(error)(nil)}

// RetryError makes an error which indicates it would like to be retried
func RetryError(err error) error {
	if err == nil {
		err = errors.New("needs retry")
	}
	return wrappedRetryError{err}
}

// IsRetryError returns true if err conforms to the Retry interface
// and calling the Retry method returns true.
func IsRetryError(err error) bool {
	if err == nil {
		return false
	}
	err = errors.Cause(err)
	if r, ok := err.(Retrier); ok {
		return r.Retry()
	}
	return false
}

// Fataler is an optional interface for error as to whether the
// operation should cause the entire operation to finish immediately.
//
// This should be returned from Update or Put methods as required
type Fataler interface {
	error
	Fatal() bool
}

// wrappedFatalError is an error wrapped so it will satisfy the
// Retrier interface and return true
type wrappedFatalError struct {
	error
}

// Fatal interface
func (err wrappedFatalError) Fatal() bool {
	return true
}

// Check interface
var _ Fataler = wrappedFatalError{(error)(nil)}

// FatalError makes an error which indicates it is a fatal error and
// the sync should stop.
func FatalError(err error) error {
	if err == nil {
		err = errors.New("fatal error")
	}
	return wrappedFatalError{err}
}

// IsFatalError returns true if err conforms to the Fatal interface
// and calling the Fatal method returns true.
func IsFatalError(err error) bool {
	if err == nil {
		return false
	}
	err = errors.Cause(err)
	if r, ok := err.(Fataler); ok {
		return r.Fatal()
	}
	return false
}

// NoRetrier is an optional interface for error as to whether the
// operation should not be retried at a high level.
//
// If only NoRetry errors are returned in a sync then the sync won't
// be retried.
//
// This should be returned from Update or Put methods as required
type NoRetrier interface {
	error
	NoRetry() bool
}

// wrappedNoRetryError is an error wrapped so it will satisfy the
// Retrier interface and return true
type wrappedNoRetryError struct {
	error
}

// NoRetry interface
func (err wrappedNoRetryError) NoRetry() bool {
	return true
}

// Check interface
var _ NoRetrier = wrappedNoRetryError{(error)(nil)}

// NoRetryError makes an error which indicates the sync shouldn't be
// retried.
func NoRetryError(err error) error {
	return wrappedNoRetryError{err}
}

// IsNoRetryError returns true if err conforms to the NoRetry
// interface and calling the NoRetry method returns true.
func IsNoRetryError(err error) bool {
	if err == nil {
		return false
	}
	err = errors.Cause(err)
	if r, ok := err.(NoRetrier); ok {
		return r.NoRetry()
	}
	return false
}

// Cause is a souped up errors.Cause which can unwrap some standard
// library errors too.  It returns true if any of the intermediate
// errors had a Timeout() or Temporary() method which returned true.
func Cause(cause error) (retriable bool, err error) {
	err = cause
	for prev := err; err != nil; prev = err {
		// Check for net error Timeout()
		if x, ok := err.(interface {
			Timeout() bool
		}); ok && x.Timeout() {
			retriable = true
		}

		// Check for net error Temporary()
		if x, ok := err.(interface {
			Temporary() bool
		}); ok && x.Temporary() {
			retriable = true
		}

		// Unwrap 1 level if possible
		err = errors.Cause(err)
		if err == prev {
			// Unpack any struct or *struct with a field
			// of name Err which satisfies the error
			// interface.  This includes *url.Error,
			// *net.OpError, *os.SyscallError and many
			// others in the stdlib
			errType := reflect.TypeOf(err)
			errValue := reflect.ValueOf(err)
			if errType.Kind() == reflect.Ptr {
				errType = errType.Elem()
				errValue = errValue.Elem()
			}
			if errType.Kind() == reflect.Struct {
				if errField := errValue.FieldByName("Err"); errField.IsValid() {
					errFieldValue := errField.Interface()
					if newErr, ok := errFieldValue.(error); ok {
						err = newErr
					}
				}
			}
		}
		if err == prev {
			break
		}
	}
	return retriable, err
}

// retriableErrorStrings is a list of phrases which when we find it
// in an an error, we know it is a networking error which should be
// retried.
//
// This is incredibly ugly - if only errors.Cause worked for all
// errors and all errors were exported from the stdlib.
var retriableErrorStrings = []string{
	"use of closed network connection", // not exported :-(
	"unexpected EOF reading trailer",
}

// Errors which indicate networking errors which should be retried
//
// These are added to in retriable_errors*.go
var retriableErrors = []error{
	io.EOF,
	io.ErrUnexpectedEOF,
}

// ShouldRetry looks at an error and tries to work out if retrying the
// operation that caused it would be a good idea. It returns true if
// the error implements Timeout() or Temporary() or if the error
// indicates a premature closing of the connection.
func ShouldRetry(err error) bool {
	if err == nil {
		return false
	}

	// Find root cause if available
	retriable, err := Cause(err)
	if retriable {
		return true
	}

	// Check if it is a retriable error
	for _, retriableErr := range retriableErrors {
		if err == retriableErr {
			return true
		}
	}

	// Check error strings (yuch!) too
	errString := err.Error()
	for _, phrase := range retriableErrorStrings {
		if strings.Contains(errString, phrase) {
			return true
		}
	}

	return false
}

// ShouldRetryHTTP returns a boolean as to whether this resp deserves.
// It checks to see if the HTTP response code is in the slice
// retryErrorCodes.
func ShouldRetryHTTP(resp *http.Response, retryErrorCodes []int) bool {
	if resp == nil {
		return false
	}
	for _, e := range retryErrorCodes {
		if resp.StatusCode == e {
			return true
		}
	}
	return false
}
<commit_msg>fs: Add more errors to retry - fixes #1733<commit_after>// Errors and error handling

package fs

import (
	"fmt"
	"io"
	"net/http"
	"reflect"
	"strings"

	"github.com/pkg/errors"
)

// Retrier is an optional interface for error as to whether the
// operation should be retried at a high level.
//
// This should be returned from Update or Put methods as required
type Retrier interface {
	error
	Retry() bool
}

// retryError is a type of error
type retryError string

// Error interface
func (r retryError) Error() string {
	return string(r)
}

// Retry interface
func (r retryError) Retry() bool {
	return true
}

// Check interface
var _ Retrier = retryError("")

// RetryErrorf makes an error which indicates it would like to be retried
func RetryErrorf(format string, a ...interface{}) error {
	return retryError(fmt.Sprintf(format, a...))
}

// wrappedRetryError is an error wrapped so it will satisfy the
// Retrier interface and return true
type wrappedRetryError struct {
	error
}

// Retry interface
func (err wrappedRetryError) Retry() bool {
	return true
}

// Check interface
var _ Retrier = wrappedRetryError{(error)(nil)}

// RetryError makes an error which indicates it would like to be retried
func RetryError(err error) error {
	if err == nil {
		err = errors.New("needs retry")
	}
	return wrappedRetryError{err}
}

// IsRetryError returns true if err conforms to the Retry interface
// and calling the Retry method returns true.
func IsRetryError(err error) bool {
	if err == nil {
		return false
	}
	err = errors.Cause(err)
	if r, ok := err.(Retrier); ok {
		return r.Retry()
	}
	return false
}

// Fataler is an optional interface for error as to whether the
// operation should cause the entire operation to finish immediately.
//
// This should be returned from Update or Put methods as required
type Fataler interface {
	error
	Fatal() bool
}

// wrappedFatalError is an error wrapped so it will satisfy the
// Retrier interface and return true
type wrappedFatalError struct {
	error
}

// Fatal interface
func (err wrappedFatalError) Fatal() bool {
	return true
}

// Check interface
var _ Fataler = wrappedFatalError{(error)(nil)}

// FatalError makes an error which indicates it is a fatal error and
// the sync should stop.
func FatalError(err error) error {
	if err == nil {
		err = errors.New("fatal error")
	}
	return wrappedFatalError{err}
}

// IsFatalError returns true if err conforms to the Fatal interface
// and calling the Fatal method returns true.
func IsFatalError(err error) bool {
	if err == nil {
		return false
	}
	err = errors.Cause(err)
	if r, ok := err.(Fataler); ok {
		return r.Fatal()
	}
	return false
}

// NoRetrier is an optional interface for error as to whether the
// operation should not be retried at a high level.
//
// If only NoRetry errors are returned in a sync then the sync won't
// be retried.
//
// This should be returned from Update or Put methods as required
type NoRetrier interface {
	error
	NoRetry() bool
}

// wrappedNoRetryError is an error wrapped so it will satisfy the
// Retrier interface and return true
type wrappedNoRetryError struct {
	error
}

// NoRetry interface
func (err wrappedNoRetryError) NoRetry() bool {
	return true
}

// Check interface
var _ NoRetrier = wrappedNoRetryError{(error)(nil)}

// NoRetryError makes an error which indicates the sync shouldn't be
// retried.
func NoRetryError(err error) error {
	return wrappedNoRetryError{err}
}

// IsNoRetryError returns true if err conforms to the NoRetry
// interface and calling the NoRetry method returns true.
func IsNoRetryError(err error) bool {
	if err == nil {
		return false
	}
	err = errors.Cause(err)
	if r, ok := err.(NoRetrier); ok {
		return r.NoRetry()
	}
	return false
}

// Cause is a souped up errors.Cause which can unwrap some standard
// library errors too.  It returns true if any of the intermediate
// errors had a Timeout() or Temporary() method which returned true.
func Cause(cause error) (retriable bool, err error) {
	err = cause
	for prev := err; err != nil; prev = err {
		// Check for net error Timeout()
		if x, ok := err.(interface {
			Timeout() bool
		}); ok && x.Timeout() {
			retriable = true
		}

		// Check for net error Temporary()
		if x, ok := err.(interface {
			Temporary() bool
		}); ok && x.Temporary() {
			retriable = true
		}

		// Unwrap 1 level if possible
		err = errors.Cause(err)
		if err == prev {
			// Unpack any struct or *struct with a field
			// of name Err which satisfies the error
			// interface.  This includes *url.Error,
			// *net.OpError, *os.SyscallError and many
			// others in the stdlib
			errType := reflect.TypeOf(err)
			errValue := reflect.ValueOf(err)
			if errType.Kind() == reflect.Ptr {
				errType = errType.Elem()
				errValue = errValue.Elem()
			}
			if errType.Kind() == reflect.Struct {
				if errField := errValue.FieldByName("Err"); errField.IsValid() {
					errFieldValue := errField.Interface()
					if newErr, ok := errFieldValue.(error); ok {
						err = newErr
					}
				}
			}
		}
		if err == prev {
			break
		}
	}
	return retriable, err
}

// retriableErrorStrings is a list of phrases which when we find it
// in an an error, we know it is a networking error which should be
// retried.
//
// This is incredibly ugly - if only errors.Cause worked for all
// errors and all errors were exported from the stdlib.
var retriableErrorStrings = []string{
	"use of closed network connection", // internal/poll/fd.go
	"unexpected EOF reading trailer",   // net/http/transfer.go
	"transport connection broken",      // net/http/transport.go
	"http: ContentLength=",             // net/http/transfer.go
}

// Errors which indicate networking errors which should be retried
//
// These are added to in retriable_errors*.go
var retriableErrors = []error{
	io.EOF,
	io.ErrUnexpectedEOF,
}

// ShouldRetry looks at an error and tries to work out if retrying the
// operation that caused it would be a good idea. It returns true if
// the error implements Timeout() or Temporary() or if the error
// indicates a premature closing of the connection.
func ShouldRetry(err error) bool {
	if err == nil {
		return false
	}

	// Find root cause if available
	retriable, err := Cause(err)
	if retriable {
		return true
	}

	// Check if it is a retriable error
	for _, retriableErr := range retriableErrors {
		if err == retriableErr {
			return true
		}
	}

	// Check error strings (yuch!) too
	errString := err.Error()
	for _, phrase := range retriableErrorStrings {
		if strings.Contains(errString, phrase) {
			return true
		}
	}

	return false
}

// ShouldRetryHTTP returns a boolean as to whether this resp deserves.
// It checks to see if the HTTP response code is in the slice
// retryErrorCodes.
func ShouldRetryHTTP(resp *http.Response, retryErrorCodes []int) bool {
	if resp == nil {
		return false
	}
	for _, e := range retryErrorCodes {
		if resp.StatusCode == e {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 fs

import (
	"os"
	"syscall"
)

func syscallPermissions(permissions os.FileMode) (o uint32) {
	// Include r/w/x permission bits.
	o = uint32(permissions & os.ModePerm)

	// Also include setuid/setgid/sticky bits.
	if permissions&os.ModeSetuid != 0 {
		o |= syscall.S_ISUID
	}

	if permissions&os.ModeSetgid != 0 {
		o |= syscall.S_ISGID
	}

	if permissions&os.ModeSticky != 0 {
		o |= syscall.S_ISVTX
	}

	return
}

func (fs *fileSystem) SetPermissions(path string, permissions os.FileMode) error {
	// Open the file without following symlinks.
	fd, err := syscall.Open(path, syscall.O_RDONLY|syscall.O_SYMLINK, 0)
	if err != nil {
		return err
	}

	defer syscall.Close(fd)

	// Call fchmod.
	mode := syscallPermissions(permissions)
	err = syscall.Fchmod(fd, mode)
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>Fixed a bug.<commit_after>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 fs

import (
	"os"
	"syscall"
)

func syscallPermissions(permissions os.FileMode) (o uint32) {
	// Include r/w/x permission bits.
	o = uint32(permissions & os.ModePerm)

	// Also include setuid/setgid/sticky bits.
	if permissions&os.ModeSetuid != 0 {
		o |= syscall.S_ISUID
	}

	if permissions&os.ModeSetgid != 0 {
		o |= syscall.S_ISGID
	}

	if permissions&os.ModeSticky != 0 {
		o |= syscall.S_ISVTX
	}

	return
}

func (fs *fileSystem) SetPermissions(path string, permissions os.FileMode) error {
	// Open the file without following symlinks. Use O_NONBLOCK to allow opening
	// of named pipes without a writer.
	fd, err := syscall.Open(path, syscall.O_NONBLOCK|syscall.O_SYMLINK, 0)
	if err != nil {
		return err
	}

	defer syscall.Close(fd)

	// Call fchmod.
	mode := syscallPermissions(permissions)
	err = syscall.Fchmod(fd, mode)
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package main

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

	"gopkg.in/mgo.v2"
)

// StyleHandler reports this auth backend's "style" attribute. This is reported through cloudpipe
// to API consumers to provide them with a hint about other auth interactions that are possible at
// this endpoint.
func StyleHandler(c *Context, w http.ResponseWriter, r *http.Request) {
	if !MethodOk(w, r, "GET") {
		return
	}

	w.Header().Set("Content-Type", "text/plain")
	fmt.Fprintf(w, "auth-store")
}

// AccountHandler dispatches requests to handlers that manage the /account resource based on
// request method.
func AccountHandler(c *Context, w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "POST":
		CreateHandler(c, w, r)
	default:
		APIError{
			Message: fmt.Sprintf("Unsupported method %s. Only POST is accepted for this resource.",
				r.Method),
		}.Log("").Report(w, http.StatusMethodNotAllowed)
	}
}

// CreateHandler creates and persists a new account based on a username and password. An error is
// returned if the username is not unique. Otherwise, an accepted status is returned.
func CreateHandler(c *Context, w http.ResponseWriter, r *http.Request) {
	type request struct {
		Name     string `json:"name"`
		Password string `json:"password"`
	}

	var req request
	err := json.NewDecoder(r.Body).Decode(&req)
	if err != nil {
		APIError{
			Message: fmt.Sprintf("Unable to parse JSON from your request: %v", err),
		}.Log("").Report(w, http.StatusBadRequest)
		return
	}

	account, err := NewAccount(req.Name, req.Password)
	if err != nil {
		APIError{
			Message: fmt.Sprintf("Unable to create account: %v", err),
		}.Log("").Report(w, http.StatusInternalServerError)
		return
	}

	err = c.Storage.CreateAccount(account)
	if mgo.IsDup(err) {
		APIError{
			Message: fmt.Sprintf(
				`The account name "%s" has already been taken. Please choose another.`,
				req.Name,
			),
		}.Log("").Report(w, http.StatusConflict)
		return
	}
	if err != nil {
		APIError{Message: "Internal storage error."}.Log(req.Name).Report(w, http.StatusInternalServerError)
		return
	}

	w.WriteHeader(http.StatusCreated)
}
<commit_msg>Log successful account creation.<commit_after>package main

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

	log "github.com/Sirupsen/logrus"
	"gopkg.in/mgo.v2"
)

// StyleHandler reports this auth backend's "style" attribute. This is reported through cloudpipe
// to API consumers to provide them with a hint about other auth interactions that are possible at
// this endpoint.
func StyleHandler(c *Context, w http.ResponseWriter, r *http.Request) {
	if !MethodOk(w, r, "GET") {
		return
	}

	w.Header().Set("Content-Type", "text/plain")
	fmt.Fprintf(w, "auth-store")
}

// AccountHandler dispatches requests to handlers that manage the /account resource based on
// request method.
func AccountHandler(c *Context, w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "POST":
		CreateHandler(c, w, r)
	default:
		APIError{
			Message: fmt.Sprintf("Unsupported method %s. Only POST is accepted for this resource.",
				r.Method),
		}.Log("").Report(w, http.StatusMethodNotAllowed)
	}
}

// CreateHandler creates and persists a new account based on a username and password. An error is
// returned if the username is not unique. Otherwise, an accepted status is returned.
func CreateHandler(c *Context, w http.ResponseWriter, r *http.Request) {
	type request struct {
		Name     string `json:"name"`
		Password string `json:"password"`
	}

	var req request
	err := json.NewDecoder(r.Body).Decode(&req)
	if err != nil {
		APIError{
			Message: fmt.Sprintf("Unable to parse JSON from your request: %v", err),
		}.Log("").Report(w, http.StatusBadRequest)
		return
	}

	account, err := NewAccount(req.Name, req.Password)
	if err != nil {
		APIError{
			Message: fmt.Sprintf("Unable to create account: %v", err),
		}.Log("").Report(w, http.StatusInternalServerError)
		return
	}

	err = c.Storage.CreateAccount(account)
	if mgo.IsDup(err) {
		APIError{
			Message: fmt.Sprintf(
				`The account name "%s" has already been taken. Please choose another.`,
				req.Name,
			),
		}.Log("").Report(w, http.StatusConflict)
		return
	}
	if err != nil {
		APIError{Message: "Internal storage error."}.Log(req.Name).Report(w, http.StatusInternalServerError)
		return
	}

	log.WithFields(log.Fields{
		"account": req.Name,
	}).Info("Account created successfully.")

	w.WriteHeader(http.StatusCreated)
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Michael Wendland
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 *
 * 	Authors:
 * 		Michael Wendland <michael@michiwend.com>
 */

package gomusicbrainz

import (
	"encoding/xml"
	"strings"
	"time"
)

// MBID represents a MusicBrainz ID.
type MBID string

// MBCoordinates represents a tuple of latitude,longitude values.
type MBCoordinates struct {
	// TODO maybe use $geolocation library and its generic type.
	Lat string `xml:"latitude"`
	Lng string `xml:"longitude"`
}

// ScoreMap maps addresses of search request results to its scores.
type ScoreMap map[interface{}]int

type ISO31662Code string

// BrainzTime implements XMLUnmarshaler interface and is used to unmarshal the
// XML date fields.
type BrainzTime struct {
	time.Time
}

func (t *BrainzTime) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var v string
	var p time.Time
	var err error
	d.DecodeElement(&v, &start)

	switch strings.Count(v, "-") {
	case 0:
		p, err = time.Parse("2006", v)
	case 1:
		p, err = time.Parse("2006-01", v)
	case 2:
		p, err = time.Parse("2006-01-02", v)
	}

	// TODO handle empty fields

	if err != nil {
		return err
	}
	*t = BrainzTime{p}
	return nil
}

// WS2ListResponse is an abstract common type that provides the Count and Offset
// fields for ervery list response.
type WS2ListResponse struct {
	Count  int `xml:"count,attr"`
	Offset int `xml:"offset,attr"`
}

type Lifespan struct {
	Ended bool       `xml:"ended"`
	Begin BrainzTime `xml:"begin"`
	End   BrainzTime `xml:"end"`
}

// Alias is a type for aliases/misspellings of artists, works, areas, labels
// and places.
type Alias struct {
	Name     string `xml:",chardata"`
	SortName string `xml:"sort-name,attr"`
	Locale   string `xml:"locale,attr"`
	Type     string `xml:"type,attr"`
	Primary  string `xml:"primary,attr"`
}

type LabelInfo struct {
	CatalogNumber string `xml:"catalog-number"`
	Label         Label  `xml:"label"`
}

type Medium struct {
	Format string `xml:"format"`
	//DiscList TODO implement type
	//TrackList TODO implement type
}

type TextRepresentation struct {
	Language string `xml:"language"`
	Script   string `xml:"script"`
}

type ArtistCredit struct {
	NameCredit NameCredit `xml:"name-credit"`
}

type NameCredit struct {
	Artist Artist `xml:"artist"`
}
<commit_msg>missing doc strings<commit_after>/*
 * Copyright (c) 2014 Michael Wendland
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 *
 * 	Authors:
 * 		Michael Wendland <michael@michiwend.com>
 */

package gomusicbrainz

import (
	"encoding/xml"
	"strings"
	"time"
)

// MBID represents a MusicBrainz ID.
type MBID string

// MBCoordinates represents a tuple of latitude,longitude values.
type MBCoordinates struct {
	// TODO maybe use $geolocation library and its generic type.
	Lat string `xml:"latitude"`
	Lng string `xml:"longitude"`
}

// ScoreMap maps addresses of search request results to its scores.
type ScoreMap map[interface{}]int

type ISO31662Code string

// BrainzTime implements XMLUnmarshaler interface and is used to unmarshal the
// XML date fields.
type BrainzTime struct {
	time.Time
}

func (t *BrainzTime) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var v string
	var p time.Time
	var err error
	d.DecodeElement(&v, &start)

	switch strings.Count(v, "-") {
	case 0:
		p, err = time.Parse("2006", v)
	case 1:
		p, err = time.Parse("2006-01", v)
	case 2:
		p, err = time.Parse("2006-01-02", v)
	}

	// TODO handle empty fields

	if err != nil {
		return err
	}
	*t = BrainzTime{p}
	return nil
}

// WS2ListResponse is an abstract common type that provides the Count and Offset
// fields for ervery list response.
type WS2ListResponse struct {
	Count  int `xml:"count,attr"`
	Offset int `xml:"offset,attr"`
}

// Lifespan represents either the life span of a natural person or more
// generally the period of time in which an entity e.g. a Label existed.
type Lifespan struct {
	Ended bool       `xml:"ended"`
	Begin BrainzTime `xml:"begin"`
	End   BrainzTime `xml:"end"`
}

// Alias is a type for aliases/misspellings of artists, works, areas, labels
// and places.
type Alias struct {
	Name     string `xml:",chardata"`
	SortName string `xml:"sort-name,attr"`
	Locale   string `xml:"locale,attr"`
	Type     string `xml:"type,attr"`
	Primary  string `xml:"primary,attr"`
}

type LabelInfo struct {
	CatalogNumber string `xml:"catalog-number"`
	Label         Label  `xml:"label"`
}

// Medium represents one of the physical, separate things you would get when
// you buy something in a record store e.g. CDs, vinyls, etc. Mediums are
// always included in a release. For more information visit
// https://musicbrainz.org/doc/Medium
type Medium struct {
	Format string `xml:"format"`
	//DiscList TODO implement type
	//TrackList TODO implement type
}

type TextRepresentation struct {
	Language string `xml:"language"`
	Script   string `xml:"script"`
}

// ArtistCredit is either used to link multiple artists to one
// release/recording or to credit an artist with a different name.
// Visist https://musicbrainz.org/doc/Artist_Credit for more information.
type ArtistCredit struct {
	NameCredit NameCredit `xml:"name-credit"`
}

type NameCredit struct {
	Artist Artist `xml:"artist"`
}
<|endoftext|>


<commit_before>// Game map functions
package game

import (
	"bufio"
	"encoding/gob"
	"fmt"
	"github.com/nsf/termbox-go"
	"github.com/nsf/tulib"
	"image"
	"log"
	"os"
	"math/rand"
)

type TerrainType uint32
type Direction int

func (d Direction) String() string {
	return fmt.Sprintf("%s", DirTable[d])
}

const (
	MAP_WIDTH  = 256
	MAP_HEIGHT = 256

	T_EMPTY  TerrainType = iota
	T_WALL               // can't pass/see through wall
	T_GROUND             // passable/visible
	T_UNIT

	DIR_UP Direction = iota // player movement instructions
	DIR_DOWN
	DIR_LEFT
	DIR_RIGHT
)

var (
	DirTable = map[Direction]image.Point{
		DIR_UP:    image.Point{0, -1},
		DIR_DOWN:  image.Point{0, 1},
		DIR_LEFT:  image.Point{-1, 0},
		DIR_RIGHT: image.Point{1, 0},
	}

	GLYPH_EMPTY  = termbox.Cell{Ch: ' '}
	GLYPH_WALL   = termbox.Cell{Ch: '#', Fg: termbox.ColorBlack, Bg: termbox.ColorWhite}
	GLYPH_GROUND = termbox.Cell{Ch: '.', Fg: termbox.ColorGreen}
	GLYPH_FLAG   = termbox.Cell{Ch: '%', Fg: termbox.ColorCyan}
	GLYPH_ITEM   = termbox.Cell{Ch: '?', Fg: termbox.ColorCyan}
	GLYPH_HUMAN  = termbox.Cell{Ch: '@'}

	// convert a rune to a terrain square
	glyphTable = map[rune]*Terrain{
		' ': &Terrain{GLYPH_EMPTY, T_EMPTY},
		'#': &Terrain{GLYPH_WALL, T_WALL},
		'.': &Terrain{GLYPH_GROUND, T_GROUND},
		'@': &Terrain{GLYPH_HUMAN, T_UNIT},
	}
)

func init() {
	gob.Register(DIR_UP)
	gob.Register(&MapChunk{})
	gob.Register(&Terrain{})
	gob.Register(T_EMPTY)
}

func (tt *TerrainType) String() string {
	switch *tt {
	case T_EMPTY:
		return "empty"
	case T_WALL:
		return "wall"
	case T_GROUND:
		return "ground"
	case T_UNIT:
		return "unit"
	}

	return "unknown"
}

func GlyphToTerrain(g rune) (t *Terrain, ok bool) {
	t, ok = glyphTable[g]
	if !ok {
		t = glyphTable[' ']
	}
	return
}

type Terrain struct {
	//*GameObject
	Glyph termbox.Cell
	Type  TerrainType
}

func (t Terrain) String() string {
	return fmt.Sprintf("(%c %s)", t.Glyph.Ch, t.Type)
}

func (t *Terrain) Draw(b *tulib.Buffer, pt image.Point) {
	b.Set(pt.X, pt.Y, t.Glyph)
}

func (t *Terrain) IsEmpty() bool {
	return t.Type == T_EMPTY
}

func (t *Terrain) IsWall() bool {
	return t.Type == T_WALL
}

func (t *Terrain) IsGround() bool {
	return t.Type == T_GROUND
}

type MapChunk struct {
	Size        image.Point
	Rect        image.Rectangle
	Locations   [][]*Terrain  // land features
	GameObjects []*GameObject // active game objects
	Players     []*Player     // active players
}

func (mc *MapChunk) String() string {
	return fmt.Sprintf("(%s %s objs %d players %d)", mc.Size, mc.Rect, len(mc.GameObjects), len(mc.Players))
}

func NewMapChunk() *MapChunk {
	ch := MapChunk{Size: image.Pt(MAP_WIDTH, MAP_HEIGHT)}
	ch.Rect = image.Rect(0, 0, MAP_WIDTH, MAP_HEIGHT)

	ch.Locations = make([][]*Terrain, MAP_WIDTH)
	for row := range ch.Locations {
		ch.Locations[row] = make([]*Terrain, MAP_HEIGHT)
	}

	for x := 0; x < MAP_WIDTH; x++ {
		for y := 0; y < MAP_HEIGHT; y++ {
			g, _ := GlyphToTerrain('.')
			ch.Locations[x][y] = g
		}
	}

	return &ch
}

// return true if the map chunk has a cell with coordinates v.X, v.Y
func (mc *MapChunk) HasCell(pt image.Point) bool {
	return pt.In(mc.Rect)
}

// get terrain at v. returns nil, false if it is not present
func (mc *MapChunk) GetTerrain(pt image.Point) (t *Terrain, ok bool) {
	if ok = mc.HasCell(pt); !ok {
		return
	}
	return mc.Locations[pt.X][pt.Y], true
}

func (mc *MapChunk) CheckCollision(gob *GameObject, pos image.Point) bool {
	t, ok := mc.GetTerrain(pos)
	if ok {
		return !t.IsWall()
	}

	return false
}

// Generates an array of (x,y) tuples of open
// spots on the map, called open, and selects
// random(1, len(open))
func (mc *MapChunk) RandCell() image.Point {
	var open []image.Point

	for x := 0; x < MAP_WIDTH; x++ {
		for y := 0; y < MAP_HEIGHT; y++ {
			if !mc.Locations[x][y].IsWall() {
				open = append(open, image.Pt(x, y))
			}
		}
	}

	// choose random location in range or len(open)
	i := rand.Intn(len(open))
	return open[i]
}

func MapChunkFromFile(mapfile string) *MapChunk {
	mfh, err := os.Open(mapfile)
	if err != nil {
		log.Printf("Error loading map chunk file '%s': %s", mapfile, err)
		return nil
	}

	defer mfh.Close()

	r := bufio.NewReader(mfh)

	mc := NewMapChunk()

	for y := 0; y < MAP_HEIGHT; y++ {
		str, err := r.ReadString('\n')
		if err != nil {
			log.Printf("map read error: %s", err)
			return nil
		}

		for x := 0; x < MAP_WIDTH; x++ {
			g, ok := GlyphToTerrain(rune(str[x]))
			if !ok {
				log.Printf("invalid map tile '%c' at %s:%d:%d", str[x], mapfile, y, x)
				return nil
			}

			mc.Locations[x][y] = g
		}
	}

	return mc
}
<commit_msg>Migrated Directions to generic Actions<commit_after>// Game map functions
package game

import (
	"bufio"
	"encoding/gob"
	"fmt"
	"github.com/nsf/termbox-go"
	"github.com/nsf/tulib"
	"image"
	"log"
	"os"
	"math/rand"
)

type TerrainType uint32
type Action int

func (a Action) String() string {
	return fmt.Sprintf("%s", DirTable[a])
}

const (
	MAP_WIDTH  = 256
	MAP_HEIGHT = 256

	T_EMPTY  TerrainType = iota
	T_WALL               // can't pass/see through wall
	T_GROUND             // passable/visible
	T_UNIT

	DIR_UP Action = iota // player movement instructions
	DIR_DOWN
	DIR_LEFT
	DIR_RIGHT

	ACTION_ITEM_PICKUP
	ACTION_ITEM_DROP
	ACTION_ITEM_LIST_INVENTORY
)

var (
	DirTable = map[Action]image.Point{
		DIR_UP:    image.Point{0, -1},
		DIR_DOWN:  image.Point{0, 1},
		DIR_LEFT:  image.Point{-1, 0},
		DIR_RIGHT: image.Point{1, 0},
	}

	GLYPH_EMPTY  = termbox.Cell{Ch: ' '}
	GLYPH_WALL   = termbox.Cell{Ch: '#', Fg: termbox.ColorBlack, Bg: termbox.ColorWhite}
	GLYPH_GROUND = termbox.Cell{Ch: '.', Fg: termbox.ColorGreen}
	GLYPH_FLAG   = termbox.Cell{Ch: '%', Fg: termbox.ColorCyan}
	GLYPH_ITEM   = termbox.Cell{Ch: '?', Fg: termbox.ColorCyan}
	GLYPH_HUMAN  = termbox.Cell{Ch: '@'}

	// convert a rune to a terrain square
	glyphTable = map[rune]*Terrain{
		' ': &Terrain{GLYPH_EMPTY, T_EMPTY},
		'#': &Terrain{GLYPH_WALL, T_WALL},
		'.': &Terrain{GLYPH_GROUND, T_GROUND},
		'@': &Terrain{GLYPH_HUMAN, T_UNIT},
	}
)

func init() {
	gob.Register(DIR_UP)
	gob.Register(&MapChunk{})
	gob.Register(&Terrain{})
	gob.Register(T_EMPTY)
}

func (tt *TerrainType) String() string {
	switch *tt {
	case T_EMPTY:
		return "empty"
	case T_WALL:
		return "wall"
	case T_GROUND:
		return "ground"
	case T_UNIT:
		return "unit"
	}

	return "unknown"
}

func GlyphToTerrain(g rune) (t *Terrain, ok bool) {
	t, ok = glyphTable[g]
	if !ok {
		t = glyphTable[' ']
	}
	return
}

type Terrain struct {
	//*GameObject
	Glyph termbox.Cell
	Type  TerrainType
}

func (t Terrain) String() string {
	return fmt.Sprintf("(%c %s)", t.Glyph.Ch, t.Type)
}

func (t *Terrain) Draw(b *tulib.Buffer, pt image.Point) {
	b.Set(pt.X, pt.Y, t.Glyph)
}

func (t *Terrain) IsEmpty() bool {
	return t.Type == T_EMPTY
}

func (t *Terrain) IsWall() bool {
	return t.Type == T_WALL
}

func (t *Terrain) IsGround() bool {
	return t.Type == T_GROUND
}

type MapChunk struct {
	Size        image.Point
	Rect        image.Rectangle
	Locations   [][]*Terrain  // land features
	GameObjects []*GameObject // active game objects
	Players     []*Player     // active players
}

func (mc *MapChunk) String() string {
	return fmt.Sprintf("(%s %s objs %d players %d)", mc.Size, mc.Rect, len(mc.GameObjects), len(mc.Players))
}

func NewMapChunk() *MapChunk {
	ch := MapChunk{Size: image.Pt(MAP_WIDTH, MAP_HEIGHT)}
	ch.Rect = image.Rect(0, 0, MAP_WIDTH, MAP_HEIGHT)

	ch.Locations = make([][]*Terrain, MAP_WIDTH)
	for row := range ch.Locations {
		ch.Locations[row] = make([]*Terrain, MAP_HEIGHT)
	}

	for x := 0; x < MAP_WIDTH; x++ {
		for y := 0; y < MAP_HEIGHT; y++ {
			g, _ := GlyphToTerrain('.')
			ch.Locations[x][y] = g
		}
	}

	return &ch
}

// return true if the map chunk has a cell with coordinates v.X, v.Y
func (mc *MapChunk) HasCell(pt image.Point) bool {
	return pt.In(mc.Rect)
}

// get terrain at v. returns nil, false if it is not present
func (mc *MapChunk) GetTerrain(pt image.Point) (t *Terrain, ok bool) {
	if ok = mc.HasCell(pt); !ok {
		return
	}
	return mc.Locations[pt.X][pt.Y], true
}

func (mc *MapChunk) CheckCollision(gob *GameObject, pos image.Point) bool {
	t, ok := mc.GetTerrain(pos)
	if ok {
		return !t.IsWall()
	}

	return false
}

// Generates an array of (x,y) tuples of open
// spots on the map, called open, and selects
// random(1, len(open))
func (mc *MapChunk) RandCell() image.Point {
	var open []image.Point

	for x := 0; x < MAP_WIDTH; x++ {
		for y := 0; y < MAP_HEIGHT; y++ {
			if !mc.Locations[x][y].IsWall() {
				open = append(open, image.Pt(x, y))
			}
		}
	}

	// choose random location in range or len(open)
	i := rand.Intn(len(open))
	return open[i]
}

func MapChunkFromFile(mapfile string) *MapChunk {
	mfh, err := os.Open(mapfile)
	if err != nil {
		log.Printf("Error loading map chunk file '%s': %s", mapfile, err)
		return nil
	}

	defer mfh.Close()

	r := bufio.NewReader(mfh)

	mc := NewMapChunk()

	for y := 0; y < MAP_HEIGHT; y++ {
		str, err := r.ReadString('\n')
		if err != nil {
			log.Printf("map read error: %s", err)
			return nil
		}

		for x := 0; x < MAP_WIDTH; x++ {
			g, ok := GlyphToTerrain(rune(str[x]))
			if !ok {
				log.Printf("invalid map tile '%c' at %s:%d:%d", str[x], mapfile, y, x)
				return nil
			}

			mc.Locations[x][y] = g
		}
	}

	return mc
}
<|endoftext|>


<commit_before>package perigee

import (
	"bytes"
	"fmt"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
)

func TestNormal(t *testing.T) {
	handler := http.HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			w.Write([]byte("testing"))
		})
	ts := httptest.NewServer(handler)
	defer ts.Close()

	response, err := Request("GET", ts.URL, Options{})
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}
	if response.StatusCode != 200 {
		t.Fatalf("response code %d is not 200", response.StatusCode)
	}
}

func TestOKCodes(t *testing.T) {
	expectCode := 201
	handler := http.HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			w.WriteHeader(expectCode)
			w.Write([]byte("testing"))
		})
	ts := httptest.NewServer(handler)
	defer ts.Close()

	options := Options{
		OkCodes: []int{expectCode},
	}
	results, err := Request("GET", ts.URL, options)
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}
	if results.StatusCode != expectCode {
		t.Fatalf("response code %d is not %d", results.StatusCode, expectCode)
	}
}

func TestLocation(t *testing.T) {
	newLocation := "http://www.example.com"
	handler := http.HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			w.Header().Set("Location", newLocation)
			w.Write([]byte("testing"))
		})
	ts := httptest.NewServer(handler)
	defer ts.Close()

	response, err := Request("GET", ts.URL, Options{})
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	location, err := response.HttpResponse.Location()
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if location.String() != newLocation {
		t.Fatalf("location returned \"%s\" is not \"%s\"", location.String(), newLocation)
	}
}

func TestHeaders(t *testing.T) {
	newLocation := "http://www.example.com"
	handler := http.HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			w.Header().Set("Location", newLocation)
			w.Write([]byte("testing"))
		})
	ts := httptest.NewServer(handler)
	defer ts.Close()

	response, err := Request("GET", ts.URL, Options{})
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	location := response.HttpResponse.Header.Get("Location")
	if location == "" {
		t.Fatalf("Location should not empty")
	}

	if location != newLocation {
		t.Fatalf("location returned \"%s\" is not \"%s\"", location, newLocation)
	}
}

func TestCustomHeaders(t *testing.T) {
	var contentType, accept, contentLength string

	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		m := map[string][]string(r.Header)
		contentType = m["Content-Type"][0]
		accept = m["Accept"][0]
		contentLength = m["Content-Length"][0]
	})
	ts := httptest.NewServer(handler)
	defer ts.Close()

	_, err := Request("GET", ts.URL, Options{
		ContentLength: 5,
		ContentType:   "x-application/vb",
		Accept:        "x-application/c",
		ReqBody:       strings.NewReader("Hello"),
	})
	if err != nil {
		t.Fatalf(err.Error())
	}

	if contentType != "x-application/vb" {
		t.Fatalf("I expected x-application/vb; got ", contentType)
	}

	if contentLength != "5" {
		t.Fatalf("I expected 5 byte content length; got ", contentLength)
	}

	if accept != "x-application/c" {
		t.Fatalf("I expected x-application/c; got ", accept)
	}
}

func TestJson(t *testing.T) {
	newLocation := "http://www.example.com"
	jsonBytes := []byte(`{"foo": {"bar": "baz"}}`)
	handler := http.HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			w.Header().Set("Location", newLocation)
			w.Write(jsonBytes)
		})
	ts := httptest.NewServer(handler)
	defer ts.Close()

	type Data struct {
		Foo struct {
			Bar string `json:"bar"`
		} `json:"foo"`
	}
	var data Data

	response, err := Request("GET", ts.URL, Options{Results: &data})
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if bytes.Compare(jsonBytes, response.JsonResult) != 0 {
		t.Fatalf("json returned \"%s\" is not \"%s\"", response.JsonResult, jsonBytes)
	}

	if data.Foo.Bar != "baz" {
		t.Fatalf("Results returned %v", data)
	}
}

func TestSetHeaders(t *testing.T) {
	var wasCalled bool
	handler := http.HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			w.Write([]byte("Hi"))
		})
	ts := httptest.NewServer(handler)
	defer ts.Close()

	_, err := Request("GET", ts.URL, Options{
		SetHeaders: func(r *http.Request) error {
			wasCalled = true
			return nil
		},
	})

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

	if !wasCalled {
		t.Fatal("I expected header setter callback to be called, but it wasn't")
	}

	myError := fmt.Errorf("boo")

	_, err = Request("GET", ts.URL, Options{
		SetHeaders: func(r *http.Request) error {
			return myError
		},
	})

	if err != myError {
		t.Fatal("I expected errors to propegate back to the caller.")
	}
}

func TestBodilessMethodsAreSentWithoutContentHeaders(t *testing.T) {
	var h map[string][]string

	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		h = r.Header
	})
	ts := httptest.NewServer(handler)
	defer ts.Close()

	_, err := Request("GET", ts.URL, Options{})
	if err != nil {
		t.Fatalf(err.Error())
	}

	if len(h["Content-Type"]) != 0 {
		t.Fatalf("I expected nothing for Content-Type but got ", h["Content-Type"])
	}

	if len(h["Content-Length"]) != 0 {
		t.Fatalf("I expected nothing for Content-Length but got ", h["Content-Type"])
	}
}
<commit_msg>Fixing small mistake<commit_after>package perigee

import (
	"bytes"
	"fmt"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
)

func TestNormal(t *testing.T) {
	handler := http.HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			w.Write([]byte("testing"))
		})
	ts := httptest.NewServer(handler)
	defer ts.Close()

	response, err := Request("GET", ts.URL, Options{})
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}
	if response.StatusCode != 200 {
		t.Fatalf("response code %d is not 200", response.StatusCode)
	}
}

func TestOKCodes(t *testing.T) {
	expectCode := 201
	handler := http.HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			w.WriteHeader(expectCode)
			w.Write([]byte("testing"))
		})
	ts := httptest.NewServer(handler)
	defer ts.Close()

	options := Options{
		OkCodes: []int{expectCode},
	}
	results, err := Request("GET", ts.URL, options)
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}
	if results.StatusCode != expectCode {
		t.Fatalf("response code %d is not %d", results.StatusCode, expectCode)
	}
}

func TestLocation(t *testing.T) {
	newLocation := "http://www.example.com"
	handler := http.HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			w.Header().Set("Location", newLocation)
			w.Write([]byte("testing"))
		})
	ts := httptest.NewServer(handler)
	defer ts.Close()

	response, err := Request("GET", ts.URL, Options{})
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	location, err := response.HttpResponse.Location()
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if location.String() != newLocation {
		t.Fatalf("location returned \"%s\" is not \"%s\"", location.String(), newLocation)
	}
}

func TestHeaders(t *testing.T) {
	newLocation := "http://www.example.com"
	handler := http.HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			w.Header().Set("Location", newLocation)
			w.Write([]byte("testing"))
		})
	ts := httptest.NewServer(handler)
	defer ts.Close()

	response, err := Request("GET", ts.URL, Options{})
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	location := response.HttpResponse.Header.Get("Location")
	if location == "" {
		t.Fatalf("Location should not empty")
	}

	if location != newLocation {
		t.Fatalf("location returned \"%s\" is not \"%s\"", location, newLocation)
	}
}

func TestCustomHeaders(t *testing.T) {
	var contentType, accept, contentLength string

	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		m := map[string][]string(r.Header)
		contentType = m["Content-Type"][0]
		accept = m["Accept"][0]
		contentLength = m["Content-Length"][0]
	})
	ts := httptest.NewServer(handler)
	defer ts.Close()

	_, err := Request("GET", ts.URL, Options{
		ContentLength: 5,
		ContentType:   "x-application/vb",
		Accept:        "x-application/c",
		ReqBody:       strings.NewReader("Hello"),
	})
	if err != nil {
		t.Fatalf(err.Error())
	}

	if contentType != "x-application/vb" {
		t.Fatalf("I expected x-application/vb; got ", contentType)
	}

	if contentLength != "5" {
		t.Fatalf("I expected 5 byte content length; got ", contentLength)
	}

	if accept != "x-application/c" {
		t.Fatalf("I expected x-application/c; got ", accept)
	}
}

func TestJson(t *testing.T) {
	newLocation := "http://www.example.com"
	jsonBytes := []byte(`{"foo": {"bar": "baz"}}`)
	handler := http.HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			w.Header().Set("Location", newLocation)
			w.Write(jsonBytes)
		})
	ts := httptest.NewServer(handler)
	defer ts.Close()

	type Data struct {
		Foo struct {
			Bar string `json:"bar"`
		} `json:"foo"`
	}
	var data Data

	response, err := Request("GET", ts.URL, Options{Results: &data})
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if bytes.Compare(jsonBytes, response.JsonResult) != 0 {
		t.Fatalf("json returned \"%s\" is not \"%s\"", response.JsonResult, jsonBytes)
	}

	if data.Foo.Bar != "baz" {
		t.Fatalf("Results returned %v", data)
	}
}

func TestSetHeaders(t *testing.T) {
	var wasCalled bool
	handler := http.HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			w.Write([]byte("Hi"))
		})
	ts := httptest.NewServer(handler)
	defer ts.Close()

	_, err := Request("GET", ts.URL, Options{
		SetHeaders: func(r *http.Request) error {
			wasCalled = true
			return nil
		},
	})

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

	if !wasCalled {
		t.Fatal("I expected header setter callback to be called, but it wasn't")
	}

	myError := fmt.Errorf("boo")

	_, err = Request("GET", ts.URL, Options{
		SetHeaders: func(r *http.Request) error {
			return myError
		},
	})

	if err != myError {
		t.Fatal("I expected errors to propegate back to the caller.")
	}
}

func TestBodilessMethodsAreSentWithoutContentHeaders(t *testing.T) {
	var h map[string][]string

	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		h = r.Header
	})
	ts := httptest.NewServer(handler)
	defer ts.Close()

	_, err := Request("GET", ts.URL, Options{})
	if err != nil {
		t.Fatalf(err.Error())
	}

	if len(h["Content-Type"]) != 0 {
		t.Fatalf("I expected nothing for Content-Type but got ", h["Content-Type"])
	}

	if len(h["Content-Length"]) != 0 {
		t.Fatalf("I expected nothing for Content-Length but got ", h["Content-Length"])
	}
}
<|endoftext|>