<commit_before>// Package sudoku is a generic solver for sudoku type puzzles. It can solve a puzzle of any shape and size.
package sudoku

import "fmt"

var (
	s4 = []Constraint{
		Unique{0, 1, 2, 3},
		Unique{4, 5, 6, 7},
		Unique{8, 9, 10, 11},
		Unique{12, 13, 14, 15},
		Unique{0, 4, 8, 12},
		Unique{1, 5, 9, 13},
		Unique{2, 6, 10, 14},
		Unique{3, 7, 11, 15},
		Unique{0, 1, 4, 5},
		Unique{2, 3, 6, 7},
		Unique{8, 9, 12, 13},
		Unique{10, 11, 14, 15},
	}
	s9 = []Constraint{
		Unique{0, 1, 2, 3, 4, 5, 6, 7, 8},
		Unique{9, 10, 11, 12, 13, 14, 15, 16, 17},
		Unique{18, 19, 20, 21, 22, 23, 24, 25, 26},
		Unique{27, 28, 29, 30, 31, 32, 33, 34, 35},
		Unique{36, 37, 38, 39, 40, 41, 42, 43, 44},
		Unique{45, 46, 47, 48, 49, 50, 51, 52, 53},
		Unique{54, 55, 56, 57, 58, 59, 60, 61, 62},
		Unique{63, 64, 65, 66, 67, 68, 69, 70, 71},
		Unique{72, 73, 74, 75, 76, 77, 78, 79, 80},
		Unique{0, 9, 18, 27, 36, 45, 54, 63, 72},
		Unique{1, 10, 19, 28, 37, 46, 55, 64, 73},
		Unique{2, 11, 20, 29, 38, 47, 56, 65, 74},
		Unique{3, 12, 21, 30, 39, 48, 57, 66, 75},
		Unique{4, 13, 22, 31, 40, 49, 58, 67, 76},
		Unique{5, 14, 23, 32, 41, 50, 59, 68, 77},
		Unique{6, 15, 24, 33, 42, 51, 60, 69, 78},
		Unique{7, 16, 25, 34, 43, 52, 61, 70, 79},
		Unique{8, 17, 26, 35, 44, 53, 62, 71, 80},
		Unique{0, 1, 2, 9, 10, 11, 18, 19, 20},
		Unique{3, 4, 5, 12, 13, 14, 21, 22, 23},
		Unique{6, 7, 8, 15, 16, 17, 24, 25, 26},
		Unique{27, 28, 29, 36, 37, 38, 45, 46, 47},
		Unique{30, 31, 32, 39, 40, 41, 48, 49, 50},
		Unique{33, 34, 35, 42, 43, 44, 51, 52, 53},
		Unique{54, 55, 56, 63, 64, 65, 72, 73, 74},
		Unique{57, 58, 59, 66, 67, 68, 75, 76, 77},
		Unique{60, 61, 62, 69, 70, 71, 78, 79, 80},
	}
)

// MakeBox is a helper function to make it easier to create the sections in standard rectangular puzzles
func MakeBox(gridWidth, gridHeight, boxWidth, boxHeight int) []Constraint {
	toRet := make([]Constraint, 0, gridWidth/boxWidth*gridHeight/boxHeight)
	for j := 0; j < gridHeight; j += boxHeight {
		for i := 0; i < gridWidth; i += boxWidth {
			thisGrid := make(Unique, 0, boxWidth*boxHeight)
			for y := 0; y < boxHeight; y++ {
				for x := 0; x < boxWidth; x++ {
					thisGrid = append(thisGrid, i+x+(j+y)*gridWidth)
				}
			}
			toRet = append(toRet, thisGrid)
		}
	}
	return toRet
}

// Solve9 is a sudoku puzzle of the standard 9x9 format
func Solve9(data []int) bool {
	if len(data) != 81 {
		return false
	}
	s := Sudoku{
		data:        data,
		chars:       9,
		constraints: s9,
	}
	return s.Solve()
}

// Solve4 is a sudoku puzzle of the 4x4 format
func Solve4(data []int) bool {
	if len(data) != 16 {
		return false
	}
	s := Sudoku{
		data:        data,
		chars:       4,
		constraints: s4,
	}
	return s.Solve()
}

// Solve allows the creation of a non-standard Sudoku puzzle and solves it.
//
// data is the puzzle information, layed out left to right, then top to bottom
//
// chars is any valid 'character' the puzzle uses - 0 is used for an unfilled space
//
// structure is a slice of sections, each of which is a slice of positions, len(chars)
// in length, which describes the rows, columns, boxes or other shapes in which there
// can only be one of each character
//
// Will return true if puzzle is solveable and the solution will be stored in the data slice.
// Upon a failure, will return false and the data slice will be as original.
func Solve(data []int, chars int, constraints []Constraint) bool {
	s := Sudoku{data, chars, constraints}
	return s.Solve()
}

func slicePos(s []int, p int) int {
	for n, sp := range s {
		if sp == p {
			return n
		}
	}
	return -1
}

// Constraint defines the interface through which the character constraints are processed
type Constraint interface {
	Constrain(*Sudoku, int, []bool) bool
}

// Unique represents a section of data where each cell needs to be different
type Unique []int

// Constrain implements the Constraint interface
func (u Unique) Constrain(s *Sudoku, pos int, marked []bool) bool {
	if slicePos([]int(u), pos) == -1 {
		return true
	}
	myMark := make([]int, 0, len(u))
	for _, p := range u {
		if mp := s.data[p]; mp != 0 {
			if slicePos(myMark, mp) != -1 {
				fmt.Println(u, pos, myMark, mp)
				return false
			}
			myMark = append(myMark, mp)
			marked[mp] = true
		}
	}
	return true
}

/*type Sorted []int

func (s Sorted) Constrain(su *Sudoku, pos int, marked []bool) bool {
	if slicePos([]int(s), pos) == -1 {
		return true
	}
	num := 0
	for _, p := range s {
		if mp := su.data[p]; mp != 0 {
			if mp > num {
				num = mp
			} else {
				return false
			}
		} else if mp == pos {

		}
	}
	return true
}

type UniqueSum struct {
	positions []int
	total     int
}

func (u UniqueSum) Constrain(s *Sudoku, pos int, marked []bool) bool {
	if slicePos(u.positions, pos) == -1 {
		return true
	}
	total := 0
	myMark := make([]int, len(u.positions))
	unmarked := 0
	for _, p := range u.positions {
		if mp := s.data[p]; mp == 0 {
			unmarked++
		} else {
			if slicePos(myMark, mp) != -1 {
				return false
			}
			myMark = append(myMark, mp)
			marked[slicePos(s.chars, mp)] = true
			total += mp
		}
	}
	left := u.total - total
	if left < 0 {
		return false
	}
	return true
}*/

// Sudoku puzzle information
type Sudoku struct {
	data        []int
	chars       int
	constraints []Constraint
}

func (s *Sudoku) possible(pos int) []int {
	if pos < 0 || pos > len(s.data) || s.data[pos] != 0 {
		return nil
	}
	marked := make([]bool, s.chars+1)
	for _, c := range s.constraints {
		any := c.Constrain(s, pos, marked)
		if !any {
			return []int{}
		}
	}
	toRet := make([]int, 0, s.chars)
	for p, m := range marked[1:] {
		if !m {
			toRet = append(toRet, p+1)
		}
	}
	return toRet
}

// Solve will solve any solveable puzzle and return whether is was sucessful.
func (s *Sudoku) Solve() bool {
	l := len(s.data)
	possibilities := make([][]int, l)
	var pos int
	for ; pos < l; pos++ {
		if p := s.possible(pos); p != nil {
			possibilities[pos] = p
			break
		}
	}
	for pos < l {
		if len(possibilities[pos]) == 0 {
			s.data[pos] = 0
			for pos--; pos >= 0 && len(possibilities[pos]) == 0; pos-- {
				if possibilities[pos] != nil {
					s.data[pos] = 0
				}
			}
			if pos < 0 {
				return false
			}
			continue
		}
		s.data[pos] = possibilities[pos][0]
		possibilities[pos] = possibilities[pos][1:]
		for pos++; pos < l; pos++ {
			if p := s.possible(pos); p != nil {
				possibilities[pos] = p
				break
			}
		}
	}
	return true
}
<commit_msg>Removed logging<commit_after>// Package sudoku is a generic solver for sudoku type puzzles. It can solve a puzzle of any shape and size.
package sudoku

var (
	s4 = []Constraint{
		Unique{0, 1, 2, 3},
		Unique{4, 5, 6, 7},
		Unique{8, 9, 10, 11},
		Unique{12, 13, 14, 15},
		Unique{0, 4, 8, 12},
		Unique{1, 5, 9, 13},
		Unique{2, 6, 10, 14},
		Unique{3, 7, 11, 15},
		Unique{0, 1, 4, 5},
		Unique{2, 3, 6, 7},
		Unique{8, 9, 12, 13},
		Unique{10, 11, 14, 15},
	}
	s9 = []Constraint{
		Unique{0, 1, 2, 3, 4, 5, 6, 7, 8},
		Unique{9, 10, 11, 12, 13, 14, 15, 16, 17},
		Unique{18, 19, 20, 21, 22, 23, 24, 25, 26},
		Unique{27, 28, 29, 30, 31, 32, 33, 34, 35},
		Unique{36, 37, 38, 39, 40, 41, 42, 43, 44},
		Unique{45, 46, 47, 48, 49, 50, 51, 52, 53},
		Unique{54, 55, 56, 57, 58, 59, 60, 61, 62},
		Unique{63, 64, 65, 66, 67, 68, 69, 70, 71},
		Unique{72, 73, 74, 75, 76, 77, 78, 79, 80},
		Unique{0, 9, 18, 27, 36, 45, 54, 63, 72},
		Unique{1, 10, 19, 28, 37, 46, 55, 64, 73},
		Unique{2, 11, 20, 29, 38, 47, 56, 65, 74},
		Unique{3, 12, 21, 30, 39, 48, 57, 66, 75},
		Unique{4, 13, 22, 31, 40, 49, 58, 67, 76},
		Unique{5, 14, 23, 32, 41, 50, 59, 68, 77},
		Unique{6, 15, 24, 33, 42, 51, 60, 69, 78},
		Unique{7, 16, 25, 34, 43, 52, 61, 70, 79},
		Unique{8, 17, 26, 35, 44, 53, 62, 71, 80},
		Unique{0, 1, 2, 9, 10, 11, 18, 19, 20},
		Unique{3, 4, 5, 12, 13, 14, 21, 22, 23},
		Unique{6, 7, 8, 15, 16, 17, 24, 25, 26},
		Unique{27, 28, 29, 36, 37, 38, 45, 46, 47},
		Unique{30, 31, 32, 39, 40, 41, 48, 49, 50},
		Unique{33, 34, 35, 42, 43, 44, 51, 52, 53},
		Unique{54, 55, 56, 63, 64, 65, 72, 73, 74},
		Unique{57, 58, 59, 66, 67, 68, 75, 76, 77},
		Unique{60, 61, 62, 69, 70, 71, 78, 79, 80},
	}
)

// MakeBox is a helper function to make it easier to create the sections in standard rectangular puzzles
func MakeBox(gridWidth, gridHeight, boxWidth, boxHeight int) []Constraint {
	toRet := make([]Constraint, 0, gridWidth/boxWidth*gridHeight/boxHeight)
	for j := 0; j < gridHeight; j += boxHeight {
		for i := 0; i < gridWidth; i += boxWidth {
			thisGrid := make(Unique, 0, boxWidth*boxHeight)
			for y := 0; y < boxHeight; y++ {
				for x := 0; x < boxWidth; x++ {
					thisGrid = append(thisGrid, i+x+(j+y)*gridWidth)
				}
			}
			toRet = append(toRet, thisGrid)
		}
	}
	return toRet
}

// Solve9 is a sudoku puzzle of the standard 9x9 format
func Solve9(data []int) bool {
	if len(data) != 81 {
		return false
	}
	s := Sudoku{
		data:        data,
		chars:       9,
		constraints: s9,
	}
	return s.Solve()
}

// Solve4 is a sudoku puzzle of the 4x4 format
func Solve4(data []int) bool {
	if len(data) != 16 {
		return false
	}
	s := Sudoku{
		data:        data,
		chars:       4,
		constraints: s4,
	}
	return s.Solve()
}

// Solve allows the creation of a non-standard Sudoku puzzle and solves it.
//
// data is the puzzle information, layed out left to right, then top to bottom
//
// chars is any valid 'character' the puzzle uses - 0 is used for an unfilled space
//
// structure is a slice of sections, each of which is a slice of positions, len(chars)
// in length, which describes the rows, columns, boxes or other shapes in which there
// can only be one of each character
//
// Will return true if puzzle is solveable and the solution will be stored in the data slice.
// Upon a failure, will return false and the data slice will be as original.
func Solve(data []int, chars int, constraints []Constraint) bool {
	s := Sudoku{data, chars, constraints}
	return s.Solve()
}

func slicePos(s []int, p int) int {
	for n, sp := range s {
		if sp == p {
			return n
		}
	}
	return -1
}

// Constraint defines the interface through which the character constraints are processed
type Constraint interface {
	Constrain(*Sudoku, int, []bool) bool
}

// Unique represents a section of data where each cell needs to be different
type Unique []int

// Constrain implements the Constraint interface
func (u Unique) Constrain(s *Sudoku, pos int, marked []bool) bool {
	if slicePos([]int(u), pos) == -1 {
		return true
	}
	myMark := make([]int, 0, len(u))
	for _, p := range u {
		if mp := s.data[p]; mp != 0 {
			if slicePos(myMark, mp) != -1 {
				return false
			}
			myMark = append(myMark, mp)
			marked[mp] = true
		}
	}
	return true
}

