<commit_before>// Package web Cozy Stack API.
//
// Cozy is a personal platform as a service with a focus on data.
package web

import (
	"context"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path"
	"time"

	"github.com/cozy/cozy-stack/pkg/apps"
	"github.com/cozy/cozy-stack/pkg/apps/appfs"
	"github.com/cozy/cozy-stack/pkg/config"
	"github.com/cozy/cozy-stack/pkg/consts"
	"github.com/cozy/cozy-stack/pkg/i18n"
	"github.com/cozy/cozy-stack/pkg/permissions"
	"github.com/cozy/cozy-stack/pkg/utils"
	webapps "github.com/cozy/cozy-stack/web/apps"
	"github.com/cozy/cozy-stack/web/middlewares"

	"github.com/cozy/echo"
	"github.com/cozy/echo/middleware"

	"github.com/cozy/afero"
	statikFS "github.com/cozy/cozy-stack/pkg/statik/fs"
)

// ReadHeaderTimeout is the amount of time allowed to read request headers for
// all servers. This is activated for all handlers from all http servers
// created by the stack.
var ReadHeaderTimeout = 15 * time.Second

// LoadSupportedLocales reads the po files packed in go or from the assets directory
// and loads them for translations
func LoadSupportedLocales() error {
	// By default, use the po files packed in the binary
	// but use assets from the disk is assets option is filled in config
	assetsPath := config.GetConfig().Assets
	if assetsPath != "" {
		for _, locale := range consts.SupportedLocales {
			pofile := path.Join(assetsPath, "locales", locale+".po")
			po, err := ioutil.ReadFile(pofile)
			if err != nil {
				return fmt.Errorf("Can't load the po file for %s", locale)
			}
			i18n.LoadLocale(locale, po)
		}
		return nil
	}

	for _, locale := range consts.SupportedLocales {
		f, err := statikFS.Open("/locales/" + locale + ".po")
		if err != nil {
			return fmt.Errorf("Can't load the po file for %s", locale)
		}
		po, err := ioutil.ReadAll(f)
		if err != nil {
			return err
		}
		i18n.LoadLocale(locale, po)
	}
	return nil
}

// ListenAndServe creates and setups all the necessary http endpoints and start
// them.
func ListenAndServe() (*Servers, error) {
	return listenAndServe(webapps.Serve)
}

// ListenAndServeWithAppDir creates and setup all the necessary http endpoints
// and serve the specified application on a app subdomain.
//
// In order to serve the application, the specified directory should provide
// a manifest.webapp file that will be used to parameterize the application
// permissions.
func ListenAndServeWithAppDir(appsdir map[string]string) (*Servers, error) {
	for slug, dir := range appsdir {
		dir = utils.AbsPath(dir)
		appsdir[slug] = dir
		exists, err := utils.DirExists(dir)
		if err != nil {
			return nil, err
		}
		if !exists {
			return nil, fmt.Errorf("Directory %s does not exist", dir)
		}
		if err = checkExists(path.Join(dir, apps.WebappManifestName)); err != nil {
			return nil, err
		}
		if err = checkExists(path.Join(dir, "index.html")); err != nil {
			return nil, err
		}
	}
	return listenAndServe(func(c echo.Context) error {
		slug := c.Get("slug").(string)
		dir, ok := appsdir[slug]
		if !ok {
			return webapps.Serve(c)
		}
		method := c.Request().Method
		if method != "GET" && method != "HEAD" {
			return echo.NewHTTPError(http.StatusMethodNotAllowed, "Method not allowed")
		}
		fs := afero.NewBasePathFs(afero.NewOsFs(), dir)
		manFile, err := fs.Open(apps.WebappManifestName)
		if err != nil {
			if os.IsNotExist(err) {
				return fmt.Errorf("Could not find the %s file in your application directory %s",
					apps.WebappManifestName, dir)
			}
			return err
		}
		var app apps.Manifest = &apps.WebappManifest{}
		app, err = app.ReadManifest(manFile, slug, "file://localhost"+dir)
		if err != nil {
			return fmt.Errorf("Could not parse the %s file: %s",
				apps.WebappManifestName, err.Error())
		}
		webapp := app.(*apps.WebappManifest)
		i := middlewares.GetInstance(c)
		f := appfs.NewAferoFileServer(fs, func(_, _, _, file string) string {
			return path.Join("/", file)
		})
		// Save permissions in couchdb before loading an index page
		if _, file := webapp.FindRoute(path.Clean(c.Request().URL.Path)); file == "" {
			if webapp.Permissions() != nil {
				if err := permissions.ForceWebapp(i, webapp.Slug(), webapp.Permissions()); err != nil {
					return err
				}
			}
		}
		return webapps.ServeAppFile(c, i, f, webapp)
	})
}

func checkExists(filepath string) error {
	exists, err := utils.FileExists(filepath)
	if err != nil {
		return err
	}
	if !exists {
		return fmt.Errorf("Directory %s should contain a %s file",
			path.Dir(filepath), path.Base(filepath))
	}
	return nil
}

func listenAndServe(appsHandler echo.HandlerFunc) (*Servers, error) {
	e := echo.New()
	e.HideBanner = true
	e.HidePort = true

	major, err := CreateSubdomainProxy(e, appsHandler)
	if err != nil {
		return nil, err
	}
	if err = LoadSupportedLocales(); err != nil {
		return nil, err
	}

	if config.IsDevRelease() {
		major.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
			Format: "time=${time_rfc3339}\tstatus=${status}\tmethod=${method}\thost=${host}\turi=${uri}\tbytes_out=${bytes_out}\n",
		}))
	}

	admin := echo.New()
	admin.HideBanner = true
	admin.HidePort = true

	if err = SetupAdminRoutes(admin); err != nil {
		return nil, err
	}

	return &Servers{
		major: major,
		admin: admin,
	}, nil
}

// Servers contains the started HTTP servers and implement the Shutdowner
// interface.
type Servers struct {
	major *echo.Echo
	admin *echo.Echo
	errs  chan error
}

// Start starts the servers.
func (e *Servers) Start() {
	e.errs = make(chan error)

	go e.start(e.major, "major", &http.Server{
		Addr:              config.ServerAddr(),
		ReadHeaderTimeout: ReadHeaderTimeout,
	})

	go e.start(e.admin, "admin", &http.Server{
		Addr:              config.AdminServerAddr(),
		ReadHeaderTimeout: ReadHeaderTimeout,
	})
}

func (e *Servers) start(s *echo.Echo, name string, server *http.Server) {
	fmt.Printf("  http server %s started on %q\n", name, server.Addr)
	e.errs <- s.StartServer(server)
}

// Wait for servers to stop or fall in error.
func (e *Servers) Wait() <-chan error {
	return e.errs
}

// Shutdown gracefully stops the servers.
func (e *Servers) Shutdown(ctx context.Context) error {
	g := utils.NewGroupShutdown(e.admin, e.major)
	fmt.Print("  shutting down servers...")
	if err := g.Shutdown(ctx); err != nil {
		fmt.Println("failed: ", err.Error())
		return err
	}
	fmt.Println("ok.")
	return nil
}
<commit_msg>Warn on empty --addir instead of fail (#1805)<commit_after>// Package web Cozy Stack API.
//
// Cozy is a personal platform as a service with a focus on data.
package web

import (
	"context"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path"
	"time"

	"github.com/cozy/cozy-stack/pkg/apps"
	"github.com/cozy/cozy-stack/pkg/apps/appfs"
	"github.com/cozy/cozy-stack/pkg/config"
	"github.com/cozy/cozy-stack/pkg/consts"
	"github.com/cozy/cozy-stack/pkg/i18n"
	"github.com/cozy/cozy-stack/pkg/logger"
	"github.com/cozy/cozy-stack/pkg/permissions"
	"github.com/cozy/cozy-stack/pkg/utils"
	webapps "github.com/cozy/cozy-stack/web/apps"
	"github.com/cozy/cozy-stack/web/middlewares"

	"github.com/cozy/echo"
	"github.com/cozy/echo/middleware"

	"github.com/cozy/afero"
	statikFS "github.com/cozy/cozy-stack/pkg/statik/fs"
)

// ReadHeaderTimeout is the amount of time allowed to read request headers for
// all servers. This is activated for all handlers from all http servers
// created by the stack.
var ReadHeaderTimeout = 15 * time.Second

// LoadSupportedLocales reads the po files packed in go or from the assets directory
// and loads them for translations
func LoadSupportedLocales() error {
	// By default, use the po files packed in the binary
	// but use assets from the disk is assets option is filled in config
	assetsPath := config.GetConfig().Assets
	if assetsPath != "" {
		for _, locale := range consts.SupportedLocales {
			pofile := path.Join(assetsPath, "locales", locale+".po")
			po, err := ioutil.ReadFile(pofile)
			if err != nil {
				return fmt.Errorf("Can't load the po file for %s", locale)
			}
			i18n.LoadLocale(locale, po)
		}
		return nil
	}

	for _, locale := range consts.SupportedLocales {
		f, err := statikFS.Open("/locales/" + locale + ".po")
		if err != nil {
			return fmt.Errorf("Can't load the po file for %s", locale)
		}
		po, err := ioutil.ReadAll(f)
		if err != nil {
			return err
		}
		i18n.LoadLocale(locale, po)
	}
	return nil
}

// ListenAndServe creates and setups all the necessary http endpoints and start
// them.
func ListenAndServe() (*Servers, error) {
	return listenAndServe(webapps.Serve)
}

// ListenAndServeWithAppDir creates and setup all the necessary http endpoints
// and serve the specified application on a app subdomain.
//
// In order to serve the application, the specified directory should provide
// a manifest.webapp file that will be used to parameterize the application
// permissions.
func ListenAndServeWithAppDir(appsdir map[string]string) (*Servers, error) {
	for slug, dir := range appsdir {
		dir = utils.AbsPath(dir)
		appsdir[slug] = dir
		exists, err := utils.DirExists(dir)
		if err != nil {
			return nil, err
		}
		if !exists {
			return nil, fmt.Errorf("Directory %s does not exist", dir)
		}
		if err = checkExists(path.Join(dir, apps.WebappManifestName)); err != nil {
			logger.WithNamespace("dev").Warnf("The app manifest is missing: %s", err)
		}
		if err = checkExists(path.Join(dir, "index.html")); err != nil {
			logger.WithNamespace("dev").Warnf("The index.html is missing: %s", err)
		}
	}
	return listenAndServe(func(c echo.Context) error {
		slug := c.Get("slug").(string)
		dir, ok := appsdir[slug]
		if !ok {
			return webapps.Serve(c)
		}
		method := c.Request().Method
		if method != "GET" && method != "HEAD" {
			return echo.NewHTTPError(http.StatusMethodNotAllowed, "Method not allowed")
		}
		fs := afero.NewBasePathFs(afero.NewOsFs(), dir)
		manFile, err := fs.Open(apps.WebappManifestName)
		if err != nil {
			if os.IsNotExist(err) {
				return fmt.Errorf("Could not find the %s file in your application directory %s",
					apps.WebappManifestName, dir)
			}
			return err
		}
		var app apps.Manifest = &apps.WebappManifest{}
		app, err = app.ReadManifest(manFile, slug, "file://localhost"+dir)
		if err != nil {
			return fmt.Errorf("Could not parse the %s file: %s",
				apps.WebappManifestName, err.Error())
		}
		webapp := app.(*apps.WebappManifest)
		i := middlewares.GetInstance(c)
		f := appfs.NewAferoFileServer(fs, func(_, _, _, file string) string {
			return path.Join("/", file)
		})
		// Save permissions in couchdb before loading an index page
		if _, file := webapp.FindRoute(path.Clean(c.Request().URL.Path)); file == "" {
			if webapp.Permissions() != nil {
				if err := permissions.ForceWebapp(i, webapp.Slug(), webapp.Permissions()); err != nil {
					return err
				}
			}
		}
		return webapps.ServeAppFile(c, i, f, webapp)
	})
}

func checkExists(filepath string) error {
	exists, err := utils.FileExists(filepath)
	if err != nil {
		return err
	}
	if !exists {
		return fmt.Errorf("Directory %s should contain a %s file",
			path.Dir(filepath), path.Base(filepath))
	}
	return nil
}

func listenAndServe(appsHandler echo.HandlerFunc) (*Servers, error) {
	e := echo.New()
	e.HideBanner = true
	e.HidePort = true

	major, err := CreateSubdomainProxy(e, appsHandler)
	if err != nil {
		return nil, err
	}
	if err = LoadSupportedLocales(); err != nil {
		return nil, err
	}

	if config.IsDevRelease() {
		major.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
			Format: "time=${time_rfc3339}\tstatus=${status}\tmethod=${method}\thost=${host}\turi=${uri}\tbytes_out=${bytes_out}\n",
		}))
	}

	admin := echo.New()
	admin.HideBanner = true
	admin.HidePort = true

	if err = SetupAdminRoutes(admin); err != nil {
		return nil, err
	}

	return &Servers{
		major: major,
		admin: admin,
	}, nil
}

// Servers contains the started HTTP servers and implement the Shutdowner
// interface.
type Servers struct {
	major *echo.Echo
	admin *echo.Echo
	errs  chan error
}

// Start starts the servers.
func (e *Servers) Start() {
	e.errs = make(chan error)

	go e.start(e.major, "major", &http.Server{
		Addr:              config.ServerAddr(),
		ReadHeaderTimeout: ReadHeaderTimeout,
	})

	go e.start(e.admin, "admin", &http.Server{
		Addr:              config.AdminServerAddr(),
		ReadHeaderTimeout: ReadHeaderTimeout,
	})
}

func (e *Servers) start(s *echo.Echo, name string, server *http.Server) {
	fmt.Printf("  http server %s started on %q\n", name, server.Addr)
	e.errs <- s.StartServer(server)
}

// Wait for servers to stop or fall in error.
func (e *Servers) Wait() <-chan error {
	return e.errs
}

// Shutdown gracefully stops the servers.
func (e *Servers) Shutdown(ctx context.Context) error {
	g := utils.NewGroupShutdown(e.admin, e.major)
	fmt.Print("  shutting down servers...")
	if err := g.Shutdown(ctx); err != nil {
		fmt.Println("failed: ", err.Error())
		return err
	}
	fmt.Println("ok.")
	return nil
}
<|endoftext|>


