<commit_before>// Copyright 2016 tsuru-autoscale 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 web

import (
	"fmt"
	"net/http"

	"github.com/ajg/form"
	"github.com/gorilla/mux"
	"github.com/tsuru/tsuru-autoscale/action"
	"github.com/tsuru/tsuru-autoscale/alarm"
	"github.com/tsuru/tsuru-autoscale/datasource"
)

func alarmHandler(w http.ResponseWriter, r *http.Request) error {
	a, err := alarm.FindAlarmBy(nil)
	if err != nil {
		return err
	}
	return render(w, "web/templates/alarm/list.html", a)
}

func alarmDetailHandler(w http.ResponseWriter, r *http.Request) error {
	vars := mux.Vars(r)
	a, err := alarm.FindAlarmByName(vars["name"])
	if err != nil {
		return err
	}
	ds, err := datasource.FindBy(nil)
	if err != nil {
		return err
	}
	actions, err := action.All()
	if err != nil {
		return err
	}
	context := struct {
		DataSources []datasource.DataSource
		Actions     []action.Action
		Alarm       *alarm.Alarm
	}{
		ds,
		actions,
		a,
	}
	return render(w, "web/templates/alarm/detail.html", context)
}

func alarmAdd(w http.ResponseWriter, r *http.Request) error {
	if r.Method == http.MethodPost {
		err := r.ParseForm()
		if err != nil {
			return err
		}
		ds := []string{}
		for _, d := range r.Form["datasources"] {
			ds = append(ds, d)
		}
		r.Form.Del("datasources")
		envs := map[string]string{}
		for i := range r.Form["key"] {
			if r.Form["key"][i] != "" {
				envs[r.Form["key"][i]] = r.Form["value"][i]
			}
		}
		r.Form.Del("key")
		r.Form.Del("value")
		actions := []string{}
		for _, a := range r.Form["actions"] {
			actions = append(actions, a)
		}
		r.Form.Del("actions")
		var a alarm.Alarm
		d := form.NewDecoder(nil)
		d.IgnoreCase(true)
		d.IgnoreUnknownKeys(true)
		err = d.DecodeValues(&a, r.Form)
		if err != nil {
			return err
		}
		a.DataSources = ds
		a.Actions = actions
		a.Envs = envs
		err = alarm.NewAlarm(&a)
		if err != nil {
			return err
		}
		http.Redirect(w, r, "/web/alarm", 302)
		return nil
	}
	ds, err := datasource.FindBy(nil)
	if err != nil {
		return err
	}
	actions, err := action.All()
	if err != nil {
		return err
	}
	context := struct {
		DataSources []datasource.DataSource
		Actions     []action.Action
	}{
		ds,
		actions,
	}
	return render(w, "web/templates/alarm/add.html", context)
}

func alarmRemove(w http.ResponseWriter, r *http.Request) error {
	vars := mux.Vars(r)
	a, err := alarm.FindAlarmByName(vars["name"])
	if err != nil {
		return err
	}
	err = alarm.RemoveAlarm(a)
	if err != nil {
		return err
	}
	http.Redirect(w, r, "/web/alarm", 302)
	return nil
}

func alarmEnable(w http.ResponseWriter, r *http.Request) error {
	vars := mux.Vars(r)
	a, err := alarm.FindAlarmByName(vars["name"])
	if err != nil {
		return err
	}
	err = alarm.Enable(a)
	if err != nil {
		return err
	}
	http.Redirect(w, r, fmt.Sprintf("/web/alarm/%s", vars["name"]), 302)
	return nil
}

func alarmDisable(w http.ResponseWriter, r *http.Request) error {
	vars := mux.Vars(r)
	a, err := alarm.FindAlarmByName(vars["name"])
	if err != nil {
		return err
	}
	err = alarm.Disable(a)
	if err != nil {
		return err
	}
	http.Redirect(w, r, fmt.Sprintf("/web/alarm/%s", vars["name"]), 302)
	return nil
}

func alarmEdit(w http.ResponseWriter, r *http.Request) error {
	err := r.ParseForm()
	if err != nil {
		return err
	}
	ds := []string{}
	for _, d := range r.Form["datasources"] {
		ds = append(ds, d)
	}
	r.Form.Del("datasources")
	envs := map[string]string{}
	for i := range r.Form["key"] {
		if r.Form["key"][i] != "" {
			envs[r.Form["key"][i]] = r.Form["value"][i]
		}
	}
	r.Form.Del("key")
	r.Form.Del("value")
	actions := []string{}
	for _, a := range r.Form["actions"] {
		actions = append(actions, a)
	}
	r.Form.Del("actions")
	d := form.NewDecoder(nil)
	d.IgnoreCase(true)
	d.IgnoreUnknownKeys(true)
	var a alarm.Alarm
	err = d.DecodeValues(&a, r.Form)
	if err != nil {
		return err
	}
	a.DataSources = ds
	a.Actions = actions
	a.Envs = envs
	oldAlarm, err := alarm.FindAlarmByName(a.Name)
	if err != nil {
		return err
	}
	a.Instance = oldAlarm.Instance
	err = alarm.UpdateAlarm(&a)
	if err != nil {
		return err
	}
	http.Redirect(w, r, "/web/alarm", 302)
	return nil
}
<commit_msg>web/alarm: edit redirect to the alarm page<commit_after>// Copyright 2016 tsuru-autoscale 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 web

import (
	"fmt"
	"net/http"

	"github.com/ajg/form"
	"github.com/gorilla/mux"
	"github.com/tsuru/tsuru-autoscale/action"
	"github.com/tsuru/tsuru-autoscale/alarm"
	"github.com/tsuru/tsuru-autoscale/datasource"
)

func alarmHandler(w http.ResponseWriter, r *http.Request) error {
	a, err := alarm.FindAlarmBy(nil)
	if err != nil {
		return err
	}
	return render(w, "web/templates/alarm/list.html", a)
}

func alarmDetailHandler(w http.ResponseWriter, r *http.Request) error {
	vars := mux.Vars(r)
	a, err := alarm.FindAlarmByName(vars["name"])
	if err != nil {
		return err
	}
	ds, err := datasource.FindBy(nil)
	if err != nil {
		return err
	}
	actions, err := action.All()
	if err != nil {
		return err
	}
	context := struct {
		DataSources []datasource.DataSource
		Actions     []action.Action
		Alarm       *alarm.Alarm
	}{
		ds,
		actions,
		a,
	}
	return render(w, "web/templates/alarm/detail.html", context)
}

func alarmAdd(w http.ResponseWriter, r *http.Request) error {
	if r.Method == http.MethodPost {
		err := r.ParseForm()
		if err != nil {
			return err
		}
		ds := []string{}
		for _, d := range r.Form["datasources"] {
			ds = append(ds, d)
		}
		r.Form.Del("datasources")
		envs := map[string]string{}
		for i := range r.Form["key"] {
			if r.Form["key"][i] != "" {
				envs[r.Form["key"][i]] = r.Form["value"][i]
			}
		}
		r.Form.Del("key")
		r.Form.Del("value")
		actions := []string{}
		for _, a := range r.Form["actions"] {
			actions = append(actions, a)
		}
		r.Form.Del("actions")
		var a alarm.Alarm
		d := form.NewDecoder(nil)
		d.IgnoreCase(true)
		d.IgnoreUnknownKeys(true)
		err = d.DecodeValues(&a, r.Form)
		if err != nil {
			return err
		}
		a.DataSources = ds
		a.Actions = actions
		a.Envs = envs
		err = alarm.NewAlarm(&a)
		if err != nil {
			return err
		}
		http.Redirect(w, r, "/web/alarm", 302)
		return nil
	}
	ds, err := datasource.FindBy(nil)
	if err != nil {
		return err
	}
	actions, err := action.All()
	if err != nil {
		return err
	}
	context := struct {
		DataSources []datasource.DataSource
		Actions     []action.Action
	}{
		ds,
		actions,
	}
	return render(w, "web/templates/alarm/add.html", context)
}

func alarmRemove(w http.ResponseWriter, r *http.Request) error {
	vars := mux.Vars(r)
	a, err := alarm.FindAlarmByName(vars["name"])
	if err != nil {
		return err
	}
	err = alarm.RemoveAlarm(a)
	if err != nil {
		return err
	}
	http.Redirect(w, r, "/web/alarm", 302)
	return nil
}

func alarmEnable(w http.ResponseWriter, r *http.Request) error {
	vars := mux.Vars(r)
	a, err := alarm.FindAlarmByName(vars["name"])
	if err != nil {
		return err
	}
	err = alarm.Enable(a)
	if err != nil {
		return err
	}
	http.Redirect(w, r, fmt.Sprintf("/web/alarm/%s", vars["name"]), 302)
	return nil
}

func alarmDisable(w http.ResponseWriter, r *http.Request) error {
	vars := mux.Vars(r)
	a, err := alarm.FindAlarmByName(vars["name"])
	if err != nil {
		return err
	}
	err = alarm.Disable(a)
	if err != nil {
		return err
	}
	http.Redirect(w, r, fmt.Sprintf("/web/alarm/%s", vars["name"]), 302)
	return nil
}

func alarmEdit(w http.ResponseWriter, r *http.Request) error {
	err := r.ParseForm()
	if err != nil {
		return err
	}
	ds := []string{}
	for _, d := range r.Form["datasources"] {
		ds = append(ds, d)
	}
	r.Form.Del("datasources")
	envs := map[string]string{}
	for i := range r.Form["key"] {
		if r.Form["key"][i] != "" {
			envs[r.Form["key"][i]] = r.Form["value"][i]
		}
	}
	r.Form.Del("key")
	r.Form.Del("value")
	actions := []string{}
	for _, a := range r.Form["actions"] {
		actions = append(actions, a)
	}
	r.Form.Del("actions")
	d := form.NewDecoder(nil)
	d.IgnoreCase(true)
	d.IgnoreUnknownKeys(true)
	var a alarm.Alarm
	err = d.DecodeValues(&a, r.Form)
	if err != nil {
		return err
	}
	a.DataSources = ds
	a.Actions = actions
	a.Envs = envs
	oldAlarm, err := alarm.FindAlarmByName(a.Name)
	if err != nil {
		return err
	}
	a.Instance = oldAlarm.Instance
	err = alarm.UpdateAlarm(&a)
	if err != nil {
		return err
	}
	u := fmt.Sprintf("/web/alarm/%s", a.Name)
	http.Redirect(w, r, u, 302)
	return nil
}
<|endoftext|>


<commit_before>package cmd

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"testing"

	"github.com/pachyderm/pachyderm/src/client/pkg/config"
	"github.com/pachyderm/pachyderm/src/client/pkg/require"
	deploycmds "github.com/pachyderm/pachyderm/src/server/pkg/deploy/cmds"
	api "k8s.io/kubernetes/pkg/api/v1"
)

func TestMetricsNormalDeployment(t *testing.T) {
	// Run deploy normally, should see METRICS=true
	testDeploy(t, false, false, true)
}

func TestMetricsNormalDeploymentNoMetricsFlagSet(t *testing.T) {
	// Run deploy normally, should see METRICS=true
	testDeploy(t, false, true, false)
}

func TestMetricsDevDeployment(t *testing.T) {
	// Run deploy w dev flag, should see METRICS=false
	testDeploy(t, true, false, false)
}

func TestMetricsDevDeploymentNoMetricsFlagSet(t *testing.T) {
	// Run deploy w dev flag, should see METRICS=false
	testDeploy(t, true, true, false)
}

func testDeploy(t *testing.T, devFlag bool, noMetrics bool, expectedEnvValue bool) {

	// Setup user config prior to test
	// So that stdout only contains JSON no warnings
	_, err := config.Read()
	require.NoError(t, err)

	fmt.Printf("running testDeploy: dev %v, nometrics %v, expectedval %v\n", devFlag, noMetrics, expectedEnvValue)
	old := os.Stdout
	r, w, _ := os.Pipe()
	os.Stdout = w

	os.Args = []string{
		"deploy",
		"local",
		"--dry-run",
		fmt.Sprintf("-d=%v", devFlag),
	}
	// the noMetrics flag is defined globally, so is undefined on just this command
	// but we can pass it in directly to the command:
	err = deploycmds.DeployCmd(!noMetrics).Execute()
	require.NoError(t, err)
	require.NoError(t, w.Close())
	// restore stdout
	os.Stdout = old

	b := make([]byte, 100000)
	n, err := r.Read(b)
	b = b[0:n]
	jsonReader := bytes.NewBuffer(b)
	fmt.Printf("got result [%v]\n", string(b))

	decoder := json.NewDecoder(jsonReader)
	foundPachdManifest := false
	// Loop through generated manifest until we find a
	// ReplicationController (limit of 100 makes sure test
	// fails quickly if there is no RC)
	for i := 0; i < 100; i++ {
		var manifest *api.ReplicationController
		err = decoder.Decode(&manifest)
		if err == io.EOF {
			fmt.Printf("got EOF\n")
			break
		}
		if err != nil {
			// Not a replication controller
			fmt.Printf("Got error decoding: %v\n", err)
			continue
		}
		require.NoError(t, err)
		fmt.Printf("this manifest obj: %v\n", manifest)
		fmt.Printf("this name: %v\n", manifest.ObjectMeta.Name)
		fmt.Printf("this kind: %v\n\n", manifest.Kind)
		if manifest.ObjectMeta.Name == "pachd" && manifest.Kind == "ReplicationController" {
			foundPachdManifest = true
			expectedMetricEnvVar := api.EnvVar{
				Name:  "METRICS",
				Value: fmt.Sprintf("%v", expectedEnvValue),
			}
			var env []interface{}
			require.Equal(t, 1, len(manifest.Spec.Template.Spec.Containers))
			for _, value := range manifest.Spec.Template.Spec.Containers[0].Env {
				env = append(env, value)
			}
			require.OneOfEquals(t, interface{}(expectedMetricEnvVar), env)
		}
	}
	require.Equal(t, true, foundPachdManifest)
}
<commit_msg>Remove debug statements<commit_after>package cmd

