<commit_before>package query

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"io"
	"math"
	"sort"

	"github.com/gogo/protobuf/proto"
	"github.com/influxdata/influxdb/influxql"
	internal "github.com/influxdata/influxdb/query/internal"
)

// ZeroTime is the Unix nanosecond timestamp for no time.
// This time is not used by the query engine or the storage engine as a valid time.
const ZeroTime = int64(math.MinInt64)

// Point represents a value in a series that occurred at a given time.
type Point interface {
	// Name and tags uniquely identify the series the value belongs to.
	name() string
	tags() Tags

	// The time that the value occurred at.
	time() int64

	// The value at the given time.
	value() interface{}

	// Auxillary values passed along with the value.
	aux() []interface{}
}

// Points represents a list of points.
type Points []Point

// Clone returns a deep copy of a.
func (a Points) Clone() []Point {
	other := make([]Point, len(a))
	for i, p := range a {
		if p == nil {
			other[i] = nil
			continue
		}

		switch p := p.(type) {
		case *FloatPoint:
			other[i] = p.Clone()
		case *IntegerPoint:
			other[i] = p.Clone()
		case *UnsignedPoint:
			other[i] = p.Clone()
		case *StringPoint:
			other[i] = p.Clone()
		case *BooleanPoint:
			other[i] = p.Clone()
		default:
			panic(fmt.Sprintf("unable to clone point: %T", p))
		}
	}
	return other
}

// Tags represent a map of keys and values.
// It memoizes its key so it can be used efficiently during query execution.
type Tags struct {
	id string
	m  map[string]string
}

// NewTags returns a new instance of Tags.
func NewTags(m map[string]string) Tags {
	if len(m) == 0 {
		return Tags{}
	}
	return Tags{
		id: string(encodeTags(m)),
		m:  m,
	}
}

// newTagsID returns a new instance of Tags by parsing the given tag ID.
func newTagsID(id string) Tags {
	m := decodeTags([]byte(id))
	if len(m) == 0 {
		return Tags{}
	}
	return Tags{id: id, m: m}
}

// Equal compares if the Tags are equal to each other.
func (t Tags) Equal(other Tags) bool {
	return t.ID() == other.ID()
}

// ID returns the string identifier for the tags.
func (t Tags) ID() string { return t.id }

// KeyValues returns the underlying map for the tags.
func (t Tags) KeyValues() map[string]string { return t.m }

// Keys returns a sorted list of all keys on the tag.
func (t *Tags) Keys() []string {
	if t == nil {
		return nil
	}

	var a []string
	for k := range t.m {
		a = append(a, k)
	}
	sort.Strings(a)
	return a
}

// Values returns a sorted list of all values on the tag.
func (t *Tags) Values() []string {
	if t == nil {
		return nil
	}

	a := make([]string, 0, len(t.m))
	for _, v := range t.m {
		a = append(a, v)
	}
	sort.Strings(a)
	return a
}

// Value returns the value for a given key.
func (t *Tags) Value(k string) string {
	if t == nil {
		return ""
	}
	return t.m[k]
}

// Subset returns a new tags object with a subset of the keys.
func (t *Tags) Subset(keys []string) Tags {
	if len(keys) == 0 {
		return Tags{}
	}

	// If keys match existing keys, simply return this tagset.
	if keysMatch(t.m, keys) {
		return *t
	}

	// Otherwise create new tag set.
	m := make(map[string]string, len(keys))
	for _, k := range keys {
		m[k] = t.m[k]
	}
	return NewTags(m)
}

// Equals returns true if t equals other.
func (t *Tags) Equals(other *Tags) bool {
	if t == nil && other == nil {
		return true
	} else if t == nil || other == nil {
		return false
	}
	return t.id == other.id
}

// keysMatch returns true if m has exactly the same keys as listed in keys.
func keysMatch(m map[string]string, keys []string) bool {
	if len(keys) != len(m) {
		return false
	}

	for _, k := range keys {
		if _, ok := m[k]; !ok {
			return false
		}
	}

	return true
}

// encodeTags converts a map of strings to an identifier.
func encodeTags(m map[string]string) []byte {
	// Empty maps marshal to empty bytes.
	if len(m) == 0 {
		return nil
	}

	// Extract keys and determine final size.
	sz := (len(m) * 2) - 1 // separators
	keys := make([]string, 0, len(m))
	for k, v := range m {
		keys = append(keys, k)
		sz += len(k) + len(v)
	}
	sort.Strings(keys)

	// Generate marshaled bytes.
	b := make([]byte, sz)
	buf := b
	for _, k := range keys {
		copy(buf, k)
		buf[len(k)] = '\x00'
		buf = buf[len(k)+1:]
	}
	for i, k := range keys {
		v := m[k]
		copy(buf, v)
		if i < len(keys)-1 {
			buf[len(v)] = '\x00'
			buf = buf[len(v)+1:]
		}
	}
	return b
}

// decodeTags parses an identifier into a map of tags.
func decodeTags(id []byte) map[string]string {
	a := bytes.Split(id, []byte{'\x00'})

	// There must be an even number of segments.
	if len(a) > 0 && len(a)%2 == 1 {
		a = a[:len(a)-1]
	}

	// Return nil if there are no segments.
	if len(a) == 0 {
		return nil
	}
	mid := len(a) / 2

	// Decode key/value tags.
	m := make(map[string]string)
	for i := 0; i < mid; i++ {
		m[string(a[i])] = string(a[i+mid])
	}
	return m
}

func encodeAux(aux []interface{}) []*internal.Aux {
	pb := make([]*internal.Aux, len(aux))
	for i := range aux {
		switch v := aux[i].(type) {
		case float64:
			pb[i] = &internal.Aux{DataType: proto.Int32(influxql.Float), FloatValue: proto.Float64(v)}
		case *float64:
			pb[i] = &internal.Aux{DataType: proto.Int32(influxql.Float)}
		case int64:
			pb[i] = &internal.Aux{DataType: proto.Int32(influxql.Integer), IntegerValue: proto.Int64(v)}
		case *int64:
			pb[i] = &internal.Aux{DataType: proto.Int32(influxql.Integer)}
		case string:
			pb[i] = &internal.Aux{DataType: proto.Int32(influxql.String), StringValue: proto.String(v)}
		case *string:
			pb[i] = &internal.Aux{DataType: proto.Int32(influxql.String)}
		case bool:
			pb[i] = &internal.Aux{DataType: proto.Int32(influxql.Boolean), BooleanValue: proto.Bool(v)}
		case *bool:
			pb[i] = &internal.Aux{DataType: proto.Int32(influxql.Boolean)}
		default:
			pb[i] = &internal.Aux{DataType: proto.Int32(int32(influxql.Unknown))}
		}
	}
	return pb
}

func decodeAux(pb []*internal.Aux) []interface{} {
	if len(pb) == 0 {
		return nil
	}

	aux := make([]interface{}, len(pb))
	for i := range pb {
		switch pb[i].GetDataType() {
		case influxql.Float:
			if pb[i].FloatValue != nil {
				aux[i] = *pb[i].FloatValue
			} else {
				aux[i] = (*float64)(nil)
			}
		case influxql.Integer:
			if pb[i].IntegerValue != nil {
				aux[i] = *pb[i].IntegerValue
			} else {
				aux[i] = (*int64)(nil)
			}
		case influxql.String:
			if pb[i].StringValue != nil {
				aux[i] = *pb[i].StringValue
			} else {
				aux[i] = (*string)(nil)
			}
		case influxql.Boolean:
			if pb[i].BooleanValue != nil {
				aux[i] = *pb[i].BooleanValue
			} else {
				aux[i] = (*bool)(nil)
			}
		default:
			aux[i] = nil
		}
	}
	return aux
}

func cloneAux(src []interface{}) []interface{} {
	if src == nil {
		return src
	}
	dest := make([]interface{}, len(src))
	copy(dest, src)
	return dest
}

// PointDecoder decodes generic points from a reader.
type PointDecoder struct {
	r     io.Reader
	stats IteratorStats
}

// NewPointDecoder returns a new instance of PointDecoder that reads from r.
func NewPointDecoder(r io.Reader) *PointDecoder {
	return &PointDecoder{r: r}
}

// Stats returns iterator stats embedded within the stream.
func (dec *PointDecoder) Stats() IteratorStats { return dec.stats }

// DecodePoint reads from the underlying reader and unmarshals into p.
func (dec *PointDecoder) DecodePoint(p *Point) error {
	for {
		// Read length.
		var sz uint32
		if err := binary.Read(dec.r, binary.BigEndian, &sz); err != nil {
			return err
		}

		// Read point data.
		buf := make([]byte, sz)
		if _, err := io.ReadFull(dec.r, buf); err != nil {
			return err
		}

		// Unmarshal into point.
		var pb internal.Point
		if err := proto.Unmarshal(buf, &pb); err != nil {
			return err
		}

		// If the point contains stats then read stats and retry.
		if pb.Stats != nil {
			dec.stats = decodeIteratorStats(pb.Stats)
			continue
		}

		if pb.IntegerValue != nil {
			*p = decodeIntegerPoint(&pb)
		} else if pb.StringValue != nil {
			*p = decodeStringPoint(&pb)
		} else if pb.BooleanValue != nil {
			*p = decodeBooleanPoint(&pb)
		} else {
			*p = decodeFloatPoint(&pb)
		}

		return nil
	}
}
<commit_msg>Support marshaling unsigned points<commit_after>package query

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"io"
	"math"
	"sort"

	"github.com/gogo/protobuf/proto"
	"github.com/influxdata/influxdb/influxql"
	internal "github.com/influxdata/influxdb/query/internal"
)

// ZeroTime is the Unix nanosecond timestamp for no time.
// This time is not used by the query engine or the storage engine as a valid time.
const ZeroTime = int64(math.MinInt64)

// Point represents a value in a series that occurred at a given time.
type Point interface {
	// Name and tags uniquely identify the series the value belongs to.
	name() string
	tags() Tags

	// The time that the value occurred at.
	time() int64

	// The value at the given time.
	value() interface{}

	// Auxillary values passed along with the value.
	aux() []interface{}
}

// Points represents a list of points.
type Points []Point

// Clone returns a deep copy of a.
func (a Points) Clone() []Point {
	other := make([]Point, len(a))
	for i, p := range a {
		if p == nil {
			other[i] = nil
			continue
		}

		switch p := p.(type) {
		case *FloatPoint:
			other[i] = p.Clone()
		case *IntegerPoint:
			other[i] = p.Clone()
		case *UnsignedPoint:
			other[i] = p.Clone()
		case *StringPoint:
			other[i] = p.Clone()
		case *BooleanPoint:
			other[i] = p.Clone()
		default:
			panic(fmt.Sprintf("unable to clone point: %T", p))
		}
	}
	return other
}

// Tags represent a map of keys and values.
// It memoizes its key so it can be used efficiently during query execution.
type Tags struct {
	id string
	m  map[string]string
}

// NewTags returns a new instance of Tags.
func NewTags(m map[string]string) Tags {
	if len(m) == 0 {
		return Tags{}
	}
	return Tags{
		id: string(encodeTags(m)),
		m:  m,
	}
}

// newTagsID returns a new instance of Tags by parsing the given tag ID.
func newTagsID(id string) Tags {
	m := decodeTags([]byte(id))
	if len(m) == 0 {
		return Tags{}
	}
	return Tags{id: id, m: m}
}

// Equal compares if the Tags are equal to each other.
func (t Tags) Equal(other Tags) bool {
	return t.ID() == other.ID()
}

