<commit_before>package parser

import (
	"github.com/stephens2424/php/ast"
	"github.com/stephens2424/php/lexer"
	"github.com/stephens2424/php/token"
)

func (p *Parser) parseInstantiation() ast.Expr {
	p.expectCurrent(token.NewOperator)
	p.next()

	p.instantiation = true
	expr := &ast.NewCallExpr{}
	expr.Class = p.parseOperand()
	p.instantiation = false

	if p.peek().Typ == token.OpenParen {
		p.expect(token.OpenParen)
		if p.peek().Typ != token.CloseParen {
			expr.Arguments = append(expr.Arguments, p.parseNextExpression())
			for p.peek().Typ == token.Comma {
				p.expect(token.Comma)
				expr.Arguments = append(expr.Arguments, p.parseNextExpression())
			}
		}
		p.expect(token.CloseParen)
	}
	return expr
}

func (p *Parser) parseClass() *ast.Class {
	if p.current.Typ == token.Abstract {
		p.expect(token.Class)
	}
	if p.current.Typ == token.Final {
		p.expect(token.Class)
	}
	switch p.next(); {
	case p.current.Typ == token.Identifier:
	case lexer.IsKeyword(p.current.Typ, p.current.Val):
	default:
		p.errorf("unexpected variable operand %s", p.current)
	}

	name := p.current.Val
	if p.peek().Typ == token.Extends {
		p.expect(token.Extends)
		p.expect(token.Identifier)
	}
	if p.peek().Typ == token.Implements {
		p.expect(token.Implements)
		p.expect(token.Identifier)
		for p.peek().Typ == token.Comma {
			p.expect(token.Comma)
			p.expect(token.Identifier)
		}
	}
	p.expect(token.BlockBegin)
	c := p.parseClassFields(&ast.Class{Name: name})
	p.namespace.ClassesAndInterfaces[c.Name] = c
	return c
}

func (p *Parser) parseObjectLookup(r ast.Expr) (expr ast.Expr) {
	p.expectCurrent(token.ObjectOperator)
	prop := &ast.PropertyCallExpr{
		Receiver: r,
	}
	switch p.next(); p.current.Typ {
	case token.BlockBegin:
		prop.Name = p.parseNextExpression()
		p.expect(token.BlockEnd)
	case token.VariableOperator:
		prop.Name = p.parseExpression()
	case token.Identifier:
		prop.Name = &ast.Identifier{Value: p.current.Val}
	}
	expr = prop
	switch pk := p.peek(); pk.Typ {
	case token.OpenParen:
		expr = &ast.MethodCallExpr{
			Receiver:         r,
			FunctionCallExpr: p.parseFunctionCall(prop.Name),
		}
	}
	expr = p.parseOperation(p.parenLevel, expr)
	return
}

func (p *Parser) parseVisibility() (vis ast.Visibility, found bool) {
	switch p.peek().Typ {
	case token.Private:
		vis = ast.Private
	case token.Public:
		vis = ast.Public
	case token.Protected:
		vis = ast.Protected
	default:
		return ast.Public, false
	}
	p.next()
	return vis, true
}

func (p *Parser) parseAbstract() bool {
	if p.peek().Typ == token.Abstract {
		p.next()
		return true
	}
	return false
}

func (p *Parser) parseClassFields(c *ast.Class) *ast.Class {
	// Starting on BlockBegin
	c.Methods = make([]*ast.Method, 0)
	c.Properties = make([]*ast.Property, 0)
	for p.peek().Typ != token.BlockEnd {
		vis, _, _, abstract := p.parseClassMemberSettings()
		p.next()
		switch p.current.Typ {
		case token.Function:
			if abstract {
				f := p.parseFunctionDefinition()
				m := &ast.Method{
					Visibility:   vis,
					FunctionStmt: &ast.FunctionStmt{FunctionDefinition: f},
				}
				c.Methods = append(c.Methods, m)
				p.expect(token.StatementEnd)
			} else {
				c.Methods = append(c.Methods, &ast.Method{
					Visibility:   vis,
					FunctionStmt: p.parseFunctionStmt(true),
				})
			}
		case token.Var:
			p.expect(token.VariableOperator)
			fallthrough
		case token.VariableOperator:
			for {
				p.expect(token.Identifier)
				prop := &ast.Property{
					Visibility: vis,
					Name:       "$" + p.current.Val,
				}
				if p.peek().Typ == token.AssignmentOperator {
					p.expect(token.AssignmentOperator)
					prop.Initialization = p.parseNextExpression()
				}
				c.Properties = append(c.Properties, prop)
				if p.accept(token.StatementEnd) {
					break
				}
				p.expect(token.Comma)
				p.expect(token.VariableOperator)
			}
		case token.Const:
			constant := &ast.Constant{}
			p.expect(token.Identifier)
			constant.Name = p.current.Val
			if p.peek().Typ == token.AssignmentOperator {
				p.expect(token.AssignmentOperator)
				constant.Value = p.parseNextExpression()
			}
			c.Constants = append(c.Constants, constant)
			p.expect(token.StatementEnd)
		default:
			p.errorf("unexpected class member %v", p.current)
			return c
		}
	}
	p.expect(token.BlockEnd)
	return c
}

func (p *Parser) parseInterface() *ast.Interface {
	i := &ast.Interface{
		Inherits: make([]string, 0),
	}
	p.expect(token.Identifier)
	i.Name = p.current.Val
	p.namespace.ClassesAndInterfaces[i.Name] = i
	if p.peek().Typ == token.Extends {
		p.expect(token.Extends)
		for {
			p.expect(token.Identifier)
			i.Inherits = append(i.Inherits, p.current.Val)
			if p.peek().Typ != token.Comma {
				break
			}
			p.expect(token.Comma)
		}
	}
	p.expect(token.BlockBegin)
	for p.peek().Typ != token.BlockEnd {
		vis, _ := p.parseVisibility()
		if p.peek().Typ == token.Static {
			p.next()
		}
		p.next()
		switch p.current.Typ {
		case token.Function:
			f := p.parseFunctionDefinition()
			m := ast.Method{
				Visibility:   vis,
				FunctionStmt: &ast.FunctionStmt{FunctionDefinition: f},
			}
			i.Methods = append(i.Methods, m)
			p.expect(token.StatementEnd)
		case token.Const:
			constant := ast.Constant{}
			p.expect(token.Identifier)
			constant.Name = p.current.Val
			if p.peek().Typ == token.AssignmentOperator {
				p.expect(token.AssignmentOperator)
				constant.Value = p.parseNextExpression()
			}
			i.Constants = append(i.Constants, constant)
			p.expect(token.StatementEnd)
		default:
			p.errorf("unexpected interface member %v", p.current)
		}
	}
	p.expect(token.BlockEnd)
	return i
}

func (p *Parser) parseClassMemberSettings() (vis ast.Visibility, static, final, abstract bool) {
	var foundVis bool
	vis = ast.Public
	for {
		switch p.peek().Typ {
		case token.Abstract:
			if abstract {
				p.errorf("found multiple abstract declarations")
			}
			abstract = true
			p.next()
		case token.Private, token.Public, token.Protected:
			if foundVis {
				p.errorf("found multiple visibility declarations")
			}
			vis, foundVis = p.parseVisibility()
		case token.Final:
			if final {
				p.errorf("found multiple final declarations")
			}
			final = true
			p.next()
		case token.Static:
			if static {
				p.errorf("found multiple static declarations")
			}
			static = true
			p.next()
		default:
			return
		}
	}
}
<commit_msg>cleaning up oop parsing<commit_after>package parser

import (
	"github.com/stephens2424/php/ast"
	"github.com/stephens2424/php/lexer"
	"github.com/stephens2424/php/token"
)

func (p *Parser) parseInstantiation() ast.Expr {
	p.expectCurrent(token.NewOperator)
	p.next()

	p.instantiation = true
	expr := &ast.NewCallExpr{}
	expr.Class = p.parseOperand()
	p.instantiation = false

	if p.peek().Typ == token.OpenParen {
		p.expect(token.OpenParen)
		if p.peek().Typ != token.CloseParen {
			expr.Arguments = append(expr.Arguments, p.parseNextExpression())
			for p.peek().Typ == token.Comma {
				p.expect(token.Comma)
				expr.Arguments = append(expr.Arguments, p.parseNextExpression())
			}
		}
		p.expect(token.CloseParen)
	}
	return expr
}

func (p *Parser) parseClass() *ast.Class {
	if p.current.Typ == token.Abstract {
		p.expect(token.Class)
	}
	if p.current.Typ == token.Final {
		p.expect(token.Class)
	}
	switch p.next(); {
	case p.current.Typ == token.Identifier:
	case lexer.IsKeyword(p.current.Typ, p.current.Val):
	default:
		p.errorf("unexpected variable operand %s", p.current)
	}

	name := p.current.Val
	if p.peek().Typ == token.Extends {
		p.expect(token.Extends)
		p.expect(token.Identifier)
	}
	if p.peek().Typ == token.Implements {
		p.expect(token.Implements)
		p.expect(token.Identifier)
		for p.peek().Typ == token.Comma {
			p.expect(token.Comma)
			p.expect(token.Identifier)
		}
	}
	p.expect(token.BlockBegin)
	c := p.parseClassFields(&ast.Class{Name: name})
	p.namespace.ClassesAndInterfaces[c.Name] = c
	return c
}

func (p *Parser) parseObjectLookup(r ast.Expr) (expr ast.Expr) {
	p.expectCurrent(token.ObjectOperator)
	prop := &ast.PropertyCallExpr{
		Receiver: r,
	}
	switch p.next(); p.current.Typ {
	case token.BlockBegin:
		prop.Name = p.parseNextExpression()
		p.expect(token.BlockEnd)
	case token.VariableOperator:
		prop.Name = p.parseExpression()
	case token.Identifier:
		prop.Name = &ast.Identifier{Value: p.current.Val}
	}
	expr = prop
	switch pk := p.peek(); pk.Typ {
	case token.OpenParen:
		expr = &ast.MethodCallExpr{
			Receiver:         r,
			FunctionCallExpr: p.parseFunctionCall(prop.Name),
		}
	}
	expr = p.parseOperation(p.parenLevel, expr)
	return
}

func (p *Parser) parseVisibility() (vis ast.Visibility, found bool) {
	switch p.peek().Typ {
	case token.Private:
		vis = ast.Private
	case token.Public:
		vis = ast.Public
	case token.Protected:
		vis = ast.Protected
	default:
		return ast.Public, false
	}
	p.next()
	return vis, true
}

func (p *Parser) parseAbstract() bool {
	if p.peek().Typ == token.Abstract {
		p.next()
		return true
	}
	return false
}

func (p *Parser) parseClassFields(c *ast.Class) *ast.Class {
	// Starting on BlockBegin
	c.Methods = make([]*ast.Method, 0)
	c.Properties = make([]*ast.Property, 0)
	for p.peek().Typ != token.BlockEnd {
		vis, _, _, abstract := p.parseClassMemberSettings()
		p.next()
		switch p.current.Typ {
		case token.Function:
			p.parseClassMethod(c, abstract, vis)
		case token.Var:
			p.expect(token.VariableOperator)
			fallthrough
		case token.VariableOperator:
			p.parseClassVariables(c, vis)
		case token.Const:
			p.parseClassConst(c)
		default:
			p.errorf("unexpected class member %v", p.current)
			return c
		}
	}
	p.expect(token.BlockEnd)
	return c
}

func (p *Parser) parseClassConst(c *ast.Class) {
	constant := &ast.Constant{}
	p.expect(token.Identifier)
	constant.Name = p.current.Val
	if p.peek().Typ == token.AssignmentOperator {
		p.expect(token.AssignmentOperator)
		constant.Value = p.parseNextExpression()
	}
	c.Constants = append(c.Constants, constant)
	p.expect(token.StatementEnd)
}

func (p *Parser) parseClassVariables(c *ast.Class, vis ast.Visibility) {
	for {
		p.expect(token.Identifier)
		prop := &ast.Property{
			Visibility: vis,
			Name:       "$" + p.current.Val,
		}
		if p.peek().Typ == token.AssignmentOperator {
			p.expect(token.AssignmentOperator)
			prop.Initialization = p.parseNextExpression()
		}
		c.Properties = append(c.Properties, prop)
		if p.accept(token.StatementEnd) {
			break
		}
		p.expect(token.Comma)
		p.expect(token.VariableOperator)
	}
}

func (p *Parser) parseClassMethod(c *ast.Class, abstract bool, vis ast.Visibility) {
	if abstract {
		f := p.parseFunctionDefinition()
		m := &ast.Method{
			Visibility:   vis,
			FunctionStmt: &ast.FunctionStmt{FunctionDefinition: f},
		}
		c.Methods = append(c.Methods, m)
		p.expect(token.StatementEnd)
	} else {
		c.Methods = append(c.Methods, &ast.Method{
			Visibility:   vis,
			FunctionStmt: p.parseFunctionStmt(true),
		})
	}
}

func (p *Parser) parseInterface() *ast.Interface {
	i := &ast.Interface{
		Inherits: make([]string, 0),
	}
	p.expect(token.Identifier)
	i.Name = p.current.Val
	p.namespace.ClassesAndInterfaces[i.Name] = i
	if p.peek().Typ == token.Extends {
		p.expect(token.Extends)
		for {
			p.expect(token.Identifier)
			i.Inherits = append(i.Inherits, p.current.Val)
			if p.peek().Typ != token.Comma {
				break
			}
			p.expect(token.Comma)
		}
	}
	p.expect(token.BlockBegin)
	for p.peek().Typ != token.BlockEnd {
		vis, _ := p.parseVisibility()
		if p.peek().Typ == token.Static {
			p.next()
		}
		p.next()
		switch p.current.Typ {
		case token.Function:
			f := p.parseFunctionDefinition()
			m := ast.Method{
				Visibility:   vis,
				FunctionStmt: &ast.FunctionStmt{FunctionDefinition: f},
			}
			i.Methods = append(i.Methods, m)
			p.expect(token.StatementEnd)
		case token.Const:
			constant := ast.Constant{}
			p.expect(token.Identifier)
			constant.Name = p.current.Val
			if p.peek().Typ == token.AssignmentOperator {
				p.expect(token.AssignmentOperator)
				constant.Value = p.parseNextExpression()
			}
			i.Constants = append(i.Constants, constant)
			p.expect(token.StatementEnd)
		default:
			p.errorf("unexpected interface member %v", p.current)
		}
	}
	p.expect(token.BlockEnd)
	return i
}