import (
	"encoding/json"
	"fmt"
	"io"
	"os"
	"testing"

	"github.com/pachyderm/pachyderm/src/client/pkg/config"
	"github.com/pachyderm/pachyderm/src/client/pkg/require"
	deploycmds "github.com/pachyderm/pachyderm/src/server/pkg/deploy/cmds"
	api "k8s.io/kubernetes/pkg/api/v1"
)

func TestMetricsNormalDeployment(t *testing.T) {
	// Run deploy normally, should see METRICS=true
	testDeploy(t, false, false, true)
}

func TestMetricsNormalDeploymentNoMetricsFlagSet(t *testing.T) {
	// Run deploy normally, should see METRICS=true
	testDeploy(t, false, true, false)
}

func TestMetricsDevDeployment(t *testing.T) {
	// Run deploy w dev flag, should see METRICS=false
	testDeploy(t, true, false, false)
}

func TestMetricsDevDeploymentNoMetricsFlagSet(t *testing.T) {
	// Run deploy w dev flag, should see METRICS=false
	testDeploy(t, true, true, false)
}

func testDeploy(t *testing.T, devFlag bool, noMetrics bool, expectedEnvValue bool) {

	// Setup user config prior to test
	// So that stdout only contains JSON no warnings
	_, err := config.Read()
	require.NoError(t, err)

	old := os.Stdout
	r, w, _ := os.Pipe()
	os.Stdout = w

	os.Args = []string{
		"deploy",
		"local",
		"--dry-run",
		fmt.Sprintf("-d=%v", devFlag),
	}
	// the noMetrics flag is defined globally, so is undefined on just this command
	// but we can pass it in directly to the command:
	err = deploycmds.DeployCmd(!noMetrics).Execute()
	require.NoError(t, err)
	require.NoError(t, w.Close())
	// restore stdout
	os.Stdout = old

	decoder := json.NewDecoder(r)
	foundPachdManifest := false
	// Loop through generated manifest until we find a
	// ReplicationController (limit of 100 makes sure test
	// fails quickly if there is no RC)
	for i := 0; i < 100; i++ {
		var manifest *api.ReplicationController
		err = decoder.Decode(&manifest)
		if err == io.EOF {
			break
		}
		if err != nil {
			// Not a replication controller
			continue
		}
		require.NoError(t, err)
		if manifest.ObjectMeta.Name == "pachd" && manifest.Kind == "ReplicationController" {
			foundPachdManifest = true
			expectedMetricEnvVar := api.EnvVar{
				Name:  "METRICS",
				Value: fmt.Sprintf("%v", expectedEnvValue),
			}
			var env []interface{}
			require.Equal(t, 1, len(manifest.Spec.Template.Spec.Containers))
			for _, value := range manifest.Spec.Template.Spec.Containers[0].Env {
				env = append(env, value)
			}
			require.OneOfEquals(t, interface{}(expectedMetricEnvVar), env)
		}
	}
	require.Equal(t, true, foundPachdManifest)
}
<|endoftext|>


<commit_before>package query

import "strings"

// Token represents a lexical token.
type Token int

const (
	ILLEGAL Token = iota // Illegal tokens
	EOF                  // End-of-file
	WS                   // Whitespace
	COLON                // ;

	// Search terms
	STRING // search fields terms

	keywordBeg

	AND // AND boolean
	OR  // OR boolean
	NOT // NOT boolean

	keywordEnd

	LPAREN // (
	RPAREN // )

)

var tokens = [...]string{
	ILLEGAL: "ILLEGAL",
	EOF:     "EOF",
	WS:      "WS",
	COLON:   ":",

	AND: "AND",
	OR:  "OR",
	NOT: "NOT",

	LPAREN: "(",
	RPAREN: ")",
}

var keywords map[string]Token

func init() {
	keywords = make(map[string]Token)
	for tok := keywordBeg + 1; tok < keywordEnd; tok++ {
		keywords[strings.ToLower(tokens[tok])] = tok
	}
	for _, tok := range []Token{AND, OR} {
		keywords[strings.ToLower(tokens[tok])] = tok
	}
}

func (t Token) isOperator() bool {
	return t == AND || t == OR || t == NOT
}

// String returns the string representation of the token.
func (t Token) String() string {
	if t >= 0 && t < Token(len(tokens)) {
		return tokens[t]
	}
	return ""
}

// Precedence returns the operator precedence of the binary operator token.
func (t Token) Precedence() int {
	switch t {
	case OR:
		return 1
	case AND:
		return 2
	case NOT:
		return 3
	}
	return 0
}

// Lookup returns the token associated with a given string.
func Lookup(ident string) (Token, bool) {
	if tok, ok := keywords[strings.ToLower(ident)]; ok {
		return tok, true
	}
	return ILLEGAL, false
}

// tokstr returns a literal if provided, otherwise returns the token string.
func tokstr(t Token, lit string) string {
	if lit != "" {
		return lit
	}
	return t.String()
}
<commit_msg>Minor linting<commit_after>package query

import "strings"

// Token represents a lexical token.
type Token int

const (
	ILLEGAL Token = iota // Illegal tokens
	EOF                  // End-of-file
	WS                   // Whitespace
	COLON                // ;

	// STRING represents search terms
	STRING // search fields terms

	keywordBeg

	AND // AND boolean
	OR  // OR boolean
	NOT // NOT boolean

	keywordEnd

	LPAREN // (
	RPAREN // )

)

var tokens = [...]string{
	ILLEGAL: "ILLEGAL",
	EOF:     "EOF",
	WS:      "WS",
	COLON:   ":",

	AND: "AND",
	OR:  "OR",
	NOT: "NOT",

	LPAREN: "(",
	RPAREN: ")",
}

var keywords map[string]Token

func init() {
	keywords = make(map[string]Token)
	for tok := keywordBeg + 1; tok < keywordEnd; tok++ {
		keywords[strings.ToLower(tokens[tok])] = tok
	}
	for _, tok := range []Token{AND, OR} {
		keywords[strings.ToLower(tokens[tok])] = tok
	}
}

func (t Token) isOperator() bool {
	return t == AND || t == OR || t == NOT
}

// String returns the string representation of the token.
func (t Token) String() string {
	if t >= 0 && t < Token(len(tokens)) {
		return tokens[t]
	}
	return ""
}

// Precedence returns the operator precedence of the binary operator token.
func (t Token) Precedence() int {
	switch t {
	case OR:
		return 1
	case AND:
		return 2
	case NOT:
		return 3
	}
	return 0
}

// Lookup returns the token associated with a given string.
func Lookup(ident string) (Token, bool) {
	if tok, ok := keywords[strings.ToLower(ident)]; ok {
		return tok, true
	}
	return ILLEGAL, false
}

// tokstr returns a literal if provided, otherwise returns the token string.
func tokstr(t Token, lit string) string {
	if lit != "" {
		return lit
	}
	return t.String()
}
<|endoftext|>


<commit_before>package queue

import (
	"sync"
	"time"

	"github.com/satori/go.uuid"
)

// Local implements Interface as an in-memory queue.
//
// No guarantees are made about performance or efficiency.
type Local struct {
	queue         []string
	queueMutex    *sync.Mutex
	messages      map[string][]byte
	messagesMutex *sync.RWMutex
	received      map[string]*time.Timer
	receivedMutex *sync.RWMutex
}

// NewLocal initializes and returns a Local in-memory queue.
func NewLocal() *Local {
	return &Local{
		queue:         []string{},
		queueMutex:    &sync.Mutex{},
		messages:      map[string][]byte{},
		messagesMutex: &sync.RWMutex{},
		received:      map[string]*time.Timer{},
		receivedMutex: &sync.RWMutex{},
	}
}

// SendMessage adds a message to the end of the queue.
func (l *Local) SendMessage(message []byte) error {
	var id string
	l.messagesMutex.Lock()
	// make sure id is truly unique; usually this loop should always finish
	// after the first iteration, but better to be safe than sorry
	for {
		id = uuid.NewV4().String()
		if _, ok := l.messages[id]; !ok {
			break
		}
	}
	l.messages[id] = message
	l.messagesMutex.Unlock()
	l.queueMutex.Lock()
	l.queue = append(l.queue, id)
	l.queueMutex.Unlock()
	return nil
}

// ReceiveMessage receives a message from the head of the queue.
//
// A timeout of 0 (or less) will cause the message to be removed from the queue
// immediately.
//
// A positive timeout will cause the message to appear back at the head of the
// queue once the timeout expires. The returned id should be passed to DeleteMessage
// once the message is processed to remove it from the queue.
func (l *Local) ReceiveMessage(timeout time.Duration) (id string, message []byte, err error) {
	l.queueMutex.Lock()
	if len(l.queue) == 0 {
		err = ErrNoMessages
		l.queueMutex.Unlock()
		return
	}
	l.messagesMutex.RLock()
	// skip/remove any messages that ended up back in the queue after a timeout
	// but were subsequently deleted
	for {
		id, l.queue = l.queue[0], l.queue[1:]
		var ok bool
		if message, ok = l.messages[id]; ok {
			break
		}
	}
	l.messagesMutex.RUnlock()
	l.queueMutex.Unlock()

	if timeout < 1 {
		// delete the message immediately; no need to set timer
		l.messagesMutex.Lock()
		delete(l.messages, id)
		l.messagesMutex.Unlock()
		return
	}

	l.receivedMutex.Lock()
	l.received[id] = time.AfterFunc(timeout, func() {
		l.queueMutex.Lock()
		l.queue = append([]string{id}, l.queue...)
		l.queueMutex.Unlock()

		l.receivedMutex.Lock()
		delete(l.received, id)
		l.receivedMutex.Unlock()
	})
	l.receivedMutex.Unlock()

	return
}

// DeleteMessage removes the message with the passed id from the queue. An invalid
// id (or one for a message that has already been deleted) results in a no-op.
func (l *Local) DeleteMessage(id string) error {
	l.receivedMutex.Lock()
	timer, ok := l.received[id]
	if ok {
		timer.Stop()
		delete(l.received, id)
	}
	l.receivedMutex.Unlock()
	l.messagesMutex.Lock()
	delete(l.messages, id)
	l.messagesMutex.Unlock()
	return nil
}
<commit_msg>Queue: Handle timer corner case<commit_after>package queue

import (
	"sync"
	"time"

	"github.com/satori/go.uuid"
)

// Local implements Interface as an in-memory queue.
//
// No guarantees are made about performance or efficiency.
type Local struct {
	queue         []string
	queueMutex    *sync.Mutex
	messages      map[string][]byte
	messagesMutex *sync.RWMutex
	received      map[string]*time.Timer
	receivedMutex *sync.RWMutex
}

// NewLocal initializes and returns a Local in-memory queue.
func NewLocal() *Local {
	return &Local{
		queue:         []string{},
		queueMutex:    &sync.Mutex{},
		messages:      map[string][]byte{},
		messagesMutex: &sync.RWMutex{},
		received:      map[string]*time.Timer{},
		receivedMutex: &sync.RWMutex{},
	}
}

// SendMessage adds a message to the end of the queue.
func (l *Local) SendMessage(message []byte) error {
	var id string
	l.messagesMutex.Lock()
	// make sure id is truly unique; usually this loop should always finish
	// after the first iteration, but better to be safe than sorry
	for {
		id = uuid.NewV4().String()
		if _, ok := l.messages[id]; !ok {
			break
		}
	}
	l.messages[id] = message
	l.messagesMutex.Unlock()
	l.queueMutex.Lock()
	l.queue = append(l.queue, id)
	l.queueMutex.Unlock()
	return nil
}

// ReceiveMessage receives a message from the head of the queue.
//
// A timeout of 0 (or less) will cause the message to be removed from the queue
// immediately.
//
// A positive timeout will cause the message to appear back at the head of the
// queue once the timeout expires. The returned id should be passed to DeleteMessage
// once the message is processed to remove it from the queue.
func (l *Local) ReceiveMessage(timeout time.Duration) (id string, message []byte, err error) {
	l.queueMutex.Lock()
	if len(l.queue) == 0 {
		err = ErrNoMessages
		l.queueMutex.Unlock()
		return
	}
	l.messagesMutex.RLock()
	// skip/remove any messages that ended up back in the queue after a timeout
	// but were subsequently deleted
	for {
		id, l.queue = l.queue[0], l.queue[1:]
		var ok bool
		if message, ok = l.messages[id]; ok {
			break
		}
	}
	l.messagesMutex.RUnlock()
	l.queueMutex.Unlock()

	if timeout < 1 {
		// delete the message immediately; no need to set timer
		l.messagesMutex.Lock()
		delete(l.messages, id)
		l.messagesMutex.Unlock()
		return
	}

	l.receivedMutex.Lock()
	l.received[id] = time.AfterFunc(timeout, func() {
		l.queueMutex.Lock()
		l.queue = append([]string{id}, l.queue...)
		l.queueMutex.Unlock()

		l.receivedMutex.Lock()
		delete(l.received, id)
		l.receivedMutex.Unlock()
	})
	l.receivedMutex.Unlock()

	return
}