<commit_before>package controllers

import (
	"bytes"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/assert"
	"gopkg.in/DATA-DOG/go-sqlmock.v1"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/eirka/eirka-libs/audit"
	"github.com/eirka/eirka-libs/db"
	"github.com/eirka/eirka-libs/redis"
	"github.com/eirka/eirka-libs/user"
)

func init() {
	user.Secret = "secret"

	// Set up fake Redis connection
	redis.NewRedisMock()
}

func performRequest(r http.Handler, method, path string) *httptest.ResponseRecorder {
	req, _ := http.NewRequest(method, path, nil)
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)
	return w
}

func performJsonRequest(r http.Handler, method, path string, body []byte) *httptest.ResponseRecorder {
	req, _ := http.NewRequest(method, path, bytes.NewBuffer(body))
	req.Header.Set("Content-Type", "application/json")
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)
	return w
}

func errorMessage(err error) string {
	return fmt.Sprintf(`{"error_message":"%s"}`, err)
}

func successMessage(message string) string {
	return fmt.Sprintf(`{"success_message":"%s"}`, message)
}

func TestAddTagController(t *testing.T) {

	var err error

	gin.SetMode(gin.ReleaseMode)

	router := gin.New()

	router.Use(user.Auth(false))

	router.POST("/tag/add", AddTagController)

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	statusrows := sqlmock.NewRows([]string{"count"}).AddRow(1)
	mock.ExpectQuery(`SELECT count\(1\) FROM images`).WillReturnRows(statusrows)

	duperows := sqlmock.NewRows([]string{"count"}).AddRow(0)
	mock.ExpectQuery(`select count\(1\) from tagmap`).WillReturnRows(duperows)

	mock.ExpectExec("INSERT into tagmap").
		WithArgs(1, 1).
		WillReturnResult(sqlmock.NewResult(1, 1))

	redis.RedisCache.Mock.Command("DEL", "tags:1", "tag:1:1", "image:1")

	first := performRequest(router, "POST", "/tag/add")

	assert.Equal(t, first.Code, 400, "HTTP request code should match")

	request1 := []byte(`{"ib": 1, "tag": 1, "image": 1}`)

	second := performJsonRequest(router, "POST", "/tag/add", request1)

	assert.Equal(t, second.Code, 200, "HTTP request code should match")
	assert.JSONEq(t, second.Body.String(), successMessage(audit.AuditAddTag), "HTTP response should match")

}
<commit_msg>add redis mock<commit_after>package controllers

import (
	"bytes"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/assert"
	"gopkg.in/DATA-DOG/go-sqlmock.v1"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/eirka/eirka-libs/audit"
	"github.com/eirka/eirka-libs/db"
	e "github.com/eirka/eirka-libs/errors"
	"github.com/eirka/eirka-libs/redis"
	"github.com/eirka/eirka-libs/user"
)

func init() {
	user.Secret = "secret"

	// Set up fake Redis connection
	redis.NewRedisMock()
}

func performRequest(r http.Handler, method, path string) *httptest.ResponseRecorder {
	req, _ := http.NewRequest(method, path, nil)
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)
	return w
}

func performJsonRequest(r http.Handler, method, path string, body []byte) *httptest.ResponseRecorder {
	req, _ := http.NewRequest(method, path, bytes.NewBuffer(body))
	req.Header.Set("Content-Type", "application/json")
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)
	return w
}

func errorMessage(err error) string {
	return fmt.Sprintf(`{"error_message":"%s"}`, err)
}

func successMessage(message string) string {
	return fmt.Sprintf(`{"success_message":"%s"}`, message)
}

func TestAddTagController(t *testing.T) {

	var err error

	gin.SetMode(gin.ReleaseMode)

	router := gin.New()

	router.Use(user.Auth(false))

	router.POST("/tag/add", AddTagController)

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	statusrows := sqlmock.NewRows([]string{"count"}).AddRow(1)
	mock.ExpectQuery(`SELECT count\(1\) FROM images`).WillReturnRows(statusrows)

	duperows := sqlmock.NewRows([]string{"count"}).AddRow(0)
	mock.ExpectQuery(`select count\(1\) from tagmap`).WillReturnRows(duperows)

	mock.ExpectExec("INSERT into tagmap").
		WithArgs(1, 1).
		WillReturnResult(sqlmock.NewResult(1, 1))

	redis.RedisCache.Mock.Command("DEL", "tags:1", "tag:1:1", "image:1")

	request1 := []byte(`{"ib": 1, "tag": 1, "image": 1}`)

	second := performJsonRequest(router, "POST", "/tag/add", request1)

	assert.Equal(t, second.Code, 200, "HTTP request code should match")
	assert.JSONEq(t, second.Body.String(), successMessage(audit.AuditAddTag), "HTTP response should match")

}

func TestAddTagControllerNoInput(t *testing.T) {

	var err error

	gin.SetMode(gin.ReleaseMode)

	router := gin.New()

	router.Use(user.Auth(false))

	router.POST("/tag/add", AddTagController)

	first := performRequest(router, "POST", "/tag/add")

	assert.Equal(t, first.Code, 400, "HTTP request code should match")
	assert.JSONEq(t, second.Body.String(), errorMessage(e.ErrInvalidParam), "HTTP response should match")

}
<|endoftext|>


<commit_before>package marionette_client

import (
	"encoding/json"
)

type ElementRect struct {
	X      float32
	Y      float32
	Width  float32
	Height float32
}

type WebElement struct {
	id string //`json:"element-6066-11e4-a52e-4f735466cecf"`
	c  *Client
}

func (e *WebElement) Id() string {
	return e.id
}

func (e *WebElement) FindElement(by By, value string) (*WebElement, error) {
	return findElement(e.c, by, value, &e.id)
}

func (e *WebElement) FindElements(by By, value string) ([]*WebElement, error) {
	return findElements(e.c, by, value, &e.id)
}

func (e *WebElement) Enabled() bool {
	return isElementEnabled(e.c, e.id)
}

func (e *WebElement) Selected() bool {
	return isElementSelected(e.c, e.id)
}

func (e *WebElement) Displayed() bool {
	return isElementDisplayed(e.c, e.id)
}

func (e *WebElement) TagName() string {
	return getElementTagName(e.c, e.id)
}

func (e *WebElement) Text() string {
	return getElementText(e.c, e.id)
}

func (e *WebElement) Attribute(name string) string {
	return getElementAttribute(e.c, e.id, name)
}

func (e *WebElement) CssValue(property string) string {
	return getElementCssPropertyValue(e.c, e.id, property)
}

func (e *WebElement) Rect() (*ElementRect, error) {
	return getElementRect(e.c, e.id)
}

func (e *WebElement) Click() {
	clickElement(e.c, e.id)
}

func (e *WebElement) SendKeys(keys string) {
	sendKeysToElement(e.c, e.id, keys)
}

func (e *WebElement) Clear() {
	clearElement(e.c, e.id)
}

func (e *WebElement) Location() (x float32, y float32, err error) {
	r, err := getElementRect(e.c, e.id)
	if err != nil {
		return x, y, err
	}

	return r.X, r.Y, nil
}

func (e *WebElement) Size() (w float32, h float32, err error) {
	r, err := getElementRect(e.c, e.id)
	if err != nil {
		return w, h, err
	}

	return r.Width, r.Height, nil
}

func (e *WebElement) UnmarshalJSON(data []byte) error {
	var d map[string]map[string]string
	err := json.Unmarshal([]byte(data), &d)
	if err != nil {
		return err
	}

	e.id = d["value"][WEBDRIVER_ELEMENT_KEY]

	return nil
}
<commit_msg>added Point and Size structs, refactor ElementRect struct.<commit_after>package marionette_client

import (
	"encoding/json"
)

type Point struct {
	X      float32
	Y      float32
}

type Size struct {
	Width  float32
	Height float32
}

type ElementRect struct {
	Point
	Size
}

type WebElement struct {
	id string //`json:"element-6066-11e4-a52e-4f735466cecf"`
	c  *Client
}

func (e *WebElement) Id() string {
	return e.id
}

func (e *WebElement) FindElement(by By, value string) (*WebElement, error) {
	return findElement(e.c, by, value, &e.id)
}

func (e *WebElement) FindElements(by By, value string) ([]*WebElement, error) {
	return findElements(e.c, by, value, &e.id)
}

func (e *WebElement) Enabled() bool {
	return isElementEnabled(e.c, e.id)
}

func (e *WebElement) Selected() bool {
	return isElementSelected(e.c, e.id)
}

func (e *WebElement) Displayed() bool {
	return isElementDisplayed(e.c, e.id)
}

func (e *WebElement) TagName() string {
	return getElementTagName(e.c, e.id)
}

func (e *WebElement) Text() string {
	return getElementText(e.c, e.id)
}

func (e *WebElement) Attribute(name string) string {
	return getElementAttribute(e.c, e.id, name)
}

func (e *WebElement) CssValue(property string) string {
	return getElementCssPropertyValue(e.c, e.id, property)
}

func (e *WebElement) Rect() (*ElementRect, error) {
	return getElementRect(e.c, e.id)
}

func (e *WebElement) Click() {
	clickElement(e.c, e.id)
}

func (e *WebElement) SendKeys(keys string) {
	sendKeysToElement(e.c, e.id, keys)
}

func (e *WebElement) Clear() {
	clearElement(e.c, e.id)
}

func (e *WebElement) Location() (x float32, y float32, err error) {
	r, err := getElementRect(e.c, e.id)
	if err != nil {
		return x, y, err
	}

	return r.X, r.Y, nil
}

func (e *WebElement) Size() (w float32, h float32, err error) {
	r, err := getElementRect(e.c, e.id)
	if err != nil {
		return w, h, err
	}

	return r.Width, r.Height, nil
}

