<commit_before>package main

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

	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
)

type service struct {
	gin                  *gin.Engine
	wsUpgrder            *websocket.Upgrader
	currentSubscriptions subscriptions
	timeout              time.Duration
	sync                 chan bool
	cache                *Cache
}

func newService(
	currentSubscriptions subscriptions,
	readBufferSize int,
	writeBufferSize int,
	timeout time.Duration,
	debugMode string,
	cache *Cache,
) *service {

	if debugMode == "DEBUG" {
		gin.SetMode(gin.ReleaseMode)
	}

	upgrader := &websocket.Upgrader{
		ReadBufferSize:  readBufferSize,
		WriteBufferSize: writeBufferSize,
		CheckOrigin:     func(request *http.Request) bool { return true },
	}

	return &service{
		gin.Default(),
		upgrader,
		currentSubscriptions,
		timeout,
		make(chan bool, 1),
		cache,
	}

}

func (s *service) run(
	listen string,
) {

	v1 := s.gin.Group("v1")
	{
		v1.GET("/subscribe", s.handleSubscription)
		v1.PUT("/publish", s.handlePublish)
		v1.GET("/stats", s.handleStats)
		v1.GET("/stats/sessions", s.handleStatsSessions)
		v1.GET("/health", s.handleHealth)
	}

	//	ginpprof.Wrap(s.gin)
	logger.Debugf("run service on %s", listen)
	s.gin.Run(listen)
}

func (s *service) handleSubscription(context *gin.Context) {

	logger.Debugf(
		"handling new request from %s",
		context.Request.RemoteAddr,
	)

	authInfo := make(chan string)
	isDisconnected := make(chan bool, 1)
	terminateAuthentication := make(chan bool, 1)
	terminateKeepAlive := make(chan bool, 1)
	incomingMessages := make(chan string)

	connection, err := s.wsUpgrder.Upgrade(
		context.Writer, context.Request, nil,
	)

	if err != nil {
		logger.Errorf(
			"something happing wrong during create websocket connection, "+
				"reason %s",
			err.Error(),
		)

		return
	}

	defer func() {
		err := connection.Close()

		if err != nil {
			logger.Errorf(
				"unable to close websocket connection from %s, reason: %s",
				connection.RemoteAddr().String(),
				err.Error(),
			)

			return
		}

		logger.Infof(
			"websocket connection successfully closed for client %s",
			connection.RemoteAddr().String(),
		)
		return
	}()

	connection.SetReadDeadline(time.Now().Add(s.timeout))
	connection.SetWriteDeadline(time.Now().Add(s.timeout))

	go readMessage(connection, isDisconnected, incomingMessages)
	go authenticateUser(
		incomingMessages,
		authInfo,
		terminateAuthentication,
	)

	var (
		authToken     string = ""
		sessionNumber int    = 0
		messages      chan []byte
	)

	for {
		select {
		case authToken = <-authInfo:
			logger.Debugf(
				"auth token received: %s",
				authToken,
			)

			go keepAlive(connection, s.timeout, terminateKeepAlive)

			sessionNumber, messages = s.currentSubscriptions.subscribeUser(
				authToken,
			)

			logger.Infof(
				"user %s was subscribed with ID %d",
				connection.RemoteAddr().String(),
				sessionNumber,
			)

			if len(s.cache.messages[authToken]) != 0 {
				logger.Debugf(
					"pop messages from cache for %s",
					authToken,
				)

				go func() {
					for _, cacheObject := range s.cache.pop(authToken) {
						messages <- []byte(cacheObject.message)
					}
				}()
			}

		case <-isDisconnected:
			s.sync <- true

			logger.Infof(
				"client %s with token %s with session %d will be disconnected",
				context.Request.RemoteAddr,
				authToken,
				sessionNumber,
			)

			terminateAuthentication <- true
			terminateKeepAlive <- true
			logger.Infof(
				"terminate message was successfully sended into keepalive" +
					" and authentication processes",
			)

			activeSubscribers := s.currentSubscriptions.getActiveSubscribers(
				authToken,
			)

			switch activeSubscribers {
			case 0:
				logger.Debug("there are no subscribers, exiting...")

			case 1:
				logger.Debugf(
					"there is only one subscription for user %s, "+
						"unsubscribe user",
					authToken,
				)

				s.currentSubscriptions.unsubscribeUser(authToken)

			default:
				logger.Debugf(
					"there are several sessions for user %s, "+
						"trying deactivate session %d",
					authToken,
					sessionNumber,
				)

				s.currentSubscriptions.setInactive(authToken, sessionNumber)
			}

			<-s.sync
			return

		case message := <-messages:
			s.sync <- true
			logger.Debugf("got message %s", message)

			err := connection.WriteMessage(websocket.TextMessage, message)
			if err != nil {
				logger.Errorf(
					"%s: can`t write message to websocket, reason %s",
					reflect.TypeOf(err).String(),
					err.Error(),
				)
				<-s.sync

				return
			}
			<-s.sync
		}
	}
}

func (s *service) handlePublish(context *gin.Context) {
	authToken := strings.TrimSpace(
		context.Request.Header.Get("Token"),
	)
	message, err := ioutil.ReadAll(context.Request.Body)

	if err != nil {
		logger.Errorf(
			"could not read response body, reason: %s",
			err.Error(),
		)
		context.JSON(makeInternalServerError(err.Error(), nil))
		return
	}

	if _, exists := s.currentSubscriptions[authToken]; exists {

		s.currentSubscriptions.publishMessage(authToken, message)

		context.JSON(makeStatusOk("message published", string(message)))
		return
	}

	s.cache.put(authToken, string(message))

	context.JSON(makeNotFoundError(
		fmt.Sprintf("recipient %s not found", authToken),
		string(message),
	))
	return
}

func (s *service) handleStats(context *gin.Context) {
	stat := ServiceStats{
		SubscribersCount: len(s.currentSubscriptions),
	}

	context.JSON(makeStatusOk(
		context.Request.URL.String(), stat,
	))

	return
}

func (s *service) handleStatsSessions(context *gin.Context) {

	sessionsCount := make(map[string]int)
	for authToken, sessions := range s.currentSubscriptions {
		sessionsCount[authToken] = len(sessions)

	}
	sortedCurrentSessions := newSortedSessions(sessionsCount)
	sortedCurrentSessions.Sort()

	stat := ActiveSessions{
		SubscribersSessionsCount: sessionsCount,
	}

	context.JSON(makeStatusOk(
		context.Request.URL.String(), stat,
	))

	return
}
func (s *service) handleHealth(context *gin.Context) {

	context.JSON(makeStatusOk(
		context.Request.URL.String(), "OK",
	))

	return
}
<commit_msg>fix bug concurrent read/write to map<commit_after>package main

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

	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
)

type service struct {
	gin                  *gin.Engine
	wsUpgrder            *websocket.Upgrader
	currentSubscriptions subscriptions
	timeout              time.Duration
	sync                 chan bool
	cache                *Cache
}

func newService(
	currentSubscriptions subscriptions,
	readBufferSize int,
	writeBufferSize int,
	timeout time.Duration,
	debugMode string,
	cache *Cache,
) *service {

	if debugMode == "DEBUG" {
		gin.SetMode(gin.ReleaseMode)
	}

	upgrader := &websocket.Upgrader{
		ReadBufferSize:  readBufferSize,
		WriteBufferSize: writeBufferSize,
		CheckOrigin:     func(request *http.Request) bool { return true },
	}

	return &service{
		gin.Default(),
		upgrader,
		currentSubscriptions,
		timeout,
		make(chan bool, 1),
		cache,
	}

}

func (s *service) run(
	listen string,
) {

	v1 := s.gin.Group("v1")
	{
		v1.GET("/subscribe", s.handleSubscription)
		v1.PUT("/publish", s.handlePublish)
		v1.GET("/stats", s.handleStats)
		v1.GET("/stats/sessions", s.handleStatsSessions)
		v1.GET("/health", s.handleHealth)
	}

	//	ginpprof.Wrap(s.gin)
	logger.Debugf("run service on %s", listen)
	s.gin.Run(listen)
}

func (s *service) handleSubscription(context *gin.Context) {

	logger.Debugf(
		"handling new request from %s",
		context.Request.RemoteAddr,
	)

	authInfo := make(chan string)
	isDisconnected := make(chan bool, 1)
	terminateAuthentication := make(chan bool, 1)
	terminateKeepAlive := make(chan bool, 1)
	incomingMessages := make(chan string)

	connection, err := s.wsUpgrder.Upgrade(
		context.Writer, context.Request, nil,
	)

	if err != nil {
		logger.Errorf(
			"something happing wrong during create websocket connection, "+
				"reason %s",
			err.Error(),
		)

		return
	}

	defer func() {
		err := connection.Close()

		if err != nil {
			logger.Errorf(
				"unable to close websocket connection from %s, reason: %s",
				connection.RemoteAddr().String(),
				err.Error(),
			)

			return
		}

		logger.Infof(
			"websocket connection successfully closed for client %s",
			connection.RemoteAddr().String(),
		)
		return
	}()

	connection.SetReadDeadline(time.Now().Add(s.timeout))
	connection.SetWriteDeadline(time.Now().Add(s.timeout))

	go readMessage(connection, isDisconnected, incomingMessages)
	go authenticateUser(
		incomingMessages,
		authInfo,
		terminateAuthentication,
	)

	var (
		authToken     string = ""
		sessionNumber int    = 0
		messages      chan []byte
	)

	for {
		select {
		case authToken = <-authInfo:
			logger.Debugf(
				"auth token received: %s",
				authToken,
			)

			go keepAlive(connection, s.timeout, terminateKeepAlive)

			s.sync <- true
			sessionNumber, messages = s.currentSubscriptions.subscribeUser(
				authToken,
			)
			<-s.sync

			logger.Infof(
				"user %s was subscribed with ID %d",
				connection.RemoteAddr().String(),
				sessionNumber,
			)

			if len(s.cache.messages[authToken]) != 0 {
				logger.Debugf(
					"pop messages from cache for %s",
					authToken,
				)

				go func() {
					for _, cacheObject := range s.cache.pop(authToken) {
						messages <- []byte(cacheObject.message)
					}
				}()
			}

		case <-isDisconnected:
			s.sync <- true

			logger.Infof(
				"client %s with token %s with session %d will be disconnected",
				context.Request.RemoteAddr,
				authToken,
				sessionNumber,
			)

			terminateAuthentication <- true
			terminateKeepAlive <- true
			logger.Infof(
				"terminate message was successfully sended into keepalive" +
					" and authentication processes",
			)

			activeSubscribers := s.currentSubscriptions.getActiveSubscribers(
				authToken,
			)

			switch activeSubscribers {
			case 0:
				logger.Debug("there are no subscribers, exiting...")

			case 1:
				logger.Debugf(
					"there is only one subscription for user %s, "+
						"unsubscribe user",
					authToken,
				)

				s.currentSubscriptions.unsubscribeUser(authToken)

			default:
				logger.Debugf(
					"there are several sessions for user %s, "+
						"trying deactivate session %d",
					authToken,
					sessionNumber,
				)

				s.currentSubscriptions.setInactive(authToken, sessionNumber)
			}

			<-s.sync
			return

		case message := <-messages:
			s.sync <- true
			logger.Debugf("got message %s", message)

			err := connection.WriteMessage(websocket.TextMessage, message)
			if err != nil {
				logger.Errorf(
					"%s: can`t write message to websocket, reason %s",
					reflect.TypeOf(err).String(),
					err.Error(),
				)
				<-s.sync

				return
			}
			<-s.sync
		}
	}
}