/*type Sorted []int

func (s Sorted) Constrain(su *Sudoku, pos int, marked []bool) bool {
	if slicePos([]int(s), pos) == -1 {
		return true
	}
	num := 0
	for _, p := range s {
		if mp := su.data[p]; mp != 0 {
			if mp > num {
				num = mp
			} else {
				return false
			}
		} else if mp == pos {

		}
	}
	return true
}

type UniqueSum struct {
	positions []int
	total     int
}

func (u UniqueSum) Constrain(s *Sudoku, pos int, marked []bool) bool {
	if slicePos(u.positions, pos) == -1 {
		return true
	}
	total := 0
	myMark := make([]int, len(u.positions))
	unmarked := 0
	for _, p := range u.positions {
		if mp := s.data[p]; mp == 0 {
			unmarked++
		} else {
			if slicePos(myMark, mp) != -1 {
				return false
			}
			myMark = append(myMark, mp)
			marked[slicePos(s.chars, mp)] = true
			total += mp
		}
	}
	left := u.total - total
	if left < 0 {
		return false
	}
	myNums := make([]int, 0, len(s.chars))
	for n, m := range marked {
		if !m {
			myNums = append(myNums, n)
		}
	}
	if len(myNums) < unmarked {
		return false
	}
	data := make([]int, 0, unmarked)
	marks := make([]bool, 0, len(s.chars))
	if !getCombinations(myNums, data, s.chars, left, 0, marks) {
		return false
	}
	r := false
	for n, m := range marks {
		if !m {
			marked[n] = true
			r = true
		} else if !r && !marked[n] {
			r = true
		}
	}
	return r
}

func getCombinations(nums, data, chars []int, addTo, from int, marks []bool) bool {
	if from == cap(data) {
		total := 0
		for _, n := range nums {
			total += n
		}
		if total == addTo {
			for _, n := range nums {
				marks[slicePos(chars, n)] = true // ????
			}
			return true
		}
		return false
	}
	toRet := false
	for i := from; i < cap(data); i++ {
		data = append(data, nums[i])
		if getCombinations(nums, data, chars, addTo, i+1, marks) {
			toRet = true
		}
		data = data[:len(data)-1]
	}
	return toRet
}*/

// Sudoku puzzle information
type Sudoku struct {
	data        []int
	chars       int
	constraints []Constraint
}

func (s *Sudoku) possible(pos int) []int {
	if pos < 0 || pos > len(s.data) || s.data[pos] != 0 {
		return nil
	}
	marked := make([]bool, s.chars+1)
	for _, c := range s.constraints {
		any := c.Constrain(s, pos, marked)
		if !any {
			return []int{}
		}
	}
	toRet := make([]int, 0, s.chars)
	for p, m := range marked[1:] {
		if !m {
			toRet = append(toRet, p+1)
		}
	}
	return toRet
}

// Solve will solve any solveable puzzle and return whether is was sucessful.
func (s *Sudoku) Solve() bool {
	l := len(s.data)
	possibilities := make([][]int, l)
	var pos int
	for ; pos < l; pos++ {
		if p := s.possible(pos); p != nil {
			possibilities[pos] = p
			break
		}
	}
	for pos < l {
		if len(possibilities[pos]) == 0 {
			s.data[pos] = 0
			for pos--; pos >= 0 && len(possibilities[pos]) == 0; pos-- {
				if possibilities[pos] != nil {
					s.data[pos] = 0
				}
			}
			if pos < 0 {
				return false
			}
			continue
		}
		s.data[pos] = possibilities[pos][0]
		possibilities[pos] = possibilities[pos][1:]
		for pos++; pos < l; pos++ {
			if p := s.possible(pos); p != nil {
				possibilities[pos] = p
				break
			}
		}
	}
	return true
}
<|endoftext|>


<commit_before>// Copyright 2012-present Oliver Eilhard. All rights reserved.
// Use of this source code is governed by a MIT-license.
// See http://olivere.mit-license.org/license.txt for details.

package elastic

import (
	"context"
	"encoding/json"
	"testing"
)

func TestHighlighterField(t *testing.T) {
	field := NewHighlighterField("grade")
	src, err := field.Source()
	if err != nil {
		t.Fatal(err)
	}
	data, err := json.Marshal(src)
	if err != nil {
		t.Fatalf("marshaling to JSON failed: %v", err)
	}
	got := string(data)
	expected := `{}`
	if got != expected {
		t.Errorf("expected\n%s\n,got:\n%s", expected, got)
	}
}

func TestHighlighterFieldWithOptions(t *testing.T) {
	field := NewHighlighterField("grade").FragmentSize(2).NumOfFragments(1)
	src, err := field.Source()
	if err != nil {
		t.Fatal(err)
	}
	data, err := json.Marshal(src)
	if err != nil {
		t.Fatalf("marshaling to JSON failed: %v", err)
	}
	got := string(data)
	expected := `{"fragment_size":2,"number_of_fragments":1}`
	if got != expected {
		t.Errorf("expected\n%s\n,got:\n%s", expected, got)
	}
}

func TestHighlightWithStringField(t *testing.T) {
	builder := NewHighlight().Field("grade")
	src, err := builder.Source()
	if err != nil {
		t.Fatal(err)
	}
	data, err := json.Marshal(src)
	if err != nil {
		t.Fatalf("marshaling to JSON failed: %v", err)
	}
	got := string(data)
	expected := `{"fields":{"grade":{}}}`
	if got != expected {
		t.Errorf("expected\n%s\n,got:\n%s", expected, got)
	}
}

func TestHighlightWithFields(t *testing.T) {
	gradeField := NewHighlighterField("grade")
	builder := NewHighlight().Fields(gradeField)
	src, err := builder.Source()
	if err != nil {
		t.Fatal(err)
	}
	data, err := json.Marshal(src)
	if err != nil {
		t.Fatalf("marshaling to JSON failed: %v", err)
	}
	got := string(data)
	expected := `{"fields":{"grade":{}}}`
	if got != expected {
		t.Errorf("expected\n%s\n,got:\n%s", expected, got)
	}
}

func TestHighlightWithMultipleFields(t *testing.T) {
	gradeField := NewHighlighterField("grade")
	colorField := NewHighlighterField("color")
	builder := NewHighlight().Fields(gradeField, colorField)
	src, err := builder.Source()
	if err != nil {
		t.Fatal(err)
	}
	data, err := json.Marshal(src)
	if err != nil {
		t.Fatalf("marshaling to JSON failed: %v", err)
	}
	got := string(data)
	expected := `{"fields":{"color":{},"grade":{}}}`
	if got != expected {
		t.Errorf("expected\n%s\n,got:\n%s", expected, got)
	}
}

func TestHighlighterWithExplicitFieldOrder(t *testing.T) {
	gradeField := NewHighlighterField("grade").FragmentSize(2)
	colorField := NewHighlighterField("color").FragmentSize(2).NumOfFragments(1)
	builder := NewHighlight().Fields(gradeField, colorField).UseExplicitFieldOrder(true)
	src, err := builder.Source()
	if err != nil {
		t.Fatal(err)
	}
	data, err := json.Marshal(src)
	if err != nil {
		t.Fatalf("marshaling to JSON failed: %v", err)
	}
	got := string(data)
	expected := `{"fields":[{"grade":{"fragment_size":2}},{"color":{"fragment_size":2,"number_of_fragments":1}}]}`
	if got != expected {
		t.Errorf("expected\n%s\n,got:\n%s", expected, got)
	}
}

func TestHighlightWithBoundarySettings(t *testing.T) {
	builder := NewHighlight().
		BoundaryChars(" \t\r").
		BoundaryScannerType("word")
	src, err := builder.Source()
	if err != nil {
		t.Fatal(err)
	}
	data, err := json.Marshal(src)
	if err != nil {
		t.Fatalf("marshaling to JSON failed: %v", err)
	}
	got := string(data)
	expected := `{"boundary_chars":" \t\r","boundary_scanner":"word"}`
	if got != expected {
		t.Errorf("expected\n%s\n,got:\n%s", expected, got)
	}
}

func TestHighlightWithTermQuery(t *testing.T) {
	client := setupTestClientAndCreateIndex(t)

	tweet1 := tweet{User: "olivere", Message: "Welcome to Golang and Elasticsearch."}
	tweet2 := tweet{User: "olivere", Message: "Another unrelated topic."}
	tweet3 := tweet{User: "sandrae", Message: "Cycling is fun to do."}

	// Add all documents
	_, err := client.Index().Index(testIndexName).Type("doc").Id("1").BodyJson(&tweet1).Do(context.TODO())
	if err != nil {
		t.Fatal(err)
	}

	_, err = client.Index().Index(testIndexName).Type("doc").Id("2").BodyJson(&tweet2).Do(context.TODO())
	if err != nil {
		t.Fatal(err)
	}

	_, err = client.Index().Index(testIndexName).Type("doc").Id("3").BodyJson(&tweet3).Do(context.TODO())
	if err != nil {
		t.Fatal(err)
	}

	_, err = client.Flush().Index(testIndexName).Do(context.TODO())
	if err != nil {
		t.Fatal(err)
	}

	// Specify highlighter
	hl := NewHighlight()
	hl = hl.Fields(NewHighlighterField("message"))
	hl = hl.PreTags("").PostTags("")

	// Match all should return all documents
	query := NewPrefixQuery("message", "golang")
	searchResult, err := client.Search().
		Index(testIndexName).
		Highlight(hl).
		Query(query).
		Do(context.TODO())
	if err != nil {
		t.Fatal(err)
	}
	if searchResult.Hits == nil {
		t.Fatalf("expected SearchResult.Hits != nil; got nil")
	}
	if searchResult.Hits.TotalHits != 1 {
		t.Fatalf("expected SearchResult.Hits.TotalHits = %d; got %d", 1, searchResult.Hits.TotalHits)
	}
	if len(searchResult.Hits.Hits) != 1 {
		t.Fatalf("expected len(SearchResult.Hits.Hits) = %d; got %d", 1, len(searchResult.Hits.Hits))
	}

	hit := searchResult.Hits.Hits[0]
	var tw tweet
	if err := json.Unmarshal(*hit.Source, &tw); err != nil {
		t.Fatal(err)
	}
	if hit.Highlight == nil || len(hit.Highlight) == 0 {
		t.Fatal("expected hit to have a highlight; got nil")
	}
	if hl, found := hit.Highlight["message"]; found {
		if len(hl) != 1 {
			t.Fatalf("expected to have one highlight for field \"message\"; got %d", len(hl))
		}
		expected := "Welcome to Golang and Elasticsearch."
		if hl[0] != expected {
			t.Errorf("expected to have highlight \"%s\"; got \"%s\"", expected, hl[0])
		}
	} else {
		t.Fatal("expected to have a highlight on field \"message\"; got none")
	}
}
<commit_msg>Prettify highlighter test<commit_after>// Copyright 2012-present Oliver Eilhard. All rights reserved.
// Use of this source code is governed by a MIT-license.
// See http://olivere.mit-license.org/license.txt for details.

package elastic

import (
	"context"
	"encoding/json"
	"testing"
)

func TestHighlighterField(t *testing.T) {
	field := NewHighlighterField("grade")
	src, err := field.Source()
	if err != nil {
		t.Fatal(err)
	}
	data, err := json.Marshal(src)
	if err != nil {
		t.Fatalf("marshaling to JSON failed: %v", err)
	}
	got := string(data)
	expected := `{}`
	if got != expected {
		t.Errorf("expected\n%s\n,got:\n%s", expected, got)
	}
}

func TestHighlighterFieldWithOptions(t *testing.T) {
	field := NewHighlighterField("grade").FragmentSize(2).NumOfFragments(1)
	src, err := field.Source()
	if err != nil {
		t.Fatal(err)
	}
	data, err := json.Marshal(src)
	if err != nil {
		t.Fatalf("marshaling to JSON failed: %v", err)
	}
	got := string(data)
	expected := `{"fragment_size":2,"number_of_fragments":1}`
	if got != expected {
		t.Errorf("expected\n%s\n,got:\n%s", expected, got)
	}
}

func TestHighlightWithStringField(t *testing.T) {
	builder := NewHighlight().Field("grade")
	src, err := builder.Source()
	if err != nil {
		t.Fatal(err)
	}
	data, err := json.Marshal(src)
	if err != nil {
		t.Fatalf("marshaling to JSON failed: %v", err)
	}
	got := string(data)
	expected := `{"fields":{"grade":{}}}`
	if got != expected {
		t.Errorf("expected\n%s\n,got:\n%s", expected, got)
	}
}

func TestHighlightWithFields(t *testing.T) {
	gradeField := NewHighlighterField("grade")
	builder := NewHighlight().Fields(gradeField)
	src, err := builder.Source()
	if err != nil {
		t.Fatal(err)
	}
	data, err := json.Marshal(src)
	if err != nil {
		t.Fatalf("marshaling to JSON failed: %v", err)
	}
	got := string(data)
	expected := `{"fields":{"grade":{}}}`
	if got != expected {
		t.Errorf("expected\n%s\n,got:\n%s", expected, got)
	}
}

func TestHighlightWithMultipleFields(t *testing.T) {
	gradeField := NewHighlighterField("grade")
	colorField := NewHighlighterField("color")
	builder := NewHighlight().Fields(gradeField, colorField)
	src, err := builder.Source()
	if err != nil {
		t.Fatal(err)
	}
	data, err := json.Marshal(src)
	if err != nil {
		t.Fatalf("marshaling to JSON failed: %v", err)
	}
	got := string(data)
	expected := `{"fields":{"color":{},"grade":{}}}`
	if got != expected {
		t.Errorf("expected\n%s\n,got:\n%s", expected, got)
	}
}

func TestHighlighterWithExplicitFieldOrder(t *testing.T) {
	gradeField := NewHighlighterField("grade").FragmentSize(2)
	colorField := NewHighlighterField("color").FragmentSize(2).NumOfFragments(1)
	builder := NewHighlight().Fields(gradeField, colorField).UseExplicitFieldOrder(true)
	src, err := builder.Source()
	if err != nil {
		t.Fatal(err)
	}
	data, err := json.Marshal(src)
	if err != nil {
		t.Fatalf("marshaling to JSON failed: %v", err)
	}
	got := string(data)
	expected := `{"fields":[{"grade":{"fragment_size":2}},{"color":{"fragment_size":2,"number_of_fragments":1}}]}`
	if got != expected {
		t.Errorf("expected\n%s\n,got:\n%s", expected, got)
	}
}

func TestHighlightWithBoundarySettings(t *testing.T) {
	builder := NewHighlight().
		BoundaryChars(" \t\r").
		BoundaryScannerType("word")
	src, err := builder.Source()
	if err != nil {
		t.Fatal(err)
	}
	data, err := json.Marshal(src)
	if err != nil {
		t.Fatalf("marshaling to JSON failed: %v", err)
	}
	got := string(data)
	expected := `{"boundary_chars":" \t\r","boundary_scanner":"word"}`
	if got != expected {
		t.Errorf("expected\n%s\n,got:\n%s", expected, got)
	}
}

