<commit_before>package cf_mysql_service

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"

	"fmt"
	. "github.com/cloudfoundry-incubator/cf-test-helpers/cf"
	. "github.com/cloudfoundry-incubator/cf-test-helpers/generator"
	. "github.com/cloudfoundry-incubator/cf-test-helpers/runner"
	"strconv"
	"time"
)

var (
	_ = Describe("P-MySQL Service", func() {
		timeout := 120.0
		retryInterval := 1.0

		AssertAppIsRunning := func(appName string) {
			pingUri := AppUri(appName) + "/ping"
			fmt.Println("Checking that the app is responding at url: ", pingUri)
			Eventually(Curl(pingUri), timeout, retryInterval).Should(Say("OK"))
			fmt.Println("\n")
		}

		It("Registers a route", func() {
			uri := "http://" + IntegrationConfig.BrokerHost + "/v2/catalog"

			fmt.Println("Curling url: ", uri)
			Eventually(Curl(uri), timeout, retryInterval).Should(Say("HTTP Basic: Access denied."))
		})

		Describe("Service instance lifecycle", func() {
			var appName string

			BeforeEach(func() {
				appName = RandomName()
				Eventually(Cf("push", appName, "-m", "256M", "-p", sinatraPath, "-no-start"), 60*time.Second).Should(Exit(0))
			})

			AfterEach(func() {
				Eventually(Cf("delete", appName, "-f"), 20*time.Second).Should(Exit(0))
			})

			AssertLifeCycleBehavior := func(PlanName string) {
				It("Allows users to create, bind, write to, read from, unbind, and destroy a service instance a plan", func() {
					serviceInstanceName := RandomName()
					uri := AppUri(appName) + "/service/mysql/" + serviceInstanceName + "/mykey"

					Eventually(Cf("create-service", IntegrationConfig.ServiceName, PlanName, serviceInstanceName),
						60*time.Second).Should(Exit(0))

					Eventually(Cf("bind-service", appName, serviceInstanceName), 60*time.Second).Should(Exit(0))
					Eventually(Cf("start", appName), 5*60*time.Second).Should(Exit(0))
					AssertAppIsRunning(appName)

					fmt.Println("Posting to url: ", uri)
					Eventually(Curl("-d", "myvalue", uri), timeout, retryInterval).Should(Say("myvalue"))
					fmt.Println("\n")

					fmt.Println("Curling url: ", uri)
					Eventually(Curl(uri), timeout, retryInterval).Should(Say("myvalue"))
					fmt.Println("\n")

					Eventually(Cf("unbind-service", appName, serviceInstanceName), 20*time.Second).Should(Exit(0))
					Eventually(Cf("delete-service", "-f", serviceInstanceName), 20*time.Second).Should(Exit(0))
				})
			}

			Context("using a new service instance", func() {
				for _, plan := range IntegrationConfig.Plans {
					AssertLifeCycleBehavior(plan.Name)
				}
			})
		})

		Describe("Enforcing MySQL storage and connection quota", func() {
			var appName string
			var serviceInstanceName string

			BeforeEach(func() {
				appName = RandomName()
				serviceInstanceName = RandomName()

				Eventually(Cf("push", appName, "-m", "256M", "-p", sinatraPath, "-no-start"), 60*time.Second).Should(Exit(0))
			})

			AfterEach(func() {
				Eventually(Cf("unbind-service", appName, serviceInstanceName), 20*time.Second).Should(Exit(0))
				Eventually(Cf("delete-service", "-f", serviceInstanceName), 20*time.Second).Should(Exit(0))
				Eventually(Cf("delete", appName, "-f"), 20*time.Second).Should(Exit(0))
			})

			CreatesBindsAndStartsApp := func(PlanName string) {
				Eventually(Cf("create-service", IntegrationConfig.ServiceName, PlanName, serviceInstanceName),
					60*time.Second).Should(Exit(0))
				Eventually(Cf("bind-service", appName, serviceInstanceName), 60*time.Second).Should(Exit(0))
				Eventually(Cf("start", appName), 5*60*time.Second).Should(Exit(0))
				AssertAppIsRunning(appName)
			}

			AssertStorageQuotaBehavior := func(PlanName string, MaxStorageMb string) {
				It("enforces the storage quota for the plan", func() {
					CreatesBindsAndStartsApp(PlanName)

					quotaEnforcerSleepTime := 10 * time.Second
					uri := AppUri(appName) + "/service/mysql/" + serviceInstanceName + "/mykey"
					writeUri := AppUri(appName) + "/service/mysql/" + serviceInstanceName + "/write-bulk-data"
					deleteUri := AppUri(appName) + "/service/mysql/" + serviceInstanceName + "/delete-bulk-data"
					firstValue := RandomName()[:20]
					secondValue := RandomName()[:20]

					fmt.Println("*** Proving we can write")
					Eventually(Curl("-d", firstValue, uri), timeout, retryInterval).Should(Say(firstValue))
					fmt.Println("*** Proving we can read")
					Eventually(Curl(uri), timeout, retryInterval).Should(Say(firstValue))

					fmt.Println("*** Exceeding quota")
					Eventually(Curl("-d", MaxStorageMb, writeUri), 5*60*time.Second, retryInterval).Should(Say("Database now contains"))

					fmt.Println("*** Sleeping to let quota enforcer run")
					time.Sleep(quotaEnforcerSleepTime)

					fmt.Println("*** Proving we cannot write")
					Eventually(Curl("-d", firstValue, uri), timeout, retryInterval).Should(Say("Error: (INSERT|UPDATE) command denied .* for table 'data_values'"))
					fmt.Println("*** Proving we can read")
					Eventually(Curl(uri), timeout, retryInterval).Should(Say(firstValue))

					fmt.Println("*** Deleting below quota")
					Eventually(Curl("-d", "20", deleteUri), timeout, retryInterval).Should(Say("Database now contains"))

					fmt.Println("*** Sleeping to let quota enforcer run")
					time.Sleep(quotaEnforcerSleepTime)

					fmt.Println("*** Proving we can write")
					Eventually(Curl("-d", secondValue, uri), timeout, retryInterval).Should(Say(secondValue))
					fmt.Println("*** Proving we can read")
					Eventually(Curl(uri), timeout, retryInterval).Should(Say(secondValue))
				})
			}

			AssertConnectionQuotaBehavior := func(PlanName string) {
				It("enforces the connection quota for the plan", func() {
					CreatesBindsAndStartsApp(PlanName)

					uri := AppUri(appName) + "/connections/mysql/" + serviceInstanceName + "/"
					allowable_connection_num := IntegrationConfig.MaxUserConnections
					over_maximum_connection_num := allowable_connection_num + 1

					fmt.Println("*** Proving we can use the max num of connections")
					Eventually(Curl(uri+strconv.Itoa(allowable_connection_num)), timeout, retryInterval).Should(Say("success"))

					fmt.Println("*** Proving the connection quota is enforced")
					Eventually(Curl(uri+strconv.Itoa(over_maximum_connection_num)), timeout, retryInterval).Should(Say("Error"))
				})
			}

			Context("for each plan", func() {
				for _, plan := range IntegrationConfig.Plans {
					AssertStorageQuotaBehavior(plan.Name, strconv.Itoa(plan.MaxStorageMb))
					AssertConnectionQuotaBehavior(plan.Name)
				}
			})
		})
	})
)
<commit_msg>Quota enforcement tests write data in chunks<commit_after>package cf_mysql_service

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"

	"fmt"
	. "github.com/cloudfoundry-incubator/cf-test-helpers/cf"
	. "github.com/cloudfoundry-incubator/cf-test-helpers/generator"
	. "github.com/cloudfoundry-incubator/cf-test-helpers/runner"
	"strconv"
	"time"
)

var (
	_ = Describe("P-MySQL Service", func() {
		timeout := 120.0
		retryInterval := 1.0

		AssertAppIsRunning := func(appName string) {
			pingUri := AppUri(appName) + "/ping"
			fmt.Println("Checking that the app is responding at url: ", pingUri)
			Eventually(Curl(pingUri), timeout, retryInterval).Should(Say("OK"))
			fmt.Println("\n")
		}

		It("Registers a route", func() {
			uri := "http://" + IntegrationConfig.BrokerHost + "/v2/catalog"

			fmt.Println("Curling url: ", uri)
			Eventually(Curl(uri), timeout, retryInterval).Should(Say("HTTP Basic: Access denied."))
		})

		Describe("Service instance lifecycle", func() {
			var appName string

			BeforeEach(func() {
				appName = RandomName()
				Eventually(Cf("push", appName, "-m", "256M", "-p", sinatraPath, "-no-start"), 60*time.Second).Should(Exit(0))
			})

			AfterEach(func() {
				Eventually(Cf("delete", appName, "-f"), 20*time.Second).Should(Exit(0))
			})

			AssertLifeCycleBehavior := func(PlanName string) {
				It("Allows users to create, bind, write to, read from, unbind, and destroy a service instance a plan", func() {
					serviceInstanceName := RandomName()
					uri := AppUri(appName) + "/service/mysql/" + serviceInstanceName + "/mykey"

					Eventually(Cf("create-service", IntegrationConfig.ServiceName, PlanName, serviceInstanceName),
						60*time.Second).Should(Exit(0))

					Eventually(Cf("bind-service", appName, serviceInstanceName), 60*time.Second).Should(Exit(0))
					Eventually(Cf("start", appName), 5*60*time.Second).Should(Exit(0))
					AssertAppIsRunning(appName)

					fmt.Println("Posting to url: ", uri)
					Eventually(Curl("-d", "myvalue", uri), timeout, retryInterval).Should(Say("myvalue"))
					fmt.Println("\n")

					fmt.Println("Curling url: ", uri)
					Eventually(Curl(uri), timeout, retryInterval).Should(Say("myvalue"))
					fmt.Println("\n")

					Eventually(Cf("unbind-service", appName, serviceInstanceName), 20*time.Second).Should(Exit(0))
					Eventually(Cf("delete-service", "-f", serviceInstanceName), 20*time.Second).Should(Exit(0))
				})
			}

			Context("using a new service instance", func() {
				for _, plan := range IntegrationConfig.Plans {
					AssertLifeCycleBehavior(plan.Name)
				}
			})
		})

		Describe("Enforcing MySQL storage and connection quota", func() {
			var appName string
			var serviceInstanceName string

			BeforeEach(func() {
				appName = RandomName()
				serviceInstanceName = RandomName()

				Eventually(Cf("push", appName, "-m", "256M", "-p", sinatraPath, "-no-start"), 60*time.Second).Should(Exit(0))
			})

			AfterEach(func() {
				Eventually(Cf("unbind-service", appName, serviceInstanceName), 20*time.Second).Should(Exit(0))
				Eventually(Cf("delete-service", "-f", serviceInstanceName), 20*time.Second).Should(Exit(0))
				Eventually(Cf("delete", appName, "-f"), 20*time.Second).Should(Exit(0))
			})

			CreatesBindsAndStartsApp := func(PlanName string) {
				Eventually(Cf("create-service", IntegrationConfig.ServiceName, PlanName, serviceInstanceName),
					60*time.Second).Should(Exit(0))
				Eventually(Cf("bind-service", appName, serviceInstanceName), 60*time.Second).Should(Exit(0))
				Eventually(Cf("start", appName), 5*60*time.Second).Should(Exit(0))
				AssertAppIsRunning(appName)
			}

			AssertStorageQuotaBehavior := func(PlanName string, MaxStorageMb int) {
				It("enforces the storage quota for the plan", func() {
					CreatesBindsAndStartsApp(PlanName)

					quotaEnforcerSleepTime := 10 * time.Second
					uri := AppUri(appName) + "/service/mysql/" + serviceInstanceName + "/mykey"
					writeUri := AppUri(appName) + "/service/mysql/" + serviceInstanceName + "/write-bulk-data"
					deleteUri := AppUri(appName) + "/service/mysql/" + serviceInstanceName + "/delete-bulk-data"
					firstValue := RandomName()[:20]
					secondValue := RandomName()[:20]

					fmt.Println("*** Proving we can write")
					Eventually(Curl("-d", firstValue, uri), timeout, retryInterval).Should(Say(firstValue))
					fmt.Println("*** Proving we can read")
					Eventually(Curl(uri), timeout, retryInterval).Should(Say(firstValue))

					fmt.Println("*** Exceeding quota")

					mbToWrite := 100
					loopIterations := (MaxStorageMb / mbToWrite)
					if MaxStorageMb%mbToWrite == 0 {
						loopIterations += 1
					}

					for i := 0; i < loopIterations; i += 1 {
						Eventually(Curl("-v", "-d", strconv.Itoa(mbToWrite), writeUri), 5*60*time.Second, retryInterval).Should(Say("Database now contains"))
					}

					fmt.Println("*** Sleeping to let quota enforcer run")
					time.Sleep(quotaEnforcerSleepTime)

					fmt.Println("*** Proving we cannot write")
					Eventually(Curl("-d", firstValue, uri), timeout, retryInterval).Should(Say("Error: (INSERT|UPDATE) command denied .* for table 'data_values'"))
					fmt.Println("*** Proving we can read")
					Eventually(Curl(uri), timeout, retryInterval).Should(Say(firstValue))

					fmt.Println("*** Deleting below quota")
					Eventually(Curl("-d", "20", deleteUri), timeout, retryInterval).Should(Say("Database now contains"))

					fmt.Println("*** Sleeping to let quota enforcer run")
					time.Sleep(quotaEnforcerSleepTime)

					fmt.Println("*** Proving we can write")
					Eventually(Curl("-d", secondValue, uri), timeout, retryInterval).Should(Say(secondValue))
					fmt.Println("*** Proving we can read")
					Eventually(Curl(uri), timeout, retryInterval).Should(Say(secondValue))
				})
			}

			AssertConnectionQuotaBehavior := func(PlanName string) {
				It("enforces the connection quota for the plan", func() {
					CreatesBindsAndStartsApp(PlanName)

					uri := AppUri(appName) + "/connections/mysql/" + serviceInstanceName + "/"
					allowable_connection_num := IntegrationConfig.MaxUserConnections
					over_maximum_connection_num := allowable_connection_num + 1

					fmt.Println("*** Proving we can use the max num of connections")
					Eventually(Curl(uri+strconv.Itoa(allowable_connection_num)), timeout, retryInterval).Should(Say("success"))

					fmt.Println("*** Proving the connection quota is enforced")
					Eventually(Curl(uri+strconv.Itoa(over_maximum_connection_num)), timeout, retryInterval).Should(Say("Error"))
				})
			}

			Context("for each plan", func() {
				for _, plan := range IntegrationConfig.Plans {
					AssertStorageQuotaBehavior(plan.Name, plan.MaxStorageMb)
					AssertConnectionQuotaBehavior(plan.Name)
				}
			})
		})
	})
)
<|endoftext|>