func (p *Parser) parseClassMemberSettings() (vis ast.Visibility, static, final, abstract bool) {
	var foundVis bool
	vis = ast.Public
	for {
		switch p.peek().Typ {
		case token.Abstract:
			if abstract {
				p.errorf("found multiple abstract declarations")
			}
			abstract = true
			p.next()
		case token.Private, token.Public, token.Protected:
			if foundVis {
				p.errorf("found multiple visibility declarations")
			}
			vis, foundVis = p.parseVisibility()
		case token.Final:
			if final {
				p.errorf("found multiple final declarations")
			}
			final = true
			p.next()
		case token.Static:
			if static {
				p.errorf("found multiple static declarations")
			}
			static = true
			p.next()
		default:
			return
		}
	}
}
<|endoftext|>


<commit_before>package service

import (
	"errors"
	"strconv"

	"github.com/godbus/dbus"
	"github.com/godbus/dbus/introspect"
	"github.com/muka/go-bluetooth/bluez"
	"github.com/muka/go-bluetooth/bluez/profile"
)

//UUIDSuffix fixed 128bit UUID [0000]+[xxxx]+[-0000-1000-8000-00805F9B34FB]
const UUIDSuffix = "-0000-1000-8000-00805F9B34FB"

//NewApplication instantiate a new application service
func NewApplication(config *ApplicationConfig) (*Application, error) {

	if config.ObjectName == "" {
		return nil, errors.New("objectName is required")
	}
	if config.ObjectPath == "" {
		return nil, errors.New("objectPath is required")
	}

	if config.conn == nil {
		conn, err := dbus.SystemBus()
		if err != nil {
			return nil, err
		}
		config.conn = conn
	}

	om, err := NewObjectManager(config.conn)
	if err != nil {
		return nil, err
	}

	// props, err := NewProperties(config.conn)
	// if err != nil {
	// 	return nil, err
	// }

	s := &Application{
		config:        config,
		objectManager: om,
		services:      make(map[dbus.ObjectPath]*GattService1),
	}

	return s, nil
}

//GattWriteCallback A callback we can register to handle write requests
type GattWriteCallback func(app *Application, service_uuid string, charUUID string, value []byte) error

//GattDescriptorWriteCallback A callback we can register to handle descriptor write requests
type GattDescriptorWriteCallback func(app *Application, service_uuid string, charUUID string, descUUID string, value []byte) error

//GattReadCallback A callback we can register to handle read requests
type GattReadCallback func(app *Application, service_uuid string, charUUID string) ([]byte, error)

//GattDescriptorReadCallback A callback we can register to handle descriptor ead requests
type GattDescriptorReadCallback func(app *Application, service_uuid string, charUUID string, descUUID string) ([]byte, error)

// ApplicationConfig configuration for the bluetooth service
type ApplicationConfig struct {
	UUIDSuffix   string
	UUID         string
	conn         *dbus.Conn
	ObjectName   string
	ObjectPath   dbus.ObjectPath
	serviceIndex int
	LocalName    string

	WriteFunc     GattWriteCallback
	ReadFunc      GattReadCallback
	DescWriteFunc GattDescriptorWriteCallback
	DescReadFunc  GattDescriptorReadCallback
}

// Application a bluetooth service exposed by bluez
type Application struct {
	config        *ApplicationConfig
	objectManager *ObjectManager
	services      map[dbus.ObjectPath]*GattService1

	adMgr         *profile.LEAdvertisingManager1
	advertisement *LEAdvertisement1
}

//GetObjectManager return the object manager interface handler
func (app *Application) GetObjectManager() *ObjectManager {
	return app.objectManager
}

//Path return the object path
func (app *Application) Path() dbus.ObjectPath {
	return app.config.ObjectPath
}

//Name return the object name
func (app *Application) Name() string {
	return app.config.ObjectName
}

// GenerateUUID generate a 128bit UUID
func (app *Application) GenerateUUID(uuidVal string) string {
	base := app.config.UUID
	if len(uuidVal) == 8 {
		base = ""
	}
	return base + uuidVal + app.config.UUIDSuffix
}

//CreateService create a new GattService1 instance
func (app *Application) CreateService(props *profile.GattService1Properties, advertisedOptional ...bool) (*GattService1, error) {
	app.config.serviceIndex++
	appPath := string(app.Path())
	if appPath == "/" {
		appPath = ""
	}

	advertise := false
	if len(advertisedOptional) > 0 {
		advertise = advertisedOptional[0]
	}

	path := appPath + "/service" + strconv.Itoa(app.config.serviceIndex)
	c := &GattService1Config{
		app:        app,
		objectPath: dbus.ObjectPath(path),
		ID:         app.config.serviceIndex,
		conn:       app.config.conn,
		advertised: advertise,
	}
	s, err := NewGattService1(c, props)
	return s, err
}

//AddService add service to expose
func (app *Application) AddService(service *GattService1) error {

	app.services[service.Path()] = service

	err := service.Expose()
	if err != nil {
		return err
	}

	err = app.exportTree()
	if err != nil {
		return err
	}

	err = app.GetObjectManager().AddObject(service.Path(), service.Properties())
	if err != nil {
		return err
	}

	return err
}

//RemoveService remove an exposed service
func (app *Application) RemoveService(service *GattService1) error {
	if _, ok := app.services[service.Path()]; ok {

		delete(app.services, service.Path())
		err := app.GetObjectManager().RemoveObject(service.Path())

		//TODO: remove chars + descritptors too
		if err != nil {
			return err
		}

		err = app.exportTree()
		if err != nil {
			return err
		}
	}
	return nil
}

//GetServices return the registered services
func (app *Application) GetServices() map[dbus.ObjectPath]*GattService1 {
	return app.services
}

//expose dbus interfaces
func (app *Application) expose() error {

	conn := app.config.conn
	_, err := conn.RequestName(app.Name(), dbus.NameFlagDoNotQueue&dbus.NameFlagReplaceExisting)
	if err != nil {
		return err
	}

	// / path
	err = conn.Export(app.objectManager, app.Path(), bluez.ObjectManagerInterface)
	if err != nil {
		return err
	}

	err = app.exportTree()
	if err != nil {
		return err
	}

	return nil
}

func (app *Application) exportTree() error {

	childrenNode := make([]introspect.Node, 0)

	for servicePath, service := range app.GetServices() {
		childrenNode = append(childrenNode, introspect.Node{
			Name: string(servicePath)[1:],
		})
		for charPath, char := range service.GetCharacteristics() {
			childrenNode = append(childrenNode, introspect.Node{
				Name: string(charPath)[1:],
			})
			for descPath := range char.GetDescriptors() {
				childrenNode = append(childrenNode, introspect.Node{
					Name: string(descPath)[1:],
				})
			}
		}
	}

	// must include also child nodes
	node := &introspect.Node{
		Interfaces: []introspect.Interface{
			//Introspect
			introspect.IntrospectData,
			//ObjectManager
			bluez.ObjectManagerIntrospectData,
		},
		Children: childrenNode,
	}

	err := app.config.conn.Export(
		introspect.NewIntrospectable(node),
		app.Path(),
		"org.freedesktop.DBus.Introspectable")

	return err
}

// CallbackError error from a callback
type CallbackError struct {
	msg  string
	code int
}

func (e *CallbackError) Error() string {
	return e.msg
}

//NewCallbackError create a new callback error
func NewCallbackError(code int, msg string) *CallbackError {
	result := &CallbackError{msg: msg, code: code}
	return result
}

//CallbackNotRegistered callback not registered
const CallbackNotRegistered = -1

//CallbackFunctionError callback reported an error
const CallbackFunctionError = -2

//HandleRead Handle application read
func (app *Application) HandleRead(srvUUID string, uuid string) ([]byte, *CallbackError) {
	if app.config.ReadFunc == nil {
		b := make([]byte, 0)
		return b, NewCallbackError(-1, "No callback registered.")
	}

	var cberr *CallbackError
	b, err := app.config.ReadFunc(app, srvUUID, uuid)
	if err != nil {
		cberr = NewCallbackError(-2, err.Error())
	}

	return b, cberr
}

// HandleWrite handle application write
func (app *Application) HandleWrite(srvUUID string, uuid string, value []byte) *CallbackError {
	if app.config.WriteFunc == nil {
		return NewCallbackError(-1, "No callback registered.")
	}

	err := app.config.WriteFunc(app, srvUUID, uuid, value)
	if err != nil {
		return NewCallbackError(-2, err.Error())
	}

	return nil
}

//HandleDescriptorRead handle descriptor read
func (app *Application) HandleDescriptorRead(srvUUID string, charUUID string, descUUID string) ([]byte, *CallbackError) {
	if app.config.DescReadFunc == nil {
		b := make([]byte, 0)
		return b, NewCallbackError(-1, "No callback registered.")
	}

	var cberr *CallbackError
	b, err := app.config.DescReadFunc(app, srvUUID, charUUID, descUUID)
	if err != nil {
		cberr = NewCallbackError(-2, err.Error())
	}

	return b, cberr
}

//HandleDescriptorWrite handle descriptor write
func (app *Application) HandleDescriptorWrite(srvUUID string, charUUID string, descUUID string, value []byte) *CallbackError {
	if app.config.DescWriteFunc == nil {
		return NewCallbackError(-1, "No callback registered.")
	}

	err := app.config.DescWriteFunc(app, srvUUID, charUUID, descUUID, value)
	if err != nil {
		return NewCallbackError(-2, err.Error())
	}

	return nil
}

//Run start the application
func (app *Application) Run() error {

	err := app.expose()
	if err != nil {
		return err
	}

	return nil
}

//StartAdvertising advertise information for a service
func (app *Application) StartAdvertising(deviceInterface string) error {
	if app.advertisement != nil && app.adMgr != nil {
		// Already advertising
		return nil
	}

	path := "/org/bluez/advertisement/0"

	config := &LEAdvertisement1Config{
		conn:       app.config.conn,
		objectPath: dbus.ObjectPath(path),
	}

	serviceUUIDs := make([]string, 0)

	for _, serv := range app.services {
		if serv.Advertised() {
			serviceUUIDs = append(serviceUUIDs, serv.properties.UUID)
		}
	}

	props := &profile.LEAdvertisement1Properties{
		Type:         "peripheral",
		LocalName:    app.config.LocalName,
		ServiceUUIDs: serviceUUIDs,
	}

	var err error

	app.advertisement, err = NewLEAdvertisement1(config, props)
	if err != nil {
		app.advertisement = nil
		return err
	}

	err = app.advertisement.Expose()
	if err != nil {
		app.advertisement = nil
		return err
	}

	options := make(map[string]interface{})

	app.adMgr = profile.NewLEAdvertisingManager1(deviceInterface)

	err = app.adMgr.RegisterAdvertisement(path, options)
	if err != nil {
		app.advertisement = nil
		app.adMgr = nil
		return err
	}

	adapter := profile.NewAdapter1(deviceInterface)
	err = adapter.SetProperty("Discoverable", dbus.MakeVariant(true))
	if err != nil {
		return err
	}

	err = adapter.SetProperty("Powered", dbus.MakeVariant(true))
	if err != nil {
		return err
	}

	return nil
}

//StopAdvertising stop advertising information on a service
func (app *Application) StopAdvertising() error {
	if app.advertisement == nil || app.adMgr == nil {
		// Not advertising
		return nil
	}

	err := app.adMgr.UnregisterAdvertisement(string(app.advertisement.config.objectPath))

	app.advertisement = nil
	app.adMgr = nil

	if err != nil {
		return err
	}

	return nil
}
<commit_msg>added warning when adv data is over 31 bytes, close #60<commit_after>package service

import (
	"errors"
	"fmt"
	"strconv"
	"strings"

	"github.com/godbus/dbus"
	"github.com/godbus/dbus/introspect"
	"github.com/muka/go-bluetooth/bluez"
	"github.com/muka/go-bluetooth/bluez/profile"
	"github.com/sirupsen/logrus"
)

//UUIDSuffix fixed 128bit UUID [0000]+[xxxx]+[-0000-1000-8000-00805F9B34FB]
const UUIDSuffix = "-0000-1000-8000-00805F9B34FB"

//NewApplication instantiate a new application service
func NewApplication(config *ApplicationConfig) (*Application, error) {

	if config.ObjectName == "" {
		return nil, errors.New("objectName is required")
	}

	if config.ObjectPath == "" {
		return nil, errors.New("objectPath is required")
	}

	if config.conn == nil {
		conn, err := dbus.SystemBus()
		if err != nil {
			return nil, err
		}
		config.conn = conn
	}

	om, err := NewObjectManager(config.conn)
	if err != nil {
		return nil, err
	}

	// props, err := NewProperties(config.conn)
	// if err != nil {
	// 	return nil, err
	// }

	s := &Application{
		config:        config,
		objectManager: om,
		services:      make(map[dbus.ObjectPath]*GattService1),
	}

	return s, nil
}

//GattWriteCallback A callback we can register to handle write requests
type GattWriteCallback func(app *Application, service_uuid string, charUUID string, value []byte) error

//GattDescriptorWriteCallback A callback we can register to handle descriptor write requests
type GattDescriptorWriteCallback func(app *Application, service_uuid string, charUUID string, descUUID string, value []byte) error

