<commit_before>// Copyright 2011 Google Inc. All Rights Reserved.
// This file is available under the Apache license.

package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"path/filepath"
	"regexp"
	"strconv"
	"time"
)

var compile_only *bool = flag.Bool("compile_only", false, "Compile programs only.")

type opcode int

const (
	match     opcode = iota // Match a regular expression against input
	jnm                     // Jump if no match
	inc                     // Increment an exported variable value
	strptime                // Parse into the timestamp register
	timestamp               // Return value of timestamp register
	ret                     // Return, end program successfully
	push                    // Push operand onto stack
	capref                  // Push capture group reference at operand onto stack
	str                     // Push string constant at operand onto stack
	set                     // Set an exported variable value
	add                     // Add top values on stack and push to stack
	sub                     // Subtract tpo value from second top value on stack, and push to stack.
	mload                   // Load metric at operand onto top of stack.
	dload                   // Pop operand keys and metric off stack and load datum at metric[key] onto stack.
)

var opNames = map[opcode]string{
	match:     "match",
	jnm:       "jnm",
	inc:       "inc",
	strptime:  "strptime",
	timestamp: "timestamp",
	ret:       "ret",
	push:      "push",
	capref:    "capref",
	str:       "str",
	set:       "set",
	add:       "add",
	sub:       "sub",
	mload:     "mload",
	dload:     "dload",
}

var builtin = map[string]opcode{
	"strptime":  strptime,
	"timestamp": timestamp,
}

type instr struct {
	op   opcode
	opnd int
}

func (i instr) String() string {
	return fmt.Sprintf("%s %d", opNames[i.op], i.opnd)
}

type thread struct {
	pc      int
	reg     int
	matches map[int][]string
	time    time.Time
}

type vm struct {
	name string
	prog []instr

	// const regexps
	re []*regexp.Regexp
	// const strings
	str []string

	// data segment
	symtab *scope

	// exported metrics
	//metrics []*interface{}

	stack Stack
	t     thread
}

func (v *vm) errorf(format string, args ...interface{}) bool {
	log.Printf("Runtime error: "+format+"\n", args...)
	v.t.reg = 0
	return true
}

// Execute acts on the current instruction, and returns a boolean indicating
// if the current thread should terminate.
func (v *vm) execute(t *thread, i instr, input string) bool {
	switch i.op {
	case match:
		// match regex and store success
		t.matches[i.opnd] = v.re[i.opnd].FindStringSubmatch(input)
		if t.matches[i.opnd] != nil {
			t.reg = 1
		} else {
			t.reg = 0
		}
	case jnm:
		if t.reg == 0 {
			t.pc = i.opnd
			return false
		}
	case inc:
		// increment a counter
		var delta int64 = 1
		// If opnd is nonzero, the delta is on the stack.
		if i.opnd > 0 {
			val := v.stack.Pop()
			// Don't know what type it is on the stack though.
			switch n := val.(type) {
			case int:
				delta = int64(n)
			case int64:
				delta = n
			case string:
				var err error
				delta, err = strconv.ParseInt(n, 10, 64)
				if err != nil {
					return v.errorf("conversion of %q to numeric failed: %s", val, err)
				}
			default:
				return v.errorf("Unexpected type %T %q", val, val)
			}
		}
		switch d := v.stack.Pop().(type) {
		case Incrementable:
			d.IncBy(delta, t.time)
		case int:
			m := metrics[d].(Incrementable)
			m.IncBy(delta, t.time)
		default:
			return v.errorf("Unexpected type to increment: %T %q", d, d)
		}

	case set:
		// Set a gauge
		var value int64
		val := v.stack.Pop()
		// Don't know what type it is on the stack though.
		switch n := val.(type) {
		case int:
			value = int64(n)
		case int64:
			value = n
		case string:
			var err error
			value, err = strconv.ParseInt(n, 10, 64)
			if err != nil {
				return v.errorf("conversion of %q to numeric failed: %s", val, err)
			}
		case time.Time:
			value = n.Unix()
		default:
			return v.errorf("Unexpected type %T %q\n", val, val)
		}
		switch d := v.stack.Pop().(type) {
		case Settable:
			d.Set(value, t.time)
		case int:
			m := metrics[d].(Settable)
			m.Set(value, t.time)
		default:
			return v.errorf("Unexpected type to set: %T %q", d, d)
		}

	case strptime:
		layout := v.stack.Pop().(string)

		var ts string
		switch s := v.stack.Pop().(type) {
		case string:
			ts = s

		case int: /* capref */
			re := v.stack.Pop().(int)
			ts = t.matches[re][s]
		}

		tm, err := time.Parse(layout, ts)
		if err != nil {
			return v.errorf("time.Parse(%s, %s) failed: %s", layout, ts, err)
		}
		t.time = tm

	case timestamp:
		v.stack.Push(t.time)

	case capref:
		re := v.stack.Pop().(int)
		v.stack.Push(t.matches[re][i.opnd])

	case str:
		v.stack.Push(v.str[i.opnd])

	case ret:
		return true

	case push:
		v.stack.Push(i.opnd)

	case add:
		var a, b int64
		switch d := v.stack.Pop().(type) {
		case *Datum:
			a = d.Value
		case int64:
			a = d
		case int:
			a = int64(d)
		default:
			return v.errorf("Unexpected type for sub %T %q\n", d, d)
		}
		switch d := v.stack.Pop().(type) {
		case *Datum:
			b = d.Value
		case int64:
			b = d
		case int:
			b = int64(d)
		default:
			return v.errorf("Unexpected type for sub %T %q\n", d, d)
		}
		v.stack.Push(a + b)

	case sub:
		var a, b int64
		switch d := v.stack.Pop().(type) {
		case *Datum:
			a = d.Value
		case int64:
			a = d
		case int:
			a = int64(d)
		default:
			return v.errorf("Unexpected type for sub %T %q\n", d, d)
		}
		switch d := v.stack.Pop().(type) {
		case *Datum:
			b = d.Value
		case int64:
			b = d
		case int:
			b = int64(d)
		default:
			return v.errorf("Unexpected type for sub %T %q\n", d, d)
		}
		v.stack.Push(b - a)

	case mload:
		v.stack.Push(metrics[i.opnd])

	case dload:
		m := v.stack.Pop().(*DimensionedMetric)
		var keys []string
		for a := 0; a < i.opnd; a++ {
			keys = append(keys, v.stack.Pop().(string))
		}
		h := key_hash(keys)
		if _, ok := m.Values[h]; !ok {
			m.Values[h] = &Datum{}
		}
		v.stack.Push(m.Values[h])

	default:
		return v.errorf("illegal instruction: %q", i.op)
	}
	t.pc++
	return false
}

// Run fetches and executes each instruction in the program on the input string
// until termination. It returns a boolean indicating a successful match.
func (v *vm) Run(input string) bool {
	t := v.t
	t.matches = make(map[int][]string, 0)
	for {
		if t.pc >= len(v.prog) {
			return false
		}
		i := v.prog[t.pc]
		terminate := v.execute(&t, i, input)
		if terminate {
			// t.reg contains the result of the last match.
			return t.reg == 1
		}
	}
	panic("not reached")
}

type compiler struct {
	name   string   // Name of the program.
	errors []string // Compile errors.

	prog []instr          // The emitted program.
	str  []string         // Static strings.
	re   []*regexp.Regexp // Static regular expressions.

	symtab *scope

	//metrics []*interface{}
}

func Compile(name string, input io.Reader) (*vm, []string) {
	p := NewParser(name, input)
	r := EmtailParse(p)
	if r != 0 || p == nil || len(p.errors) > 0 {
		return nil, p.errors
	}
	if *compile_only {
		output := unparse(p.root)
		log.Printf("Unparsing %s:\n%s", name, output)
	}
	file := filepath.Base(name)
	c := &compiler{name: file, symtab: p.s}
	//c.metrics = make([]*interface{}, 0)
	c.compile(p.root)
	if len(c.errors) > 0 {
		return nil, c.errors
	}
	vm := &vm{
		name:   file,
		re:     c.re,
		str:    c.str,
		symtab: c.symtab,
		//metrics: c.metrics,
		prog: c.prog}
	return vm, nil
}

func (c *compiler) errorf(format string, args ...interface{}) {
	e := fmt.Sprintf(c.name+": "+format, args...)
	c.errors = append(c.errors, e)
}

func (c *compiler) emit(i instr) {
	c.prog = append(c.prog, i)
}

func (c *compiler) compile(n node) {
	switch v := n.(type) {
	case *stmtlistNode:
		for _, child := range v.children {
			c.compile(child)
		}

	case *exprlistNode:
		for _, child := range v.children {
			c.compile(child)
		}

	case *declNode:
		v.sym.addr = len(metrics)
		metrics = append(metrics, v.m)

	case *condNode:
		// TODO(jaq): split off a new goroutine thread instead of doing conds serially.
		if v.cond != nil {
			c.compile(v.cond)
		}
		c.emit(instr{op: jnm})
		// Save PC of jump instruction
		pc := len(c.prog) - 1
		for _, child := range v.children {
			c.compile(child)
		}
		c.emit(instr{ret, 1})
		// rewrite jump target
		c.prog[pc].opnd = len(c.prog)

	case *regexNode:
		if v.re == nil {
			re, err := regexp.Compile(v.pattern)
			if err != nil {
				c.errorf("%s", err)
				return
			} else {
				c.re = append(c.re, re)
				v.re = re
				v.addr = len(c.re) - 1
			}
		}
		c.emit(instr{match, v.addr})

	case *stringNode:
		c.str = append(c.str, v.text)
		c.emit(instr{str, len(c.str) - 1})

	case *idNode:
		c.emit(instr{mload, v.sym.addr})
		switch m := v.sym.binding.(type) {
		case (*DimensionedMetric):
			c.emit(instr{dload, len(m.Keys)})
		}

	case *caprefNode:
		rn := v.sym.binding.(*regexNode)
		c.emit(instr{push, rn.addr})
		c.emit(instr{capref, v.sym.addr})

	case *builtinNode:
		if v.args != nil {
			c.compile(v.args)
			c.emit(instr{builtin[v.name], len(v.args.(*exprlistNode).children)})
		} else {
			c.emit(instr{op: builtin[v.name]})
		}

	case *additiveExprNode:
		c.compile(v.lhs)
		c.compile(v.rhs)
		switch v.op {
		case '+':
			c.emit(instr{op: add})
		case '-':
			c.emit(instr{op: sub})
		default:
			c.errorf("invalid op: %q\n", v.op)
		}

	case *assignExprNode:
		c.compile(v.lhs)
		c.compile(v.rhs)
		c.emit(instr{op: set})

	case *indexedExprNode:
		c.compile(v.index)
		c.compile(v.lhs)

	case *incExprNode:
		c.compile(v.lhs)
		c.emit(instr{op: inc})

	case *incByExprNode:
		c.compile(v.lhs)
		c.compile(v.rhs)
		c.emit(instr{inc, 1})

	case *constExprNode:
		c.emit(instr{push, v.value})

	default:
		c.errorf("undefined node type %T", n)
	}
}
<commit_msg>support additive arithmetic on time.Time types<commit_after>// Copyright 2011 Google Inc. All Rights Reserved.
// This file is available under the Apache license.

package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"path/filepath"
	"regexp"
	"strconv"
	"time"
)

var compile_only *bool = flag.Bool("compile_only", false, "Compile programs only.")

type opcode int

const (
	match     opcode = iota // Match a regular expression against input
	jnm                     // Jump if no match
	inc                     // Increment an exported variable value
	strptime                // Parse into the timestamp register
	timestamp               // Return value of timestamp register
	ret                     // Return, end program successfully
	push                    // Push operand onto stack
	capref                  // Push capture group reference at operand onto stack
	str                     // Push string constant at operand onto stack
	set                     // Set an exported variable value
	add                     // Add top values on stack and push to stack
	sub                     // Subtract tpo value from second top value on stack, and push to stack.
	mload                   // Load metric at operand onto top of stack.
	dload                   // Pop operand keys and metric off stack and load datum at metric[key] onto stack.
)

var opNames = map[opcode]string{
	match:     "match",
	jnm:       "jnm",
	inc:       "inc",
	strptime:  "strptime",
	timestamp: "timestamp",
	ret:       "ret",
	push:      "push",
	capref:    "capref",
	str:       "str",
	set:       "set",
	add:       "add",
	sub:       "sub",
	mload:     "mload",
	dload:     "dload",
}

