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

// Build the parser:
//go:generate go tool yacc -v y.output -o parser.go -p mtail parser.y

package vm

import (
	"fmt"
	"io"
	"path/filepath"
	"regexp"

	"github.com/google/mtail/metrics"
)

type compiler struct {
	name string // Name of the program.

	errors ErrorList         // Compile errors.
	prog   []instr           // The emitted program.
	str    []string          // Static strings.
	re     []*regexp.Regexp  // Static regular expressions.
	m      []*metrics.Metric // Metrics accessible to this program.

	decos []*decoNode // Decorator stack to unwind

	symtab *scope
}

// Compile compiles a program from the input into a virtual machine or a list
// of compile errors.  It takes the program's name and the metric store as
// additional arguments to build the virtual machine.
func Compile(name string, input io.Reader, ms *metrics.Store, compileOnly bool, syslogUseCurrentYear bool) (*VM, error) {
	name = filepath.Base(name)
	p := newParser(name, input, ms)
	r := mtailParse(p)
	if r != 0 || p == nil || p.errors != nil {
		return nil, p.errors
	}
	c := &compiler{name: name, symtab: p.s}
	c.compile(p.root)
	if len(c.errors) > 0 {
		return nil, c.errors
	}
	if compileOnly {
		return nil, nil
	}

	vm := New(name, c.re, c.str, c.m, c.prog, syslogUseCurrentYear)
	return vm, nil
}

func (c *compiler) errorf(format string, args ...interface{}) {
	e := fmt.Sprintf(format, args...)
	c.errors.Add(position{filename: c.name}, e)
}

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

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

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

	case *declNode:
		// Build the list of addressable metrics for this program, and set the symbol's address.
		n.sym.addr = len(c.m)
		c.m = append(c.m, n.sym.binding.(*metrics.Metric))

	case *condNode:
		if n.cond != nil {
			c.compile(n.cond)
		}
		// Save PC of previous jump instruction emitted by the n.cond
		// compilation.  (See regexNode and relNode cases, which will emit a
		// jump as the last instr.)  This jump will skip over the truthNode.
		pc := len(c.prog) - 1
		// Set matched flag false for children.
		c.emit(instr{setmatched, false})
		c.compile(n.truthNode)
		// Re-set matched flag to true for rest of current block.
		c.emit(instr{setmatched, true})
		// Rewrite n.cond's jump target to jump to instruction after block.
		c.prog[pc].opnd = len(c.prog)
		// Now also emit the else clause, and a jump.
		if n.elseNode != nil {
			c.emit(instr{op: jmp})
			// Rewrite jump again to avoid this else-skipper just emitted.
			c.prog[pc].opnd = len(c.prog)
			// Now get the PC of the else-skipper just emitted.
			pc = len(c.prog) - 1
			c.compile(n.elseNode)
			// Rewrite else-skipper to the next PC.
			c.prog[pc].opnd = len(c.prog)
		}

	case *regexNode:
		re, err := regexp.Compile(n.pattern)
		if err != nil {
			c.errorf("%s", err)
			return
		}
		c.re = append(c.re, re)
		// Store the location of this regular expression in the regexNode
		n.addr = len(c.re) - 1
		c.emit(instr{match, n.addr})
		c.emit(instr{op: jnm})

	case *binaryExprNode:
		c.compile(n.lhs)
		c.compile(n.rhs)
		switch n.op {
		case LT:
			c.emit(instr{cmp, -1})
			c.emit(instr{op: jnm})
		case GT:
			c.emit(instr{cmp, 1})
			c.emit(instr{op: jnm})
		case LE:
			c.emit(instr{cmp, 1})
			c.emit(instr{op: jm})
		case GE:
			c.emit(instr{cmp, -1})
			c.emit(instr{op: jm})
		case EQ:
			c.emit(instr{cmp, 0})
			c.emit(instr{op: jnm})
		case NE:
			c.emit(instr{cmp, 0})
			c.emit(instr{op: jm})
		case '+':
			c.emit(instr{op: add})
		case '-':
			c.emit(instr{op: sub})
		case '*':
			c.emit(instr{op: mul})
		case '/':
			c.emit(instr{op: div})
		case '%':
			c.emit(instr{op: mod})
		case AND:
			c.emit(instr{op: and})
		case OR:
			c.emit(instr{op: or})
		case XOR:
			c.emit(instr{op: xor})
		case ASSIGN:
			c.emit(instr{op: set})
		case ADD_ASSIGN:
			c.emit(instr{inc, 1})
		case SHL:
			c.emit(instr{op: shl})
		case SHR:
			c.emit(instr{op: shr})
		case POW:
			c.emit(instr{op: pow})
		}

	case *unaryExprNode:
		c.compile(n.lhs)
		switch n.op {
		case INC:
			c.emit(instr{op: inc})
		case NOT:
			c.emit(instr{op: not})
		}

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

	case *numericExprNode:
		if n.isint {
			c.emit(instr{push, n.i})
		} else {
			c.emit(instr{push, n.f})
		}

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

	case *idNode:
		c.emit(instr{mload, n.sym.addr})
		m := n.sym.binding.(*metrics.Metric)
		c.emit(instr{dload, len(m.Keys)})

	case *caprefNode:
		rn := n.sym.binding.(*regexNode)
		// rn.addr contains the index of the regular expression object,
		// which correlates to storage on the re heap
		c.emit(instr{push, rn.addr})
		c.emit(instr{capref, n.sym.addr})

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

	case *defNode:
		// Do nothing, defs are inlined.

	case *decoNode:
		// Put the current block on the stack
		c.decos = append(c.decos, n)
		// then iterate over the decorator's nodes
		for _, child := range n.def.children {
			c.compile(child)
		}
		// Pop the block off
		c.decos = c.decos[:len(c.decos)-1]

	case *nextNode:
		// Visit the 'next' block on the decorated block stack
		deco := c.decos[len(c.decos)-1]
		for _, child := range deco.children {
			c.compile(child)
		}

	case *otherwiseNode:
		c.emit(instr{op: otherwise})
		c.emit(instr{op: jnm})

	default:
		c.errorf("undefined node type %T (%q)6", untypedNode, untypedNode)
	}
}
<commit_msg>Update comments.<commit_after>// Copyright 2011 Google Inc. All Rights Reserved.
// This file is available under the Apache license.

// Build the parser:
//go:generate go tool yacc -v y.output -o parser.go -p mtail parser.y

package vm

import (
	"fmt"
	"io"
	"path/filepath"
	"regexp"

	"github.com/google/mtail/metrics"
)

type compiler struct {
	name string // Name of the program.

	errors ErrorList         // Compile errors.
	prog   []instr           // The emitted program.
	str    []string          // Static strings.
	re     []*regexp.Regexp  // Static regular expressions.
	m      []*metrics.Metric // Metrics accessible to this program.

	decos []*decoNode // Decorator stack to unwind

	symtab *scope
}

// Compile compiles a program from the input into a virtual machine or a list
// of compile errors.  It takes the program's name and the metric store as
// additional arguments to build the virtual machine.
func Compile(name string, input io.Reader, ms *metrics.Store, compileOnly bool, syslogUseCurrentYear bool) (*VM, error) {
	name = filepath.Base(name)
	p := newParser(name, input, ms)
	r := mtailParse(p)
	if r != 0 || p == nil || p.errors != nil {
		return nil, p.errors
	}
	c := &compiler{name: name, symtab: p.s}
	c.compile(p.root)
	if len(c.errors) > 0 {
		return nil, c.errors
	}
	if compileOnly {
		return nil, nil
	}

	vm := New(name, c.re, c.str, c.m, c.prog, syslogUseCurrentYear)
	return vm, nil
}

func (c *compiler) errorf(format string, args ...interface{}) {
	e := fmt.Sprintf(format, args...)
	c.errors.Add(position{filename: c.name}, e)
}

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

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

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

	case *declNode:
		// Build the list of addressable metrics for this program, and set the symbol's address.
		n.sym.addr = len(c.m)
		c.m = append(c.m, n.sym.binding.(*metrics.Metric))

	case *condNode:
		if n.cond != nil {
			c.compile(n.cond)
		}
		// Save PC of previous jump instruction emitted by the n.cond
		// compilation.  (See regexNode and relNode cases, which will emit a
		// jump as the last instr.)  This jump will skip over the truthNode.
		pc := len(c.prog) - 1
		// Set matched flag false for children.
		c.emit(instr{setmatched, false})
		c.compile(n.truthNode)
		// Re-set matched flag to true for rest of current block.
		c.emit(instr{setmatched, true})
		// Rewrite n.cond's jump target to jump to instruction after block.
		c.prog[pc].opnd = len(c.prog)
		// Now also emit the else clause, and a jump.
		if n.elseNode != nil {
			c.emit(instr{op: jmp})
			// Rewrite jump again to avoid this else-skipper just emitted.
			c.prog[pc].opnd = len(c.prog)
			// Now get the PC of the else-skipper just emitted.
			pc = len(c.prog) - 1
			c.compile(n.elseNode)
			// Rewrite else-skipper to the next PC.
			c.prog[pc].opnd = len(c.prog)
		}

	case *regexNode:
		re, err := regexp.Compile(n.pattern)
		if err != nil {
			c.errorf("%s", err)
			return
		}
		c.re = append(c.re, re)
		// Store the location of this regular expression in the regexNode
		n.addr = len(c.re) - 1
		c.emit(instr{match, n.addr})
		c.emit(instr{op: jnm})

	case *binaryExprNode:
		c.compile(n.lhs)
		c.compile(n.rhs)
		switch n.op {
		case LT:
			c.emit(instr{cmp, -1})
			c.emit(instr{op: jnm})
		case GT:
			c.emit(instr{cmp, 1})
			c.emit(instr{op: jnm})
		case LE:
			c.emit(instr{cmp, 1})
			c.emit(instr{op: jm})
		case GE:
			c.emit(instr{cmp, -1})
			c.emit(instr{op: jm})
		case EQ:
			c.emit(instr{cmp, 0})
			c.emit(instr{op: jnm})
		case NE:
			c.emit(instr{cmp, 0})
			c.emit(instr{op: jm})
		case '+':
			c.emit(instr{op: add})
		case '-':
			c.emit(instr{op: sub})
		case '*':
			c.emit(instr{op: mul})
		case '/':
			c.emit(instr{op: div})
		case '%':
			c.emit(instr{op: mod})
		case AND:
			c.emit(instr{op: and})
		case OR:
			c.emit(instr{op: or})
		case XOR:
			c.emit(instr{op: xor})
		case ASSIGN:
			c.emit(instr{op: set})
		case ADD_ASSIGN:
			c.emit(instr{inc, 1})
		case SHL:
			c.emit(instr{op: shl})
		case SHR:
			c.emit(instr{op: shr})
		case POW:
			c.emit(instr{op: pow})
		}

	case *unaryExprNode:
		c.compile(n.lhs)
		switch n.op {
		case INC:
			c.emit(instr{op: inc})
		case NOT:
			c.emit(instr{op: not})
		}

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

	case *numericExprNode:
		if n.isint {
			c.emit(instr{push, n.i})
		} else {
			c.emit(instr{push, n.f})
		}

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

	case *idNode:
		c.emit(instr{mload, n.sym.addr})
		m := n.sym.binding.(*metrics.Metric)
		c.emit(instr{dload, len(m.Keys)})

	case *caprefNode:
		rn := n.sym.binding.(*regexNode)
		// rn.addr contains the index of the regular expression object,
		// which correlates to storage on the re slice
		c.emit(instr{push, rn.addr})
		// n.sym.addr is the capture group offset
		c.emit(instr{capref, n.sym.addr})

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

	case *defNode:
		// Do nothing, defs are inlined.

	case *decoNode:
		// Put the current block on the stack
		c.decos = append(c.decos, n)
		// then iterate over the decorator's nodes
		for _, child := range n.def.children {
			c.compile(child)
		}
		// Pop the block off
		c.decos = c.decos[:len(c.decos)-1]

	case *nextNode:
		// Visit the 'next' block on the decorated block stack
		deco := c.decos[len(c.decos)-1]
		for _, child := range deco.children {
			c.compile(child)
		}

	case *otherwiseNode:
		c.emit(instr{op: otherwise})
		c.emit(instr{op: jnm})

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


<commit_before>// Copyright 2014 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 test

import (
	"math/rand"
	"reflect"
	"testing"
	"time"

	"github.com/google/cadvisor/info"
	"github.com/google/cadvisor/storage"
)