// ID returns the string identifier for the tags.
func (t Tags) ID() string { return t.id }

// KeyValues returns the underlying map for the tags.
func (t Tags) KeyValues() map[string]string { return t.m }

// Keys returns a sorted list of all keys on the tag.
func (t *Tags) Keys() []string {
	if t == nil {
		return nil
	}

	var a []string
	for k := range t.m {
		a = append(a, k)
	}
	sort.Strings(a)
	return a
}

// Values returns a sorted list of all values on the tag.
func (t *Tags) Values() []string {
	if t == nil {
		return nil
	}

	a := make([]string, 0, len(t.m))
	for _, v := range t.m {
		a = append(a, v)
	}
	sort.Strings(a)
	return a
}

// Value returns the value for a given key.
func (t *Tags) Value(k string) string {
	if t == nil {
		return ""
	}
	return t.m[k]
}

// Subset returns a new tags object with a subset of the keys.
func (t *Tags) Subset(keys []string) Tags {
	if len(keys) == 0 {
		return Tags{}
	}

	// If keys match existing keys, simply return this tagset.
	if keysMatch(t.m, keys) {
		return *t
	}

	// Otherwise create new tag set.
	m := make(map[string]string, len(keys))
	for _, k := range keys {
		m[k] = t.m[k]
	}
	return NewTags(m)
}

// Equals returns true if t equals other.
func (t *Tags) Equals(other *Tags) bool {
	if t == nil && other == nil {
		return true
	} else if t == nil || other == nil {
		return false
	}
	return t.id == other.id
}

// keysMatch returns true if m has exactly the same keys as listed in keys.
func keysMatch(m map[string]string, keys []string) bool {
	if len(keys) != len(m) {
		return false
	}

	for _, k := range keys {
		if _, ok := m[k]; !ok {
			return false
		}
	}

	return true
}

// encodeTags converts a map of strings to an identifier.
func encodeTags(m map[string]string) []byte {
	// Empty maps marshal to empty bytes.
	if len(m) == 0 {
		return nil
	}

	// Extract keys and determine final size.
	sz := (len(m) * 2) - 1 // separators
	keys := make([]string, 0, len(m))
	for k, v := range m {
		keys = append(keys, k)
		sz += len(k) + len(v)
	}
	sort.Strings(keys)

	// Generate marshaled bytes.
	b := make([]byte, sz)
	buf := b
	for _, k := range keys {
		copy(buf, k)
		buf[len(k)] = '\x00'
		buf = buf[len(k)+1:]
	}
	for i, k := range keys {
		v := m[k]
		copy(buf, v)
		if i < len(keys)-1 {
			buf[len(v)] = '\x00'
			buf = buf[len(v)+1:]
		}
	}
	return b
}

// decodeTags parses an identifier into a map of tags.
func decodeTags(id []byte) map[string]string {
	a := bytes.Split(id, []byte{'\x00'})

	// There must be an even number of segments.
	if len(a) > 0 && len(a)%2 == 1 {
		a = a[:len(a)-1]
	}

	// Return nil if there are no segments.
	if len(a) == 0 {
		return nil
	}
	mid := len(a) / 2

	// Decode key/value tags.
	m := make(map[string]string)
	for i := 0; i < mid; i++ {
		m[string(a[i])] = string(a[i+mid])
	}
	return m
}

func encodeAux(aux []interface{}) []*internal.Aux {
	pb := make([]*internal.Aux, len(aux))
	for i := range aux {
		switch v := aux[i].(type) {
		case float64:
			pb[i] = &internal.Aux{DataType: proto.Int32(influxql.Float), FloatValue: proto.Float64(v)}
		case *float64:
			pb[i] = &internal.Aux{DataType: proto.Int32(influxql.Float)}
		case int64:
			pb[i] = &internal.Aux{DataType: proto.Int32(influxql.Integer), IntegerValue: proto.Int64(v)}
		case *int64:
			pb[i] = &internal.Aux{DataType: proto.Int32(influxql.Integer)}
		case uint64:
			pb[i] = &internal.Aux{DataType: proto.Int32(influxql.Unsigned), UnsignedValue: proto.Uint64(v)}
		case *uint64:
			pb[i] = &internal.Aux{DataType: proto.Int32(influxql.Unsigned)}
		case string:
			pb[i] = &internal.Aux{DataType: proto.Int32(influxql.String), StringValue: proto.String(v)}
		case *string:
			pb[i] = &internal.Aux{DataType: proto.Int32(influxql.String)}
		case bool:
			pb[i] = &internal.Aux{DataType: proto.Int32(influxql.Boolean), BooleanValue: proto.Bool(v)}
		case *bool:
			pb[i] = &internal.Aux{DataType: proto.Int32(influxql.Boolean)}
		default:
			pb[i] = &internal.Aux{DataType: proto.Int32(int32(influxql.Unknown))}
		}
	}
	return pb
}

func decodeAux(pb []*internal.Aux) []interface{} {
	if len(pb) == 0 {
		return nil
	}

	aux := make([]interface{}, len(pb))
	for i := range pb {
		switch pb[i].GetDataType() {
		case influxql.Float:
			if pb[i].FloatValue != nil {
				aux[i] = *pb[i].FloatValue
			} else {
				aux[i] = (*float64)(nil)
			}
		case influxql.Integer:
			if pb[i].IntegerValue != nil {
				aux[i] = *pb[i].IntegerValue
			} else {
				aux[i] = (*int64)(nil)
			}
		case influxql.Unsigned:
			if pb[i].UnsignedValue != nil {
				aux[i] = *pb[i].UnsignedValue
			} else {
				aux[i] = (*uint64)(nil)
			}
		case influxql.String:
			if pb[i].StringValue != nil {
				aux[i] = *pb[i].StringValue
			} else {
				aux[i] = (*string)(nil)
			}
		case influxql.Boolean:
			if pb[i].BooleanValue != nil {
				aux[i] = *pb[i].BooleanValue
			} else {
				aux[i] = (*bool)(nil)
			}
		default:
			aux[i] = nil
		}
	}
	return aux
}

func cloneAux(src []interface{}) []interface{} {
	if src == nil {
		return src
	}
	dest := make([]interface{}, len(src))
	copy(dest, src)
	return dest
}

// PointDecoder decodes generic points from a reader.
type PointDecoder struct {
	r     io.Reader
	stats IteratorStats
}

// NewPointDecoder returns a new instance of PointDecoder that reads from r.
func NewPointDecoder(r io.Reader) *PointDecoder {
	return &PointDecoder{r: r}
}

// Stats returns iterator stats embedded within the stream.
func (dec *PointDecoder) Stats() IteratorStats { return dec.stats }

// DecodePoint reads from the underlying reader and unmarshals into p.
func (dec *PointDecoder) DecodePoint(p *Point) error {
	for {
		// Read length.
		var sz uint32
		if err := binary.Read(dec.r, binary.BigEndian, &sz); err != nil {
			return err
		}

		// Read point data.
		buf := make([]byte, sz)
		if _, err := io.ReadFull(dec.r, buf); err != nil {
			return err
		}

		// Unmarshal into point.
		var pb internal.Point
		if err := proto.Unmarshal(buf, &pb); err != nil {
			return err
		}

		// If the point contains stats then read stats and retry.
		if pb.Stats != nil {
			dec.stats = decodeIteratorStats(pb.Stats)
			continue
		}

		if pb.IntegerValue != nil {
			*p = decodeIntegerPoint(&pb)
		} else if pb.UnsignedValue != nil {
			*p = decodeUnsignedPoint(&pb)
		} else if pb.StringValue != nil {
			*p = decodeStringPoint(&pb)
		} else if pb.BooleanValue != nil {
			*p = decodeBooleanPoint(&pb)
		} else {
			*p = decodeFloatPoint(&pb)
		}

		return nil
	}
}
<|endoftext|>


<commit_before>package main

import (
	"html/template"
	"io/ioutil"
	"net/http"
)

const (
	viewPath = "/view/"
	editPath = "/edit/"
	savePath = "/save/"
)

type Page struct {
	Title string
	Body  []byte
}

func (p *Page) save() error {
	filename := p.Title + ".txt"
	return ioutil.WriteFile(filename, p.Body, 0600)
}

func loadPage(title string) (*Page, error) {
	filename := title + ".txt"
	body, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}

	return &Page{title, body}, err
}

func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
	t, err := template.ParseFiles(tmpl)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	err = t.Execute(w, p)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func viewHandler(w http.ResponseWriter, r *http.Request) {
	title := r.URL.Path[len(viewPath):]
	page, err := loadPage(title)
	if err != nil {
		http.Redirect(w, r, editPath+title, http.StatusFound)
		return
	}

	renderTemplate(w, "view.html", page)
}

func editHandler(w http.ResponseWriter, r *http.Request) {
	title := r.URL.Path[len(editPath):]
	page, err := loadPage(title)
	if err != nil {
		page = &Page{title, nil}
	}

	renderTemplate(w, "edit.html", page)
}

func saveHandler(w http.ResponseWriter, r *http.Request) {
	title := r.URL.Path[len(savePath):]
	body := r.FormValue("body")

	p := &Page{title, []byte(body)}
	err := p.save()
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	http.Redirect(w, r, "/view/"+title, http.StatusFound)
}

func main() {
	page := &Page{"TestPage", []byte("This is a sample page.")}
	page.save()

	http.HandleFunc(viewPath, viewHandler)
	http.HandleFunc(editPath, editHandler)
	http.HandleFunc(savePath, saveHandler)
	http.ListenAndServe("localhost:8080", nil)
}
<commit_msg>Cache templates at start<commit_after>package main

import (
	"html/template"
	"io/ioutil"
	"net/http"
)

const (
	viewPath = "/view/"
	editPath = "/edit/"
	savePath = "/save/"
)

var templates = template.Must(template.ParseFiles("view.html", "edit.html"))

type Page struct {
	Title string
	Body  []byte
}

func (p *Page) save() error {
	filename := p.Title + ".txt"
	return ioutil.WriteFile(filename, p.Body, 0600)
}

func loadPage(title string) (*Page, error) {
	filename := title + ".txt"
	body, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}

	return &Page{title, body}, err
}

func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
	err := templates.ExecuteTemplate(w, tmpl, p)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func viewHandler(w http.ResponseWriter, r *http.Request) {
	title := r.URL.Path[len(viewPath):]
	page, err := loadPage(title)
	if err != nil {
		http.Redirect(w, r, editPath+title, http.StatusFound)
		return
	}

	renderTemplate(w, "view.html", page)
}

func editHandler(w http.ResponseWriter, r *http.Request) {
	title := r.URL.Path[len(editPath):]
	page, err := loadPage(title)
	if err != nil {
		page = &Page{title, nil}
	}

	renderTemplate(w, "edit.html", page)
}

func saveHandler(w http.ResponseWriter, r *http.Request) {
	title := r.URL.Path[len(savePath):]
	body := r.FormValue("body")

	p := &Page{title, []byte(body)}
	err := p.save()
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	http.Redirect(w, r, "/view/"+title, http.StatusFound)
}

func main() {
	page := &Page{"TestPage", []byte("This is a sample page.")}
	page.save()

	http.HandleFunc(viewPath, viewHandler)
	http.HandleFunc(editPath, editHandler)
	http.HandleFunc(savePath, saveHandler)
	http.ListenAndServe("localhost:8080", nil)
}
<|endoftext|>


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

package testutil

import (
	"math/rand"
	"os"
	"strconv"
	"sync"
	"time"

	"v.io/x/lib/vlog"
)