<commit_before>package nerdz

import (
	"bytes"
	"database/sql"
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"

	"github.com/RangelReale/osin"
	"github.com/labstack/echo"
	"github.com/nerdzeu/nerdz-api/utils"
)

// isValidScope checks if scope is a valid scope
func (s *OAuth2Storage) isValidScope(scope string) error {
	scopes := strings.Split(scope, " ")
	for _, s := range scopes {
		parts := strings.Split(s, ":")
		if len(parts) != 2 {
			return errors.New("Scope (" + s + ") has invalid format. The valid format is: scope:[read,write]")
		}
		if !utils.InSlice(parts[0], Configuration.Scopes) {
			return errors.New("Requested scope (" + s + ") does not exist")
		}
		rw := strings.Split(parts[1], ",")
		for _, permission := range rw {
			if permission != "read" && permission != "write" {
				return errors.New("Invalid permission: " + permission + ". Allowed: read,write")
			}
		}
	}
	return nil
}

// OAuth2Storage implements osin.Storage interface
type OAuth2Storage struct {
}

// Clone the storage if needed. For example, using mgo, you can clone the session with session.Clone
// to avoid concurrent access problems.
// This is to avoid cloning the connection at each method access.
// Can return itself if not a problem.
func (s *OAuth2Storage) Clone() osin.Storage {
	return s
}

// Close the resources the Storage potentially holds (using Clone for example)
func (s *OAuth2Storage) Close() {
}

// GetClient loads the client by id (client_id)
func (s *OAuth2Storage) GetClient(id string) (osin.Client, error) {
	var err error
	var numericID uint64
	if numericID, err = strconv.ParseUint(id, 10, 64); err != nil {
		return nil, fmt.Errorf("invalid client_id: %s", id)
	}

	client := new(OAuth2Client)
	err = Db().First(client, numericID)
	return client, err
}

// SaveAuthorize saves authorize data.
func (s *OAuth2Storage) SaveAuthorize(data *osin.AuthorizeData) error {
	var clientID uint64
	var err error
	if clientID, err = strconv.ParseUint(data.Client.GetId(), 10, 64); err != nil {
		return err
	}

	if err = s.isValidScope(data.Scope); err != nil {
		return fmt.Errorf("Saving Authorize: " + err.Error())
	}

	d := &OAuth2AuthorizeData{
		ClientID: clientID,
		Code:     data.Code,
		// CreatedAt field is automatically filled by the dbms
		ExpiresIn:   uint64(data.ExpiresIn),
		RedirectURI: data.RedirectUri,
		Scope:       data.Scope,
		State:       data.State,
		UserID:      data.UserData.(uint64)}

	return Db().Create(d)
}

// LoadAuthorize looks up osin.AuthorizeData by a code.
// osin.Client information MUST be loaded together.
// Optionally can return error if expired.
func (s *OAuth2Storage) LoadAuthorize(code string) (*osin.AuthorizeData, error) {
	authorize := new(OAuth2AuthorizeData)
	e := Db().Model(OAuth2AuthorizeData{}).Where(&OAuth2AuthorizeData{Code: code}).Scan(authorize)
	if e != nil {
		return nil, e
	}
	if code != authorize.Code {
		return nil, errors.New("Authorization data not found")
	}

	authData := &osin.AuthorizeData{
		Code:        code,
		CreatedAt:   authorize.CreatedAt.Round(time.Second),
		ExpiresIn:   int32(authorize.ExpiresIn),
		RedirectUri: authorize.RedirectURI,
		Scope:       authorize.Scope,
		State:       authorize.State,
		UserData:    authorize.UserID}

	if authData.IsExpired() {
		return nil, errors.New("Authorization data expired")
	}

	if client, err := s.GetClient(strconv.FormatUint(authorize.ClientID, 10)); err == nil {
		authData.Client = client
		return authData, nil
	}
	return nil, errors.New("LoadAuthorize: Client not found")
}

// RemoveAuthorize revokes or deletes the authorization code.
func (s *OAuth2Storage) RemoveAuthorize(code string) error {
	return Db().Where(&OAuth2AuthorizeData{Code: code}).Delete(OAuth2AuthorizeData{})
}

// SaveAccess writes osin.AccessData.
// If RefreshToken is not blank, it must save in a way that can be loaded using LoadRefresh.
func (s *OAuth2Storage) SaveAccess(accessData *osin.AccessData) error {
	var clientID uint64
	var err error
	if clientID, err = strconv.ParseUint(accessData.Client.GetId(), 10, 64); err != nil {
		return errors.New("Invalid Client ID")
	}

	if err = s.isValidScope(accessData.Scope); err != nil {
		return fmt.Errorf("Saving Access: " + err.Error())
	}

	var accessDataIDPtr sql.NullInt64
	if accessData.AccessData != nil {
		var father OAuth2AccessData
		if err = Db().Model(OAuth2AccessData{}).Where(&OAuth2AccessData{AccessToken: accessData.AccessData.AccessToken}).Scan(&father); err != nil {
			return errors.New("Error fetching parent Access Data ID")
		}

		accessDataIDPtr.Int64, accessDataIDPtr.Valid = int64(father.ID), true
	}

	// required to fill the foreign key
	var authorizeDataIDPtr sql.NullInt64
	if accessData.AuthorizeData != nil {
		var authorizeData OAuth2AuthorizeData
		if err = Db().Model(OAuth2AuthorizeData{}).Where(&OAuth2AuthorizeData{Code: accessData.AuthorizeData.Code}).Scan(&authorizeData); err != nil {
			return fmt.Errorf("SaveAccess: can't load authorize data with code: %s", accessData.AuthorizeData.Code)
		}

		authorizeDataIDPtr.Int64, authorizeDataIDPtr.Valid = int64(authorizeData.ID), true
	}

	tx := Db().Begin()

	var refreshTokenFK sql.NullInt64

	oauthAccessData := &OAuth2AccessData{
		AccessDataID:    accessDataIDPtr,
		AccessToken:     accessData.AccessToken,
		AuthorizeDataID: authorizeDataIDPtr,
		ClientID:        clientID,
		//CreatedAt:       accessData.CreatedAt, <- dbms handled
		ExpiresIn:   uint64(accessData.ExpiresIn),
		RedirectURI: accessData.RedirectUri,
		Scope:       accessData.Scope,
		UserID:      accessData.UserData.(uint64)}

	if accessData.RefreshToken != "" {
		// Create refresh token
		var newRefreshToken OAuth2RefreshToken
		newRefreshToken.Token = accessData.RefreshToken
		if err := tx.Create(&newRefreshToken); err != nil {
			tx.Rollback()
			return err
		}
		refreshTokenFK.Int64 = int64(newRefreshToken.ID)
		refreshTokenFK.Valid = true
	}

	// Put refresh token id, into OAuth2AccessData.refreshtoken fk
	oauthAccessData.RefreshTokenID = refreshTokenFK

	if err := tx.Create(oauthAccessData); err != nil {
		tx.Rollback()
		return err
	}

	if err := tx.Commit(); err != nil {
		return err
	}

	return nil
}

// LoadAccess retrieves access data by token. osin.Client information MUST be loaded together.
// osin.AuthorizeData and osin.AccessData DON'T NEED to be loaded if not easily available.
// Optionally can return error if expired.
func (s *OAuth2Storage) LoadAccess(token string) (*osin.AccessData, error) {
	oad := new(OAuth2AccessData)
	if err := Db().Model(OAuth2AccessData{}).Where(&OAuth2AccessData{AccessToken: token}).Scan(oad); err != nil {
		return nil, errors.New("LoadAccess: AccessToken not found")
	}

	var ret osin.AccessData

	ret.CreatedAt = oad.CreatedAt
	ret.ExpiresIn = int32(oad.ExpiresIn)
	if ret.IsExpired() {
		return nil, errors.New("Access token expired")
	}

	if client, err := s.GetClient(strconv.FormatUint(oad.ClientID, 10)); err == nil {
		ret.Client = client
	} else {
		return nil, err
	}

	ret.AccessToken = token
	ret.Scope = oad.Scope
	ret.RedirectUri = oad.RedirectURI
	ret.UserData = oad.UserID

	if oad.RefreshTokenID.Valid {
		var refreshToken OAuth2RefreshToken
		if err := Db().First(&refreshToken, uint64(oad.RefreshTokenID.Int64)); err != nil {
			return nil, err
		}
		ret.RefreshToken = refreshToken.Token
	}

	return &ret, nil
}

// RemoveAccess revokes or deletes an osin.AccessData.
func (s *OAuth2Storage) RemoveAccess(token string) error {
	return Db().Where(&OAuth2AccessData{AccessToken: token}).Delete(OAuth2AccessData{})
}

// LoadRefresh retrieves refresh osin.AccessData. osin.Client information MUST be loaded together.
// osin.AuthorizeData and osin.AccessData DON'T NEED to be loaded if not easily available.
// Optionally can return error if expired.
func (s *OAuth2Storage) LoadRefresh(token string) (*osin.AccessData, error) {
	var pointedAccessData OAuth2AccessData
	var refreshToken OAuth2RefreshToken
	if err := Db().Model(OAuth2RefreshToken{}).Where(&OAuth2RefreshToken{Token: token}).Scan(&refreshToken); err != nil {
		return nil, errors.New("Refresh token not found")
	}

	var refreshTokenNullInt64 sql.NullInt64
	refreshTokenNullInt64.Int64, refreshTokenNullInt64.Valid = int64(refreshToken.ID), true

	if err := Db().Model(OAuth2AccessData{}).Where(&OAuth2AccessData{RefreshTokenID: refreshTokenNullInt64}).Scan(&pointedAccessData); err != nil {
		return nil, err
	}
	return s.LoadAccess(pointedAccessData.AccessToken)
}

// RemoveRefresh revokes or deletes refresh osin.AccessData.
func (s *OAuth2Storage) RemoveRefresh(token string) error {
	return Db().Where(&OAuth2RefreshToken{Token: token}).Delete(OAuth2RefreshToken{})
}

// Implementing the osin.Client interface

// GetId returns the client ID
func (d *OAuth2Client) GetId() string {
	return strconv.FormatUint(d.ID, 10)
}

// GetSecret returns the client secret
func (d *OAuth2Client) GetSecret() string {
	return d.Secret
}

// GetRedirectUri returns the client redirect URI
func (d *OAuth2Client) GetRedirectUri() string {
	return d.RedirectURI
}

// GetUserData returns client UserData
func (d *OAuth2Client) GetUserData() interface{} {
	return d.UserID
}

// Additional methods

// RemoveClient removes the client by id (primary key)
func (s *OAuth2Storage) RemoveClient(id uint64) error {
	if id <= 0 {
		return errors.New("Invalid client id")
	}

	return Db().Where(&OAuth2Client{ID: id}).Delete(OAuth2Client{})
}

// CreateClient creates a new OAuth2 Client
func (s *OAuth2Storage) CreateClient(c osin.Client, name string) (*OAuth2Client, error) {
	client := OAuth2Client{
		Name:        name,
		RedirectURI: c.GetRedirectUri(),
		Secret:      c.GetSecret(),
		UserID:      c.GetUserData().(uint64),
	}

	if err := Db().Create(&client); err != nil {
		return nil, err
	}

	return &client, nil
}