func TestHighlightWithTermQuery(t *testing.T) {
	client := setupTestClientAndCreateIndex(t) //, SetTraceLog(log.New(os.Stdout, "", 0)))

	tweet1 := tweet{User: "olivere", Message: "Welcome to Golang and Elasticsearch."}
	tweet2 := tweet{User: "olivere", Message: "Another unrelated topic."}
	tweet3 := tweet{User: "sandrae", Message: "Cycling is fun to do."}

	// Add all documents
	_, err := client.Index().Index(testIndexName).Type("doc").Id("1").BodyJson(&tweet1).Do(context.TODO())
	if err != nil {
		t.Fatal(err)
	}

	_, err = client.Index().Index(testIndexName).Type("doc").Id("2").BodyJson(&tweet2).Do(context.TODO())
	if err != nil {
		t.Fatal(err)
	}

	_, err = client.Index().Index(testIndexName).Type("doc").Id("3").BodyJson(&tweet3).Do(context.TODO())
	if err != nil {
		t.Fatal(err)
	}

	_, err = client.Flush().Index(testIndexName).Do(context.TODO())
	if err != nil {
		t.Fatal(err)
	}

	// Specify highlighter
	hl := NewHighlight()
	hl = hl.Fields(NewHighlighterField("message"))
	hl = hl.PreTags("").PostTags("")

	// Match all should return all documents
	query := NewPrefixQuery("message", "golang")
	searchResult, err := client.Search().
		Index(testIndexName).
		Highlight(hl).
		Query(query).
		Pretty(true).
		Do(context.TODO())
	if err != nil {
		t.Fatal(err)
	}
	if searchResult.Hits == nil {
		t.Fatalf("expected SearchResult.Hits != nil; got nil")
	}
	if searchResult.Hits.TotalHits != 1 {
		t.Fatalf("expected SearchResult.Hits.TotalHits = %d; got %d", 1, searchResult.Hits.TotalHits)
	}
	if len(searchResult.Hits.Hits) != 1 {
		t.Fatalf("expected len(SearchResult.Hits.Hits) = %d; got %d", 1, len(searchResult.Hits.Hits))
	}

	hit := searchResult.Hits.Hits[0]
	var tw tweet
	if err := json.Unmarshal(*hit.Source, &tw); err != nil {
		t.Fatal(err)
	}
	if hit.Highlight == nil || len(hit.Highlight) == 0 {
		t.Fatal("expected hit to have a highlight; got nil")
	}
	if hl, found := hit.Highlight["message"]; found {
		if len(hl) != 1 {
			t.Fatalf("expected to have one highlight for field \"message\"; got %d", len(hl))
		}
		expected := "Welcome to Golang and Elasticsearch."
		if hl[0] != expected {
			t.Errorf("expected to have highlight \"%s\"; got \"%s\"", expected, hl[0])
		}
	} else {
		t.Fatal("expected to have a highlight on field \"message\"; got none")
	}
}
<|endoftext|>


<commit_before>// Copyright 2012, 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 cgzip

/*
#cgo pkg-config: zlib

#include "zlib.h"

// inflateInit2 is a macro, so using a wrapper function
int cgzipInflateInit(z_stream *strm) {
    strm->zalloc = Z_NULL;
    strm->zfree = Z_NULL;
    strm->opaque = Z_NULL;
    strm->avail_in = 0;
    strm->next_in = Z_NULL;
 return inflateInit2(strm,
                     16+15); // 16 makes it understand only gzip files
}
*/
import "C"

import (
	"fmt"
	"io"
	"unsafe"
)

// err starts out as nil
// we will call inflateEnd when we set err to a value:
// - whatever error is returned by the underlying reader
// - io.EOF if Close was called
type reader struct {
	r    io.Reader
	in   []byte
	strm C.z_stream
	err  error
}

func NewReader(r io.Reader) (io.ReadCloser, error) {
	return NewReaderBuffer(r, DEFAULT_COMPRESSED_BUFFER_SIZE)
}

func NewReaderBuffer(r io.Reader, bufferSize int) (io.ReadCloser, error) {
	z := &reader{r: r, in: make([]byte, bufferSize)}
	result := C.cgzipInflateInit(&z.strm)
	if result != Z_OK {
		return nil, fmt.Errorf("cgzip: failed to initialize (%v): %v", result, C.GoString(z.strm.msg))
	}
	return z, nil
}

func (z *reader) Read(p []byte) (int, error) {
	if z.err != nil {
		return 0, z.err
	}

	if len(p) == 0 {
		return 0, nil
	}

	// read and deflate until the output buffer is full
	z.strm.next_out = (*C.Bytef)(unsafe.Pointer(&p[0]))
	z.strm.avail_out = (C.uInt)(len(p))
	for {
		// if we have no data to inflate, read more
		if z.strm.avail_in == 0 {
			var n int
			n, z.err = z.r.Read(z.in)
			if z.err != nil {
				C.inflateEnd(&z.strm)
				return 0, z.err
			}
			z.strm.next_in = (*C.Bytef)(unsafe.Pointer(&z.in[0]))
			z.strm.avail_in = (C.uInt)(n)
		}

		// inflate some
		ret := C.inflate(&z.strm, C.Z_NO_FLUSH)
		switch ret {
		case Z_NEED_DICT:
			ret = Z_DATA_ERROR
			fallthrough
		case Z_DATA_ERROR, Z_MEM_ERROR:
			z.err = fmt.Errorf("cgzip: failed to inflate (%v): %v", ret, C.GoString(z.strm.msg))
			C.inflateEnd(&z.strm)
			return 0, z.err
		}

		// if we read something, we're good
		have := len(p) - int(z.strm.avail_out)
		if have > 0 {
			return have, nil
		}
	}
	panic("Unreachable")
}

// Close closes the Reader. It does not close the underlying io.Reader.
func (z *reader) Close() error {
	if z.err != nil {
		return z.err
	}
	C.inflateEnd(&z.strm)
	z.err = io.EOF
	return nil
}
<commit_msg>Integrating a bug fix in cgzip from outside.<commit_after>// Copyright 2012, 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 cgzip

/*
#cgo pkg-config: zlib

#include "zlib.h"

// inflateInit2 is a macro, so using a wrapper function
int cgzipInflateInit(z_stream *strm) {
    strm->zalloc = Z_NULL;
    strm->zfree = Z_NULL;
    strm->opaque = Z_NULL;
    strm->avail_in = 0;
    strm->next_in = Z_NULL;
 return inflateInit2(strm,
                     16+15); // 16 makes it understand only gzip files
}
*/
import "C"

import (
	"fmt"
	"io"
	"unsafe"
)

// err starts out as nil
// we will call inflateEnd when we set err to a value:
// - whatever error is returned by the underlying reader
// - io.EOF if Close was called
type reader struct {
	r      io.Reader
	in     []byte
	strm   C.z_stream
	err    error
	skipIn bool
}

func NewReader(r io.Reader) (io.ReadCloser, error) {
	return NewReaderBuffer(r, DEFAULT_COMPRESSED_BUFFER_SIZE)
}

func NewReaderBuffer(r io.Reader, bufferSize int) (io.ReadCloser, error) {
	z := &reader{r: r, in: make([]byte, bufferSize)}
	result := C.cgzipInflateInit(&z.strm)
	if result != Z_OK {
		return nil, fmt.Errorf("cgzip: failed to initialize (%v): %v", result, C.GoString(z.strm.msg))
	}
	return z, nil
}

func (z *reader) Read(p []byte) (int, error) {
	if z.err != nil {
		return 0, z.err
	}

	if len(p) == 0 {
		return 0, nil
	}

	// read and deflate until the output buffer is full
	z.strm.next_out = (*C.Bytef)(unsafe.Pointer(&p[0]))
	z.strm.avail_out = (C.uInt)(len(p))

	for {
		// if we have no data to inflate, read more
		if !z.skipIn && z.strm.avail_in == 0 {
			var n int
			n, z.err = z.r.Read(z.in)
			if (z.err != nil && z.err != io.EOF) || (n == 0 && z.err == io.EOF) {
				C.inflateEnd(&z.strm)
				return 0, z.err
			}

			z.strm.next_in = (*C.Bytef)(unsafe.Pointer(&z.in[0]))
			z.strm.avail_in = (C.uInt)(n)
		} else {
			z.skipIn = false
		}

		// inflate some
		ret := C.inflate(&z.strm, C.Z_NO_FLUSH)
		switch ret {
		case Z_NEED_DICT:
			ret = Z_DATA_ERROR
			fallthrough
		case Z_DATA_ERROR, Z_MEM_ERROR:
			z.err = fmt.Errorf("cgzip: failed to inflate (%v): %v", ret, C.GoString(z.strm.msg))
			C.inflateEnd(&z.strm)
			return 0, z.err
		}

		// if we read something, we're good
		have := len(p) - int(z.strm.avail_out)
		if have > 0 {
			z.skipIn = ret == Z_OK && z.strm.avail_out == 0
			return have, z.err
		}
	}
	panic("Unreachable")
}

// Close closes the Reader. It does not close the underlying io.Reader.
func (z *reader) Close() error {
	if z.err != nil {
		if z.err != io.EOF {
			return z.err
		}
		return nil
	}
	C.inflateEnd(&z.strm)
	z.err = io.EOF
	return nil
}
<|endoftext|>


<commit_before>package hm_test

import (
	"errors"
	"time"
	. "github.com/cloudfoundry/hm9000/hm"
	"github.com/cloudfoundry/hm9000/testhelpers/fakelogger"
	"github.com/cloudfoundry/storeadapter/fakestoreadapter"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Daemon", func() {
	var adapter *fakestoreadapter.FakeStoreAdapter

	BeforeEach(func() {
		adapter = fakestoreadapter.New()
	})

	It("should call the function every PERIOD seconds, unless the function takes *longer* than PERIOD, and it should timeout when the function takes *too* long", func(done Done) {
		defer close(done)

		go func() {
			released := <-adapter.ReleaseNodeChannel
			released <- true
		}()

		adapter.MaintainNodeStatus <- true

		callTimes := []float64{}
		startTime := time.Now()
		i := 0
		err := Daemonize("Daemon Test", func() error {
			callTimes = append(callTimes, time.Since(startTime).Seconds())
			i += 1
			time.Sleep(time.Duration(i*10) * time.Millisecond)
			return nil
		}, 20*time.Millisecond, 35*time.Millisecond, fakelogger.NewFakeLogger(), adapter)

		Ω(callTimes).Should(HaveLen(4))

		Ω(callTimes[0]).Should(BeNumerically("~", 0, 0.005), "The first call happens immediately and sleeps for 10 seconds")
		Ω(callTimes[1]).Should(BeNumerically("~", 0.02, 0.005), "The second call happens after PERIOD and sleeps for 20 seconds")
		Ω(callTimes[2]).Should(BeNumerically("~", 0.04, 0.005), "The third call happens after PERIOD and sleeps for 30 seconds")
		Ω(callTimes[3]).Should(BeNumerically("~", 0.07, 0.005), "The fourth call waits for function to finish and happens after 30 seconds (> PERIOD) and sleeps for 40 seconds which...")
		Ω(err).Should(Equal(errors.New("Daemon timed out. Aborting!")), "..causes a timeout")
	})

	It("acquires the lock once", func() {
		go Daemonize(
			"ComponentName",
			func() error { return nil },
			20*time.Millisecond,
			35*time.Millisecond,
			fakelogger.NewFakeLogger(),
			adapter,
		)

		Eventually(func() string { return adapter.MaintainedNodeName }).Should(Equal("/hm/locks/ComponentName"))
	})

	Context("when the locker fails", func() {
		disaster := errors.New("oh no!")

		BeforeEach(func() {
			adapter.MaintainNodeError = disaster
		})

		It("returns the error", func() {
			err := Daemonize(
				"Daemon Test",
				func() error { Fail("NOPE"); return nil },
				20*time.Millisecond,
				35*time.Millisecond,
				fakelogger.NewFakeLogger(),
				adapter,
			)

			Ω(err).Should(Equal(disaster))
		})
	})

	Context("when the callback times out", func() {
		It("releases the lock", func(done Done) {
			defer close(done)

			didRelease := make(chan bool)

			go func() {
				released := <-adapter.ReleaseNodeChannel
				released <- true
				didRelease <- true
			}()

			adapter.MaintainNodeStatus <- true

			Daemonize(
				"Daemon Test",
				func() error { time.Sleep(1 * time.Second); return nil },
				20*time.Millisecond,
				35*time.Millisecond,
				fakelogger.NewFakeLogger(),
				adapter,
			)

			<-didRelease
		})
	})
})
<commit_msg>be more forgiving<commit_after>package hm_test