func buildTrace(cpu, mem []uint64, duration time.Duration) []*info.ContainerStats {
	if len(cpu) != len(mem) {
		panic("len(cpu) != len(mem)")
	}

	ret := make([]*info.ContainerStats, len(cpu))
	currentTime := time.Now()

	var cpuTotalUsage uint64 = 0
	for i, cpuUsage := range cpu {
		cpuTotalUsage += cpuUsage
		stats := new(info.ContainerStats)
		stats.Cpu = new(info.CpuStats)
		stats.Memory = new(info.MemoryStats)
		stats.Timestamp = currentTime
		currentTime = currentTime.Add(duration)

		stats.Cpu.Usage.Total = cpuTotalUsage
		stats.Cpu.Usage.User = stats.Cpu.Usage.Total
		stats.Cpu.Usage.System = 0
		stats.Cpu.Usage.PerCpu = []uint64{cpuUsage}

		stats.Memory.Usage = mem[i]

		ret[i] = stats
	}
	return ret
}

func samplesInTrace(samples []*info.ContainerStatsSample, cpuTrace, memTrace []uint64, samplePeriod time.Duration, t *testing.T) {
	for _, sample := range samples {
		if sample.Duration != samplePeriod {
			t.Errorf("sample duration is %v, not %v", sample.Duration, samplePeriod)
		}
		cpuUsage := sample.Cpu.Usage
		memUsage := sample.Memory.Usage
		found := false
		for _, u := range cpuTrace {
			if u == cpuUsage {
				found = true
				break
			}
		}
		if !found {
			t.Errorf("unable to find cpu usage %v", cpuUsage)
		}
		found = false
		for _, u := range memTrace {
			if u == memUsage {
				found = true
				break
			}
		}
		if !found {
			t.Errorf("unable to find mem usage %v", memUsage)
		}
	}
}

func StorageDriverTestSampleCpuUsage(driver storage.StorageDriver, t *testing.T) {
	defer driver.Close()
	N := 100
	cpuTrace := make([]uint64, 0, N)
	memTrace := make([]uint64, 0, N)

	// We need N+1 observations to get N samples
	for i := 0; i < N+1; i++ {
		cpuTrace = append(cpuTrace, uint64(rand.Intn(1000)))
		memTrace = append(memTrace, uint64(rand.Intn(1000)))
	}

	samplePeriod := 1 * time.Second

	ref := info.ContainerReference{
		Name: "container",
	}

	trace := buildTrace(cpuTrace, memTrace, samplePeriod)

	for _, stats := range trace {
		err := driver.AddStats(ref, stats)
		if err != nil {
			t.Fatalf("unable to add stats: %v", err)
		}
		// set the trace to someting else. The stats stored in the
		// storage should not be affected.
		stats.Cpu.Usage.Total = 0
		stats.Cpu.Usage.System = 0
		stats.Cpu.Usage.User = 0
	}

	samples, err := driver.Samples(ref.Name, N)
	if err != nil {
		t.Errorf("unable to sample stats: %v", err)
	}
	samplesInTrace(samples, cpuTrace, memTrace, samplePeriod, t)

	samples, err = driver.Samples(ref.Name, -1)
	if err != nil {
		t.Errorf("unable to sample stats: %v", err)
	}
	samplesInTrace(samples, cpuTrace, memTrace, samplePeriod, t)

	samples, err = driver.Samples(ref.Name, N-5)
	if err != nil {
		t.Errorf("unable to sample stats: %v", err)
	}
	samplesInTrace(samples, cpuTrace, memTrace, samplePeriod, t)
}

func StorageDriverTestMaxMemoryUsage(driver storage.StorageDriver, t *testing.T) {
	defer driver.Close()
	N := 100
	memTrace := make([]uint64, N)
	cpuTrace := make([]uint64, N)
	for i := 0; i < N; i++ {
		memTrace[i] = uint64(i + 1)
		cpuTrace[i] = uint64(1)
	}

	ref := info.ContainerReference{
		Name: "container",
	}

	trace := buildTrace(cpuTrace, memTrace, 1*time.Second)

	for _, stats := range trace {
		err := driver.AddStats(ref, stats)
		if err != nil {
			t.Fatalf("unable to add stats: %v", err)
		}
		// set the trace to someting else. The stats stored in the
		// storage should not be affected.
		stats.Cpu.Usage.Total = 0
		stats.Cpu.Usage.System = 0
		stats.Cpu.Usage.User = 0
		stats.Memory.Usage = 0
	}

	percentiles, err := driver.Percentiles(ref.Name, []int{50}, []int{50})
	if err != nil {
		t.Errorf("unable to call Percentiles(): %v", err)
	}
	maxUsage := uint64(N)
	if percentiles.MaxMemoryUsage != maxUsage {
		t.Fatalf("Max memory usage should be %v; received %v", maxUsage, percentiles.MaxMemoryUsage)
	}
}

func StorageDriverTestSamplesWithoutSample(driver storage.StorageDriver, t *testing.T) {
	defer driver.Close()
	trace := buildTrace(
		[]uint64{10},
		[]uint64{10},
		1*time.Second)
	ref := info.ContainerReference{
		Name: "container",
	}
	driver.AddStats(ref, trace[0])
	samples, err := driver.Samples(ref.Name, -1)
	if err != nil {
		t.Fatal(err)
	}
	if len(samples) != 0 {
		t.Errorf("There should be no sample")
	}
}

func StorageDriverTestPercentilesWithoutSample(driver storage.StorageDriver, t *testing.T) {
	defer driver.Close()
	trace := buildTrace(
		[]uint64{10},
		[]uint64{10},
		1*time.Second)
	ref := info.ContainerReference{
		Name: "container",
	}
	driver.AddStats(ref, trace[0])
	percentiles, err := driver.Percentiles(
		ref.Name,
		[]int{50},
		[]int{50},
	)
	if err != nil {
		t.Fatal(err)
	}
	if percentiles != nil {
		t.Errorf("There should be no percentiles")
	}
}

func StorageDriverTestPercentiles(driver storage.StorageDriver, t *testing.T) {
	defer driver.Close()
	N := 100
	cpuTrace := make([]uint64, N)
	memTrace := make([]uint64, N)
	for i := 1; i < N+1; i++ {
		cpuTrace[i-1] = uint64(i)
		memTrace[i-1] = uint64(i)
	}

	trace := buildTrace(cpuTrace, memTrace, 1*time.Second)

	ref := info.ContainerReference{
		Name: "container",
	}
	for _, stats := range trace {
		driver.AddStats(ref, stats)
	}
	percentages := []int{
		80,
		90,
		50,
	}
	percentiles, err := driver.Percentiles(ref.Name, percentages, percentages)
	if err != nil {
		t.Fatal(err)
	}
	for _, x := range percentiles.CpuUsagePercentiles {
		for _, y := range percentiles.CpuUsagePercentiles {
			// lower percentage, smaller value
			if x.Percentage < y.Percentage && x.Value > y.Value {
				t.Errorf("%v percent is %v; while %v percent is %v",
					x.Percentage, x.Value, y.Percentage, y.Value)
			}
		}
	}
	for _, x := range percentiles.MemoryUsagePercentiles {
		for _, y := range percentiles.MemoryUsagePercentiles {
			if x.Percentage < y.Percentage && x.Value > y.Value {
				t.Errorf("%v percent is %v; while %v percent is %v",
					x.Percentage, x.Value, y.Percentage, y.Value)
			}
		}
	}
}

func StorageDriverTestRetrievePartialRecentStats(driver storage.StorageDriver, t *testing.T) {
	defer driver.Close()
	N := 100
	memTrace := make([]uint64, N)
	cpuTrace := make([]uint64, N)
	for i := 0; i < N; i++ {
		memTrace[i] = uint64(i + 1)
		cpuTrace[i] = uint64(1)
	}

	ref := info.ContainerReference{
		Name: "container",
	}

	trace := buildTrace(cpuTrace, memTrace, 1*time.Second)

	for _, stats := range trace {
		driver.AddStats(ref, stats)
	}

	recentStats, err := driver.RecentStats(ref.Name, 10)
	if err != nil {
		t.Fatal(err)
	}

	if len(recentStats) > 10 {
		t.Fatalf("returned %v stats, not 10.", len(recentStats))
	}

	actualRecentStats := trace[len(trace)-len(recentStats):]

	for _, r := range recentStats {
		found := false
		for _, s := range actualRecentStats {
			if reflect.DeepEqual(s, r) {
				found = true
			}
		}
		if !found {
			t.Errorf("unexpected stats %+v with memory usage %v", r, r.Memory.Usage)
		}
	}
}

func StorageDriverTestRetrieveAllRecentStats(driver storage.StorageDriver, t *testing.T) {
	defer driver.Close()
	N := 100
	memTrace := make([]uint64, N)
	cpuTrace := make([]uint64, N)
	for i := 0; i < N; i++ {
		memTrace[i] = uint64(i + 1)
		cpuTrace[i] = uint64(1)
	}

	ref := info.ContainerReference{
		Name: "container",
	}

	trace := buildTrace(cpuTrace, memTrace, 1*time.Second)

	for _, stats := range trace {
		driver.AddStats(ref, stats)
	}

	recentStats, err := driver.RecentStats(ref.Name, -1)
	if err != nil {
		t.Fatal(err)
	}
	if len(recentStats) > N {
		t.Fatalf("returned %v stats, not 100.", len(recentStats))
	}

	actualRecentStats := trace[len(trace)-len(recentStats):]

	for _, r := range recentStats {
		found := false
		for _, s := range actualRecentStats {
			if reflect.DeepEqual(s, r) {
				found = true
			}
		}
		if !found {
			t.Errorf("unexpected stats %+v with memory usage %v", r, r.Memory.Usage)
		}
	}
}

func StorageDriverTestNoRecentStats(driver storage.StorageDriver, t *testing.T) {
	defer driver.Close()
	nonExistContainer := "somerandomecontainer"
	stats, _ := driver.RecentStats(nonExistContainer, -1)
	if len(stats) > 0 {
		t.Errorf("RecentStats() returns %v stats on non exist container", len(stats))
	}
}

func StorageDriverTestNoSamples(driver storage.StorageDriver, t *testing.T) {
	defer driver.Close()
	nonExistContainer := "somerandomecontainer"
	samples, _ := driver.Samples(nonExistContainer, -1)
	if len(samples) > 0 {
		t.Errorf("Samples() returns %v samples on non exist container", len(samples))
	}
}

func StorageDriverTestPercentilesWithoutStats(driver storage.StorageDriver, t *testing.T) {
	defer driver.Close()
	nonExistContainer := "somerandomecontainer"
	percentiles, _ := driver.Percentiles(nonExistContainer, []int{50, 80}, []int{50, 80})
	if percentiles == nil {
		return
	}
	if percentiles.MaxMemoryUsage != 0 {
		t.Errorf("Percentiles() reports max memory usage > 0 when there's no stats.")
	}
	for _, p := range percentiles.CpuUsagePercentiles {
		if p.Value != 0 {
			t.Errorf("Percentiles() reports cpu usage is %v when there's no stats.", p.Value)
		}
	}
	for _, p := range percentiles.MemoryUsagePercentiles {
		if p.Value != 0 {
			t.Errorf("Percentiles() reports memory usage is %v when there's no stats.", p.Value)
		}
	}
}
<commit_msg>fix typo<commit_after>// Copyright 2014 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 test

import (
	"math/rand"
	"reflect"
	"testing"
	"time"

	"github.com/google/cadvisor/info"
	"github.com/google/cadvisor/storage"
)

func buildTrace(cpu, mem []uint64, duration time.Duration) []*info.ContainerStats {
	if len(cpu) != len(mem) {
		panic("len(cpu) != len(mem)")
	}

	ret := make([]*info.ContainerStats, len(cpu))
	currentTime := time.Now()

	var cpuTotalUsage uint64 = 0
	for i, cpuUsage := range cpu {
		cpuTotalUsage += cpuUsage
		stats := new(info.ContainerStats)
		stats.Cpu = new(info.CpuStats)
		stats.Memory = new(info.MemoryStats)
		stats.Timestamp = currentTime
		currentTime = currentTime.Add(duration)

		stats.Cpu.Usage.Total = cpuTotalUsage
		stats.Cpu.Usage.User = stats.Cpu.Usage.Total
		stats.Cpu.Usage.System = 0
		stats.Cpu.Usage.PerCpu = []uint64{cpuUsage}

		stats.Memory.Usage = mem[i]

		ret[i] = stats
	}
	return ret
}

func samplesInTrace(samples []*info.ContainerStatsSample, cpuTrace, memTrace []uint64, samplePeriod time.Duration, t *testing.T) {
	for _, sample := range samples {
		if sample.Duration != samplePeriod {
			t.Errorf("sample duration is %v, not %v", sample.Duration, samplePeriod)
		}
		cpuUsage := sample.Cpu.Usage
		memUsage := sample.Memory.Usage
		found := false
		for _, u := range cpuTrace {
			if u == cpuUsage {
				found = true
				break
			}
		}
		if !found {
			t.Errorf("unable to find cpu usage %v", cpuUsage)
		}
		found = false
		for _, u := range memTrace {
			if u == memUsage {
				found = true
				break
			}
		}
		if !found {
			t.Errorf("unable to find mem usage %v", memUsage)
		}
	}
}