func (s *service) handlePublish(context *gin.Context) {
	authToken := strings.TrimSpace(
		context.Request.Header.Get("Token"),
	)
	message, err := ioutil.ReadAll(context.Request.Body)

	if err != nil {
		logger.Errorf(
			"could not read response body, reason: %s",
			err.Error(),
		)
		context.JSON(makeInternalServerError(err.Error(), nil))
		return
	}

	if _, exists := s.currentSubscriptions[authToken]; exists {

		s.currentSubscriptions.publishMessage(authToken, message)

		context.JSON(makeStatusOk("message published", string(message)))
		return
	}

	s.cache.put(authToken, string(message))

	context.JSON(makeNotFoundError(
		fmt.Sprintf("recipient %s not found", authToken),
		string(message),
	))
	return
}

func (s *service) handleStats(context *gin.Context) {
	stat := ServiceStats{
		SubscribersCount: len(s.currentSubscriptions),
	}

	context.JSON(makeStatusOk(
		context.Request.URL.String(), stat,
	))

	return
}

func (s *service) handleStatsSessions(context *gin.Context) {

	sessionsCount := make(map[string]int)
	for authToken, sessions := range s.currentSubscriptions {
		sessionsCount[authToken] = len(sessions)

	}
	sortedCurrentSessions := newSortedSessions(sessionsCount)
	sortedCurrentSessions.Sort()

	stat := ActiveSessions{
		SubscribersSessionsCount: sessionsCount,
	}

	context.JSON(makeStatusOk(
		context.Request.URL.String(), stat,
	))

	return
}
func (s *service) handleHealth(context *gin.Context) {

	context.JSON(makeStatusOk(
		context.Request.URL.String(), "OK",
	))

	return
}
<|endoftext|>


<commit_before>package qb

import (
	"database/sql"
	"fmt"
	"sort"
)

// NewSession generates a new Session given engine and returns session pointer
func NewSession(metadata *MetaData) *Session {
	return &Session{
		queries:  []*Query{},
		mapper:   NewMapper(metadata.Engine().Driver()),
		metadata: metadata,
		Builder: NewBuilder(metadata.engine.Driver()),
	}
}

// Session is the composition of engine connection & orm mappings
type Session struct {
	queries  []*Query
	mapper   *Mapper
	metadata *MetaData
	tx       *sql.Tx
	*Builder
}

func (s *Session) add(query *Query) {
	var err error
	if s.tx == nil {
		s.queries = []*Query{}
		s.tx, err = s.metadata.Engine().DB().Begin()
		if err != nil {
			panic(err)
		}
	}
	s.queries = append(s.queries, query)
}

// Delete adds a single delete query to the session
func (s *Session) Delete(model interface{}) {

	kv := s.mapper.ToMap(model)

	tName := s.mapper.ModelName(model)

	d := s.metadata.Table(tName).Delete()
	ands := []string{}
	bindings := []interface{}{}

	pcols := s.metadata.Table(tName).PrimaryKey()

	// if table has primary key
	if len(pcols) > 0 {

		for _, pk := range pcols {
			b := kv[pk]
			ands = append(ands, fmt.Sprintf("%s = %s", pk, d.Placeholder()))
			bindings = append(bindings, b)
		}

	} else {
		for k, v := range kv {
			ands = append(ands, fmt.Sprintf("%s = %s", s.mapper.ColName(k), d.Placeholder()))
			bindings = append(bindings, v)
		}
	}

	del := d.Where(d.And(ands...), bindings...).Query()
	s.add(del)
}

// Add adds a single query to the session. The query must be insert or update
func (s *Session) Add(model interface{}) {

	rawMap := s.mapper.ToMap(model)

	kv := map[string]interface{}{}

	for k, v := range rawMap {
		kv[s.mapper.ColName(k)] = v
	}

	q := s.metadata.Table(s.mapper.ModelName(model)).Insert(kv).Query()
	s.add(q)
}

// AddAll adds multiple models an adds an insert statement to current queries
func (s *Session) AddAll(models ...interface{}) {
	for _, m := range models {
		s.Add(m)
	}
}

// Commit commits the current transaction with queries
func (s *Session) Commit() error {

	for _, q := range s.queries {
		_, err := s.tx.Exec(q.SQL(), q.Bindings()...)
		if err != nil {
			return err
		}
	}

	err := s.tx.Commit()
	s.tx = nil
	return err
}

//// Find returns a row given model properties
func (s *Session) Find(model interface{}) *Session {

	tName := s.mapper.ModelName(model)
	rModelMap := s.mapper.ToRawMap(model)

	sqlColNames := []string{}
	for k, _ := range rModelMap {
		sqlColNames = append(sqlColNames, s.mapper.ColName(k))
	}

	sort.Strings(sqlColNames)

	s.Builder = NewBuilder(s.metadata.Engine().Driver())
	s.Builder.Select(sqlColNames...).From(tName)

	modelMap := s.mapper.ToMap(model)

	ands := []string{}
	bindings := []interface{}{}

	for k, v := range modelMap {
		ands = append(ands, fmt.Sprintf("%s = %s", s.mapper.ColName(k), s.Builder.Placeholder()))
		bindings = append(bindings, v)
	}

	s.Builder.Where(s.Builder.And(ands...), bindings...)
	return s
}

// First returns the first record mapped as a model
// The interface should be struct pointer instead of struct
func (s *Session) First(model interface{}) error {
	query := s.Builder.Query()
	return s.metadata.Engine().Get(query, model)
}

// All returns all the records mapped as a model slice
// The interface should be struct pointer instead of struct
func (s *Session) All(models interface{}) error {
	query := s.Builder.Query()
	return s.metadata.Engine().Select(query, models)
}
<commit_msg>add builder wrapper functions to session<commit_after>package qb

import (
	"database/sql"
	"fmt"
	"sort"
)

// NewSession generates a new Session given engine and returns session pointer
func NewSession(metadata *MetaData) *Session {
	return &Session{
		queries:  []*Query{},
		mapper:   NewMapper(metadata.Engine().Driver()),
		metadata: metadata,
		builder: NewBuilder(metadata.engine.Driver()),
	}
}

// Session is the composition of engine connection & orm mappings
type Session struct {
	queries  []*Query
	mapper   *Mapper
	metadata *MetaData
	tx       *sql.Tx
	builder  *Builder
}

func (s *Session) add(query *Query) {
	var err error
	if s.tx == nil {
		s.queries = []*Query{}
		s.tx, err = s.metadata.Engine().DB().Begin()
		if err != nil {
			panic(err)
		}
	}
	s.queries = append(s.queries, query)
}

// Delete adds a single delete query to the session
func (s *Session) Delete(model interface{}) {

	kv := s.mapper.ToMap(model)

	tName := s.mapper.ModelName(model)

	d := s.metadata.Table(tName).Delete()
	ands := []string{}
	bindings := []interface{}{}

	pcols := s.metadata.Table(tName).PrimaryKey()

	// if table has primary key
	if len(pcols) > 0 {

		for _, pk := range pcols {
			b := kv[pk]
			ands = append(ands, fmt.Sprintf("%s = %s", pk, d.Placeholder()))
			bindings = append(bindings, b)
		}

	} else {
		for k, v := range kv {
			ands = append(ands, fmt.Sprintf("%s = %s", s.mapper.ColName(k), d.Placeholder()))
			bindings = append(bindings, v)
		}
	}

	del := d.Where(d.And(ands...), bindings...).Query()
	s.add(del)
}

// Add adds a single query to the session. The query must be insert or update
func (s *Session) Add(model interface{}) {

	rawMap := s.mapper.ToMap(model)

	kv := map[string]interface{}{}

	for k, v := range rawMap {
		kv[s.mapper.ColName(k)] = v
	}

	q := s.metadata.Table(s.mapper.ModelName(model)).Insert(kv).Query()
	s.add(q)
}

// AddAll adds multiple models an adds an insert statement to current queries
func (s *Session) AddAll(models ...interface{}) {
	for _, m := range models {
		s.Add(m)
	}
}

// Commit commits the current transaction with queries
func (s *Session) Commit() error {

	for _, q := range s.queries {
		_, err := s.tx.Exec(q.SQL(), q.Bindings()...)
		if err != nil {
			return err
		}
	}

	err := s.tx.Commit()
	s.tx = nil
	return err
}

//// Find returns a row given model properties
func (s *Session) Find(model interface{}) *Session {

	tName := s.mapper.ModelName(model)
	rModelMap := s.mapper.ToRawMap(model)

	sqlColNames := []string{}
	for k, _ := range rModelMap {
		sqlColNames = append(sqlColNames, s.mapper.ColName(k))
	}

	sort.Strings(sqlColNames)

	s.builder = NewBuilder(s.metadata.Engine().Driver())
	s.builder.Select(sqlColNames...).From(tName)

	modelMap := s.mapper.ToMap(model)

	ands := []string{}
	bindings := []interface{}{}

	for k, v := range modelMap {
		ands = append(ands, fmt.Sprintf("%s = %s", s.mapper.ColName(k), s.builder.Placeholder()))
		bindings = append(bindings, v)
	}

	s.builder.Where(s.builder.And(ands...), bindings...)
	return s
}

// First returns the first record mapped as a model
// The interface should be struct pointer instead of struct
func (s *Session) First(model interface{}) error {
	query := s.builder.Query()
	return s.metadata.Engine().Get(query, model)
}

// All returns all the records mapped as a model slice
// The interface should be struct pointer instead of struct
func (s *Session) All(models interface{}) error {
	query := s.builder.Query()
	return s.metadata.Engine().Select(query, models)
}

// builder overrides for session
// Select generates "select %s" statement
func (s *Session) Select(columns ...string) *Session {
	s.builder.Select(columns...)
	return s
}

// From generates "from %s" statement for each table name
func (s *Session) From(tables ...string) *Session {
	s.builder.From(tables...)
	return s
}

// InnerJoin generates "inner join %s on %s" statement for each expression
func (s *Session) InnerJoin(table string, expressions ...string) *Session {
	s.builder.InnerJoin(table, expressions...)
	return s
}

// CrossJoin generates "cross join %s" statement for table
func (s *Session) CrossJoin(table string) *Session {
	s.builder.CrossJoin(table)
	return s
}

// LeftOuterJoin generates "left outer join %s on %s" statement for each expression
func (s *Session) LeftOuterJoin(table string, expressions ...string) *Session {
	s.builder.LeftOuterJoin(table, expressions...)
	return s
}

// RightOuterJoin generates "right outer join %s on %s" statement for each expression
func (s *Session) RightOuterJoin(table string, expressions ...string) *Session {
	s.builder.RightOuterJoin(table, expressions...)
	return s
}

// FullOuterJoin generates "full outer join %s on %s" for each expression
func (s *Session) FullOuterJoin(table string, expressions ...string) *Session {
	s.builder.FullOuterJoin(table, expressions...)
	return s
}

// Where generates "where %s" for the expression and adds bindings for each value
func (s *Session) Where(expression string, bindings ...interface{}) *Session {
	s.builder.Where(expression, bindings...)
	return s
}

// OrderBy generates "order by %s" for each expression
func (s *Session) OrderBy(expressions ...string) *Session {
	s.builder.OrderBy(expressions...)
	return s
}

// GroupBy generates "group by %s" for each column
func (s *Session) GroupBy(columns ...string) *Session {
	s.builder.GroupBy(columns...)
	return s
}

// Having generates "having %s" for each expression
func (s *Session) Having(expressions ...string) *Session {
	s.builder.Having(expressions...)
	return s
}