// UpdateClient update client with id c.GetId()
func (s *OAuth2Storage) UpdateClient(c osin.Client) (*OAuth2Client, error) {
	var numericID uint64
	var err error
	if numericID, err = strconv.ParseUint(c.GetId(), 10, 64); err != nil {
		return nil, fmt.Errorf("invalid client_id: %s", c.GetId())
	}

	client := OAuth2Client{
		ID:          numericID,
		RedirectURI: c.GetRedirectUri(),
		Secret:      c.GetSecret(),
		UserID:      c.GetUserData().(uint64),
	}

	if err := Db().Updates(&client); err != nil {
		return nil, err
	}

	return &client, nil
}

// HandleLoginPage is an helper used by the OAuth2 authentication process to login the user (if it's not logged)
// and to show a basic login form that redirect to the authorization endpoint
func HandleLoginPage(ar *osin.AuthorizeRequest, c *echo.Context) (*User, error) {
	r := c.Request()
	r.ParseForm()
	if r.Method == "POST" {
		if user, err := Login(r.Form.Get("login"), r.Form.Get("password")); err == nil { // succcessful logged in
			return user, nil
		} else {
			c.HTML(http.StatusBadRequest, ""+err.Error()+"")
			return nil, err
		}
	}

	var buffer bytes.Buffer
	buffer.WriteString("")
	buffer.WriteString(fmt.Sprintf("LOGIN %s
", (ar.Client.(*OAuth2Client)).Name))
	buffer.WriteString(
		fmt.Sprintf(`<form action="authorize?response_type=%s&client_id=%s&state=%s&redirect_uri=%s&scope=%s" method="POST">`,
			ar.Type, ar.Client.GetId(), ar.State, url.QueryEscape(ar.RedirectUri), url.QueryEscape(ar.Scope)))

	buffer.WriteString(`Login: <input type="text" name="login" /><br/>`)
	buffer.WriteString(`Password: <input type="password" name="password" /><br/>`)
	buffer.WriteString(`<input type="submit"/>`)
	buffer.WriteString("</form>")
	c.HTML(http.StatusOK, buffer.String())
	return nil, errors.New("Login required")
}

// DownloadAccessToken is an helper used by the OAuth2 basic authentication process. It downloads the access token
func DownloadAccessToken(url string, auth *osin.BasicAuth, output map[string]interface{}) error {
	// download access token
	preq, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return err
	}
	if auth != nil {
		preq.SetBasicAuth(auth.Username, auth.Password)
	}

	pclient := &http.Client{}
	presp, err := pclient.Do(preq)
	if err != nil {
		return err
	}

	if presp.StatusCode != 200 {
		return errors.New("Invalid status code")
	}

	jdec := json.NewDecoder(presp.Body)
	err = jdec.Decode(&output)
	return err
}
<commit_msg>Upgrading to echo v2<commit_after>package nerdz

import (
	"bytes"
	"database/sql"
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"

	"github.com/RangelReale/osin"
	"github.com/labstack/echo"
	"github.com/nerdzeu/nerdz-api/utils"
)

// isValidScope checks if scope is a valid scope
func (s *OAuth2Storage) isValidScope(scope string) error {
	scopes := strings.Split(scope, " ")
	for _, s := range scopes {
		parts := strings.Split(s, ":")
		if len(parts) != 2 {
			return errors.New("Scope (" + s + ") has invalid format. The valid format is: scope:[read,write]")
		}
		if !utils.InSlice(parts[0], Configuration.Scopes) {
			return errors.New("Requested scope (" + s + ") does not exist")
		}
		rw := strings.Split(parts[1], ",")
		for _, permission := range rw {
			if permission != "read" && permission != "write" {
				return errors.New("Invalid permission: " + permission + ". Allowed: read,write")
			}
		}
	}
	return nil
}

// OAuth2Storage implements osin.Storage interface
type OAuth2Storage struct {
}

// Clone the storage if needed. For example, using mgo, you can clone the session with session.Clone
// to avoid concurrent access problems.
// This is to avoid cloning the connection at each method access.
// Can return itself if not a problem.
func (s *OAuth2Storage) Clone() osin.Storage {
	return s
}

// Close the resources the Storage potentially holds (using Clone for example)
func (s *OAuth2Storage) Close() {
}

// GetClient loads the client by id (client_id)
func (s *OAuth2Storage) GetClient(id string) (osin.Client, error) {
	var err error
	var numericID uint64
	if numericID, err = strconv.ParseUint(id, 10, 64); err != nil {
		return nil, fmt.Errorf("invalid client_id: %s", id)
	}

	client := new(OAuth2Client)
	err = Db().First(client, numericID)
	return client, err
}

// SaveAuthorize saves authorize data.
func (s *OAuth2Storage) SaveAuthorize(data *osin.AuthorizeData) error {
	var clientID uint64
	var err error
	if clientID, err = strconv.ParseUint(data.Client.GetId(), 10, 64); err != nil {
		return err
	}

	if err = s.isValidScope(data.Scope); err != nil {
		return fmt.Errorf("Saving Authorize: " + err.Error())
	}

	d := &OAuth2AuthorizeData{
		ClientID: clientID,
		Code:     data.Code,
		// CreatedAt field is automatically filled by the dbms
		ExpiresIn:   uint64(data.ExpiresIn),
		RedirectURI: data.RedirectUri,
		Scope:       data.Scope,
		State:       data.State,
		UserID:      data.UserData.(uint64)}

	return Db().Create(d)
}

// LoadAuthorize looks up osin.AuthorizeData by a code.
// osin.Client information MUST be loaded together.
// Optionally can return error if expired.
func (s *OAuth2Storage) LoadAuthorize(code string) (*osin.AuthorizeData, error) {
	authorize := new(OAuth2AuthorizeData)
	e := Db().Model(OAuth2AuthorizeData{}).Where(&OAuth2AuthorizeData{Code: code}).Scan(authorize)
	if e != nil {
		return nil, e
	}
	if code != authorize.Code {
		return nil, errors.New("Authorization data not found")
	}

	authData := &osin.AuthorizeData{
		Code:        code,
		CreatedAt:   authorize.CreatedAt.Round(time.Second),
		ExpiresIn:   int32(authorize.ExpiresIn),
		RedirectUri: authorize.RedirectURI,
		Scope:       authorize.Scope,
		State:       authorize.State,
		UserData:    authorize.UserID}

	if authData.IsExpired() {
		return nil, errors.New("Authorization data expired")
	}

	if client, err := s.GetClient(strconv.FormatUint(authorize.ClientID, 10)); err == nil {
		authData.Client = client
		return authData, nil
	}
	return nil, errors.New("LoadAuthorize: Client not found")
}

// RemoveAuthorize revokes or deletes the authorization code.
func (s *OAuth2Storage) RemoveAuthorize(code string) error {
	return Db().Where(&OAuth2AuthorizeData{Code: code}).Delete(OAuth2AuthorizeData{})
}

// SaveAccess writes osin.AccessData.
// If RefreshToken is not blank, it must save in a way that can be loaded using LoadRefresh.
func (s *OAuth2Storage) SaveAccess(accessData *osin.AccessData) error {
	var clientID uint64
	var err error
	if clientID, err = strconv.ParseUint(accessData.Client.GetId(), 10, 64); err != nil {
		return errors.New("Invalid Client ID")
	}

	if err = s.isValidScope(accessData.Scope); err != nil {
		return fmt.Errorf("Saving Access: " + err.Error())
	}

	var accessDataIDPtr sql.NullInt64
	if accessData.AccessData != nil {
		var father OAuth2AccessData
		if err = Db().Model(OAuth2AccessData{}).Where(&OAuth2AccessData{AccessToken: accessData.AccessData.AccessToken}).Scan(&father); err != nil {
			return errors.New("Error fetching parent Access Data ID")
		}

		accessDataIDPtr.Int64, accessDataIDPtr.Valid = int64(father.ID), true
	}

	// required to fill the foreign key
	var authorizeDataIDPtr sql.NullInt64
	if accessData.AuthorizeData != nil {
		var authorizeData OAuth2AuthorizeData
		if err = Db().Model(OAuth2AuthorizeData{}).Where(&OAuth2AuthorizeData{Code: accessData.AuthorizeData.Code}).Scan(&authorizeData); err != nil {
			return fmt.Errorf("SaveAccess: can't load authorize data with code: %s", accessData.AuthorizeData.Code)
		}

		authorizeDataIDPtr.Int64, authorizeDataIDPtr.Valid = int64(authorizeData.ID), true
	}

	tx := Db().Begin()

	var refreshTokenFK sql.NullInt64

	oauthAccessData := &OAuth2AccessData{
		AccessDataID:    accessDataIDPtr,
		AccessToken:     accessData.AccessToken,
		AuthorizeDataID: authorizeDataIDPtr,
		ClientID:        clientID,
		//CreatedAt:       accessData.CreatedAt, <- dbms handled
		ExpiresIn:   uint64(accessData.ExpiresIn),
		RedirectURI: accessData.RedirectUri,
		Scope:       accessData.Scope,
		UserID:      accessData.UserData.(uint64)}

	if accessData.RefreshToken != "" {
		// Create refresh token
		var newRefreshToken OAuth2RefreshToken
		newRefreshToken.Token = accessData.RefreshToken
		if err := tx.Create(&newRefreshToken); err != nil {
			tx.Rollback()
			return err
		}
		refreshTokenFK.Int64 = int64(newRefreshToken.ID)
		refreshTokenFK.Valid = true
	}

	// Put refresh token id, into OAuth2AccessData.refreshtoken fk
	oauthAccessData.RefreshTokenID = refreshTokenFK

	if err := tx.Create(oauthAccessData); err != nil {
		tx.Rollback()
		return err
	}

	if err := tx.Commit(); err != nil {
		return err
	}

	return nil
}

// LoadAccess retrieves access data by token. osin.Client information MUST be loaded together.
// osin.AuthorizeData and osin.AccessData DON'T NEED to be loaded if not easily available.
// Optionally can return error if expired.
func (s *OAuth2Storage) LoadAccess(token string) (*osin.AccessData, error) {
	oad := new(OAuth2AccessData)
	if err := Db().Model(OAuth2AccessData{}).Where(&OAuth2AccessData{AccessToken: token}).Scan(oad); err != nil {
		return nil, errors.New("LoadAccess: AccessToken not found")
	}

	var ret osin.AccessData

	ret.CreatedAt = oad.CreatedAt
	ret.ExpiresIn = int32(oad.ExpiresIn)
	if ret.IsExpired() {
		return nil, errors.New("Access token expired")
	}

	if client, err := s.GetClient(strconv.FormatUint(oad.ClientID, 10)); err == nil {
		ret.Client = client
	} else {
		return nil, err
	}

	ret.AccessToken = token
	ret.Scope = oad.Scope
	ret.RedirectUri = oad.RedirectURI
	ret.UserData = oad.UserID

	if oad.RefreshTokenID.Valid {
		var refreshToken OAuth2RefreshToken
		if err := Db().First(&refreshToken, uint64(oad.RefreshTokenID.Int64)); err != nil {
			return nil, err
		}
		ret.RefreshToken = refreshToken.Token
	}

	return &ret, nil
}

// RemoveAccess revokes or deletes an osin.AccessData.
func (s *OAuth2Storage) RemoveAccess(token string) error {
	return Db().Where(&OAuth2AccessData{AccessToken: token}).Delete(OAuth2AccessData{})
}

// LoadRefresh retrieves refresh osin.AccessData. osin.Client information MUST be loaded together.
// osin.AuthorizeData and osin.AccessData DON'T NEED to be loaded if not easily available.
// Optionally can return error if expired.
func (s *OAuth2Storage) LoadRefresh(token string) (*osin.AccessData, error) {
	var pointedAccessData OAuth2AccessData
	var refreshToken OAuth2RefreshToken
	if err := Db().Model(OAuth2RefreshToken{}).Where(&OAuth2RefreshToken{Token: token}).Scan(&refreshToken); err != nil {
		return nil, errors.New("Refresh token not found")
	}

	var refreshTokenNullInt64 sql.NullInt64
	refreshTokenNullInt64.Int64, refreshTokenNullInt64.Valid = int64(refreshToken.ID), true

	if err := Db().Model(OAuth2AccessData{}).Where(&OAuth2AccessData{RefreshTokenID: refreshTokenNullInt64}).Scan(&pointedAccessData); err != nil {
		return nil, err
	}
	return s.LoadAccess(pointedAccessData.AccessToken)
}

// RemoveRefresh revokes or deletes refresh osin.AccessData.
func (s *OAuth2Storage) RemoveRefresh(token string) error {
	return Db().Where(&OAuth2RefreshToken{Token: token}).Delete(OAuth2RefreshToken{})
}

// Implementing the osin.Client interface

// GetId returns the client ID
func (d *OAuth2Client) GetId() string {
	return strconv.FormatUint(d.ID, 10)
}

// GetSecret returns the client secret
func (d *OAuth2Client) GetSecret() string {
	return d.Secret
}

// GetRedirectUri returns the client redirect URI
func (d *OAuth2Client) GetRedirectUri() string {
	return d.RedirectURI
}

// GetUserData returns client UserData
func (d *OAuth2Client) GetUserData() interface{} {
	return d.UserID
}

// Additional methods

// RemoveClient removes the client by id (primary key)
func (s *OAuth2Storage) RemoveClient(id uint64) error {
	if id <= 0 {
		return errors.New("Invalid client id")
	}

	return Db().Where(&OAuth2Client{ID: id}).Delete(OAuth2Client{})
}

// CreateClient creates a new OAuth2 Client
func (s *OAuth2Storage) CreateClient(c osin.Client, name string) (*OAuth2Client, error) {
	client := OAuth2Client{
		Name:        name,
		RedirectURI: c.GetRedirectUri(),
		Secret:      c.GetSecret(),
		UserID:      c.GetUserData().(uint64),
	}

	if err := Db().Create(&client); err != nil {
		return nil, err
	}

	return &client, nil
}

// UpdateClient update client with id c.GetId()
func (s *OAuth2Storage) UpdateClient(c osin.Client) (*OAuth2Client, error) {
	var numericID uint64
	var err error
	if numericID, err = strconv.ParseUint(c.GetId(), 10, 64); err != nil {
		return nil, fmt.Errorf("invalid client_id: %s", c.GetId())
	}

	client := OAuth2Client{
		ID:          numericID,
		RedirectURI: c.GetRedirectUri(),
		Secret:      c.GetSecret(),
		UserID:      c.GetUserData().(uint64),
	}

	if err := Db().Updates(&client); err != nil {
		return nil, err
	}

	return &client, nil
}

// HandleLoginPage is an helper used by the OAuth2 authentication process to login the user (if it's not logged)
// and to show a basic login form that redirect to the authorization endpoint
func HandleLoginPage(ar *osin.AuthorizeRequest, c echo.Context) (*User, error) {
	r := c.Request()
	if r.Method() == "POST" {
		if user, err := Login(r.FormValue("login"), r.FormValue("password")); err == nil { // succcessful logged in
			return user, nil
		} else {
			c.HTML(http.StatusBadRequest, ""+err.Error()+"")
			return nil, err
		}
	}

	var buffer bytes.Buffer
	buffer.WriteString("")
	buffer.WriteString(fmt.Sprintf("LOGIN %s
", (ar.Client.(*OAuth2Client)).Name))
	buffer.WriteString(
		fmt.Sprintf(`<form action="authorize?response_type=%s&client_id=%s&state=%s&redirect_uri=%s&scope=%s" method="POST">`,
			ar.Type, ar.Client.GetId(), ar.State, url.QueryEscape(ar.RedirectUri), url.QueryEscape(ar.Scope)))

	buffer.WriteString(`Login: <input type="text" name="login" /><br/>`)
	buffer.WriteString(`Password: <input type="password" name="password" /><br/>`)
	buffer.WriteString(`<input type="submit"/>`)
	buffer.WriteString("</form>")
	c.HTML(http.StatusOK, buffer.String())
	return nil, errors.New("Login required")
}

// DownloadAccessToken is an helper used by the OAuth2 basic authentication process. It downloads the access token
func DownloadAccessToken(url string, auth *osin.BasicAuth, output map[string]interface{}) error {
	// download access token
	preq, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return err
	}
	if auth != nil {
		preq.SetBasicAuth(auth.Username, auth.Password)
	}

	pclient := &http.Client{}
	presp, err := pclient.Do(preq)
	if err != nil {
		return err
	}

	if presp.StatusCode != 200 {
		return errors.New("Invalid status code")
	}

	jdec := json.NewDecoder(presp.Body)
	err = jdec.Decode(&output)
	return err
}
<|endoftext|>


<commit_before>package msgsystem

import (
	"fmt"
)

type MsgSubSystem interface {
	MessageInChan() chan Message
	SetMessageInChan(channel chan Message)

	MessageOutChan() chan Message
	SetMessageOutChan(channel chan Message)

	Name() string
	Run()
}

type Message struct {
    To  []string
    Msg string
}

var (
	MessagesIn = make(chan Message)
	MessagesOut = make(chan Message)

	subsystems []*MsgSubSystem
)

func init() {
	fmt.Println("Initializing messaging subsystem...")
}

func RegisterSubSystem(system MsgSubSystem) {
	fmt.Println("Registering msg-subsystem:", system.Name())

	system.SetMessageInChan(MessagesIn)
	system.SetMessageOutChan(MessagesOut)

	subsystems = append(subsystems, &system)
}

func StartSubSystems() {
	for _, system := range subsystems {
		(*system).Run()
	}
}
<commit_msg>* Added command message queues.<commit_after>package msgsystem

import (
	"fmt"
)

type MsgSubSystem interface {
	MessageInChan() chan Message
	SetMessageInChan(channel chan Message)

	MessageOutChan() chan Message
	SetMessageOutChan(channel chan Message)

	Name() string
	Run()
}

type Message struct {
    To  []string
    Msg string
}

var (
	CommandsIn = make(chan Message)
	MessagesOut = make(chan Message)

	subsystems []*MsgSubSystem
)

func init() {
	fmt.Println("Initializing messaging subsystem...")
}

func RegisterSubSystem(system MsgSubSystem) {
	fmt.Println("Registering msg-subsystem:", system.Name())

	system.SetMessageInChan(CommandsIn)
	system.SetMessageOutChan(MessagesOut)

	subsystems = append(subsystems, &system)
}

func StartSubSystems() {
	for _, system := range subsystems {
		(*system).Run()
	}
}
<|endoftext|>


<commit_before><commit_msg>Fixed the start_x unmarshalling.<commit_after><|endoftext|>


<commit_before>package etcd

const version = "v2"
<commit_msg>*: bump to v2.0.0<commit_after>package etcd

const (
	version        = "v2"
	packageVersion = "v2.0.0"
)
<|endoftext|>


<commit_before>package ethpub

import (
	"encoding/hex"
	"encoding/json"
	"github.com/ethereum/eth-go/ethchain"
	"github.com/ethereum/eth-go/ethutil"
	_ "log"
	"strings"
)

// Block interface exposed to QML
type PBlock struct {
	ref          *ethchain.Block
	Number       int    `json:"number"`
	Hash         string `json:"hash"`
	Transactions string `json:"transactions"`
	Time         int64  `json:"time"`
}

// Creates a new QML Block from a chain block
func NewPBlock(block *ethchain.Block) *PBlock {
	if block == nil {
		return nil
	}

	var ptxs []PTx
	for _, tx := range block.Transactions() {
		ptxs = append(ptxs, *NewPTx(tx))
	}

	txJson, err := json.Marshal(ptxs)
	if err != nil {
		return nil
	}

	return &PBlock{ref: block, Number: int(block.Number.Uint64()), Hash: ethutil.Hex(block.Hash()), Transactions: string(txJson), Time: block.Time}
}

func (self *PBlock) ToString() string {
	if self.ref != nil {
		return self.ref.String()
	}

	return ""
}

func (self *PBlock) GetTransaction(hash string) *PTx {
	tx := self.ref.GetTransaction(ethutil.FromHex(hash))
	if tx == nil {
		return nil
	}

	return NewPTx(tx)
}

type PTx struct {
	ref *ethchain.Transaction

	Value    string `json:"value"`
	Gas      string `json:"gas"`
	GasPrice string `json:"gasPrice"`
	Hash     string `json:"hash"`
	Address  string `json:"address"`
	Sender   string `json:"sender"`
	Data     string `json:"data"`
	Contract bool   `json:"isContract"`
}

func NewPTx(tx *ethchain.Transaction) *PTx {
	hash := hex.EncodeToString(tx.Hash())
	receiver := hex.EncodeToString(tx.Recipient)

	if receiver == "" {
		receiver = hex.EncodeToString(tx.CreationAddress())
	}
	sender := hex.EncodeToString(tx.Sender())
	data := strings.Join(ethchain.Disassemble(tx.Data), "\n")

	isContract := len(tx.Data) > 0

	return &PTx{ref: tx, Hash: hash, Value: ethutil.CurrencyToString(tx.Value), Address: receiver, Contract: isContract, Gas: tx.Gas.String(), GasPrice: tx.GasPrice.String(), Data: data, Sender: sender}
}

func (self *PTx) ToString() string {
	return self.ref.String()
}

type PKey struct {
	Address    string `json:"address"`
	PrivateKey string `json:"privateKey"`
	PublicKey  string `json:"publicKey"`
}

func NewPKey(key *ethutil.KeyPair) *PKey {
	return &PKey{ethutil.Hex(key.Address()), ethutil.Hex(key.PrivateKey), ethutil.Hex(key.PublicKey)}
}

type PReceipt struct {
	CreatedContract bool   `json:"createdContract"`
	Address         string `json:"address"`
	Hash            string `json:"hash"`
	Sender          string `json:"sender"`
}

func NewPReciept(contractCreation bool, creationAddress, hash, address []byte) *PReceipt {
	return &PReceipt{
		contractCreation,
		ethutil.Hex(creationAddress),
		ethutil.Hex(hash),
		ethutil.Hex(address),
	}
}

type PStateObject struct {
	object *ethchain.StateObject
}

func NewPStateObject(object *ethchain.StateObject) *PStateObject {
	return &PStateObject{object: object}
}

func (c *PStateObject) GetStorage(address string) string {
	// Because somehow, even if you return nil to QML it
	// still has some magical object so we can't rely on
	// undefined or null at the QML side
	if c.object != nil {
		val := c.object.GetMem(ethutil.Big("0x" + address))

		return val.BigInt().String()
	}

	return ""
}

func (c *PStateObject) Value() string {
	if c.object != nil {
		return c.object.Amount.String()
	}

	return ""
}

func (c *PStateObject) Address() string {
	if c.object != nil {
		return ethutil.Hex(c.object.Address())
	}

	return ""
}

func (c *PStateObject) Nonce() int {
	if c.object != nil {
		return int(c.object.Nonce)
	}

	return 0
}

func (c *PStateObject) Root() string {
	if c.object != nil {
		return ethutil.Hex(ethutil.NewValue(c.object.State().Root()).Bytes())
	}

	return "<err>"
}

func (c *PStateObject) IsContract() bool {
	if c.object != nil {
		return len(c.object.Script()) > 0
	}

	return false
}

func (c *PStateObject) Script() string {
	if c.object != nil {
		return strings.Join(ethchain.Disassemble(c.object.Script()), " ")
	}

	return ""
}

type PStorageState struct {
	StateAddress string
	Address      string
	Value        string
}

func NewPStorageState(storageObject *ethchain.StorageState) *PStorageState {
	return &PStorageState{ethutil.Hex(storageObject.StateAddress), ethutil.Hex(storageObject.Address), storageObject.Value.String()}
}
<commit_msg>Hooked up the Block Explorer to the Debugger so we can instantly debug made transactions<commit_after>package ethpub

import (
	"encoding/hex"
	"encoding/json"
	"github.com/ethereum/eth-go/ethchain"
	"github.com/ethereum/eth-go/ethutil"
	_ "log"
	"strings"
)

// Block interface exposed to QML
type PBlock struct {
	ref          *ethchain.Block
	Number       int    `json:"number"`
	Hash         string `json:"hash"`
	Transactions string `json:"transactions"`
	Time         int64  `json:"time"`
}

// Creates a new QML Block from a chain block
func NewPBlock(block *ethchain.Block) *PBlock {
	if block == nil {
		return nil
	}

	var ptxs []PTx
	for _, tx := range block.Transactions() {
		ptxs = append(ptxs, *NewPTx(tx))
	}

	txJson, err := json.Marshal(ptxs)
	if err != nil {
		return nil
	}

	return &PBlock{ref: block, Number: int(block.Number.Uint64()), Hash: ethutil.Hex(block.Hash()), Transactions: string(txJson), Time: block.Time}
}

func (self *PBlock) ToString() string {
	if self.ref != nil {
		return self.ref.String()
	}

	return ""
}

func (self *PBlock) GetTransaction(hash string) *PTx {
	tx := self.ref.GetTransaction(ethutil.FromHex(hash))
	if tx == nil {
		return nil
	}

	return NewPTx(tx)
}

type PTx struct {
	ref *ethchain.Transaction

	Value           string `json:"value"`
	Gas             string `json:"gas"`
	GasPrice        string `json:"gasPrice"`
	Hash            string `json:"hash"`
	Address         string `json:"address"`
	Sender          string `json:"sender"`
	RawData         string `json:"rawData"`
	Data            string `json:"data"`
	Contract        bool   `json:"isContract"`
	CreatesContract bool   `json:"createsContract"`
}

func NewPTx(tx *ethchain.Transaction) *PTx {
	hash := hex.EncodeToString(tx.Hash())
	receiver := hex.EncodeToString(tx.Recipient)

	if receiver == "" {
		receiver = hex.EncodeToString(tx.CreationAddress())
	}
	sender := hex.EncodeToString(tx.Sender())
	createsContract := tx.CreatesContract()

	data := strings.Join(ethchain.Disassemble(tx.Data), "\n")

	isContract := len(tx.Data) > 0

	return &PTx{ref: tx, Hash: hash, Value: ethutil.CurrencyToString(tx.Value), Address: receiver, Contract: isContract, Gas: tx.Gas.String(), GasPrice: tx.GasPrice.String(), Data: data, Sender: sender, CreatesContract: createsContract, RawData: hex.EncodeToString(tx.Data)}
}

func (self *PTx) ToString() string {
	return self.ref.String()
}

type PKey struct {
	Address    string `json:"address"`
	PrivateKey string `json:"privateKey"`
	PublicKey  string `json:"publicKey"`
}

func NewPKey(key *ethutil.KeyPair) *PKey {
	return &PKey{ethutil.Hex(key.Address()), ethutil.Hex(key.PrivateKey), ethutil.Hex(key.PublicKey)}
}

type PReceipt struct {
	CreatedContract bool   `json:"createdContract"`
	Address         string `json:"address"`
	Hash            string `json:"hash"`
	Sender          string `json:"sender"`
}

func NewPReciept(contractCreation bool, creationAddress, hash, address []byte) *PReceipt {
	return &PReceipt{
		contractCreation,
		ethutil.Hex(creationAddress),
		ethutil.Hex(hash),
		ethutil.Hex(address),
	}
}

type PStateObject struct {
	object *ethchain.StateObject
}

func NewPStateObject(object *ethchain.StateObject) *PStateObject {
	return &PStateObject{object: object}
}

func (c *PStateObject) GetStorage(address string) string {
	// Because somehow, even if you return nil to QML it
	// still has some magical object so we can't rely on
	// undefined or null at the QML side
	if c.object != nil {
		val := c.object.GetMem(ethutil.Big("0x" + address))

		return val.BigInt().String()
	}

	return ""
}

func (c *PStateObject) Value() string {
	if c.object != nil {
		return c.object.Amount.String()
	}

	return ""
}

func (c *PStateObject) Address() string {
	if c.object != nil {
		return ethutil.Hex(c.object.Address())
	}

	return ""
}

func (c *PStateObject) Nonce() int {
	if c.object != nil {
		return int(c.object.Nonce)
	}

	return 0
}

func (c *PStateObject) Root() string {
	if c.object != nil {
		return ethutil.Hex(ethutil.NewValue(c.object.State().Root()).Bytes())
	}

	return "<err>"
}

func (c *PStateObject) IsContract() bool {
	if c.object != nil {
		return len(c.object.Script()) > 0
	}

	return false
}

func (c *PStateObject) Script() string {
	if c.object != nil {
		return strings.Join(ethchain.Disassemble(c.object.Script()), " ")
	}

	return ""
}

type PStorageState struct {
	StateAddress string
	Address      string
	Value        string
}

func NewPStorageState(storageObject *ethchain.StorageState) *PStorageState {
	return &PStorageState{ethutil.Hex(storageObject.StateAddress), ethutil.Hex(storageObject.Address), storageObject.Value.String()}
}
<|endoftext|>


<commit_before>package eval

import (
	"errors"
	"io"
	"os"
	"strconv"
	"strings"
)

var builtins = map[string]func(*Evaluator, []string) error{
	"cd":      cd,
	"echo":    echo,
	"exit":    exit,
	"setpath": setpath,
}

func cd(_ *Evaluator, args []string) error {
	var dir string
	switch len(args) {
	case 0:
		dir = os.Getenv("HOME")
	case 1:
		dir = args[0]
	default:
		return errors.New("cd: too many arguments")
	}
	return os.Chdir(dir)
}

func echo(e *Evaluator, args []string) error {
	if len(args) == 0 {
		_, err := e.out.Write([]byte{'\n'})
		return err
	}
	_, err := io.WriteString(e.out, args[0])
	if err != nil {
		return err
	}
	if len(args) == 1 {
		_, err := e.out.Write([]byte{'\n'})
		return err
	}
	args = args[1:]
	for _, arg := range args {
		_, err := e.out.Write([]byte{' '})
		if err != nil {
			return err
		}
		_, err = io.WriteString(e.out, arg)
		if err != nil {
			return err
		}
	}
	_, err = e.out.Write([]byte{'\n'})
	return err
}

func exit(_ *Evaluator, args []string) error {
	var code int
	switch len(args) {
	case 0:
		//FIXME: exit with no args should use the exit code of the last command executed.
		code = 0
	case 1:
		i, err := strconv.Atoi(args[0])
		if err != nil {
			return err
		}
		code = i
	default:
		return errors.New("exit: too many arguments")
	}
	os.Exit(code)
	return nil
}

func setpath(_ *Evaluator, args []string) error {
	switch len(args) {
	case 0:
		return errors.New("setpath: need 1 or more arguments")
	}
	paths := strings.Split(os.Getenv("PATH"), ":")
	var newPaths []string
	for _, path := range paths {
		if contains(args, path) {
			continue
		}
		newPaths = append(newPaths, path)
	}
	newPaths = append(args, newPaths...)
	os.Setenv("PATH", strings.Join(newPaths, ":"))
	return nil
}

func contains(x []string, s string) bool {
	for i := range x {
		if x[i] == s {
			return true
		}
	}
	return false
}
<commit_msg>Add setenv command for users to set environment varlables<commit_after>package eval

import (
	"errors"
	"io"
	"os"
	"strconv"
	"strings"
)

var builtins = map[string]func(*Evaluator, []string) error{
	"cd":      cd,
	"echo":    echo,
	"exit":    exit,
	"setpath": setpath,
	"setenv":  setenv,
}

func cd(_ *Evaluator, args []string) error {
	var dir string
	switch len(args) {
	case 0:
		dir = os.Getenv("HOME")
	case 1:
		dir = args[0]
	default:
		return errors.New("cd: too many arguments")
	}
	return os.Chdir(dir)
}

func echo(e *Evaluator, args []string) error {
	if len(args) == 0 {
		_, err := e.out.Write([]byte{'\n'})
		return err
	}
	_, err := io.WriteString(e.out, args[0])
	if err != nil {
		return err
	}
	if len(args) == 1 {
		_, err := e.out.Write([]byte{'\n'})
		return err
	}
	args = args[1:]
	for _, arg := range args {
		_, err := e.out.Write([]byte{' '})
		if err != nil {
			return err
		}
		_, err = io.WriteString(e.out, arg)
		if err != nil {
			return err
		}
	}
	_, err = e.out.Write([]byte{'\n'})
	return err
}

func exit(_ *Evaluator, args []string) error {
	var code int
	switch len(args) {
	case 0:
		//FIXME: exit with no args should use the exit code of the last command executed.
		code = 0
	case 1:
		i, err := strconv.Atoi(args[0])
		if err != nil {
			return err
		}
		code = i
	default:
		return errors.New("exit: too many arguments")
	}
	os.Exit(code)
	return nil
}

func setpath(_ *Evaluator, args []string) error {
	switch len(args) {
	case 0:
		return errors.New("setpath: need 1 or more arguments")
	}
	paths := strings.Split(os.Getenv("PATH"), ":")
	var newPaths []string
	for _, path := range paths {
		if contains(args, path) {
			continue
		}
		newPaths = append(newPaths, path)
	}
	newPaths = append(args, newPaths...)
	os.Setenv("PATH", strings.Join(newPaths, ":"))
	return nil
}

func contains(x []string, s string) bool {
	for i := range x {
		if x[i] == s {
			return true
		}
	}
	return false
}

func setenv(_ *Evaluator, args []string) error {
	if len(args)%2 == 1 {
		return errors.New("setenv: need even arguments")
	}
	for i := 0; i < len(args); i += 2 {
		os.Setenv(args[i], args[i+1])
	}
	return nil
}
<|endoftext|>


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

package gce

import (
	"strings"
	"sync"

	"code.google.com/p/google-api-go-client/compute/v1"
	"github.com/juju/errors"
	"github.com/juju/loggo"

	"github.com/juju/juju/constraints"
	"github.com/juju/juju/environs"
	"github.com/juju/juju/environs/config"
	"github.com/juju/juju/environs/simplestreams"
	"github.com/juju/juju/instance"
	"github.com/juju/juju/provider/common"
)

// Note: This provider/environment does *not* implement storage.

const (
	metadataKeyRole = "juju-machine-role"
	// This is defined by the cloud-init code:
	// http://bazaar.launchpad.net/~cloud-init-dev/cloud-init/trunk/view/head:/cloudinit/sources/DataSourceGCE.py
	// http://cloudinit.readthedocs.org/en/latest/
	// https://cloud.google.com/compute/docs/metadata
	metadataKeyCloudInit = "user-data"
	metadataKeyEncoding  = "user-data-encoding"
	// GCE uses this specific key for authentication (*handwaving*)
	// https://cloud.google.com/compute/docs/instances#sshkeys
	metadataKeySSHKeys = "sshKeys"

	roleState = "state"

	// See https://cloud.google.com/compute/docs/operating-systems/linux-os#ubuntu
	// TODO(ericsnow) Should this be handled in cloud-images (i.e.
	// simplestreams)?
	imageBasePath = "projects/ubuntu-os-cloud/global/images/"
)

var (
	logger = loggo.GetLogger("juju.provider.gce")

	errNotImplemented = errors.NotImplementedf("gce provider")

	signedImageDataOnly = false
)

type environ struct {
	common.SupportsUnitPlacementPolicy

	name string

	lock sync.Mutex
	ecfg *environConfig

	gce *gceConnection
}

var _ environs.Environ = (*environ)(nil)
var _ simplestreams.HasRegion = (*environ)(nil)

// Name returns the name of the environment.
func (env *environ) Name() string {
	return env.name
}

// Provider returns the environment provider that created this env.
func (*environ) Provider() environs.EnvironProvider {
	return providerInstance
}

// Region returns the CloudSpec to use for the provider, as configured.
func (env *environ) Region() (simplestreams.CloudSpec, error) {
	cloudSpec, err := env.cloudSpec(env.ecfg.region())
	return cloudSpec, errors.Trace(err)
}

func (env *environ) cloudSpec(region string) (simplestreams.CloudSpec, error) {
	cloudSpec := simplestreams.CloudSpec{
		Region:   region,
		Endpoint: env.ecfg.imageEndpoint(),
	}
	return cloudSpec, nil
}

// SetConfig updates the env's configuration.
func (env *environ) SetConfig(cfg *config.Config) error {
	env.lock.Lock()
	defer env.lock.Unlock()

	// Build the config.
	var oldCfg *config.Config
	if env.ecfg != nil {
		oldCfg = env.ecfg.Config
	}
	cfg, err := providerInstance.Validate(cfg, oldCfg)
	if err != nil {
		return errors.Trace(err)
	}
	env.ecfg = &environConfig{cfg, cfg.UnknownAttrs()}

	// Connect and authenticate.
	env.gce = env.ecfg.newConnection()
	err = env.gce.connect(env.ecfg.auth())

	return errors.Trace(err)
}

func (env *environ) getSnapshot() *environ {
	env.lock.Lock()
	clone := *env
	// The config values are all immutable so we don't need to also copy
	// env.ecfg and env.gce by value. If that changes we need to
	// re-evaluate copying them by value.
	env.lock.Unlock()

	clone.lock = sync.Mutex{}
	return &clone
}

// Config returns the configuration data with which the env was created.
func (env *environ) Config() *config.Config {
	return env.getSnapshot().ecfg.Config
}

// Bootstrap creates a new instance, chosing the series and arch out of
// available tools. The series and arch are returned along with a func
// that must be called to finalize the bootstrap process by transferring
// the tools and installing the initial juju state server.
func (env *environ) Bootstrap(ctx environs.BootstrapContext, params environs.BootstrapParams) (arch, series string, _ environs.BootstrapFinalizer, _ error) {
	return common.Bootstrap(ctx, env, params)
}

// Destroy shuts down all known machines and destroys the rest of the
// known environment.
func (env *environ) Destroy() error {
	return common.Destroy(env)
}

// instance stuff

var instStatuses = []string{statusPending, statusStaging, statusRunning}

// Instances returns the available instances in the environment that
// match the provided instance IDs. For IDs that did not match any
// instances, the result at the corresponding index will be nil. In that
// case the error will be environs.ErrPartialInstances (or
// ErrNoInstances if none of the IDs match an instance).
func (env *environ) Instances(ids []instance.Id) ([]instance.Instance, error) {
	if len(ids) == 0 {
		return nil, environs.ErrNoInstances
	}

	instances, err := env.instances()
	if err != nil {
		// We don't return the error since we need to pack one instance
		// for each ID into the result. If there is a problem then we
		// will return either ErrPartialInstances or ErrNoInstances.
		// TODO(ericsnow) Skip returning here only for certain errors?
		logger.Errorf("failed to get instances from GCE: %v", err)
		err = errors.Trace(err)
	}

	// Build the result, matching the provided instance IDs.
	numFound := 0 // This will never be greater than len(ids).
	results := make([]instance.Instance, len(ids))
	for i, id := range ids {
		inst := findInst(id, instances)
		if inst == nil {
			numFound += 1
		}
		results[i] = inst
	}

	if numFound == 0 {
		if err == nil {
			err = environs.ErrNoInstances
		}
	} else if numFound != len(ids) {
		err = environs.ErrPartialInstances
	}
	return results, err
}

func rawInstances(env *environ) ([]*compute.Instance, error) {
	// rawInstances() only returns instances that are part of the
	// environment (instance IDs matches "juju-<env name>-machine-*").
	// This is important because otherwise juju will see they are not
	// tracked in state, assume they're stale/rogue, and shut them down.
	instances, err := env.gce.instances(env)
	err = errors.Trace(err)

	// We further filter on the instance status, regardless of if there
	// was any error.
	instances = filterInstances(instances, instStatuses...)
	return instances, err
}

func (env *environ) instances() ([]instance.Instance, error) {
	env = env.getSnapshot()

	instances, err := rawInstances(env)
	err = errors.Trace(err)

	// Turn *compute.Instance values into *environInstance values,
	// whether or not we got an error.
	var results []instance.Instance
	for _, raw := range instances {
		inst := newInstance(raw, env)
		results = append(results, inst)
	}

	return results, err
}

// StateServerInstances returns the IDs of the instances corresponding
// to juju state servers.
func (env *environ) StateServerInstances() ([]instance.Id, error) {
	env = env.getSnapshot()

	instances, err := rawInstances(env)
	if err != nil {
		return nil, errors.Trace(err)
	}

	var results []instance.Id
	for _, inst := range instances {
		role, ok := unpackMetadata(inst.Metadata)[metadataKeyRole]
		if ok && role == roleState {
			results = append(results, instance.Id(inst.Name))
		}
	}
	if len(results) == 0 {
		return nil, environs.ErrNotBootstrapped
	}
	return results, nil
}

func (env *environ) parsePlacement(placement string) (*gceAvailabilityZone, error) {
	pos := strings.IndexRune(placement, '=')
	if pos == -1 {
		return nil, errors.Errorf("unknown placement directive: %v", placement)
	}
	switch key, value := placement[:pos], placement[pos+1:]; key {
	case "zone":
		zoneName := value
		zones, err := env.AvailabilityZones()
		if err != nil {
			return nil, errors.Trace(err)
		}
		for _, z := range zones {
			if z.Name() == zoneName {
				return z.(*gceAvailabilityZone), nil
			}
		}
		return nil, errors.Errorf("invalid availability zone %q", zoneName)
	}
	return nil, errors.Errorf("unknown placement directive: %v", placement)
}

func checkInstanceType(cons constraints.Value) bool {
	// Constraint has an instance-type constraint so let's see if it is valid.
	for _, itype := range allInstanceTypes {
		if itype.Name == *cons.InstanceType {
			return true
		}
	}
	return false
}
<commit_msg>provider/gce: Fix a (logic) typo.<commit_after>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package gce

import (
	"strings"
	"sync"

	"code.google.com/p/google-api-go-client/compute/v1"
	"github.com/juju/errors"
	"github.com/juju/loggo"

	"github.com/juju/juju/constraints"
	"github.com/juju/juju/environs"
	"github.com/juju/juju/environs/config"
	"github.com/juju/juju/environs/simplestreams"
	"github.com/juju/juju/instance"
	"github.com/juju/juju/provider/common"
)

// Note: This provider/environment does *not* implement storage.

const (
	metadataKeyRole = "juju-machine-role"
	// This is defined by the cloud-init code:
	// http://bazaar.launchpad.net/~cloud-init-dev/cloud-init/trunk/view/head:/cloudinit/sources/DataSourceGCE.py
	// http://cloudinit.readthedocs.org/en/latest/
	// https://cloud.google.com/compute/docs/metadata
	metadataKeyCloudInit = "user-data"
	metadataKeyEncoding  = "user-data-encoding"
	// GCE uses this specific key for authentication (*handwaving*)
	// https://cloud.google.com/compute/docs/instances#sshkeys
	metadataKeySSHKeys = "sshKeys"

	roleState = "state"

	// See https://cloud.google.com/compute/docs/operating-systems/linux-os#ubuntu
	// TODO(ericsnow) Should this be handled in cloud-images (i.e.
	// simplestreams)?
	imageBasePath = "projects/ubuntu-os-cloud/global/images/"
)

var (
	logger = loggo.GetLogger("juju.provider.gce")

	errNotImplemented = errors.NotImplementedf("gce provider")

	signedImageDataOnly = false
)

type environ struct {
	common.SupportsUnitPlacementPolicy

	name string

	lock sync.Mutex
	ecfg *environConfig

	gce *gceConnection
}

var _ environs.Environ = (*environ)(nil)
var _ simplestreams.HasRegion = (*environ)(nil)

// Name returns the name of the environment.
func (env *environ) Name() string {
	return env.name
}

// Provider returns the environment provider that created this env.
func (*environ) Provider() environs.EnvironProvider {
	return providerInstance
}

// Region returns the CloudSpec to use for the provider, as configured.
func (env *environ) Region() (simplestreams.CloudSpec, error) {
	cloudSpec, err := env.cloudSpec(env.ecfg.region())
	return cloudSpec, errors.Trace(err)
}

func (env *environ) cloudSpec(region string) (simplestreams.CloudSpec, error) {
	cloudSpec := simplestreams.CloudSpec{
		Region:   region,
		Endpoint: env.ecfg.imageEndpoint(),
	}
	return cloudSpec, nil
}

// SetConfig updates the env's configuration.
func (env *environ) SetConfig(cfg *config.Config) error {
	env.lock.Lock()
	defer env.lock.Unlock()

	// Build the config.
	var oldCfg *config.Config
	if env.ecfg != nil {
		oldCfg = env.ecfg.Config
	}
	cfg, err := providerInstance.Validate(cfg, oldCfg)
	if err != nil {
		return errors.Trace(err)
	}
	env.ecfg = &environConfig{cfg, cfg.UnknownAttrs()}

	// Connect and authenticate.
	env.gce = env.ecfg.newConnection()
	err = env.gce.connect(env.ecfg.auth())

	return errors.Trace(err)
}

func (env *environ) getSnapshot() *environ {
	env.lock.Lock()
	clone := *env
	// The config values are all immutable so we don't need to also copy
	// env.ecfg and env.gce by value. If that changes we need to
	// re-evaluate copying them by value.
	env.lock.Unlock()

	clone.lock = sync.Mutex{}
	return &clone
}

// Config returns the configuration data with which the env was created.
func (env *environ) Config() *config.Config {
	return env.getSnapshot().ecfg.Config
}

// Bootstrap creates a new instance, chosing the series and arch out of
// available tools. The series and arch are returned along with a func
// that must be called to finalize the bootstrap process by transferring
// the tools and installing the initial juju state server.
func (env *environ) Bootstrap(ctx environs.BootstrapContext, params environs.BootstrapParams) (arch, series string, _ environs.BootstrapFinalizer, _ error) {
	return common.Bootstrap(ctx, env, params)
}

// Destroy shuts down all known machines and destroys the rest of the
// known environment.
func (env *environ) Destroy() error {
	return common.Destroy(env)
}

// instance stuff

var instStatuses = []string{statusPending, statusStaging, statusRunning}

// Instances returns the available instances in the environment that
// match the provided instance IDs. For IDs that did not match any
// instances, the result at the corresponding index will be nil. In that
// case the error will be environs.ErrPartialInstances (or
// ErrNoInstances if none of the IDs match an instance).
func (env *environ) Instances(ids []instance.Id) ([]instance.Instance, error) {
	if len(ids) == 0 {
		return nil, environs.ErrNoInstances
	}

	instances, err := env.instances()
	if err != nil {
		// We don't return the error since we need to pack one instance
		// for each ID into the result. If there is a problem then we
		// will return either ErrPartialInstances or ErrNoInstances.
		// TODO(ericsnow) Skip returning here only for certain errors?
		logger.Errorf("failed to get instances from GCE: %v", err)
		err = errors.Trace(err)
	}

	// Build the result, matching the provided instance IDs.
	numFound := 0 // This will never be greater than len(ids).
	results := make([]instance.Instance, len(ids))
	for i, id := range ids {
		inst := findInst(id, instances)
		if inst != nil {
			numFound += 1
		}
		results[i] = inst
	}

	if numFound == 0 {
		if err == nil {
			err = environs.ErrNoInstances
		}
	} else if numFound != len(ids) {
		err = environs.ErrPartialInstances
	}
	return results, err
}

func rawInstances(env *environ) ([]*compute.Instance, error) {
	// rawInstances() only returns instances that are part of the
	// environment (instance IDs matches "juju-<env name>-machine-*").
	// This is important because otherwise juju will see they are not
	// tracked in state, assume they're stale/rogue, and shut them down.
	instances, err := env.gce.instances(env)
	err = errors.Trace(err)

	// We further filter on the instance status, regardless of if there
	// was any error.
	instances = filterInstances(instances, instStatuses...)
	return instances, err
}

func (env *environ) instances() ([]instance.Instance, error) {
	env = env.getSnapshot()

	instances, err := rawInstances(env)
	err = errors.Trace(err)

	// Turn *compute.Instance values into *environInstance values,
	// whether or not we got an error.
	var results []instance.Instance
	for _, raw := range instances {
		inst := newInstance(raw, env)
		results = append(results, inst)
	}

	return results, err
}

// StateServerInstances returns the IDs of the instances corresponding
// to juju state servers.
func (env *environ) StateServerInstances() ([]instance.Id, error) {
	env = env.getSnapshot()

	instances, err := rawInstances(env)
	if err != nil {
		return nil, errors.Trace(err)
	}

	var results []instance.Id
	for _, inst := range instances {
		role, ok := unpackMetadata(inst.Metadata)[metadataKeyRole]
		if ok && role == roleState {
			results = append(results, instance.Id(inst.Name))
		}
	}
	if len(results) == 0 {
		return nil, environs.ErrNotBootstrapped
	}
	return results, nil
}

func (env *environ) parsePlacement(placement string) (*gceAvailabilityZone, error) {
	pos := strings.IndexRune(placement, '=')
	if pos == -1 {
		return nil, errors.Errorf("unknown placement directive: %v", placement)
	}
	switch key, value := placement[:pos], placement[pos+1:]; key {
	case "zone":
		zoneName := value
		zones, err := env.AvailabilityZones()
		if err != nil {
			return nil, errors.Trace(err)
		}
		for _, z := range zones {
			if z.Name() == zoneName {
				return z.(*gceAvailabilityZone), nil
			}
		}
		return nil, errors.Errorf("invalid availability zone %q", zoneName)
	}
	return nil, errors.Errorf("unknown placement directive: %v", placement)
}

func checkInstanceType(cons constraints.Value) bool {
	// Constraint has an instance-type constraint so let's see if it is valid.
	for _, itype := range allInstanceTypes {
		if itype.Name == *cons.InstanceType {
			return true
		}
	}
	return false
}
<|endoftext|>


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

package maas

import (
	"errors"
	"fmt"
	"net/url"
	"strings"

	"launchpad.net/juju-core/environs/config"
	"launchpad.net/juju-core/schema"
)

var configFields = schema.Fields{
	"maas-server": schema.String(),
	// maas-oauth is a colon-separated triplet of:
	// consumer-key:resource-token:resource-secret
	"maas-oauth": schema.String(),
}
var configDefaults = schema.Defaults{}

type maasEnvironConfig struct {
	*config.Config
	attrs map[string]interface{}
}

func (cfg *maasEnvironConfig) maasServer() string {
	return cfg.attrs["maas-server"].(string)
}

func (cfg *maasEnvironConfig) maasOAuth() string {
	return cfg.attrs["maas-oauth"].(string)
}

func (cfg *maasEnvironConfig) maasEnvironmentUUID() string {
	if uuid, ok := cfg.attrs["maas-environment-uuid"].(string); ok {
		return uuid
	}
	return ""
}

func (prov maasEnvironProvider) newConfig(cfg *config.Config) (*maasEnvironConfig, error) {
	validCfg, err := prov.Validate(cfg, nil)
	if err != nil {
		return nil, err
	}
	result := new(maasEnvironConfig)
	result.Config = validCfg
	result.attrs = validCfg.UnknownAttrs()
	return result, nil
}

var errMalformedMaasOAuth = errors.New("malformed maas-oauth (3 items separated by colons)")

func (prov maasEnvironProvider) Validate(cfg, oldCfg *config.Config) (*config.Config, error) {
	// Validate base configuration change before validating MAAS specifics.
	err := config.Validate(cfg, oldCfg)
	if err != nil {
		return nil, err
	}

	validated, err := cfg.ValidateUnknownAttrs(configFields, configDefaults)
	if err != nil {
		return nil, err
	}
	envCfg := new(maasEnvironConfig)
	envCfg.Config = cfg
	envCfg.attrs = validated
	server := envCfg.maasServer()
	serverURL, err := url.Parse(server)
	if err != nil || serverURL.Scheme == "" || serverURL.Host == "" {
		return nil, fmt.Errorf("malformed maas-server URL '%v': %s", server, err)
	}
	oauth := envCfg.maasOAuth()
	if strings.Count(oauth, ":") != 2 {
		return nil, errMalformedMaasOAuth
	}
	return cfg.Apply(envCfg.attrs)
}
<commit_msg>Make maas-environment-uuid an official config option.<commit_after>// Copyright 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package maas

import (
	"errors"
	"fmt"
	"net/url"
	"strings"

	"launchpad.net/juju-core/environs/config"
	"launchpad.net/juju-core/schema"
)

var configFields = schema.Fields{
	"maas-server": schema.String(),
	// maas-oauth is a colon-separated triplet of:
	// consumer-key:resource-token:resource-secret
	"maas-oauth": schema.String(),
	// maas-environment-uuid is an optional UUID to group the machines
	// acquired from MAAS, to support multiple environments per MAAS user.
	"maas-environment-uuid": schema.String(),
}
var configDefaults = schema.Defaults{
	// For backward-compatibility, maas-environment-uuid is the empty string
	// by default. However, new environments should all use a UUID.
	"maas-environment-uuid": "",
}

type maasEnvironConfig struct {
	*config.Config
	attrs map[string]interface{}
}

func (cfg *maasEnvironConfig) maasServer() string {
	return cfg.attrs["maas-server"].(string)
}

func (cfg *maasEnvironConfig) maasOAuth() string {
	return cfg.attrs["maas-oauth"].(string)
}

func (cfg *maasEnvironConfig) maasEnvironmentUUID() string {
	if uuid, ok := cfg.attrs["maas-environment-uuid"].(string); ok {
		return uuid
	}
	return ""
}

func (prov maasEnvironProvider) newConfig(cfg *config.Config) (*maasEnvironConfig, error) {
	validCfg, err := prov.Validate(cfg, nil)
	if err != nil {
		return nil, err
	}
	result := new(maasEnvironConfig)
	result.Config = validCfg
	result.attrs = validCfg.UnknownAttrs()
	return result, nil
}

var errMalformedMaasOAuth = errors.New("malformed maas-oauth (3 items separated by colons)")

func (prov maasEnvironProvider) Validate(cfg, oldCfg *config.Config) (*config.Config, error) {
	// Validate base configuration change before validating MAAS specifics.
	err := config.Validate(cfg, oldCfg)
	if err != nil {
		return nil, err
	}

	validated, err := cfg.ValidateUnknownAttrs(configFields, configDefaults)
	if err != nil {
		return nil, err
	}
	envCfg := new(maasEnvironConfig)
	envCfg.Config = cfg
	envCfg.attrs = validated
	server := envCfg.maasServer()
	serverURL, err := url.Parse(server)
	if err != nil || serverURL.Scheme == "" || serverURL.Host == "" {
		return nil, fmt.Errorf("malformed maas-server URL '%v': %s", server, err)
	}
	oauth := envCfg.maasOAuth()
	if strings.Count(oauth, ":") != 2 {
		return nil, errMalformedMaasOAuth
	}
	return cfg.Apply(envCfg.attrs)
}
<|endoftext|>


<commit_before>package tmysql

import (
	"fmt"
	"math/rand"
	"net/url"
	"time"

	"github.com/jinzhu/gorm"
	"github.com/tolexo/aero/conf"
	"github.com/tolexo/aero/db/orm"

	"github.com/jinzhu/gorm"
	"github.com/tolexo/aero/conf"
)

var (
	engines        map[string]gorm.DB
	connContainer  map[string]string
	connMySqlWrite string
	connMySqlRead  []string
)

func init() {
	engines = make(map[string]gorm.DB)
	connContainer = make(map[string]string)
}

func initMaster() {
	lookup := "database.master"
	if conf.Exists(lookup) {
		connMySqlWrite = getMySqlConnString(lookup)
	}
}
func initSlaves() {
	lookup := "database.slaves"
	if conf.Exists(lookup) {
		slaves := conf.StringSlice(lookup, []string{})
		connMySqlRead = make([]string, len(slaves))
		for i, container := range slaves {
			connMySqlRead[i] = getMySqlConnString(container)
		}
	}
}
func getMySqlConnString(container string) (connStr string) {
	if !conf.Exists(container) {
		panic("Container for mysql configuration not found")
	}
	username := conf.String(container+".username", "")
	password := conf.String(container+".password", "")
	host := conf.String(container+".host", "")
	port := conf.String(container+".port", "")
	db := conf.String(container+".db", "")
	timezone := conf.String(container+".timezone", "")

	connStr = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?parseTime=true&loc=%s",
		username, password,
		host, port, db,
		url.QueryEscape(timezone),
	)
	connContainer[connStr] = container
	return
}

func getDefaultConn(write bool) string {
	if write {
		initMaster()
		return connMySqlWrite
	} else {
		initSlaves()
		if connMySqlRead == nil || len(connMySqlRead) == 0 {
			initMaster()
			return connMySqlWrite
		}
		return connMySqlRead[rand.Intn(len(connMySqlRead))]
	}
}

//newConn will create new database connection and initialize all database setting
func newConn(connStr string) (dbConn gorm.DB, err error) {
	if dbConn, err = gorm.Open("mysql", connStr); err == nil {
		engines[connStr] = dbConn
		container := connContainer[connStr]
		connMaxLifetime := conf.Int(container+".maxlifetime", 10)
		maxIdleConns := conf.Int(container+".maxidleconn", 10)
		maxOpenConns := conf.Int(container+".maxopenconn", 200)
		dbConn.DB().SetConnMaxLifetime(time.Second * time.Duration(connMaxLifetime))
		dbConn.DB().SetMaxIdleConns(maxIdleConns)
		dbConn.DB().SetMaxOpenConns(maxOpenConns)
	}
	return
}

//Get MySql connection
func GetMySqlTmpConn(writable bool) (dbConn gorm.DB, err error) {
	dbConn = orm.Get(writable)
	return
}

//Get MySql connection
func GetMySqlConn(writable bool) (dbConn gorm.DB, err error) {
	var connExists bool
	connStr := getDefaultConn(writable)
	if dbConn, connExists = engines[connStr]; connExists == true {
		err = dbConn.DB().Ping()
	}
	if connExists == false || err != nil {
		dbConn, err = newConn(connStr)
	}
	return
}
<commit_msg>PRA-TMYSQL-POOL: package corrected<commit_after>package tmysql

import (
	"fmt"
	"math/rand"
	"net/url"
	"time"

	"github.com/jinzhu/gorm"
	"github.com/tolexo/aero/conf"
	"github.com/tolexo/aero/db/orm"
)

var (
	engines        map[string]gorm.DB
	connContainer  map[string]string
	connMySqlWrite string
	connMySqlRead  []string
)

func init() {
	engines = make(map[string]gorm.DB)
	connContainer = make(map[string]string)
}

func initMaster() {
	lookup := "database.master"
	if conf.Exists(lookup) {
		connMySqlWrite = getMySqlConnString(lookup)
	}
}
func initSlaves() {
	lookup := "database.slaves"
	if conf.Exists(lookup) {
		slaves := conf.StringSlice(lookup, []string{})
		connMySqlRead = make([]string, len(slaves))
		for i, container := range slaves {
			connMySqlRead[i] = getMySqlConnString(container)
		}
	}
}
func getMySqlConnString(container string) (connStr string) {
	if !conf.Exists(container) {
		panic("Container for mysql configuration not found")
	}
	username := conf.String(container+".username", "")
	password := conf.String(container+".password", "")
	host := conf.String(container+".host", "")
	port := conf.String(container+".port", "")
	db := conf.String(container+".db", "")
	timezone := conf.String(container+".timezone", "")

	connStr = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?parseTime=true&loc=%s",
		username, password,
		host, port, db,
		url.QueryEscape(timezone),
	)
	connContainer[connStr] = container
	return
}

