<commit_before>// Copyright (c) 2015 Andy Leap, Google
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

// Run the shared test suite from https://github.com/microformats/tests

package microformats_test

import (
	"bytes"
	"encoding/json"
	"io/ioutil"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"reflect"
	"strings"
	"testing"

	"willnorris.com/go/microformats"
)

// skip the tests which we don't pass yet
var skipTests = []string{
	"microformats-v2/h-as-note/note",
	"microformats-v2/h-card/impliedname",
	"microformats-v2/h-card/impliedphoto",
	"microformats-v2/h-card/impliedurl",
	"microformats-v2/h-card/nested",
	"microformats-v2/h-entry/summarycontent",
	"microformats-v2/h-entry/urlincontent",
	"microformats-v2/h-event/concatenate",
	"microformats-v2/h-event/dates",
	"microformats-v2/h-event/time",
	"microformats-v2/h-feed/implied-title",
	"microformats-v2/h-feed/simple",
	"microformats-v2/h-news/all",
	"microformats-v2/h-news/minimum",
	"microformats-v2/h-recipe/all",
	"microformats-v2/h-resume/affiliation",
	"microformats-v2/h-review/vcard",
	"microformats-v2/rel/duplicate-rels",
	"microformats-v2/rel/varying-text-duplicate-rels",
}

func TestSuite(t *testing.T) {
	for _, version := range []string{"microformats-v2"} {
		t.Run(version, func(t *testing.T) {
			base := filepath.Join("testdata", "tests", version)
			tests, err := listTests(base)
			if err != nil {
				t.Fatalf("error reading test cases: %v", err)
			}

			for _, test := range tests {
				t.Run(test, func(t *testing.T) {
					for _, skip := range skipTests {
						if path.Join(version, test) == skip {
							t.Skip()
						}
					}

					runTest(t, filepath.Join(base, test))
				})
			}
		})
	}
}

// listTests recursively lists microformat tests in the specified root
// directory.  A test is identified as pair of matching .html and .json files
// in the same directory.  Returns a slice of named tests, where the test name
// is the path to the html and json files relative to root, excluding any file
// extension.
func listTests(root string) ([]string, error) {
	tests := []string{}
	err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if info.IsDir() {
			return nil
		}
		if ext := filepath.Ext(path); ext == ".json" {
			test := strings.TrimSuffix(path, ext)
			// ensure .html file exists with the same name
			if _, err := os.Stat(test + ".html"); os.IsNotExist(err) {
				return nil
			}
			test, err = filepath.Rel(root, test)
			if err != nil {
				return err
			}
			tests = append(tests, test)
		}
		return nil
	})
	return tests, err
}

func runTest(t *testing.T, test string) {
	input, err := ioutil.ReadFile(test + ".html")
	if err != nil {
		t.Fatalf("error reading file %q: %v", test+".html", err)
	}

	URL, _ := url.Parse("http://example.com/")
	data := microformats.Parse(bytes.NewReader(input), URL)

	expectedJSON, err := ioutil.ReadFile(test + ".json")
	if err != nil {
		t.Fatalf("error reading file %q: %v", test+".json", err)
	}
	want := make(map[string]interface{})
	err = json.Unmarshal(expectedJSON, &want)
	if err != nil {
		t.Fatalf("error unmarshaling json in file %q: %v", test+".json", err)
	}

	outputJSON, _ := json.Marshal(data)
	got := make(map[string]interface{})
	err = json.Unmarshal(outputJSON, &got)
	if err != nil {
		t.Fatalf("error unmarshaling json: %v", err)
	}

	if !reflect.DeepEqual(got, want) {
		t.Fatalf("Parse returned %v\n\nwant: %v\n\n", got, want)
	}
}
<commit_msg>run testsuite tests in parallel<commit_after>// Copyright (c) 2015 Andy Leap, Google
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

// Run the shared test suite from https://github.com/microformats/tests

package microformats_test

import (
	"bytes"
	"encoding/json"
	"io/ioutil"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"reflect"
	"strings"
	"testing"

	"willnorris.com/go/microformats"
)

// skip the tests which we don't pass yet
var skipTests = []string{
	"microformats-v2/h-as-note/note",
	"microformats-v2/h-card/impliedname",
	"microformats-v2/h-card/impliedphoto",
	"microformats-v2/h-card/impliedurl",
	"microformats-v2/h-card/nested",
	"microformats-v2/h-entry/summarycontent",
	"microformats-v2/h-entry/urlincontent",
	"microformats-v2/h-event/concatenate",
	"microformats-v2/h-event/dates",
	"microformats-v2/h-event/time",
	"microformats-v2/h-feed/implied-title",
	"microformats-v2/h-feed/simple",
	"microformats-v2/h-news/all",
	"microformats-v2/h-news/minimum",
	"microformats-v2/h-recipe/all",
	"microformats-v2/h-resume/affiliation",
	"microformats-v2/h-review/vcard",
	"microformats-v2/rel/duplicate-rels",
	"microformats-v2/rel/varying-text-duplicate-rels",
}

func TestSuite(t *testing.T) {
	for _, version := range []string{"microformats-v2"} {
		t.Run(version, func(t *testing.T) {
			t.Parallel()
			base := filepath.Join("testdata", "tests", version)
			tests, err := listTests(base)
			if err != nil {
				t.Fatalf("error reading test cases: %v", err)
			}

			for _, test := range tests {
				t.Run(test, func(t *testing.T) {
					t.Parallel()
					for _, skip := range skipTests {
						if path.Join(version, test) == skip {
							t.Skip()
						}
					}

					runTest(t, filepath.Join(base, test))
				})
			}
		})
	}
}

// listTests recursively lists microformat tests in the specified root
// directory.  A test is identified as pair of matching .html and .json files
// in the same directory.  Returns a slice of named tests, where the test name
// is the path to the html and json files relative to root, excluding any file
// extension.
func listTests(root string) ([]string, error) {
	tests := []string{}
	err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if info.IsDir() {
			return nil
		}
		if ext := filepath.Ext(path); ext == ".json" {
			test := strings.TrimSuffix(path, ext)
			// ensure .html file exists with the same name
			if _, err := os.Stat(test + ".html"); os.IsNotExist(err) {
				return nil
			}
			test, err = filepath.Rel(root, test)
			if err != nil {
				return err
			}
			tests = append(tests, test)
		}
		return nil
	})
	return tests, err
}