const (
	SeedEnv = "VANADIUM_RNG_SEED"
)

// An instance of Random initialized by the InitRandomGenerator function.
var (
	Rand *Random
	once sync.Once
)

// Random is a concurrent-access friendly source of randomness.
type Random struct {
	mu   sync.Mutex
	rand *rand.Rand
}

// Int returns a non-negative pseudo-random int.
func (r *Random) Int() int {
	r.mu.Lock()
	defer r.mu.Unlock()
	return r.rand.Int()
}

// Intn returns a non-negative pseudo-random int in the range [0, n).
func (r *Random) Intn(n int) int {
	r.mu.Lock()
	defer r.mu.Unlock()
	return r.rand.Intn(n)
}

// Int63 returns a non-negative 63-bit pseudo-random integer as an int64.
func (r *Random) Int63() int64 {
	r.mu.Lock()
	defer r.mu.Unlock()
	return r.rand.Int63()
}

// RandomBytes generates the given number of random bytes.
func (rand *Random) RandomBytes(size int) []byte {
	buffer := make([]byte, size)
	randomMutex.Lock()
	defer randomMutex.Unlock()
	// Generate a 10MB of random bytes since that is a value commonly
	// used in the tests.
	if len(random) == 0 {
		random = generateRandomBytes(rand, 10<<20)
	}
	if size > len(random) {
		extra := generateRandomBytes(rand, size-len(random))
		random = append(random, extra...)
	}
	start := rand.Intn(len(random) - size + 1)
	copy(buffer, random[start:start+size])
	return buffer
}

// Create a new pseudo-random number generator, the seed may be supplied
// by the VANADIUM_RNG_SEED to allow for reproducing a previous sequence.
func NewRandGenerator() *Random {
	seed := time.Now().UnixNano()
	seedString := os.Getenv(SeedEnv)
	if seedString != "" {
		var err error
		base, bitSize := 0, 64
		seed, err = strconv.ParseInt(seedString, base, bitSize)
		if err != nil {
			vlog.Fatalf("ParseInt(%v, %v, %v) failed: %v", seedString, base, bitSize, err)
		}
	}
	vlog.Infof("Seeding pseudo-random number generator with %v", seed)
	return &Random{rand: rand.New(rand.NewSource(seed))}
}

// InitRandGenerator creates an instance of Random in the public variable Rand.
func InitRandGenerator() {
	once.Do(func() {
		Rand = NewRandGenerator()
	})
}

var (
	random      []byte
	randomMutex sync.Mutex
)

func generateRandomBytes(rand *Random, size int) []byte {
	buffer := make([]byte, size)
	offset := 0
	for {
		bits := int64(rand.Int63())
		for i := 0; i < 8; i++ {
			buffer[offset] = byte(bits & 0xff)
			size--
			if size == 0 {
				return buffer
			}
			offset++
			bits >>= 8
		}
	}
}

// Int returns a non-negative pseudo-random int using the public variable Rand.
func Int() int {
	return Rand.Int()
}

// Intn returns a non-negative pseudo-random int in the range [0, n) using
// the public variable Rand.
func Intn(n int) int {
	return Rand.Intn(n)
}

// Int63 returns a non-negative 63-bit pseudo-random integer as an int64
// using the public variable Rand.
func Int63() int64 {
	return Rand.Int63()
}

// RandomBytes generates the given number of random bytes using
// the public variable Rand.
func RandomBytes(size int) []byte {
	return Rand.RandomBytes(size)
}
<commit_msg>test: More VEYRON -> V23 renaming for enviroment variables.<commit_after>// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package testutil

import (
	"math/rand"
	"os"
	"strconv"
	"sync"
	"time"

	"v.io/x/lib/vlog"
)

const (
	SeedEnv = "V23_RNG_SEED"
)

// An instance of Random initialized by the InitRandomGenerator function.
var (
	Rand *Random
	once sync.Once
)

// Random is a concurrent-access friendly source of randomness.
type Random struct {
	mu   sync.Mutex
	rand *rand.Rand
}

// Int returns a non-negative pseudo-random int.
func (r *Random) Int() int {
	r.mu.Lock()
	defer r.mu.Unlock()
	return r.rand.Int()
}

// Intn returns a non-negative pseudo-random int in the range [0, n).
func (r *Random) Intn(n int) int {
	r.mu.Lock()
	defer r.mu.Unlock()
	return r.rand.Intn(n)
}

// Int63 returns a non-negative 63-bit pseudo-random integer as an int64.
func (r *Random) Int63() int64 {
	r.mu.Lock()
	defer r.mu.Unlock()
	return r.rand.Int63()
}

// RandomBytes generates the given number of random bytes.
func (rand *Random) RandomBytes(size int) []byte {
	buffer := make([]byte, size)
	randomMutex.Lock()
	defer randomMutex.Unlock()
	// Generate a 10MB of random bytes since that is a value commonly
	// used in the tests.
	if len(random) == 0 {
		random = generateRandomBytes(rand, 10<<20)
	}
	if size > len(random) {
		extra := generateRandomBytes(rand, size-len(random))
		random = append(random, extra...)
	}
	start := rand.Intn(len(random) - size + 1)
	copy(buffer, random[start:start+size])
	return buffer
}

// Create a new pseudo-random number generator, the seed may be supplied
// by V23_RNG_SEED to allow for reproducing a previous sequence.
func NewRandGenerator() *Random {
	seed := time.Now().UnixNano()
	seedString := os.Getenv(SeedEnv)
	if seedString != "" {
		var err error
		base, bitSize := 0, 64
		seed, err = strconv.ParseInt(seedString, base, bitSize)
		if err != nil {
			vlog.Fatalf("ParseInt(%v, %v, %v) failed: %v", seedString, base, bitSize, err)
		}
	}
	vlog.Infof("Seeding pseudo-random number generator with %v", seed)
	return &Random{rand: rand.New(rand.NewSource(seed))}
}

// InitRandGenerator creates an instance of Random in the public variable Rand.
func InitRandGenerator() {
	once.Do(func() {
		Rand = NewRandGenerator()
	})
}

var (
	random      []byte
	randomMutex sync.Mutex
)

func generateRandomBytes(rand *Random, size int) []byte {
	buffer := make([]byte, size)
	offset := 0
	for {
		bits := int64(rand.Int63())
		for i := 0; i < 8; i++ {
			buffer[offset] = byte(bits & 0xff)
			size--
			if size == 0 {
				return buffer
			}
			offset++
			bits >>= 8
		}
	}
}

// Int returns a non-negative pseudo-random int using the public variable Rand.
func Int() int {
	return Rand.Int()
}

// Intn returns a non-negative pseudo-random int in the range [0, n) using
// the public variable Rand.
func Intn(n int) int {
	return Rand.Intn(n)
}

// Int63 returns a non-negative 63-bit pseudo-random integer as an int64
// using the public variable Rand.
func Int63() int64 {
	return Rand.Int63()
}

// RandomBytes generates the given number of random bytes using
// the public variable Rand.
func RandomBytes(size int) []byte {
	return Rand.RandomBytes(size)
}
<|endoftext|>


<commit_before>package gorethink

import (
	p "github.com/dancannon/gorethink/ql2"
)

type InsertOpts struct {
	Durability    interface{} `gorethink:"durability,omitempty"`
	ReturnChanges interface{} `gorethink:"return_changes,omitempty"`
	CacheSize     interface{} `gorethink:"cache_size,omitempty"`
	Upsert        interface{} `gorethink:"upsert,omitempty"`
}

func (o *InsertOpts) toMap() map[string]interface{} {
	return optArgsToMap(o)
}

// Insert JSON documents into a table. Accepts a single JSON document or an array
// of documents. You may also pass the optional argument durability with value
// 'hard' or 'soft', to override the table or query's default durability setting,
// or the optional argument return_changes, which will return the value of the row
// you're inserting (and the old value if you use upsert) when set to true.
//
//	table.Insert(map[string]interface{}{"name": "Joe", "email": "joe@example.com"}).RunWrite(sess)
//	table.Insert([]interface{}{map[string]interface{}{"name": "Joe"}, map[string]interface{}{"name": "Paul"}}).RunWrite(sess)
func (t Term) Insert(arg interface{}, optArgs ...InsertOpts) Term {
	opts := map[string]interface{}{}
	if len(optArgs) >= 1 {
		opts = optArgs[0].toMap()
	}
	return constructMethodTerm(t, "Insert", p.Term_INSERT, []interface{}{funcWrap(arg)}, opts)
}

type UpdateOpts struct {
	Durability    interface{} `gorethink:"durability,omitempty"`
	ReturnChanges interface{} `gorethink:"return_changes,omitempty"`
	NotAtomic     interface{} `gorethink:"non_atomic,omitempty"`
}

func (o *UpdateOpts) toMap() map[string]interface{} {
	return optArgsToMap(o)
}

// Update JSON documents in a table. Accepts a JSON document, a RQL expression,
// or a combination of the two. The optional argument durability with value
// 'hard' or 'soft' will override the table or query's default durability setting.
// The optional argument return_changes will return the old and new values of the
// row you're modifying when set to true (only valid for single-row updates).
// The optional argument non_atomic lets you permit non-atomic updates.
func (t Term) Update(arg interface{}, optArgs ...UpdateOpts) Term {
	opts := map[string]interface{}{}
	if len(optArgs) >= 1 {
		opts = optArgs[0].toMap()
	}
	return constructMethodTerm(t, "Update", p.Term_UPDATE, []interface{}{funcWrap(arg)}, opts)
}

type ReplaceOpts struct {
	Durability    interface{} `gorethink:"durability,omitempty"`
	ReturnChanges interface{} `gorethink:"return_changes,omitempty"`
	NotAtomic     interface{} `gorethink:"non_atomic,omitempty"`
}

func (o *ReplaceOpts) toMap() map[string]interface{} {
	return optArgsToMap(o)
}

// Replace documents in a table. Accepts a JSON document or a RQL expression,
// and replaces the original document with the new one. The new document must
// have the same primary key as the original document. The optional argument
// durability with value 'hard' or 'soft' will override the table or query's
// default durability setting. The optional argument return_changes will return
// the old and new values of the row you're modifying when set to true (only
// valid for single-row replacements). The optional argument non_atomic lets
// you permit non-atomic updates.
func (t Term) Replace(arg interface{}, optArgs ...ReplaceOpts) Term {
	opts := map[string]interface{}{}
	if len(optArgs) >= 1 {
		opts = optArgs[0].toMap()
	}
	return constructMethodTerm(t, "Replace", p.Term_REPLACE, []interface{}{funcWrap(arg)}, opts)
}

type DeleteOpts struct {
	Durability    interface{} `gorethink:"durability,omitempty"`
	ReturnChanges interface{} `gorethink:"return_changes,omitempty"`
}

func (o *DeleteOpts) toMap() map[string]interface{} {
	return optArgsToMap(o)
}

// Delete one or more documents from a table. The optional argument return_changes
// will return the old value of the row you're deleting when set to true (only
// valid for single-row deletes). The optional argument durability with value
// 'hard' or 'soft' will override the table or query's default durability setting.
func (t Term) Delete(optArgs ...DeleteOpts) Term {
	opts := map[string]interface{}{}
	if len(optArgs) >= 1 {
		opts = optArgs[0].toMap()
	}
	return constructMethodTerm(t, "Delete", p.Term_DELETE, []interface{}{}, opts)
}