func getDefaultConn(write bool) string {
	if write {
		initMaster()
		return connMySqlWrite
	} else {
		initSlaves()
		if connMySqlRead == nil || len(connMySqlRead) == 0 {
			initMaster()
			return connMySqlWrite
		}
		return connMySqlRead[rand.Intn(len(connMySqlRead))]
	}
}

//newConn will create new database connection and initialize all database setting
func newConn(connStr string) (dbConn gorm.DB, err error) {
	if dbConn, err = gorm.Open("mysql", connStr); err == nil {
		engines[connStr] = dbConn
		container := connContainer[connStr]
		connMaxLifetime := conf.Int(container+".maxlifetime", 10)
		maxIdleConns := conf.Int(container+".maxidleconn", 10)
		maxOpenConns := conf.Int(container+".maxopenconn", 200)
		dbConn.DB().SetConnMaxLifetime(time.Second * time.Duration(connMaxLifetime))
		dbConn.DB().SetMaxIdleConns(maxIdleConns)
		dbConn.DB().SetMaxOpenConns(maxOpenConns)
	}
	return
}

//Get MySql connection
func GetMySqlTmpConn(writable bool) (dbConn gorm.DB, err error) {
	dbConn = orm.Get(writable)
	return
}

//Get MySql connection
func GetMySqlConn(writable bool) (dbConn gorm.DB, err error) {
	var connExists bool
	connStr := getDefaultConn(writable)
	if dbConn, connExists = engines[connStr]; connExists == true {
		err = dbConn.DB().Ping()
	}
	if connExists == false || err != nil {
		dbConn, err = newConn(connStr)
	}
	return
}
<|endoftext|>