// Limit generates limit %d offset %d for offset and count
func (s *Session) Limit(offset int, count int) *Session {
	s.builder.Limit(offset, count)
	return s
}

// aggregates

// Avg function generates "avg(%s)" statement for column
func (s *Session) Avg(column string) string {
	return s.builder.Avg(column)
}

// Count function generates "count(%s)" statement for column
func (s *Session) Count(column string) string {
	return s.builder.Count(column)
}

// Sum function generates "sum(%s)" statement for column
func (s *Session) Sum(column string) string {
	return s.builder.Sum(column)
}

// Min function generates "min(%s)" statement for column
func (s *Session) Min(column string) string {
	return s.builder.Min(column)
}

// Max function generates "max(%s)" statement for column
func (s *Session) Max(column string) string {
	return s.builder.Max(column)
}

// expressions

// NotIn function generates "%s not in (%s)" for key and adds bindings for each value
func (s *Session) NotIn(key string, values ...interface{}) string {
	return s.builder.NotIn(key, values...)
}

// In function generates "%s in (%s)" for key and adds bindings for each value
func (s *Session) In(key string, values ...interface{}) string {
	return s.builder.In(key, values...)
}

// NotEq function generates "%s != placeholder" for key and adds binding for value
func (s *Session) NotEq(key string, value interface{}) string {
	return s.builder.NotEq(key, value)
}

// Eq function generates "%s = placeholder" for key and adds binding for value
func (s *Session) Eq(key string, value interface{}) string {
	return s.builder.Eq(key, value)
}

// Gt function generates "%s > placeholder" for key and adds binding for value
func (s *Session) Gt(key string, value interface{}) string {
	return s.builder.Gt(key, value)
}

// Gte function generates "%s >= placeholder" for key and adds binding for value
func (s *Session) Gte(key string, value interface{}) string {
	return s.builder.Gte(key, value)
}

// St function generates "%s < placeholder" for key and adds binding for value
func (s *Session) St(key string, value interface{}) string {
	return s.builder.St(key, value)
}

// Ste function generates "%s <= placeholder" for key and adds binding for value
func (s *Session) Ste(key string, value interface{}) string {
	return s.builder.Ste(key, value)
}

// And function generates " AND " between any number of expressions
func (s *Session) And(expressions ...string) string {
	return s.builder.And(expressions...)
}

// Or function generates " OR " between any number of expressions
func (s *Session) Or(expressions ...string) string {
	return s.builder.Or(expressions...)
}
<|endoftext|>


<commit_before>package password

import (
	"net/http"
)

// GetSession gets the currently active session from the store based on the
// value from the requests cookie.
func GetSession(r *http.Request) {

}

// AuthorizeSession sets the session.
func AuthorizeSession(r *http.Request) {

}
<commit_msg>Setup to use gorilla sessions<commit_after>package password

import (
	"net/http"

	"github.com/gorilla/sessions"
)

var store = sessions.NewCookieStore(genRandBytes())

// GetSession gets the currently active session from the store based on the
// value from the requests cookie.
func GetSession(r *http.Request) {

}

// AuthorizeSession sets the session.
func AuthorizeSession(r *http.Request) {

}
<|endoftext|>


<commit_before>package gockle

import (
	"fmt"

	"github.com/gocql/gocql"
	"github.com/maraino/go-mock"
)

// Session wraps *gocql.Session.
type Session interface {
	// Close closes the session.
	Close()

	// Columns returns a map from column names to types for keyspace and table.
	// Schema changes during a session are not reflected.
	Columns(keyspace, table string) (map[string]gocql.TypeInfo, error)

	// QueryBatch returns a Batch with type kind for batched queries.
	QueryBatch(kind BatchKind) Batch

	// QueryExec runs statement with arguments.
	QueryExec(statement string, arguments ...interface{}) error

	// QueryIterator runs statement with arguments and returns an Iterator for
	// the results.
	QueryIterator(statement string, arguments ...interface{}) Iterator

	// QueryScan runs statement with arguments.
	QueryScan(statement string, arguments, results []interface{}) error

	// QueryScanMap runs statement with arguments and puts the first result row
	// in results.
	QueryScanMap(statement string, arguments []interface{}, results map[string]interface{}) error

	// QueryScanMapTx runs statement with arguments as a lightweight transaction and
	// puts the first result row in results. It returns whether the transaction
	// succeeded. If not, it puts the old values in results.
	QueryScanMapTx(statement string, arguments []interface{}, results map[string]interface{}) (bool, error)

	// QuerySliceMap runs statement with arguments and returns all result rows.
	QuerySliceMap(statement string, arguments ...interface{}) ([]map[string]interface{}, error)

	// Tables returns the table names for keyspace. Schema changes during a session
	// are not reflected. Invalid keyspace names are not errors.
	Tables(keyspace string) ([]string, error)
}

var (
	_ Session = SessionMock{}
	_ Session = session{}
)

// NewSession returns a new Session for s.
func NewSession(s *gocql.Session) Session {
	return session{s: s}
}

// NewSimpleSession returns a new Session for hosts.
func NewSimpleSession(hosts ...string) (Session, error) {
	var c = gocql.NewCluster(hosts...)

	c.ProtoVersion = 4

	var s, err = c.CreateSession()

	if err != nil {
		return nil, err
	}

	return session{s: s}, nil
}

// SessionMock is a mock Session.
type SessionMock struct {
	mock.Mock
}

// Close implements Session.
func (m SessionMock) Close() {
	m.Called()
}

// Columns implements Session.
func (m SessionMock) Columns(keyspace, table string) (map[string]gocql.TypeInfo, error) {
	var r = m.Called(keyspace, table)

	return r.Get(0).(map[string]gocql.TypeInfo), r.Error(1)
}

// QueryBatch implements Session.
func (m SessionMock) QueryBatch(kind BatchKind) Batch {
	return m.Called(kind).Get(0).(Batch)
}

// QueryExec implements Session.
func (m SessionMock) QueryExec(statement string, arguments ...interface{}) error {
	return m.Called(statement, arguments).Error(0)
}

// QueryIterator implements Session.
func (m SessionMock) QueryIterator(statement string, arguments ...interface{}) Iterator {
	return m.Called(statement, arguments).Get(0).(Iterator)
}

// QueryScan implements Session.
func (m SessionMock) QueryScan(statement string, arguments, results []interface{}) error {
	return m.Called(statement, arguments, results).Error(0)
}

// QueryScanMap implements Session.
func (m SessionMock) QueryScanMap(statement string, arguments []interface{}, results map[string]interface{}) error {
	return m.Called(statement, arguments, results).Error(0)
}

// QueryScanMapTx implements Session.
func (m SessionMock) QueryScanMapTx(statement string, arguments []interface{}, results map[string]interface{}) (bool, error) {
	var r = m.Called(statement, arguments, results)

	return r.Bool(0), r.Error(1)
}

// QuerySliceMap implements Session.
func (m SessionMock) QuerySliceMap(statement string, arguments ...interface{}) ([]map[string]interface{}, error) {
	var r = m.Called(statement, arguments)

	return r.Get(0).([]map[string]interface{}), r.Error(1)
}

// Tables implements Session.
func (m SessionMock) Tables(keyspace string) ([]string, error) {
	var r = m.Called(keyspace)

	return r.Get(0).([]string), r.Error(1)
}

type session struct {
	s *gocql.Session
}

func (s session) Close() {
	s.s.Close()
}

func (s session) Columns(keyspace, table string) (map[string]gocql.TypeInfo, error) {
	var m, err = s.s.KeyspaceMetadata(keyspace)

	if err != nil {
		return nil, err
	}

	var t, ok = m.Tables[table]

	if !ok {
		return nil, fmt.Errorf("gockle: table %v.%v invalid", keyspace, table)
	}

	var types = map[string]gocql.TypeInfo{}

	for n, c := range t.Columns {
		types[n] = c.Type
	}

	return types, nil
}

func (s session) QueryBatch(kind BatchKind) Batch {
	return batch{b: s.s.NewBatch(gocql.BatchType(kind)), s: s.s}
}

func (s session) QueryExec(statement string, arguments ...interface{}) error {
	return s.s.Query(statement, arguments...).Exec()
}

func (s session) QueryIterator(statement string, arguments ...interface{}) Iterator {
	return iterator{i: s.s.Query(statement, arguments...).Iter()}
}

func (s session) QueryScan(statement string, arguments, results []interface{}) error {
	return s.s.Query(statement, arguments...).Scan(results...)
}

func (s session) QueryScanMap(statement string, arguments []interface{}, results map[string]interface{}) error {
	return s.s.Query(statement, arguments...).MapScan(results)
}

func (s session) QueryScanMapTx(statement string, arguments []interface{}, results map[string]interface{}) (bool, error) {
	return s.s.Query(statement, arguments...).MapScanCAS(results)
}

func (s session) QuerySliceMap(statement string, arguments ...interface{}) ([]map[string]interface{}, error) {
	return s.s.Query(statement, arguments...).Iter().SliceMap()
}

func (s session) Tables(keyspace string) ([]string, error) {
	var m, err = s.s.KeyspaceMetadata(keyspace)

	if err != nil {
		return nil, err
	}

	var ts []string

	for t := range m.Tables {
		ts = append(ts, t)
	}

	return ts, nil
}
<commit_msg>Improve Session doc<commit_after>package gockle

import (
	"fmt"

	"github.com/gocql/gocql"
	"github.com/maraino/go-mock"
)

func metadata(s *gocql.Session, keyspace string) (*gocql.KeyspaceMetadata, error) {
	var m, err = s.KeyspaceMetadata(keyspace)

	if err != nil {
		return nil, err
	}

	if m.DurableWrites && m.Name == keyspace && m.StrategyClass == "" && m.StrategyOptions == nil && m.Tables == nil {
		return nil, fmt.Errorf("gockle: keyspace %v invalid", keyspace)
	}

	return m, nil
}

// Session is a Cassandra connection. The Query methods run CQL queries. The
// Columns and Tables methods provide simple metadata.
type Session interface {
	// Close closes the Session.
	Close()

	// Columns returns a map from column names to types for keyspace and table.
	// Schema changes during a session are not reflected; you must open a new
	// Session to observe them.
	Columns(keyspace, table string) (map[string]gocql.TypeInfo, error)

	// QueryBatch returns a Batch for the Session.
	QueryBatch(kind BatchKind) Batch

	// QueryExec runs statement with arguments.
	QueryExec(statement string, arguments ...interface{}) error

	// QueryIterator runs statement with arguments and returns an Iterator for the
	// results.
	QueryIterator(statement string, arguments ...interface{}) Iterator

	// QueryScan runs statement with arguments and puts the first result row in
	// results.
	QueryScan(statement string, arguments, results []interface{}) error

	// QueryScanMap runs statement with arguments and puts the first result row
	// in results.
	QueryScanMap(statement string, arguments []interface{}, results map[string]interface{}) error

	// QueryScanMapTx runs the conditional statement with arguments as a lightweight
	// transaction. If it succeeded, it puts the new values in results, and
	// otherwise puts the old values in results. It returns whether it succeeded.
	QueryScanMapTx(statement string, arguments []interface{}, results map[string]interface{}) (bool, error)

	// QuerySliceMap runs statement with arguments and returns all the result rows.
	QuerySliceMap(statement string, arguments ...interface{}) ([]map[string]interface{}, error)

	// Tables returns the table names for keyspace. Schema changes during a session
	// are not reflected; you must open a new Session to observe them.
	Tables(keyspace string) ([]string, error)
}