// DeleteMessage removes the message with the passed id from the queue. An invalid
// id (or one for a message that has already been deleted) results in a no-op.
func (l *Local) DeleteMessage(id string) error {
	l.receivedMutex.Lock()
	timer, ok := l.received[id]
	if ok {
		if !timer.Stop() {
			select {
			case <-timer.C:
			default:
			}
		}
		delete(l.received, id)
	}
	l.receivedMutex.Unlock()

	l.messagesMutex.Lock()
	delete(l.messages, id)
	l.messagesMutex.Unlock()
	return nil
}
<|endoftext|>


<commit_before>package v2

import (
	"os"

	"code.cloudfoundry.org/cli/cf/cmd"
	"code.cloudfoundry.org/cli/command"
	"code.cloudfoundry.org/cli/command/flag"
)

type PushCommand struct {
	AppPorts             string                      `long:"app-ports" description:"Comma delimited list of ports the application may listen on" hidden:"true"` //TODO: Custom AppPorts flag
	BuildpackName        string                      `short:"b" description:"Custom buildpack by name (e.g. my-buildpack) or Git URL (e.g. 'https://github.com/cloudfoundry/java-buildpack.git') or Git URL with a branch or tag (e.g. 'https://github.com/cloudfoundry/java-buildpack.git#v3.3.0' for 'v3.3.0' tag). To use built-in buildpacks only, specify 'default' or 'null'"`
	StartupCommand       string                      `short:"c" description:"Startup command, set to null to reset to default start command"`
	Domain               string                      `short:"d" description:"Domain (e.g. example.com)"`
	DockerImage          string                      `long:"docker-image" short:"o" description:"Docker-image to be used (e.g. user/docker-image-name)"`
	DockerUsername       string                      `long:"docker-username" description:"Repository username; used with password from environment variable CF_DOCKER_PASSWORD"`
	PathToManifest       flag.PathWithExistenceCheck `short:"f" description:"Path to manifest"`
	HealthCheckType      flag.HealthCheckType        `long:"health-check-type" short:"u" description:"Application health check type (Default: 'port', 'none' accepted for 'process', 'http' implies endpoint '/')"`
	Hostname             string                      `long:"hostname" short:"n" description:"Hostname (e.g. my-subdomain)"`
	NumInstances         int                         `short:"i" description:"Number of instances"`
	DiskLimit            string                      `short:"k" description:"Disk limit (e.g. 256M, 1024M, 1G)"`
	MemoryLimit          string                      `short:"m" description:"Memory limit (e.g. 256M, 1024M, 1G)"`
	NoHostname           bool                        `long:"no-hostname" description:"Map the root domain to this app"`
	NoManifest           bool                        `long:"no-manifest" description:"Ignore manifest file"`
	NoRoute              bool                        `long:"no-route" description:"Do not map a route to this app and remove routes from previous pushes of this app"`
	NoStart              bool                        `long:"no-start" description:"Do not start an app after pushing"`
	DirectoryPath        flag.PathWithExistenceCheck `short:"p" description:"Path to app directory or to a zip file of the contents of the app directory"`
	RandomRoute          bool                        `long:"random-route" description:"Create a random route for this app"`
	RoutePath            string                      `long:"route-path" description:"Path for the route"`
	Stack                string                      `short:"s" description:"Stack to use (a stack is a pre-built file system, including an operating system, that can run apps)"`
	ApplicationStartTime int                         `short:"t" description:"Time (in seconds) allowed to elapse between starting up an app and the first healthy response from the app"`
	usage                interface{}                 `usage:"cf push APP_NAME [-b BUILDPACK_NAME] [-c COMMAND] [-f MANIFEST_PATH | --no-manifest] [--no-start]\n   [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [-p PATH] [-s STACK] [-t HEALTH_TIMEOUT] [-u (process | port | http)]\n   [--no-route | --random-route | --hostname HOST | --no-hostname] [-d DOMAIN] [--route-path ROUTE_PATH]\n\n   cf push APP_NAME --docker-image [REGISTRY_HOST:PORT/]IMAGE[:TAG] [--docker-username USERNAME]\n   [-c COMMAND] [-f MANIFEST_PATH | --no-manifest] [--no-start]\n   [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [-t HEALTH_TIMEOUT] [-u (process | port | http)]\n   [--no-route | --random-route | --hostname HOST | --no-hostname] [-d DOMAIN] [--route-path ROUTE_PATH]\n\n   cf push -f MANIFEST_WITH_MULTIPLE_APPS_PATH [--no-start]"`
	envCFStagingTimeout  interface{}                 `environmentName:"CF_STAGING_TIMEOUT" environmentDescription:"Max wait time for buildpack staging, in minutes" environmentDefault:"15"`
	envCFStartupTimeout  interface{}                 `environmentName:"CF_STARTUP_TIMEOUT" environmentDescription:"Max wait time for app instance startup, in minutes" environmentDefault:"5"`
	dockerPassword       interface{}                 `environmentName:"CF_DOCKER_PASSWORD" environmentDescription:"Password used for private docker repository"`
	relatedCommands      interface{}                 `related_commands:"apps, create-app-manifest, logs, ssh, start"`
}

func (_ PushCommand) Setup(config command.Config, ui command.UI) error {
	return nil
}

func (_ PushCommand) Execute(args []string) error {
	cmd.Main(os.Getenv("CF_TRACE"), os.Args)
	return nil
}
<commit_msg>added RequiredArgs  AppName to PushCommmand struct<commit_after>package v2

import (
	"os"

	"code.cloudfoundry.org/cli/cf/cmd"
	"code.cloudfoundry.org/cli/command"
	"code.cloudfoundry.org/cli/command/flag"
)

type PushCommand struct {
	RequiredArgs         flag.AppName                `positional-args:"yes"`
	AppPorts             string                      `long:"app-ports" description:"Comma delimited list of ports the application may listen on" hidden:"true"` //TODO: Custom AppPorts flag
	BuildpackName        string                      `short:"b" description:"Custom buildpack by name (e.g. my-buildpack) or Git URL (e.g. 'https://github.com/cloudfoundry/java-buildpack.git') or Git URL with a branch or tag (e.g. 'https://github.com/cloudfoundry/java-buildpack.git#v3.3.0' for 'v3.3.0' tag). To use built-in buildpacks only, specify 'default' or 'null'"`
	StartupCommand       string                      `short:"c" description:"Startup command, set to null to reset to default start command"`
	Domain               string                      `short:"d" description:"Domain (e.g. example.com)"`
	DockerImage          string                      `long:"docker-image" short:"o" description:"Docker-image to be used (e.g. user/docker-image-name)"`
	DockerUsername       string                      `long:"docker-username" description:"Repository username; used with password from environment variable CF_DOCKER_PASSWORD"`
	PathToManifest       flag.PathWithExistenceCheck `short:"f" description:"Path to manifest"`
	HealthCheckType      flag.HealthCheckType        `long:"health-check-type" short:"u" description:"Application health check type (Default: 'port', 'none' accepted for 'process', 'http' implies endpoint '/')"`
	Hostname             string                      `long:"hostname" short:"n" description:"Hostname (e.g. my-subdomain)"`
	NumInstances         int                         `short:"i" description:"Number of instances"`
	DiskLimit            string                      `short:"k" description:"Disk limit (e.g. 256M, 1024M, 1G)"`
	MemoryLimit          string                      `short:"m" description:"Memory limit (e.g. 256M, 1024M, 1G)"`
	NoHostname           bool                        `long:"no-hostname" description:"Map the root domain to this app"`
	NoManifest           bool                        `long:"no-manifest" description:"Ignore manifest file"`
	NoRoute              bool                        `long:"no-route" description:"Do not map a route to this app and remove routes from previous pushes of this app"`
	NoStart              bool                        `long:"no-start" description:"Do not start an app after pushing"`
	DirectoryPath        flag.PathWithExistenceCheck `short:"p" description:"Path to app directory or to a zip file of the contents of the app directory"`
	RandomRoute          bool                        `long:"random-route" description:"Create a random route for this app"`
	RoutePath            string                      `long:"route-path" description:"Path for the route"`
	Stack                string                      `short:"s" description:"Stack to use (a stack is a pre-built file system, including an operating system, that can run apps)"`
	ApplicationStartTime int                         `short:"t" description:"Time (in seconds) allowed to elapse between starting up an app and the first healthy response from the app"`
	usage                interface{}                 `usage:"cf push APP_NAME [-b BUILDPACK_NAME] [-c COMMAND] [-f MANIFEST_PATH | --no-manifest] [--no-start]\n   [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [-p PATH] [-s STACK] [-t HEALTH_TIMEOUT] [-u (process | port | http)]\n   [--no-route | --random-route | --hostname HOST | --no-hostname] [-d DOMAIN] [--route-path ROUTE_PATH]\n\n   cf push APP_NAME --docker-image [REGISTRY_HOST:PORT/]IMAGE[:TAG] [--docker-username USERNAME]\n   [-c COMMAND] [-f MANIFEST_PATH | --no-manifest] [--no-start]\n   [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [-t HEALTH_TIMEOUT] [-u (process | port | http)]\n   [--no-route | --random-route | --hostname HOST | --no-hostname] [-d DOMAIN] [--route-path ROUTE_PATH]\n\n   cf push -f MANIFEST_WITH_MULTIPLE_APPS_PATH [--no-start]"`
	envCFStagingTimeout  interface{}                 `environmentName:"CF_STAGING_TIMEOUT" environmentDescription:"Max wait time for buildpack staging, in minutes" environmentDefault:"15"`
	envCFStartupTimeout  interface{}                 `environmentName:"CF_STARTUP_TIMEOUT" environmentDescription:"Max wait time for app instance startup, in minutes" environmentDefault:"5"`
	dockerPassword       interface{}                 `environmentName:"CF_DOCKER_PASSWORD" environmentDescription:"Password used for private docker repository"`
	relatedCommands      interface{}                 `related_commands:"apps, create-app-manifest, logs, ssh, start"`
}

func (_ PushCommand) Setup(config command.Config, ui command.UI) error {
	return nil
}

func (_ PushCommand) Execute(args []string) error {
	cmd.Main(os.Getenv("CF_TRACE"), os.Args)
	return nil
}
<|endoftext|>


<commit_before>// Package activitystreams provides all the basic ActivityStreams
// implementation needed for Write.as.
package activitystreams

import (
	"time"
)

const (
	Namespace = "https://www.w3.org/ns/activitystreams"
	toPublic  = "https://www.w3.org/ns/activitystreams#Public"
)

var Extensions = map[string]string{
	"sc":              "http://schema.org#",
	"commentsEnabled": "sc:Boolean",
}

// Activity describes actions that have either already occurred, are in the
// process of occurring, or may occur in the future.
type Activity struct {
	BaseObject
	Actor     string    `json:"actor"`
	Published time.Time `json:"published,omitempty"`
	To        []string  `json:"to,omitempty"`
	CC        []string  `json:"cc,omitempty"`
	Object    *Object   `json:"object"`
}

type FollowActivity struct {
	BaseObject
	Actor     string    `json:"actor"`
	Published time.Time `json:"published,omitempty"`
	To        []string  `json:"to,omitempty"`
	CC        []string  `json:"cc,omitempty"`
	Object    string    `json:"object"`
}

// NewCreateActivity builds a basic Create activity that includes the given
// Object and the Object's AttributedTo property as the Actor.
func NewCreateActivity(o *Object) *Activity {
	a := Activity{
		BaseObject: BaseObject{
			Context: []interface{}{
				Namespace,
				Extensions,
			},
			ID:   o.ID,
			Type: "Create",
		},
		Actor:     o.AttributedTo,
		Object:    o,
		Published: o.Published,
	}
	return &a
}

// NewUpdateActivity builds a basic Update activity that includes the given
// Object and the Object's AttributedTo property as the Actor.
func NewUpdateActivity(o *Object) *Activity {
	a := Activity{
		BaseObject: BaseObject{
			Context: []interface{}{
				Namespace,
				Extensions,
			},
			ID:   o.ID,
			Type: "Update",
		},
		Actor:     o.AttributedTo,
		Object:    o,
		Published: o.Published,
	}
	return &a
}

// NewDeleteActivity builds a basic Delete activity that includes the given
// Object and the Object's AttributedTo property as the Actor.
func NewDeleteActivity(o *Object) *Activity {
	a := Activity{
		BaseObject: BaseObject{
			Context: []interface{}{
				Namespace,
			},
			ID:   o.ID,
			Type: "Delete",
		},
		Actor:  o.AttributedTo,
		Object: o,
	}
	return &a
}

// NewFollowActivity builds a basic Follow activity.
func NewFollowActivity(actorIRI, followeeIRI string) *FollowActivity {
	a := FollowActivity{
		BaseObject: BaseObject{
			Context: []interface{}{
				Namespace,
			},
			Type: "Follow",
		},
		Actor:  actorIRI,
		Object: followeeIRI,
	}
	return &a
}

// Object is the primary base type for the Activity Streams vocabulary.
type Object struct {
	BaseObject
	Published    time.Time         `json:"published"`
	Summary      *string           `json:"summary,omitempty"`
	InReplyTo    *string           `json:"inReplyTo"`
	URL          string            `json:"url"`
	AttributedTo string            `json:"attributedTo"`
	To           []string          `json:"to"`
	CC           []string          `json:"cc,omitempty"`
	Name         string            `json:"name,omitempty"`
	Content      string            `json:"content"`
	ContentMap   map[string]string `json:"contentMap,omitempty"`
	Tag          []Tag             `json:"tag"`

	// Extensions
	CommentsEnabled bool `json:"commentsEnabled"`
}