<commit_before>package css // import "github.com/tdewolff/parse/css"

import (
	"bytes"
	"fmt"
	"io"
	"strconv"
	"testing"

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

func assertTokens(t *testing.T, s string, tokentypes ...TokenType) {
	stringify := helperStringify(t, s)
	l := NewLexer(bytes.NewBufferString(s))
	i := 0
	for {
		tt, _ := l.Next()
		if tt == ErrorToken {
			assert.Equal(t, io.EOF, l.Err(), "error must be EOF in "+stringify)
			assert.Equal(t, len(tokentypes), i, "when error occurred we must be at the end in "+stringify)
			break
		} else if tt == WhitespaceToken {
			continue
		}
		assert.False(t, i >= len(tokentypes), "index must not exceed tokentypes size in "+stringify)
		if i < len(tokentypes) {
			assert.Equal(t, tokentypes[i], tt, "tokentypes must match at index "+strconv.Itoa(i)+" in "+stringify)
		}
		i++
	}
	return
}

func helperStringify(t *testing.T, input string) string {
	s := ""
	l := NewLexer(bytes.NewBufferString(input))
	for i := 0; i < 10; i++ {
		tt, text := l.Next()
		if tt == ErrorToken {
			s += tt.String() + "('" + l.Err().Error() + "')"
			break
		} else if tt == WhitespaceToken {
			continue
		} else {
			s += tt.String() + "('" + string(text) + "') "
		}
	}
	return s
}

////////////////////////////////////////////////////////////////

func TestTokens(t *testing.T) {
	assertTokens(t, " ")
	assertTokens(t, "5.2 .4", NumberToken, NumberToken)
	assertTokens(t, "color: red;", IdentToken, ColonToken, IdentToken, SemicolonToken)
	assertTokens(t, "background: url(\"http://x\");", IdentToken, ColonToken, URLToken, SemicolonToken)
	assertTokens(t, "background: URL(x.png);", IdentToken, ColonToken, URLToken, SemicolonToken)
	assertTokens(t, "color: rgb(4, 0%, 5em);", IdentToken, ColonToken, FunctionToken, NumberToken, CommaToken, PercentageToken, CommaToken, DimensionToken, RightParenthesisToken, SemicolonToken)
	assertTokens(t, "body { \"string\" }", IdentToken, LeftBraceToken, StringToken, RightBraceToken)
	assertTokens(t, "body { \"str\\\"ing\" }", IdentToken, LeftBraceToken, StringToken, RightBraceToken)
	assertTokens(t, ".class { }", DelimToken, IdentToken, LeftBraceToken, RightBraceToken)
	assertTokens(t, "#class { }", HashToken, LeftBraceToken, RightBraceToken)
	assertTokens(t, "#class\\#withhash { }", HashToken, LeftBraceToken, RightBraceToken)
	assertTokens(t, "@media print { }", AtKeywordToken, IdentToken, LeftBraceToken, RightBraceToken)
	assertTokens(t, "/*comment*/", CommentToken)
	assertTokens(t, "/*com* /ment*/", CommentToken)
	assertTokens(t, "~= |= ^= $= *=", IncludeMatchToken, DashMatchToken, PrefixMatchToken, SuffixMatchToken, SubstringMatchToken)
	assertTokens(t, "||", ColumnToken)
	assertTokens(t, "<!-- -->", CDOToken, CDCToken)
	assertTokens(t, "U+1234", UnicodeRangeToken)
	assertTokens(t, "5.2 .4 4e-22", NumberToken, NumberToken, NumberToken)

	// unexpected ending
	assertTokens(t, "ident", IdentToken)
	assertTokens(t, "123.", NumberToken, DelimToken)
	assertTokens(t, "\"string", StringToken)
	assertTokens(t, "123/*comment", NumberToken, CommentToken)
	assertTokens(t, "U+1-", IdentToken, NumberToken, DelimToken)

	// unicode
	assertTokens(t, "fooδbar􀀀", IdentToken)
	assertTokens(t, "foo\\æ\\†", IdentToken)
	//assertTokens(t, "foo\x00bar", IdentToken)
	assertTokens(t, "'foo\u554abar'", StringToken)
	assertTokens(t, "\\000026B", IdentToken)
	assertTokens(t, "\\26 B", IdentToken)

	// hacks
	assertTokens(t, `\-\mo\z\-b\i\nd\in\g:\url(//business\i\nfo.co.uk\/labs\/xbl\/xbl\.xml\#xss);`, IdentToken, ColonToken, URLToken, SemicolonToken)
	assertTokens(t, "width/**/:/**/ 40em;", IdentToken, CommentToken, ColonToken, CommentToken, DimensionToken, SemicolonToken)
	assertTokens(t, ":root *> #quince", ColonToken, IdentToken, DelimToken, DelimToken, HashToken)
	assertTokens(t, "html[xmlns*=\"\"]:root", IdentToken, LeftBracketToken, IdentToken, SubstringMatchToken, StringToken, RightBracketToken, ColonToken, IdentToken)
	assertTokens(t, "body:nth-of-type(1)", IdentToken, ColonToken, FunctionToken, NumberToken, RightParenthesisToken)
	assertTokens(t, "color/*\\**/: blue\\9;", IdentToken, CommentToken, ColonToken, IdentToken, SemicolonToken)
	assertTokens(t, "color: blue !ie;", IdentToken, ColonToken, IdentToken, DelimToken, IdentToken, SemicolonToken)

	// escapes, null and replacement character
	assertTokens(t, "c\\\x00olor: white;", IdentToken, ColonToken, IdentToken, SemicolonToken)
	assertTokens(t, "null\\0", IdentToken)
	assertTokens(t, "eof\\", IdentToken)
	assertTokens(t, "\"a\x00b\"", StringToken)
	assertTokens(t, "a\\\x00b", IdentToken)
	assertTokens(t, "url(a\x00b)", BadURLToken) // null character cannot be unquoted
	assertTokens(t, "/*a\x00b*/", CommentToken)

	// coverage
	assertTokens(t, "  \n\r\n\r\"\\\r\n\\\r\"", StringToken)
	assertTokens(t, "U+?????? U+ABCD?? U+ABC-DEF", UnicodeRangeToken, UnicodeRangeToken, UnicodeRangeToken)
	assertTokens(t, "U+? U+A?", IdentToken, DelimToken, DelimToken, IdentToken, DelimToken, IdentToken, DelimToken)
	assertTokens(t, "-5.23 -moz", NumberToken, IdentToken)
	assertTokens(t, "()", LeftParenthesisToken, RightParenthesisToken)
	assertTokens(t, "url( //url  )", URLToken)
	assertTokens(t, "url( ", URLToken)
	assertTokens(t, "url( //url", URLToken)
	assertTokens(t, "url(\")a", URLToken)
	assertTokens(t, "url(a'\\\n)a", BadURLToken, IdentToken)
	assertTokens(t, "url(\"\n)a", BadURLToken, IdentToken)
	assertTokens(t, "url(a h)a", BadURLToken, IdentToken)
	assertTokens(t, "<!- | @4 ## /2", DelimToken, DelimToken, DelimToken, DelimToken, DelimToken, NumberToken, DelimToken, DelimToken, DelimToken, NumberToken)
	assertTokens(t, "\"s\\\n\"", StringToken)
	assertTokens(t, "\"a\\\"b\"", StringToken)
	assertTokens(t, "\"s\n", BadStringToken)
	//assertTokenError(t, "\\\n", ErrBadEscape)

	assert.Equal(t, "Whitespace", WhitespaceToken.String())
	assert.Equal(t, "Empty", EmptyToken.String())
	assert.Equal(t, "Invalid(100)", TokenType(100).String())
	assert.Equal(t, ErrorToken, NewLexer(bytes.NewBufferString("x")).consumeBracket())
}

func TestTokensSmall(t *testing.T) {
	assertTokens(t, "\"abcd", StringToken)
	assertTokens(t, "/*comment", CommentToken)
	assertTokens(t, "U+A-B", UnicodeRangeToken)
	assertTokens(t, "url((", BadURLToken)
	assertTokens(t, "id\u554a", IdentToken)

	buffer.MinBuf = 5
	assertTokens(t, "ab,d,e", IdentToken, CommaToken, IdentToken, CommaToken, IdentToken)
	assertTokens(t, "ab,cd,e", IdentToken, CommaToken, IdentToken, CommaToken, IdentToken)
}

////////////////////////////////////////////////////////////////

func ExampleNewLexer() {
	l := NewLexer(bytes.NewBufferString("color: red;"))
	out := ""
	for {
		tt, data := l.Next()
		if tt == ErrorToken {
			break
		} else if tt == WhitespaceToken || tt == CommentToken {
			continue
		}
		out += string(data)
	}
	fmt.Println(out)
	// Output: color:red;
}
<commit_msg>Comment-out minbuf in test<commit_after>package css // import "github.com/tdewolff/parse/css"

import (
	"bytes"
	"fmt"
	"io"
	"strconv"
	"testing"

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

func assertTokens(t *testing.T, s string, tokentypes ...TokenType) {
	stringify := helperStringify(t, s)
	l := NewLexer(bytes.NewBufferString(s))
	i := 0
	for {
		tt, _ := l.Next()
		if tt == ErrorToken {
			assert.Equal(t, io.EOF, l.Err(), "error must be EOF in "+stringify)
			assert.Equal(t, len(tokentypes), i, "when error occurred we must be at the end in "+stringify)
			break
		} else if tt == WhitespaceToken {
			continue
		}
		assert.False(t, i >= len(tokentypes), "index must not exceed tokentypes size in "+stringify)
		if i < len(tokentypes) {
			assert.Equal(t, tokentypes[i], tt, "tokentypes must match at index "+strconv.Itoa(i)+" in "+stringify)
		}
		i++
	}
	return
}

func helperStringify(t *testing.T, input string) string {
	s := ""
	l := NewLexer(bytes.NewBufferString(input))
	for i := 0; i < 10; i++ {
		tt, text := l.Next()
		if tt == ErrorToken {
			s += tt.String() + "('" + l.Err().Error() + "')"
			break
		} else if tt == WhitespaceToken {
			continue
		} else {
			s += tt.String() + "('" + string(text) + "') "
		}
	}
	return s
}

////////////////////////////////////////////////////////////////

func TestTokens(t *testing.T) {
	assertTokens(t, " ")
	assertTokens(t, "5.2 .4", NumberToken, NumberToken)
	assertTokens(t, "color: red;", IdentToken, ColonToken, IdentToken, SemicolonToken)
	assertTokens(t, "background: url(\"http://x\");", IdentToken, ColonToken, URLToken, SemicolonToken)
	assertTokens(t, "background: URL(x.png);", IdentToken, ColonToken, URLToken, SemicolonToken)
	assertTokens(t, "color: rgb(4, 0%, 5em);", IdentToken, ColonToken, FunctionToken, NumberToken, CommaToken, PercentageToken, CommaToken, DimensionToken, RightParenthesisToken, SemicolonToken)
	assertTokens(t, "body { \"string\" }", IdentToken, LeftBraceToken, StringToken, RightBraceToken)
	assertTokens(t, "body { \"str\\\"ing\" }", IdentToken, LeftBraceToken, StringToken, RightBraceToken)
	assertTokens(t, ".class { }", DelimToken, IdentToken, LeftBraceToken, RightBraceToken)
	assertTokens(t, "#class { }", HashToken, LeftBraceToken, RightBraceToken)
	assertTokens(t, "#class\\#withhash { }", HashToken, LeftBraceToken, RightBraceToken)
	assertTokens(t, "@media print { }", AtKeywordToken, IdentToken, LeftBraceToken, RightBraceToken)
	assertTokens(t, "/*comment*/", CommentToken)
	assertTokens(t, "/*com* /ment*/", CommentToken)
	assertTokens(t, "~= |= ^= $= *=", IncludeMatchToken, DashMatchToken, PrefixMatchToken, SuffixMatchToken, SubstringMatchToken)
	assertTokens(t, "||", ColumnToken)
	assertTokens(t, "<!-- -->", CDOToken, CDCToken)
	assertTokens(t, "U+1234", UnicodeRangeToken)
	assertTokens(t, "5.2 .4 4e-22", NumberToken, NumberToken, NumberToken)

	// unexpected ending
	assertTokens(t, "ident", IdentToken)
	assertTokens(t, "123.", NumberToken, DelimToken)
	assertTokens(t, "\"string", StringToken)
	assertTokens(t, "123/*comment", NumberToken, CommentToken)
	assertTokens(t, "U+1-", IdentToken, NumberToken, DelimToken)

	// unicode
	assertTokens(t, "fooδbar􀀀", IdentToken)
	assertTokens(t, "foo\\æ\\†", IdentToken)
	//assertTokens(t, "foo\x00bar", IdentToken)
	assertTokens(t, "'foo\u554abar'", StringToken)
	assertTokens(t, "\\000026B", IdentToken)
	assertTokens(t, "\\26 B", IdentToken)

	// hacks
	assertTokens(t, `\-\mo\z\-b\i\nd\in\g:\url(//business\i\nfo.co.uk\/labs\/xbl\/xbl\.xml\#xss);`, IdentToken, ColonToken, URLToken, SemicolonToken)
	assertTokens(t, "width/**/:/**/ 40em;", IdentToken, CommentToken, ColonToken, CommentToken, DimensionToken, SemicolonToken)
	assertTokens(t, ":root *> #quince", ColonToken, IdentToken, DelimToken, DelimToken, HashToken)
	assertTokens(t, "html[xmlns*=\"\"]:root", IdentToken, LeftBracketToken, IdentToken, SubstringMatchToken, StringToken, RightBracketToken, ColonToken, IdentToken)
	assertTokens(t, "body:nth-of-type(1)", IdentToken, ColonToken, FunctionToken, NumberToken, RightParenthesisToken)
	assertTokens(t, "color/*\\**/: blue\\9;", IdentToken, CommentToken, ColonToken, IdentToken, SemicolonToken)
	assertTokens(t, "color: blue !ie;", IdentToken, ColonToken, IdentToken, DelimToken, IdentToken, SemicolonToken)

	// escapes, null and replacement character
	assertTokens(t, "c\\\x00olor: white;", IdentToken, ColonToken, IdentToken, SemicolonToken)
	assertTokens(t, "null\\0", IdentToken)
	assertTokens(t, "eof\\", IdentToken)
	assertTokens(t, "\"a\x00b\"", StringToken)
	assertTokens(t, "a\\\x00b", IdentToken)
	assertTokens(t, "url(a\x00b)", BadURLToken) // null character cannot be unquoted
	assertTokens(t, "/*a\x00b*/", CommentToken)

	// coverage
	assertTokens(t, "  \n\r\n\r\"\\\r\n\\\r\"", StringToken)
	assertTokens(t, "U+?????? U+ABCD?? U+ABC-DEF", UnicodeRangeToken, UnicodeRangeToken, UnicodeRangeToken)
	assertTokens(t, "U+? U+A?", IdentToken, DelimToken, DelimToken, IdentToken, DelimToken, IdentToken, DelimToken)
	assertTokens(t, "-5.23 -moz", NumberToken, IdentToken)
	assertTokens(t, "()", LeftParenthesisToken, RightParenthesisToken)
	assertTokens(t, "url( //url  )", URLToken)
	assertTokens(t, "url( ", URLToken)
	assertTokens(t, "url( //url", URLToken)
	assertTokens(t, "url(\")a", URLToken)
	assertTokens(t, "url(a'\\\n)a", BadURLToken, IdentToken)
	assertTokens(t, "url(\"\n)a", BadURLToken, IdentToken)
	assertTokens(t, "url(a h)a", BadURLToken, IdentToken)
	assertTokens(t, "<!- | @4 ## /2", DelimToken, DelimToken, DelimToken, DelimToken, DelimToken, NumberToken, DelimToken, DelimToken, DelimToken, NumberToken)
	assertTokens(t, "\"s\\\n\"", StringToken)
	assertTokens(t, "\"a\\\"b\"", StringToken)
	assertTokens(t, "\"s\n", BadStringToken)
	//assertTokenError(t, "\\\n", ErrBadEscape)

	assert.Equal(t, "Whitespace", WhitespaceToken.String())
	assert.Equal(t, "Empty", EmptyToken.String())
	assert.Equal(t, "Invalid(100)", TokenType(100).String())
	assert.Equal(t, ErrorToken, NewLexer(bytes.NewBufferString("x")).consumeBracket())
}

func TestTokensSmall(t *testing.T) {
	assertTokens(t, "\"abcd", StringToken)
	assertTokens(t, "/*comment", CommentToken)
	assertTokens(t, "U+A-B", UnicodeRangeToken)
	assertTokens(t, "url((", BadURLToken)
	assertTokens(t, "id\u554a", IdentToken)

	// TODO
	// buffer.MinBuf = 5
	// assertTokens(t, "ab,d,e", IdentToken, CommaToken, IdentToken, CommaToken, IdentToken)
	// assertTokens(t, "ab,cd,e", IdentToken, CommaToken, IdentToken, CommaToken, IdentToken)
}

////////////////////////////////////////////////////////////////

func ExampleNewLexer() {
	l := NewLexer(bytes.NewBufferString("color: red;"))
	out := ""
	for {
		tt, data := l.Next()
		if tt == ErrorToken {
			break
		} else if tt == WhitespaceToken || tt == CommentToken {
			continue
		}
		out += string(data)
	}
	fmt.Println(out)
	// Output: color:red;
}
<|endoftext|>