func StorageDriverTestSampleCpuUsage(driver storage.StorageDriver, t *testing.T) {
	defer driver.Close()
	N := 100
	cpuTrace := make([]uint64, 0, N)
	memTrace := make([]uint64, 0, N)

	// We need N+1 observations to get N samples
	for i := 0; i < N+1; i++ {
		cpuTrace = append(cpuTrace, uint64(rand.Intn(1000)))
		memTrace = append(memTrace, uint64(rand.Intn(1000)))
	}

	samplePeriod := 1 * time.Second

	ref := info.ContainerReference{
		Name: "container",
	}

	trace := buildTrace(cpuTrace, memTrace, samplePeriod)

	for _, stats := range trace {
		err := driver.AddStats(ref, stats)
		if err != nil {
			t.Fatalf("unable to add stats: %v", err)
		}
		// set the trace to something else. The stats stored in the
		// storage should not be affected.
		stats.Cpu.Usage.Total = 0
		stats.Cpu.Usage.System = 0
		stats.Cpu.Usage.User = 0
	}

	samples, err := driver.Samples(ref.Name, N)
	if err != nil {
		t.Errorf("unable to sample stats: %v", err)
	}
	samplesInTrace(samples, cpuTrace, memTrace, samplePeriod, t)

	samples, err = driver.Samples(ref.Name, -1)
	if err != nil {
		t.Errorf("unable to sample stats: %v", err)
	}
	samplesInTrace(samples, cpuTrace, memTrace, samplePeriod, t)

	samples, err = driver.Samples(ref.Name, N-5)
	if err != nil {
		t.Errorf("unable to sample stats: %v", err)
	}
	samplesInTrace(samples, cpuTrace, memTrace, samplePeriod, t)
}

func StorageDriverTestMaxMemoryUsage(driver storage.StorageDriver, t *testing.T) {
	defer driver.Close()
	N := 100
	memTrace := make([]uint64, N)
	cpuTrace := make([]uint64, N)
	for i := 0; i < N; i++ {
		memTrace[i] = uint64(i + 1)
		cpuTrace[i] = uint64(1)
	}

	ref := info.ContainerReference{
		Name: "container",
	}

	trace := buildTrace(cpuTrace, memTrace, 1*time.Second)

	for _, stats := range trace {
		err := driver.AddStats(ref, stats)
		if err != nil {
			t.Fatalf("unable to add stats: %v", err)
		}
		// set the trace to something else. The stats stored in the
		// storage should not be affected.
		stats.Cpu.Usage.Total = 0
		stats.Cpu.Usage.System = 0
		stats.Cpu.Usage.User = 0
		stats.Memory.Usage = 0
	}

	percentiles, err := driver.Percentiles(ref.Name, []int{50}, []int{50})
	if err != nil {
		t.Errorf("unable to call Percentiles(): %v", err)
	}
	maxUsage := uint64(N)
	if percentiles.MaxMemoryUsage != maxUsage {
		t.Fatalf("Max memory usage should be %v; received %v", maxUsage, percentiles.MaxMemoryUsage)
	}
}

func StorageDriverTestSamplesWithoutSample(driver storage.StorageDriver, t *testing.T) {
	defer driver.Close()
	trace := buildTrace(
		[]uint64{10},
		[]uint64{10},
		1*time.Second)
	ref := info.ContainerReference{
		Name: "container",
	}
	driver.AddStats(ref, trace[0])
	samples, err := driver.Samples(ref.Name, -1)
	if err != nil {
		t.Fatal(err)
	}
	if len(samples) != 0 {
		t.Errorf("There should be no sample")
	}
}

func StorageDriverTestPercentilesWithoutSample(driver storage.StorageDriver, t *testing.T) {
	defer driver.Close()
	trace := buildTrace(
		[]uint64{10},
		[]uint64{10},
		1*time.Second)
	ref := info.ContainerReference{
		Name: "container",
	}
	driver.AddStats(ref, trace[0])
	percentiles, err := driver.Percentiles(
		ref.Name,
		[]int{50},
		[]int{50},
	)
	if err != nil {
		t.Fatal(err)
	}
	if percentiles != nil {
		t.Errorf("There should be no percentiles")
	}
}

func StorageDriverTestPercentiles(driver storage.StorageDriver, t *testing.T) {
	defer driver.Close()
	N := 100
	cpuTrace := make([]uint64, N)
	memTrace := make([]uint64, N)
	for i := 1; i < N+1; i++ {
		cpuTrace[i-1] = uint64(i)
		memTrace[i-1] = uint64(i)
	}

	trace := buildTrace(cpuTrace, memTrace, 1*time.Second)

	ref := info.ContainerReference{
		Name: "container",
	}
	for _, stats := range trace {
		driver.AddStats(ref, stats)
	}
	percentages := []int{
		80,
		90,
		50,
	}
	percentiles, err := driver.Percentiles(ref.Name, percentages, percentages)
	if err != nil {
		t.Fatal(err)
	}
	for _, x := range percentiles.CpuUsagePercentiles {
		for _, y := range percentiles.CpuUsagePercentiles {
			// lower percentage, smaller value
			if x.Percentage < y.Percentage && x.Value > y.Value {
				t.Errorf("%v percent is %v; while %v percent is %v",
					x.Percentage, x.Value, y.Percentage, y.Value)
			}
		}
	}
	for _, x := range percentiles.MemoryUsagePercentiles {
		for _, y := range percentiles.MemoryUsagePercentiles {
			if x.Percentage < y.Percentage && x.Value > y.Value {
				t.Errorf("%v percent is %v; while %v percent is %v",
					x.Percentage, x.Value, y.Percentage, y.Value)
			}
		}
	}
}

func StorageDriverTestRetrievePartialRecentStats(driver storage.StorageDriver, t *testing.T) {
	defer driver.Close()
	N := 100
	memTrace := make([]uint64, N)
	cpuTrace := make([]uint64, N)
	for i := 0; i < N; i++ {
		memTrace[i] = uint64(i + 1)
		cpuTrace[i] = uint64(1)
	}

	ref := info.ContainerReference{
		Name: "container",
	}

	trace := buildTrace(cpuTrace, memTrace, 1*time.Second)

	for _, stats := range trace {
		driver.AddStats(ref, stats)
	}

	recentStats, err := driver.RecentStats(ref.Name, 10)
	if err != nil {
		t.Fatal(err)
	}

	if len(recentStats) > 10 {
		t.Fatalf("returned %v stats, not 10.", len(recentStats))
	}

	actualRecentStats := trace[len(trace)-len(recentStats):]

	for _, r := range recentStats {
		found := false
		for _, s := range actualRecentStats {
			if reflect.DeepEqual(s, r) {
				found = true
			}
		}
		if !found {
			t.Errorf("unexpected stats %+v with memory usage %v", r, r.Memory.Usage)
		}
	}
}

func StorageDriverTestRetrieveAllRecentStats(driver storage.StorageDriver, t *testing.T) {
	defer driver.Close()
	N := 100
	memTrace := make([]uint64, N)
	cpuTrace := make([]uint64, N)
	for i := 0; i < N; i++ {
		memTrace[i] = uint64(i + 1)
		cpuTrace[i] = uint64(1)
	}

	ref := info.ContainerReference{
		Name: "container",
	}

	trace := buildTrace(cpuTrace, memTrace, 1*time.Second)

	for _, stats := range trace {
		driver.AddStats(ref, stats)
	}

	recentStats, err := driver.RecentStats(ref.Name, -1)
	if err != nil {
		t.Fatal(err)
	}
	if len(recentStats) > N {
		t.Fatalf("returned %v stats, not 100.", len(recentStats))
	}

	actualRecentStats := trace[len(trace)-len(recentStats):]

	for _, r := range recentStats {
		found := false
		for _, s := range actualRecentStats {
			if reflect.DeepEqual(s, r) {
				found = true
			}
		}
		if !found {
			t.Errorf("unexpected stats %+v with memory usage %v", r, r.Memory.Usage)
		}
	}
}

func StorageDriverTestNoRecentStats(driver storage.StorageDriver, t *testing.T) {
	defer driver.Close()
	nonExistContainer := "somerandomecontainer"
	stats, _ := driver.RecentStats(nonExistContainer, -1)
	if len(stats) > 0 {
		t.Errorf("RecentStats() returns %v stats on non exist container", len(stats))
	}
}

func StorageDriverTestNoSamples(driver storage.StorageDriver, t *testing.T) {
	defer driver.Close()
	nonExistContainer := "somerandomecontainer"
	samples, _ := driver.Samples(nonExistContainer, -1)
	if len(samples) > 0 {
		t.Errorf("Samples() returns %v samples on non exist container", len(samples))
	}
}

func StorageDriverTestPercentilesWithoutStats(driver storage.StorageDriver, t *testing.T) {
	defer driver.Close()
	nonExistContainer := "somerandomecontainer"
	percentiles, _ := driver.Percentiles(nonExistContainer, []int{50, 80}, []int{50, 80})
	if percentiles == nil {
		return
	}
	if percentiles.MaxMemoryUsage != 0 {
		t.Errorf("Percentiles() reports max memory usage > 0 when there's no stats.")
	}
	for _, p := range percentiles.CpuUsagePercentiles {
		if p.Value != 0 {
			t.Errorf("Percentiles() reports cpu usage is %v when there's no stats.", p.Value)
		}
	}
	for _, p := range percentiles.MemoryUsagePercentiles {
		if p.Value != 0 {
			t.Errorf("Percentiles() reports memory usage is %v when there's no stats.", p.Value)
		}
	}
}
<|endoftext|>


<commit_before>package sourcegraph

import (
	"fmt"

	"sourcegraph.com/sourcegraph/vcsstore/vcsclient"

	"sourcegraph.com/sourcegraph/go-sourcegraph/router"
	"sourcegraph.com/sourcegraph/go-vcs/vcs"
)

// RepoTreeService communicates with the Sourcegraph API endpoints that
// fetch file and directory entries in repositories.
type RepoTreeService interface {
	Get(entry TreeEntrySpec, opt *RepoTreeGetOptions) (*TreeEntry, Response, error)
	Search(RepoRevSpec, *RepoTreeSearchOptions) ([]*vcs.SearchResult, Response, error)
}

type repoTreeService struct {
	client *Client
}

var _ RepoTreeService = &repoTreeService{}

type TreeEntrySpec struct {
	RepoRev RepoRevSpec
	Path    string
}

func (s *TreeEntrySpec) RouteVars() map[string]string {
	m := s.RepoRev.RouteVars()
	m["Path"] = s.Path
	return m
}

func (s TreeEntrySpec) String() string {
	return fmt.Sprintf("%v: %s (rev %q)", s.RepoRev, s.Path, s.RepoRev.Rev)
}

// TreeEntry is a file or directory in a repository, with additional feedback
// from the formatting operation (if Formatted is true in the options).
type TreeEntry struct {
	*vcsclient.TreeEntry

	*vcsclient.FileRange // only set for files

	ContentsString string `json:",omitempty"`

	// SourceCode is set when TokenizedSource is enabled in RepoTreeGetOptions.
	SourceCode *SourceCode `json:",omitempty"`

	// FormatResult is only set if this TreeEntry is a file.
	FormatResult *FormatResult `json:",omitempty"`
}

// SourceCode contains a snippet of code with linked and classed tokens,
// along with other information about the contents.
//
// This data structure is useful when one desires to take full control of
// rendering and manipulating the contents of the requested TreeEntry or snippet,
// rather than dealing with an (annotated) string or parsing text. To obtain
// this strcture in the TreeEntry, TokenizedSource must be set to "true" in the
// RepoTreeGetOptions.
type SourceCode struct {
	// Lines contains all the lines of the contained code snippet.
	Lines []*SourceCodeLine `json:",omitempty"`

	NumRefs     int
	TooManyRefs bool
}

// SourceCodeLine contains all tokens on this line along with other information
// such as byte offsets in original source.
type SourceCodeLine struct {
	// StartByte and EndByte are the start and end offsets in bytes, in the original file.
	StartByte int
	EndByte   int

	// Tokens contains any tokens that may be on this line, including whitespace. Whitespace
	// is stored as an HTML encoded "string" and token information is stored as
	// "SourceCodeToken". New lines ('\n') are not present.
	Tokens []interface{} `json:",omitempty"`
}

// SourceCodeToken contains information about a code token.
type SourceCodeToken struct {
	// Start and end byte offsets in original file.
	StartByte int `json:"-"`
	EndByte   int `json:"-"`

	// If the token is a reference URL contains the DefKey-based URLs for all the
	// definitions at this position.
	URL []string `json:",omitempty"`

	// IsDef specifies whether the token is a definition.
	IsDef bool `json:",omitempty"`

	// Class specifies the token type as per
	// [google-code-prettify](https://code.google.com/p/google-code-prettify/).
	Class string

	// Label is non-whitespace HTML encoded source code.
	Label string
}