var builtin = map[string]opcode{
	"strptime":  strptime,
	"timestamp": timestamp,
}

type instr struct {
	op   opcode
	opnd int
}

func (i instr) String() string {
	return fmt.Sprintf("%s %d", opNames[i.op], i.opnd)
}

type thread struct {
	pc      int
	reg     int
	matches map[int][]string
	time    time.Time
}

type vm struct {
	name string
	prog []instr

	// const regexps
	re []*regexp.Regexp
	// const strings
	str []string

	// data segment
	symtab *scope

	// exported metrics
	//metrics []*interface{}

	stack Stack
	t     thread
}

func (v *vm) errorf(format string, args ...interface{}) bool {
	log.Printf("Runtime error: "+format+"\n", args...)
	v.t.reg = 0
	return true
}

// Execute acts on the current instruction, and returns a boolean indicating
// if the current thread should terminate.
func (v *vm) execute(t *thread, i instr, input string) bool {
	switch i.op {
	case match:
		// match regex and store success
		t.matches[i.opnd] = v.re[i.opnd].FindStringSubmatch(input)
		if t.matches[i.opnd] != nil {
			t.reg = 1
		} else {
			t.reg = 0
		}
	case jnm:
		if t.reg == 0 {
			t.pc = i.opnd
			return false
		}
	case inc:
		// increment a counter
		var delta int64 = 1
		// If opnd is nonzero, the delta is on the stack.
		if i.opnd > 0 {
			val := v.stack.Pop()
			// Don't know what type it is on the stack though.
			switch n := val.(type) {
			case int:
				delta = int64(n)
			case int64:
				delta = n
			case string:
				var err error
				delta, err = strconv.ParseInt(n, 10, 64)
				if err != nil {
					return v.errorf("conversion of %q to numeric failed: %s", val, err)
				}
			default:
				return v.errorf("Unexpected type %T %q", val, val)
			}
		}
		switch d := v.stack.Pop().(type) {
		case Incrementable:
			d.IncBy(delta, t.time)
		case int:
			m := metrics[d].(Incrementable)
			m.IncBy(delta, t.time)
		default:
			return v.errorf("Unexpected type to increment: %T %q", d, d)
		}

	case set:
		// Set a gauge
		var value int64
		val := v.stack.Pop()
		// Don't know what type it is on the stack though.
		switch n := val.(type) {
		case int:
			value = int64(n)
		case int64:
			value = n
		case string:
			var err error
			value, err = strconv.ParseInt(n, 10, 64)
			if err != nil {
				return v.errorf("conversion of %q to numeric failed: %s", val, err)
			}
		case time.Time:
			value = n.Unix()
		default:
			return v.errorf("Unexpected type %T %q\n", val, val)
		}
		switch d := v.stack.Pop().(type) {
		case Settable:
			d.Set(value, t.time)
		case int:
			m := metrics[d].(Settable)
			m.Set(value, t.time)
		default:
			return v.errorf("Unexpected type to set: %T %q", d, d)
		}

	case strptime:
		layout := v.stack.Pop().(string)

		var ts string
		switch s := v.stack.Pop().(type) {
		case string:
			ts = s

		case int: /* capref */
			re := v.stack.Pop().(int)
			ts = t.matches[re][s]
		}

		tm, err := time.Parse(layout, ts)
		if err != nil {
			return v.errorf("time.Parse(%s, %s) failed: %s", layout, ts, err)
		}
		t.time = tm

	case timestamp:
		v.stack.Push(t.time)

	case capref:
		re := v.stack.Pop().(int)
		v.stack.Push(t.matches[re][i.opnd])

	case str:
		v.stack.Push(v.str[i.opnd])

	case ret:
		return true

	case push:
		v.stack.Push(i.opnd)

	case add:
		var a, b int64
		switch d := v.stack.Pop().(type) {
		case *Datum:
			a = d.Value
		case int64:
			a = d
		case int:
			a = int64(d)
		case time.Time:
			a = d.Unix()
		default:
			return v.errorf("Unexpected type for add %T %q\n", d, d)
		}
		switch d := v.stack.Pop().(type) {
		case *Datum:
			b = d.Value
		case int64:
			b = d
		case int:
			b = int64(d)
		case time.Time:
			b = d.Unix()
		default:
			return v.errorf("Unexpected type for add %T %q\n", d, d)
		}
		v.stack.Push(a + b)

	case sub:
		var a, b int64
		switch d := v.stack.Pop().(type) {
		case *Datum:
			a = d.Value
		case int64:
			a = d
		case int:
			a = int64(d)
		case time.Time:
			a = d.Unix()
		default:
			return v.errorf("Unexpected type for sub %T %q\n", d, d)
		}
		switch d := v.stack.Pop().(type) {
		case *Datum:
			b = d.Value
		case int64:
			b = d
		case int:
			b = int64(d)
		case time.Time:
			b = d.Unix()
		default:
			return v.errorf("Unexpected type for sub %T %q\n", d, d)
		}
		v.stack.Push(b - a)

	case mload:
		v.stack.Push(metrics[i.opnd])

	case dload:
		m := v.stack.Pop().(*DimensionedMetric)
		var keys []string
		for a := 0; a < i.opnd; a++ {
			keys = append(keys, v.stack.Pop().(string))
		}
		h := key_hash(keys)
		if _, ok := m.Values[h]; !ok {
			m.Values[h] = &Datum{}
		}
		v.stack.Push(m.Values[h])

	default:
		return v.errorf("illegal instruction: %q", i.op)
	}
	t.pc++
	return false
}

// Run fetches and executes each instruction in the program on the input string
// until termination. It returns a boolean indicating a successful match.
func (v *vm) Run(input string) bool {
	t := v.t
	t.matches = make(map[int][]string, 0)
	for {
		if t.pc >= len(v.prog) {
			return false
		}
		i := v.prog[t.pc]
		terminate := v.execute(&t, i, input)
		if terminate {
			// t.reg contains the result of the last match.
			return t.reg == 1
		}
	}
	panic("not reached")
}

type compiler struct {
	name   string   // Name of the program.
	errors []string // Compile errors.

	prog []instr          // The emitted program.
	str  []string         // Static strings.
	re   []*regexp.Regexp // Static regular expressions.

	symtab *scope

	//metrics []*interface{}
}

func Compile(name string, input io.Reader) (*vm, []string) {
	p := NewParser(name, input)
	r := EmtailParse(p)
	if r != 0 || p == nil || len(p.errors) > 0 {
		return nil, p.errors
	}
	if *compile_only {
		output := unparse(p.root)
		log.Printf("Unparsing %s:\n%s", name, output)
	}
	file := filepath.Base(name)
	c := &compiler{name: file, symtab: p.s}
	//c.metrics = make([]*interface{}, 0)
	c.compile(p.root)
	if len(c.errors) > 0 {
		return nil, c.errors
	}
	vm := &vm{
		name:   file,
		re:     c.re,
		str:    c.str,
		symtab: c.symtab,
		//metrics: c.metrics,
		prog: c.prog}
	return vm, nil
}

func (c *compiler) errorf(format string, args ...interface{}) {
	e := fmt.Sprintf(c.name+": "+format, args...)
	c.errors = append(c.errors, e)
}

func (c *compiler) emit(i instr) {
	c.prog = append(c.prog, i)
}