//GattReadCallback A callback we can register to handle read requests
type GattReadCallback func(app *Application, service_uuid string, charUUID string) ([]byte, error)

//GattDescriptorReadCallback A callback we can register to handle descriptor ead requests
type GattDescriptorReadCallback func(app *Application, service_uuid string, charUUID string, descUUID string) ([]byte, error)

// ApplicationConfig configuration for the bluetooth service
type ApplicationConfig struct {
	UUIDSuffix   string
	UUID         string
	conn         *dbus.Conn
	ObjectName   string
	ObjectPath   dbus.ObjectPath
	serviceIndex int
	LocalName    string

	WriteFunc     GattWriteCallback
	ReadFunc      GattReadCallback
	DescWriteFunc GattDescriptorWriteCallback
	DescReadFunc  GattDescriptorReadCallback
}

// Application a bluetooth service exposed by bluez
type Application struct {
	config        *ApplicationConfig
	objectManager *ObjectManager
	services      map[dbus.ObjectPath]*GattService1

	adMgr         *profile.LEAdvertisingManager1
	advertisement *LEAdvertisement1
}

//GetObjectManager return the object manager interface handler
func (app *Application) GetObjectManager() *ObjectManager {
	return app.objectManager
}

//Path return the object path
func (app *Application) Path() dbus.ObjectPath {
	return app.config.ObjectPath
}

//Name return the object name
func (app *Application) Name() string {
	return app.config.ObjectName
}

// GenerateUUID generate a 128bit UUID
func (app *Application) GenerateUUID(uuidVal string) string {
	base := app.config.UUID
	if len(uuidVal) == 8 {
		base = ""
	}
	return base + uuidVal + app.config.UUIDSuffix
}

//CreateService create a new GattService1 instance
func (app *Application) CreateService(props *profile.GattService1Properties, advertisedOptional ...bool) (*GattService1, error) {
	app.config.serviceIndex++
	appPath := string(app.Path())
	if appPath == "/" {
		appPath = ""
	}

	advertise := false
	if len(advertisedOptional) > 0 {
		advertise = advertisedOptional[0]
	}

	path := appPath + "/service" + strconv.Itoa(app.config.serviceIndex)
	c := &GattService1Config{
		app:        app,
		objectPath: dbus.ObjectPath(path),
		ID:         app.config.serviceIndex,
		conn:       app.config.conn,
		advertised: advertise,
	}
	s, err := NewGattService1(c, props)
	return s, err
}

//AddService add service to expose
func (app *Application) AddService(service *GattService1) error {

	app.services[service.Path()] = service

	err := service.Expose()
	if err != nil {
		return err
	}

	err = app.exportTree()
	if err != nil {
		return err
	}

	err = app.GetObjectManager().AddObject(service.Path(), service.Properties())
	if err != nil {
		return err
	}

	return err
}

//RemoveService remove an exposed service
func (app *Application) RemoveService(service *GattService1) error {
	if _, ok := app.services[service.Path()]; ok {

		delete(app.services, service.Path())
		err := app.GetObjectManager().RemoveObject(service.Path())

		//TODO: remove chars + descritptors too
		if err != nil {
			return err
		}

		err = app.exportTree()
		if err != nil {
			return err
		}
	}
	return nil
}

//GetServices return the registered services
func (app *Application) GetServices() map[dbus.ObjectPath]*GattService1 {
	return app.services
}

//expose dbus interfaces
func (app *Application) expose() error {

	conn := app.config.conn
	_, err := conn.RequestName(app.Name(), dbus.NameFlagDoNotQueue&dbus.NameFlagReplaceExisting)
	if err != nil {
		return err
	}

	// / path
	err = conn.Export(app.objectManager, app.Path(), bluez.ObjectManagerInterface)
	if err != nil {
		return err
	}

	err = app.exportTree()
	if err != nil {
		return err
	}

	return nil
}

func (app *Application) exportTree() error {

	childrenNode := make([]introspect.Node, 0)

	for servicePath, service := range app.GetServices() {
		childrenNode = append(childrenNode, introspect.Node{
			Name: string(servicePath)[1:],
		})
		for charPath, char := range service.GetCharacteristics() {
			childrenNode = append(childrenNode, introspect.Node{
				Name: string(charPath)[1:],
			})
			for descPath := range char.GetDescriptors() {
				childrenNode = append(childrenNode, introspect.Node{
					Name: string(descPath)[1:],
				})
			}
		}
	}

	// must include also child nodes
	node := &introspect.Node{
		Interfaces: []introspect.Interface{
			//Introspect
			introspect.IntrospectData,
			//ObjectManager
			bluez.ObjectManagerIntrospectData,
		},
		Children: childrenNode,
	}

	err := app.config.conn.Export(
		introspect.NewIntrospectable(node),
		app.Path(),
		"org.freedesktop.DBus.Introspectable")

	return err
}

// CallbackError error from a callback
type CallbackError struct {
	msg  string
	code int
}

func (e *CallbackError) Error() string {
	return e.msg
}

//NewCallbackError create a new callback error
func NewCallbackError(code int, msg string) *CallbackError {
	result := &CallbackError{msg: msg, code: code}
	return result
}

//CallbackNotRegistered callback not registered
const CallbackNotRegistered = -1

//CallbackFunctionError callback reported an error
const CallbackFunctionError = -2

//HandleRead Handle application read
func (app *Application) HandleRead(srvUUID string, uuid string) ([]byte, *CallbackError) {
	if app.config.ReadFunc == nil {
		b := make([]byte, 0)
		return b, NewCallbackError(-1, "No callback registered.")
	}

	var cberr *CallbackError
	b, err := app.config.ReadFunc(app, srvUUID, uuid)
	if err != nil {
		cberr = NewCallbackError(-2, err.Error())
	}

	return b, cberr
}

// HandleWrite handle application write
func (app *Application) HandleWrite(srvUUID string, uuid string, value []byte) *CallbackError {
	if app.config.WriteFunc == nil {
		return NewCallbackError(-1, "No callback registered.")
	}

	err := app.config.WriteFunc(app, srvUUID, uuid, value)
	if err != nil {
		return NewCallbackError(-2, err.Error())
	}

	return nil
}

//HandleDescriptorRead handle descriptor read
func (app *Application) HandleDescriptorRead(srvUUID string, charUUID string, descUUID string) ([]byte, *CallbackError) {
	if app.config.DescReadFunc == nil {
		b := make([]byte, 0)
		return b, NewCallbackError(-1, "No callback registered.")
	}

	var cberr *CallbackError
	b, err := app.config.DescReadFunc(app, srvUUID, charUUID, descUUID)
	if err != nil {
		cberr = NewCallbackError(-2, err.Error())
	}

	return b, cberr
}

//HandleDescriptorWrite handle descriptor write
func (app *Application) HandleDescriptorWrite(srvUUID string, charUUID string, descUUID string, value []byte) *CallbackError {
	if app.config.DescWriteFunc == nil {
		return NewCallbackError(-1, "No callback registered.")
	}

	err := app.config.DescWriteFunc(app, srvUUID, charUUID, descUUID, value)
	if err != nil {
		return NewCallbackError(-2, err.Error())
	}

	return nil
}

//Run start the application
func (app *Application) Run() error {

	err := app.expose()
	if err != nil {
		return err
	}

	return nil
}

//StartAdvertising advertise information for a service
func (app *Application) StartAdvertising(deviceInterface string) error {

	if app.advertisement != nil || app.adMgr != nil {
		logrus.Debugf("Already advertising on %s", deviceInterface)
		return nil
	}

	path := fmt.Sprintf("/org/bluez/advertisement/%s", deviceInterface)

	logrus.Debugf("Registering service on %s (%s)", deviceInterface, path)

	config := &LEAdvertisement1Config{
		conn:       app.config.conn,
		objectPath: dbus.ObjectPath(path),
	}

	serviceUUIDs := make([]string, 0)

	for _, serv := range app.services {
		if serv.Advertised() {
			serviceUUIDs = append(serviceUUIDs, serv.properties.UUID)
		}
	}

	if len([]byte(strings.Join(serviceUUIDs, ","))) > 31 {
		logrus.Warn("Advertisment limit of 31 bytes may have been exceeded. Consider not exposing all services IDs with `CreateService(props, false)`")
	}

	props := &profile.LEAdvertisement1Properties{
		Type:         "peripheral",
		LocalName:    app.config.LocalName,
		ServiceUUIDs: serviceUUIDs,
	}

	var err error

	advertisement, err := NewLEAdvertisement1(config, props)
	if err != nil {
		return fmt.Errorf("NewLEAdvertisement1: %s", err)
	}

	app.advertisement = advertisement

	err = advertisement.Expose()
	if err != nil {
		app.advertisement = nil
		return fmt.Errorf("Expose: %s", err)
	}

	options := make(map[string]interface{})

	app.adMgr = profile.NewLEAdvertisingManager1(deviceInterface)

	err = app.adMgr.RegisterAdvertisement(path, options)
	if err != nil {
		app.advertisement = nil
		app.adMgr = nil
		return fmt.Errorf("RegisterAdvertisement: %s", err)
	}

	adapter := profile.NewAdapter1(deviceInterface)
	err = adapter.SetProperty("Discoverable", true)
	if err != nil {
		return err
	}

	err = adapter.SetProperty("Powered", true)
	if err != nil {
		return err
	}

	return nil
}