// FormatResult contains information about and warnings from the formatting
// operation (if Formatted is true in the options).
type FormatResult struct {
	// TooManyRefs indicates that the file being formatted exceeded the maximum
	// number of refs that are linked. Only the first NumRefs refs are linked.
	TooManyRefs bool `json:",omitempty"`

	// NumRefs is the number of refs that were linked in this file. If the total
	// number of refs in the file exceeds the (server-defined) limit, NumRefs is
	// capped at the limit.
	NumRefs int

	// LineStartByteOffsets is the byte offset of each line's first
	// byte.
	LineStartByteOffsets []int
}

// RepoTreeGetOptions specifies options for (RepoTreeService).Get.
type RepoTreeGetOptions struct {
	// Formatted is whether the specified entry, if it's a file, should have its
	// Contents code-formatted using HTML.
	Formatted bool

	// HighlightStrings is a list of fixed strings that should be
	// wrapped in a  in the returned HTML. It
	// only takes effect if Formatted is true.
	HighlightStrings []string

	// TokenizedSource requests that the source code be returned as a tokenized data
	// structure rather than an (annotated) string.
	//
	// This is useful when the client wants to take full control of rendering and manipulating
	// the contents.
	TokenizedSource bool `url:",omitempty"`

	ContentsAsString bool `url:",omitempty"`

	vcsclient.GetFileOptions
}

func (s *repoTreeService) Get(entry TreeEntrySpec, opt *RepoTreeGetOptions) (*TreeEntry, Response, error) {
	url, err := s.client.URL(router.RepoTreeEntry, entry.RouteVars(), opt)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("GET", url.String(), nil)
	if err != nil {
		return nil, nil, err
	}

	var entry_ *TreeEntry
	resp, err := s.client.Do(req, &entry_)
	if err != nil {
		return nil, resp, err
	}

	return entry_, resp, nil
}

type RepoTreeSearchOptions struct {
	vcs.SearchOptions
	Formatted bool
}

func (s *repoTreeService) Search(repoRev RepoRevSpec, opt *RepoTreeSearchOptions) ([]*vcs.SearchResult, Response, error) {
	url, err := s.client.URL(router.RepoTreeSearch, repoRev.RouteVars(), opt)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("GET", url.String(), nil)
	if err != nil {
		return nil, nil, err
	}

	var res []*vcs.SearchResult
	resp, err := s.client.Do(req, &res)
	if err != nil {
		return nil, resp, err
	}

	return res, resp, nil
}

var _ RepoTreeService = &MockRepoTreeService{}
<commit_msg>Specify parameter names for RepoTreeService.Search.<commit_after>package sourcegraph

import (
	"fmt"

	"sourcegraph.com/sourcegraph/vcsstore/vcsclient"

	"sourcegraph.com/sourcegraph/go-sourcegraph/router"
	"sourcegraph.com/sourcegraph/go-vcs/vcs"
)

// RepoTreeService communicates with the Sourcegraph API endpoints that
// fetch file and directory entries in repositories.
type RepoTreeService interface {
	Get(entry TreeEntrySpec, opt *RepoTreeGetOptions) (*TreeEntry, Response, error)
	Search(rev RepoRevSpec, opt *RepoTreeSearchOptions) ([]*vcs.SearchResult, Response, error)
}

type repoTreeService struct {
	client *Client
}

var _ RepoTreeService = &repoTreeService{}

type TreeEntrySpec struct {
	RepoRev RepoRevSpec
	Path    string
}

func (s *TreeEntrySpec) RouteVars() map[string]string {
	m := s.RepoRev.RouteVars()
	m["Path"] = s.Path
	return m
}

func (s TreeEntrySpec) String() string {
	return fmt.Sprintf("%v: %s (rev %q)", s.RepoRev, s.Path, s.RepoRev.Rev)
}

// TreeEntry is a file or directory in a repository, with additional feedback
// from the formatting operation (if Formatted is true in the options).
type TreeEntry struct {
	*vcsclient.TreeEntry

	*vcsclient.FileRange // only set for files

	ContentsString string `json:",omitempty"`

	// SourceCode is set when TokenizedSource is enabled in RepoTreeGetOptions.
	SourceCode *SourceCode `json:",omitempty"`

	// FormatResult is only set if this TreeEntry is a file.
	FormatResult *FormatResult `json:",omitempty"`
}

// SourceCode contains a snippet of code with linked and classed tokens,
// along with other information about the contents.
//
// This data structure is useful when one desires to take full control of
// rendering and manipulating the contents of the requested TreeEntry or snippet,
// rather than dealing with an (annotated) string or parsing text. To obtain
// this strcture in the TreeEntry, TokenizedSource must be set to "true" in the
// RepoTreeGetOptions.
type SourceCode struct {
	// Lines contains all the lines of the contained code snippet.
	Lines []*SourceCodeLine `json:",omitempty"`

	NumRefs     int
	TooManyRefs bool
}

// SourceCodeLine contains all tokens on this line along with other information
// such as byte offsets in original source.
type SourceCodeLine struct {
	// StartByte and EndByte are the start and end offsets in bytes, in the original file.
	StartByte int
	EndByte   int

	// Tokens contains any tokens that may be on this line, including whitespace. Whitespace
	// is stored as an HTML encoded "string" and token information is stored as
	// "SourceCodeToken". New lines ('\n') are not present.
	Tokens []interface{} `json:",omitempty"`
}

// SourceCodeToken contains information about a code token.
type SourceCodeToken struct {
	// Start and end byte offsets in original file.
	StartByte int `json:"-"`
	EndByte   int `json:"-"`

	// If the token is a reference URL contains the DefKey-based URLs for all the
	// definitions at this position.
	URL []string `json:",omitempty"`

	// IsDef specifies whether the token is a definition.
	IsDef bool `json:",omitempty"`

	// Class specifies the token type as per
	// [google-code-prettify](https://code.google.com/p/google-code-prettify/).
	Class string

	// Label is non-whitespace HTML encoded source code.
	Label string
}

// FormatResult contains information about and warnings from the formatting
// operation (if Formatted is true in the options).
type FormatResult struct {
	// TooManyRefs indicates that the file being formatted exceeded the maximum
	// number of refs that are linked. Only the first NumRefs refs are linked.
	TooManyRefs bool `json:",omitempty"`

	// NumRefs is the number of refs that were linked in this file. If the total
	// number of refs in the file exceeds the (server-defined) limit, NumRefs is
	// capped at the limit.
	NumRefs int

	// LineStartByteOffsets is the byte offset of each line's first
	// byte.
	LineStartByteOffsets []int
}

// RepoTreeGetOptions specifies options for (RepoTreeService).Get.
type RepoTreeGetOptions struct {
	// Formatted is whether the specified entry, if it's a file, should have its
	// Contents code-formatted using HTML.
	Formatted bool

	// HighlightStrings is a list of fixed strings that should be
	// wrapped in a  in the returned HTML. It
	// only takes effect if Formatted is true.
	HighlightStrings []string

	// TokenizedSource requests that the source code be returned as a tokenized data
	// structure rather than an (annotated) string.
	//
	// This is useful when the client wants to take full control of rendering and manipulating
	// the contents.
	TokenizedSource bool `url:",omitempty"`

	ContentsAsString bool `url:",omitempty"`

	vcsclient.GetFileOptions
}

func (s *repoTreeService) Get(entry TreeEntrySpec, opt *RepoTreeGetOptions) (*TreeEntry, Response, error) {
	url, err := s.client.URL(router.RepoTreeEntry, entry.RouteVars(), opt)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("GET", url.String(), nil)
	if err != nil {
		return nil, nil, err
	}

	var entry_ *TreeEntry
	resp, err := s.client.Do(req, &entry_)
	if err != nil {
		return nil, resp, err
	}

	return entry_, resp, nil
}

type RepoTreeSearchOptions struct {
	vcs.SearchOptions
	Formatted bool
}

func (s *repoTreeService) Search(repoRev RepoRevSpec, opt *RepoTreeSearchOptions) ([]*vcs.SearchResult, Response, error) {
	url, err := s.client.URL(router.RepoTreeSearch, repoRev.RouteVars(), opt)
	if err != nil {
		return nil, nil, err
	}

	req, err := s.client.NewRequest("GET", url.String(), nil)
	if err != nil {
		return nil, nil, err
	}

	var res []*vcs.SearchResult
	resp, err := s.client.Do(req, &res)
	if err != nil {
		return nil, resp, err
	}

	return res, resp, nil
}

var _ RepoTreeService = &MockRepoTreeService{}
<|endoftext|>


<commit_before>package containercommands

import (
	"fmt"

	"github.com/rackspace/rack/commandoptions"
	"github.com/rackspace/rack/handler"
	"github.com/rackspace/rack/internal/github.com/codegangsta/cli"
	"github.com/rackspace/rack/internal/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/containers"
	"github.com/rackspace/rack/util"
)

var remove = cli.Command{
	Name:        "delete",
	Usage:       util.Usage(commandPrefix, "delete", "[--name <containerName> | --stdin name]"),
	Description: "Deletes a container",
	Action:      actionDelete,
	Flags:       commandoptions.CommandFlags(flagsDelete, keysDelete),
	BashComplete: func(c *cli.Context) {
		commandoptions.CompleteFlags(commandoptions.CommandFlags(flagsDelete, keysDelete))
	},
}

func flagsDelete() []cli.Flag {
	return []cli.Flag{
		cli.StringFlag{
			Name:  "name",
			Usage: "[optional; required if `stdin` isn't provided] The name of the container",
		},
		cli.BoolFlag{
			Name:  "purge",
			Usage: "[optional] If set, this command will delete all objects in the container, and then delete the container.",
		},
		cli.StringFlag{
			Name:  "stdin",
			Usage: "[optional; required if `name` isn't provided] The field being piped into STDIN. Valid values are: name",
		},
		cli.IntFlag{
			Name:  "concurrency",
			Usage: "[optional] If `purge` is provided, the amount of concurrent workers that will empty the container.",
		},
		cli.BoolFlag{
			Name:  "quiet",
			Usage: "[optional] By default, every object deleted will be outputted. If --quiet is provided, only a final summary will be outputted.",
		},
	}
}

var keysDelete = []string{}

type paramsDelete struct {
	container   string
	purge       bool
	quiet       bool
	concurrency int
}

type commandDelete handler.Command

func actionDelete(c *cli.Context) {
	command := &commandDelete{
		Ctx: &handler.Context{
			CLIContext: c,
		},
	}
	handler.Handle(command)
}

func (command *commandDelete) Context() *handler.Context {
	return command.Ctx
}

func (command *commandDelete) Keys() []string {
	return keysDelete
}

func (command *commandDelete) ServiceClientType() string {
	return serviceClientType
}

func (command *commandDelete) HandleFlags(resource *handler.Resource) error {
	resource.Params = &paramsDelete{
		purge:       command.Ctx.CLIContext.Bool("purge"),
		quiet:       command.Ctx.CLIContext.Bool("quiet"),
		concurrency: command.Ctx.CLIContext.Int("concurrency"),
	}
	return nil
}

func (command *commandDelete) HandlePipe(resource *handler.Resource, item string) error {
	resource.Params.(*paramsDelete).container = item
	return nil
}

func (command *commandDelete) HandleSingle(resource *handler.Resource) error {
	err := command.Ctx.CheckFlagsSet([]string{"name"})
	if err != nil {
		return err
	}
	resource.Params.(*paramsDelete).container = command.Ctx.CLIContext.String("name")
	return nil
}

func (command *commandDelete) Execute(resource *handler.Resource) {
	params := resource.Params.(*paramsDelete)
	containerName := params.container
	if params.purge {
		emptyParams := &handleEmptyParams{
			container:   containerName,
			quiet:       params.quiet,
			concurrency: params.concurrency,
		}
		handleEmpty(command, resource, emptyParams)
	}

	fmt.Println("Running containers.Delete")
	rawResponse := containers.Delete(command.Ctx.ServiceClient, containerName)
	if rawResponse.Err != nil {
		resource.Err = rawResponse.Err
		return
	}
	resource.Result = fmt.Sprintf("Successfully deleted container [%s]\n", containerName)
}

func (command *commandDelete) StdinField() string {
	return "name"
}
<commit_msg>remove debugging line<commit_after>package containercommands

import (
	"fmt"

	"github.com/rackspace/rack/commandoptions"
	"github.com/rackspace/rack/handler"
	"github.com/rackspace/rack/internal/github.com/codegangsta/cli"
	"github.com/rackspace/rack/internal/github.com/rackspace/gophercloud/rackspace/objectstorage/v1/containers"
	"github.com/rackspace/rack/util"
)