import (
	"errors"
	"time"
	. "github.com/cloudfoundry/hm9000/hm"
	"github.com/cloudfoundry/hm9000/testhelpers/fakelogger"
	"github.com/cloudfoundry/storeadapter/fakestoreadapter"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Daemon", func() {
	var adapter *fakestoreadapter.FakeStoreAdapter

	BeforeEach(func() {
		adapter = fakestoreadapter.New()
	})

	It("should call the function every PERIOD seconds, unless the function takes *longer* than PERIOD, and it should timeout when the function takes *too* long", func(done Done) {
		defer close(done)

		go func() {
			released := <-adapter.ReleaseNodeChannel
			released <- true
		}()

		adapter.MaintainNodeStatus <- true

		callTimes := []float64{}
		startTime := time.Now()
		i := 0
		err := Daemonize("Daemon Test", func() error {
			callTimes = append(callTimes, time.Since(startTime).Seconds())
			i += 1
			time.Sleep(time.Duration(i*10) * time.Millisecond)
			return nil
		}, 20*time.Millisecond, 35*time.Millisecond, fakelogger.NewFakeLogger(), adapter)

		Ω(callTimes).Should(HaveLen(4))

		Ω(callTimes[0]).Should(BeNumerically("~", 0, 0.01), "The first call happens immediately and sleeps for 10 seconds")
		Ω(callTimes[1]).Should(BeNumerically("~", 0.02, 0.01), "The second call happens after PERIOD and sleeps for 20 seconds")
		Ω(callTimes[2]).Should(BeNumerically("~", 0.04, 0.01), "The third call happens after PERIOD and sleeps for 30 seconds")
		Ω(callTimes[3]).Should(BeNumerically("~", 0.07, 0.01), "The fourth call waits for function to finish and happens after 30 seconds (> PERIOD) and sleeps for 40 seconds which...")
		Ω(err).Should(Equal(errors.New("Daemon timed out. Aborting!")), "..causes a timeout")
	})

	It("acquires the lock once", func() {
		go Daemonize(
			"ComponentName",
			func() error { return nil },
			20*time.Millisecond,
			35*time.Millisecond,
			fakelogger.NewFakeLogger(),
			adapter,
		)

		Eventually(func() string { return adapter.MaintainedNodeName }).Should(Equal("/hm/locks/ComponentName"))
	})

	Context("when the locker fails", func() {
		disaster := errors.New("oh no!")

		BeforeEach(func() {
			adapter.MaintainNodeError = disaster
		})

		It("returns the error", func() {
			err := Daemonize(
				"Daemon Test",
				func() error { Fail("NOPE"); return nil },
				20*time.Millisecond,
				35*time.Millisecond,
				fakelogger.NewFakeLogger(),
				adapter,
			)

			Ω(err).Should(Equal(disaster))
		})
	})

	Context("when the callback times out", func() {
		It("releases the lock", func(done Done) {
			defer close(done)

			didRelease := make(chan bool)

			go func() {
				released := <-adapter.ReleaseNodeChannel
				released <- true
				didRelease <- true
			}()

			adapter.MaintainNodeStatus <- true

			Daemonize(
				"Daemon Test",
				func() error { time.Sleep(1 * time.Second); return nil },
				20*time.Millisecond,
				35*time.Millisecond,
				fakelogger.NewFakeLogger(),
				adapter,
			)

			<-didRelease
		})
	})
})
<|endoftext|>


<commit_before>package gocassa

type mapT struct {
	Table
	idField string
}

func (m *mapT) Update(id interface{}, ma map[string]interface{}) Op {
	return m.Where(Eq(m.idField, id)).Update(ma)
}

func (m *mapT) Delete(id interface{}) Op {
	return m.Where(Eq(m.idField, id)).Delete()
}

func (m *mapT) Read(id, pointer interface{}) Op {
	return m.Where(Eq(m.idField, id)).ReadOne(pointer)
}

func (m *mapT) MultiRead(ids []interface{}, pointerToASlice interface{}) Op {
	return m.Where(In(m.idField, ids...)).Read(pointerToASlice)
}

func (m *mapT) WithOptions(o Options) MapTable {
	return &mapT{
		Table:   m.Table.WithOptions(o),
		idField: m.idField,
	}
}

func (mm *mapT) GetTable() Table {
	return mm.Table
}
<commit_msg>Remove last gettable reference<commit_after>package gocassa

type mapT struct {
	Table
	idField string
}

func (m *mapT) Update(id interface{}, ma map[string]interface{}) Op {
	return m.Where(Eq(m.idField, id)).Update(ma)
}

func (m *mapT) Delete(id interface{}) Op {
	return m.Where(Eq(m.idField, id)).Delete()
}

func (m *mapT) Read(id, pointer interface{}) Op {
	return m.Where(Eq(m.idField, id)).ReadOne(pointer)
}

func (m *mapT) MultiRead(ids []interface{}, pointerToASlice interface{}) Op {
	return m.Where(In(m.idField, ids...)).Read(pointerToASlice)
}

func (m *mapT) WithOptions(o Options) MapTable {
	return &mapT{
		Table:   m.Table.WithOptions(o),
		idField: m.idField,
	}
}
<|endoftext|>


<commit_before>// Copyright 2014 Hajime Hoshi
//
// 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 ebiten

import (
	"github.com/hajimehoshi/ebiten/internal/clock"
	"github.com/hajimehoshi/ebiten/internal/graphics"
	"github.com/hajimehoshi/ebiten/internal/hooks"
	"github.com/hajimehoshi/ebiten/internal/restorable"
	"github.com/hajimehoshi/ebiten/internal/ui"
	"github.com/hajimehoshi/ebiten/internal/web"
)

func newGraphicsContext(f func(*Image) error) *graphicsContext {
	return &graphicsContext{
		f: f,
	}
}

type graphicsContext struct {
	f           func(*Image) error
	offscreen   *Image
	screen      *Image
	initialized bool
	invalidated bool // browser only
	offsetX     float64
	offsetY     float64
}

func (c *graphicsContext) Invalidate() {
	// Note that this is called only on browsers so far.
	// TODO: On mobiles, this function is not called and instead IsTexture is called
	// to detect if the context is lost. This is simple but might not work on some platforms.
	// Should Invalidate be called explicitly?
	c.invalidated = true
}

func (c *graphicsContext) SetSize(screenWidth, screenHeight int, screenScale float64) {
	if c.screen != nil {
		_ = c.screen.Dispose()
	}
	if c.offscreen != nil {
		_ = c.offscreen.Dispose()
	}
	offscreen := newVolatileImage(screenWidth, screenHeight, FilterDefault)

	w := int(float64(screenWidth) * screenScale)
	h := int(float64(screenHeight) * screenScale)
	px0, py0, _, _ := ui.ScreenPadding()
	c.screen = newImageWithScreenFramebuffer(w, h)
	_ = c.screen.Clear()

	c.offscreen = offscreen

	c.offsetX = px0
	c.offsetY = py0
}

func (c *graphicsContext) initializeIfNeeded() error {
	if !c.initialized {
		if err := restorable.InitializeGLState(); err != nil {
			return err
		}
		c.initialized = true
	}
	if err := c.restoreIfNeeded(); err != nil {
		return err
	}
	return nil
}

func (c *graphicsContext) Update(afterFrameUpdate func()) error {
	updateCount := clock.Update()

	if err := c.initializeIfNeeded(); err != nil {
		return err
	}
	for i := 0; i < updateCount; i++ {
		c.offscreen.fill(0, 0, 0, 0)

		setRunningSlowly(i < updateCount-1)
		if err := hooks.Run(); err != nil {
			return err
		}
		if err := c.f(c.offscreen); err != nil {
			return err
		}
		afterFrameUpdate()
	}

	// Clear the screen framebuffer by DrawImage instad of Fill
	// to clear the whole region including fullscreen's padding.
	// TODO: This clear is needed only when the screen size is changed.
	if c.offsetX > 0 || c.offsetY > 0 {
		op := &DrawImageOptions{}
		w, h := emptyImage.Size()
		// graphics.MaxImageSize should be the maximum size of framebuffer.
		op.GeoM.Scale(graphics.MaxImageSize/float64(w), graphics.MaxImageSize/float64(h))
		op.CompositeMode = CompositeModeCopy
		op.Filter = filterScreen // any filter is fine: just use the same filter as below.
		c.screen.DrawImage(emptyImage, op)
	}

	dw, dh := c.screen.Size()
	sw, _ := c.offscreen.Size()
	scale := float64(dw) / float64(sw)

	op := &DrawImageOptions{}
	// c.screen is special: its Y axis is down to up,
	// and the origin point is lower left.
	op.GeoM.Scale(scale, -scale)
	op.GeoM.Translate(0, float64(dh))
	op.GeoM.Translate(c.offsetX, c.offsetY)

	op.CompositeMode = CompositeModeCopy
	op.Filter = filterScreen
	_ = c.screen.DrawImage(c.offscreen, op)

	if err := restorable.ResolveStaleImages(); err != nil {
		return err
	}
	return nil
}

func (c *graphicsContext) needsRestoring() (bool, error) {
	if web.IsBrowser() {
		return c.invalidated, nil
	}
	return c.offscreen.restorable.IsInvalidated()
}

func (c *graphicsContext) restoreIfNeeded() error {
	if !restorable.IsRestoringEnabled() {
		return nil
	}
	r, err := c.needsRestoring()
	if err != nil {
		return err
	}
	if !r {
		return nil
	}
	if err := restorable.Restore(); err != nil {
		return err
	}
	c.invalidated = false
	return nil
}
<commit_msg>graphics: Remove unneeded 'Clear' on the screen framebuffer<commit_after>// Copyright 2014 Hajime Hoshi
//
// 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 ebiten

import (
	"github.com/hajimehoshi/ebiten/internal/clock"
	"github.com/hajimehoshi/ebiten/internal/graphics"
	"github.com/hajimehoshi/ebiten/internal/hooks"
	"github.com/hajimehoshi/ebiten/internal/restorable"
	"github.com/hajimehoshi/ebiten/internal/ui"
	"github.com/hajimehoshi/ebiten/internal/web"
)

func newGraphicsContext(f func(*Image) error) *graphicsContext {
	return &graphicsContext{
		f: f,
	}
}

type graphicsContext struct {
	f           func(*Image) error
	offscreen   *Image
	screen      *Image
	initialized bool
	invalidated bool // browser only
	offsetX     float64
	offsetY     float64
}

func (c *graphicsContext) Invalidate() {
	// Note that this is called only on browsers so far.
	// TODO: On mobiles, this function is not called and instead IsTexture is called
	// to detect if the context is lost. This is simple but might not work on some platforms.
	// Should Invalidate be called explicitly?
	c.invalidated = true
}

func (c *graphicsContext) SetSize(screenWidth, screenHeight int, screenScale float64) {
	if c.screen != nil {
		_ = c.screen.Dispose()
	}
	if c.offscreen != nil {
		_ = c.offscreen.Dispose()
	}
	offscreen := newVolatileImage(screenWidth, screenHeight, FilterDefault)

	w := int(float64(screenWidth) * screenScale)
	h := int(float64(screenHeight) * screenScale)
	px0, py0, _, _ := ui.ScreenPadding()
	c.screen = newImageWithScreenFramebuffer(w, h)

	c.offscreen = offscreen

	c.offsetX = px0
	c.offsetY = py0
}

func (c *graphicsContext) initializeIfNeeded() error {
	if !c.initialized {
		if err := restorable.InitializeGLState(); err != nil {
			return err
		}
		c.initialized = true
	}
	if err := c.restoreIfNeeded(); err != nil {
		return err
	}
	return nil
}

func (c *graphicsContext) Update(afterFrameUpdate func()) error {
	updateCount := clock.Update()

	if err := c.initializeIfNeeded(); err != nil {
		return err
	}
	for i := 0; i < updateCount; i++ {
		c.offscreen.fill(0, 0, 0, 0)

		setRunningSlowly(i < updateCount-1)
		if err := hooks.Run(); err != nil {
			return err
		}
		if err := c.f(c.offscreen); err != nil {
			return err
		}
		afterFrameUpdate()
	}

	// Clear the screen framebuffer by DrawImage instad of Fill
	// to clear the whole region including fullscreen's padding.
	// TODO: This clear is needed only when the screen size is changed.
	if c.offsetX > 0 || c.offsetY > 0 {
		op := &DrawImageOptions{}
		w, h := emptyImage.Size()
		// graphics.MaxImageSize should be the maximum size of framebuffer.
		op.GeoM.Scale(graphics.MaxImageSize/float64(w), graphics.MaxImageSize/float64(h))
		op.CompositeMode = CompositeModeCopy
		op.Filter = filterScreen // any filter is fine: just use the same filter as below.
		c.screen.DrawImage(emptyImage, op)
	}

	dw, dh := c.screen.Size()
	sw, _ := c.offscreen.Size()
	scale := float64(dw) / float64(sw)

	op := &DrawImageOptions{}
	// c.screen is special: its Y axis is down to up,
	// and the origin point is lower left.
	op.GeoM.Scale(scale, -scale)
	op.GeoM.Translate(0, float64(dh))
	op.GeoM.Translate(c.offsetX, c.offsetY)

	op.CompositeMode = CompositeModeCopy
	op.Filter = filterScreen
	_ = c.screen.DrawImage(c.offscreen, op)

	if err := restorable.ResolveStaleImages(); err != nil {
		return err
	}
	return nil
}

func (c *graphicsContext) needsRestoring() (bool, error) {
	if web.IsBrowser() {
		return c.invalidated, nil
	}
	return c.offscreen.restorable.IsInvalidated()
}

func (c *graphicsContext) restoreIfNeeded() error {
	if !restorable.IsRestoringEnabled() {
		return nil
	}
	r, err := c.needsRestoring()
	if err != nil {
		return err
	}
	if !r {
		return nil
	}
	if err := restorable.Restore(); err != nil {
		return err
	}
	c.invalidated = false
	return nil
}
<|endoftext|>


<commit_before>package tarpan

import (
	"errors"
	"log"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/kr/pretty"
	"github.com/soniah/gosnmp"
)

// Tarpan constants
const (
	ConcurrentProcesses = 5
)

// Exit code
const (
	ExitCodeOK = iota
	ExitCodeConfError
	ExitCodeParseFlagError
)

// SNMP constants
const (
	community = "public"
	port      = 161
	timeout   = 2
	retry     = 3
	//MaximumPDUBytes = 512
)

// JSON structure definition
type DataSet struct {
	Default Defaults `json:"defaults"`
	Targets []Target `json:"targets"`
}

type Defaults struct {
	Port      uint16 `json:"port"`
	Version   string `json:"version"`
	Community string `json:"community"`
}

type Target struct {
	Name      string `json:"name"`
	Address   string `json:"address"`
	Port      uint16 `json:"port"`
	Version   string `json:"version"`
	Community string `json:"community"`
	OIDs      []OID  `json:"oids"`
}

type OID struct {
	OID         string `json:"oid"`
	Description string `json:"description"`
}

// Tarpan result structures
type TarpanResult struct {
	Name      string    `json:"name"`
	Address   string    `json:"address"`
	Port      uint16    `json:"port"`
	Version   string    `json:"version"`
	Community string    `json:"community"`
	VarBinds  []VarBind `json:"varbinds"`
}

type VarBind struct {
	Description string         `json:"description"`
	OID         string         `json:"oid"`
	Type        gosnmp.Asn1BER `json:"type"`
	Value       interface{}    `json:"value"`
	Time        int64          `json:"time"`
}

type Tarpan interface {
	makeRequestBody()
	SetManager()
	SetParams()
	Get(params map[string]string, oids []string) ([]gosnmp.SnmpPDU, error)
	Run()
}