// NewNoteObject creates a basic Note object that includes the public
// namespace in IRIs it's addressed to.
func NewNoteObject() *Object {
	o := Object{
		BaseObject: BaseObject{
			Type: "Note",
		},
		To: []string{
			toPublic,
		},
	}
	return &o
}

// NewArticleObject creates a basic Article object that includes the public
// namespace in IRIs it's addressed to.
func NewArticleObject() *Object {
	o := Object{
		BaseObject: BaseObject{
			Type: "Article",
		},
		To: []string{
			toPublic,
		},
	}
	return &o
}
<commit_msg>Remove commentsEnabled AP extension<commit_after>// Package activitystreams provides all the basic ActivityStreams
// implementation needed for Write.as.
package activitystreams

import (
	"time"
)

const (
	Namespace = "https://www.w3.org/ns/activitystreams"
	toPublic  = "https://www.w3.org/ns/activitystreams#Public"
)

var Extensions = map[string]string{}

// Activity describes actions that have either already occurred, are in the
// process of occurring, or may occur in the future.
type Activity struct {
	BaseObject
	Actor     string    `json:"actor"`
	Published time.Time `json:"published,omitempty"`
	To        []string  `json:"to,omitempty"`
	CC        []string  `json:"cc,omitempty"`
	Object    *Object   `json:"object"`
}

type FollowActivity struct {
	BaseObject
	Actor     string    `json:"actor"`
	Published time.Time `json:"published,omitempty"`
	To        []string  `json:"to,omitempty"`
	CC        []string  `json:"cc,omitempty"`
	Object    string    `json:"object"`
}

// NewCreateActivity builds a basic Create activity that includes the given
// Object and the Object's AttributedTo property as the Actor.
func NewCreateActivity(o *Object) *Activity {
	a := Activity{
		BaseObject: BaseObject{
			Context: []interface{}{
				Namespace,
				Extensions,
			},
			ID:   o.ID,
			Type: "Create",
		},
		Actor:     o.AttributedTo,
		Object:    o,
		Published: o.Published,
	}
	return &a
}

// NewUpdateActivity builds a basic Update activity that includes the given
// Object and the Object's AttributedTo property as the Actor.
func NewUpdateActivity(o *Object) *Activity {
	a := Activity{
		BaseObject: BaseObject{
			Context: []interface{}{
				Namespace,
				Extensions,
			},
			ID:   o.ID,
			Type: "Update",
		},
		Actor:     o.AttributedTo,
		Object:    o,
		Published: o.Published,
	}
	return &a
}

// NewDeleteActivity builds a basic Delete activity that includes the given
// Object and the Object's AttributedTo property as the Actor.
func NewDeleteActivity(o *Object) *Activity {
	a := Activity{
		BaseObject: BaseObject{
			Context: []interface{}{
				Namespace,
			},
			ID:   o.ID,
			Type: "Delete",
		},
		Actor:  o.AttributedTo,
		Object: o,
	}
	return &a
}

// NewFollowActivity builds a basic Follow activity.
func NewFollowActivity(actorIRI, followeeIRI string) *FollowActivity {
	a := FollowActivity{
		BaseObject: BaseObject{
			Context: []interface{}{
				Namespace,
			},
			Type: "Follow",
		},
		Actor:  actorIRI,
		Object: followeeIRI,
	}
	return &a
}

// Object is the primary base type for the Activity Streams vocabulary.
type Object struct {
	BaseObject
	Published    time.Time         `json:"published"`
	Summary      *string           `json:"summary,omitempty"`
	InReplyTo    *string           `json:"inReplyTo"`
	URL          string            `json:"url"`
	AttributedTo string            `json:"attributedTo"`
	To           []string          `json:"to"`
	CC           []string          `json:"cc,omitempty"`
	Name         string            `json:"name,omitempty"`
	Content      string            `json:"content"`
	ContentMap   map[string]string `json:"contentMap,omitempty"`
	Tag          []Tag             `json:"tag"`

	// Extensions
	// NOTE: add extensions here
}

// NewNoteObject creates a basic Note object that includes the public
// namespace in IRIs it's addressed to.
func NewNoteObject() *Object {
	o := Object{
		BaseObject: BaseObject{
			Type: "Note",
		},
		To: []string{
			toPublic,
		},
	}
	return &o
}

// NewArticleObject creates a basic Article object that includes the public
// namespace in IRIs it's addressed to.
func NewArticleObject() *Object {
	o := Object{
		BaseObject: BaseObject{
			Type: "Article",
		},
		To: []string{
			toPublic,
		},
	}
	return &o
}
<|endoftext|>


<commit_before>package slack