func (c *compiler) compile(n node) {
	switch v := n.(type) {
	case *stmtlistNode:
		for _, child := range v.children {
			c.compile(child)
		}

	case *exprlistNode:
		for _, child := range v.children {
			c.compile(child)
		}

	case *declNode:
		v.sym.addr = len(metrics)
		metrics = append(metrics, v.m)

	case *condNode:
		// TODO(jaq): split off a new goroutine thread instead of doing conds serially.
		if v.cond != nil {
			c.compile(v.cond)
		}
		c.emit(instr{op: jnm})
		// Save PC of jump instruction
		pc := len(c.prog) - 1
		for _, child := range v.children {
			c.compile(child)
		}
		c.emit(instr{ret, 1})
		// rewrite jump target
		c.prog[pc].opnd = len(c.prog)

	case *regexNode:
		if v.re == nil {
			re, err := regexp.Compile(v.pattern)
			if err != nil {
				c.errorf("%s", err)
				return
			} else {
				c.re = append(c.re, re)
				v.re = re
				v.addr = len(c.re) - 1
			}
		}
		c.emit(instr{match, v.addr})

	case *stringNode:
		c.str = append(c.str, v.text)
		c.emit(instr{str, len(c.str) - 1})

	case *idNode:
		c.emit(instr{mload, v.sym.addr})
		switch m := v.sym.binding.(type) {
		case (*DimensionedMetric):
			c.emit(instr{dload, len(m.Keys)})
		}

	case *caprefNode:
		rn := v.sym.binding.(*regexNode)
		c.emit(instr{push, rn.addr})
		c.emit(instr{capref, v.sym.addr})

	case *builtinNode:
		if v.args != nil {
			c.compile(v.args)
			c.emit(instr{builtin[v.name], len(v.args.(*exprlistNode).children)})
		} else {
			c.emit(instr{op: builtin[v.name]})
		}

	case *additiveExprNode:
		c.compile(v.lhs)
		c.compile(v.rhs)
		switch v.op {
		case '+':
			c.emit(instr{op: add})
		case '-':
			c.emit(instr{op: sub})
		default:
			c.errorf("invalid op: %q\n", v.op)
		}

	case *assignExprNode:
		c.compile(v.lhs)
		c.compile(v.rhs)
		c.emit(instr{op: set})

	case *indexedExprNode:
		c.compile(v.index)
		c.compile(v.lhs)

	case *incExprNode:
		c.compile(v.lhs)
		c.emit(instr{op: inc})

	case *incByExprNode:
		c.compile(v.lhs)
		c.compile(v.rhs)
		c.emit(instr{inc, 1})

	case *constExprNode:
		c.emit(instr{push, v.value})

	default:
		c.errorf("undefined node type %T", n)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"strconv"

	"github.com/ostlerc/nurikabe/grid"
	"github.com/ostlerc/nurikabe/stats"
	"github.com/ostlerc/nurikabe/validator"

	"gopkg.in/qml.v1"
)

const (
	statsFile = ".stats.json"
	levelDir  = "levels/"
)

type window struct {
	g       *grid.Grid
	v       validator.GridValidator
	objs    []qml.Object
	records *stats.Records

	tileComponent qml.Object
	btnComponent  qml.Object
	txtComponent  qml.Object
	winComponent  *qml.Window

	currentDifficulty string
	currentBoard      string
	currentMode       gameMode
}

type gameMode int

const (
	mainMenu = iota
	difficultySelect
	levelSelect
	rulesPage
	statsPage
	nurikabePage
)

const (
	MenuPlay  = "Play"
	MenuStats = "Records"
	MenuRules = "Rules"
	MenuExit  = "Exit"
)

const rulesText = `Each puzzle consists of a grid containing clues in various places.` +
	` The object is to create islands by partitioning between clues with walls so:` +
	` Each island contains exactly one clue.` +
	` The number of squares in each island equals the value of the clue.` +
	` All islands are isolated from each other horizontally and vertically.` +
	` There are no wall areas of 2x2 or larger.` +
	` When completed, all walls form a continuous path.`

var MenuItems = []string{MenuPlay, MenuStats, MenuRules, MenuExit}

func NewMainWindow(engine *qml.Engine) (*window, error) {
	windowComponent, err := engine.LoadFile("qml/window.qml")
	if err != nil {
		return nil, err
	}

	window := &window{
		v:            validator.NewNurikabe(),
		winComponent: windowComponent.CreateWindow(nil),
	}

	window.tileComponent, err = engine.LoadFile("qml/tile.qml")
	if err != nil {
		return nil, err
	}

	window.btnComponent, err = engine.LoadFile("qml/button.qml")
	if err != nil {
		return nil, err
	}

	window.txtComponent, err = engine.LoadFile("qml/text.qml")
	if err != nil {
		return nil, err
	}

	return window, nil
}

func (w *window) setGameMode(mode gameMode) {
	w.currentMode = mode
	w.clearGrid()
	w.setSource("qml/game.qml") //reload screen

	w.qToolBtn().Set("visible", mode != mainMenu)
	w.qStepsText().Set("visible", mode == nurikabePage)
	w.qTimeText().Set("visible", mode == nurikabePage)
	w.qRecordText().Set("visible", mode == nurikabePage)

	switch mode {
	case mainMenu:
		w.buildMainMenu()
	case difficultySelect:
		w.buildDifficultySelect()
	case levelSelect:
		w.buildLevelSelect()
	case nurikabePage:
		w.buildNurikabeGrid()
	case rulesPage:
		w.buildRules()
	case statsPage:
		w.buildStats()
	}
}

func (w *window) ToolButtonClicked() {
	switch w.currentMode {
	case rulesPage:
		fallthrough
	case statsPage:
		w.setGameMode(mainMenu)
	case difficultySelect:
		w.setGameMode(mainMenu)
	case levelSelect:
		w.setGameMode(difficultySelect)
	case nurikabePage:
		w.setGameMode(levelSelect)
	}
}

func (w *window) OnBtnClicked(data string) {
	switch w.currentMode {
	case mainMenu:
		switch data {
		case MenuPlay:
			w.setGameMode(difficultySelect)
		case MenuStats:
			w.setGameMode(statsPage)
		case MenuRules:
			w.setGameMode(rulesPage)
		case MenuExit:
			w.records.Save(statsFile)
			os.Exit(0)
		}
	case difficultySelect:
		w.currentDifficulty = data
		w.setGameMode(levelSelect)
	case levelSelect:
		w.currentBoard = data
		w.loadLevel(levelDir + w.currentDifficulty + "/" + data)
	case nurikabePage: //This is handled by TileChecked
		panic("Err")
	case rulesPage:
		panic("Err")
	}
}

func (w *window) TileChecked(i int) {
	w.qStepsText().Set("moves", w.qStepsText().Int("moves")+1)
	w.g.Toggle(i)
	if w.v.CheckWin(w.g) {
		w.records.Log(w.currentDifficulty, levelInt(w.currentBoard), w.qStepsText().Int("moves"), w.qTimeText().Int("seconds"))
		w.records.Save(statsFile)
		w.setStatus("Nurikabe - Completed")
		w.qRecordText().Set("text", w.records.String(w.currentDifficulty, levelInt(w.currentBoard)))
		w.setTimer(false)
	}
}

func levelInt(file string) int {
	ret, err := strconv.Atoi(levelStr(file))
	if err != nil {
		panic(err)
	}
	return ret
}

func levelStr(file string) string {
	return file[:len(file)-5]
}

func (w *window) loadLevel(file string) {
	if file != "" {
		r, err := os.Open(file)
		if err != nil {
			fmt.Fprintln(os.Stderr, "failed to load json file "+file)
			w.setGameMode(levelSelect)
			return
		} else {
			w.g, err = grid.FromJson(r)
			if err != nil {
				panic(err)
			}
			w.setGameMode(nurikabePage)
		}
	}
}

func (w *window) clearGrid() {
	for i, _ := range w.objs {
		w.objs[i].Set("visible", false)
		w.objs[i].Destroy()
	}
	w.objs = nil
}

func (w *window) buildNurikabeGrid() {
	w.setStatus("Nurikabe - " + w.currentDifficulty[2:] + " " + levelStr(w.currentBoard))
	w.qRecordText().Set("text", w.records.String(w.currentDifficulty, levelInt(w.currentBoard)))
	w.qGameGrid().Set("spacing", 1)
	w.qToolBtn().Set("text", "Back")
	w.setTimer(true)

	l := w.g.Rows() * w.g.Columns()
	w.qGameGrid().Set("columns", w.g.Columns())

	w.clearGrid()
	w.objs = make([]qml.Object, l, l)
	dimension := w.g.Columns()
	if rows := w.g.Rows(); rows > dimension {
		dimension = rows
	}
	windowDim := w.winComponent.Root().Int("width") - 50
	if height := w.winComponent.Root().Int("height") - 60; height < windowDim {
		windowDim = height
	}
	dimension = windowDim / dimension
	for i := 0; i < l; i++ {
		w.objs[i] = w.tileComponent.Create(nil)
		w.objs[i].Set("parent", w.qGameGrid())
		w.objs[i].Set("index", i)
		w.objs[i].Set("count", w.g.Count(i))
		w.objs[i].Set("width", dimension)
		w.objs[i].Set("height", dimension)
	}
}

func (w *window) buildMainMenu() {
	w.setStatus("Nurikabe - Main Menu")
	w.qGameGrid().Set("spacing", 15)
	w.qGameGrid().Set("columns", 1)

	w.objs = make([]qml.Object, len(MenuItems), len(MenuItems))
	for i, name := range MenuItems {
		w.objs[i] = w.btnComponent.Create(nil)
		w.objs[i].Set("parent", w.qGameGrid())
		w.objs[i].Set("text", name)
		w.objs[i].Set("data", name)
		w.objs[i].Set("alignCenter", true)
		w.objs[i].Set("width", w.winComponent.Root().Int("width")-150)
	}
}

func (w *window) buildLevelSelect() {
	w.currentBoard = ""
	w.setStatus("Nurikabe - " + w.currentDifficulty[2:])
	w.qGameGrid().Set("spacing", 15)
	w.qToolBtn().Set("text", "Back")
	w.qGameGrid().Set("columns", 4)

	names := files(levelDir + w.currentDifficulty)
	w.objs = make([]qml.Object, len(names), len(names))
	for i, name := range names {
		_, ok := w.records.Level(w.currentDifficulty, levelInt(name))
		w.objs[i] = w.btnComponent.Create(nil)
		w.objs[i].Set("parent", w.qGameGrid())
		w.objs[i].Set("text", levelStr(name)) //remove '.json' from name
		w.objs[i].Set("data", name)
		w.objs[i].Set("showstar", true)
		w.objs[i].Set("completed", ok)
		w.objs[i].Set("width", 50)
	}
}

func (w *window) buildDifficultySelect() {
	w.setStatus("Nurikabe - Select Difficulty")
	w.qGameGrid().Set("spacing", 15)
	w.qGameGrid().Set("columns", 1)
	w.qToolBtn().Set("text", "Menu")

	names := dirs(levelDir)
	w.objs = make([]qml.Object, len(names), len(names))
	for i, name := range names {
		w.objs[i] = w.btnComponent.Create(nil)
		w.objs[i].Set("parent", w.qGameGrid())
		w.objs[i].Set("text", name[2:])
		w.objs[i].Set("data", name)
		w.objs[i].Set("alignCenter", true)
		w.objs[i].Set("width", w.winComponent.Root().Int("width")-150)
	}
}

func (w *window) buildRules() {
	w.currentBoard = ""
	w.setStatus("Nurikabe - Rules")
	w.qToolBtn().Set("text", "Back")
	w.qGameGrid().Set("columns", 4)

	w.objs = make([]qml.Object, 1, 1)
	w.objs[0] = w.txtComponent.Create(nil)
	w.objs[0].Set("parent", w.qGameGrid())
	w.objs[0].Set("text", rulesText)
	w.objs[0].Set("width", w.winComponent.Root().Int("width")-50)
}

func (w *window) buildStats() {
	w.currentBoard = ""
	w.setStatus("Nurikabe - Records")
	w.qGameGrid().Set("spacing", 7)
	w.qToolBtn().Set("text", "Back")
	w.qGameGrid().Set("columns", 4)

	l := w.records.Length()
	w.objs = make([]qml.Object, 0, l+1)

	buildTxtBox := func(s string) {
		obj := w.txtComponent.Create(nil)
		obj.Set("parent", w.qGameGrid())
		obj.Set("text", s)
		w.objs = append(w.objs, obj)
	}

	headers := []string{"Difficulty", "Level", "Steps", "Seconds"}
	for _, txt := range headers {
		buildTxtBox(txt)
	}
	for range headers {
		buildTxtBox("----------")
	}

	for _, rec := range w.records.All() {
		buildTxtBox(rec.Difficulty[2:])
		buildTxtBox(strconv.Itoa(rec.Lvl))
		buildTxtBox(strconv.Itoa(rec.Steps))
		buildTxtBox(strconv.Itoa(rec.Seconds))
	}
}

func (w *window) loadStats() {
	var err error
	d := dirs(levelDir)
	sorter := make(map[string]int, len(d))
	for _, f := range dirs(levelDir) {
		sorter[f[2:]] = int(f[0] - '0')

	}
	w.records, err = stats.Load(statsFile, sorter)
	if err != nil {
		fmt.Println("Error loading stats", err)
		w.records = stats.New(sorter)
	}
}

func (w *window) setTimer(running bool) {
	w.qStatus().Set("finished", !running)
}

func (w *window) setStatus(s string) {
	w.qStatus().Set("text", s)
}

func (w *window) setSource(page string) {
	w.qLoader().Set("source", page)
}

func (w *window) obj(name string) qml.Object {
	return w.winComponent.Root().ObjectByName(name)
}

func (w *window) qStatus() qml.Object {
	return w.obj("statusText")
}

func (w *window) qGameGrid() qml.Object {
	return w.obj("grid")
}

func (w *window) qLoader() qml.Object {
	return w.obj("pageLoader")
}

func (w *window) qToolBtn() qml.Object {
	return w.obj("toolBtn")
}

func (w *window) qStepsText() qml.Object {
	return w.obj("movesText")
}

func (w *window) qTimeText() qml.Object {
	return w.obj("timerText")
}

func (w *window) qRecordText() qml.Object {
	return w.obj("recordText")
}

func RunNurikabe(engine *qml.Engine) error {
	context := engine.Context()

	window, err := NewMainWindow(engine)
	if err != nil {
		return err
	}

	context.SetVar("window", window)
	window.loadStats()
	window.setGameMode(mainMenu)

	window.winComponent.Show()
	window.winComponent.Wait()
	window.records.Save(statsFile)
	return nil
}
<commit_msg>add ubuntu compile error<commit_after>package main

import (
	"fmt"
	"os"
	"strconv"

	"github.com/ostlerc/nurikabe/grid"
	"github.com/ostlerc/nurikabe/stats"
	"github.com/ostlerc/nurikabe/validator"

	"gopkg.in/qml.v1"
)

const (
	statsFile = ".stats.json"
	levelDir  = "levels/"
)

type window struct {
	g       *grid.Grid
	v       validator.GridValidator
	objs    []qml.Object
	records *stats.Records

	tileComponent qml.Object
	btnComponent  qml.Object
	txtComponent  qml.Object
	winComponent  *qml.Window

	currentDifficulty string
	currentBoard      string
	currentMode       gameMode
}

type gameMode int

const (
	mainMenu = iota
	difficultySelect
	levelSelect
	rulesPage
	statsPage
	nurikabePage
)

const (
	MenuPlay  = "Play"
	MenuStats = "Records"
	MenuRules = "Rules"
	MenuExit  = "Exit"
)

const rulesText = `Each puzzle consists of a grid containing clues in various places.` +
	` The object is to create islands by partitioning between clues with walls so:` +
	` Each island contains exactly one clue.` +
	` The number of squares in each island equals the value of the clue.` +
	` All islands are isolated from each other horizontally and vertically.` +
	` There are no wall areas of 2x2 or larger.` +
	` When completed, all walls form a continuous path.`

var MenuItems = []string{MenuPlay, MenuStats, MenuRules, MenuExit}

func NewMainWindow(engine *qml.Engine) (*window, error) {
	windowComponent, err := engine.LoadFile("qml/window.qml")
	if err != nil {
		return nil, err
	}

	window := &window{
		v:            validator.NewNurikabe(),
		winComponent: windowComponent.CreateWindow(nil),
	}

	window.tileComponent, err = engine.LoadFile("qml/tile.qml")
	if err != nil {
		return nil, err
	}

	window.btnComponent, err = engine.LoadFile("qml/button.qml")
	if err != nil {
		return nil, err
	}

	window.txtComponent, err = engine.LoadFile("qml/text.qml")
	if err != nil {
		return nil, err
	}

	return window, nil
}

func (w *window) setGameMode(mode gameMode) {
	w.currentMode = mode
	w.clearGrid()
	w.setSource("qml/game.qml") //reload screen

	w.qToolBtn().Set("visible", mode != mainMenu)
	w.qStepsText().Set("visible", mode == nurikabePage)
	w.qTimeText().Set("visible", mode == nurikabePage)
	w.qRecordText().Set("visible", mode == nurikabePage)

	switch mode {
	case mainMenu:
		w.buildMainMenu()
	case difficultySelect:
		w.buildDifficultySelect()
	case levelSelect:
		w.buildLevelSelect()
	case nurikabePage:
		w.buildNurikabeGrid()
	case rulesPage:
		w.buildRules()
	case statsPage:
		w.buildStats()
	}
}

func (w *window) ToolButtonClicked() {
	switch w.currentMode {
	case rulesPage:
		fallthrough
	case statsPage:
		w.setGameMode(mainMenu)
	case difficultySelect:
		w.setGameMode(mainMenu)
	case levelSelect:
		w.setGameMode(difficultySelect)
	case nurikabePage:
		w.setGameMode(levelSelect)
	}
}

func (w *window) OnBtnClicked(data string) {
	switch w.currentMode {
	case mainMenu:
		switch data {
		case MenuPlay:
			w.setGameMode(difficultySelect)
		case MenuStats:
			w.setGameMode(statsPage)
		case MenuRules:
			w.setGameMode(rulesPage)
		case MenuExit:
			w.records.Save(statsFile)
			os.Exit(0)
		}
	case difficultySelect:
		w.currentDifficulty = data
		w.setGameMode(levelSelect)
	case levelSelect:
		w.currentBoard = data
		w.loadLevel(levelDir + w.currentDifficulty + "/" + data)
	case nurikabePage: //This is handled by TileChecked
		panic("Err")
	case rulesPage:
		panic("Err")
	}
}

func (w *window) TileChecked(i int) {
	w.qStepsText().Set("moves", w.qStepsText().Int("moves")+1)
	w.g.Toggle(i)
	if w.v.CheckWin(w.g) {
		w.records.Log(w.currentDifficulty, levelInt(w.currentBoard), w.qStepsText().Int("moves"), w.qTimeText().Int("seconds"))
		w.records.Save(statsFile)
		w.setStatus("Nurikabe - Completed")
		w.qRecordText().Set("text", w.records.String(w.currentDifficulty, levelInt(w.currentBoard)))
		w.setTimer(false)
	}
}

func levelInt(file string) int {
	ret, err := strconv.Atoi(levelStr(file))
	if err != nil {
		panic(err)
	}
	return ret
}

func levelStr(file string) string {
	return file[:len(file)-5]
}

func (w *window) loadLevel(file string) {
	if file != "" {
		r, err := os.Open(file)
		if err != nil {
			fmt.Fprintln(os.Stderr, "failed to load json file "+file)
			w.setGameMode(levelSelect)
			return
		} else {
			w.g, err = grid.FromJson(r)
			if err != nil {
				panic(err)
			}
			w.setGameMode(nurikabePage)
		}
	}
}

func (w *window) clearGrid() {
	for i, _ := range w.objs {
		w.objs[i].Set("visible", false)
		w.objs[i].Destroy()
	}
	w.objs = nil
}

func (w *window) buildNurikabeGrid() {
	w.setStatus("Nurikabe - " + w.currentDifficulty[2:] + " " + levelStr(w.currentBoard))
	w.qRecordText().Set("text", w.records.String(w.currentDifficulty, levelInt(w.currentBoard)))
	w.qGameGrid().Set("spacing", 1)
	w.qToolBtn().Set("text", "Back")
	w.setTimer(true)

	l := w.g.Rows() * w.g.Columns()
	w.qGameGrid().Set("columns", w.g.Columns())

	w.clearGrid()
	w.objs = make([]qml.Object, l, l)
	dimension := w.g.Columns()
	if rows := w.g.Rows(); rows > dimension {
		dimension = rows
	}
	windowDim := w.winComponent.Root().Int("width") - 50
	if height := w.winComponent.Root().Int("height") - 60; height < windowDim {
		windowDim = height
	}
	dimension = windowDim / dimension
	for i := 0; i < l; i++ {
		w.objs[i] = w.tileComponent.Create(nil)
		w.objs[i].Set("parent", w.qGameGrid())
		w.objs[i].Set("index", i)
		w.objs[i].Set("count", w.g.Count(i))
		w.objs[i].Set("width", dimension)
		w.objs[i].Set("height", dimension)
	}
}

func (w *window) buildMainMenu() {
	w.setStatus("Nurikabe - Main Menu")
	w.qGameGrid().Set("spacing", 15)
	w.qGameGrid().Set("columns", 1)

	w.objs = make([]qml.Object, len(MenuItems), len(MenuItems))
	for i, name := range MenuItems {
		w.objs[i] = w.btnComponent.Create(nil)
		w.objs[i].Set("parent", w.qGameGrid())
		w.objs[i].Set("text", name)
		w.objs[i].Set("data", name)
		w.objs[i].Set("alignCenter", true)
		w.objs[i].Set("width", w.winComponent.Root().Int("width")-150)
	}
}

func (w *window) buildLevelSelect() {
	w.currentBoard = ""
	w.setStatus("Nurikabe - " + w.currentDifficulty[2:])
	w.qGameGrid().Set("spacing", 15)
	w.qToolBtn().Set("text", "Back")
	w.qGameGrid().Set("columns", 4)

	names := files(levelDir + w.currentDifficulty)
	w.objs = make([]qml.Object, len(names), len(names))
	for i, name := range names {
		_, ok := w.records.Level(w.currentDifficulty, levelInt(name))
		w.objs[i] = w.btnComponent.Create(nil)
		w.objs[i].Set("parent", w.qGameGrid())
		w.objs[i].Set("text", levelStr(name)) //remove '.json' from name
		w.objs[i].Set("data", name)
		w.objs[i].Set("showstar", true)
		w.objs[i].Set("completed", ok)
		w.objs[i].Set("width", 50)
	}
}

func (w *window) buildDifficultySelect() {
	w.setStatus("Nurikabe - Select Difficulty")
	w.qGameGrid().Set("spacing", 15)
	w.qGameGrid().Set("columns", 1)
	w.qToolBtn().Set("text", "Menu")

	names := dirs(levelDir)
	w.objs = make([]qml.Object, len(names), len(names))
	for i, name := range names {
		w.objs[i] = w.btnComponent.Create(nil)
		w.objs[i].Set("parent", w.qGameGrid())
		w.objs[i].Set("text", name[2:])
		w.objs[i].Set("data", name)
		w.objs[i].Set("alignCenter", true)
		w.objs[i].Set("width", w.winComponent.Root().Int("width")-150)
	}
}

func (w *window) buildRules() {
	w.currentBoard = ""
	w.setStatus("Nurikabe - Rules")
	w.qToolBtn().Set("text", "Back")
	w.qGameGrid().Set("columns", 4)

	w.objs = make([]qml.Object, 1, 1)
	w.objs[0] = w.txtComponent.Create(nil)
	w.objs[0].Set("parent", w.qGameGrid())
	w.objs[0].Set("text", rulesText)
	w.objs[0].Set("width", w.winComponent.Root().Int("width")-50)
}

func (w *window) buildStats() {
	w.currentBoard = ""
	w.setStatus("Nurikabe - Records")
	w.qGameGrid().Set("spacing", 7)
	w.qToolBtn().Set("text", "Back")
	w.qGameGrid().Set("columns", 4)

	l := w.records.Length()
	w.objs = make([]qml.Object, 0, l+1)

	buildTxtBox := func(s string) {
		obj := w.txtComponent.Create(nil)
		obj.Set("parent", w.qGameGrid())
		obj.Set("text", s)
		w.objs = append(w.objs, obj)
	}

	headers := []string{"Difficulty", "Level", "Steps", "Seconds"}
	for _, txt := range headers {
		buildTxtBox(txt)
	}
	for _, _ = range headers {
		buildTxtBox("----------")
	}

	for _, rec := range w.records.All() {
		buildTxtBox(rec.Difficulty[2:])
		buildTxtBox(strconv.Itoa(rec.Lvl))
		buildTxtBox(strconv.Itoa(rec.Steps))
		buildTxtBox(strconv.Itoa(rec.Seconds))
	}
}

func (w *window) loadStats() {
	var err error
	d := dirs(levelDir)
	sorter := make(map[string]int, len(d))
	for _, f := range dirs(levelDir) {
		sorter[f[2:]] = int(f[0] - '0')

	}
	w.records, err = stats.Load(statsFile, sorter)
	if err != nil {
		fmt.Println("Error loading stats", err)
		w.records = stats.New(sorter)
	}
}

func (w *window) setTimer(running bool) {
	w.qStatus().Set("finished", !running)
}

func (w *window) setStatus(s string) {
	w.qStatus().Set("text", s)
}

func (w *window) setSource(page string) {
	w.qLoader().Set("source", page)
}

func (w *window) obj(name string) qml.Object {
	return w.winComponent.Root().ObjectByName(name)
}

func (w *window) qStatus() qml.Object {
	return w.obj("statusText")
}

func (w *window) qGameGrid() qml.Object {
	return w.obj("grid")
}

func (w *window) qLoader() qml.Object {
	return w.obj("pageLoader")
}

func (w *window) qToolBtn() qml.Object {
	return w.obj("toolBtn")
}

func (w *window) qStepsText() qml.Object {
	return w.obj("movesText")
}

func (w *window) qTimeText() qml.Object {
	return w.obj("timerText")
}

func (w *window) qRecordText() qml.Object {
	return w.obj("recordText")
}

func RunNurikabe(engine *qml.Engine) error {
	context := engine.Context()

	window, err := NewMainWindow(engine)
	if err != nil {
		return err
	}

	context.SetVar("window", window)
	window.loadStats()
	window.setGameMode(mainMenu)

	window.winComponent.Show()
	window.winComponent.Wait()
	window.records.Save(statsFile)
	return nil
}
<|endoftext|>


<commit_before>package metacpan

import (
	"fmt"
	"net/url"

	"github.com/zquestz/s/providers"
)

func init() {
	providers.AddProvider("metacpan", &Provider{})
}

// Provider merely implements the Provider interface.
type Provider struct{
}

// BuildURI generates a search URL for MetaCPAN.
func (p *Provider) BuildURI(q string) string {
	return fmt.Sprintf("https://metacpan.org/search?q=%s", url.QueryEscape(q))
}<commit_msg>Fix go formatting<commit_after>package metacpan

import (
	"fmt"
	"net/url"

	"github.com/zquestz/s/providers"
)

func init() {
	providers.AddProvider("metacpan", &Provider{})
}

// Provider merely implements the Provider interface.
type Provider struct {
}

// BuildURI generates a search URL for MetaCPAN.
func (p *Provider) BuildURI(q string) string {
	return fmt.Sprintf("https://metacpan.org/search?q=%s", url.QueryEscape(q))
}
<|endoftext|>


<commit_before>// Copyright 2015 CoreOS, Inc.
//
// 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 main

import (
	"fmt"
	"log"
	"os"
	"time"

	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/cheggaaa/pb"
	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/spf13/cobra"
	"github.com/coreos/etcd/Godeps/_workspace/src/golang.org/x/net/context"
	v3 "github.com/coreos/etcd/clientv3"
	"github.com/samuel/go-zookeeper/zk"
)

// rangeCmd represents the range command
var rangeCmd = &cobra.Command{
	Use:   "range key [end-range]",
	Short: "Benchmark range",

	Run: rangeFunc,
}

var (
	rangeTotal       int
	rangeConsistency string
	singleKey        bool
)

func init() {
	Command.AddCommand(rangeCmd)
	rangeCmd.Flags().IntVar(&rangeTotal, "total", 10000, "Total number of range requests")
	rangeCmd.Flags().StringVar(&rangeConsistency, "consistency", "l", "Linearizable(l) or Serializable(s)")
	rangeCmd.Flags().BoolVar(&singleKey, "single-key", false, "'true' to get only one single key (automatic put before test)")
	rangeCmd.Flags().IntVar(&keySize, "key-size", 64, "key size")
	rangeCmd.Flags().IntVar(&valSize, "val-size", 128, "value size")
}

func rangeFunc(cmd *cobra.Command, args []string) {
	var k string
	if singleKey { // write 'foo'
		k = string(randBytes(keySize))
		v := randBytes(valSize)
		switch database {
		case "etcd":
			fmt.Printf("PUT '%s' to etcd\n", k)
			clients := mustCreateClients(1, 1)
			_, err := clients[0].Do(context.Background(), v3.OpPut(k, string(v)))
			if err != nil {
				fmt.Fprintln(os.Stderr, err)
				os.Exit(1)
			}
			fmt.Printf("Done with PUT '%s' to etcd\n", k)
		case "zk":
			fmt.Printf("PUT '%s' to zookeeper\n", k)
			conns := mustCreateConnsZk(totalConns)
			_, err := conns[0].Create(k, v, zkCreateFlags, zkCreateAcl)
			if err != nil {
				fmt.Fprintln(os.Stderr, err)
				os.Exit(1)
			}
			fmt.Printf("Done with PUT '%s' to zookeeper\n", k)
		}
	} else if len(args) == 0 || len(args) > 2 {
		fmt.Fprintln(os.Stderr, cmd.Usage())
		os.Exit(1)
	}

	var end string
	if !singleKey {
		k = args[0]
		if len(args) == 2 {
			end = args[1]
		}
	}

	if rangeConsistency == "l" {
		fmt.Println("bench with linearizable range")
	} else if rangeConsistency == "s" {
		fmt.Println("bench with serializable range")
	} else {
		fmt.Fprintln(os.Stderr, cmd.Usage())
		os.Exit(1)
	}

	results = make(chan result)
	requests := make(chan request, totalClients)
	bar = pb.New(rangeTotal)

	bar.Format("Bom !")
	bar.Start()

	switch database {
	case "etcd":
		clients := mustCreateClients(totalClients, totalConns)
		for i := range clients {
			wg.Add(1)
			go doRange(clients[i].KV, requests)
		}
		defer func() {
			for i := range clients {
				clients[i].Close()
			}
		}()
	case "zk":
		conns := mustCreateConnsZk(totalConns)
		defer func() {
			for i := range conns {
				conns[i].Close()
			}
		}()
		for i := range conns {
			wg.Add(1)
			go doRangeZk(conns[i], requests)
		}
	default:
		log.Fatalf("unknown database %s", database)
	}

	pdoneC := printReport(results)
	go func() {
		for i := 0; i < rangeTotal; i++ {
			switch database {
			case "etcd":
				opts := []v3.OpOption{v3.WithRange(end)}
				if rangeConsistency == "s" {
					opts = append(opts, v3.WithSerializable())
				}
				requests <- request{etcdOp: v3.OpGet(k, opts...)}
			case "zk":
				requests <- request{zkOp: zkOp{key: k}}
			}
		}
		close(requests)
	}()

	wg.Wait()

	bar.Finish()

	close(results)
	<-pdoneC
}

func doRange(client v3.KV, requests <-chan request) {
	defer wg.Done()

	for req := range requests {
		op := req.etcdOp
		st := time.Now()
		_, err := client.Do(context.Background(), op)

		var errStr string
		if err != nil {
			errStr = err.Error()
		}
		results <- result{errStr: errStr, duration: time.Since(st), happened: time.Now()}
		bar.Increment()
	}
}

func doRangeZk(conn *zk.Conn, requests <-chan request) {
	defer wg.Done()

	for req := range requests {
		op := req.zkOp
		st := time.Now()
		_, _, err := conn.Get(op.key)

		var errStr string
		if err != nil {
			errStr = err.Error()
		}
		results <- result{errStr: errStr, duration: time.Since(st), happened: time.Now()}
		bar.Increment()
	}
}
<commit_msg>slash<commit_after>// Copyright 2015 CoreOS, Inc.
//
// 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 main

import (
	"fmt"
	"log"
	"os"
	"time"

	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/cheggaaa/pb"
	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/spf13/cobra"
	"github.com/coreos/etcd/Godeps/_workspace/src/golang.org/x/net/context"
	v3 "github.com/coreos/etcd/clientv3"
	"github.com/samuel/go-zookeeper/zk"
)

// rangeCmd represents the range command
var rangeCmd = &cobra.Command{
	Use:   "range key [end-range]",
	Short: "Benchmark range",

	Run: rangeFunc,
}

var (
	rangeTotal       int
	rangeConsistency string
	singleKey        bool
)

func init() {
	Command.AddCommand(rangeCmd)
	rangeCmd.Flags().IntVar(&rangeTotal, "total", 10000, "Total number of range requests")
	rangeCmd.Flags().StringVar(&rangeConsistency, "consistency", "l", "Linearizable(l) or Serializable(s)")
	rangeCmd.Flags().BoolVar(&singleKey, "single-key", false, "'true' to get only one single key (automatic put before test)")
	rangeCmd.Flags().IntVar(&keySize, "key-size", 64, "key size")
	rangeCmd.Flags().IntVar(&valSize, "val-size", 128, "value size")
}

func rangeFunc(cmd *cobra.Command, args []string) {
	var k string
	if singleKey { // write 'foo'
		k = "/" + string(randBytes(keySize))
		v := randBytes(valSize)
		switch database {
		case "etcd":
			fmt.Printf("PUT '%s' to etcd\n", k)
			clients := mustCreateClients(1, 1)
			_, err := clients[0].Do(context.Background(), v3.OpPut(k, string(v)))
			if err != nil {
				fmt.Fprintln(os.Stderr, err)
				os.Exit(1)
			}
			fmt.Printf("Done with PUT '%s' to etcd\n", k)
		case "zk":
			fmt.Printf("PUT '%s' to zookeeper\n", k)
			conns := mustCreateConnsZk(totalConns)
			_, err := conns[0].Create(k, v, zkCreateFlags, zkCreateAcl)
			if err != nil {
				fmt.Fprintln(os.Stderr, err)
				os.Exit(1)
			}
			fmt.Printf("Done with PUT '%s' to zookeeper\n", k)
		}
	} else if len(args) == 0 || len(args) > 2 {
		fmt.Fprintln(os.Stderr, cmd.Usage())
		os.Exit(1)
	}

	var end string
	if !singleKey {
		k = args[0]
		if len(args) == 2 {
			end = args[1]
		}
	}

	if rangeConsistency == "l" {
		fmt.Println("bench with linearizable range")
	} else if rangeConsistency == "s" {
		fmt.Println("bench with serializable range")
	} else {
		fmt.Fprintln(os.Stderr, cmd.Usage())
		os.Exit(1)
	}

	results = make(chan result)
	requests := make(chan request, totalClients)
	bar = pb.New(rangeTotal)

	bar.Format("Bom !")
	bar.Start()

	switch database {
	case "etcd":
		clients := mustCreateClients(totalClients, totalConns)
		for i := range clients {
			wg.Add(1)
			go doRange(clients[i].KV, requests)
		}
		defer func() {
			for i := range clients {
				clients[i].Close()
			}
		}()
	case "zk":
		conns := mustCreateConnsZk(totalConns)
		defer func() {
			for i := range conns {
				conns[i].Close()
			}
		}()
		for i := range conns {
			wg.Add(1)
			go doRangeZk(conns[i], requests)
		}
	default:
		log.Fatalf("unknown database %s", database)
	}

	pdoneC := printReport(results)
	go func() {
		for i := 0; i < rangeTotal; i++ {
			switch database {
			case "etcd":
				opts := []v3.OpOption{v3.WithRange(end)}
				if rangeConsistency == "s" {
					opts = append(opts, v3.WithSerializable())
				}
				requests <- request{etcdOp: v3.OpGet(k, opts...)}
			case "zk":
				requests <- request{zkOp: zkOp{key: k}}
			}
		}
		close(requests)
	}()

	wg.Wait()

	bar.Finish()

	close(results)
	<-pdoneC
}

func doRange(client v3.KV, requests <-chan request) {
	defer wg.Done()

	for req := range requests {
		op := req.etcdOp
		st := time.Now()
		_, err := client.Do(context.Background(), op)

		var errStr string
		if err != nil {
			errStr = err.Error()
		}
		results <- result{errStr: errStr, duration: time.Since(st), happened: time.Now()}
		bar.Increment()
	}
}

func doRangeZk(conn *zk.Conn, requests <-chan request) {
	defer wg.Done()

	for req := range requests {
		op := req.zkOp
		st := time.Now()
		_, _, err := conn.Get(op.key)

		var errStr string
		if err != nil {
			errStr = err.Error()
		}
		results <- result{errStr: errStr, duration: time.Since(st), happened: time.Now()}
		bar.Increment()
	}
}
<|endoftext|>


<commit_before>// Copyright 2013 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package id3

import (
	"fmt"
	"io"
)

const (
	HeaderSize = 10
)

// Tag represents an ID3v2 tag
type Tag struct {
	Header
	frames                map[string][]Framer
	padding               uint
	commonMap             map[string]string
	frameHeaderSize       int
	frameConstructor      func(io.Reader) Framer
	frameBytesConstructor func(Framer) []byte
}

// Creates a new tag
func NewTag(reader io.Reader) *Tag {
	t := &Tag{
		Header: NewHeader(reader),
		frames: make(map[string][]Framer),
	}

	if t.Header == nil {
		return nil
	}

	switch t.Header.Version() {
	case "2.2.0":
		t.commonMap = V22CommonFrame
		t.frameConstructor = NewV22Frame
		t.frameHeaderSize = V22FrameHeaderSize
		t.frameBytesConstructor = V22Bytes
	case "2.3.0":
		t.commonMap = V23CommonFrame
		t.frameConstructor = NewV23Frame
		t.frameHeaderSize = FrameHeaderSize
		t.frameBytesConstructor = V23Bytes
	default:
		t.commonMap = V23CommonFrame
		t.frameConstructor = NewV23Frame
		t.frameHeaderSize = FrameHeaderSize
		t.frameBytesConstructor = V23Bytes
	}

	var frame Framer
	size := t.Header.Size()
	for size > 0 {
		frame = t.frameConstructor(reader)

		if frame == nil {
			break
		}

		id := frame.Id()
		t.frames[id] = append(t.frames[id], frame)
		frame.setOwner(t)

		size -= t.frameHeaderSize + int(frame.Size())
	}

	t.padding = uint(size)
	nAdvance := int(t.padding) - t.frameHeaderSize
	if n, err := io.ReadFull(reader, make([]byte, nAdvance)); n != nAdvance || err != nil {
		return nil
	}

	return t
}

// Size of the tag
// Recalculated as frames and padding can be changed
func (t Tag) Size() int {
	size := 0
	for _, v := range t.frames {
		for _, f := range v {
			size += t.frameHeaderSize + int(f.Size())
		}
	}

	headerSize := t.Header.Size()
	if padding := headerSize - size; padding < 0 {
		t.padding = 0
		head := t.Header.(Head)
		head.size = int32(size)
		return size
	} else {
		t.padding = uint(padding)
		return headerSize
	}
}

func (t Tag) Bytes() []byte {
	data := make([]byte, t.Size())

	index := 0
	for _, v := range t.frames {
		for _, f := range v {
			size := t.frameHeaderSize + int(f.Size())
			copy(data[index:index+size], t.frameBytesConstructor(f))

			index += size
		}
	}

	return append(t.Header.Bytes(), data...)
}

// All frames
func (t Tag) AllFrames() []Framer {
	// Most of the time each ID will only have one frame
	m := len(t.frames)
	frames := make([]Framer, m)

	i := 0
	for _, frameSlice := range t.frames {
		if i >= m {
			frames = append(frames, frameSlice...)
		}

		n := copy(frames[i:], frameSlice)
		i += n
		if n < len(frameSlice) {
			frames = append(frames, frameSlice[n:]...)
		}
	}

	return frames
}

// All frames with specified ID
func (t Tag) Frames(id string) []Framer {
	if frames, ok := t.frames[id]; ok && frames != nil {
		return frames
	}

	return []Framer{}
}

// First frame with specified ID
func (t Tag) Frame(id string) Framer {
	if frames := t.Frames(id); frames != nil {
		return frames[0]
	}

	return nil
}

// Delete and return all frames with specified ID
func (t *Tag) DeleteFrames(id string) []Framer {
	frames := t.Frames(id)
	if frames == nil {
		return nil
	}

	delete(t.frames, id)

	return frames
}

// Add frame
func (t *Tag) AddFrame(frame Framer) {
	id := frame.Id()
	t.frames[id] = append(t.frames[id], frame)
}

// Header represents the useful information contained in the data
type Header interface {
	Version() string
	Size() int
	Bytes() []byte
}

func (t Tag) Title() string {
	return t.textFrameText(t.commonMap["Title"])
}

func (t Tag) Artist() string {
	return t.textFrameText(t.commonMap["Artist"])
}

func (t Tag) Album() string {
	return t.textFrameText(t.commonMap["Album"])
}

func (t Tag) Year() string {
	return t.textFrameText(t.commonMap["Year"])
}

func (t Tag) Genre() string {
	return t.textFrameText(t.commonMap["Genre"])
}

func (t Tag) Comments() []string {
	frames := t.Frames(t.commonMap["Comments"])
	if frames == nil {
		return nil
	}

	comments := make([]string, len(frames))
	for i, frame := range frames {
		comments[i] = frame.String()
	}

	return comments
}

func (t *Tag) SetTitle(text string) {
	t.setTextFrameText(t.commonMap["Title"], text)
}

func (t *Tag) SetArtist(text string) {
	t.setTextFrameText(t.commonMap["Artist"], text)
}

func (t *Tag) SetAlbum(text string) {
	t.setTextFrameText(t.commonMap["Album"], text)
}

func (t *Tag) SetYear(text string) {
	t.setTextFrameText(t.commonMap["Year"], text)
}

func (t *Tag) SetGenre(text string) {
	t.setTextFrameText(t.commonMap["Genre"], text)
}

func (t *Tag) textFrame(id string) TextFramer {
	if frame := t.Frame(id); frame != nil {
		if textFramer, ok := frame.(TextFramer); ok {
			return textFramer
		}
	}

	return nil
}

func (t Tag) textFrameText(id string) string {
	if frame := t.textFrame(id); frame != nil {
		return frame.Text()
	}

	return ""
}

func (t *Tag) setTextFrameText(id, text string) {
	if frame := t.textFrame(id); frame != nil {
		frame.SetText(text)
	}
}

func NewHeader(reader io.Reader) Header {
	data := make([]byte, HeaderSize)
	n, err := io.ReadFull(reader, data)
	if n < HeaderSize || err != nil || string(data[:3]) != "ID3" {
		return nil
	}

	size, err := synchint(data[6:])
	if err != nil {
		return nil
	}

	return Head{
		version:  data[3],
		revision: data[4],
		flags:    data[5],
		size:     size,
	}
}

// Head represents the data of the header of the entire tag
type Head struct {
	version, revision byte
	flags             byte
	size              int32
}

func (h Head) Version() string {
	return fmt.Sprintf("2.%d.%d", h.version, h.revision)
}

func (h Head) Size() int {
	return int(h.size)
}

func (h Head) Bytes() []byte {
	data := make([]byte, HeaderSize)

	copy(data[:3], []byte("ID3"))
	copy(data[6:], synchbytes(h.size))
	data[3] = h.version
	data[4] = h.revision
	data[5] = h.flags

	return data
}
<commit_msg>Fix nil check to empty check<commit_after>// Copyright 2013 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package id3

import (
	"fmt"
	"io"
)

const (
	HeaderSize = 10
)

// Tag represents an ID3v2 tag
type Tag struct {
	Header
	frames                map[string][]Framer
	padding               uint
	commonMap             map[string]string
	frameHeaderSize       int
	frameConstructor      func(io.Reader) Framer
	frameBytesConstructor func(Framer) []byte
}

// Creates a new tag
func NewTag(reader io.Reader) *Tag {
	t := &Tag{
		Header: NewHeader(reader),
		frames: make(map[string][]Framer),
	}

	if t.Header == nil {
		return nil
	}

	switch t.Header.Version() {
	case "2.2.0":
		t.commonMap = V22CommonFrame
		t.frameConstructor = NewV22Frame
		t.frameHeaderSize = V22FrameHeaderSize
		t.frameBytesConstructor = V22Bytes
	case "2.3.0":
		t.commonMap = V23CommonFrame
		t.frameConstructor = NewV23Frame
		t.frameHeaderSize = FrameHeaderSize
		t.frameBytesConstructor = V23Bytes
	default:
		t.commonMap = V23CommonFrame
		t.frameConstructor = NewV23Frame
		t.frameHeaderSize = FrameHeaderSize
		t.frameBytesConstructor = V23Bytes
	}

	var frame Framer
	size := t.Header.Size()
	for size > 0 {
		frame = t.frameConstructor(reader)

		if frame == nil {
			break
		}

		id := frame.Id()
		t.frames[id] = append(t.frames[id], frame)
		frame.setOwner(t)

		size -= t.frameHeaderSize + int(frame.Size())
	}

	t.padding = uint(size)
	nAdvance := int(t.padding) - t.frameHeaderSize
	if n, err := io.ReadFull(reader, make([]byte, nAdvance)); n != nAdvance || err != nil {
		return nil
	}

	return t
}

// Size of the tag
// Recalculated as frames and padding can be changed
func (t Tag) Size() int {
	size := 0
	for _, v := range t.frames {
		for _, f := range v {
			size += t.frameHeaderSize + int(f.Size())
		}
	}

	headerSize := t.Header.Size()
	if padding := headerSize - size; padding < 0 {
		t.padding = 0
		head := t.Header.(Head)
		head.size = int32(size)
		return size
	} else {
		t.padding = uint(padding)
		return headerSize
	}
}

func (t Tag) Bytes() []byte {
	data := make([]byte, t.Size())

	index := 0
	for _, v := range t.frames {
		for _, f := range v {
			size := t.frameHeaderSize + int(f.Size())
			copy(data[index:index+size], t.frameBytesConstructor(f))

			index += size
		}
	}

	return append(t.Header.Bytes(), data...)
}

// All frames
func (t Tag) AllFrames() []Framer {
	// Most of the time each ID will only have one frame
	m := len(t.frames)
	frames := make([]Framer, m)

	i := 0
	for _, frameSlice := range t.frames {
		if i >= m {
			frames = append(frames, frameSlice...)
		}

		n := copy(frames[i:], frameSlice)
		i += n
		if n < len(frameSlice) {
			frames = append(frames, frameSlice[n:]...)
		}
	}

	return frames
}

// All frames with specified ID
func (t Tag) Frames(id string) []Framer {
	if frames, ok := t.frames[id]; ok && frames != nil {
		return frames
	}

	return []Framer{}
}

// First frame with specified ID
func (t Tag) Frame(id string) Framer {
	if frames := t.Frames(id); len(frames) != 0 {
		return frames[0]
	}

	return nil
}

// Delete and return all frames with specified ID
func (t *Tag) DeleteFrames(id string) []Framer {
	frames := t.Frames(id)
	if frames == nil {
		return nil
	}

	delete(t.frames, id)

	return frames
}

// Add frame
func (t *Tag) AddFrame(frame Framer) {
	id := frame.Id()
	t.frames[id] = append(t.frames[id], frame)
}

// Header represents the useful information contained in the data
type Header interface {
	Version() string
	Size() int
	Bytes() []byte
}

func (t Tag) Title() string {
	return t.textFrameText(t.commonMap["Title"])
}

func (t Tag) Artist() string {
	return t.textFrameText(t.commonMap["Artist"])
}

func (t Tag) Album() string {
	return t.textFrameText(t.commonMap["Album"])
}

func (t Tag) Year() string {
	return t.textFrameText(t.commonMap["Year"])
}

func (t Tag) Genre() string {
	return t.textFrameText(t.commonMap["Genre"])
}

func (t Tag) Comments() []string {
	frames := t.Frames(t.commonMap["Comments"])
	if frames == nil {
		return nil
	}

	comments := make([]string, len(frames))
	for i, frame := range frames {
		comments[i] = frame.String()
	}

	return comments
}

func (t *Tag) SetTitle(text string) {
	t.setTextFrameText(t.commonMap["Title"], text)
}

func (t *Tag) SetArtist(text string) {
	t.setTextFrameText(t.commonMap["Artist"], text)
}

func (t *Tag) SetAlbum(text string) {
	t.setTextFrameText(t.commonMap["Album"], text)
}

func (t *Tag) SetYear(text string) {
	t.setTextFrameText(t.commonMap["Year"], text)
}

func (t *Tag) SetGenre(text string) {
	t.setTextFrameText(t.commonMap["Genre"], text)
}

func (t *Tag) textFrame(id string) TextFramer {
	if frame := t.Frame(id); frame != nil {
		if textFramer, ok := frame.(TextFramer); ok {
			return textFramer
		}
	}

	return nil
}

func (t Tag) textFrameText(id string) string {
	if frame := t.textFrame(id); frame != nil {
		return frame.Text()
	}

	return ""
}

func (t *Tag) setTextFrameText(id, text string) {
	if frame := t.textFrame(id); frame != nil {
		frame.SetText(text)
	}
}

func NewHeader(reader io.Reader) Header {
	data := make([]byte, HeaderSize)
	n, err := io.ReadFull(reader, data)
	if n < HeaderSize || err != nil || string(data[:3]) != "ID3" {
		return nil
	}

	size, err := synchint(data[6:])
	if err != nil {
		return nil
	}

	return Head{
		version:  data[3],
		revision: data[4],
		flags:    data[5],
		size:     size,
	}
}

// Head represents the data of the header of the entire tag
type Head struct {
	version, revision byte
	flags             byte
	size              int32
}

func (h Head) Version() string {
	return fmt.Sprintf("2.%d.%d", h.version, h.revision)
}

func (h Head) Size() int {
	return int(h.size)
}

func (h Head) Bytes() []byte {
	data := make([]byte, HeaderSize)

	copy(data[:3], []byte("ID3"))
	copy(data[6:], synchbytes(h.size))
	data[3] = h.version
	data[4] = h.revision
	data[5] = h.flags

	return data
}
<|endoftext|>


<commit_before>// licence goes here

// +build linux,!cgo

package serial

import (
	"bufio"
	"errors"
	"os"
	"syscall"
)

var (
	errConnOpen = errors.New("serial connection error: connection is not open")
)

// structs and its functions

// Open a connection.
func (connection *Connection) Open() error {

	// syscall: https://golang.org/pkg/syscall/

	// The serial port is basically a file we are writing to and reading from.
	// 	O_RDWR allows us to read and write.
	// 	O_NOCTTY prevents the device from controlling the terminal.
	// 	O_NONBLOCK prevents the system from blocking for a long time.
	connection.f, err = os.OpenFile(connection.Port, syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_NONBLOCK, 0666)
	if err != nil {
		return err
	}

	connection.open = true
	return nil
}

// Write a byte array to an open connection.
func (connection *Connection) Write(b []byte) (int, error) {
	if connection.open {
		return connection.f.Write(b)
	}

	return _, errConnOpen
}

// Read from an open connection until the delimter is reached.
func (connection *Connection) Read(delimter byte) ([]byte, error) {
	if connection.open {
		reader := bufio.NewReader(connection.f)
		return reader.ReadBytes(delimiter)
	}

	return _, errConnOpen
}

// Close a connection.
func (connection *Connection) Close() error {
	err := connection.f.Close()
	connection.open = false

	return err
}
<commit_msg>added a defer to close the file on error occurence<commit_after>// licence goes here

// +build linux,!cgo

package serial

import (
	"bufio"
	"errors"
	"os"
	"syscall"
)

var (
	errConnOpen = errors.New("serial connection error: connection is not open")
)

// structs and its functions

// Open a connection.
func (connection *Connection) Open() error {

	// syscall: https://golang.org/pkg/syscall/

	// The serial port is basically a file we are writing to and reading from.
	// 	O_RDWR allows us to read and write.
	// 	O_NOCTTY prevents the device from controlling the terminal.
	// 	O_NONBLOCK prevents the system from blocking for a long time.
	connection.f, err = os.OpenFile(connection.Port, syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_NONBLOCK, 0666)
	if err != nil {
		return err
	}

	// Close the file on error occurrence.
	defer func() {
		if err != nil && f != nil {
			f.Close()
		}
	}()

	connection.open = true
	return nil
}

// Write a byte array to an open connection.
func (connection *Connection) Write(b []byte) (int, error) {
	if connection.open {
		return connection.f.Write(b)
	}

	return _, errConnOpen
}

// Read from an open connection until the delimter is reached.
func (connection *Connection) Read(delimter byte) ([]byte, error) {
	if connection.open {
		reader := bufio.NewReader(connection.f)
		return reader.ReadBytes(delimiter)
	}

	return _, errConnOpen
}

// Close a connection.
func (connection *Connection) Close() error {
	err := connection.f.Close()
	connection.open = false

	return err
}
<|endoftext|>


<commit_before>package main

import (
	"dns"
	"errors"
	"log"
	"os"
)

// ReadZone reads a zone and adds it.
func (c *Config) ReadZone(origin, file string) error {
	z := dns.NewZone(origin)
	if z == nil {
		return errors.New("fksd: failed to open zone file")
	}
	f, e := os.Open(file)
	if e != nil {
		return e
	}
	for rr := range dns.ParseZone(f, origin, file) {
		if rr.Error == nil {
			z.Insert(rr.RR)
		} else {
			log.Printf("fksd: failed to parse: %s\n", rr.Error.Error())
		}
	}
	c.Zones[origin] = z
	dns.HandleFunc(origin, func(w dns.ResponseWriter, req *dns.Msg) { serve(w, req, c.Zones[origin]) })
	return nil
}
<commit_msg>more sane logging<commit_after>package main

import (
	"dns"
	"errors"
	"os"
)

// ReadZone reads a zone and adds it.
func (c *Config) ReadZone(origin, file string) error {
	z := dns.NewZone(origin)
	if z == nil {
		return errors.New("fksd: failed to open zone file")
	}
	f, e := os.Open(file)
	if e != nil {
		return e
	}
	for rr := range dns.ParseZone(f, origin, file) {
		if rr.Error == nil {
			z.Insert(rr.RR)
		} else {
			logPrintf("failed to parse: %s\n", rr.Error.Error())
		}
	}
	c.Zones[origin] = z
	dns.HandleFunc(origin, func(w dns.ResponseWriter, req *dns.Msg) { serve(w, req, c.Zones[origin]) })
	return nil
}
<|endoftext|>


<commit_before>package server

import (
	"os"

	"github.com/dirtyhairy/moneypenny/server/service/persistence"
	"github.com/labstack/echo"
	"github.com/labstack/echo/middleware"
	"github.com/labstack/gommon/log"
)

type server struct {
	config      Config
	persistence persistence.Provider
	echo        *echo.Echo
}

func Create(config Config) (_s Server, err error) {
	s := server{
		config:      config,
		persistence: config.Persistence,
		echo:        echo.New(),
	}

	if config.LogWriter == nil {
		config.LogWriter = os.Stderr
	}

	s.echo.Logger.SetOutput(config.LogWriter)
	if config.Debug {
		s.echo.Logger.SetLevel(log.DEBUG)
	}

	s.echo.Use(s.addContextMiddleware())

	s.echo.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
		Output: config.LogWriter,
	}))

	s.echo.Use(middleware.RecoverWithConfig(middleware.RecoverConfig{
		DisablePrintStack: !config.Debug,
	}))

	s.setupRouting()

	_s = &s
	return
}