var remove = cli.Command{
	Name:        "delete",
	Usage:       util.Usage(commandPrefix, "delete", "[--name <containerName> | --stdin name]"),
	Description: "Deletes a container",
	Action:      actionDelete,
	Flags:       commandoptions.CommandFlags(flagsDelete, keysDelete),
	BashComplete: func(c *cli.Context) {
		commandoptions.CompleteFlags(commandoptions.CommandFlags(flagsDelete, keysDelete))
	},
}

func flagsDelete() []cli.Flag {
	return []cli.Flag{
		cli.StringFlag{
			Name:  "name",
			Usage: "[optional; required if `stdin` isn't provided] The name of the container",
		},
		cli.BoolFlag{
			Name:  "purge",
			Usage: "[optional] If set, this command will delete all objects in the container, and then delete the container.",
		},
		cli.StringFlag{
			Name:  "stdin",
			Usage: "[optional; required if `name` isn't provided] The field being piped into STDIN. Valid values are: name",
		},
		cli.IntFlag{
			Name:  "concurrency",
			Usage: "[optional] If `purge` is provided, the amount of concurrent workers that will empty the container.",
		},
		cli.BoolFlag{
			Name:  "quiet",
			Usage: "[optional] By default, every object deleted will be outputted. If --quiet is provided, only a final summary will be outputted.",
		},
	}
}

var keysDelete = []string{}

type paramsDelete struct {
	container   string
	purge       bool
	quiet       bool
	concurrency int
}

type commandDelete handler.Command

func actionDelete(c *cli.Context) {
	command := &commandDelete{
		Ctx: &handler.Context{
			CLIContext: c,
		},
	}
	handler.Handle(command)
}

func (command *commandDelete) Context() *handler.Context {
	return command.Ctx
}

func (command *commandDelete) Keys() []string {
	return keysDelete
}

func (command *commandDelete) ServiceClientType() string {
	return serviceClientType
}

func (command *commandDelete) HandleFlags(resource *handler.Resource) error {
	resource.Params = &paramsDelete{
		purge:       command.Ctx.CLIContext.Bool("purge"),
		quiet:       command.Ctx.CLIContext.Bool("quiet"),
		concurrency: command.Ctx.CLIContext.Int("concurrency"),
	}
	return nil
}

func (command *commandDelete) HandlePipe(resource *handler.Resource, item string) error {
	resource.Params.(*paramsDelete).container = item
	return nil
}

func (command *commandDelete) HandleSingle(resource *handler.Resource) error {
	err := command.Ctx.CheckFlagsSet([]string{"name"})
	if err != nil {
		return err
	}
	resource.Params.(*paramsDelete).container = command.Ctx.CLIContext.String("name")
	return nil
}

func (command *commandDelete) Execute(resource *handler.Resource) {
	params := resource.Params.(*paramsDelete)
	containerName := params.container
	if params.purge {
		emptyParams := &handleEmptyParams{
			container:   containerName,
			quiet:       params.quiet,
			concurrency: params.concurrency,
		}
		handleEmpty(command, resource, emptyParams)
	}

	rawResponse := containers.Delete(command.Ctx.ServiceClient, containerName)
	if rawResponse.Err != nil {
		resource.Err = rawResponse.Err
		return
	}
	resource.Result = fmt.Sprintf("Successfully deleted container [%s]\n", containerName)
}

func (command *commandDelete) StdinField() string {
	return "name"
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"
)

func showBoxlist(w http.ResponseWriter, token string) {
	var blp BoxListPage
	tp := "templates/box/list.html"
	blp.Default.Sidebar = BuildSidebar(BoxesActive)
	blp.Default.Pagename = "Item List"

	err := sendauthorizedHTTPRequest("GET", "box/list", token, nil, &blp.Boxes)
	if err != nil {
		blp.Default.Message = BuildMessage(errormessage, "Error creating item/list request: "+err.Error())
		showtemplate(w, tp, blp)
		return
	}
	showtemplate(w, tp, blp)
}

func showBoxAddForm(w http.ResponseWriter, token string) {
	var bap BoxAddPage
	tp := "templates/box/add.html"
	bap.Default.Sidebar = BuildSidebar(BoxesActive)
	bap.Default.Pagename = "Add Box"
	err := sendauthorizedHTTPRequest("GET", "store/list", token, nil, &bap.Stores)
	if err != nil {
		bap.Default.Message = BuildMessage(errormessage, "Error sending Box request: "+err.Error())
		showtemplate(w, tp, bap)
		return
	}
	showtemplate(w, tp, bap)
}

func saveNewBox(w http.ResponseWriter, r *http.Request, token string) {
	var bap BoxAddPage
	tp := "templates/obx/add.html"
	var bnp BoxNewPage
	tp2 := "templates/box/new.html"
	bap.Default.Sidebar = BuildSidebar(BoxesActive)
	bap.Default.Pagename = "Add Box"
	d := r.FormValue("description")
	s := r.FormValue("store")
	sid, err := strconv.Atoi(s)
	if err != nil {
		bap.Default.Message = BuildMessage(errormessage, "Error converting Store ID"+err.Error())
		showtemplate(w, tp, bap)
		return
	}

	var bo Box
	bo.Description = d
	bo.StoreID = sid

	b := new(bytes.Buffer)
	encoder := json.NewEncoder(b)
	encoder.Encode(bo)

	bnp.Default.Pagename = "New Box"
	bnp.Default.Sidebar = BuildSidebar(BoxesActive)
	err = sendauthorizedHTTPRequest("POST", "box/", token, b, &bo)
	if err != nil {
		bnp.Default.Message = BuildMessage(errormessage, "Error sending Box request: "+err.Error())
		showtemplate(w, tp2, bnp)
		return
	}

	var bx boxResponse
	err = sendauthorizedHTTPRequest("GET", "box/"+strconv.Itoa(bo.BoxID), token, nil, &bx)
	if err != nil {
		bnp.Default.Message = BuildMessage(errormessage, "Error recieving Box request: "+err.Error())
		showtemplate(w, tp2, bnp)
		return
	}

	bnp.ID = strconv.Itoa(bx.Box.Code)
	bnp.Description = bx.Box.Description
	bnp.Store = bx.Store.Name

	showtemplate(w, tp2, bnp)
}

func boxLabel(w http.ResponseWriter, r *http.Request, token string) {

	s := r.FormValue("store")
	e := r.FormValue("EAN")
	w.Header().Set("Content-type", "application/pdf")
	err := createlabel(e, s, w)
	if err != nil {
		fmt.Println(err)
	}
}

func boxHandler(w http.ResponseWriter, r *http.Request) {

	token, err := GetCookie(r, "token")
	if err != nil {
		http.Redirect(w, r, "/login", http.StatusTemporaryRedirect)
		return
	}

	a := r.FormValue("action")
	switch a {
	case "add":
		showBoxAddForm(w, token)
	case "save":
		saveNewBox(w, r, token)
	case "edit":
		showItemEditForm(w, r, token)
	case "patch":
		patchItem(w, r, token)
	case "delete":
		deleteItem(w, r, token)
	case "view":
		viewItem(w, r, token)
	case "label":
		boxLabel(w, r, token)
	case "add-fault":
		addFault(w, r, token)
	default:
		showBoxlist(w, token)
	}

}
<commit_msg>Fixing Box list heading<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"
)

func showBoxlist(w http.ResponseWriter, token string) {
	var blp BoxListPage
	tp := "templates/box/list.html"
	blp.Default.Sidebar = BuildSidebar(BoxesActive)
	blp.Default.Pagename = "Box List"

	err := sendauthorizedHTTPRequest("GET", "box/list", token, nil, &blp.Boxes)
	if err != nil {
		blp.Default.Message = BuildMessage(errormessage, "Error creating item/list request: "+err.Error())
		showtemplate(w, tp, blp)
		return
	}
	showtemplate(w, tp, blp)
}

func showBoxAddForm(w http.ResponseWriter, token string) {
	var bap BoxAddPage
	tp := "templates/box/add.html"
	bap.Default.Sidebar = BuildSidebar(BoxesActive)
	bap.Default.Pagename = "Add Box"
	err := sendauthorizedHTTPRequest("GET", "store/list", token, nil, &bap.Stores)
	if err != nil {
		bap.Default.Message = BuildMessage(errormessage, "Error sending Box request: "+err.Error())
		showtemplate(w, tp, bap)
		return
	}
	showtemplate(w, tp, bap)
}

func saveNewBox(w http.ResponseWriter, r *http.Request, token string) {
	var bap BoxAddPage
	tp := "templates/obx/add.html"
	var bnp BoxNewPage
	tp2 := "templates/box/new.html"
	bap.Default.Sidebar = BuildSidebar(BoxesActive)
	bap.Default.Pagename = "Add Box"
	d := r.FormValue("description")
	s := r.FormValue("store")
	sid, err := strconv.Atoi(s)
	if err != nil {
		bap.Default.Message = BuildMessage(errormessage, "Error converting Store ID"+err.Error())
		showtemplate(w, tp, bap)
		return
	}

	var bo Box
	bo.Description = d
	bo.StoreID = sid

	b := new(bytes.Buffer)
	encoder := json.NewEncoder(b)
	encoder.Encode(bo)

	bnp.Default.Pagename = "New Box"
	bnp.Default.Sidebar = BuildSidebar(BoxesActive)
	err = sendauthorizedHTTPRequest("POST", "box/", token, b, &bo)
	if err != nil {
		bnp.Default.Message = BuildMessage(errormessage, "Error sending Box request: "+err.Error())
		showtemplate(w, tp2, bnp)
		return
	}

	var bx boxResponse
	err = sendauthorizedHTTPRequest("GET", "box/"+strconv.Itoa(bo.BoxID), token, nil, &bx)
	if err != nil {
		bnp.Default.Message = BuildMessage(errormessage, "Error recieving Box request: "+err.Error())
		showtemplate(w, tp2, bnp)
		return
	}

	bnp.ID = strconv.Itoa(bx.Box.Code)
	bnp.Description = bx.Box.Description
	bnp.Store = bx.Store.Name

	showtemplate(w, tp2, bnp)
}

func boxLabel(w http.ResponseWriter, r *http.Request, token string) {

	s := r.FormValue("store")
	e := r.FormValue("EAN")
	w.Header().Set("Content-type", "application/pdf")
	err := createlabel(e, s, w)
	if err != nil {
		fmt.Println(err)
	}
}

func boxHandler(w http.ResponseWriter, r *http.Request) {

	token, err := GetCookie(r, "token")
	if err != nil {
		http.Redirect(w, r, "/login", http.StatusTemporaryRedirect)
		return
	}

	a := r.FormValue("action")
	switch a {
	case "add":
		showBoxAddForm(w, token)
	case "save":
		saveNewBox(w, r, token)
	case "edit":
		showItemEditForm(w, r, token)
	case "patch":
		patchItem(w, r, token)
	case "delete":
		deleteItem(w, r, token)
	case "view":
		viewItem(w, r, token)
	case "label":
		boxLabel(w, r, token)
	case "add-fault":
		addFault(w, r, token)
	default:
		showBoxlist(w, token)
	}

}
<|endoftext|>


<commit_before>// +build e2e

