<commit_before>package readline

import (
	"bytes"
	"fmt"
	"strings"
	"unicode"

	"github.com/atotto/clipboard"
	"github.com/zetamatta/go-getch"
)

func KeyFuncPass(this *Buffer) Result {
	return CONTINUE
}

func KeyFuncEnter(this *Buffer) Result { // Ctrl-M
	return ENTER
}

func KeyFuncIntr(this *Buffer) Result { // Ctrl-C
	this.Length = 0
	this.Cursor = 0
	this.ViewStart = 0
	return ENTER
}

func KeyFuncHead(this *Buffer) Result { // Ctrl-A
	Backspace(this.GetWidthBetween(this.ViewStart, this.Cursor))
	this.Cursor = 0
	this.ViewStart = 0
	this.Repaint(0, 1)
	return CONTINUE
}

func KeyFuncBackword(this *Buffer) Result { // Ctrl-B
	if this.Cursor <= 0 {
		return CONTINUE
	}
	this.Cursor--
	if this.Cursor < this.ViewStart {
		this.ViewStart--
		this.Repaint(this.Cursor, 1)
	} else {
		Backspace(GetCharWidth(this.Buffer[this.Cursor]))
	}
	return CONTINUE
}

func KeyFuncTail(this *Buffer) Result { // Ctrl-E
	allength := this.GetWidthBetween(this.ViewStart, this.Length)
	if allength < this.ViewWidth() {
		for ; this.Cursor < this.Length; this.Cursor++ {
			PutRune(this.Buffer[this.Cursor])
		}
	} else {
		fmt.Fprint(Console, "\a")
		Backspace(this.GetWidthBetween(this.ViewStart, this.Cursor))
		this.ViewStart = this.Length - 1
		w := GetCharWidth(this.Buffer[this.ViewStart])
		for {
			if this.ViewStart <= 0 {
				break
			}
			w_ := w + GetCharWidth(this.Buffer[this.ViewStart-1])
			if w_ >= this.ViewWidth() {
				break
			}
			w = w_
			this.ViewStart--
		}
		for this.Cursor = this.ViewStart; this.Cursor < this.Length; this.Cursor++ {
			PutRune(this.Buffer[this.Cursor])
		}
	}
	return CONTINUE
}

func KeyFuncForward(this *Buffer) Result { // Ctrl-F
	if this.Cursor >= this.Length {
		return CONTINUE
	}
	w := this.GetWidthBetween(this.ViewStart, this.Cursor+1)
	if w < this.ViewWidth() {
		// No Scroll
		PutRune(this.Buffer[this.Cursor])
	} else {
		// Right Scroll
		Backspace(this.GetWidthBetween(this.ViewStart, this.Cursor))
		if GetCharWidth(this.Buffer[this.Cursor]) > GetCharWidth(this.Buffer[this.ViewStart]) {
			this.ViewStart++
		}
		this.ViewStart++
		for i := this.ViewStart; i <= this.Cursor; i++ {
			PutRune(this.Buffer[i])
		}
		Eraseline()
	}
	this.Cursor++
	return CONTINUE
}

func KeyFuncBackSpace(this *Buffer) Result { // Backspace
	if this.Cursor > 0 {
		this.Cursor--
		delw := this.Delete(this.Cursor, 1)
		if this.Cursor >= this.ViewStart {
			Backspace(delw)
		} else {
			this.ViewStart = this.Cursor
		}
		this.Repaint(this.Cursor, delw)
	}
	return CONTINUE
}

func KeyFuncDelete(this *Buffer) Result { // Del
	delw := this.Delete(this.Cursor, 1)
	this.Repaint(this.Cursor, delw)
	return CONTINUE
}

func KeyFuncDeleteOrAbort(this *Buffer) Result { // Ctrl-D
	if this.Length > 0 {
		return KeyFuncDelete(this)
	} else {
		return ABORT
	}
}

func KeyFuncInsertSelf(this *Buffer) Result {
	ch := this.Unicode
	this.Insert(this.Cursor, []rune{ch})

	w := this.GetWidthBetween(this.ViewStart, this.Cursor)
	w1 := GetCharWidth(ch)
	if w+w1 >= this.ViewWidth() {
		// scroll left
		Backspace(w)
		this.Cursor++
		this.ResetViewStart()
		for i := this.ViewStart; i < this.Cursor; i++ {
			PutRune(this.Buffer[i])
		}
		Eraseline()
	} else {
		this.Repaint(this.Cursor, -w1)
		this.Cursor++
	}
	return CONTINUE
}

func KeyFuncInsertReport(this *Buffer) Result {
	this.InsertAndRepaint(fmt.Sprintf("[%X]", this.Unicode))
	return CONTINUE
}

func KeyFuncClearAfter(this *Buffer) Result {
	var killbuf bytes.Buffer
	for j := this.Cursor; j < this.Length; j++ {
		killbuf.WriteRune(this.Buffer[j])
	}
	clipboard.WriteAll(killbuf.String())

	Eraseline()
	this.Length = this.Cursor
	return CONTINUE
}

func KeyFuncClear(this *Buffer) Result {
	width := this.GetWidthBetween(this.ViewStart, this.Cursor)
	Backspace(width)
	Eraseline()
	this.Length = 0
	this.Cursor = 0
	this.ViewStart = 0
	return CONTINUE
}

func KeyFuncWordRubout(this *Buffer) Result {
	org_cursor := this.Cursor
	for this.Cursor > 0 && unicode.IsSpace(this.Buffer[this.Cursor-1]) {
		this.Cursor--
	}
	i := this.CurrentWordTop()
	var killbuf bytes.Buffer
	for j := i; j < org_cursor; j++ {
		killbuf.WriteRune(this.Buffer[j])
	}
	clipboard.WriteAll(killbuf.String())
	keta := this.Delete(i, org_cursor-i)
	if i >= this.ViewStart {
		Backspace(keta)
	} else {
		Backspace(this.GetWidthBetween(this.ViewStart, org_cursor))
	}
	this.Cursor = i
	this.Repaint(i, keta)
	return CONTINUE
}

func KeyFuncClearBefore(this *Buffer) Result {
	keta := this.GetWidthBetween(this.ViewStart, this.Cursor)
	var killbuf bytes.Buffer
	for i := 0; i < this.Cursor; i++ {
		killbuf.WriteRune(this.Buffer[i])
	}
	clipboard.WriteAll(killbuf.String())
	this.Delete(0, this.Cursor)
	Backspace(keta)
	this.Cursor = 0
	this.ViewStart = 0
	this.Repaint(0, keta)
	return CONTINUE
}

func KeyFuncCLS(this *Buffer) Result {
	fmt.Fprint(Console, "\x1B[1;1H\x1B[2J")
	this.RepaintAll()
	return CONTINUE
}

func KeyFuncRepaintOnNewline(this *Buffer) Result {
	fmt.Fprint(Console, "\n")
	this.RepaintAll()
	return CONTINUE
}

func KeyFuncQuotedInsert(this *Buffer) Result {
	fmt.Fprint(Console, CURSOR_ON)
	defer fmt.Fprint(Console, CURSOR_OFF)
	for {
		e := getch.All()
		if e.Key != nil && e.Key.Rune != 0 {
			this.Unicode = e.Key.Rune
			return KeyFuncInsertSelf(this)
		}
	}
}

func KeyFuncPaste(this *Buffer) Result {
	text, err := clipboard.ReadAll()
	if err != nil {
		return CONTINUE
	}
	text = strings.Replace(text, "\n", " ", -1)
	text = strings.Replace(text, "\r", "", -1)
	text = strings.Replace(text, "\t", " ", -1)
	this.InsertAndRepaint(text)
	return CONTINUE
}

func KeyFuncPasteQuote(this *Buffer) Result {
	text, err := clipboard.ReadAll()
	if err != nil {
		return CONTINUE
	}
	text = strings.Replace(text, "\n", " ", -1)
	text = strings.Replace(text, "\r", "", -1)
	text = strings.Replace(text, "\t", " ", -1)
	if strings.IndexRune(text, ' ') >= 0 &&
		!strings.HasPrefix(text, `"`) {
		text = `"` + strings.Replace(text, `"`, `""`, -1) + `"`
	}
	this.InsertAndRepaint(text)
	return CONTINUE
}

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

func KeyFuncSwapChar(this *Buffer) Result {
	if this.Length == this.Cursor {
		if this.Cursor < 2 {
			return CONTINUE
		}
		this.Buffer[this.Cursor-2], this.Buffer[this.Cursor-1] = this.Buffer[this.Cursor-1], this.Buffer[this.Cursor-2]

		redrawStart := maxInt(this.Cursor-2, this.ViewStart)
		Backspace(this.GetWidthBetween(redrawStart, this.Cursor))
		for i := redrawStart; i < this.Cursor; i++ {
			PutRune(this.Buffer[i])
		}
	} else {
		if this.Cursor < 1 {
			return CONTINUE
		}

		w := this.GetWidthBetween(this.ViewStart, this.Cursor+1)
		this.Buffer[this.Cursor-1], this.Buffer[this.Cursor] = this.Buffer[this.Cursor], this.Buffer[this.Cursor-1]
		if w >= this.ViewWidth() {
			// cursor move right and scroll
			w_1 := w - GetCharWidth(this.Buffer[this.Cursor])
			Backspace(w_1)
			this.ViewStart++
			for i := this.ViewStart; i <= this.Cursor; i++ {
				PutRune(this.Buffer[i])
			}
		} else {
			// no neccesary to scroll
			redrawStart := maxInt(this.Cursor-1, this.ViewStart)
			Backspace(this.GetWidthBetween(redrawStart, this.Cursor))
			for i := redrawStart; i <= this.Cursor; i++ {
				PutRune(this.Buffer[i])
			}
		}
		this.Cursor++
	}
	return CONTINUE
}
<commit_msg>readline: paste control-charactors as is (stop converting to space)<commit_after>package readline

import (
	"bytes"
	"fmt"
	"strings"
	"unicode"

	"github.com/atotto/clipboard"
	"github.com/zetamatta/go-getch"
)

func KeyFuncPass(this *Buffer) Result {
	return CONTINUE
}

func KeyFuncEnter(this *Buffer) Result { // Ctrl-M
	return ENTER
}

func KeyFuncIntr(this *Buffer) Result { // Ctrl-C
	this.Length = 0
	this.Cursor = 0
	this.ViewStart = 0
	return ENTER
}

func KeyFuncHead(this *Buffer) Result { // Ctrl-A
	Backspace(this.GetWidthBetween(this.ViewStart, this.Cursor))
	this.Cursor = 0
	this.ViewStart = 0
	this.Repaint(0, 1)
	return CONTINUE
}

func KeyFuncBackword(this *Buffer) Result { // Ctrl-B
	if this.Cursor <= 0 {
		return CONTINUE
	}
	this.Cursor--
	if this.Cursor < this.ViewStart {
		this.ViewStart--
		this.Repaint(this.Cursor, 1)
	} else {
		Backspace(GetCharWidth(this.Buffer[this.Cursor]))
	}
	return CONTINUE
}

func KeyFuncTail(this *Buffer) Result { // Ctrl-E
	allength := this.GetWidthBetween(this.ViewStart, this.Length)
	if allength < this.ViewWidth() {
		for ; this.Cursor < this.Length; this.Cursor++ {
			PutRune(this.Buffer[this.Cursor])
		}
	} else {
		fmt.Fprint(Console, "\a")
		Backspace(this.GetWidthBetween(this.ViewStart, this.Cursor))
		this.ViewStart = this.Length - 1
		w := GetCharWidth(this.Buffer[this.ViewStart])
		for {
			if this.ViewStart <= 0 {
				break
			}
			w_ := w + GetCharWidth(this.Buffer[this.ViewStart-1])
			if w_ >= this.ViewWidth() {
				break
			}
			w = w_
			this.ViewStart--
		}
		for this.Cursor = this.ViewStart; this.Cursor < this.Length; this.Cursor++ {
			PutRune(this.Buffer[this.Cursor])
		}
	}
	return CONTINUE
}

func KeyFuncForward(this *Buffer) Result { // Ctrl-F
	if this.Cursor >= this.Length {
		return CONTINUE
	}
	w := this.GetWidthBetween(this.ViewStart, this.Cursor+1)
	if w < this.ViewWidth() {
		// No Scroll
		PutRune(this.Buffer[this.Cursor])
	} else {
		// Right Scroll
		Backspace(this.GetWidthBetween(this.ViewStart, this.Cursor))
		if GetCharWidth(this.Buffer[this.Cursor]) > GetCharWidth(this.Buffer[this.ViewStart]) {
			this.ViewStart++
		}
		this.ViewStart++
		for i := this.ViewStart; i <= this.Cursor; i++ {
			PutRune(this.Buffer[i])
		}
		Eraseline()
	}
	this.Cursor++
	return CONTINUE
}

func KeyFuncBackSpace(this *Buffer) Result { // Backspace
	if this.Cursor > 0 {
		this.Cursor--
		delw := this.Delete(this.Cursor, 1)
		if this.Cursor >= this.ViewStart {
			Backspace(delw)
		} else {
			this.ViewStart = this.Cursor
		}
		this.Repaint(this.Cursor, delw)
	}
	return CONTINUE
}

func KeyFuncDelete(this *Buffer) Result { // Del
	delw := this.Delete(this.Cursor, 1)
	this.Repaint(this.Cursor, delw)
	return CONTINUE
}

func KeyFuncDeleteOrAbort(this *Buffer) Result { // Ctrl-D
	if this.Length > 0 {
		return KeyFuncDelete(this)
	} else {
		return ABORT
	}
}

func KeyFuncInsertSelf(this *Buffer) Result {
	ch := this.Unicode
	this.Insert(this.Cursor, []rune{ch})

	w := this.GetWidthBetween(this.ViewStart, this.Cursor)
	w1 := GetCharWidth(ch)
	if w+w1 >= this.ViewWidth() {
		// scroll left
		Backspace(w)
		this.Cursor++
		this.ResetViewStart()
		for i := this.ViewStart; i < this.Cursor; i++ {
			PutRune(this.Buffer[i])
		}
		Eraseline()
	} else {
		this.Repaint(this.Cursor, -w1)
		this.Cursor++
	}
	return CONTINUE
}