//StopAdvertising stop advertising information on a service
func (app *Application) StopAdvertising() error {

	if app.advertisement == nil || app.adMgr == nil {
		// Not advertising
		return nil
	}

	err := app.adMgr.UnregisterAdvertisement(string(app.advertisement.config.objectPath))

	app.advertisement = nil
	app.adMgr = nil

	return err
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Contributor:
// - Aaron Meihm ameihm@mozilla.com

package main

import (
	"encoding/json"
	slib "github.com/mozilla/service-map/servicelib"
	"io/ioutil"
	"net/http"
	"strings"
	"testing"
)

func TestGetRRA(t *testing.T) {
	op := opContext{}
	op.newContext(dbconn, false, "127.0.0.1")
	// Tests service1
	rra, err := getRRA(op, 1)
	if err != nil {
		t.Fatalf("getRRA: %v", err)
	}
	if rra.Name != "test service" {
		t.Fatalf("getRRA: unexpected service name")
	}
	if rra.ConfiRepImpact != "high" {
		t.Fatalf("getRRA: unexpected impact for test service attribute")
	}
}

func TestServiceGetRRA(t *testing.T) {
	client := http.Client{}

	// Tests service1
	rr, err := client.Get(testserv.URL + "/api/v1/rra/id?id=1")
	if err != nil {
		t.Fatalf("client.Get: %v", err)
	}
	if rr.StatusCode != http.StatusOK {
		t.Fatalf("rra get response code %v", rr.StatusCode)
	}
	buf, err := ioutil.ReadAll(rr.Body)
	if err != nil {
		t.Fatalf("ioutil.ReadAll: %v", err)
	}
	rr.Body.Close()
	var rra slib.RRA
	err = json.Unmarshal(buf, &rra)
	if err != nil {
		t.Fatalf("json.Unmarshal: %v", err)
	}
	if rra.Name != "test service" {
		t.Fatalf("rra get rra had unexpected name")
	}
	if rra.ConfiRepImpact != "high" {
		t.Fatalf("rra get rra had unexpected service attribute value")
	}
	// The RRA should have one group associated with it
	if len(rra.Groups) != 1 {
		t.Fatalf("rra get rra associated with unexpected number of groups")
	}
}

func TestServiceGetNonExistRRA(t *testing.T) {
	client := http.Client{}

	rr, err := client.Get(testserv.URL + "/api/v1/rra/id?id=999")
	if err != nil {
		t.Fatalf("client.Get: %v", err)
	}
	if rr.StatusCode != http.StatusNotFound {
		t.Fatalf("rra get response code %v", rr.StatusCode)
	}
	rr.Body.Close()
}

func TestServiceGetRRARisk(t *testing.T) {
	client := http.Client{}

	// Tests service1
	rr, err := client.Get(testserv.URL + "/api/v1/rra/risk?id=1")
	if err != nil {
		t.Fatalf("client.Get: %v", err)
	}
	if rr.StatusCode != http.StatusOK {
		t.Fatalf("rra get response code %v", rr.StatusCode)
	}
	buf, err := ioutil.ReadAll(rr.Body)
	if err != nil {
		t.Fatalf("ioutil.ReadAll: %v", err)
	}
	rr.Body.Close()
	var r slib.Risk
	err = json.Unmarshal(buf, &r)
	if err != nil {
		t.Fatalf("json.Unmarshal: %v", err)
	}
	t.Logf("%+v\n", r)
}

func TestServiceRRAs(t *testing.T) {
	client := http.Client{}

	rr, err := client.Get(testserv.URL + "/api/v1/rras")
	if err != nil {
		t.Fatalf("client.Get: %v", err)
	}
	if rr.StatusCode != http.StatusOK {
		t.Fatalf("rras get response code %v", rr.StatusCode)
	}

	// The number of RRAs returned should correspond with the number of
	// valid test RRAs we have
	var rraresp slib.RRAsResponse
	dirlist, err := ioutil.ReadDir("./testdata")
	if err != nil {
		t.Fatalf("ioutil.ReadDir: %v", err)
	}
	cnt := 0
	for _, x := range dirlist {
		if !strings.HasPrefix(x.Name(), "service") {
			continue
		}
		cnt++
	}
	buf, err := ioutil.ReadAll(rr.Body)
	if err != nil {
		t.Fatalf("ioutil.ReadAll: %v", err)
	}
	rr.Body.Close()
	err = json.Unmarshal(buf, &rraresp)
	if err != nil {
		t.Fatalf("json.Unmarshal: %v", err)
	}
	if cnt != len(rraresp.RRAs) {
		t.Fatalf("unexpected rra count from rras endpoint")
	}
}
<commit_msg>add basic service1 median value test<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Contributor:
// - Aaron Meihm ameihm@mozilla.com

package main

import (
	"encoding/json"
	slib "github.com/mozilla/service-map/servicelib"
	"io/ioutil"
	"net/http"
	"strings"
	"testing"
)

func TestGetRRA(t *testing.T) {
	op := opContext{}
	op.newContext(dbconn, false, "127.0.0.1")
	// Tests service1
	rra, err := getRRA(op, 1)
	if err != nil {
		t.Fatalf("getRRA: %v", err)
	}
	if rra.Name != "test service" {
		t.Fatalf("getRRA: unexpected service name")
	}
	if rra.ConfiRepImpact != "high" {
		t.Fatalf("getRRA: unexpected impact for test service attribute")
	}
}

func TestServiceGetRRA(t *testing.T) {
	client := http.Client{}

	// Tests service1
	rr, err := client.Get(testserv.URL + "/api/v1/rra/id?id=1")
	if err != nil {
		t.Fatalf("client.Get: %v", err)
	}
	if rr.StatusCode != http.StatusOK {
		t.Fatalf("rra get response code %v", rr.StatusCode)
	}
	buf, err := ioutil.ReadAll(rr.Body)
	if err != nil {
		t.Fatalf("ioutil.ReadAll: %v", err)
	}
	rr.Body.Close()
	var rra slib.RRA
	err = json.Unmarshal(buf, &rra)
	if err != nil {
		t.Fatalf("json.Unmarshal: %v", err)
	}
	if rra.Name != "test service" {
		t.Fatalf("rra get rra had unexpected name")
	}
	if rra.ConfiRepImpact != "high" {
		t.Fatalf("rra get rra had unexpected service attribute value")
	}
	// The RRA should have one group associated with it
	if len(rra.Groups) != 1 {
		t.Fatalf("rra get rra associated with unexpected number of groups")
	}
}

func TestServiceGetNonExistRRA(t *testing.T) {
	client := http.Client{}

	rr, err := client.Get(testserv.URL + "/api/v1/rra/id?id=999")
	if err != nil {
		t.Fatalf("client.Get: %v", err)
	}
	if rr.StatusCode != http.StatusNotFound {
		t.Fatalf("rra get response code %v", rr.StatusCode)
	}
	rr.Body.Close()
}

func TestServiceGetRRARisk(t *testing.T) {
	client := http.Client{}

	// Tests service1
	rr, err := client.Get(testserv.URL + "/api/v1/rra/risk?id=1")
	if err != nil {
		t.Fatalf("client.Get: %v", err)
	}
	if rr.StatusCode != http.StatusOK {
		t.Fatalf("rra get response code %v", rr.StatusCode)
	}
	buf, err := ioutil.ReadAll(rr.Body)
	if err != nil {
		t.Fatalf("ioutil.ReadAll: %v", err)
	}
	rr.Body.Close()
	var r slib.Risk
	err = json.Unmarshal(buf, &r)
	if err != nil {
		t.Fatalf("json.Unmarshal: %v", err)
	}
	if r.Risk.MedianLabel != "medium" {
		t.Fatalf("rra get risk had unexpected median label value")
	}
}

func TestServiceRRAs(t *testing.T) {
	client := http.Client{}

	rr, err := client.Get(testserv.URL + "/api/v1/rras")
	if err != nil {
		t.Fatalf("client.Get: %v", err)
	}
	if rr.StatusCode != http.StatusOK {
		t.Fatalf("rras get response code %v", rr.StatusCode)
	}

	// The number of RRAs returned should correspond with the number of
	// valid test RRAs we have
	var rraresp slib.RRAsResponse
	dirlist, err := ioutil.ReadDir("./testdata")
	if err != nil {
		t.Fatalf("ioutil.ReadDir: %v", err)
	}
	cnt := 0
	for _, x := range dirlist {
		if !strings.HasPrefix(x.Name(), "service") {
			continue
		}
		cnt++
	}
	buf, err := ioutil.ReadAll(rr.Body)
	if err != nil {
		t.Fatalf("ioutil.ReadAll: %v", err)
	}
	rr.Body.Close()
	err = json.Unmarshal(buf, &rraresp)
	if err != nil {
		t.Fatalf("json.Unmarshal: %v", err)
	}
	if cnt != len(rraresp.RRAs) {
		t.Fatalf("unexpected rra count from rras endpoint")
	}
}
<|endoftext|>


<commit_before>package broadcast

import (
	"sync"
	"time"
)

const (
	broadcastMainChanBufferSize = 64
	broadcastChanBufferSize     = 64
	broadcastSendTimeout        = time.Millisecond * 100
)

type BroadcastMessage string

type GroupBroadcast struct {
	chStop chan struct{}
	chMain chan BroadcastMessage
	chs    []chan BroadcastMessage
	chsMux *sync.RWMutex

	flagStarted bool
}

func NewGroupBroadcast() *GroupBroadcast {
	return &GroupBroadcast{
		chStop: make(chan struct{}),
		chMain: make(chan BroadcastMessage, broadcastMainChanBufferSize),
		chs:    make([]chan BroadcastMessage, 0),
		chsMux: &sync.RWMutex{},
	}
}

func (gb *GroupBroadcast) BroadcastMessageTimeout(message BroadcastMessage, timeout time.Duration) bool {
	var timer = time.NewTimer(timeout)
	defer timer.Stop()

	select {
	case gb.chMain <- message:
		return true
	case <-gb.chStop:
	case <-timer.C:
	}

	return false
}

func (gb *GroupBroadcast) BroadcastMessage(message BroadcastMessage) {
	select {
	case gb.chMain <- message:
	case <-gb.chStop:
	}
}

func (gb *GroupBroadcast) Start(stop <-chan struct{}) {
	if gb.flagStarted {
		return
	}
	gb.flagStarted = true

	go func() {
		select {
		case <-stop:
		}
		gb.stop()
	}()

	go func() {
		for {
			select {
			case message, ok := <-gb.chMain:
				if !ok {
					return
				}
				gb.broadcast(message)
			case <-gb.chStop:
				return
			}
		}
	}()
}

func (gb *GroupBroadcast) broadcast(message BroadcastMessage) {
	gb.chsMux.RLock()
	defer gb.chsMux.RUnlock()

	for _, ch := range gb.chs {
		select {
		case ch <- message:
		case <-gb.chStop:
		}
	}
}

func (gb *GroupBroadcast) createChan() chan BroadcastMessage {
	ch := make(chan BroadcastMessage, broadcastChanBufferSize)

	gb.chsMux.Lock()
	gb.chs = append(gb.chs, ch)
	gb.chsMux.Unlock()

	return ch
}

func (gb *GroupBroadcast) deleteChan(ch chan BroadcastMessage) {
	go func() {
		for range ch {
		}
	}()

	gb.chsMux.Lock()
	for i := range gb.chs {
		if gb.chs[i] == ch {
			gb.chs = append(gb.chs[:i], gb.chs[i+1:]...)
			close(ch)
			break
		}
	}
	gb.chsMux.Unlock()
}

func (gb *GroupBroadcast) ListenMessages(stop <-chan struct{}, buffer uint) <-chan BroadcastMessage {
	ch := gb.createChan()
	chOut := make(chan BroadcastMessage, buffer)

	go func() {
		defer close(chOut)
		defer gb.deleteChan(ch)

		for {
			select {
			case <-stop:
				return
			case <-gb.chStop:
				return
			case message, ok := <-ch:
				if !ok {
					return
				}
				gb.send(chOut, message, stop, broadcastSendTimeout)
			}
		}
	}()

	return chOut
}

func (gb *GroupBroadcast) send(ch chan BroadcastMessage, message BroadcastMessage, stop <-chan struct{}, timeout time.Duration) {
	const tickSize = 5

	var timer = time.NewTimer(timeout)
	defer timer.Stop()

	var ticker = time.NewTicker(timeout / tickSize)
	defer ticker.Stop()

	if cap(ch) == 0 {
		select {
		case ch <- message:
		case <-gb.chStop:
		case <-stop:
		case <-timer.C:
		}
	} else {
		for {
			select {
			case ch <- message:
				return
			case <-gb.chStop:
				return
			case <-stop:
				return
			case <-timer.C:
				return
			case <-ticker.C:
				if len(ch) == cap(ch) {
					select {
					case <-ch:
					case ch <- message:
						return
					case <-stop:
						return
					case <-gb.chStop:
						return
					case <-timer.C:
						return
					}
				}
			}
		}
	}
}

func (gb *GroupBroadcast) stop() {
	close(gb.chStop)
	close(gb.chMain)

	gb.chsMux.Lock()
	defer gb.chsMux.Unlock()

	for _, ch := range gb.chs {
		close(ch)
	}

	gb.chs = gb.chs[:0]
}
<commit_msg>Rewrite broadcast sendMessageTimeout<commit_after>package broadcast

import (
	"sync"
	"time"
)

const (
	broadcastMainChanBufferSize = 64
	broadcastChanBufferSize     = 64
	broadcastSendTimeout        = time.Millisecond * 100
)

// TODO: Rename type.
type BroadcastMessage string

type GroupBroadcast struct {
	chStop chan struct{}
	chMain chan BroadcastMessage
	chs    []chan BroadcastMessage
	chsMux *sync.RWMutex

	flagStarted bool
}

func NewGroupBroadcast() *GroupBroadcast {
	return &GroupBroadcast{
		chStop: make(chan struct{}),
		chMain: make(chan BroadcastMessage, broadcastMainChanBufferSize),
		chs:    make([]chan BroadcastMessage, 0),
		chsMux: &sync.RWMutex{},
	}
}

func (gb *GroupBroadcast) BroadcastMessageTimeout(message BroadcastMessage, timeout time.Duration) bool {
	var timer = time.NewTimer(timeout)
	defer timer.Stop()

	select {
	case gb.chMain <- message:
		return true
	case <-gb.chStop:
	case <-timer.C:
	}

	return false
}

func (gb *GroupBroadcast) BroadcastMessage(message BroadcastMessage) {
	select {
	case gb.chMain <- message:
	case <-gb.chStop:
	}
}

func (gb *GroupBroadcast) Start(stop <-chan struct{}) {
	if gb.flagStarted {
		return
	}
	gb.flagStarted = true

	go func() {
		select {
		case <-stop:
		}
		gb.stop()
	}()

	go func() {
		for {
			select {
			case message, ok := <-gb.chMain:
				if !ok {
					return
				}
				gb.broadcast(message)
			case <-gb.chStop:
				return
			}
		}
	}()
}

func (gb *GroupBroadcast) broadcast(message BroadcastMessage) {
	gb.chsMux.RLock()
	defer gb.chsMux.RUnlock()

	for _, ch := range gb.chs {
		select {
		case ch <- message:
		case <-gb.chStop:
		}
	}
}

func (gb *GroupBroadcast) createChan() chan BroadcastMessage {
	ch := make(chan BroadcastMessage, broadcastChanBufferSize)

	gb.chsMux.Lock()
	gb.chs = append(gb.chs, ch)
	gb.chsMux.Unlock()

	return ch
}

func (gb *GroupBroadcast) deleteChan(ch chan BroadcastMessage) {
	go func() {
		for range ch {
		}
	}()

	gb.chsMux.Lock()
	for i := range gb.chs {
		if gb.chs[i] == ch {
			gb.chs = append(gb.chs[:i], gb.chs[i+1:]...)
			close(ch)
			break
		}
	}
	gb.chsMux.Unlock()
}

func (gb *GroupBroadcast) ListenMessages(stop <-chan struct{}, buffer uint) <-chan BroadcastMessage {
	ch := gb.createChan()
	chOut := make(chan BroadcastMessage, buffer)

	go func() {
		defer close(chOut)
		defer gb.deleteChan(ch)

		for {
			select {
			case <-stop:
				return
			case <-gb.chStop:
				return
			case message, ok := <-ch:
				if !ok {
					return
				}
				gb.sendMessageTimeout(chOut, message, stop, broadcastSendTimeout)
			}
		}
	}()

	return chOut
}

func (gb *GroupBroadcast) sendMessageTimeout(ch chan BroadcastMessage, message BroadcastMessage, stop <-chan struct{}, timeout time.Duration) {
	var timer = time.NewTimer(timeout)
	defer timer.Stop()
	select {
	case ch <- message:
	case <-gb.chStop:
	case <-stop:
	case <-timer.C:
	}
}

func (gb *GroupBroadcast) stop() {
	close(gb.chStop)
	close(gb.chMain)

	gb.chsMux.Lock()
	defer gb.chsMux.Unlock()

	for _, ch := range gb.chs {
		close(ch)
	}

	gb.chs = gb.chs[:0]
}
<|endoftext|>


<commit_before>package version

// Version contains the LXD version number
var Version = "3.22"
<commit_msg>Release LXD 3.23<commit_after>package version

// Version contains the LXD version number
var Version = "3.23"
<|endoftext|>


<commit_before>package main

/*
 * mktun_openbsd.go
 * OpenBSD-specific source to make the tun(4) device
 * by J. Stuart McMurray
 * created 20150116
 * last modified 20150214
 *
 * Copyright (c) 2014 J. Stuart McMurray <kd5pbo@gmail.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

import (
	"flag"
	"fmt"
	"os"
	"os/exec"
	"regexp"
	"strings"
)

var (
	mac = flag.String("mac", "", "MAC address to use for tun(4) "+
		"device.  If none is specified, none will be set, and "+
		"OpenBSD will assign an address.")
	ip = flag.String("ip", "", "IP Address to use for tun(4) "+
		"device.  Should probably be an IP address on the remote "+
		"subnet.  If not set, no address will be assigned (e.g. for "+
		"DHCP).")
	netmask = flag.String("nm", "", "Netmask.  Will only be set if an "+
		"IP address is specified.")
	mtu = flag.UInt("mtu", 1500, "MTU.  If 0 is specified, the default "+
		"will be used.")
)

const (
	MTUWARN = 2 * *14 /* Expected MTU limit */
)