// Sync ensures that writes on a given table are written to permanent storage.
// Queries that specify soft durability (Durability: "soft") do not give such
// guarantees, so sync can be used to ensure the state of these queries. A call
// to sync does not return until all previous writes to the table are persisted.
func (t Term) Sync(args ...interface{}) Term {
	return constructMethodTerm(t, "Sync", p.Term_SYNC, args, map[string]interface{}{})
}
<commit_msg>Renamed the upsert optarg with conflict<commit_after>package gorethink

import (
	p "github.com/dancannon/gorethink/ql2"
)

type InsertOpts struct {
	Durability    interface{} `gorethink:"durability,omitempty"`
	ReturnChanges interface{} `gorethink:"return_changes,omitempty"`
	CacheSize     interface{} `gorethink:"cache_size,omitempty"`
	Conflict      interface{} `gorethink:"conflict,omitempty"`
}

func (o *InsertOpts) toMap() map[string]interface{} {
	return optArgsToMap(o)
}

// Insert JSON documents into a table. Accepts a single JSON document or an array
// of documents. You may also pass the optional argument durability with value
// 'hard' or 'soft', to override the table or query's default durability setting,
// or the optional argument return_changes, which will return the value of the row
// you're inserting when set to true.
//
//	table.Insert(map[string]interface{}{"name": "Joe", "email": "joe@example.com"}).RunWrite(sess)
//	table.Insert([]interface{}{map[string]interface{}{"name": "Joe"}, map[string]interface{}{"name": "Paul"}}).RunWrite(sess)
func (t Term) Insert(arg interface{}, optArgs ...InsertOpts) Term {
	opts := map[string]interface{}{}
	if len(optArgs) >= 1 {
		opts = optArgs[0].toMap()
	}
	return constructMethodTerm(t, "Insert", p.Term_INSERT, []interface{}{funcWrap(arg)}, opts)
}

type UpdateOpts struct {
	Durability    interface{} `gorethink:"durability,omitempty"`
	ReturnChanges interface{} `gorethink:"return_changes,omitempty"`
	NotAtomic     interface{} `gorethink:"non_atomic,omitempty"`
}

func (o *UpdateOpts) toMap() map[string]interface{} {
	return optArgsToMap(o)
}

// Update JSON documents in a table. Accepts a JSON document, a RQL expression,
// or a combination of the two. The optional argument durability with value
// 'hard' or 'soft' will override the table or query's default durability setting.
// The optional argument return_changes will return the old and new values of the
// row you're modifying when set to true (only valid for single-row updates).
// The optional argument non_atomic lets you permit non-atomic updates.
func (t Term) Update(arg interface{}, optArgs ...UpdateOpts) Term {
	opts := map[string]interface{}{}
	if len(optArgs) >= 1 {
		opts = optArgs[0].toMap()
	}
	return constructMethodTerm(t, "Update", p.Term_UPDATE, []interface{}{funcWrap(arg)}, opts)
}

type ReplaceOpts struct {
	Durability    interface{} `gorethink:"durability,omitempty"`
	ReturnChanges interface{} `gorethink:"return_changes,omitempty"`
	NotAtomic     interface{} `gorethink:"non_atomic,omitempty"`
}

func (o *ReplaceOpts) toMap() map[string]interface{} {
	return optArgsToMap(o)
}

// Replace documents in a table. Accepts a JSON document or a RQL expression,
// and replaces the original document with the new one. The new document must
// have the same primary key as the original document. The optional argument
// durability with value 'hard' or 'soft' will override the table or query's
// default durability setting. The optional argument return_changes will return
// the old and new values of the row you're modifying when set to true (only
// valid for single-row replacements). The optional argument non_atomic lets
// you permit non-atomic updates.
func (t Term) Replace(arg interface{}, optArgs ...ReplaceOpts) Term {
	opts := map[string]interface{}{}
	if len(optArgs) >= 1 {
		opts = optArgs[0].toMap()
	}
	return constructMethodTerm(t, "Replace", p.Term_REPLACE, []interface{}{funcWrap(arg)}, opts)
}

type DeleteOpts struct {
	Durability    interface{} `gorethink:"durability,omitempty"`
	ReturnChanges interface{} `gorethink:"return_changes,omitempty"`
}

func (o *DeleteOpts) toMap() map[string]interface{} {
	return optArgsToMap(o)
}

// Delete one or more documents from a table. The optional argument return_changes
// will return the old value of the row you're deleting when set to true (only
// valid for single-row deletes). The optional argument durability with value
// 'hard' or 'soft' will override the table or query's default durability setting.
func (t Term) Delete(optArgs ...DeleteOpts) Term {
	opts := map[string]interface{}{}
	if len(optArgs) >= 1 {
		opts = optArgs[0].toMap()
	}
	return constructMethodTerm(t, "Delete", p.Term_DELETE, []interface{}{}, opts)
}

// Sync ensures that writes on a given table are written to permanent storage.
// Queries that specify soft durability (Durability: "soft") do not give such
// guarantees, so sync can be used to ensure the state of these queries. A call
// to sync does not return until all previous writes to the table are persisted.
func (t Term) Sync(args ...interface{}) Term {
	return constructMethodTerm(t, "Sync", p.Term_SYNC, args, map[string]interface{}{})
}
<|endoftext|>


<commit_before>package dukedb

import (
	"encoding/json"
	"fmt"
	"strings"

	"github.com/theduke/go-apperror"
)

/**
 * Query parser functions.
 */

func ParseJsonQuery(js []byte) (Query, apperror.Error) {
	var data map[string]interface{}
	if err := json.Unmarshal(js, &data); err != nil {
		return nil, &apperror.Err{
			Public:  true,
			Code:    "invalid_json",
			Message: "Query json could not be unmarshaled. Check for invalid json.",
		}
	}

	return ParseQuery(data)
}

// Build a database query based a map[string]interface{} data structure
// resembling a Mongo query.
//
// It returns a Query equal to the Mongo query, with unsupported features omitted.
// An error is returned if the building of the query fails.
//
// Format: {
//   // Order by field:
//   order: "field",
//  //  Order descending:
//  order: "-field",
//
//  // Joins:
//  joins: ["myJoin", "my.nestedJoin"],
//
//  // Filters:
//  Filters conform to the mongo query syntax.
//  See http://docs.mongodb.org/manual/reference/operator/query/.
//  filters: {
//  	id: "22",
//    weight: {$gt: 222},
//    type: {$in: ["type1", "type2"]}
//  },
//
//  // Limiting:
//  limit: 100,
//
//  // Offset:
//  offset: 20
// }
//
func ParseQuery(data map[string]interface{}) (Query, apperror.Error) {
	if data == nil {
		return nil, apperror.New("empty_query_data")
	}

	collection, _ := data["collection"].(string)
	if collection == "" {
		return nil, apperror.New("no_collection", "Query must contain a 'collection' key.")
	}

	q := Q(collection)

	// First, Handle joins so query and field specification parsing can use
	// join info.
	if rawJoins, ok := data["joins"]; ok {
		rawJoinSlice, ok := rawJoins.([]interface{})
		if !ok {
			return nil, &apperror.Err{
				Code:    "invalid_joins",
				Message: "Joins must be an array of strings",
			}
		}

		// Convert []interface{} joins to []string.

		joins := make([]string, 0)
		for _, rawJoin := range rawJoinSlice {
			join, ok := rawJoin.(string)
			if !ok {
				return nil, &apperror.Err{
					Code:    "invalid_joins",
					Message: "Joins must be an array of strings",
				}
			}
			joins = append(joins, join)
		}

		// To handle nested joins, parseQueryJoins has to be called repeatedly
		// until no more joins are returned.
		for depth := 1; true; depth++ {
			var err apperror.Error
			joins, err = parseQueryJoins(q, joins, depth)
			if err != nil {
				return nil, err
			}

			if len(joins) == 0 {
				break
			}
		}
	}

	// Handle filters.

	if rawQuery, ok := data["filters"]; ok {
		query, ok := rawQuery.(map[string]interface{})
		if !ok {
			return nil, &apperror.Err{
				Code:    "invalid_filters",
				Message: "The filters key must contain a dict",
			}
		}

		if err := parseQueryFilters(q, query); err != nil {
			return nil, err
		}
	}

	// Handle fields.
	if rawFields, ok := data["fields"]; ok {
		fields, ok := rawFields.([]interface{})
		if !ok {
			return nil, &apperror.Err{
				Code:    "invalid_fields",
				Message: "Fields specification must be an array",
			}
		}

		for _, rawField := range fields {
			field, ok := rawField.(string)
			if !ok {
				return nil, &apperror.Err{
					Code:    "invalid_fields",
					Message: "Fields specification must be an array of strings",
				}
			}

			parts := strings.Split(field, ".")
			if len(parts) > 1 {
				// Possibly a field on a joined model. Check if a parent join can be found.
				joinQ := q.GetJoin(strings.Join(parts[:len(parts)-1], "."))
				if joinQ != nil {
					// Join query found, add field to the join query.
					joinQ.AddFields(parts[len(parts)-1])
				} else {
					// No join query found, maybe the backend supports nested fields.
					joinQ.AddFields(field)
				}
			} else {
				// Not nested, just add the field.
				q.AddFields(field)
			}
		}
	}

	// Handle orders.
	if rawOrders, ok := data["order"]; ok {
		var orders []interface{}

		// Order may either be a single string, or a list of strings.

		if oneOrder, ok := rawOrders.(string); ok {
			orders = []interface{}{oneOrder}
		} else {
			var ok bool
			orders, ok = rawOrders.([]interface{})
			if !ok {
				return nil, &apperror.Err{
					Code:    "invalid_orders",
					Message: "Order specification must be an array",
				}
			}
		}

		for _, rawOrder := range orders {
			field, ok := rawOrder.(string)
			if !ok {
				return nil, &apperror.Err{
					Code:    "invalid_orders",
					Message: "Order specification must be an array of strings.",
				}
			}

			ascending := true
			if field[0] == '-' {
				ascending = false
				field = strings.TrimLeft(field, "-")
			} else if field[0] == '+' {
				field = strings.TrimLeft(field, "-")
			}

			if field == "" {
				return nil, &apperror.Err{
					Code:    "invalid_orders_empty_field",
					Message: "Order specification is empty",
				}
			}

			q.Order(field, ascending)
		}
	}

	// Handle limit.
	if rawLimit, ok := data["limit"]; ok {
		if limit, err := NumericToInt64(rawLimit); err != nil {
			return nil, &apperror.Err{
				Code:    "limit_non_numeric",
				Message: "Limit must be a number",
			}
		} else {
			q.Limit(int(limit))
		}
	}

	// Handle offset.
	if rawOffset, ok := data["offset"]; ok {
		if offset, err := NumericToInt64(rawOffset); err != nil {
			return nil, &apperror.Err{
				Code:    "offset_non_numeric",
				Message: "Offset must be a number",
			}
		} else {
			q.Offset(int(offset))
		}
	}

	return q, nil
}

func parseQueryJoins(q Query, joins []string, depth int) ([]string, apperror.Error) {
	remaining := make([]string, 0)

	for _, name := range joins {
		parts := strings.Split(name, ".")
		joinDepth := len(parts)
		if joinDepth == depth {
			// The depth of the join equals to the one that should be processed, so do!
			if len(parts) > 1 {
				// Nested join! So try to retrieve the parent join query.
				joinQ := q.GetJoin(strings.Join(parts[:joinDepth-1], "."))
				if joinQ == nil {
					// Parent join not found, obviosly an error.
					return nil, &apperror.Err{
						Code:    "invalid_nested_join",
						Message: fmt.Sprintf("Tried to join %v, but the parent join was not found", name),
					}
				}
				// Join the current join on the parent join.
				joinQ.Join(parts[len(parts)-1])
			} else {
				// Not nested, just join on the main query.
				q.Join(name)
			}
		} else {
			// Join has other depth than the one that is processed, so append to
			// remaining.
			remaining = append(remaining, name)
		}
	}

	return remaining, nil
}