func KeyFuncInsertReport(this *Buffer) Result {
	this.InsertAndRepaint(fmt.Sprintf("[%X]", this.Unicode))
	return CONTINUE
}

func KeyFuncClearAfter(this *Buffer) Result {
	var killbuf bytes.Buffer
	for j := this.Cursor; j < this.Length; j++ {
		killbuf.WriteRune(this.Buffer[j])
	}
	clipboard.WriteAll(killbuf.String())

	Eraseline()
	this.Length = this.Cursor
	return CONTINUE
}

func KeyFuncClear(this *Buffer) Result {
	width := this.GetWidthBetween(this.ViewStart, this.Cursor)
	Backspace(width)
	Eraseline()
	this.Length = 0
	this.Cursor = 0
	this.ViewStart = 0
	return CONTINUE
}

func KeyFuncWordRubout(this *Buffer) Result {
	org_cursor := this.Cursor
	for this.Cursor > 0 && unicode.IsSpace(this.Buffer[this.Cursor-1]) {
		this.Cursor--
	}
	i := this.CurrentWordTop()
	var killbuf bytes.Buffer
	for j := i; j < org_cursor; j++ {
		killbuf.WriteRune(this.Buffer[j])
	}
	clipboard.WriteAll(killbuf.String())
	keta := this.Delete(i, org_cursor-i)
	if i >= this.ViewStart {
		Backspace(keta)
	} else {
		Backspace(this.GetWidthBetween(this.ViewStart, org_cursor))
	}
	this.Cursor = i
	this.Repaint(i, keta)
	return CONTINUE
}

func KeyFuncClearBefore(this *Buffer) Result {
	keta := this.GetWidthBetween(this.ViewStart, this.Cursor)
	var killbuf bytes.Buffer
	for i := 0; i < this.Cursor; i++ {
		killbuf.WriteRune(this.Buffer[i])
	}
	clipboard.WriteAll(killbuf.String())
	this.Delete(0, this.Cursor)
	Backspace(keta)
	this.Cursor = 0
	this.ViewStart = 0
	this.Repaint(0, keta)
	return CONTINUE
}

func KeyFuncCLS(this *Buffer) Result {
	fmt.Fprint(Console, "\x1B[1;1H\x1B[2J")
	this.RepaintAll()
	return CONTINUE
}

func KeyFuncRepaintOnNewline(this *Buffer) Result {
	fmt.Fprint(Console, "\n")
	this.RepaintAll()
	return CONTINUE
}

func KeyFuncQuotedInsert(this *Buffer) Result {
	fmt.Fprint(Console, CURSOR_ON)
	defer fmt.Fprint(Console, CURSOR_OFF)
	for {
		e := getch.All()
		if e.Key != nil && e.Key.Rune != 0 {
			this.Unicode = e.Key.Rune
			return KeyFuncInsertSelf(this)
		}
	}
}

func KeyFuncPaste(this *Buffer) Result {
	text, err := clipboard.ReadAll()
	if err != nil {
		return CONTINUE
	}
	this.InsertAndRepaint(text)
	return CONTINUE
}

func KeyFuncPasteQuote(this *Buffer) Result {
	text, err := clipboard.ReadAll()
	if err != nil {
		return CONTINUE
	}
	if strings.IndexRune(text, ' ') >= 0 &&
		!strings.HasPrefix(text, `"`) {
		text = `"` + strings.Replace(text, `"`, `""`, -1) + `"`
	}
	this.InsertAndRepaint(text)
	return CONTINUE
}

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

func KeyFuncSwapChar(this *Buffer) Result {
	if this.Length == this.Cursor {
		if this.Cursor < 2 {
			return CONTINUE
		}
		this.Buffer[this.Cursor-2], this.Buffer[this.Cursor-1] = this.Buffer[this.Cursor-1], this.Buffer[this.Cursor-2]

		redrawStart := maxInt(this.Cursor-2, this.ViewStart)
		Backspace(this.GetWidthBetween(redrawStart, this.Cursor))
		for i := redrawStart; i < this.Cursor; i++ {
			PutRune(this.Buffer[i])
		}
	} else {
		if this.Cursor < 1 {
			return CONTINUE
		}

		w := this.GetWidthBetween(this.ViewStart, this.Cursor+1)
		this.Buffer[this.Cursor-1], this.Buffer[this.Cursor] = this.Buffer[this.Cursor], this.Buffer[this.Cursor-1]
		if w >= this.ViewWidth() {
			// cursor move right and scroll
			w_1 := w - GetCharWidth(this.Buffer[this.Cursor])
			Backspace(w_1)
			this.ViewStart++
			for i := this.ViewStart; i <= this.Cursor; i++ {
				PutRune(this.Buffer[i])
			}
		} else {
			// no neccesary to scroll
			redrawStart := maxInt(this.Cursor-1, this.ViewStart)
			Backspace(this.GetWidthBetween(redrawStart, this.Cursor))
			for i := redrawStart; i <= this.Cursor; i++ {
				PutRune(this.Buffer[i])
			}
		}
		this.Cursor++
	}
	return CONTINUE
}
<|endoftext|>


<commit_before>package record