func (s *server) Start() error {
	return s.echo.Start(s.config.Listen)
}

func (s *server) addContextMiddleware() echo.MiddlewareFunc {
	return func(handler echo.HandlerFunc) echo.HandlerFunc {
		return func(c echo.Context) error {
			ourContext := context{
				Context:     c,
				persistence: s.persistence,
			}

			return handler(&ourContext)
		}
	}
}<commit_msg>Enable gzip on server.<commit_after>package server

import (
	"os"

	"github.com/dirtyhairy/moneypenny/server/service/persistence"
	"github.com/labstack/echo"
	"github.com/labstack/echo/middleware"
	"github.com/labstack/gommon/log"
)

type server struct {
	config      Config
	persistence persistence.Provider
	echo        *echo.Echo
}

func Create(config Config) (_s Server, err error) {
	s := server{
		config:      config,
		persistence: config.Persistence,
		echo:        echo.New(),
	}

	if config.LogWriter == nil {
		config.LogWriter = os.Stderr
	}

	s.echo.Logger.SetOutput(config.LogWriter)
	if config.Debug {
		s.echo.Logger.SetLevel(log.DEBUG)
	}

	s.echo.Use(s.addContextMiddleware())

	s.echo.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
		Output: config.LogWriter,
	}))

	s.echo.Use(middleware.RecoverWithConfig(middleware.RecoverConfig{
		DisablePrintStack: !config.Debug,
	}))

	s.echo.Use(middleware.Gzip())

	s.setupRouting()

	_s = &s
	return
}