/* Struct representing a tunnel.  Implements the Tunnel interface */
type TunOpenBSD struct {
	f *os.File /* /dev/tun file */
}

/* Read and return a frame from the kernel */
func (t *TunOpenBSD) Read() ([]byte, error) {
	/* Read buffer.  We should never fill this */
	buf := make([]byte, 2*MTUWARN)
	/* Block until we have data */
	n, err := t.f.Read(buf)
	if nil != err {
		return nil, err
	}
	/* If we read more than MTUWARN bytes, something's buggy */
	if n > MTUWARN {
		return nil, fmt.Errorf("read a %v-byte ethernet frame from %v.  This is "+
			"way too big and likely indicates a bug.", n)
	}
	/* Give back the read bytes */
	return buf[:n], nil
}

/* Write a frame to the kernel */
func (t *TunOpenBSD) Write(b []byte) error {
	/* Send the frame to the kernel */
	n, err := t.f.Write(b)
	if nil != err {
		return fmt.Errorf("only wrote %v/%v bytes: %v", n, len(b))
	}
	return nil
}

/* Close the tunnel */
func (t *TunOpenBSD) Close() error {
	return t.f.Close()
}

/* Make and open a tun(4) device. */
func MakeTun() (*TunOpenBSD, string, error) {
	var t *os.File = nil /* Tun device */
	var devname = ""     /* Name of tun device */

	/* Validate MAC and IP Addres */
	if "" != *mac && !regexp.MustCompile(`^[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:`+
		`[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:`+
		`[0-9A-Fa-f]{2}$`).MatchString(*mac) {
		return nil, "", fmt.Errorf("invalid MAC address: %v", *mac)
	}
	if "" != *ip && !regexp.MustCompile(`^[0-9A-Fa-f:]{2,39}|`+
		`\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$`).MatchString(*ip) {
		return nil, "", fmt.Errorf("Invalid IP address: %v", *ip)
	}

	/* Try successive device numbers until one works */
	for i := 0; i < 256; i++ {
		/* Work out which device to open */
		devname = fmt.Sprintf("tun%v", i)
		/* Try to open a tun device */
		var err error
		if t, err = os.Open(fmt.Sprintf("/dev/%v", devname)); nil !=
			err {
			debug("Unable to open %v: %v", devname, err)
			continue
		}
		debug("Opened /dev/%v", devname)
		break
	}

	/* If we still have no device, give up */
	if nil == t {
		return nil, "", fmt.Errorf("unable to open any tun device")
	}

	/* Set device to layer 2 tunneling */
	if output, err := exec.Command("/sbin/ifconfig", devname,
		"link0").CombinedOutput(); nil != err {
		return nil, "", fmt.Errorf("setting link0: %v (output: %v)",
			err, strings.TrimSpace(string(output)))
	}
	/* Set mac address if one is given */
	if "" != *mac {
		if output, err := exec.Command("/sbin/ifconfig", devname,
			"lladdr", *mac).CombinedOutput(); nil != err {
			return nil, "", fmt.Errorf("setting mac address "+
				"(%v): %v (output %v)",
				*mac, err, strings.TrimSpace(string(output)))
		}
	}

	//o, e := exec.Command("ifconfig").CombinedOutput() /* DEBUG */
	//log.Printf("(%v) %v", e, string(o)) /* DEBUG */

	/* Set the IP address if one is given */
	if "" != *ip {
		if output, err := exec.Command("/sbin/ifconfig", devname,
			"inet", *ip).CombinedOutput(); nil != err {
			return nil, "", fmt.Errorf("setting IP address (%v): "+
				"%v (output %v)",
				*ip, err, strings.TrimSpace(string(output)))
		}
		/* Set the netmask if it's given */
		if "" != *netmask {
			if err := exec.Command("/sbin/ifconfig", devname,
				"netmask", *netmask); nil != err {
				return nil, "", fmt.Errorf("setting netmask "+
					"(%v): %v (output %v)",
					*netmask, err,
					strings.TrimSpace(string(output)))
			}
		}
	}

	/* Set the MTU if one is given */
	if *mtu > MTUWARN {
		log.Printf("MTU (%v) is unusually high.  It probably should "+
			"be lower", *mtu)
	}
	if *mtu < 0 {
		return nil, "", fmt.Errorf("MTU (%v) less than 0", *mtu)
	}
	if 0 != *mtu {
		if output, err := exec.Command("/sbin/ifconfig", devname,
			"mtu", strconv.Itoa(*mtu)); nil != err {
			return nil, "", fmt.Errorf("setting mtu (%v): %v "+
				"(output %v)",
				*mtu, err, strings.TrimSpace(string(output)))
		}
	}
	return &TunOpenBSD{f: t}, devname, nil
}

/* Destroy the tunnel */
func destroy_tun(devname string) {
	if output, err := exec.Command("/sbin/ifconfig", devname,
		"destroy").CombinedOutput(); nil != err {
		debug("Unable to destroy %v: %v (output %v)",
			devname, err, strings.TrimSpace(string(output)))
	}
	debug("Destroyed %v", devname)
}
<commit_msg>Set MTU, bring interface up<commit_after>package main

/*
 * mktun_openbsd.go
 * OpenBSD-specific source to make the tun(4) device
 * by J. Stuart McMurray
 * created 20150116
 * last modified 20150218
 *
 * Copyright (c) 2014 J. Stuart McMurray <kd5pbo@gmail.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

import (
	"flag"
	"fmt"
	"log"
	"os"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
)

/* Flags speficic to openbsd */
var (
	mac = flag.String("mac", "", "MAC address to use for tun(4) "+
		"device.  If none is specified, none will be set, and "+
		"OpenBSD will assign an address.")
	ip = flag.String("ip", "", "IP Address to use for tun(4) "+
		"device.  Should probably be an IP address on the remote "+
		"subnet.  If not set, no address will be assigned (e.g. for "+
		"DHCP).")
	netmask = flag.String("nm", "", "Netmask.  Will only be set if an "+
		"IP address is specified.")
	mtu = flag.Int("mtu", 1500, "MTU.  If 0 is specified, the default "+
		"will be used.")
)

const (
	MTUWARN = 1 << 14 /* Expected MTU limit */
)

/* Struct representing a tunnel.  Implements the Tunnel interface */
type TunOpenBSD struct {
	f *os.File /* /dev/tun file */
}

/* Read and return a frame from the kernel */
func (t *TunOpenBSD) Read() (Frame, error) {
	/* Read buffer.  We should never fill this */
	buf := make([]byte, 2*MTUWARN)
	/* Block until we have data */
	n, err := t.f.Read(buf)
	if nil != err {
		return nil, err
	}
	/* If we read more than MTUWARN bytes, something's buggy */
	if n > MTUWARN {
		return nil, fmt.Errorf("read a %v-byte ethernet frame from "+
			"%v.  This is way too big and likely indicates a bug.",
			n)
	}
	/* Give back the read bytes */
	return buf[:n], nil
}

/* Write a frame to the kernel */
func (t *TunOpenBSD) Write(b Frame) error {
	/* Send the frame to the kernel */
	n, err := t.f.Write(b)
	if nil != err {
		return fmt.Errorf("only wrote %v/%v bytes: %v", n, len(b))
	}
	return nil
}

/* Close the tunnel */
func (t *TunOpenBSD) Close() error {
	return t.f.Close()
}

/* Make and open a tun(4) device. */
func MakeTun() (*TunOpenBSD, string, error) {
	var t *os.File = nil /* Tun device */
	var devname = ""     /* Name of tun device */

	/* Validate MAC and IP Addres */
	if "" != *mac && !regexp.MustCompile(`^[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:`+
		`[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:`+
		`[0-9A-Fa-f]{2}$`).MatchString(*mac) {
		return nil, "", fmt.Errorf("invalid MAC address: %v", *mac)
	}
	if "" != *ip && !regexp.MustCompile(`^[0-9A-Fa-f:]{2,39}|`+
		`\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$`).MatchString(*ip) {
		return nil, "", fmt.Errorf("Invalid IP address: %v", *ip)
	}

	/* Make sure MTU is > 0 */
	if 0 >= *mtu {
		return nil, "", fmt.Errorf("mtu must be greater than zero.")
	}

	/* Try successive device numbers until one works */
	for i := 0; i < 256; i++ {
		/* Work out which device to open */
		devname = fmt.Sprintf("tun%v", i)
		/* Try to open a tun device */
		var err error
		if t, err = os.Open(fmt.Sprintf("/dev/%v", devname)); nil !=
			err {
			debug("Unable to open %v: %v", devname, err)
			continue
		}
		debug("Opened /dev/%v", devname)
		break
	}

	/* If we still have no device, give up */
	if nil == t {
		return nil, "", fmt.Errorf("unable to open any tun device")
	}

	/* Set device to layer 2 tunneling */
	if output, err := exec.Command("/sbin/ifconfig", devname,
		"link0").CombinedOutput(); nil != err {
		return nil, "", fmt.Errorf("setting link0: %v (output: %v)",
			err, strings.TrimSpace(string(output)))
	}
	/* Set mac address if one is given */
	if "" != *mac {
		if output, err := exec.Command("/sbin/ifconfig", devname,
			"lladdr", *mac).CombinedOutput(); nil != err {
			return nil, "", fmt.Errorf("setting mac address "+
				"(%v): %v (output %v)",
				*mac, err, strings.TrimSpace(string(output)))
		}
	}

	//o, e := exec.Command("ifconfig").CombinedOutput() /* DEBUG */
	//log.Printf("(%v) %v", e, string(o)) /* DEBUG */

	/* Set the IP address if one is given */
	if "" != *ip {
		if output, err := exec.Command("/sbin/ifconfig", devname,
			"inet", *ip).CombinedOutput(); nil != err {
			return nil, "", fmt.Errorf("setting IP address (%v): "+
				"%v (output %v)",
				*ip, err, strings.TrimSpace(string(output)))
		}
		/* Set the netmask if it's given */
		if "" != *netmask {
			output, err := exec.Command("/sbin/ifconfig",
				devname,
				"netmask",
				*netmask).CombinedOutput()
			if nil != err {
				return nil, "", fmt.Errorf("setting netmask "+
					"(%v): %v (output %v)",
					*netmask, err,
					strings.TrimSpace(string(output)))
			}
		}
	}

	/* Set the MTU if one is given */
	if *mtu > MTUWARN {
		log.Printf("MTU (%v) is unusually high.  It probably should "+
			"be lower", *mtu)
	}
	if *mtu < 0 {
		return nil, "", fmt.Errorf("MTU (%v) less than 0", *mtu)
	}
	if 0 != *mtu {
		if output, err := exec.Command(
			"/sbin/ifconfig",
			devname,
			"mtu",
			strconv.Itoa(*mtu),
		).CombinedOutput(); nil != err {
			return nil, "", fmt.Errorf("setting mtu (%v): %v "+
				"(output %v)",
				*mtu, err, strings.TrimSpace(string(output)))
		}
	}

	/* Bring the interface up */
	if output, err := exec.Command(
		"/sbin/ifconfig",
		devname,
		"up",
	).CombinedOutput(); nil != err {
		return nil, "", fmt.Errorf("Bringing %v up: %v (output %v)",
			devname, err, output)
	}
	return &TunOpenBSD{f: t}, devname, nil
}

/* Destroy the tunnel */
func destroy_tun(devname string) {
	if output, err := exec.Command("/sbin/ifconfig", devname,
		"destroy").CombinedOutput(); nil != err {
		debug("Unable to destroy %v: %v (output %v)",
			devname, err, strings.TrimSpace(string(output)))
	}
	debug("Destroyed %v", devname)
}
<|endoftext|>


<commit_before>// This file is basically copied from $GOROOT/src/syscall/js/js_test.go

// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build js

// To run these tests:
//
// - Install Node
// - Add /path/to/go/misc/wasm to your $PATH (so that "go test" can find
//   "go_js_wasm_exec").
// - GOOS=js GOARCH=wasm go test
//
// See -exec in "go help test", and "go help run" for details.

package js_test

import (
	"fmt"
	"math"
	"syscall/js"
	"testing"
)

func TestMain(m *testing.M) {
	// Suppress the 'deadlock' error on GopherJS by goroutine
	// (https://github.com/gopherjs/gopherjs/issues/826).
	go func() {
		m.Run()
	}()
}

var dummys = js.Global().Call("eval", `({
	someBool: true,
	someString: "abc\u1234",
	someInt: 42,
	someFloat: 42.123,
	someArray: [41, 42, 43],
	someDate: new Date(),
	add: function(a, b) {
		return a + b;
	},
	zero: 0,
	stringZero: "0",
	NaN: NaN,
	emptyObj: {},
	emptyArray: [],
	Infinity: Infinity,
	NegInfinity: -Infinity,
	objNumber0: new Number(0),
	objBooleanFalse: new Boolean(false),
})`)

func TestBool(t *testing.T) {
	want := true
	o := dummys.Get("someBool")
	if got := o.Bool(); got != want {
		t.Errorf("got %#v, want %#v", got, want)
	}
	dummys.Set("otherBool", want)
	if got := dummys.Get("otherBool").Bool(); got != want {
		t.Errorf("got %#v, want %#v", got, want)
	}
	if dummys.Get("someBool") != dummys.Get("someBool") {
		t.Errorf("same value not equal")
	}
}