import (
	"encoding/json"
	"io"
	"strings"
	"testing"

	ch "github.com/BatchLabs/charlatan"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func testJSONDecoder() *json.Decoder {
	return json.NewDecoder(strings.NewReader(`
	{
		"name": "Michel",
		"b": true,
		"age": 92,
		"n": null,
		"a": [],
		"we":{"need": {"to": {"go": {"deeper": 1, "a": "d"}}}}
	}
	`))
}

func TestFindUnexistingField(t *testing.T) {
	r, err := NewJSONRecordFromDecoder(testJSONDecoder())
	require.Nil(t, err)
	require.NotNil(t, r)

	_, err = r.Find(ch.NewField("yolo"))
	assert.NotNil(t, err)
}

func TestFindNotAConstField(t *testing.T) {
	r, err := NewJSONRecordFromDecoder(testJSONDecoder())
	require.Nil(t, err)
	require.NotNil(t, r)

	_, err = r.Find(ch.NewField("we"))
	assert.NotNil(t, err)

	_, err = r.Find(ch.NewField("a"))
	assert.NotNil(t, err)
}

func TestFindTopLevelStringField(t *testing.T) {
	r, err := NewJSONRecordFromDecoder(testJSONDecoder())
	require.Nil(t, err)
	require.NotNil(t, r)

	c, err := r.Find(ch.NewField("name"))
	require.Nil(t, err)
	require.NotNil(t, c)

	assert.True(t, c.IsString())
	assert.Equal(t, "Michel", c.AsString())
}

func TestFindTopLevelIntField(t *testing.T) {
	r, err := NewJSONRecordFromDecoder(testJSONDecoder())
	require.Nil(t, err)
	require.NotNil(t, r)

	c, err := r.Find(ch.NewField("age"))
	require.Nil(t, err)
	require.NotNil(t, c)

	assert.True(t, c.IsNumeric())
	assert.Equal(t, int64(92), c.AsInt())
}

func TestFindTopLevelBoolField(t *testing.T) {
	r, err := NewJSONRecordFromDecoder(testJSONDecoder())
	require.Nil(t, err)
	require.NotNil(t, r)

	c, err := r.Find(ch.NewField("b"))
	require.Nil(t, err)
	require.NotNil(t, c)

	assert.True(t, c.IsBool())
	assert.Equal(t, true, c.AsBool())
}

func TestFindTopLevelNullField(t *testing.T) {
	r, err := NewJSONRecordFromDecoder(testJSONDecoder())
	require.Nil(t, err)
	require.NotNil(t, r)

	c, err := r.Find(ch.NewField("n"))
	require.Nil(t, err)
	require.NotNil(t, c)

	assert.True(t, c.IsNull())
}

func TestFindTopLevelEmptyStringField(t *testing.T) {
	r, err := NewJSONRecordFromDecoder(json.NewDecoder(strings.NewReader(`{"foo": ""}`)))
	require.Nil(t, err)
	require.NotNil(t, r)

	c, err := r.Find(ch.NewField("foo"))
	require.Nil(t, err)
	require.NotNil(t, c)

	assert.False(t, c.IsNull())
	assert.True(t, c.IsString())
}

func TestFindDeepStringField(t *testing.T) {
	r, err := NewJSONRecordFromDecoder(testJSONDecoder())
	require.Nil(t, err)
	require.NotNil(t, r)

	c, err := r.Find(ch.NewField("we.need.to.go.deeper"))
	require.Nil(t, err)
	require.NotNil(t, c)

	assert.True(t, c.IsNumeric())
	assert.Equal(t, int64(1), c.AsInt())
}

func TestJSONDecoderMultipleRecords(t *testing.T) {
	r := json.NewDecoder(strings.NewReader(`
	{"age": 42}
	{"age": 19}
	`))
	require.NotNil(t, r)

	_, err := NewJSONRecordFromDecoder(r)
	require.Nil(t, err)

	_, err = NewJSONRecordFromDecoder(r)
	require.Nil(t, err)

	_, err = NewJSONRecordFromDecoder(r)
	assert.Equal(t, io.EOF, err)
}

func TestJSONRecordSelectStar(t *testing.T) {
	r := json.NewDecoder(strings.NewReader(`{"foo": 42}`))
	require.NotNil(t, r)

	rec, err := NewJSONRecordFromDecoder(r)
	require.Nil(t, err)
	require.NotNil(t, rec)

	all, err := rec.Find(ch.NewField("*"))
	require.Nil(t, err)
	require.NotNil(t, all)

	require.True(t, all.IsString())
	require.Equal(t, `{"foo":42}`, all.AsString())
}

func TestJSONRecordTopLevelSoftFind(t *testing.T) {
	rec, err := NewJSONRecordFromDecoder(json.NewDecoder(strings.NewReader(`{"foo":42}`)))
	require.Nil(t, err)
	require.NotNil(t, rec)

	_, err = rec.Find(ch.NewField("yo"))
	assert.NotNil(t, err)

	rec.SoftMatching = true
	v, err := rec.Find(ch.NewField("yo"))
	assert.Nil(t, err)
	assert.True(t, v.IsNull())
}

func TestJSONRecordSoftFindNotAnObject(t *testing.T) {
	rec, err := NewJSONRecordFromDecoder(json.NewDecoder(strings.NewReader(`{"foo":42}`)))
	require.Nil(t, err)
	require.NotNil(t, rec)

	_, err = rec.Find(ch.NewField("foo.bar.qux"))
	assert.NotNil(t, err)

	rec.SoftMatching = true
	v, err := rec.Find(ch.NewField("foo.bar.qux"))
	assert.Nil(t, err)
	require.NotNil(t, v)
	assert.True(t, v.IsNull())
}

func TestJSONRecordSoftFind(t *testing.T) {
	rec, err := NewJSONRecordFromDecoder(json.NewDecoder(strings.NewReader(`
		{"foo": {"a": 2}}
	`)))
	require.Nil(t, err)
	require.NotNil(t, rec)

	_, err = rec.Find(ch.NewField("foo.bar.qux"))
	assert.NotNil(t, err)

	rec.SoftMatching = true
	v, err := rec.Find(ch.NewField("foo.bar.qux"))
	assert.Nil(t, err)
	require.NotNil(t, v)
	assert.True(t, v.IsNull())
}
<commit_msg>record: tests that arrays and objects are correctly parsed<commit_after>package record

import (
	"encoding/json"
	"io"
	"strings"
	"testing"

	ch "github.com/BatchLabs/charlatan"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func testJSONDecoder() *json.Decoder {
	return json.NewDecoder(strings.NewReader(`
	{
		"name": "Michel",
		"b": true,
		"age": 92,
		"n": null,
		"a": [],
		"we":{"need": {"to": {"go": {"deeper": 1, "a": "d"}}}}
	}
	`))
}

func TestFindUnexistingField(t *testing.T) {
	r, err := NewJSONRecordFromDecoder(testJSONDecoder())
	require.Nil(t, err)
	require.NotNil(t, r)

	_, err = r.Find(ch.NewField("yolo"))
	assert.NotNil(t, err)
}

func TestFindArrayField(t *testing.T) {
	r, err := NewJSONRecordFromDecoder(testJSONDecoder())
	require.Nil(t, err)
	require.NotNil(t, r)

	c, err := r.Find(ch.NewField("a"))
	require.Nil(t, err)
	require.NotNil(t, c)

	require.True(t, c.IsString())
	require.Equal(t, `[]`, c.AsString())
}

func TestFindObjectField(t *testing.T) {
	r, err := NewJSONRecordFromDecoder(testJSONDecoder())
	require.Nil(t, err)
	require.NotNil(t, r)

	c, err := r.Find(ch.NewField("we"))
	require.Nil(t, err)
	require.NotNil(t, c)

	require.True(t, c.IsString())
	require.Equal(t, `{"need": {"to": {"go": {"deeper": 1, "a": "d"}}}}`, c.AsString())
}

func TestFindTopLevelStringField(t *testing.T) {
	r, err := NewJSONRecordFromDecoder(testJSONDecoder())
	require.Nil(t, err)
	require.NotNil(t, r)

	c, err := r.Find(ch.NewField("name"))
	require.Nil(t, err)
	require.NotNil(t, c)

	assert.True(t, c.IsString())
	assert.Equal(t, "Michel", c.AsString())
}

func TestFindTopLevelIntField(t *testing.T) {
	r, err := NewJSONRecordFromDecoder(testJSONDecoder())
	require.Nil(t, err)
	require.NotNil(t, r)

	c, err := r.Find(ch.NewField("age"))
	require.Nil(t, err)
	require.NotNil(t, c)

	assert.True(t, c.IsNumeric())
	assert.Equal(t, int64(92), c.AsInt())
}

func TestFindTopLevelBoolField(t *testing.T) {
	r, err := NewJSONRecordFromDecoder(testJSONDecoder())
	require.Nil(t, err)
	require.NotNil(t, r)

	c, err := r.Find(ch.NewField("b"))
	require.Nil(t, err)
	require.NotNil(t, c)

	assert.True(t, c.IsBool())
	assert.Equal(t, true, c.AsBool())
}

func TestFindTopLevelNullField(t *testing.T) {
	r, err := NewJSONRecordFromDecoder(testJSONDecoder())
	require.Nil(t, err)
	require.NotNil(t, r)

	c, err := r.Find(ch.NewField("n"))
	require.Nil(t, err)
	require.NotNil(t, c)

	assert.True(t, c.IsNull())
}

func TestFindTopLevelEmptyStringField(t *testing.T) {
	r, err := NewJSONRecordFromDecoder(json.NewDecoder(strings.NewReader(`{"foo": ""}`)))
	require.Nil(t, err)
	require.NotNil(t, r)

	c, err := r.Find(ch.NewField("foo"))
	require.Nil(t, err)
	require.NotNil(t, c)

	assert.False(t, c.IsNull())
	assert.True(t, c.IsString())
}

func TestFindDeepStringField(t *testing.T) {
	r, err := NewJSONRecordFromDecoder(testJSONDecoder())
	require.Nil(t, err)
	require.NotNil(t, r)

	c, err := r.Find(ch.NewField("we.need.to.go.deeper"))
	require.Nil(t, err)
	require.NotNil(t, c)

	assert.True(t, c.IsNumeric())
	assert.Equal(t, int64(1), c.AsInt())
}

func TestJSONDecoderMultipleRecords(t *testing.T) {
	r := json.NewDecoder(strings.NewReader(`
	{"age": 42}
	{"age": 19}
	`))
	require.NotNil(t, r)

	_, err := NewJSONRecordFromDecoder(r)
	require.Nil(t, err)

	_, err = NewJSONRecordFromDecoder(r)
	require.Nil(t, err)

	_, err = NewJSONRecordFromDecoder(r)
	assert.Equal(t, io.EOF, err)
}

func TestJSONRecordSelectStar(t *testing.T) {
	r := json.NewDecoder(strings.NewReader(`{"foo": 42}`))
	require.NotNil(t, r)

	rec, err := NewJSONRecordFromDecoder(r)
	require.Nil(t, err)
	require.NotNil(t, rec)

	all, err := rec.Find(ch.NewField("*"))
	require.Nil(t, err)
	require.NotNil(t, all)

	require.True(t, all.IsString())
	require.Equal(t, `{"foo":42}`, all.AsString())
}

func TestJSONRecordTopLevelSoftFind(t *testing.T) {
	rec, err := NewJSONRecordFromDecoder(json.NewDecoder(strings.NewReader(`{"foo":42}`)))
	require.Nil(t, err)
	require.NotNil(t, rec)

	_, err = rec.Find(ch.NewField("yo"))
	assert.NotNil(t, err)

	rec.SoftMatching = true
	v, err := rec.Find(ch.NewField("yo"))
	assert.Nil(t, err)
	assert.True(t, v.IsNull())
}

func TestJSONRecordSoftFindNotAnObject(t *testing.T) {
	rec, err := NewJSONRecordFromDecoder(json.NewDecoder(strings.NewReader(`{"foo":42}`)))
	require.Nil(t, err)
	require.NotNil(t, rec)

	_, err = rec.Find(ch.NewField("foo.bar.qux"))
	assert.NotNil(t, err)

	rec.SoftMatching = true
	v, err := rec.Find(ch.NewField("foo.bar.qux"))
	assert.Nil(t, err)
	require.NotNil(t, v)
	assert.True(t, v.IsNull())
}

func TestJSONRecordSoftFind(t *testing.T) {
	rec, err := NewJSONRecordFromDecoder(json.NewDecoder(strings.NewReader(`
		{"foo": {"a": 2}}
	`)))
	require.Nil(t, err)
	require.NotNil(t, rec)

	_, err = rec.Find(ch.NewField("foo.bar.qux"))
	assert.NotNil(t, err)

	rec.SoftMatching = true
	v, err := rec.Find(ch.NewField("foo.bar.qux"))
	assert.Nil(t, err)
	require.NotNil(t, v)
	assert.True(t, v.IsNull())
}
<|endoftext|>


<commit_before>package kinesumer

import (
	"sync"
	"time"

	"github.com/garyburd/redigo/redis"
	"github.com/remind101/pkg/logger"
)

type RedisStateSync struct {
	heads    map[string]string
	c        chan *KinesisRecord
	mut      sync.Mutex
	pool     *redis.Pool
	redisKey string
	ticker   <-chan time.Time
	logger   logger.Logger
	wg       sync.WaitGroup
	modified bool
}

type RedisStateSyncOptions struct {
	ShardStateSyncOptions
	RedisURL string
	RedisKey string
}

func NewRedisStateSync(opt *RedisStateSyncOptions) (*RedisStateSync, error) {
	redisPool, err := NewRedisPool(opt.RedisURL)
	if err != nil {
		return nil, err
	}
	return &RedisStateSync{
		heads:    make(map[string]string),
		c:        make(chan *KinesisRecord),
		mut:      sync.Mutex{},
		pool:     redisPool,
		redisKey: opt.RedisKey,
		ticker:   opt.Ticker,
		logger:   opt.Logger,
		modified: true,
	}, nil
}

func (r *RedisStateSync) DoneC() chan *KinesisRecord {
	return r.c
}

func (r *RedisStateSync) Sync() {
	r.logger.Info("Writing sequence numbers")
	r.mut.Lock()
	defer r.mut.Unlock()
	conn := r.pool.Get()
	if len(r.heads) > 0 && r.modified {
		if _, err := conn.Do("HMSET", redis.Args{r.redisKey}.AddFlat(r.heads)...); err != nil {
			r.logger.Error("Failed to sync sequence numbers", "error", err)
		}
		r.modified = false
	} else {
		r.logger.Info("No sequence numbers to write")
	}
}

func (r *RedisStateSync) RunShardSync() {
loop:
	for {
		select {
		case <-r.ticker:
			r.Sync()
		case state, ok := <-r.c:
			if !ok {
				break loop
			}
			r.mut.Lock()
			r.heads[*state.ShardID] = *state.Record.SequenceNumber
			r.modified = true
			r.mut.Unlock()
		}
	}
	r.Sync()
	r.wg.Done()
}

func (r *RedisStateSync) Begin() error {
	conn := r.pool.Get()
	defer conn.Close()
	res, err := conn.Do("HGETALL", r.redisKey)
	r.heads, err = redis.StringMap(res, err)
	if err != nil {
		return err
	}

	r.wg.Add(1)
	go r.RunShardSync()
	return nil
}

func (r *RedisStateSync) End() {
	r.logger.Info("Redis state sync stopping")
	close(r.c)
	r.wg.Wait()
	r.logger.Info("Redis state sync stopped")

}

func (r *RedisStateSync) GetStartSequence(shardID *string) *string {
	val, ok := r.heads[*shardID]
	if ok {
		return &val
	} else {
		return nil
	}
}
<commit_msg>Close redis connections<commit_after>package kinesumer

import (
	"sync"
	"time"

	"github.com/garyburd/redigo/redis"
	"github.com/remind101/pkg/logger"
)

type RedisStateSync struct {
	heads    map[string]string
	c        chan *KinesisRecord
	mut      sync.Mutex
	pool     *redis.Pool
	redisKey string
	ticker   <-chan time.Time
	logger   logger.Logger
	wg       sync.WaitGroup
	modified bool
}

type RedisStateSyncOptions struct {
	ShardStateSyncOptions
	RedisURL string
	RedisKey string
}

func NewRedisStateSync(opt *RedisStateSyncOptions) (*RedisStateSync, error) {
	redisPool, err := NewRedisPool(opt.RedisURL)
	if err != nil {
		return nil, err
	}
	return &RedisStateSync{
		heads:    make(map[string]string),
		c:        make(chan *KinesisRecord),
		mut:      sync.Mutex{},
		pool:     redisPool,
		redisKey: opt.RedisKey,
		ticker:   opt.Ticker,
		logger:   opt.Logger,
		modified: true,
	}, nil
}

func (r *RedisStateSync) DoneC() chan *KinesisRecord {
	return r.c
}

func (r *RedisStateSync) Sync() {
	r.logger.Info("Writing sequence numbers")
	r.mut.Lock()
	defer r.mut.Unlock()
	if len(r.heads) > 0 && r.modified {
		conn := r.pool.Get()
		defer conn.Close()
		if _, err := conn.Do("HMSET", redis.Args{r.redisKey}.AddFlat(r.heads)...); err != nil {
			r.logger.Error("Failed to sync sequence numbers", "error", err)
		}
		r.modified = false
	} else {
		r.logger.Info("No sequence numbers to write")
	}
}

func (r *RedisStateSync) RunShardSync() {
loop:
	for {
		select {
		case <-r.ticker:
			r.Sync()
		case state, ok := <-r.c:
			if !ok {
				break loop
			}
			r.mut.Lock()
			r.heads[*state.ShardID] = *state.Record.SequenceNumber
			r.modified = true
			r.mut.Unlock()
		}
	}
	r.Sync()
	r.wg.Done()
}

func (r *RedisStateSync) Begin() error {
	conn := r.pool.Get()
	defer conn.Close()
	res, err := conn.Do("HGETALL", r.redisKey)
	r.heads, err = redis.StringMap(res, err)
	if err != nil {
		return err
	}

	r.wg.Add(1)
	go r.RunShardSync()
	return nil
}

func (r *RedisStateSync) End() {
	r.logger.Info("Redis state sync stopping")
	close(r.c)
	r.wg.Wait()
	r.logger.Info("Redis state sync stopped")

}

func (r *RedisStateSync) GetStartSequence(shardID *string) *string {
	val, ok := r.heads[*shardID]
	if ok {
		return &val
	} else {
		return nil
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package engine

import (
	"golang.org/x/net/context"

	"github.com/keybase/client/go/kex2"
	"github.com/keybase/client/go/libkb"
	keybase1 "github.com/keybase/client/go/protocol/keybase1"
)

// DeviceAdd is an engine.
type DeviceAdd struct {
	libkb.Contextified
}

// NewDeviceAdd creates a DeviceAdd engine.
func NewDeviceAdd(g *libkb.GlobalContext) *DeviceAdd {
	return &DeviceAdd{
		Contextified: libkb.NewContextified(g),
	}
}

// Name is the unique engine name.
func (e *DeviceAdd) Name() string {
	return "DeviceAdd"
}

// GetPrereqs returns the engine prereqs.
func (e *DeviceAdd) Prereqs() Prereqs {
	return Prereqs{Device: true}
}

// RequiredUIs returns the required UIs.
func (e *DeviceAdd) RequiredUIs() []libkb.UIKind {
	return []libkb.UIKind{libkb.ProvisionUIKind}
}

// SubConsumers returns the other UI consumers for this engine.
func (e *DeviceAdd) SubConsumers() []libkb.UIConsumer {
	return []libkb.UIConsumer{
		&Kex2Provisioner{},
	}
}

// Run starts the engine.
func (e *DeviceAdd) Run(m libkb.MetaContext) (err error) {
	defer m.CTrace("DeviceAdd#Run", func() error { return err })()

	e.G().LocalSigchainGuard().Set(m.Ctx(), "DeviceAdd")
	defer e.G().LocalSigchainGuard().Clear(m.Ctx(), "DeviceAdd")

	arg := keybase1.ChooseDeviceTypeArg{Kind: keybase1.ChooseType_NEW_DEVICE}
	provisioneeType, err := m.UIs().ProvisionUI.ChooseDeviceType(context.TODO(), arg)
	if err != nil {
		return err
	}
	m.CDebugf("provisionee device type: %v", provisioneeType)

	// make a new secret:
	useMobileSecret := provisioneeType == keybase1.DeviceType_MOBILE ||
		e.G().GetAppType() == libkb.DeviceTypeMobile
	secret, err := libkb.NewKex2Secret(useMobileSecret)
	if err != nil {
		return err
	}
	m.CDebugf("secret phrase received")

	// provisioner needs ppstream, and UI is confusing when it asks for
	// it at the same time as asking for the secret, so get it first
	// before prompting for the kex2 secret:
	pps, err := libkb.GetPassphraseStreamStored(m)
	if err != nil {
		return err
	}

	// create provisioner engine
	provisioner := NewKex2Provisioner(m.G(), secret.Secret(), pps)

	var canceler func()
	m, canceler = m.WithContextCancel()

	// display secret and prompt for secret from X in a goroutine:
	go func() {
		sb := secret.Secret()
		arg := keybase1.DisplayAndPromptSecretArg{
			Secret:          sb[:],
			Phrase:          secret.Phrase(),
			OtherDeviceType: provisioneeType,
		}
		for i := 0; i < 10; i++ {
			receivedSecret, err := m.UIs().ProvisionUI.DisplayAndPromptSecret(m.Ctx(), arg)
			if err != nil {
				m.CWarningf("DisplayAndPromptSecret error: %s", err)
				canceler()
				break
			} else if receivedSecret.Secret != nil && len(receivedSecret.Secret) > 0 {
				m.CDebugf("received secret, adding to provisioner")
				var ks kex2.Secret
				copy(ks[:], receivedSecret.Secret)
				provisioner.AddSecret(ks)
				break
			} else if len(receivedSecret.Phrase) > 0 {
				m.CDebugf("received secret phrase, checking validity")
				checker := libkb.MakeCheckKex2SecretPhrase(e.G())
				if !checker.F(receivedSecret.Phrase) {
					m.CDebugf("secret phrase failed validity check (attempt %d)", i+1)
					arg.PreviousErr = checker.Hint
					continue
				}
				m.CDebugf("received secret phrase, adding to provisioner")
				ks, err := libkb.NewKex2SecretFromPhrase(receivedSecret.Phrase)
				if err != nil {
					m.CWarningf("NewKex2SecretFromPhrase error: %s", err)
					canceler()
				} else {
					provisioner.AddSecret(ks.Secret())
				}
				break
			} else if provisioneeType == keybase1.DeviceType_MOBILE {
				// for mobile provisionee, only displaying the secret so it's
				// ok/expected that nothing came back
				m.CDebugf("device add DisplayAndPromptSecret returned empty secret, stopping retry loop")
				break
			}
		}
	}()

	defer func() {
		canceler()
	}()

	if err := RunEngine2(m, provisioner); err != nil {
		if err == kex2.ErrHelloTimeout {
			err = libkb.CanceledError{M: "Failed to provision device: are you sure you typed the secret properly?"}
		}
		return err
	}

	m.G().KeyfamilyChanged(m.G().Env.GetUID())

	return nil
}
<commit_msg>handle 10 bad kex2 phrase attempts (#13035)<commit_after>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package engine

import (
	"golang.org/x/net/context"

	"github.com/keybase/client/go/kex2"
	"github.com/keybase/client/go/libkb"
	keybase1 "github.com/keybase/client/go/protocol/keybase1"
)

// DeviceAdd is an engine.
type DeviceAdd struct {
	libkb.Contextified
}

// NewDeviceAdd creates a DeviceAdd engine.
func NewDeviceAdd(g *libkb.GlobalContext) *DeviceAdd {
	return &DeviceAdd{
		Contextified: libkb.NewContextified(g),
	}
}

// Name is the unique engine name.
func (e *DeviceAdd) Name() string {
	return "DeviceAdd"
}

// GetPrereqs returns the engine prereqs.
func (e *DeviceAdd) Prereqs() Prereqs {
	return Prereqs{Device: true}
}

// RequiredUIs returns the required UIs.
func (e *DeviceAdd) RequiredUIs() []libkb.UIKind {
	return []libkb.UIKind{libkb.ProvisionUIKind}
}

// SubConsumers returns the other UI consumers for this engine.
func (e *DeviceAdd) SubConsumers() []libkb.UIConsumer {
	return []libkb.UIConsumer{
		&Kex2Provisioner{},
	}
}

func (e *DeviceAdd) promptLoop(m libkb.MetaContext, provisioner *Kex2Provisioner, secret *libkb.Kex2Secret, provisioneeType keybase1.DeviceType) (err error) {
	sb := secret.Secret()
	arg := keybase1.DisplayAndPromptSecretArg{
		Secret:          sb[:],
		Phrase:          secret.Phrase(),
		OtherDeviceType: provisioneeType,
	}
	for i := 0; i < 10; i++ {
		receivedSecret, err := m.UIs().ProvisionUI.DisplayAndPromptSecret(m.Ctx(), arg)
		if err != nil {
			m.CWarningf("DisplayAndPromptSecret error: %s", err)
			return err
		}

		if receivedSecret.Secret != nil && len(receivedSecret.Secret) > 0 {
			m.CDebugf("received secret, adding to provisioner")
			var ks kex2.Secret
			copy(ks[:], receivedSecret.Secret)
			provisioner.AddSecret(ks)
			return nil
		}

		if len(receivedSecret.Phrase) > 0 {
			m.CDebugf("received secret phrase, checking validity")
			checker := libkb.MakeCheckKex2SecretPhrase(e.G())
			if !checker.F(receivedSecret.Phrase) {
				m.CDebugf("secret phrase failed validity check (attempt %d)", i+1)
				arg.PreviousErr = checker.Hint
				continue
			}
			m.CDebugf("received secret phrase, adding to provisioner")
			ks, err := libkb.NewKex2SecretFromPhrase(receivedSecret.Phrase)
			if err != nil {
				m.CWarningf("NewKex2SecretFromPhrase error: %s", err)
				return err
			}
			provisioner.AddSecret(ks.Secret())
			return nil
		}

		if provisioneeType == keybase1.DeviceType_MOBILE {
			// for mobile provisionee, only displaying the secret so it's
			// ok/expected that nothing came back
			m.CDebugf("device add DisplayAndPromptSecret returned empty secret, stopping retry loop")
			return nil
		}
	}

	return libkb.RetryExhaustedError{}
}

// Run starts the engine.
func (e *DeviceAdd) Run(m libkb.MetaContext) (err error) {
	defer m.CTrace("DeviceAdd#Run", func() error { return err })()

	e.G().LocalSigchainGuard().Set(m.Ctx(), "DeviceAdd")
	defer e.G().LocalSigchainGuard().Clear(m.Ctx(), "DeviceAdd")

	arg := keybase1.ChooseDeviceTypeArg{Kind: keybase1.ChooseType_NEW_DEVICE}
	provisioneeType, err := m.UIs().ProvisionUI.ChooseDeviceType(context.TODO(), arg)
	if err != nil {
		return err
	}
	m.CDebugf("provisionee device type: %v", provisioneeType)

	// make a new secret:
	useMobileSecret := provisioneeType == keybase1.DeviceType_MOBILE ||
		e.G().GetAppType() == libkb.DeviceTypeMobile
	secret, err := libkb.NewKex2Secret(useMobileSecret)
	if err != nil {
		return err
	}
	m.CDebugf("secret phrase received")

	// provisioner needs ppstream, and UI is confusing when it asks for
	// it at the same time as asking for the secret, so get it first
	// before prompting for the kex2 secret:
	pps, err := libkb.GetPassphraseStreamStored(m)
	if err != nil {
		return err
	}

	// create provisioner engine
	provisioner := NewKex2Provisioner(m.G(), secret.Secret(), pps)

	var canceler func()
	m, canceler = m.WithContextCancel()

	// display secret and prompt for secret from X in a goroutine:
	go func() {
		err := e.promptLoop(m, provisioner, secret, provisioneeType)
		if err != nil {
			m.CDebugf("DeviceAdd prompt loop error: %s", err)
			canceler()
		}
	}()

	defer func() {
		canceler()
	}()

	if err := RunEngine2(m, provisioner); err != nil {
		if err == kex2.ErrHelloTimeout {
			err = libkb.CanceledError{M: "Failed to provision device: are you sure you typed the secret properly?"}
		}
		return err
	}

	m.G().KeyfamilyChanged(m.G().Env.GetUID())

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package provider_test

import (
	"bytes"
	"io/ioutil"

	gc "launchpad.net/gocheck"
	"launchpad.net/goyaml"

	"launchpad.net/juju-core/environs"
	"launchpad.net/juju-core/environs/config"
	"launchpad.net/juju-core/environs/localstorage"
	"launchpad.net/juju-core/errors"
	"launchpad.net/juju-core/instance"
	"launchpad.net/juju-core/provider"
	"launchpad.net/juju-core/testing"
	jc "launchpad.net/juju-core/testing/checkers"
)

type StateSuite struct{}

var _ = gc.Suite(&StateSuite{})

// makeDummyStorage creates a local storage.
// Returns a cleanup function that must be called when done with the storage.
func makeDummyStorage(c *gc.C) (environs.Storage, func()) {
	listener, err := localstorage.Serve("127.0.0.1:0", c.MkDir())
	c.Assert(err, gc.IsNil)
	storage := localstorage.Client(listener.Addr().String())
	cleanup := func() { listener.Close() }
	return storage, cleanup
}

func (*StateSuite) TestCreateStateFileWritesEmptyStateFile(c *gc.C) {
	storage, cleanup := makeDummyStorage(c)
	defer cleanup()

	url, err := provider.CreateStateFile(storage)
	c.Assert(err, gc.IsNil)

	reader, err := storage.Get(provider.StateFile)
	c.Assert(err, gc.IsNil)
	data, err := ioutil.ReadAll(reader)
	c.Assert(err, gc.IsNil)
	c.Check(string(data), gc.Equals, "")
	c.Assert(url, gc.NotNil)
	expectedURL, err := storage.URL(provider.StateFile)
	c.Assert(err, gc.IsNil)
	c.Check(url, gc.Equals, expectedURL)
}

func (suite *StateSuite) TestSaveStateWritesStateFile(c *gc.C) {
	storage, cleanup := makeDummyStorage(c)
	defer cleanup()
	arch := "amd64"
	state := provider.BootstrapState{
		StateInstances:  []instance.Id{instance.Id("an-instance-id")},
		Characteristics: []instance.HardwareCharacteristics{{Arch: &arch}}}
	marshaledState, err := goyaml.Marshal(state)
	c.Assert(err, gc.IsNil)

	err = provider.SaveState(storage, &state)
	c.Assert(err, gc.IsNil)

	loadedState, err := storage.Get(provider.StateFile)
	c.Assert(err, gc.IsNil)
	content, err := ioutil.ReadAll(loadedState)
	c.Assert(err, gc.IsNil)
	c.Check(content, gc.DeepEquals, marshaledState)
}

func (suite *StateSuite) setUpSavedState(c *gc.C, storage environs.Storage) provider.BootstrapState {
	arch := "amd64"
	state := provider.BootstrapState{
		StateInstances:  []instance.Id{instance.Id("an-instance-id")},
		Characteristics: []instance.HardwareCharacteristics{{Arch: &arch}}}
	content, err := goyaml.Marshal(state)
	c.Assert(err, gc.IsNil)
	err = storage.Put(provider.StateFile, ioutil.NopCloser(bytes.NewReader(content)), int64(len(content)))
	c.Assert(err, gc.IsNil)
	return state
}

func (suite *StateSuite) TestLoadStateReadsStateFile(c *gc.C) {
	storage, cleanup := makeDummyStorage(c)
	defer cleanup()
	state := suite.setUpSavedState(c, storage)
	storedState, err := provider.LoadState(storage)
	c.Assert(err, gc.IsNil)
	c.Check(*storedState, gc.DeepEquals, state)
}

func (suite *StateSuite) TestLoadStateFromURLReadsStateFile(c *gc.C) {
	storage, cleanup := makeDummyStorage(c)
	defer cleanup()
	state := suite.setUpSavedState(c, storage)
	url, err := storage.URL(provider.StateFile)
	c.Assert(err, gc.IsNil)
	storedState, err := provider.LoadStateFromURL(url)
	c.Assert(err, gc.IsNil)
	c.Check(*storedState, gc.DeepEquals, state)
}

func (suite *StateSuite) TestLoadStateMissingFile(c *gc.C) {
	storage, cleanup := makeDummyStorage(c)
	defer cleanup()

	_, err := provider.LoadState(storage)

	c.Check(err, jc.Satisfies, errors.IsNotBootstrapped)
}

func (suite *StateSuite) TestLoadStateIntegratesWithSaveState(c *gc.C) {
	storage, cleanup := makeDummyStorage(c)
	defer cleanup()
	arch := "amd64"
	state := provider.BootstrapState{
		StateInstances:  []instance.Id{instance.Id("an-instance-id")},
		Characteristics: []instance.HardwareCharacteristics{{Arch: &arch}}}
	err := provider.SaveState(storage, &state)
	c.Assert(err, gc.IsNil)
	storedState, err := provider.LoadState(storage)
	c.Assert(err, gc.IsNil)

	c.Check(*storedState, gc.DeepEquals, state)
}

func (suite *StateSuite) TestGetDNSNamesAcceptsNil(c *gc.C) {
	result := provider.GetDNSNames(nil)
	c.Check(result, gc.DeepEquals, []string{})
}

func (suite *StateSuite) TestGetDNSNamesReturnsNames(c *gc.C) {
	instances := []instance.Instance{
		&dnsNameFakeInstance{name: "foo"},
		&dnsNameFakeInstance{name: "bar"},
	}

	c.Check(provider.GetDNSNames(instances), gc.DeepEquals, []string{"foo", "bar"})
}

func (suite *StateSuite) TestGetDNSNamesIgnoresNils(c *gc.C) {
	c.Check(provider.GetDNSNames([]instance.Instance{nil, nil}), gc.DeepEquals, []string{})
}

func (suite *StateSuite) TestGetDNSNamesIgnoresInstancesWithoutNames(c *gc.C) {
	instances := []instance.Instance{&dnsNameFakeInstance{err: instance.ErrNoDNSName}}
	c.Check(provider.GetDNSNames(instances), gc.DeepEquals, []string{})
}

func (suite *StateSuite) TestGetDNSNamesIgnoresInstancesWithBlankNames(c *gc.C) {
	instances := []instance.Instance{&dnsNameFakeInstance{name: ""}}
	c.Check(provider.GetDNSNames(instances), gc.DeepEquals, []string{})
}

func (suite *StateSuite) TestComposeAddressesAcceptsNil(c *gc.C) {
	c.Check(provider.ComposeAddresses(nil, 1433), gc.DeepEquals, []string{})
}

func (suite *StateSuite) TestComposeAddressesSuffixesAddresses(c *gc.C) {
	c.Check(
		provider.ComposeAddresses([]string{"onehost", "otherhost"}, 1957),
		gc.DeepEquals,
		[]string{"onehost:1957", "otherhost:1957"})
}

func (suite *StateSuite) TestGetStateInfo(c *gc.C) {
	cert := testing.CACert
	cfg, err := config.New(map[string]interface{}{
		// Some config items we're going to test for:
		"ca-cert":    cert,
		"state-port": 123,
		"api-port":   456,
		// And some required but irrelevant items:
		"name":           "aname",
		"type":           "dummy",
		"ca-private-key": testing.CAKey,
	})
	c.Assert(err, gc.IsNil)
	hostnames := []string{"onehost", "otherhost"}

	stateInfo, apiInfo := provider.GetStateInfo(cfg, hostnames)

	c.Check(stateInfo.Addrs, gc.DeepEquals, []string{"onehost:123", "otherhost:123"})
	c.Check(string(stateInfo.CACert), gc.Equals, cert)
	c.Check(apiInfo.Addrs, gc.DeepEquals, []string{"onehost:456", "otherhost:456"})
	c.Check(string(apiInfo.CACert), gc.Equals, cert)
}
<commit_msg>provider: tests pass<commit_after>// Copyright 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package provider_test

import (
	"bytes"
	"io/ioutil"

	gc "launchpad.net/gocheck"
	"launchpad.net/goyaml"

	"launchpad.net/juju-core/environs"
	"launchpad.net/juju-core/environs/config"
	"launchpad.net/juju-core/environs/localstorage"
	envtesting "launchpad.net/juju-core/environs/testing"
	"launchpad.net/juju-core/errors"
	"launchpad.net/juju-core/instance"
	"launchpad.net/juju-core/provider"
	"launchpad.net/juju-core/testing"
	jc "launchpad.net/juju-core/testing/checkers"
)

type StateSuite struct{}

var _ = gc.Suite(&StateSuite{})

// makeDummyStorage creates a local storage.
// Returns a cleanup function that must be called when done with the storage.
func makeDummyStorage(c *gc.C) (environs.Storage, func()) {
	listener, err := localstorage.Serve("127.0.0.1:0", c.MkDir())
	c.Assert(err, gc.IsNil)
	storage := localstorage.Client(listener.Addr().String())
	cleanup := func() { listener.Close() }
	return storage, cleanup
}

func (*StateSuite) TestCreateStateFileWritesEmptyStateFile(c *gc.C) {
	storage, cleanup := makeDummyStorage(c)
	defer cleanup()

	url, err := provider.CreateStateFile(storage)
	c.Assert(err, gc.IsNil)

	reader, err := storage.Get(provider.StateFile)
	c.Assert(err, gc.IsNil)
	data, err := ioutil.ReadAll(reader)
	c.Assert(err, gc.IsNil)
	c.Check(string(data), gc.Equals, "")
	c.Assert(url, gc.NotNil)
	expectedURL, err := storage.URL(provider.StateFile)
	c.Assert(err, gc.IsNil)
	c.Check(url, gc.Equals, expectedURL)
}

func (suite *StateSuite) TestSaveStateWritesStateFile(c *gc.C) {
	storage, cleanup := makeDummyStorage(c)
	defer cleanup()
	arch := "amd64"
	state := provider.BootstrapState{
		StateInstances:  []instance.Id{instance.Id("an-instance-id")},
		Characteristics: []instance.HardwareCharacteristics{{Arch: &arch}}}
	marshaledState, err := goyaml.Marshal(state)
	c.Assert(err, gc.IsNil)

	err = provider.SaveState(storage, &state)
	c.Assert(err, gc.IsNil)

	loadedState, err := storage.Get(provider.StateFile)
	c.Assert(err, gc.IsNil)
	content, err := ioutil.ReadAll(loadedState)
	c.Assert(err, gc.IsNil)
	c.Check(content, gc.DeepEquals, marshaledState)
}

func (suite *StateSuite) setUpSavedState(c *gc.C, storage environs.Storage) provider.BootstrapState {
	arch := "amd64"
	state := provider.BootstrapState{
		StateInstances:  []instance.Id{instance.Id("an-instance-id")},
		Characteristics: []instance.HardwareCharacteristics{{Arch: &arch}}}
	content, err := goyaml.Marshal(state)
	c.Assert(err, gc.IsNil)
	err = storage.Put(provider.StateFile, ioutil.NopCloser(bytes.NewReader(content)), int64(len(content)))
	c.Assert(err, gc.IsNil)
	return state
}

func (suite *StateSuite) TestLoadStateReadsStateFile(c *gc.C) {
	storage, cleanup := makeDummyStorage(c)
	defer cleanup()
	state := suite.setUpSavedState(c, storage)
	storedState, err := provider.LoadState(storage)
	c.Assert(err, gc.IsNil)
	c.Check(*storedState, gc.DeepEquals, state)
}

func (suite *StateSuite) TestLoadStateFromURLReadsStateFile(c *gc.C) {
	storage, cleanup := makeDummyStorage(c)
	defer cleanup()
	state := suite.setUpSavedState(c, storage)
	url, err := storage.URL(provider.StateFile)
	c.Assert(err, gc.IsNil)
	storedState, err := provider.LoadStateFromURL(url)
	c.Assert(err, gc.IsNil)
	c.Check(*storedState, gc.DeepEquals, state)
}

func (suite *StateSuite) TestLoadStateMissingFile(c *gc.C) {
	storage, cleanup := makeDummyStorage(c)
	defer cleanup()

	_, err := provider.LoadState(storage)

	c.Check(err, jc.Satisfies, errors.IsNotBootstrapped)
}

func (suite *StateSuite) TestLoadStateIntegratesWithSaveState(c *gc.C) {
	storage, cleanup := makeDummyStorage(c)
	defer cleanup()
	arch := "amd64"
	state := provider.BootstrapState{
		StateInstances:  []instance.Id{instance.Id("an-instance-id")},
		Characteristics: []instance.HardwareCharacteristics{{Arch: &arch}}}
	err := provider.SaveState(storage, &state)
	c.Assert(err, gc.IsNil)
	storedState, err := provider.LoadState(storage)
	c.Assert(err, gc.IsNil)

	c.Check(*storedState, gc.DeepEquals, state)
}

func (suite *StateSuite) TestGetDNSNamesAcceptsNil(c *gc.C) {
	result := provider.GetDNSNames(nil)
	c.Check(result, gc.DeepEquals, []string{})
}

func (suite *StateSuite) TestGetDNSNamesReturnsNames(c *gc.C) {
	instances := []instance.Instance{
		&dnsNameFakeInstance{name: "foo"},
		&dnsNameFakeInstance{name: "bar"},
	}

	c.Check(provider.GetDNSNames(instances), gc.DeepEquals, []string{"foo", "bar"})
}

func (suite *StateSuite) TestGetDNSNamesIgnoresNils(c *gc.C) {
	c.Check(provider.GetDNSNames([]instance.Instance{nil, nil}), gc.DeepEquals, []string{})
}

func (suite *StateSuite) TestGetDNSNamesIgnoresInstancesWithoutNames(c *gc.C) {
	instances := []instance.Instance{&dnsNameFakeInstance{err: instance.ErrNoDNSName}}
	c.Check(provider.GetDNSNames(instances), gc.DeepEquals, []string{})
}

func (suite *StateSuite) TestGetDNSNamesIgnoresInstancesWithBlankNames(c *gc.C) {
	instances := []instance.Instance{&dnsNameFakeInstance{name: ""}}
	c.Check(provider.GetDNSNames(instances), gc.DeepEquals, []string{})
}

func (suite *StateSuite) TestComposeAddressesAcceptsNil(c *gc.C) {
	c.Check(provider.ComposeAddresses(nil, 1433), gc.DeepEquals, []string{})
}

func (suite *StateSuite) TestComposeAddressesSuffixesAddresses(c *gc.C) {
	c.Check(
		provider.ComposeAddresses([]string{"onehost", "otherhost"}, 1957),
		gc.DeepEquals,
		[]string{"onehost:1957", "otherhost:1957"})
}

func (suite *StateSuite) TestGetStateInfo(c *gc.C) {
	cert := testing.CACert
	attrs := envtesting.FakeConfig.Merge(testing.Attrs{
		"ca-cert":    cert,
		"state-port": 123,
		"api-port":   456,
	})
	cfg, err := config.New(config.NoDefaults, attrs)
	c.Assert(err, gc.IsNil)
	hostnames := []string{"onehost", "otherhost"}

	stateInfo, apiInfo := provider.GetStateInfo(cfg, hostnames)

	c.Check(stateInfo.Addrs, gc.DeepEquals, []string{"onehost:123", "otherhost:123"})
	c.Check(string(stateInfo.CACert), gc.Equals, cert)
	c.Check(apiInfo.Addrs, gc.DeepEquals, []string{"onehost:456", "otherhost:456"})
	c.Check(string(apiInfo.CACert), gc.Equals, cert)
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Vitess Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package mysql

import (
	"io/ioutil"
	"net"
	"os"
	"strings"
	"sync"
	"testing"
	"time"

	"golang.org/x/net/context"
)

// assertSQLError makes sure we get the right error.
func assertSQLError(t *testing.T, err error, code int, sqlState string, subtext string, query string) {
	t.Helper()

	if err == nil {
		t.Fatalf("was expecting SQLError %v / %v / %v but got no error.", code, sqlState, subtext)
	}
	serr, ok := err.(*SQLError)
	if !ok {
		t.Fatalf("was expecting SQLError %v / %v / %v but got: %v", code, sqlState, subtext, err)
	}
	if serr.Num != code {
		t.Fatalf("was expecting SQLError %v / %v / %v but got code %v", code, sqlState, subtext, serr.Num)
	}
	if serr.State != sqlState {
		t.Fatalf("was expecting SQLError %v / %v / %v but got state %v", code, sqlState, subtext, serr.State)
	}
	if subtext != "" && !strings.Contains(serr.Message, subtext) {
		t.Fatalf("was expecting SQLError %v / %v / %v but got message %v", code, sqlState, subtext, serr.Message)
	}
	if serr.Query != query {
		t.Fatalf("was expecting SQLError %v / %v / %v with Query '%v' but got query '%v'", code, sqlState, subtext, query, serr.Query)
	}
}

// TestConnectTimeout runs connection failure scenarios against a
// server that's not listening or has trouble.  This test is not meant
// to use a valid server. So we do not test bad handshakes here.
func TestConnectTimeout(t *testing.T) {
	// Create a socket, but it's not accepting. So all Dial
	// attempts will timeout.
	listener, err := net.Listen("tcp", ":0")
	if err != nil {
		t.Fatalf("cannot listen: %v", err)
	}
	host, port := getHostPort(t, listener.Addr())
	params := &ConnParams{
		Host: host,
		Port: port,
	}
	defer listener.Close()

	// Test that canceling the context really interrupts the Connect.
	ctx, cancel := context.WithCancel(context.Background())
	done := make(chan struct{})
	go func() {
		_, err := Connect(ctx, params)
		if err != context.Canceled {
			t.Errorf("Was expecting context.Canceled but got: %v", err)
		}
		close(done)
	}()
	time.Sleep(100 * time.Millisecond)
	cancel()
	<-done

	// Tests a connection timeout works.
	ctx, cancel = context.WithTimeout(context.Background(), 100*time.Millisecond)
	_, err = Connect(ctx, params)
	cancel()
	if err != context.DeadlineExceeded {
		t.Errorf("Was expecting context.DeadlineExceeded but got: %v", err)
	}

	// Tests a connection timeout through params
	ctx = context.Background()
	paramsWithTimeout := params
	paramsWithTimeout.ConnectTimeoutMs = 1
	_, err = Connect(ctx, paramsWithTimeout)
	cancel()
	if err != context.DeadlineExceeded {
		t.Errorf("Was expecting context.DeadlineExceeded but got: %v", err)
	}

	// Now the server will listen, but close all connections on accept.
	wg := sync.WaitGroup{}
	wg.Add(1)
	go func() {
		defer wg.Done()
		for {
			conn, err := listener.Accept()
			if err != nil {
				// Listener was closed.
				return
			}
			conn.Close()
		}
	}()
	ctx = context.Background()
	_, err = Connect(ctx, params)
	assertSQLError(t, err, CRServerLost, SSUnknownSQLState, "initial packet read failed", "")

	// Now close the listener. Connect should fail right away,
	// check the error.
	listener.Close()
	wg.Wait()
	_, err = Connect(ctx, params)
	assertSQLError(t, err, CRConnHostError, SSUnknownSQLState, "connection refused", "")

	// Tests a connection where Dial to a unix socket fails
	// properly returns the right error. To simulate exactly the
	// right failure, try to dial a Unix socket that's just a temp file.
	fd, err := ioutil.TempFile("", "mysql")
	if err != nil {
		t.Fatalf("cannot create TemFile: %v", err)
	}
	name := fd.Name()
	fd.Close()
	params.UnixSocket = name
	ctx = context.Background()
	_, err = Connect(ctx, params)
	os.Remove(name)
	assertSQLError(t, err, CRConnectionError, SSUnknownSQLState, "connection refused", "")
}
<commit_msg>go/mysql: Fix flaky TestConnectTimeout. (#6188)<commit_after>/*
Copyright 2019 The Vitess Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package mysql

import (
	"io/ioutil"
	"net"
	"os"
	"strings"
	"sync"
	"testing"
	"time"

	"golang.org/x/net/context"
)

// assertSQLError makes sure we get the right error.
func assertSQLError(t *testing.T, err error, code int, sqlState string, subtext string, query string) {
	t.Helper()

	if err == nil {
		t.Fatalf("was expecting SQLError %v / %v / %v but got no error.", code, sqlState, subtext)
	}
	serr, ok := err.(*SQLError)
	if !ok {
		t.Fatalf("was expecting SQLError %v / %v / %v but got: %v", code, sqlState, subtext, err)
	}
	if serr.Num != code {
		t.Fatalf("was expecting SQLError %v / %v / %v but got code %v", code, sqlState, subtext, serr.Num)
	}
	if serr.State != sqlState {
		t.Fatalf("was expecting SQLError %v / %v / %v but got state %v", code, sqlState, subtext, serr.State)
	}
	if subtext != "" && !strings.Contains(serr.Message, subtext) {
		t.Fatalf("was expecting SQLError %v / %v / %v but got message %v", code, sqlState, subtext, serr.Message)
	}
	if serr.Query != query {
		t.Fatalf("was expecting SQLError %v / %v / %v with Query '%v' but got query '%v'", code, sqlState, subtext, query, serr.Query)
	}
}

// TestConnectTimeout runs connection failure scenarios against a
// server that's not listening or has trouble.  This test is not meant
// to use a valid server. So we do not test bad handshakes here.
func TestConnectTimeout(t *testing.T) {
	// Create a socket, but it's not accepting. So all Dial
	// attempts will timeout.
	listener, err := net.Listen("tcp", ":0")
	if err != nil {
		t.Fatalf("cannot listen: %v", err)
	}
	host, port := getHostPort(t, listener.Addr())
	params := &ConnParams{
		Host: host,
		Port: port,
	}
	defer listener.Close()

	// Test that canceling the context really interrupts the Connect.
	ctx, cancel := context.WithCancel(context.Background())
	done := make(chan struct{})
	go func() {
		_, err := Connect(ctx, params)
		if err != context.Canceled {
			t.Errorf("Was expecting context.Canceled but got: %v", err)
		}
		close(done)
	}()
	time.Sleep(100 * time.Millisecond)
	cancel()
	<-done

	// Tests a connection timeout works.
	ctx, cancel = context.WithTimeout(context.Background(), 100*time.Millisecond)
	_, err = Connect(ctx, params)
	cancel()
	if err != context.DeadlineExceeded {
		t.Errorf("Was expecting context.DeadlineExceeded but got: %v", err)
	}

	// Tests a connection timeout through params
	ctx = context.Background()
	paramsWithTimeout := *params
	paramsWithTimeout.ConnectTimeoutMs = 1
	_, err = Connect(ctx, &paramsWithTimeout)
	cancel()
	if err != context.DeadlineExceeded {
		t.Errorf("Was expecting context.DeadlineExceeded but got: %v", err)
	}

	// Now the server will listen, but close all connections on accept.
	wg := sync.WaitGroup{}
	wg.Add(1)
	go func() {
		defer wg.Done()
		for {
			conn, err := listener.Accept()
			if err != nil {
				// Listener was closed.
				return
			}
			conn.Close()
		}
	}()
	ctx = context.Background()
	_, err = Connect(ctx, params)
	assertSQLError(t, err, CRServerLost, SSUnknownSQLState, "initial packet read failed", "")

	// Now close the listener. Connect should fail right away,
	// check the error.
	listener.Close()
	wg.Wait()
	_, err = Connect(ctx, params)
	assertSQLError(t, err, CRConnHostError, SSUnknownSQLState, "connection refused", "")

	// Tests a connection where Dial to a unix socket fails
	// properly returns the right error. To simulate exactly the
	// right failure, try to dial a Unix socket that's just a temp file.
	fd, err := ioutil.TempFile("", "mysql")
	if err != nil {
		t.Fatalf("cannot create TemFile: %v", err)
	}
	name := fd.Name()
	fd.Close()
	params.UnixSocket = name
	ctx = context.Background()
	_, err = Connect(ctx, params)
	os.Remove(name)
	assertSQLError(t, err, CRConnectionError, SSUnknownSQLState, "connection refused", "")
}
<|endoftext|>


<commit_before>// Copyright 2015 go-swagger maintainers
//
// 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 swag

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"path/filepath"
	"strings"
	"time"
)

// LoadHTTPTimeout the default timeout for load requests
var LoadHTTPTimeout = 30 * time.Second

// LoadFromFileOrHTTP loads the bytes from a file or a remote http server based on the path passed in
func LoadFromFileOrHTTP(path string) ([]byte, error) {
	return LoadStrategy(path, ioutil.ReadFile, loadHTTPBytes(LoadHTTPTimeout))(path)
}

// LoadFromFileOrHTTPWithTimeout loads the bytes from a file or a remote http server based on the path passed in
// timeout arg allows for per request overriding of the request timeout
func LoadFromFileOrHTTPWithTimeout(path string, timeout time.Duration) ([]byte, error) {
	return LoadStrategy(path, ioutil.ReadFile, loadHTTPBytes(timeout))(path)
}

// LoadStrategy returns a loader function for a given path or uri
func LoadStrategy(path string, local, remote func(string) ([]byte, error)) func(string) ([]byte, error) {
	if strings.HasPrefix(path, "http") {
		return remote
	}
	return func(pth string) ([]byte, error) { return local(filepath.FromSlash(pth)) }
}

func loadHTTPBytes(timeout time.Duration) func(path string) ([]byte, error) {
	return func(path string) ([]byte, error) {
		client := &http.Client{Timeout: timeout}
		req, err := http.NewRequest("GET", path, nil)
		if err != nil {
			return nil, err
		}
		resp, err := client.Do(req)
		defer func() {
			if resp != nil {
				if e := resp.Body.Close(); e != nil {
					log.Println(e)
				}
			}
		}()
		if err != nil {
			return nil, err
		}

		if resp.StatusCode != http.StatusOK {
			return nil, fmt.Errorf("could not access document at %q [%s] ", path, resp.Status)
		}

		return ioutil.ReadAll(resp.Body)
	}
}
<commit_msg>Escape URI for local file load strategy<commit_after>// Copyright 2015 go-swagger maintainers
//
// 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 swag

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"path/filepath"
	"strings"
	"time"
)

// LoadHTTPTimeout the default timeout for load requests
var LoadHTTPTimeout = 30 * time.Second

// LoadFromFileOrHTTP loads the bytes from a file or a remote http server based on the path passed in
func LoadFromFileOrHTTP(path string) ([]byte, error) {
	return LoadStrategy(path, ioutil.ReadFile, loadHTTPBytes(LoadHTTPTimeout))(path)
}

// LoadFromFileOrHTTPWithTimeout loads the bytes from a file or a remote http server based on the path passed in
// timeout arg allows for per request overriding of the request timeout
func LoadFromFileOrHTTPWithTimeout(path string, timeout time.Duration) ([]byte, error) {
	return LoadStrategy(path, ioutil.ReadFile, loadHTTPBytes(timeout))(path)
}

// LoadStrategy returns a loader function for a given path or uri
func LoadStrategy(path string, local, remote func(string) ([]byte, error)) func(string) ([]byte, error) {
	if strings.HasPrefix(path, "http") {
		return remote
	}
	return func(pth string) ([]byte, error) {
		upth, _ := url.PathUnescape(pth)
		return local(filepath.FromSlash(upth))
	}
}

func loadHTTPBytes(timeout time.Duration) func(path string) ([]byte, error) {
	return func(path string) ([]byte, error) {
		client := &http.Client{Timeout: timeout}
		req, err := http.NewRequest("GET", path, nil)
		if err != nil {
			return nil, err
		}
		resp, err := client.Do(req)
		defer func() {
			if resp != nil {
				if e := resp.Body.Close(); e != nil {
					log.Println(e)
				}
			}
		}()
		if err != nil {
			return nil, err
		}

		if resp.StatusCode != http.StatusOK {
			return nil, fmt.Errorf("could not access document at %q [%s] ", path, resp.Status)
		}

		return ioutil.ReadAll(resp.Body)
	}
}
<|endoftext|>


<commit_before>// Copyright 2013 tsuru 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 provision provides interfaces that need to be satisfied in order to
// implement a new provisioner on tsuru.
package provision

import (
	"fmt"
	"io"
)

type Status string

func (s Status) String() string {
	return string(s)
}

const (
	StatusStarted    = Status("started")
	StatusPending    = Status("pending")
	StatusDown       = Status("down")
	StatusError      = Status("error")
	StatusInstalling = Status("installing")
	StatusCreating   = Status("creating")
)

// Unit represents a provision unit. Can be a machine, container or anything
// IP-addressable.
type Unit struct {
	Name       string
	AppName    string
	Type       string
	InstanceId string
	Machine    int
	Ip         string
	Status     Status
}

// Named is something that has a name, providing the GetName method.
type Named interface {
	GetName() string
}

// AppUnit represents a unit in an app.
type AppUnit interface {
	Named

	// Returns the number of the unit.
	GetMachine() int

	// Returns the status of the unit.
	GetStatus() Status

	// Returns the IP of the unit.
	GetIp() string

	// Returns the instance id of the unit.
	GetInstanceId() string
}

// App represents a tsuru app.
//
// It contains only relevant information for provisioning.
type App interface {
	Named

	// Log should be used to log messages in the app.
	Log(message, source string) error

	// GetPlatform returns the platform (type) of the app. It is equivalent
	// to the Unit `Type` field.
	GetPlatform() string

	// ProvisionUnits returns all units of the app, in a slice.
	ProvisionUnits() []AppUnit

	// RemoveUnit removes the given unit from the app.
	RemoveUnit(id string) error

	// Run executes the command in app units, sourcing apprc before running the
	// command.
	Run(cmd string, w io.Writer) error

	// Restart restarts the application process
	Restart(io.Writer) error
}

// Provisioner is the basic interface of this package.
//
// Any tsuru provisioner must implement this interface in order to provision
// tsuru apps.
//
// Tsuru comes with a default provisioner: juju. One can add other provisioners
// by satisfying this interface and registering it using the function Register.
type Provisioner interface {
	Deploy(App, io.Writer) error

	// Provision is called when tsuru is creating the app.
	Provision(App) error

	// Destroy is called when tsuru is destroying the app.
	Destroy(App) error

	// AddUnits adds units to an app. The first parameter is the app, the
	// second is the number of units to add.
	//
	// It returns a slice containing all added units
	AddUnits(App, uint) ([]Unit, error)

	// RemoveUnit removes a unit from the app. It receives the app and the name
	// of the unit to be removed.
	RemoveUnit(App, string) error

	// ExecuteCommand runs a command in all units of the app.
	ExecuteCommand(stdout, stderr io.Writer, app App, cmd string, args ...string) error

	// Restart restarts the app.
	Restart(App) error

	// CollectStatus returns information about all provisioned units. It's used
	// by tsuru collector when updating the status of apps in the database.
	CollectStatus() ([]Unit, error)

	// Addr returns the address for an app. It will probably be a DNS name
	// or IP address.
	//
	// Tsuru will use this method to get the IP (althought it might not be
	// an actual IP, collector calls it "IP") of the app from the
	// provisioner.
	Addr(App) (string, error)

	// InstallDeps installs the dependencies required for the application
	// to run and writes the log in the received writer
	InstallDeps(app App, w io.Writer) error
}

var provisioners = make(map[string]Provisioner)

// Register registers a new provisioner in the Provisioner registry.
func Register(name string, p Provisioner) {
	provisioners[name] = p
}

// Get gets the named provisioner from the registry.
func Get(name string) (Provisioner, error) {
	p, ok := provisioners[name]
	if !ok {
		return nil, fmt.Errorf("Unknown provisioner: %q.", name)
	}
	return p, nil
}

type Error struct {
	Reason string
	Err    error
}

func (e *Error) Error() string {
	var err string
	if e.Err != nil {
		err = e.Err.Error() + ": " + e.Reason
	} else {
		err = e.Reason
	}
	return err
}
<commit_msg>provision: add Ready method to the app type<commit_after>// Copyright 2013 tsuru 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 provision provides interfaces that need to be satisfied in order to
// implement a new provisioner on tsuru.
package provision

import (
	"fmt"
	"io"
)

type Status string

func (s Status) String() string {
	return string(s)
}

const (
	StatusStarted    = Status("started")
	StatusPending    = Status("pending")
	StatusDown       = Status("down")
	StatusError      = Status("error")
	StatusInstalling = Status("installing")
	StatusCreating   = Status("creating")
)

// Unit represents a provision unit. Can be a machine, container or anything
// IP-addressable.
type Unit struct {
	Name       string
	AppName    string
	Type       string
	InstanceId string
	Machine    int
	Ip         string
	Status     Status
}

// Named is something that has a name, providing the GetName method.
type Named interface {
	GetName() string
}

// AppUnit represents a unit in an app.
type AppUnit interface {
	Named

	// Returns the number of the unit.
	GetMachine() int

	// Returns the status of the unit.
	GetStatus() Status

	// Returns the IP of the unit.
	GetIp() string

	// Returns the instance id of the unit.
	GetInstanceId() string
}

// App represents a tsuru app.
//
// It contains only relevant information for provisioning.
type App interface {
	Named

	// Log should be used to log messages in the app.
	Log(message, source string) error

	// GetPlatform returns the platform (type) of the app. It is equivalent
	// to the Unit `Type` field.
	GetPlatform() string

	// ProvisionUnits returns all units of the app, in a slice.
	ProvisionUnits() []AppUnit

	// RemoveUnit removes the given unit from the app.
	RemoveUnit(id string) error

	// Run executes the command in app units, sourcing apprc before running the
	// command.
	Run(cmd string, w io.Writer) error

	// Restart restarts the application process
	Restart(io.Writer) error

	// Ready marks the app as ready, meaning that user can deploy code to
	// it.
	Ready() error
}

// Provisioner is the basic interface of this package.
//
// Any tsuru provisioner must implement this interface in order to provision
// tsuru apps.
//
// Tsuru comes with a default provisioner: juju. One can add other provisioners
// by satisfying this interface and registering it using the function Register.
type Provisioner interface {
	Deploy(App, io.Writer) error

	// Provision is called when tsuru is creating the app.
	Provision(App) error

	// Destroy is called when tsuru is destroying the app.
	Destroy(App) error

	// AddUnits adds units to an app. The first parameter is the app, the
	// second is the number of units to add.
	//
	// It returns a slice containing all added units
	AddUnits(App, uint) ([]Unit, error)

	// RemoveUnit removes a unit from the app. It receives the app and the name
	// of the unit to be removed.
	RemoveUnit(App, string) error

	// ExecuteCommand runs a command in all units of the app.
	ExecuteCommand(stdout, stderr io.Writer, app App, cmd string, args ...string) error

	// Restart restarts the app.
	Restart(App) error

	// CollectStatus returns information about all provisioned units. It's used
	// by tsuru collector when updating the status of apps in the database.
	CollectStatus() ([]Unit, error)

	// Addr returns the address for an app. It will probably be a DNS name
	// or IP address.
	//
	// Tsuru will use this method to get the IP (althought it might not be
	// an actual IP, collector calls it "IP") of the app from the
	// provisioner.
	Addr(App) (string, error)

	// InstallDeps installs the dependencies required for the application
	// to run and writes the log in the received writer
	InstallDeps(app App, w io.Writer) error
}

var provisioners = make(map[string]Provisioner)

// Register registers a new provisioner in the Provisioner registry.
func Register(name string, p Provisioner) {
	provisioners[name] = p
}

// Get gets the named provisioner from the registry.
func Get(name string) (Provisioner, error) {
	p, ok := provisioners[name]
	if !ok {
		return nil, fmt.Errorf("Unknown provisioner: %q.", name)
	}
	return p, nil
}

type Error struct {
	Reason string
	Err    error
}

func (e *Error) Error() string {
	var err string
	if e.Err != nil {
		err = e.Err.Error() + ": " + e.Reason
	} else {
		err = e.Reason
	}
	return err
}
<|endoftext|>


<commit_before>package render

import (
	"image"
	"image/draw"

	"github.com/oakmound/oak/alg/floatgeom"
	"github.com/oakmound/oak/render/mod"
)

// Composite Types, distinct from Compound Types,
// Display all of their parts at the same time,
// and respect the positions and layers of their
// parts.
type Composite struct {
	LayeredPoint
	rs []Modifiable
}

// NewComposite creates a Composite
func NewComposite(sl ...Modifiable) *Composite {
	cs := new(Composite)
	cs.LayeredPoint = NewLayeredPoint(0, 0, 0)
	cs.rs = sl
	return cs
}

// AppendOffset adds a new offset modifiable to the composite
func (cs *Composite) AppendOffset(r Modifiable, p floatgeom.Point2) {
	r.SetPos(p.X(), p.Y())
	cs.Append(r)
}

// Append adds a renderable as is to the composite
func (cs *Composite) Append(r Modifiable) {
	cs.rs = append(cs.rs, r)
}

// SetIndex places a renderable at a certain point in the composites renderable slice
func (cs *Composite) SetIndex(i int, r Modifiable) {
	cs.rs[i] = r
}

// Len returns the number of renderables in this composite.
func (cs *Composite) Len() int {
	return len(cs.rs)
}

// AddOffset offsets all renderables in the composite by a vector
func (cs *Composite) AddOffset(i int, p floatgeom.Point2) {
	if i < len(cs.rs) {
		cs.rs[i].SetPos(p.X(), p.Y())
	}
}

// SetOffsets applies the initial offsets to the entire Composite
func (cs *Composite) SetOffsets(vs ...floatgeom.Point2) {
	for i, v := range vs {
		if i < len(cs.rs) {
			cs.rs[i].SetPos(v.X(), v.Y())
		}
	}
}

// Get returns a renderable at the given index within the composite
func (cs *Composite) Get(i int) Modifiable {
	return cs.rs[i]
}

// DrawOffset draws the Composite with some offset from its logical position (and therefore sub renderables logical positions).
func (cs *Composite) DrawOffset(buff draw.Image, xOff, yOff float64) {
	for _, c := range cs.rs {
		c.DrawOffset(buff, cs.X()+xOff, cs.Y()+yOff)
	}
}

// Draw draws the Composite at its logical position
func (cs *Composite) Draw(buff draw.Image) {
	for _, c := range cs.rs {
		c.DrawOffset(buff, cs.X(), cs.Y())
	}
}

// UnDraw stops the composite from being drawn
func (cs *Composite) UnDraw() {
	cs.layer = Undraw
	for _, c := range cs.rs {
		c.UnDraw()
	}
}

// GetRGBA does not work on a composite and therefore returns nil
func (cs *Composite) GetRGBA() *image.RGBA {
	return nil
}

// Modify applies mods to the composite
func (cs *Composite) Modify(ms ...mod.Mod) Modifiable {
	for _, r := range cs.rs {
		r.Modify(ms...)
	}
	return cs
}

// Filter filters each component part of this composite by all of the inputs.
func (cs *Composite) Filter(fs ...mod.Filter) {
	for _, r := range cs.rs {
		r.Filter(fs...)
	}
}

// Copy makes a new Composite with the same renderables
func (cs *Composite) Copy() Modifiable {
	cs2 := new(Composite)
	cs2.layer = cs.layer
	cs2.Vector = cs.Vector
	cs2.rs = make([]Modifiable, len(cs.rs))
	for i, v := range cs.rs {
		cs2.rs[i] = v.Copy()
	}
	return cs2
}

// CompositeR keeps track of a set of renderables at a location
type CompositeR struct {
	LayeredPoint
	toPush []Renderable
	rs     []Renderable
}

// NewCompositeR creates a new CompositeR from a slice of renderables
func NewCompositeR(sl ...Renderable) *CompositeR {
	cs := new(CompositeR)
	cs.LayeredPoint = NewLayeredPoint(0, 0, 0)
	cs.toPush = make([]Renderable, 0)
	cs.rs = sl
	return cs
}

// AppendOffset adds a new renderable to CompositeR with an offset
func (cs *CompositeR) AppendOffset(r Renderable, p floatgeom.Point2) {
	r.SetPos(p.X(), p.Y())
	cs.Append(r)
}

// AddOffset adds an offset to a given renderable of the slice
func (cs *CompositeR) AddOffset(i int, p floatgeom.Point2) {
	if i < len(cs.rs) {
		cs.rs[i].SetPos(p.X(), p.Y())
	}
}

// Append adds a new renderable to CompositeR
func (cs *CompositeR) Append(r Renderable) {
	cs.rs = append(cs.rs, r)
}

// Len returns the number of renderables in this composite.
func (cs *CompositeR) Len() int {
	return len(cs.rs)
}

// SetIndex places a renderable at a certain point in the composites renderable slice
func (cs *CompositeR) SetIndex(i int, r Renderable) {
	cs.rs[i] = r
}

// SetOffsets sets all renderables in CompositeR to the passed in Vector positions positions
func (cs *CompositeR) SetOffsets(ps ...floatgeom.Point2) {
	for i, p := range ps {
		if i < len(cs.rs) {
			cs.rs[i].SetPos(p.X(), p.Y())
		}
	}
}

// DrawOffset Draws the CompositeR with an offset from its logical location.
func (cs *CompositeR) DrawOffset(buff draw.Image, xOff, yOff float64) {
	for _, c := range cs.rs {
		c.DrawOffset(buff, cs.X()+xOff, cs.Y()+yOff)
	}
}

// Draw draws the CompositeR at its logical location and therefore its consituent renderables as well
func (cs *CompositeR) Draw(buff draw.Image) {
	for _, c := range cs.rs {
		c.DrawOffset(buff, cs.X(), cs.Y())
	}
}

// UnDraw undraws the CompositeR and its consituent renderables
func (cs *CompositeR) UnDraw() {
	cs.layer = Undraw
	for _, c := range cs.rs {
		c.UnDraw()
	}
}

// GetRGBA always returns nil from Composites
func (cs *CompositeR) GetRGBA() *image.RGBA {
	return nil
}

// Get returns renderable from a given index in CompositeR
func (cs *CompositeR) Get(i int) Renderable {
	return cs.rs[i]
}

// Add stages a renderable to be added to the Composite at the next PreDraw
func (cs *CompositeR) Add(r Renderable, _ ...int) Renderable {
	cs.toPush = append(cs.toPush, r)
	return r
}

// Replace updates a renderable in the CompositeR to the new Renderable
func (cs *CompositeR) Replace(r1, r2 Renderable, i int) {
	cs.Add(r2, i)
	r1.UnDraw()
}

// PreDraw updates the CompositeR with the new renderables to add. This helps keep consistency and mitigates the threat of unsafe operations.
func (cs *CompositeR) PreDraw() {
	push := cs.toPush
	cs.toPush = []Renderable{}
	cs.rs = append(cs.rs, push...)
}

// Copy returns a new composite with the same length slice of renderables but no actual renderables...
// CompositeRs cannot have their internal elements copied,
// as renderables cannot be copied.
func (cs *CompositeR) Copy() Stackable {
	cs2 := new(CompositeR)
	cs2.LayeredPoint = cs.LayeredPoint
	cs2.rs = make([]Renderable, len(cs.rs))
	return cs2
}

func (cs *CompositeR) draw(world draw.Image, viewPos image.Point, screenW, screenH int) {
	realLength := len(cs.rs)
	for i := 0; i < realLength; i++ {
		r := cs.rs[i]
		for (r == nil || r.GetLayer() == Undraw) && realLength > i {
			cs.rs[i], cs.rs[realLength-1] = cs.rs[realLength-1], cs.rs[i]
			realLength--
			r = cs.rs[i]
		}
		if realLength == i {
			break
		}
		x := int(r.X())
		y := int(r.Y())
		x2 := x
		y2 := y
		w, h := r.GetDims()
		x += w
		y += h
		if x > viewPos.X && y > viewPos.Y &&
			x2 < viewPos.X+screenW && y2 < viewPos.Y+screenH {

			if InDrawPolygon(x, y, x2, y2) {
				r.DrawOffset(world, float64(-viewPos.X), float64(-viewPos.Y))
			}
		}
	}
	cs.rs = cs.rs[0:realLength]
}
<commit_msg>Adds Prepend to composites<commit_after>package render

import (
	"image"
	"image/draw"

	"github.com/oakmound/oak/alg/floatgeom"
	"github.com/oakmound/oak/render/mod"
)

// Composite Types, distinct from Compound Types,
// Display all of their parts at the same time,
// and respect the positions and layers of their
// parts.
type Composite struct {
	LayeredPoint
	rs []Modifiable
}

// NewComposite creates a Composite
func NewComposite(sl ...Modifiable) *Composite {
	cs := new(Composite)
	cs.LayeredPoint = NewLayeredPoint(0, 0, 0)
	cs.rs = sl
	return cs
}

// AppendOffset adds a new offset modifiable to the composite
func (cs *Composite) AppendOffset(r Modifiable, p floatgeom.Point2) {
	r.SetPos(p.X(), p.Y())
	cs.Append(r)
}

// Append adds a renderable as is to the composite
func (cs *Composite) Append(r Modifiable) {
	cs.rs = append(cs.rs, r)
}

// Prepend adds a new renderable to the front of the CompositeR.
func (cs *Composite) Prepend(r Modifiable) {
	cs.rs = append([]Modifiable{r}, cs.rs...)
}

// SetIndex places a renderable at a certain point in the composites renderable slice
func (cs *Composite) SetIndex(i int, r Modifiable) {
	cs.rs[i] = r
}

// Len returns the number of renderables in this composite.
func (cs *Composite) Len() int {
	return len(cs.rs)
}

// AddOffset offsets all renderables in the composite by a vector
func (cs *Composite) AddOffset(i int, p floatgeom.Point2) {
	if i < len(cs.rs) {
		cs.rs[i].SetPos(p.X(), p.Y())
	}
}

// SetOffsets applies the initial offsets to the entire Composite
func (cs *Composite) SetOffsets(vs ...floatgeom.Point2) {
	for i, v := range vs {
		if i < len(cs.rs) {
			cs.rs[i].SetPos(v.X(), v.Y())
		}
	}
}

// Get returns a renderable at the given index within the composite
func (cs *Composite) Get(i int) Modifiable {
	return cs.rs[i]
}

// DrawOffset draws the Composite with some offset from its logical position (and therefore sub renderables logical positions).
func (cs *Composite) DrawOffset(buff draw.Image, xOff, yOff float64) {
	for _, c := range cs.rs {
		c.DrawOffset(buff, cs.X()+xOff, cs.Y()+yOff)
	}
}

// Draw draws the Composite at its logical position
func (cs *Composite) Draw(buff draw.Image) {
	for _, c := range cs.rs {
		c.DrawOffset(buff, cs.X(), cs.Y())
	}
}

// UnDraw stops the composite from being drawn
func (cs *Composite) UnDraw() {
	cs.layer = Undraw
	for _, c := range cs.rs {
		c.UnDraw()
	}
}

// GetRGBA does not work on a composite and therefore returns nil
func (cs *Composite) GetRGBA() *image.RGBA {
	return nil
}

// Modify applies mods to the composite
func (cs *Composite) Modify(ms ...mod.Mod) Modifiable {
	for _, r := range cs.rs {
		r.Modify(ms...)
	}
	return cs
}

// Filter filters each component part of this composite by all of the inputs.
func (cs *Composite) Filter(fs ...mod.Filter) {
	for _, r := range cs.rs {
		r.Filter(fs...)
	}
}

// Copy makes a new Composite with the same renderables
func (cs *Composite) Copy() Modifiable {
	cs2 := new(Composite)
	cs2.layer = cs.layer
	cs2.Vector = cs.Vector
	cs2.rs = make([]Modifiable, len(cs.rs))
	for i, v := range cs.rs {
		cs2.rs[i] = v.Copy()
	}
	return cs2
}

// CompositeR keeps track of a set of renderables at a location
type CompositeR struct {
	LayeredPoint
	toPush []Renderable
	rs     []Renderable
}

// NewCompositeR creates a new CompositeR from a slice of renderables
func NewCompositeR(sl ...Renderable) *CompositeR {
	cs := new(CompositeR)
	cs.LayeredPoint = NewLayeredPoint(0, 0, 0)
	cs.toPush = make([]Renderable, 0)
	cs.rs = sl
	return cs
}

// AppendOffset adds a new renderable to CompositeR with an offset
func (cs *CompositeR) AppendOffset(r Renderable, p floatgeom.Point2) {
	r.SetPos(p.X(), p.Y())
	cs.Append(r)
}

// AddOffset adds an offset to a given renderable of the slice
func (cs *CompositeR) AddOffset(i int, p floatgeom.Point2) {
	if i < len(cs.rs) {
		cs.rs[i].SetPos(p.X(), p.Y())
	}
}

// Append adds a new renderable to the end of the CompositeR.
func (cs *CompositeR) Append(r Renderable) {
	cs.rs = append(cs.rs, r)
}

// Prepend adds a new renderable to the front of the CompositeR.
func (cs *CompositeR) Prepend(r Renderable) {
	cs.rs = append([]Renderable{r}, cs.rs...)
}

// Len returns the number of renderables in this composite.
func (cs *CompositeR) Len() int {
	return len(cs.rs)
}

// SetIndex places a renderable at a certain point in the composites renderable slice
func (cs *CompositeR) SetIndex(i int, r Renderable) {
	cs.rs[i] = r
}

// SetOffsets sets all renderables in CompositeR to the passed in Vector positions positions
func (cs *CompositeR) SetOffsets(ps ...floatgeom.Point2) {
	for i, p := range ps {
		if i < len(cs.rs) {
			cs.rs[i].SetPos(p.X(), p.Y())
		}
	}
}

// DrawOffset Draws the CompositeR with an offset from its logical location.
func (cs *CompositeR) DrawOffset(buff draw.Image, xOff, yOff float64) {
	for _, c := range cs.rs {
		c.DrawOffset(buff, cs.X()+xOff, cs.Y()+yOff)
	}
}

// Draw draws the CompositeR at its logical location and therefore its consituent renderables as well
func (cs *CompositeR) Draw(buff draw.Image) {
	for _, c := range cs.rs {
		c.DrawOffset(buff, cs.X(), cs.Y())
	}
}

// UnDraw undraws the CompositeR and its consituent renderables
func (cs *CompositeR) UnDraw() {
	cs.layer = Undraw
	for _, c := range cs.rs {
		c.UnDraw()
	}
}

// GetRGBA always returns nil from Composites
func (cs *CompositeR) GetRGBA() *image.RGBA {
	return nil
}

// Get returns renderable from a given index in CompositeR
func (cs *CompositeR) Get(i int) Renderable {
	return cs.rs[i]
}

// Add stages a renderable to be added to the Composite at the next PreDraw
func (cs *CompositeR) Add(r Renderable, _ ...int) Renderable {
	cs.toPush = append(cs.toPush, r)
	return r
}

// Replace updates a renderable in the CompositeR to the new Renderable
func (cs *CompositeR) Replace(r1, r2 Renderable, i int) {
	cs.Add(r2, i)
	r1.UnDraw()
}

// PreDraw updates the CompositeR with the new renderables to add. This helps keep consistency and mitigates the threat of unsafe operations.
func (cs *CompositeR) PreDraw() {
	push := cs.toPush
	cs.toPush = []Renderable{}
	cs.rs = append(cs.rs, push...)
}

// Copy returns a new composite with the same length slice of renderables but no actual renderables...
// CompositeRs cannot have their internal elements copied,
// as renderables cannot be copied.
func (cs *CompositeR) Copy() Stackable {
	cs2 := new(CompositeR)
	cs2.LayeredPoint = cs.LayeredPoint
	cs2.rs = make([]Renderable, len(cs.rs))
	return cs2
}

func (cs *CompositeR) draw(world draw.Image, viewPos image.Point, screenW, screenH int) {
	realLength := len(cs.rs)
	for i := 0; i < realLength; i++ {
		r := cs.rs[i]
		for (r == nil || r.GetLayer() == Undraw) && realLength > i {
			cs.rs[i], cs.rs[realLength-1] = cs.rs[realLength-1], cs.rs[i]
			realLength--
			r = cs.rs[i]
		}
		if realLength == i {
			break
		}
		x := int(r.X())
		y := int(r.Y())
		x2 := x
		y2 := y
		w, h := r.GetDims()
		x += w
		y += h
		if x > viewPos.X && y > viewPos.Y &&
			x2 < viewPos.X+screenW && y2 < viewPos.Y+screenH {

			if InDrawPolygon(x, y, x2, y2) {
				r.DrawOffset(world, float64(-viewPos.X), float64(-viewPos.Y))
			}
		}
	}
	cs.rs = cs.rs[0:realLength]
}
<|endoftext|>


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

// Package googleapi contains the common code shared by all Google API
// libraries.
package googleapi

import (
	"bytes"
	"fmt"
	"http"
	"io"
	"io/ioutil"
	"json"
	"mime/multipart"
	"net/textproto"
	"os"
	"strings"
	"url"
)

// ContentTyper is an interface for Readers which know (or would like
// to override) their Content-Type. If a media body doesn't implement
// ContentTyper, the type is sniffed from the content using
// http.DetectContentType.
type ContentTyper interface {
	ContentType() string
}

const Version = "0.5"

type Error struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
}

func (e *Error) String() string {
	return fmt.Sprintf("googleapi: Error %d: %s", e.Code, e.Message)
}

type errorReply struct {
	Error *Error `json:"error"`
}

func CheckResponse(res *http.Response) os.Error {
	if res.StatusCode >= 200 && res.StatusCode <= 299 {
		return nil
	}
	slurp, err := ioutil.ReadAll(res.Body)
	if err == nil {
		jerr := new(errorReply)
		err = json.Unmarshal(slurp, jerr)
		if err == nil && jerr.Error != nil {
			return jerr.Error
		}
	}
	return fmt.Errorf("googleapi: got HTTP response code %d and error reading body: %v",
		res.StatusCode, err)
}

type MarshalStyle bool

var WithDataWrapper = MarshalStyle(true)
var WithoutDataWrapper = MarshalStyle(false)

func (wrap MarshalStyle) JSONReader(v interface{}) (io.Reader, os.Error) {
	buf := new(bytes.Buffer)
	if wrap {
		buf.Write([]byte(`{"data": `))
	}
	err := json.NewEncoder(buf).Encode(v)
	if err != nil {
		return nil, err
	}
	if wrap {
		buf.Write([]byte(`}`))
	}
	return buf, nil
}

func getMediaType(media io.Reader) (io.Reader, string) {
	if typer, ok := media.(ContentTyper); ok {
		return media, typer.ContentType()
	}

	typ := "application/octet-stream"
	buf := make([]byte, 1024)
	n, err := media.Read(buf)
	buf = buf[:n]
	if err == nil {
		typ = http.DetectContentType(buf)
	}
	return io.MultiReader(bytes.NewBuffer(buf), media), typ
}

type Lengther interface {
	Len() int
}

// endingWithErrorReader from r until it returns an error.  If the
// final error from r is os.EOF and e is non-nil, e is used instead.
type endingWithErrorReader struct {
	r io.Reader
	e os.Error
}

func (er endingWithErrorReader) Read(p []byte) (n int, err os.Error) {
	n, err = er.r.Read(p)
	if err == os.EOF && er.e != nil {
		err = er.e
	}
	return
}

func getReaderSize(r io.Reader) (io.Reader, int64) {
	// Ideal case, the reader knows its own size.
	if lr, ok := r.(Lengther); ok {
		return r, int64(lr.Len())
	}

	// But maybe it's a seeker and we can seek to the end to find its size.
	if s, ok := r.(io.Seeker); ok {
		pos0, err := s.Seek(0, os.SEEK_CUR)
		if err == nil {
			posend, err := s.Seek(0, os.SEEK_END)
			if err == nil {
				_, err = s.Seek(pos0, os.SEEK_SET)
				if err == nil {
					return r, posend - pos0
				} else {
					// We moved it forward but can't restore it.
					// Seems unlikely, but can't really restore now.
					return endingWithErrorReader{strings.NewReader(""), err}, posend - pos0
				}
			}
		}
	}

	// Otherwise we have to make a copy to calculate how big the reader is.
	buf := new(bytes.Buffer)
	// TODO(bradfitz): put a cap on this copy? spill to disk after
	// a certain point?
	_, err := io.Copy(buf, r)
	return endingWithErrorReader{buf, err}, int64(buf.Len())
}

func typeHeader(contentType string) textproto.MIMEHeader {
	h := make(textproto.MIMEHeader)
	h.Set("Content-Type", contentType)
	return h
}

// countingWriter counts the number of bytes it receives to write, but
// discards them.
type countingWriter struct {
	n *int64
}

func (w countingWriter) Write(p []byte) (int, os.Error) {
	*w.n += int64(len(p))
	return len(p), nil
}

// ConditionallyIncludeMedia does nothing if media is nil.
//
// bodyp is an in/out parameter.  It should initially point to the
// reader of the application/json (or whatever) payload to send in the
// API request.  It's updated to point to the multipart body reader.
//
// ctypep is an in/out parameter.  It should initially point to the
// content type of the bodyp, usually "application/json".  It's updated
// to the "multipart/related" content type, with random boundary.
//
// The return value is the content-length of the entire multpart body.
func ConditionallyIncludeMedia(media io.Reader, bodyp *io.Reader, ctypep *string) (totalContentLength int64, ok bool) {
	if media == nil {
		return
	}
	// Get the media type and size. The type check might return a
	// different reader instance, so do the size check first,
	// which looks at the specific type of the io.Reader.
	media, mediaSize := getReaderSize(media)
	media, mediaType := getMediaType(media)
	body, bodyType := *bodyp, *ctypep
	body, bodySize := getReaderSize(body)

	// Calculate how big the the multipart will be.
	{
		totalContentLength = bodySize + mediaSize
		mpw := multipart.NewWriter(countingWriter{&totalContentLength})
		mpw.CreatePart(typeHeader(bodyType))
		mpw.CreatePart(typeHeader(mediaType))
		mpw.Close()
	}

	pr, pw := io.Pipe()
	mpw := multipart.NewWriter(pw)
	*bodyp = pr
	*ctypep = "multipart/related; boundary=" + mpw.Boundary()
	go func() {
		defer pw.Close()
		defer mpw.Close()

		w, err := mpw.CreatePart(typeHeader(bodyType))
		if err != nil {
			return
		}
		_, err = io.Copy(w, body)
		if err != nil {
			return
		}

		w, err = mpw.CreatePart(typeHeader(mediaType))
		if err != nil {
			return
		}
		_, err = io.Copy(w, media)
		if err != nil {
			return
		}
	}()
	return totalContentLength, true
}

func ResolveRelative(basestr, relstr string) string {
	u, _ := url.Parse(basestr)
	rel, _ := url.Parse(relstr)
	u = u.ResolveReference(rel)
	us := u.String()
	us = strings.Replace(us, "%7B", "{", -1)
	us = strings.Replace(us, "%7D", "}", -1)
	return us
}
<commit_msg>gofix for go 1<commit_after>// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package googleapi contains the common code shared by all Google API
// libraries.
package googleapi

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"net/textproto"
	"net/url"
	"os"
	"strings"
)

// ContentTyper is an interface for Readers which know (or would like
// to override) their Content-Type. If a media body doesn't implement
// ContentTyper, the type is sniffed from the content using
// http.DetectContentType.
type ContentTyper interface {
	ContentType() string
}

const Version = "0.5"

type Error struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
}

func (e *Error) Error() string {
	return fmt.Sprintf("googleapi: Error %d: %s", e.Code, e.Message)
}

type errorReply struct {
	Error *Error `json:"error"`
}

func CheckResponse(res *http.Response) error {
	if res.StatusCode >= 200 && res.StatusCode <= 299 {
		return nil
	}
	slurp, err := ioutil.ReadAll(res.Body)
	if err == nil {
		jerr := new(errorReply)
		err = json.Unmarshal(slurp, jerr)
		if err == nil && jerr.Error != nil {
			return jerr.Error
		}
	}
	return fmt.Errorf("googleapi: got HTTP response code %d and error reading body: %v",
		res.StatusCode, err)
}

type MarshalStyle bool

var WithDataWrapper = MarshalStyle(true)
var WithoutDataWrapper = MarshalStyle(false)

func (wrap MarshalStyle) JSONReader(v interface{}) (io.Reader, error) {
	buf := new(bytes.Buffer)
	if wrap {
		buf.Write([]byte(`{"data": `))
	}
	err := json.NewEncoder(buf).Encode(v)
	if err != nil {
		return nil, err
	}
	if wrap {
		buf.Write([]byte(`}`))
	}
	return buf, nil
}

func getMediaType(media io.Reader) (io.Reader, string) {
	if typer, ok := media.(ContentTyper); ok {
		return media, typer.ContentType()
	}

	typ := "application/octet-stream"
	buf := make([]byte, 1024)
	n, err := media.Read(buf)
	buf = buf[:n]
	if err == nil {
		typ = http.DetectContentType(buf)
	}
	return io.MultiReader(bytes.NewBuffer(buf), media), typ
}

type Lengther interface {
	Len() int
}

// endingWithErrorReader from r until it returns an error.  If the
// final error from r is os.EOF and e is non-nil, e is used instead.
type endingWithErrorReader struct {
	r io.Reader
	e error
}

func (er endingWithErrorReader) Read(p []byte) (n int, err error) {
	n, err = er.r.Read(p)
	if err == io.EOF && er.e != nil {
		err = er.e
	}
	return
}

func getReaderSize(r io.Reader) (io.Reader, int64) {
	// Ideal case, the reader knows its own size.
	if lr, ok := r.(Lengther); ok {
		return r, int64(lr.Len())
	}

	// But maybe it's a seeker and we can seek to the end to find its size.
	if s, ok := r.(io.Seeker); ok {
		pos0, err := s.Seek(0, os.SEEK_CUR)
		if err == nil {
			posend, err := s.Seek(0, os.SEEK_END)
			if err == nil {
				_, err = s.Seek(pos0, os.SEEK_SET)
				if err == nil {
					return r, posend - pos0
				} else {
					// We moved it forward but can't restore it.
					// Seems unlikely, but can't really restore now.
					return endingWithErrorReader{strings.NewReader(""), err}, posend - pos0
				}
			}
		}
	}

	// Otherwise we have to make a copy to calculate how big the reader is.
	buf := new(bytes.Buffer)
	// TODO(bradfitz): put a cap on this copy? spill to disk after
	// a certain point?
	_, err := io.Copy(buf, r)
	return endingWithErrorReader{buf, err}, int64(buf.Len())
}

func typeHeader(contentType string) textproto.MIMEHeader {
	h := make(textproto.MIMEHeader)
	h.Set("Content-Type", contentType)
	return h
}

// countingWriter counts the number of bytes it receives to write, but
// discards them.
type countingWriter struct {
	n *int64
}

func (w countingWriter) Write(p []byte) (int, error) {
	*w.n += int64(len(p))
	return len(p), nil
}

// ConditionallyIncludeMedia does nothing if media is nil.
//
// bodyp is an in/out parameter.  It should initially point to the
// reader of the application/json (or whatever) payload to send in the
// API request.  It's updated to point to the multipart body reader.
//
// ctypep is an in/out parameter.  It should initially point to the
// content type of the bodyp, usually "application/json".  It's updated
// to the "multipart/related" content type, with random boundary.
//
// The return value is the content-length of the entire multpart body.
func ConditionallyIncludeMedia(media io.Reader, bodyp *io.Reader, ctypep *string) (totalContentLength int64, ok bool) {
	if media == nil {
		return
	}
	// Get the media type and size. The type check might return a
	// different reader instance, so do the size check first,
	// which looks at the specific type of the io.Reader.
	media, mediaSize := getReaderSize(media)
	media, mediaType := getMediaType(media)
	body, bodyType := *bodyp, *ctypep
	body, bodySize := getReaderSize(body)

	// Calculate how big the the multipart will be.
	{
		totalContentLength = bodySize + mediaSize
		mpw := multipart.NewWriter(countingWriter{&totalContentLength})
		mpw.CreatePart(typeHeader(bodyType))
		mpw.CreatePart(typeHeader(mediaType))
		mpw.Close()
	}

	pr, pw := io.Pipe()
	mpw := multipart.NewWriter(pw)
	*bodyp = pr
	*ctypep = "multipart/related; boundary=" + mpw.Boundary()
	go func() {
		defer pw.Close()
		defer mpw.Close()

		w, err := mpw.CreatePart(typeHeader(bodyType))
		if err != nil {
			return
		}
		_, err = io.Copy(w, body)
		if err != nil {
			return
		}

		w, err = mpw.CreatePart(typeHeader(mediaType))
		if err != nil {
			return
		}
		_, err = io.Copy(w, media)
		if err != nil {
			return
		}
	}()
	return totalContentLength, true
}

func ResolveRelative(basestr, relstr string) string {
	u, _ := url.Parse(basestr)
	rel, _ := url.Parse(relstr)
	u = u.ResolveReference(rel)
	us := u.String()
	us = strings.Replace(us, "%7B", "{", -1)
	us = strings.Replace(us, "%7D", "}", -1)
	return us
}
<|endoftext|>