func (s *server) Start() error {
	return s.echo.Start(s.config.Listen)
}

func (s *server) addContextMiddleware() echo.MiddlewareFunc {
	return func(handler echo.HandlerFunc) echo.HandlerFunc {
		return func(c echo.Context) error {
			ourContext := context{
				Context:     c,
				persistence: s.persistence,
			}

			return handler(&ourContext)
		}
	}
}
<|endoftext|>


<commit_before>// Package alice provides a convenient way to chain http handlers.
package alice

import "net/http"

// A constructor for a piece of middleware.
// Some middleware use this constructor out of the box,
// so in most cases you can just pass somepackage.New
type Constructor func(http.Handler) http.Handler

// Chain acts as a list of http.Handler constructors.
// Chain is effectively immutable:
// once created, it will always hold
// the same set of constructors in the same order.
type Chain struct {
	constructors []Constructor
}

// New creates a new chain,
// memorizing the given list of middleware constructors.
// New serves no other function,
// constructors are only called upon a call to Then().
func New(constructors ...Constructor) Chain {
	return Chain{append(([]Constructor)(nil), constructors...)}
}

// Then chains the middleware and returns the final http.Handler.
//     New(m1, m2, m3).Then(h)
// is equivalent to:
//     m1(m2(m3(h)))
// When the request comes in, it will be passed to m1, then m2, then m3
// and finally, the given handler
// (assuming every middleware calls the following one).
//
// A chain can be safely reused by calling Then() several times.
//     stdStack := alice.New(ratelimitHandler, csrfHandler)
//     indexPipe = stdStack.Then(indexHandler)
//     authPipe = stdStack.Then(authHandler)
// Note that constructors are called on every call to Then()
// and thus several instances of the same middleware will be created
// when a chain is reused in this way.
// For proper middleware, this should cause no problems.
//
// Then() treats nil as http.DefaultServeMux.
func (c Chain) Then(h http.Handler) http.Handler {
	if h == nil {
		h = http.DefaultServeMux
	}

	for i := range c.constructors {
		h = c.constructors[len(c.constructors)-1-i](h)
	}

	return h
}