import (
	"encoding/json"
	"errors"
	"io"
	"log"
	"net"
	"net/url"
	"sync"
	"time"

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

const (
	EV_MESSAGE = iota
	EV_USER_TYPING
)

type SlackWS struct {
	conn      *websocket.Conn
	messageId int
	mutex     sync.Mutex
	Slack
}

var portMapping = map[string]string{"ws": "80", "wss": "443"}

func fixUrlPort(orig string) (string, error) {
	urlObj, err := url.ParseRequestURI(orig)
	if err != nil {
		return "", err
	}
	_, _, err = net.SplitHostPort(urlObj.Host)
	if err != nil {
		return urlObj.Scheme + "://" + urlObj.Host + ":" + portMapping[urlObj.Scheme] + urlObj.Path, nil
	}
	return orig, nil
}

func (api *Slack) StartRTM(protocol, origin string) (*SlackWS, error) {
	response := &infoResponseFull{}
	err := parseResponse("rtm.start", url.Values{"token": {api.config.token}}, response, api.debug)
	if err != nil {
		return nil, err
	}
	if !response.Ok {
		return nil, errors.New(response.Error)
	}
	api.info = response.Info
	// websocket.Dial does not accept url without the port (yet)
	// Fixed by: https://github.com/golang/net/commit/5058c78c3627b31e484a81463acd51c7cecc06f3
	// but slack returns the address with no port, so we have to fix it
	api.info.Url, err = fixUrlPort(api.info.Url)
	if err != nil {
		return nil, err
	}
	api.config.protocol, api.config.origin = protocol, origin
	wsApi := &SlackWS{Slack: *api}
	wsApi.conn, err = websocket.Dial(api.info.Url, api.config.protocol, api.config.origin)
	if err != nil {
		return nil, err
	}
	return wsApi, nil
}

func (api *SlackWS) Ping() error {
	api.mutex.Lock()
	defer api.mutex.Unlock()
	api.messageId++
	msg := &Ping{Id: api.messageId, Type: "ping"}
	if err := websocket.JSON.Send(api.conn, msg); err != nil {
		return err
	}
	return nil
}

func (api *SlackWS) Keepalive(interval time.Duration) {
	ticker := time.NewTicker(interval)

	for {
		select {
		case <-ticker.C:
			if err := api.Ping(); err != nil {
				log.Fatal(err)
			}
		}
	}
}

func (api *SlackWS) SendMessage(msg OutgoingMessage) error {
	if err := websocket.JSON.Send(api.conn, msg); err != nil {
		return err
	}
	return nil
}

func (api *SlackWS) HandleIncomingEvents(ch *chan SlackEvent) {
	event := json.RawMessage{}
	for {
		if err := websocket.JSON.Receive(api.conn, &event); err == io.EOF {
			//log.Println("Derpi derp, should we destroy conn and start over?")
			//if err = api.StartRTM(); err != nil {
			//	log.Fatal(err)
			//}
			// should we reconnect here?
			if !api.conn.IsClientConn() {
				api.conn, err = websocket.Dial(api.info.Url, api.config.protocol, api.config.origin)
				if err != nil {
					log.Panic(err)
				}
			}
			// XXX: check for timeout and implement exponential backoff
		} else if err != nil {
			log.Panic(err)
		}
		if len(event) == 0 {
			log.Println("Event Empty. WTF?")
		} else {
			if api.debug {
				log.Println(string(event[:]))
			}
			handleEvent(ch, event)
		}
		time.Sleep(time.Millisecond * 500)
	}
}

func handleEvent(ch *chan SlackEvent, event json.RawMessage) {
	em := Event{}
	err := json.Unmarshal(event, &em)
	if err != nil {
		log.Fatal(err)
	}
	switch em.Type {
	case "":
		// try ok
		ack := AckMessage{}
		if err = json.Unmarshal(event, &ack); err != nil {
			log.Fatal(err)
		}
		if ack.Ok {
			log.Printf("Received an ok for: %d", ack.ReplyTo)
		} else {
			log.Println(event)
			log.Println("XXX: ?")
		}
	case "hello":
		return
	case "pong":
		// XXX: Eventually check to which ping this matched with
		//      Allows us to have stats about latency and what not
		return
	case "presence_change":
		//log.Printf("`%s is %s`\n", info.GetUserById(event.PUserId).Name, event.Presence)
	case "message":
		handleMessage(ch, event)
	case "channel_marked":
		log.Printf("XXX: To implement %s", em)
	case "user_typing":
		handleUserTyping(ch, event)
	default:
		log.Println("XXX: " + string(event))
	}
}

func handleUserTyping(ch *chan SlackEvent, event json.RawMessage) {
	msg := UserTyping{}
	if err := json.Unmarshal(event, &msg); err != nil {
		log.Fatal(err)
	}
	*ch <- SlackEvent{Type: EV_USER_TYPING, Data: msg}
}

func handleMessage(ch *chan SlackEvent, event json.RawMessage) {
	msg := Message{}
	err := json.Unmarshal(event, &msg)
	if err != nil {
		log.Fatal(err)
	}
	*ch <- SlackEvent{Type: EV_MESSAGE, Data: msg}
}
<commit_msg>Adjust SendMessage to take a pointer.<commit_after>package slack

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"log"
	"net"
	"net/url"
	"sync"
	"time"

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

const (
	EV_MESSAGE = iota
	EV_USER_TYPING
)

type SlackWS struct {
	conn      *websocket.Conn
	messageId int
	mutex     sync.Mutex
	Slack
}

var portMapping = map[string]string{"ws": "80", "wss": "443"}

func fixUrlPort(orig string) (string, error) {
	urlObj, err := url.ParseRequestURI(orig)
	if err != nil {
		return "", err
	}
	_, _, err = net.SplitHostPort(urlObj.Host)
	if err != nil {
		return urlObj.Scheme + "://" + urlObj.Host + ":" + portMapping[urlObj.Scheme] + urlObj.Path, nil
	}
	return orig, nil
}

func (api *Slack) StartRTM(protocol, origin string) (*SlackWS, error) {
	response := &infoResponseFull{}
	err := parseResponse("rtm.start", url.Values{"token": {api.config.token}}, response, api.debug)
	if err != nil {
		return nil, err
	}
	if !response.Ok {
		return nil, errors.New(response.Error)
	}
	api.info = response.Info
	// websocket.Dial does not accept url without the port (yet)
	// Fixed by: https://github.com/golang/net/commit/5058c78c3627b31e484a81463acd51c7cecc06f3
	// but slack returns the address with no port, so we have to fix it
	api.info.Url, err = fixUrlPort(api.info.Url)
	if err != nil {
		return nil, err
	}
	api.config.protocol, api.config.origin = protocol, origin
	wsApi := &SlackWS{Slack: *api}
	wsApi.conn, err = websocket.Dial(api.info.Url, api.config.protocol, api.config.origin)
	if err != nil {
		return nil, err
	}
	return wsApi, nil
}

func (api *SlackWS) Ping() error {
	api.mutex.Lock()
	defer api.mutex.Unlock()
	api.messageId++
	msg := &Ping{Id: api.messageId, Type: "ping"}
	if err := websocket.JSON.Send(api.conn, msg); err != nil {
		return err
	}
	return nil
}

func (api *SlackWS) Keepalive(interval time.Duration) {
	ticker := time.NewTicker(interval)

	for {
		select {
		case <-ticker.C:
			if err := api.Ping(); err != nil {
				log.Fatal(err)
			}
		}
	}
}

func (api *SlackWS) SendMessage(msg *OutgoingMessage) error {
	if msg == nil {
		return fmt.Errorf("Can't send a nil message")
	}

	if err := websocket.JSON.Send(api.conn, *msg); err != nil {
		return err
	}
	return nil
}

func (api *SlackWS) HandleIncomingEvents(ch *chan SlackEvent) {
	event := json.RawMessage{}
	for {
		if err := websocket.JSON.Receive(api.conn, &event); err == io.EOF {
			//log.Println("Derpi derp, should we destroy conn and start over?")
			//if err = api.StartRTM(); err != nil {
			//	log.Fatal(err)
			//}
			// should we reconnect here?
			if !api.conn.IsClientConn() {
				api.conn, err = websocket.Dial(api.info.Url, api.config.protocol, api.config.origin)
				if err != nil {
					log.Panic(err)
				}
			}
			// XXX: check for timeout and implement exponential backoff
		} else if err != nil {
			log.Panic(err)
		}
		if len(event) == 0 {
			log.Println("Event Empty. WTF?")
		} else {
			if api.debug {
				log.Println(string(event[:]))
			}
			handleEvent(ch, event)
		}
		time.Sleep(time.Millisecond * 500)
	}
}

func handleEvent(ch *chan SlackEvent, event json.RawMessage) {
	em := Event{}
	err := json.Unmarshal(event, &em)
	if err != nil {
		log.Fatal(err)
	}
	switch em.Type {
	case "":
		// try ok
		ack := AckMessage{}
		if err = json.Unmarshal(event, &ack); err != nil {
			log.Fatal(err)
		}
		if ack.Ok {
			log.Printf("Received an ok for: %d", ack.ReplyTo)
		} else {
			log.Println(event)
			log.Println("XXX: ?")
		}
	case "hello":
		return
	case "pong":
		// XXX: Eventually check to which ping this matched with
		//      Allows us to have stats about latency and what not
		return
	case "presence_change":
		//log.Printf("`%s is %s`\n", info.GetUserById(event.PUserId).Name, event.Presence)
	case "message":
		handleMessage(ch, event)
	case "channel_marked":
		log.Printf("XXX: To implement %s", em)
	case "user_typing":
		handleUserTyping(ch, event)
	default:
		log.Println("XXX: " + string(event))
	}
}

func handleUserTyping(ch *chan SlackEvent, event json.RawMessage) {
	msg := UserTyping{}
	if err := json.Unmarshal(event, &msg); err != nil {
		log.Fatal(err)
	}
	*ch <- SlackEvent{Type: EV_USER_TYPING, Data: msg}
}

func handleMessage(ch *chan SlackEvent, event json.RawMessage) {
	msg := Message{}
	err := json.Unmarshal(event, &msg)
	if err != nil {
		log.Fatal(err)
	}
	*ch <- SlackEvent{Type: EV_MESSAGE, Data: msg}
}
<|endoftext|>


<commit_before>package net

import (
	"encoding/json"
	"fmt"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"io/ioutil"
	"net/http"
	"strings"
)

type JSONMapRequest map[string]interface{}

func (json *JSONMapRequest) String() string {
	return fmt.Sprintf("%#v", *json)
}

type JSONArrayRequest []interface{}

func (json *JSONArrayRequest) String() string {
	return fmt.Sprintf("%#v", *json)
}

func bytesToInterface(jsonBytes []byte) (interface{}, error) {
	mapResult := &JSONMapRequest{}
	err := json.Unmarshal(jsonBytes, mapResult)
	if err == nil {
		return mapResult, err
	}

	arrayResult := &JSONArrayRequest{}
	err = json.Unmarshal(jsonBytes, arrayResult)
	return arrayResult, err
}

func RequestBodyMatcher(expectedBodyString string) RequestMatcher {
	return func(request *http.Request) {
		bodyBytes, err := ioutil.ReadAll(request.Body)
		if err != nil {
			Fail(fmt.Sprintf("Error reading request body: %s", err))
		}

		actualBody, err := bytesToInterface(bodyBytes)
		if err != nil {
			Fail(fmt.Sprintf("Error unmarshalling request", err.Error()))
		}

		expectedBody, err := bytesToInterface([]byte(expectedBodyString))
		if err != nil {
			Fail(fmt.Sprintf("Error unmarshalling expected json", err.Error()))
		}

		Expect(expectedBody).To(Equal(actualBody), "\nEXPECTED: %s\nACTUAL: %s", expectedBody, actualBody)
		Expect(request.Header.Get("content-type")).To(Equal("application/json"), "Content Type was not application/json.")
	}
}

func RequestBodyMatcherWithContentType(expectedBody, expectedContentType string) RequestMatcher {
	return func(request *http.Request) {
		bodyBytes, err := ioutil.ReadAll(request.Body)
		if err != nil {
			Fail(fmt.Sprintf("Error reading request body: %s", err))
		}

		actualBody := string(bodyBytes)
		Expect(RemoveWhiteSpaceFromBody(actualBody)).To(Equal(RemoveWhiteSpaceFromBody(expectedBody)), "Body did not match.")

		actualContentType := request.Header.Get("content-type")
		Expect(actualContentType).To(Equal(expectedContentType), "Content Type did not match.")
	}
}

func RemoveWhiteSpaceFromBody(body string) string {
	body = strings.Replace(body, " ", "", -1)
	body = strings.Replace(body, "\n", "", -1)
	body = strings.Replace(body, "\r", "", -1)
	body = strings.Replace(body, "\t", "", -1)
	return body
}
<commit_msg>GinkgoRecover() in goroutines<commit_after>package net

import (
	"encoding/json"
	"fmt"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"io/ioutil"
	"net/http"
	"strings"
)

type JSONMapRequest map[string]interface{}

func (json *JSONMapRequest) String() string {
	return fmt.Sprintf("%#v", *json)
}

type JSONArrayRequest []interface{}

func (json *JSONArrayRequest) String() string {
	return fmt.Sprintf("%#v", *json)
}

func bytesToInterface(jsonBytes []byte) (interface{}, error) {
	mapResult := &JSONMapRequest{}
	err := json.Unmarshal(jsonBytes, mapResult)
	if err == nil {
		return mapResult, err
	}

	arrayResult := &JSONArrayRequest{}
	err = json.Unmarshal(jsonBytes, arrayResult)
	return arrayResult, err
}

func RequestBodyMatcher(expectedBodyString string) RequestMatcher {
	return func(request *http.Request) {
		defer GinkgoRecover()
		bodyBytes, err := ioutil.ReadAll(request.Body)
		if err != nil {
			Fail(fmt.Sprintf("Error reading request body: %s", err))
		}

		actualBody, err := bytesToInterface(bodyBytes)
		if err != nil {
			Fail(fmt.Sprintf("Error unmarshalling request", err.Error()))
		}

		expectedBody, err := bytesToInterface([]byte(expectedBodyString))
		if err != nil {
			Fail(fmt.Sprintf("Error unmarshalling expected json", err.Error()))
		}

		Expect(expectedBody).To(Equal(actualBody), "\nEXPECTED: %s\nACTUAL: %s", expectedBody, actualBody)
		Expect(request.Header.Get("content-type")).To(Equal("application/json"), "Content Type was not application/json.")
	}
}

func RequestBodyMatcherWithContentType(expectedBody, expectedContentType string) RequestMatcher {
	return func(request *http.Request) {
		defer GinkgoRecover()
		bodyBytes, err := ioutil.ReadAll(request.Body)
		if err != nil {
			Fail(fmt.Sprintf("Error reading request body: %s", err))
		}

		actualBody := string(bodyBytes)
		Expect(RemoveWhiteSpaceFromBody(actualBody)).To(Equal(RemoveWhiteSpaceFromBody(expectedBody)), "Body did not match.")

		actualContentType := request.Header.Get("content-type")
		Expect(actualContentType).To(Equal(expectedContentType), "Content Type did not match.")
	}
}

func RemoveWhiteSpaceFromBody(body string) string {
	body = strings.Replace(body, " ", "", -1)
	body = strings.Replace(body, "\n", "", -1)
	body = strings.Replace(body, "\r", "", -1)
	body = strings.Replace(body, "\t", "", -1)
	return body
}
<|endoftext|>


<commit_before>package yenc

import (
	"bytes"
	"encoding/hex"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"testing"
)

func TestDecoder(t *testing.T) {
	encoded, err := os.Open("./test/00000005.ntx")

	if err != nil {
		t.Fatalf("could not begin test: ntx file not readable")
	}

	unencoded, err := ioutil.ReadFile("./test/testfile.txt")

	if err != nil {
		t.Fatalf("could not read unencoded test file")
	}

	decBytes, err := ioutil.ReadAll(NewReader(encoded))

	if err != nil {
		t.Fatalf("Error reading decoded bytes: %v", err)
	}

	if !bytes.Equal(decBytes, unencoded) {
		fmt.Println(hex.Dump(decBytes))

		diff := getDiff(unencoded, decBytes)
		t.Errorf("Decoded bytes did not equal unencoded bytes. Diff was %d long; dec was %d long", len(diff), len(decBytes))
	}
}

func BenchmarkDecoder(b *testing.B) {
	encoded, err := os.Open("./test/00000005.ntx")

	if err != nil {
		b.Fatalf("could not begin test: ntx file not readable")
	}

	bs, err := ioutil.ReadAll(encoded)
	if err != nil {
		log.Fatal(err)
	}

	buf := bytes.NewBuffer(bs)

	empty := make([]byte, 2<<20)

	b.SetBytes(int64(len(bs)))

	for i := 0; i < b.N; i++ {
		NewReader(buf).Read(empty)
	}
}

func getDiff(b1, b2 []byte) []byte {
	b1c := make([]byte, len(b1))
	copy(b1c, b1)

	b2c := make([]byte, len(b2))
	copy(b2c, b2)

	for len(b1c) > 0 && len(b2c) > 0 && b1c[0] == b2c[0] {
		b1c = b1c[1:]
		b2c = b2c[1:]
	}

	if len(b1c) > 0 {
		return b1c
	}

	return b2c
}
<commit_msg>Make benchmark show actual performance and report errors<commit_after>package yenc

import (
	"bytes"
	"encoding/hex"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"testing"
)

func TestDecoder(t *testing.T) {
	encoded, err := os.Open("./test/00000005.ntx")

	if err != nil {
		t.Fatalf("could not begin test: ntx file not readable")
	}

	unencoded, err := ioutil.ReadFile("./test/testfile.txt")

	if err != nil {
		t.Fatalf("could not read unencoded test file")
	}

	decBytes, err := ioutil.ReadAll(NewReader(encoded))

	if err != nil {
		t.Fatalf("Error reading decoded bytes: %v", err)
	}

	if !bytes.Equal(decBytes, unencoded) {
		fmt.Println(hex.Dump(decBytes))

		diff := getDiff(unencoded, decBytes)
		t.Errorf("Decoded bytes did not equal unencoded bytes. Diff was %d long; dec was %d long", len(diff), len(decBytes))
	}
}

func BenchmarkDecoder(b *testing.B) {
	encoded, err := ioutil.ReadFile("./test/00000005.ntx")

	if err != nil {
		b.Fatalf("could not begin test: ntx file not readable")
	}

	empty := make([]byte, 2<<20)

	b.SetBytes(int64(len(encoded)))

	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			buf := bytes.NewReader(encoded)
			n, err := NewReader(buf).Read(empty)

			if err != nil && err != io.EOF {
				b.Fatal(err)
			}
			if n == 0 {
				b.Fatal("Didn't read anything")
			}
		}
	})
}

func getDiff(b1, b2 []byte) []byte {
	b1c := make([]byte, len(b1))
	copy(b1c, b1)

	b2c := make([]byte, len(b2))
	copy(b2c, b2)

	for len(b1c) > 0 && len(b2c) > 0 && b1c[0] == b2c[0] {
		b1c = b1c[1:]
		b2c = b2c[1:]
	}

	if len(b1c) > 0 {
		return b1c
	}

	return b2c
}
<|endoftext|>


<commit_before>// +build all integration

package gocql

import (
	"fmt"
	"reflect"
	"sort"
	"gopkg.in/inf.v0"
	"testing"
	"time"
)

type WikiPage struct {
	Title       string
	RevId       UUID
	Body        string
	Views       int64
	Protected   bool
	Modified    time.Time
	Rating      *inf.Dec
	Tags        []string
	Attachments map[string]WikiAttachment
}

type WikiAttachment []byte

var wikiTestData = []*WikiPage{
	&WikiPage{
		Title:    "Frontpage",
		RevId:    TimeUUID(),
		Body:     "Welcome to this wiki page!",
		Rating:   inf.NewDec(131, 3),
		Modified: time.Date(2013, time.August, 13, 9, 52, 3, 0, time.UTC),
		Tags:     []string{"start", "important", "test"},
		Attachments: map[string]WikiAttachment{
			"logo":    WikiAttachment("\x00company logo\x00"),
			"favicon": WikiAttachment("favicon.ico"),
		},
	},
	&WikiPage{
		Title:    "Foobar",
		RevId:    TimeUUID(),
		Body:     "foo::Foo f = new foo::Foo(foo::Foo::INIT);",
		Modified: time.Date(2013, time.August, 13, 9, 52, 3, 0, time.UTC),
	},
}

type WikiTest struct {
	session *Session
	tb      testing.TB
}

func (w *WikiTest) CreateSchema() {

	if err := w.session.Query(`DROP TABLE wiki_page`).Exec(); err != nil && err.Error() != "unconfigured columnfamily wiki_page" {
		w.tb.Fatal("CreateSchema:", err)
	}
	err := createTable(w.session, `CREATE TABLE wiki_page (
			title       varchar,
			revid       timeuuid,
			body        varchar,
			views       bigint,
			protected   boolean,
			modified    timestamp,
			rating      decimal,
			tags        set<varchar>,
			attachments map<varchar, blob>,
			PRIMARY KEY (title, revid)
		)`)
	if *clusterSize > 1 {
		// wait for table definition to propogate
		time.Sleep(250 * time.Millisecond)
	}
	if err != nil {
		w.tb.Fatal("CreateSchema:", err)
	}
}

func (w *WikiTest) CreatePages(n int) {
	var page WikiPage
	t0 := time.Now()
	for i := 0; i < n; i++ {
		page.Title = fmt.Sprintf("generated_%d", (i&16)+1)
		page.Modified = t0.Add(time.Duration(i-n) * time.Minute)
		page.RevId = UUIDFromTime(page.Modified)
		page.Body = fmt.Sprintf("text %d", i)
		if err := w.InsertPage(&page); err != nil {
			w.tb.Error("CreatePages:", err)
		}
	}
}