/*
Copyright 2019 Google LLC

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 e2e

import (
	"log"
	"os"
	"testing"

	cloudevents "github.com/cloudevents/sdk-go/v1"
	eventingtest "knative.dev/eventing/test"
	e2ehelpers "knative.dev/eventing/test/e2e/helpers"
	eventingtestlib "knative.dev/eventing/test/lib"
	"knative.dev/pkg/test/zipkin"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"knative.dev/pkg/test/logstream"

	messagingv1alpha1 "github.com/google/knative-gcp/pkg/apis/messaging/v1alpha1"
	"github.com/google/knative-gcp/test/e2e/lib"
	"github.com/google/knative-gcp/test/e2e/lib/resources"
	conformancehelpers "knative.dev/eventing/test/conformance/helpers"
)

var channelTestRunner eventingtestlib.ChannelTestRunner

func TestMain(m *testing.M) {
	eventingtest.InitializeEventingFlags()
	channelTestRunner = eventingtestlib.ChannelTestRunner{
		// ChannelFeatureMap saves the channel-features mapping.
		// Each pair means the channel support the given list of features.
		ChannelFeatureMap: map[metav1.TypeMeta][]eventingtestlib.Feature{
			{
				APIVersion: resources.MessagingAPIVersion,
				Kind:       "Channel",
			}: {
				eventingtestlib.FeatureBasic,
				eventingtestlib.FeatureRedelivery,
				eventingtestlib.FeaturePersistence,
			},
		},
		ChannelsToTest: eventingtest.EventingFlags.Channels,
	}

	// Any tests may SetupZipkinTracing, it will only actually be done once. This should be the ONLY
	// place that cleans it up. If an individual test calls this instead, then it will break other
	// tests that need the tracing in place.
	defer zipkin.CleanupZipkinTracingSetup(log.Printf)

	os.Exit(m.Run())
}

// All e2e tests go below:

// TestSmoke makes sure we can run tests.
func TestSmokeChannel(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	SmokeTestChannelImpl(t)
}

func TestSingleBinaryEventForChannel(t *testing.T) {
	t.Skip("Skipping until https://github.com/google/knative-gcp/issues/486 is fixed.")
	cancel := logstream.Start(t)
	defer cancel()
	e2ehelpers.SingleEventForChannelTestHelper(t, cloudevents.Binary, "v1alpha1", channelTestRunner, lib.DuplicatePubSubSecret)
}

func TestSingleStructuredEventForChannel(t *testing.T) {
	t.Skip("Skipping until https://github.com/google/knative-gcp/issues/486 is fixed.")
	cancel := logstream.Start(t)
	defer cancel()
	e2ehelpers.SingleEventForChannelTestHelper(t, cloudevents.Structured, "v1alpha1", channelTestRunner, lib.DuplicatePubSubSecret)
}

func TestChannelClusterDefaulter(t *testing.T) {
	t.Skip("Skipping until https://github.com/knative/eventing-contrib/issues/627 is fixed")
	cancel := logstream.Start(t)
	defer cancel()
	e2ehelpers.ChannelClusterDefaulterTestHelper(t, channelTestRunner, lib.DuplicatePubSubSecret)
}

func TestChannelNamespaceDefaulter(t *testing.T) {
	t.Skip("Skipping until https://github.com/knative/eventing-contrib/issues/627 is fixed")
	cancel := logstream.Start(t)
	defer cancel()
	e2ehelpers.ChannelNamespaceDefaulterTestHelper(t, channelTestRunner, lib.DuplicatePubSubSecret)
}

func TestEventTransformationForSubscription(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	e2ehelpers.EventTransformationForSubscriptionTestHelper(t, channelTestRunner, lib.DuplicatePubSubSecret)
}

func TestChannelChain(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	e2ehelpers.ChannelChainTestHelper(t, channelTestRunner, lib.DuplicatePubSubSecret)
}

func TestEventTransformationForTrigger(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	e2ehelpers.EventTransformationForTriggerTestHelper(t, "ChannelBasedBroker" /*brokerClass*/, channelTestRunner, lib.DuplicatePubSubSecret)
}

func TestBrokerChannelFlow(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	e2ehelpers.BrokerChannelFlowTestHelper(t, "ChannelBasedBroker" /*brokerClass*/, channelTestRunner, lib.DuplicatePubSubSecret)
}

func TestChannelDeadLetterSink(t *testing.T) {
	t.Skip("Skipping until https://github.com/google/knative-gcp/issues/485 is fixed.")
	cancel := logstream.Start(t)
	defer cancel()
	e2ehelpers.ChannelDeadLetterSinkTestHelper(t, channelTestRunner, lib.DuplicatePubSubSecret)
}

func TestBrokerDeadLetterSink(t *testing.T) {
	t.Skip("Skipping until https://github.com/google/knative-gcp/issues/485 is fixed.")
	cancel := logstream.Start(t)
	defer cancel()
	e2ehelpers.BrokerDeadLetterSinkTestHelper(t, "ChannelBasedBroker" /*brokerClass*/, channelTestRunner, lib.DuplicatePubSubSecret)
}

func TestBrokerTracing(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	conformancehelpers.BrokerTracingTestHelperWithChannelTestRunner(
		t, "ChannelBasedBroker", channelTestRunner,
		func(client *eventingtestlib.Client) {
			lib.DuplicatePubSubSecret(client)
			lib.SetTracingToZipkin(client)
		},
	)
}

func TestChannelTracing(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	conformancehelpers.ChannelTracingTestHelper(t, metav1.TypeMeta{
		APIVersion: messagingv1alpha1.SchemeGroupVersion.String(),
		Kind:       "Channel",
	}, func(client *eventingtestlib.Client) {
		// This test is running based on code in knative/eventing, so it does not use the same
		// Client that tests in this repo use. Therefore, we need to duplicate the logic from this
		// repo's Setup() here. See test/e2e/lifecycle.go's Setup() for the function used in this
		// repo whose functionality we need to copy here.

		// Copy the secret from the default namespace to the namespace used in the test.
		lib.DuplicatePubSubSecret(client)
		lib.SetTracingToZipkin(client)
	})
}

// TestSmokePullSubscription makes sure we can run tests on PullSubscriptions.
func TestSmokePullSubscription(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	SmokePullSubscriptionTestImpl(t)
}

// TestPullSubscriptionWithTarget tests we can knock down a target.
func TestPullSubscriptionWithTarget(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	PullSubscriptionWithTargetTestImpl(t)
}

// TestSmokeCloudPubSubSource makes sure we can run tests on the CloudPubSubSource.
func TestSmokeCloudPubSubSource(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	SmokeCloudPubSubSourceTestImpl(t)
}

// TestCloudPubSubSourceWithTarget tests we can knock down a target from a CloudPubSubSource.
func TestCloudPubSubSourceWithTarget(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	CloudPubSubSourceWithTargetTestImpl(t, false /*assertMetrics */)
}

// TestCloudPubSubSourceStackDriverMetrics tests we can knock down a target from a CloudPubSubSource and that we send metrics to StackDriver.
func TestCloudPubSubSourceStackDriverMetrics(t *testing.T) {
	t.Skip("See issues https://github.com/google/knative-gcp/issues/317 and https://github.com/cloudevents/sdk-go/pull/234")
	cancel := logstream.Start(t)
	defer cancel()
	CloudPubSubSourceWithTargetTestImpl(t, true /*assertMetrics */)
}

// TestBrokerWithPubSubChannel tests we can knock a Knative Service from a broker with PubSub Channel.
func TestBrokerWithPubSubChannel(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	BrokerWithPubSubChannelTestImpl(t)
}

// TestCloudPubSubSourceBrokerWithPubSubChannel tests we can knock a Knative Service from a broker with PubSub Channel from a CloudPubSubSource.
func TestCloudPubSubSourceBrokerWithPubSubChannel(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	PubSubSourceBrokerWithPubSubChannelTestImpl(t)
}

// TestCloudStorageSourceBrokerWithPubSubChannel tests we can knock a Knative Service from a broker with PubSub Channel from a CloudStorageSource.
func TestCloudStorageSourceBrokerWithPubSubChannel(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	StorageSourceBrokerWithPubSubChannelTestImpl(t)
}

// TestCloudAuditLogsSourceBrokerWithPubSubChannel tests we can knock a Knative Service from a broker with PubSub Channel from a CloudAuditLogsSource.
func TestCloudAuditLogsSourceBrokerWithPubSubChannel(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	AuditLogsSourceBrokerWithPubSubChannelTestImpl(t)
}

// TestCloudSchedulerSourceBrokerWithPubSubChannel tests we can knock a Knative Service from a broker with PubSub Channel from a CloudSchedulerSource.
func TestCloudSchedulerSourceBrokerWithPubSubChannel(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	SchedulerSourceBrokerWithPubSubChannelTestImpl(t)
}

// TestCloudStorageSource tests we can knock down a target from a CloudStorageSource.
func TestCloudStorageSource(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	CloudStorageSourceWithTestImpl(t, false /*assertMetrics */)
}

// TestCloudStorageSourceStackDriverMetrics tests we can knock down a target from a CloudStorageSource and that we send metrics to StackDriver.
func TestCloudStorageSourceStackDriverMetrics(t *testing.T) {
	t.Skip("See issue https://github.com/google/knative-gcp/issues/317")
	cancel := logstream.Start(t)
	defer cancel()
	CloudStorageSourceWithTestImpl(t, true /*assertMetrics */)
}

// TestCloudAuditLogsSource tests we can knock down a target from an CloudAuditLogsSource.
func TestCloudAuditLogsSource(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	CloudAuditLogsSourceWithTestImpl(t)
}

// TestSmokeCloudSchedulerSourceSetup tests if we can create a CloudSchedulerSource resource and get it to a ready state.
func TestSmokeCloudSchedulerSourceSetup(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	SmokeCloudSchedulerSourceSetup(t)
}

// TestCloudSchedulerSourceWithTargetTestImpl tests if we can receive an event on a bespoke sink from a CloudSchedulerSource source.
func TestCloudSchedulerSourceWithTargetTestImpl(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	CloudSchedulerSourceWithTargetTestImpl(t)
}
<commit_msg>Ensure that e2e test cleanup functions are run (#783)<commit_after>// +build e2e

/*
Copyright 2019 Google LLC

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 e2e

import (
	"log"
	"os"
	"testing"

	cloudevents "github.com/cloudevents/sdk-go/v1"
	eventingtest "knative.dev/eventing/test"
	e2ehelpers "knative.dev/eventing/test/e2e/helpers"
	eventingtestlib "knative.dev/eventing/test/lib"
	"knative.dev/pkg/test/zipkin"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"knative.dev/pkg/test/logstream"

	messagingv1alpha1 "github.com/google/knative-gcp/pkg/apis/messaging/v1alpha1"
	"github.com/google/knative-gcp/test/e2e/lib"
	"github.com/google/knative-gcp/test/e2e/lib/resources"
	conformancehelpers "knative.dev/eventing/test/conformance/helpers"
)

var channelTestRunner eventingtestlib.ChannelTestRunner

func TestMain(m *testing.M) {
	os.Exit(func() int {
		eventingtest.InitializeEventingFlags()
		channelTestRunner = eventingtestlib.ChannelTestRunner{
			// ChannelFeatureMap saves the channel-features mapping.
			// Each pair means the channel support the given list of features.
			ChannelFeatureMap: map[metav1.TypeMeta][]eventingtestlib.Feature{
				{
					APIVersion: resources.MessagingAPIVersion,
					Kind:       "Channel",
				}: {
					eventingtestlib.FeatureBasic,
					eventingtestlib.FeatureRedelivery,
					eventingtestlib.FeaturePersistence,
				},
			},
			ChannelsToTest: eventingtest.EventingFlags.Channels,
		}

		// Any tests may SetupZipkinTracing, it will only actually be done once. This should be the ONLY
		// place that cleans it up. If an individual test calls this instead, then it will break other
		// tests that need the tracing in place.
		defer zipkin.CleanupZipkinTracingSetup(log.Printf)

		return m.Run()
	}())
}

// All e2e tests go below:

// TestSmoke makes sure we can run tests.
func TestSmokeChannel(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	SmokeTestChannelImpl(t)
}

func TestSingleBinaryEventForChannel(t *testing.T) {
	t.Skip("Skipping until https://github.com/google/knative-gcp/issues/486 is fixed.")
	cancel := logstream.Start(t)
	defer cancel()
	e2ehelpers.SingleEventForChannelTestHelper(t, cloudevents.Binary, "v1alpha1", channelTestRunner, lib.DuplicatePubSubSecret)
}

func TestSingleStructuredEventForChannel(t *testing.T) {
	t.Skip("Skipping until https://github.com/google/knative-gcp/issues/486 is fixed.")
	cancel := logstream.Start(t)
	defer cancel()
	e2ehelpers.SingleEventForChannelTestHelper(t, cloudevents.Structured, "v1alpha1", channelTestRunner, lib.DuplicatePubSubSecret)
}

func TestChannelClusterDefaulter(t *testing.T) {
	t.Skip("Skipping until https://github.com/knative/eventing-contrib/issues/627 is fixed")
	cancel := logstream.Start(t)
	defer cancel()
	e2ehelpers.ChannelClusterDefaulterTestHelper(t, channelTestRunner, lib.DuplicatePubSubSecret)
}

func TestChannelNamespaceDefaulter(t *testing.T) {
	t.Skip("Skipping until https://github.com/knative/eventing-contrib/issues/627 is fixed")
	cancel := logstream.Start(t)
	defer cancel()
	e2ehelpers.ChannelNamespaceDefaulterTestHelper(t, channelTestRunner, lib.DuplicatePubSubSecret)
}

func TestEventTransformationForSubscription(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	e2ehelpers.EventTransformationForSubscriptionTestHelper(t, channelTestRunner, lib.DuplicatePubSubSecret)
}

func TestChannelChain(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	e2ehelpers.ChannelChainTestHelper(t, channelTestRunner, lib.DuplicatePubSubSecret)
}

func TestEventTransformationForTrigger(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	e2ehelpers.EventTransformationForTriggerTestHelper(t, "ChannelBasedBroker" /*brokerClass*/, channelTestRunner, lib.DuplicatePubSubSecret)
}

func TestBrokerChannelFlow(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	e2ehelpers.BrokerChannelFlowTestHelper(t, "ChannelBasedBroker" /*brokerClass*/, channelTestRunner, lib.DuplicatePubSubSecret)
}

func TestChannelDeadLetterSink(t *testing.T) {
	t.Skip("Skipping until https://github.com/google/knative-gcp/issues/485 is fixed.")
	cancel := logstream.Start(t)
	defer cancel()
	e2ehelpers.ChannelDeadLetterSinkTestHelper(t, channelTestRunner, lib.DuplicatePubSubSecret)
}