// ThenFunc works identically to Then, but takes
// a HandlerFunc instead of a Handler.
//
// The following two statements are equivalent:
//     c.Then(http.HandlerFunc(fn))
//     c.ThenFunc(fn)
//
// ThenFunc provides all the guarantees of Then.
func (c Chain) ThenFunc(fn http.HandlerFunc) http.Handler {
	if fn == nil {
		return c.Then(nil)
	}
	return c.Then(fn)
}

// Append extends a chain, adding the specified constructors
// as the last ones in the request flow.
//
// Append returns a new chain, leaving the original one untouched.
//
//     stdChain := alice.New(m1, m2)
//     extChain := stdChain.Append(m3, m4)
//     // requests in stdChain go m1 -> m2
//     // requests in extChain go m1 -> m2 -> m3 -> m4
func (c Chain) Append(constructors ...Constructor) Chain {
	newCons := make([]Constructor, 0, len(c.constructors)+len(constructors))
	newCons = append(newCons, c.constructors...)
	newCons = append(newCons, constructors...)

	return New(newCons...)
}

// Extend extends a chain by adding the specified chain
// as the last one in the request flow.
//
// Extend returns a new chain, leaving the original one untouched.
//
//     stdChain := alice.New(m1, m2)
//     ext1Chain := alice.New(m3, m4)
//     ext2Chain := stdChain.Extend(ext1Chain)
//     // requests in stdChain go  m1 -> m2
//     // requests in ext1Chain go m3 -> m4
//     // requests in ext2Chain go m1 -> m2 -> m3 -> m4
//
// Another example:
//  aHtmlAfterNosurf := alice.New(m2)
// 	aHtml := alice.New(m1, func(h http.Handler) http.Handler {
// 		csrf := nosurf.New(h)
// 		csrf.SetFailureHandler(aHtmlAfterNosurf.ThenFunc(csrfFail))
// 		return csrf
// 	}).Extend(aHtmlAfterNosurf)
//		// requests to aHtml hitting nosurfs success handler go m1 -> nosurf -> m2 -> target-handler
//		// requests to aHtml hitting nosurfs failure handler go m1 -> nosurf -> m2 -> csrfFail
func (c Chain) Extend(chain Chain) Chain {
	return c.Append(chain.constructors...)
}
<commit_msg>avoid unnecessary allocation with New() in Append()<commit_after>// Package alice provides a convenient way to chain http handlers.
package alice