var (
	_ Session = SessionMock{}
	_ Session = session{}
)

// NewSession returns a new Session for s.
func NewSession(s *gocql.Session) Session {
	return session{s: s}
}

// NewSimpleSession returns a new Session for hosts. It uses native protocol
// version 4.
func NewSimpleSession(hosts ...string) (Session, error) {
	var c = gocql.NewCluster(hosts...)

	c.ProtoVersion = 4

	var s, err = c.CreateSession()

	if err != nil {
		return nil, err
	}

	return session{s: s}, nil
}

// SessionMock is a mock Session.
type SessionMock struct {
	mock.Mock
}

// Close implements Session.
func (m SessionMock) Close() {
	m.Called()
}

// Columns implements Session.
func (m SessionMock) Columns(keyspace, table string) (map[string]gocql.TypeInfo, error) {
	var r = m.Called(keyspace, table)

	return r.Get(0).(map[string]gocql.TypeInfo), r.Error(1)
}

// QueryBatch implements Session.
func (m SessionMock) QueryBatch(kind BatchKind) Batch {
	return m.Called(kind).Get(0).(Batch)
}

// QueryExec implements Session.
func (m SessionMock) QueryExec(statement string, arguments ...interface{}) error {
	return m.Called(statement, arguments).Error(0)
}

// QueryIterator implements Session.
func (m SessionMock) QueryIterator(statement string, arguments ...interface{}) Iterator {
	return m.Called(statement, arguments).Get(0).(Iterator)
}

// QueryScan implements Session.
func (m SessionMock) QueryScan(statement string, arguments, results []interface{}) error {
	return m.Called(statement, arguments, results).Error(0)
}

// QueryScanMap implements Session.
func (m SessionMock) QueryScanMap(statement string, arguments []interface{}, results map[string]interface{}) error {
	return m.Called(statement, arguments, results).Error(0)
}

// QueryScanMapTx implements Session.
func (m SessionMock) QueryScanMapTx(statement string, arguments []interface{}, results map[string]interface{}) (bool, error) {
	var r = m.Called(statement, arguments, results)

	return r.Bool(0), r.Error(1)
}

// QuerySliceMap implements Session.
func (m SessionMock) QuerySliceMap(statement string, arguments ...interface{}) ([]map[string]interface{}, error) {
	var r = m.Called(statement, arguments)

	return r.Get(0).([]map[string]interface{}), r.Error(1)
}

// Tables implements Session.
func (m SessionMock) Tables(keyspace string) ([]string, error) {
	var r = m.Called(keyspace)

	return r.Get(0).([]string), r.Error(1)
}

type session struct {
	s *gocql.Session
}

func (s session) Close() {
	s.s.Close()
}

func (s session) Columns(keyspace, table string) (map[string]gocql.TypeInfo, error) {
	var m, err = metadata(s.s, keyspace)

	if err != nil {
		return nil, err
	}

	var t, ok = m.Tables[table]

	if !ok {
		return nil, fmt.Errorf("gockle: table %v.%v invalid", keyspace, table)
	}

	var types = map[string]gocql.TypeInfo{}

	for n, c := range t.Columns {
		types[n] = c.Type
	}

	return types, nil
}

func (s session) QueryBatch(kind BatchKind) Batch {
	return batch{b: s.s.NewBatch(gocql.BatchType(kind)), s: s.s}
}

func (s session) QueryExec(statement string, arguments ...interface{}) error {
	return s.s.Query(statement, arguments...).Exec()
}

func (s session) QueryIterator(statement string, arguments ...interface{}) Iterator {
	return iterator{i: s.s.Query(statement, arguments...).Iter()}
}

func (s session) QueryScan(statement string, arguments, results []interface{}) error {
	return s.s.Query(statement, arguments...).Scan(results...)
}

func (s session) QueryScanMap(statement string, arguments []interface{}, results map[string]interface{}) error {
	return s.s.Query(statement, arguments...).MapScan(results)
}

func (s session) QueryScanMapTx(statement string, arguments []interface{}, results map[string]interface{}) (bool, error) {
	return s.s.Query(statement, arguments...).MapScanCAS(results)
}

func (s session) QuerySliceMap(statement string, arguments ...interface{}) ([]map[string]interface{}, error) {
	return s.s.Query(statement, arguments...).Iter().SliceMap()
}

func (s session) Tables(keyspace string) ([]string, error) {
	var m, err = metadata(s.s, keyspace)

	if err != nil {
		return nil, err
	}

	var ts []string

	for t := range m.Tables {
		ts = append(ts, t)
	}

	return ts, nil
}
<|endoftext|>


<commit_before>// The sfs package providing a secure file system, with access limitations.
package sfs

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

// Flags alter how access checks are made.
type Flags int

const (
	_    Flags = (1 << iota) / 2
	Root       // Path is accessible if it is a root directory.
)

// FS contains wrappers for common file system functions that also check whether
// a given path can be accessed. The zero value of an FS is ready for use.
//
// A path is accessible if it is a descendant of a root in FS. A root is not
// accessible unless the Root flag is specified.
type FS struct {
	mtx   sync.RWMutex
	roots []string
}

// access returns whether the given path can be accessed.
func (fs *FS) access(path string, flags Flags) bool {
	//TODO: Implement.
	return true
}

// AddRoot adds path as a root. Returns an error if the path could not be
// converted to an absolute path. Does nothing if the path is already a root.
func (fs *FS) AddRoot(path string) error {
	fs.mtx.Lock()
	defer fs.mtx.Unlock()

	path, err := filepath.Abs(path)
	if err != nil {
		return err
	}
	for _, root := range fs.roots {
		if path == root {
			return nil
		}
	}
	fs.roots = append(fs.roots, path)
	return nil
}

// RemoveRoot removes path as a root. Returns an error if the path could not be
// converted to an absolute path. Does nothing if the path is not a root.
func (fs *FS) RemoveRoot(path string) error {
	fs.mtx.Lock()
	defer fs.mtx.Unlock()

	path, err := filepath.Abs(path)
	if err != nil {
		return err
	}
	for i, root := range fs.roots {
		if path == root {
			fs.roots[i] = fs.roots[len(fs.roots)-1]
			fs.roots = fs.roots[:len(fs.roots)-1]
			return nil
		}
	}
	return nil
}

// accessible returns a common error if path cannot be accessed.
func (fs *FS) accessible(path string, flags Flags) error {
	if fs.access(path, flags) {
		return nil
	}
	return fmt.Errorf("%s: path not accessible", path)
}

// Accessible returns an error if path cannot be accessed.
func (fs *FS) Accessible(path string, flags Flags) error {
	fs.mtx.RLock()
	defer fs.mtx.RUnlock()
	return fs.accessible(path, flags)
}

// Create wraps os.Create, returning an error if name cannot be accessed.
func (fs *FS) Create(name string) (*os.File, error) {
	fs.mtx.RLock()
	defer fs.mtx.RUnlock()
	if err := fs.accessible(name, 0); err != nil {
		return nil, err
	}
	return os.Create(name)
}

// Create wraps os.Mkdir, returning an error if name cannot be accessed.
func (fs *FS) Mkdir(name string, perm os.FileMode) error {
	fs.mtx.RLock()
	defer fs.mtx.RUnlock()
	if err := fs.accessible(name, 0); err != nil {
		return err
	}
	return os.Mkdir(name, perm)
}

// Create wraps os.MkdirAll, returning an error if name cannot be accessed.
func (fs *FS) MkdirAll(name string, perm os.FileMode) error {
	fs.mtx.RLock()
	defer fs.mtx.RUnlock()
	if err := fs.accessible(name, 0); err != nil {
		return err
	}
	return os.MkdirAll(name, perm)
}

// Create wraps os.Open, returning an error if name cannot be accessed.
func (fs *FS) Open(name string) (*os.File, error) {
	fs.mtx.RLock()
	defer fs.mtx.RUnlock()
	if err := fs.accessible(name, 0); err != nil {
		return nil, err
	}
	return os.Open(name)
}

// Create wraps ioutil.ReadDir, returning an error if dirname cannot be
// accessed. dirname is allowed to be a root.
func (fs *FS) ReadDir(dirname string) ([]os.FileInfo, error) {
	fs.mtx.RLock()
	defer fs.mtx.RUnlock()
	if err := fs.accessible(dirname, Root); err != nil {
		return nil, err
	}
	return ioutil.ReadDir(dirname)
}

// Create wraps os.Remove, returning an error if name cannot be accessed.
func (fs *FS) Remove(name string) error {
	fs.mtx.RLock()
	defer fs.mtx.RUnlock()
	if err := fs.accessible(name, 0); err != nil {
		return err
	}
	return os.Remove(name)
}

// Create wraps os.RemoveAll, returning an error if name cannot be accessed.
func (fs *FS) RemoveAll(path string) error {
	fs.mtx.RLock()
	defer fs.mtx.RUnlock()
	if err := fs.accessible(path, 0); err != nil {
		return err
	}
	return os.RemoveAll(path)
}

// Create wraps os.Rename, returning an error if oldpath or newpath cannot be
// accessed.
func (fs *FS) Rename(oldpath, newpath string) error {
	fs.mtx.RLock()
	defer fs.mtx.RUnlock()
	if err := fs.accessible(oldpath, 0); err != nil {
		return err
	}
	if err := fs.accessible(newpath, 0); err != nil {
		return err
	}
	return os.Rename(oldpath, newpath)
}

// Create wraps os.Stat, returning an error if name cannot be accessed.
func (fs *FS) Stat(name string) (os.FileInfo, error) {
	fs.mtx.RLock()
	defer fs.mtx.RUnlock()
	if err := fs.accessible(name, 0); err != nil {
		return nil, err
	}
	return os.Stat(name)
}
<commit_msg>The destination of a file move is allowed to be a root.<commit_after>// The sfs package providing a secure file system, with access limitations.
package sfs

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

// Flags alter how access checks are made.
type Flags int

const (
	_    Flags = (1 << iota) / 2
	Root       // Path is accessible if it is a root directory.
)

// FS contains wrappers for common file system functions that also check whether
// a given path can be accessed. The zero value of an FS is ready for use.
//
// A path is accessible if it is a descendant of a root in FS. A root is not
// accessible unless the Root flag is specified.
type FS struct {
	mtx   sync.RWMutex
	roots []string
}

// access returns whether the given path can be accessed.
func (fs *FS) access(path string, flags Flags) bool {
	//TODO: Implement.
	return true
}

// AddRoot adds path as a root. Returns an error if the path could not be
// converted to an absolute path. Does nothing if the path is already a root.
func (fs *FS) AddRoot(path string) error {
	fs.mtx.Lock()
	defer fs.mtx.Unlock()

	path, err := filepath.Abs(path)
	if err != nil {
		return err
	}
	for _, root := range fs.roots {
		if path == root {
			return nil
		}
	}
	fs.roots = append(fs.roots, path)
	return nil
}

// RemoveRoot removes path as a root. Returns an error if the path could not be
// converted to an absolute path. Does nothing if the path is not a root.
func (fs *FS) RemoveRoot(path string) error {
	fs.mtx.Lock()
	defer fs.mtx.Unlock()

	path, err := filepath.Abs(path)
	if err != nil {
		return err
	}
	for i, root := range fs.roots {
		if path == root {
			fs.roots[i] = fs.roots[len(fs.roots)-1]
			fs.roots = fs.roots[:len(fs.roots)-1]
			return nil
		}
	}
	return nil
}