func (e *WebElement) UnmarshalJSON(data []byte) error {
	var d map[string]map[string]string
	err := json.Unmarshal([]byte(data), &d)
	if err != nil {
		return err
	}

	e.id = d["value"][WEBDRIVER_ELEMENT_KEY]

	return nil
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The xridge kubestone contributors.

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 s3bench

import (
	perfv1alpha1 "github.com/xridge/kubestone/api/v1alpha1"
	"github.com/xridge/kubestone/pkg/k8s"
	batchv1 "k8s.io/api/batch/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"strconv"
)

// NewJob creates a s3bench benchmark job
func NewJob(cr *perfv1alpha1.S3Bench) *batchv1.Job {
	objectMeta := metav1.ObjectMeta{
		Name:      cr.Name,
		Namespace: cr.Namespace,
	}

	s3benchCmdLineArgs := []string{}
	s3benchCmdLineArgs = append(s3benchCmdLineArgs, cr.Spec.Mode)
	s3benchCmdLineArgs = append(s3benchCmdLineArgs, ProcessS3BenchArgs(&cr.Spec)...)

	image := cr.Spec.Image
	if (image == perfv1alpha1.ImageSpec{}) {
		image = perfv1alpha1.ImageSpec{
			Name:       "minio/warp:v0.3.5",
			PullPolicy: "IfNotPresent",
		}
	}

	job := k8s.NewPerfJob(objectMeta, "s3bench", image, cr.Spec.PodConfig)
	job.Spec.Template.Spec.Containers[0].Args = s3benchCmdLineArgs
	return job
}

func ProcessS3BenchArgs(spec *perfv1alpha1.S3BenchSpec) []string {
	var cmdArgs []string
	cmdArgs = append(cmdArgs, "--host", spec.Host)

	if (spec.S3BenchOptions != perfv1alpha1.S3BenchOptions{}) {
		opts := spec.S3BenchOptions

		checkAndAppendBool(&cmdArgs, opts.NoColor, "--no-color")
		checkAndAppendBool(&cmdArgs, opts.Debug, "--debug")
		checkAndAppendBool(&cmdArgs, opts.Debug, "--insecure")
		checkAndAppendString(&cmdArgs, opts.AccessKey, "--access-key")
		checkAndAppendString(&cmdArgs, opts.SecretKey, "--secret-key")
		checkAndAppendBool(&cmdArgs, opts.Tls, "--tls")
		checkAndAppendString(&cmdArgs, opts.Region, "--region")
		checkAndAppendBool(&cmdArgs, opts.Encrypt, "--encrypt")
		checkAndAppendString(&cmdArgs, opts.Bucket, "--bucket")
		checkAndAppendString(&cmdArgs, opts.HostSelect, "--host-select")
		checkAndAppendInt(&cmdArgs, opts.Concurrent, "--concurrent")
		checkAndAppendBool(&cmdArgs, opts.NoPrefix, "--noprefix")
		checkAndAppendString(&cmdArgs, opts.BenchOutput, "--benchdata")
		checkAndAppendString(&cmdArgs, opts.Duration, "--duration")
		checkAndAppendBool(&cmdArgs, opts.NoClear, "--noclear")

		// TODO: Possibly set this to +1 min from create time or something. May be needed if use clients
		checkAndAppendString(&cmdArgs, opts.SyncStart, "--syncstart")
		checkAndAppendBool(&cmdArgs, opts.Requests, "--requests")
	}

	if (spec.S3ObjectOptions != perfv1alpha1.S3ObjectOptions{}) {
		opts := spec.S3ObjectOptions
		checkAndAppendInt(&cmdArgs, opts.Count, "--objects")
		checkAndAppendString(&cmdArgs, opts.Size, "--obj.size")
		checkAndAppendString(&cmdArgs, opts.Generator, "--obj.generator")
		checkAndAppendBool(&cmdArgs, opts.RandomSize, "--obj.randsize")

	}

	if (spec.S3AutoTermOptions != perfv1alpha1.S3AutoTermOptions{}) {
		opts := spec.S3AutoTermOptions

		if opts.Enabled {
			checkAndAppendBool(&cmdArgs, opts.Enabled, "--autoterm")
			checkAndAppendString(&cmdArgs, opts.Duration, "--autoterm.dur")
			checkAndAppendString(&cmdArgs, opts.Percent, "--autoterm.pct")

		}
	}

	if (spec.S3AnalysisOptions != perfv1alpha1.S3AnalysisOptions{}) {
		opts := spec.S3AnalysisOptions

		checkAndAppendString(&cmdArgs, opts.Duration, "--analyze.dur")
		checkAndAppendString(&cmdArgs, opts.Output, "--analyze.out")
		checkAndAppendString(&cmdArgs, opts.OperationFilter, "--analyze.op")
		checkAndAppendBool(&cmdArgs, opts.PrintErrors, "--analyze.errors")
		checkAndAppendString(&cmdArgs, opts.HostFilter, "--analyze.host")
		checkAndAppendString(&cmdArgs, opts.Skip, "--analyze.skip")
		checkAndAppendBool(&cmdArgs, opts.HostDetails, "--analyze.hostdetails")
	}

	if spec.Mode == "mixed" {
		if (spec.MixedDistributionOptions != perfv1alpha1.MixedDistributionOptions{}) {
			checkAndAppendInt(&cmdArgs, spec.MixedDistributionOptions.GetDist, "--get-distrib")
			checkAndAppendInt(&cmdArgs, spec.MixedDistributionOptions.StatDist, "--stat-distrib")
			checkAndAppendInt(&cmdArgs, spec.MixedDistributionOptions.PutDist, "--put-distrib")
			checkAndAppendInt(&cmdArgs, spec.MixedDistributionOptions.DeleteDist, "--delete-distrib")
		}
	}

	return cmdArgs
}

func checkAndAppendInt(cmdArgs *[]string, dist int32, arg string) {
	if dist > 0 {
		*cmdArgs = append(*cmdArgs, arg, strconv.Itoa(int(dist)))
	}
}

func checkAndAppendBool(cmdArgs *[]string, dist bool, arg string) {
	if dist {
		*cmdArgs = append(*cmdArgs, arg)
	}
}

func checkAndAppendString(cmdArgs *[]string, dist string, arg string) {
	if dist != "" {
		*cmdArgs = append(*cmdArgs, arg, dist)
	}
}
<commit_msg>fix var declaration<commit_after>/*
Copyright 2019 The xridge kubestone contributors.

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 s3bench

import (
	perfv1alpha1 "github.com/xridge/kubestone/api/v1alpha1"
	"github.com/xridge/kubestone/pkg/k8s"
	batchv1 "k8s.io/api/batch/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"strconv"
)

// NewJob creates a s3bench benchmark job
func NewJob(cr *perfv1alpha1.S3Bench) *batchv1.Job {
	objectMeta := metav1.ObjectMeta{
		Name:      cr.Name,
		Namespace: cr.Namespace,
	}

	var s3benchCmdLineArgs []string
	s3benchCmdLineArgs = append(s3benchCmdLineArgs, cr.Spec.Mode)
	s3benchCmdLineArgs = append(s3benchCmdLineArgs, ProcessS3BenchArgs(&cr.Spec)...)

	image := cr.Spec.Image
	if (image == perfv1alpha1.ImageSpec{}) {
		image = perfv1alpha1.ImageSpec{
			Name:       "minio/warp:v0.3.5",
			PullPolicy: "IfNotPresent",
		}
	}

	job := k8s.NewPerfJob(objectMeta, "s3bench", image, cr.Spec.PodConfig)
	job.Spec.Template.Spec.Containers[0].Args = s3benchCmdLineArgs
	return job
}

func ProcessS3BenchArgs(spec *perfv1alpha1.S3BenchSpec) []string {
	var cmdArgs []string
	cmdArgs = append(cmdArgs, "--host", spec.Host)

	if (spec.S3BenchOptions != perfv1alpha1.S3BenchOptions{}) {
		opts := spec.S3BenchOptions

		checkAndAppendBool(&cmdArgs, opts.NoColor, "--no-color")
		checkAndAppendBool(&cmdArgs, opts.Debug, "--debug")
		checkAndAppendBool(&cmdArgs, opts.Debug, "--insecure")
		checkAndAppendString(&cmdArgs, opts.AccessKey, "--access-key")
		checkAndAppendString(&cmdArgs, opts.SecretKey, "--secret-key")
		checkAndAppendBool(&cmdArgs, opts.Tls, "--tls")
		checkAndAppendString(&cmdArgs, opts.Region, "--region")
		checkAndAppendBool(&cmdArgs, opts.Encrypt, "--encrypt")
		checkAndAppendString(&cmdArgs, opts.Bucket, "--bucket")
		checkAndAppendString(&cmdArgs, opts.HostSelect, "--host-select")
		checkAndAppendInt(&cmdArgs, opts.Concurrent, "--concurrent")
		checkAndAppendBool(&cmdArgs, opts.NoPrefix, "--noprefix")
		checkAndAppendString(&cmdArgs, opts.BenchOutput, "--benchdata")
		checkAndAppendString(&cmdArgs, opts.Duration, "--duration")
		checkAndAppendBool(&cmdArgs, opts.NoClear, "--noclear")

		// TODO: Possibly set this to +1 min from create time or something. May be needed if use clients
		checkAndAppendString(&cmdArgs, opts.SyncStart, "--syncstart")
		checkAndAppendBool(&cmdArgs, opts.Requests, "--requests")
	}

	if (spec.S3ObjectOptions != perfv1alpha1.S3ObjectOptions{}) {
		opts := spec.S3ObjectOptions
		checkAndAppendInt(&cmdArgs, opts.Count, "--objects")
		checkAndAppendString(&cmdArgs, opts.Size, "--obj.size")
		checkAndAppendString(&cmdArgs, opts.Generator, "--obj.generator")
		checkAndAppendBool(&cmdArgs, opts.RandomSize, "--obj.randsize")

	}

	if (spec.S3AutoTermOptions != perfv1alpha1.S3AutoTermOptions{}) {
		opts := spec.S3AutoTermOptions

		if opts.Enabled {
			checkAndAppendBool(&cmdArgs, opts.Enabled, "--autoterm")
			checkAndAppendString(&cmdArgs, opts.Duration, "--autoterm.dur")
			checkAndAppendString(&cmdArgs, opts.Percent, "--autoterm.pct")

		}
	}

	if (spec.S3AnalysisOptions != perfv1alpha1.S3AnalysisOptions{}) {
		opts := spec.S3AnalysisOptions

		checkAndAppendString(&cmdArgs, opts.Duration, "--analyze.dur")
		checkAndAppendString(&cmdArgs, opts.Output, "--analyze.out")
		checkAndAppendString(&cmdArgs, opts.OperationFilter, "--analyze.op")
		checkAndAppendBool(&cmdArgs, opts.PrintErrors, "--analyze.errors")
		checkAndAppendString(&cmdArgs, opts.HostFilter, "--analyze.host")
		checkAndAppendString(&cmdArgs, opts.Skip, "--analyze.skip")
		checkAndAppendBool(&cmdArgs, opts.HostDetails, "--analyze.hostdetails")
	}

	if spec.Mode == "mixed" {
		if (spec.MixedDistributionOptions != perfv1alpha1.MixedDistributionOptions{}) {
			checkAndAppendInt(&cmdArgs, spec.MixedDistributionOptions.GetDist, "--get-distrib")
			checkAndAppendInt(&cmdArgs, spec.MixedDistributionOptions.StatDist, "--stat-distrib")
			checkAndAppendInt(&cmdArgs, spec.MixedDistributionOptions.PutDist, "--put-distrib")
			checkAndAppendInt(&cmdArgs, spec.MixedDistributionOptions.DeleteDist, "--delete-distrib")
		}
	}

	return cmdArgs
}

func checkAndAppendInt(cmdArgs *[]string, dist int32, arg string) {
	if dist > 0 {
		*cmdArgs = append(*cmdArgs, arg, strconv.Itoa(int(dist)))
	}
}

func checkAndAppendBool(cmdArgs *[]string, dist bool, arg string) {
	if dist {
		*cmdArgs = append(*cmdArgs, arg)
	}
}

func checkAndAppendString(cmdArgs *[]string, dist string, arg string) {
	if dist != "" {
		*cmdArgs = append(*cmdArgs, arg, dist)
	}
}
<|endoftext|>


<commit_before>package controllers

import (
	"net/http"
	"testing"

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

func TestGetTables(t *testing.T) {
	Convey("Get tables without custom where clause", t, func() {
		r, err := http.NewRequest("GET", "/tables", nil)
		So(err, ShouldBeNil)
		validate(r, GetTables)
	})

	Convey("Get tables with custom where clause", t, func() {
		r, err := http.NewRequest("GET", "/tables?name=prest", nil)
		So(err, ShouldBeNil)
		validate(r, GetTables)
	})
}
<commit_msg>fix column name<commit_after>package controllers

import (
	"net/http"
	"testing"

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

func TestGetTables(t *testing.T) {
	Convey("Get tables without custom where clause", t, func() {
		r, err := http.NewRequest("GET", "/tables", nil)
		So(err, ShouldBeNil)
		validate(r, GetTables)
	})

	Convey("Get tables with custom where clause", t, func() {
		r, err := http.NewRequest("GET", "/tables?c.relname=prest", nil)
		So(err, ShouldBeNil)
		validate(r, GetTables)
	})
}
<|endoftext|>


<commit_before>package js

import (
	log "github.com/Sirupsen/logrus"
	"github.com/loadimpact/speedboat/stats"
	"github.com/robertkrimen/otto"
	"github.com/valyala/fasthttp"
	"time"
)

var (
	mRequests = stats.Stat{Name: "requests", Type: stats.HistogramType, Intent: stats.TimeIntent}
	mErrors   = stats.Stat{Name: "errors", Type: stats.CounterType}
)

type HTTPParams struct {
	Quiet   bool
	Headers map[string]string
}

type HTTPResponse struct {
	Status  int
	Headers map[string]string
	Body    string
}

func (res HTTPResponse) ToValue(vm *otto.Otto) (otto.Value, error) {
	obj, err := Make(vm, "HTTPResponse")
	if err != nil {
		return otto.UndefinedValue(), err
	}

	obj.Set("status", res.Status)
	obj.Set("headers", res.Headers)
	obj.Set("body", res.Body)

	return vm.ToValue(obj)
}

func (u *VU) HTTPRequest(method, url, body string, params HTTPParams) (HTTPResponse, error) {
	req := fasthttp.AcquireRequest()
	defer fasthttp.ReleaseRequest(req)

	req.Header.SetMethod(method)

	if method == "GET" || method == "HEAD" {
		req.SetRequestURI(putBodyInURL(url, body))
	} else if body != "" {
		req.SetRequestURI(url)
		req.SetBodyString(body)
	}

	resp := fasthttp.AcquireResponse()
	defer fasthttp.ReleaseResponse(resp)

	startTime := time.Now()
	err := u.Client.Do(req, resp)
	duration := time.Since(startTime)

	tags := stats.Tags{
		"url":    url,
		"method": method,
		"status": resp.StatusCode(),
	}
	u.Collector.Add(stats.Point{
		Stat:   &mRequests,
		Tags:   tags,
		Values: stats.Values{"duration": float64(duration)},
	})

	if err != nil {
		u.Collector.Add(stats.Point{
			Stat:   &mErrors,
			Tags:   tags,
			Values: stats.Value(1),
		})
		return HTTPResponse{}, err
	}

	headers := make(map[string]string)
	resp.Header.VisitAll(func(key []byte, value []byte) {
		headers[string(key)] = string(value)
	})

	return HTTPResponse{
		Status:  resp.StatusCode(),
		Headers: headers,
		Body:    string(resp.Body()),
	}, nil
}

func (u *VU) Sleep(t float64) {
	time.Sleep(time.Duration(t * float64(time.Second)))
}

func (u *VU) Log(level, msg string, fields map[string]interface{}) {
	e := u.Runner.logger.WithFields(log.Fields(fields))

	switch level {
	case "debug":
		e.Debug(msg)
	case "info":
		e.Info(msg)
	case "warn":
		e.Warn(msg)
	case "error":
		e.Error(msg)
	}
}
<commit_msg>[fix] Actually send headers along<commit_after>package js

import (
	log "github.com/Sirupsen/logrus"
	"github.com/loadimpact/speedboat/stats"
	"github.com/robertkrimen/otto"
	"github.com/valyala/fasthttp"
	"time"
)

var (
	mRequests = stats.Stat{Name: "requests", Type: stats.HistogramType, Intent: stats.TimeIntent}
	mErrors   = stats.Stat{Name: "errors", Type: stats.CounterType}
)

type HTTPParams struct {
	Quiet   bool
	Headers map[string]string
}

type HTTPResponse struct {
	Status  int
	Headers map[string]string
	Body    string
}

func (res HTTPResponse) ToValue(vm *otto.Otto) (otto.Value, error) {
	obj, err := Make(vm, "HTTPResponse")
	if err != nil {
		return otto.UndefinedValue(), err
	}

	obj.Set("status", res.Status)
	obj.Set("headers", res.Headers)
	obj.Set("body", res.Body)

	return vm.ToValue(obj)
}

func (u *VU) HTTPRequest(method, url, body string, params HTTPParams) (HTTPResponse, error) {
	req := fasthttp.AcquireRequest()
	defer fasthttp.ReleaseRequest(req)

	req.Header.SetMethod(method)

	if method == "GET" || method == "HEAD" {
		req.SetRequestURI(putBodyInURL(url, body))
	} else if body != "" {
		req.SetRequestURI(url)
		req.SetBodyString(body)
	}

	for key, value := range params.Headers {
		req.Header.Set(key, value)
	}

	resp := fasthttp.AcquireResponse()
	defer fasthttp.ReleaseResponse(resp)

	startTime := time.Now()
	err := u.Client.Do(req, resp)
	duration := time.Since(startTime)

	tags := stats.Tags{
		"url":    url,
		"method": method,
		"status": resp.StatusCode(),
	}
	u.Collector.Add(stats.Point{
		Stat:   &mRequests,
		Tags:   tags,
		Values: stats.Values{"duration": float64(duration)},
	})

	if err != nil {
		u.Collector.Add(stats.Point{
			Stat:   &mErrors,
			Tags:   tags,
			Values: stats.Value(1),
		})
		return HTTPResponse{}, err
	}

	headers := make(map[string]string)
	resp.Header.VisitAll(func(key []byte, value []byte) {
		headers[string(key)] = string(value)
	})

	return HTTPResponse{
		Status:  resp.StatusCode(),
		Headers: headers,
		Body:    string(resp.Body()),
	}, nil
}

func (u *VU) Sleep(t float64) {
	time.Sleep(time.Duration(t * float64(time.Second)))
}

func (u *VU) Log(level, msg string, fields map[string]interface{}) {
	e := u.Runner.logger.WithFields(log.Fields(fields))

	switch level {
	case "debug":
		e.Debug(msg)
	case "info":
		e.Info(msg)
	case "warn":
		e.Warn(msg)
	case "error":
		e.Error(msg)
	}
}
<|endoftext|>


<commit_before>package meta

import (
	"bytes"
	"path"

	"github.com/Alienero/Rambo/config"
	"github.com/Alienero/Rambo/mysql"

	"github.com/coreos/go-etcd/etcd"
	"github.com/golang/glog"
)

// Meta is metaDB's global public instance.
var Meta metaDB

type metaDB struct {
	client *etcd.Client
}

func (m *metaDB) AddUser(user, password string) error {
	_, err := m.client.Create(path.Join(UserInfo, user, Password), password, 0)
	return err
}

func (m *metaDB) AddBDatabase(db *Database) error {
	return nil
}

func (m *metaDB) IsDBExist(db string) (bool, error) {
	_, e := m.client.Get(path.Join(Databases, db), false, false)
	if e != nil {
		if err, ok := e.(*etcd.EtcdError); ok {
			if err.ErrorCode == NotFoud {
				return false, nil
			}
			return false, err
		}
		return false, e
	}
	return true, nil
}

func (m *metaDB) CheckUser(user string, auth []byte, salt []byte, db string) bool {
	password, err := m.getPassword(user)
	if err != nil {
		return false
	}

	if isExist := bytes.Equal(auth, mysql.CalcPassword(salt, []byte(password))); !isExist {
		glog.V(2).Infof("Password(!= %v) is nq", password)
		return false
	}
	if db != "" {
		_, err = m.client.Get(UserInfo+"/"+user+DB+db, false, false)
		if err != nil {
			glog.Infof("Can not get Etcd user db error:%v", err)
			return false
		}

	}
	return true
}

func (m *metaDB) CheckUserDirect(user, password string) bool {
	p, err := m.getPassword(user)
	if err != nil {
		return false
	}
	return password == p
}

func (m *metaDB) getPassword(user string) (string, error) {
	resp, err := m.client.Get(UserInfo+"/"+user+Password, false, false)
	if err != nil {
		glog.Warningf("Get Etcd User password error:%v", err)
		return "", err
	}
	return resp.Node.Value, nil
}

// scheme include : special fied, shard scheme, shard key
// TODO: we should cache the information.
// func (m *metaDB) GetSchemeTables(user string, db string, table string) (string, []string, error) {
// 	prefix := UserInfo + "/" + user + DB + db + Tables + table
// 	scheme, err := m.client.Get(prefix+Scheme, false, false)
// 	if err != nil {
// 		glog.Warningf("Get Etcd User table scheme info error:%v", err)
// 		return "", nil, err
// 	}
// 	tables, err := m.client.Get(prefix+ChildTable, true, false)
// 	if err != nil {
// 		glog.Warningf("Get Etcd User table's map info error:%v", err)
// 		return "", nil, err
// 	}
// 	ts := make([]string, 0, len(tables.Node.Nodes))
// 	for _, node := range tables.Node.Nodes {
// 		ts = append(ts, node.Value)
// 	}
// 	return scheme.Node.Value, ts, nil
// }

// InitMetaDB will Init DB.
func InitMetaDB() {
	Meta.client = etcd.NewClient(config.Config.Etcd.EtcdAddr)
}

type DBInfo struct {
	Scheme string   `json:"scheme"` // default is `hash`
	Tables []*Table `json:"tables"`
}

type Table struct {
	Name         string     `json:"name"`
	PartitionKey string     `json:"partition-key"`
	Backends     []*Backend `json:"backends"`
}

type Backend struct {
	Host     string `json:"host"`
	UserName string `json:"user-name"`
	Password string `json:"password"`
	Name     string `json:"name"`
}

// MysqlNode is one mysql server.
type MysqlNode struct {
	Host     string `json:"host"`
	UserName string `json:"user-name"`
	Password string `json:"password"`
	Name     string `json:"name"`
}

// Database is global database config.
type Database struct {
	Name     string     `json:"name"`
	Backends []*Backend `json:"backends"`
}
<commit_msg>chore<meta>: update table info<commit_after>package meta

import (
	"bytes"
	"path"

	"github.com/Alienero/Rambo/config"
	"github.com/Alienero/Rambo/mysql"

	"github.com/coreos/go-etcd/etcd"
	"github.com/golang/glog"
)

// Meta is metaDB's global public instance.
var Meta metaDB

type metaDB struct {
	client *etcd.Client
}

func (m *metaDB) AddUser(user, password string) error {
	_, err := m.client.Create(path.Join(UserInfo, user, Password), password, 0)
	return err
}

func (m *metaDB) AddBDatabase(db *Database) error {
	return nil
}

func (m *metaDB) IsDBExist(db string) (bool, error) {
	_, e := m.client.Get(path.Join(Databases, db), false, false)
	if e != nil {
		if err, ok := e.(*etcd.EtcdError); ok {
			if err.ErrorCode == NotFoud {
				return false, nil
			}
			return false, err
		}
		return false, e
	}
	return true, nil
}

func (m *metaDB) CheckUser(user string, auth []byte, salt []byte, db string) bool {
	password, err := m.getPassword(user)
	if err != nil {
		return false
	}

	if isExist := bytes.Equal(auth, mysql.CalcPassword(salt, []byte(password))); !isExist {
		glog.V(2).Infof("Password(!= %v) is nq", password)
		return false
	}
	if db != "" {
		_, err = m.client.Get(UserInfo+"/"+user+DB+db, false, false)
		if err != nil {
			glog.Infof("Can not get Etcd user db error:%v", err)
			return false
		}

	}
	return true
}

func (m *metaDB) CheckUserDirect(user, password string) bool {
	p, err := m.getPassword(user)
	if err != nil {
		return false
	}
	return password == p
}

func (m *metaDB) getPassword(user string) (string, error) {
	resp, err := m.client.Get(UserInfo+"/"+user+Password, false, false)
	if err != nil {
		glog.Warningf("Get Etcd User password error:%v", err)
		return "", err
	}
	return resp.Node.Value, nil
}

// scheme include : special fied, shard scheme, shard key
// TODO: we should cache the information.
// func (m *metaDB) GetSchemeTables(user string, db string, table string) (string, []string, error) {
// 	prefix := UserInfo + "/" + user + DB + db + Tables + table
// 	scheme, err := m.client.Get(prefix+Scheme, false, false)
// 	if err != nil {
// 		glog.Warningf("Get Etcd User table scheme info error:%v", err)
// 		return "", nil, err
// 	}
// 	tables, err := m.client.Get(prefix+ChildTable, true, false)
// 	if err != nil {
// 		glog.Warningf("Get Etcd User table's map info error:%v", err)
// 		return "", nil, err
// 	}
// 	ts := make([]string, 0, len(tables.Node.Nodes))
// 	for _, node := range tables.Node.Nodes {
// 		ts = append(ts, node.Value)
// 	}
// 	return scheme.Node.Value, ts, nil
// }

// InitMetaDB will Init DB.
func InitMetaDB() {
	Meta.client = etcd.NewClient(config.Config.Etcd.EtcdAddr)
}

type DBInfo struct {
	Scheme   string     `json:"scheme"` // default is `hash`
	Tables   []*Table   `json:"tables"`
	Backends []*Backend `json:"backends"`
}

// Table is mysql table meta info.
type Table struct {
	Name         string   `json:"name"`
	PartitionKey string   `json:"partition-key"`
	AutoKeys     []string `json:"auto-keys"`
}

type Backend struct {
	Host     string `json:"host"`
	UserName string `json:"user-name"`
	Password string `json:"password"`
	Name     string `json:"name"`
}

// MysqlNode is one mysql server.
type MysqlNode struct {
	Host     string `json:"host"`
	UserName string `json:"user-name"`
	Password string `json:"password"`
	Name     string `json:"name"`
}

// Database is global database config.
type Database struct {
	Name     string     `json:"name"`
	Backends []*Backend `json:"backends"`
}
<|endoftext|>


<commit_before>package charm_test

import (
	"bytes"
	"io"
	"io/ioutil"
	. "launchpad.net/gocheck"
	"launchpad.net/juju-core/charm"
	"launchpad.net/juju-core/testing"
	"os"
	"path/filepath"
	"strings"
)

func repoMeta(name string) io.Reader {
	charmDir := testing.Charms.DirPath("series", name)
	file, err := os.Open(filepath.Join(charmDir, "metadata.yaml"))
	if err != nil {
		panic(err)
	}
	defer file.Close()
	data, err := ioutil.ReadAll(file)
	if err != nil {
		panic(err)
	}
	return bytes.NewBuffer(data)
}

type MetaSuite struct{}

var _ = Suite(&MetaSuite{})

func (s *MetaSuite) TestReadMetaVersion1(c *C) {
	meta, err := charm.ReadMeta(repoMeta("dummy"))
	c.Assert(err, IsNil)
	c.Assert(meta.Name, Equals, "dummy")
	c.Assert(meta.Summary, Equals, "That's a dummy charm.")
	c.Assert(meta.Description, Equals,
		"This is a longer description which\npotentially contains multiple lines.\n")
	c.Assert(meta.Format, Equals, 1)
	c.Assert(meta.OldRevision, Equals, 0)
	c.Assert(meta.Subordinate, Equals, false)
}

func (s *MetaSuite) TestReadMetaVersion2(c *C) {
	meta, err := charm.ReadMeta(repoMeta("dummy-v2"))
	c.Assert(err, IsNil)
	c.Assert(meta.Name, Equals, "dummy-v2")
	c.Assert(meta.Summary, Equals, "That's a new dummy charm.")
	c.Assert(meta.Description, Equals,
		"This is a longer description which\npotentially contains multiple lines.\n")
	c.Assert(meta.Format, Equals, 2)
	c.Assert(meta.OldRevision, Equals, 0)
	c.Assert(meta.Subordinate, Equals, false)
}

func (s *MetaSuite) TestSubordinate(c *C) {
	meta, err := charm.ReadMeta(repoMeta("logging"))
	c.Assert(err, IsNil)
	c.Assert(meta.Subordinate, Equals, true)
}

func (s *MetaSuite) TestSubordinateWithoutContainerRelation(c *C) {
	r := repoMeta("dummy")
	hackYaml := ReadYaml(r)
	hackYaml["subordinate"] = true
	_, err := charm.ReadMeta(hackYaml.Reader())
	c.Assert(err, ErrorMatches, "subordinate charm \"dummy\" lacks requires relation with container scope")
}

func (s *MetaSuite) TestScopeConstraint(c *C) {
	meta, err := charm.ReadMeta(repoMeta("logging"))
	c.Assert(err, IsNil)
	c.Assert(meta.Provides["logging-client"].Scope, Equals, charm.ScopeGlobal)
	c.Assert(meta.Requires["logging-directory"].Scope, Equals, charm.ScopeContainer)
	c.Assert(meta.Subordinate, Equals, true)
}

func (s *MetaSuite) TestParseMetaRelations(c *C) {
	meta, err := charm.ReadMeta(repoMeta("mysql"))
	c.Assert(err, IsNil)
	c.Assert(meta.Provides["server"], Equals, charm.Relation{Interface: "mysql", Scope: charm.ScopeGlobal})
	c.Assert(meta.Requires, IsNil)
	c.Assert(meta.Peers, IsNil)

	meta, err = charm.ReadMeta(repoMeta("riak"))
	c.Assert(err, IsNil)
	c.Assert(meta.Provides["endpoint"], Equals, charm.Relation{Interface: "http", Scope: charm.ScopeGlobal})
	c.Assert(meta.Provides["admin"], Equals, charm.Relation{Interface: "http", Scope: charm.ScopeGlobal})
	c.Assert(meta.Peers["ring"], Equals, charm.Relation{Interface: "riak", Limit: 1, Scope: charm.ScopeGlobal})
	c.Assert(meta.Requires, IsNil)

	meta, err = charm.ReadMeta(repoMeta("terracotta"))
	c.Assert(err, IsNil)
	c.Assert(meta.Provides["dso"], Equals, charm.Relation{Interface: "terracotta", Optional: true, Scope: charm.ScopeGlobal})
	c.Assert(meta.Peers["server-array"], Equals, charm.Relation{Interface: "terracotta-server", Limit: 1, Scope: charm.ScopeGlobal})
	c.Assert(meta.Requires, IsNil)

	meta, err = charm.ReadMeta(repoMeta("wordpress"))
	c.Assert(err, IsNil)
	c.Assert(meta.Provides["url"], Equals, charm.Relation{Interface: "http", Scope: charm.ScopeGlobal})
	c.Assert(meta.Requires["db"], Equals, charm.Relation{Interface: "mysql", Limit: 1, Scope: charm.ScopeGlobal})
	c.Assert(meta.Requires["cache"], Equals, charm.Relation{Interface: "varnish", Limit: 2, Optional: true, Scope: charm.ScopeGlobal})
	c.Assert(meta.Peers, IsNil)
}

var relationsConstraintsTests = []struct {
	rels string
	err  string
}{
	{
		"provides:\n  foo: ping\nrequires:\n  foo: pong",
		`"foo" relation redeclared`,
	}, {
		"requires:\n  foo: ping\npeers:\n  foo: pong",
		`"foo" relation redeclared`,
	}, {
		"peers:\n  foo: ping\nprovides:\n  foo: pong",
		`"foo" relation redeclared`,
	}, {
		"provides:\n  juju: blob",
		`"juju" is a reserved relation name`,
	}, {
		"requires:\n  juju: blob",
		`"juju" is a reserved relation name`,
	}, {
		"peers:\n  juju: blob",
		`"juju" is a reserved relation name`,
	}, {
		"provides:\n  juju-snap: blub",
		`"juju-snap" is a reserved relation name`,
	}, {
		"requires:\n  juju-crackle: blub",
		`"juju-crackle" is a reserved relation name`,
	}, {
		"peers:\n  juju-pop: blub",
		`"juju-pop" is a reserved relation name`,
	}, {
		"provides:\n  innocuous: juju-snap",
		`"innocuous" relation uses the reserved provider interface name "juju-snap"`,
	}, {
		"requires:\n  innocuous: juju-snap",
		``,
	}, {
		"peers:\n  innocuous: juju-snap",
		``,
	},
}

func (s *MetaSuite) TestRelationsConstraints(c *C) {
	prefix := "name: a\nsummary: b\ndescription: c\n"
	for i, t := range relationsConstraintsTests {
		c.Logf("test %d", i)
		r := strings.NewReader(prefix + t.rels)
		meta, err := charm.ReadMeta(r)
		if t.err != "" {
			c.Assert(err, ErrorMatches, t.err)
			c.Assert(meta, IsNil)
		} else {
			c.Assert(err, IsNil)
			c.Assert(meta, NotNil)
		}
	}
}

// Test rewriting of a given interface specification into long form.
//
// InterfaceExpander uses `coerce` to do one of two things:
//
//   - Rewrite shorthand to the long form used for actual storage
//   - Fills in defaults, including a configurable `limit`
//
// This test ensures test coverage on each of these branches, along
// with ensuring the conversion object properly raises SchemaError
// exceptions on invalid data.
func (s *MetaSuite) TestIfaceExpander(c *C) {
	e := charm.IfaceExpander(nil)

	path := []string{"<pa", "th>"}

	// Shorthand is properly rewritten
	v, err := e.Coerce("http", path)
	c.Assert(err, IsNil)
	c.Assert(v, DeepEquals, map[string]interface{}{"interface": "http", "limit": nil, "optional": false, "scope": string(charm.ScopeGlobal)})

	// Defaults are properly applied
	v, err = e.Coerce(map[string]interface{}{"interface": "http"}, path)
	c.Assert(err, IsNil)
	c.Assert(v, DeepEquals, map[string]interface{}{"interface": "http", "limit": nil, "optional": false, "scope": string(charm.ScopeGlobal)})

	v, err = e.Coerce(map[string]interface{}{"interface": "http", "limit": 2}, path)
	c.Assert(err, IsNil)
	c.Assert(v, DeepEquals, map[string]interface{}{"interface": "http", "limit": int64(2), "optional": false, "scope": string(charm.ScopeGlobal)})

	v, err = e.Coerce(map[string]interface{}{"interface": "http", "optional": true}, path)
	c.Assert(err, IsNil)
	c.Assert(v, DeepEquals, map[string]interface{}{"interface": "http", "limit": nil, "optional": true, "scope": string(charm.ScopeGlobal)})

	// Invalid data raises an error.
	v, err = e.Coerce(42, path)
	c.Assert(err, ErrorMatches, "<path>: expected map, got 42")

	v, err = e.Coerce(map[string]interface{}{"interface": "http", "optional": nil}, path)
	c.Assert(err, ErrorMatches, "<path>.optional: expected bool, got nothing")

	v, err = e.Coerce(map[string]interface{}{"interface": "http", "limit": "none, really"}, path)
	c.Assert(err, ErrorMatches, "<path>.limit: unexpected value.*")

	// Can change default limit
	e = charm.IfaceExpander(1)
	v, err = e.Coerce(map[string]interface{}{"interface": "http"}, path)
	c.Assert(err, IsNil)
	c.Assert(v, DeepEquals, map[string]interface{}{"interface": "http", "limit": int64(1), "optional": false, "scope": string(charm.ScopeGlobal)})
}
<commit_msg>extended tests a little<commit_after>package charm_test

import (
	"bytes"
	"io"
	"io/ioutil"
	. "launchpad.net/gocheck"
	"launchpad.net/juju-core/charm"
	"launchpad.net/juju-core/testing"
	"os"
	"path/filepath"
	"strings"
)

func repoMeta(name string) io.Reader {
	charmDir := testing.Charms.DirPath("series", name)
	file, err := os.Open(filepath.Join(charmDir, "metadata.yaml"))
	if err != nil {
		panic(err)
	}
	defer file.Close()
	data, err := ioutil.ReadAll(file)
	if err != nil {
		panic(err)
	}
	return bytes.NewBuffer(data)
}

type MetaSuite struct{}

var _ = Suite(&MetaSuite{})

func (s *MetaSuite) TestReadMetaVersion1(c *C) {
	meta, err := charm.ReadMeta(repoMeta("dummy"))
	c.Assert(err, IsNil)
	c.Assert(meta.Name, Equals, "dummy")
	c.Assert(meta.Summary, Equals, "That's a dummy charm.")
	c.Assert(meta.Description, Equals,
		"This is a longer description which\npotentially contains multiple lines.\n")
	c.Assert(meta.Format, Equals, 1)
	c.Assert(meta.OldRevision, Equals, 0)
	c.Assert(meta.Subordinate, Equals, false)
}

func (s *MetaSuite) TestReadMetaVersion2(c *C) {
	meta, err := charm.ReadMeta(repoMeta("dummy-v2"))
	c.Assert(err, IsNil)
	c.Assert(meta.Name, Equals, "dummy-v2")
	c.Assert(meta.Summary, Equals, "That's a new dummy charm.")
	c.Assert(meta.Description, Equals,
		"This is a longer description which\npotentially contains multiple lines.\n")
	c.Assert(meta.Format, Equals, 2)
	c.Assert(meta.OldRevision, Equals, 0)
	c.Assert(meta.Subordinate, Equals, false)
}

func (s *MetaSuite) TestSubordinate(c *C) {
	meta, err := charm.ReadMeta(repoMeta("logging"))
	c.Assert(err, IsNil)
	c.Assert(meta.Subordinate, Equals, true)
}

func (s *MetaSuite) TestSubordinateWithoutContainerRelation(c *C) {
	r := repoMeta("dummy")
	hackYaml := ReadYaml(r)
	hackYaml["subordinate"] = true
	_, err := charm.ReadMeta(hackYaml.Reader())
	c.Assert(err, ErrorMatches, "subordinate charm \"dummy\" lacks requires relation with container scope")
}

func (s *MetaSuite) TestScopeConstraint(c *C) {
	meta, err := charm.ReadMeta(repoMeta("logging"))
	c.Assert(err, IsNil)
	c.Assert(meta.Provides["logging-client"].Scope, Equals, charm.ScopeGlobal)
	c.Assert(meta.Requires["logging-directory"].Scope, Equals, charm.ScopeContainer)
	c.Assert(meta.Subordinate, Equals, true)
}

func (s *MetaSuite) TestParseMetaRelations(c *C) {
	meta, err := charm.ReadMeta(repoMeta("mysql"))
	c.Assert(err, IsNil)
	c.Assert(meta.Provides["server"], Equals, charm.Relation{Interface: "mysql", Scope: charm.ScopeGlobal})
	c.Assert(meta.Requires, IsNil)
	c.Assert(meta.Peers, IsNil)

	meta, err = charm.ReadMeta(repoMeta("riak"))
	c.Assert(err, IsNil)
	c.Assert(meta.Provides["endpoint"], Equals, charm.Relation{Interface: "http", Scope: charm.ScopeGlobal})
	c.Assert(meta.Provides["admin"], Equals, charm.Relation{Interface: "http", Scope: charm.ScopeGlobal})
	c.Assert(meta.Peers["ring"], Equals, charm.Relation{Interface: "riak", Limit: 1, Scope: charm.ScopeGlobal})
	c.Assert(meta.Requires, IsNil)

	meta, err = charm.ReadMeta(repoMeta("terracotta"))
	c.Assert(err, IsNil)
	c.Assert(meta.Provides["dso"], Equals, charm.Relation{Interface: "terracotta", Optional: true, Scope: charm.ScopeGlobal})
	c.Assert(meta.Peers["server-array"], Equals, charm.Relation{Interface: "terracotta-server", Limit: 1, Scope: charm.ScopeGlobal})
	c.Assert(meta.Requires, IsNil)

	meta, err = charm.ReadMeta(repoMeta("wordpress"))
	c.Assert(err, IsNil)
	c.Assert(meta.Provides["url"], Equals, charm.Relation{Interface: "http", Scope: charm.ScopeGlobal})
	c.Assert(meta.Requires["db"], Equals, charm.Relation{Interface: "mysql", Limit: 1, Scope: charm.ScopeGlobal})
	c.Assert(meta.Requires["cache"], Equals, charm.Relation{Interface: "varnish", Limit: 2, Optional: true, Scope: charm.ScopeGlobal})
	c.Assert(meta.Peers, IsNil)
}

var relationsConstraintsTests = []struct {
	rels string
	err  string
}{
	{
		"provides:\n  foo: ping\nrequires:\n  foo: pong",
		`"foo" relation redeclared`,
	}, {
		"requires:\n  foo: ping\npeers:\n  foo: pong",
		`"foo" relation redeclared`,
	}, {
		"peers:\n  foo: ping\nprovides:\n  foo: pong",
		`"foo" relation redeclared`,
	}, {
		"provides:\n  juju: blob",
		`"juju" is a reserved relation name`,
	}, {
		"requires:\n  juju: blob",
		`"juju" is a reserved relation name`,
	}, {
		"peers:\n  juju: blob",
		`"juju" is a reserved relation name`,
	}, {
		"provides:\n  juju-snap: blub",
		`"juju-snap" is a reserved relation name`,
	}, {
		"requires:\n  juju-crackle: blub",
		`"juju-crackle" is a reserved relation name`,
	}, {
		"peers:\n  juju-pop: blub",
		`"juju-pop" is a reserved relation name`,
	}, {
		"provides:\n  innocuous: juju",
		`"innocuous" relation uses the reserved provider interface name "juju"`,
	}, {
		rels: "requires:\n  innocuous: juju",
	}, {
		rels: "peers:\n  innocuous: juju",
	}, {
		"provides:\n  innocuous: juju-snap",
		`"innocuous" relation uses the reserved provider interface name "juju-snap"`,
	}, {
		rels: "requires:\n  innocuous: juju-snap",
	}, {
		rels: "peers:\n  innocuous: juju-snap",
	},
}

func (s *MetaSuite) TestRelationsConstraints(c *C) {
	prefix := "name: a\nsummary: b\ndescription: c\n"
	for i, t := range relationsConstraintsTests {
		c.Logf("test %d", i)
		r := strings.NewReader(prefix + t.rels)
		meta, err := charm.ReadMeta(r)
		if t.err != "" {
			c.Assert(err, ErrorMatches, t.err)
			c.Assert(meta, IsNil)
		} else {
			c.Assert(err, IsNil)
			c.Assert(meta, NotNil)
		}
	}
}

// Test rewriting of a given interface specification into long form.
//
// InterfaceExpander uses `coerce` to do one of two things:
//
//   - Rewrite shorthand to the long form used for actual storage
//   - Fills in defaults, including a configurable `limit`
//
// This test ensures test coverage on each of these branches, along
// with ensuring the conversion object properly raises SchemaError
// exceptions on invalid data.
func (s *MetaSuite) TestIfaceExpander(c *C) {
	e := charm.IfaceExpander(nil)

	path := []string{"<pa", "th>"}

	// Shorthand is properly rewritten
	v, err := e.Coerce("http", path)
	c.Assert(err, IsNil)
	c.Assert(v, DeepEquals, map[string]interface{}{"interface": "http", "limit": nil, "optional": false, "scope": string(charm.ScopeGlobal)})

	// Defaults are properly applied
	v, err = e.Coerce(map[string]interface{}{"interface": "http"}, path)
	c.Assert(err, IsNil)
	c.Assert(v, DeepEquals, map[string]interface{}{"interface": "http", "limit": nil, "optional": false, "scope": string(charm.ScopeGlobal)})

	v, err = e.Coerce(map[string]interface{}{"interface": "http", "limit": 2}, path)
	c.Assert(err, IsNil)
	c.Assert(v, DeepEquals, map[string]interface{}{"interface": "http", "limit": int64(2), "optional": false, "scope": string(charm.ScopeGlobal)})

	v, err = e.Coerce(map[string]interface{}{"interface": "http", "optional": true}, path)
	c.Assert(err, IsNil)
	c.Assert(v, DeepEquals, map[string]interface{}{"interface": "http", "limit": nil, "optional": true, "scope": string(charm.ScopeGlobal)})

	// Invalid data raises an error.
	v, err = e.Coerce(42, path)
	c.Assert(err, ErrorMatches, "<path>: expected map, got 42")

	v, err = e.Coerce(map[string]interface{}{"interface": "http", "optional": nil}, path)
	c.Assert(err, ErrorMatches, "<path>.optional: expected bool, got nothing")

	v, err = e.Coerce(map[string]interface{}{"interface": "http", "limit": "none, really"}, path)
	c.Assert(err, ErrorMatches, "<path>.limit: unexpected value.*")

	// Can change default limit
	e = charm.IfaceExpander(1)
	v, err = e.Coerce(map[string]interface{}{"interface": "http"}, path)
	c.Assert(err, IsNil)
	c.Assert(v, DeepEquals, map[string]interface{}{"interface": "http", "limit": int64(1), "optional": false, "scope": string(charm.ScopeGlobal)})
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/robertkrimen/otto"
	"gopkg.in/alecthomas/kingpin.v2"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"sort"
	"strings"
)

var (
	codeListPtr  = ArgsStrList(kingpin.Arg("code", "the js code you want to run").Required())
	lineSeqPtr   = kingpin.Flag("line-seq", "the char used for split line").Short('l').Default("\n").String()
	columnSeqPtr = kingpin.Flag("column-seq", "the char used for split column").Short('c').Default(" ").String()
	funcListPtr  = ArgsStrList(kingpin.Flag("funcion", "function").Short('f'))
	pathListPtr  = ArgsStrList(kingpin.Flag("path", "command search path").Short('p'))
	jsListPtr    = ArgsStrList(kingpin.Flag("js", "Javascript file").Short('j'))
	reversePtr   = kingpin.Flag("reverse", "execute code with reverse order").Short('r').Bool()
)

type argsStrList []string

func (i *argsStrList) Set(value string) error {
	*i = append(*i, value)
	return nil
}

func (i *argsStrList) String() string {
	return ""
}

func (i *argsStrList) IsCumulative() bool {
	return true
}

func ArgsStrList(s kingpin.Settings) (target *[]string) {
	target = new([]string)
	s.SetValue((*argsStrList)(target))
	return
}

var builtinFuncCode = []string{
	`
printArray = function(arr) {
	for(i=0;i<arr.length;i+=1){
		console.log(i)
	}
}

`,
	`
function isFunc(val) {
	if(typeof val === 'function') {
		return true;
	}else{
		return false;
	}
}
`,
	`
mapIf = function(arr, func, preFunc, postFunc) {
	ret = []
	for(i=0;i<arr.length;i+=1) {
		val = arr[i];
		if(isFunc(preFunc) && !preFunc(val)){
			continue;
		}
		out = func(val);
		if(isFunc(postFunc) && !postFunc(out)){
			continue;
		}
		ret.push(val);
	}
	return ret;
}

`,
}

func readAll() string {
	bytes, err := ioutil.ReadAll(os.Stdin)
	if err == nil {
		return string(bytes)
	} else {
		panic("Failed to read stdin")
	}
}

func readJSFile(vm *otto.Otto, path string) {
	file, err := os.Open(path)
	defer file.Close()
	if err != nil {
		panic(err)
	}
	bytes, err := ioutil.ReadAll(file)
	if err != nil {
		panic(err)
	}
	_, err = vm.Run(string(bytes))
	if err != nil {
		panic(err)
	}
}

type Matrix [][]string

func setBuiltinFunc(vm *otto.Otto) {
	for _, ele := range builtinFuncCode {
		_, err := vm.Run(ele)
		if err != nil {
			panic(err)
		}
	}

	vm.Set("exec", func(call otto.FunctionCall) otto.Value {
		args := make([]string, len(call.ArgumentList))
		cmdPath, err := call.Argument(0).ToString()
		if err != nil {
			panic(err)
		}
		for i := 1; i < len(call.ArgumentList); i += 1 {
			ret, err := call.Argument(i).ToString()
			if err == nil {
				args[i] = ret
			} else {
				panic(err)
			}

		}
		output := callExternalFunc(cmdPath, args)
		result, err := vm.ToValue(output)
		if err != nil {
			panic(err)
		}

		return result
	})

	vm.Set("execStdin", func(call otto.FunctionCall) otto.Value {
		args := make([]string, len(call.ArgumentList))
		cmdPath, err := call.Argument(0).ToString()
		if err != nil {
			panic(err)
		}
		stdin, err := call.Argument(1).ToString()
		if err != nil {
			panic(err)
		}
		for i := 2; i < len(call.ArgumentList); i += 1 {
			ret, err := call.Argument(i).ToString()
			if err == nil {
				args[i] = ret
			} else {
				panic(err)
			}

		}
		output := callExternalFuncWithStdin(cmdPath, stdin, args)
		result, err := vm.ToValue(output)
		if err != nil {
			panic(err)
		}

		return result
	})
}

func callExternalFunc(cmd string, args []string) string {
	out, err := exec.Command(cmd, args...).Output()
	if err != nil {
		panic(err)
	}
	return string(out)
}

func callExternalFuncWithStdin(cmd string, stdin string, args []string) string {
	p := exec.Command(cmd, args...)
	p.Stdin = strings.NewReader(stdin)
	out, err := p.Output()
	if err != nil {
		panic(err)
	}
	return string(out)
}

func addPATHEnv(path string) {
	oldEnv := os.Getenv("PATH")
	newEnv := path + ":" + oldEnv
	os.Setenv("PATH", newEnv)
}

func getWd() string {
	cwd, err := os.Getwd()
	if err != nil {
		panic(err)
	}
	return cwd
}

func initExternelFunc(vm *otto.Otto, cmdPath string) {
	funcName := cmdPath[:len(cmdPath)-len(filepath.Ext(cmdPath))]
	vm.Set(funcName, func(call otto.FunctionCall) otto.Value {
		args := make([]string, len(call.ArgumentList))
		for i := 0; i < len(call.ArgumentList); i += 1 {
			ret, err := call.Argument(i).ToString()
			if err == nil {
				args[i] = ret
			} else {
				panic(err)
			}

		}
		output := callExternalFunc(cmdPath, args)
		result, err := vm.ToValue(output)
		if err != nil {
			panic(err)
		}
		return result
	})

}

func main() {
	addPATHEnv(getWd())
	fmt.Printf("")
	kingpin.Parse()

	stdin := readAll()
	lines := strings.Split(stdin, *lineSeqPtr)
	matrixPtr := new(Matrix)

	for i := 0; i < len(lines); i += 1 {
		*matrixPtr = append(*matrixPtr, strings.Split(lines[i], *columnSeqPtr))
	}

	vm := otto.New()

	vm.Set("stdin", stdin)
	vm.Set("stdout", "")
	vm.Set("lines", lines)
	vm.Set("matrix", *matrixPtr)
	vm.Run("print = console.log")
	setBuiltinFunc(vm)

	for i := 0; i < len(*funcListPtr); i += 1 {
		initExternelFunc(vm, (*funcListPtr)[i])
	}

	for i := 0; i < len(*pathListPtr); i += 1 {
		addPATHEnv((*pathListPtr)[i])
	}

	for i := 0; i < len(*jsListPtr); i += 1 {
		readJSFile(vm, (*jsListPtr)[i])
	}

	codeList := sort.StringSlice(*codeListPtr)

	if *reversePtr {
		for i, j := 0, len(codeList)-1; i < j; i, j = i+1, j-1 {
			codeList[i], codeList[j] = codeList[j], codeList[i]
		}
	}

	for i := 0; i < len(codeList); i += 1 {
		_, err := vm.Run(codeList[i])
		if err != nil {
			panic(err)
		}
	}

}
<commit_msg>add print, printf, sprintf func<commit_after>package main

import (
	"fmt"
	"github.com/robertkrimen/otto"
	"gopkg.in/alecthomas/kingpin.v2"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"sort"
	"strings"
)

var (
	codeListPtr  = ArgsStrList(kingpin.Arg("code", "the js code you want to run").Required())
	lineSeqPtr   = kingpin.Flag("line-seq", "the char used for split line").Short('l').Default("\n").String()
	columnSeqPtr = kingpin.Flag("column-seq", "the char used for split column").Short('c').Default(" ").String()
	funcListPtr  = ArgsStrList(kingpin.Flag("funcion", "function").Short('f'))
	pathListPtr  = ArgsStrList(kingpin.Flag("path", "command search path").Short('p'))
	jsListPtr    = ArgsStrList(kingpin.Flag("js", "Javascript file").Short('j'))
	reversePtr   = kingpin.Flag("reverse", "execute code with reverse order").Short('r').Bool()
)

type argsStrList []string

func (i *argsStrList) Set(value string) error {
	*i = append(*i, value)
	return nil
}

func (i *argsStrList) String() string {
	return ""
}

func (i *argsStrList) IsCumulative() bool {
	return true
}

func ArgsStrList(s kingpin.Settings) (target *[]string) {
	target = new([]string)
	s.SetValue((*argsStrList)(target))
	return
}

var builtinFuncCode = []string{
	`
printArray = function(arr) {
	for(i=0;i<arr.length;i+=1){
		console.log(i)
	}
}

`,
	`
function isFunc(val) {
	if(typeof val === 'function') {
		return true;
	}else{
		return false;
	}
}
`,
	`
mapIf = function(arr, func, preFunc, postFunc) {
	ret = []
	for(i=0;i<arr.length;i+=1) {
		val = arr[i];
		if(isFunc(preFunc) && !preFunc(val)){
			continue;
		}
		out = func(val);
		if(isFunc(postFunc) && !postFunc(out)){
			continue;
		}
		ret.push(val);
	}
	return ret;
}

`,
}

func readAll() string {
	bytes, err := ioutil.ReadAll(os.Stdin)
	if err == nil {
		return string(bytes)
	} else {
		panic("Failed to read stdin")
	}
}

func readJSFile(vm *otto.Otto, path string) {
	file, err := os.Open(path)
	defer file.Close()
	if err != nil {
		panic(err)
	}
	bytes, err := ioutil.ReadAll(file)
	if err != nil {
		panic(err)
	}
	_, err = vm.Run(string(bytes))
	if err != nil {
		panic(err)
	}
}

type Matrix [][]string

func setBuiltinFunc(vm *otto.Otto) {
	for _, ele := range builtinFuncCode {
		_, err := vm.Run(ele)
		if err != nil {
			panic(err)
		}
	}

	vm.Set("exec", func(call otto.FunctionCall) otto.Value {
		args := make([]string, len(call.ArgumentList))
		cmdPath, err := call.Argument(0).ToString()
		if err != nil {
			panic(err)
		}
		for i := 1; i < len(call.ArgumentList); i += 1 {
			ret, err := call.Argument(i).ToString()
			if err == nil {
				args[i] = ret
			} else {
				panic(err)
			}

		}
		output := callExternalFunc(cmdPath, args)
		result, err := vm.ToValue(output)
		if err != nil {
			panic(err)
		}

		return result
	})

	vm.Set("execStdin", func(call otto.FunctionCall) otto.Value {
		args := make([]string, len(call.ArgumentList))
		cmdPath, err := call.Argument(0).ToString()
		if err != nil {
			panic(err)
		}
		stdin, err := call.Argument(1).ToString()
		if err != nil {
			panic(err)
		}
		for i := 2; i < len(call.ArgumentList); i += 1 {
			ret, err := call.Argument(i).ToString()
			if err == nil {
				args[i] = ret
			} else {
				panic(err)
			}

		}
		output := callExternalFuncWithStdin(cmdPath, stdin, args)
		result, err := vm.ToValue(output)
		if err != nil {
			panic(err)
		}

		return result
	})
	vm.Set("print", func(call otto.FunctionCall) otto.Value {
		for i := 0; i < len(call.ArgumentList); i += 1 {
			str, err := call.Argument(i).ToString()
			if err == nil {
				fmt.Print(str)
			} else {
				panic(err)
			}
		}
		val, _ := vm.ToValue("")
		return val
	})

	sprintf := func(call otto.FunctionCall) string {
		args := make([]interface{}, len(call.ArgumentList)-1)
		format, err := call.Argument(0).ToString()
		if err != nil {
			panic(err)
		}
		for i := 1; i < len(call.ArgumentList); i += 1 {
			str, err := call.Argument(i).ToString()
			if err == nil {
				args[i-1] = str
			} else {
				panic(err)
			}
		}
		return fmt.Sprintf(format, args...)
	}

	vm.Set("sprint", func(call otto.FunctionCall) otto.Value {
		val := sprintf(call)
		ret, _ := vm.ToValue(val)
		return ret
	})
	vm.Set("printf", func(call otto.FunctionCall) otto.Value {
		val := sprintf(call)
		fmt.Print(val)
		ret, _ := vm.ToValue(val)
		return ret
	})
}

func callExternalFunc(cmd string, args []string) string {
	out, err := exec.Command(cmd, args...).Output()
	if err != nil {
		panic(err)
	}
	return string(out)
}

func callExternalFuncWithStdin(cmd string, stdin string, args []string) string {
	p := exec.Command(cmd, args...)
	p.Stdin = strings.NewReader(stdin)
	out, err := p.Output()
	if err != nil {
		panic(err)
	}
	return string(out)
}

func addPATHEnv(path string) {
	oldEnv := os.Getenv("PATH")
	newEnv := path + ":" + oldEnv
	os.Setenv("PATH", newEnv)
}

func getWd() string {
	cwd, err := os.Getwd()
	if err != nil {
		panic(err)
	}
	return cwd
}

func initExternelFunc(vm *otto.Otto, cmdPath string) {
	funcName := cmdPath[:len(cmdPath)-len(filepath.Ext(cmdPath))]
	vm.Set(funcName, func(call otto.FunctionCall) otto.Value {
		args := make([]string, len(call.ArgumentList))
		for i := 0; i < len(call.ArgumentList); i += 1 {
			ret, err := call.Argument(i).ToString()
			if err == nil {
				args[i] = ret
			} else {
				panic(err)
			}

		}
		output := callExternalFunc(cmdPath, args)
		result, err := vm.ToValue(output)
		if err != nil {
			panic(err)
		}
		return result
	})

}

func main() {
	addPATHEnv(getWd())
	fmt.Printf("")
	kingpin.Parse()

	stdin := readAll()
	lines := strings.Split(stdin, *lineSeqPtr)
	matrixPtr := new(Matrix)

	for i := 0; i < len(lines); i += 1 {
		*matrixPtr = append(*matrixPtr, strings.Split(lines[i], *columnSeqPtr))
	}

	vm := otto.New()

	vm.Set("stdin", stdin)
	vm.Set("stdout", "")
	vm.Set("lines", lines)
	vm.Set("matrix", *matrixPtr)
	vm.Run("println = console.log")
	setBuiltinFunc(vm)

	for i := 0; i < len(*funcListPtr); i += 1 {
		initExternelFunc(vm, (*funcListPtr)[i])
	}

	for i := 0; i < len(*pathListPtr); i += 1 {
		addPATHEnv((*pathListPtr)[i])
	}

	for i := 0; i < len(*jsListPtr); i += 1 {
		readJSFile(vm, (*jsListPtr)[i])
	}

	codeList := sort.StringSlice(*codeListPtr)

	if *reversePtr {
		for i, j := 0, len(codeList)-1; i < j; i, j = i+1, j-1 {
			codeList[i], codeList[j] = codeList[j], codeList[i]
		}
	}

	for i := 0; i < len(codeList); i += 1 {
		_, err := vm.Run(codeList[i])
		if err != nil {
			panic(err)
		}
	}

}
<|endoftext|>


<commit_before>package vector

import (
	"math"
)

type Vector struct {
	X float64
	Y float64
}

func ZERO() Vector {
	return Vector{0, 0}
}

func (v *Vector) Invert() {
	v.X = -v.X
	v.Y = -v.Y
}

func (v *Vector) Magnitude() float64 {
	return math.Sqrt(v.SquareMagnitude())
}

func (v *Vector) SquareMagnitude() float64 {
	return (v.X * v.X) + (v.Y * v.Y)
}

func (v *Vector) Normalize() {
	l := v.Magnitude()
	if l > 0 {
		v.X /= l
		v.Y /= l
	}
}

func (v *Vector) Multiply(val float64) {
	v.X *= val
	v.Y *= val
}

func Multiply(v Vector, val float64) Vector {
	return Vector{v.X * val, v.Y * val}
}

func (v *Vector) Add(o Vector) {
	v.X += o.X
	v.Y += o.Y
}

func Add(lhs, rhs Vector) Vector {
	return Vector{lhs.X + rhs.X, lhs.Y + rhs.Y}
}

func (v *Vector) AddScaledVector(o Vector, scale float64) {
	v.X += o.X * scale
	v.Y += o.Y * scale
}

func (v *Vector) Subtract(o Vector) {
	v.X -= o.X
	v.Y -= o.Y
}

func Subtract(lhs, rhs Vector) Vector {
	return Vector{lhs.X - rhs.X, lhs.Y - rhs.Y}
}

func (v *Vector) Clear() {
	v.X = 0
	v.Y = 0
}

func Product(lhs, rhs Vector) Vector {
	return Vector{lhs.X * rhs.X, lhs.Y * rhs.Y}
}

func Dot(lhs, rhs Vector) float64 {
	return (lhs.X * rhs.X) + (lhs.Y * rhs.Y)
}

func Cross(lhs, rhs Vector) float64 {
	return (lhs.Y * rhs.X) - (lhs.X * rhs.Y)
}

func (v Vector) OnTheRight(o Vector) bool {
	return Cross(v, o) >= 0
}

func (v Vector) Size() float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func (v Vector) SizeSquared() float64 {
	return v.X*v.X + v.Y*v.Y
}
<commit_msg>Fix cross product wrong implementation<commit_after>package vector

import (
	"math"
)

type Vector struct {
	X float64
	Y float64
}

func ZERO() Vector {
	return Vector{0, 0}
}

func (v *Vector) Invert() {
	v.X = -v.X
	v.Y = -v.Y
}

func (v *Vector) Magnitude() float64 {
	return math.Sqrt(v.SquareMagnitude())
}

func (v *Vector) SquareMagnitude() float64 {
	return (v.X * v.X) + (v.Y * v.Y)
}

func (v *Vector) Normalize() {
	l := v.Magnitude()
	if l > 0 {
		v.X /= l
		v.Y /= l
	}
}

func (v *Vector) Multiply(val float64) {
	v.X *= val
	v.Y *= val
}

func Multiply(v Vector, val float64) Vector {
	return Vector{v.X * val, v.Y * val}
}

func (v *Vector) Add(o Vector) {
	v.X += o.X
	v.Y += o.Y
}

func Add(lhs, rhs Vector) Vector {
	return Vector{lhs.X + rhs.X, lhs.Y + rhs.Y}
}

func (v *Vector) AddScaledVector(o Vector, scale float64) {
	v.X += o.X * scale
	v.Y += o.Y * scale
}

func (v *Vector) Subtract(o Vector) {
	v.X -= o.X
	v.Y -= o.Y
}

func Subtract(lhs, rhs Vector) Vector {
	return Vector{lhs.X - rhs.X, lhs.Y - rhs.Y}
}

func (v *Vector) Clear() {
	v.X = 0
	v.Y = 0
}

func Product(lhs, rhs Vector) Vector {
	return Vector{lhs.X * rhs.X, lhs.Y * rhs.Y}
}

func Dot(lhs, rhs Vector) float64 {
	return (lhs.X * rhs.X) + (lhs.Y * rhs.Y)
}

func Cross(lhs, rhs Vector) float64 {
	return (lhs.X * rhs.Y) - (lhs.Y * rhs.X)
}

func (v Vector) OnTheRight(o Vector) bool {
	return Cross(v, o) < 0
}

func (v Vector) Size() float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func (v Vector) SizeSquared() float64 {
	return v.X*v.X + v.Y*v.Y
}
<|endoftext|>


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

package upgrades

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

// WriteReplacementFile create a file called filename with the specified
// contents, allowing for the fact that filename may already exist.
// It first writes data to a temp file and then renames so that if the
// writing fails, any original content is preserved.
func WriteReplacementFile(filename string, data []byte) error {
	// Write the data to a temp file
	confDir := filepath.Dir(filename)
	tempDir, err := ioutil.TempDir(confDir, "")
	if err != nil {
		return err
	}
	tempFile := filepath.Join(tempDir, "newfile")
	defer os.RemoveAll(tempDir)
	err = ioutil.WriteFile(tempFile, []byte(data), 0644)
	if err != nil {
		return err
	}
	return os.Rename(tempFile, filename)
}
<commit_msg>tweak WriteReplacementFile<commit_after>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package upgrades

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

// WriteReplacementFile create a file called filename with the specified
// contents, allowing for the fact that filename may already exist.
// It first writes data to a temp file and then renames so that if the
// writing fails, any original content is preserved.
func WriteReplacementFile(filename string, data []byte) error {
	// Write the data to a temp file
	confDir := filepath.Dir(filename)
	tempFile, err := ioutil.TempFile(confDir, "")
	if err != nil {
		return err
	}
	defer os.Remove(tempFile.Name())
	err = ioutil.WriteFile(tempFile.Name(), []byte(data), 0644)
	if err != nil {
		return err
	}
	return os.Rename(tempFile.Name(), filename)
}
<|endoftext|>


<commit_before>package tuple

import (
	. "github.com/smartystreets/goconvey/convey"
	"testing"
)

func TestMapscanDocstrings(t *testing.T) {
	storeData := Map{
		"name": String("store name"),
		"book": Array([]Value{
			Map{
				"title": String("book name"),
			},
		}),
	}
	m := Map{"store": storeData}

	Convey("Map.Get examples should be correct", t, func() {
		examples := map[string]interface{}{
			"store":                         storeData,
			"store.name":                    String("store name"),
			"store.book[0].title":           String("book name"),
			`["store"]`:                     storeData,
			`["store"]["name"]`:             String("store name"),
			`["store"]["book"][0]["title"]`: String("book name"),
		}
		for input, expected := range examples {
			actual, err := m.Get(input)
			So(err, ShouldBeNil)
			So(actual, ShouldResemble, expected)
		}
	})

	Convey("split examples should be correct", t, func() {
		examples := map[string]interface{}{
			"store.book[0].title":           []string{"store", "book[0]", "title"},
			`["store"]["book"][0]["title"]`: []string{"store", "book[0]", "title"},
		}
		for input, expected := range examples {
			actual := split(input)
			So(actual, ShouldResemble, expected)
		}
	})

	Convey("splitBracket examples should be correct", t, func() {
		examples := map[string]interface{}{
			`a["hoge"].b`:    "hoge",
			`a["hoge"][123]`: "hoge[123]",
		}
		for input, expected := range examples {
			actual := splitBracket([]rune(input), 3, '"')
			So(actual, ShouldResemble, expected)
		}
	})

	Convey("getArrayIndex examples should be correct", t, func() {
		examples := map[string]interface{}{
			`hoge[123]`: "[123]",
		}
		for input, expected := range examples {
			actual := getArrayIndex([]rune(input), 5)
			So(actual, ShouldResemble, expected)
		}
	})
}

func TestScanMap(t *testing.T) {
	nestedData := Map{
		"nested.string":    String("keywithdot"),
		"nested..string":   String("keywithtwodots"),
		"nestedstring]":    String("keywithbracket"),
		"nested\"string":   String("keywithdoublequote"),
		"nested'string":    String("keywithsinglequote"),
		"nested\\\"string": String("keywithescapeddoublequote"),
		"nestedstring\\":   String("keywithbackslash"),
		"nested\nstring":   String("keywithnewline"),
		"内部マップ":            String("内部ﾏｯﾌﾟ"),
		"nestedstring":     String("normalkey"),
	}
	var testData = Map{
		"string":   String("homhom"),
		"array":    Array([]Value{String("saysay"), String("mammam")}),
		"map":      nestedData,
		"arraymap": Array([]Value{Map{"mappedstring": String("boo")}}),
	}
	Convey("Given a Map with values in it", t, func() {
		Convey("When accessing an empty string key", func() {
			var v Value
			err := scanMap(testData, "", &v)
			Convey("Then lookup should fail", func() {
				So(err, ShouldNotBeNil)
				So(err.Error(), ShouldEqual, "empty key is not supported")
			})
		})
		Convey("When accessing an invalid string key", func() {
			var v Value
			err := scanMap(testData, "ab[a", &v)
			Convey("Then lookup should fail", func() {
				So(err, ShouldNotBeNil)
				So(err.Error(), ShouldEqual, "invalid path component: ab[a")
			})
		})
		Convey("When accessing a non-existing key", func() {
			var v Value
			err := scanMap(testData, "str", &v)
			Convey("Then lookup should fail", func() {
				So(err, ShouldNotBeNil)
				So(err.Error(), ShouldEqual, "not found the key in map: str")
			})
		})
		Convey("When accessing an invalid index in array key", func() {
			var v Value
			err := scanMap(testData, "array[2147483648]", &v)
			Convey("Then lookup should fail", func() {
				So(err, ShouldNotBeNil)
				So(err.Error(), ShouldEqual, "overflow index number: array[2147483648]")
			})
		})
		Convey("When accessing an invalid array key", func() {
			var v Value
			err := scanMap(testData, "string[0]", &v)
			Convey("Then lookup should fail", func() {
				So(err, ShouldNotBeNil)
				So(err.Error(), ShouldEqual, "cannot access a tuple.String using index 0")
			})
		})
		Convey("When accessing only an array key", func() {
			var v Value
			err := scanMap(testData, "[0]", &v)
			Convey("Then lookup should fail", func() {
				So(err, ShouldNotBeNil)
				So(err.Error(), ShouldEqual, "cannot access a tuple.Map using index 0")
			})
		})
		Convey("When accessing an out-of-range index", func() {
			var v Value
			err := scanMap(testData, "array[2]", &v)
			Convey("Then lookup should fail", func() {
				So(err, ShouldNotBeNil)
				So(err.Error(), ShouldEqual, "out of range access: array[2]")
			})
		})

		Convey("When accessing nonsense bracket holders", func() {
			var x1, x2 Value
			err1 := scanMap(testData, `["string']`, &x1)
			err2 := scanMap(testData, `['string"]`, &x2)
			Convey("Then lookup should fail", func() {
				So(err1, ShouldNotBeNil)
				So(err2, ShouldNotBeNil)
			})
		})
		Convey("When accessing bracket holders", func() {
			var x1, x2 Value
			err1 := scanMap(testData, `["string"]`, &x1)
			err2 := scanMap(testData, "['string']", &x2)
			Convey("Then lookup should succeed", func() {
				So(err1, ShouldBeNil)
				So(err2, ShouldBeNil)
				Convey("and it should be match the original value", func() {
					s1, _ := x1.AsString()
					s2, _ := x2.AsString()
					So(s1, ShouldEqual, "homhom")
					So(s2, ShouldEqual, "homhom")
				})
			})
		})
		Convey("When accessing nested bracket holders", func() {
			Convey("With valid nested bracket", func() {
				samples := map[string]string{
					`map["nested.string"]`:  "keywithdot",
					`map['nested..string']`: "keywithtwodots",
					`map['nestedstring]']`:  "keywithbracket",
					`map['nested"string']`:  "keywithdoublequote",
					`map['nested'string']`:  "keywithsinglequote",
					`map['nested\"string']`: "keywithescapeddoublequote",
					`map['nestedstring\']`:  "keywithbackslash",
					"map['nested\nstring']": "keywithnewline",
					`map['内部マップ']`:          "内部ﾏｯﾌﾟ",
				}
				Convey("Then lookup should succeed and match the original value", func() {
					for input, expected := range samples {
						var v Value
						err := scanMap(testData, input, &v)
						So(err, ShouldBeNil)
						actual, _ := v.AsString()
						So(actual, ShouldEqual, expected)
					}
				})
			})
			Convey("With invalid nested bracket", func() {
				samples := []string{
					`map[]`,
					`map..nestedstring`, // currently invalid path
					`map[nestedstring]`,
					`map["nestedstring']`,
					`map['nestedstring"]`,
					`map[nested.string]`,
					`string["string"]`,
				}
				Convey("Then lookup should fail", func() {
					for idx, input := range samples {
						var v Value
						err := scanMap(testData, input, &v)
						if idx == 1 {
							SkipSo(err, ShouldNotBeNil)
						} else {
							So(err, ShouldNotBeNil)
						}

					}
				})
			})
		})
		Convey("When accessing bracket array holder", func() {
			Convey("With valid array index", func() {
				samples := map[string]string{
					`['array'][0]`:                    "saysay",
					`array[0]`:                        "saysay",
					`array.[0]`:                       "saysay",
					`array[0].`:                       "saysay",
					`['arraymap'][0]['mappedstring']`: "boo",
				}
				Convey("Then lookup should succeed and match the original value", func() {
					for input, expected := range samples {
						var v Value
						err := scanMap(testData, input, &v)
						So(err, ShouldBeNil)
						actual, _ := v.AsString()
						So(actual, ShouldEqual, expected)
					}
				})
			})
			Convey("With invalid array index", func() {
				samples := []string{
					`array[０]`, // zenkaku
					`array[0][`,
					`array[0]]`,
					`array[-1]`,
					`array[0:1]`,
				}
				Convey("Then lookup should fail", func() {
					for _, input := range samples {
						var v Value
						err := scanMap(testData, input, &v)
						So(err, ShouldNotBeNil)
						So(err.Error(), ShouldEqual, "invalid path component: "+input)

					}
				})
			})
		})
	})
}

func TestGetArrayIndex(t *testing.T) {
	Convey("Given strings including array index", t, func() {
		s := "[0]aaa[1]"
		Convey("Then getArrayIndex returns that index", func() {
			index1 := getArrayIndex([]rune(s), 1)
			index2 := getArrayIndex([]rune(s), 7)
			So(index1, ShouldEqual, "[0]")
			So(index2, ShouldEqual, "[1]")
		})
		Convey("Then getArrayIndex returns an empty string", func() {
			index1 := getArrayIndex([]rune(s), 0)
			index2 := getArrayIndex([]rune(s), 2)
			So(index1, ShouldEqual, "")
			So(index2, ShouldEqual, "")

		})
	})
}

func TestSplitBracket(t *testing.T) {
	Convey("Given a string that starts with bracket", t, func() {
		Convey("When the expression is valid", func() {
			samples := map[string]string{
				`[""]abc`:       "",
				`["a"]"]`:       "a",
				`['a']['`:       "a",
				`["ab\"]`:       "ab\\",
				`["a]b"]`:       "a]b",
				`["a"b"]`:       "a\"b",
				"a[\"hoge\"].b": "hoge",
				`a["hog"e"].b`:  "hog\"e",
				`a["b"][123]`:   "b[123]",
				`a["b"][]`:      "b",
			}
			Convey("Then splitBracket() returns the contained string", func() {
				for input, expected := range samples {
					from := 2
					if input[0] == 'a' {
						from = 3
					}
					quote := '"'
					if input[1] == '\'' {
						quote = '\''
					}
					actual := splitBracket([]rune(input), from, quote)
					So(actual, ShouldEqual, expected)
				}
			})
		})
		Convey("When the expression is invalid", func() {
			samples := []string{
				`["a`,
				`['a`,
				`['a"]`,
				`["ab']`,
				`["a]`,
				`["a"`,
			}
			Convey("Then splitBracket() returns an empty string", func() {
				for _, input := range samples {
					quote := '"'
					if input[1] == '\'' {
						quote = '\''
					}
					actual := splitBracket([]rune(input), 2, quote)
					So(actual, ShouldEqual, "")
				}
			})
		})
	})
}

func TestSplit(t *testing.T) {
	Convey("Given a path expression", t, func() {
		samples := map[string][]string{
			`path1.pa\.th2.[pa]th3["path4"]['path5'][0]path6[0]`: []string{"path1", "pa.th2", "[pa]th3", "path4", "path5[0]", "path6[0]"},
			`path1..path2.["path3\"].['pat.h4'].path5`:           []string{"path1", "path2", "path3\\", "pat.h4", "path5"},
			`path1["path1']`:                                     []string{"path1[\"path1']"},
			`path2['path2"]`:                                     []string{"path2['path2\"]"},
		}
		Convey("Then split() returns a proper list of components", func() {
			for input, expected := range samples {
				actual := split(input)
				So(actual, ShouldResemble, expected)
			}
		})
	})
}
<commit_msg>add more "err ShouldBeNil" checks<commit_after>package tuple

import (
	. "github.com/smartystreets/goconvey/convey"
	"testing"
)

func TestMapscanDocstrings(t *testing.T) {
	storeData := Map{
		"name": String("store name"),
		"book": Array([]Value{
			Map{
				"title": String("book name"),
			},
		}),
	}
	m := Map{"store": storeData}

	Convey("Map.Get examples should be correct", t, func() {
		examples := map[string]interface{}{
			"store":                         storeData,
			"store.name":                    String("store name"),
			"store.book[0].title":           String("book name"),
			`["store"]`:                     storeData,
			`["store"]["name"]`:             String("store name"),
			`["store"]["book"][0]["title"]`: String("book name"),
		}
		for input, expected := range examples {
			actual, err := m.Get(input)
			So(err, ShouldBeNil)
			So(actual, ShouldResemble, expected)
		}
	})

	Convey("split examples should be correct", t, func() {
		examples := map[string]interface{}{
			"store.book[0].title":           []string{"store", "book[0]", "title"},
			`["store"]["book"][0]["title"]`: []string{"store", "book[0]", "title"},
		}
		for input, expected := range examples {
			actual := split(input)
			So(actual, ShouldResemble, expected)
		}
	})

	Convey("splitBracket examples should be correct", t, func() {
		examples := map[string]interface{}{
			`a["hoge"].b`:    "hoge",
			`a["hoge"][123]`: "hoge[123]",
		}
		for input, expected := range examples {
			actual := splitBracket([]rune(input), 3, '"')
			So(actual, ShouldResemble, expected)
		}
	})

	Convey("getArrayIndex examples should be correct", t, func() {
		examples := map[string]interface{}{
			`hoge[123]`: "[123]",
		}
		for input, expected := range examples {
			actual := getArrayIndex([]rune(input), 5)
			So(actual, ShouldResemble, expected)
		}
	})
}

func TestScanMap(t *testing.T) {
	nestedData := Map{
		"nested.string":    String("keywithdot"),
		"nested..string":   String("keywithtwodots"),
		"nestedstring]":    String("keywithbracket"),
		"nested\"string":   String("keywithdoublequote"),
		"nested'string":    String("keywithsinglequote"),
		"nested\\\"string": String("keywithescapeddoublequote"),
		"nestedstring\\":   String("keywithbackslash"),
		"nested\nstring":   String("keywithnewline"),
		"内部マップ":            String("内部ﾏｯﾌﾟ"),
		"nestedstring":     String("normalkey"),
	}
	var testData = Map{
		"string":   String("homhom"),
		"array":    Array([]Value{String("saysay"), String("mammam")}),
		"map":      nestedData,
		"arraymap": Array([]Value{Map{"mappedstring": String("boo")}}),
	}
	Convey("Given a Map with values in it", t, func() {
		Convey("When accessing an empty string key", func() {
			var v Value
			err := scanMap(testData, "", &v)
			Convey("Then lookup should fail", func() {
				So(err, ShouldNotBeNil)
				So(err.Error(), ShouldEqual, "empty key is not supported")
			})
		})
		Convey("When accessing an invalid string key", func() {
			var v Value
			err := scanMap(testData, "ab[a", &v)
			Convey("Then lookup should fail", func() {
				So(err, ShouldNotBeNil)
				So(err.Error(), ShouldEqual, "invalid path component: ab[a")
			})
		})
		Convey("When accessing a non-existing key", func() {
			var v Value
			err := scanMap(testData, "str", &v)
			Convey("Then lookup should fail", func() {
				So(err, ShouldNotBeNil)
				So(err.Error(), ShouldEqual, "not found the key in map: str")
			})
		})
		Convey("When accessing an invalid index in array key", func() {
			var v Value
			err := scanMap(testData, "array[2147483648]", &v)
			Convey("Then lookup should fail", func() {
				So(err, ShouldNotBeNil)
				So(err.Error(), ShouldEqual, "overflow index number: array[2147483648]")
			})
		})
		Convey("When accessing an invalid array key", func() {
			var v Value
			err := scanMap(testData, "string[0]", &v)
			Convey("Then lookup should fail", func() {
				So(err, ShouldNotBeNil)
				So(err.Error(), ShouldEqual, "cannot access a tuple.String using index 0")
			})
		})
		Convey("When accessing only an array key", func() {
			var v Value
			err := scanMap(testData, "[0]", &v)
			Convey("Then lookup should fail", func() {
				So(err, ShouldNotBeNil)
				So(err.Error(), ShouldEqual, "cannot access a tuple.Map using index 0")
			})
		})
		Convey("When accessing an out-of-range index", func() {
			var v Value
			err := scanMap(testData, "array[2]", &v)
			Convey("Then lookup should fail", func() {
				So(err, ShouldNotBeNil)
				So(err.Error(), ShouldEqual, "out of range access: array[2]")
			})
		})

		Convey("When accessing nonsense bracket holders", func() {
			var x1, x2 Value
			err1 := scanMap(testData, `["string']`, &x1)
			err2 := scanMap(testData, `['string"]`, &x2)
			Convey("Then lookup should fail", func() {
				So(err1, ShouldNotBeNil)
				So(err2, ShouldNotBeNil)
			})
		})
		Convey("When accessing bracket holders", func() {
			var x1, x2 Value
			err1 := scanMap(testData, `["string"]`, &x1)
			err2 := scanMap(testData, "['string']", &x2)
			Convey("Then lookup should succeed", func() {
				So(err1, ShouldBeNil)
				So(err2, ShouldBeNil)
				Convey("and it should be match the original value", func() {
					s1, err3 := x1.AsString()
					s2, err4 := x2.AsString()
					So(err3, ShouldBeNil)
					So(err4, ShouldBeNil)
					So(s1, ShouldEqual, "homhom")
					So(s2, ShouldEqual, "homhom")
				})
			})
		})
		Convey("When accessing nested bracket holders", func() {
			Convey("With valid nested bracket", func() {
				samples := map[string]string{
					`map["nested.string"]`:  "keywithdot",
					`map['nested..string']`: "keywithtwodots",
					`map['nestedstring]']`:  "keywithbracket",
					`map['nested"string']`:  "keywithdoublequote",
					`map['nested'string']`:  "keywithsinglequote",
					`map['nested\"string']`: "keywithescapeddoublequote",
					`map['nestedstring\']`:  "keywithbackslash",
					"map['nested\nstring']": "keywithnewline",
					`map['内部マップ']`:          "内部ﾏｯﾌﾟ",
				}
				Convey("Then lookup should succeed and match the original value", func() {
					for input, expected := range samples {
						var v Value
						err := scanMap(testData, input, &v)
						So(err, ShouldBeNil)
						actual, _ := v.AsString()
						So(actual, ShouldEqual, expected)
					}
				})
			})
			Convey("With invalid nested bracket", func() {
				samples := []string{
					`map[]`,
					`map..nestedstring`, // currently invalid path
					`map[nestedstring]`,
					`map["nestedstring']`,
					`map['nestedstring"]`,
					`map[nested.string]`,
					`string["string"]`,
				}
				Convey("Then lookup should fail", func() {
					for idx, input := range samples {
						var v Value
						err := scanMap(testData, input, &v)
						if idx == 1 {
							SkipSo(err, ShouldNotBeNil)
						} else {
							So(err, ShouldNotBeNil)
						}

					}
				})
			})
		})
		Convey("When accessing bracket array holder", func() {
			Convey("With valid array index", func() {
				samples := map[string]string{
					`['array'][0]`:                    "saysay",
					`array[0]`:                        "saysay",
					`array.[0]`:                       "saysay",
					`array[0].`:                       "saysay",
					`['arraymap'][0]['mappedstring']`: "boo",
				}
				Convey("Then lookup should succeed and match the original value", func() {
					for input, expected := range samples {
						var v Value
						err := scanMap(testData, input, &v)
						So(err, ShouldBeNil)
						actual, _ := v.AsString()
						So(actual, ShouldEqual, expected)
					}
				})
			})
			Convey("With invalid array index", func() {
				samples := []string{
					`array[０]`, // zenkaku
					`array[0][`,
					`array[0]]`,
					`array[-1]`,
					`array[0:1]`,
				}
				Convey("Then lookup should fail", func() {
					for _, input := range samples {
						var v Value
						err := scanMap(testData, input, &v)
						So(err, ShouldNotBeNil)
						So(err.Error(), ShouldEqual, "invalid path component: "+input)

					}
				})
			})
		})
	})
}

func TestGetArrayIndex(t *testing.T) {
	Convey("Given strings including array index", t, func() {
		s := "[0]aaa[1]"
		Convey("Then getArrayIndex returns that index", func() {
			index1 := getArrayIndex([]rune(s), 1)
			index2 := getArrayIndex([]rune(s), 7)
			So(index1, ShouldEqual, "[0]")
			So(index2, ShouldEqual, "[1]")
		})
		Convey("Then getArrayIndex returns an empty string", func() {
			index1 := getArrayIndex([]rune(s), 0)
			index2 := getArrayIndex([]rune(s), 2)
			So(index1, ShouldEqual, "")
			So(index2, ShouldEqual, "")

		})
	})
}

func TestSplitBracket(t *testing.T) {
	Convey("Given a string that starts with bracket", t, func() {
		Convey("When the expression is valid", func() {
			samples := map[string]string{
				`[""]abc`:       "",
				`["a"]"]`:       "a",
				`['a']['`:       "a",
				`["ab\"]`:       "ab\\",
				`["a]b"]`:       "a]b",
				`["a"b"]`:       "a\"b",
				"a[\"hoge\"].b": "hoge",
				`a["hog"e"].b`:  "hog\"e",
				`a["b"][123]`:   "b[123]",
				`a["b"][]`:      "b",
			}
			Convey("Then splitBracket() returns the contained string", func() {
				for input, expected := range samples {
					from := 2
					if input[0] == 'a' {
						from = 3
					}
					quote := '"'
					if input[1] == '\'' {
						quote = '\''
					}
					actual := splitBracket([]rune(input), from, quote)
					So(actual, ShouldEqual, expected)
				}
			})
		})
		Convey("When the expression is invalid", func() {
			samples := []string{
				`["a`,
				`['a`,
				`['a"]`,
				`["ab']`,
				`["a]`,
				`["a"`,
			}
			Convey("Then splitBracket() returns an empty string", func() {
				for _, input := range samples {
					quote := '"'
					if input[1] == '\'' {
						quote = '\''
					}
					actual := splitBracket([]rune(input), 2, quote)
					So(actual, ShouldEqual, "")
				}
			})
		})
	})
}

func TestSplit(t *testing.T) {
	Convey("Given a path expression", t, func() {
		samples := map[string][]string{
			`path1.pa\.th2.[pa]th3["path4"]['path5'][0]path6[0]`: []string{"path1", "pa.th2", "[pa]th3", "path4", "path5[0]", "path6[0]"},
			`path1..path2.["path3\"].['pat.h4'].path5`:           []string{"path1", "path2", "path3\\", "pat.h4", "path5"},
			`path1["path1']`:                                     []string{"path1[\"path1']"},
			`path2['path2"]`:                                     []string{"path2['path2\"]"},
		}
		Convey("Then split() returns a proper list of components", func() {
			for input, expected := range samples {
				actual := split(input)
				So(actual, ShouldResemble, expected)
			}
		})
	})
}
<|endoftext|>