func (w *WikiTest) InsertPage(page *WikiPage) error {
	return w.session.Query(`INSERT INTO wiki_page
		(title, revid, body, views, protected, modified, rating, tags, attachments)
		VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
		page.Title, page.RevId, page.Body, page.Views, page.Protected,
		page.Modified, page.Rating, page.Tags, page.Attachments).Exec()
}

func (w *WikiTest) SelectPage(page *WikiPage, title string, revid UUID) error {
	return w.session.Query(`SELECT title, revid, body, views, protected,
		modified,tags, attachments, rating
		FROM wiki_page WHERE title = ? AND revid = ? LIMIT 1`,
		title, revid).Scan(&page.Title, &page.RevId,
		&page.Body, &page.Views, &page.Protected, &page.Modified, &page.Tags,
		&page.Attachments, &page.Rating)
}

func (w *WikiTest) GetPageCount() int {
	var count int
	if err := w.session.Query(`SELECT COUNT(*) FROM wiki_page`).Scan(&count); err != nil {
		w.tb.Error("GetPageCount", err)
	}
	return count
}

func TestWikiCreateSchema(t *testing.T) {
	session := createSession(t)
	defer session.Close()

	w := WikiTest{session, t}
	w.CreateSchema()
}

func BenchmarkWikiCreateSchema(b *testing.B) {
	b.StopTimer()
	session := createSession(b)
	defer func() {
		b.StopTimer()
		session.Close()
	}()
	w := WikiTest{session, b}
	b.StartTimer()

	for i := 0; i < b.N; i++ {
		w.CreateSchema()
	}
}

func TestWikiCreatePages(t *testing.T) {
	session := createSession(t)
	defer session.Close()

	w := WikiTest{session, t}
	w.CreateSchema()
	numPages := 5
	w.CreatePages(numPages)
	if count := w.GetPageCount(); count != numPages {
		t.Errorf("expected %d pages, got %d pages.", numPages, count)
	}
}

func BenchmarkWikiCreatePages(b *testing.B) {
	b.StopTimer()
	session := createSession(b)
	defer func() {
		b.StopTimer()
		session.Close()
	}()
	w := WikiTest{session, b}
	w.CreateSchema()
	b.StartTimer()

	w.CreatePages(b.N)
}

func BenchmarkWikiSelectAllPages(b *testing.B) {
	b.StopTimer()
	session := createSession(b)
	defer func() {
		b.StopTimer()
		session.Close()
	}()
	w := WikiTest{session, b}
	w.CreateSchema()
	w.CreatePages(100)
	b.StartTimer()

	var page WikiPage
	for i := 0; i < b.N; i++ {
		iter := session.Query(`SELECT title, revid, body, views, protected,
			modified, tags, attachments, rating
			FROM wiki_page`).Iter()
		for iter.Scan(&page.Title, &page.RevId, &page.Body, &page.Views,
			&page.Protected, &page.Modified, &page.Tags, &page.Attachments,
			&page.Rating) {
			// pass
		}
		if err := iter.Close(); err != nil {
			b.Error(err)
		}
	}
}

func BenchmarkWikiSelectSinglePage(b *testing.B) {
	b.StopTimer()
	session := createSession(b)
	defer func() {
		b.StopTimer()
		session.Close()
	}()
	w := WikiTest{session, b}
	w.CreateSchema()
	pages := make([]WikiPage, 100)
	w.CreatePages(len(pages))
	iter := session.Query(`SELECT title, revid FROM wiki_page`).Iter()
	for i := 0; i < len(pages); i++ {
		if !iter.Scan(&pages[i].Title, &pages[i].RevId) {
			pages = pages[:i]
			break
		}
	}
	if err := iter.Close(); err != nil {
		b.Error(err)
	}
	b.StartTimer()

	var page WikiPage
	for i := 0; i < b.N; i++ {
		p := &pages[i%len(pages)]
		if err := w.SelectPage(&page, p.Title, p.RevId); err != nil {
			b.Error(err)
		}
	}
}

func BenchmarkWikiSelectPageCount(b *testing.B) {
	b.StopTimer()
	session := createSession(b)
	defer func() {
		b.StopTimer()
		session.Close()
	}()
	w := WikiTest{session, b}
	w.CreateSchema()
	numPages := 10
	w.CreatePages(numPages)
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		if count := w.GetPageCount(); count != numPages {
			b.Errorf("expected %d pages, got %d pages.", numPages, count)
		}
	}
}

func TestWikiTypicalCRUD(t *testing.T) {
	session := createSession(t)
	defer session.Close()

	w := WikiTest{session, t}
	w.CreateSchema()
	for _, page := range wikiTestData {
		if err := w.InsertPage(page); err != nil {
			t.Error("InsertPage:", err)
		}
	}
	if count := w.GetPageCount(); count != len(wikiTestData) {
		t.Errorf("count: expected %d, got %d\n", len(wikiTestData), count)
	}
	for _, original := range wikiTestData {
		page := new(WikiPage)
		if err := w.SelectPage(page, original.Title, original.RevId); err != nil {
			t.Error("SelectPage:", err)
			continue
		}
		sort.Sort(sort.StringSlice(page.Tags))
		sort.Sort(sort.StringSlice(original.Tags))
		if !reflect.DeepEqual(page, original) {
			t.Errorf("page: expected %#v, got %#v\n", original, page)
		}
	}
}
<commit_msg>Run each wiki test in its own table<commit_after>// +build all integration

package gocql

import (
	"fmt"
	"reflect"
	"sort"
	"testing"
	"time"

	"gopkg.in/inf.v0"
)

type WikiPage struct {
	Title       string
	RevId       UUID
	Body        string
	Views       int64
	Protected   bool
	Modified    time.Time
	Rating      *inf.Dec
	Tags        []string
	Attachments map[string]WikiAttachment
}

type WikiAttachment []byte

var wikiTestData = []*WikiPage{
	&WikiPage{
		Title:    "Frontpage",
		RevId:    TimeUUID(),
		Body:     "Welcome to this wiki page!",
		Rating:   inf.NewDec(131, 3),
		Modified: time.Date(2013, time.August, 13, 9, 52, 3, 0, time.UTC),
		Tags:     []string{"start", "important", "test"},
		Attachments: map[string]WikiAttachment{
			"logo":    WikiAttachment("\x00company logo\x00"),
			"favicon": WikiAttachment("favicon.ico"),
		},
	},
	&WikiPage{
		Title:    "Foobar",
		RevId:    TimeUUID(),
		Body:     "foo::Foo f = new foo::Foo(foo::Foo::INIT);",
		Modified: time.Date(2013, time.August, 13, 9, 52, 3, 0, time.UTC),
	},
}

type WikiTest struct {
	session *Session
	tb      testing.TB

	table string
}

func CreateSchema(session *Session, tb testing.TB, table string) *WikiTest {
	table = "wiki_" + table
	if err := session.Query(fmt.Sprintf("DROP TABLE IF EXISTS %s", table)).Exec(); err != nil {
		tb.Fatal("CreateSchema:", err)
	}

	err := createTable(session, fmt.Sprintf(`CREATE TABLE %s (
			title       varchar,
			revid       timeuuid,
			body        varchar,
			views       bigint,
			protected   boolean,
			modified    timestamp,
			rating      decimal,
			tags        set<varchar>,
			attachments map<varchar, blob>,
			PRIMARY KEY (title, revid)
		)`, table))

	if err != nil {
		tb.Fatal("CreateSchema:", err)
	}

	return &WikiTest{
		session: session,
		tb:      tb,
		table:   table,
	}
}

func (w *WikiTest) CreatePages(n int) {
	var page WikiPage
	t0 := time.Now()
	for i := 0; i < n; i++ {
		page.Title = fmt.Sprintf("generated_%d", (i&16)+1)
		page.Modified = t0.Add(time.Duration(i-n) * time.Minute)
		page.RevId = UUIDFromTime(page.Modified)
		page.Body = fmt.Sprintf("text %d", i)
		if err := w.InsertPage(&page); err != nil {
			w.tb.Error("CreatePages:", err)
		}
	}
}

func (w *WikiTest) InsertPage(page *WikiPage) error {
	return w.session.Query(fmt.Sprintf(`INSERT INTO %s
		(title, revid, body, views, protected, modified, rating, tags, attachments)
		VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, w.table),
		page.Title, page.RevId, page.Body, page.Views, page.Protected,
		page.Modified, page.Rating, page.Tags, page.Attachments).Exec()
}

func (w *WikiTest) SelectPage(page *WikiPage, title string, revid UUID) error {
	return w.session.Query(fmt.Sprintf(`SELECT title, revid, body, views, protected,
		modified,tags, attachments, rating
		FROM %s WHERE title = ? AND revid = ? LIMIT 1`, w.table),
		title, revid).Scan(&page.Title, &page.RevId,
		&page.Body, &page.Views, &page.Protected, &page.Modified, &page.Tags,
		&page.Attachments, &page.Rating)
}

func (w *WikiTest) GetPageCount() int {
	var count int
	if err := w.session.Query(fmt.Sprintf(`SELECT COUNT(*) FROM %s`, w.table)).Scan(&count); err != nil {
		w.tb.Error("GetPageCount", err)
	}
	return count
}

func TestWikiCreateSchema(t *testing.T) {
	session := createSession(t)
	defer session.Close()

	CreateSchema(session, t, "create")
}

func BenchmarkWikiCreateSchema(b *testing.B) {
	b.StopTimer()
	session := createSession(b)
	defer func() {
		b.StopTimer()
		session.Close()
	}()

	b.StartTimer()
	for i := 0; i < b.N; i++ {
		CreateSchema(session, b, "bench_create")
	}
}

func TestWikiCreatePages(t *testing.T) {
	session := createSession(t)
	defer session.Close()

	w := CreateSchema(session, t, "create_pages")

	numPages := 5
	w.CreatePages(numPages)
	if count := w.GetPageCount(); count != numPages {
		t.Errorf("expected %d pages, got %d pages.", numPages, count)
	}
}

func BenchmarkWikiCreatePages(b *testing.B) {
	b.StopTimer()
	session := createSession(b)
	defer func() {
		b.StopTimer()
		session.Close()
	}()

	w := CreateSchema(session, b, "bench_create_pages")

	b.StartTimer()

	w.CreatePages(b.N)
}

func BenchmarkWikiSelectAllPages(b *testing.B) {
	b.StopTimer()
	session := createSession(b)
	defer func() {
		b.StopTimer()
		session.Close()
	}()
	w := CreateSchema(session, b, "bench_select_all")

	w.CreatePages(100)
	b.StartTimer()

	var page WikiPage
	for i := 0; i < b.N; i++ {
		iter := session.Query(fmt.Sprintf(`SELECT title, revid, body, views, protected,
			modified, tags, attachments, rating
			FROM %s`, w.table)).Iter()
		for iter.Scan(&page.Title, &page.RevId, &page.Body, &page.Views,
			&page.Protected, &page.Modified, &page.Tags, &page.Attachments,
			&page.Rating) {
			// pass
		}
		if err := iter.Close(); err != nil {
			b.Error(err)
		}
	}
}

func BenchmarkWikiSelectSinglePage(b *testing.B) {
	b.StopTimer()
	session := createSession(b)
	defer func() {
		b.StopTimer()
		session.Close()
	}()
	w := CreateSchema(session, b, "bench_select_single")
	pages := make([]WikiPage, 100)
	w.CreatePages(len(pages))
	iter := session.Query(fmt.Sprintf(`SELECT title, revid FROM %s`, w.table)).Iter()
	for i := 0; i < len(pages); i++ {
		if !iter.Scan(&pages[i].Title, &pages[i].RevId) {
			pages = pages[:i]
			break
		}
	}
	if err := iter.Close(); err != nil {
		b.Error(err)
	}
	b.StartTimer()

	var page WikiPage
	for i := 0; i < b.N; i++ {
		p := &pages[i%len(pages)]
		if err := w.SelectPage(&page, p.Title, p.RevId); err != nil {
			b.Error(err)
		}
	}
}

func BenchmarkWikiSelectPageCount(b *testing.B) {
	b.StopTimer()
	session := createSession(b)
	defer func() {
		b.StopTimer()
		session.Close()
	}()

	w := CreateSchema(session, b, "bench_page_count")
	const numPages = 10
	w.CreatePages(numPages)
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		if count := w.GetPageCount(); count != numPages {
			b.Errorf("expected %d pages, got %d pages.", numPages, count)
		}
	}
}

func TestWikiTypicalCRUD(t *testing.T) {
	session := createSession(t)
	defer session.Close()

	w := CreateSchema(session, t, "crud")

	for _, page := range wikiTestData {
		if err := w.InsertPage(page); err != nil {
			t.Error("InsertPage:", err)
		}
	}
	if count := w.GetPageCount(); count != len(wikiTestData) {
		t.Errorf("count: expected %d, got %d\n", len(wikiTestData), count)
	}
	for _, original := range wikiTestData {
		page := new(WikiPage)
		if err := w.SelectPage(page, original.Title, original.RevId); err != nil {
			t.Error("SelectPage:", err)
			continue
		}
		sort.Sort(sort.StringSlice(page.Tags))
		sort.Sort(sort.StringSlice(original.Tags))
		if !reflect.DeepEqual(page, original) {
			t.Errorf("page: expected %#v, got %#v\n", original, page)
		}
	}
}
<|endoftext|>


<commit_before>package govaluate

import (
  "testing"
)

/*
  Contains test cases for all the expression examples given in the README.
  While all of the functionality for these cases should be covered in other tests,
  this is really just a sanity check.
*/

func TestBasicEvaluation(test *testing.T) {

  expression, _ := NewEvaluableExpression("10 > 0");
	result, _ := expression.Evaluate(nil);

  if(result != true) {
    test.Logf("Expected 'true', got '%v'\n", result)
    test.Fail()
  }
}