func runTest(t *testing.T, test string) {
	input, err := ioutil.ReadFile(test + ".html")
	if err != nil {
		t.Fatalf("error reading file %q: %v", test+".html", err)
	}

	URL, _ := url.Parse("http://example.com/")
	data := microformats.Parse(bytes.NewReader(input), URL)

	expectedJSON, err := ioutil.ReadFile(test + ".json")
	if err != nil {
		t.Fatalf("error reading file %q: %v", test+".json", err)
	}
	want := make(map[string]interface{})
	err = json.Unmarshal(expectedJSON, &want)
	if err != nil {
		t.Fatalf("error unmarshaling json in file %q: %v", test+".json", err)
	}

	outputJSON, _ := json.Marshal(data)
	got := make(map[string]interface{})
	err = json.Unmarshal(outputJSON, &got)
	if err != nil {
		t.Fatalf("error unmarshaling json: %v", err)
	}

	if !reflect.DeepEqual(got, want) {
		t.Fatalf("Parse returned %v\n\nwant: %v\n\n", got, want)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"net/http"
	"os"

	"github.com/dynport/dgtk/browser"
	"github.com/dynport/gocli"
)

const (
	railControllerUrl = "http://2nd.railnet.train/railnet/php_logic/T_railcontroller.php?include_id=1&lang=de_DE"
	connectUrl        = "https://hotspot.t-mobile.net/wlan/start.do"
	disconnectUrl     = "https://hotspot.t-mobile.net/wlan/stop.do"
	checkHost         = "www.heise.de"
	envLogin          = "TMOBILE_LOGIN"
	envPwd            = "TMOBILE_PWD"
)

var logger = log.New(os.Stderr, "", 0)

func online() (bool, error) {
	rsp, e := http.Head("http://" + checkHost)
	if e != nil {
		return false, e
	}
	return rsp.Request.URL.Host == checkHost, nil
}

func newBrowser() (*browser.Browser, error) {
	b, e := browser.New()
	if e != nil {
		return nil, e
	}
	b.Logger = logger
	return b, nil

}

func getEnv(key string) (string, error) {
	if v := os.Getenv(key); v != "" {
		return v, nil
	} else {
		return "", fmt.Errorf("key %q not found in env", key)
	}
}

func red(s string) string {
	return gocli.Red(s)
}

func green(s string) string {
	return gocli.Green(s)
}

func yellow(s string) string {
	return gocli.Yellow(s)
}
<commit_msg>disable browser logging<commit_after>package main

import (
	"fmt"
	"log"
	"net/http"
	"os"

	"github.com/dynport/dgtk/browser"
	"github.com/dynport/gocli"
)

const (
	railControllerUrl = "http://2nd.railnet.train/railnet/php_logic/T_railcontroller.php?include_id=1&lang=de_DE"
	connectUrl        = "https://hotspot.t-mobile.net/wlan/start.do"
	disconnectUrl     = "https://hotspot.t-mobile.net/wlan/stop.do"
	checkHost         = "www.heise.de"
	envLogin          = "TMOBILE_LOGIN"
	envPwd            = "TMOBILE_PWD"
)

var logger = log.New(os.Stderr, "", 0)

func online() (bool, error) {
	rsp, e := http.Head("http://" + checkHost)
	if e != nil {
		return false, e
	}
	return rsp.Request.URL.Host == checkHost, nil
}

func newBrowser() (*browser.Browser, error) {
	b, e := browser.New()
	if e != nil {
		return nil, e
	}
	return b, nil

}

func getEnv(key string) (string, error) {
	if v := os.Getenv(key); v != "" {
		return v, nil
	} else {
		return "", fmt.Errorf("key %q not found in env", key)
	}
}

func red(s string) string {
	return gocli.Red(s)
}

func green(s string) string {
	return gocli.Green(s)
}

func yellow(s string) string {
	return gocli.Yellow(s)
}
<|endoftext|>


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

package gonum

import (
	"gonum.org/v1/gonum/blas"
	"gonum.org/v1/gonum/blas/blas64"
)

// Dgebrd reduces a general m×n matrix A to upper or lower bidiagonal form B by
// an orthogonal transformation:
//  Q^T * A * P = B.
// The diagonal elements of B are stored in d and the off-diagonal elements are stored
// in e. These are additionally stored along the diagonal of A and the off-diagonal
// of A. If m >= n B is an upper-bidiagonal matrix, and if m < n B is a
// lower-bidiagonal matrix.
//
// The remaining elements of A store the data needed to construct Q and P.
// The matrices Q and P are products of elementary reflectors
//  if m >= n, Q = H_0 * H_1 * ... * H_{n-1},
//             P = G_0 * G_1 * ... * G_{n-2},
//  if m < n,  Q = H_0 * H_1 * ... * H_{m-2},
//             P = G_0 * G_1 * ... * G_{m-1},
// where
//  H_i = I - tauQ[i] * v_i * v_i^T,
//  G_i = I - tauP[i] * u_i * u_i^T.
//
// As an example, on exit the entries of A when m = 6, and n = 5
//  [ d   e  u1  u1  u1]
//  [v1   d   e  u2  u2]
//  [v1  v2   d   e  u3]
//  [v1  v2  v3   d   e]
//  [v1  v2  v3  v4   d]
//  [v1  v2  v3  v4  v5]
// and when m = 5, n = 6
//  [ d  u1  u1  u1  u1  u1]
//  [ e   d  u2  u2  u2  u2]
//  [v1   e   d  u3  u3  u3]
//  [v1  v2   e   d  u4  u4]
//  [v1  v2  v3   e   d  u5]
//
// d, tauQ, and tauP must all have length at least min(m,n), and e must have
// length min(m,n) - 1, unless lwork is -1 when there is no check except for
// work which must have a length of at least one.
//
// work is temporary storage, and lwork specifies the usable memory length.
// At minimum, lwork >= max(1,m,n) or be -1 and this function will panic otherwise.
// Dgebrd is blocked decomposition, but the block size is limited
// by the temporary space available. If lwork == -1, instead of performing Dgebrd,
// the optimal work length will be stored into work[0].
//
// Dgebrd is an internal routine. It is exported for testing purposes.
func (impl Implementation) Dgebrd(m, n int, a []float64, lda int, d, e, tauQ, tauP, work []float64, lwork int) {
	checkMatrix(m, n, a, lda)
	// Calculate optimal work.
	nb := impl.Ilaenv(1, "DGEBRD", " ", m, n, -1, -1)
	var lworkOpt int
	if lwork == -1 {
		if len(work) < 1 {
			panic(badWork)
		}
		lworkOpt = ((m + n) * nb)
		work[0] = float64(max(1, lworkOpt))
		return
	}
	minmn := min(m, n)
	if len(d) < minmn {
		panic(badD)
	}
	if len(e) < minmn-1 {
		panic(badE)
	}
	if len(tauQ) < minmn {
		panic(badTauQ)
	}
	if len(tauP) < minmn {
		panic(badTauP)
	}
	ws := max(m, n)
	if lwork < max(1, ws) {
		panic(badWork)
	}
	if len(work) < lwork {
		panic(badWork)
	}
	var nx int
	if nb > 1 && nb < minmn {
		nx = max(nb, impl.Ilaenv(3, "DGEBRD", " ", m, n, -1, -1))
		if nx < minmn {
			ws = (m + n) * nb
			if lwork < ws {
				nbmin := impl.Ilaenv(2, "DGEBRD", " ", m, n, -1, -1)
				if lwork >= (m+n)*nbmin {
					nb = lwork / (m + n)
				} else {
					nb = minmn
					nx = minmn
				}
			}
		}
	} else {
		nx = minmn
	}
	bi := blas64.Implementation()
	ldworkx := nb
	ldworky := nb
	var i int
	// Netlib lapack has minmn - nx, but this makes the last nx rows (which by
	// default is large) be unblocked. As written here, the blocking is more
	// consistent.
	for i = 0; i < minmn-nb; i += nb {
		// Reduce rows and columns i:i+nb to bidiagonal form and return
		// the matrices X and Y which are needed to update the unreduced
		// part of the matrix.
		// X is stored in the first m rows of work, y in the next rows.
		x := work[:m*ldworkx]
		y := work[m*ldworkx:]
		impl.Dlabrd(m-i, n-i, nb, a[i*lda+i:], lda,
			d[i:], e[i:], tauQ[i:], tauP[i:],
			x, ldworkx, y, ldworky)

		// Update the trailing submatrix A[i+nb:m,i+nb:n], using an update
		// of the form  A := A - V*Y**T - X*U**T
		bi.Dgemm(blas.NoTrans, blas.Trans, m-i-nb, n-i-nb, nb,
			-1, a[(i+nb)*lda+i:], lda, y[nb*ldworky:], ldworky,
			1, a[(i+nb)*lda+i+nb:], lda)

		bi.Dgemm(blas.NoTrans, blas.NoTrans, m-i-nb, n-i-nb, nb,
			-1, x[nb*ldworkx:], ldworkx, a[i*lda+i+nb:], lda,
			1, a[(i+nb)*lda+i+nb:], lda)

		// Copy diagonal and off-diagonal elements of B back into A.
		if m >= n {
			for j := i; j < i+nb; j++ {
				a[j*lda+j] = d[j]
				a[j*lda+j+1] = e[j]
			}
		} else {
			for j := i; j < i+nb; j++ {
				a[j*lda+j] = d[j]
				a[(j+1)*lda+j] = e[j]
			}
		}
	}
	// Use unblocked code to reduce the remainder of the matrix.
	impl.Dgebd2(m-i, n-i, a[i*lda+i:], lda, d[i:], e[i:], tauQ[i:], tauP[i:], work)
	work[0] = float64(lworkOpt)
}
<commit_msg>lapack/gonum: use blocking crossover point in Dgebrd<commit_after>// Copyright ©2015 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gonum

import (
	"gonum.org/v1/gonum/blas"
	"gonum.org/v1/gonum/blas/blas64"
)

// Dgebrd reduces a general m×n matrix A to upper or lower bidiagonal form B by
// an orthogonal transformation:
//  Q^T * A * P = B.
// The diagonal elements of B are stored in d and the off-diagonal elements are stored
// in e. These are additionally stored along the diagonal of A and the off-diagonal
// of A. If m >= n B is an upper-bidiagonal matrix, and if m < n B is a
// lower-bidiagonal matrix.
//
// The remaining elements of A store the data needed to construct Q and P.
// The matrices Q and P are products of elementary reflectors
//  if m >= n, Q = H_0 * H_1 * ... * H_{n-1},
//             P = G_0 * G_1 * ... * G_{n-2},
//  if m < n,  Q = H_0 * H_1 * ... * H_{m-2},
//             P = G_0 * G_1 * ... * G_{m-1},
// where
//  H_i = I - tauQ[i] * v_i * v_i^T,
//  G_i = I - tauP[i] * u_i * u_i^T.
//
// As an example, on exit the entries of A when m = 6, and n = 5
//  [ d   e  u1  u1  u1]
//  [v1   d   e  u2  u2]
//  [v1  v2   d   e  u3]
//  [v1  v2  v3   d   e]
//  [v1  v2  v3  v4   d]
//  [v1  v2  v3  v4  v5]
// and when m = 5, n = 6
//  [ d  u1  u1  u1  u1  u1]
//  [ e   d  u2  u2  u2  u2]
//  [v1   e   d  u3  u3  u3]
//  [v1  v2   e   d  u4  u4]
//  [v1  v2  v3   e   d  u5]
//
// d, tauQ, and tauP must all have length at least min(m,n), and e must have
// length min(m,n) - 1, unless lwork is -1 when there is no check except for
// work which must have a length of at least one.
//
// work is temporary storage, and lwork specifies the usable memory length.
// At minimum, lwork >= max(1,m,n) or be -1 and this function will panic otherwise.
// Dgebrd is blocked decomposition, but the block size is limited
// by the temporary space available. If lwork == -1, instead of performing Dgebrd,
// the optimal work length will be stored into work[0].
//
// Dgebrd is an internal routine. It is exported for testing purposes.
func (impl Implementation) Dgebrd(m, n int, a []float64, lda int, d, e, tauQ, tauP, work []float64, lwork int) {
	switch {
	case m < 0:
		panic(mLT0)
	case n < 0:
		panic(nLT0)
	case lda < max(1, n):
		panic(badLdA)
	case lwork < max(1, max(m, n)) && lwork != -1:
		panic(badWork)
	case len(work) < max(1, lwork):
		panic(shortWork)
	}

	// Quick return if possible.
	minmn := min(m, n)
	if minmn == 0 {
		work[0] = 1
		return
	}

	nb := impl.Ilaenv(1, "DGEBRD", " ", m, n, -1, -1)
	lwkopt := (m + n) * nb
	if lwork == -1 {
		work[0] = float64(lwkopt)
		return
	}

	switch {
	case len(a) < (m-1)*lda+n:
		panic("lapack: insufficient length of a")
	case len(d) < minmn:
		panic(badD)
	case len(e) < minmn-1:
		panic(badE)
	case len(tauQ) < minmn:
		panic(badTauQ)
	case len(tauP) < minmn:
		panic(badTauP)
	}

	nx := minmn
	ws := max(m, n)
	if 1 < nb && nb < minmn {
		// At least one blocked operation can be done.
		// Get the crossover point nx.
		nx = max(nb, impl.Ilaenv(3, "DGEBRD", " ", m, n, -1, -1))
		// Determine when to switch from blocked to unblocked code.
		if nx < minmn {
			// At least one blocked operation will be done.
			ws = (m + n) * nb
			if lwork < ws {
				// Not enough work space for the optimal nb,
				// consider using a smaller block size.
				nbmin := impl.Ilaenv(2, "DGEBRD", " ", m, n, -1, -1)
				if lwork >= (m+n)*nbmin {
					// Enough work space for minimum block size.
					nb = lwork / (m + n)
				} else {
					nb = minmn
					nx = minmn
				}
			}
		}
	}
	bi := blas64.Implementation()
	ldworkx := nb
	ldworky := nb
	var i int
	for i = 0; i < minmn-nx; i += nb {
		// Reduce rows and columns i:i+nb to bidiagonal form and return
		// the matrices X and Y which are needed to update the unreduced
		// part of the matrix.
		// X is stored in the first m rows of work, y in the next rows.
		x := work[:m*ldworkx]
		y := work[m*ldworkx:]
		impl.Dlabrd(m-i, n-i, nb, a[i*lda+i:], lda,
			d[i:], e[i:], tauQ[i:], tauP[i:],
			x, ldworkx, y, ldworky)

		// Update the trailing submatrix A[i+nb:m,i+nb:n], using an update
		// of the form  A := A - V*Y**T - X*U**T
		bi.Dgemm(blas.NoTrans, blas.Trans, m-i-nb, n-i-nb, nb,
			-1, a[(i+nb)*lda+i:], lda, y[nb*ldworky:], ldworky,
			1, a[(i+nb)*lda+i+nb:], lda)

		bi.Dgemm(blas.NoTrans, blas.NoTrans, m-i-nb, n-i-nb, nb,
			-1, x[nb*ldworkx:], ldworkx, a[i*lda+i+nb:], lda,
			1, a[(i+nb)*lda+i+nb:], lda)

		// Copy diagonal and off-diagonal elements of B back into A.
		if m >= n {
			for j := i; j < i+nb; j++ {
				a[j*lda+j] = d[j]
				a[j*lda+j+1] = e[j]
			}
		} else {
			for j := i; j < i+nb; j++ {
				a[j*lda+j] = d[j]
				a[(j+1)*lda+j] = e[j]
			}
		}
	}
	// Use unblocked code to reduce the remainder of the matrix.
	impl.Dgebd2(m-i, n-i, a[i*lda+i:], lda, d[i:], e[i:], tauQ[i:], tauP[i:], work)
	work[0] = float64(ws)
}
<|endoftext|>


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

package gonum

// Ilaenv returns algorithm tuning parameters for the algorithm given by the
// input string. ispec specifies the parameter to return:
//  1: The optimal block size for a blocked algorithm.
//  2: The minimum block size for a blocked algorithm.
//  3: The block size of unprocessed data at which a blocked algorithm should
//     crossover to an unblocked version.
//  4: The number of shifts.
//  5: The minimum column dimension for blocking to be used.
//  6: The crossover point for SVD (to use QR factorization or not).
//  7: The number of processors.
//  8: The crossover point for multi-shift in QR and QZ methods for non-symmetric eigenvalue problems.
//  9: Maximum size of the subproblems in divide-and-conquer algorithms.
//  10: ieee NaN arithmetic can be trusted not to trap.
//  11: infinity arithmetic can be trusted not to trap.
//  12...16: parameters for Dhseqr and related functions. See Iparmq for more
//           information.
//
// Ilaenv is an internal routine. It is exported for testing purposes.
func (impl Implementation) Ilaenv(ispec int, name string, opts string, n1, n2, n3, n4 int) int {
	// TODO(btracey): Replace this with a constant lookup? A list of constants?
	sname := name[0] == 'S' || name[0] == 'D'
	cname := name[0] == 'C' || name[0] == 'Z'
	if !sname && !cname {
		panic(badName)
	}
	c2 := name[1:3]
	c3 := name[3:6]
	c4 := c3[1:3]

	switch ispec {
	default:
		panic(badIspec)
	case 1:
		switch c2 {
		default:
			panic(badName)
		case "GE":
			switch c3 {
			default:
				panic(badName)
			case "TRF":
				if sname {
					return 64
				}
				return 64
			case "QRF", "RQF", "LQF", "QLF":
				if sname {
					return 32
				}
				return 32
			case "HRD":
				if sname {
					return 32
				}
				return 32
			case "BRD":
				if sname {
					return 32
				}
				return 32
			case "TRI":
				if sname {
					return 64
				}
				return 64
			}
		case "PO":
			switch c3 {
			default:
				panic(badName)
			case "TRF":
				if sname {
					return 64
				}
				return 64
			}
		case "SY":
			switch c3 {
			default:
				panic(badName)
			case "TRF":
				if sname {
					return 64
				}
				return 64
			case "TRD":
				return 32
			case "GST":
				return 64
			}
		case "HE":
			switch c3 {
			default:
				panic(badName)
			case "TRF":
				return 64
			case "TRD":
				return 32
			case "GST":
				return 64
			}
		case "OR":
			switch c3[0] {
			default:
				panic(badName)
			case 'G':
				switch c3[1:] {
				default:
					panic(badName)
				case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR":
					return 32
				}
			case 'M':
				switch c3[1:] {
				default:
					panic(badName)
				case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR":
					return 32
				}
			}
		case "UN":
			switch c3[0] {
			default:
				panic(badName)
			case 'G':
				switch c3[1:] {
				default:
					panic(badName)
				case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR":
					return 32
				}
			case 'M':
				switch c3[1:] {
				default:
					panic(badName)
				case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR":
					return 32
				}
			}
		case "GB":
			switch c3 {
			default:
				panic(badName)
			case "TRF":
				if sname {
					if n4 <= 64 {
						return 1
					}
					return 32
				}
				if n4 <= 64 {
					return 1
				}
				return 32
			}
		case "PB":
			switch c3 {
			default:
				panic(badName)
			case "TRF":
				if sname {
					if n4 <= 64 {
						return 1
					}
					return 32
				}
				if n4 <= 64 {
					return 1
				}
				return 32
			}
		case "TR":
			switch c3 {
			default:
				panic(badName)
			case "TRI":
				if sname {
					return 64
				}
				return 64
			case "EVC":
				if sname {
					return 64
				}
				return 64
			}
		case "LA":
			switch c3 {
			default:
				panic(badName)
			case "UUM":
				if sname {
					return 64
				}
				return 64
			}
		case "ST":
			if sname && c3 == "EBZ" {
				return 1
			}
			panic(badName)
		}
	case 2:
		switch c2 {
		default:
			panic(badName)
		case "GE":
			switch c3 {
			default:
				panic(badName)
			case "QRF", "RQF", "LQF", "QLF":
				if sname {
					return 2
				}
				return 2
			case "HRD":
				if sname {
					return 2
				}
				return 2
			case "BRD":
				if sname {
					return 2
				}
				return 2
			case "TRI":
				if sname {
					return 2
				}
				return 2
			}
		case "SY":
			switch c3 {
			default:
				panic(badName)
			case "TRF":
				if sname {
					return 8
				}
				return 8
			case "TRD":
				if sname {
					return 2
				}
				panic(badName)
			}
		case "HE":
			if c3 == "TRD" {
				return 2
			}
			panic(badName)
		case "OR":
			if !sname {
				panic(badName)
			}
			switch c3[0] {
			default:
				panic(badName)
			case 'G':
				switch c4 {
				default:
					panic(badName)
				case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR":
					return 2
				}
			case 'M':
				switch c4 {
				default:
					panic(badName)
				case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR":
					return 2
				}
			}
		case "UN":
			switch c3[0] {
			default:
				panic(badName)
			case 'G':
				switch c4 {
				default:
					panic(badName)
				case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR":
					return 2
				}
			case 'M':
				switch c4 {
				default:
					panic(badName)
				case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR":
					return 2
				}
			}
		}
	case 3:
		switch c2 {
		default:
			panic(badName)
		case "GE":
			switch c3 {
			default:
				panic(badName)
			case "QRF", "RQF", "LQF", "QLF":
				if sname {
					return 128
				}
				return 128
			case "HRD":
				if sname {
					return 128
				}
				return 128
			case "BRD":
				if sname {
					return 128
				}
				return 128
			}
		case "SY":
			if sname && c3 == "TRD" {
				return 32
			}
			panic(badName)
		case "HE":
			if c3 == "TRD" {
				return 32
			}
			panic(badName)
		case "OR":
			switch c3[0] {
			default:
				panic(badName)
			case 'G':
				switch c4 {
				default:
					panic(badName)
				case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR":
					return 128
				}
			}
		case "UN":
			switch c3[0] {
			default:
				panic(badName)
			case 'G':
				switch c4 {
				default:
					panic(badName)
				case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR":
					return 128
				}
			}
		}
	case 4:
		// Used by xHSEQR
		return 6
	case 5:
		// Not used
		return 2
	case 6:
		// Used by xGELSS and xGESVD
		return int(float64(min(n1, n2)) * 1.6)
	case 7:
		// Not used
		return 1
	case 8:
		// Used by xHSEQR
		return 50
	case 9:
		// used by xGELSD and xGESDD
		return 25
	case 10:
		// Go guarantees ieee
		return 1
	case 11:
		// Go guarantees ieee
		return 1
	case 12, 13, 14, 15, 16:
		// Dhseqr and related functions for eigenvalue problems.
		return impl.Iparmq(ispec, name, opts, n1, n2, n3, n4)
	}
}
<commit_msg>lapack/gonum: fix Ilaenv for DPBTRF<commit_after>// Copyright ©2015 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gonum

// Ilaenv returns algorithm tuning parameters for the algorithm given by the
// input string. ispec specifies the parameter to return:
//  1: The optimal block size for a blocked algorithm.
//  2: The minimum block size for a blocked algorithm.
//  3: The block size of unprocessed data at which a blocked algorithm should
//     crossover to an unblocked version.
//  4: The number of shifts.
//  5: The minimum column dimension for blocking to be used.
//  6: The crossover point for SVD (to use QR factorization or not).
//  7: The number of processors.
//  8: The crossover point for multi-shift in QR and QZ methods for non-symmetric eigenvalue problems.
//  9: Maximum size of the subproblems in divide-and-conquer algorithms.
//  10: ieee NaN arithmetic can be trusted not to trap.
//  11: infinity arithmetic can be trusted not to trap.
//  12...16: parameters for Dhseqr and related functions. See Iparmq for more
//           information.
//
// Ilaenv is an internal routine. It is exported for testing purposes.
func (impl Implementation) Ilaenv(ispec int, name string, opts string, n1, n2, n3, n4 int) int {
	// TODO(btracey): Replace this with a constant lookup? A list of constants?
	sname := name[0] == 'S' || name[0] == 'D'
	cname := name[0] == 'C' || name[0] == 'Z'
	if !sname && !cname {
		panic(badName)
	}
	c2 := name[1:3]
	c3 := name[3:6]
	c4 := c3[1:3]

	switch ispec {
	default:
		panic(badIspec)
	case 1:
		switch c2 {
		default:
			panic(badName)
		case "GE":
			switch c3 {
			default:
				panic(badName)
			case "TRF":
				if sname {
					return 64
				}
				return 64
			case "QRF", "RQF", "LQF", "QLF":
				if sname {
					return 32
				}
				return 32
			case "HRD":
				if sname {
					return 32
				}
				return 32
			case "BRD":
				if sname {
					return 32
				}
				return 32
			case "TRI":
				if sname {
					return 64
				}
				return 64
			}
		case "PO":
			switch c3 {
			default:
				panic(badName)
			case "TRF":
				if sname {
					return 64
				}
				return 64
			}
		case "SY":
			switch c3 {
			default:
				panic(badName)
			case "TRF":
				if sname {
					return 64
				}
				return 64
			case "TRD":
				return 32
			case "GST":
				return 64
			}
		case "HE":
			switch c3 {
			default:
				panic(badName)
			case "TRF":
				return 64
			case "TRD":
				return 32
			case "GST":
				return 64
			}
		case "OR":
			switch c3[0] {
			default:
				panic(badName)
			case 'G':
				switch c3[1:] {
				default:
					panic(badName)
				case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR":
					return 32
				}
			case 'M':
				switch c3[1:] {
				default:
					panic(badName)
				case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR":
					return 32
				}
			}
		case "UN":
			switch c3[0] {
			default:
				panic(badName)
			case 'G':
				switch c3[1:] {
				default:
					panic(badName)
				case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR":
					return 32
				}
			case 'M':
				switch c3[1:] {
				default:
					panic(badName)
				case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR":
					return 32
				}
			}
		case "GB":
			switch c3 {
			default:
				panic(badName)
			case "TRF":
				if sname {
					if n4 <= 64 {
						return 1
					}
					return 32
				}
				if n4 <= 64 {
					return 1
				}
				return 32
			}
		case "PB":
			switch c3 {
			default:
				panic(badName)
			case "TRF":
				if sname {
					if n2 <= 64 {
						return 1
					}
					return 32
				}
				if n2 <= 64 {
					return 1
				}
				return 32
			}
		case "TR":
			switch c3 {
			default:
				panic(badName)
			case "TRI":
				if sname {
					return 64
				}
				return 64
			case "EVC":
				if sname {
					return 64
				}
				return 64
			}
		case "LA":
			switch c3 {
			default:
				panic(badName)
			case "UUM":
				if sname {
					return 64
				}
				return 64
			}
		case "ST":
			if sname && c3 == "EBZ" {
				return 1
			}
			panic(badName)
		}
	case 2:
		switch c2 {
		default:
			panic(badName)
		case "GE":
			switch c3 {
			default:
				panic(badName)
			case "QRF", "RQF", "LQF", "QLF":
				if sname {
					return 2
				}
				return 2
			case "HRD":
				if sname {
					return 2
				}
				return 2
			case "BRD":
				if sname {
					return 2
				}
				return 2
			case "TRI":
				if sname {
					return 2
				}
				return 2
			}
		case "SY":
			switch c3 {
			default:
				panic(badName)
			case "TRF":
				if sname {
					return 8
				}
				return 8
			case "TRD":
				if sname {
					return 2
				}
				panic(badName)
			}
		case "HE":
			if c3 == "TRD" {
				return 2
			}
			panic(badName)
		case "OR":
			if !sname {
				panic(badName)
			}
			switch c3[0] {
			default:
				panic(badName)
			case 'G':
				switch c4 {
				default:
					panic(badName)
				case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR":
					return 2
				}
			case 'M':
				switch c4 {
				default:
					panic(badName)
				case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR":
					return 2
				}
			}
		case "UN":
			switch c3[0] {
			default:
				panic(badName)
			case 'G':
				switch c4 {
				default:
					panic(badName)
				case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR":
					return 2
				}
			case 'M':
				switch c4 {
				default:
					panic(badName)
				case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR":
					return 2
				}
			}
		}
	case 3:
		switch c2 {
		default:
			panic(badName)
		case "GE":
			switch c3 {
			default:
				panic(badName)
			case "QRF", "RQF", "LQF", "QLF":
				if sname {
					return 128
				}
				return 128
			case "HRD":
				if sname {
					return 128
				}
				return 128
			case "BRD":
				if sname {
					return 128
				}
				return 128
			}
		case "SY":
			if sname && c3 == "TRD" {
				return 32
			}
			panic(badName)
		case "HE":
			if c3 == "TRD" {
				return 32
			}
			panic(badName)
		case "OR":
			switch c3[0] {
			default:
				panic(badName)
			case 'G':
				switch c4 {
				default:
					panic(badName)
				case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR":
					return 128
				}
			}
		case "UN":
			switch c3[0] {
			default:
				panic(badName)
			case 'G':
				switch c4 {
				default:
					panic(badName)
				case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR":
					return 128
				}
			}
		}
	case 4:
		// Used by xHSEQR
		return 6
	case 5:
		// Not used
		return 2
	case 6:
		// Used by xGELSS and xGESVD
		return int(float64(min(n1, n2)) * 1.6)
	case 7:
		// Not used
		return 1
	case 8:
		// Used by xHSEQR
		return 50
	case 9:
		// used by xGELSD and xGESDD
		return 25
	case 10:
		// Go guarantees ieee
		return 1
	case 11:
		// Go guarantees ieee
		return 1
	case 12, 13, 14, 15, 16:
		// Dhseqr and related functions for eigenvalue problems.
		return impl.Iparmq(ispec, name, opts, n1, n2, n3, n4)
	}
}
<|endoftext|>


<commit_before>package throttler

import (
	"fmt"
	"os/exec"
	"strconv"
)

const (
	ipfwAddPipe  = `sudo ipfw add 1 pipe 1 ip from any to any`
	ipfwTeardown = `sudo ipfw delete 1`
	ipfwConfig   = `sudo ipfw pipe 1 config`
	ipfwExists   = `sudo ipfw list | grep "pipe 1"`
	ipfwCheck    = `sudo ipfw list`
)

type ipfwThrottler struct{}

func (i *ipfwThrottler) setup(c *Config) error {
	fmt.Println(ipfwAddPipe)
	if err := exec.Command("/bin/sh", "-c", ipfwAddPipe).Run(); err != nil {
		return err
	}

	configCmd := i.buildConfigCommand(c)
	fmt.Println(configCmd)
	return exec.Command("/bin/sh", "-c", configCmd).Run()
}

func (i *ipfwThrottler) teardown(_ *Config) error {
	fmt.Println(ipfwTeardown)
	return exec.Command("/bin/sh", "-c", ipfwTeardown).Run()
}

func (i *ipfwThrottler) exists() bool {
	fmt.Println(ipfwExists)
	return exec.Command("/bin/sh", "-c", ipfwExists).Run() == nil
}

func (i *ipfwThrottler) check() string {
	return ipfwCheck
}

func (i *ipfwThrottler) buildConfigCommand(c *Config) string {
	cmd := ipfwConfig

	if c.Latency > 0 {
		cmd = cmd + " delay " + strconv.Itoa(c.Latency) + "ms"
	}

	if c.Bandwidth > 0 {
		cmd = cmd + " bw " + strconv.Itoa(c.Bandwidth) + "Kbit/s"
	}

	if c.PacketLoss > 0 {
		cmd = cmd + " plr " + strconv.FormatFloat(c.PacketLoss, 'f', 2, 64)
	}

	cmd = cmd + " via " + c.Device

	return cmd
}
<commit_msg>Fix ipfw device configuration<commit_after>package throttler

import (
	"fmt"
	"os/exec"
	"strconv"
)

const (
	ipfwAddPipe  = `sudo ipfw add 1 pipe 1 ip from any to any via `
	ipfwTeardown = `sudo ipfw delete 1`
	ipfwConfig   = `sudo ipfw pipe 1 config`
	ipfwExists   = `sudo ipfw list | grep "pipe 1"`
	ipfwCheck    = `sudo ipfw list`
)

type ipfwThrottler struct{}

func (i *ipfwThrottler) setup(c *Config) error {
	fmt.Println(ipfwAddPipe + c.Device)
	if err := exec.Command("/bin/sh", "-c", ipfwAddPipe+c.Device).Run(); err != nil {
		return err
	}

	configCmd := i.buildConfigCommand(c)
	fmt.Println(configCmd)
	return exec.Command("/bin/sh", "-c", configCmd).Run()
}

func (i *ipfwThrottler) teardown(_ *Config) error {
	fmt.Println(ipfwTeardown)
	return exec.Command("/bin/sh", "-c", ipfwTeardown).Run()
}

func (i *ipfwThrottler) exists() bool {
	fmt.Println(ipfwExists)
	return exec.Command("/bin/sh", "-c", ipfwExists).Run() == nil
}

func (i *ipfwThrottler) check() string {
	return ipfwCheck
}

func (i *ipfwThrottler) buildConfigCommand(c *Config) string {
	cmd := ipfwConfig

	if c.Latency > 0 {
		cmd = cmd + " delay " + strconv.Itoa(c.Latency) + "ms"
	}

	if c.Bandwidth > 0 {
		cmd = cmd + " bw " + strconv.Itoa(c.Bandwidth) + "Kbit/s"
	}

	if c.PacketLoss > 0 {
		cmd = cmd + " plr " + strconv.FormatFloat(c.PacketLoss, 'f', 2, 64)
	}

	return cmd
}
<|endoftext|>


<commit_before>package services_test

import (
	"encoding/json"
	"fmt"
	"os"
	"time"

	"github.com/cloudfoundry-incubator/cf-test-helpers/cf"
	"github.com/cloudfoundry-incubator/cf-test-helpers/generator"
	"github.com/cloudfoundry/cf-acceptance-tests/helpers/assets"
	. "github.com/cloudfoundry/cf-acceptance-tests/helpers/services"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"
)

type LastOperation struct {
	State string `json:"state"`
}

type Service struct {
	Name          string        `json:"name"`
	LastOperation LastOperation `json:"last_operation"`
}

type Resource struct {
	Entity Service `json:"entity"`
}

type Response struct {
	Resources []Resource `json:"resources"`
}

var _ = Describe("Service Instance Lifecycle", func() {
	var broker ServiceBroker
	var ASYNC_OPERATION_TIMEOUT = 2 * time.Minute
	var ASYNC_OPERATION_POLL_INTERVAL = 5 * time.Second

	waitForAsyncDeletionToComplete := func(broker ServiceBroker, instanceName string) {
		Eventually(func() *Session {
			return cf.Cf("service", instanceName).Wait(DEFAULT_TIMEOUT)
		}, ASYNC_OPERATION_TIMEOUT, ASYNC_OPERATION_POLL_INTERVAL).Should(Say("not found"))
	}

	waitForAsyncOperationToComplete := func(broker ServiceBroker, instanceName string) {
		Eventually(func() *Session {
			serviceDetails := cf.Cf("service", instanceName).Wait(DEFAULT_TIMEOUT)
			Expect(serviceDetails).To(Exit(0), "failed getting service instance details")
			return serviceDetails
		}, ASYNC_OPERATION_TIMEOUT, ASYNC_OPERATION_POLL_INTERVAL).Should(Say("succeeded"))
	}

	Context("Synchronous operations", func() {
		BeforeEach(func() {
			broker = NewServiceBroker(generator.RandomName(), assets.NewAssets().ServiceBroker, context, true)
			broker.Push()
			broker.Configure()
			broker.Create()
			broker.PublicizePlans()
		})

		AfterEach(func() {
			broker.Destroy()
		})

		Context("just service instances", func() {
			It("can create a service instance", func() {
				tags := "['tag1', 'tag2']"
				type Params struct{ param1 string }
				params, _ := json.Marshal(Params{param1: "value"})

				instanceName := generator.RandomName()
				createService := cf.Cf("create-service", broker.Service.Name, broker.SyncPlans[0].Name, instanceName, "-c", string(params), "-t", tags).Wait(DEFAULT_TIMEOUT)
				Expect(createService).To(Exit(0))

				os.Setenv("CF_TRACE", "true")
				serviceInfo := cf.Cf("service", instanceName).Wait(DEFAULT_TIMEOUT)
				Expect(serviceInfo).To(Say(fmt.Sprintf("Plan: %s", broker.SyncPlans[0].Name)))
				Expect(serviceInfo.Out.Contents()).To(MatchRegexp(`"tags":\s*\[\n.*tag1.*\n.*tag2.*\n.*\]`))
				os.Setenv("CF_TRACE", "false")
			})

			Context("when there is an existing service instance", func() {
				var instanceName string
				BeforeEach(func() {
					instanceName = generator.RandomName()
					createService := cf.Cf("create-service", broker.Service.Name, broker.SyncPlans[0].Name, instanceName).Wait(DEFAULT_TIMEOUT)
					Expect(createService).To(Exit(0), "failed creating service")
				})

				It("can delete a service instance", func() {
					deleteService := cf.Cf("delete-service", instanceName, "-f").Wait(DEFAULT_TIMEOUT)
					Expect(deleteService).To(Exit(0))

					serviceInfo := cf.Cf("service", instanceName).Wait(DEFAULT_TIMEOUT)
					Expect(serviceInfo).To(Say("not found"))
				})

				Context("updating a service instance", func() {
					tags := "['tag1', 'tag2']"
					type Params struct{ param1 string }
					params, _ := json.Marshal(Params{param1: "value"})

					It("can rename a service", func() {
						newname := "newname"
						updateService := cf.Cf("rename-service", instanceName, newname).Wait(DEFAULT_TIMEOUT)
						Expect(updateService).To(Exit(0))

						serviceInfo := cf.Cf("service", newname).Wait(DEFAULT_TIMEOUT)
						Expect(serviceInfo).To(Say(newname))

						serviceInfo = cf.Cf("service", instanceName).Wait(DEFAULT_TIMEOUT)
						Expect(serviceInfo).To(Exit(1))
					})
					It("can update a service plan", func() {
						updateService := cf.Cf("update-service", instanceName, "-p", broker.SyncPlans[1].Name).Wait(DEFAULT_TIMEOUT)
						Expect(updateService).To(Exit(0))

						serviceInfo := cf.Cf("service", instanceName).Wait(DEFAULT_TIMEOUT)
						Expect(serviceInfo).To(Say(fmt.Sprintf("Plan: %s", broker.SyncPlans[1].Name)))
					})
					It("can update service tags", func() {
						updateService := cf.Cf("update-service", instanceName, "-t", tags).Wait(DEFAULT_TIMEOUT)
						Expect(updateService).To(Exit(0))

						os.Setenv("CF_TRACE", "true")
						serviceInfo := cf.Cf("service", instanceName).Wait(DEFAULT_TIMEOUT)
						Expect(serviceInfo.Out.Contents()).To(MatchRegexp(`"tags":\s*\[\n.*tag1.*\n.*tag2.*\n.*\]`))
						os.Setenv("CF_TRACE", "false")
					})

					It("can update arbitrary parameters", func() {
						updateService := cf.Cf("update-service", instanceName, "-c", string(params)).Wait(DEFAULT_TIMEOUT)
						Expect(updateService).To(Exit(0), "Failed updating service")
						//Note: We don't necessarily get these back through a service instance lookup
					})
					It("can update all available parameters", func() {
						updateService := cf.Cf("update-service", instanceName, "-p", broker.SyncPlans[1].Name, "-t", tags, "-c", string(params)).Wait(DEFAULT_TIMEOUT)
						Expect(updateService).To(Exit(0))

						os.Setenv("CF_TRACE", "true")
						serviceInfo := cf.Cf("service", instanceName).Wait(DEFAULT_TIMEOUT)
						Expect(serviceInfo).To(Say(fmt.Sprintf("Plan: %s", broker.SyncPlans[1].Name)))
						Expect(serviceInfo.Out.Contents()).To(MatchRegexp(`"tags":\s*\[\n.*tag1.*\n.*tag2.*\n.*\]`))
						os.Setenv("CF_TRACE", "false")
					})

				})
			})
		})

		Context("when there is an app", func() {
			var instanceName, appName string
			BeforeEach(func() {
				appName = generator.PrefixedRandomName("CATS-APP-")
				createApp := cf.Cf("push", appName, "-p", assets.NewAssets().Dora).Wait(CF_PUSH_TIMEOUT)
				Expect(createApp).To(Exit(0), "failed creating app")

				checkForEvents(appName, []string{"audit.app.create"})

				instanceName = generator.RandomName()
				createService := cf.Cf("create-service", broker.Service.Name, broker.SyncPlans[0].Name, instanceName).Wait(DEFAULT_TIMEOUT)
				Expect(createService).To(Exit(0), "failed creating service")
			})

			It("can bind service to app and check app env and events", func() {
				bindService := cf.Cf("bind-service", appName, instanceName).Wait(DEFAULT_TIMEOUT)
				Expect(bindService).To(Exit(0), "failed binding app to service")

				checkForEvents(appName, []string{"audit.app.update"})

				restageApp := cf.Cf("restage", appName).Wait(CF_PUSH_TIMEOUT)
				Expect(restageApp).To(Exit(0), "failed restaging app")

				checkForEvents(appName, []string{"audit.app.restage"})

				appEnv := cf.Cf("env", appName).Wait(DEFAULT_TIMEOUT)
				Expect(appEnv).To(Exit(0), "failed get env for app")
				Expect(appEnv).To(Say(fmt.Sprintf("credentials")))
			})

			Context("when there is an existing binding", func() {
				BeforeEach(func() {
					bindService := cf.Cf("bind-service", appName, instanceName).Wait(DEFAULT_TIMEOUT)
					Expect(bindService).To(Exit(0), "failed binding app to service")
				})

				It("can unbind service to app and check app env and events", func() {
					unbindService := cf.Cf("unbind-service", appName, instanceName).Wait(DEFAULT_TIMEOUT)
					Expect(unbindService).To(Exit(0), "failed unbinding app to service")

					checkForEvents(appName, []string{"audit.app.update"})

					appEnv := cf.Cf("env", appName).Wait(DEFAULT_TIMEOUT)
					Expect(appEnv).To(Exit(0), "failed get env for app")
					Expect(appEnv).ToNot(Say(fmt.Sprintf("credentials")))
				})
			})
		})
	})

	Context("Asynchronous operations", func() {
		BeforeEach(func() {
			broker = NewServiceBroker(generator.RandomName(), assets.NewAssets().ServiceBroker, context, true)
			broker.Push()
			broker.Configure()
			broker.Create()
			broker.PublicizePlans()
		})

		AfterEach(func() {
			broker.Destroy()
		})

		It("can create a service instance", func() {
			instanceName := generator.RandomName()
			createService := cf.Cf("create-service", broker.Service.Name, broker.AsyncPlans[0].Name, instanceName).Wait(DEFAULT_TIMEOUT)
			Expect(createService).To(Exit(0))
			Expect(createService).To(Say("Create in progress."))

			waitForAsyncOperationToComplete(broker, instanceName)

			serviceInfo := cf.Cf("service", instanceName).Wait(DEFAULT_TIMEOUT)
			Expect(serviceInfo).To(Say(fmt.Sprintf("Plan: %s", broker.AsyncPlans[0].Name)))
			Expect(serviceInfo).To(Say("Status: create succeeded"))
			Expect(serviceInfo).To(Say("Message: 100 percent done"))
		})

		Context("when there is an existing service instance", func() {
			var instanceName string
			BeforeEach(func() {
				instanceName = generator.RandomName()
				createService := cf.Cf("create-service", broker.Service.Name, broker.AsyncPlans[0].Name, instanceName).Wait(DEFAULT_TIMEOUT)
				Expect(createService).To(Exit(0))
				Expect(createService).To(Say("Create in progress."))

				waitForAsyncOperationToComplete(broker, instanceName)
			})

			It("can update a service instance", func() {
				updateService := cf.Cf("update-service", instanceName, "-p", broker.AsyncPlans[1].Name).Wait(DEFAULT_TIMEOUT)
				Expect(updateService).To(Exit(0))
				Expect(updateService).To(Say("Update in progress."))

				serviceInfo := cf.Cf("service", instanceName).Wait(DEFAULT_TIMEOUT)
				Expect(serviceInfo).To(Exit(0), "failed getting service instance details")
				Expect(serviceInfo).To(Say(fmt.Sprintf("Plan: %s", broker.AsyncPlans[0].Name)))

				waitForAsyncOperationToComplete(broker, instanceName)

				serviceInfo = cf.Cf("service", instanceName).Wait(DEFAULT_TIMEOUT)
				Expect(serviceInfo).To(Exit(0), "failed getting service instance details")
				Expect(serviceInfo).To(Say(fmt.Sprintf("Plan: %s", broker.AsyncPlans[1].Name)))
			})
			It("can delete a service instance", func() {
				deleteService := cf.Cf("delete-service", instanceName, "-f").Wait(DEFAULT_TIMEOUT)
				Expect(deleteService).To(Exit(0), "failed making delete request")
				Expect(deleteService).To(Say("Delete in progress."))

				waitForAsyncDeletionToComplete(broker, instanceName)
			})

			Context("when there is an app", func() {
				var appName string
				BeforeEach(func() {
					appName = generator.PrefixedRandomName("CATS-APP-")
					createApp := cf.Cf("push", appName, "-p", assets.NewAssets().Dora).Wait(CF_PUSH_TIMEOUT)
					Expect(createApp).To(Exit(0), "failed creating app")
				})
				It("can bind a service instance", func() {
					bindService := cf.Cf("bind-service", appName, instanceName).Wait(DEFAULT_TIMEOUT)
					Expect(bindService).To(Exit(0), "failed binding app to service")

					checkForEvents(appName, []string{"audit.app.update"})

					restageApp := cf.Cf("restage", appName).Wait(CF_PUSH_TIMEOUT)
					Expect(restageApp).To(Exit(0), "failed restaging app")

					checkForEvents(appName, []string{"audit.app.restage"})

					appEnv := cf.Cf("env", appName).Wait(DEFAULT_TIMEOUT)
					Expect(appEnv).To(Exit(0), "failed get env for app")
					Expect(appEnv).To(Say(fmt.Sprintf("credentials")))
				})

				Context("when there is an existing binding", func() {
					BeforeEach(func() {
						bindService := cf.Cf("bind-service", appName, instanceName).Wait(DEFAULT_TIMEOUT)
						Expect(bindService).To(Exit(0), "failed binding app to service")
					})
					It("can unbind a service instance", func() {
						unbindService := cf.Cf("unbind-service", appName, instanceName).Wait(DEFAULT_TIMEOUT)
						Expect(unbindService).To(Exit(0), "failed unbinding app to service")

						checkForEvents(appName, []string{"audit.app.update"})

						appEnv := cf.Cf("env", appName).Wait(DEFAULT_TIMEOUT)
						Expect(appEnv).To(Exit(0), "failed get env for app")
						Expect(appEnv).ToNot(Say(fmt.Sprintf("credentials")))
					})
				})
			})
		})
	})
})

func checkForEvents(name string, eventNames []string) {
	events := cf.Cf("events", name).Wait(DEFAULT_TIMEOUT)
	Expect(events).To(Exit(0), fmt.Sprintf("failed getting events for %s", name))

	for _, eventName := range eventNames {
		Expect(events).To(Say(eventName), "failed to find event")
	}
}
<commit_msg>Add tests for arbitrary params<commit_after>package services_test

import (
	"encoding/json"
	"fmt"
	"os"
	"time"

	"github.com/cloudfoundry-incubator/cf-test-helpers/cf"
	"github.com/cloudfoundry-incubator/cf-test-helpers/generator"
	"github.com/cloudfoundry/cf-acceptance-tests/helpers/assets"
	. "github.com/cloudfoundry/cf-acceptance-tests/helpers/services"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"
)

type LastOperation struct {
	State string `json:"state"`
}

type Service struct {
	Name          string        `json:"name"`
	LastOperation LastOperation `json:"last_operation"`
}

type Resource struct {
	Entity Service `json:"entity"`
}

type Response struct {
	Resources []Resource `json:"resources"`
}

var _ = Describe("Service Instance Lifecycle", func() {
	var broker ServiceBroker
	var ASYNC_OPERATION_TIMEOUT = 2 * time.Minute
	var ASYNC_OPERATION_POLL_INTERVAL = 5 * time.Second

	waitForAsyncDeletionToComplete := func(broker ServiceBroker, instanceName string) {
		Eventually(func() *Session {
			return cf.Cf("service", instanceName).Wait(DEFAULT_TIMEOUT)
		}, ASYNC_OPERATION_TIMEOUT, ASYNC_OPERATION_POLL_INTERVAL).Should(Say("not found"))
	}

	waitForAsyncOperationToComplete := func(broker ServiceBroker, instanceName string) {
		Eventually(func() *Session {
			serviceDetails := cf.Cf("service", instanceName).Wait(DEFAULT_TIMEOUT)
			Expect(serviceDetails).To(Exit(0), "failed getting service instance details")
			return serviceDetails
		}, ASYNC_OPERATION_TIMEOUT, ASYNC_OPERATION_POLL_INTERVAL).Should(Say("succeeded"))
	}

	Context("Synchronous operations", func() {
		BeforeEach(func() {
			broker = NewServiceBroker(generator.RandomName(), assets.NewAssets().ServiceBroker, context, true)
			broker.Push()
			broker.Configure()
			broker.Create()
			broker.PublicizePlans()
		})

		AfterEach(func() {
			broker.Destroy()
		})

		Context("just service instances", func() {
			It("can create a service instance", func() {
				tags := "['tag1', 'tag2']"
				type Params struct{ Param1 string }
				params, _ := json.Marshal(Params{Param1: "value"})

				instanceName := generator.RandomName()
				createService := cf.Cf("create-service", broker.Service.Name, broker.SyncPlans[0].Name, instanceName, "-c", string(params), "-t", tags).Wait(DEFAULT_TIMEOUT)
				Expect(createService).To(Exit(0))

				os.Setenv("CF_TRACE", "true")
				serviceInfo := cf.Cf("service", instanceName).Wait(DEFAULT_TIMEOUT)
				Expect(serviceInfo).To(Say(fmt.Sprintf("Plan: %s", broker.SyncPlans[0].Name)))
				Expect(serviceInfo.Out.Contents()).To(MatchRegexp(`"tags":\s*\[\n.*tag1.*\n.*tag2.*\n.*\]`))
				os.Setenv("CF_TRACE", "false")
			})

			Context("when there is an existing service instance", func() {
				var instanceName string
				BeforeEach(func() {
					instanceName = generator.RandomName()
					createService := cf.Cf("create-service", broker.Service.Name, broker.SyncPlans[0].Name, instanceName).Wait(DEFAULT_TIMEOUT)
					Expect(createService).To(Exit(0), "failed creating service")
				})

				It("can delete a service instance", func() {
					deleteService := cf.Cf("delete-service", instanceName, "-f").Wait(DEFAULT_TIMEOUT)
					Expect(deleteService).To(Exit(0))

					serviceInfo := cf.Cf("service", instanceName).Wait(DEFAULT_TIMEOUT)
					Expect(serviceInfo).To(Say("not found"))
				})

				Context("updating a service instance", func() {
					tags := "['tag1', 'tag2']"
					type Params struct{ Param1 string }
					params, _ := json.Marshal(Params{Param1: "value"})

					It("can rename a service", func() {
						newname := "newname"
						updateService := cf.Cf("rename-service", instanceName, newname).Wait(DEFAULT_TIMEOUT)
						Expect(updateService).To(Exit(0))

						serviceInfo := cf.Cf("service", newname).Wait(DEFAULT_TIMEOUT)
						Expect(serviceInfo).To(Say(newname))

						serviceInfo = cf.Cf("service", instanceName).Wait(DEFAULT_TIMEOUT)
						Expect(serviceInfo).To(Exit(1))
					})
					It("can update a service plan", func() {
						updateService := cf.Cf("update-service", instanceName, "-p", broker.SyncPlans[1].Name).Wait(DEFAULT_TIMEOUT)
						Expect(updateService).To(Exit(0))

						serviceInfo := cf.Cf("service", instanceName).Wait(DEFAULT_TIMEOUT)
						Expect(serviceInfo).To(Say(fmt.Sprintf("Plan: %s", broker.SyncPlans[1].Name)))
					})
					It("can update service tags", func() {
						updateService := cf.Cf("update-service", instanceName, "-t", tags).Wait(DEFAULT_TIMEOUT)
						Expect(updateService).To(Exit(0))

						os.Setenv("CF_TRACE", "true")
						serviceInfo := cf.Cf("service", instanceName).Wait(DEFAULT_TIMEOUT)
						Expect(serviceInfo.Out.Contents()).To(MatchRegexp(`"tags":\s*\[\n.*tag1.*\n.*tag2.*\n.*\]`))
						os.Setenv("CF_TRACE", "false")
					})

					It("can update arbitrary parameters", func() {
						updateService := cf.Cf("update-service", instanceName, "-c", string(params)).Wait(DEFAULT_TIMEOUT)
						Expect(updateService).To(Exit(0), "Failed updating service")
						//Note: We don't necessarily get these back through a service instance lookup
					})
					It("can update all available parameters at once", func() {
						updateService := cf.Cf(
							"update-service", instanceName,
							"-p", broker.SyncPlans[1].Name,
							"-t", tags,
							"-c", string(params)).Wait(DEFAULT_TIMEOUT)
						Expect(updateService).To(Exit(0))

						os.Setenv("CF_TRACE", "true")
						serviceInfo := cf.Cf("service", instanceName).Wait(DEFAULT_TIMEOUT)
						Expect(serviceInfo).To(Say(fmt.Sprintf("Plan: %s", broker.SyncPlans[1].Name)))
						Expect(serviceInfo.Out.Contents()).To(MatchRegexp(`"tags":\s*\[\n.*tag1.*\n.*tag2.*\n.*\]`))
						os.Setenv("CF_TRACE", "false")
					})

				})
			})
		})

		Context("when there is an app", func() {
			var instanceName, appName string
			type Params struct{ Param1 string }
			params, _ := json.Marshal(Params{Param1: "value"})

			BeforeEach(func() {
				appName = generator.PrefixedRandomName("CATS-APP-")
				createApp := cf.Cf("push", appName, "-p", assets.NewAssets().Dora).Wait(CF_PUSH_TIMEOUT)
				Expect(createApp).To(Exit(0), "failed creating app")

				checkForEvents(appName, []string{"audit.app.create"})

				instanceName = generator.RandomName()
				createService := cf.Cf("create-service", broker.Service.Name, broker.SyncPlans[0].Name, instanceName).Wait(DEFAULT_TIMEOUT)
				Expect(createService).To(Exit(0), "failed creating service")
			})

			It("can bind service to app and check app env and events", func() {
				bindService := cf.Cf("bind-service", appName, instanceName).Wait(DEFAULT_TIMEOUT)
				Expect(bindService).To(Exit(0), "failed binding app to service")

				checkForEvents(appName, []string{"audit.app.update"})

				restageApp := cf.Cf("restage", appName).Wait(CF_PUSH_TIMEOUT)
				Expect(restageApp).To(Exit(0), "failed restaging app")

				checkForEvents(appName, []string{"audit.app.restage"})

				appEnv := cf.Cf("env", appName).Wait(DEFAULT_TIMEOUT)
				Expect(appEnv).To(Exit(0), "failed get env for app")
				Expect(appEnv).To(Say(fmt.Sprintf("credentials")))
			})

			It("can bind service to app and send arbitrary params", func() {
				bindService := cf.Cf("bind-service", appName, instanceName, "-c", string(params)).Wait(DEFAULT_TIMEOUT)
				Expect(bindService).To(Exit(0), "failed binding app to service")
			})

			Context("when there is an existing binding", func() {
				BeforeEach(func() {
					bindService := cf.Cf("bind-service", appName, instanceName).Wait(DEFAULT_TIMEOUT)
					Expect(bindService).To(Exit(0), "failed binding app to service")
				})

				It("can unbind service to app and check app env and events", func() {
					unbindService := cf.Cf("unbind-service", appName, instanceName).Wait(DEFAULT_TIMEOUT)
					Expect(unbindService).To(Exit(0), "failed unbinding app to service")

					checkForEvents(appName, []string{"audit.app.update"})

					appEnv := cf.Cf("env", appName).Wait(DEFAULT_TIMEOUT)
					Expect(appEnv).To(Exit(0), "failed get env for app")
					Expect(appEnv).ToNot(Say(fmt.Sprintf("credentials")))
				})
			})
		})
	})

	Context("Asynchronous operations", func() {
		BeforeEach(func() {
			broker = NewServiceBroker(generator.RandomName(), assets.NewAssets().ServiceBroker, context, true)
			broker.Push()
			broker.Configure()
			broker.Create()
			broker.PublicizePlans()
		})

		AfterEach(func() {
			broker.Destroy()
		})

		It("can create a service instance", func() {
			tags := "['tag1', 'tag2']"
			type Params struct{ Param1 string }
			params, _ := json.Marshal(Params{Param1: "value"})

			instanceName := generator.RandomName()
			createService := cf.Cf("create-service", broker.Service.Name, broker.AsyncPlans[0].Name, instanceName, "-t", tags, "-c", string(params)).Wait(DEFAULT_TIMEOUT)
			Expect(createService).To(Exit(0))
			Expect(createService).To(Say("Create in progress."))

			waitForAsyncOperationToComplete(broker, instanceName)

			os.Setenv("CF_TRACE", "true")
			serviceInfo := cf.Cf("service", instanceName).Wait(DEFAULT_TIMEOUT)
			Expect(serviceInfo).To(Say(fmt.Sprintf("Plan: %s", broker.AsyncPlans[0].Name)))
			Expect(serviceInfo).To(Say("Status: create succeeded"))
			Expect(serviceInfo).To(Say("Message: 100 percent done"))
			Expect(serviceInfo.Out.Contents()).To(MatchRegexp(`"tags":\s*\[\n.*tag1.*\n.*tag2.*\n.*\]`))
			os.Setenv("CF_TRACE", "false")
		})

		Context("when there is an existing service instance", func() {
			tags := "['tag1', 'tag2']"
			type Params struct{ Param1 string }
			params, _ := json.Marshal(Params{Param1: "value"})

			var instanceName string
			BeforeEach(func() {
				instanceName = generator.RandomName()
				createService := cf.Cf("create-service", broker.Service.Name, broker.AsyncPlans[0].Name, instanceName).Wait(DEFAULT_TIMEOUT)
				Expect(createService).To(Exit(0))
				Expect(createService).To(Say("Create in progress."))

				waitForAsyncOperationToComplete(broker, instanceName)
			})

			It("can update a service plan", func() {
				updateService := cf.Cf("update-service", instanceName, "-p", broker.AsyncPlans[1].Name).Wait(DEFAULT_TIMEOUT)
				Expect(updateService).To(Exit(0))
				Expect(updateService).To(Say("Update in progress."))

				serviceInfo := cf.Cf("service", instanceName).Wait(DEFAULT_TIMEOUT)
				Expect(serviceInfo).To(Exit(0), "failed getting service instance details")
				Expect(serviceInfo).To(Say(fmt.Sprintf("Plan: %s", broker.AsyncPlans[0].Name)))

				waitForAsyncOperationToComplete(broker, instanceName)

				serviceInfo = cf.Cf("service", instanceName).Wait(DEFAULT_TIMEOUT)
				Expect(serviceInfo).To(Exit(0), "failed getting service instance details")
				Expect(serviceInfo).To(Say(fmt.Sprintf("Plan: %s", broker.AsyncPlans[1].Name)))
			})

			It("can update the arbitrary params", func() {
				params, _ := json.Marshal(Params{Param1: "value"})
				updateService := cf.Cf("update-service", instanceName, "-c", string(params)).Wait(DEFAULT_TIMEOUT)
				Expect(updateService).To(Exit(0))
				Expect(updateService).To(Say("Update in progress."))

				waitForAsyncOperationToComplete(broker, instanceName)
			})

			It("can update all of the possible parameters at once", func() {
				updateService := cf.Cf(
					"update-service", instanceName,
					"-t", tags,
					"-c", string(params),
					"-p", broker.AsyncPlans[1].Name).Wait(DEFAULT_TIMEOUT)
				Expect(updateService).To(Exit(0))
				Expect(updateService).To(Say("Update in progress."))

				waitForAsyncOperationToComplete(broker, instanceName)

				os.Setenv("CF_TRACE", "true")
				serviceInfo := cf.Cf("service", instanceName).Wait(DEFAULT_TIMEOUT)
				Expect(serviceInfo).To(Exit(0), "failed getting service instance details")
				Expect(serviceInfo).To(Say(fmt.Sprintf("Plan: %s", broker.AsyncPlans[1].Name)))
				Expect(serviceInfo.Out.Contents()).To(MatchRegexp(`"tags":\s*\[\n.*tag1.*\n.*tag2.*\n.*\]`))
				os.Setenv("CF_TRACE", "false")
			})

			It("can delete a service instance", func() {
				deleteService := cf.Cf("delete-service", instanceName, "-f").Wait(DEFAULT_TIMEOUT)
				Expect(deleteService).To(Exit(0), "failed making delete request")
				Expect(deleteService).To(Say("Delete in progress."))

				waitForAsyncDeletionToComplete(broker, instanceName)
			})

			Context("when there is an app", func() {
				var appName string
				BeforeEach(func() {
					appName = generator.PrefixedRandomName("CATS-APP-")
					createApp := cf.Cf("push", appName, "-p", assets.NewAssets().Dora).Wait(CF_PUSH_TIMEOUT)
					Expect(createApp).To(Exit(0), "failed creating app")
				})
				It("can bind a service instance", func() {
					bindService := cf.Cf("bind-service", appName, instanceName).Wait(DEFAULT_TIMEOUT)
					Expect(bindService).To(Exit(0), "failed binding app to service")

					checkForEvents(appName, []string{"audit.app.update"})

					restageApp := cf.Cf("restage", appName).Wait(CF_PUSH_TIMEOUT)
					Expect(restageApp).To(Exit(0), "failed restaging app")

					checkForEvents(appName, []string{"audit.app.restage"})

					appEnv := cf.Cf("env", appName).Wait(DEFAULT_TIMEOUT)
					Expect(appEnv).To(Exit(0), "failed get env for app")
					Expect(appEnv).To(Say(fmt.Sprintf("credentials")))
				})

				It("can bind service to app and send arbitrary params", func() {
					bindService := cf.Cf("bind-service", appName, instanceName, "-c", string(params)).Wait(DEFAULT_TIMEOUT)
					Expect(bindService).To(Exit(0), "failed binding app to service")

					checkForEvents(appName, []string{"audit.app.update"})
				})

				Context("when there is an existing binding", func() {
					BeforeEach(func() {
						bindService := cf.Cf("bind-service", appName, instanceName).Wait(DEFAULT_TIMEOUT)
						Expect(bindService).To(Exit(0), "failed binding app to service")
					})
					It("can unbind a service instance", func() {
						unbindService := cf.Cf("unbind-service", appName, instanceName).Wait(DEFAULT_TIMEOUT)
						Expect(unbindService).To(Exit(0), "failed unbinding app to service")

						checkForEvents(appName, []string{"audit.app.update"})

						appEnv := cf.Cf("env", appName).Wait(DEFAULT_TIMEOUT)
						Expect(appEnv).To(Exit(0), "failed get env for app")
						Expect(appEnv).ToNot(Say(fmt.Sprintf("credentials")))
					})
				})
			})
		})
	})
})

func checkForEvents(name string, eventNames []string) {
	events := cf.Cf("events", name).Wait(DEFAULT_TIMEOUT)
	Expect(events).To(Exit(0), fmt.Sprintf("failed getting events for %s", name))

	for _, eventName := range eventNames {
		Expect(events).To(Say(eventName), "failed to find event")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"strings"

	"github.com/phrase/phraseapp-go/phraseapp"
)

type UploadCleanupCommand struct {
	*phraseapp.Config
	ID             string `cli:"arg required"`
	SuppressPrompt bool   `cli:"opt --yes desc='Don’t ask for confirmation'"`
}

func (cmd *UploadCleanupCommand) Run() error {

	client, err := newClient(cmd.Config.Credentials)
	if err != nil {
		return err
	}

	return UploadCleanup(client, cmd)
}

func UploadCleanup(client *phraseapp.Client, cmd *UploadCleanupCommand) error {
	q := "unmentioned_in_upload:" + cmd.ID
	params := &phraseapp.KeysListParams{Q: &q}

	var err error
	page := 1

	keys, err := client.KeysList(cmd.Config.DefaultProjectID, page, 25, params)
	if err != nil {
		return err
	}

	if len(keys) == 0 {
		fmt.Println("There were no keys unmentioned in that upload.")
		return nil
	}

	for len(keys) != 0 {
		ids := make([]string, len(keys), len(keys))
		names := make([]string, len(keys), len(keys))
		for i, key := range keys {
			ids[i] = key.ID
			names[i] = key.Name
		}

		if !cmd.SuppressPrompt {
			fmt.Println("You are about to delete the following key(s) from your project:")
			fmt.Println(strings.Join(names, " "))
			fmt.Print("Are you sure you want to continue? (y/n) [n] ")

			confirmation := prompt()
			if err != nil {
				return err
			}

			if strings.ToLower(confirmation) != "y" {
				fmt.Println("Clean up aborted")
				return nil
			}
		}

		q := "ids:" + strings.Join(ids, ",")
		affected, err := client.KeysDelete(cmd.Config.DefaultProjectID, &phraseapp.KeysDeleteParams{
			Q: &q,
		})

		if err != nil {
			return err
		}

		fmt.Printf("%d key(s) successfully deleted.\n", affected.RecordsAffected)

		page++
		keys, err = client.KeysList(cmd.Config.DefaultProjectID, page, 25, params)
	}

	return nil
}
<commit_msg>upload cleanup: rename --yes to --confirm and sort names to confirm<commit_after>package main

import (
	"fmt"
	"sort"
	"strings"

	"github.com/phrase/phraseapp-go/phraseapp"
)

type UploadCleanupCommand struct {
	*phraseapp.Config
	ID      string `cli:"arg required"`
	Confirm bool   `cli:"opt --confirm desc='Don’t ask for confirmation'"`
}

func (cmd *UploadCleanupCommand) Run() error {

	client, err := newClient(cmd.Config.Credentials)
	if err != nil {
		return err
	}

	return UploadCleanup(client, cmd)
}

func UploadCleanup(client *phraseapp.Client, cmd *UploadCleanupCommand) error {
	q := "unmentioned_in_upload:" + cmd.ID
	params := &phraseapp.KeysListParams{Q: &q}

	var err error
	page := 1

	keys, err := client.KeysList(cmd.Config.DefaultProjectID, page, 25, params)
	if err != nil {
		return err
	}

	if len(keys) == 0 {
		fmt.Println("There were no keys unmentioned in that upload.")
		return nil
	}

	for len(keys) != 0 {
		ids := make([]string, len(keys), len(keys))
		names := make([]string, len(keys), len(keys))
		for i, key := range keys {
			ids[i] = key.ID
			names[i] = key.Name
		}

		if !cmd.Confirm {
			fmt.Println("You are about to delete the following key(s) from your project:")
			sort.Strings(names)
			fmt.Println(strings.Join(names, "\n"))
			fmt.Print("Are you sure you want to continue? (y/n) [n] ")

			confirmation := prompt()
			if err != nil {
				return err
			}

			if strings.ToLower(confirmation) != "y" {
				fmt.Println("Clean up aborted")
				return nil
			}
		}

		q := "ids:" + strings.Join(ids, ",")
		affected, err := client.KeysDelete(cmd.Config.DefaultProjectID, &phraseapp.KeysDeleteParams{
			Q: &q,
		})

		if err != nil {
			return err
		}

		fmt.Printf("%d key(s) successfully deleted.\n", affected.RecordsAffected)

		page++
		keys, err = client.KeysList(cmd.Config.DefaultProjectID, page, 25, params)
	}

	return nil
}
<|endoftext|>


<commit_before>package util

import (
	"testing"
	"net/http"
)

type testObj struct {
	Name string `json:"name"`
	UrlType string `json:"url_type"`
	Normal map[string]interface{} `json:"normal"`
	RunList []string `json:"run_list"`
}

func (to *testObj) GetName() string {
	return to.Name
}

func (to *testObj) URLType() string {
	return to.UrlType
}

// The strange URLs are because the config doesn't get parsed here, so it ends
// up using the really-really default settings.

func TestObjURL(t *testing.T){
	obj := &testObj{ Name: "foo", UrlType: "bar" }
	url := ObjURL(obj)
	expectedUrl := "http://:0/bar/foo"
	if url != expectedUrl {
		t.Errorf("expected %s, got %s", expectedUrl, url)
	}
}

func TestCustomObjUrl(t *testing.T){
	obj := &testObj{ Name: "foo", UrlType: "bar" }
	url := CustomObjURL(obj, "/baz")
	expectedUrl := "http://:0/bar/foo/baz"
	if url != expectedUrl {
		t.Errorf("expected %s, got %s", expectedUrl, url)
	}
}

func TestCustomURL(t *testing.T){
	initUrl := "/foo/bar"
	url := CustomURL(initUrl)
	expectedUrl := "http://:0/foo/bar"
	if url != expectedUrl {
		t.Errorf("expected %s, got %s", expectedUrl, url)
	}
	initUrl = "foo/bar"
	url = CustomURL(initUrl)
	if url != expectedUrl {
		t.Errorf("expected %s, got %s", expectedUrl, url)
	}
}

func TestGerror(t *testing.T){
	errmsg := "foo bar"
	err := Errorf(errmsg)
	if err.Error() != errmsg {
		t.Errorf("expected %s to match %s", err.Error(), errmsg)
	}
	if err.Status() != http.StatusBadRequest {
		t.Errorf("err.Status() did not return expected default")
	}
	err.SetStatus(http.StatusNotFound)
	if err.Status() != http.StatusNotFound {
		t.Errorf("SetStatus did not set Status correctly")
	}
}

func TestFlatten(t *testing.T){
	rl := []string{ "recipe[foo]", "role[bar]" }
	normmap := make(map[string]interface{})
	normmap["foo"] = "bar"
	normmap["baz"] = "buz"
	normmap["slice"] = []string{ "fee", "fie", "fo" }
	normmap["map"] = make(map[string]interface{})
	normmap["map"].(map[string]interface{})["first"] = "mook"
	normmap["map"].(map[string]interface{})["second"] = "nork"
	obj := &testObj{ Name: "foo", UrlType: "bar", RunList: rl, Normal: normmap }
	flattened := FlattenObj(obj)
	if _, ok := flattened["name"]; !ok {
		t.Errorf("obj name was not flattened correctly")
	}
	if flattened["name"].(string) != obj.Name {
		t.Errorf("flattened name not correct, wanted %s got %v", obj.Name, flattened["name"])
	}
	if _, ok := flattened["foo"]; !ok {
		t.Errorf("Foo should have been set, but it wasn't")
	}
	if _, ok := flattened["normal"]; ok {
		t.Errorf("The 'normal' field was set, but shouldn't have been.")
	}
	if _, ok := flattened["map_first"]; !ok {
		t.Errorf("normal -> map -> second should have been flattened to map_second, but it wasn't")
	}
	if r, ok := flattened["recipe"]; ok {
		if r.([]string)[0] != "foo" {
			t.Errorf("recipe list should have included foo, but it had %v instead", r.([]string)[0])
		}
	} else {
		t.Errorf("No recipe list")
	}
	if r, ok := flattened["role"]; ok {
		if r.([]string)[0] != "bar" {
			t.Errorf("role list should have included bar, but it had %v instead", r.([]string)[0])
		}
	} else {
		t.Errorf("No role list")
	}
}

func TestMapify(t *testing.T){

}

func TestIndexify(t *testing.T){

}
<commit_msg>Starting on validation testing<commit_after>package util

import (
	"testing"
	"net/http"
)

type testObj struct {
	Name string `json:"name"`
	UrlType string `json:"url_type"`
	Normal map[string]interface{} `json:"normal"`
	RunList []string `json:"run_list"`
}

func (to *testObj) GetName() string {
	return to.Name
}

func (to *testObj) URLType() string {
	return to.UrlType
}

// The strange URLs are because the config doesn't get parsed here, so it ends
// up using the really-really default settings.

func TestObjURL(t *testing.T){
	obj := &testObj{ Name: "foo", UrlType: "bar" }
	url := ObjURL(obj)
	expectedUrl := "http://:0/bar/foo"
	if url != expectedUrl {
		t.Errorf("expected %s, got %s", expectedUrl, url)
	}
}

func TestCustomObjUrl(t *testing.T){
	obj := &testObj{ Name: "foo", UrlType: "bar" }
	url := CustomObjURL(obj, "/baz")
	expectedUrl := "http://:0/bar/foo/baz"
	if url != expectedUrl {
		t.Errorf("expected %s, got %s", expectedUrl, url)
	}
}

func TestCustomURL(t *testing.T){
	initUrl := "/foo/bar"
	url := CustomURL(initUrl)
	expectedUrl := "http://:0/foo/bar"
	if url != expectedUrl {
		t.Errorf("expected %s, got %s", expectedUrl, url)
	}
	initUrl = "foo/bar"
	url = CustomURL(initUrl)
	if url != expectedUrl {
		t.Errorf("expected %s, got %s", expectedUrl, url)
	}
}

func TestGerror(t *testing.T){
	errmsg := "foo bar"
	err := Errorf(errmsg)
	if err.Error() != errmsg {
		t.Errorf("expected %s to match %s", err.Error(), errmsg)
	}
	if err.Status() != http.StatusBadRequest {
		t.Errorf("err.Status() did not return expected default")
	}
	err.SetStatus(http.StatusNotFound)
	if err.Status() != http.StatusNotFound {
		t.Errorf("SetStatus did not set Status correctly")
	}
}

func TestFlatten(t *testing.T){
	rl := []string{ "recipe[foo]", "role[bar]" }
	normmap := make(map[string]interface{})
	normmap["foo"] = "bar"
	normmap["baz"] = "buz"
	normmap["slice"] = []string{ "fee", "fie", "fo" }
	normmap["map"] = make(map[string]interface{})
	normmap["map"].(map[string]interface{})["first"] = "mook"
	normmap["map"].(map[string]interface{})["second"] = "nork"
	obj := &testObj{ Name: "foo", UrlType: "bar", RunList: rl, Normal: normmap }
	flattened := FlattenObj(obj)
	if _, ok := flattened["name"]; !ok {
		t.Errorf("obj name was not flattened correctly")
	}
	if flattened["name"].(string) != obj.Name {
		t.Errorf("flattened name not correct, wanted %s got %v", obj.Name, flattened["name"])
	}
	if _, ok := flattened["foo"]; !ok {
		t.Errorf("Foo should have been set, but it wasn't")
	}
	if _, ok := flattened["normal"]; ok {
		t.Errorf("The 'normal' field was set, but shouldn't have been.")
	}
	if _, ok := flattened["map_first"]; !ok {
		t.Errorf("normal -> map -> second should have been flattened to map_second, but it wasn't")
	}
	if r, ok := flattened["recipe"]; ok {
		if r.([]string)[0] != "foo" {
			t.Errorf("recipe list should have included foo, but it had %v instead", r.([]string)[0])
		}
	} else {
		t.Errorf("No recipe list")
	}
	if r, ok := flattened["role"]; ok {
		if r.([]string)[0] != "bar" {
			t.Errorf("role list should have included bar, but it had %v instead", r.([]string)[0])
		}
	} else {
		t.Errorf("No role list")
	}
}

func TestMapify(t *testing.T){
	rl := []string{ "recipe[foo]", "role[bar]" }
	normmap := make(map[string]interface{})
	normmap["foo"] = "bar"
	normmap["baz"] = "buz"
	normmap["slice"] = []string{ "fee", "fie", "fo" }
	normmap["map"] = make(map[string]interface{})
	normmap["map"].(map[string]interface{})["first"] = "mook"
	normmap["map"].(map[string]interface{})["second"] = "nork"
	obj := &testObj{ Name: "foo", UrlType: "bar", RunList: rl, Normal: normmap }
	mapify := MapifyObject(obj)
	if mapify["name"].(string) != obj.Name {
		t.Errorf("Mapify names didn't match, expecte %s, got %v", obj.Name, mapify["name"])
	}
	if _, ok := mapify["normal"]; !ok {
		t.Errorf("There should have been a normal key for the map")
	}
	if _, ok := mapify["foo"]; ok {
		t.Errorf("There was a foo key in mapify, and there should not have been.")
	}
}

func TestIndexify(t *testing.T){
	rl := []string{ "recipe[foo]", "role[bar]" }
	normmap := make(map[string]interface{})
	normmap["foo"] = "bar"
	normmap["baz"] = "buz"
	normmap["slice"] = []string{ "fee", "fie", "fo" }
	normmap["map"] = make(map[string]interface{})
	normmap["map"].(map[string]interface{})["first"] = "mook"
	normmap["map"].(map[string]interface{})["second"] = "nork"
	obj := &testObj{ Name: "foo", UrlType: "bar", RunList: rl, Normal: normmap }
	flatten := FlattenObj(obj)
	indexificate := Indexify(flatten)
	if indexificate[0] != "baz:buz" {
		t.Errorf("The first element of the indexified object should have been 'baz:buz', but instead it was %s", indexificate[0])
	}
}

func TestValidateName(t *testing.T){
	goodName := "foo-bar"
	badName := "FAh!!"
	if !ValidateName(goodName){
		t.Errorf("%s should have passed name validation, but didn't", goodName)
	}
	if ValidateName(badName){
		t.Errorf("%s should not have passed name validation, but somehow did", badName)
	}
}
<|endoftext|>


<commit_before>// +build !windows

package util

import (
	"fmt"
	"os"
	"os/exec"
)

// IsPrivileged will return true if the current process is running under a
// privileged user, like root
func IsPrivileged() bool {

	// Execute a syscall to return the user id. If the user id is 0 then we're
	// running with root escalation.
	if os.Geteuid() == 0 {
		return true
	}

	return false
}

// PrivilegeExec runs a command as sudo
func PrivilegeExec(command string) error {
	//
	cmd := exec.Command("/bin/sh", "-c", fmt.Sprintf("sudo %v --internal", command))

	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	// run command
	return cmd.Run()
}
<commit_msg>add an acception for when sudo isnt present fixes #241<commit_after>// +build !windows

package util

import (
	"bufio"
	"fmt"
	"os"
	"os/exec"
)

// IsPrivileged will return true if the current process is running under a
// privileged user, like root
func IsPrivileged() bool {

	// Execute a syscall to return the user id. If the user id is 0 then we're
	// running with root escalation.
	if os.Geteuid() == 0 {
		return true
	}

	return false
}

// PrivilegeExec runs a command as sudo
func PrivilegeExec(command string) error {
	//
	if !sudoExists() {
		fmt.Println("We could not find the 'sudo' in your path")
		fmt.Println("please run the following command then press enter when its complete")
		fmt.Printf("sudo %v --internal", command)
		reader := bufio.NewReader(os.Stdin)
		reader.ReadString('\n')
		return nil
	}

	cmd := exec.Command("/bin/sh", "-c", fmt.Sprintf("sudo %v --internal", command))

	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	// run command
	return cmd.Run()
}

func sudoExists() bool {
	_, err := exec.LookPath("sudo")
	return err == nil
}<|endoftext|>


<commit_before>package repository

import (
	"database/sql"
	"fmt"

	"github.com/alexcarol/bicing-oracle/station-state/collection"
	"math"
	"sort"
)

type stationStateStorage struct{}

// StationStatePersister takes the data from a collection.StationStateCollection and saves it to a persistent storage
type StationStatePersister interface {
	PersistCollection(collection.StationStateCollection) error
}

// NewSQLStorage returns a StationStaterPersister that will persist data in the database/sql passed to it
func NewSQLStorage(db *sql.DB) StationStatePersister {
	db.Exec("CREATE TABLE IF NOT EXISTS `station` ( `id` int(11) NOT NULL, `latitude` float DEFAULT NULL, `longitude` float DEFAULT NULL, `street` varchar(255) DEFAULT NULL, `height` int(11) DEFAULT NULL, `street_number` varchar(255) DEFAULT NULL, `nearby_station_list` varchar(255) DEFAULT NULL, `last_updatetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;")
	db.Exec("CREATE TABLE IF NOT EXISTS `station_state` ( `id` int(11) NOT NULL DEFAULT '0', `updatetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `slots` int(11) DEFAULT NULL, `bikes` int(11) DEFAULT NULL, PRIMARY KEY (`id`,`updatetime`), CONSTRAINT `station_state_ibfk_1` FOREIGN KEY (`id`) REFERENCES `station` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8;")
	return sqlStorage{db}
}

func (storage stationStateStorage) PersistCollection(collection collection.StationStateCollection) error {
	return nil
}

type sqlStorage struct {
	database *sql.DB
}

func (storage sqlStorage) PersistCollection(collection collection.StationStateCollection) error {
	transaction, err := storage.database.Begin()
	if nil != err {
		return err
	}
	for _, stationState := range collection.StationStates {
		_, stationInsertErr := transaction.Exec("insert into station values (?, ?, ?, ?, ?, ?, ?, FROM_UNIXTIME(?)) ON DUPLICATE KEY UPDATE last_updatetime = FROM_UNIXTIME(?);", stationState.ID, stationState.Latitude, stationState.Longitude, stationState.Street, stationState.Height, stationState.StreetNumber, stationState.NearbyStationList, collection.Updatetime, collection.Updatetime)
		if stationInsertErr != nil {
			fmt.Println("Error executing statement " + stationInsertErr.Error())
			rollErr := transaction.Rollback()
			if rollErr != nil {
				fmt.Println("Error doing rollback" + err.Error())
				return rollErr
			}

			return err
		}
		_, err := transaction.Exec("insert into station_state values (?, FROM_UNIXTIME(?), ?, ?, ?);", stationState.ID, collection.Updatetime, stationState.FreeSlots, stationState.Bikes, stationState.Status)
		if err != nil {
			fmt.Println("Error executing statement " + err.Error())
			rollErr := transaction.Rollback()
			if rollErr != nil {
				fmt.Println("Error doing rollback" + err.Error())
				return rollErr
			}

			return err
		}
	}

	return transaction.Commit()
}

// StationProvider gives you a list of the nearby stations
type StationProvider interface {
	GetNearbyStations(lat, lon float64, minStations int) ([]Station, error)
}

// Station contains info about a station
type Station struct {
	ID           int
	Type         string
	Street       string
	StreetNumber string
	Height       int
	Lon          float64
	Lat          float64
	Distance     float64
}

// NewSQLStationProvider returns a StationStateProvider that uses mysql to retrieve the information
func NewSQLStationProvider(db *sql.DB) StationProvider {
	return sqlStorage{db}
}

func (storage sqlStorage) GetNearbyStations(lat float64, lon float64, minStations int) ([]Station, error) {
	rows, err := storage.database.Query("SELECT id, latitude, longitude, street, street_number, height  FROM station")
	if err != nil {
		return nil, err
	}

	var stationList = make([]Station, 0, 500) // TODO check if this can be adjusted

	defer rows.Close()
	rows.Columns()

	for rows.Next() {
		var currentStation Station

		err = rows.Scan(&currentStation.ID, &currentStation.Lat, &currentStation.Lon, &currentStation.Street, &currentStation.StreetNumber, &currentStation.Height)
		if err != nil {
			return nil, err
		}

		currentStation.Distance = distance(currentStation, lat, lon)
		stationList = append(stationList, currentStation)
	}

	err = rows.Err()
	if err != nil {
		return nil, err
	}

	sort.Stable(byDistance(stationList))

	return stationList[:minStations], nil
}

func distance(s Station, lat, lon float64) float64 {
	latDistance := math.Abs(s.Lat - lat)
	lonDistance := math.Abs(s.Lon - lon)

	return math.Sqrt(latDistance*latDistance + lonDistance*lonDistance)
}

type byDistance []Station

func (s byDistance) Len() int {
	return len(s)
}

func (s byDistance) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}

func (s byDistance) Less(i, j int) bool {
	return s[i].Distance < s[j].Distance
}
<commit_msg>Fixed panic in mysql transaction<commit_after>package repository

import (
	"database/sql"
	"fmt"

	"github.com/alexcarol/bicing-oracle/station-state/collection"
	"math"
	"sort"
)

type stationStateStorage struct{}

// StationStatePersister takes the data from a collection.StationStateCollection and saves it to a persistent storage
type StationStatePersister interface {
	PersistCollection(collection.StationStateCollection) error
}

// NewSQLStorage returns a StationStaterPersister that will persist data in the database/sql passed to it
func NewSQLStorage(db *sql.DB) StationStatePersister {
	db.Exec("CREATE TABLE IF NOT EXISTS `station` ( `id` int(11) NOT NULL, `latitude` float DEFAULT NULL, `longitude` float DEFAULT NULL, `street` varchar(255) DEFAULT NULL, `height` int(11) DEFAULT NULL, `street_number` varchar(255) DEFAULT NULL, `nearby_station_list` varchar(255) DEFAULT NULL, `last_updatetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;")
	db.Exec("CREATE TABLE IF NOT EXISTS `station_state` ( `id` int(11) NOT NULL DEFAULT '0', `updatetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `slots` int(11) DEFAULT NULL, `bikes` int(11) DEFAULT NULL, PRIMARY KEY (`id`,`updatetime`), CONSTRAINT `station_state_ibfk_1` FOREIGN KEY (`id`) REFERENCES `station` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8;")
	return sqlStorage{db}
}

func (storage stationStateStorage) PersistCollection(collection collection.StationStateCollection) error {
	return nil
}

type sqlStorage struct {
	database *sql.DB
}

func (storage sqlStorage) PersistCollection(collection collection.StationStateCollection) error {
	transaction, err := storage.database.Begin()
	if nil != err {
		return err
	}
	for _, stationState := range collection.StationStates {
		_, stationInsertErr := transaction.Exec("insert into station values (?, ?, ?, ?, ?, ?, ?, FROM_UNIXTIME(?)) ON DUPLICATE KEY UPDATE last_updatetime = FROM_UNIXTIME(?);", stationState.ID, stationState.Latitude, stationState.Longitude, stationState.Street, stationState.Height, stationState.StreetNumber, stationState.NearbyStationList, collection.Updatetime, collection.Updatetime)
		if stationInsertErr != nil {
			fmt.Println("Error executing statement " + stationInsertErr.Error())
			rollErr := transaction.Rollback()
			if rollErr != nil {
				fmt.Println("Error doing rollback" + rollErr.Error())

				return rollErr
			}

			return err
		}
		_, err := transaction.Exec("insert into station_state values (?, FROM_UNIXTIME(?), ?, ?, ?);", stationState.ID, collection.Updatetime, stationState.FreeSlots, stationState.Bikes, stationState.Status)
		if err != nil {
			fmt.Println("Error executing statement " + err.Error())
			rollErr := transaction.Rollback()
			if rollErr != nil {
				fmt.Println("Error doing rollback" + rollErr.Error())

				return rollErr
			}

			return err
		}
	}

	return transaction.Commit()
}

// StationProvider gives you a list of the nearby stations
type StationProvider interface {
	GetNearbyStations(lat, lon float64, minStations int) ([]Station, error)
}

// Station contains info about a station
type Station struct {
	ID           int
	Type         string
	Street       string
	StreetNumber string
	Height       int
	Lon          float64
	Lat          float64
	Distance     float64
}

// NewSQLStationProvider returns a StationStateProvider that uses mysql to retrieve the information
func NewSQLStationProvider(db *sql.DB) StationProvider {
	return sqlStorage{db}
}

func (storage sqlStorage) GetNearbyStations(lat float64, lon float64, minStations int) ([]Station, error) {
	rows, err := storage.database.Query("SELECT id, latitude, longitude, street, street_number, height  FROM station")
	if err != nil {
		return nil, err
	}

	var stationList = make([]Station, 0, 500) // TODO check if this can be adjusted

	defer rows.Close()
	rows.Columns()

	for rows.Next() {
		var currentStation Station

		err = rows.Scan(&currentStation.ID, &currentStation.Lat, &currentStation.Lon, &currentStation.Street, &currentStation.StreetNumber, &currentStation.Height)
		if err != nil {
			return nil, err
		}

		currentStation.Distance = distance(currentStation, lat, lon)
		stationList = append(stationList, currentStation)
	}

	err = rows.Err()
	if err != nil {
		return nil, err
	}

	sort.Stable(byDistance(stationList))

	return stationList[:minStations], nil
}

func distance(s Station, lat, lon float64) float64 {
	latDistance := math.Abs(s.Lat - lat)
	lonDistance := math.Abs(s.Lon - lon)

	return math.Sqrt(latDistance*latDistance + lonDistance*lonDistance)
}

type byDistance []Station

func (s byDistance) Len() int {
	return len(s)
}

func (s byDistance) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}