// accessible returns a common error if path cannot be accessed.
func (fs *FS) accessible(path string, flags Flags) error {
	if fs.access(path, flags) {
		return nil
	}
	return fmt.Errorf("%s: path not accessible", path)
}

// Accessible returns an error if path cannot be accessed.
func (fs *FS) Accessible(path string, flags Flags) error {
	fs.mtx.RLock()
	defer fs.mtx.RUnlock()
	return fs.accessible(path, flags)
}

// Create wraps os.Create, returning an error if name cannot be accessed.
func (fs *FS) Create(name string) (*os.File, error) {
	fs.mtx.RLock()
	defer fs.mtx.RUnlock()
	if err := fs.accessible(name, 0); err != nil {
		return nil, err
	}
	return os.Create(name)
}

// Create wraps os.Mkdir, returning an error if name cannot be accessed.
func (fs *FS) Mkdir(name string, perm os.FileMode) error {
	fs.mtx.RLock()
	defer fs.mtx.RUnlock()
	if err := fs.accessible(name, 0); err != nil {
		return err
	}
	return os.Mkdir(name, perm)
}

// Create wraps os.MkdirAll, returning an error if name cannot be accessed.
func (fs *FS) MkdirAll(name string, perm os.FileMode) error {
	fs.mtx.RLock()
	defer fs.mtx.RUnlock()
	if err := fs.accessible(name, 0); err != nil {
		return err
	}
	return os.MkdirAll(name, perm)
}

// Create wraps os.Open, returning an error if name cannot be accessed.
func (fs *FS) Open(name string) (*os.File, error) {
	fs.mtx.RLock()
	defer fs.mtx.RUnlock()
	if err := fs.accessible(name, 0); err != nil {
		return nil, err
	}
	return os.Open(name)
}

// Create wraps ioutil.ReadDir, returning an error if dirname cannot be
// accessed. dirname is allowed to be a root.
func (fs *FS) ReadDir(dirname string) ([]os.FileInfo, error) {
	fs.mtx.RLock()
	defer fs.mtx.RUnlock()
	if err := fs.accessible(dirname, Root); err != nil {
		return nil, err
	}
	return ioutil.ReadDir(dirname)
}

// Create wraps os.Remove, returning an error if name cannot be accessed.
func (fs *FS) Remove(name string) error {
	fs.mtx.RLock()
	defer fs.mtx.RUnlock()
	if err := fs.accessible(name, 0); err != nil {
		return err
	}
	return os.Remove(name)
}

// Create wraps os.RemoveAll, returning an error if name cannot be accessed.
func (fs *FS) RemoveAll(path string) error {
	fs.mtx.RLock()
	defer fs.mtx.RUnlock()
	if err := fs.accessible(path, 0); err != nil {
		return err
	}
	return os.RemoveAll(path)
}

// Create wraps os.Rename, returning an error if oldpath or newpath cannot be
// accessed.
func (fs *FS) Rename(oldpath, newpath string) error {
	fs.mtx.RLock()
	defer fs.mtx.RUnlock()
	if err := fs.accessible(oldpath, 0); err != nil {
		return err
	}
	if err := fs.accessible(newpath, Root); err != nil {
		return err
	}
	return os.Rename(oldpath, newpath)
}

// Create wraps os.Stat, returning an error if name cannot be accessed.
func (fs *FS) Stat(name string) (os.FileInfo, error) {
	fs.mtx.RLock()
	defer fs.mtx.RUnlock()
	if err := fs.accessible(name, 0); err != nil {
		return nil, err
	}
	return os.Stat(name)
}
<|endoftext|>


<commit_before>// TODO: handle sigint correctly

//go:generate go tool yacc -p "sh" sh.y

package main

import (
	"bufio"
	"fmt"
	"io"
	"log"
	"os"
)

func main() {
	log.SetPrefix("sh: ")
	log.SetFlags(0)
	setupEnv()
	in := bufio.NewReader(os.Stdin)
	tty := isTTY(os.Stdin)
	for {
		if tty {
			fmt.Print(os.Getenv("prompt"))
		}
		line, err := in.ReadString('\n')
		if err == io.EOF {
			return
		}
		if err != nil {
			log.Fatal(err)
		}
		shParse(&shLex{line: os.ExpandEnv(line)})
	}
}
<commit_msg>sh: add l flag<commit_after>// TODO: handle sigint correctly

//go:generate go tool yacc -p "sh" sh.y

package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
)

var lflag = flag.String("l", "", "read commands from `file` before reading normal input")

func main() {
	log.SetPrefix("sh: ")
	log.SetFlags(0)
	setupEnv()
	flag.Parse()
	if *lflag != "" {
		f, err := os.Open(*lflag)
		if err != nil {
			log.Print(err)
		} else {
			parse(f)
		}
	}
	parse(os.Stdin)
}

func parse(f *os.File) {
	in := bufio.NewReader(f)
	tty := isTTY(f)
	for {
		if tty {
			fmt.Print(os.Getenv("prompt"))
		}
		line, err := in.ReadString('\n')
		if err == io.EOF {
			return
		}
		if err != nil {
			log.Fatal(err)
		}
		shParse(&shLex{line: os.ExpandEnv(line)})
	}
}
<|endoftext|>


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

package state

import (
	"github.com/juju/names"
	jujutesting "github.com/juju/testing"
	jc "github.com/juju/testing/checkers"
	gc "gopkg.in/check.v1"
	"gopkg.in/mgo.v2/txn"

	"github.com/juju/juju/mongo"
	"github.com/juju/juju/mongo/mongotest"
	"github.com/juju/juju/testing"
)

var _ = gc.Suite(&internalStateSuite{})

// internalStateSuite manages a *State instance for tests in the state
// package (i.e. internal tests) that need it. It is similar to
// state.testing.StateSuite but is duplicated to avoid cyclic imports.
type internalStateSuite struct {
	jujutesting.MgoSuite
	testing.BaseSuite
	state *State
	owner names.UserTag
	model names.ModelTag
}

func getInfo() *mongo.MongoInfo {
	// Copied from NewMongoInfo (due to import loops).
	return &mongo.MongoInfo{
		Info: mongo.Info{
			Addrs:  []string{jujutesting.MgoServer.Addr()},
			CACert: testing.CACert,
		},
	}
}

func (s *internalStateSuite) SetUpSuite(c *gc.C) {
	txn.SetLogger(c)
	txn.SetDebug(true)

	s.MgoSuite.SetUpSuite(c)
	s.BaseSuite.SetUpSuite(c)
	s.owner = names.NewLocalUserTag("test-admin")
	st, err := Initialize(s.owner, getInfo(), testing.ModelConfig(c), mongotest.DialOpts(), nil)
	c.Assert(err, jc.ErrorIsNil)
	s.model = st.modelTag
	st.Close()
}

func (s *internalStateSuite) TearDownSuite(c *gc.C) {
	s.BaseSuite.TearDownSuite(c)
	s.MgoSuite.TearDownSuite(c)
}

func (s *internalStateSuite) SetUpTest(c *gc.C) {
	s.MgoSuite.SetUpTest(c)
	s.BaseSuite.SetUpTest(c)
	st, err := Open(s.model, getInfo(), mongotest.DialOpts(), nil)
	c.Assert(err, jc.ErrorIsNil)
	s.state = st
	s.AddCleanup(func(c *gc.C) {
		c.Logf("closing state")
		s.state.Close()
	})
}

func (s *internalStateSuite) TearDownTest(c *gc.C) {
	s.BaseSuite.TearDownTest(c)
	s.MgoSuite.TearDownTest(c)
	c.Logf("repopulating model")
	err := PopulateEmptyModel(s.state, s.owner, getInfo(), testing.ModelConfig(c))
	c.Assert(err, jc.ErrorIsNil)
	c.Logf("leaving internalStateSuite.TearDownTest")
}
<commit_msg>Do BaseSuite teardown last<commit_after>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package state

import (
	"github.com/juju/names"
	jujutesting "github.com/juju/testing"
	jc "github.com/juju/testing/checkers"
	gc "gopkg.in/check.v1"

	"github.com/juju/juju/mongo"
	"github.com/juju/juju/mongo/mongotest"
	"github.com/juju/juju/testing"
)

var _ = gc.Suite(&internalStateSuite{})

// internalStateSuite manages a *State instance for tests in the state
// package (i.e. internal tests) that need it. It is similar to
// state.testing.StateSuite but is duplicated to avoid cyclic imports.
type internalStateSuite struct {
	jujutesting.MgoSuite
	testing.BaseSuite
	state *State
	owner names.UserTag
	model names.ModelTag
}

func getInfo() *mongo.MongoInfo {
	// Copied from NewMongoInfo (due to import loops).
	return &mongo.MongoInfo{
		Info: mongo.Info{
			Addrs:  []string{jujutesting.MgoServer.Addr()},
			CACert: testing.CACert,
		},
	}
}

func (s *internalStateSuite) SetUpSuite(c *gc.C) {
	s.MgoSuite.SetUpSuite(c)
	s.BaseSuite.SetUpSuite(c)
	s.owner = names.NewLocalUserTag("test-admin")
	st, err := Initialize(s.owner, getInfo(), testing.ModelConfig(c), mongotest.DialOpts(), nil)
	c.Assert(err, jc.ErrorIsNil)
	s.model = st.modelTag
	st.Close()
}

func (s *internalStateSuite) TearDownSuite(c *gc.C) {
	s.BaseSuite.TearDownSuite(c)
	s.MgoSuite.TearDownSuite(c)
}

func (s *internalStateSuite) SetUpTest(c *gc.C) {
	s.MgoSuite.SetUpTest(c)
	s.BaseSuite.SetUpTest(c)
	st, err := Open(s.model, getInfo(), mongotest.DialOpts(), nil)
	c.Logf("opening state")
	c.Assert(err, jc.ErrorIsNil)
	s.state = st
	s.AddCleanup(func(c *gc.C) {
		s.state.Close()
		c.Logf("state closed")
	})
}

func (s *internalStateSuite) TearDownTest(c *gc.C) {
	s.MgoSuite.TearDownTest(c)
	c.Logf("repopulating model")
	err := PopulateEmptyModel(s.state, s.owner, getInfo(), testing.ModelConfig(c))
	c.Assert(err, jc.ErrorIsNil)
	c.Logf("leaving internalStateSuite.TearDownTest")
	s.BaseSuite.TearDownTest(c)
}
<|endoftext|>


<commit_before>package test

import (
	"sync/atomic"
	"testing"
	"time"

	"github.com/nats-io/nats"
)

// More advanced tests on subscriptions

func TestServerAutoUnsub(t *testing.T) {
	s := RunDefaultServer()
	defer s.Shutdown()

	nc := NewDefaultConnection(t)
	defer nc.Close()
	received := int32(0)
	max := int32(10)
	sub, err := nc.Subscribe("foo", func(_ *nats.Msg) {
		atomic.AddInt32(&received, 1)
	})
	if err != nil {
		t.Fatal("Failed to subscribe: ", err)
	}
	sub.AutoUnsubscribe(int(max))
	total := 100
	for i := 0; i < total; i++ {
		nc.Publish("foo", []byte("Hello"))
	}
	nc.Flush()
	time.Sleep(10 * time.Millisecond)

	if atomic.LoadInt32(&received) != max {
		t.Fatalf("Received %d msgs, wanted only %d\n", received, max)
	}
}