import "net/http"

// A constructor for a piece of middleware.
// Some middleware use this constructor out of the box,
// so in most cases you can just pass somepackage.New
type Constructor func(http.Handler) http.Handler

// Chain acts as a list of http.Handler constructors.
// Chain is effectively immutable:
// once created, it will always hold
// the same set of constructors in the same order.
type Chain struct {
	constructors []Constructor
}

// New creates a new chain,
// memorizing the given list of middleware constructors.
// New serves no other function,
// constructors are only called upon a call to Then().
func New(constructors ...Constructor) Chain {
	return Chain{append(([]Constructor)(nil), constructors...)}
}

// Then chains the middleware and returns the final http.Handler.
//     New(m1, m2, m3).Then(h)
// is equivalent to:
//     m1(m2(m3(h)))
// When the request comes in, it will be passed to m1, then m2, then m3
// and finally, the given handler
// (assuming every middleware calls the following one).
//
// A chain can be safely reused by calling Then() several times.
//     stdStack := alice.New(ratelimitHandler, csrfHandler)
//     indexPipe = stdStack.Then(indexHandler)
//     authPipe = stdStack.Then(authHandler)
// Note that constructors are called on every call to Then()
// and thus several instances of the same middleware will be created
// when a chain is reused in this way.
// For proper middleware, this should cause no problems.
//
// Then() treats nil as http.DefaultServeMux.
func (c Chain) Then(h http.Handler) http.Handler {
	if h == nil {
		h = http.DefaultServeMux
	}

	for i := range c.constructors {
		h = c.constructors[len(c.constructors)-1-i](h)
	}

	return h
}

// ThenFunc works identically to Then, but takes
// a HandlerFunc instead of a Handler.
//
// The following two statements are equivalent:
//     c.Then(http.HandlerFunc(fn))
//     c.ThenFunc(fn)
//
// ThenFunc provides all the guarantees of Then.
func (c Chain) ThenFunc(fn http.HandlerFunc) http.Handler {
	if fn == nil {
		return c.Then(nil)
	}
	return c.Then(fn)
}

// Append extends a chain, adding the specified constructors
// as the last ones in the request flow.
//
// Append returns a new chain, leaving the original one untouched.
//
//     stdChain := alice.New(m1, m2)
//     extChain := stdChain.Append(m3, m4)
//     // requests in stdChain go m1 -> m2
//     // requests in extChain go m1 -> m2 -> m3 -> m4
func (c Chain) Append(constructors ...Constructor) Chain {
	newCons := make([]Constructor, 0, len(c.constructors)+len(constructors))
	newCons = append(newCons, c.constructors...)
	newCons = append(newCons, constructors...)

	return Chain{newCons}
}

// Extend extends a chain by adding the specified chain
// as the last one in the request flow.
//
// Extend returns a new chain, leaving the original one untouched.
//
//     stdChain := alice.New(m1, m2)
//     ext1Chain := alice.New(m3, m4)
//     ext2Chain := stdChain.Extend(ext1Chain)
//     // requests in stdChain go  m1 -> m2
//     // requests in ext1Chain go m3 -> m4
//     // requests in ext2Chain go m1 -> m2 -> m3 -> m4
//
// Another example:
//  aHtmlAfterNosurf := alice.New(m2)
// 	aHtml := alice.New(m1, func(h http.Handler) http.Handler {
// 		csrf := nosurf.New(h)
// 		csrf.SetFailureHandler(aHtmlAfterNosurf.ThenFunc(csrfFail))
// 		return csrf
// 	}).Extend(aHtmlAfterNosurf)
//		// requests to aHtml hitting nosurfs success handler go m1 -> nosurf -> m2 -> target-handler
//		// requests to aHtml hitting nosurfs failure handler go m1 -> nosurf -> m2 -> csrfFail
func (c Chain) Extend(chain Chain) Chain {
	return c.Append(chain.constructors...)
}
<|endoftext|>


<commit_before>// Copyright 2022 Google Inc. All Rights Reserved.
//
// 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 storage

import (
	"context"
	"errors"
	"testing"

	"github.com/fsouza/fake-gcs-server/fakestorage"
	"github.com/jacobsa/gcloud/gcs"
	. "github.com/jacobsa/ogletest"
)

const missingObjectName string = "test/foo"
const dstObjectName string = "gcsfuse/dst.txt"

// FakeGCSServer is not handling generation and metageneration checks for Delete flow.
// Hence, we are not writing tests for these flows.
// https://github.com/GoogleCloudPlatform/gcsfuse/blob/master/vendor/github.com/fsouza/fake-gcs-server/fakestorage/object.go#L515