func (s byDistance) Less(i, j int) bool {
	return s[i].Distance < s[j].Distance
}
<|endoftext|>


<commit_before>/*
Copyright 2021 The Kubernetes Authors All rights reserved.

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

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

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

package config

import (
	"bufio"
	"encoding/json"
	"os"
	"strings"
	"testing"

	"k8s.io/minikube/pkg/minikube/out"
)

func TestAddonsList(t *testing.T) {
	t.Run("NonExistingClusterTable", func(t *testing.T) {
		r, w, err := os.Pipe()
		if err != nil {
			t.Fatalf("failed to create pipe: %v", err)
		}
		old := os.Stdout
		defer func() { os.Stdout = old }()
		os.Stdout = w
		printAddonsList(nil)
		if err := w.Close(); err != nil {
			t.Fatalf("failed to close pipe: %v", err)
		}
		buf := bufio.NewScanner(r)
		pipeCount := 0
		got := ""
		// Pull the first 3 lines from stdout
		for i := 0; i < 3; i++ {
			if !buf.Scan() {
				t.Fatalf("failed to read stdout")
			}
			pipeCount += strings.Count(buf.Text(), "|")
			got += buf.Text()
		}
		// The lines we pull should look something like
		// |-----------------------------|-----------------------|
		// |         ADDON NAME          |      MAINTAINER       |
		// |-----------------------------|-----------------------|
		// which has 9 pipes
		expected := 9
		if pipeCount != expected {
			t.Errorf("Expected header to have %d pipes; got = %d: %q", expected, pipeCount, got)
		}
	})

	t.Run("NonExistingClusterJSON", func(t *testing.T) {
		type addons struct {
			Ambassador *interface{} `json:"ambassador"`
		}

		b := make([]byte, 534)
		r, w, err := os.Pipe()
		if err != nil {
			t.Fatalf("failed to create pipe: %v", err)
		}
		old := os.Stdout
		defer func() {
			os.Stdout = old
			out.SetOutFile(os.Stdout)
		}()
		os.Stdout = w
		out.SetOutFile(os.Stdout)
		printAddonsJSON(nil)
		if err := w.Close(); err != nil {
			t.Fatalf("failed to close pipe: %v", err)
		}
		if _, err := r.Read(b); err != nil {
			t.Fatalf("failed to read bytes: %v", err)
		}
		got := addons{}
		if err := json.Unmarshal(b, &got); err != nil {
			t.Fatalf("failed to unmarshal output; output: %q; err: %v", string(b), err)
		}
		if got.Ambassador == nil {
			t.Errorf("expected `ambassador` field to not be nil, but was")
		}
	})
}
<commit_msg>fixing broken addons_list_test<commit_after>/*
Copyright 2021 The Kubernetes Authors All rights reserved.

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

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

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

package config

import (
	"bufio"
	"encoding/json"
	"os"
	"strings"
	"testing"

	"k8s.io/minikube/pkg/minikube/out"
)

func TestAddonsList(t *testing.T) {
	t.Run("NonExistingClusterTable", func(t *testing.T) {
		r, w, err := os.Pipe()
		if err != nil {
			t.Fatalf("failed to create pipe: %v", err)
		}
		old := os.Stdout
		defer func() { os.Stdout = old }()
		os.Stdout = w
		printAddonsList(nil)
		if err := w.Close(); err != nil {
			t.Fatalf("failed to close pipe: %v", err)
		}
		buf := bufio.NewScanner(r)
		pipeCount := 0
		got := ""
		// Pull the first 3 lines from stdout
		for i := 0; i < 3; i++ {
			if !buf.Scan() {
				t.Fatalf("failed to read stdout")
			}
			pipeCount += strings.Count(buf.Text(), "|")
			got += buf.Text()
		}
		// The lines we pull should look something like
		// |-----------------------------|-----------------------|
		// |         ADDON NAME          |      MAINTAINER       |
		// |-----------------------------|-----------------------|
		// which has 9 pipes
		expected := 9
		if pipeCount != expected {
			t.Errorf("Expected header to have %d pipes; got = %d: %q", expected, pipeCount, got)
		}
	})

	t.Run("NonExistingClusterJSON", func(t *testing.T) {
		type addons struct {
			Ambassador *interface{} `json:"ambassador"`
		}

		b := make([]byte, 544)
		r, w, err := os.Pipe()
		if err != nil {
			t.Fatalf("failed to create pipe: %v", err)
		}
		old := os.Stdout
		defer func() {
			os.Stdout = old
			out.SetOutFile(os.Stdout)
		}()
		os.Stdout = w
		out.SetOutFile(os.Stdout)
		printAddonsJSON(nil)
		if err := w.Close(); err != nil {
			t.Fatalf("failed to close pipe: %v", err)
		}
		if _, err := r.Read(b); err != nil {
			t.Fatalf("failed to read bytes: %v", err)
		}
		got := addons{}
		if err := json.Unmarshal(b, &got); err != nil {
			t.Fatalf("failed to unmarshal output; output: %q; err: %v", string(b), err)
		}
		if got.Ambassador == nil {
			t.Errorf("expected `ambassador` field to not be nil, but was")
		}
	})
}
<|endoftext|>