func TestString(t *testing.T) {
	want := "abc\u1234"
	o := dummys.Get("someString")
	if got := o.String(); got != want {
		t.Errorf("got %#v, want %#v", got, want)
	}
	dummys.Set("otherString", want)
	if got := dummys.Get("otherString").String(); got != want {
		t.Errorf("got %#v, want %#v", got, want)
	}
	if dummys.Get("someString") != dummys.Get("someString") {
		t.Errorf("same value not equal")
	}

	wantInt := "42"
	o = dummys.Get("someInt")
	if got := o.String(); got != wantInt {
		t.Errorf("got %#v, want %#v", got, wantInt)
	}
}

func TestInt(t *testing.T) {
	want := 42
	o := dummys.Get("someInt")
	if got := o.Int(); got != want {
		t.Errorf("got %#v, want %#v", got, want)
	}
	dummys.Set("otherInt", want)
	if got := dummys.Get("otherInt").Int(); got != want {
		t.Errorf("got %#v, want %#v", got, want)
	}
	if dummys.Get("someInt") != dummys.Get("someInt") {
		t.Errorf("same value not equal")
	}
	if got := dummys.Get("zero").Int(); got != 0 {
		t.Errorf("got %#v, want %#v", got, 0)
	}
}

func TestIntConversion(t *testing.T) {
	testIntConversion(t, 0)
	testIntConversion(t, 1)
	testIntConversion(t, -1)
	testIntConversion(t, 1<<20)
	testIntConversion(t, -1<<20)

	// Skip too big integers. They cannot be compiled with 32bit environment, and GopherJS is one of them.
	// testIntConversion(t, 1<<40)
	// testIntConversion(t, -1<<40)
	// testIntConversion(t, 1<<60)
	// testIntConversion(t, -1<<60)
}

func testIntConversion(t *testing.T, want int) {
	if got := js.ValueOf(want).Int(); got != want {
		t.Errorf("got %#v, want %#v", got, want)
	}
}

func TestFloat(t *testing.T) {
	want := 42.123
	o := dummys.Get("someFloat")
	if got := o.Float(); got != want {
		t.Errorf("got %#v, want %#v", got, want)
	}
	dummys.Set("otherFloat", want)
	if got := dummys.Get("otherFloat").Float(); got != want {
		t.Errorf("got %#v, want %#v", got, want)
	}
	if dummys.Get("someFloat") != dummys.Get("someFloat") {
		t.Errorf("same value not equal")
	}
}

func TestObject(t *testing.T) {
	if dummys.Get("someArray") != dummys.Get("someArray") {
		t.Errorf("same value not equal")
	}

	// An object and its prototype should not be equal.
	proto := js.Global().Get("Object").Get("prototype")
	o := js.Global().Call("eval", "new Object()")
	if proto == o {
		t.Errorf("object equals to its prototype")
	}
}

func TestFrozenObject(t *testing.T) {
	o := js.Global().Call("eval", "(function () { let o = new Object(); o.field = 5; Object.freeze(o); return o; })()")
	want := 5
	if got := o.Get("field").Int(); want != got {
		t.Errorf("got %#v, want %#v", got, want)
	}
}

func TestTypedArrayOf(t *testing.T) {
	testTypedArrayOf(t, "[]int8", []int8{0, -42, 0}, -42)
	testTypedArrayOf(t, "[]int16", []int16{0, -42, 0}, -42)
	testTypedArrayOf(t, "[]int32", []int32{0, -42, 0}, -42)
	testTypedArrayOf(t, "[]uint8", []uint8{0, 42, 0}, 42)
	testTypedArrayOf(t, "[]uint16", []uint16{0, 42, 0}, 42)
	testTypedArrayOf(t, "[]uint32", []uint32{0, 42, 0}, 42)
	testTypedArrayOf(t, "[]float32", []float32{0, -42.5, 0}, -42.5)
	testTypedArrayOf(t, "[]float64", []float64{0, -42.5, 0}, -42.5)
}

func testTypedArrayOf(t *testing.T, name string, slice interface{}, want float64) {
	t.Run(name, func(t *testing.T) {
		a := js.TypedArrayOf(slice)
		got := a.Index(1).Float()
		a.Release()
		if got != want {
			t.Errorf("got %#v, want %#v", got, want)
		}
	})
}

func TestNaN(t *testing.T) {
	t.Skip("NaN cannot be compared")

	want := js.ValueOf(math.NaN())
	got := dummys.Get("NaN")
	if got != want {
		t.Errorf("got %#v, want %#v", got, want)
	}
}

func TestUndefined(t *testing.T) {
	dummys.Set("test", js.Undefined())
	if dummys == js.Undefined() || dummys.Get("test") != js.Undefined() || dummys.Get("xyz") != js.Undefined() {
		t.Errorf("js.Undefined expected")
	}
}

func TestNull(t *testing.T) {
	dummys.Set("test1", nil)
	dummys.Set("test2", js.Null())
	if dummys == js.Null() || dummys.Get("test1") != js.Null() || dummys.Get("test2") != js.Null() {
		t.Errorf("js.Null expected")
	}
}

func TestLength(t *testing.T) {
	if got := dummys.Get("someArray").Length(); got != 3 {
		t.Errorf("got %#v, want %#v", got, 3)
	}
}

func TestIndex(t *testing.T) {
	if got := dummys.Get("someArray").Index(1).Int(); got != 42 {
		t.Errorf("got %#v, want %#v", got, 42)
	}
}

func TestSetIndex(t *testing.T) {
	dummys.Get("someArray").SetIndex(2, 99)
	if got := dummys.Get("someArray").Index(2).Int(); got != 99 {
		t.Errorf("got %#v, want %#v", got, 99)
	}
}

func TestCall(t *testing.T) {
	var i int64 = 40
	if got := dummys.Call("add", i, 2).Int(); got != 42 {
		t.Errorf("got %#v, want %#v", got, 42)
	}
	if got := dummys.Call("add", js.Global().Call("eval", "40"), 2).Int(); got != 42 {
		t.Errorf("got %#v, want %#v", got, 42)
	}
}

func TestInvoke(t *testing.T) {
	var i int64 = 40
	if got := dummys.Get("add").Invoke(i, 2).Int(); got != 42 {
		t.Errorf("got %#v, want %#v", got, 42)
	}
}

func TestNew(t *testing.T) {
	if got := js.Global().Get("Array").New(42).Length(); got != 42 {
		t.Errorf("got %#v, want %#v", got, 42)
	}
}

func TestInstanceOf(t *testing.T) {
	someArray := js.Global().Get("Array").New()
	if got, want := someArray.InstanceOf(js.Global().Get("Array")), true; got != want {
		t.Errorf("got %#v, want %#v", got, want)
	}
	if got, want := someArray.InstanceOf(js.Global().Get("Function")), false; got != want {
		t.Errorf("got %#v, want %#v", got, want)
	}
}

func TestType(t *testing.T) {
	if got, want := js.Undefined().Type(), js.TypeUndefined; got != want {
		t.Errorf("got %s, want %s", got, want)
	}
	if got, want := js.Null().Type(), js.TypeNull; got != want {
		t.Errorf("got %s, want %s", got, want)
	}
	if got, want := js.ValueOf(true).Type(), js.TypeBoolean; got != want {
		t.Errorf("got %s, want %s", got, want)
	}
	if got, want := js.ValueOf(0).Type(), js.TypeNumber; got != want {
		t.Errorf("got %s, want %s", got, want)
	}
	if got, want := js.ValueOf(42).Type(), js.TypeNumber; got != want {
		t.Errorf("got %s, want %s", got, want)
	}
	if got, want := js.ValueOf("test").Type(), js.TypeString; got != want {
		t.Errorf("got %s, want %s", got, want)
	}
	if got, want := js.Global().Get("Symbol").Invoke("test").Type(), js.TypeSymbol; got != want {
		t.Errorf("got %s, want %s", got, want)
	}
	if got, want := js.Global().Get("Array").New().Type(), js.TypeObject; got != want {
		t.Errorf("got %s, want %s", got, want)
	}
	if got, want := js.Global().Get("Array").Type(), js.TypeFunction; got != want {
		t.Errorf("got %s, want %s", got, want)
	}
}

type object = map[string]interface{}
type array = []interface{}

func TestValueOf(t *testing.T) {
	a := js.ValueOf(array{0, array{0, 42, 0}, 0})
	if got := a.Index(1).Index(1).Int(); got != 42 {
		t.Errorf("got %v, want %v", got, 42)
	}

	o := js.ValueOf(object{"x": object{"y": 42}})
	if got := o.Get("x").Get("y").Int(); got != 42 {
		t.Errorf("got %v, want %v", got, 42)
	}
}

func TestZeroValue(t *testing.T) {
	var v js.Value
	if v != js.Undefined() {
		t.Error("zero js.Value is not js.Undefined()")
	}
}

func TestFuncOf(t *testing.T) {
	c := make(chan struct{})
	cb := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		if got := args[0].Int(); got != 42 {
			t.Errorf("got %#v, want %#v", got, 42)
		}
		c <- struct{}{}
		return nil
	})
	defer cb.Release()
	js.Global().Call("setTimeout", cb, 0, 42)
	<-c
}

func TestInvokeFunction(t *testing.T) {
	called := false
	cb := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		cb2 := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
			called = true
			return 42
		})
		defer cb2.Release()
		return cb2.Invoke()
	})
	defer cb.Release()
	if got := cb.Invoke().Int(); got != 42 {
		t.Errorf("got %#v, want %#v", got, 42)
	}
	if !called {
		t.Error("function not called")
	}
}

func ExampleFuncOf() {
	var cb js.Func
	cb = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		fmt.Println("button clicked")
		cb.Release() // release the function if the button will not be clicked again
		return nil
	})
	js.Global().Get("document").Call("getElementById", "myButton").Call("addEventListener", "click", cb)
}

// See
// - https://developer.mozilla.org/en-US/docs/Glossary/Truthy
// - https://stackoverflow.com/questions/19839952/all-falsey-values-in-javascript/19839953#19839953
// - http://www.ecma-international.org/ecma-262/5.1/#sec-9.2
func TestTruthy(t *testing.T) {
	want := true
	for _, key := range []string{
		"someBool", "someString", "someInt", "someFloat", "someArray", "someDate",
		"stringZero", // "0" is truthy
		"add",        // functions are truthy
		"emptyObj", "emptyArray", "Infinity", "NegInfinity",
		// All objects are truthy, even if they're Number(0) or Boolean(false).
		"objNumber0", "objBooleanFalse",
	} {
		if got := dummys.Get(key).Truthy(); got != want {
			t.Errorf("%s: got %#v, want %#v", key, got, want)
		}
	}

	want = false
	if got := dummys.Get("zero").Truthy(); got != want {
		t.Errorf("got %#v, want %#v", got, want)
	}
	if got := dummys.Get("NaN").Truthy(); got != want {
		t.Errorf("got %#v, want %#v", got, want)
	}
	if got := js.ValueOf("").Truthy(); got != want {
		t.Errorf("got %#v, want %#v", got, want)
	}
	if got := js.Null().Truthy(); got != want {
		t.Errorf("got %#v, want %#v", got, want)
	}
	if got := js.Undefined().Truthy(); got != want {
		t.Errorf("got %#v, want %#v", got, want)
	}
}
<commit_msg>Remove our forked copy of syscall/js tests.<commit_after><|endoftext|>


<commit_before>// Copyright 2015, David Howden
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package player

import (
	"encoding/json"
	"fmt"
)

// RepFn is a type which represents a command function which will be called
// with a standardised command structure when Player methods are used.
type RepFn func(interface{})

type rep struct {
	key string
	fn  RepFn
}

// NewRep creates a Player p which will call fn with a standardised representation for each
// call to methods of p (eee RepActions for the Action mapping).
// FIXME: this is possibly a unhelpful and overly generic mess.
func NewRep(key string, fn RepFn) Player {
	return &rep{
		key: key,
		fn:  fn,
	}
}

func (r rep) sendAction(data interface{}) error {
	r.fn(data)
	return nil
}

func (r rep) sendCtrlValue(key string, value interface{}) error {
	r.sendAction(struct {
		Key   string
		Value interface{}
	}{
		Key:   key,
		Value: value,
	})
	return nil
}

func (r rep) Key() string { return r.key }

var RepActions = map[Action]string{
	ActionPlay:            "PLAY",
	ActionPause:           "PAUSE",
	ActionNext:            "NEXT",
	ActionPrev:            "PREV",
	ActionTogglePlayPause: "TOGGLE_PLAY_PAUSE",
	ActionToggleMute:      "TOGGLE_MUTE",

	ActionSetVolume: "SET_VOLUME",
	ActionSetMute:   "SET_MUTE",
	ActionSetTime:   "SET_TIME",
}

func RepActionToAction(a string) (Action, bool) {
	for k, v := range RepActions {
		if v == a {
			return k, true
		}
	}
	return Action(""), false
}

type InvalidActionError string

func (i InvalidActionError) Error() string {
	return fmt.Sprintf("invalid player action: '%s'", string(i))
}

func (r rep) Do(a Action) error {
	s, ok := RepActions[a]
	if !ok {
		return InvalidActionError(a)
	}
	return r.sendAction(s)
}

func (r rep) SetMute(b bool) error      { return r.sendCtrlValue("mute", b) }
func (r rep) SetVolume(f float64) error { return r.sendCtrlValue("volume", f) }
func (r rep) SetTime(f float64) error   { return r.sendCtrlValue("time", f) }

func (r rep) MarshalJSON() ([]byte, error) {
	rep := struct {
		Key string `json:"key"`
	}{
		Key: r.key,
	}
	return json.Marshal(rep)
}
<commit_msg>Added RepAction struct to represent the Player action in-transit.<commit_after>// Copyright 2015, David Howden
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package player

import (
	"encoding/json"
	"fmt"
)

// RepFn is a type which represents a command function which will be called
// with a standardised command structure when Player methods are used.
type RepFn func(interface{})

// RepAction is a representation of a player action as it would be transmitted.
type RepAction struct {
	Action string      `json:"action"`
	Value  interface{} `json:",omitempty"`
}

