<commit_before>package chartserver

import (
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"time"

	commonhttp "github.com/goharbor/harbor/src/common/http"
	"github.com/pkg/errors"
)

const (
	clientTimeout         = 10 * time.Second
	maxIdleConnections    = 10
	idleConnectionTimeout = 30 * time.Second
)

// ChartClient is a http client to get the content from the external http server
type ChartClient struct {
	// HTTP client
	httpClient *http.Client

	// Auth info
	credential *Credential
}

// NewChartClient is constructor of ChartClient
// credential can be nil
func NewChartClient(credential *Credential) *ChartClient { // Create http client with customized timeouts
	client := &http.Client{
		Timeout: clientTimeout,
		Transport: &http.Transport{
			MaxIdleConns:    maxIdleConnections,
			IdleConnTimeout: idleConnectionTimeout,
		},
	}

	return &ChartClient{
		httpClient: client,
		credential: credential,
	}
}

// GetContent get the bytes from the specified url
func (cc *ChartClient) GetContent(addr string) ([]byte, error) {
	response, err := cc.sendRequest(addr, http.MethodGet, nil)
	if err != nil {
		err = errors.Wrap(err, "get content failed")
		return nil, err
	}

	content, err := ioutil.ReadAll(response.Body)
	if err != nil {
		err = errors.Wrap(err, "Read response body error")
		return nil, err
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusOK {
		text, err := extractError(content)
		if err != nil {
			err = errors.Wrap(err, "Extract content error failed")
			return nil, err
		}
		return nil, &commonhttp.Error{
			Code:    response.StatusCode,
			Message: text,
		}
	}
	return content, nil
}

// DeleteContent sends deleting request to the addr to delete content
func (cc *ChartClient) DeleteContent(addr string) error {
	response, err := cc.sendRequest(addr, http.MethodDelete, nil)
	if err != nil {
		return err
	}

	content, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return err
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusOK {
		text, err := extractError(content)
		if err != nil {
			return err
		}
		return &commonhttp.Error{
			Code:    response.StatusCode,
			Message: text,
		}
	}

	return nil
}

// sendRequest sends requests to the addr with the specified spec
func (cc *ChartClient) sendRequest(addr string, method string, body io.Reader) (*http.Response, error) {
	if len(strings.TrimSpace(addr)) == 0 {
		return nil, errors.New("empty url is not allowed")
	}

	fullURI, err := url.Parse(addr)
	if err != nil {
		err = errors.Wrap(err, "Invalid url")
		return nil, err
	}

	request, err := http.NewRequest(method, addr, body)
	if err != nil {
		return nil, err
	}

	// Set basic auth
	if cc.credential != nil {
		request.SetBasicAuth(cc.credential.Username, cc.credential.Password)
	}

	response, err := cc.httpClient.Do(request)
	if err != nil {
		err = errors.Wrap(err, fmt.Sprintf("send request %s %s failed", method, fullURI.Path))
		return nil, err
	}

	return response, nil
}
<commit_msg>Feat: enable tls in chart<commit_after>package chartserver

import (
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"time"

	commonhttp "github.com/goharbor/harbor/src/common/http"
	"github.com/pkg/errors"
)

const (
	clientTimeout         = 10 * time.Second
	maxIdleConnections    = 10
	idleConnectionTimeout = 30 * time.Second
)

// ChartClient is a http client to get the content from the external http server
type ChartClient struct {
	// HTTP client
	httpClient *http.Client

	// Auth info
	credential *Credential
}

// NewChartClient is constructor of ChartClient
// credential can be nil
func NewChartClient(credential *Credential) *ChartClient { // Create http client with customized timeouts
	tr := commonhttp.GetHTTPTransport(commonhttp.InternalTransport)
	tr.MaxIdleConns = maxIdleConnections
	tr.IdleConnTimeout = idleConnectionTimeout
	client := &http.Client{
		Timeout:   clientTimeout,
		Transport: tr,
	}

	return &ChartClient{
		httpClient: client,
		credential: credential,
	}
}

// GetContent get the bytes from the specified url
func (cc *ChartClient) GetContent(addr string) ([]byte, error) {
	response, err := cc.sendRequest(addr, http.MethodGet, nil)
	if err != nil {
		err = errors.Wrap(err, "get content failed")
		return nil, err
	}

	content, err := ioutil.ReadAll(response.Body)
	if err != nil {
		err = errors.Wrap(err, "Read response body error")
		return nil, err
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusOK {
		text, err := extractError(content)
		if err != nil {
			err = errors.Wrap(err, "Extract content error failed")
			return nil, err
		}
		return nil, &commonhttp.Error{
			Code:    response.StatusCode,
			Message: text,
		}
	}
	return content, nil
}

// DeleteContent sends deleting request to the addr to delete content
func (cc *ChartClient) DeleteContent(addr string) error {
	response, err := cc.sendRequest(addr, http.MethodDelete, nil)
	if err != nil {
		return err
	}

	content, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return err
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusOK {
		text, err := extractError(content)
		if err != nil {
			return err
		}
		return &commonhttp.Error{
			Code:    response.StatusCode,
			Message: text,
		}
	}

	return nil
}

// sendRequest sends requests to the addr with the specified spec
func (cc *ChartClient) sendRequest(addr string, method string, body io.Reader) (*http.Response, error) {
	if len(strings.TrimSpace(addr)) == 0 {
		return nil, errors.New("empty url is not allowed")
	}

	fullURI, err := url.Parse(addr)
	if err != nil {
		err = errors.Wrap(err, "Invalid url")
		return nil, err
	}

	request, err := http.NewRequest(method, addr, body)
	if err != nil {
		return nil, err
	}

	// Set basic auth
	if cc.credential != nil {
		request.SetBasicAuth(cc.credential.Username, cc.credential.Password)
	}

	response, err := cc.httpClient.Do(request)
	if err != nil {
		err = errors.Wrap(err, fmt.Sprintf("send request %s %s failed", method, fullURI.Path))
		return nil, err
	}

	return response, nil
}
<|endoftext|>


<commit_before>package numgo

import (
	"encoding/json"
	"fmt"
	"math"
	"strings"
	"testing"
)

func init() {
	debug = true
}

func TestNewArray64(t *testing.T) {
	t.Parallel()
	shp := []int{2, 3, 4}
	a := NewArray64(nil, shp...)
	if len(a.data) != 24 {
		t.Logf("Length %d, expected %d", len(a.data), 24)
		t.FailNow()
	}

	for _, v := range a.data {
		if v != 0 {
			t.Logf("Value %f, expected %d", v, 0)
			t.Fail()
		}
	}
	a = NewArray64(nil)
	if e := a.GetErr(); e != nil {
		t.Log("Unexpected error:", e)
		t.Fail()
	}

	a = NewArray64([]float64{0, 1, 2, 3, 4})
	if e := a.Equals(Arange(5)); !e.All().At(0) {
		t.Log("Slice Assignment Failed", a.GetErr(), e)
		t.Fail()
	}

	a = NewArray64([]float64{0, 1, 2, 3, 4}, 3)
	if e := a.Equals(Arange(3)); !e.All().At(0) {
		t.Log("Slice Assignment Failed", a.GetErr(), e)
		t.Fail()
	}

	a = NewArray64([]float64{0, 1, 2, 3, 4, 5}, 2, -1, 3)
	if e := a.GetErr(); e != NegativeAxis {
		t.Log("Expected NegativeAxis, got:", e)
		t.Fail()
	}

	a = NewArray64(nil, 1, 2, 5, 9)
	if e := a.Equals(newArray64(1, 2, 5, 9)); !e.All().At(0) {
		t.Log("Creation has different results:", e)
		t.Fail()
	}
}
func TestFull(t *testing.T) {
	t.Parallel()
	shp := []int{2, 3, 4}
	a := FullArray64(1, shp...)
	if len(a.data) != 24 {
		t.Logf("Length %d, expected %d\n", len(a.data), 24)
		t.Fail()
	}

	for _, v := range a.data {
		if v != 1 {
			t.Logf("Value %f, expected %d\n", v, 1)
			t.Fail()
			break
		}
	}

	if e := a.Equals(full(1, 2, 3, 4)); !e.All().At(0) {
		t.Log("Full creation has different results:", e)
		t.Fail()
	}
	if e := FullArray64(0, shp...).Equals(full(0, 2, 3, 4)); !e.All().At(0) {
		t.Log("Full creation has different results:", e)
		t.Fail()
	}
}

func TestShapes(t *testing.T) {
	shp := []int{3, 3, 4, 7}
	a := NewArray64(nil, shp...)
	for i, v := range a.shape {
		if int(shp[i]) != v {
			t.Log(a.shape, "!=", shp)
			t.FailNow()
		}
	}
}

func TestRandArray64(t *testing.T) {
	t.Parallel()
	a := RandArray64(0, 2, []int{2, 3, -7, 12}...)
	if e := a.GetErr(); e != NegativeAxis {
		t.Log("Expected NegativeAxis, got:", e)
		t.Fail()
	}
}

func TestArange(t *testing.T) {
	t.Parallel()
	a := Arange(24)
	if len(a.data) != 24 {
		t.Logf("Length %d.  Expected size %d\n", len(a.data), 24)
	}
	if len(a.shape) != 1 {
		t.Logf("Axis %d.  Expected %d\n", len(a.shape), 1)
	}
	for i, v := range a.data {
		if float64(i) != v {
			t.Logf("Value %f.  Expected %d\n", v, i)
		}
	}

	if e := a.Equals(Arange(1, 25).SubtrC(1)); e.All().At(0) {
		t.Log("Arange generating incorrect ranges", e)
		t.Fail()
	}

	a = Arange(24, 0)
	for i := 1; i < len(a.data); i++ {
		if a.data[i]-a.data[i-1] != -1 {
			t.Log("Stepping incorrect for negative range.", a)
			t.Fail()
		}
	}

	if e := a.Equals(Arange(-24).MultC(-1)); !e.All().At(0) {
		t.Log("Negative Arange failed", e)
		t.Fail()
	}

	a = Arange(24, 0, 2)
	if e := a.GetErr(); e != ShapeError {
		t.Log("Expected ShapeError, got", e)
		t.Fail()
	}

	a = Arange(0)
	if a.shape[0] != 1 {
		t.Log("Arange(0) shape error:", a.shape[0])
		t.Fail()
	}

	a = Arange()
	if a.shape[0] != 0 {
		t.Log("Arange() shape error:", a.shape[0])
		t.Fail()
	}
}

func TestIdent(t *testing.T) {
	t.Parallel()
	var tmp *Array64
	for k := 0; k < 5; k++ {
		tmp = Identity(k)
		if len(tmp.shape) != 2 {
			t.Log("Incorrect identity shape.", tmp.shape)
			t.Fail()
		}
		if tmp.shape[0] != int(k) || tmp.shape[1] != int(k) {
			t.Log("Incorrect shape values. I()", k, tmp.shape)
			t.Fail()
		}
		if len(tmp.data) != k*k {
			t.Log("Data array incorrect.", tmp.data)
			t.Fail()
		}
		for i := 0; i < k; i++ {
			for j := 0; j < k; j++ {
				if i != j && tmp.At(i, j) != 0 {
					t.Log("Data Value incorrect at", i, j, len(tmp.data))
					t.Fail()
				}
				if i == j && tmp.At(i, j) != 1 {
					t.Log("Data Value incorrect at", i, j, len(tmp.data))
					t.Fail()
				}
			}
		}
	}

	tmp = Identity(-10)
	if e := tmp.GetErr(); e != NegativeAxis {
		t.Log("Error failed.  Expected NegativeAxis, got", e)
		t.Fail()
	}
}

func TestSubArray(t *testing.T) {
	t.Parallel()
	a := Arange(100).Reshape(2, 5, 10)
	b := Arange(50).Reshape(5, 10)
	c := a.SubArr(0)
	if !c.Equals(b).All().At(0) {
		t.Log("Subarray incorrect. Expected\n", b, "\nReceived\n", c)
		t.Fail()
	}

	b = Arange(50).AddC(50).Reshape(5, 10)
	c = a.SubArr(1)
	if !c.Equals(b).All().At(0) {
		t.Log("Subarray incorrect. Expected\n", b, "\nReceived\n", c)
		t.Fail()
	}
}

func TestString(t *testing.T) {
	t.Parallel()
	tests := []struct {
		a   *Array64
		str string
	}{
		{nil, "<nil>"},
		{newArray64(0), "[]"},
		{&Array64{err: InvIndexError}, "Error: " + InvIndexError.s},
		{Arange(10), fmt.Sprint(Arange(10).data)},
		{Arange(10).Reshape(2, 5), "[[0 1 2 3 4] \n [5 6 7 8 9]]"},
		{Arange(20).Reshape(2, 2, 5), "[[[0 1 2 3 4]  \n  [5 6 7 8 9]] \n\n [[10 11 12 13 14]  \n  [15 16 17 18 19]]]"},
		{&Array64{}, "<nil>"},
	}

	for i, tst := range tests {
		if !strings.EqualFold(tst.a.String(), tst.str) {
			t.Log("String() gave unexpected results in test", i)
			t.Log(tst.a)
			t.Log(tst.str)
			t.Fail()
		}
	}
}

func TestReshape(t *testing.T) {
	t.Parallel()
	tests := []struct {
		a   *Array64
		sh  []int
		err error
	}{
		{Arange(10), []int{2, 5}, nil},
		{Arange(11), []int{2, 5}, ReshapeError},
		{Arange(10), []int{2, -5}, NegativeAxis},
		{&Array64{err: InvIndexError}, []int{0}, InvIndexError},
		{nil, []int{1}, NilError},
	}

	for i, tst := range tests {
		tst.a.Reshape(tst.sh...)
		if e := tst.a.GetErr(); e != tst.err {
			t.Log("Error incorrect in test", i, ", expected", tst.err, "\ngot", e)
			t.Fail()
		}
		if tst.err != nil {
			continue
		}
		for j, v := range tst.a.shape {
			if v != int(tst.sh[j]) {
				t.Log("Reshape incorrect in test", i, ", expected", tst.sh, "got", tst.a.shape)
				t.Fail()
				break
			}
		}
	}
}

func TestJSON(t *testing.T) {
	//t.Parallel()

	tests := []*Array64{
		NewArray64(nil, 0),
		Arange(10),
		RandArray64(0, 2, ([]int{10, 10})...).Div(Arange(10)),
		Arange(10).Reshape(2, 2),
		FullArray64(math.NaN(), 10),
		FullArray64(math.Inf(1), 10),
		FullArray64(math.Inf(-1), 10),
	}
	for i, v := range tests {
		b, err := json.Marshal(v)
		if err != nil {
			t.Log("Marshal Error in test", i, ":", err)
			t.Fail()
			continue
		}
		tmp := new(Array64)
		err = json.Unmarshal(b, tmp)
		if err != nil {
			t.Log("Unmarshal Errorin test", i, ":", err)
			t.Fail()
			continue
		}

		e1, e2 := v.GetErr(), tmp.GetErr()
		if e1 != e2 {
			t.Log("Error mismatch in test", i)
			t.Log("From:", e1)
			t.Log("To:", e2)
			t.Fail()
		}

		if e := tmp.Equals(v); !e.All().At(0) {
			t.Log("Value changedin test", i)
			t.Log(string(b))
			t.Log(v)
			t.Log(tmp)
			t.Fail()
		}
	}

	var v *Array64
	b, err := json.Marshal(v)
	if err != nil {
		t.Log("Marshal Error in nil test:", err)
		t.Fail()
	}
	tmp := new(Array64)
	err = json.Unmarshal(b, tmp)
	if err != nil {
		t.Log("Unmarshal Error in nil test:", err)
		t.Fail()
	}

	e1, e2 := v.GetErr(), tmp.GetErr()
	if e1 != e2 {
		t.Log("Error mismatch in nil test")
		t.Log("From:", e1)
		t.Log("To:", e2)
		t.Fail()
	}

	b, err = json.Marshal(Arange(10))
	v = nil
	e1 = json.Unmarshal(b, v)
	if e1 == nil {
		t.Log("Empty unmarshal didn't return error:")
		t.Log("Res:", v)
		t.Fail()
	}

	v = new(Array64)
	e1 = json.Unmarshal([]byte(`{"junk": "This will not pass."}`), v)
	if e1 != nil || v.err != NilError {
		t.Log("Error unmarshal didn't error correctly:")
		t.Log(v)
		t.Fail()
	}
}
<commit_msg>removed unnessesary int casts from numgo_test.go<commit_after>package numgo

import (
	"encoding/json"
	"fmt"
	"math"
	"strings"
	"testing"
)

func init() {
	debug = true
}

func TestNewArray64(t *testing.T) {
	t.Parallel()
	shp := []int{2, 3, 4}
	a := NewArray64(nil, shp...)
	if len(a.data) != 24 {
		t.Logf("Length %d, expected %d", len(a.data), 24)
		t.FailNow()
	}

	for _, v := range a.data {
		if v != 0 {
			t.Logf("Value %f, expected %d", v, 0)
			t.Fail()
		}
	}
	a = NewArray64(nil)
	if e := a.GetErr(); e != nil {
		t.Log("Unexpected error:", e)
		t.Fail()
	}

	a = NewArray64([]float64{0, 1, 2, 3, 4})
	if e := a.Equals(Arange(5)); !e.All().At(0) {
		t.Log("Slice Assignment Failed", a.GetErr(), e)
		t.Fail()
	}

	a = NewArray64([]float64{0, 1, 2, 3, 4}, 3)
	if e := a.Equals(Arange(3)); !e.All().At(0) {
		t.Log("Slice Assignment Failed", a.GetErr(), e)
		t.Fail()
	}

	a = NewArray64([]float64{0, 1, 2, 3, 4, 5}, 2, -1, 3)
	if e := a.GetErr(); e != NegativeAxis {
		t.Log("Expected NegativeAxis, got:", e)
		t.Fail()
	}

	a = NewArray64(nil, 1, 2, 5, 9)
	if e := a.Equals(newArray64(1, 2, 5, 9)); !e.All().At(0) {
		t.Log("Creation has different results:", e)
		t.Fail()
	}
}
func TestFull(t *testing.T) {
	t.Parallel()
	shp := []int{2, 3, 4}
	a := FullArray64(1, shp...)
	if len(a.data) != 24 {
		t.Logf("Length %d, expected %d\n", len(a.data), 24)
		t.Fail()
	}

	for _, v := range a.data {
		if v != 1 {
			t.Logf("Value %f, expected %d\n", v, 1)
			t.Fail()
			break
		}
	}

	if e := a.Equals(full(1, 2, 3, 4)); !e.All().At(0) {
		t.Log("Full creation has different results:", e)
		t.Fail()
	}
	if e := FullArray64(0, shp...).Equals(full(0, 2, 3, 4)); !e.All().At(0) {
		t.Log("Full creation has different results:", e)
		t.Fail()
	}
}

func TestShapes(t *testing.T) {
	shp := []int{3, 3, 4, 7}
	a := NewArray64(nil, shp...)
	for i, v := range a.shape {
		if shp[i] != v {
			t.Log(a.shape, "!=", shp)
			t.FailNow()
		}
	}
}

func TestRandArray64(t *testing.T) {
	t.Parallel()
	a := RandArray64(0, 2, []int{2, 3, -7, 12}...)
	if e := a.GetErr(); e != NegativeAxis {
		t.Log("Expected NegativeAxis, got:", e)
		t.Fail()
	}
}

func TestArange(t *testing.T) {
	t.Parallel()
	a := Arange(24)
	if len(a.data) != 24 {
		t.Logf("Length %d.  Expected size %d\n", len(a.data), 24)
	}
	if len(a.shape) != 1 {
		t.Logf("Axis %d.  Expected %d\n", len(a.shape), 1)
	}
	for i, v := range a.data {
		if float64(i) != v {
			t.Logf("Value %f.  Expected %d\n", v, i)
		}
	}

	if e := a.Equals(Arange(1, 25).SubtrC(1)); e.All().At(0) {
		t.Log("Arange generating incorrect ranges", e)
		t.Fail()
	}

	a = Arange(24, 0)
	for i := 1; i < len(a.data); i++ {
		if a.data[i]-a.data[i-1] != -1 {
			t.Log("Stepping incorrect for negative range.", a)
			t.Fail()
		}
	}

	if e := a.Equals(Arange(-24).MultC(-1)); !e.All().At(0) {
		t.Log("Negative Arange failed", e)
		t.Fail()
	}

	a = Arange(24, 0, 2)
	if e := a.GetErr(); e != ShapeError {
		t.Log("Expected ShapeError, got", e)
		t.Fail()
	}

	a = Arange(0)
	if a.shape[0] != 1 {
		t.Log("Arange(0) shape error:", a.shape[0])
		t.Fail()
	}

	a = Arange()
	if a.shape[0] != 0 {
		t.Log("Arange() shape error:", a.shape[0])
		t.Fail()
	}
}

func TestIdent(t *testing.T) {
	t.Parallel()
	var tmp *Array64
	for k := 0; k < 5; k++ {
		tmp = Identity(k)
		if len(tmp.shape) != 2 {
			t.Log("Incorrect identity shape.", tmp.shape)
			t.Fail()
		}
		if tmp.shape[0] != k || tmp.shape[1] != k {
			t.Log("Incorrect shape values. I()", k, tmp.shape)
			t.Fail()
		}
		if len(tmp.data) != k*k {
			t.Log("Data array incorrect.", tmp.data)
			t.Fail()
		}
		for i := 0; i < k; i++ {
			for j := 0; j < k; j++ {
				if i != j && tmp.At(i, j) != 0 {
					t.Log("Data Value incorrect at", i, j, len(tmp.data))
					t.Fail()
				}
				if i == j && tmp.At(i, j) != 1 {
					t.Log("Data Value incorrect at", i, j, len(tmp.data))
					t.Fail()
				}
			}
		}
	}

	tmp = Identity(-10)
	if e := tmp.GetErr(); e != NegativeAxis {
		t.Log("Error failed.  Expected NegativeAxis, got", e)
		t.Fail()
	}
}

func TestSubArray(t *testing.T) {
	t.Parallel()
	a := Arange(100).Reshape(2, 5, 10)
	b := Arange(50).Reshape(5, 10)
	c := a.SubArr(0)
	if !c.Equals(b).All().At(0) {
		t.Log("Subarray incorrect. Expected\n", b, "\nReceived\n", c)
		t.Fail()
	}

	b = Arange(50).AddC(50).Reshape(5, 10)
	c = a.SubArr(1)
	if !c.Equals(b).All().At(0) {
		t.Log("Subarray incorrect. Expected\n", b, "\nReceived\n", c)
		t.Fail()
	}
}

func TestString(t *testing.T) {
	t.Parallel()
	tests := []struct {
		a   *Array64
		str string
	}{
		{nil, "<nil>"},
		{newArray64(0), "[]"},
		{&Array64{err: InvIndexError}, "Error: " + InvIndexError.s},
		{Arange(10), fmt.Sprint(Arange(10).data)},
		{Arange(10).Reshape(2, 5), "[[0 1 2 3 4] \n [5 6 7 8 9]]"},
		{Arange(20).Reshape(2, 2, 5), "[[[0 1 2 3 4]  \n  [5 6 7 8 9]] \n\n [[10 11 12 13 14]  \n  [15 16 17 18 19]]]"},
		{&Array64{}, "<nil>"},
	}

	for i, tst := range tests {
		if !strings.EqualFold(tst.a.String(), tst.str) {
			t.Log("String() gave unexpected results in test", i)
			t.Log(tst.a)
			t.Log(tst.str)
			t.Fail()
		}
	}
}

func TestReshape(t *testing.T) {
	t.Parallel()
	tests := []struct {
		a   *Array64
		sh  []int
		err error
	}{
		{Arange(10), []int{2, 5}, nil},
		{Arange(11), []int{2, 5}, ReshapeError},
		{Arange(10), []int{2, -5}, NegativeAxis},
		{&Array64{err: InvIndexError}, []int{0}, InvIndexError},
		{nil, []int{1}, NilError},
	}

	for i, tst := range tests {
		tst.a.Reshape(tst.sh...)
		if e := tst.a.GetErr(); e != tst.err {
			t.Log("Error incorrect in test", i, ", expected", tst.err, "\ngot", e)
			t.Fail()
		}
		if tst.err != nil {
			continue
		}
		for j, v := range tst.a.shape {
			if v != tst.sh[j] {
				t.Log("Reshape incorrect in test", i, ", expected", tst.sh, "got", tst.a.shape)
				t.Fail()
				break
			}
		}
	}
}

func TestJSON(t *testing.T) {
	//t.Parallel()

	tests := []*Array64{
		NewArray64(nil, 0),
		Arange(10),
		RandArray64(0, 2, ([]int{10, 10})...).Div(Arange(10)),
		Arange(10).Reshape(2, 2),
		FullArray64(math.NaN(), 10),
		FullArray64(math.Inf(1), 10),
		FullArray64(math.Inf(-1), 10),
	}
	for i, v := range tests {
		b, err := json.Marshal(v)
		if err != nil {
			t.Log("Marshal Error in test", i, ":", err)
			t.Fail()
			continue
		}
		tmp := new(Array64)
		err = json.Unmarshal(b, tmp)
		if err != nil {
			t.Log("Unmarshal Errorin test", i, ":", err)
			t.Fail()
			continue
		}

		e1, e2 := v.GetErr(), tmp.GetErr()
		if e1 != e2 {
			t.Log("Error mismatch in test", i)
			t.Log("From:", e1)
			t.Log("To:", e2)
			t.Fail()
		}

		if e := tmp.Equals(v); !e.All().At(0) {
			t.Log("Value changedin test", i)
			t.Log(string(b))
			t.Log(v)
			t.Log(tmp)
			t.Fail()
		}
	}

	var v *Array64
	b, err := json.Marshal(v)
	if err != nil {
		t.Log("Marshal Error in nil test:", err)
		t.Fail()
	}
	tmp := new(Array64)
	err = json.Unmarshal(b, tmp)
	if err != nil {
		t.Log("Unmarshal Error in nil test:", err)
		t.Fail()
	}

	e1, e2 := v.GetErr(), tmp.GetErr()
	if e1 != e2 {
		t.Log("Error mismatch in nil test")
		t.Log("From:", e1)
		t.Log("To:", e2)
		t.Fail()
	}

	b, err = json.Marshal(Arange(10))
	v = nil
	e1 = json.Unmarshal(b, v)
	if e1 == nil {
		t.Log("Empty unmarshal didn't return error:")
		t.Log("Res:", v)
		t.Fail()
	}

	v = new(Array64)
	e1 = json.Unmarshal([]byte(`{"junk": "This will not pass."}`), v)
	if e1 != nil || v.err != NilError {
		t.Log("Error unmarshal didn't error correctly:")
		t.Log(v)
		t.Fail()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"flag"
	"log"
	"time"

	"pixur.org/pixur/be/schema"
	sdb "pixur.org/pixur/be/schema/db"
	tab "pixur.org/pixur/be/schema/tables"
	"pixur.org/pixur/be/server/config"
	"pixur.org/pixur/be/tasks"
)

func run() error {
	db, err := sdb.Open(config.Conf.DbName, config.Conf.DbConfig)
	if err != nil {
		return err
	}
	defer db.Close()

	j, err := tab.NewJob(context.Background(), db)
	if err != nil {
		return err
	}
	defer j.Rollback()

	perPicFn := func(p *schema.Pic) error {
		return perPic(p, db, config.Conf.PixPath)
	}

	return j.ScanPics(sdb.Opts{
		Prefix: tab.PicsPrimary{},
		Lock:   sdb.LockNone,
	}, perPicFn)
}

func perPic(p *schema.Pic, db sdb.DB, pixPath string) error {
	now := time.Now()
	// No deletion info
	if p.DeletionStatus == nil {
		return nil
	}
	// Some deletion info, but it isn't on the chopping block.
	if p.DeletionStatus.PendingDeletedTs == nil {
		return nil
	}
	// It was already hard deleted, ignore it
	if p.DeletionStatus.ActualDeletedTs != nil {
		return nil
	}

	pendingTime := schema.FromTs(p.DeletionStatus.PendingDeletedTs)
	// It is pending deletion, just not yet.
	if !now.After(pendingTime) {
		return nil
	}

	log.Println("Preparing to delete", p.GetVarPicID(), pendingTime)
	var task = &tasks.HardDeletePicTask{
		DB:      db,
		PixPath: pixPath,
		PicID:   p.PicId,
	}
	runner := new(tasks.TaskRunner)
	// TODO: use real userid
	if err := runner.Run(tasks.CtxFromUserID(context.TODO(), -12345), task); err != nil {
		return err
	}

	return nil
}

func main() {
	flag.Parse()

	if err := run(); err != nil {
		log.Println(err.(stringer).String())
	}
}

type stringer interface {
	String() string
}
<commit_msg>tools: update deleted file pruner's time calculation<commit_after>package main

import (
	"context"
	"flag"
	"log"
	"time"

	"pixur.org/pixur/be/schema"
	sdb "pixur.org/pixur/be/schema/db"
	tab "pixur.org/pixur/be/schema/tables"
	"pixur.org/pixur/be/server/config"
	"pixur.org/pixur/be/tasks"
)

func run() error {
	db, err := sdb.Open(config.Conf.DbName, config.Conf.DbConfig)
	if err != nil {
		return err
	}
	defer db.Close()

	j, err := tab.NewJob(context.Background(), db)
	if err != nil {
		return err
	}
	defer j.Rollback()

	perPicFn := func(p *schema.Pic) error {
		return perPic(p, db, config.Conf.PixPath)
	}

	return j.ScanPics(sdb.Opts{
		Prefix: tab.PicsPrimary{},
		Lock:   sdb.LockNone,
	}, perPicFn)
}

func perPic(p *schema.Pic, db sdb.DB, pixPath string) error {
	now := time.Now()
	// No deletion info
	if p.DeletionStatus == nil {
		return nil
	}
	// Some deletion info, but it isn't on the chopping block.
	if p.DeletionStatus.PendingDeletedTs == nil {
		return nil
	}
	// It was already hard deleted, ignore it
	if p.DeletionStatus.ActualDeletedTs != nil {
		return nil
	}

	pendingTime := schema.ToTime(p.DeletionStatus.PendingDeletedTs)
	// It is pending deletion, just not yet.
	if !now.After(pendingTime) {
		return nil
	}

	log.Println("Preparing to delete", p.GetVarPicID(), pendingTime)
	var task = &tasks.HardDeletePicTask{
		DB:      db,
		PixPath: pixPath,
		PicID:   p.PicId,
	}
	runner := new(tasks.TaskRunner)
	// TODO: use real userid
	if err := runner.Run(tasks.CtxFromUserID(context.TODO(), -12345), task); err != nil {
		return err
	}

	return nil
}

func main() {
	flag.Parse()

	if err := run(); err != nil {
		log.Println(err.(stringer).String())
	}
}

type stringer interface {
	String() string
}
<|endoftext|>


<commit_before>package cloud

import (
	"context"
	"fmt"
	"strings"

	"github.com/hashicorp/go-tfe"
)

type taskResultSummary struct {
	unreachable     bool
	pending         int
	failed          int
	failedMandatory int
	passed          int
}

type taskStageReadFunc func(b *Cloud, stopCtx context.Context) (*tfe.TaskStage, error)

func summarizeTaskResults(taskResults []*tfe.TaskResult) *taskResultSummary {
	var pendingCount, errCount, errMandatoryCount, passedCount int
	for _, task := range taskResults {
		if task.Status == "unreachable" {
			return &taskResultSummary{
				unreachable: true,
			}
		} else if task.Status == "running" || task.Status == "pending" {
			pendingCount++
		} else if task.Status == "passed" {
			passedCount++
		} else {
			// Everything else is a failure
			errCount++
			if task.WorkspaceTaskEnforcementLevel == "mandatory" {
				errMandatoryCount++
			}
		}
	}

	return &taskResultSummary{
		unreachable:     false,
		pending:         pendingCount,
		failed:          errCount,
		failedMandatory: errMandatoryCount,
		passed:          passedCount,
	}
}

func (b *Cloud) runTasksWithTaskResults(context *IntegrationContext, output IntegrationOutputWriter, fetchTaskStage taskStageReadFunc) error {
	return context.Poll(func(i int) (bool, error) {
		stage, err := fetchTaskStage(b, context.StopContext)

		if err != nil {
			return false, generalError("Failed to retrieve pre-apply task stage", err)
		}

		summary := summarizeTaskResults(stage.TaskResults)

		if summary.unreachable {
			output.Output("Skipping task results.")
			output.End()
			return false, nil
		}

		if summary.pending > 0 {
			pendingMessage := "%d tasks still pending, %d passed, %d failed ... "
			message := fmt.Sprintf(pendingMessage, summary.pending, summary.passed, summary.failed)

			if i%4 == 0 {
				if i > 0 {
					output.OutputElapsed(message, len(pendingMessage)) // Up to 2 digits are allowed by the max message allocation
				}
			}
			return true, nil
		}

		// No more tasks pending/running. Print all the results.

		// Track the first task name that is a mandatory enforcement level breach.
		var firstMandatoryTaskFailed *string = nil

		if i == 0 {
			output.Output(fmt.Sprintf("All tasks completed! %d passed, %d failed", summary.passed, summary.failed))
		} else {
			output.OutputElapsed(fmt.Sprintf("All tasks completed! %d passed, %d failed", summary.passed, summary.failed), 50)
		}

		output.Output("")

		for _, t := range stage.TaskResults {
			capitalizedStatus := string(t.Status)
			capitalizedStatus = strings.ToUpper(capitalizedStatus[:1]) + capitalizedStatus[1:]

			status := "[green]" + capitalizedStatus
			if t.Status != "passed" {
				level := string(t.WorkspaceTaskEnforcementLevel)
				level = strings.ToUpper(level[:1]) + level[1:]
				status = fmt.Sprintf("[red]%s (%s)", capitalizedStatus, level)

				if t.WorkspaceTaskEnforcementLevel == "mandatory" && firstMandatoryTaskFailed == nil {
					firstMandatoryTaskFailed = &t.TaskName
				}
			}

			title := fmt.Sprintf(`%s ⸺   %s`, t.TaskName, status)
			output.SubOutput(title)

			output.SubOutput(fmt.Sprintf("[dim]%s", t.Message))
			output.SubOutput("")
		}

		// If a mandatory enforcement level is breached, return an error.
		var taskErr error = nil
		var overall string = "[green]Passed"
		if firstMandatoryTaskFailed != nil {
			overall = "[red]Failed"
			if summary.failedMandatory > 1 {
				taskErr = fmt.Errorf("the run failed because %d mandatory tasks are required to succeed", summary.failedMandatory)
			} else {
				taskErr = fmt.Errorf("the run failed because the run task, %s, is required to succeed", *firstMandatoryTaskFailed)
			}
		} else if summary.failed > 0 { // we have failures but none of them mandatory
			overall = "[green]Passed with advisory failures"
		}

		output.SubOutput("")
		output.SubOutput("[bold]Overall Result: " + overall)

		output.End()

		return false, taskErr
	})
}

func (b *Cloud) runTasks(ctx *IntegrationContext, output IntegrationOutputWriter, stageID string) error {
	return b.runTasksWithTaskResults(ctx, output, func(b *Cloud, stopCtx context.Context) (*tfe.TaskStage, error) {
		options := tfe.TaskStageReadOptions{
			Include: []tfe.TaskStageIncludeOpt{tfe.TaskStageTaskResults},
		}

		return b.client.TaskStages.Read(ctx.StopContext, stageID, &options)
	})
}
<commit_msg>add url to summary and check for optional values (#30993)<commit_after>package cloud

import (
	"context"
	"fmt"
	"strings"

	"github.com/hashicorp/go-tfe"
)

type taskResultSummary struct {
	unreachable     bool
	pending         int
	failed          int
	failedMandatory int
	passed          int
}

type taskStageReadFunc func(b *Cloud, stopCtx context.Context) (*tfe.TaskStage, error)

func summarizeTaskResults(taskResults []*tfe.TaskResult) *taskResultSummary {
	var pendingCount, errCount, errMandatoryCount, passedCount int
	for _, task := range taskResults {
		if task.Status == "unreachable" {
			return &taskResultSummary{
				unreachable: true,
			}
		} else if task.Status == "running" || task.Status == "pending" {
			pendingCount++
		} else if task.Status == "passed" {
			passedCount++
		} else {
			// Everything else is a failure
			errCount++
			if task.WorkspaceTaskEnforcementLevel == "mandatory" {
				errMandatoryCount++
			}
		}
	}

	return &taskResultSummary{
		unreachable:     false,
		pending:         pendingCount,
		failed:          errCount,
		failedMandatory: errMandatoryCount,
		passed:          passedCount,
	}
}

func (b *Cloud) runTasksWithTaskResults(context *IntegrationContext, output IntegrationOutputWriter, fetchTaskStage taskStageReadFunc) error {
	return context.Poll(func(i int) (bool, error) {
		stage, err := fetchTaskStage(b, context.StopContext)

		if err != nil {
			return false, generalError("Failed to retrieve pre-apply task stage", err)
		}

		summary := summarizeTaskResults(stage.TaskResults)

		if summary.unreachable {
			output.Output("Skipping task results.")
			output.End()
			return false, nil
		}

		if summary.pending > 0 {
			pendingMessage := "%d tasks still pending, %d passed, %d failed ... "
			message := fmt.Sprintf(pendingMessage, summary.pending, summary.passed, summary.failed)

			if i%4 == 0 {
				if i > 0 {
					output.OutputElapsed(message, len(pendingMessage)) // Up to 2 digits are allowed by the max message allocation
				}
			}
			return true, nil
		}

		// No more tasks pending/running. Print all the results.

		// Track the first task name that is a mandatory enforcement level breach.
		var firstMandatoryTaskFailed *string = nil

		if i == 0 {
			output.Output(fmt.Sprintf("All tasks completed! %d passed, %d failed", summary.passed, summary.failed))
		} else {
			output.OutputElapsed(fmt.Sprintf("All tasks completed! %d passed, %d failed", summary.passed, summary.failed), 50)
		}

		output.Output("")

		for _, t := range stage.TaskResults {
			capitalizedStatus := string(t.Status)
			capitalizedStatus = strings.ToUpper(capitalizedStatus[:1]) + capitalizedStatus[1:]

			status := "[green]" + capitalizedStatus
			if t.Status != "passed" {
				level := string(t.WorkspaceTaskEnforcementLevel)
				level = strings.ToUpper(level[:1]) + level[1:]
				status = fmt.Sprintf("[red]%s (%s)", capitalizedStatus, level)

				if t.WorkspaceTaskEnforcementLevel == "mandatory" && firstMandatoryTaskFailed == nil {
					firstMandatoryTaskFailed = &t.TaskName
				}
			}

			title := fmt.Sprintf(`%s ⸺   %s`, t.TaskName, status)
			output.SubOutput(title)

			if len(t.Message) > 0 {
				output.SubOutput(fmt.Sprintf("[dim]%s", t.Message))
			}
			if len(t.URL) > 0 {
				output.SubOutput(fmt.Sprintf("[dim]Details: %s", t.URL))
			}
			output.SubOutput("")
		}

		// If a mandatory enforcement level is breached, return an error.
		var taskErr error = nil
		var overall string = "[green]Passed"
		if firstMandatoryTaskFailed != nil {
			overall = "[red]Failed"
			if summary.failedMandatory > 1 {
				taskErr = fmt.Errorf("the run failed because %d mandatory tasks are required to succeed", summary.failedMandatory)
			} else {
				taskErr = fmt.Errorf("the run failed because the run task, %s, is required to succeed", *firstMandatoryTaskFailed)
			}
		} else if summary.failed > 0 { // we have failures but none of them mandatory
			overall = "[green]Passed with advisory failures"
		}

		output.SubOutput("")
		output.SubOutput("[bold]Overall Result: " + overall)

		output.End()

		return false, taskErr
	})
}

func (b *Cloud) runTasks(ctx *IntegrationContext, output IntegrationOutputWriter, stageID string) error {
	return b.runTasksWithTaskResults(ctx, output, func(b *Cloud, stopCtx context.Context) (*tfe.TaskStage, error) {
		options := tfe.TaskStageReadOptions{
			Include: []tfe.TaskStageIncludeOpt{tfe.TaskStageTaskResults},
		}

		return b.client.TaskStages.Read(ctx.StopContext, stageID, &options)
	})
}
<|endoftext|>


<commit_before>// Copyright 2016 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

// +build go1.3

package lxdclient

import (
	"fmt"

	"github.com/lxc/lxd"
	"github.com/lxc/lxd/shared"

	"github.com/juju/juju/network"
)

type rawNetworkClient interface {
	NetworkCreate(name string, config map[string]string) error
	NetworkGet(name string) (shared.NetworkConfig, error)
}

type networkClient struct {
	raw       rawNetworkClient
	supported bool
}

func (c *networkClient) NetworkCreate(name string, config map[string]string) error {
	if !c.supported {
		return fmt.Errorf("network API not supported on this remote")
	}

	return c.raw.NetworkCreate(name, config)
}

func (c *networkClient) NetworkGet(name string) (shared.NetworkConfig, error) {
	if !c.supported {
		return shared.NetworkConfig{}, fmt.Errorf("network API not supported on this remote")
	}

	return c.raw.NetworkGet(name)
}

type creator interface {
	rawNetworkClient
	ProfileDeviceAdd(profile, devname, devtype string, props []string) (*lxd.Response, error)
	ProfileConfig(profile string) (*shared.ProfileConfig, error)
}

func CreateDefaultBridgeInDefaultProfile(client creator) error {
	/* create the default bridge if it doesn't exist */
	n, err := client.NetworkGet(network.DefaultLXDBridge)
	if err != nil {
		err := client.NetworkCreate(network.DefaultLXDBridge, map[string]string{})
		if err != nil {
			return err
		}

		n, err = client.NetworkGet(network.DefaultLXDBridge)
		if err != nil {
			return err
		}
	}

	nicType := "macvlan"
	if n.Type == "bridge" {
		nicType = "bridged"
	}

	props := []string{fmt.Sprintf("nictype=%s", nicType), fmt.Sprintf("parent=%s", network.DefaultLXDBridge)}

	config, err := client.ProfileConfig("default")
	if err != nil {
		return err
	}

	_, ok := config.Devices["eth0"]
	if ok {
		/* don't configure an eth0 if it already exists */
		return nil
	}

	_, err = client.ProfileDeviceAdd("default", "eth0", "nic", props)
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>add some comments<commit_after>// Copyright 2016 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

// +build go1.3

package lxdclient

import (
	"fmt"

	"github.com/lxc/lxd"
	"github.com/lxc/lxd/shared"

	"github.com/juju/juju/network"
)

type rawNetworkClient interface {
	NetworkCreate(name string, config map[string]string) error
	NetworkGet(name string) (shared.NetworkConfig, error)
}

type networkClient struct {
	raw       rawNetworkClient
	supported bool
}

// create a network
func (c *networkClient) NetworkCreate(name string, config map[string]string) error {
	if !c.supported {
		return fmt.Errorf("network API not supported on this remote")
	}

	return c.raw.NetworkCreate(name, config)
}

// acquire a network's configuration
func (c *networkClient) NetworkGet(name string) (shared.NetworkConfig, error) {
	if !c.supported {
		return shared.NetworkConfig{}, fmt.Errorf("network API not supported on this remote")
	}

	return c.raw.NetworkGet(name)
}

type creator interface {
	rawNetworkClient
	ProfileDeviceAdd(profile, devname, devtype string, props []string) (*lxd.Response, error)
	ProfileConfig(profile string) (*shared.ProfileConfig, error)
}

// Create a default bridge and (if necessary) insert it into the default profile.
func CreateDefaultBridgeInDefaultProfile(client creator) error {
	/* create the default bridge if it doesn't exist */
	n, err := client.NetworkGet(network.DefaultLXDBridge)
	if err != nil {
		err := client.NetworkCreate(network.DefaultLXDBridge, map[string]string{})
		if err != nil {
			return err
		}

		n, err = client.NetworkGet(network.DefaultLXDBridge)
		if err != nil {
			return err
		}
	}

	nicType := "macvlan"
	if n.Type == "bridge" {
		nicType = "bridged"
	}

	props := []string{fmt.Sprintf("nictype=%s", nicType), fmt.Sprintf("parent=%s", network.DefaultLXDBridge)}

	config, err := client.ProfileConfig("default")
	if err != nil {
		return err
	}

	_, ok := config.Devices["eth0"]
	if ok {
		/* don't configure an eth0 if it already exists */
		return nil
	}

	_, err = client.ProfileDeviceAdd("default", "eth0", "nic", props)
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package query

// Token represents the token of the query expression.
type Token struct {
	Token   int
	Literal string
}

// Expr represents each of query expression.
type Expr interface{}

// BoolExpr provides Number expression.
type BoolExpr struct {
	Literal bool
}

// NumberExpr provides Number expression.
type NumberExpr struct {
	Literal float64
}

// StringExpr provides String expression.
type StringExpr struct {
	Literal string
}

// SeriesListExpr provides SeriesList expression.
type SeriesListExpr struct {
	Literal string
}

// GroupSeriesExpr provides grouping series expression.
type GroupSeriesExpr struct {
	Prefix    string
	ValueList []string
	Postfix   string
}

// FuncExpr provides function expression.
type FuncExpr struct {
	Name     string
	SubExprs []Expr
}
<commit_msg>Enable each ast node to do fmt.Sprintf(%s) to richen error message<commit_after>package query

import (
	"fmt"
	"strings"
)

// Token represents the token of the query expression.
type Token struct {
	Token   int
	Literal string
}

// Expr represents each of query expression.
type Expr interface{}

// BoolExpr provides Number expression.
type BoolExpr struct {
	Literal bool
}

func (e BoolExpr) String() string {
	return fmt.Sprintf("%t", e.Literal)
}

// NumberExpr provides Number expression.
type NumberExpr struct {
	Literal float64
}

func (e NumberExpr) String() string {
	return fmt.Sprintf("%g", e.Literal)
}

// StringExpr provides String expression.
type StringExpr struct {
	Literal string
}

func (e StringExpr) String() string {
	return e.Literal
}

// SeriesListExpr provides SeriesList expression.
type SeriesListExpr struct {
	Literal string
}

func (e SeriesListExpr) String() string {
	return e.Literal
}

// GroupSeriesExpr provides grouping series expression.
type GroupSeriesExpr struct {
	Prefix    string
	ValueList []string
	Postfix   string
}

func (e GroupSeriesExpr) String() string {
	vals := strings.Join(e.ValueList, ",")
	return fmt.Sprintf(e.Prefix + "{" + vals + "}" + e.Postfix)
}

// FuncExpr provides function expression.
type FuncExpr struct {
	Name     string
	SubExprs []Expr
}

func (e FuncExpr) String() string {
	return e.Name
}
<|endoftext|>


<commit_before>// +build integration

package tests

import (
	"os"
	"testing"

	"github.com/deis/deis/tests/utils"
)

var (
	appsCreateCmd  = "apps:create {{.AppName}}"
	appsListCmd    = "apps:list"
	appsRunCmd     = "apps:run echo hello"
	appsOpenCmd    = "apps:open --app={{.AppName}}"
	appsLogsCmd    = "apps:logs --app={{.AppName}}"
	appsInfoCmd    = "apps:info --app={{.AppName}}"
	appsDestroyCmd = "apps:destroy --app={{.AppName}} --confirm={{.AppName}}"
)

func TestApps(t *testing.T) {
	params := appsSetup(t)
	appsCreateTest(t, params)
	appsListTest(t, params, false)
	appsLogsTest(t, params)
	appsInfoTest(t, params)
	appsRunTest(t, params)
	appsOpenTest(t, params)
	appsDestroyTest(t, params)
	appsListTest(t, params, true)
}

func appsSetup(t *testing.T) *utils.DeisTestConfig {
	cfg := utils.GetGlobalConfig()
	cfg.AppName = "appssample"
	utils.Execute(t, authLoginCmd, cfg, false, "")
	utils.Execute(t, gitCloneCmd, cfg, false, "")
	return cfg
}

func appsCreateTest(t *testing.T, params *utils.DeisTestConfig) {
	wd, _ := os.Getwd()
	defer os.Chdir(wd)
	if err := utils.Chdir(params.ExampleApp); err != nil {
		t.Fatal(err)
	}
	cmd := appsCreateCmd
	utils.Execute(t, cmd, params, false, "")
	utils.Execute(t, cmd, params, true, "App with this Id already exists")
}

func appsDestroyTest(t *testing.T, params *utils.DeisTestConfig) {
	if err := utils.Chdir(params.ExampleApp); err != nil {
		t.Fatal(err)
	}
	utils.Execute(t, appsDestroyCmd, params, false, "")
	if err := utils.Chdir(".."); err != nil {
		t.Fatal(err)
	}
	if err := utils.Rmdir(params.ExampleApp); err != nil {
		t.Fatal(err)
	}
}

func appsInfoTest(t *testing.T, params *utils.DeisTestConfig) {
	utils.Execute(t, appsInfoCmd, params, false, "")
}

func appsListTest(t *testing.T, params *utils.DeisTestConfig, notflag bool) {
	utils.CheckList(t, appsListCmd, params, params.AppName, notflag)
}

func appsLogsTest(t *testing.T, params *utils.DeisTestConfig) {
	cmd := appsLogsCmd
	// test for application lifecycle logs
	utils.Execute(t, cmd, params, false, "204 NO CONTENT")
	if err := utils.Chdir(params.ExampleApp); err != nil {
		t.Fatal(err)
	}
	utils.Execute(t, gitPushCmd, params, false, "")
	utils.Curl(t, params)
	utils.Execute(t, cmd, params, false, "")
	if err := utils.Chdir(".."); err != nil {
		t.Fatal(err)
	}
}

func appsOpenTest(t *testing.T, params *utils.DeisTestConfig) {
	utils.Curl(t, params)
}

func appsRunTest(t *testing.T, params *utils.DeisTestConfig) {
	cmd := appsRunCmd
	if err := utils.Chdir(params.ExampleApp); err != nil {
		t.Fatal(err)
	}
	utils.Execute(t, cmd, params, false, "hello")
	if err := utils.Chdir(".."); err != nil {
		t.Fatal(err)
	}
	utils.Execute(t, cmd, params, true, "Not found")
}
<commit_msg>test(logspout): add deis log tests<commit_after>// +build integration

package tests

import (
	"os"
	"testing"

	"github.com/deis/deis/tests/utils"
)

var (
	appsCreateCmd  = "apps:create {{.AppName}}"
	appsListCmd    = "apps:list"
	appsRunCmd     = "apps:run echo hello"
	appsOpenCmd    = "apps:open --app={{.AppName}}"
	appsLogsCmd    = "apps:logs --app={{.AppName}}"
	appsInfoCmd    = "apps:info --app={{.AppName}}"
	appsDestroyCmd = "apps:destroy --app={{.AppName}} --confirm={{.AppName}}"
)

func TestApps(t *testing.T) {
	params := appsSetup(t)
	appsCreateTest(t, params)
	appsListTest(t, params, false)
	appsLogsTest(t, params)
	appsInfoTest(t, params)
	appsRunTest(t, params)
	appsOpenTest(t, params)
	appsDestroyTest(t, params)
	appsListTest(t, params, true)
}

func appsSetup(t *testing.T) *utils.DeisTestConfig {
	cfg := utils.GetGlobalConfig()
	cfg.AppName = "appssample"
	utils.Execute(t, authLoginCmd, cfg, false, "")
	utils.Execute(t, gitCloneCmd, cfg, false, "")
	return cfg
}

func appsCreateTest(t *testing.T, params *utils.DeisTestConfig) {
	wd, _ := os.Getwd()
	defer os.Chdir(wd)
	if err := utils.Chdir(params.ExampleApp); err != nil {
		t.Fatal(err)
	}
	cmd := appsCreateCmd
	utils.Execute(t, cmd, params, false, "")
	utils.Execute(t, cmd, params, true, "App with this Id already exists")
}

func appsDestroyTest(t *testing.T, params *utils.DeisTestConfig) {
	if err := utils.Chdir(params.ExampleApp); err != nil {
		t.Fatal(err)
	}
	utils.Execute(t, appsDestroyCmd, params, false, "")
	if err := utils.Chdir(".."); err != nil {
		t.Fatal(err)
	}
	if err := utils.Rmdir(params.ExampleApp); err != nil {
		t.Fatal(err)
	}
}

func appsInfoTest(t *testing.T, params *utils.DeisTestConfig) {
	utils.Execute(t, appsInfoCmd, params, false, "")
}

func appsListTest(t *testing.T, params *utils.DeisTestConfig, notflag bool) {
	utils.CheckList(t, appsListCmd, params, params.AppName, notflag)
}

func appsLogsTest(t *testing.T, params *utils.DeisTestConfig) {
	cmd := appsLogsCmd
	// test for application lifecycle logs
	utils.Execute(t, cmd, params, false, "204 NO CONTENT")
	if err := utils.Chdir(params.ExampleApp); err != nil {
		t.Fatal(err)
	}
	utils.Execute(t, gitPushCmd, params, false, "")
	utils.Curl(t, params)
	utils.Execute(t, cmd, params, false, "created initial release")
	utils.Execute(t, cmd, params, false, "listening on 5000...")
	if err := utils.Chdir(".."); err != nil {
		t.Fatal(err)
	}
}

func appsOpenTest(t *testing.T, params *utils.DeisTestConfig) {
	utils.Curl(t, params)
}

func appsRunTest(t *testing.T, params *utils.DeisTestConfig) {
	cmd := appsRunCmd
	if err := utils.Chdir(params.ExampleApp); err != nil {
		t.Fatal(err)
	}
	utils.Execute(t, cmd, params, false, "hello")
	if err := utils.Chdir(".."); err != nil {
		t.Fatal(err)
	}
	utils.Execute(t, cmd, params, true, "Not found")
}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package util

import "k8s.io/api/core/v1"

// Common allocation units
const (
	KiB int64 = 1024
	MiB int64 = 1024 * KiB
	GiB int64 = 1024 * MiB
	TiB int64 = 1024 * GiB
)

// RoundUpSize calculates how many allocation units are needed to accommodate
// a volume of given size. E.g. when user wants 1500MiB volume, while AWS EBS
// allocates volumes in gibibyte-sized chunks,
// RoundUpSize(1500 * 1024*1024, 1024*1024*1024) returns '2'
// (2 GiB is the smallest allocatable volume that can hold 1500MiB)
func RoundUpSize(volumeSizeBytes int64, allocationUnitBytes int64) int64 {
	return (volumeSizeBytes + allocationUnitBytes - 1) / allocationUnitBytes
}

// AccessModesContains returns whether the requested mode is contained by modes
func AccessModesContains(modes []v1.PersistentVolumeAccessMode, mode v1.PersistentVolumeAccessMode) bool {
	for _, m := range modes {
		if m == mode {
			return true
		}
	}
	return false
}

// AccessModesContainedInAll returns whether all of the requested modes are contained by modes
func AccessModesContainedInAll(indexedModes []v1.PersistentVolumeAccessMode, requestedModes []v1.PersistentVolumeAccessMode) bool {
	for _, mode := range requestedModes {
		if !AccessModesContains(indexedModes, mode) {
			return false
		}
	}
	return true
}
<commit_msg>lib:util: Introduce RoundUpToGiB()<commit_after>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package util

import "k8s.io/api/core/v1"

// Common allocation units
const (
	KiB int64 = 1024
	MiB int64 = 1024 * KiB
	GiB int64 = 1024 * MiB
	TiB int64 = 1024 * GiB
)

// RoundUpSize calculates how many allocation units are needed to accommodate
// a volume of given size. E.g. when user wants 1500MiB volume, while AWS EBS
// allocates volumes in gibibyte-sized chunks,
// RoundUpSize(1500 * 1024*1024, 1024*1024*1024) returns '2'
// (2 GiB is the smallest allocatable volume that can hold 1500MiB)
func RoundUpSize(volumeSizeBytes int64, allocationUnitBytes int64) int64 {
	return (volumeSizeBytes + allocationUnitBytes - 1) / allocationUnitBytes
}

// RoundUpToGiB rounds up given quantity upto chunks of GiB
func RoundUpToGiB(sizeBytes int64) int64 {
	return RoundUpSize(sizeBytes, GiB)
}

// AccessModesContains returns whether the requested mode is contained by modes
func AccessModesContains(modes []v1.PersistentVolumeAccessMode, mode v1.PersistentVolumeAccessMode) bool {
	for _, m := range modes {
		if m == mode {
			return true
		}
	}
	return false
}

// AccessModesContainedInAll returns whether all of the requested modes are contained by modes
func AccessModesContainedInAll(indexedModes []v1.PersistentVolumeAccessMode, requestedModes []v1.PersistentVolumeAccessMode) bool {
	for _, mode := range requestedModes {
		if !AccessModesContains(indexedModes, mode) {
			return false
		}
	}
	return true
}
<|endoftext|>


<commit_before>package testutil

// TestServer is a test helper. It uses a fork/exec model to create
// a test Consul server instance in the background and initialize it
// with some data and/or services. The test server can then be used
// to run a unit test, and offers an easy API to tear itself down
// when the test has completed. The only prerequisite is to have a consul
// binary available on the $PATH.
//
// This package does not use Consul's official API client. This is
// because we use TestServer to test the API client, which would
// otherwise cause an import cycle.

import (
	"context"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"os"
	"os/exec"
	"strconv"
	"strings"

	"github.com/hashicorp/go-cleanhttp"
	"github.com/pkg/errors"
)

// TestPerformanceConfig configures the performance parameters.
type TestPerformanceConfig struct {
	RaftMultiplier uint `json:"raft_multiplier,omitempty"`
}

// TestPortConfig configures the various ports used for services
// provided by the Consul server.
type TestPortConfig struct {
	DNS     int `json:"dns,omitempty"`
	HTTP    int `json:"http,omitempty"`
	SerfLan int `json:"serf_lan,omitempty"`
	SerfWan int `json:"serf_wan,omitempty"`
	Server  int `json:"server,omitempty"`

	// Deprecated
	RPC int `json:"rpc,omitempty"`
}

// TestAddressConfig contains the bind addresses for various
// components of the Consul server.
type TestAddressConfig struct {
	HTTP string `json:"http,omitempty"`
}

// TestServerConfig is the main server configuration struct.
type TestServerConfig struct {
	NodeName          string                 `json:"node_name"`
	NodeMeta          map[string]string      `json:"node_meta,omitempty"`
	Performance       *TestPerformanceConfig `json:"performance,omitempty"`
	Bootstrap         bool                   `json:"bootstrap,omitempty"`
	Server            bool                   `json:"server,omitempty"`
	DataDir           string                 `json:"data_dir,omitempty"`
	Datacenter        string                 `json:"datacenter,omitempty"`
	DisableCheckpoint bool                   `json:"disable_update_check"`
	LogLevel          string                 `json:"log_level,omitempty"`
	Bind              string                 `json:"bind_addr,omitempty"`
	Addresses         *TestAddressConfig     `json:"addresses,omitempty"`
	Ports             *TestPortConfig        `json:"ports,omitempty"`
	RaftProtocol      int                    `json:"raft_protocol,omitempty"`
	ACLMasterToken    string                 `json:"acl_master_token,omitempty"`
	ACLDatacenter     string                 `json:"acl_datacenter,omitempty"`
	ACLDefaultPolicy  string                 `json:"acl_default_policy,omitempty"`
	Encrypt           string                 `json:"encrypt,omitempty"`
	Stdout, Stderr    io.Writer              `json:"-"`
	Args              []string               `json:"-"`
}

// ServerConfigCallback is a function interface which can be
// passed to NewTestServerConfig to modify the server config.
type ServerConfigCallback func(c *TestServerConfig)

// defaultServerConfig returns a new TestServerConfig struct
// with all of the listen ports incremented by one.
func defaultServerConfig() *TestServerConfig {
	return &TestServerConfig{
		NodeName:          fmt.Sprintf("node%d", randomPort()),
		DisableCheckpoint: true,
		Performance: &TestPerformanceConfig{
			RaftMultiplier: 1,
		},
		Bootstrap: true,
		Server:    true,
		LogLevel:  "debug",
		Bind:      "127.0.0.1",
		Addresses: &TestAddressConfig{},
		Ports: &TestPortConfig{
			DNS:     randomPort(),
			HTTP:    randomPort(),
			SerfLan: randomPort(),
			SerfWan: randomPort(),
			Server:  randomPort(),
			RPC:     randomPort(),
		},
	}
}

// randomPort asks the kernel for a random port to use.
func randomPort() int {
	l, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		panic(err)
	}
	defer l.Close()
	return l.Addr().(*net.TCPAddr).Port
}

// TestService is used to serialize a service definition.
type TestService struct {
	ID      string   `json:",omitempty"`
	Name    string   `json:",omitempty"`
	Tags    []string `json:",omitempty"`
	Address string   `json:",omitempty"`
	Port    int      `json:",omitempty"`
}

// TestCheck is used to serialize a check definition.
type TestCheck struct {
	ID        string `json:",omitempty"`
	Name      string `json:",omitempty"`
	ServiceID string `json:",omitempty"`
	TTL       string `json:",omitempty"`
}

// TestKVResponse is what we use to decode KV data.
type TestKVResponse struct {
	Value string
}

// TestServer is the main server wrapper struct.
type TestServer struct {
	cmd    *exec.Cmd
	Config *TestServerConfig

	HTTPAddr string
	LANAddr  string
	WANAddr  string

	HttpClient *http.Client
}

// NewTestServer is an easy helper method to create a new Consul
// test server with the most basic configuration.
func NewTestServer() (*TestServer, error) {
	return NewTestServerConfig(nil)
}

// NewTestServerConfig creates a new TestServer, and makes a call to an optional
// callback function to modify the configuration. If there is an error
// configuring or starting the server, the server will NOT be running when the
// function returns (thus you do not need to stop it).
func NewTestServerConfig(cb ServerConfigCallback) (*TestServer, error) {
	if path, err := exec.LookPath("consul"); err != nil || path == "" {
		return nil, fmt.Errorf("consul not found on $PATH - download and install " +
			"consul or skip this test")
	}

	dataDir, err := ioutil.TempDir("", "consul")
	if err != nil {
		return nil, errors.Wrap(err, "failed creating tempdir")
	}

	configFile, err := ioutil.TempFile(dataDir, "config")
	if err != nil {
		defer os.RemoveAll(dataDir)
		return nil, errors.Wrap(err, "failed creating temp config")
	}

	consulConfig := defaultServerConfig()
	consulConfig.DataDir = dataDir

	if cb != nil {
		cb(consulConfig)
	}

	configContent, err := json.Marshal(consulConfig)
	if err != nil {
		return nil, errors.Wrap(err, "failed marshaling json")
	}

	if _, err := configFile.Write(configContent); err != nil {
		defer configFile.Close()
		defer os.RemoveAll(dataDir)
		return nil, errors.Wrap(err, "failed writing config content")
	}
	configFile.Close()

	stdout := io.Writer(os.Stdout)
	if consulConfig.Stdout != nil {
		stdout = consulConfig.Stdout
	}

	stderr := io.Writer(os.Stderr)
	if consulConfig.Stderr != nil {
		stderr = consulConfig.Stderr
	}

	// Start the server
	args := []string{"agent", "-config-file", configFile.Name()}
	args = append(args, consulConfig.Args...)
	cmd := exec.Command("consul", args...)
	cmd.Stdout = stdout
	cmd.Stderr = stderr
	if err := cmd.Start(); err != nil {
		return nil, errors.Wrap(err, "failed starting command")
	}

	var httpAddr string
	var client *http.Client
	if strings.HasPrefix(consulConfig.Addresses.HTTP, "unix://") {
		httpAddr = consulConfig.Addresses.HTTP
		trans := cleanhttp.DefaultTransport()
		trans.DialContext = func(_ context.Context, _, _ string) (net.Conn, error) {
			return net.Dial("unix", httpAddr[7:])
		}
		client = &http.Client{
			Transport: trans,
		}
	} else {
		httpAddr = fmt.Sprintf("127.0.0.1:%d", consulConfig.Ports.HTTP)
		client = cleanhttp.DefaultClient()
	}

	server := &TestServer{
		Config: consulConfig,
		cmd:    cmd,

		HTTPAddr: httpAddr,
		LANAddr:  fmt.Sprintf("127.0.0.1:%d", consulConfig.Ports.SerfLan),
		WANAddr:  fmt.Sprintf("127.0.0.1:%d", consulConfig.Ports.SerfWan),

		HttpClient: client,
	}

	// Wait for the server to be ready
	var startErr error
	if consulConfig.Bootstrap {
		startErr = server.waitForLeader()
	} else {
		startErr = server.waitForAPI()
	}
	if startErr != nil {
		defer server.Stop()
		return nil, errors.Wrap(err, "failed waiting for server to start")
	}

	return server, nil
}

// Stop stops the test Consul server, and removes the Consul data
// directory once we are done.
func (s *TestServer) Stop() error {
	defer os.RemoveAll(s.Config.DataDir)

	if s.cmd != nil {
		if s.cmd.Process != nil {
			if err := s.cmd.Process.Kill(); err != nil {
				return errors.Wrap(err, "failed to kill consul server")
			}
		}

		// wait for the process to exit to be sure that the data dir can be
		// deleted on all platforms.
		return s.cmd.Wait()
	}

	// There was no process
	return nil
}

// waitForAPI waits for only the agent HTTP endpoint to start
// responding. This is an indication that the agent has started,
// but will likely return before a leader is elected.
func (s *TestServer) waitForAPI() error {
	if err := WaitForResult(func() (bool, error) {
		resp, err := s.HttpClient.Get(s.url("/v1/agent/self"))
		if err != nil {
			return false, errors.Wrap(err, "failed http get")
		}
		defer resp.Body.Close()
		if err := s.requireOK(resp); err != nil {
			return false, errors.Wrap(err, "failed OK response")
		}
		return true, nil
	}); err != nil {
		return errors.Wrap(err, "failed waiting for API")
	}
	return nil
}

// waitForLeader waits for the Consul server's HTTP API to become
// available, and then waits for a known leader and an index of
// 1 or more to be observed to confirm leader election is done.
// It then waits to ensure the anti-entropy sync has completed.
func (s *TestServer) waitForLeader() error {
	var index int64
	if err := WaitForResult(func() (bool, error) {
		// Query the API and check the status code.
		url := s.url(fmt.Sprintf("/v1/catalog/nodes?index=%d&wait=2s", index))
		resp, err := s.HttpClient.Get(url)
		if err != nil {
			return false, errors.Wrap(err, "failed http get")
		}
		defer resp.Body.Close()
		if err := s.requireOK(resp); err != nil {
			return false, errors.Wrap(err, "failed OK response")
		}

		// Ensure we have a leader and a node registration.
		if leader := resp.Header.Get("X-Consul-KnownLeader"); leader != "true" {
			return false, fmt.Errorf("Consul leader status: %#v", leader)
		}
		index, err = strconv.ParseInt(resp.Header.Get("X-Consul-Index"), 10, 64)
		if err != nil {
			return false, errors.Wrap(err, "bad consul index")
		}
		if index == 0 {
			return false, fmt.Errorf("consul index is 0")
		}

		// Watch for the anti-entropy sync to finish.
		var parsed []map[string]interface{}
		dec := json.NewDecoder(resp.Body)
		if err := dec.Decode(&parsed); err != nil {
			return false, err
		}
		if len(parsed) < 1 {
			return false, fmt.Errorf("No nodes")
		}
		taggedAddresses, ok := parsed[0]["TaggedAddresses"].(map[string]interface{})
		if !ok {
			return false, fmt.Errorf("Missing tagged addresses")
		}
		if _, ok := taggedAddresses["lan"]; !ok {
			return false, fmt.Errorf("No lan tagged addresses")
		}
		return true, nil
	}); err != nil {
		return errors.Wrap(err, "failed waiting for leader")
	}
	return nil
}
<commit_msg>Fixes test server startup returning wrong error.<commit_after>package testutil

// TestServer is a test helper. It uses a fork/exec model to create
// a test Consul server instance in the background and initialize it
// with some data and/or services. The test server can then be used
// to run a unit test, and offers an easy API to tear itself down
// when the test has completed. The only prerequisite is to have a consul
// binary available on the $PATH.
//
// This package does not use Consul's official API client. This is
// because we use TestServer to test the API client, which would
// otherwise cause an import cycle.

import (
	"context"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"os"
	"os/exec"
	"strconv"
	"strings"

	"github.com/hashicorp/go-cleanhttp"
	"github.com/pkg/errors"
)

// TestPerformanceConfig configures the performance parameters.
type TestPerformanceConfig struct {
	RaftMultiplier uint `json:"raft_multiplier,omitempty"`
}

// TestPortConfig configures the various ports used for services
// provided by the Consul server.
type TestPortConfig struct {
	DNS     int `json:"dns,omitempty"`
	HTTP    int `json:"http,omitempty"`
	SerfLan int `json:"serf_lan,omitempty"`
	SerfWan int `json:"serf_wan,omitempty"`
	Server  int `json:"server,omitempty"`

	// Deprecated
	RPC int `json:"rpc,omitempty"`
}

// TestAddressConfig contains the bind addresses for various
// components of the Consul server.
type TestAddressConfig struct {
	HTTP string `json:"http,omitempty"`
}

// TestServerConfig is the main server configuration struct.
type TestServerConfig struct {
	NodeName          string                 `json:"node_name"`
	NodeMeta          map[string]string      `json:"node_meta,omitempty"`
	Performance       *TestPerformanceConfig `json:"performance,omitempty"`
	Bootstrap         bool                   `json:"bootstrap,omitempty"`
	Server            bool                   `json:"server,omitempty"`
	DataDir           string                 `json:"data_dir,omitempty"`
	Datacenter        string                 `json:"datacenter,omitempty"`
	DisableCheckpoint bool                   `json:"disable_update_check"`
	LogLevel          string                 `json:"log_level,omitempty"`
	Bind              string                 `json:"bind_addr,omitempty"`
	Addresses         *TestAddressConfig     `json:"addresses,omitempty"`
	Ports             *TestPortConfig        `json:"ports,omitempty"`
	RaftProtocol      int                    `json:"raft_protocol,omitempty"`
	ACLMasterToken    string                 `json:"acl_master_token,omitempty"`
	ACLDatacenter     string                 `json:"acl_datacenter,omitempty"`
	ACLDefaultPolicy  string                 `json:"acl_default_policy,omitempty"`
	Encrypt           string                 `json:"encrypt,omitempty"`
	Stdout, Stderr    io.Writer              `json:"-"`
	Args              []string               `json:"-"`
}

// ServerConfigCallback is a function interface which can be
// passed to NewTestServerConfig to modify the server config.
type ServerConfigCallback func(c *TestServerConfig)

// defaultServerConfig returns a new TestServerConfig struct
// with all of the listen ports incremented by one.
func defaultServerConfig() *TestServerConfig {
	return &TestServerConfig{
		NodeName:          fmt.Sprintf("node%d", randomPort()),
		DisableCheckpoint: true,
		Performance: &TestPerformanceConfig{
			RaftMultiplier: 1,
		},
		Bootstrap: true,
		Server:    true,
		LogLevel:  "debug",
		Bind:      "127.0.0.1",
		Addresses: &TestAddressConfig{},
		Ports: &TestPortConfig{
			DNS:     randomPort(),
			HTTP:    randomPort(),
			SerfLan: randomPort(),
			SerfWan: randomPort(),
			Server:  randomPort(),
			RPC:     randomPort(),
		},
	}
}

// randomPort asks the kernel for a random port to use.
func randomPort() int {
	l, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		panic(err)
	}
	defer l.Close()
	return l.Addr().(*net.TCPAddr).Port
}

// TestService is used to serialize a service definition.
type TestService struct {
	ID      string   `json:",omitempty"`
	Name    string   `json:",omitempty"`
	Tags    []string `json:",omitempty"`
	Address string   `json:",omitempty"`
	Port    int      `json:",omitempty"`
}

// TestCheck is used to serialize a check definition.
type TestCheck struct {
	ID        string `json:",omitempty"`
	Name      string `json:",omitempty"`
	ServiceID string `json:",omitempty"`
	TTL       string `json:",omitempty"`
}

// TestKVResponse is what we use to decode KV data.
type TestKVResponse struct {
	Value string
}

// TestServer is the main server wrapper struct.
type TestServer struct {
	cmd    *exec.Cmd
	Config *TestServerConfig

	HTTPAddr string
	LANAddr  string
	WANAddr  string

	HttpClient *http.Client
}

// NewTestServer is an easy helper method to create a new Consul
// test server with the most basic configuration.
func NewTestServer() (*TestServer, error) {
	return NewTestServerConfig(nil)
}

// NewTestServerConfig creates a new TestServer, and makes a call to an optional
// callback function to modify the configuration. If there is an error
// configuring or starting the server, the server will NOT be running when the
// function returns (thus you do not need to stop it).
func NewTestServerConfig(cb ServerConfigCallback) (*TestServer, error) {
	if path, err := exec.LookPath("consul"); err != nil || path == "" {
		return nil, fmt.Errorf("consul not found on $PATH - download and install " +
			"consul or skip this test")
	}

	dataDir, err := ioutil.TempDir("", "consul")
	if err != nil {
		return nil, errors.Wrap(err, "failed creating tempdir")
	}

	configFile, err := ioutil.TempFile(dataDir, "config")
	if err != nil {
		defer os.RemoveAll(dataDir)
		return nil, errors.Wrap(err, "failed creating temp config")
	}

	consulConfig := defaultServerConfig()
	consulConfig.DataDir = dataDir

	if cb != nil {
		cb(consulConfig)
	}

	configContent, err := json.Marshal(consulConfig)
	if err != nil {
		return nil, errors.Wrap(err, "failed marshaling json")
	}

	if _, err := configFile.Write(configContent); err != nil {
		defer configFile.Close()
		defer os.RemoveAll(dataDir)
		return nil, errors.Wrap(err, "failed writing config content")
	}
	configFile.Close()

	stdout := io.Writer(os.Stdout)
	if consulConfig.Stdout != nil {
		stdout = consulConfig.Stdout
	}

	stderr := io.Writer(os.Stderr)
	if consulConfig.Stderr != nil {
		stderr = consulConfig.Stderr
	}

	// Start the server
	args := []string{"agent", "-config-file", configFile.Name()}
	args = append(args, consulConfig.Args...)
	cmd := exec.Command("consul", args...)
	cmd.Stdout = stdout
	cmd.Stderr = stderr
	if err := cmd.Start(); err != nil {
		return nil, errors.Wrap(err, "failed starting command")
	}

	var httpAddr string
	var client *http.Client
	if strings.HasPrefix(consulConfig.Addresses.HTTP, "unix://") {
		httpAddr = consulConfig.Addresses.HTTP
		trans := cleanhttp.DefaultTransport()
		trans.DialContext = func(_ context.Context, _, _ string) (net.Conn, error) {
			return net.Dial("unix", httpAddr[7:])
		}
		client = &http.Client{
			Transport: trans,
		}
	} else {
		httpAddr = fmt.Sprintf("127.0.0.1:%d", consulConfig.Ports.HTTP)
		client = cleanhttp.DefaultClient()
	}

	server := &TestServer{
		Config: consulConfig,
		cmd:    cmd,

		HTTPAddr: httpAddr,
		LANAddr:  fmt.Sprintf("127.0.0.1:%d", consulConfig.Ports.SerfLan),
		WANAddr:  fmt.Sprintf("127.0.0.1:%d", consulConfig.Ports.SerfWan),

		HttpClient: client,
	}

	// Wait for the server to be ready
	var startErr error
	if consulConfig.Bootstrap {
		startErr = server.waitForLeader()
	} else {
		startErr = server.waitForAPI()
	}
	if startErr != nil {
		defer server.Stop()
		return nil, errors.Wrap(startErr, "failed waiting for server to start")
	}

	return server, nil
}

// Stop stops the test Consul server, and removes the Consul data
// directory once we are done.
func (s *TestServer) Stop() error {
	defer os.RemoveAll(s.Config.DataDir)

	if s.cmd != nil {
		if s.cmd.Process != nil {
			if err := s.cmd.Process.Kill(); err != nil {
				return errors.Wrap(err, "failed to kill consul server")
			}
		}

		// wait for the process to exit to be sure that the data dir can be
		// deleted on all platforms.
		return s.cmd.Wait()
	}

	// There was no process
	return nil
}

// waitForAPI waits for only the agent HTTP endpoint to start
// responding. This is an indication that the agent has started,
// but will likely return before a leader is elected.
func (s *TestServer) waitForAPI() error {
	if err := WaitForResult(func() (bool, error) {
		resp, err := s.HttpClient.Get(s.url("/v1/agent/self"))
		if err != nil {
			return false, errors.Wrap(err, "failed http get")
		}
		defer resp.Body.Close()
		if err := s.requireOK(resp); err != nil {
			return false, errors.Wrap(err, "failed OK response")
		}
		return true, nil
	}); err != nil {
		return errors.Wrap(err, "failed waiting for API")
	}
	return nil
}

// waitForLeader waits for the Consul server's HTTP API to become
// available, and then waits for a known leader and an index of
// 1 or more to be observed to confirm leader election is done.
// It then waits to ensure the anti-entropy sync has completed.
func (s *TestServer) waitForLeader() error {
	var index int64
	if err := WaitForResult(func() (bool, error) {
		// Query the API and check the status code.
		url := s.url(fmt.Sprintf("/v1/catalog/nodes?index=%d&wait=2s", index))
		resp, err := s.HttpClient.Get(url)
		if err != nil {
			return false, errors.Wrap(err, "failed http get")
		}
		defer resp.Body.Close()
		if err := s.requireOK(resp); err != nil {
			return false, errors.Wrap(err, "failed OK response")
		}

		// Ensure we have a leader and a node registration.
		if leader := resp.Header.Get("X-Consul-KnownLeader"); leader != "true" {
			return false, fmt.Errorf("Consul leader status: %#v", leader)
		}
		index, err = strconv.ParseInt(resp.Header.Get("X-Consul-Index"), 10, 64)
		if err != nil {
			return false, errors.Wrap(err, "bad consul index")
		}
		if index == 0 {
			return false, fmt.Errorf("consul index is 0")
		}

		// Watch for the anti-entropy sync to finish.
		var parsed []map[string]interface{}
		dec := json.NewDecoder(resp.Body)
		if err := dec.Decode(&parsed); err != nil {
			return false, err
		}
		if len(parsed) < 1 {
			return false, fmt.Errorf("No nodes")
		}
		taggedAddresses, ok := parsed[0]["TaggedAddresses"].(map[string]interface{})
		if !ok {
			return false, fmt.Errorf("Missing tagged addresses")
		}
		if _, ok := taggedAddresses["lan"]; !ok {
			return false, fmt.Errorf("No lan tagged addresses")
		}
		return true, nil
	}); err != nil {
		return errors.Wrap(err, "failed waiting for leader")
	}
	return nil
}
<|endoftext|>


<commit_before>package spartan

import (
	"errors"

	"github.com/nsf/termbox-go"
	"github.com/sparkymat/spartan/direction"
	"github.com/sparkymat/spartan/gravity"
	"github.com/sparkymat/spartan/size"
)

type LinearLayout struct {
	parent     ViewGroup
	views      []View
	x          uint32
	y          uint32
	width      size.Size
	height     size.Size
	direction  direction.Type
	isBordered bool
	title      string
}

func (layout *LinearLayout) SetTitle(title string) {
	layout.title = title
}

func (layout LinearLayout) GetTitle() string {
	return layout.title
}

func (layout *LinearLayout) EnableBorder() {
	layout.isBordered = true
}

func (layout *LinearLayout) DisableBorder() {
	layout.isBordered = false
}

func (layout *LinearLayout) SetWidth(width size.Size) {
	layout.width = width
}

func (layout *LinearLayout) SetHeight(height size.Size) {
	layout.height = height
}

func (layout *LinearLayout) SetLeftMargin(x uint32) {
	layout.x = x
}

func (layout *LinearLayout) SetTopMargin(y uint32) {
	layout.y = y
}

func (layout *LinearLayout) AddView(view View) {
	layout.views = append(layout.views, view)
}

func (layout LinearLayout) GetChildCount() uint32 {
	return uint32(len(layout.views))
}

func (layout LinearLayout) GetChildAt(index uint32) (View, error) {
	if index >= layout.GetChildCount() {
		return nil, errors.New("index out of bounds")
	}

	return layout.views[index], nil
}

func (layout LinearLayout) GetAbsoluteX() uint32 {
	if layout.GetParent() == nil {
		return layout.x
	} else {
		return layout.GetParent().GetAbsoluteX() + layout.x
	}
}

func (layout LinearLayout) GetAbsoluteY() uint32 {
	if layout.GetParent() == nil {
		return layout.y
	} else {
		return layout.GetParent().GetAbsoluteY() + layout.y
	}
}

func (layout LinearLayout) GetAbsoluteWidth() uint32 {
	if layout.width == size.MatchParent {
		if layout.parent == nil {
			width, _ := termbox.Size()
			return uint32(width)
		} else {
			return layout.parent.GetAbsoluteWidth()
		}
	} else {
		return uint32(layout.width)
	}
}

func (layout LinearLayout) GetAbsoluteHeight() uint32 {
	if layout.height == size.MatchParent {
		if layout.parent == nil {
			_, height := termbox.Size()
			return uint32(height)
		} else {
			return layout.parent.GetAbsoluteHeight()
		}
	} else {
		return uint32(layout.height)
	}
}

func (layout LinearLayout) draw() {
	containerLeft := layout.GetAbsoluteX()
	containerTop := layout.GetAbsoluteY()
	containerWidth := layout.GetAbsoluteWidth()
	containerHeight := layout.GetAbsoluteHeight()
	containerRight := containerLeft + containerWidth
	containerBottom := containerTop + containerHeight

	if layout.isBordered {
		containerLeft += 1
		containerRight -= 1
		containerWidth -= 2

		containerTop += 1
		containerBottom -= 1
		containerHeight -= 2
	}

	if layout.direction == direction.Vertical {
		heights := make([]uint32, len(layout.views), len(layout.views))

		stretchiesCount := uint32(0)
		totalFixedHeight := uint32(0)

		for i, view := range layout.views {
			if view.GetHeight() == size.MatchParent {
				stretchiesCount += 1
			} else {
				heights[i] = uint32(view.GetHeight())
				totalFixedHeight += uint32(view.GetHeight())
			}
		}

		if stretchiesCount > 0 {

			for i, view := range layout.views {
				if view.GetHeight() == size.MatchParent {
					heights[i] = (containerHeight - totalFixedHeight) / stretchiesCount
				}
			}
		}

		currentTop := containerTop

		for i, view := range layout.views {
			height := heights[i]
			width := view.GetAbsoluteWidth()

			currentLeft := uint32(0)

			if view.GetLayoutGravity() == gravity.Left {
				currentLeft = containerLeft + view.GetLeftMargin()
			} else if view.GetLayoutGravity() == gravity.Right {
				currentLeft = containerLeft + (containerWidth - width - view.GetRightMargin())
			} else if view.GetLayoutGravity() == gravity.Middle {
				currentLeft = containerLeft + (containerWidth-width)/2
			}

			currentRight := currentLeft + width - 1
			currentBottom := currentTop + height - 1

			// Clip to container dimensions
			if currentLeft < containerLeft {
				currentLeft = containerLeft
			}

			if currentRight > containerRight {
				currentRight = containerRight
			}

			if currentTop < containerTop {
				currentTop = containerTop
			}

			if currentBottom > containerBottom {
				currentBottom = containerBottom
			}

			view.draw(currentLeft, currentTop, currentRight, currentBottom)

			currentTop += height
		}
	} else if layout.direction == direction.Horizontal {
		widths := make([]uint32, len(layout.views), len(layout.views))

		stretchiesCount := uint32(0)
		totalFixedWidth := uint32(0)

		for i, view := range layout.views {
			if view.GetWidth() == size.MatchParent {
				stretchiesCount += 1
			} else {
				widths[i] = uint32(view.GetWidth())
				totalFixedWidth += uint32(view.GetWidth())
			}
		}

		if stretchiesCount > 0 {

			for i, view := range layout.views {
				if view.GetWidth() == size.MatchParent {
					widths[i] = (containerWidth - totalFixedWidth) / stretchiesCount
				}
			}
		}

		currentLeft := containerLeft

		for i, view := range layout.views {
			width := widths[i]
			height := view.GetAbsoluteHeight()

			currentTop := uint32(0)

			if view.GetLayoutGravity() == gravity.Top {
				currentTop = containerTop + view.GetTopMargin()
			} else if view.GetLayoutGravity() == gravity.Bottom {
				currentTop = containerTop + (containerHeight - height - view.GetBottomMargin())
			} else if view.GetLayoutGravity() == gravity.Center {
				currentTop = containerTop + (containerHeight-height)/2
			}

			currentRight := currentLeft + width - 1
			currentBottom := currentTop + height - 1

			// Clip to container dimensions
			if currentLeft < containerLeft {
				currentLeft = containerLeft
			}

			if currentRight > containerRight {
				currentRight = containerRight
			}

			if currentTop < containerTop {
				currentTop = containerTop
			}

			if currentBottom > containerBottom {
				currentBottom = containerBottom
			}

			view.draw(currentLeft, currentTop, currentLeft+width, currentTop+height)
			currentLeft += width
		}
	}
}

func (layout LinearLayout) GetParent() ViewGroup {
	return layout.parent
}

func (layout *LinearLayout) SetParent(parent ViewGroup) {
	layout.parent = parent
}

func (layout *LinearLayout) SetDirection(direction direction.Type) {
	layout.direction = direction
}

func (layout LinearLayout) GetDirection() direction.Type {
	return layout.direction
}
<commit_msg>Added border and title<commit_after>package spartan

import (
	"errors"

	"github.com/nsf/termbox-go"
	"github.com/sparkymat/spartan/direction"
	"github.com/sparkymat/spartan/gravity"
	"github.com/sparkymat/spartan/size"
)

type LinearLayout struct {
	parent     ViewGroup
	views      []View
	x          uint32
	y          uint32
	width      size.Size
	height     size.Size
	direction  direction.Type
	isBordered bool
	title      string
}

func (layout *LinearLayout) SetTitle(title string) {
	layout.title = title
}

func (layout LinearLayout) GetTitle() string {
	return layout.title
}

func (layout *LinearLayout) EnableBorder() {
	layout.isBordered = true
}

func (layout *LinearLayout) DisableBorder() {
	layout.isBordered = false
}

func (layout *LinearLayout) SetWidth(width size.Size) {
	layout.width = width
}

func (layout *LinearLayout) SetHeight(height size.Size) {
	layout.height = height
}

func (layout *LinearLayout) SetLeftMargin(x uint32) {
	layout.x = x
}

func (layout *LinearLayout) SetTopMargin(y uint32) {
	layout.y = y
}

func (layout *LinearLayout) AddView(view View) {
	layout.views = append(layout.views, view)
}

func (layout LinearLayout) GetChildCount() uint32 {
	return uint32(len(layout.views))
}

func (layout LinearLayout) GetChildAt(index uint32) (View, error) {
	if index >= layout.GetChildCount() {
		return nil, errors.New("index out of bounds")
	}

	return layout.views[index], nil
}

func (layout LinearLayout) GetAbsoluteX() uint32 {
	if layout.GetParent() == nil {
		return layout.x
	} else {
		return layout.GetParent().GetAbsoluteX() + layout.x
	}
}

func (layout LinearLayout) GetAbsoluteY() uint32 {
	if layout.GetParent() == nil {
		return layout.y
	} else {
		return layout.GetParent().GetAbsoluteY() + layout.y
	}
}

func (layout LinearLayout) GetAbsoluteWidth() uint32 {
	if layout.width == size.MatchParent {
		if layout.parent == nil {
			width, _ := termbox.Size()
			return uint32(width)
		} else {
			return layout.parent.GetAbsoluteWidth()
		}
	} else {
		return uint32(layout.width)
	}
}

func (layout LinearLayout) GetAbsoluteHeight() uint32 {
	if layout.height == size.MatchParent {
		if layout.parent == nil {
			_, height := termbox.Size()
			return uint32(height)
		} else {
			return layout.parent.GetAbsoluteHeight()
		}
	} else {
		return uint32(layout.height)
	}
}

func (layout LinearLayout) draw() {
	containerLeft := layout.GetAbsoluteX()
	containerTop := layout.GetAbsoluteY()
	containerWidth := layout.GetAbsoluteWidth()
	containerHeight := layout.GetAbsoluteHeight()
	containerRight := containerLeft + containerWidth - 1
	containerBottom := containerTop + containerHeight - 1

	if layout.isBordered {
		containerLeft += 1
		containerRight -= 1
		containerWidth -= 2

		containerTop += 1
		containerBottom -= 1
		containerHeight -= 2

		layout.drawBorder()
		layout.drawTitle()
	}

	if layout.direction == direction.Vertical {
		heights := make([]uint32, len(layout.views), len(layout.views))

		stretchiesCount := uint32(0)
		totalFixedHeight := uint32(0)

		for i, view := range layout.views {
			if view.GetHeight() == size.MatchParent {
				stretchiesCount += 1
			} else {
				heights[i] = uint32(view.GetHeight())
				totalFixedHeight += uint32(view.GetHeight())
			}
		}

		if stretchiesCount > 0 {

			for i, view := range layout.views {
				if view.GetHeight() == size.MatchParent {
					heights[i] = (containerHeight - totalFixedHeight) / stretchiesCount
				}
			}
		}

		currentTop := containerTop

		for i, view := range layout.views {
			height := heights[i]
			width := view.GetAbsoluteWidth()

			currentLeft := uint32(0)

			if view.GetLayoutGravity() == gravity.Left {
				currentLeft = containerLeft + view.GetLeftMargin()
			} else if view.GetLayoutGravity() == gravity.Right {
				currentLeft = containerLeft + (containerWidth - width - view.GetRightMargin())
			} else if view.GetLayoutGravity() == gravity.Middle {
				currentLeft = containerLeft + (containerWidth-width)/2
			}

			currentRight := currentLeft + width - 1
			currentBottom := currentTop + height - 1

			// Clip to container dimensions
			if currentLeft < containerLeft {
				currentLeft = containerLeft
			}

			if currentRight > containerRight {
				currentRight = containerRight
			}

			if currentTop < containerTop {
				currentTop = containerTop
			}

			if currentBottom > containerBottom {
				currentBottom = containerBottom
			}

			view.draw(currentLeft, currentTop, currentRight, currentBottom)

			currentTop += height
		}
	} else if layout.direction == direction.Horizontal {
		widths := make([]uint32, len(layout.views), len(layout.views))

		stretchiesCount := uint32(0)
		totalFixedWidth := uint32(0)

		for i, view := range layout.views {
			if view.GetWidth() == size.MatchParent {
				stretchiesCount += 1
			} else {
				widths[i] = uint32(view.GetWidth())
				totalFixedWidth += uint32(view.GetWidth())
			}
		}

		if stretchiesCount > 0 {

			for i, view := range layout.views {
				if view.GetWidth() == size.MatchParent {
					widths[i] = (containerWidth - totalFixedWidth) / stretchiesCount
				}
			}
		}

		currentLeft := containerLeft

		for i, view := range layout.views {
			width := widths[i]
			height := view.GetAbsoluteHeight()

			currentTop := uint32(0)

			if view.GetLayoutGravity() == gravity.Top {
				currentTop = containerTop + view.GetTopMargin()
			} else if view.GetLayoutGravity() == gravity.Bottom {
				currentTop = containerTop + (containerHeight - height - view.GetBottomMargin())
			} else if view.GetLayoutGravity() == gravity.Center {
				currentTop = containerTop + (containerHeight-height)/2
			}

			currentRight := currentLeft + width - 1
			currentBottom := currentTop + height - 1

			// Clip to container dimensions
			if currentLeft < containerLeft {
				currentLeft = containerLeft
			}

			if currentRight > containerRight {
				currentRight = containerRight
			}

			if currentTop < containerTop {
				currentTop = containerTop
			}

			if currentBottom > containerBottom {
				currentBottom = containerBottom
			}

			view.draw(currentLeft, currentTop, currentLeft+width, currentTop+height)
			currentLeft += width
		}
	}
}

func (layout LinearLayout) drawBorder() {
	containerLeft := int(layout.GetAbsoluteX())
	containerTop := int(layout.GetAbsoluteY())
	containerWidth := int(layout.GetAbsoluteWidth())
	containerHeight := int(layout.GetAbsoluteHeight())
	containerRight := containerLeft + containerWidth - 1
	containerBottom := containerTop + containerHeight - 1

	leftTop := '\u250c'
	rightTop := '\u2510'
	leftBottom := '\u2514'
	rightBottom := '\u2518'

	horizontal := '\u2500'
	vertical := '\u2502'

	termbox.SetCell(containerLeft, containerTop, leftTop, termbox.ColorDefault, termbox.ColorDefault)
	termbox.SetCell(containerRight, containerTop, rightTop, termbox.ColorDefault, termbox.ColorDefault)
	termbox.SetCell(containerLeft, containerBottom, leftBottom, termbox.ColorDefault, termbox.ColorDefault)
	termbox.SetCell(containerRight, containerBottom, rightBottom, termbox.ColorDefault, termbox.ColorDefault)

	// Horizontal
	for i := containerLeft + 1; i <= containerRight-1; i++ {
		termbox.SetCell(i, containerTop, horizontal, termbox.ColorDefault, termbox.ColorDefault)
		termbox.SetCell(i, containerBottom, horizontal, termbox.ColorDefault, termbox.ColorDefault)
	}

	// Vertical
	for j := containerTop + 1; j <= containerBottom-1; j++ {
		termbox.SetCell(containerLeft, j, vertical, termbox.ColorDefault, termbox.ColorDefault)
		termbox.SetCell(containerRight, j, vertical, termbox.ColorDefault, termbox.ColorDefault)
	}
}

func (layout LinearLayout) drawTitle() {
	containerLeft := int(layout.GetAbsoluteX())
	containerTop := int(layout.GetAbsoluteY())
	containerWidth := int(layout.GetAbsoluteWidth())
	length := len(layout.title)
	titleLeft := containerLeft + (containerWidth-length)/2
	titleRight := titleLeft + length - 1
	for i := titleLeft; i <= titleRight; i++ {
		termbox.SetCell(i, containerTop, rune(layout.title[i-titleLeft]), termbox.AttrBold|termbox.ColorDefault, termbox.ColorDefault)
	}
}

func (layout LinearLayout) GetParent() ViewGroup {
	return layout.parent
}

func (layout *LinearLayout) SetParent(parent ViewGroup) {
	layout.parent = parent
}

func (layout *LinearLayout) SetDirection(direction direction.Type) {
	layout.direction = direction
}

func (layout LinearLayout) GetDirection() direction.Type {
	return layout.direction
}
<|endoftext|>


<commit_before>package todolist

import (
	"fmt"
	"os"
	"regexp"
	"strconv"
	"strings"
	"time"
)

type Parser struct {
	input string
}

func (p *Parser) ParseNewTodo(input string) *Todo {
	if input == "" {
		return nil
	}

	todo := NewTodo()
	todo.Subject = p.Subject(input)
	todo.Projects = p.Projects(input)
	todo.Contexts = p.Contexts(input)
	if p.hasDue(input) {
		todo.Due = p.Due(input, time.Now())
	}
	return todo
}

func (p Parser) parseId() int {
	r := regexp.MustCompile(`(\d+)`)
	matches := r.FindStringSubmatch(p.input)
	if len(matches) == 0 {
		fmt.Println("Could match id")
		return -1
	}
	id, err := strconv.Atoi(matches[1])
	if err != nil {
		fmt.Println("Invalid id.")
		return -1
	}
	return id
}

func (p Parser) parseSubject() string {
	r := regexp.MustCompile(`(\d+) (.*)`)
	matches := r.FindStringSubmatch(p.input)
	if len(matches) < 3 {
		return ""
	}
	return matches[2]
}

func (p Parser) Parse() (int, string) {

	id := p.parseId()
	subject := p.parseSubject()

	return id, subject
}

func (p *Parser) Subject(input string) string {
	if strings.Contains(input, " due") {
		index := strings.LastIndex(input, " due")
		return input[0:index]
	} else {
		return input
	}
}

func (p *Parser) ExpandProject(input string) string {
	r := regexp.MustCompile(`(\+[\p{L}\d_-]+):`)
	matches := r.FindStringSubmatch(input)
	if len(matches) < 2 {
		return ""
	}

	return matches[1]
}

func (p *Parser) Projects(input string) []string {
	r := regexp.MustCompile(`\+[\p{L}\d_-]+`)
	return p.matchWords(input, r)
}

func (p *Parser) Contexts(input string) []string {
	r, err := regexp.Compile(`\@[\p{L}\d_]+`)
	if err != nil {
		fmt.Println("regex error", err)
	}
	return p.matchWords(input, r)
}

func (p *Parser) hasDue(input string) bool {
	r1, _ := regexp.Compile(`due \w+$`)
	r2, _ := regexp.Compile(`due \w+ \d+$`)
	return (r1.MatchString(input) || r2.MatchString(input))
}

func (p *Parser) Due(input string, day time.Time) string {
	r, _ := regexp.Compile(`due .*$`)

	res := r.FindString(input)
	res = res[4:]
	switch res {
	case "none":
		return ""
	case "today", "tod":
		return bod(time.Now()).Format("2006-01-02")
	case "tomorrow", "tom":
		return bod(time.Now()).AddDate(0, 0, 1).Format("2006-01-02")
	case "monday", "mon":
		return p.monday(day)
	case "tuesday", "tue":
		return p.tuesday(day)
	case "wednesday", "wed":
		return p.wednesday(day)
	case "thursday", "thu":
		return p.thursday(day)
	case "friday", "fri":
		return p.friday(day)
	case "saturday", "sat":
		return p.saturday(day)
	case "sunday", "sun":
		return p.sunday(day)
	case "last week":
		n := bod(time.Now())
		return getNearestMonday(n).AddDate(0, 0, -7).Format("2006-01-02")
	case "next week":
		n := bod(time.Now())
		return getNearestMonday(n).AddDate(0, 0, 7).Format("2006-01-02")
	}
	return p.parseArbitraryDate(res, time.Now())
}

func (p *Parser) parseArbitraryDate(_date string, pivot time.Time) string {
	d1 := p.parseArbitraryDateWithYear(_date, pivot.Year())

	var diff1 time.Duration
	if d1.After(time.Now()) {
		diff1 = d1.Sub(pivot)
	} else {
		diff1 = pivot.Sub(d1)
	}
	d2 := p.parseArbitraryDateWithYear(_date, pivot.Year()+1)
	if d2.Sub(pivot) > diff1 {
		return d1.Format("2006-01-02")
	} else {
		return d2.Format("2006-01-02")
	}
}

func (p *Parser) parseArbitraryDateWithYear(_date string, year int) time.Time {
	res := strings.Join([]string{_date, strconv.Itoa(year)}, " ")
	if date, err := time.Parse("Jan 2 2006", res); err == nil {
		return date
	}

	if date, err := time.Parse("2 Jan 2006", res); err == nil {
		return date
	}
	fmt.Printf("Could not parse the date you gave me: %s\n", _date)
	fmt.Println("I'm expecting a date like \"Dec 22\" or \"22 Dec\".")
	fmt.Println("See http://todolist.site/#adding for more info.")
	os.Exit(-1)
	return time.Now()
}

func (p *Parser) monday(day time.Time) string {
	mon := getNearestMonday(day)
	return p.thisOrNextWeek(mon, day)
}

func (p *Parser) tuesday(day time.Time) string {
	tue := getNearestMonday(day).AddDate(0, 0, 1)
	return p.thisOrNextWeek(tue, day)
}

func (p *Parser) wednesday(day time.Time) string {
	tue := getNearestMonday(day).AddDate(0, 0, 2)
	return p.thisOrNextWeek(tue, day)
}

func (p *Parser) thursday(day time.Time) string {
	tue := getNearestMonday(day).AddDate(0, 0, 3)
	return p.thisOrNextWeek(tue, day)
}

func (p *Parser) friday(day time.Time) string {
	tue := getNearestMonday(day).AddDate(0, 0, 4)
	return p.thisOrNextWeek(tue, day)
}

func (p *Parser) saturday(day time.Time) string {
	tue := getNearestMonday(day).AddDate(0, 0, 5)
	return p.thisOrNextWeek(tue, day)
}

func (p *Parser) sunday(day time.Time) string {
	tue := getNearestMonday(day).AddDate(0, 0, 6)
	return p.thisOrNextWeek(tue, day)
}

func (p *Parser) thisOrNextWeek(day time.Time, pivotDay time.Time) string {
	if day.Before(pivotDay) {
		return day.AddDate(0, 0, 7).Format("2006-01-02")
	} else {
		return day.Format("2006-01-02")
	}
}

func (p *Parser) matchWords(input string, r *regexp.Regexp) []string {
	results := r.FindAllString(input, -1)
	ret := []string{}

	for _, val := range results {
		ret = append(ret, val[1:])
	}
	return ret
}
<commit_msg>use MustCompile when regexp is static<commit_after>package todolist

import (
	"fmt"
	"os"
	"regexp"
	"strconv"
	"strings"
	"time"
)

type Parser struct {
	input string
}

func (p *Parser) ParseNewTodo(input string) *Todo {
	if input == "" {
		return nil
	}

	todo := NewTodo()
	todo.Subject = p.Subject(input)
	todo.Projects = p.Projects(input)
	todo.Contexts = p.Contexts(input)
	if p.hasDue(input) {
		todo.Due = p.Due(input, time.Now())
	}
	return todo
}

func (p Parser) parseId() int {
	r := regexp.MustCompile(`(\d+)`)
	matches := r.FindStringSubmatch(p.input)
	if len(matches) == 0 {
		fmt.Println("Could match id")
		return -1
	}
	id, err := strconv.Atoi(matches[1])
	if err != nil {
		fmt.Println("Invalid id.")
		return -1
	}
	return id
}

func (p Parser) parseSubject() string {
	r := regexp.MustCompile(`(\d+) (.*)`)
	matches := r.FindStringSubmatch(p.input)
	if len(matches) < 3 {
		return ""
	}
	return matches[2]
}

func (p Parser) Parse() (int, string) {

	id := p.parseId()
	subject := p.parseSubject()

	return id, subject
}

func (p *Parser) Subject(input string) string {
	if strings.Contains(input, " due") {
		index := strings.LastIndex(input, " due")
		return input[0:index]
	} else {
		return input
	}
}

func (p *Parser) ExpandProject(input string) string {
	r := regexp.MustCompile(`(\+[\p{L}\d_-]+):`)
	matches := r.FindStringSubmatch(input)
	if len(matches) < 2 {
		return ""
	}

	return matches[1]
}

func (p *Parser) Projects(input string) []string {
	r := regexp.MustCompile(`\+[\p{L}\d_-]+`)
	return p.matchWords(input, r)
}

func (p *Parser) Contexts(input string) []string {
	r := regexp.MustCompile(`\@[\p{L}\d_]+`)
	return p.matchWords(input, r)
}

func (p *Parser) hasDue(input string) bool {
	r1 := regexp.MustCompile(`due \w+$`)
	r2 := regexp.MustCompile(`due \w+ \d+$`)
	return (r1.MatchString(input) || r2.MatchString(input))
}

func (p *Parser) Due(input string, day time.Time) string {
	r := regexp.MustCompile(`due .*$`)

	res := r.FindString(input)
	res = res[4:]
	switch res {
	case "none":
		return ""
	case "today", "tod":
		return bod(time.Now()).Format("2006-01-02")
	case "tomorrow", "tom":
		return bod(time.Now()).AddDate(0, 0, 1).Format("2006-01-02")
	case "monday", "mon":
		return p.monday(day)
	case "tuesday", "tue":
		return p.tuesday(day)
	case "wednesday", "wed":
		return p.wednesday(day)
	case "thursday", "thu":
		return p.thursday(day)
	case "friday", "fri":
		return p.friday(day)
	case "saturday", "sat":
		return p.saturday(day)
	case "sunday", "sun":
		return p.sunday(day)
	case "last week":
		n := bod(time.Now())
		return getNearestMonday(n).AddDate(0, 0, -7).Format("2006-01-02")
	case "next week":
		n := bod(time.Now())
		return getNearestMonday(n).AddDate(0, 0, 7).Format("2006-01-02")
	}
	return p.parseArbitraryDate(res, time.Now())
}

func (p *Parser) parseArbitraryDate(_date string, pivot time.Time) string {
	d1 := p.parseArbitraryDateWithYear(_date, pivot.Year())

	var diff1 time.Duration
	if d1.After(time.Now()) {
		diff1 = d1.Sub(pivot)
	} else {
		diff1 = pivot.Sub(d1)
	}
	d2 := p.parseArbitraryDateWithYear(_date, pivot.Year()+1)
	if d2.Sub(pivot) > diff1 {
		return d1.Format("2006-01-02")
	} else {
		return d2.Format("2006-01-02")
	}
}

func (p *Parser) parseArbitraryDateWithYear(_date string, year int) time.Time {
	res := strings.Join([]string{_date, strconv.Itoa(year)}, " ")
	if date, err := time.Parse("Jan 2 2006", res); err == nil {
		return date
	}

	if date, err := time.Parse("2 Jan 2006", res); err == nil {
		return date
	}
	fmt.Printf("Could not parse the date you gave me: %s\n", _date)
	fmt.Println("I'm expecting a date like \"Dec 22\" or \"22 Dec\".")
	fmt.Println("See http://todolist.site/#adding for more info.")
	os.Exit(-1)
	return time.Now()
}

func (p *Parser) monday(day time.Time) string {
	mon := getNearestMonday(day)
	return p.thisOrNextWeek(mon, day)
}

func (p *Parser) tuesday(day time.Time) string {
	tue := getNearestMonday(day).AddDate(0, 0, 1)
	return p.thisOrNextWeek(tue, day)
}

func (p *Parser) wednesday(day time.Time) string {
	tue := getNearestMonday(day).AddDate(0, 0, 2)
	return p.thisOrNextWeek(tue, day)
}

func (p *Parser) thursday(day time.Time) string {
	tue := getNearestMonday(day).AddDate(0, 0, 3)
	return p.thisOrNextWeek(tue, day)
}

func (p *Parser) friday(day time.Time) string {
	tue := getNearestMonday(day).AddDate(0, 0, 4)
	return p.thisOrNextWeek(tue, day)
}

func (p *Parser) saturday(day time.Time) string {
	tue := getNearestMonday(day).AddDate(0, 0, 5)
	return p.thisOrNextWeek(tue, day)
}

func (p *Parser) sunday(day time.Time) string {
	tue := getNearestMonday(day).AddDate(0, 0, 6)
	return p.thisOrNextWeek(tue, day)
}

func (p *Parser) thisOrNextWeek(day time.Time, pivotDay time.Time) string {
	if day.Before(pivotDay) {
		return day.AddDate(0, 0, 7).Format("2006-01-02")
	} else {
		return day.Format("2006-01-02")
	}
}

func (p *Parser) matchWords(input string, r *regexp.Regexp) []string {
	results := r.FindAllString(input, -1)
	ret := []string{}

	for _, val := range results {
		ret = append(ret, val[1:])
	}
	return ret
}
<|endoftext|>