func TestParameterEvaluation(test *testing.T) {

  expression, _ := NewEvaluableExpression("foo > 0");

	parameters := make(map[string]interface{}, 8)
	parameters["foo"] = -1;

	result, _ := expression.Evaluate(parameters);

  if(result != false) {
    test.Logf("Expected 'false', got '%v'\n", result)
    test.Fail()
  }
}

func TestModifierEvaluation(test *testing.T) {

  expression, _ := NewEvaluableExpression("(requests_made * requests_succeeded / 100) >= 90");

	parameters := make(map[string]interface{}, 8)
	parameters["requests_made"] = 100;
	parameters["requests_succeeded"] = 80;

	result, _ := expression.Evaluate(parameters);

  if(result != false) {
    test.Logf("Expected 'false', got '%v'\n", result)
    test.Fail()
  }
}

func TestStringEvaluation(test *testing.T) {

  expression, _ := NewEvaluableExpression("http_response_body == 'service is ok'");

	parameters := make(map[string]interface{}, 8)
	parameters["http_response_body"] = "service is ok";

	result, _ := expression.Evaluate(parameters);

  if(result != true) {
    test.Logf("Expected 'false', got '%v'\n", result)
    test.Fail()
  }
}

func TestFloatEvaluation(test *testing.T) {

  expression, _ := NewEvaluableExpression("(mem_used / total_mem) * 100");

	parameters := make(map[string]interface{}, 8)
	parameters["total_mem"] = 1024;
	parameters["mem_used"] = 512;

	result, _ := expression.Evaluate(parameters);

  if(result != 50.0) {
    test.Logf("Expected '50.0', got '%v'\n", result)
    test.Fail()
  }
}

func TestDateComparison(test *testing.T) {

  expression, _ := NewEvaluableExpression("'2014-01-02' > '2014-01-01 23:59:59'");
	result, _ := expression.Evaluate(nil);

  if(result != true) {
    test.Logf("Expected 'true', got '%v'\n", result)
    test.Fail()
  }
}

func TestMultipleEvaluation(test *testing.T) {
  expression, _ := NewEvaluableExpression("response_time <= 100");
	parameters := make(map[string]interface{}, 8)

	for i := 0; i < 64; i++ {
		parameters["response_time"] = i
		result, _ := expression.Evaluate(parameters)

    if(result != true) {
      test.Logf("Expected 'true', got '%v'\n", result)
      test.Fail()
    }
	}
}
<commit_msg>Moved comment, so as to not associate it with any specific test<commit_after>package govaluate

/*
  Contains test cases for all the expression examples given in the README.
  While all of the functionality for these cases should be covered in other tests,
  this is really just a sanity check.
*/
import (
  "testing"
)

func TestBasicEvaluation(test *testing.T) {

  expression, _ := NewEvaluableExpression("10 > 0");
	result, _ := expression.Evaluate(nil);

  if(result != true) {
    test.Logf("Expected 'true', got '%v'\n", result)
    test.Fail()
  }
}

func TestParameterEvaluation(test *testing.T) {

  expression, _ := NewEvaluableExpression("foo > 0");

	parameters := make(map[string]interface{}, 8)
	parameters["foo"] = -1;

	result, _ := expression.Evaluate(parameters);

  if(result != false) {
    test.Logf("Expected 'false', got '%v'\n", result)
    test.Fail()
  }
}

func TestModifierEvaluation(test *testing.T) {

  expression, _ := NewEvaluableExpression("(requests_made * requests_succeeded / 100) >= 90");

	parameters := make(map[string]interface{}, 8)
	parameters["requests_made"] = 100;
	parameters["requests_succeeded"] = 80;

	result, _ := expression.Evaluate(parameters);

  if(result != false) {
    test.Logf("Expected 'false', got '%v'\n", result)
    test.Fail()
  }
}

func TestStringEvaluation(test *testing.T) {

  expression, _ := NewEvaluableExpression("http_response_body == 'service is ok'");

	parameters := make(map[string]interface{}, 8)
	parameters["http_response_body"] = "service is ok";

	result, _ := expression.Evaluate(parameters);

  if(result != true) {
    test.Logf("Expected 'false', got '%v'\n", result)
    test.Fail()
  }
}

func TestFloatEvaluation(test *testing.T) {

  expression, _ := NewEvaluableExpression("(mem_used / total_mem) * 100");

	parameters := make(map[string]interface{}, 8)
	parameters["total_mem"] = 1024;
	parameters["mem_used"] = 512;

	result, _ := expression.Evaluate(parameters);

  if(result != 50.0) {
    test.Logf("Expected '50.0', got '%v'\n", result)
    test.Fail()
  }
}

func TestDateComparison(test *testing.T) {

  expression, _ := NewEvaluableExpression("'2014-01-02' > '2014-01-01 23:59:59'");
	result, _ := expression.Evaluate(nil);

  if(result != true) {
    test.Logf("Expected 'true', got '%v'\n", result)
    test.Fail()
  }
}

func TestMultipleEvaluation(test *testing.T) {
  expression, _ := NewEvaluableExpression("response_time <= 100");
	parameters := make(map[string]interface{}, 8)

	for i := 0; i < 64; i++ {
		parameters["response_time"] = i
		result, _ := expression.Evaluate(parameters)

    if(result != true) {
      test.Logf("Expected 'true', got '%v'\n", result)
      test.Fail()
    }
	}
}
<|endoftext|>


<commit_before>package wini

import (
	"path/filepath"
	"runtime"
	"testing"

	"github.com/bmizerany/assert"
)

func Test1(t *testing.T) {

	filename := filepath.Join(getTestDataDir(t), "ini_parser_testfile.ini")
	ini := New()
	err := ini.ParseFile(filename)
	assert.Equal(t, nil, err)

	v, ok := ini.Get("mid")
	assert.Equal(t, v, "ac9219aa5232c4e519ae5fcb4d77ae5b")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("product")
	assert.Equal(t, v, "ppp")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("combo")
	assert.Equal(t, v, "ccc")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("aa")
	assert.Equal(t, v, "bb")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("axxxa")
	assert.Equal(t, v, "")
	assert.Equal(t, ok, false)

	m, ok := ini.GetKvmap("")
	assert.Equal(t, len(m), 6)
	assert.Equal(t, ok, true)

	n, ok := ini.GetKvmap("n")
	assert.Equal(t, len(n), 0)
	assert.Equal(t, ok, false)

	sss, ok := ini.GetKvmap("sss")
	assert.Equal(t, len(sss), 2)
	assert.Equal(t, ok, true)
	v, ok = ini.SectionGet("sss", "aa")
	assert.Equal(t, v, "bb")
	assert.Equal(t, ok, true)
	v, ok = ini.SectionGet("sss", "appext")
	assert.Equal(t, v, "ab=cd")
	assert.Equal(t, ok, true)
}

func TestUft8(t *testing.T) {
	/*
		title=百度搜索_ipad2
		url=http://www.baidu.com/s?bs=ipad&f=8&rsv_bp=1&wd=ipad2&inputT=397
		url_md5=5844a75423cd3372e1997360bd110a25
		refer=http://www.google.com
		anchor_text= google
		ret_form = json
		 ret_start = 0
		 ret_limit =    50
		page_info   =  0,0,50,1,0,20
		local=0
		mid=c4ca4238a0b923820dcc509a6f75849b
		product=test
		combo=test
		version=1.0.0.1
		debug=1
		encoding=1

	*/

	filename := filepath.Join(getTestDataDir(t), "utf8.ini")
	ini := New()
	err := ini.ParseFile(filename)
	assert.Equal(t, nil, err)

	v, ok := ini.Get("title")
	assert.Equal(t, v, "百度搜索_ipad2")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("url_md5")
	assert.Equal(t, v, "5844a75423cd3372e1997360bd110a25")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("ret_form")
	assert.Equal(t, v, "json")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("ret_start")
	assert.Equal(t, v, "0")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("ret_limit")
	assert.Equal(t, v, "50")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("axxxa")
	assert.Equal(t, v, "")
	assert.Equal(t, ok, false)

	m, ok := ini.GetKvmap("")
	assert.Equal(t, len(m), 16)
	assert.Equal(t, ok, true)

	n, ok := ini.GetKvmap("n")
	assert.Equal(t, len(n), 0)
	assert.Equal(t, ok, false)
}

func TestErrorFormat(t *testing.T) {
	filename := filepath.Join(getTestDataDir(t), "error.ini")
	ini := New()
	err := ini.ParseFile(filename)
	assert.NotEqual(t, nil, err)
}

func TestMemoryData1(t *testing.T) {
	raw := []byte("a:av||b:bv||c:cv||||d:dv||||||")
	ini := New()
	err := ini.Parse(raw, "|", ":")
	assert.Equal(t, nil, err)

	v, ok := ini.Get("a")
	assert.Equal(t, v, "av")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("b")
	assert.Equal(t, v, "bv")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("c")
	assert.Equal(t, v, "cv")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("d")
	assert.Equal(t, v, "dv")
	assert.Equal(t, ok, true)

	m, ok := ini.GetKvmap("")
	assert.Equal(t, len(m), 4)
	assert.Equal(t, ok, true)

	n, ok := ini.GetKvmap("n")
	assert.Equal(t, len(n), 0)
	assert.Equal(t, ok, false)
}

func TestMemoryData2(t *testing.T) {
	raw := []byte("a:av||b:bv||c:cv||||d:dv||||||")
	ini := New()
	err := ini.Parse(raw, "||", ":") // DIFFERENT with TestMemoryData1. use "||" instead of "|"
	assert.Equal(t, nil, err)

	v, ok := ini.Get("a")
	assert.Equal(t, v, "av")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("b")
	assert.Equal(t, v, "bv")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("c")
	assert.Equal(t, v, "cv")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("d")
	assert.Equal(t, v, "dv")
	assert.Equal(t, ok, true)

	m, ok := ini.GetKvmap("")
	assert.Equal(t, len(m), 4)
	assert.Equal(t, ok, true)

	n, ok := ini.GetKvmap("n")
	assert.Equal(t, len(n), 0)
	assert.Equal(t, ok, false)
}

func TestMemoryData3(t *testing.T) {
	raw := []byte("@|@|@|@|@|@|  a:av  @| b : bv @| c:cv  @|@|d:  dv@|@|@|@|@|@|@|")
	ini := New()
	err := ini.Parse(raw, "@|", ":")
	assert.Equal(t, nil, err)

	v, ok := ini.Get("a")
	assert.Equal(t, v, "av")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("b")
	assert.Equal(t, v, "bv")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("c")
	assert.Equal(t, v, "cv")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("d")
	assert.Equal(t, v, "dv")
	assert.Equal(t, ok, true)

	m, ok := ini.GetKvmap("")
	assert.Equal(t, len(m), 4)
	assert.Equal(t, ok, true)

	n, ok := ini.GetKvmap("n")
	assert.Equal(t, len(n), 0)
	assert.Equal(t, ok, false)
}

func getTestDataDir(t *testing.T) string {
	var file string
	var ok bool
	_, file, _, ok = runtime.Caller(0)
	assert.Equal(t, ok, true)

	curdir := filepath.Dir(file)
	return filepath.Join(curdir, "test/data")
}
<commit_msg>Add invalid INI format unit test case<commit_after>package wini

import (
	"path/filepath"
	"runtime"
	"testing"

	"github.com/bmizerany/assert"
)

func Test1(t *testing.T) {

	filename := filepath.Join(getTestDataDir(t), "ini_parser_testfile.ini")
	ini := New()
	err := ini.ParseFile(filename)
	assert.Equal(t, nil, err)

	v, ok := ini.Get("mid")
	assert.Equal(t, v, "ac9219aa5232c4e519ae5fcb4d77ae5b")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("product")
	assert.Equal(t, v, "ppp")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("combo")
	assert.Equal(t, v, "ccc")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("aa")
	assert.Equal(t, v, "bb")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("axxxa")
	assert.Equal(t, v, "")
	assert.Equal(t, ok, false)

	m, ok := ini.GetKvmap("")
	assert.Equal(t, len(m), 6)
	assert.Equal(t, ok, true)

	n, ok := ini.GetKvmap("n")
	assert.Equal(t, len(n), 0)
	assert.Equal(t, ok, false)

	sss, ok := ini.GetKvmap("sss")
	assert.Equal(t, len(sss), 2)
	assert.Equal(t, ok, true)
	v, ok = ini.SectionGet("sss", "aa")
	assert.Equal(t, v, "bb")
	assert.Equal(t, ok, true)
	v, ok = ini.SectionGet("sss", "appext")
	assert.Equal(t, v, "ab=cd")
	assert.Equal(t, ok, true)
}

func TestUft8(t *testing.T) {
	/*
		title=百度搜索_ipad2
		url=http://www.baidu.com/s?bs=ipad&f=8&rsv_bp=1&wd=ipad2&inputT=397
		url_md5=5844a75423cd3372e1997360bd110a25
		refer=http://www.google.com
		anchor_text= google
		ret_form = json
		 ret_start = 0
		 ret_limit =    50
		page_info   =  0,0,50,1,0,20
		local=0
		mid=c4ca4238a0b923820dcc509a6f75849b
		product=test
		combo=test
		version=1.0.0.1
		debug=1
		encoding=1

	*/

	filename := filepath.Join(getTestDataDir(t), "utf8.ini")
	ini := New()
	err := ini.ParseFile(filename)
	assert.Equal(t, nil, err)

	v, ok := ini.Get("title")
	assert.Equal(t, v, "百度搜索_ipad2")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("url_md5")
	assert.Equal(t, v, "5844a75423cd3372e1997360bd110a25")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("ret_form")
	assert.Equal(t, v, "json")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("ret_start")
	assert.Equal(t, v, "0")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("ret_limit")
	assert.Equal(t, v, "50")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("axxxa")
	assert.Equal(t, v, "")
	assert.Equal(t, ok, false)

	m, ok := ini.GetKvmap("")
	assert.Equal(t, len(m), 16)
	assert.Equal(t, ok, true)

	n, ok := ini.GetKvmap("n")
	assert.Equal(t, len(n), 0)
	assert.Equal(t, ok, false)
}