type TarpanManager struct {
	snmp *gosnmp.GoSNMP
}

type SnmpResult struct {
	target  Target
	results []gosnmp.SnmpPDU
	time    int64
}

type Channels struct {
	semaphoe chan int
	results  chan SnmpResult
}

func (t *TarpanManager) Get(params map[string]string,
	oids []string) ([]gosnmp.SnmpPDU, error) {
	log.Println("Get:", params)
	log.Println("Tm Address:", &t)
	log.Println("TmSNMP Address:", &t.snmp)
	log.Printf("Before Set Tarpan %# v", pretty.Formatter(t.snmp))
	t.SetParams(params)
	log.Printf("Afer Set Tarpan %# v", pretty.Formatter(t.snmp))
	connection_err := t.snmp.Connect()
	if connection_err != nil {
		log.Fatalf("Connection error: %")
		return nil, errors.New(connection_err.Error())
	}
	result, request_err := t.snmp.Get(oids)
	if request_err != nil {
		return nil, errors.New(request_err.Error())
	}
	t.snmp.Conn.Close()

	return result.Variables, nil
}

func (t *TarpanManager) SetManager(manager *gosnmp.GoSNMP) {
	log.Println("Before Tm Address:", &t.snmp)
	t.snmp = manager
	log.Println("After Tm Address:", &t.snmp)
	return
}

func (t *TarpanManager) SetParams(p map[string]string) {
	if value, ok := p["target"]; ok {
		t.snmp.Target = value
	}
	if value, ok := p["port"]; ok {
		port, _ := strconv.ParseUint(value, 10, 16)
		t.snmp.Port = uint16(port)
	} else {
		t.snmp.Port = uint16(port)
	}
	if value, ok := p["community"]; ok {
		t.snmp.Community = value
	}
	if value, ok := p["version"]; ok {
		if value == "2c" {
			t.snmp.Version = gosnmp.Version2c
		}
	}
	if value, ok := p["timeout"]; ok {
		sec, _ := strconv.Atoi(value)
		t.snmp.Timeout = time.Duration(sec) * time.Second
	} else {
		t.snmp.Timeout = time.Duration(timeout) * time.Second
	}
	if value, ok := p["retries"]; ok {
		retries, _ := strconv.Atoi(value)
		t.snmp.Retries = retries
	} else {
		t.snmp.Retries = retry

	}

	return
}

func makeRequestBody(ds *DataSet, idx int) (map[string]string, error) {
	address := ""
	err := validateIP(ds.Targets[idx].Address)
	if err == nil {
		address = ds.Targets[idx].Address
	} else {
		return map[string]string{}, err
	}
	community := ds.Targets[idx].Community
	if community == "" {
		community = ds.Default.Community
	}
	version := ds.Targets[idx].Version
	if version == "" {
		version = ds.Default.Version
	}
	port := ds.Targets[idx].Port
	if port == 0 {
		port = ds.Default.Port
	}

	request_body := map[string]string{
		"target":    address,
		"community": community,
		"version":   version,
		"port":      strconv.Itoa(int(port)),
	}

	return request_body, err
}

func makeChannel(result_buffer_length int) *Channels {
	channel := &Channels{
		semaphoe: make(chan int, ConcurrentProcesses),
		results:  make(chan SnmpResult, result_buffer_length),
	}

	return channel
}

func makeTarpanResult(c *Channels) []*TarpanResult {
	var tarpanResults []*TarpanResult
	var varbinds []VarBind
	var result SnmpResult
	length := len(c.results)
	for i := 0; i < length; i++ {
		varbinds = []VarBind{}
		result = <-c.results
		for _, val := range result.results {
			for _, o := range result.target.OIDs {
				n := strings.TrimLeft(val.Name, ".")
				if o.OID == n {
					v := VarBind{
						Description: o.Description,
						OID:         val.Name,
						Type:        val.Type,
						Value:       val.Value,
						Time:        result.time,
					}
					varbinds = append(varbinds, v)
					break
				}
			}
		}
		tr := &TarpanResult{
			Name:      result.target.Name,
			Address:   result.target.Address,
			Port:      result.target.Port,
			Version:   result.target.Version,
			Community: result.target.Community,
			VarBinds:  varbinds,
		}
		tarpanResults = append(tarpanResults, tr)
	}

	return tarpanResults
}

func Collect(dataset *DataSet) []*TarpanResult {
	var waitGroup sync.WaitGroup
	var managers []*TarpanManager
	//var tm TarpanManager
	var channels *Channels
	var oids []string

	for i := 0; i < len(dataset.Targets); i++ {
		managers = append(managers, &TarpanManager{
			snmp: &gosnmp.GoSNMP{},
		})
	}

	channels = makeChannel(len(dataset.Targets))
	for index := range dataset.Targets {
		//tm = TarpanManager{}
		//tm.SetManager(new(gosnmp.GoSNMP))

		// TODO: split oid slice according to PDU size
		oids = []string{}
		for oid_idx := range dataset.Targets[index].OIDs {
			oids = append(oids, dataset.Targets[index].OIDs[oid_idx].OID)
		}
		log.Print("OIDS:", oids)

		waitGroup.Add(1)
		go func(ds *DataSet, idx int, o []string, c *Channels) {
			/*
				tm = TarpanManager{}
				fmt.Println("HOGE", tm)
				log.Println("KOKO Tm Address:", &tm.snmp)
				log.Println("KOKO Tm Address:", tm.snmp)
				tm.SetManager(new(gosnmp.GoSNMP))
				log.Println("KOKO Tm Address:", tm.snmp)
			*/
			c.semaphoe <- 0
			req_body, req_body_err := makeRequestBody(ds, idx)
			log.Print(req_body)
			if req_body_err != nil {
				log.Print(req_body_err)
				<-c.semaphoe
				return
			}
			t := time.Now()
			//results, err := tm.Get(req_body, o)
			results, err := managers[idx].Get(req_body, o)
			if err != nil {
				log.Print(err)
				<-c.semaphoe
				waitGroup.Done()
				return
			}
			ret := SnmpResult{
				target:  ds.Targets[idx],
				results: results,
				time:    t.Unix(),
			}
			c.results <- ret
			<-c.semaphoe
			waitGroup.Done()
		}(dataset, index, oids, channels)
	}
	waitGroup.Wait()
	tr := makeTarpanResult(channels)

	return tr
}

func Run(target string) (int, error) {
	var err error

	// Load targets
	dataset, loadErr := loadConfig(target)
	if loadErr != nil {
		return ExitCodeConfError, loadErr
	}

	// collect data
	tr := Collect(dataset)

	// output
	Write("aa", tr)

	return ExitCodeOK, err
}
<commit_msg>move tarpan structure initialization to outside of goroutine<commit_after>package tarpan

import (
	"errors"
	"log"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/soniah/gosnmp"
)

// Tarpan constants
const (
	ConcurrentProcesses = 5
)

// Exit code
const (
	ExitCodeOK = iota
	ExitCodeConfError
	ExitCodeParseFlagError
)

// SNMP constants
const (
	community = "public"
	port      = 161
	timeout   = 2
	retry     = 3
	//MaximumPDUBytes = 512
)

// JSON structure definition
type DataSet struct {
	Default Defaults `json:"defaults"`
	Targets []Target `json:"targets"`
}

type Defaults struct {
	Port      uint16 `json:"port"`
	Version   string `json:"version"`
	Community string `json:"community"`
}

type Target struct {
	Name      string `json:"name"`
	Address   string `json:"address"`
	Port      uint16 `json:"port"`
	Version   string `json:"version"`
	Community string `json:"community"`
	OIDs      []OID  `json:"oids"`
}

type OID struct {
	OID         string `json:"oid"`
	Description string `json:"description"`
}

// Tarpan result structures
type TarpanResult struct {
	Name      string    `json:"name"`
	Address   string    `json:"address"`
	Port      uint16    `json:"port"`
	Version   string    `json:"version"`
	Community string    `json:"community"`
	VarBinds  []VarBind `json:"varbinds"`
}

type VarBind struct {
	Description string         `json:"description"`
	OID         string         `json:"oid"`
	Type        gosnmp.Asn1BER `json:"type"`
	Value       interface{}    `json:"value"`
	Time        int64          `json:"time"`
}

type Tarpan interface {
	makeRequestBody()
	SetManager()
	SetParams()
	Get(params map[string]string, oids []string) ([]gosnmp.SnmpPDU, error)
	Run()
}

type TarpanManager struct {
	snmp *gosnmp.GoSNMP
}

type SnmpResult struct {
	target  Target
	results []gosnmp.SnmpPDU
	time    int64
}

type Channels struct {
	semaphoe chan int
	results  chan SnmpResult
}

func (t *TarpanManager) Get(params map[string]string,
	oids []string) ([]gosnmp.SnmpPDU, error) {
	t.SetParams(params)
	connection_err := t.snmp.Connect()
	if connection_err != nil {
		log.Fatalf("Connection error: %")
		return nil, errors.New(connection_err.Error())
	}
	result, request_err := t.snmp.Get(oids)
	if request_err != nil {
		return nil, errors.New(request_err.Error())
	}
	t.snmp.Conn.Close()

	return result.Variables, nil
}

func (t *TarpanManager) SetManager(manager *gosnmp.GoSNMP) {
	t.snmp = manager

	return
}

func (t *TarpanManager) SetParams(p map[string]string) {
	if value, ok := p["target"]; ok {
		t.snmp.Target = value
	}
	if value, ok := p["port"]; ok {
		port, _ := strconv.ParseUint(value, 10, 16)
		t.snmp.Port = uint16(port)
	} else {
		t.snmp.Port = uint16(port)
	}
	if value, ok := p["community"]; ok {
		t.snmp.Community = value
	}
	if value, ok := p["version"]; ok {
		if value == "2c" {
			t.snmp.Version = gosnmp.Version2c
		}
	}
	if value, ok := p["timeout"]; ok {
		sec, _ := strconv.Atoi(value)
		t.snmp.Timeout = time.Duration(sec) * time.Second
	} else {
		t.snmp.Timeout = time.Duration(timeout) * time.Second
	}
	if value, ok := p["retries"]; ok {
		retries, _ := strconv.Atoi(value)
		t.snmp.Retries = retries
	} else {
		t.snmp.Retries = retry

	}

	return
}

func makeRequestBody(ds *DataSet, idx int) (map[string]string, error) {
	address := ""
	err := validateIP(ds.Targets[idx].Address)
	if err == nil {
		address = ds.Targets[idx].Address
	} else {
		return map[string]string{}, err
	}
	community := ds.Targets[idx].Community
	if community == "" {
		community = ds.Default.Community
	}
	version := ds.Targets[idx].Version
	if version == "" {
		version = ds.Default.Version
	}
	port := ds.Targets[idx].Port
	if port == 0 {
		port = ds.Default.Port
	}

	request_body := map[string]string{
		"target":    address,
		"community": community,
		"version":   version,
		"port":      strconv.Itoa(int(port)),
	}

	return request_body, err
}

func makeChannel(result_buffer_length int) *Channels {
	channel := &Channels{
		semaphoe: make(chan int, ConcurrentProcesses),
		results:  make(chan SnmpResult, result_buffer_length),
	}

	return channel
}

func makeTarpanResult(c *Channels) []*TarpanResult {
	var tarpanResults []*TarpanResult
	var varbinds []VarBind
	var result SnmpResult
	length := len(c.results)
	for i := 0; i < length; i++ {
		varbinds = []VarBind{}
		result = <-c.results
		for _, val := range result.results {
			for _, o := range result.target.OIDs {
				n := strings.TrimLeft(val.Name, ".")
				if o.OID == n {
					v := VarBind{
						Description: o.Description,
						OID:         val.Name,
						Type:        val.Type,
						Value:       val.Value,
						Time:        result.time,
					}
					varbinds = append(varbinds, v)
					break
				}
			}
		}
		tr := &TarpanResult{
			Name:      result.target.Name,
			Address:   result.target.Address,
			Port:      result.target.Port,
			Version:   result.target.Version,
			Community: result.target.Community,
			VarBinds:  varbinds,
		}
		tarpanResults = append(tarpanResults, tr)
	}

	return tarpanResults
}

func Collect(dataset *DataSet) []*TarpanResult {
	var waitGroup sync.WaitGroup
	var managers []*TarpanManager
	//var tm TarpanManager
	var channels *Channels
	var oids []string

	for i := 0; i < len(dataset.Targets); i++ {
		managers = append(managers, &TarpanManager{
			snmp: &gosnmp.GoSNMP{},
		})
	}

	channels = makeChannel(len(dataset.Targets))
	for index := range dataset.Targets {

		// TODO: split oid slice according to PDU size
		oids = []string{}
		for oid_idx := range dataset.Targets[index].OIDs {
			oids = append(oids, dataset.Targets[index].OIDs[oid_idx].OID)
		}

		waitGroup.Add(1)
		go func(ds *DataSet, idx int, o []string, c *Channels) {
			c.semaphoe <- 0
			req_body, req_body_err := makeRequestBody(ds, idx)
			if req_body_err != nil {
				log.Print(req_body_err)
				<-c.semaphoe
				return
			}
			t := time.Now()
			results, err := managers[idx].Get(req_body, o)
			if err != nil {
				log.Print(err)
				<-c.semaphoe
				waitGroup.Done()
				return
			}
			ret := SnmpResult{
				target:  ds.Targets[idx],
				results: results,
				time:    t.Unix(),
			}
			c.results <- ret
			<-c.semaphoe
			waitGroup.Done()
		}(dataset, index, oids, channels)
	}
	waitGroup.Wait()
	tr := makeTarpanResult(channels)

	return tr
}

func Run(target string) (int, error) {
	var err error

	// Load targets
	dataset, loadErr := loadConfig(target)
	if loadErr != nil {
		return ExitCodeConfError, loadErr
	}

	// collect data
	tr := Collect(dataset)

	// output
	Write("aa", tr)

	return ExitCodeOK, err
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"compress/gzip"
	"fmt"
	"io"
	"log"
	"os"
)

const (
	TAG_END        = 0
	TAG_BYTE       = 1
	TAG_SHORT      = 2
	TAG_INT        = 3
	TAG_LONG       = 4
	TAG_FLOAT      = 5
	TAG_DOUBLE     = 6
	TAG_BYTE_ARRAY = 7
	TAG_STRING     = 8
	TAG_LIST       = 9
	TAG_COMPOUND   = 10
)