func parseQueryFilters(q Query, filters map[string]interface{}) apperror.Error {
	filter, err := parseQueryFilter("", filters, q)
	if err != nil {
		return err
	}

	// If filter is an and, add the and clauses separately to the query.
	// Done for prettier query without top level AND.
	if andFilter, ok := filter.(*AndCondition); ok {
		for _, filter := range andFilter.Filters {
			q.FilterQ(filter)
		}
	} else {
		q.FilterQ(filter)
	}

	return nil
}

// Parses a mongo query filter to a Filter.
// All mongo operators expect $nor are supported.
// Refer to http://docs.mongodb.org/manual/reference/operator/query.
func parseQueryFilter(name string, data interface{}, query Query) (Filter, apperror.Error) {
	// Handle
	switch name {
	case "$eq":
		return Eq("placeholder", data), nil
	case "$ne":
		return Neq("placeholder", data), nil
	case "$in":
		return In("placeholder", data), nil
	case "$like":
		return Like("placeholder", data), nil
	case "$gt":
		return Gt("placeholder", data), nil
	case "$gte":
		return Gte("placeholder", data), nil
	case "$lt":
		return Lt("placeholder", data), nil
	case "$lte":
		return Lte("placeholder", data), nil
	case "$nin":
		return Not(In("placeholder", data)), nil
	}

	if name == "$nor" {
		return nil, &apperror.Err{
			Code:    "unsupported_nor_query",
			Message: "$nor queryies are not supported",
		}
	}

	// Handle OR.
	if name == "$or" {
		orClauses, ok := data.([]interface{})
		if !ok {
			return nil, &apperror.Err{Code: "invalid_or_data"}
		}

		or := Or()
		for _, rawClause := range orClauses {
			clause, ok := rawClause.(map[string]interface{})
			if !ok {
				return nil, &apperror.Err{Code: "invalid_or_data"}
			}

			filter, err := parseQueryFilter("", clause, query)
			if err != nil {
				return nil, err
			}
			or.Add(filter)
		}

		return or, nil
	}

	if nestedData, ok := data.(map[string]interface{}); ok {
		// Nested dict with multipe AND clauses.

		// Build an AND filter.
		and := And()
		for key := range nestedData {
			filter, err := parseQueryFilter(key, nestedData[key], query)
			if err != nil {
				return nil, err
			}

			doAdd := true

			if key == "$or" || key == "$and" || key == "$not" {
				// Do nothing
			} else {
				field := name
				if field == "" {
					field = key
				}

				// Check for joins.

				parts := strings.Split(field, ".")
				if len(parts) > 1 {
					// Possibly a field on a joined model. Check if a parent join can be found.
					joinQ := query.GetJoin(strings.Join(parts[:len(parts)-1], "."))
					if joinQ != nil {
						// Join query found, add filter to the join query.
						filter.SetField(parts[len(parts)-1])
						joinQ.FilterQ(filter)
						// Set flag to prevent adding to regular query.
						doAdd = false
					}
				}

				if doAdd {
					filter.SetField(field)
				}
			}

			if doAdd {
				and.Add(filter)
			}
		}

		if len(and.Filters) == 1 {
			return and.Filters[0], nil
		} else {
			return and, nil
		}
	}

	// If execution reaches this point, the filter must be a simple equals filter
	// with a value.
	return Eq(name, data), nil
}
<commit_msg>fixed queryparser for join filters<commit_after>package dukedb

import (
	"encoding/json"
	"fmt"
	"strings"

	"github.com/theduke/go-apperror"
)

/**
 * Query parser functions.
 */

func ParseJsonQuery(js []byte) (Query, apperror.Error) {
	var data map[string]interface{}
	if err := json.Unmarshal(js, &data); err != nil {
		return nil, &apperror.Err{
			Public:  true,
			Code:    "invalid_json",
			Message: "Query json could not be unmarshaled. Check for invalid json.",
		}
	}

	return ParseQuery(data)
}

// Build a database query based a map[string]interface{} data structure
// resembling a Mongo query.
//
// It returns a Query equal to the Mongo query, with unsupported features omitted.
// An error is returned if the building of the query fails.
//
// Format: {
//   // Order by field:
//   order: "field",
//  //  Order descending:
//  order: "-field",
//
//  // Joins:
//  joins: ["myJoin", "my.nestedJoin"],
//
//  // Filters:
//  Filters conform to the mongo query syntax.
//  See http://docs.mongodb.org/manual/reference/operator/query/.
//  filters: {
//  	id: "22",
//    weight: {$gt: 222},
//    type: {$in: ["type1", "type2"]}
//  },
//
//  // Limiting:
//  limit: 100,
//
//  // Offset:
//  offset: 20
// }
//
func ParseQuery(data map[string]interface{}) (Query, apperror.Error) {
	if data == nil {
		return nil, apperror.New("empty_query_data")
	}

	collection, _ := data["collection"].(string)
	if collection == "" {
		return nil, apperror.New("no_collection", "Query must contain a 'collection' key.")
	}

	q := Q(collection)

	// First, Handle joins so query and field specification parsing can use
	// join info.
	if rawJoins, ok := data["joins"]; ok {
		rawJoinSlice, ok := rawJoins.([]interface{})
		if !ok {
			return nil, &apperror.Err{
				Code:    "invalid_joins",
				Message: "Joins must be an array of strings",
			}
		}

		// Convert []interface{} joins to []string.

		joins := make([]string, 0)
		for _, rawJoin := range rawJoinSlice {
			join, ok := rawJoin.(string)
			if !ok {
				return nil, &apperror.Err{
					Code:    "invalid_joins",
					Message: "Joins must be an array of strings",
				}
			}
			joins = append(joins, join)
		}

		// To handle nested joins, parseQueryJoins has to be called repeatedly
		// until no more joins are returned.
		for depth := 1; true; depth++ {
			var err apperror.Error
			joins, err = parseQueryJoins(q, joins, depth)
			if err != nil {
				return nil, err
			}

			if len(joins) == 0 {
				break
			}
		}
	}

	// Handle filters.

	if rawQuery, ok := data["filters"]; ok {
		query, ok := rawQuery.(map[string]interface{})
		if !ok {
			return nil, &apperror.Err{
				Code:    "invalid_filters",
				Message: "The filters key must contain a dict",
			}
		}

		if err := parseQueryFilters(q, query); err != nil {
			return nil, err
		}
	}

	// Handle fields.
	if rawFields, ok := data["fields"]; ok {
		fields, ok := rawFields.([]interface{})
		if !ok {
			return nil, &apperror.Err{
				Code:    "invalid_fields",
				Message: "Fields specification must be an array",
			}
		}

		for _, rawField := range fields {
			field, ok := rawField.(string)
			if !ok {
				return nil, &apperror.Err{
					Code:    "invalid_fields",
					Message: "Fields specification must be an array of strings",
				}
			}

			parts := strings.Split(field, ".")
			if len(parts) > 1 {
				// Possibly a field on a joined model. Check if a parent join can be found.
				joinQ := q.GetJoin(strings.Join(parts[:len(parts)-1], "."))
				if joinQ != nil {
					// Join query found, add field to the join query.
					joinQ.AddFields(parts[len(parts)-1])
				} else {
					// No join query found, maybe the backend supports nested fields.
					q.AddFields(field)
				}
			} else {
				// Not nested, just add the field.
				q.AddFields(field)
			}
		}
	}

	// Handle orders.
	if rawOrders, ok := data["order"]; ok {
		var orders []interface{}

		// Order may either be a single string, or a list of strings.

		if oneOrder, ok := rawOrders.(string); ok {
			orders = []interface{}{oneOrder}
		} else {
			var ok bool
			orders, ok = rawOrders.([]interface{})
			if !ok {
				return nil, &apperror.Err{
					Code:    "invalid_orders",
					Message: "Order specification must be an array",
				}
			}
		}

		for _, rawOrder := range orders {
			field, ok := rawOrder.(string)
			if !ok {
				return nil, &apperror.Err{
					Code:    "invalid_orders",
					Message: "Order specification must be an array of strings.",
				}
			}

			ascending := true
			if field[0] == '-' {
				ascending = false
				field = strings.TrimLeft(field, "-")
			} else if field[0] == '+' {
				field = strings.TrimLeft(field, "-")
			}

			if field == "" {
				return nil, &apperror.Err{
					Code:    "invalid_orders_empty_field",
					Message: "Order specification is empty",
				}
			}

			q.Order(field, ascending)
		}
	}

	// Handle limit.
	if rawLimit, ok := data["limit"]; ok {
		if limit, err := NumericToInt64(rawLimit); err != nil {
			return nil, &apperror.Err{
				Code:    "limit_non_numeric",
				Message: "Limit must be a number",
			}
		} else {
			q.Limit(int(limit))
		}
	}

	// Handle offset.
	if rawOffset, ok := data["offset"]; ok {
		if offset, err := NumericToInt64(rawOffset); err != nil {
			return nil, &apperror.Err{
				Code:    "offset_non_numeric",
				Message: "Offset must be a number",
			}
		} else {
			q.Offset(int(offset))
		}
	}

	return q, nil
}

func parseQueryJoins(q Query, joins []string, depth int) ([]string, apperror.Error) {
	remaining := make([]string, 0)

	for _, name := range joins {
		parts := strings.Split(name, ".")
		joinDepth := len(parts)
		if joinDepth == depth {
			// The depth of the join equals to the one that should be processed, so do!
			if len(parts) > 1 {
				// Nested join! So try to retrieve the parent join query.
				joinQ := q.GetJoin(strings.Join(parts[:joinDepth-1], "."))
				if joinQ == nil {
					// Parent join not found, obviosly an error.
					return nil, &apperror.Err{
						Code:    "invalid_nested_join",
						Message: fmt.Sprintf("Tried to join %v, but the parent join was not found", name),
					}
				}
				// Join the current join on the parent join.
				joinQ.Join(parts[len(parts)-1])
			} else {
				// Not nested, just join on the main query.
				q.Join(name)
			}
		} else {
			// Join has other depth than the one that is processed, so append to
			// remaining.
			remaining = append(remaining, name)
		}
	}

	return remaining, nil
}

func parseQueryFilters(q Query, filters map[string]interface{}) apperror.Error {
	filter, err := parseQueryFilter("", filters, q)
	if err != nil {
		return err
	}

	// If filter is an and, add the and clauses separately to the query.
	// Done for prettier query without top level AND.
	if andFilter, ok := filter.(*AndCondition); ok {
		for _, filter := range andFilter.Filters {
			q.FilterQ(filter)
		}
	} else {
		q.FilterQ(filter)
	}

	return nil
}

