<commit_before>package api

import (
	"io"
	"net/http"
)

// putObjectRequest builds a request for uploading an object
func (c *Client) putObjectRequest(objectID string, content io.ReadCloser) (*http.Request, error) {
	req, err := http.NewRequest("PUT", c.BaseURL+"/blobs/"+objectID,
		content)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Content-Type", "application/octet-stream")
	SignWithKey(req, c.signingPrivateKey)
	return req, nil
}

// PutObject uploads an object to the server
func (c *Client) PutObject(objectID string, content io.ReadCloser) error {
	req, err := c.putObjectRequest(objectID, content)
	if err != nil {
		return err
	}
	_, err = c.doRequest(req, http.StatusCreated, http.StatusOK)
	return err
}

// getObjectRequest builds a request for downloading an object
func (c *Client) getObjectRequest(objectID string) (*http.Request, error) {
	req, err := http.NewRequest("GET", c.BaseURL+"/blobs/"+objectID, nil)
	if err != nil {
		return nil, err
	}
	SignWithKey(req, c.signingPrivateKey)
	return req, nil
}

// GetObject downloads an object from the server
func (c *Client) GetObject(objectID string) (io.Reader, error) {
	req, err := c.getObjectRequest(objectID)
	if err != nil {
		return nil, err
	}
	resp, err := c.doRequest(req, http.StatusCreated, http.StatusOK)
	return resp.Body, err
}
<commit_msg>api: fixed a missing null pointer check in the Client.GetObject method.<commit_after>package api

import (
	"io"
	"net/http"
)

// putObjectRequest builds a request for uploading an object
func (c *Client) putObjectRequest(objectID string, content io.ReadCloser) (*http.Request, error) {
	req, err := http.NewRequest("PUT", c.BaseURL+"/blobs/"+objectID,
		content)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Content-Type", "application/octet-stream")
	SignWithKey(req, c.signingPrivateKey)
	return req, nil
}

// PutObject uploads an object to the server
func (c *Client) PutObject(objectID string, content io.ReadCloser) error {
	req, err := c.putObjectRequest(objectID, content)
	if err != nil {
		return err
	}
	_, err = c.doRequest(req, http.StatusCreated, http.StatusOK)
	return err
}

// getObjectRequest builds a request for downloading an object
func (c *Client) getObjectRequest(objectID string) (*http.Request, error) {
	req, err := http.NewRequest("GET", c.BaseURL+"/blobs/"+objectID, nil)
	if err != nil {
		return nil, err
	}
	SignWithKey(req, c.signingPrivateKey)
	return req, nil
}

// GetObject downloads an object from the server
func (c *Client) GetObject(objectID string) (io.Reader, error) {
	req, err := c.getObjectRequest(objectID)
	if err != nil {
		return nil, err
	}
	resp, err := c.doRequest(req, http.StatusCreated, http.StatusOK)
	if resp == nil {
		return nil, err
	}
	return resp.Body, err
}
<|endoftext|>


<commit_before>package bongo

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

	"github.com/jinzhu/gorm"
)

func (b *Bongo) Fetch(i Modellable) error {
	if i.GetId() == 0 {
		return errors.New(fmt.Sprintf("Id is not set for %s", i.TableName()))
	}

	if err := b.DB.Table(i.TableName()).
		Find(i).
		Error; err != nil {
		return err
	}

	return nil
}

func (b *Bongo) ById(i Modellable, id int64) error {
	if err := b.DB.
		Table(i.TableName()).
		Where("id = ?", id).
		Find(i).
		Error; err != nil {
		return err
	}

	return nil
}

func (b *Bongo) Create(i Modellable) error {
	if err := b.DB.Save(i).Error; err != nil {
		return err
	}

	return nil
}

func (b *Bongo) Update(i Modellable) error {
	if i.GetId() == 0 {
		return errors.New(fmt.Sprintf("Id is not set for %s", i.TableName()))
	}

	// Update and Create is using the Save method, so they are
	// same functions but GORM handles, AfterCreate and AfterUpdate
	// in correct manner
	return b.Create(i)
}

func (b *Bongo) Delete(i Modellable) error {
	if i.GetId() == 0 {
		return errors.New(fmt.Sprintf("Id is not set for %s", i.TableName()))
	}

	if err := b.DB.Delete(i).Error; err != nil {
		return err
	}

	return nil
}

func (b *Bongo) FetchByIds(i Modellable, data interface{}, ids []int64) error {
	if len(ids) == 0 {
		return nil
	}

	orderByQuery := ""
	comma := ""
	for _, id := range ids {
		orderByQuery = orderByQuery + comma + " id = " + strconv.FormatInt(id, 10) + " desc"
		comma = ","
	}
	return b.DB.
		Table(i.TableName()).
		Order(orderByQuery).
		Where(ids).
		Find(data).
		Error

}

func (b *Bongo) UpdatePartial(i Modellable, set map[string]interface{}) error {
	if i.GetId() == 0 {
		return errors.New(fmt.Sprintf("Id is not set for %s", i.TableName()))
	}

	query := b.DB.Table(i.TableName())

	query = query.Where(i.GetId())

	if err := query.Update(set).Error; err != nil {
		return err
	}

	if err := b.Fetch(i); err != nil {
		return err
	}

	b.AfterUpdate(i)
	return nil
}

// selector, set
func (b *Bongo) UpdateMulti(i Modellable, rest ...map[string]interface{}) error {
	var set, selector map[string]interface{}

	switch len(rest) {
	case 1:
		set = rest[0]
		selector = nil
	case 2:
		selector = rest[0]
		set = rest[1]
	default:
		return errors.New("Update partial parameter list is wrong")
	}

	query := b.DB.Table(i.TableName())

	//add selector
	query = addWhere(query, selector)

	if err := query.Update(set).Error; err != nil {
		return err
	}

	return nil
}

func (b *Bongo) Count(i Modellable, where ...interface{}) (int, error) {
	var count int

	// init query
	query := b.DB

	// add table name
	query = query.Table(i.TableName())

	// add query
	query = query.Where(where[0], where[1:len(where)]...)

	return count, query.Count(&count).Error
}

type Query struct {
	Selector map[string]interface{}
	Sort     map[string]string
	Limit    int
	Skip     int
	Pluck    string
}

func NewQS(selector map[string]interface{}) *Query {
	return &Query{
		Selector: selector,
	}
}

// selector, sort, limit, pluck,
func (b *Bongo) Some(i Modellable, data interface{}, q *Query) error {
	err := b.buildQuery(i, data, q)
	if err == gorm.RecordNotFound {
		return nil
	}
	return err
}

func (b *Bongo) One(i Modellable, data interface{}, q *Query) error {
	q.Limit = 1
	return b.buildQuery(i, data, q)
}

func (b *Bongo) buildQuery(i Modellable, data interface{}, q *Query) error {
	// init query
	query := b.DB

	// add table name
	query = query.Table(i.TableName())

	// add sort options
	query = addSort(query, q.Sort)

	// add selector
	query = addWhere(query, q.Selector)

	// if limit is minus or 0 ignore
	if q.Limit > 0 {
		query.Limit(q.Limit)
	}

	var err error
	// TODO refactor this part
	if q.Pluck != "" {
		if strings.Contains(q.Pluck, ",") {
			// add pluck data
			query = addPluck(query, q.Pluck)

			err = query.Find(data).Error
		} else {
			err = query.Pluck(q.Pluck, data).Error
		}
	} else {
		err = query.Find(data).Error
	}
	return err
}

func (b *Bongo) AfterCreate(i Modellable) {
	data, err := json.Marshal(i)
	if err != nil {
		return
	}

	err = b.Broker.Publish(i.TableName()+"_created", data)
	if err != nil {
		return
	}
}

func (b *Bongo) AfterUpdate(i Modellable) {
	data, err := json.Marshal(i)
	if err != nil {
		return
	}

	err = b.Broker.Publish(i.TableName()+"_updated", data)
	if err != nil {
		return
	}
}

func (b *Bongo) AfterDelete(i Modellable) {
	data, err := json.Marshal(i)
	if err != nil {
		return
	}

	err = b.Broker.Publish(i.TableName()+"_deleted", data)
	if err != nil {
		return
	}
}

func addSort(query *gorm.DB, options map[string]string) *gorm.DB {

	if options == nil {
		return query
	}

	if len(options) == 0 {
		return query
	}

	var opts []string
	for key, val := range options {
		opts = append(opts, fmt.Sprintf("%s %v", key, val))
	}
	return query.Order(strings.Join(opts, ","))
}

func addPluck(query *gorm.DB, plucked string) *gorm.DB {
	if plucked == "" {
		return query
	}

	return query.Select(plucked)
}

func addWhere(query *gorm.DB, selector map[string]interface{}) *gorm.DB {
	if selector == nil {
		return query
	}
	return query.Where(selector)
}
<commit_msg>Social: retire UpdateMulti function<commit_after>package bongo

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

	"github.com/jinzhu/gorm"
)

func (b *Bongo) Fetch(i Modellable) error {
	if i.GetId() == 0 {
		return errors.New(fmt.Sprintf("Id is not set for %s", i.TableName()))
	}

	if err := b.DB.Table(i.TableName()).
		Find(i).
		Error; err != nil {
		return err
	}

	return nil
}

func (b *Bongo) ById(i Modellable, id int64) error {
	if err := b.DB.
		Table(i.TableName()).
		Where("id = ?", id).
		Find(i).
		Error; err != nil {
		return err
	}

	return nil
}

func (b *Bongo) Create(i Modellable) error {
	if err := b.DB.Save(i).Error; err != nil {
		return err
	}

	return nil
}

func (b *Bongo) Update(i Modellable) error {
	if i.GetId() == 0 {
		return errors.New(fmt.Sprintf("Id is not set for %s", i.TableName()))
	}

	// Update and Create is using the Save method, so they are
	// same functions but GORM handles, AfterCreate and AfterUpdate
	// in correct manner
	return b.Create(i)
}

func (b *Bongo) Delete(i Modellable) error {
	if i.GetId() == 0 {
		return errors.New(fmt.Sprintf("Id is not set for %s", i.TableName()))
	}

	if err := b.DB.Delete(i).Error; err != nil {
		return err
	}

	return nil
}

func (b *Bongo) FetchByIds(i Modellable, data interface{}, ids []int64) error {
	if len(ids) == 0 {
		return nil
	}

	orderByQuery := ""
	comma := ""
	for _, id := range ids {
		orderByQuery = orderByQuery + comma + " id = " + strconv.FormatInt(id, 10) + " desc"
		comma = ","
	}
	return b.DB.
		Table(i.TableName()).
		Order(orderByQuery).
		Where(ids).
		Find(data).
		Error

}

func (b *Bongo) UpdatePartial(i Modellable, set map[string]interface{}) error {
	if i.GetId() == 0 {
		return errors.New(fmt.Sprintf("Id is not set for %s", i.TableName()))
	}

	query := b.DB.Table(i.TableName())

	query = query.Where(i.GetId())

	if err := query.Update(set).Error; err != nil {
		return err
	}

	if err := b.Fetch(i); err != nil {
		return err
	}

	b.AfterUpdate(i)
	return nil
}

func (b *Bongo) Count(i Modellable, where ...interface{}) (int, error) {
	var count int

	// init query
	query := b.DB

	// add table name
	query = query.Table(i.TableName())

	// add query
	query = query.Where(where[0], where[1:len(where)]...)

	return count, query.Count(&count).Error
}

type Query struct {
	Selector map[string]interface{}
	Sort     map[string]string
	Limit    int
	Skip     int
	Pluck    string
}

func NewQS(selector map[string]interface{}) *Query {
	return &Query{
		Selector: selector,
	}
}

// selector, sort, limit, pluck,
func (b *Bongo) Some(i Modellable, data interface{}, q *Query) error {
	err := b.buildQuery(i, data, q)
	if err == gorm.RecordNotFound {
		return nil
	}
	return err
}

func (b *Bongo) One(i Modellable, data interface{}, q *Query) error {
	q.Limit = 1
	return b.buildQuery(i, data, q)
}

func (b *Bongo) buildQuery(i Modellable, data interface{}, q *Query) error {
	// init query
	query := b.DB

	// add table name
	query = query.Table(i.TableName())

	// add sort options
	query = addSort(query, q.Sort)

	// add selector
	query = addWhere(query, q.Selector)

	// if limit is minus or 0 ignore
	if q.Limit > 0 {
		query.Limit(q.Limit)
	}

	var err error
	// TODO refactor this part
	if q.Pluck != "" {
		if strings.Contains(q.Pluck, ",") {
			// add pluck data
			query = addPluck(query, q.Pluck)

			err = query.Find(data).Error
		} else {
			err = query.Pluck(q.Pluck, data).Error
		}
	} else {
		err = query.Find(data).Error
	}
	return err
}

func (b *Bongo) AfterCreate(i Modellable) {
	data, err := json.Marshal(i)
	if err != nil {
		return
	}

	err = b.Broker.Publish(i.TableName()+"_created", data)
	if err != nil {
		return
	}
}