type NBTReader struct {
	r *bufio.Reader
}

func NewNBTReader(r io.Reader) (nr *NBTReader, err os.Error) {
	var rd io.Reader
	if rd, err = gzip.NewReader(r); err != nil {
		return
	}
	return &NBTReader{r: bufio.NewReader(rd)}, nil
}

type Tag int

func (r *NBTReader) ReadString() (str string, err os.Error) {
	var l int
	if l, err = r.ReadShort(); err != nil {
		return
	}
	data := make([]byte, l)
	if _, err = r.r.Read(data); err != nil {
		return
	}
	return string(data), nil
}

func (r *NBTReader) ReadShort() (val int, err os.Error) {
	buf := [2]byte{}
	if _, err = r.r.Read(buf[:]); err != nil {
		return
	}
	val = int(buf[1]) + (int(buf[0]) << 8) // Big Endian
	return
}

func (r *NBTReader) ReadInt() (val int, err os.Error) {
	buf := [4]byte{}
	if _, err = r.r.Read(buf[:]); err != nil {
		return
	}
	for i := 0; i < 4; i++ {
		val <<= 8
		val += int(buf[i])
	}
	return
}

func (r *NBTReader) ReadTagName() (typ byte, name string, err os.Error) {
	if typ, err = r.r.ReadByte(); err != nil {
		return
	}
	if typ == TAG_END {
		return
	}
	name, err = r.ReadString()
	fmt.Printf("Typ: %d, Name: %s\n", typ, name)
	return
}

func (r *NBTReader) ReadByteArray() (data []byte, err os.Error) {
	var l int
	if l, err = r.ReadInt(); err != nil {
		return
	}
	data = make([]byte, l)
	_, err = r.r.Read(data)
	return
}

type SchematicReader struct {
	r *NBTReader
}

func NewSchematicReader(r io.Reader) (sr *SchematicReader, err os.Error) {
	var nr *NBTReader
	if nr, err = NewNBTReader(r); err != nil {
		return
	}
	return &SchematicReader{r: nr}, nil
}

type Schematic struct {
	Width     int
	Length    int
	Height    int
	Materials string
	Blocks    []byte
}

func (r *SchematicReader) Parse() (s *Schematic, err os.Error) {
	var typ byte
	var name string
	if typ, name, err = r.r.ReadTagName(); err != nil {
		return
	}
	if typ != TAG_COMPOUND {
		return nil, fmt.Errorf("Top level tag must be compound. Got: %d", typ)
	}
	if name != "Schematic" {
		return nil, fmt.Errorf("Unexpected tag name: %s, want: Schematic", name)
	}
	s = new(Schematic)
	for {
		if typ, name, err = r.r.ReadTagName(); err != nil {
			return
		}
		if typ == TAG_END {
			break
		}
		switch name {
		case "Width":
			s.Width, err = r.r.ReadShort()
		case "Length":
			s.Length, err = r.r.ReadShort()
		case "Height":
			s.Height, err = r.r.ReadShort()
		case "Materials":
			s.Materials, err = r.r.ReadString()
		case "Blocks":
			s.Blocks, err = r.r.ReadByteArray()
		default:
			return nil, fmt.Errorf("Unexpected tag: %d, name: %s\n", typ, name)
		}
		if err != nil {
			return
		}
	}
	if s.Materials != "Alpha" {
		return nil, fmt.Errorf("Materials must have 'Alpha' value, got: '%s'", s.Materials)
	}
	return
}

func ReadSchematic(input io.Reader) (err os.Error) {
	var r *SchematicReader
	if r, err = NewSchematicReader(input); err != nil {
		return
	}
	_, err = r.Parse()
	return
}

func main() {
	if err := ReadSchematic(os.Stdin); err != nil {
		log.Fatalf("ReadSchematic: %v", err)
	}
}
<commit_msg>Schematic now implements BoolVoxelVolume interface<commit_after>package main

import (
	"bufio"
	"compress/gzip"
	"fmt"
	"io"
	"log"
	"os"
)

const (
	TAG_END        = 0
	TAG_BYTE       = 1
	TAG_SHORT      = 2
	TAG_INT        = 3
	TAG_LONG       = 4
	TAG_FLOAT      = 5
	TAG_DOUBLE     = 6
	TAG_BYTE_ARRAY = 7
	TAG_STRING     = 8
	TAG_LIST       = 9
	TAG_COMPOUND   = 10
)

type NBTReader struct {
	r *bufio.Reader
}

func NewNBTReader(r io.Reader) (nr *NBTReader, err os.Error) {
	var rd io.Reader
	if rd, err = gzip.NewReader(r); err != nil {
		return
	}
	return &NBTReader{r: bufio.NewReader(rd)}, nil
}

type Tag int

func (r *NBTReader) ReadString() (str string, err os.Error) {
	var l int
	if l, err = r.ReadShort(); err != nil {
		return
	}
	data := make([]byte, l)
	if _, err = r.r.Read(data); err != nil {
		return
	}
	return string(data), nil
}

func (r *NBTReader) ReadShort() (val int, err os.Error) {
	buf := [2]byte{}
	if _, err = r.r.Read(buf[:]); err != nil {
		return
	}
	val = int(buf[1]) + (int(buf[0]) << 8) // Big Endian
	return
}

func (r *NBTReader) ReadInt() (val int, err os.Error) {
	buf := [4]byte{}
	if _, err = r.r.Read(buf[:]); err != nil {
		return
	}
	for i := 0; i < 4; i++ {
		val <<= 8
		val += int(buf[i])
	}
	return
}

func (r *NBTReader) ReadTagName() (typ byte, name string, err os.Error) {
	if typ, err = r.r.ReadByte(); err != nil {
		return
	}
	if typ == TAG_END {
		return
	}
	name, err = r.ReadString()
	fmt.Printf("Typ: %d, Name: %s\n", typ, name)
	return
}

func (r *NBTReader) ReadByteArray() (data []byte, err os.Error) {
	var l int
	if l, err = r.ReadInt(); err != nil {
		return
	}
	data = make([]byte, l)
	_, err = r.r.Read(data)
	return
}

type SchematicReader struct {
	r *NBTReader
}

type BoolVoxelVolume interface {
	Get(x, y, z int) bool
	XLen() int
	YLen() int
	ZLen() int
}

func NewSchematicReader(r io.Reader) (sr *SchematicReader, err os.Error) {
	var nr *NBTReader
	if nr, err = NewNBTReader(r); err != nil {
		return
	}
	return &SchematicReader{r: nr}, nil
}

type Schematic struct {
	Width     int
	Length    int
	Height    int
	Materials string
	Blocks    []byte
}

func (r *SchematicReader) Parse() (s *Schematic, err os.Error) {
	var typ byte
	var name string
	if typ, name, err = r.r.ReadTagName(); err != nil {
		return
	}
	if typ != TAG_COMPOUND {
		return nil, fmt.Errorf("Top level tag must be compound. Got: %d", typ)
	}
	if name != "Schematic" {
		return nil, fmt.Errorf("Unexpected tag name: %s, want: Schematic", name)
	}
	s = new(Schematic)
	for {
		if typ, name, err = r.r.ReadTagName(); err != nil {
			return
		}
		if typ == TAG_END {
			break
		}
		switch name {
		case "Width":
			s.Width, err = r.r.ReadShort()
		case "Length":
			s.Length, err = r.r.ReadShort()
		case "Height":
			s.Height, err = r.r.ReadShort()
		case "Materials":
			s.Materials, err = r.r.ReadString()
		case "Blocks":
			s.Blocks, err = r.r.ReadByteArray()
		default:
			return nil, fmt.Errorf("Unexpected tag: %d, name: %s\n", typ, name)
		}
		if err != nil {
			return
		}
	}
	if s.Materials != "Alpha" {
		return nil, fmt.Errorf("Materials must have 'Alpha' value, got: '%s'", s.Materials)
	}
	return
}

func (s *Schematic) XLen() int {
	return s.Width
}

func (s *Schematic) YLen() int {
	return s.Height
}

func (s *Schematic) ZLen() int {
	return s.Length
}

func (s *Schematic) Get(x, y, z int) bool {
	index := y*s.XLen()*s.ZLen() + z*s.XLen() + x
	return s.Blocks[index] != 0
}

func ReadSchematic(input io.Reader) (vol BoolVoxelVolume, err os.Error) {
	var r *SchematicReader
	if r, err = NewSchematicReader(input); err != nil {
		return
	}
	vol, err = r.Parse()
	return
}

func main() {
	vol, err := ReadSchematic(os.Stdin)
	if err != nil {
		log.Fatalf("ReadSchematic: %v", err)
	}
	fmt.Printf("Xlen: %d, YLen: %d, ZLen: %d\n", vol.XLen(), vol.YLen(), vol.ZLen())
}
<|endoftext|>


<commit_before>package http2

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

	"github.com/summerwind/h2spec/config"
	"github.com/summerwind/h2spec/spec"
)

func Data() *spec.TestGroup {
	tg := NewTestGroup("6.1", "DATA")

	// DATA frames MUST be associated with a stream. If a DATA frame is
	// received whose stream identifier field is 0x0, the recipient
	// MUST respond with a connection error (Section 5.4.1) of type
	// PROTOCOL_ERROR.
	tg.AddTestCase(&spec.TestCase{
		Desc:        "Sends a DATA frame with 0x0 stream identifier",
		Requirement: "The endpoint MUST respond with a connection error of type PROTOCOL_ERROR.",
		Run: func(c *config.Config, conn *spec.Conn) error {
			err := conn.Handshake()
			if err != nil {
				return err
			}

			conn.WriteData(0, true, []byte("test"))

			return spec.VerifyConnectionError(conn, http2.ErrCodeProtocol)
		},
	})

	// If a DATA frame is received whose stream is not in "open" or
	// "half-closed (local)" state, the recipient MUST respond with
	// a stream error (Section 5.4.2) of type STREAM_CLOSED.
	//
	// Note: This test case is duplicated with 5.1.
	tg.AddTestCase(&spec.TestCase{
		Desc:        "Sends a DATA frame on the stream that is not in \"open\" or \"half-closed (local)\" state",
		Requirement: "The endpoint MUST respond with a stream error of type STREAM_CLOSED.",
		Run: func(c *config.Config, conn *spec.Conn) error {
			var streamID uint32 = 1

			err := conn.Handshake()
			if err != nil {
				return err
			}

			headers := spec.CommonHeaders(c)
			headers[0].Value = "POST"

			hp := http2.HeadersFrameParam{
				StreamID:      streamID,
				EndStream:     true,
				EndHeaders:    true,
				BlockFragment: conn.EncodeHeaders(headers),
			}

			conn.WriteHeaders(hp)
			conn.WriteData(streamID, true, []byte("test"))

			return spec.VerifyStreamError(conn, http2.ErrCodeStreamClosed)
		},
	})

	// If the length of the padding is the length of the frame payload
	// or greater, the recipient MUST treat this as a connection error
	// (Section 5.4.1) of type PROTOCOL_ERROR.
	tg.AddTestCase(&spec.TestCase{
		Desc:        "Sends a DATA frame with invalid pad length",
		Requirement: "The endpoint MUST treat this as a connection error of type PROTOCOL_ERROR.",
		Run: func(c *config.Config, conn *spec.Conn) error {
			var streamID uint32 = 1

			err := conn.Handshake()
			if err != nil {
				return err
			}

			headers := spec.CommonHeaders(c)
			headers[0].Value = "POST"
			headers = append(headers, spec.HeaderField("content-length", "4"))

			hp := http2.HeadersFrameParam{
				StreamID:      streamID,
				EndStream:     false,
				EndHeaders:    true,
				BlockFragment: conn.EncodeHeaders(headers),
			}

			conn.WriteHeaders(hp)

			// DATA frame:
			// frame length: 5, pad length: 6
			conn.Send([]byte("\x00\x00\x05\x00\x09\x00\x00\x00\x01"))
			conn.Send([]byte("\x06\x54\x65\x73\x74"))

			return spec.VerifyStreamError(conn, http2.ErrCodeProtocol)
		},
	})

	return tg
}
<commit_msg>Treat as connection error with invalid pad length<commit_after>package http2

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

	"github.com/summerwind/h2spec/config"
	"github.com/summerwind/h2spec/spec"
)

func Data() *spec.TestGroup {
	tg := NewTestGroup("6.1", "DATA")

	// DATA frames MUST be associated with a stream. If a DATA frame is
	// received whose stream identifier field is 0x0, the recipient
	// MUST respond with a connection error (Section 5.4.1) of type
	// PROTOCOL_ERROR.
	tg.AddTestCase(&spec.TestCase{
		Desc:        "Sends a DATA frame with 0x0 stream identifier",
		Requirement: "The endpoint MUST respond with a connection error of type PROTOCOL_ERROR.",
		Run: func(c *config.Config, conn *spec.Conn) error {
			err := conn.Handshake()
			if err != nil {
				return err
			}

			conn.WriteData(0, true, []byte("test"))

			return spec.VerifyConnectionError(conn, http2.ErrCodeProtocol)
		},
	})

	// If a DATA frame is received whose stream is not in "open" or
	// "half-closed (local)" state, the recipient MUST respond with
	// a stream error (Section 5.4.2) of type STREAM_CLOSED.
	//
	// Note: This test case is duplicated with 5.1.
	tg.AddTestCase(&spec.TestCase{
		Desc:        "Sends a DATA frame on the stream that is not in \"open\" or \"half-closed (local)\" state",
		Requirement: "The endpoint MUST respond with a stream error of type STREAM_CLOSED.",
		Run: func(c *config.Config, conn *spec.Conn) error {
			var streamID uint32 = 1

			err := conn.Handshake()
			if err != nil {
				return err
			}

			headers := spec.CommonHeaders(c)
			headers[0].Value = "POST"

			hp := http2.HeadersFrameParam{
				StreamID:      streamID,
				EndStream:     true,
				EndHeaders:    true,
				BlockFragment: conn.EncodeHeaders(headers),
			}

			conn.WriteHeaders(hp)
			conn.WriteData(streamID, true, []byte("test"))

			return spec.VerifyStreamError(conn, http2.ErrCodeStreamClosed)
		},
	})

	// If the length of the padding is the length of the frame payload
	// or greater, the recipient MUST treat this as a connection error
	// (Section 5.4.1) of type PROTOCOL_ERROR.
	tg.AddTestCase(&spec.TestCase{
		Desc:        "Sends a DATA frame with invalid pad length",
		Requirement: "The endpoint MUST treat this as a connection error of type PROTOCOL_ERROR.",
		Run: func(c *config.Config, conn *spec.Conn) error {
			var streamID uint32 = 1

			err := conn.Handshake()
			if err != nil {
				return err
			}

			headers := spec.CommonHeaders(c)
			headers[0].Value = "POST"
			headers = append(headers, spec.HeaderField("content-length", "4"))

			hp := http2.HeadersFrameParam{
				StreamID:      streamID,
				EndStream:     false,
				EndHeaders:    true,
				BlockFragment: conn.EncodeHeaders(headers),
			}

			conn.WriteHeaders(hp)

			// DATA frame:
			// frame length: 5, pad length: 6
			conn.Send([]byte("\x00\x00\x05\x00\x09\x00\x00\x00\x01"))
			conn.Send([]byte("\x06\x54\x65\x73\x74"))

			return spec.VerifyConnectionError(conn, http2.ErrCodeProtocol)
		},
	})

	return tg
}
<|endoftext|>