func TestClientSyncAutoUnsub(t *testing.T) {
	s := RunDefaultServer()
	defer s.Shutdown()

	nc := NewDefaultConnection(t)
	defer nc.Close()
	received := 0
	max := 10
	sub, _ := nc.SubscribeSync("foo")
	total := 100
	for i := 0; i < total; i++ {
		nc.Publish("foo", []byte("Hello"))
	}
	sub.AutoUnsubscribe(max)
	nc.Flush()
	for {
		_, err := sub.NextMsg(1 * time.Millisecond)
		if err != nil {
			break
		}
		received += 1
	}
	if received != max {
		t.Fatalf("Received %d msgs, wanted only %d\n", received, max)
	}
}

func TestClientASyncAutoUnsub(t *testing.T) {
	s := RunDefaultServer()
	defer s.Shutdown()

	nc := NewDefaultConnection(t)
	defer nc.Close()
	received := int32(0)
	max := int32(10)
	sub, err := nc.Subscribe("foo", func(_ *nats.Msg) {
		atomic.AddInt32(&received, 1)
	})
	if err != nil {
		t.Fatal("Failed to subscribe: ", err)
	}
	total := 100
	for i := 0; i < total; i++ {
		nc.Publish("foo", []byte("Hello"))
	}
	sub.AutoUnsubscribe(int(max))
	nc.Flush()
	time.Sleep(10 * time.Millisecond)

	if atomic.LoadInt32(&received) != max {
		t.Fatalf("Received %d msgs, wanted only %d\n", received, max)
	}
}

func TestCloseSubRelease(t *testing.T) {
	s := RunDefaultServer()
	defer s.Shutdown()

	nc := NewDefaultConnection(t)
	sub, _ := nc.SubscribeSync("foo")
	start := time.Now()
	go func() {
		time.Sleep(5 * time.Millisecond)
		nc.Close()
	}()
	_, err := sub.NextMsg(50 * time.Millisecond)
	if err == nil {
		t.Fatalf("Expected an error from NextMsg")
	}
	elapsed := time.Since(start)
	if elapsed > 10*time.Millisecond {
		t.Fatalf("Too much time has elapsed to release NextMsg: %dms",
			(elapsed / time.Millisecond))
	}
}

func TestIsValidSubscriber(t *testing.T) {
	s := RunDefaultServer()
	defer s.Shutdown()

	nc := NewDefaultConnection(t)
	defer nc.Close()

	sub, err := nc.SubscribeSync("foo")
	if !sub.IsValid() {
		t.Fatalf("Subscription should be valid")
	}
	for i := 0; i < 10; i++ {
		nc.Publish("foo", []byte("Hello"))
	}
	nc.Flush()
	_, err = sub.NextMsg(200 * time.Millisecond)
	if err != nil {
		t.Fatalf("NextMsg returned an error")
	}
	sub.Unsubscribe()
	_, err = sub.NextMsg(200 * time.Millisecond)
	if err == nil {
		t.Fatalf("NextMsg should have returned an error")
	}
}

func TestSlowSubscriber(t *testing.T) {
	s := RunDefaultServer()
	defer s.Shutdown()

	nc := NewDefaultConnection(t)
	defer nc.Close()

	sub, _ := nc.SubscribeSync("foo")
	for i := 0; i < (nc.Opts.SubChanLen + 100); i++ {
		nc.Publish("foo", []byte("Hello"))
	}
	timeout := 5 * time.Second
	start := time.Now()
	nc.FlushTimeout(timeout)
	elapsed := time.Since(start)
	if elapsed >= timeout {
		t.Fatalf("Flush did not return before timeout: %d > %d", elapsed, timeout)
	}
	// Make sure NextMsg returns an error to indicate slow consumer
	_, err := sub.NextMsg(200 * time.Millisecond)
	if err == nil {
		t.Fatalf("NextMsg did not return an error")
	}
}

func TestSlowAsyncSubscriber(t *testing.T) {
	s := RunDefaultServer()
	defer s.Shutdown()

	nc := NewDefaultConnection(t)
	defer nc.Close()

	bch := make(chan bool)

	nc.Subscribe("foo", func(_ *nats.Msg) {
		// block to back us up..
		<-bch
	})
	for i := 0; i < (nc.Opts.SubChanLen + 100); i++ {
		nc.Publish("foo", []byte("Hello"))
	}
	timeout := 5 * time.Second
	start := time.Now()
	err := nc.FlushTimeout(timeout)
	elapsed := time.Since(start)
	if elapsed >= timeout {
		t.Fatalf("Flush did not return before timeout")
	}
	if err == nil {
		t.Fatal("Expected an error indicating slow consumer")
	}
	// release the sub
	bch <- true
}

func TestAsyncErrHandler(t *testing.T) {
	s := RunDefaultServer()
	defer s.Shutdown()

	// Limit internal subchan length to trip condition easier.
	opts := nats.DefaultOptions
	opts.SubChanLen = 10

	nc, err := opts.Connect()
	if err != nil {
		t.Fatalf("Could not connect to server: %v\n", err)
	}
	defer nc.Close()

	subj := "async_test"
	bch := make(chan bool)

	sub, err := nc.Subscribe(subj, func(_ *nats.Msg) {
		// block to back us up..
		<-bch
	})
	if err != nil {
		t.Fatalf("Could not subscribe: %v\n", err)
	}

	ch := make(chan bool)

	aeCalled := false

	nc.Opts.AsyncErrorCB = func(c *nats.Conn, s *nats.Subscription, e error) {
		// Suppress additional calls
		if aeCalled {
			return
		}
		aeCalled = true

		if s != sub {
			t.Fatal("Did not receive proper subscription")
		}
		if e != nats.ErrSlowConsumer {
			t.Fatalf("Did not receive proper error: %v vs %v\n", e, nats.ErrSlowConsumer)
		}
		// release the sub
		bch <- true

		// release the test
		ch <- true
	}

	b := []byte("Hello World!")
	for i := 0; i < (nc.Opts.SubChanLen + 100); i++ {
		nc.Publish(subj, b)
	}
	nc.Flush()

	if e := Wait(ch); e != nil {
		t.Fatal("Failed to call async err handler")
	}
}

// Test to make sure that we can send and async receive messages on
// different subjects within a callback.
func TestAsyncSubscriberStarvation(t *testing.T) {
	s := RunDefaultServer()
	defer s.Shutdown()

	nc := NewDefaultConnection(t)
	defer nc.Close()

	// Helper
	nc.Subscribe("helper", func(m *nats.Msg) {
		nc.Publish(m.Reply, []byte("Hello"))
	})

	ch := make(chan bool)

	// Kickoff
	nc.Subscribe("start", func(m *nats.Msg) {
		// Helper Response
		response := nats.NewInbox()
		nc.Subscribe(response, func(_ *nats.Msg) {
			ch <- true
		})
		nc.PublishRequest("helper", response, []byte("Help Me!"))
	})

	nc.Publish("start", []byte("Begin"))
	nc.Flush()

	if e := Wait(ch); e != nil {
		t.Fatal("Was stalled inside of callback waiting on another callback")
	}
}

func TestAsyncSubscribersOnClose(t *testing.T) {
	s := RunDefaultServer()
	defer s.Shutdown()

	nc := NewDefaultConnection(t)

	toSend := 10
	callbacks := int32(0)
	ch := make(chan bool, toSend)

	nc.Subscribe("foo", func(_ *nats.Msg) {
		atomic.AddInt32(&callbacks, 1)
		<-ch
	})

	for i := 0; i < toSend; i++ {
		nc.Publish("foo", []byte("Hello World!"))
	}
	nc.Flush()
	time.Sleep(10 * time.Millisecond)
	nc.Close()

	// Release callbacks
	for i := 1; i < toSend; i++ {
		ch <- true
	}

	// Wait for some time.
	time.Sleep(10 * time.Millisecond)
	seen := atomic.LoadInt32(&callbacks)
	if seen != 1 {
		t.Fatalf("Expected only one callback, received %d callbacks\n", seen)
	}
}

func TestNextMsgCallOnAsyncSub(t *testing.T) {
	s := RunDefaultServer()
	defer s.Shutdown()

	nc := NewDefaultConnection(t)
	defer nc.Close()
	sub, err := nc.Subscribe("foo", func(_ *nats.Msg) {
	})
	if err != nil {
		t.Fatal("Failed to subscribe: ", err)
	}
	_, err = sub.NextMsg(time.Second)
	if err == nil {
		t.Fatal("Expected an error call NextMsg() on AsyncSubscriber")
	}
}
<commit_msg>test fixes<commit_after>package test

import (
	"sync/atomic"
	"testing"
	"time"

	"github.com/nats-io/nats"
)

// More advanced tests on subscriptions

func TestServerAutoUnsub(t *testing.T) {
	s := RunDefaultServer()
	defer s.Shutdown()

	nc := NewDefaultConnection(t)
	defer nc.Close()
	received := int32(0)
	max := int32(10)
	sub, err := nc.Subscribe("foo", func(_ *nats.Msg) {
		atomic.AddInt32(&received, 1)
	})
	if err != nil {
		t.Fatal("Failed to subscribe: ", err)
	}
	sub.AutoUnsubscribe(int(max))
	total := 100
	for i := 0; i < total; i++ {
		nc.Publish("foo", []byte("Hello"))
	}
	nc.Flush()
	time.Sleep(10 * time.Millisecond)

	if atomic.LoadInt32(&received) != max {
		t.Fatalf("Received %d msgs, wanted only %d\n", received, max)
	}
}

func TestClientSyncAutoUnsub(t *testing.T) {
	s := RunDefaultServer()
	defer s.Shutdown()

	nc := NewDefaultConnection(t)
	defer nc.Close()
	received := 0
	max := 10
	sub, _ := nc.SubscribeSync("foo")
	total := 100
	for i := 0; i < total; i++ {
		nc.Publish("foo", []byte("Hello"))
	}
	sub.AutoUnsubscribe(max)
	nc.Flush()
	for {
		_, err := sub.NextMsg(1 * time.Millisecond)
		if err != nil {
			break
		}
		received += 1
	}
	if received != max {
		t.Fatalf("Received %d msgs, wanted only %d\n", received, max)
	}
}

func TestClientASyncAutoUnsub(t *testing.T) {
	s := RunDefaultServer()
	defer s.Shutdown()

	nc := NewDefaultConnection(t)
	defer nc.Close()
	received := int32(0)
	max := int32(10)
	sub, err := nc.Subscribe("foo", func(_ *nats.Msg) {
		atomic.AddInt32(&received, 1)
	})
	if err != nil {
		t.Fatal("Failed to subscribe: ", err)
	}
	sub.AutoUnsubscribe(int(max))
	total := 100
	for i := 0; i < total; i++ {
		nc.Publish("foo", []byte("Hello"))
	}
	nc.Flush()
	time.Sleep(10 * time.Millisecond)

	if atomic.LoadInt32(&received) != max {
		t.Fatalf("Received %d msgs, wanted only %d\n", received, max)
	}
}

func TestCloseSubRelease(t *testing.T) {
	s := RunDefaultServer()
	defer s.Shutdown()

	nc := NewDefaultConnection(t)
	sub, _ := nc.SubscribeSync("foo")
	start := time.Now()
	go func() {
		time.Sleep(5 * time.Millisecond)
		nc.Close()
	}()
	_, err := sub.NextMsg(50 * time.Millisecond)
	if err == nil {
		t.Fatalf("Expected an error from NextMsg")
	}
	elapsed := time.Since(start)
	if elapsed > 10*time.Millisecond {
		t.Fatalf("Too much time has elapsed to release NextMsg: %dms",
			(elapsed / time.Millisecond))
	}
}