type rep struct {
	key string
	fn  RepFn
}

// NewRep creates a Player p which will call fn with a standardised representation for each
// call to methods of p (eee RepActions for the Action mapping).
// FIXME: this is possibly a unhelpful and overly generic mess.
func NewRep(key string, fn RepFn) Player {
	return &rep{
		key: key,
		fn:  fn,
	}
}

func (r rep) sendAction(action string) error {
	r.fn(RepAction{
		Action: action,
	})
	return nil
}

func (r rep) sendActionValue(action string, value interface{}) error {
	r.fn(RepAction{
		Action: action,
		Value:  value,
	})
	return nil
}

func (r rep) Key() string { return r.key }

var RepActions = map[Action]string{
	ActionPlay:            "PLAY",
	ActionPause:           "PAUSE",
	ActionNext:            "NEXT",
	ActionPrev:            "PREV",
	ActionTogglePlayPause: "TOGGLE_PLAY_PAUSE",
	ActionToggleMute:      "TOGGLE_MUTE",

	ActionSetVolume: "SET_VOLUME",
	ActionSetMute:   "SET_MUTE",
	ActionSetTime:   "SET_TIME",
}

func RepActionToAction(a string) (Action, bool) {
	for k, v := range RepActions {
		if v == a {
			return k, true
		}
	}
	return Action(""), false
}

type InvalidActionError string

func (i InvalidActionError) Error() string {
	return fmt.Sprintf("invalid player action: '%s'", string(i))
}

func (r rep) Do(a Action) error {
	s, ok := RepActions[a]
	if !ok {
		return InvalidActionError(a)
	}
	return r.sendAction(s)
}

func (r rep) SetMute(b bool) error      { return r.sendActionValue("mute", b) }
func (r rep) SetVolume(f float64) error { return r.sendActionValue("volume", f) }
func (r rep) SetTime(f float64) error   { return r.sendActionValue("time", f) }

func (r rep) MarshalJSON() ([]byte, error) {
	rep := struct {
		Key string `json:"key"`
	}{
		Key: r.key,
	}
	return json.Marshal(rep)
}
<|endoftext|>


<commit_before>// Copyright 2015 Dorival Pedroso and Raul Durand. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package plt

import "github.com/cpmech/gosl/io"

// Formatter defines an interface to format lines with markers and colors
type Formatter interface {
	GetArgs(start string) string
}

// FmtS implemetns a formatter using a slice of strings
type FmtS []string

// ShapeData holds data for drawing shapes
type FmtH struct {
	Fc     string
	Ec     string
	Lw     int
	Closed bool
}

// LineData holds data for ploting lines
type FmtL struct {
	L  string
	C  string
	Lw float64
	Ms float64 // negative values => default
	M  string
	Ls string
}

// Init initialises ShapeData with default values
func (o *FmtH) Init() {
	o.Fc = "#edf5ff"
	o.Ec = "black"
	o.Lw = 1
}

// GetArgs returns the arguments for plt
func (o FmtS) GetArgs(start string) string {
	l := "'"
	for _, s := range o {
		l += s
	}
	if start != "" {
		return l + "'" + "," + start
	}
	return l + "'"
}

// GetArgs returns arguments for Plot
func (o FmtL) GetArgs(start string) string {
	l := start
	if o.L != "" {
		if len(l) > 0 {
			l += ","
		}
		l += io.Sf("label='%s'", o.L)
	}
	if o.C != "" {
		if len(l) > 0 {
			l += ","
		}
		l += io.Sf("color='%s'", o.C)
	}
	if o.Lw > 0 {
		if len(l) > 0 {
			l += ","
		}
		l += io.Sf("lw=%g", o.Lw)
	}
	if o.Ms > 0 {
		if len(l) > 0 {
			l += ","
		}
		l += io.Sf("ms=%d", int(o.Ms))
	}
	if o.M != "" {
		if len(l) > 0 {
			l += ","
		}
		l += io.Sf("marker='%s'", o.M)
	}
	if o.Ls != "" {
		if len(l) > 0 {
			l += ","
		}
		l += io.Sf("ls='%s'", o.Ls)
	}
	return l
}
<commit_msg>comments added<commit_after>// Copyright 2015 Dorival Pedroso and Raul Durand. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package plt

import "github.com/cpmech/gosl/io"

// Formatter defines an interface to format lines with markers and colors
type Formatter interface {
	GetArgs(start string) string
}

// FmtS implemetns a formatter using a slice of strings
type FmtS []string

// ShapeData holds data for drawing shapes
type FmtH struct {
	Fc     string // face color
	Ec     string // edge color
	Lw     int    // linewidth
	Closed bool   // closed shape
}

// LineData holds data for ploting lines
type FmtL struct {
	L  string  // label
	C  string  // color
	Lw float64 // linewidth
	Ms float64 // negative values => default
	M  string  // marker
	Ls string  // linestype
}

// Init initialises ShapeData with default values
func (o *FmtH) Init() {
	o.Fc = "#edf5ff"
	o.Ec = "black"
	o.Lw = 1
}

// GetArgs returns the arguments for plt
func (o FmtS) GetArgs(start string) string {
	l := "'"
	for _, s := range o {
		l += s
	}
	if start != "" {
		return l + "'" + "," + start
	}
	return l + "'"
}

// GetArgs returns arguments for Plot
func (o FmtL) GetArgs(start string) string {
	l := start
	if o.L != "" {
		if len(l) > 0 {
			l += ","
		}
		l += io.Sf("label='%s'", o.L)
	}
	if o.C != "" {
		if len(l) > 0 {
			l += ","
		}
		l += io.Sf("color='%s'", o.C)
	}
	if o.Lw > 0 {
		if len(l) > 0 {
			l += ","
		}
		l += io.Sf("lw=%g", o.Lw)
	}
	if o.Ms > 0 {
		if len(l) > 0 {
			l += ","
		}
		l += io.Sf("ms=%d", int(o.Ms))
	}
	if o.M != "" {
		if len(l) > 0 {
			l += ","
		}
		l += io.Sf("marker='%s'", o.M)
	}
	if o.Ls != "" {
		if len(l) > 0 {
			l += ","
		}
		l += io.Sf("ls='%s'", o.Ls)
	}
	return l
}
<|endoftext|>


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

package state

import (
	"github.com/juju/loggo"
)

var logger = loggo.GetLogger("juju.resource.state")

// RawState defines the functionality needed from state.State for resources.
type RawState interface {
	rawSpecState
}

// State exposes the state functionality needed for resources.
type State struct {
	*specState
}

// NewState returns a new State for the given raw Juju state.
func NewState(raw RawState) *State {
	return &State{
		specState: &specState{raw},
	}
}
<commit_msg>Add some logging.<commit_after>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package state

import (
	"github.com/juju/loggo"
)

var logger = loggo.GetLogger("juju.resource.state")

// RawState defines the functionality needed from state.State for resources.
type RawState interface {
	rawSpecState
}

// State exposes the state functionality needed for resources.
type State struct {
	*specState
}

// NewState returns a new State for the given raw Juju state.
func NewState(raw RawState) *State {
	logger.Tracef("wrapping state for resources")
	return &State{
		specState: &specState{raw},
	}
}
<|endoftext|>


<commit_before>package generatorControllers

import (
	. "eaciit/wfdemo-git/library/models"
	. "eaciit/wfdemo-git/processapp/summaryGenerator/controllers"
	"eaciit/wfdemo-git/web/helper"
	"os"
	"time"

	"github.com/eaciit/dbox"
	_ "github.com/eaciit/dbox/dbc/mongo"
	"github.com/eaciit/toolkit"
)

type GenDataPeriod struct {
	*BaseController
}

func (d *GenDataPeriod) Generate(base *BaseController) {
	d.BaseController = base
	conn, e := PrepareConnection()
	if e != nil {
		toolkit.Println("Scada Summary : " + e.Error())
		os.Exit(0)
	}

	// reset data
	// #faisal
	// remove this function
	d.BaseController.Ctx.DeleteMany(NewLatestDataPeriod(), dbox.Ne("projectname", ""))

	projects, _ := helper.GetProjectList()

	for _, proj := range projects {
		projectName := proj.Value
		scadaResults := make([]time.Time, 2)
		dgrResults := make([]time.Time, 2)
		alarmResults := make([]time.Time, 2)
		jmrResults := make([]time.Time, 2)
		metResults := make([]time.Time, 2)
		durationResults := make([]time.Time, 2)
		scadaAnomalyresults := make([]time.Time, 2)
		alarmOverlappingresults := make([]time.Time, 2)
		alarmScadaAnomalyresults := make([]time.Time, 2)
		scadaHFDResult := make([]time.Time, 2)
		warningResult := make([]time.Time, 2)
		scadaOEMResult := make([]time.Time, 2)

		scadaResults[0], scadaResults[1], e = getDataDateAvailable(conn, new(ScadaData).TableName(), "timestamp", dbox.Eq("projectname", projectName))
		dgrResults[0], dgrResults[1], e = getDataDateAvailable(conn, new(DGRModel).TableName(), "dateinfo.dateid", dbox.Eq("site", projectName))
		alarmResults[0], alarmResults[1], e = getDataDateAvailable(conn, new(Alarm).TableName(), "startdate", dbox.Eq("farm", projectName))
		alarmOverlappingresults[0], alarmOverlappingresults[1], e = getDataDateAvailable(conn, new(AlarmOverlapping).TableName(), "startdate", dbox.Eq("farm", projectName))
		alarmScadaAnomalyresults[0], alarmScadaAnomalyresults[1], e = getDataDateAvailable(conn, new(AlarmScadaAnomaly).TableName(), "startdate", dbox.Eq("farm", projectName))
		jmrResults[0], jmrResults[1], e = getDataDateAvailable(conn, new(ScadaData).TableName(), "dateinfo.dateid", dbox.Eq("projectname", projectName))
		metResults[0], metResults[1], e = getDataDateAvailable(conn, new(MetTower).TableName(), "timestamp", dbox.Eq("project", projectName))
		durationResults[0], durationResults[1], e = getDataDateAvailable(conn, new(ScadaData).TableName(), "timestamp", dbox.And(dbox.Eq("isvalidtimeduration", false), dbox.Eq("projectname", projectName)))
		scadaAnomalyresults[0], scadaAnomalyresults[1], e = getDataDateAvailable(conn, new(ScadaData).TableName(), "timestamp", dbox.And(dbox.Eq("isvalidtimeduration", true), dbox.Eq("projectname", projectName)))
		scadaHFDResult[0], scadaHFDResult[1], e = getDataDateAvailable(conn, new(ScadaDataHFD).TableName(), "timestamp", dbox.Eq("projectname", projectName))
		warningResult[0], warningResult[1], e = getDataDateAvailable(conn, new(EventAlarm).TableName(), "timeend", dbox.Eq("projectname", projectName))
		scadaOEMResult[0], scadaOEMResult[1], e = getDataDateAvailable(conn, new(ScadaDataOEM).TableName(), "timestamp", dbox.Eq("projectname", projectName))

		availdatedata := struct {
			ScadaData         []time.Time
			DGRData           []time.Time
			Alarm             []time.Time
			JMR               []time.Time
			MET               []time.Time
			Duration          []time.Time
			ScadaAnomaly      []time.Time
			AlarmOverlapping  []time.Time
			AlarmScadaAnomaly []time.Time
			ScadaDataHFD      []time.Time
			Warning           []time.Time
			ScadaDataOEM      []time.Time
		}{
			ScadaData:         scadaResults,
			DGRData:           dgrResults,
			Alarm:             alarmResults,
			JMR:               jmrResults,
			MET:               metResults,
			Duration:          durationResults,
			ScadaAnomaly:      scadaAnomalyresults,
			AlarmOverlapping:  alarmOverlappingresults,
			AlarmScadaAnomaly: alarmScadaAnomalyresults,
			ScadaDataHFD:      scadaHFDResult,
			Warning:           warningResult,
			ScadaDataOEM:      scadaOEMResult,
		}

		mdl := NewLatestDataPeriod()
		mdl.Type = "ScadaData"
		mdl.ProjectName = projectName
		mdl.Data = availdatedata.ScadaData

		d.BaseController.Ctx.Insert(mdl)

		mdl = NewLatestDataPeriod()
		mdl.Type = "DGRData"
		mdl.ProjectName = projectName
		mdl.Data = availdatedata.DGRData

		d.BaseController.Ctx.Insert(mdl)

		mdl = NewLatestDataPeriod()
		mdl.Type = "Alarm"
		mdl.ProjectName = projectName
		mdl.Data = availdatedata.Alarm

		d.BaseController.Ctx.Insert(mdl)

		mdl = NewLatestDataPeriod()
		mdl.Type = "JMR"
		mdl.ProjectName = projectName
		mdl.Data = availdatedata.JMR

		d.BaseController.Ctx.Insert(mdl)

		mdl = NewLatestDataPeriod()
		mdl.Type = "MET"
		mdl.ProjectName = projectName
		mdl.Data = availdatedata.MET

		d.BaseController.Ctx.Insert(mdl)

		mdl = NewLatestDataPeriod()
		mdl.Type = "Duration"
		mdl.ProjectName = projectName
		mdl.Data = availdatedata.Duration

		d.BaseController.Ctx.Insert(mdl)

		mdl = NewLatestDataPeriod()
		mdl.Type = "ScadaAnomaly"
		mdl.ProjectName = projectName
		mdl.Data = availdatedata.ScadaAnomaly

		d.BaseController.Ctx.Insert(mdl)

		mdl = NewLatestDataPeriod()
		mdl.Type = "AlarmOverlapping"
		mdl.ProjectName = projectName
		mdl.Data = availdatedata.AlarmOverlapping

		d.BaseController.Ctx.Insert(mdl)

		mdl = NewLatestDataPeriod()
		mdl.Type = "AlarmScadaAnomaly"
		mdl.ProjectName = projectName
		mdl.Data = availdatedata.AlarmScadaAnomaly

		d.BaseController.Ctx.Insert(mdl)

		mdl = NewLatestDataPeriod()
		mdl.Type = "ScadaDataHFD"
		mdl.ProjectName = projectName
		mdl.Data = availdatedata.ScadaDataHFD

		d.BaseController.Ctx.Insert(mdl)

		mdl = NewLatestDataPeriod()
		mdl.Type = "Warning"
		mdl.ProjectName = projectName
		mdl.Data = availdatedata.Warning

		d.BaseController.Ctx.Insert(mdl)

		mdl = NewLatestDataPeriod()
		mdl.Type = "ScadaDataOEM"
		mdl.ProjectName = projectName
		mdl.Data = availdatedata.ScadaDataOEM

		d.BaseController.Ctx.Insert(mdl)
	}

}