<commit_before>package fixer

import (
	"encoding/json"
	"fmt"
	"time"

	"github.com/flynn/flynn/controller/utils"
	"github.com/flynn/flynn/discoverd/client"
	"github.com/flynn/flynn/host/types"
	"github.com/flynn/flynn/pkg/cluster"
	sirenia "github.com/flynn/flynn/pkg/sirenia/client"
	state "github.com/flynn/flynn/pkg/sirenia/state"
)

func (f *ClusterFixer) CheckSirenia(svc string) error {
	log := f.l.New("fn", "CheckSirenia", "service", svc)
	log.Info("checking sirenia cluster status")
	service := discoverd.NewService(svc)
	leader, _ := service.Leader()
	if leader == nil || leader.Addr == "" {
		log.Info("no running leader")
		leader = nil
	} else {
		log.Info("found running leader")
	}
	instances, _ := service.Instances()
	log.Info("found running instances", "count", len(instances))

	log.Info("getting sirenia status")
	var status *sirenia.Status
	if leader != nil && leader.Addr != "" {
		client := sirenia.NewClient(leader.Addr)
		var err error
		status, err = client.Status()
		if err != nil {
			log.Error("error getting status from leader", "error", err)
		}
	}
	if status != nil && status.Database != nil && status.Database.ReadWrite {
		log.Info("cluster claims to be read-write")
		return nil
	}
	return fmt.Errorf("cluster isn't read-write")
}

func (f *ClusterFixer) FixSirenia(svc string) error {
	log := f.l.New("fn", "FixSirenia", "service", svc)

	service := discoverd.NewService(svc)
	instances, _ := service.Instances()
	leader, _ := service.Leader()

	log.Info("getting service metadata")
	meta, err := service.GetMeta()
	if err != nil {
		return fmt.Errorf("error getting sirenia state from discoverd: %s", err)
	}

	var state state.State
	if err := json.Unmarshal(meta.Data, &state); err != nil {
		return fmt.Errorf("error decoding state: %s", err)
	}
	if state.Primary == nil {
		return fmt.Errorf("no primary in sirenia state")
	}

	log.Info("getting primary job info", "job.id", state.Primary.Meta["FLYNN_JOB_ID"])
	primaryJob, primaryHost, err := f.GetJob(state.Primary.Meta["FLYNN_JOB_ID"])
	if err != nil {
		log.Error("unable to get primary job info")
	}
	var syncJob *host.Job
	var syncHost *cluster.Host
	if state.Sync != nil {
		log.Info("getting sync job info", "job.id", state.Sync.Meta["FLYNN_JOB_ID"])
		syncJob, syncHost, err = f.GetJob(state.Sync.Meta["FLYNN_JOB_ID"])
		if err != nil {
			log.Error("unable to get sync job info")
		}
	}

	waitForInstance := func(jobID string) (func() (string, error), error) {
		watchCh := make(chan *discoverd.Event)
		upCh := make(chan string)
		stream, err := service.Watch(watchCh)
		if err != nil {
			return nil, fmt.Errorf("error watching discoverd service: %s", err)
		}
		go func() {
			var current bool
			for event := range watchCh {
				if event.Kind == discoverd.EventKindCurrent {
					current = true
					continue
				}
				if !current || event.Kind != discoverd.EventKindUp {
					continue
				}
				if event.Instance.Meta["FLYNN_JOB_ID"] == jobID {
					upCh <- event.Instance.Addr
				}
			}
		}()
		return func() (string, error) {
			log.Info("waiting for instance to start", "job.id", jobID)
			defer stream.Close()
			select {
			case addr := <-upCh:
				return addr, nil
			case <-time.After(time.Minute):
				return "", fmt.Errorf("timed out waiting for sirenia instance to come up")
			}
		}, nil
	}

	log.Info("terminating unassigned sirenia instances")
outer:
	for _, i := range instances {
		if i.Addr == state.Primary.Addr || (state.Sync != nil && i.Addr == state.Sync.Addr) {
			continue
		}
		for _, a := range state.Async {
			if i.Addr == a.Addr {
				continue outer
			}
		}
		// job not assigned in state, attempt to terminate it
		if jobID, ok := i.Meta["FLYNN_JOB_ID"]; ok {
			hostID, err := cluster.ExtractHostID(jobID)
			if err != nil {
				log.Error("error extracting host id from jobID", "jobID", jobID, "err", err)
			}
			h := f.Host(hostID)
			if h != nil {
				if err := h.StopJob(jobID); err != nil {
					log.Error("error stopping unassigned sirenia job", "jobID", jobID)
				}
			} else {
				log.Error("host not found", "hostID", hostID)
			}
		}
	}

	isRunning := func(addr string) bool {
		for _, i := range instances {
			if i.Addr == addr {
				return true
			}
		}
		return false
	}

	// if the leader isn't currently running then start it using primaryJob/primaryHost
	var wait func() (string, error)
	if !isRunning(state.Primary.Addr) {
		// if we don't have info about the primary job attempt to promote the sync
		if primaryJob == nil {
			if syncJob != nil {
				// set primary job to sync
				primaryJob = syncJob
				primaryHost = syncHost

				// nil out sync job now so we can re-allocate it.
				syncJob = nil
				syncHost = nil
			} else {
				return fmt.Errorf("neither primary or sync job info available")
			}
		}

		primaryJob.ID = cluster.GenerateJobID(primaryHost.ID(), "")
		f.FixJobEnv(primaryJob)
		log.Info("starting primary job", "job.id", primaryJob.ID)
		wait, err = waitForInstance(primaryJob.ID)
		if err != nil {
			return err
		}
		if err := primaryHost.AddJob(primaryJob); err != nil {
			return fmt.Errorf("error starting primary job on %s: %s", primaryHost.ID(), err)
		}
	}
	if !state.Singleton && !isRunning(state.Sync.Addr) {
		if syncHost == nil {
			for _, h := range f.hosts {
				if h.ID() != primaryHost.ID() {
					syncHost = h
					break
				}
			}
			if syncHost == nil {
				// if there are no other hosts, use the same one we put the primary on
				syncHost = primaryHost
			}
		}
		// if we don't have a sync job then copy the primary job
		// and provision a new volume
		if syncJob == nil {
			syncJob = primaryJob
			if err := utils.ProvisionVolume(syncHost, syncJob); err != nil {
				return fmt.Errorf("error creating volume on %s: %s", syncHost.ID(), err)
			}
		}
		syncJob.ID = cluster.GenerateJobID(syncHost.ID(), "")
		f.FixJobEnv(syncJob)
		log.Info("starting sync job", "job.id", syncJob.ID)
		if wait == nil {
			wait, err = waitForInstance(syncJob.ID)
			if err != nil {
				return err
			}
		}
		if err := syncHost.AddJob(syncJob); err != nil {
			return fmt.Errorf("error starting additional job on %s: %s", syncHost.ID(), err)
		}
	}

	if wait != nil {
		addr, err := wait()
		if err != nil {
			return err
		}
		if leader != nil {
			addr = leader.Addr
		}
		log.Info("waiting for cluster to come up read-write")
		return sirenia.NewClient(addr).WaitForReadWrite(5 * time.Minute)
	}
	return nil
}
<commit_msg>host/fixer: Don't use empty leader addr to confirm read/write<commit_after>package fixer

import (
	"encoding/json"
	"fmt"
	"time"

	"github.com/flynn/flynn/controller/utils"
	"github.com/flynn/flynn/discoverd/client"
	"github.com/flynn/flynn/host/types"
	"github.com/flynn/flynn/pkg/cluster"
	sirenia "github.com/flynn/flynn/pkg/sirenia/client"
	state "github.com/flynn/flynn/pkg/sirenia/state"
)

func (f *ClusterFixer) CheckSirenia(svc string) error {
	log := f.l.New("fn", "CheckSirenia", "service", svc)
	log.Info("checking sirenia cluster status")
	service := discoverd.NewService(svc)
	leader, _ := service.Leader()
	if leader == nil || leader.Addr == "" {
		log.Info("no running leader")
		leader = nil
	} else {
		log.Info("found running leader")
	}
	instances, _ := service.Instances()
	log.Info("found running instances", "count", len(instances))

	log.Info("getting sirenia status")
	var status *sirenia.Status
	if leader != nil && leader.Addr != "" {
		client := sirenia.NewClient(leader.Addr)
		var err error
		status, err = client.Status()
		if err != nil {
			log.Error("error getting status from leader", "error", err)
		}
	}
	if status != nil && status.Database != nil && status.Database.ReadWrite {
		log.Info("cluster claims to be read-write")
		return nil
	}
	return fmt.Errorf("cluster isn't read-write")
}

func (f *ClusterFixer) FixSirenia(svc string) error {
	log := f.l.New("fn", "FixSirenia", "service", svc)

	service := discoverd.NewService(svc)
	instances, _ := service.Instances()
	leader, _ := service.Leader()

	log.Info("getting service metadata")
	meta, err := service.GetMeta()
	if err != nil {
		return fmt.Errorf("error getting sirenia state from discoverd: %s", err)
	}

	var state state.State
	if err := json.Unmarshal(meta.Data, &state); err != nil {
		return fmt.Errorf("error decoding state: %s", err)
	}
	if state.Primary == nil {
		return fmt.Errorf("no primary in sirenia state")
	}

	log.Info("getting primary job info", "job.id", state.Primary.Meta["FLYNN_JOB_ID"])
	primaryJob, primaryHost, err := f.GetJob(state.Primary.Meta["FLYNN_JOB_ID"])
	if err != nil {
		log.Error("unable to get primary job info")
	}
	var syncJob *host.Job
	var syncHost *cluster.Host
	if state.Sync != nil {
		log.Info("getting sync job info", "job.id", state.Sync.Meta["FLYNN_JOB_ID"])
		syncJob, syncHost, err = f.GetJob(state.Sync.Meta["FLYNN_JOB_ID"])
		if err != nil {
			log.Error("unable to get sync job info")
		}
	}

	waitForInstance := func(jobID string) (func() (string, error), error) {
		watchCh := make(chan *discoverd.Event)
		upCh := make(chan string)
		stream, err := service.Watch(watchCh)
		if err != nil {
			return nil, fmt.Errorf("error watching discoverd service: %s", err)
		}
		go func() {
			var current bool
			for event := range watchCh {
				if event.Kind == discoverd.EventKindCurrent {
					current = true
					continue
				}
				if !current || event.Kind != discoverd.EventKindUp {
					continue
				}
				if event.Instance.Meta["FLYNN_JOB_ID"] == jobID {
					upCh <- event.Instance.Addr
				}
			}
		}()
		return func() (string, error) {
			log.Info("waiting for instance to start", "job.id", jobID)
			defer stream.Close()
			select {
			case addr := <-upCh:
				return addr, nil
			case <-time.After(time.Minute):
				return "", fmt.Errorf("timed out waiting for sirenia instance to come up")
			}
		}, nil
	}

	log.Info("terminating unassigned sirenia instances")
outer:
	for _, i := range instances {
		if i.Addr == state.Primary.Addr || (state.Sync != nil && i.Addr == state.Sync.Addr) {
			continue
		}
		for _, a := range state.Async {
			if i.Addr == a.Addr {
				continue outer
			}
		}
		// job not assigned in state, attempt to terminate it
		if jobID, ok := i.Meta["FLYNN_JOB_ID"]; ok {
			hostID, err := cluster.ExtractHostID(jobID)
			if err != nil {
				log.Error("error extracting host id from jobID", "jobID", jobID, "err", err)
			}
			h := f.Host(hostID)
			if h != nil {
				if err := h.StopJob(jobID); err != nil {
					log.Error("error stopping unassigned sirenia job", "jobID", jobID)
				}
			} else {
				log.Error("host not found", "hostID", hostID)
			}
		}
	}

	isRunning := func(addr string) bool {
		for _, i := range instances {
			if i.Addr == addr {
				return true
			}
		}
		return false
	}

	// if the leader isn't currently running then start it using primaryJob/primaryHost
	var wait func() (string, error)
	if !isRunning(state.Primary.Addr) {
		// if we don't have info about the primary job attempt to promote the sync
		if primaryJob == nil {
			if syncJob != nil {
				// set primary job to sync
				primaryJob = syncJob
				primaryHost = syncHost

				// nil out sync job now so we can re-allocate it.
				syncJob = nil
				syncHost = nil
			} else {
				return fmt.Errorf("neither primary or sync job info available")
			}
		}

		primaryJob.ID = cluster.GenerateJobID(primaryHost.ID(), "")
		f.FixJobEnv(primaryJob)
		log.Info("starting primary job", "job.id", primaryJob.ID)
		wait, err = waitForInstance(primaryJob.ID)
		if err != nil {
			return err
		}
		if err := primaryHost.AddJob(primaryJob); err != nil {
			return fmt.Errorf("error starting primary job on %s: %s", primaryHost.ID(), err)
		}
	}
	if !state.Singleton && !isRunning(state.Sync.Addr) {
		if syncHost == nil {
			for _, h := range f.hosts {
				if h.ID() != primaryHost.ID() {
					syncHost = h
					break
				}
			}
			if syncHost == nil {
				// if there are no other hosts, use the same one we put the primary on
				syncHost = primaryHost
			}
		}
		// if we don't have a sync job then copy the primary job
		// and provision a new volume
		if syncJob == nil {
			syncJob = primaryJob
			if err := utils.ProvisionVolume(syncHost, syncJob); err != nil {
				return fmt.Errorf("error creating volume on %s: %s", syncHost.ID(), err)
			}
		}
		syncJob.ID = cluster.GenerateJobID(syncHost.ID(), "")
		f.FixJobEnv(syncJob)
		log.Info("starting sync job", "job.id", syncJob.ID)
		if wait == nil {
			wait, err = waitForInstance(syncJob.ID)
			if err != nil {
				return err
			}
		}
		if err := syncHost.AddJob(syncJob); err != nil {
			return fmt.Errorf("error starting additional job on %s: %s", syncHost.ID(), err)
		}
	}

	if wait != nil {
		addr, err := wait()
		if err != nil {
			return err
		}
		if leader != nil && leader.Addr != "" {
			addr = leader.Addr
		}
		log.Info("waiting for cluster to come up read-write", "addr", addr)
		return sirenia.NewClient(addr).WaitForReadWrite(5 * time.Minute)
	}
	return nil
}
<|endoftext|>