func (b *Bongo) AfterUpdate(i Modellable) {
	data, err := json.Marshal(i)
	if err != nil {
		return
	}

	err = b.Broker.Publish(i.TableName()+"_updated", data)
	if err != nil {
		return
	}
}

func (b *Bongo) AfterDelete(i Modellable) {
	data, err := json.Marshal(i)
	if err != nil {
		return
	}

	err = b.Broker.Publish(i.TableName()+"_deleted", data)
	if err != nil {
		return
	}
}

func addSort(query *gorm.DB, options map[string]string) *gorm.DB {

	if options == nil {
		return query
	}

	if len(options) == 0 {
		return query
	}

	var opts []string
	for key, val := range options {
		opts = append(opts, fmt.Sprintf("%s %v", key, val))
	}
	return query.Order(strings.Join(opts, ","))
}

func addPluck(query *gorm.DB, plucked string) *gorm.DB {
	if plucked == "" {
		return query
	}

	return query.Select(plucked)
}

func addWhere(query *gorm.DB, selector map[string]interface{}) *gorm.DB {
	if selector == nil {
		return query
	}
	return query.Where(selector)
}
<|endoftext|>


<commit_before>/*
Copyright 2020 The Vitess Authors.

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

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

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

package engine

import (
	"context"
	"errors"
	"fmt"
	"testing"

	"vitess.io/vitess/go/test/utils"

	"github.com/stretchr/testify/require"
	"vitess.io/vitess/go/sqltypes"
)

func TestConcatenate_NoErrors(t *testing.T) {
	type testCase struct {
		testName       string
		inputs         []*sqltypes.Result
		expectedResult *sqltypes.Result
		expectedError  string
	}

	testCases := []*testCase{{
		testName: "empty results",
		inputs: []*sqltypes.Result{
			sqltypes.MakeTestResult(sqltypes.MakeTestFields("id1|col11|col12", "int64|varbinary|varbinary")),
			sqltypes.MakeTestResult(sqltypes.MakeTestFields("id2|col21|col22", "int64|varbinary|varbinary")),
		},
		expectedResult: sqltypes.MakeTestResult(sqltypes.MakeTestFields("id1|col11|col12", "int64|varbinary|varbinary")),
	}, {
		testName: "2 non empty result",
		inputs: []*sqltypes.Result{
			sqltypes.MakeTestResult(sqltypes.MakeTestFields("myid|mycol1|mycol2", "int64|varchar|varbinary"), "11|m1|n1", "22|m2|n2"),
			sqltypes.MakeTestResult(sqltypes.MakeTestFields("id|col1|col2", "int64|varchar|varbinary"), "1|a1|b1", "2|a2|b2"),
		},
		expectedResult: sqltypes.MakeTestResult(sqltypes.MakeTestFields("myid|mycol1|mycol2", "int64|varchar|varbinary"), "11|m1|n1", "22|m2|n2", "1|a1|b1", "2|a2|b2"),
	}, {
		testName: "mismatch field type",
		inputs: []*sqltypes.Result{
			sqltypes.MakeTestResult(sqltypes.MakeTestFields("id|col1|col2", "int64|varbinary|varbinary"), "1|a1|b1", "2|a2|b2"),
			sqltypes.MakeTestResult(sqltypes.MakeTestFields("id|col3|col4", "int64|varchar|varbinary"), "1|a1|b1", "2|a2|b2"),
		},
		expectedError: "column field type does not match for name",
	}, {
		testName: "input source has different column count",
		inputs: []*sqltypes.Result{
			sqltypes.MakeTestResult(sqltypes.MakeTestFields("id|col1|col2", "int64|varchar|varchar"), "1|a1|b1", "2|a2|b2"),
			sqltypes.MakeTestResult(sqltypes.MakeTestFields("id|col3|col4|col5", "int64|varchar|varchar|int32"), "1|a1|b1|5", "2|a2|b2|6"),
		},
		expectedError: "The used SELECT statements have a different number of columns",
	}, {
		testName: "1 empty result and 1 non empty result",
		inputs: []*sqltypes.Result{
			sqltypes.MakeTestResult(sqltypes.MakeTestFields("myid|mycol1|mycol2", "int64|varchar|varbinary")),
			sqltypes.MakeTestResult(sqltypes.MakeTestFields("id|col1|col2", "int64|varchar|varbinary"), "1|a1|b1", "2|a2|b2"),
		},
		expectedResult: sqltypes.MakeTestResult(sqltypes.MakeTestFields("myid|mycol1|mycol2", "int64|varchar|varbinary"), "1|a1|b1", "2|a2|b2"),
	}}

	for _, tc := range testCases {
		require.Equal(t, 2, len(tc.inputs))
		concatenate := &Concatenate{
			Sources: []Primitive{
				&fakePrimitive{results: []*sqltypes.Result{tc.inputs[0], tc.inputs[0]}, sendErr: errors.New("abc")},
				&fakePrimitive{results: []*sqltypes.Result{tc.inputs[1], tc.inputs[1]}, sendErr: errors.New("abc")},
			},
		}

		t.Run(tc.testName+"-Execute", func(t *testing.T) {
			qr, err := concatenate.Execute(&noopVCursor{ctx: context.Background()}, nil, true)
			if tc.expectedError == "" {
				require.NoError(t, err)
				require.Equal(t, tc.expectedResult, qr)
			} else {
				require.Error(t, err)
				require.Contains(t, err.Error(), tc.expectedError)
			}
		})

		t.Run(tc.testName+"-StreamExecute", func(t *testing.T) {
			qr, err := wrapStreamExecute(concatenate, &noopVCursor{ctx: context.Background()}, nil, true)
			if tc.expectedError == "" {
				require.NoError(t, err)
				require.Equal(t, utils.SortString(fmt.Sprintf("%v", tc.expectedResult.Rows)), utils.SortString(fmt.Sprintf("%v", qr.Rows)))
			} else {
				require.Error(t, err)
				require.Contains(t, err.Error(), tc.expectedError)
			}
		})
	}
}

func TestConcatenate_WithErrors(t *testing.T) {
	strFailed := "failed"
	errString := "Concatenate.Execute: " + strFailed

	fake := sqltypes.MakeTestResult(sqltypes.MakeTestFields("id|col1|col2", "int64|varchar|varbinary"), "1|a1|b1", "2|a2|b2")
	concatenate := &Concatenate{
		Sources: []Primitive{
			&fakePrimitive{results: []*sqltypes.Result{nil, nil}, sendErr: errors.New(strFailed)},
			&fakePrimitive{results: []*sqltypes.Result{fake, fake}},
		},
	}
	ctx := context.Background()
	_, err := concatenate.Execute(&noopVCursor{ctx: ctx}, nil, true)
	require.EqualError(t, err, errString)

	_, err = wrapStreamExecute(concatenate, &noopVCursor{ctx: ctx}, nil, true)
	require.EqualError(t, err, strFailed)

	concatenate = &Concatenate{
		Sources: []Primitive{
			&fakePrimitive{results: []*sqltypes.Result{fake, fake}},
			&fakePrimitive{results: []*sqltypes.Result{nil, nil}, sendErr: errors.New(strFailed)},
		},
	}
	_, err = concatenate.Execute(&noopVCursor{ctx: ctx}, nil, true)
	require.EqualError(t, err, errString)
	_, err = wrapStreamExecute(concatenate, &noopVCursor{ctx: ctx}, nil, true)
	require.EqualError(t, err, strFailed)
}
<commit_msg>cleaned up test<commit_after>/*
Copyright 2020 The Vitess Authors.

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

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

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

package engine

import (
	"context"
	"errors"
	"fmt"
	"testing"

	"vitess.io/vitess/go/test/utils"

	"github.com/stretchr/testify/require"
	"vitess.io/vitess/go/sqltypes"
)

func r(names, types string, rows ...string) *sqltypes.Result {
	return sqltypes.MakeTestResult(sqltypes.MakeTestFields(names, types), rows...)
}

func TestConcatenate_NoErrors(t *testing.T) {
	type testCase struct {
		testName       string
		inputs         []*sqltypes.Result
		expectedResult *sqltypes.Result
		expectedError  string
	}

	testCases := []*testCase{{
		testName: "empty results",
		inputs: []*sqltypes.Result{
			r("id1|col11|col12", "int64|varbinary|varbinary"),
			r("id2|col21|col22", "int64|varbinary|varbinary"),
		},
		expectedResult: r("id1|col11|col12", "int64|varbinary|varbinary"),
	}, {
		testName: "2 non empty result",
		inputs: []*sqltypes.Result{
			r("myid|mycol1|mycol2", "int64|varchar|varbinary", "11|m1|n1", "22|m2|n2"),
			r("id|col1|col2", "int64|varchar|varbinary", "1|a1|b1", "2|a2|b2"),
		},
		expectedResult: r("myid|mycol1|mycol2", "int64|varchar|varbinary", "11|m1|n1", "22|m2|n2", "1|a1|b1", "2|a2|b2"),
	}, {
		testName: "mismatch field type",
		inputs: []*sqltypes.Result{
			r("id|col1|col2", "int64|varbinary|varbinary", "1|a1|b1", "2|a2|b2"),
			r("id|col3|col4", "int64|varchar|varbinary", "1|a1|b1", "2|a2|b2"),
		},
		expectedError: "column field type does not match for name",
	}, {
		testName: "input source has different column count",
		inputs: []*sqltypes.Result{
			r("id|col1|col2", "int64|varchar|varchar", "1|a1|b1", "2|a2|b2"),
			r("id|col3|col4|col5", "int64|varchar|varchar|int32", "1|a1|b1|5", "2|a2|b2|6"),
		},
		expectedError: "The used SELECT statements have a different number of columns",
	}, {
		testName: "1 empty result and 1 non empty result",
		inputs: []*sqltypes.Result{
			r("myid|mycol1|mycol2", "int64|varchar|varbinary"),
			r("id|col1|col2", "int64|varchar|varbinary", "1|a1|b1", "2|a2|b2"),
		},
		expectedResult: r("myid|mycol1|mycol2", "int64|varchar|varbinary", "1|a1|b1", "2|a2|b2"),
	}}

	for _, tc := range testCases {
		require.Equal(t, 2, len(tc.inputs))
		concatenate := &Concatenate{
			Sources: []Primitive{
				&fakePrimitive{results: []*sqltypes.Result{tc.inputs[0], tc.inputs[0]}},
				&fakePrimitive{results: []*sqltypes.Result{tc.inputs[1], tc.inputs[1]}},
			},
		}

		t.Run(tc.testName+"-Execute", func(t *testing.T) {
			qr, err := concatenate.Execute(&noopVCursor{ctx: context.Background()}, nil, true)
			if tc.expectedError == "" {
				require.NoError(t, err)
				require.Equal(t, tc.expectedResult, qr)
			} else {
				require.Error(t, err)
				require.Contains(t, err.Error(), tc.expectedError)
			}
		})

		t.Run(tc.testName+"-StreamExecute", func(t *testing.T) {
			qr, err := wrapStreamExecute(concatenate, &noopVCursor{ctx: context.Background()}, nil, true)
			if tc.expectedError == "" {
				require.NoError(t, err)
				require.Equal(t, utils.SortString(fmt.Sprintf("%v", tc.expectedResult.Rows)), utils.SortString(fmt.Sprintf("%v", qr.Rows)))
			} else {
				require.Error(t, err)
				require.Contains(t, err.Error(), tc.expectedError)
			}
		})
	}
}

func TestConcatenate_WithErrors(t *testing.T) {
	strFailed := "failed"
	errString := "Concatenate.Execute: " + strFailed

	fake := r("id|col1|col2", "int64|varchar|varbinary", "1|a1|b1", "2|a2|b2")
	concatenate := &Concatenate{
		Sources: []Primitive{
			&fakePrimitive{results: []*sqltypes.Result{nil, nil}, sendErr: errors.New(strFailed)},
			&fakePrimitive{results: []*sqltypes.Result{fake, fake}},
		},
	}
	ctx := context.Background()
	_, err := concatenate.Execute(&noopVCursor{ctx: ctx}, nil, true)
	require.EqualError(t, err, errString)

	_, err = wrapStreamExecute(concatenate, &noopVCursor{ctx: ctx}, nil, true)
	require.EqualError(t, err, strFailed)

	concatenate = &Concatenate{
		Sources: []Primitive{
			&fakePrimitive{results: []*sqltypes.Result{fake, fake}},
			&fakePrimitive{results: []*sqltypes.Result{nil, nil}, sendErr: errors.New(strFailed)},
		},
	}
	_, err = concatenate.Execute(&noopVCursor{ctx: ctx}, nil, true)
	require.EqualError(t, err, errString)
	_, err = wrapStreamExecute(concatenate, &noopVCursor{ctx: ctx}, nil, true)
	require.EqualError(t, err, strFailed)
}
<|endoftext|>


<commit_before>// Copyright 2009 The freegeoip 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 apiserver

import (
	"bytes"
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"net/url"
	"path/filepath"
	"runtime"
	"testing"
)

func newTestHandler() (http.Handler, error) {
	_, f, _, _ := runtime.Caller(0)
	c := NewConfig()
	c.APIPrefix = "/api"
	c.PublicDir = "."
	c.DB = filepath.Join(filepath.Dir(f), "../testdata/db.gz")
	c.RateLimitLimit = 5
	c.RateLimitBackend = "map"
	c.Silent = true
	return NewHandler(c)
}

func TestHandler(t *testing.T) {
	f, err := newTestHandler()
	if err != nil {
		t.Fatal(err)
	}
	w := &httptest.ResponseRecorder{Body: &bytes.Buffer{}}
	r := &http.Request{
		Method:     "GET",
		URL:        &url.URL{Path: "/api/json/200.1.2.3"},
		RemoteAddr: "[::1]:1905",
	}
	f.ServeHTTP(w, r)
	if w.Code != http.StatusOK {
		t.Fatalf("Unexpected response: %d %s", w.Code, w.Body.String())
	}
	m := struct {
		Country string `json:"country_name"`
		City    string `json:"city"`
	}{}
	if err = json.NewDecoder(w.Body).Decode(&m); err != nil {
		t.Fatal(err)
	}
	if m.Country != "Venezuela" && m.City != "Caracas" {
		t.Fatalf("Query data does not match: want Caracas,Venezuela, have %q,%q",
			m.City, m.Country)
	}
}

func TestMetricsHandler(t *testing.T) {
	f, err := newTestHandler()
	if err != nil {
		t.Fatal(err)
	}
	tp := []http.Request{
		http.Request{
			Method:     "GET",
			URL:        &url.URL{Path: "/api/json/200.1.2.3"},
			RemoteAddr: "[::1]:1905",
		},
		http.Request{
			Method:     "GET",
			URL:        &url.URL{Path: "/api/json/200.1.2.3"},
			RemoteAddr: "127.0.0.1:1905",
		},
		http.Request{
			Method:     "GET",
			URL:        &url.URL{Path: "/api/json/200.1.2.3"},
			RemoteAddr: "200.1.2.3:1905",
		},
	}
	for i, r := range tp {
		w := &httptest.ResponseRecorder{Body: &bytes.Buffer{}}
		f.ServeHTTP(w, &r)
		if w.Code != http.StatusOK {
			t.Fatalf("Test %d: Unexpected response: %d %s", i, w.Code, w.Body.String())
		}
	}
}

func TestWriters(t *testing.T) {
	f, err := newTestHandler()
	if err != nil {
		t.Fatal(err)
	}
	tp := []http.Request{
		http.Request{
			Method:     "GET",
			URL:        &url.URL{Path: "/api/csv/"},
			RemoteAddr: "[::1]:1905",
		},
		http.Request{
			Method:     "GET",
			URL:        &url.URL{Path: "/api/xml/"},
			RemoteAddr: "[::1]:1905",
		},
		http.Request{
			Method:     "GET",
			URL:        &url.URL{Path: "/api/json/"},
			RemoteAddr: "[::1]:1905",
		},
	}
	for i, r := range tp {
		w := &httptest.ResponseRecorder{Body: &bytes.Buffer{}}
		f.ServeHTTP(w, &r)
		if w.Code != http.StatusOK {
			t.Fatalf("Test %d: Unexpected response: %d %s", i, w.Code, w.Body.String())
		}
	}
}
<commit_msg>Run gofmt -s<commit_after>// Copyright 2009 The freegeoip 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 apiserver

import (
	"bytes"
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"net/url"
	"path/filepath"
	"runtime"
	"testing"
)

func newTestHandler() (http.Handler, error) {
	_, f, _, _ := runtime.Caller(0)
	c := NewConfig()
	c.APIPrefix = "/api"
	c.PublicDir = "."
	c.DB = filepath.Join(filepath.Dir(f), "../testdata/db.gz")
	c.RateLimitLimit = 5
	c.RateLimitBackend = "map"
	c.Silent = true
	return NewHandler(c)
}

func TestHandler(t *testing.T) {
	f, err := newTestHandler()
	if err != nil {
		t.Fatal(err)
	}
	w := &httptest.ResponseRecorder{Body: &bytes.Buffer{}}
	r := &http.Request{
		Method:     "GET",
		URL:        &url.URL{Path: "/api/json/200.1.2.3"},
		RemoteAddr: "[::1]:1905",
	}
	f.ServeHTTP(w, r)
	if w.Code != http.StatusOK {
		t.Fatalf("Unexpected response: %d %s", w.Code, w.Body.String())
	}
	m := struct {
		Country string `json:"country_name"`
		City    string `json:"city"`
	}{}
	if err = json.NewDecoder(w.Body).Decode(&m); err != nil {
		t.Fatal(err)
	}
	if m.Country != "Venezuela" && m.City != "Caracas" {
		t.Fatalf("Query data does not match: want Caracas,Venezuela, have %q,%q",
			m.City, m.Country)
	}
}

func TestMetricsHandler(t *testing.T) {
	f, err := newTestHandler()
	if err != nil {
		t.Fatal(err)
	}
	tp := []http.Request{
		{
			Method:     "GET",
			URL:        &url.URL{Path: "/api/json/200.1.2.3"},
			RemoteAddr: "[::1]:1905",
		},
		{
			Method:     "GET",
			URL:        &url.URL{Path: "/api/json/200.1.2.3"},
			RemoteAddr: "127.0.0.1:1905",
		},
		{
			Method:     "GET",
			URL:        &url.URL{Path: "/api/json/200.1.2.3"},
			RemoteAddr: "200.1.2.3:1905",
		},
	}
	for i, r := range tp {
		w := &httptest.ResponseRecorder{Body: &bytes.Buffer{}}
		f.ServeHTTP(w, &r)
		if w.Code != http.StatusOK {
			t.Fatalf("Test %d: Unexpected response: %d %s", i, w.Code, w.Body.String())
		}
	}
}

func TestWriters(t *testing.T) {
	f, err := newTestHandler()
	if err != nil {
		t.Fatal(err)
	}
	tp := []http.Request{
		{
			Method:     "GET",
			URL:        &url.URL{Path: "/api/csv/"},
			RemoteAddr: "[::1]:1905",
		},
		{
			Method:     "GET",
			URL:        &url.URL{Path: "/api/xml/"},
			RemoteAddr: "[::1]:1905",
		},
		{
			Method:     "GET",
			URL:        &url.URL{Path: "/api/json/"},
			RemoteAddr: "[::1]:1905",
		},
	}
	for i, r := range tp {
		w := &httptest.ResponseRecorder{Body: &bytes.Buffer{}}
		f.ServeHTTP(w, &r)
		if w.Code != http.StatusOK {
			t.Fatalf("Test %d: Unexpected response: %d %s", i, w.Code, w.Body.String())
		}
	}
}
<|endoftext|>


<commit_before>package app_test

import (
	"github.com/Sirupsen/logrus"
	"github.com/Tapjoy/dynamiq/app"
	"github.com/hashicorp/memberlist"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/tpjg/goriakpbc"
	"github.com/tpjg/goriakpbc/pb"
	"io/ioutil"
	"testing"
	"time"
)

var cfg *app.Config
var core app.Core
var queues *app.Queues
var duration time.Duration
var memberList *memberlist.Memberlist
var testQueueName = "test_queue"
var RDtMap *riak.RDtMap

func TestPartitions(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "App Suite")

}

var _ = BeforeSuite(func() {
	cfg = &app.Config{}
	// Create the basic Configuration object
	// later tests can change these values as needed
	core = app.Core{
		Name:                  "john",
		Port:                  8000,
		SeedServer:            "steve",
		SeedPort:              8001,
		HttpPort:              8003,
		RiakNodes:             "127.0.0.1",
		BackendConnectionPool: 16,
		SyncConfigInterval:    duration,
	}

	queueMap := make(map[string]*app.Queue)
	configRDtMap := riak.RDtMap{
		Values:   make(map[riak.MapKey]interface{}),
		ToAdd:    make([]*pb.MapUpdate, 1),
		ToRemove: make([]*pb.MapField, 1),
	}

	configRDtMap.Values[riak.MapKey{Key: "max_partitions", Type: pb.MapField_REGISTER}] = &riak.RDtRegister{Value: []byte(app.DEFAULT_SETTINGS[app.MAX_PARTITIONS])}
	configRDtMap.Values[riak.MapKey{Key: "min_partitions", Type: pb.MapField_REGISTER}] = &riak.RDtRegister{Value: []byte(app.DEFAULT_SETTINGS[app.MIN_PARTITIONS])}
	configRDtMap.Values[riak.MapKey{Key: "visibility_timeout", Type: pb.MapField_REGISTER}] = &riak.RDtRegister{Value: []byte(app.DEFAULT_SETTINGS[app.VISIBILITY_TIMEOUT])}

	queue := &app.Queue{
		Name:   testQueueName,
		Config: &configRDtMap,
	}
	queueMap[testQueueName] = queue

	queues = &app.Queues{
		QueueMap: queueMap,
	}

	cfg.Core = core
	cfg.Queues = queues

	// Create a memberlist, aka the list of possible RiaQ processes to communicate with
	memberList = app.InitMember(cfg)

	// Disable log output during tests
	logrus.SetOutput(ioutil.Discard)
})

var _ = AfterSuite(func() {

	// Shut this down incase another suite of tests needs the port, or it's own instance
	memberList.Shutdown()
})
<commit_msg>Fixing app test suite<commit_after>package app_test

import (
	"github.com/Sirupsen/logrus"
	"github.com/Tapjoy/dynamiq/app"
	"github.com/hashicorp/memberlist"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/tpjg/goriakpbc"
	"github.com/tpjg/goriakpbc/pb"
	"io/ioutil"
	"testing"
	"time"
)

var cfg *app.Config
var core app.Core
var queues *app.Queues
var duration time.Duration
var memberList *memberlist.Memberlist
var testQueueName = "test_queue"
var RDtMap *riak.RDtMap

func TestPartitions(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "App Suite")

}

var _ = BeforeSuite(func() {
	cfg = &app.Config{}
	// Create the basic Configuration object
	// later tests can change these values as needed
	core = app.Core{
		Name:                  "john",
		Port:                  8000,
		SeedServer:            "steve",
		SeedServers:           []string{"steve"},
		SeedPort:              8001,
		HttpPort:              8003,
		RiakNodes:             "127.0.0.1",
		BackendConnectionPool: 16,
		SyncConfigInterval:    duration,
	}

	queueMap := make(map[string]*app.Queue)
	configRDtMap := riak.RDtMap{
		Values:   make(map[riak.MapKey]interface{}),
		ToAdd:    make([]*pb.MapUpdate, 1),
		ToRemove: make([]*pb.MapField, 1),
	}

	configRDtMap.Values[riak.MapKey{Key: "max_partitions", Type: pb.MapField_REGISTER}] = &riak.RDtRegister{Value: []byte(app.DEFAULT_SETTINGS[app.MAX_PARTITIONS])}
	configRDtMap.Values[riak.MapKey{Key: "min_partitions", Type: pb.MapField_REGISTER}] = &riak.RDtRegister{Value: []byte(app.DEFAULT_SETTINGS[app.MIN_PARTITIONS])}
	configRDtMap.Values[riak.MapKey{Key: "visibility_timeout", Type: pb.MapField_REGISTER}] = &riak.RDtRegister{Value: []byte(app.DEFAULT_SETTINGS[app.VISIBILITY_TIMEOUT])}

	queue := &app.Queue{
		Name:   testQueueName,
		Config: &configRDtMap,
	}
	queueMap[testQueueName] = queue

	queues = &app.Queues{
		QueueMap: queueMap,
	}

	cfg.Core = core
	cfg.Queues = queues

	// Create a memberlist, aka the list of possible RiaQ processes to communicate with
	memberList, _, _ = app.InitMemberList(core.Name, core.Port, core.SeedServers, core.SeedPort)

	// Disable log output during tests
	logrus.SetOutput(ioutil.Discard)
})

var _ = AfterSuite(func() {

	// Shut this down incase another suite of tests needs the port, or it's own instance
	memberList.Shutdown()
})
<|endoftext|>


<commit_before>// run

// Copyright 2014 The Go 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 main

import "time"

func main() {
	now := time.Now()
	f := now.Unix
	if now.Unix() != f() {
		println("BUG: ", now.Unix(), "!=", f())
	}
}
<commit_msg>test: expand issue7863 test<commit_after>// run

// Copyright 2014 The Go 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 main

import (
	"fmt"
)

type Foo int64

func (f *Foo) F() int64 {
	return int64(*f)
}

type Bar int64

func (b Bar) F() int64 {
	return int64(b)
}

type Baz int32

func (b Baz) F() int64 {
	return int64(b)
}

func main() {
	foo := Foo(123)
	f := foo.F
	if foo.F() != f() {
		bug()
		fmt.Println("foo.F", foo.F(), f())
	}
	bar := Bar(123)
	f = bar.F
	if bar.F() != f() {
		bug()
		fmt.Println("bar.F", bar.F(), f()) // duh!
	}

	baz := Baz(123)
	f = baz.F
	if baz.F() != f() {
		bug()
		fmt.Println("baz.F", baz.F(), f())
	}
}

var bugged bool

func bug() {
	if !bugged {
		bugged = true
		fmt.Println("BUG")
	}
}
<|endoftext|>


<commit_before>package cfg

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"
)

func TestLoadConfig(t *testing.T) {
	_, err := LoadConfig("foobar")
	if err == nil {
		t.Error("Loading an invalid config file should return an error")
	}

	_, err = LoadConfig(filepath.Join("testdata", "beehive.conf"))
	if err != nil {
		t.Error("Error loading config file fixture")
	}
}

func TestSaveConfig(t *testing.T) {
	tmpfile, err := ioutil.TempFile("", "example")
	if err != nil {
		t.Error("Could not create temp file")
	}
	defer os.Remove(tmpfile.Name()) // clean up

	testConfPath := filepath.Join("testdata", "beehive.conf")
	testConf, err := LoadConfig(testConfPath)
	if err != nil {
		t.Errorf("Failed to load config fixture %s: %v", testConfPath, err)
	}

	configFile := tmpfile.Name()
	err = SaveConfig(configFile, testConf)
	if err != nil {
		t.Errorf("Failed to save the config to %s", configFile)
	}

	if _, err := os.Stat(configFile); os.IsNotExist(err) {
		t.Error("Configuration file wasn't saved")
	}
}

func TestSaveCurrentConfig(t *testing.T) {
	tmpfile, err := ioutil.TempFile("", "example")
	if err != nil {
		t.Error("Could not create temp file")
	}
	defer os.Remove(tmpfile.Name()) // clean up

	t.Run("configFile empty", func(t *testing.T) {
		err = SaveCurrentConfig("")
		if err == nil {
			t.Error("Configuration file should not be saved")
		}
	})

	t.Run("configFile tmpfile", func(t *testing.T) {
		configFile := tmpfile.Name()
		err = SaveCurrentConfig(configFile)
		if err != nil {
			t.Error("Configuration file should have been saved")
		}
	})
}
<commit_msg>One more test<commit_after>package cfg

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"
)

func TestLoadConfig(t *testing.T) {
	_, err := LoadConfig("foobar")
	if err == nil {
		t.Error("Loading an invalid config file should return an error")
	}

	_, err = LoadConfig(filepath.Join("testdata", "beehive.conf"))
	if err != nil {
		t.Error("Error loading config file fixture")
	}
}

func TestSaveConfig(t *testing.T) {
	tmpfile, err := ioutil.TempFile("", "example")
	if err != nil {
		t.Error("Could not create temp file")
	}
	defer os.Remove(tmpfile.Name()) // clean up

	testConfPath := filepath.Join("testdata", "beehive.conf")
	testConf, err := LoadConfig(testConfPath)
	if err != nil {
		t.Errorf("Failed to load config fixture %s: %v", testConfPath, err)
	}

	configFile := tmpfile.Name()
	err = SaveConfig(configFile, testConf)
	if err != nil {
		t.Errorf("Failed to save the config to %s", configFile)
	}

	if !Exist(configFile) {
		t.Error("Configuration file wasn't saved")
	}
}

func TestSaveCurrentConfig(t *testing.T) {
	tmpfile, err := ioutil.TempFile("", "example")
	if err != nil {
		t.Error("Could not create temp file")
	}
	defer os.Remove(tmpfile.Name()) // clean up

	t.Run("configFile empty", func(t *testing.T) {
		err = SaveCurrentConfig("")
		if err == nil {
			t.Error("Configuration file should not be saved")
		}
	})

	t.Run("configFile tmpfile", func(t *testing.T) {
		configFile := tmpfile.Name()
		err = SaveCurrentConfig(configFile)
		if err != nil {
			t.Error("Configuration file should have been saved")
		}
	})
}
<|endoftext|>


<commit_before>package clang

// #cgo darwin LDFLAGS: -L/opt/local/libexec/llvm-3.5/lib
import "C"

//EOF
<commit_msg>Use homebrew version of llvm<commit_after>package clang

// #cgo darwin LDFLAGS: -L/usr/local/opt/llvm35/lib/llvm-3.5/lib
import "C"

//EOF
<|endoftext|>


<commit_before>package chanrpc

import (
	"errors"
	"fmt"
	"github.com/name5566/leaf/conf"
	"github.com/name5566/leaf/log"
	"runtime"
)

// one server per goroutine (goroutine not safe)
// one client per goroutine (goroutine not safe)
type Server struct {
	// id -> function
	//
	// function:
	// func(args []interface{})
	// func(args []interface{}) interface{}
	// func(args []interface{}) []interface{}
	functions map[interface{}]interface{}
	ChanCall  chan *CallInfo
}

type CallInfo struct {
	f       interface{}
	args    []interface{}
	chanRet chan *RetInfo
	cb      interface{}
}

type RetInfo struct {
	// nil
	// interface{}
	// []interface{}
	ret interface{}
	err error
	// callback:
	// func(err error)
	// func(ret interface{}, err error)
	// func(ret []interface{}, err error)
	cb interface{}
}

type Client struct {
	s               *Server
	chanSyncRet     chan *RetInfo
	ChanAsynRet     chan *RetInfo
	pendingAsynCall int
}

func NewServer(l int) *Server {
	s := new(Server)
	s.functions = make(map[interface{}]interface{})
	s.ChanCall = make(chan *CallInfo, l)
	return s
}

func assert(i interface{}) []interface{} {
	if i == nil {
		return nil
	} else {
		return i.([]interface{})
	}
}

// you must call the function before calling Open and Go
func (s *Server) Register(id interface{}, f interface{}) {
	switch f.(type) {
	case func([]interface{}):
	case func([]interface{}) interface{}:
	case func([]interface{}) []interface{}:
	default:
		panic(fmt.Sprintf("function id %v: definition of function is invalid", id))
	}

	if _, ok := s.functions[id]; ok {
		panic(fmt.Sprintf("function id %v: already registered", id))
	}

	s.functions[id] = f
}

func (s *Server) ret(ci *CallInfo, ri *RetInfo) (err error) {
	if ci.chanRet == nil {
		return
	}

	defer func() {
		if r := recover(); r != nil {
			err = r.(error)
		}
	}()

	ri.cb = ci.cb
	ci.chanRet <- ri
	return
}

func (s *Server) exec(ci *CallInfo) (err error) {
	defer func() {
		if r := recover(); r != nil {
			if conf.LenStackBuf > 0 {
				buf := make([]byte, conf.LenStackBuf)
				l := runtime.Stack(buf, false)
				err = fmt.Errorf("%v: %s", r, buf[:l])
			} else {
				err = fmt.Errorf("%v", r)
			}

			s.ret(ci, &RetInfo{err: fmt.Errorf("%v", r)})
		}
	}()

	// execute
	switch ci.f.(type) {
	case func([]interface{}):
		ci.f.(func([]interface{}))(ci.args)
		return s.ret(ci, &RetInfo{})
	case func([]interface{}) interface{}:
		ret := ci.f.(func([]interface{}) interface{})(ci.args)
		return s.ret(ci, &RetInfo{ret: ret})
	case func([]interface{}) []interface{}:
		ret := ci.f.(func([]interface{}) []interface{})(ci.args)
		return s.ret(ci, &RetInfo{ret: ret})
	}

	panic("bug")
}

func (s *Server) Exec(ci *CallInfo) {
	err := s.exec(ci)
	if err != nil {
		log.Error("%v", err)
	}
}

// goroutine safe
func (s *Server) Go(id interface{}, args ...interface{}) {
	f := s.functions[id]
	if f == nil {
		return
	}

	defer func() {
		recover()
	}()

	s.ChanCall <- &CallInfo{
		f:    f,
		args: args,
	}
}

// goroutine safe
func (s *Server) Call0(id interface{}, args ...interface{}) error {
	return s.Open(0).Call0(id, args...)
}

// goroutine safe
func (s *Server) Call1(id interface{}, args ...interface{}) (interface{}, error) {
	return s.Open(0).Call1(id, args...)
}

// goroutine safe
func (s *Server) CallN(id interface{}, args ...interface{}) ([]interface{}, error) {
	return s.Open(0).CallN(id, args...)
}

func (s *Server) Close() {
	close(s.ChanCall)

	for ci := range s.ChanCall {
		s.ret(ci, &RetInfo{
			err: errors.New("chanrpc server closed"),
		})
	}
}

// goroutine safe
func (s *Server) Open(l int) *Client {
	c := NewClient(l)
	c.Attach(s)
	return c
}

func NewClient(l int) *Client {
	c := new(Client)
	c.chanSyncRet = make(chan *RetInfo, 1)
	c.ChanAsynRet = make(chan *RetInfo, l)
	return c
}

func (c *Client) Attach(s *Server) {
	c.s = s
}

func (c *Client) call(ci *CallInfo, block bool) (err error) {
	defer func() {
		if r := recover(); r != nil {
			err = r.(error)
		}
	}()

	if block {
		c.s.ChanCall <- ci
	} else {
		select {
		case c.s.ChanCall <- ci:
		default:
			err = errors.New("chanrpc channel full")
		}
	}
	return
}

func (c *Client) f(id interface{}, n int) (f interface{}, err error) {
	if c.s == nil {
		err = errors.New("server not attached")
		return
	}

	f = c.s.functions[id]
	if f == nil {
		err = fmt.Errorf("function id %v: function not registered", id)
		return
	}

	var ok bool
	switch n {
	case 0:
		_, ok = f.(func([]interface{}))
	case 1:
		_, ok = f.(func([]interface{}) interface{})
	case 2:
		_, ok = f.(func([]interface{}) []interface{})
	default:
		panic("bug")
	}

	if !ok {
		err = fmt.Errorf("function id %v: return type mismatch", id)
	}
	return
}

func (c *Client) Call0(id interface{}, args ...interface{}) error {
	f, err := c.f(id, 0)
	if err != nil {
		return err
	}

	err = c.call(&CallInfo{
		f:       f,
		args:    args,
		chanRet: c.chanSyncRet,
	}, true)
	if err != nil {
		return err
	}

	ri := <-c.chanSyncRet
	return ri.err
}

func (c *Client) Call1(id interface{}, args ...interface{}) (interface{}, error) {
	f, err := c.f(id, 1)
	if err != nil {
		return nil, err
	}

	err = c.call(&CallInfo{
		f:       f,
		args:    args,
		chanRet: c.chanSyncRet,
	}, true)
	if err != nil {
		return nil, err
	}

	ri := <-c.chanSyncRet
	return ri.ret, ri.err
}

func (c *Client) CallN(id interface{}, args ...interface{}) ([]interface{}, error) {
	f, err := c.f(id, 2)
	if err != nil {
		return nil, err
	}

	err = c.call(&CallInfo{
		f:       f,
		args:    args,
		chanRet: c.chanSyncRet,
	}, true)
	if err != nil {
		return nil, err
	}

	ri := <-c.chanSyncRet
	return assert(ri.ret), ri.err
}

func (c *Client) asynCall(id interface{}, args []interface{}, cb interface{}, n int) {
	f, err := c.f(id, n)
	if err != nil {
		c.ChanAsynRet <- &RetInfo{err: err, cb: cb}
		return
	}

	err = c.call(&CallInfo{
		f:       f,
		args:    args,
		chanRet: c.ChanAsynRet,
		cb:      cb,
	}, false)
	if err != nil {
		c.ChanAsynRet <- &RetInfo{err: err, cb: cb}
		return
	}
}

func (c *Client) AsynCall(id interface{}, _args ...interface{}) {
	if len(_args) < 1 {
		panic("callback function not found")
	}

	args := _args[:len(_args)-1]
	cb := _args[len(_args)-1]

	var n int
	switch cb.(type) {
	case func(error):
		n = 0
	case func(interface{}, error):
		n = 1
	case func([]interface{}, error):
		n = 2
	default:
		panic("definition of callback function is invalid")
	}

	// too many calls
	if c.pendingAsynCall >= cap(c.ChanAsynRet) {
		execCb(&RetInfo{err: errors.New("too many calls"), cb: cb})
		return
	}

	c.asynCall(id, args, cb, n)
	c.pendingAsynCall++
}

func execCb(ri *RetInfo) {
	defer func() {
		if r := recover(); r != nil {
			if conf.LenStackBuf > 0 {
				buf := make([]byte, conf.LenStackBuf)
				l := runtime.Stack(buf, false)
				log.Error("%v: %s", r, buf[:l])
			} else {
				log.Error("%v", r)
			}
		}
	}()

	// execute
	switch ri.cb.(type) {
	case func(error):
		ri.cb.(func(error))(ri.err)
	case func(interface{}, error):
		ri.cb.(func(interface{}, error))(ri.ret, ri.err)
	case func([]interface{}, error):
		ri.cb.(func([]interface{}, error))(assert(ri.ret), ri.err)
	default:
		panic("bug")
	}
	return
}

func (c *Client) Cb(ri *RetInfo) {
	c.pendingAsynCall--
	execCb(ri)
}

func (c *Client) Close() {
	for c.pendingAsynCall > 0 {
		c.Cb(<-c.ChanAsynRet)
	}
}

func (c *Client) Idle() bool {
	return c.pendingAsynCall == 0
}
<commit_msg>fix chanrpc example test failed.<commit_after>package chanrpc

import (
	"errors"
	"fmt"
	"github.com/name5566/leaf/conf"
	"github.com/name5566/leaf/log"
	"runtime"
)

// one server per goroutine (goroutine not safe)
// one client per goroutine (goroutine not safe)
type Server struct {
	// id -> function
	//
	// function:
	// func(args []interface{})
	// func(args []interface{}) interface{}
	// func(args []interface{}) []interface{}
	functions map[interface{}]interface{}
	ChanCall  chan *CallInfo
}

type CallInfo struct {
	f       interface{}
	args    []interface{}
	chanRet chan *RetInfo
	cb      interface{}
}

type RetInfo struct {
	// nil
	// interface{}
	// []interface{}
	ret interface{}
	err error
	// callback:
	// func(err error)
	// func(ret interface{}, err error)
	// func(ret []interface{}, err error)
	cb interface{}
}

type Client struct {
	s               *Server
	chanSyncRet     chan *RetInfo
	ChanAsynRet     chan *RetInfo
	pendingAsynCall int
}

func NewServer(l int) *Server {
	s := new(Server)
	s.functions = make(map[interface{}]interface{})
	s.ChanCall = make(chan *CallInfo, l)
	return s
}

func assert(i interface{}) []interface{} {
	if i == nil {
		return nil
	} else {
		return i.([]interface{})
	}
}

// you must call the function before calling Open and Go
func (s *Server) Register(id interface{}, f interface{}) {
	switch f.(type) {
	case func([]interface{}):
	case func([]interface{}) interface{}:
	case func([]interface{}) []interface{}:
	default:
		panic(fmt.Sprintf("function id %v: definition of function is invalid", id))
	}

	if _, ok := s.functions[id]; ok {
		panic(fmt.Sprintf("function id %v: already registered", id))
	}

	s.functions[id] = f
}

func (s *Server) ret(ci *CallInfo, ri *RetInfo) (err error) {
	if ci.chanRet == nil {
		return
	}

	defer func() {
		if r := recover(); r != nil {
			err = r.(error)
		}
	}()

	ri.cb = ci.cb
	ci.chanRet <- ri
	return
}

func (s *Server) exec(ci *CallInfo) (err error) {
	defer func() {
		if r := recover(); r != nil {
			if conf.LenStackBuf > 0 {
				buf := make([]byte, conf.LenStackBuf)
				l := runtime.Stack(buf, false)
				err = fmt.Errorf("%v: %s", r, buf[:l])
			} else {
				err = fmt.Errorf("%v", r)
			}

			s.ret(ci, &RetInfo{err: fmt.Errorf("%v", r)})
		}
	}()

	// execute
	switch ci.f.(type) {
	case func([]interface{}):
		ci.f.(func([]interface{}))(ci.args)
		return s.ret(ci, &RetInfo{})
	case func([]interface{}) interface{}:
		ret := ci.f.(func([]interface{}) interface{})(ci.args)
		return s.ret(ci, &RetInfo{ret: ret})
	case func([]interface{}) []interface{}:
		ret := ci.f.(func([]interface{}) []interface{})(ci.args)
		return s.ret(ci, &RetInfo{ret: ret})
	}

	panic("bug")
}

func (s *Server) Exec(ci *CallInfo) error{
	err := s.exec(ci)
	if err != nil {
		log.Error("%v", err)
	}
	return err
}

// goroutine safe
func (s *Server) Go(id interface{}, args ...interface{}) {
	f := s.functions[id]
	if f == nil {
		return
	}

	defer func() {
		recover()
	}()

	s.ChanCall <- &CallInfo{
		f:    f,
		args: args,
	}
}

// goroutine safe
func (s *Server) Call0(id interface{}, args ...interface{}) error {
	return s.Open(0).Call0(id, args...)
}

// goroutine safe
func (s *Server) Call1(id interface{}, args ...interface{}) (interface{}, error) {
	return s.Open(0).Call1(id, args...)
}

// goroutine safe
func (s *Server) CallN(id interface{}, args ...interface{}) ([]interface{}, error) {
	return s.Open(0).CallN(id, args...)
}

func (s *Server) Close() {
	close(s.ChanCall)

	for ci := range s.ChanCall {
		s.ret(ci, &RetInfo{
			err: errors.New("chanrpc server closed"),
		})
	}
}

// goroutine safe
func (s *Server) Open(l int) *Client {
	c := NewClient(l)
	c.Attach(s)
	return c
}

func NewClient(l int) *Client {
	c := new(Client)
	c.chanSyncRet = make(chan *RetInfo, 1)
	c.ChanAsynRet = make(chan *RetInfo, l)
	return c
}

func (c *Client) Attach(s *Server) {
	c.s = s
}

func (c *Client) call(ci *CallInfo, block bool) (err error) {
	defer func() {
		if r := recover(); r != nil {
			err = r.(error)
		}
	}()

	if block {
		c.s.ChanCall <- ci
	} else {
		select {
		case c.s.ChanCall <- ci:
		default:
			err = errors.New("chanrpc channel full")
		}
	}
	return
}

func (c *Client) f(id interface{}, n int) (f interface{}, err error) {
	if c.s == nil {
		err = errors.New("server not attached")
		return
	}

	f = c.s.functions[id]
	if f == nil {
		err = fmt.Errorf("function id %v: function not registered", id)
		return
	}

	var ok bool
	switch n {
	case 0:
		_, ok = f.(func([]interface{}))
	case 1:
		_, ok = f.(func([]interface{}) interface{})
	case 2:
		_, ok = f.(func([]interface{}) []interface{})
	default:
		panic("bug")
	}

	if !ok {
		err = fmt.Errorf("function id %v: return type mismatch", id)
	}
	return
}

func (c *Client) Call0(id interface{}, args ...interface{}) error {
	f, err := c.f(id, 0)
	if err != nil {
		return err
	}

	err = c.call(&CallInfo{
		f:       f,
		args:    args,
		chanRet: c.chanSyncRet,
	}, true)
	if err != nil {
		return err
	}

	ri := <-c.chanSyncRet
	return ri.err
}

func (c *Client) Call1(id interface{}, args ...interface{}) (interface{}, error) {
	f, err := c.f(id, 1)
	if err != nil {
		return nil, err
	}

	err = c.call(&CallInfo{
		f:       f,
		args:    args,
		chanRet: c.chanSyncRet,
	}, true)
	if err != nil {
		return nil, err
	}

	ri := <-c.chanSyncRet
	return ri.ret, ri.err
}

func (c *Client) CallN(id interface{}, args ...interface{}) ([]interface{}, error) {
	f, err := c.f(id, 2)
	if err != nil {
		return nil, err
	}

	err = c.call(&CallInfo{
		f:       f,
		args:    args,
		chanRet: c.chanSyncRet,
	}, true)
	if err != nil {
		return nil, err
	}

	ri := <-c.chanSyncRet
	return assert(ri.ret), ri.err
}

func (c *Client) asynCall(id interface{}, args []interface{}, cb interface{}, n int) {
	f, err := c.f(id, n)
	if err != nil {
		c.ChanAsynRet <- &RetInfo{err: err, cb: cb}
		return
	}

	err = c.call(&CallInfo{
		f:       f,
		args:    args,
		chanRet: c.ChanAsynRet,
		cb:      cb,
	}, false)
	if err != nil {
		c.ChanAsynRet <- &RetInfo{err: err, cb: cb}
		return
	}
}

func (c *Client) AsynCall(id interface{}, _args ...interface{}) {
	if len(_args) < 1 {
		panic("callback function not found")
	}

	args := _args[:len(_args)-1]
	cb := _args[len(_args)-1]

	var n int
	switch cb.(type) {
	case func(error):
		n = 0
	case func(interface{}, error):
		n = 1
	case func([]interface{}, error):
		n = 2
	default:
		panic("definition of callback function is invalid")
	}

	// too many calls
	if c.pendingAsynCall >= cap(c.ChanAsynRet) {
		execCb(&RetInfo{err: errors.New("too many calls"), cb: cb})
		return
	}

	c.asynCall(id, args, cb, n)
	c.pendingAsynCall++
}

func execCb(ri *RetInfo) {
	defer func() {
		if r := recover(); r != nil {
			if conf.LenStackBuf > 0 {
				buf := make([]byte, conf.LenStackBuf)
				l := runtime.Stack(buf, false)
				log.Error("%v: %s", r, buf[:l])
			} else {
				log.Error("%v", r)
			}
		}
	}()

	// execute
	switch ri.cb.(type) {
	case func(error):
		ri.cb.(func(error))(ri.err)
	case func(interface{}, error):
		ri.cb.(func(interface{}, error))(ri.ret, ri.err)
	case func([]interface{}, error):
		ri.cb.(func([]interface{}, error))(assert(ri.ret), ri.err)
	default:
		panic("bug")
	}
	return
}

func (c *Client) Cb(ri *RetInfo) {
	c.pendingAsynCall--
	execCb(ri)
}

func (c *Client) Close() {
	for c.pendingAsynCall > 0 {
		c.Cb(<-c.ChanAsynRet)
	}
}

func (c *Client) Idle() bool {
	return c.pendingAsynCall == 0
}
<|endoftext|>


<commit_before>package margelet

import (
	"gopkg.in/redis.v3"
	"strconv"
	"strings"
)

// ChatRepository - repository for started chats
type ChatRepository struct {
	key   string
	redis *redis.Client
}

func newChatRepository(prefix string, redis *redis.Client) *ChatRepository {
	key := strings.Join([]string{prefix, "margelet_chats"}, "-")
	return &ChatRepository{key, redis}
}

func (chat *ChatRepository) Add(id int64) {
	chat.redis.SAdd(chat.key, strconv.FormatInt(id, 10))
}

func (chat *ChatRepository) Remove(id int64) {
	chat.redis.SRem(chat.key, strconv.FormatInt(id, 10))
}

func (chat *ChatRepository) All() []int64 {
	var result []int64
	strings, _ := chat.redis.SMembers(chat.key).Result()

	for _, str := range strings {
		if c, err := strconv.ParseInt(str, 10, 64); err == nil {
			result = append(result, c)
		}
	}
	return result
}
<commit_msg>ChatRepository::exist<commit_after>package margelet

import (
	"gopkg.in/redis.v3"
	"strconv"
	"strings"
)

// ChatRepository - repository for started chats
type ChatRepository struct {
	key   string
	redis *redis.Client
}

func newChatRepository(prefix string, redis *redis.Client) *ChatRepository {
	key := strings.Join([]string{prefix, "margelet_chats"}, "-")
	return &ChatRepository{key, redis}
}

func (chat *ChatRepository) Add(id int64) {
	chat.redis.SAdd(chat.key, strconv.FormatInt(id, 10))
}

func (chat *ChatRepository) Exist(id int64) (res bool) {
	res, _ = chat.redis.SIsMember(chat.key, strconv.FormatInt(id, 10)).Result()
	return
}

func (chat *ChatRepository) Remove(id int64) {
	chat.redis.SRem(chat.key, strconv.FormatInt(id, 10))
}

func (chat *ChatRepository) All() []int64 {
	var result []int64
	strings, _ := chat.redis.SMembers(chat.key).Result()

	for _, str := range strings {
		if c, err := strconv.ParseInt(str, 10, 64); err == nil {
			result = append(result, c)
		}
	}
	return result
}
<|endoftext|>


<commit_before>package chess
<commit_msg>adding pawn tests<commit_after>package chess

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestPawn_ValidMoves(t *testing.T) {
	boardFEN := func(fen FEN) *Board {
		b, _ := BoardFEN(fen)
		return b
	}

	type fields struct {
		board      *Board
		Coordinate Coordinate
	}

	tests := []struct {
		name   string
		fields fields
		want   []string
	}{
		{
			"A White Pawn may advance 2 square on it's first move",
			fields{boardFEN(StartingPositionFEN), Coordinate{A, 2}},
			[]string{"a2a3, a2a4"},
		},
		{
			"A Black Pawn may advance 2 square on it's first move",
			fields{boardFEN(StartingPositionFEN), Coordinate{A, 7}},
			[]string{"a7a6, a7a5"},
		},

		{
			"A White Pawn may only advance 1 square at a time",
			fields{boardFEN("k7/8/3p4/8/8/3P4/8/K7 w - - 0 1"), Coordinate{D, 3}},
			[]string{"d3d4"},
		},
		{
			"A Black Pawn may only advance 1 square at a time",
			fields{boardFEN("k7/8/3p4/8/8/3P4/8/K7 w - - 0 1"), Coordinate{D, 6}},
			[]string{"d6d5"},
		},
		{
			"A white pawn may cannot capture a piece directly in front of itself",
			fields{boardFEN("k7/8/8/3p4/3P4/8/8/K7 w - - 0 1"), Coordinate{D, 4}},
			[]string{},
		},
		{
			"A black pawn may cannot capture a piece directly in front of itself",
			fields{boardFEN("k7/8/8/3p4/3P4/8/8/K7 w - - 0 1"), Coordinate{D, 5}},
			[]string{},
		},
		{
			"A white pawn may capture a piece diagonally one square in front itself",
			fields{boardFEN("k7/8/8/2npn3/2NPN3/8/8/K7 w - - 0 1"), Coordinate{D, 4}},
			[]string{"d4xc5", "d4xe5"},
		},
		{
			"A black pawn may capture a piece diagonally one square in front itself",
			fields{boardFEN("k7/8/8/2npn3/2NPN3/8/8/K7 w - - 0 1"), Coordinate{D, 5}},
			[]string{"d5xc4", "d5xe4"},
		},
		{
			"A white pawn may not capture a piece that is more than diagonal square away",
			fields{boardFEN("k7/8/1n3n2/3p4/3P4/1N3N2/8/K7 w - - 0 1"), Coordinate{D, 4}},
			[]string{},
		},
		{
			"A black pawn may not capture a piece that is more than diagonal square away",
			fields{boardFEN("k7/8/1n3n2/3p4/3P4/1N3N2/8/K7 w - - 0 1"), Coordinate{D, 5}},
			[]string{},
		},
		{
			"A white pawn may not move backwards",
			fields{boardFEN("k7/8/8/3p4/3P4/8/8/K7 w - - 0 1"), Coordinate{D, 4}},
			[]string{},
		},
		{
			"A black pawn may not move backwards",
			fields{boardFEN("k7/8/8/3p4/3P4/8/8/K7 w - - 0 1"), Coordinate{D, 5}},
			[]string{},
		},
		{
			"A white pawn may not jump over it's own piece",
			fields{boardFEN("k7/8/8/2RRR3/2RPR3/2RRR3/8/K7 w - - 0 1"), Coordinate{D, 4}},
			[]string{},
		},
		{
			"A black pawn may not jump over it's own piece",
			fields{boardFEN("k7/8/2rrr3/2rpr3/2rrr3/8/8/K7 w - - 0 1"), Coordinate{D, 5}},
			[]string{},
		},

		{
			"A white pawn may not capture a oponents king",
			fields{boardFEN("8/8/6p1/5KRR/1rrk4/2P5/8/8 w - - 0 1"), Coordinate{C, 3}},
			[]string{"c3xb4"},
		},
		{
			"A black pawn may not capture a oponents king",
			fields{boardFEN("8/8/6p1/5KRR/1rrk4/2P5/8/8 w - - 0 1"), Coordinate{G, 6}},
			[]string{"g6xh5"},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			pawn := tt.fields.board.GetSquare(tt.fields.Coordinate.File, tt.fields.Coordinate.Rank).CurrentPiece
			aMoves := pawn.ValidMoves(tt.fields.board)
			assert.Equal(t, PawnType, pawn.PieceType(), "Wrong piece type")

			assert.Equal(t, len(tt.want), len(aMoves), "Incorrect Number of Moves")

			var aMovePGNS []string
			for _, m := range aMoves {
				aMovePGNS = append(aMovePGNS, m.PGNName())
			}

			for _, aMove := range aMoves {
				assert.Contains(t, tt.want, aMove.PGNName(), "Expected Slice doesn't contain actual")
			}

			for _, eMove := range tt.want {
				assert.Contains(t, aMovePGNS, eMove, "Actual Slice doesn't contain expected")
			}
		})
	}
}
<|endoftext|>


<commit_before>package cli

import (
	"fmt"
	"net"
	"os"
	"testing"

	"github.com/juju/errgo"
	. "github.com/onsi/gomega"

	"github.com/giantswarm/formica/controller"
	"github.com/giantswarm/formica/file-system/fake"
	"github.com/giantswarm/formica/fleet"
)

type testFileSystemSetup struct {
	FileName    string
	FileContent []byte
	FilePerm    os.FileMode
}

func Test_Common_createRequestWithContent(t *testing.T) {
	testCases := []struct {
		Setup    []testFileSystemSetup
		Input    []string
		Error    error
		Expected controller.Request
	}{
		// This test ensures that loading a single unit from a directory results in
		// the expected controller request.
		{
			Setup: []testFileSystemSetup{
				{
					FileName:    "dirname/dirname_unit.service",
					FileContent: []byte("some unit content"),
					FilePerm:    os.FileMode(0644),
				},
			},
			Input: []string{"dirname"},
			Error: nil,
			Expected: controller.Request{
				SliceIDs: []string{},
				Units: []controller.Unit{
					{
						Name:    "dirname_unit.service",
						Content: "some unit content",
					},
				},
			},
		},

		// This test ensures that trying to load unit files with invalid input
		// throws an error.
		{
			Setup:    []testFileSystemSetup{},
			Input:    []string{},
			Error:    invalidArgumentsError,
			Expected: controller.Request{},
		},

		// This test ensures that trying to load unit files when no files are in
		// the file system throws an error.
		{
			Setup: []testFileSystemSetup{},
			Input: []string{"dirname"},
			Error: &os.PathError{
				Op:   "open",
				Path: "dirname",
				Err:  errgo.New("no such file or directory"),
			},
			Expected: controller.Request{},
		},

		// This test ensures that loading a single unit from a directory with the
		// slice expression "@1" results in the expected controller request.
		{
			Setup: []testFileSystemSetup{
				{
					FileName:    "dirname/dirname_unit@.service",
					FileContent: []byte("some unit content"),
					FilePerm:    os.FileMode(0644),
				},
			},
			Input: []string{"dirname@1"},
			Error: nil,
			Expected: controller.Request{
				SliceIDs: []string{"1"},
				Units: []controller.Unit{
					{
						Name:    "dirname_unit@.service",
						Content: "some unit content",
					},
				},
			},
		},

		// This test ensures that loading a single unit from a directory with the
		// slice expression "@1", "@foo" and "@5" results in the expected
		// controller request.
		{
			Setup: []testFileSystemSetup{
				{
					FileName:    "dirname/dirname_unit@.service",
					FileContent: []byte("some unit content"),
					FilePerm:    os.FileMode(0644),
				},
			},
			Input: []string{"dirname@1", "dirname@foo", "dirname@5"},
			Error: nil,
			Expected: controller.Request{
				SliceIDs: []string{"1", "foo", "5"},
				Units: []controller.Unit{
					{
						Name:    "dirname_unit@.service",
						Content: "some unit content",
					},
				},
			},
		},
	}

	for i, testCase := range testCases {
		newFileSystem = filesystemfake.NewFileSystem()

		for _, setup := range testCase.Setup {
			err := newFileSystem.WriteFile(setup.FileName, setup.FileContent, setup.FilePerm)
			if err != nil {
				t.Fatalf("FileSystem.WriteFile returned error: %#v", err)
			}
		}

		output, err := createRequestWithContent(testCase.Input)
		fmt.Printf("output: %#v\n", output)
		fmt.Printf("err: %#v\n", err)
		if testCase.Error != nil && err.Error() != testCase.Error.Error() {
			t.Fatalf("(test case %d) createRequestWithContent was expected to return error: %#v", i+1, testCase.Error)
		}

		if len(output.SliceIDs) != len(testCase.Expected.SliceIDs) {
			t.Fatalf("(test case %d) sliceIDs of generated output differs from expected sliceIDs", i+1)
		}

		for i, outputUnit := range output.Units {
			if outputUnit.Name != testCase.Expected.Units[i].Name {
				t.Fatalf("output unit name '%s' is not equal to expected unit name '%s'", outputUnit.Name, testCase.Expected.Units[i].Name)
			}
		}
	}
}

func Test_Common_createRequest(t *testing.T) {
	testCases := []struct {
		Input    []string
		Error    error
		Expected controller.Request
	}{
		// This test ensures that loading a single unit from a directory results in
		// the expected controller request.
		{
			Input: []string{"dirname"},
			Error: nil,
			Expected: controller.Request{
				SliceIDs: []string{},
				Units: []controller.Unit{
					{
						Name:    "dirname_unit.service",
						Content: "some unit content",
					},
				},
			},
		},

		// This test ensures that trying to load unit files with invalid input
		// throws an error.
		{
			Input:    []string{},
			Error:    invalidArgumentsError,
			Expected: controller.Request{},
		},

		// This test ensures that loading a single unit from a directory with the
		// slice expression "@1" results in the expected controller request.
		{
			Input: []string{"dirname@1"},
			Error: nil,
			Expected: controller.Request{
				SliceIDs: []string{"1"},
				Units: []controller.Unit{
					{
						Name:    "dirname_unit@.service",
						Content: "some unit content",
					},
				},
			},
		},

		// This test ensures that loading a single unit from a directory with the
		// slice expression "@1", "@foo" and "@5" results in the expected
		// controller request.
		{
			Input: []string{"dirname@1", "dirname@foo", "dirname@5"},
			Expected: controller.Request{
				SliceIDs: []string{"1", "foo", "5"},
				Units: []controller.Unit{
					{
						Name:    "dirname_unit@.service",
						Content: "some unit content",
					},
				},
			},
		},
	}

	for i, testCase := range testCases {
		output, err := createRequest(testCase.Input)
		if testCase.Error != nil && err.Error() != testCase.Error.Error() {
			t.Fatalf("createRequest was expected to return error: %#v", testCase.Error)
		}

		if len(output.SliceIDs) != len(testCase.Expected.SliceIDs) {
			t.Fatalf("(test case %d) sliceIDs of generated output differs from expected sliceIDs", i+1)
		}

		for i, outputUnit := range output.Units {
			if outputUnit.Name != testCase.Expected.Units[i].Name {
				t.Fatalf("output unit name '%s' is not equal to expected unit name '%s'", outputUnit.Name, testCase.Expected.Units[i].Name)
			}
		}
	}
}

// tests the status formating for three slices of a group
func Test_Common_createStatus_Group_ThreeSlices(t *testing.T) {
	RegisterTestingT(t)

	expectedStatusOutput := []string{
		"Group | Units | FDState | FCState | SAState | IP | Machine",
		"",
		"example@1 | * | loaded | loaded | inactive | 172.17.8.101 | 505e0d7802d7439a924c269b76f34b5f",
		"example@2 | * | loaded | loaded | inactive | 172.17.8.102 | 9ebb53b04b0d46fb94b4fd1b3f562d2b",
		"example@3 | * | loaded | loaded | inactive | 172.17.8.103 | e3cb5f13a9164ba5b7eff6c920475e61",
		"",
	}

	group := "example"

	statusList := controller.UnitStatusList{
		unitStatus("example-foo@1.service", "@1", "172.17.8.101", "505e0d7802d7439a924c269b76f34b5f"),
		unitStatus("example-bar@1.service", "@1", "172.17.8.101", "505e0d7802d7439a924c269b76f34b5f"),
		unitStatus("example-foo@2.service", "@2", "172.17.8.102", "9ebb53b04b0d46fb94b4fd1b3f562d2b"),
		unitStatus("example-bar@2.service", "@2", "172.17.8.102", "9ebb53b04b0d46fb94b4fd1b3f562d2b"),
		unitStatus("example-foo@3.service", "@3", "172.17.8.103", "e3cb5f13a9164ba5b7eff6c920475e61"),
		unitStatus("example-bar@3.service", "@3", "172.17.8.103", "e3cb5f13a9164ba5b7eff6c920475e61"),
	}

	status, err := createStatus(group, statusList)
	Expect(err).To(Not(HaveOccurred()))
	Expect(status).To(Equal(expectedStatusOutput))
}

// tests the status formating for one slice of a group
func Test_Common_createStatus_Group_OneSlice(t *testing.T) {
	RegisterTestingT(t)

	expectedStatusOutput := []string{
		"Group | Units | FDState | FCState | SAState | IP | Machine",
		"",
		"example@1 | * | loaded | loaded | inactive | 172.17.8.101 | 505e0d7802d7439a924c269b76f34b5f",
		"",
	}

	group := "example"

	statusList := controller.UnitStatusList{
		unitStatus("example-foo", "@1", "172.17.8.101", "505e0d7802d7439a924c269b76f34b5f"),
		unitStatus("example-bar", "@1", "172.17.8.101", "505e0d7802d7439a924c269b76f34b5f"),
	}

	status, err := createStatus(group, statusList)
	Expect(err).To(Not(HaveOccurred()))

	Expect(status).To(Equal(expectedStatusOutput))
}

func Test_Common_createStatus_Group_ThreeSlices_Verbose(t *testing.T) {
	RegisterTestingT(t)

	globalFlags.Verbose = true
	expectedStatusOutput := []string{
		"Group | Units | FDState | FCState | SAState | Hash | IP | Machine",
		"",
		"example@1 | example-foo@1.service | loaded | loaded | inactive | 4311 | 172.17.8.101 | 505e0d7802d7439a924c269b76f34b5f",
		"example@1 | example-bar@1.service | loaded | loaded | inactive | 4311 | 172.17.8.101 | 505e0d7802d7439a924c269b76f34b5f",

		"example@2 | example-foo@2.service | loaded | loaded | inactive | 4311 | 172.17.8.102 | 9ebb53b04b0d46fb94b4fd1b3f562d2b",
		"example@2 | example-bar@2.service | loaded | loaded | inactive | 4311 | 172.17.8.102 | 9ebb53b04b0d46fb94b4fd1b3f562d2b",

		"example@3 | example-foo@3.service | loaded | loaded | inactive | 4311 | 172.17.8.103 | e3cb5f13a9164ba5b7eff6c920475e61",
		"example@3 | example-bar@3.service | loaded | loaded | inactive | 4311 | 172.17.8.103 | e3cb5f13a9164ba5b7eff6c920475e61",
		"",
	}

	group := "example"

	statusList := controller.UnitStatusList{
		unitStatus("example-foo@1.service", "@1", "172.17.8.101", "505e0d7802d7439a924c269b76f34b5f"),
		unitStatus("example-bar@1.service", "@1", "172.17.8.101", "505e0d7802d7439a924c269b76f34b5f"),
		unitStatus("example-foo@2.service", "@2", "172.17.8.102", "9ebb53b04b0d46fb94b4fd1b3f562d2b"),
		unitStatus("example-bar@2.service", "@2", "172.17.8.102", "9ebb53b04b0d46fb94b4fd1b3f562d2b"),
		unitStatus("example-foo@3.service", "@3", "172.17.8.103", "e3cb5f13a9164ba5b7eff6c920475e61"),
		unitStatus("example-bar@3.service", "@3", "172.17.8.103", "e3cb5f13a9164ba5b7eff6c920475e61"),
	}

	status, err := createStatus(group, statusList)
	Expect(err).To(Not(HaveOccurred()))
	Expect(status).To(Equal(expectedStatusOutput))
}

func unitStatus(name, slice, machineIP, machineID string) fleet.UnitStatus {
	return fleet.UnitStatus{
		Current: "loaded",
		Desired: "loaded",
		Machine: []fleet.MachineStatus{
			fleet.MachineStatus{
				ID:            machineID,
				IP:            net.ParseIP(machineIP),
				SystemdActive: "inactive",
				SystemdSub:    "inactive",
				UnitHash:      "4311",
			},
		},
		Name:  name,
		Slice: slice,
	}
}
<commit_msg>refactored tests<commit_after>package cli

import (
	"fmt"
	"net"
	"os"
	"testing"

	"github.com/juju/errgo"
	. "github.com/onsi/gomega"

	"github.com/giantswarm/formica/controller"
	"github.com/giantswarm/formica/file-system/fake"
	"github.com/giantswarm/formica/fleet"
)

type testFileSystemSetup struct {
	FileName    string
	FileContent []byte
	FilePerm    os.FileMode
}

func Test_Common_createRequestWithContent(t *testing.T) {
	testCases := []struct {
		Setup    []testFileSystemSetup
		Input    []string
		Error    error
		Expected controller.Request
	}{
		// This test ensures that loading a single unit from a directory results in
		// the expected controller request.
		{
			Setup: []testFileSystemSetup{
				{
					FileName:    "dirname/dirname_unit.service",
					FileContent: []byte("some unit content"),
					FilePerm:    os.FileMode(0644),
				},
			},
			Input: []string{"dirname"},
			Error: nil,
			Expected: controller.Request{
				SliceIDs: []string{},
				Units: []controller.Unit{
					{
						Name:    "dirname_unit.service",
						Content: "some unit content",
					},
				},
			},
		},

		// This test ensures that trying to load unit files with invalid input
		// throws an error.
		{
			Setup:    []testFileSystemSetup{},
			Input:    []string{},
			Error:    invalidArgumentsError,
			Expected: controller.Request{},
		},

		// This test ensures that trying to load unit files when no files are in
		// the file system throws an error.
		{
			Setup: []testFileSystemSetup{},
			Input: []string{"dirname"},
			Error: &os.PathError{
				Op:   "open",
				Path: "dirname",
				Err:  errgo.New("no such file or directory"),
			},
			Expected: controller.Request{},
		},

		// This test ensures that loading a single unit from a directory with the
		// slice expression "@1" results in the expected controller request.
		{
			Setup: []testFileSystemSetup{
				{
					FileName:    "dirname/dirname_unit@.service",
					FileContent: []byte("some unit content"),
					FilePerm:    os.FileMode(0644),
				},
			},
			Input: []string{"dirname@1"},
			Error: nil,
			Expected: controller.Request{
				SliceIDs: []string{"1"},
				Units: []controller.Unit{
					{
						Name:    "dirname_unit@.service",
						Content: "some unit content",
					},
				},
			},
		},

		// This test ensures that loading a single unit from a directory with the
		// slice expression "@1", "@foo" and "@5" results in the expected
		// controller request.
		{
			Setup: []testFileSystemSetup{
				{
					FileName:    "dirname/dirname_unit@.service",
					FileContent: []byte("some unit content"),
					FilePerm:    os.FileMode(0644),
				},
			},
			Input: []string{"dirname@1", "dirname@foo", "dirname@5"},
			Error: nil,
			Expected: controller.Request{
				SliceIDs: []string{"1", "foo", "5"},
				Units: []controller.Unit{
					{
						Name:    "dirname_unit@.service",
						Content: "some unit content",
					},
				},
			},
		},
	}

	for i, testCase := range testCases {
		newFileSystem = filesystemfake.NewFileSystem()

		for _, setup := range testCase.Setup {
			err := newFileSystem.WriteFile(setup.FileName, setup.FileContent, setup.FilePerm)
			if err != nil {
				t.Fatalf("FileSystem.WriteFile returned error: %#v", err)
			}
		}

		output, err := createRequestWithContent(testCase.Input)
		fmt.Printf("output: %#v\n", output)
		fmt.Printf("err: %#v\n", err)
		if testCase.Error != nil && err.Error() != testCase.Error.Error() {
			t.Fatalf("(test case %d) createRequestWithContent was expected to return error: %#v", i+1, testCase.Error)
		}

		if len(output.SliceIDs) != len(testCase.Expected.SliceIDs) {
			t.Fatalf("(test case %d) sliceIDs of generated output differs from expected sliceIDs", i+1)
		}

		for i, outputUnit := range output.Units {
			if outputUnit.Name != testCase.Expected.Units[i].Name {
				t.Fatalf("output unit name '%s' is not equal to expected unit name '%s'", outputUnit.Name, testCase.Expected.Units[i].Name)
			}
		}
	}
}

func Test_Common_createRequest(t *testing.T) {
	testCases := []struct {
		Input    []string
		Error    error
		Expected controller.Request
	}{
		// This test ensures that loading a single unit from a directory results in
		// the expected controller request.
		{
			Input: []string{"dirname"},
			Error: nil,
			Expected: controller.Request{
				SliceIDs: []string{},
				Units: []controller.Unit{
					{
						Name:    "dirname_unit.service",
						Content: "some unit content",
					},
				},
			},
		},

		// This test ensures that trying to load unit files with invalid input
		// throws an error.
		{
			Input:    []string{},
			Error:    invalidArgumentsError,
			Expected: controller.Request{},
		},

		// This test ensures that loading a single unit from a directory with the
		// slice expression "@1" results in the expected controller request.
		{
			Input: []string{"dirname@1"},
			Error: nil,
			Expected: controller.Request{
				SliceIDs: []string{"1"},
				Units: []controller.Unit{
					{
						Name:    "dirname_unit@.service",
						Content: "some unit content",
					},
				},
			},
		},

		// This test ensures that loading a single unit from a directory with the
		// slice expression "@1", "@foo" and "@5" results in the expected
		// controller request.
		{
			Input: []string{"dirname@1", "dirname@foo", "dirname@5"},
			Expected: controller.Request{
				SliceIDs: []string{"1", "foo", "5"},
				Units: []controller.Unit{
					{
						Name:    "dirname_unit@.service",
						Content: "some unit content",
					},
				},
			},
		},
	}

	for i, testCase := range testCases {
		output, err := createRequest(testCase.Input)
		if testCase.Error != nil && err.Error() != testCase.Error.Error() {
			t.Fatalf("createRequest was expected to return error: %#v", testCase.Error)
		}

		if len(output.SliceIDs) != len(testCase.Expected.SliceIDs) {
			t.Fatalf("(test case %d) sliceIDs of generated output differs from expected sliceIDs", i+1)
		}

		for i, outputUnit := range output.Units {
			if outputUnit.Name != testCase.Expected.Units[i].Name {
				t.Fatalf("output unit name '%s' is not equal to expected unit name '%s'", outputUnit.Name, testCase.Expected.Units[i].Name)
			}
		}
	}
}

func Test_Common_createStatus(t *testing.T) {
	RegisterTestingT(t)

	type input struct {
		Group   string
		USL     controller.UnitStatusList
		Verbose bool
	}
	type testCase struct {
		Comment       string
		Expected      []string
		Input         input
		ShouldBeEqual bool
	}

	testCases := []testCase{
		// 3 slices of 1 group with 2 units
		testCase{
			Comment: "3 slices of 1 group with 2 units",
			Expected: []string{
				"Group | Units | FDState | FCState | SAState | IP | Machine",
				"",
				"example@1 | * | loaded | loaded | inactive | 172.17.8.101 | 505e0d7802d7439a924c269b76f34b5f",
				"example@2 | * | loaded | loaded | inactive | 172.17.8.102 | 9ebb53b04b0d46fb94b4fd1b3f562d2b",
				"example@3 | * | loaded | loaded | inactive | 172.17.8.103 | e3cb5f13a9164ba5b7eff6c920475e61",
				"",
			},
			Input: input{
				Group: "example",
				USL: controller.UnitStatusList{
					unitStatus("example-foo@1.service", "@1", "172.17.8.101", "505e0d7802d7439a924c269b76f34b5f"),
					unitStatus("example-bar@1.service", "@1", "172.17.8.101", "505e0d7802d7439a924c269b76f34b5f"),
					unitStatus("example-foo@2.service", "@2", "172.17.8.102", "9ebb53b04b0d46fb94b4fd1b3f562d2b"),
					unitStatus("example-bar@2.service", "@2", "172.17.8.102", "9ebb53b04b0d46fb94b4fd1b3f562d2b"),
					unitStatus("example-foo@3.service", "@3", "172.17.8.103", "e3cb5f13a9164ba5b7eff6c920475e61"),
					unitStatus("example-bar@3.service", "@3", "172.17.8.103", "e3cb5f13a9164ba5b7eff6c920475e61"),
				},
				Verbose: false,
			},
			ShouldBeEqual: true,
		},
		// 1 slice of 1 group with 2 units
		testCase{
			Comment: "1 slice of 1 group with 2 units",
			Expected: []string{
				"Group | Units | FDState | FCState | SAState | IP | Machine",
				"",
				"example@1 | * | loaded | loaded | inactive | 172.17.8.101 | 505e0d7802d7439a924c269b76f34b5f",
				"",
			},
			Input: input{
				Group: "example",
				USL: controller.UnitStatusList{
					unitStatus("example-foo", "@1", "172.17.8.101", "505e0d7802d7439a924c269b76f34b5f"),
					unitStatus("example-bar", "@1", "172.17.8.101", "505e0d7802d7439a924c269b76f34b5f"),
				},
				Verbose: false,
			},
			ShouldBeEqual: true,
		},
		// 3 slices of 1 group with 2 units - verbose
		testCase{
			Comment: "3 slices of 1 group with 2 units - verbose",
			Expected: []string{
				"Group | Units | FDState | FCState | SAState | Hash | IP | Machine",
				"",
				"example@1 | example-foo@1.service | loaded | loaded | inactive | 4311 | 172.17.8.101 | 505e0d7802d7439a924c269b76f34b5f",
				"example@1 | example-bar@1.service | loaded | loaded | inactive | 4311 | 172.17.8.101 | 505e0d7802d7439a924c269b76f34b5f",
				"example@2 | example-foo@2.service | loaded | loaded | inactive | 4311 | 172.17.8.102 | 9ebb53b04b0d46fb94b4fd1b3f562d2b",
				"example@2 | example-bar@2.service | loaded | loaded | inactive | 4311 | 172.17.8.102 | 9ebb53b04b0d46fb94b4fd1b3f562d2b",
				"example@3 | example-foo@3.service | loaded | loaded | inactive | 4311 | 172.17.8.103 | e3cb5f13a9164ba5b7eff6c920475e61",
				"example@3 | example-bar@3.service | loaded | loaded | inactive | 4311 | 172.17.8.103 | e3cb5f13a9164ba5b7eff6c920475e61",
				"",
			},
			Input: input{
				Group: "example",
				USL: controller.UnitStatusList{
					unitStatus("example-foo@1.service", "@1", "172.17.8.101", "505e0d7802d7439a924c269b76f34b5f"),
					unitStatus("example-bar@1.service", "@1", "172.17.8.101", "505e0d7802d7439a924c269b76f34b5f"),
					unitStatus("example-foo@2.service", "@2", "172.17.8.102", "9ebb53b04b0d46fb94b4fd1b3f562d2b"),
					unitStatus("example-bar@2.service", "@2", "172.17.8.102", "9ebb53b04b0d46fb94b4fd1b3f562d2b"),
					unitStatus("example-foo@3.service", "@3", "172.17.8.103", "e3cb5f13a9164ba5b7eff6c920475e61"),
					unitStatus("example-bar@3.service", "@3", "172.17.8.103", "e3cb5f13a9164ba5b7eff6c920475e61"),
				},
				Verbose: true,
			},
			ShouldBeEqual: true,
		},
	}

	// execute test cases
	for _, test := range testCases {
		globalFlags.Verbose = test.Input.Verbose

		got, err := createStatus(test.Input.Group, test.Input.USL)
		Expect(err).To(Not(HaveOccurred()))

		if test.ShouldBeEqual {
			Expect(got).To(Equal(test.Expected), test.Comment)
		} else {
			Expect(got).NotTo(Equal(test.Expected), test.Comment)
		}
	}
}

func unitStatus(name, slice, machineIP, machineID string) fleet.UnitStatus {
	return fleet.UnitStatus{
		Current: "loaded",
		Desired: "loaded",
		Machine: []fleet.MachineStatus{
			fleet.MachineStatus{
				ID:            machineID,
				IP:            net.ParseIP(machineIP),
				SystemdActive: "inactive",
				SystemdSub:    "inactive",
				UnitHash:      "4311",
			},
		},
		Name:  name,
		Slice: slice,
	}
}
<|endoftext|>


<commit_before>package cmd

import (
	"fmt"
	"net/url"
	"os"
	"strings"
	"time"

	"github.com/deis/pkg/prettyprint"

	"github.com/deis/workflow/client/controller/api"
	"github.com/deis/workflow/client/controller/client"
	"github.com/deis/workflow/client/controller/models/apps"
	"github.com/deis/workflow/client/controller/models/config"
	"github.com/deis/workflow/client/pkg/git"
	"github.com/deis/workflow/client/pkg/webbrowser"
)

// AppCreate creates an app.
func AppCreate(id string, buildpack string, remote string, noRemote bool) error {
	c, err := client.New()
	if err != nil {
		return err
	}

	fmt.Print("Creating Application... ")
	quit := progress()
	app, err := apps.New(c, id)

	quit <- true
	<-quit

	if err != nil {
		return err
	}

	fmt.Printf("done, created %s\n", app.ID)

	if buildpack != "" {
		configValues := api.Config{
			Values: map[string]interface{}{
				"BUILDPACK_URL": buildpack,
			},
		}
		if _, err = config.Set(c, app.ID, configValues); err != nil {
			return err
		}
	}

	if !noRemote {
		if err = git.CreateRemote(c.ControllerURL.Host, remote, app.ID); err != nil {
			if err.Error() == "exit status 128" {
				fmt.Println("To replace the existing git remote entry, run:")
				fmt.Printf("  git remote rename deis deis.old && deis git:remote -a %s\n", app.ID)
			}
			return err
		}
	}

	fmt.Println("remote available at", git.RemoteURL(c.ControllerURL.Host, app.ID))

	return nil
}

// AppsList lists apps on the Deis controller.
func AppsList(results int) error {
	c, err := client.New()

	if err != nil {
		return err
	}

	if results == defaultLimit {
		results = c.ResponseLimit
	}

	apps, count, err := apps.List(c, results)

	if err != nil {
		return err
	}

	fmt.Printf("=== Apps%s", limitCount(len(apps), count))

	for _, app := range apps {
		fmt.Println(app.ID)
	}
	return nil
}

// AppInfo prints info about app.
func AppInfo(appID string) error {
	c, appID, err := load(appID)

	if err != nil {
		return err
	}

	app, err := apps.Get(c, appID)

	if err != nil {
		return err
	}

	fmt.Printf("=== %s Application\n", app.ID)
	fmt.Println("updated: ", app.Updated)
	fmt.Println("uuid:    ", app.UUID)
	fmt.Println("created: ", app.Created)
	fmt.Println("url:     ", app.URL)
	fmt.Println("owner:   ", app.Owner)
	fmt.Println("id:      ", app.ID)

	fmt.Println()
	// print the app processes
	if err = PsList(app.ID, defaultLimit); err != nil {
		return err
	}

	fmt.Println()
	// print the app domains
	if err = DomainsList(app.ID, defaultLimit); err != nil {
		return err
	}

	fmt.Println()

	return nil
}

// AppOpen opens an app in the default webbrowser.
func AppOpen(appID string) error {
	c, appID, err := load(appID)

	if err != nil {
		return err
	}

	app, err := apps.Get(c, appID)

	if err != nil {
		return err
	}

	u, err := url.Parse(app.URL)

	if err != nil {
		return err
	}

	u.Scheme = "http"

	return webbrowser.Webbrowser(u.String())
}

// AppLogs returns the logs from an app.
func AppLogs(appID string, lines int) error {
	c, appID, err := load(appID)

	if err != nil {
		return err
	}

	logs, err := apps.Logs(c, appID, lines)

	if err != nil {
		return err
	}

	return printLogs(logs)
}

// printLogs prints each log line with a color matched to its category.
func printLogs(logs string) error {
	for _, log := range strings.Split(logs, `\\n\\n`) {
		category := "unknown"
		parts := strings.Split(strings.Split(log, " -- ")[0], " ")
		if len(parts) >= 2 {
			category = parts[1]
		}
		colorVars := map[string]string{
			"Color": chooseColor(category),
			"Log":   log,
		}
		fmt.Println(prettyprint.ColorizeVars("{{.V.Color}}{{.V.Log}}{{.C.Default}}", colorVars))
	}

	return nil
}

// AppRun runs a one time command in the app.
func AppRun(appID, command string) error {
	c, appID, err := load(appID)

	if err != nil {
		return err
	}

	fmt.Printf("Running '%s'...\n", command)

	out, err := apps.Run(c, appID, command)

	if err != nil {
		return err
	}

	fmt.Print(out.Output)
	os.Exit(out.ReturnCode)
	return nil
}

// AppDestroy destroys an app.
func AppDestroy(appID, confirm string) error {
	gitSession := false

	c, err := client.New()

	if err != nil {
		return err
	}

	if appID == "" {
		appID, err = git.DetectAppName(c.ControllerURL.Host)

		if err != nil {
			return err
		}

		gitSession = true
	}

	if confirm == "" {
		fmt.Printf(` !    WARNING: Potentially Destructive Action
 !    This command will destroy the application: %s
 !    To proceed, type "%s" or re-run this command with --confirm=%s

> `, appID, appID, appID)

		fmt.Scanln(&confirm)
	}

	if confirm != appID {
		return fmt.Errorf("App %s does not match confirm %s, aborting.", appID, confirm)
	}

	startTime := time.Now()
	fmt.Printf("Destroying %s...\n", appID)

	if err = apps.Delete(c, appID); err != nil {
		return err
	}

	fmt.Printf("done in %ds\n", int(time.Since(startTime).Seconds()))

	if gitSession {
		return git.DeleteRemote(appID)
	}

	return nil
}

// AppTransfer transfers app ownership to another user.
func AppTransfer(appID, username string) error {
	c, appID, err := load(appID)

	if err != nil {
		return err
	}

	fmt.Printf("Transferring %s to %s... ", appID, username)

	err = apps.Transfer(c, appID, username)

	if err != nil {
		return err
	}

	fmt.Println("done")

	return nil
}
<commit_msg>fix(logs): Update the array index for determining the color category fixes #408<commit_after>package cmd

import (
	"fmt"
	"net/url"
	"os"
	"strings"
	"time"

	"github.com/deis/pkg/prettyprint"

	"github.com/deis/workflow/client/controller/api"
	"github.com/deis/workflow/client/controller/client"
	"github.com/deis/workflow/client/controller/models/apps"
	"github.com/deis/workflow/client/controller/models/config"
	"github.com/deis/workflow/client/pkg/git"
	"github.com/deis/workflow/client/pkg/webbrowser"
)

// AppCreate creates an app.
func AppCreate(id string, buildpack string, remote string, noRemote bool) error {
	c, err := client.New()
	if err != nil {
		return err
	}

	fmt.Print("Creating Application... ")
	quit := progress()
	app, err := apps.New(c, id)

	quit <- true
	<-quit

	if err != nil {
		return err
	}

	fmt.Printf("done, created %s\n", app.ID)

	if buildpack != "" {
		configValues := api.Config{
			Values: map[string]interface{}{
				"BUILDPACK_URL": buildpack,
			},
		}
		if _, err = config.Set(c, app.ID, configValues); err != nil {
			return err
		}
	}

	if !noRemote {
		if err = git.CreateRemote(c.ControllerURL.Host, remote, app.ID); err != nil {
			if err.Error() == "exit status 128" {
				fmt.Println("To replace the existing git remote entry, run:")
				fmt.Printf("  git remote rename deis deis.old && deis git:remote -a %s\n", app.ID)
			}
			return err
		}
	}

	fmt.Println("remote available at", git.RemoteURL(c.ControllerURL.Host, app.ID))

	return nil
}

// AppsList lists apps on the Deis controller.
func AppsList(results int) error {
	c, err := client.New()

	if err != nil {
		return err
	}

	if results == defaultLimit {
		results = c.ResponseLimit
	}

	apps, count, err := apps.List(c, results)

	if err != nil {
		return err
	}

	fmt.Printf("=== Apps%s", limitCount(len(apps), count))

	for _, app := range apps {
		fmt.Println(app.ID)
	}
	return nil
}

// AppInfo prints info about app.
func AppInfo(appID string) error {
	c, appID, err := load(appID)

	if err != nil {
		return err
	}

	app, err := apps.Get(c, appID)

	if err != nil {
		return err
	}

	fmt.Printf("=== %s Application\n", app.ID)
	fmt.Println("updated: ", app.Updated)
	fmt.Println("uuid:    ", app.UUID)
	fmt.Println("created: ", app.Created)
	fmt.Println("url:     ", app.URL)
	fmt.Println("owner:   ", app.Owner)
	fmt.Println("id:      ", app.ID)

	fmt.Println()
	// print the app processes
	if err = PsList(app.ID, defaultLimit); err != nil {
		return err
	}

	fmt.Println()
	// print the app domains
	if err = DomainsList(app.ID, defaultLimit); err != nil {
		return err
	}

	fmt.Println()

	return nil
}

// AppOpen opens an app in the default webbrowser.
func AppOpen(appID string) error {
	c, appID, err := load(appID)

	if err != nil {
		return err
	}

	app, err := apps.Get(c, appID)

	if err != nil {
		return err
	}

	u, err := url.Parse(app.URL)

	if err != nil {
		return err
	}

	u.Scheme = "http"

	return webbrowser.Webbrowser(u.String())
}

// AppLogs returns the logs from an app.
func AppLogs(appID string, lines int) error {
	c, appID, err := load(appID)

	if err != nil {
		return err
	}

	logs, err := apps.Logs(c, appID, lines)

	if err != nil {
		return err
	}

	return printLogs(logs)
}

// printLogs prints each log line with a color matched to its category.
func printLogs(logs string) error {
	for _, log := range strings.Split(logs, `\\n\\n`) {
		category := "unknown"
		parts := strings.Split(strings.Split(log, " -- ")[0], " ")
		category = parts[0]
		colorVars := map[string]string{
			"Color": chooseColor(category),
			"Log":   log,
		}
		fmt.Println(prettyprint.ColorizeVars("{{.V.Color}}{{.V.Log}}{{.C.Default}}", colorVars))
	}

	return nil
}

// AppRun runs a one time command in the app.
func AppRun(appID, command string) error {
	c, appID, err := load(appID)

	if err != nil {
		return err
	}

	fmt.Printf("Running '%s'...\n", command)

	out, err := apps.Run(c, appID, command)

	if err != nil {
		return err
	}

	fmt.Print(out.Output)
	os.Exit(out.ReturnCode)
	return nil
}

// AppDestroy destroys an app.
func AppDestroy(appID, confirm string) error {
	gitSession := false

	c, err := client.New()

	if err != nil {
		return err
	}

	if appID == "" {
		appID, err = git.DetectAppName(c.ControllerURL.Host)

		if err != nil {
			return err
		}

		gitSession = true
	}

	if confirm == "" {
		fmt.Printf(` !    WARNING: Potentially Destructive Action
 !    This command will destroy the application: %s
 !    To proceed, type "%s" or re-run this command with --confirm=%s

> `, appID, appID, appID)

		fmt.Scanln(&confirm)
	}

	if confirm != appID {
		return fmt.Errorf("App %s does not match confirm %s, aborting.", appID, confirm)
	}

	startTime := time.Now()
	fmt.Printf("Destroying %s...\n", appID)

	if err = apps.Delete(c, appID); err != nil {
		return err
	}

	fmt.Printf("done in %ds\n", int(time.Since(startTime).Seconds()))

	if gitSession {
		return git.DeleteRemote(appID)
	}

	return nil
}

// AppTransfer transfers app ownership to another user.
func AppTransfer(appID, username string) error {
	c, appID, err := load(appID)

	if err != nil {
		return err
	}

	fmt.Printf("Transferring %s to %s... ", appID, username)

	err = apps.Transfer(c, appID, username)

	if err != nil {
		return err
	}

	fmt.Println("done")

	return nil
}
<|endoftext|>