func TestIsValidSubscriber(t *testing.T) {
	s := RunDefaultServer()
	defer s.Shutdown()

	nc := NewDefaultConnection(t)
	defer nc.Close()

	sub, err := nc.SubscribeSync("foo")
	if !sub.IsValid() {
		t.Fatalf("Subscription should be valid")
	}
	for i := 0; i < 10; i++ {
		nc.Publish("foo", []byte("Hello"))
	}
	nc.Flush()
	_, err = sub.NextMsg(200 * time.Millisecond)
	if err != nil {
		t.Fatalf("NextMsg returned an error")
	}
	sub.Unsubscribe()
	_, err = sub.NextMsg(200 * time.Millisecond)
	if err == nil {
		t.Fatalf("NextMsg should have returned an error")
	}
}

func TestSlowSubscriber(t *testing.T) {
	s := RunDefaultServer()
	defer s.Shutdown()

	nc := NewDefaultConnection(t)
	defer nc.Close()

	sub, _ := nc.SubscribeSync("foo")
	for i := 0; i < (nc.Opts.SubChanLen + 100); i++ {
		nc.Publish("foo", []byte("Hello"))
	}
	timeout := 5 * time.Second
	start := time.Now()
	nc.FlushTimeout(timeout)
	elapsed := time.Since(start)
	if elapsed >= timeout {
		t.Fatalf("Flush did not return before timeout: %d > %d", elapsed, timeout)
	}
	// Make sure NextMsg returns an error to indicate slow consumer
	_, err := sub.NextMsg(200 * time.Millisecond)
	if err == nil {
		t.Fatalf("NextMsg did not return an error")
	}
}

func TestSlowAsyncSubscriber(t *testing.T) {
	s := RunDefaultServer()
	defer s.Shutdown()

	nc := NewDefaultConnection(t)
	defer nc.Close()

	bch := make(chan bool)

	nc.Subscribe("foo", func(_ *nats.Msg) {
		// block to back us up..
		<-bch
	})
	for i := 0; i < (nc.Opts.SubChanLen + 100); i++ {
		nc.Publish("foo", []byte("Hello"))
	}
	timeout := 5 * time.Second
	start := time.Now()
	err := nc.FlushTimeout(timeout)
	elapsed := time.Since(start)
	if elapsed >= timeout {
		t.Fatalf("Flush did not return before timeout")
	}
	if err == nil {
		t.Fatal("Expected an error indicating slow consumer")
	}
	// release the sub
	bch <- true
}

func TestAsyncErrHandler(t *testing.T) {
	s := RunDefaultServer()
	defer s.Shutdown()

	// Limit internal subchan length to trip condition easier.
	opts := nats.DefaultOptions
	opts.SubChanLen = 10

	nc, err := opts.Connect()
	if err != nil {
		t.Fatalf("Could not connect to server: %v\n", err)
	}
	defer nc.Close()

	subj := "async_test"
	bch := make(chan bool)

	sub, err := nc.Subscribe(subj, func(_ *nats.Msg) {
		// block to back us up..
		<-bch
	})
	if err != nil {
		t.Fatalf("Could not subscribe: %v\n", err)
	}

	ch := make(chan bool)

	aeCalled := int64(0)

	nc.Opts.AsyncErrorCB = func(c *nats.Conn, s *nats.Subscription, e error) {
		// Suppress additional calls
		if atomic.LoadInt64(&aeCalled) == 1 {
			return
		}
		atomic.AddInt64(&aeCalled, 1)

		if s != sub {
			t.Fatal("Did not receive proper subscription")
		}
		if e != nats.ErrSlowConsumer {
			t.Fatalf("Did not receive proper error: %v vs %v\n", e, nats.ErrSlowConsumer)
		}
		// release the sub
		bch <- true

		// release the test
		ch <- true
	}

	b := []byte("Hello World!")
	for i := 0; i < (nc.Opts.SubChanLen + 100); i++ {
		nc.Publish(subj, b)
	}
	nc.Flush()

	if e := Wait(ch); e != nil {
		t.Fatal("Failed to call async err handler")
	}
}

// Test to make sure that we can send and async receive messages on
// different subjects within a callback.
func TestAsyncSubscriberStarvation(t *testing.T) {
	s := RunDefaultServer()
	defer s.Shutdown()

	nc := NewDefaultConnection(t)
	defer nc.Close()

	// Helper
	nc.Subscribe("helper", func(m *nats.Msg) {
		nc.Publish(m.Reply, []byte("Hello"))
	})

	ch := make(chan bool)

	// Kickoff
	nc.Subscribe("start", func(m *nats.Msg) {
		// Helper Response
		response := nats.NewInbox()
		nc.Subscribe(response, func(_ *nats.Msg) {
			ch <- true
		})
		nc.PublishRequest("helper", response, []byte("Help Me!"))
	})

	nc.Publish("start", []byte("Begin"))
	nc.Flush()

	if e := Wait(ch); e != nil {
		t.Fatal("Was stalled inside of callback waiting on another callback")
	}
}

func TestAsyncSubscribersOnClose(t *testing.T) {
	s := RunDefaultServer()
	defer s.Shutdown()

	nc := NewDefaultConnection(t)

	toSend := 10
	callbacks := int32(0)
	ch := make(chan bool, toSend)

	nc.Subscribe("foo", func(_ *nats.Msg) {
		atomic.AddInt32(&callbacks, 1)
		<-ch
	})

	for i := 0; i < toSend; i++ {
		nc.Publish("foo", []byte("Hello World!"))
	}
	nc.Flush()
	time.Sleep(10 * time.Millisecond)
	nc.Close()

	// Release callbacks
	for i := 1; i < toSend; i++ {
		ch <- true
	}

	// Wait for some time.
	time.Sleep(10 * time.Millisecond)
	seen := atomic.LoadInt32(&callbacks)
	if seen != 1 {
		t.Fatalf("Expected only one callback, received %d callbacks\n", seen)
	}
}

func TestNextMsgCallOnAsyncSub(t *testing.T) {
	s := RunDefaultServer()
	defer s.Shutdown()

	nc := NewDefaultConnection(t)
	defer nc.Close()
	sub, err := nc.Subscribe("foo", func(_ *nats.Msg) {
	})
	if err != nil {
		t.Fatal("Failed to subscribe: ", err)
	}
	_, err = sub.NextMsg(time.Second)
	if err == nil {
		t.Fatal("Expected an error call NextMsg() on AsyncSubscriber")
	}
}
<|endoftext|>


<commit_before>package invokeAndQuery

import (
	"github.com/hyperledger/fabric/core/chaincode/shim"
	"build-chaincode/entities"
	"encoding/json"
	"errors"
	"build-chaincode/util"
	"crypto/sha256"
	"encoding/hex"
)

func CreateProject(stub shim.ChaincodeStubInterface, projectAsJson string) error {
	var project entities.Project
	err := json.Unmarshal([]byte(projectAsJson), &project)
	if err != nil {
		return errors.New("Error while unmarshalling trade, reason: " + err.Error())
	}

	// check if ProjectID exists, if not, the project cant be stored in the chaincode
	if project.ProjectID == "" {
		return errors.New("ProjectID is empty")
	}

	// TODO add validation for all the other fields

	// check if current user belongs to either the freelancer or the client
	userCompany, err := util.GetCompanyByCertificate(stub)
	if err != nil {
		return errors.New("Error while getting user company, reason: " + err.Error())
	}

	if userCompany.CompanyID != project.Freelancer && userCompany.CompanyID != project.Client {
		return errors.New("Current user doesn't belong to either the client or freelancer company")
	}

	user, err := util.GetCurrentBlockchainUser(stub)
	if err != nil {
		return errors.New("Error while getting user, reason" + err.Error())
	}

	project.CreatorID = user.UserID

	//marshall the trade so it can be stored in the chain.
	projectAsBytes, err := json.Marshal(project)
	if err != nil {
		return errors.New("Error in marshalling project" + err.Error())
	}

	//use the storeobject function to store the project
	util.StoreObjectInChain(stub, project.ProjectID, util.ProjectsIndexName, projectAsBytes)

	return nil
}

func GetProjectsForTax(stub shim.ChaincodeStubInterface) ([]entities.ProjectForTax, error) {
	projectsIndex, err := util.GetIndex(stub, util.ProjectsIndexName)
	if err != nil {
		return []entities.ProjectForTax{}, errors.New("Unable to retrieve projectsIndex, reason: " + err.Error())
	}

	projects := []entities.ProjectForTax{}
	for _, projectID := range projectsIndex {
		projectAsBytes, err := stub.GetState(projectID)
		if err != nil {
			return []entities.ProjectForTax{}, errors.New("Could not retrieve project for ID " + projectID + " reason: " + err.Error())
		}

		var project entities.ProjectForTax
		err = json.Unmarshal(projectAsBytes, &project)
		if err != nil {
			return []entities.ProjectForTax{}, errors.New("Error while unmarshalling projectAsBytes, reason: " + err.Error())
		}

		if project.Signatures.SignedByBothParties {
			projects = append(projects, project)
		}
	}
	return projects, nil
}

func GetProjectsForCompanies(stub shim.ChaincodeStubInterface)  ([]entities.Project, error) {
	userCompany, err := util.GetCompanyByCertificate(stub)
	if err != nil {
		return []entities.Project{}, errors.New("Error while getting user company, reason: " + err.Error())
	}

	projectsIndex, err := util.GetIndex(stub, util.ProjectsIndexName)
	if err != nil {
		return []entities.Project{}, errors.New("Unable to retrieve projectsIndex, reason: " + err.Error())
	}

	projects := []entities.Project{}
	for _, projectID := range projectsIndex {
		projectAsBytes, err := stub.GetState(projectID)
		if err != nil {
			return []entities.Project{}, errors.New("Could not retrieve project for ID " + projectID + " reason: " + err.Error())
		}

		var project entities.Project
		err = json.Unmarshal(projectAsBytes, &project)
		if err != nil {
			return []entities.Project{}, errors.New("Error while unmarshalling projectAsBytes, reason: " + err.Error())
		}

		if project.Freelancer == userCompany.CompanyID || project.Client == userCompany.CompanyID {
			projects = append(projects, project)
		}
	}
	return projects, nil
}

func GetProjectByID(stub shim.ChaincodeStubInterface, projectID string) (entities.Project, error) {
	userCompany, err := util.GetCompanyByCertificate(stub)
	if err != nil {
		return entities.Project{}, errors.New("Error while getting user company, reason: " + err.Error())
	}

	projectAsBytes, err := stub.GetState(projectID)
	if err != nil {
		return entities.Project{}, errors.New("Could not retrieve project for ID " + projectID + " reason: " + err.Error())
	}

	var project entities.Project
	err = json.Unmarshal(projectAsBytes, &project)
	if err != nil {
		return entities.Project{}, errors.New("Error while unmarshalling projectAsBytes, reason: " + err.Error())
	}

	if project.Freelancer == userCompany.CompanyID || project.Client == userCompany.CompanyID {
		return project, nil
	}

	return entities.Project{}, nil
}