<commit_before>package parser

import (
  "testing"
  "bitbucket.org/yyuu/bs/ast"
//"bitbucket.org/yyuu/bs/duck"
  "bitbucket.org/yyuu/bs/entity"
  "bitbucket.org/yyuu/bs/xt"
)

func TestParseEmpty(t *testing.T) {
  _, err := ParseExpr("")
  xt.AssertNil(t, "", err)
}

func defvars(xs...entity.DefinedVariable) []entity.DefinedVariable {
  return xs
}

func vardecls(xs...entity.UndefinedVariable) []entity.UndefinedVariable {
  return xs
}

func defuns(xs...entity.DefinedFunction) []entity.DefinedFunction {
  return xs
}

func funcdecls(xs...entity.UndefinedFunction) []entity.UndefinedFunction {
  return xs
}

func defconsts(xs...entity.Constant) []entity.Constant {
  return xs
}

func defstructs(xs...ast.StructNode) []ast.StructNode {
  return xs
}

func defunions(xs...ast.UnionNode) []ast.UnionNode {
  return xs
}

func typedefs(xs...ast.TypedefNode) []ast.TypedefNode {
  return xs
}

/*
func TestParseFuncallWithoutArguments(t *testing.T) {
  s := `
    int f(void) {
      return getc();
    }
  `
  x := ast.AST {
    loc(1,1),
    ast.Declarations {
      Defvars: defvars(),
      Vardecls: vardecls(),
      Defuns: defuns(
//      []duck.IStmtNode {
//        ast.NewExprStmtNode(loc(1,1),
//          ast.NewFuncallNode(loc(1,1),
//            ast.NewVariableNode(loc(1,1),
//              "gets",
//            ),
//            []duck.IExprNode {
//            },
//          ),
//        ),
//      },
      ),
      Funcdecls: funcdecls(),
      Constants: defconsts(),
      Defstructs: defstructs(),
      Defunions: defunions(),
      Typedefs: typedefs(),
    },
  }
  y, err := ParseExpr(s)
  xt.AssertNil(t, "", err)
  xt.AssertStringEqualsDiff(t, "parse funcall w/o arguments", xt.JSON(y), xt.JSON(x))
  xt.AssertDeepEquals(t, "", y, x)
}
 */

/*
func TestParseFuncallWithSingleArgument(t *testing.T) {
  s := `
    void f(int n) {
      println("hello, %d", n);
    }
  `
  x := ast.AST {
//  []duck.IStmtNode {
//    ast.NewExprStmtNode(loc(1,5),
//      ast.NewFuncallNode(loc(1,5),
//        ast.NewVariableNode(loc(1,5),
//          "println",
//        ),
//        []duck.IExprNode {
//          ast.NewStringLiteralNode(loc(1,13),
//            "\"hello, world\"",
//          ),
//        },
//      ),
//    ),
//  },
    loc(1,5),
    ast.Declarations {
      Defvars: []entity.DefinedVariable { },
      Vardecls: []entity.UndefinedVariable { },
      Defuns: []entity.DefinedFunction {
      },
      Funcdecls: []entity.UndefinedFunction { },
      Constants: []entity.Constant { },
      Defstructs: []ast.StructNode { },
      Defunions: []ast.UnionNode { },
      Typedefs: []ast.TypedefNode { },
    },
  }
  y, err := ParseExpr(s)
  xt.AssertNil(t, "", err)
  xt.AssertStringEqualsDiff(t, "parse funcall w/ single argument", xt.JSON(y), xt.JSON(x))
  xt.AssertDeepEquals(t, "", y, x)
}
 */

/*
func TestParseFuncallWithMultipleArguments(t *testing.T) {
  s := `

    println(
      "hello, %s",
      "world"
    );
  `
  x := ast.AST {
//  []duck.IStmtNode {
//    ast.NewExprStmtNode(loc(2,5),
//      ast.NewFuncallNode(loc(2,5),
//        ast.NewVariableNode(loc(2,5),
//          "println",
//        ),
//        []duck.IExprNode {
//          ast.NewStringLiteralNode(loc(3,7),
//            "\"hello, %s\"",
//          ),
//          ast.NewStringLiteralNode(loc(4,7),
//            "\"world\"",
//          ),
//        },
//      ),
//    ),
//  },
    loc(2,5),
    ast.Declarations {
      Defvars: []entity.DefinedVariable { },
      Vardecls: []entity.UndefinedVariable { },
      Defuns: []entity.DefinedFunction { },
      Funcdecls: []entity.UndefinedFunction { },
      Constants: []entity.Constant { },
      Defstructs: []ast.StructNode { },
      Defunions: []ast.UnionNode { },
      Typedefs: []ast.TypedefNode { },
    },
  }
  y, err := ParseExpr(s)
  xt.AssertNil(t, "", err)
  xt.AssertStringEqualsDiff(t, "funcall w/ multiple arguments", xt.JSON(y), xt.JSON(x))
  xt.AssertDeepEquals(t, "", y, x)
}
 */

/*
func TestFor1(t *testing.T) {
  s := `
    for (i=0; i<100; i++) println(i);
`
  x := ast.AST {
//  []duck.IStmtNode {
//    ast.NewForNode(loc(1,5),
//      ast.NewAssignNode(loc(1,10),
//        ast.NewVariableNode(loc(1,10),
//          "i",
//        ),
//        ast.NewIntegerLiteralNode(loc(1,12),
//          "0",
//        ),
//      ),
//      ast.NewBinaryOpNode(loc(1,15),
//        "<",
//        ast.NewVariableNode(loc(1,15),
//          "i",
//        ),
//        ast.NewIntegerLiteralNode(loc(1,17),
//          "100",
//        ),
//      ),
//      ast.NewSuffixOpNode(loc(1,22),
//        "++",
//        ast.NewVariableNode(loc(1,22),
//          "i",
//        ),
//      ),
//      ast.NewExprStmtNode(loc(1,27),
//        ast.NewFuncallNode(loc(1,27),
//          ast.NewVariableNode(loc(1,27),
//            "println",
//          ),
//          []duck.IExprNode {
//            ast.NewVariableNode(loc(1,35),
//              "i",
//            ),
//          },
//        ),
//      ),
//    ),
//  },
    loc(2,5),
    ast.Declarations {
      Defvars: []entity.DefinedVariable { },
      Vardecls: []entity.UndefinedVariable { },
      Defuns: []entity.DefinedFunction { },
      Funcdecls: []entity.UndefinedFunction { },
      Constants: []entity.Constant { },
      Defstructs: []ast.StructNode { },
      Defunions: []ast.UnionNode { },
      Typedefs: []ast.TypedefNode { },
    },
  }
  y, err := ParseExpr(s)
  xt.AssertNil(t, "", err)
  xt.AssertStringEqualsDiff(t, "for1", xt.JSON(y), xt.JSON(x))
  xt.AssertDeepEquals(t, "", y, x)
}
 */
<commit_msg>Refactor test code of parser<commit_after>package parser

import (
  "testing"
  "bitbucket.org/yyuu/bs/ast"
//"bitbucket.org/yyuu/bs/duck"
  "bitbucket.org/yyuu/bs/entity"
  "bitbucket.org/yyuu/bs/xt"
)

func TestParseEmpty(t *testing.T) {
  _, err := ParseExpr("")
  xt.AssertNil(t, "", err)
}

func defvars(xs...entity.DefinedVariable) []entity.DefinedVariable {
  return xs
}

func vardecls(xs...entity.UndefinedVariable) []entity.UndefinedVariable {
  return xs
}

func defuns(xs...entity.DefinedFunction) []entity.DefinedFunction {
  return xs
}

func funcdecls(xs...entity.UndefinedFunction) []entity.UndefinedFunction {
  return xs
}

func defconsts(xs...entity.Constant) []entity.Constant {
  return xs
}

func defstructs(xs...ast.StructNode) []ast.StructNode {
  return xs
}

func defunions(xs...ast.UnionNode) []ast.UnionNode {
  return xs
}

func typedefs(xs...ast.TypedefNode) []ast.TypedefNode {
  return xs
}

/*
func TestParseFuncallWithoutArguments(t *testing.T) {
  s := `
    int f(void) {
      return getc();
    }
  `
  x := ast.NewAST(
    loc(1,1),
    ast.NewDeclarations(
      defvars(),
      vardecls(),
      defuns(
//      []duck.IStmtNode {
//        ast.NewExprStmtNode(loc(1,1),
//          ast.NewFuncallNode(loc(1,1),
//            ast.NewVariableNode(loc(1,1),
//              "gets",
//            ),
//            []duck.IExprNode {
//            },
//          ),
//        ),
//      },
      ),
      funcdecls(),
      defconsts(),
      defstructs(),
      defunions(),
      typedefs(),
    ),
  )
  y, err := ParseExpr(s)
  xt.AssertNil(t, "", err)
  xt.AssertStringEqualsDiff(t, "parse funcall w/o arguments", xt.JSON(y), xt.JSON(x))
  xt.AssertDeepEquals(t, "", y, x)
}
 */

/*
func TestParseFuncallWithSingleArgument(t *testing.T) {
  s := `
    void f(int n) {
      println("hello, %d", n);
    }
  `
  x := ast.NewAST {
    loc(1,5),
    ast.NewDeclarations(
      defvars(),
      vardecls(),
      defuns(
//      []duck.IStmtNode {
//        ast.NewExprStmtNode(loc(1,5),
//          ast.NewFuncallNode(loc(1,5),
//            ast.NewVariableNode(loc(1,5),
//              "println",
//            ),
//            []duck.IExprNode {
//              ast.NewStringLiteralNode(loc(1,13),
//                "\"hello, world\"",
//              ),
//            },
//          ),
//        ),
//      },
      ),
      funcdecls(),
      constants(),
      defstructs(),
      defunions(),
      typedefs(),
    ),
  )
  y, err := ParseExpr(s)
  xt.AssertNil(t, "", err)
  xt.AssertStringEqualsDiff(t, "parse funcall w/ single argument", xt.JSON(y), xt.JSON(x))
  xt.AssertDeepEquals(t, "", y, x)
}
 */

/*
func TestParseFuncallWithMultipleArguments(t *testing.T) {
  s := `

    println(
      "hello, %s",
      "world"
    );
  `
  x := ast.NewAST(
    loc(2,5),
    ast.Declarations {
      defvars(),
      vardecls(),
      defuns(
//      []duck.IStmtNode {
//        ast.NewExprStmtNode(loc(2,5),
//          ast.NewFuncallNode(loc(2,5),
//            ast.NewVariableNode(loc(2,5),
//              "println",
//            ),
//            []duck.IExprNode {
//              ast.NewStringLiteralNode(loc(3,7),
//                "\"hello, %s\"",
//              ),
//              ast.NewStringLiteralNode(loc(4,7),
//                "\"world\"",
//              ),
//            },
//          ),
//        ),
//      },
      ),
      funcdecls(),
      constants(),
      defstructs(),
      defunions(),
      typedefs(),
    ),
  )
  y, err := ParseExpr(s)
  xt.AssertNil(t, "", err)
  xt.AssertStringEqualsDiff(t, "funcall w/ multiple arguments", xt.JSON(y), xt.JSON(x))
  xt.AssertDeepEquals(t, "", y, x)
}
 */

/*
func TestFor1(t *testing.T) {
  s := `
    for (i=0; i<100; i++) println(i);
`
  x := ast.NewAST(
    loc(2,5),
    ast.NewDeclarations(
      defvars(),
      vardecls(),
      defuns(
//      []duck.IStmtNode {
//        ast.NewForNode(loc(1,5),
//          ast.NewAssignNode(loc(1,10),
//            ast.NewVariableNode(loc(1,10),
//              "i",
//            ),
//            ast.NewIntegerLiteralNode(loc(1,12),
//              "0",
//            ),
//          ),
//          ast.NewBinaryOpNode(loc(1,15),
//            "<",
//            ast.NewVariableNode(loc(1,15),
//              "i",
//            ),
//            ast.NewIntegerLiteralNode(loc(1,17),
//              "100",
//            ),
//          ),
//          ast.NewSuffixOpNode(loc(1,22),
//            "++",
//            ast.NewVariableNode(loc(1,22),
//              "i",
//            ),
//          ),
//          ast.NewExprStmtNode(loc(1,27),
//            ast.NewFuncallNode(loc(1,27),
//              ast.NewVariableNode(loc(1,27),
//                "println",
//              ),
//              []duck.IExprNode {
//                ast.NewVariableNode(loc(1,35),
//                  "i",
//                ),
//              },
//            ),
//          ),
//        ),
//      },
      ),
      funcdecls(),
      constants(),
      defstructs(),
      defunions(),
      typedefs(),
    },
  }
  y, err := ParseExpr(s)
  xt.AssertNil(t, "", err)
  xt.AssertStringEqualsDiff(t, "for1", xt.JSON(y), xt.JSON(x))
  xt.AssertDeepEquals(t, "", y, x)
}
 */
<|endoftext|>