func TestBrokerDeadLetterSink(t *testing.T) {
	t.Skip("Skipping until https://github.com/google/knative-gcp/issues/485 is fixed.")
	cancel := logstream.Start(t)
	defer cancel()
	e2ehelpers.BrokerDeadLetterSinkTestHelper(t, "ChannelBasedBroker" /*brokerClass*/, channelTestRunner, lib.DuplicatePubSubSecret)
}

func TestBrokerTracing(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	conformancehelpers.BrokerTracingTestHelperWithChannelTestRunner(
		t, "ChannelBasedBroker", channelTestRunner,
		func(client *eventingtestlib.Client) {
			lib.DuplicatePubSubSecret(client)
			lib.SetTracingToZipkin(client)
		},
	)
}

func TestChannelTracing(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	conformancehelpers.ChannelTracingTestHelper(t, metav1.TypeMeta{
		APIVersion: messagingv1alpha1.SchemeGroupVersion.String(),
		Kind:       "Channel",
	}, func(client *eventingtestlib.Client) {
		// This test is running based on code in knative/eventing, so it does not use the same
		// Client that tests in this repo use. Therefore, we need to duplicate the logic from this
		// repo's Setup() here. See test/e2e/lifecycle.go's Setup() for the function used in this
		// repo whose functionality we need to copy here.

		// Copy the secret from the default namespace to the namespace used in the test.
		lib.DuplicatePubSubSecret(client)
		lib.SetTracingToZipkin(client)
	})
}

// TestSmokePullSubscription makes sure we can run tests on PullSubscriptions.
func TestSmokePullSubscription(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	SmokePullSubscriptionTestImpl(t)
}

// TestPullSubscriptionWithTarget tests we can knock down a target.
func TestPullSubscriptionWithTarget(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	PullSubscriptionWithTargetTestImpl(t)
}

// TestSmokeCloudPubSubSource makes sure we can run tests on the CloudPubSubSource.
func TestSmokeCloudPubSubSource(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	SmokeCloudPubSubSourceTestImpl(t)
}

// TestCloudPubSubSourceWithTarget tests we can knock down a target from a CloudPubSubSource.
func TestCloudPubSubSourceWithTarget(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	CloudPubSubSourceWithTargetTestImpl(t, false /*assertMetrics */)
}

// TestCloudPubSubSourceStackDriverMetrics tests we can knock down a target from a CloudPubSubSource and that we send metrics to StackDriver.
func TestCloudPubSubSourceStackDriverMetrics(t *testing.T) {
	t.Skip("See issues https://github.com/google/knative-gcp/issues/317 and https://github.com/cloudevents/sdk-go/pull/234")
	cancel := logstream.Start(t)
	defer cancel()
	CloudPubSubSourceWithTargetTestImpl(t, true /*assertMetrics */)
}

// TestBrokerWithPubSubChannel tests we can knock a Knative Service from a broker with PubSub Channel.
func TestBrokerWithPubSubChannel(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	BrokerWithPubSubChannelTestImpl(t)
}

// TestCloudPubSubSourceBrokerWithPubSubChannel tests we can knock a Knative Service from a broker with PubSub Channel from a CloudPubSubSource.
func TestCloudPubSubSourceBrokerWithPubSubChannel(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	PubSubSourceBrokerWithPubSubChannelTestImpl(t)
}

// TestCloudStorageSourceBrokerWithPubSubChannel tests we can knock a Knative Service from a broker with PubSub Channel from a CloudStorageSource.
func TestCloudStorageSourceBrokerWithPubSubChannel(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	StorageSourceBrokerWithPubSubChannelTestImpl(t)
}

// TestCloudAuditLogsSourceBrokerWithPubSubChannel tests we can knock a Knative Service from a broker with PubSub Channel from a CloudAuditLogsSource.
func TestCloudAuditLogsSourceBrokerWithPubSubChannel(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	AuditLogsSourceBrokerWithPubSubChannelTestImpl(t)
}

// TestCloudSchedulerSourceBrokerWithPubSubChannel tests we can knock a Knative Service from a broker with PubSub Channel from a CloudSchedulerSource.
func TestCloudSchedulerSourceBrokerWithPubSubChannel(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	SchedulerSourceBrokerWithPubSubChannelTestImpl(t)
}

// TestCloudStorageSource tests we can knock down a target from a CloudStorageSource.
func TestCloudStorageSource(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	CloudStorageSourceWithTestImpl(t, false /*assertMetrics */)
}

// TestCloudStorageSourceStackDriverMetrics tests we can knock down a target from a CloudStorageSource and that we send metrics to StackDriver.
func TestCloudStorageSourceStackDriverMetrics(t *testing.T) {
	t.Skip("See issue https://github.com/google/knative-gcp/issues/317")
	cancel := logstream.Start(t)
	defer cancel()
	CloudStorageSourceWithTestImpl(t, true /*assertMetrics */)
}

// TestCloudAuditLogsSource tests we can knock down a target from an CloudAuditLogsSource.
func TestCloudAuditLogsSource(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	CloudAuditLogsSourceWithTestImpl(t)
}

// TestSmokeCloudSchedulerSourceSetup tests if we can create a CloudSchedulerSource resource and get it to a ready state.
func TestSmokeCloudSchedulerSourceSetup(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	SmokeCloudSchedulerSourceSetup(t)
}

// TestCloudSchedulerSourceWithTargetTestImpl tests if we can receive an event on a bespoke sink from a CloudSchedulerSource source.
func TestCloudSchedulerSourceWithTargetTestImpl(t *testing.T) {
	cancel := logstream.Start(t)
	defer cancel()
	CloudSchedulerSourceWithTargetTestImpl(t)
}
<|endoftext|>


<commit_before>package main

// TODO: Make this less bad, all of it

import (
	"github.com/boltdb/bolt"
)

type Database struct {
	db *bolt.DB
}

func NewDatabase() *Database {
	db, err := bolt.Open("mirror.db", 0600, nil)
	if err != nil {
		log.Fatal(err)
	}

	return &Database{db}
}

func (d *Database) Path() string {
	return d.db.Path()
}

func (d *Database) Close() {
	d.db.Close()
}

func (d *Database) StoreMirror(downstreamID int, upstreamID int) error {

	// Store the upstream->downstream id
	d.db.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte("up2down"))
		err := b.Put([]byte(upstreamID), []byte(downstreamID))
		return err
	})

	// Store the upstream->downstream id
	d.db.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte("down2up"))
		err := b.Put([]byte(downstreamID), []byte(upstreamID))
		return err
	})

	return nil
}

func (d *Database) GetDownstreamID(upstreamID int) []byte {
	var retval = []byte{0}
	d.db.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte("up2down"))
		v := b.Get([]byte(upstreamID))
		copy(retval, v)
		return nil
	})
	return retval
}

func (d *Database) GetUpstreamID(downstreamID int) []byte {
	var retval = []byte{0}
	d.db.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte("down2up"))
		v := b.Get([]byte(downstreamID))
		copy(retval, v)
		return nil
	})
	return retval
}
<commit_msg>Do it properly damn it Merge branch 'master' of https://github.com/HippieStation/PRMirror<commit_after>package main

// TODO: Make this less bad, all of it

import (
	"bytes"
	"encoding/binary"

	"github.com/boltdb/bolt"
)

type Database struct {
	db *bolt.DB
}

func NewDatabase() *Database {
	db, err := bolt.Open("mirror.db", 0600, nil)
	if err != nil {
		log.Fatal(err)
	}

	return &Database{db}
}

func (d *Database) Path() string {
	return d.db.Path()
}

func (d *Database) Close() {
	d.db.Close()
}

func (d *Database) IntToByteArray(intIn int) []byte {
	buf := new(bytes.Buffer)
	err := binary.Write(buf, binary.LittleEndian, intIn)
	if err != nil {
		panic(err)
	}
	return buf.Bytes()
}

func (d *Database) StoreMirror(downstreamID int, upstreamID int) error {
	downstreamIDBytes := d.IntToByteArray(downstreamID)
	upstreamIDBytes := d.IntToByteArray(upstreamID)

	// Store the upstream->downstream id
	d.db.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte("up2down"))
		err := b.Put(upstreamIDBytes, downstreamIDBytes)
		return err
	})

	// Store the upstream->downstream id
	d.db.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte("down2up"))
		err := b.Put(downstreamIDBytes, upstreamIDBytes)
		return err
	})

	return nil
}

func (d *Database) GetDownstreamID(upstreamID int) []byte {
	upstreamIDBytes := d.IntToByteArray(upstreamID)

	var retval = []byte{0}
	d.db.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte("up2down"))
		v := b.Get(upstreamIDBytes)
		copy(retval, v)
		return nil
	})
	return retval
}

func (d *Database) GetUpstreamID(downstreamID int) []byte {
	downstreamIDBytes := d.IntToByteArray(downstreamID)

	var retval = []byte{0}
	d.db.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte("down2up"))
		v := b.Get(downstreamIDBytes)
		copy(retval, v)
		return nil
	})
	return retval
}
<|endoftext|>


<commit_before>// Package GobDB implements a persistant key-value store of
// gob-compatible types. This is accomplished with a light
// wrapper around leveldb and Go's gob encoding library.
package GobDB

import (
	"github.com/syndtr/goleveldb/leveldb"
	"github.com/syndtr/goleveldb/leveldb/util"
	"strconv"
)

// DB is a LevelDB wrapper that stores key-value pairs of
// gob-compatible types.
type DB struct {
	internal *leveldb.DB
	location string
	encoder  FilteredEncoder
	decoder  Decoder
	prepared bool
}

// At returns an unopened database at with given datafile.
func At(path string) *DB {
	return &DB{location: path}
}

// Open sets up the internal leveldb if not done already.
func (db *DB) Open() error {
	if db.IsOpen() {
		return nil
	}

	ret, err := leveldb.OpenFile(db.location, nil)
	if err == nil {
		db.internal = ret
		db.prepare()
	}
	return err
}

// IsOpen checks whether or not the database is open.
func (db DB) IsOpen() bool {
	return db.internal != nil
}

// Close tears down the internal leveldb, writing all contents
// to file.
func (db *DB) Close() {
	if db.IsOpen() {
		db.internal.Close()
		db.internal = nil
	}
}

// Put encodes given key and value through gob, inserting resulting
// byte slices into the database's internal leveldb.
func (db *DB) Put(key, value interface{}) error {
	// Encode key via gob, registering types if necessary.
	o1, err := db.encode(key)
	if err != nil {
		return err
	}

	// Form prefixed key.
	pkey := []byte("key:")
	pkey = append(pkey, o1...)

	// Encode value via gob, registering types if necessary.
	val, err := db.encode(value)
	if err != nil {
		return err
	}

	// Insert gobbed values into leveldb.
	return db.internal.Put(pkey, val, nil)
}

// Get ncodes given key via gob, fetches the corresponding
// value from within leveldb, and decodes that value into
// parameter two.
func (db *DB) Get(key, value interface{}) error {
	// Encode key via gob, registering its type if necessary.
	obj, err := db.encode(key)
	if err != nil {
		return err
	}

	// Form prefixed key.
	pkey := []byte("key:")
	pkey = append(pkey, obj...)

	// Fetch gob-encoded value.
	val, err := db.internal.Get(pkey, nil)
	if err != nil {
		return err
	}

	// Decode value into second paramater (which should be a
	// pointer)
	return db.decoder.Decode(val, value)
}

// Has encodes given key via gob and checks if the resulting
// byte slice exists in the database's internal leveldb.
func (db DB) Has(key interface{}) bool {
	// Encode key via gob, registering its type if necessary.
	obj, err := db.encode(key)
	if err != nil {
		return false
	}

	// Note: this is niave - should check error type.
	_, err = db.internal.Get(obj, nil)
	return err == nil
}

// Delete encodes given key via gob, deleting the resulting
// byte slice from the database's internal leveldb.
func (db *DB) Delete(key interface{}) error {
	// Encode key via gob, registering its type if necessary.
	obj, err := db.encode(key)
	if err != nil {
		return err
	}

	// Form key bytes.
	kbytes := []byte("key:")
	kbytes = append(kbytes, obj...)

	// Delete!
	return db.internal.Delete(kbytes, nil)
}

// Entries counts key-value pairs in the database.
func (db *DB) Entries() int {
	i := 0
	iter := db.internal.NewIterator(util.BytesPrefix([]byte("key:")), nil)
	for iter.Next() {
		i++
	}
	iter.Release()
	return i
}

// Reset erases caches and closes leveldb. This way, the db
// is forced to reload gobbed values as though it had just
// been opened for the first time.
func (db *DB) Reset() {
	db.Close()
	db.prepared = false
}