func SignAgreement(stub shim.ChaincodeStubInterface, projectID string, timestamp int64) error {
	project, err := GetProjectByID(stub, projectID)
	if err != nil {
		return errors.New("Error while getting project, reason: " + err.Error())
	}

	user, err := util.GetCurrentBlockchainUser(stub)
	if err != nil {
		return errors.New("Unable to retrieve user, reason: " + err.Error())
	}

	userCompany, err := util.GetCompanyByCertificate(stub)
	if err != nil {
		return errors.New("Error while getting user company, reason: " + err.Error())
	}

	if userCompany.CompanyID != project.Freelancer && userCompany.CompanyID != project.Client {
		return errors.New("Current user doesn't belong to either the client or freelancer company")
	}

	userRole, err := GetUserRole(userCompany.CompanyID, project)
	if err != nil {
		return err
	}

	projectHash := createProjectHash(project)

	signature := entities.Signature{Timestamp: timestamp, Hash: projectHash, UserID: user.UserID}

	if userRole == "freelancer" {
		project.Signatures.FreelancerSignature = signature;
	} else if userRole == "client" {
		project.Signatures.ClientSignature = signature;
	}

	if project.Signatures.FreelancerSignature.Hash == project.Signatures.ClientSignature.Hash {
		project.Signatures.SignedByBothParties = true;
		project.Status = "Signed"
	} else {
		project.Status = "Pending validation"
	}

	projectAsBytes, err := json.Marshal(project)
	if err != nil {
		return errors.New("Error in marshalling project" + err.Error())
	}

	err = stub.PutState(projectID, projectAsBytes)
	if err != nil {
		return errors.New("Could not store project" + err.Error())
	}

	return nil
}

func GetUserRole(companyID string, project entities.Project) (string, error) {
	if companyID == project.Freelancer {
		return "freelancer", nil
	} else if companyID == project.Client {
		return "client", nil
	} else {
		return "", errors.New("Can't find the role")
	}
}

func createProjectHash(project entities.Project) (string) {
	return calculate_hash([]string{
		project.ProjectID,
		project.ProjectName,
		project.Freelancer,
		project.Client,
		string(project.StartDate),
		string(project.EndDate),
		string(project.HoursPerWeek),
		project.PaymentType,
		project.PaymentTrigger,
		project.Description,
		project.Deliverables,
		project.Location,
		project.CreatorID})
}

func calculate_hash(args []string) string {
	var str = ""
	for _, v := range args {
		str += v
	}
	hasher := sha256.New()
	hasher.Write([]byte(str))
	return hex.EncodeToString(hasher.Sum(nil))
}<commit_msg>add extra check for project creation<commit_after>package invokeAndQuery

import (
	"github.com/hyperledger/fabric/core/chaincode/shim"
	"build-chaincode/entities"
	"encoding/json"
	"errors"
	"build-chaincode/util"
	"crypto/sha256"
	"encoding/hex"
)

func CreateProject(stub shim.ChaincodeStubInterface, projectAsJson string) error {
	var project entities.Project
	err := json.Unmarshal([]byte(projectAsJson), &project)
	if err != nil {
		return errors.New("Error while unmarshalling trade, reason: " + err.Error())
	}

	// check if ProjectID exists, if not, the project cant be stored in the chaincode
	if project.ProjectID == "" {
		return errors.New("ProjectID is empty")
	}

	if project.ProjectName == "" {
		return errors.New("ProjectName is empty")
	}

	if project.Freelancer == "" {
		return errors.New("Freelancer is empty")
	}

	if project.Client == "" {
		return errors.New("Client is empty")
	}

	if project.StartDate > project.EndDate {
		return errors.New("StartDate is after EndDate")
	}

	if project.HoursPerWeek <= 0 {
		return errors.New("Hours per week must be greater than zero")
	}

	// check if current user belongs to either the freelancer or the client
	userCompany, err := util.GetCompanyByCertificate(stub)
	if err != nil {
		return errors.New("Error while getting user company, reason: " + err.Error())
	}

	if userCompany.CompanyID != project.Freelancer && userCompany.CompanyID != project.Client {
		return errors.New("Current user doesn't belong to either the client or freelancer company")
	}

	user, err := util.GetCurrentBlockchainUser(stub)
	if err != nil {
		return errors.New("Error while getting user, reason" + err.Error())
	}

	project.CreatorID = user.UserID

	//marshall the trade so it can be stored in the chain.
	projectAsBytes, err := json.Marshal(project)
	if err != nil {
		return errors.New("Error in marshalling project" + err.Error())
	}

	//use the storeobject function to store the project
	util.StoreObjectInChain(stub, project.ProjectID, util.ProjectsIndexName, projectAsBytes)

	return nil
}

func GetProjectsForTax(stub shim.ChaincodeStubInterface) ([]entities.ProjectForTax, error) {
	projectsIndex, err := util.GetIndex(stub, util.ProjectsIndexName)
	if err != nil {
		return []entities.ProjectForTax{}, errors.New("Unable to retrieve projectsIndex, reason: " + err.Error())
	}

	projects := []entities.ProjectForTax{}
	for _, projectID := range projectsIndex {
		projectAsBytes, err := stub.GetState(projectID)
		if err != nil {
			return []entities.ProjectForTax{}, errors.New("Could not retrieve project for ID " + projectID + " reason: " + err.Error())
		}

		var project entities.ProjectForTax
		err = json.Unmarshal(projectAsBytes, &project)
		if err != nil {
			return []entities.ProjectForTax{}, errors.New("Error while unmarshalling projectAsBytes, reason: " + err.Error())
		}

		if project.Signatures.SignedByBothParties {
			projects = append(projects, project)
		}
	}
	return projects, nil
}

func GetProjectsForCompanies(stub shim.ChaincodeStubInterface) ([]entities.Project, error) {
	userCompany, err := util.GetCompanyByCertificate(stub)
	if err != nil {
		return []entities.Project{}, errors.New("Error while getting user company, reason: " + err.Error())
	}

	projectsIndex, err := util.GetIndex(stub, util.ProjectsIndexName)
	if err != nil {
		return []entities.Project{}, errors.New("Unable to retrieve projectsIndex, reason: " + err.Error())
	}

	projects := []entities.Project{}
	for _, projectID := range projectsIndex {
		projectAsBytes, err := stub.GetState(projectID)
		if err != nil {
			return []entities.Project{}, errors.New("Could not retrieve project for ID " + projectID + " reason: " + err.Error())
		}

		var project entities.Project
		err = json.Unmarshal(projectAsBytes, &project)
		if err != nil {
			return []entities.Project{}, errors.New("Error while unmarshalling projectAsBytes, reason: " + err.Error())
		}

		if project.Freelancer == userCompany.CompanyID || project.Client == userCompany.CompanyID {
			projects = append(projects, project)
		}
	}
	return projects, nil
}

func GetProjectByID(stub shim.ChaincodeStubInterface, projectID string) (entities.Project, error) {
	userCompany, err := util.GetCompanyByCertificate(stub)
	if err != nil {
		return entities.Project{}, errors.New("Error while getting user company, reason: " + err.Error())
	}

	projectAsBytes, err := stub.GetState(projectID)
	if err != nil {
		return entities.Project{}, errors.New("Could not retrieve project for ID " + projectID + " reason: " + err.Error())
	}

	var project entities.Project
	err = json.Unmarshal(projectAsBytes, &project)
	if err != nil {
		return entities.Project{}, errors.New("Error while unmarshalling projectAsBytes, reason: " + err.Error())
	}

	if project.Freelancer == userCompany.CompanyID || project.Client == userCompany.CompanyID {
		return project, nil
	}

	return entities.Project{}, nil
}

func SignAgreement(stub shim.ChaincodeStubInterface, projectID string, timestamp int64) error {
	project, err := GetProjectByID(stub, projectID)
	if err != nil {
		return errors.New("Error while getting project, reason: " + err.Error())
	}

	user, err := util.GetCurrentBlockchainUser(stub)
	if err != nil {
		return errors.New("Unable to retrieve user, reason: " + err.Error())
	}

	userCompany, err := util.GetCompanyByCertificate(stub)
	if err != nil {
		return errors.New("Error while getting user company, reason: " + err.Error())
	}

	if userCompany.CompanyID != project.Freelancer && userCompany.CompanyID != project.Client {
		return errors.New("Current user doesn't belong to either the client or freelancer company")
	}

	userRole, err := GetUserRole(userCompany.CompanyID, project)
	if err != nil {
		return err
	}

	projectHash := createProjectHash(project)

	signature := entities.Signature{Timestamp: timestamp, Hash: projectHash, UserID: user.UserID}

	if userRole == "freelancer" {
		project.Signatures.FreelancerSignature = signature;
	} else if userRole == "client" {
		project.Signatures.ClientSignature = signature;
	}

	if project.Signatures.FreelancerSignature.Hash == project.Signatures.ClientSignature.Hash {
		project.Signatures.SignedByBothParties = true;
		project.Status = "Signed"
	} else {
		project.Status = "Pending validation"
	}

	projectAsBytes, err := json.Marshal(project)
	if err != nil {
		return errors.New("Error in marshalling project" + err.Error())
	}

	err = stub.PutState(projectID, projectAsBytes)
	if err != nil {
		return errors.New("Could not store project" + err.Error())
	}

	return nil
}

func GetUserRole(companyID string, project entities.Project) (string, error) {
	if companyID == project.Freelancer {
		return "freelancer", nil
	} else if companyID == project.Client {
		return "client", nil
	} else {
		return "", errors.New("Can't find the role")
	}
}

func createProjectHash(project entities.Project) (string) {
	return calculate_hash([]string{
		project.ProjectID,
		project.ProjectName,
		project.Freelancer,
		project.Client,
		string(project.StartDate),
		string(project.EndDate),
		string(project.HoursPerWeek),
		project.PaymentType,
		project.PaymentTrigger,
		project.Description,
		project.Deliverables,
		project.Location,
		project.CreatorID})
}

func calculate_hash(args []string) string {
	var str = ""
	for _, v := range args {
		str += v
	}
	hasher := sha256.New()
	hasher.Write([]byte(str))
	return hex.EncodeToString(hasher.Sum(nil))
}<|endoftext|>


<commit_before>// Generates reference files for a given language

// +build !release

package main

import "ldss/lib"

type generateReference struct {
	appinfo
}

func init() {
	addApp("generate-reference", &generateReference{})
}

func (app *generateReference) run() {
	lang, err := lib.LookupLanguage(app.args[0])
	if err != nil {
		panic(err)
	}
	app.fmt.Println(lang.String())
}
<commit_msg>Work on generated reference files<commit_after>// Generates reference files for a given language

// +build !release

package main

import (
	"ldss/lib"
)

type generateReference struct {
	appinfo
}

func init() {
	addApp("generate-reference", &generateReference{})
}

func (app *generateReference) run() {
	langId := app.args[1]
	app.efmt.Println(langId)
	lang, err := lib.LookupLanguage(langId)
	if err != nil {
		panic(err)
	}
	app.efmt.Println(lang.String())
	messages := lib.DownloadAll(lang, false)
	for m := range messages {
		app.efmt.Println(m.String())
	}
	catalog, err := lang.Catalog()
	if err != nil {
		panic(err)
	}

	for _, b := range catalog.Books() {
		app.runBook(b)
	}
	for _, f := range catalog.Folders() {
		app.runFolder(f)
	}
}

func (app *generateReference) runFolder(f *lib.Folder) {
	app.fmt.Printf("%v:%v:%v\n", f.ID(), f.Name(), f.Path())
	for _, b := range f.Books() {
		app.runBook(b)
	}
	for _, f := range f.Folders() {
		app.runFolder(f)
	}
}

func (app *generateReference) runBook(b *lib.Book) {
	app.fmt.Printf("%v:%v\n", b.Name(), b.Path())
	nodes, err := b.Index()
	if err != nil {
		app.efmt.Println(err)
		return
	}
	for _, n := range nodes {
		app.runNode(n)
	}
}

func (app *generateReference) runNode(n *lib.Node) {

}
<|endoftext|>