// Parses a mongo query filter to a Filter.
// All mongo operators expect $nor are supported.
// Refer to http://docs.mongodb.org/manual/reference/operator/query.
func parseQueryFilter(name string, data interface{}, query Query) (Filter, apperror.Error) {
	// Handle
	switch name {
	case "$eq":
		return Eq("placeholder", data), nil
	case "$ne":
		return Neq("placeholder", data), nil
	case "$in":
		return In("placeholder", data), nil
	case "$like":
		return Like("placeholder", data), nil
	case "$gt":
		return Gt("placeholder", data), nil
	case "$gte":
		return Gte("placeholder", data), nil
	case "$lt":
		return Lt("placeholder", data), nil
	case "$lte":
		return Lte("placeholder", data), nil
	case "$nin":
		return Not(In("placeholder", data)), nil
	}

	if name == "$nor" {
		return nil, &apperror.Err{
			Code:    "unsupported_nor_query",
			Message: "$nor queryies are not supported",
		}
	}

	// Handle OR.
	if name == "$or" {
		orClauses, ok := data.([]interface{})
		if !ok {
			return nil, &apperror.Err{Code: "invalid_or_data"}
		}

		or := Or()
		for _, rawClause := range orClauses {
			clause, ok := rawClause.(map[string]interface{})
			if !ok {
				return nil, &apperror.Err{Code: "invalid_or_data"}
			}

			filter, err := parseQueryFilter("", clause, query)
			if err != nil {
				return nil, err
			}
			or.Add(filter)
		}

		return or, nil
	}

	if nestedData, ok := data.(map[string]interface{}); ok {
		// Nested dict with multipe AND clauses.

		// Build an AND filter.
		and := And()
		for key := range nestedData {
			filter, err := parseQueryFilter(key, nestedData[key], query)
			if err != nil {
				return nil, err
			}

			doAdd := true

			if key == "$or" || key == "$and" || key == "$not" {
				// Do nothing
			} else {
				field := name
				if field == "" {
					field = key
				}

				// Check for joins.

				parts := strings.Split(field, ".")
				if len(parts) > 1 {
					// Possibly a field on a joined model. Check if a parent join can be found.
					joinQ := query.GetJoin(strings.Join(parts[:len(parts)-1], "."))
					if joinQ != nil {
						// Join query found, add filter to the join query.
						filter.SetField(parts[len(parts)-1])
						joinQ.FilterQ(filter)
						// Set flag to prevent adding to regular query.
						doAdd = false
					}
				}

				if doAdd {
					filter.SetField(field)
				}
			}

			if doAdd {
				and.Add(filter)
			}
		}

		if len(and.Filters) == 1 {
			return and.Filters[0], nil
		} else {
			return and, nil
		}
	}

	// If execution reaches this point, the filter must be a simple equals filter
	// with a value.
	return Eq(name, data), nil
}
<|endoftext|>


<commit_before>package meta

import (
	"strings"

	"github.com/markbates/inflect"
)

// Name is a string that represents the "name" of a thing, like an app, model, etc...
type Name string

// Title version of a name. ie. "foo_bar" => "Foo Bar"
func (n Name) Title() string {
	x := strings.Split(string(n), "/")
	for i, s := range x {
		x[i] = inflect.Titleize(s)
	}

	return strings.Join(x, " ")
}

// Underscore version of a name. ie. "FooBar" => "foo_bar"
func (n Name) Underscore() string {
	return inflect.Underscore(string(n))
}

// Plural version of a name
func (n Name) Plural() string {
	return inflect.Pluralize(string(n))
}

// Singular version of a name
func (n Name) Singular() string {
	return inflect.Singularize(string(n))
}

// Camel version of a name
func (n Name) Camel() string {
	return inflect.Camelize(string(n))
}

// Model version of a name. ie. "user" => "User"
func (n Name) Model() string {
	x := strings.Split(string(n), "/")
	for i, s := range x {
		x[i] = inflect.Singularize(inflect.Camelize(s))
	}

	return strings.Join(x, "")
}

// Resource version of a name
func (n Name) Resource() string {
	name := inflect.Underscore(string(n))
	x := strings.FieldsFunc(name, func(r rune) bool {
		return r == '_' || r == '/'
	})

	for i, w := range x {
		if i == len(x)-1 {
			x[i] = inflect.Camelize(inflect.Pluralize(strings.ToLower(w)))
			continue
		}

		x[i] = inflect.Camelize(w)
	}

	return strings.Join(x, "")
}

// ModelPlural version of a name. ie. "user" => "Users"
func (n Name) ModelPlural() string {
	return inflect.Pluralize(n.Model())
}

// File version of a name
func (n Name) File() string {
	return inflect.Underscore(inflect.Camelize(string(n)))
}

// Table version of a name
func (n Name) Table() string {
	return inflect.Underscore(inflect.Pluralize(string(n)))
}

// UnderSingular version of a name
func (n Name) UnderSingular() string {
	return inflect.Underscore(inflect.Singularize(string(n)))
}

// PluralCamel version of a name
func (n Name) PluralCamel() string {
	return inflect.Pluralize(inflect.Camelize(string(n)))
}

// PluralUnder version of a name
func (n Name) PluralUnder() string {
	return inflect.Pluralize(inflect.Underscore(string(n)))
}

// URL version of a name
func (n Name) URL() string {
	return n.PluralUnder()
}

// CamelSingular version of a name
func (n Name) CamelSingular() string {
	return inflect.Camelize(inflect.Singularize(string(n)))
}

// VarCaseSingular version of a name. ie. "FooBar" => "fooBar"
func (n Name) VarCaseSingular() string {
	return inflect.CamelizeDownFirst(inflect.Singularize(n.Resource()))
}

// VarCasePlural version of a name. ie. "FooBar" => "fooBar"
func (n Name) VarCasePlural() string {
	return inflect.CamelizeDownFirst(inflect.Pluralize(n.Resource()))
}

// Lower case version of a string
func (n Name) Lower() string {
	return strings.ToLower(string(n))
}
<commit_msg>fixing the way we were computing VarCasePlural and VarCaseSingular<commit_after>package meta

import (
	"strings"

	"github.com/markbates/inflect"
)

// Name is a string that represents the "name" of a thing, like an app, model, etc...
type Name string

// Title version of a name. ie. "foo_bar" => "Foo Bar"
func (n Name) Title() string {
	x := strings.Split(string(n), "/")
	for i, s := range x {
		x[i] = inflect.Titleize(s)
	}

	return strings.Join(x, " ")
}

// Underscore version of a name. ie. "FooBar" => "foo_bar"
func (n Name) Underscore() string {
	return inflect.Underscore(string(n))
}

// Plural version of a name
func (n Name) Plural() string {
	return inflect.Pluralize(string(n))
}

// Singular version of a name
func (n Name) Singular() string {
	return inflect.Singularize(string(n))
}

// Camel version of a name
func (n Name) Camel() string {
	return inflect.Camelize(string(n))
}

// Model version of a name. ie. "user" => "User"
func (n Name) Model() string {
	x := strings.Split(string(n), "/")
	for i, s := range x {
		x[i] = inflect.Singularize(inflect.Camelize(s))
	}

	return strings.Join(x, "")
}

// Resource version of a name
func (n Name) Resource() string {
	name := inflect.Underscore(string(n))
	x := strings.FieldsFunc(name, func(r rune) bool {
		return r == '_' || r == '/'
	})

	for i, w := range x {
		if i == len(x)-1 {
			x[i] = inflect.Camelize(inflect.Pluralize(strings.ToLower(w)))
			continue
		}

		x[i] = inflect.Camelize(w)
	}

	return strings.Join(x, "")
}

// ModelPlural version of a name. ie. "user" => "Users"
func (n Name) ModelPlural() string {
	return inflect.Pluralize(n.Model())
}

// File version of a name
func (n Name) File() string {
	return inflect.Underscore(inflect.Camelize(string(n)))
}

// Table version of a name
func (n Name) Table() string {
	return inflect.Underscore(inflect.Pluralize(string(n)))
}

// UnderSingular version of a name
func (n Name) UnderSingular() string {
	return inflect.Underscore(inflect.Singularize(string(n)))
}

// PluralCamel version of a name
func (n Name) PluralCamel() string {
	return inflect.Pluralize(inflect.Camelize(string(n)))
}

// PluralUnder version of a name
func (n Name) PluralUnder() string {
	return inflect.Pluralize(inflect.Underscore(string(n)))
}

// URL version of a name
func (n Name) URL() string {
	return n.PluralUnder()
}

// CamelSingular version of a name
func (n Name) CamelSingular() string {
	return inflect.Camelize(inflect.Singularize(string(n)))
}

// VarCaseSingular version of a name. ie. "FooBar" => "fooBar"
func (n Name) VarCaseSingular() string {
	return inflect.CamelizeDownFirst(inflect.Singularize(inflect.Underscore(n.Resource())))
}

// VarCasePlural version of a name. ie. "FooBar" => "fooBar"
func (n Name) VarCasePlural() string {
	return inflect.CamelizeDownFirst(n.Resource())
}

// Lower case version of a string
func (n Name) Lower() string {
	return strings.ToLower(string(n))
}
<|endoftext|>


<commit_before>package api

import (
	"testing"

	"github.com/grafana/grafana/pkg/api/dtos"
	"github.com/grafana/grafana/pkg/bus"
	m "github.com/grafana/grafana/pkg/models"
	"github.com/grafana/grafana/pkg/services/annotations"

	. "github.com/smartystreets/goconvey/convey"
)

func TestAnnotationsApiEndpoint(t *testing.T) {
	Convey("Given an annotation without a dashboard id", t, func() {
		cmd := dtos.PostAnnotationsCmd{
			DashboardId: 1,
			Time:        1000,
			Text:        "annotation text",
			Tags:        []string{"tag1", "tag2"},
			IsRegion:    false,
		}

		updateCmd := dtos.UpdateAnnotationsCmd{
			Time:     1000,
			Text:     "annotation text",
			Tags:     []string{"tag1", "tag2"},
			IsRegion: false,
		}

		Convey("When user is an Org Viewer", func() {
			role := m.ROLE_VIEWER
			Convey("Should not be allowed to save an annotation", func() {
				postAnnotationScenario("When calling POST on", "/api/annotations", "/api/annotations", role, cmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})

				putAnnotationScenario("When calling PUT on", "/api/annotations/1", "/api/annotations/:annotationId", role, updateCmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("PUT", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/1", "/api/annotations/:annotationId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationById
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/region/1", "/api/annotations/region/:regionId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationRegion
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})
			})
		})

		Convey("When user is an Org Editor", func() {
			role := m.ROLE_EDITOR
			Convey("Should be able to save an annotation", func() {
				postAnnotationScenario("When calling POST on", "/api/annotations", "/api/annotations", role, cmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})

				putAnnotationScenario("When calling PUT on", "/api/annotations/1", "/api/annotations/:annotationId", role, updateCmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("PUT", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/1", "/api/annotations/:annotationId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationById
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/region/1", "/api/annotations/region/:regionId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationRegion
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})
			})

			Convey("Should note be able to save an annotation", func() {
				cmd = dtos.PostAnnotationsCmd{
					Time: 1000,
					Text: "annotation text",
				}
				postAnnotationScenario("When calling POST without dashboardId", "/api/annotations", "/api/annotations", role, cmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 500)
				})

				cmd = dtos.PostAnnotationsCmd{
					Time:        1000,
					DashboardId: 3,
				}
				postAnnotationScenario("When calling POST without text", "/api/annotations", "/api/annotations", role, cmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 500)
				})
			})
		})
	})

	Convey("Given an annotation with a dashboard id and the dashboard does not have an acl", t, func() {
		cmd := dtos.PostAnnotationsCmd{
			Time:        1000,
			Text:        "annotation text",
			Tags:        []string{"tag1", "tag2"},
			IsRegion:    false,
			DashboardId: 1,
			PanelId:     1,
		}

		updateCmd := dtos.UpdateAnnotationsCmd{
			Time:     1000,
			Text:     "annotation text",
			Tags:     []string{"tag1", "tag2"},
			IsRegion: false,
			Id:       1,
		}

		viewerRole := m.ROLE_VIEWER
		editorRole := m.ROLE_EDITOR

		aclMockResp := []*m.DashboardAclInfoDTO{
			{Role: &viewerRole, Permission: m.PERMISSION_VIEW},
			{Role: &editorRole, Permission: m.PERMISSION_EDIT},
		}

		bus.AddHandler("test", func(query *m.GetDashboardAclInfoListQuery) error {
			query.Result = aclMockResp
			return nil
		})

		bus.AddHandler("test", func(query *m.GetTeamsByUserQuery) error {
			query.Result = []*m.Team{}
			return nil
		})

		Convey("When user is an Org Viewer", func() {
			role := m.ROLE_VIEWER
			Convey("Should not be allowed to save an annotation", func() {
				postAnnotationScenario("When calling POST on", "/api/annotations", "/api/annotations", role, cmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})

				putAnnotationScenario("When calling PUT on", "/api/annotations/1", "/api/annotations/:annotationId", role, updateCmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("PUT", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/1", "/api/annotations/:annotationId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationById
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/region/1", "/api/annotations/region/:regionId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationRegion
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})
			})
		})

		Convey("When user is an Org Editor", func() {
			role := m.ROLE_EDITOR
			Convey("Should be able to save an annotation", func() {
				postAnnotationScenario("When calling POST on", "/api/annotations", "/api/annotations", role, cmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})

				putAnnotationScenario("When calling PUT on", "/api/annotations/1", "/api/annotations/:annotationId", role, updateCmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("PUT", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/1", "/api/annotations/:annotationId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationById
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/region/1", "/api/annotations/region/:regionId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationRegion
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})
			})
		})
	})
}