// PutRaw operates identically to the origal leveldb.Put
// method. No gob encodings are performed.
func (db *DB) PutRaw(key, value []byte) error {
	kbytes := []byte("raw:")
	kbytes = append(kbytes, key...)
	return db.internal.Put(kbytes, value, nil)
}

// GetRaw operates identically to the origal leveldb.Get
// method. No gob encodings are performed.
func (db *DB) GetRaw(key []byte) ([]byte, error) {
	kbytes := []byte("raw:")
	kbytes = append(kbytes, key...)
	return db.internal.Get(kbytes, nil)
}

// DeleteRaw operates identically to the origal leveldb.Delete
// method. No gob encodings are performed.
func (db *DB) DeleteRaw(key []byte) error {
	kbytes := []byte("raw:")
	kbytes = append(kbytes, key...)
	return db.internal.Delete(kbytes, nil)
}

// Encodes given key via gob, registers its type if necessary,
// and routes any errors outward.
func (db *DB) encode(key interface{}) ([]byte, error) {
	err := db.Open()
	if err != nil {
		return []byte{}, err
	}

	// Gob encode key.
	def, obj, err := db.encoder.Encode(key)
	if err != nil {
		return []byte{}, err
	}

	// Register key with decoder.
	db.decoder.Register(append(def, obj...))

	// Register key type.
	err = db.registerType(def, obj)
	if err != nil {
		return []byte{}, err
	}

	// err = db.decoder.Decode(append(def, obj...), nil)
	// if err != nil {
	// 	return []byte{}, err
	// }

	return obj, nil
}

// When the database is opened for the first time, scrolls through
// all entries to form the same encoder that was used before the
// previous db.Close() call.
//
// Note that this is an expensive operation, scaling linearly with
// dataset size. Accordingly, you should utilize the open and close
// methods instead of initializing new DB objects all the time. For
// each initialization, the decoder is literally thrown in the
// garbage.
func (db *DB) prepare() error {
	if db.prepared == true {
		return nil
	}

	iter := db.internal.NewIterator(util.BytesPrefix([]byte("prep#")), nil)
	for iter.Next() {
		value := iter.Value()
		db.encoder.Encode(value)
		db.decoder.Register(value)
	}
	iter.Release()
	err := iter.Error()
	if err == nil {
		db.prepared = true
	}
	return err
}

func (db *DB) setPrepCount(value int) error {
	key := []byte("prep-count")
	data := []byte(strconv.Itoa(value))
	return db.internal.Put(key, data, nil)
}

func (db *DB) incPrepCount(i int) error {
	size := db.prepCount()
	if size == -1 {
		return db.setPrepCount(1)
	}
	return db.setPrepCount(size + i)
}

func (db *DB) prepCount() int {
	err := db.Open()
	if err != nil {
		return -1
	}

	val, err := db.internal.Get([]byte("prep-count"), nil)
	if err != nil {
		return 0
	}
	n, _ := strconv.Atoi(string(val))
	return n
}

// Checks if definition is present in current db.
func (db *DB) isPresent(def []byte) bool {
	err := db.Open()
	if err != nil {
		return false
	}

	key := []byte("prep:")
	key = append(key, def...)
	_, err = db.internal.Get(key, nil)
	return err == nil
}

// If not done already, registers type and example object in both
// the encoder and decoder.
func (db *DB) registerType(def, obj []byte) error {
	// Ensure that database is open.
	err := db.Open()
	if err != nil {
		return err
	}

	// Stop if type is already registered in database.
	if db.isPresent(def) {
		return nil
	}

	// Map prep#<n> to type definition bytes.
	k1 := []byte("prep#" + strconv.Itoa(db.prepCount()))
	err = db.incPrepCount(1)
	if err != nil {
		return err
	}
	v1 := []byte{}
	v1 = append(v1, def...)
	v1 = append(v1, obj...)
	err = db.internal.Put(k1, v1, nil)
	if err != nil {
		return err
	}

	// Map prep:<def> to empty string (for checking duplicate keys).
	k2 := []byte("prep:")
	k2 = append(k2, def...)
	v2 := []byte("")
	err = db.internal.Put(k2, v2, nil)
	if err != nil {
		db.internal.Delete(k1, nil)
		db.incPrepCount(-1)
		return err
	}
	return nil
}
<commit_msg>Prefixed all leveldb entries with "GobDB:". This way, clients may utilize leveldb directly without interference.<commit_after>// Package GobDB implements a persistant key-value store of
// gob-compatible types. This is accomplished with a light
// wrapper around leveldb and Go's gob encoding library.
package GobDB

import (
	"github.com/syndtr/goleveldb/leveldb"
	"github.com/syndtr/goleveldb/leveldb/util"
	"strconv"
)

// DB is a LevelDB wrapper that stores key-value pairs of
// gob-compatible types.
type DB struct {
	internal *leveldb.DB
	location string
	encoder  FilteredEncoder
	decoder  Decoder
	prepared bool
}

// At returns an unopened database at with given datafile.
func At(path string) *DB {
	return &DB{location: path}
}

// Open sets up the internal leveldb if not done already.
func (db *DB) Open() error {
	if db.IsOpen() {
		return nil
	}

	ret, err := leveldb.OpenFile(db.location, nil)
	if err == nil {
		db.internal = ret
		db.prepare()
	}
	return err
}

// IsOpen checks whether or not the database is open.
func (db DB) IsOpen() bool {
	return db.internal != nil
}

// Close tears down the internal leveldb, writing all contents
// to file.
func (db *DB) Close() {
	if db.IsOpen() {
		db.internal.Close()
		db.internal = nil
	}
}

// Put encodes given key and value through gob, inserting resulting
// byte slices into the database's internal leveldb.
func (db *DB) Put(key, value interface{}) error {
	// Encode key via gob, registering types if necessary.
	o1, err := db.encode(key)
	if err != nil {
		return err
	}

	// Form prefixed key.
	pkey := []byte("GobDB:key:")
	pkey = append(pkey, o1...)

	// Encode value via gob, registering types if necessary.
	val, err := db.encode(value)
	if err != nil {
		return err
	}

	// Insert gobbed values into leveldb.
	return db.internal.Put(pkey, val, nil)
}

// Get ncodes given key via gob, fetches the corresponding
// value from within leveldb, and decodes that value into
// parameter two.
func (db *DB) Get(key, value interface{}) error {
	// Encode key via gob, registering its type if necessary.
	obj, err := db.encode(key)
	if err != nil {
		return err
	}

	// Form prefixed key.
	pkey := []byte("GobDB:key:")
	pkey = append(pkey, obj...)

	// Fetch gob-encoded value.
	val, err := db.internal.Get(pkey, nil)
	if err != nil {
		return err
	}

	// Decode value into second paramater (which should be a
	// pointer)
	return db.decoder.Decode(val, value)
}

// Has encodes given key via gob and checks if the resulting
// byte slice exists in the database's internal leveldb.
func (db DB) Has(key interface{}) bool {
	// Encode key via gob, registering its type if necessary.
	obj, err := db.encode(key)
	if err != nil {
		return false
	}

	// Note: this is niave - should check error type.
	_, err = db.internal.Get(obj, nil)
	return err == nil
}

// Delete encodes given key via gob, deleting the resulting
// byte slice from the database's internal leveldb.
func (db *DB) Delete(key interface{}) error {
	// Encode key via gob, registering its type if necessary.
	obj, err := db.encode(key)
	if err != nil {
		return err
	}

	// Form key bytes.
	kbytes := []byte("GobDB:key:")
	kbytes = append(kbytes, obj...)

	// Delete!
	return db.internal.Delete(kbytes, nil)
}

// Entries counts key-value pairs in the database.
func (db *DB) Entries() int {
	i := 0
	iter := db.internal.NewIterator(util.BytesPrefix([]byte("GobDB:key:")), nil)
	for iter.Next() {
		i++
	}
	iter.Release()
	return i
}

// Reset erases caches and closes leveldb. This way, the db
// is forced to reload gobbed values as though it had just
// been opened for the first time.
func (db *DB) Reset() {
	db.Close()
	db.prepared = false
}

// Encodes given key via gob, registers its type if necessary,
// and routes any errors outward.
func (db *DB) encode(key interface{}) ([]byte, error) {
	err := db.Open()
	if err != nil {
		return []byte{}, err
	}

	// Gob encode key.
	def, obj, err := db.encoder.Encode(key)
	if err != nil {
		return []byte{}, err
	}

	// Register key with decoder.
	db.decoder.Register(append(def, obj...))

	// Register key type.
	err = db.registerType(def, obj)
	if err != nil {
		return []byte{}, err
	}

	// err = db.decoder.Decode(append(def, obj...), nil)
	// if err != nil {
	// 	return []byte{}, err
	// }

	return obj, nil
}

// When the database is opened for the first time, scrolls through
// all entries to form the same encoder that was used before the
// previous db.Close() call.
//
// Note that this is an expensive operation, scaling linearly with
// dataset size. Accordingly, you should utilize the open and close
// methods instead of initializing new DB objects all the time. For
// each initialization, the decoder is literally thrown in the
// garbage.
func (db *DB) prepare() error {
	if db.prepared == true {
		return nil
	}

	iter := db.internal.NewIterator(util.BytesPrefix([]byte("GobDB:prep#")), nil)
	for iter.Next() {
		value := iter.Value()
		db.encoder.Encode(value)
		db.decoder.Register(value)
	}
	iter.Release()
	err := iter.Error()
	if err == nil {
		db.prepared = true
	}
	return err
}

func (db *DB) setPrepCount(value int) error {
	key := []byte("GobDB:prep-count")
	data := []byte(strconv.Itoa(value))
	return db.internal.Put(key, data, nil)
}

func (db *DB) incPrepCount(i int) error {
	size := db.prepCount()
	if size == -1 {
		return db.setPrepCount(1)
	}
	return db.setPrepCount(size + i)
}

func (db *DB) prepCount() int {
	err := db.Open()
	if err != nil {
		return -1
	}

	val, err := db.internal.Get([]byte("GobDB:prep-count"), nil)
	if err != nil {
		return 0
	}
	n, _ := strconv.Atoi(string(val))
	return n
}

// Checks if definition is present in current db.
func (db *DB) isPresent(def []byte) bool {
	err := db.Open()
	if err != nil {
		return false
	}

	key := []byte("GobDB:prep:")
	key = append(key, def...)
	_, err = db.internal.Get(key, nil)
	return err == nil
}

// If not done already, registers type and example object in both
// the encoder and decoder.
func (db *DB) registerType(def, obj []byte) error {
	// Ensure that database is open.
	err := db.Open()
	if err != nil {
		return err
	}

	// Stop if type is already registered in database.
	if db.isPresent(def) {
		return nil
	}

	// Map prep#<n> to type definition bytes.
	k1 := []byte("GobDB:prep#" + strconv.Itoa(db.prepCount()))
	err = db.incPrepCount(1)
	if err != nil {
		return err
	}
	v1 := []byte{}
	v1 = append(v1, def...)
	v1 = append(v1, obj...)
	err = db.internal.Put(k1, v1, nil)
	if err != nil {
		return err
	}

	// Map prep:<def> to empty string (for checking duplicate keys).
	k2 := []byte("GobDB:prep:")
	k2 = append(k2, def...)
	v2 := []byte("")
	err = db.internal.Put(k2, v2, nil)
	if err != nil {
		db.internal.Delete(k1, nil)
		db.incPrepCount(-1)
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package moves

import (
	"log"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"github.com/censhin/pokedex-api/db"
)

func CollectionDao() Moves {
	session := db.Session()
	defer session.Close()

	collection := session.DB("pokedex").C("moves")

	result := []Move{}
	iter := collection.Find(nil).Iter()
	err := iter.All(&result)
	if err != nil {
		log.Fatal(err)
	}

	return Moves{result}
}

func MemberDao(name string) Move {
	session := db.Session()
	defer session.Close()

	collection := session.DB("pokedex").C("moves")

	result := Move{}
	err := collection.Find(bson.M{"name": name}).One(&result)
	if err != nil {
		log.Fatal(err)
	}

	return result
}
<commit_msg>fix(moves dao): remove unused import<commit_after>package moves

import (
	"log"
	"gopkg.in/mgo.v2/bson"
	"github.com/censhin/pokedex-api/db"
)

func CollectionDao() Moves {
	session := db.Session()
	defer session.Close()

	collection := session.DB("pokedex").C("moves")

	result := []Move{}
	iter := collection.Find(nil).Iter()
	err := iter.All(&result)
	if err != nil {
		log.Fatal(err)
	}

	return Moves{result}
}

func MemberDao(name string) Move {
	session := db.Session()
	defer session.Close()

	collection := session.DB("pokedex").C("moves")

	result := Move{}
	err := collection.Find(bson.M{"name": name}).One(&result)
	if err != nil {
		log.Fatal(err)
	}

	return result
}
<|endoftext|>