func getDataDateAvailable(conn dbox.IConnection, collectionName string, timestampColumn string, where *dbox.Filter) (min time.Time, max time.Time, err error) {
	q := conn.
		NewQuery().
		From(collectionName)

	if where != nil {
		q.Where(where)
	}

	csr, err := q.
		Aggr(dbox.AggrMin, "$"+timestampColumn, "min").
		Aggr(dbox.AggrMax, "$"+timestampColumn, "max").
		Group("enable").
		Cursor(nil)

	defer csr.Close()

	if err != nil {
		csr.Close()
		return
	}

	data := []toolkit.M{}
	err = csr.Fetch(&data, 0, false)

	if err != nil || len(data) == 0 {
		csr.Close()
		return
	}

	min = data[0].Get("min").(time.Time)
	max = data[0].Get("max").(time.Time)

	csr.Close()
	return
}
<commit_msg>bug fixing data available date for warning on summary generator<commit_after>package generatorControllers

import (
	. "eaciit/wfdemo-git/library/models"
	. "eaciit/wfdemo-git/processapp/summaryGenerator/controllers"
	"eaciit/wfdemo-git/web/helper"
	"os"
	"time"

	"github.com/eaciit/dbox"
	_ "github.com/eaciit/dbox/dbc/mongo"
	"github.com/eaciit/toolkit"
)

type GenDataPeriod struct {
	*BaseController
}

func (d *GenDataPeriod) Generate(base *BaseController) {
	d.BaseController = base
	conn, e := PrepareConnection()
	if e != nil {
		toolkit.Println("Scada Summary : " + e.Error())
		os.Exit(0)
	}

	// reset data
	// #faisal
	// remove this function
	d.BaseController.Ctx.DeleteMany(NewLatestDataPeriod(), dbox.Ne("projectname", ""))

	projects, _ := helper.GetProjectList()

	for _, proj := range projects {
		projectName := proj.Value
		scadaResults := make([]time.Time, 2)
		dgrResults := make([]time.Time, 2)
		alarmResults := make([]time.Time, 2)
		jmrResults := make([]time.Time, 2)
		metResults := make([]time.Time, 2)
		durationResults := make([]time.Time, 2)
		scadaAnomalyresults := make([]time.Time, 2)
		alarmOverlappingresults := make([]time.Time, 2)
		alarmScadaAnomalyresults := make([]time.Time, 2)
		scadaHFDResult := make([]time.Time, 2)
		warningResult := make([]time.Time, 2)
		scadaOEMResult := make([]time.Time, 2)

		scadaResults[0], scadaResults[1], e = getDataDateAvailable(conn, new(ScadaData).TableName(), "timestamp", dbox.Eq("projectname", projectName))
		dgrResults[0], dgrResults[1], e = getDataDateAvailable(conn, new(DGRModel).TableName(), "dateinfo.dateid", dbox.Eq("site", projectName))
		alarmResults[0], alarmResults[1], e = getDataDateAvailable(conn, new(Alarm).TableName(), "startdate", dbox.Eq("farm", projectName))
		alarmOverlappingresults[0], alarmOverlappingresults[1], e = getDataDateAvailable(conn, new(AlarmOverlapping).TableName(), "startdate", dbox.Eq("farm", projectName))
		alarmScadaAnomalyresults[0], alarmScadaAnomalyresults[1], e = getDataDateAvailable(conn, new(AlarmScadaAnomaly).TableName(), "startdate", dbox.Eq("farm", projectName))
		jmrResults[0], jmrResults[1], e = getDataDateAvailable(conn, new(ScadaData).TableName(), "dateinfo.dateid", dbox.Eq("projectname", projectName))
		metResults[0], metResults[1], e = getDataDateAvailable(conn, new(MetTower).TableName(), "timestamp", dbox.Eq("project", projectName))
		durationResults[0], durationResults[1], e = getDataDateAvailable(conn, new(ScadaData).TableName(), "timestamp", dbox.And(dbox.Eq("isvalidtimeduration", false), dbox.Eq("projectname", projectName)))
		scadaAnomalyresults[0], scadaAnomalyresults[1], e = getDataDateAvailable(conn, new(ScadaData).TableName(), "timestamp", dbox.And(dbox.Eq("isvalidtimeduration", true), dbox.Eq("projectname", projectName)))
		scadaHFDResult[0], scadaHFDResult[1], e = getDataDateAvailable(conn, new(ScadaDataHFD).TableName(), "timestamp", dbox.Eq("projectname", projectName))
		warningResult[0], warningResult[1], e = getDataDateAvailable(conn, new(EventAlarm).TableName(), "timestart", dbox.Eq("projectname", projectName))
		scadaOEMResult[0], scadaOEMResult[1], e = getDataDateAvailable(conn, new(ScadaDataOEM).TableName(), "timestamp", dbox.Eq("projectname", projectName))

		availdatedata := struct {
			ScadaData         []time.Time
			DGRData           []time.Time
			Alarm             []time.Time
			JMR               []time.Time
			MET               []time.Time
			Duration          []time.Time
			ScadaAnomaly      []time.Time
			AlarmOverlapping  []time.Time
			AlarmScadaAnomaly []time.Time
			ScadaDataHFD      []time.Time
			Warning           []time.Time
			ScadaDataOEM      []time.Time
		}{
			ScadaData:         scadaResults,
			DGRData:           dgrResults,
			Alarm:             alarmResults,
			JMR:               jmrResults,
			MET:               metResults,
			Duration:          durationResults,
			ScadaAnomaly:      scadaAnomalyresults,
			AlarmOverlapping:  alarmOverlappingresults,
			AlarmScadaAnomaly: alarmScadaAnomalyresults,
			ScadaDataHFD:      scadaHFDResult,
			Warning:           warningResult,
			ScadaDataOEM:      scadaOEMResult,
		}

		mdl := NewLatestDataPeriod()
		mdl.Type = "ScadaData"
		mdl.ProjectName = projectName
		mdl.Data = availdatedata.ScadaData

		d.BaseController.Ctx.Insert(mdl)

		mdl = NewLatestDataPeriod()
		mdl.Type = "DGRData"
		mdl.ProjectName = projectName
		mdl.Data = availdatedata.DGRData

		d.BaseController.Ctx.Insert(mdl)

		mdl = NewLatestDataPeriod()
		mdl.Type = "Alarm"
		mdl.ProjectName = projectName
		mdl.Data = availdatedata.Alarm

		d.BaseController.Ctx.Insert(mdl)

		mdl = NewLatestDataPeriod()
		mdl.Type = "JMR"
		mdl.ProjectName = projectName
		mdl.Data = availdatedata.JMR

		d.BaseController.Ctx.Insert(mdl)

		mdl = NewLatestDataPeriod()
		mdl.Type = "MET"
		mdl.ProjectName = projectName
		mdl.Data = availdatedata.MET

		d.BaseController.Ctx.Insert(mdl)

		mdl = NewLatestDataPeriod()
		mdl.Type = "Duration"
		mdl.ProjectName = projectName
		mdl.Data = availdatedata.Duration

		d.BaseController.Ctx.Insert(mdl)

		mdl = NewLatestDataPeriod()
		mdl.Type = "ScadaAnomaly"
		mdl.ProjectName = projectName
		mdl.Data = availdatedata.ScadaAnomaly

		d.BaseController.Ctx.Insert(mdl)

		mdl = NewLatestDataPeriod()
		mdl.Type = "AlarmOverlapping"
		mdl.ProjectName = projectName
		mdl.Data = availdatedata.AlarmOverlapping

		d.BaseController.Ctx.Insert(mdl)

		mdl = NewLatestDataPeriod()
		mdl.Type = "AlarmScadaAnomaly"
		mdl.ProjectName = projectName
		mdl.Data = availdatedata.AlarmScadaAnomaly

		d.BaseController.Ctx.Insert(mdl)

		mdl = NewLatestDataPeriod()
		mdl.Type = "ScadaDataHFD"
		mdl.ProjectName = projectName
		mdl.Data = availdatedata.ScadaDataHFD

		d.BaseController.Ctx.Insert(mdl)

		mdl = NewLatestDataPeriod()
		mdl.Type = "Warning"
		mdl.ProjectName = projectName
		mdl.Data = availdatedata.Warning

		d.BaseController.Ctx.Insert(mdl)

		mdl = NewLatestDataPeriod()
		mdl.Type = "ScadaDataOEM"
		mdl.ProjectName = projectName
		mdl.Data = availdatedata.ScadaDataOEM

		d.BaseController.Ctx.Insert(mdl)
	}

}

func getDataDateAvailable(conn dbox.IConnection, collectionName string, timestampColumn string, where *dbox.Filter) (min time.Time, max time.Time, err error) {
	q := conn.
		NewQuery().
		From(collectionName)

	if where != nil {
		q.Where(where)
	}

	csr, err := q.
		Aggr(dbox.AggrMin, "$"+timestampColumn, "min").
		Aggr(dbox.AggrMax, "$"+timestampColumn, "max").
		Group("enable").
		Cursor(nil)

	defer csr.Close()

	if err != nil {
		csr.Close()
		return
	}

	data := []toolkit.M{}
	err = csr.Fetch(&data, 0, false)

	if err != nil || len(data) == 0 {
		csr.Close()
		return
	}

	min = data[0].Get("min").(time.Time)
	max = data[0].Get("max").(time.Time)

	csr.Close()
	return
}
<|endoftext|>


<commit_before>package protein

const testVersion = 1

// FromCondon translates one RNA sequence to Proteins
func FromCodon(in string) string {
	var m map[string]string = map[string]string{
		"AUG": "Methionine",
		"UUU": "Phenylalanine",
		"UUC": "Phenylalanine",
		"UUA": "Leucine",
		"UUG": "Leucine",
		"UCU": "Serine",
		"UCC": "Serine",
		"UCA": "Serine",
		"UCG": "Serine",
		"UAU": "Tyrosine",
		"UAC": "Tyrosine",
		"UGU": "Cysteine",
		"UGC": "Cysteine",
		"UGG": "Tryptophan",
		"UAA": "STOP",
		"UAG": "STOP",
		"UGA": "STOP",
	}
	return m[in]
}

// FromRNA translates polypetides to a sequence of proteins
// stops if a STOP codon is read
func FromRNA(in string) (out []string) {
	for i := 0; i < len(in); i += 3 {
		cur := FromCodon(in[i : i+3])
		if cur == "STOP" {
			break
		}
		out = append(out, cur)
	}
	return out
}
<commit_msg>improved documentation<commit_after>package protein

const testVersion = 1

// FromCondon translates one RNA Codons to Proteins
func FromCodon(in string) string {
	var m map[string]string = map[string]string{
		"AUG": "Methionine",
		"UUU": "Phenylalanine",
		"UUC": "Phenylalanine",
		"UUA": "Leucine",
		"UUG": "Leucine",
		"UCU": "Serine",
		"UCC": "Serine",
		"UCA": "Serine",
		"UCG": "Serine",
		"UAU": "Tyrosine",
		"UAC": "Tyrosine",
		"UGU": "Cysteine",
		"UGC": "Cysteine",
		"UGG": "Tryptophan",
		"UAA": "STOP",
		"UAG": "STOP",
		"UGA": "STOP",
	}
	return m[in]
}

// FromRNA translates polypetides to a sequence of proteins
// stops if a STOP codon is read
func FromRNA(in string) (out []string) {
	for i := 0; i < len(in); i += 3 {
		cur := FromCodon(in[i : i+3])
		if cur == "STOP" {
			break
		}
		out = append(out, cur)
	}
	return out
}
<|endoftext|>


<commit_before>package gcss

import (
	"io/ioutil"
	"testing"
)

func Test_parse(t *testing.T) {
	data, err := ioutil.ReadFile("./test/1.gcss")
	if err != nil {
		t.Errorf("error occurred [error: %s]", err.Error())
	}

	elemsc, errc := parse(string(data))

	select {
	case <-elemsc:
	case <-errc:
		t.Errorf("error occurred [error: %s]", err.Error())
	}
}
<commit_msg>Update parse_test.go<commit_after>package gcss

import (
	"io/ioutil"
	"testing"
)

func Test_parse(t *testing.T) {
	data, err := ioutil.ReadFile("./test/1.gcss")
	if err != nil {
		t.Errorf("error occurred [error: %s]", err.Error())
	}

	elemsc, errc := parse(string(data))

	select {
	case <-elemsc:
	case <-errc:
		t.Errorf("error occurred [error: %s]", err.Error())
	}
}

func Test_formatLF(t *testing.T) {
	s := cr + crlf + lf + "a" + crlf + lf + cr + "b" + lf + cr + crlf
	expectedS := lf + lf + lf + "a" + lf + lf + lf + "b" + lf + lf + lf

	if formatLF(s) != expectedS {
		t.Errorf("formatLF(s) should be %s [actual: %s]", expectedS, formatLF(s))
	}
}
<|endoftext|>