type fakeAnnotationsRepo struct {
}

func (repo *fakeAnnotationsRepo) Delete(params *annotations.DeleteParams) error {
	return nil
}
func (repo *fakeAnnotationsRepo) Save(item *annotations.Item) error {
	item.Id = 1
	return nil
}
func (repo *fakeAnnotationsRepo) Update(item *annotations.Item) error {
	return nil
}
func (repo *fakeAnnotationsRepo) Find(query *annotations.ItemQuery) ([]*annotations.ItemDTO, error) {
	annotations := []*annotations.ItemDTO{{Id: 1}}
	return annotations, nil
}

var fakeAnnoRepo *fakeAnnotationsRepo

func postAnnotationScenario(desc string, url string, routePattern string, role m.RoleType, cmd dtos.PostAnnotationsCmd, fn scenarioFunc) {
	Convey(desc+" "+url, func() {
		defer bus.ClearBusHandlers()

		sc := setupScenarioContext(url)
		sc.defaultHandler = wrap(func(c *m.ReqContext) Response {
			sc.context = c
			sc.context.UserId = TestUserID
			sc.context.OrgId = TestOrgID
			sc.context.OrgRole = role

			return PostAnnotation(c, cmd)
		})

		fakeAnnoRepo = &fakeAnnotationsRepo{}
		annotations.SetRepository(fakeAnnoRepo)

		sc.m.Post(routePattern, sc.defaultHandler)

		fn(sc)
	})
}

func putAnnotationScenario(desc string, url string, routePattern string, role m.RoleType, cmd dtos.UpdateAnnotationsCmd, fn scenarioFunc) {
	Convey(desc+" "+url, func() {
		defer bus.ClearBusHandlers()

		sc := setupScenarioContext(url)
		sc.defaultHandler = wrap(func(c *m.ReqContext) Response {
			sc.context = c
			sc.context.UserId = TestUserID
			sc.context.OrgId = TestOrgID
			sc.context.OrgRole = role

			return UpdateAnnotation(c, cmd)
		})

		fakeAnnoRepo = &fakeAnnotationsRepo{}
		annotations.SetRepository(fakeAnnoRepo)

		sc.m.Put(routePattern, sc.defaultHandler)

		fn(sc)
	})
}
<commit_msg>remove api tests<commit_after>package api

import (
	"testing"

	"github.com/grafana/grafana/pkg/api/dtos"
	"github.com/grafana/grafana/pkg/bus"
	m "github.com/grafana/grafana/pkg/models"
	"github.com/grafana/grafana/pkg/services/annotations"

	. "github.com/smartystreets/goconvey/convey"
)

func TestAnnotationsApiEndpoint(t *testing.T) {
	Convey("Given an annotation without a dashboard id", t, func() {
		cmd := dtos.PostAnnotationsCmd{
			Time:     1000,
			Text:     "annotation text",
			Tags:     []string{"tag1", "tag2"},
			IsRegion: false,
		}

		updateCmd := dtos.UpdateAnnotationsCmd{
			Time:     1000,
			Text:     "annotation text",
			Tags:     []string{"tag1", "tag2"},
			IsRegion: false,
		}

		Convey("When user is an Org Viewer", func() {
			role := m.ROLE_VIEWER
			Convey("Should not be allowed to save an annotation", func() {
				postAnnotationScenario("When calling POST on", "/api/annotations", "/api/annotations", role, cmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})

				putAnnotationScenario("When calling PUT on", "/api/annotations/1", "/api/annotations/:annotationId", role, updateCmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("PUT", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/1", "/api/annotations/:annotationId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationById
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/region/1", "/api/annotations/region/:regionId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationRegion
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})
			})
		})

		Convey("When user is an Org Editor", func() {
			role := m.ROLE_EDITOR
			Convey("Should be able to save an annotation", func() {
				postAnnotationScenario("When calling POST on", "/api/annotations", "/api/annotations", role, cmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})

				putAnnotationScenario("When calling PUT on", "/api/annotations/1", "/api/annotations/:annotationId", role, updateCmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("PUT", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/1", "/api/annotations/:annotationId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationById
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/region/1", "/api/annotations/region/:regionId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationRegion
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})
			})
		})
	})

	Convey("Given an annotation with a dashboard id and the dashboard does not have an acl", t, func() {
		cmd := dtos.PostAnnotationsCmd{
			Time:        1000,
			Text:        "annotation text",
			Tags:        []string{"tag1", "tag2"},
			IsRegion:    false,
			DashboardId: 1,
			PanelId:     1,
		}

		updateCmd := dtos.UpdateAnnotationsCmd{
			Time:     1000,
			Text:     "annotation text",
			Tags:     []string{"tag1", "tag2"},
			IsRegion: false,
			Id:       1,
		}

		viewerRole := m.ROLE_VIEWER
		editorRole := m.ROLE_EDITOR

		aclMockResp := []*m.DashboardAclInfoDTO{
			{Role: &viewerRole, Permission: m.PERMISSION_VIEW},
			{Role: &editorRole, Permission: m.PERMISSION_EDIT},
		}

		bus.AddHandler("test", func(query *m.GetDashboardAclInfoListQuery) error {
			query.Result = aclMockResp
			return nil
		})

		bus.AddHandler("test", func(query *m.GetTeamsByUserQuery) error {
			query.Result = []*m.Team{}
			return nil
		})

		Convey("When user is an Org Viewer", func() {
			role := m.ROLE_VIEWER
			Convey("Should not be allowed to save an annotation", func() {
				postAnnotationScenario("When calling POST on", "/api/annotations", "/api/annotations", role, cmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})

				putAnnotationScenario("When calling PUT on", "/api/annotations/1", "/api/annotations/:annotationId", role, updateCmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("PUT", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/1", "/api/annotations/:annotationId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationById
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/region/1", "/api/annotations/region/:regionId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationRegion
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})
			})
		})

		Convey("When user is an Org Editor", func() {
			role := m.ROLE_EDITOR
			Convey("Should be able to save an annotation", func() {
				postAnnotationScenario("When calling POST on", "/api/annotations", "/api/annotations", role, cmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})

				putAnnotationScenario("When calling PUT on", "/api/annotations/1", "/api/annotations/:annotationId", role, updateCmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("PUT", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/1", "/api/annotations/:annotationId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationById
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/region/1", "/api/annotations/region/:regionId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationRegion
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})
			})
		})
	})
}

type fakeAnnotationsRepo struct {
}

func (repo *fakeAnnotationsRepo) Delete(params *annotations.DeleteParams) error {
	return nil
}
func (repo *fakeAnnotationsRepo) Save(item *annotations.Item) error {
	item.Id = 1
	return nil
}
func (repo *fakeAnnotationsRepo) Update(item *annotations.Item) error {
	return nil
}
func (repo *fakeAnnotationsRepo) Find(query *annotations.ItemQuery) ([]*annotations.ItemDTO, error) {
	annotations := []*annotations.ItemDTO{{Id: 1}}
	return annotations, nil
}

var fakeAnnoRepo *fakeAnnotationsRepo

func postAnnotationScenario(desc string, url string, routePattern string, role m.RoleType, cmd dtos.PostAnnotationsCmd, fn scenarioFunc) {
	Convey(desc+" "+url, func() {
		defer bus.ClearBusHandlers()

		sc := setupScenarioContext(url)
		sc.defaultHandler = wrap(func(c *m.ReqContext) Response {
			sc.context = c
			sc.context.UserId = TestUserID
			sc.context.OrgId = TestOrgID
			sc.context.OrgRole = role

			return PostAnnotation(c, cmd)
		})

		fakeAnnoRepo = &fakeAnnotationsRepo{}
		annotations.SetRepository(fakeAnnoRepo)

		sc.m.Post(routePattern, sc.defaultHandler)

		fn(sc)
	})
}

func putAnnotationScenario(desc string, url string, routePattern string, role m.RoleType, cmd dtos.UpdateAnnotationsCmd, fn scenarioFunc) {
	Convey(desc+" "+url, func() {
		defer bus.ClearBusHandlers()

		sc := setupScenarioContext(url)
		sc.defaultHandler = wrap(func(c *m.ReqContext) Response {
			sc.context = c
			sc.context.UserId = TestUserID
			sc.context.OrgId = TestOrgID
			sc.context.OrgRole = role

			return UpdateAnnotation(c, cmd)
		})

		fakeAnnoRepo = &fakeAnnotationsRepo{}
		annotations.SetRepository(fakeAnnoRepo)

		sc.m.Put(routePattern, sc.defaultHandler)

		fn(sc)
	})
}
<|endoftext|>


<commit_before>// +build windows