func TestBucketHandle(t *testing.T) { RunTests(t) }

type BucketHandleTest struct {
	fakeStorageServer *fakestorage.Server
	bucketHandle      *bucketHandle
}

var _ SetUpInterface = &BucketHandleTest{}
var _ TearDownInterface = &BucketHandleTest{}

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

func (t *BucketHandleTest) SetUp(_ *TestInfo) {
	var err error
	t.fakeStorageServer, err = CreateFakeStorageServer([]fakestorage.Object{GetTestFakeStorageObject()})
	AssertEq(nil, err)

	storageClient := &storageClient{client: t.fakeStorageServer.Client()}
	t.bucketHandle, err = storageClient.BucketHandle(TestBucketName)
	AssertEq(nil, err)
	AssertNe(nil, t.bucketHandle)
}

func (t *BucketHandleTest) TearDown() {
	t.fakeStorageServer.Stop()
}

func (t *BucketHandleTest) TestNewReaderMethodWithCompleteRead() {
	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: TestObjectName,
			Range: &gcs.ByteRange{
				Start: uint64(0),
				Limit: uint64(len(ContentInTestObject)),
			},
		})

	AssertEq(nil, err)
	defer rc.Close()
	buf := make([]byte, len(ContentInTestObject))
	_, err = rc.Read(buf)
	AssertEq(nil, err)
	ExpectEq(string(buf[:]), ContentInTestObject)
}

func (t *BucketHandleTest) TestNewReaderMethodWithRangeRead() {
	start := uint64(2)
	limit := uint64(8)

	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: TestObjectName,
			Range: &gcs.ByteRange{
				Start: start,
				Limit: limit,
			},
		})

	AssertEq(nil, err)
	defer rc.Close()
	buf := make([]byte, limit-start)
	_, err = rc.Read(buf)
	AssertEq(nil, err)
	ExpectEq(string(buf[:]), ContentInTestObject[start:limit])
}

func (t *BucketHandleTest) TestNewReaderMethodWithInValidObject() {
	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: missingObjectName,
			Range: &gcs.ByteRange{
				Start: uint64(0),
				Limit: uint64(len(ContentInTestObject)),
			},
		})

	AssertNe(nil, err)
	AssertEq(nil, rc)
}

func (t *BucketHandleTest) TestNewReaderMethodWithValidGeneration() {
	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: TestObjectName,
			Range: &gcs.ByteRange{
				Start: uint64(0),
				Limit: uint64(len(ContentInTestObject)),
			},
			Generation: TestObjectGeneration,
		})

	AssertEq(nil, err)
	defer rc.Close()
	buf := make([]byte, len(ContentInTestObject))
	_, err = rc.Read(buf)
	AssertEq(nil, err)
	ExpectEq(string(buf[:]), ContentInTestObject)
}

func (t *BucketHandleTest) TestNewReaderMethodWithInvalidGeneration() {
	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: TestObjectName,
			Range: &gcs.ByteRange{
				Start: uint64(0),
				Limit: uint64(len(ContentInTestObject)),
			},
			Generation: 222, // other than TestObjectGeneration, doesn't exist.
		})

	AssertNe(nil, err)
	AssertEq(nil, rc)
}

func (t *BucketHandleTest) TestDeleteObjectMethodWithValidObject() {
	err := t.bucketHandle.DeleteObject(context.Background(),
		&gcs.DeleteObjectRequest{
			Name:                       TestObjectName,
			Generation:                 TestObjectGeneration,
			MetaGenerationPrecondition: nil,
		})

	AssertEq(nil, err)
}

func (t *BucketHandleTest) TestDeleteObjectMethodWithMissingObject() {
	err := t.bucketHandle.DeleteObject(context.Background(),
		&gcs.DeleteObjectRequest{
			Name:                       missingObjectName,
			Generation:                 TestObjectGeneration,
			MetaGenerationPrecondition: nil,
		})

	AssertEq("storage: object doesn't exist", err.Error())
}

func (t *BucketHandleTest) TestStatObjectMethodWithValidObject() {
	_, err := t.bucketHandle.StatObject(context.Background(),
		&gcs.StatObjectRequest{
			Name: TestObjectName,
		})

	AssertEq(nil, err)
}

func (t *BucketHandleTest) TestStatObjectMethodWithMissingObject() {
	var notfound *gcs.NotFoundError

	_, err := t.bucketHandle.StatObject(context.Background(),
		&gcs.StatObjectRequest{
			Name: missingObjectName,
		})

	AssertTrue(errors.As(err, &notfound))
}

func (t *BucketHandleTest) TestCopyObjectMethodWithValidObject() {
	_, err := t.bucketHandle.CopyObject(context.Background(),
		&gcs.CopyObjectRequest{
			SrcName:                       TestObjectName,
			DstName:                       dstObjectName,
			SrcGeneration:                 TestObjectGeneration,
			SrcMetaGenerationPrecondition: nil,
		})

	AssertEq(nil, err)
}

func (t *BucketHandleTest) TestCopyObjectMethodWithMissingObject() {
	var notfound *gcs.NotFoundError

	_, err := t.bucketHandle.CopyObject(context.Background(),
		&gcs.CopyObjectRequest{
			SrcName:                       missingObjectName,
			DstName:                       dstObjectName,
			SrcGeneration:                 TestObjectGeneration,
			SrcMetaGenerationPrecondition: nil,
		})

	AssertTrue(errors.As(err, &notfound))
}

func (t *BucketHandleTest) TestCopyObjectMethodWithInvalidGeneration() {
	var notfound *gcs.NotFoundError

	_, err := t.bucketHandle.CopyObject(context.Background(),
		&gcs.CopyObjectRequest{
			SrcName:                       TestObjectName,
			DstName:                       dstObjectName,
			SrcGeneration:                 222, // other than TestObjectGeneration, doesn't exist.
			SrcMetaGenerationPrecondition: nil,
		})

	AssertTrue(errors.As(err, &notfound))
}
<commit_msg>copy Object method<commit_after>// Copyright 2022 Google Inc. All Rights Reserved.
//
// 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 storage

import (
	"context"
	"errors"
	"testing"

	"github.com/fsouza/fake-gcs-server/fakestorage"
	"github.com/jacobsa/gcloud/gcs"
	. "github.com/jacobsa/ogletest"
)

const missingObjectName string = "test/foo"
const dstObjectName string = "gcsfuse/dst.txt"

// FakeGCSServer is not handling generation and metageneration checks for Delete flow.
// Hence, we are not writing tests for these flows.
// https://github.com/GoogleCloudPlatform/gcsfuse/blob/master/vendor/github.com/fsouza/fake-gcs-server/fakestorage/object.go#L515

func TestBucketHandle(t *testing.T) { RunTests(t) }

type BucketHandleTest struct {
	fakeStorageServer *fakestorage.Server
	bucketHandle      *bucketHandle
}

var _ SetUpInterface = &BucketHandleTest{}
var _ TearDownInterface = &BucketHandleTest{}

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

func (t *BucketHandleTest) SetUp(_ *TestInfo) {
	var err error
	t.fakeStorageServer, err = CreateFakeStorageServer([]fakestorage.Object{GetTestFakeStorageObject()})
	AssertEq(nil, err)

	storageClient := &storageClient{client: t.fakeStorageServer.Client()}
	t.bucketHandle, err = storageClient.BucketHandle(TestBucketName)
	AssertEq(nil, err)
	AssertNe(nil, t.bucketHandle)
}

func (t *BucketHandleTest) TearDown() {
	t.fakeStorageServer.Stop()
}

func (t *BucketHandleTest) TestNewReaderMethodWithCompleteRead() {
	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: TestObjectName,
			Range: &gcs.ByteRange{
				Start: uint64(0),
				Limit: uint64(len(ContentInTestObject)),
			},
		})

	AssertEq(nil, err)
	defer rc.Close()
	buf := make([]byte, len(ContentInTestObject))
	_, err = rc.Read(buf)
	AssertEq(nil, err)
	ExpectEq(string(buf[:]), ContentInTestObject)
}

func (t *BucketHandleTest) TestNewReaderMethodWithRangeRead() {
	start := uint64(2)
	limit := uint64(8)

	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: TestObjectName,
			Range: &gcs.ByteRange{
				Start: start,
				Limit: limit,
			},
		})

	AssertEq(nil, err)
	defer rc.Close()
	buf := make([]byte, limit-start)
	_, err = rc.Read(buf)
	AssertEq(nil, err)
	ExpectEq(string(buf[:]), ContentInTestObject[start:limit])
}

func (t *BucketHandleTest) TestNewReaderMethodWithInValidObject() {
	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: missingObjectName,
			Range: &gcs.ByteRange{
				Start: uint64(0),
				Limit: uint64(len(ContentInTestObject)),
			},
		})

	AssertNe(nil, err)
	AssertEq(nil, rc)
}

func (t *BucketHandleTest) TestNewReaderMethodWithValidGeneration() {
	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: TestObjectName,
			Range: &gcs.ByteRange{
				Start: uint64(0),
				Limit: uint64(len(ContentInTestObject)),
			},
			Generation: TestObjectGeneration,
		})

	AssertEq(nil, err)
	defer rc.Close()
	buf := make([]byte, len(ContentInTestObject))
	_, err = rc.Read(buf)
	AssertEq(nil, err)
	ExpectEq(string(buf[:]), ContentInTestObject)
}

func (t *BucketHandleTest) TestNewReaderMethodWithInvalidGeneration() {
	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: TestObjectName,
			Range: &gcs.ByteRange{
				Start: uint64(0),
				Limit: uint64(len(ContentInTestObject)),
			},
			Generation: 222, // other than TestObjectGeneration, doesn't exist.
		})

	AssertNe(nil, err)
	AssertEq(nil, rc)
}

func (t *BucketHandleTest) TestDeleteObjectMethodWithValidObject() {
	err := t.bucketHandle.DeleteObject(context.Background(),
		&gcs.DeleteObjectRequest{
			Name:                       TestObjectName,
			Generation:                 TestObjectGeneration,
			MetaGenerationPrecondition: nil,
		})

	AssertEq(nil, err)
}

func (t *BucketHandleTest) TestDeleteObjectMethodWithMissingObject() {
	err := t.bucketHandle.DeleteObject(context.Background(),
		&gcs.DeleteObjectRequest{
			Name:                       missingObjectName,
			Generation:                 TestObjectGeneration,
			MetaGenerationPrecondition: nil,
		})

	AssertEq("storage: object doesn't exist", err.Error())
}

func (t *BucketHandleTest) TestStatObjectMethodWithValidObject() {
	_, err := t.bucketHandle.StatObject(context.Background(),
		&gcs.StatObjectRequest{
			Name: TestObjectName,
		})

	AssertEq(nil, err)
}

func (t *BucketHandleTest) TestStatObjectMethodWithMissingObject() {
	var notfound *gcs.NotFoundError

	_, err := t.bucketHandle.StatObject(context.Background(),
		&gcs.StatObjectRequest{
			Name: missingObjectName,
		})

	AssertTrue(errors.As(err, &notfound))
}

func (t *BucketHandleTest) TestCopyObjectMethodWithValidObject() {
	_, err := t.bucketHandle.CopyObject(context.Background(),
		&gcs.CopyObjectRequest{
			SrcName:                       TestObjectName,
			DstName:                       dstObjectName,
			SrcGeneration:                 TestObjectGeneration,
			SrcMetaGenerationPrecondition: nil,
		})

	AssertEq(nil, err)
}

func (t *BucketHandleTest) TestCopyObjectMethodWithMissingObject() {
	var notfound *gcs.NotFoundError

	_, err := t.bucketHandle.CopyObject(context.Background(),
		&gcs.CopyObjectRequest{
			SrcName:                       missingObjectName,
			DstName:                       dstObjectName,
			SrcGeneration:                 TestObjectGeneration,
			SrcMetaGenerationPrecondition: nil,
		})

	AssertTrue(errors.As(err, &notfound))
}

func (t *BucketHandleTest) TestCopyObjectMethodWithInvalidGeneration() {
	var notfound *gcs.NotFoundError

	_, err := t.bucketHandle.CopyObject(context.Background(),
		&gcs.CopyObjectRequest{
			SrcName:                       TestObjectName,
			DstName:                       dstObjectName,
			SrcGeneration:                 222, // Other than testObjectGeneration, no other generation exists.
			SrcMetaGenerationPrecondition: nil,
		})

	AssertTrue(errors.As(err, &notfound))
}
<|endoftext|>