func TestErrorFormat(t *testing.T) {
	filename := filepath.Join(getTestDataDir(t), "error.ini")
	ini := New()
	err := ini.ParseFile(filename)
	assert.NotEqual(t, nil, err)
}

func TestMemoryData1(t *testing.T) {
	raw := []byte("a:av||b:bv||c:cv||||d:dv||||||")
	ini := New()
	err := ini.Parse(raw, "|", ":")
	assert.Equal(t, nil, err)

	v, ok := ini.Get("a")
	assert.Equal(t, v, "av")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("b")
	assert.Equal(t, v, "bv")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("c")
	assert.Equal(t, v, "cv")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("d")
	assert.Equal(t, v, "dv")
	assert.Equal(t, ok, true)

	m, ok := ini.GetKvmap("")
	assert.Equal(t, len(m), 4)
	assert.Equal(t, ok, true)

	n, ok := ini.GetKvmap("n")
	assert.Equal(t, len(n), 0)
	assert.Equal(t, ok, false)
}

func TestMemoryData2(t *testing.T) {
	raw := []byte("a:av||b:bv||c:cv||||d:dv||||||")
	ini := New()
	err := ini.Parse(raw, "||", ":") // DIFFERENT with TestMemoryData1. use "||" instead of "|"
	assert.Equal(t, nil, err)

	v, ok := ini.Get("a")
	assert.Equal(t, v, "av")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("b")
	assert.Equal(t, v, "bv")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("c")
	assert.Equal(t, v, "cv")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("d")
	assert.Equal(t, v, "dv")
	assert.Equal(t, ok, true)

	m, ok := ini.GetKvmap("")
	assert.Equal(t, len(m), 4)
	assert.Equal(t, ok, true)

	n, ok := ini.GetKvmap("n")
	assert.Equal(t, len(n), 0)
	assert.Equal(t, ok, false)
}

func TestMemoryData3(t *testing.T) {
	raw := []byte("@|@|@|@|@|@|  a:av  @| b : bv @| c:cv  @|@|d:  dv@|@|@|@|@|@|@|")
	ini := New()
	err := ini.Parse(raw, "@|", ":")
	assert.Equal(t, nil, err)

	v, ok := ini.Get("a")
	assert.Equal(t, v, "av")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("b")
	assert.Equal(t, v, "bv")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("c")
	assert.Equal(t, v, "cv")
	assert.Equal(t, ok, true)

	v, ok = ini.Get("d")
	assert.Equal(t, v, "dv")
	assert.Equal(t, ok, true)

	m, ok := ini.GetKvmap("")
	assert.Equal(t, len(m), 4)
	assert.Equal(t, ok, true)

	n, ok := ini.GetKvmap("n")
	assert.Equal(t, len(n), 0)
	assert.Equal(t, ok, false)
}

func TestMemoryData4(t *testing.T) {
	raw := []byte("@|@|@|@|@|@|  a:av  @| b : bv @| c:cv  @|@|d:  dv@|@|@|@|@|@|@|")
	ini := New()
	err := ini.Parse(raw, "@", ":")
	assert.NotEqual(t, nil, err)

	err = ini.Parse(raw, "@|", ":")
	assert.Equal(t, nil, err)
}

func getTestDataDir(t *testing.T) string {
	var file string
	var ok bool
	_, file, _, ok = runtime.Caller(0)
	assert.Equal(t, ok, true)

	curdir := filepath.Dir(file)
	return filepath.Join(curdir, "test/data")
}
<|endoftext|>


<commit_before>// Package klient provides an instance and abstraction to a remote klient kite.
// It is used to easily call methods of a klient kite
package klient

import (
	"errors"
	"fmt"
	"sync"
	"time"

	"github.com/koding/kite"
	"github.com/koding/kite/protocol"
	"github.com/koding/logging"
)

var ErrDialingFailed = errors.New("Dialing klient failed.")

// KlientPool represents a pool of connected klients
type KlientPool struct {
	kite    *kite.Kite
	klients map[string]*Klient
	log     logging.Logger
	sync.Mutex
}

type Usage struct {
	// InactiveDuration reports the minimum duration since the latest activity.
	InactiveDuration time.Duration `json:"inactive_duration"`
}

// Klient represents a remote klient instance
type Klient struct {
	client   *kite.Client
	kite     *kite.Kite
	Username string
}

func NewPool(k *kite.Kite) *KlientPool {
	return &KlientPool{
		kite:    k,
		klients: make(map[string]*Klient),
		log:     logging.NewLogger("klientpool"),
	}
}

// Get returns a ready to use and connected klient from the pool.
func (k *KlientPool) Get(queryString string) (*Klient, error) {
	var klient *Klient
	var ok bool
	var err error

	k.Lock()
	defer k.Unlock()

	klient, ok = k.klients[queryString]
	if !ok {
		klient, err = Connect(k.kite, queryString)
		if err != nil {
			return nil, err
		}

		k.log.Info("creating new klient connection to %s", queryString)
		k.klients[queryString] = klient

		// remove from the pool if we loose the connection
		klient.client.OnDisconnect(func() {
			k.log.Info("klient %s disconnected. removing from the pool", queryString)
			k.Delete(queryString)
			klient.Close()
		})
	} else {
		k.log.Debug("fetching already connected klient (%s) from pool", queryString)
	}

	return klient, nil
}

// Delete removes the klient with the given queryString from the pool
func (k *KlientPool) Delete(queryString string) {
	k.Lock()
	defer k.Unlock()

	delete(k.klients, queryString)
}

// Exists checks whether the given queryString exists in Kontrol or not
func Exists(k *kite.Kite, queryString string) error {
	query, err := protocol.KiteFromString(queryString)
	if err != nil {
		return err
	}

	k.Log.Debug("Querying for Klient: %s", queryString)

	// an error indicates a non existing klient or another error.
	_, err = k.GetKites(query.Query())
	if err != nil {
		return err
	}

	return nil
}

// Connect returns a new connected klient instance to the given queryString. The
// klient is ready to use. It's connected and needs to be closed once the task
// is finished with it.
func Connect(k *kite.Kite, queryString string) (*Klient, error) {
	return ConnectTimeout(k, queryString, 0)
}

// ConnectTimeout returns a new connected klient instance to the given
// queryString. The klient is ready to use. It's tries to connect for the given
// timeout duration
func ConnectTimeout(k *kite.Kite, queryString string, t time.Duration) (*Klient, error) {
	query, err := protocol.KiteFromString(queryString)
	if err != nil {
		return nil, err
	}

	k.Log.Debug("Querying for Klient: %s", queryString)

	kites, err := k.GetKites(query.Query())
	if err != nil {
		return nil, err
	}

	remoteKite := kites[0]
	remoteKite.ReadBufferSize = 512
	remoteKite.WriteBufferSize = 512
	if err := remoteKite.DialTimeout(t); err != nil {
		return nil, ErrDialingFailed
	}

	// klient connection is ready now
	return &Klient{
		kite:     k,
		client:   remoteKite,
		Username: remoteKite.Username,
	}, nil
}

func NewWithTimeout(k *kite.Kite, queryString string, t time.Duration) (*Klient, error) {
	timeout := time.After(t)

	k.Log.Debug("Querying for Klient: %s", queryString)
	for {
		select {
		case <-time.Tick(time.Second * 2):
			if klient, err := Connect(k, queryString); err == nil {
				return klient, nil
			}

		case <-timeout:
			return nil, ErrDialingFailed
		}
	}
}

func (k *Klient) Close() {
	k.client.Close()
}

// Usage calls the usage method of remote and get's the result back
func (k *Klient) Usage() (*Usage, error) {
	resp, err := k.client.Tell("klient.usage")
	if err != nil {
		return nil, err
	}

	var usg *Usage
	if err := resp.Unmarshal(&usg); err != nil {
		return nil, err
	}

	return usg, nil
}

// Ping checks if the given klient response with "pong" to the "ping" we send.
// A nil error means a successfull pong result.
func (k *Klient) Ping() error {
	resp, err := k.client.TellWithTimeout("kite.ping", 10*time.Second)
	if err != nil {
		return err
	}

	out, err := resp.String()
	if err != nil {
		return err
	}

	if out == "pong" {
		return nil
	}

	return fmt.Errorf("wrong response %s", out)
}
<commit_msg>Kloud/Klient: export client in Klient struct<commit_after>// Package klient provides an instance and abstraction to a remote klient kite.
// It is used to easily call methods of a klient kite
package klient

import (
	"errors"
	"fmt"
	"sync"
	"time"

	"github.com/koding/kite"
	"github.com/koding/kite/protocol"
	"github.com/koding/logging"
)

var ErrDialingFailed = errors.New("Dialing klient failed.")

// KlientPool represents a pool of connected klients
type KlientPool struct {
	kite    *kite.Kite
	klients map[string]*Klient
	log     logging.Logger
	sync.Mutex
}

type Usage struct {
	// InactiveDuration reports the minimum duration since the latest activity.
	InactiveDuration time.Duration `json:"inactive_duration"`
}

// Klient represents a remote klient instance
type Klient struct {
	client   *kite.Client
	kite     *kite.Kite
	Username string
}

func NewPool(k *kite.Kite) *KlientPool {
	return &KlientPool{
		kite:    k,
		klients: make(map[string]*Klient),
		log:     logging.NewLogger("klientpool"),
	}
}

// Get returns a ready to use and connected klient from the pool.
func (k *KlientPool) Get(queryString string) (*Klient, error) {
	var klient *Klient
	var ok bool
	var err error

	k.Lock()
	defer k.Unlock()

	klient, ok = k.klients[queryString]
	if !ok {
		klient, err = Connect(k.kite, queryString)
		if err != nil {
			return nil, err
		}

		k.log.Info("creating new klient connection to %s", queryString)
		k.klients[queryString] = klient

		// remove from the pool if we loose the connection
		klient.client.OnDisconnect(func() {
			k.log.Info("klient %s disconnected. removing from the pool", queryString)
			k.Delete(queryString)
			klient.Close()
		})
	} else {
		k.log.Debug("fetching already connected klient (%s) from pool", queryString)
	}

	return klient, nil
}

// Delete removes the klient with the given queryString from the pool
func (k *KlientPool) Delete(queryString string) {
	k.Lock()
	defer k.Unlock()

	delete(k.klients, queryString)
}

// Exists checks whether the given queryString exists in Kontrol or not
func Exists(k *kite.Kite, queryString string) error {
	query, err := protocol.KiteFromString(queryString)
	if err != nil {
		return err
	}

	k.Log.Debug("Querying for Klient: %s", queryString)

	// an error indicates a non existing klient or another error.
	_, err = k.GetKites(query.Query())
	if err != nil {
		return err
	}

	return nil
}

// Connect returns a new connected klient instance to the given queryString. The
// klient is ready to use. It's connected and needs to be closed once the task
// is finished with it.
func Connect(k *kite.Kite, queryString string) (*Klient, error) {
	return ConnectTimeout(k, queryString, 0)
}

// ConnectTimeout returns a new connected klient instance to the given
// queryString. The klient is ready to use. It's tries to connect for the given
// timeout duration
func ConnectTimeout(k *kite.Kite, queryString string, t time.Duration) (*Klient, error) {
	query, err := protocol.KiteFromString(queryString)
	if err != nil {
		return nil, err
	}

	k.Log.Debug("Querying for Klient: %s", queryString)

	kites, err := k.GetKites(query.Query())
	if err != nil {
		return nil, err
	}

	remoteKite := kites[0]
	remoteKite.ReadBufferSize = 512
	remoteKite.WriteBufferSize = 512
	if err := remoteKite.DialTimeout(t); err != nil {
		return nil, ErrDialingFailed
	}

	// klient connection is ready now
	return &Klient{
		kite:     k,
		client:   remoteKite,
		Username: remoteKite.Username,
	}, nil
}

func NewWithTimeout(k *kite.Kite, queryString string, t time.Duration) (*Klient, error) {
	timeout := time.After(t)

	k.Log.Debug("Querying for Klient: %s", queryString)
	for {
		select {
		case <-time.Tick(time.Second * 2):
			if klient, err := Connect(k, queryString); err == nil {
				return klient, nil
			}

		case <-timeout:
			return nil, ErrDialingFailed
		}
	}
}

func (k *Klient) Client() *kite.Client {
	return k.client
}

func (k *Klient) Close() {
	k.client.Close()
}

// Usage calls the usage method of remote and get's the result back
func (k *Klient) Usage() (*Usage, error) {
	resp, err := k.client.Tell("klient.usage")
	if err != nil {
		return nil, err
	}

	var usg *Usage
	if err := resp.Unmarshal(&usg); err != nil {
		return nil, err
	}

	return usg, nil
}

// Ping checks if the given klient response with "pong" to the "ping" we send.
// A nil error means a successfull pong result.
func (k *Klient) Ping() error {
	resp, err := k.client.TellWithTimeout("kite.ping", 10*time.Second)
	if err != nil {
		return err
	}

	out, err := resp.String()
	if err != nil {
		return err
	}

	if out == "pong" {
		return nil
	}

	return fmt.Errorf("wrong response %s", out)
}
<|endoftext|>