/*
 * Minio Client (C) 2015 Minio, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this fs except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package fs

import (
	"path/filepath"
	"syscall"
)

func normalizePath(path string) string {
	if filepath.VolumeName(path) == "" && filepath.HasPrefix(path, "\\") {
		path, err = syscall.FullPath(path)
		if err != nil {
			panic(err)
		}
	}
	return path
}
<commit_msg>Define error for windows, minor fix pushing in<commit_after>// +build windows

/*
 * Minio Client (C) 2015 Minio, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this fs except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package fs

import (
	"path/filepath"
	"syscall"
)

func normalizePath(path string) string {
	if filepath.VolumeName(path) == "" && filepath.HasPrefix(path, "\\") {
		var err error
		path, err = syscall.FullPath(path)
		if err != nil {
			panic(err)
		}
	}
	return path
}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package store

import (
	"fmt"
	"reflect"

	"k8s.io/client-go/tools/cache"
	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/meta"
	"k8s.io/kubernetes/pkg/apis/extensions"

	ccapi "github.com/kubernetes-incubator/cluster-capacity/pkg/api"
)

type FakeResourceStore struct {
	PodsData                   func() []*api.Pod
	ServicesData               func() []*api.Service
	ReplicationControllersData func() []*api.ReplicationController
	NodesData                  func() []*api.Node
	PersistentVolumesData      func() []*api.PersistentVolume
	PersistentVolumeClaimsData func() []*api.PersistentVolumeClaim
	ReplicaSetsData            func() []*extensions.ReplicaSet
	// TODO(jchaloup): fill missing resource functions
}

func (s *FakeResourceStore) Add(resource ccapi.ResourceType, obj interface{}) error {
	return nil
}

func (s *FakeResourceStore) Update(resource ccapi.ResourceType, obj interface{}) error {
	return nil
}

func (s *FakeResourceStore) Delete(resource ccapi.ResourceType, obj interface{}) error {
	return nil
}

func resourcesToItems(objs interface{}) []interface{} {
	objsSlice := reflect.ValueOf(objs)
	items := make([]interface{}, 0, objsSlice.Len())
	for i := 0; i < objsSlice.Len(); i++ {
		items = append(items, objsSlice.Index(i).Interface())
	}
	return items
}

func findResource(obj interface{}, objs interface{}) (item interface{}, exists bool, err error) {
	key, err := cache.MetaNamespaceKeyFunc(obj)
	if err != nil {
		return nil, false, err
	}

	var obj_key string
	var key_err error
	objsSlice := reflect.ValueOf(objs)
	for i := 0; i < objsSlice.Len(); i++ {
		item := objsSlice.Index(i).Interface()
		// TODO(jchaloup): make this resource type independent
		switch item.(type) {
		case api.Pod:
			value := item.(api.Pod)
			obj_key, key_err = cache.MetaNamespaceKeyFunc(meta.Object(&value))
		case api.Service:
			value := item.(api.Service)
			obj_key, key_err = cache.MetaNamespaceKeyFunc(meta.Object(&value))
		case api.ReplicationController:
			value := item.(api.ReplicationController)
			obj_key, key_err = cache.MetaNamespaceKeyFunc(meta.Object(&value))
		case api.Node:
			value := item.(api.Node)
			obj_key, key_err = cache.MetaNamespaceKeyFunc(meta.Object(&value))
		case api.PersistentVolume:
			value := item.(api.PersistentVolume)
			obj_key, key_err = cache.MetaNamespaceKeyFunc(meta.Object(&value))
		case api.PersistentVolumeClaim:
			value := item.(api.PersistentVolumeClaim)
			obj_key, key_err = cache.MetaNamespaceKeyFunc(meta.Object(&value))
		}
		if key_err != nil {
			return nil, false, key_err
		}
		if obj_key == key {
			return item, true, nil
		}
	}
	return nil, false, fmt.Errorf("Resource obj not found")
}

func (s *FakeResourceStore) List(resource ccapi.ResourceType) []interface{} {
	switch resource {
	case ccapi.Pods:
		if s.PodsData == nil {
			return make([]interface{}, 0, 0)
		}
		return resourcesToItems(s.PodsData())
	case ccapi.Services:
		if s.ServicesData == nil {
			return make([]interface{}, 0, 0)
		}
		return resourcesToItems(s.ServicesData())
	case ccapi.ReplicationControllers:
		if s.ReplicationControllersData == nil {
			return make([]interface{}, 0, 0)
		}
		return resourcesToItems(s.ReplicationControllersData())
	case ccapi.Nodes:
		if s.NodesData == nil {
			return make([]interface{}, 0, 0)
		}
		return resourcesToItems(s.NodesData())
	case ccapi.PersistentVolumes:
		if s.PersistentVolumesData == nil {
			return make([]interface{}, 0, 0)
		}
		return resourcesToItems(s.PersistentVolumesData())
	case ccapi.PersistentVolumeClaims:
		if s.PersistentVolumeClaimsData == nil {
			return make([]interface{}, 0, 0)
		}
		return resourcesToItems(s.PersistentVolumeClaimsData())
	case ccapi.ReplicaSets:
		if s.ReplicaSetsData == nil {
			return make([]interface{}, 0, 0)
		}
		return resourcesToItems(s.ReplicaSetsData())
	}
	return make([]interface{}, 0, 0)
}

func (s *FakeResourceStore) Get(resource ccapi.ResourceType, obj interface{}) (item interface{}, exists bool, err error) {
	switch resource {
	case ccapi.Pods:
		return findResource(obj, s.PodsData())
	case ccapi.Services:
		return findResource(obj, s.ServicesData())
	case ccapi.ReplicationControllers:
		return findResource(obj, s.ReplicationControllersData())
	case ccapi.Nodes:
		return findResource(obj, s.NodesData())
	case ccapi.PersistentVolumes:
		return findResource(obj, s.PersistentVolumesData())
	case ccapi.PersistentVolumeClaims:
		return findResource(obj, s.PersistentVolumeClaimsData())
		//case "replicasets":
		//	return testReplicaSetsData().Items
	}
	return nil, false, nil
}

func (s *FakeResourceStore) GetByKey(key string) (item interface{}, exists bool, err error) {
	return nil, false, nil
}

func (s *FakeResourceStore) RegisterEventHandler(resource ccapi.ResourceType, handler cache.ResourceEventHandler) error {
	return nil
}

func (s *FakeResourceStore) Replace(resource ccapi.ResourceType, items []interface{}, resourceVersion string) error {
	return nil
}

func (s *FakeResourceStore) Resources() []ccapi.ResourceType {
	return []ccapi.ResourceType{ccapi.Pods, ccapi.Services, ccapi.ReplicationControllers, ccapi.Nodes, ccapi.PersistentVolumes, ccapi.PersistentVolumeClaims}
}
<commit_msg>pkg/framework/store/fake.go<commit_after>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package store

import (
	"fmt"
	"reflect"

	"k8s.io/client-go/tools/cache"
	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/apis/extensions"

	ccapi "github.com/kubernetes-incubator/cluster-capacity/pkg/api"
)

type FakeResourceStore struct {
	PodsData                   func() []*api.Pod
	ServicesData               func() []*api.Service
	ReplicationControllersData func() []*api.ReplicationController
	NodesData                  func() []*api.Node
	PersistentVolumesData      func() []*api.PersistentVolume
	PersistentVolumeClaimsData func() []*api.PersistentVolumeClaim
	ReplicaSetsData            func() []*extensions.ReplicaSet
	// TODO(jchaloup): fill missing resource functions
}

func (s *FakeResourceStore) Add(resource ccapi.ResourceType, obj interface{}) error {
	return nil
}

func (s *FakeResourceStore) Update(resource ccapi.ResourceType, obj interface{}) error {
	return nil
}

func (s *FakeResourceStore) Delete(resource ccapi.ResourceType, obj interface{}) error {
	return nil
}

func resourcesToItems(objs interface{}) []interface{} {
	objsSlice := reflect.ValueOf(objs)
	items := make([]interface{}, 0, objsSlice.Len())
	for i := 0; i < objsSlice.Len(); i++ {
		items = append(items, objsSlice.Index(i).Interface())
	}
	return items
}

func findResource(obj interface{}, objs interface{}) (item interface{}, exists bool, err error) {
	key, err := cache.MetaNamespaceKeyFunc(obj)
	if err != nil {
		return nil, false, err
	}

	var obj_key string
	var key_err error
	objsSlice := reflect.ValueOf(objs)
	for i := 0; i < objsSlice.Len(); i++ {
		item := objsSlice.Index(i).Interface()
		// TODO(jchaloup): make this resource type independent
		switch item.(type) {
		case api.Pod:
			value := item.(api.Pod)
			obj_key, key_err = cache.MetaNamespaceKeyFunc(value)
		case api.Service:
			value := item.(api.Service)
			obj_key, key_err = cache.MetaNamespaceKeyFunc(value)
		case api.ReplicationController:
			value := item.(api.ReplicationController)
			obj_key, key_err = cache.MetaNamespaceKeyFunc(value)
		case api.Node:
			value := item.(api.Node)
			obj_key, key_err = cache.MetaNamespaceKeyFunc(value)
		case api.PersistentVolume:
			value := item.(api.PersistentVolume)
			obj_key, key_err = cache.MetaNamespaceKeyFunc(value)
		case api.PersistentVolumeClaim:
			value := item.(api.PersistentVolumeClaim)
			obj_key, key_err = cache.MetaNamespaceKeyFunc(value)
		}
		if key_err != nil {
			return nil, false, key_err
		}
		if obj_key == key {
			return item, true, nil
		}
	}
	return nil, false, fmt.Errorf("Resource obj not found")
}

func (s *FakeResourceStore) List(resource ccapi.ResourceType) []interface{} {
	switch resource {
	case ccapi.Pods:
		if s.PodsData == nil {
			return make([]interface{}, 0, 0)
		}
		return resourcesToItems(s.PodsData())
	case ccapi.Services:
		if s.ServicesData == nil {
			return make([]interface{}, 0, 0)
		}
		return resourcesToItems(s.ServicesData())
	case ccapi.ReplicationControllers:
		if s.ReplicationControllersData == nil {
			return make([]interface{}, 0, 0)
		}
		return resourcesToItems(s.ReplicationControllersData())
	case ccapi.Nodes:
		if s.NodesData == nil {
			return make([]interface{}, 0, 0)
		}
		return resourcesToItems(s.NodesData())
	case ccapi.PersistentVolumes:
		if s.PersistentVolumesData == nil {
			return make([]interface{}, 0, 0)
		}
		return resourcesToItems(s.PersistentVolumesData())
	case ccapi.PersistentVolumeClaims:
		if s.PersistentVolumeClaimsData == nil {
			return make([]interface{}, 0, 0)
		}
		return resourcesToItems(s.PersistentVolumeClaimsData())
	case ccapi.ReplicaSets:
		if s.ReplicaSetsData == nil {
			return make([]interface{}, 0, 0)
		}
		return resourcesToItems(s.ReplicaSetsData())
	}
	return make([]interface{}, 0, 0)
}

func (s *FakeResourceStore) Get(resource ccapi.ResourceType, obj interface{}) (item interface{}, exists bool, err error) {
	switch resource {
	case ccapi.Pods:
		return findResource(obj, s.PodsData())
	case ccapi.Services:
		return findResource(obj, s.ServicesData())
	case ccapi.ReplicationControllers:
		return findResource(obj, s.ReplicationControllersData())
	case ccapi.Nodes:
		return findResource(obj, s.NodesData())
	case ccapi.PersistentVolumes:
		return findResource(obj, s.PersistentVolumesData())
	case ccapi.PersistentVolumeClaims:
		return findResource(obj, s.PersistentVolumeClaimsData())
		//case "replicasets":
		//	return testReplicaSetsData().Items
	}
	return nil, false, nil
}

func (s *FakeResourceStore) GetByKey(key string) (item interface{}, exists bool, err error) {
	return nil, false, nil
}

func (s *FakeResourceStore) RegisterEventHandler(resource ccapi.ResourceType, handler cache.ResourceEventHandler) error {
	return nil
}

func (s *FakeResourceStore) Replace(resource ccapi.ResourceType, items []interface{}, resourceVersion string) error {
	return nil
}

func (s *FakeResourceStore) Resources() []ccapi.ResourceType {
	return []ccapi.ResourceType{ccapi.Pods, ccapi.Services, ccapi.ReplicationControllers, ccapi.Nodes, ccapi.PersistentVolumes, ccapi.PersistentVolumeClaims}
}
<|endoftext|>