<commit_before>// Copyright 2017 ibelie, Chen Jie, Joungtao. All rights reserved.
// Use of this source code is governed by The MIT License
// that can be found in the LICENSE file.

package rpc

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"path"
	"sort"
	"strings"

	"github.com/ibelie/rpc/strid"
	"github.com/ibelie/rpc/uuid"
	"github.com/ibelie/ruid"
	"github.com/ibelie/tygo"
)

var JSID_ZERO = []string{
	ruid.ZERO.String(),
	uuid.ZERO.String(),
	strid.ZERO.String(),
}

var JSID_REQUIRE = []string{
	"",
	"",
	`
	goog.require('ibelie.tyts.String');`,
}

var JSID_BYTESIZE = []func(string) string{
	func(value string) string {
		return fmt.Sprintf("8")
	},
	func(value string) string {
		return fmt.Sprintf("16")
	},
	func(value string) string {
		return fmt.Sprintf("ibelie.tyts.String.ByteSize(%s, 0, false)", value)
	},
}

var JSID_WRITE = []func(string, string) string{
	func(protobuf string, value string) string {
		return fmt.Sprintf("%s.WriteBase64(%s)", protobuf, value)
	},
	func(protobuf string, value string) string {
		return fmt.Sprintf("%s.WriteBase64(%s)", protobuf, value)
	},
	func(protobuf string, value string) string {
		return fmt.Sprintf("ibelie.tyts.String.Serialize(%s, 0, false, %s)", value, protobuf)
	},
}

var JSID_READ = []func(string) string{
	func(protobuf string) string {
		return fmt.Sprintf("%s.ReadBase64(8)", protobuf)
	},
	func(protobuf string) string {
		return fmt.Sprintf("%s.ReadBase64(16)", protobuf)
	},
	func(protobuf string) string {
		return fmt.Sprintf("ibelie.tyts.String.Deserialize(null, %s)", protobuf)
	},
}

func injectJavascript(identName string, dir string, entities []*Entity, behaviors []*Behavior) {
	ident := IDENT_FromString(identName)
	var buffer bytes.Buffer
	requireMap := make(map[string]bool)
	methodsMap := make(map[string]bool)

	var methods []string
	var entcodes []string
	for _, e := range entities {
		var components []string
		for _, c := range e.Components {
			if c.Protocol == nil {
				continue
			}

			m := tygo.JS_MODULE
			if m == "" {
				m = c.Protocol.Package
			}
			m = strings.Replace(m, "/", ".", -1)
			requireMap[fmt.Sprintf(`
goog.require('%s.%s');`, m, c.Name)] = true
			components = append(components, fmt.Sprintf(`
			_this.%s = new %s.%s();`, c.Name, m, c.Name))

			for _, m := range c.Protocol.Methods {
				if ok, exist := methodsMap[m.Name]; exist && ok {
					continue
				} else if len(m.Results) > 0 {
					continue
				}
				var params []string
				for i, _ := range m.Params {
					params = append(params, fmt.Sprintf("a%d", i))
				}
				localParams := append([]string{"v"}, params...)
				methods = append(methods, fmt.Sprintf(`
Entity.prototype['D_%s'] = function(data) {
	return ibelie.rpc['%s']['D_%sParam'](data);
};

Entity.prototype.%s = function(%s) {
	if (!this.isAwake) {
		console.warn('[Entity] Not awake:', this);
		return;
	}
	for (var k in this) {
		var v = this[k];
		v.%s && v.%s.call(%s);
	}
	var data = ibelie.rpc['%s']['S_%sParam'](%s);
	this.connection.send(this, this.connection.SymDict.%s, data);
};
`, m.Name, c.Name, m.Name, m.Name, strings.Join(params, ", "),
					m.Name, m.Name, strings.Join(localParams, ", "),
					c.Name, m.Name, strings.Join(params, ", "), m.Name))
				methodsMap[m.Name] = true
			}
		}

		var entBehaviors []string
		for _, b := range e.Behaviors {
			m := b.Name
			if b.Module != "" {
				m = b.Module + "." + b.Name
			}
			requireMap[fmt.Sprintf(`
goog.require('%s');`, m)] = true
			entBehaviors = append(entBehaviors, fmt.Sprintf(`
			%s,`, m))
		}
		sort.Strings(entBehaviors)

		entcodes = append(entcodes, fmt.Sprintf(`
	'%s': (function (_super) {
		__extends(%s, _super);
		function %s() {
			var _this = _super.call(this) || this;%s
			return _this;
		}
		%s.prototype.Behaviors = [%s
		];
		__reflect(%s.prototype, '%s');
		return %s;
	}(ibelie.rpc.Entity)),`, e.Name, e.Name, e.Name, strings.Join(components, ""),
			e.Name, strings.Join(entBehaviors, ""), e.Name, e.Name, e.Name))
	}

	for _, b := range behaviors {
		log.Println("behavior", b.Name, b.Entities)
	}

	var requires []string
	for require, ok := range requireMap {
		if ok {
			requires = append(requires, require)
		}
	}
	sort.Strings(requires)

	buffer.Write([]byte(fmt.Sprintf(`// Generated by ibelie-rpc.  DO NOT EDIT!

goog.provide('ibelie.rpc.entities');
goog.provide('ibelie.rpc.behaviors');
goog.provide('ibelie.rpc.Entity');
goog.provide('ibelie.rpc.Connection');
%s
goog.require('ibelie.tyts.ProtoBuf');
goog.require('ibelie.tyts.SizeVarint');
goog.require('ibelie.tyts.SymbolEncodedLen');%s

var ZERO_ID = %q;

var __reflect = (this && this.__reflect) || function (p, c, t) {
	p.__class__ = c, t ? t.push(c) : t = [c], p.__types__ = p.__types__ ? t.concat(p.__types__) : t;
};

var __extends = (this && this.__extends) || function (d, b) {
	for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	function __() { this.constructor = d; }
	d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};

ibelie.rpc.Entity = function() {
	this.__class__ = 'Entity';
	this.isAwake = false;
	this.ID = ZERO_ID;
	this.Key = ZERO_ID;
	this.Type = '';
};

ibelie.rpc.Entity.prototype.ByteSize = function() {
	var size = 1 + ibelie.tyts.SymbolEncodedLen(this.Type);
	if (this.ID != ZERO_ID) {
		size += %s;
	}
	if (this.Key != ZERO_ID) {
		size += %s;
	}
	return size;
};

ibelie.rpc.Entity.prototype.Serialize = function() {
	var protobuf = new ibelie.tyts.ProtoBuf(new Uint8Array(this.ByteSize()));
	var t = 0;
	if (this.ID != ZERO_ID) {
		t |= 1;
	}
	if (this.Key != ZERO_ID) {
		t |= 2;
	}
	protobuf.WriteByte(t);
	if (this.ID != ZERO_ID) {
		%s;
	}
	if (this.Key != ZERO_ID) {
		%s;
	}
	protobuf.EncodeSymbol(this.Type);
	return protobuf.buffer;
};

ibelie.rpc.Entity.prototype.Deserialize = function(data) {
	var protobuf = new ibelie.tyts.ProtoBuf(data);
	var t = protobuf.ReadByte();
	this.ID = (t & 1) ? %s : ZERO_ID;
	this.Key = (t & 2) ? %s : ZERO_ID;
	this.Type = protobuf.DecodeSymbol();
};

ibelie.rpc.Entity.prototype.Awake = function(e) {
	if (!e) {
		console.warn('[Entity] No entity:', e);
		return e;
	} else if (e.isAwake) {
		console.warn('[Entity] Already awaked:', e);
		return e;
	}
	var conn = this.connection;
	var entity = conn.entities[e.ID];
	if (entity) {
		return entity
	}
	entity = new ibelie.rpc.entities[e.Type]();
	entity.ID = e.ID;
	entity.Key = e.Key;
	entity.Type = e.Type;
	entity.connection = conn;
	conn.send(e, conn.SymDict.OBSERVE);
	conn.entities[entity.ID] = entity;
	return entity;
};

ibelie.rpc.Entity.prototype.Drop = function(e) {
	if (!e || !e.isAwake) {
		console.warn('[Entity] Not awaked:', e);
		return;
	}
	for (var k in e) {
		var v = e[k];
		v.onDrop && v.onDrop();
		if (v.Entity) {
			delete v.Entity;
		}
	}
	e.isAwake = false;
	var conn = this.connection;
	conn.send(e, conn.SymDict.IGNORE);
	delete conn.entities[e.ID];
	var entity = new Entity();
	entity.ID = e.ID;
	entity.Key = e.Key;
	entity.Type = e.Type;
	return entity;
};

ibelie.rpc.Connection = function(url) {
	var conn = this;
	var socket = new WebSocket(url);
	socket.onopen = function (event) {
		socket.onmessage = function(event) {
			var entity;
			var protobuf = ibelie.tyts.ProtoBuf.FromBase64(event.data);
			var id = %s;
			if (!conn.Symbols) {
				conn.Symbols = [];
				conn.SymDict = {};
				var buffer = new ibelie.tyts.ProtoBuf(protobuf.ReadBuffer());
				var value = 0;
				while (!buffer.End()) {
					var symbol = buffer.ReadSymbol();
					conn.Symbols = conn.Symbols.concat(symbol);
					conn.SymDict[symbol] = value;
					value++;
				}
				var key = %s;
				var t = conn.Symbols[protobuf.ReadVarint()];
				entity = new ibelie.rpc.entities[t]();
				entity.connection = conn;
				entity.ID = id;
				entity.Key = key;
				entity.Type = t;
				conn.entities[id] = entity;
			} else {
				entity = conn.entities[id];
				if (!entity) {
					console.error('[Connection] Cannot find entity:', id);
					return;
				}
			}
			while (!protobuf.End()) {
				var name = conn.Symbols[protobuf.ReadVarint()];
				var data = protobuf.ReadBuffer();
				if (ibelie.rpc[name]) {
					ibelie.rpc[name].prototype.Deserialize.call(entity[name], data);
				} else if (!entity.isAwake) {
					console.error('[Connection] Entity is not awake:', id, name, entity);
					continue;
				} else if (name == 'NOTIFY') {
					var buffer = new ibelie.tyts.ProtoBuf(data);
					var compName = conn.Symbols[buffer.ReadVarint()];
					var property = conn.Symbols[buffer.ReadVarint()];
					var newValue = ibelie.rpc[compName]['D_' + property](buffer.Bytes())[0];
					var component = entity[compName];
					var oldValue = component[property];
					var handler = component[property + 'Handler'];
					if (oldValue.concat) {
						component[property] = oldValue.concat(newValue);
						handler && handler.call(component, oldValue, newValue);
					} else if ((newValue instanceof Object) && !newValue.__class__) {
						if (!component[property]) {
							component[property] = {};
						}
						for (var k in newValue) {
							var o = oldValue[k];
							var n = newValue[k];
							oldValue[k] = n;
							handler && handler.call(component, k, o, n);
						}
					} else {
						component[property] = newValue;
						handler && handler.call(component, oldValue, newValue);
					}
				} else {
					var args = entity['D_' + name](data);
					for (var k in entity) {
						var v = entity[k];
						v[name] && v[name].apply(v, args);
					}
				}
			}
			if (entity && !entity.isAwake) {
				entity.isAwake = true;
				for (var k in entity) {
					var v = entity[k];
					v.onAwake && v.onAwake();
				}
			}
		};
		socket.onclose = function(event) {
			console.warn('[Connection] Socket has been closed:', event, conn);
		};
	};
	this.socket = socket;
	this.entities = {};
};

ibelie.rpc.Connection.prototype.send = function(entity, method, data) {
	var t = this.SymDict[entity.Type] << 2;
	var size = ibelie.tyts.SizeVarint(t) + ibelie.tyts.SizeVarint(method);
	if (entity.ID != ZERO_ID) {
		size += %s;
		t |= 1;
	}
	if (entity.Key != ZERO_ID) {
		size += %s;
		t |= 2;
	}
	if (data) {
		size += data.length;
	}
	var protobuf = new ibelie.tyts.ProtoBuf(new Uint8Array(size));
	protobuf.WriteVarint(t);
	if (entity.ID != ZERO_ID) {
		%s;
	}
	if (entity.Key != ZERO_ID) {
		%s;
	}
	protobuf.WriteVarint(method);
	if (data) {
		protobuf.WriteBytes(data);
	}
	this.socket.send(protobuf.ToBase64());
};

ibelie.rpc.Connection.prototype.disconnect = function() {
	this.socket.close();
};
%s
ibelie.rpc.entities = {%s
};
`, JSID_REQUIRE[ident], strings.Join(requires, ""), JSID_ZERO[ident],
		JSID_BYTESIZE[ident]("this.ID"), JSID_BYTESIZE[ident]("this.Key"),
		JSID_WRITE[ident]("protobuf", "this.ID"), JSID_WRITE[ident]("protobuf", "this.Key"),
		JSID_READ[ident]("protobuf"), JSID_READ[ident]("protobuf"),
		JSID_READ[ident]("protobuf"), JSID_READ[ident]("protobuf"),
		JSID_BYTESIZE[ident]("this.ID"), JSID_BYTESIZE[ident]("this.Key"),
		JSID_WRITE[ident]("protobuf", "entity.ID"), JSID_WRITE[ident]("protobuf", "entity.Key"),
		strings.Join(methods, ""), strings.Join(entcodes, ""))))

	ioutil.WriteFile(path.Join(dir, "rpc.js"), buffer.Bytes(), 0666)
}
<commit_msg>inject server message<commit_after>// Copyright 2017 ibelie, Chen Jie, Joungtao. All rights reserved.
// Use of this source code is governed by The MIT License
// that can be found in the LICENSE file.

package rpc

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"path"
	"sort"
	"strings"

	"github.com/ibelie/rpc/strid"
	"github.com/ibelie/rpc/uuid"
	"github.com/ibelie/ruid"
	"github.com/ibelie/tygo"
)

var JSID_ZERO = []string{
	ruid.ZERO.String(),
	uuid.ZERO.String(),
	strid.ZERO.String(),
}

var JSID_REQUIRE = []string{
	"",
	"",
	`
	goog.require('ibelie.tyts.String');`,
}

var JSID_BYTESIZE = []func(string) string{
	func(value string) string {
		return fmt.Sprintf("8")
	},
	func(value string) string {
		return fmt.Sprintf("16")
	},
	func(value string) string {
		return fmt.Sprintf("ibelie.tyts.String.ByteSize(%s, 0, false)", value)
	},
}

var JSID_WRITE = []func(string, string) string{
	func(protobuf string, value string) string {
		return fmt.Sprintf("%s.WriteBase64(%s)", protobuf, value)
	},
	func(protobuf string, value string) string {
		return fmt.Sprintf("%s.WriteBase64(%s)", protobuf, value)
	},
	func(protobuf string, value string) string {
		return fmt.Sprintf("ibelie.tyts.String.Serialize(%s, 0, false, %s)", value, protobuf)
	},
}

var JSID_READ = []func(string) string{
	func(protobuf string) string {
		return fmt.Sprintf("%s.ReadBase64(8)", protobuf)
	},
	func(protobuf string) string {
		return fmt.Sprintf("%s.ReadBase64(16)", protobuf)
	},
	func(protobuf string) string {
		return fmt.Sprintf("ibelie.tyts.String.Deserialize(null, %s)", protobuf)
	},
}

func injectJavascript(identName string, dir string, entities []*Entity, behaviors []*Behavior) {
	ident := IDENT_FromString(identName)
	var buffer bytes.Buffer
	requireMap := make(map[string]bool)
	methodsMap := make(map[string]bool)

	var methods []string
	var entcodes []string
	for _, e := range entities {
		var components []string
		for _, c := range e.Components {
			if c.Protocol == nil {
				continue
			}

			compModule := tygo.JS_MODULE
			if compModule == "" {
				compModule = c.Protocol.Package
			}
			compModule = strings.Replace(compModule, "/", ".", -1)
			requireMap[fmt.Sprintf(`
goog.require('%s.%s');`, compModule, c.Name)] = true
			components = append(components, fmt.Sprintf(`
			_this.%s = new %s.%s();`, c.Name, compModule, c.Name))

			for _, m := range c.Protocol.Methods {
				if ok, exist := methodsMap[m.Name]; exist && ok {
					continue
				} else if len(m.Results) > 0 {
					continue
				}
				var params []string
				for i, _ := range m.Params {
					params = append(params, fmt.Sprintf("a%d", i))
				}
				localParams := append([]string{"this"}, params...)
				methods = append(methods, fmt.Sprintf(`
Entity.prototype['D_%s'] = function(data) {
	return %s.%s['D_%sParam'](data);
};

Entity.prototype.%s = function(%s) {
	if (!this.isAwake) {
		console.warn('[Entity] Not awake:', this);
		return;
	}
	for (var b of this.Behaviors) {
		var m = b['%s'];
		m && m(%s);
	}
	var data = %s.%s['S_%sParam'](%s);
	this.connection.send(this, this.connection.SymDict['%s'], data);
};
`, m.Name, compModule, c.Name, m.Name, m.Name, strings.Join(params, ", "),
					m.Name, strings.Join(localParams, ", "),
					compModule, c.Name, m.Name, strings.Join(params, ", "), m.Name))
				methodsMap[m.Name] = true
			}
		}

		var entBehaviors []string
		for _, b := range e.Behaviors {
			m := b.Name
			if b.Module != "" {
				m = b.Module + "." + b.Name
			}
			requireMap[fmt.Sprintf(`
goog.require('%s');`, m)] = true
			entBehaviors = append(entBehaviors, fmt.Sprintf(`
			%s,`, m))
		}
		sort.Strings(entBehaviors)

		entcodes = append(entcodes, fmt.Sprintf(`
	'%s': (function (_super) {
		__extends(%s, _super);
		function %s() {
			var _this = _super.call(this) || this;%s
			return _this;
		}
		%s.prototype.Behaviors = [%s
		];
		__reflect(%s.prototype, '%s');
		return %s;
	}(ibelie.rpc.Entity)),`, e.Name, e.Name, e.Name, strings.Join(components, ""),
			e.Name, strings.Join(entBehaviors, ""), e.Name, e.Name, e.Name))
	}

	for _, b := range behaviors {
		log.Println("behavior", b.Name, b.Entities)
	}

	var requires []string
	for require, ok := range requireMap {
		if ok {
			requires = append(requires, require)
		}
	}
	sort.Strings(requires)

	buffer.Write([]byte(fmt.Sprintf(`// Generated by ibelie-rpc.  DO NOT EDIT!

goog.provide('ibelie.rpc.entities');
goog.provide('ibelie.rpc.behaviors');
goog.provide('ibelie.rpc.Entity');
goog.provide('ibelie.rpc.Connection');
%s
goog.require('ibelie.tyts.ProtoBuf');
goog.require('ibelie.tyts.SizeVarint');
goog.require('ibelie.tyts.SymbolEncodedLen');%s

var ZERO_ID = %q;

var __reflect = (this && this.__reflect) || function (p, c, t) {
	p.__class__ = c, t ? t.push(c) : t = [c], p.__types__ = p.__types__ ? t.concat(p.__types__) : t;
};

var __extends = (this && this.__extends) || function (d, b) {
	for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	function __() { this.constructor = d; }
	d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};

ibelie.rpc.Entity = function() {
	this.__class__ = 'Entity';
	this.isAwake = false;
	this.ID = ZERO_ID;
	this.Key = ZERO_ID;
	this.Type = '';
};

ibelie.rpc.Entity.prototype.ByteSize = function() {
	var size = 1 + ibelie.tyts.SymbolEncodedLen(this.Type);
	if (this.ID != ZERO_ID) {
		size += %s;
	}
	if (this.Key != ZERO_ID) {
		size += %s;
	}
	return size;
};

ibelie.rpc.Entity.prototype.Serialize = function() {
	var protobuf = new ibelie.tyts.ProtoBuf(new Uint8Array(this.ByteSize()));
	var t = 0;
	if (this.ID != ZERO_ID) {
		t |= 1;
	}
	if (this.Key != ZERO_ID) {
		t |= 2;
	}
	protobuf.WriteByte(t);
	if (this.ID != ZERO_ID) {
		%s;
	}
	if (this.Key != ZERO_ID) {
		%s;
	}
	protobuf.EncodeSymbol(this.Type);
	return protobuf.buffer;
};

ibelie.rpc.Entity.prototype.Deserialize = function(data) {
	var protobuf = new ibelie.tyts.ProtoBuf(data);
	var t = protobuf.ReadByte();
	this.ID = (t & 1) ? %s : ZERO_ID;
	this.Key = (t & 2) ? %s : ZERO_ID;
	this.Type = protobuf.DecodeSymbol();
};

ibelie.rpc.Entity.prototype.Awake = function(e) {
	if (!e) {
		console.warn('[Entity] No entity:', e);
		return e;
	} else if (e.isAwake) {
		console.warn('[Entity] Already awaked:', e);
		return e;
	}
	var conn = this.connection;
	var entity = conn.entities[e.ID];
	if (entity) {
		return entity
	}
	entity = new ibelie.rpc.entities[e.Type]();
	entity.ID = e.ID;
	entity.Key = e.Key;
	entity.Type = e.Type;
	entity.connection = conn;
	conn.send(e, conn.SymDict['OBSERVE']);
	conn.entities[entity.ID] = entity;
	return entity;
};

ibelie.rpc.Entity.prototype.Drop = function(e) {
	if (!e || !e.isAwake) {
		console.warn('[Entity] Not awaked:', e);
		return;
	}
	e.onDrop && e.onDrop();
	e.isAwake = false;
	var conn = this.connection;
	conn.send(e, conn.SymDict['IGNORE']);
	delete conn.entities[e.ID];
	var entity = new Entity();
	entity.ID = e.ID;
	entity.Key = e.Key;
	entity.Type = e.Type;
	return entity;
};

ibelie.rpc.Connection = function(url) {
	var conn = this;
	var socket = new WebSocket(url);
	socket.onopen = function (event) {
		socket.onmessage = function(event) {
			var entity;
			var protobuf = ibelie.tyts.ProtoBuf.FromBase64(event.data);
			var id = %s;
			if (!conn.Symbols) {
				conn.Symbols = [];
				conn.SymDict = {};
				var buffer = new ibelie.tyts.ProtoBuf(protobuf.ReadBuffer());
				var value = 0;
				while (!buffer.End()) {
					var symbol = buffer.ReadSymbol();
					conn.Symbols = conn.Symbols.concat(symbol);
					conn.SymDict[symbol] = value;
					value++;
				}
				var key = %s;
				var t = conn.Symbols[protobuf.ReadVarint()];
				entity = new ibelie.rpc.entities[t]();
				entity.connection = conn;
				entity.ID = id;
				entity.Key = key;
				entity.Type = t;
				conn.entities[id] = entity;
			} else {
				entity = conn.entities[id];
				if (!entity) {
					console.error('[Connection] Cannot find entity:', id);
					return;
				}
			}
			while (!protobuf.End()) {
				var name = conn.Symbols[protobuf.ReadVarint()];
				var data = protobuf.ReadBuffer();
				if (ibelie.rpc[name]) {
					ibelie.rpc[name].prototype.Deserialize.call(entity[name], data);
				} else if (!entity.isAwake) {
					console.error('[Connection] Entity is not awake:', id, name, entity);
					continue;
				} else if (name == 'NOTIFY') {
					var buffer = new ibelie.tyts.ProtoBuf(data);
					var compName = conn.Symbols[buffer.ReadVarint()];
					var property = conn.Symbols[buffer.ReadVarint()];
					var newValue = ibelie.rpc[compName]['D_' + property](buffer.Bytes())[0];
					var component = entity[compName];
					var oldValue = component[property];
					var handler = component[property + 'Handler'];
					if (oldValue.concat) {
						component[property] = oldValue.concat(newValue);
						handler && handler.call(component, oldValue, newValue);
					} else if ((newValue instanceof Object) && !newValue.__class__) {
						if (!component[property]) {
							component[property] = {};
						}
						for (var k in newValue) {
							var o = oldValue[k];
							var n = newValue[k];
							oldValue[k] = n;
							handler && handler.call(component, k, o, n);
						}
					} else {
						component[property] = newValue;
						handler && handler.call(component, oldValue, newValue);
					}
				} else {
					var args = entity['D_' + name](data);
					for (var k in entity) {
						var v = entity[k];
						v[name] && v[name].apply(v, args);
					}
				}
			}
			if (entity && !entity.isAwake) {
				entity.isAwake = true;
				entity.onAwake && entity.onAwake();
			}
		};
		socket.onclose = function(event) {
			console.warn('[Connection] Socket has been closed:', event, conn);
		};
	};
	this.socket = socket;
	this.entities = {};
};

ibelie.rpc.Connection.prototype.send = function(entity, method, data) {
	var t = this.SymDict[entity.Type] << 2;
	var size = ibelie.tyts.SizeVarint(t) + ibelie.tyts.SizeVarint(method);
	if (entity.ID != ZERO_ID) {
		size += %s;
		t |= 1;
	}
	if (entity.Key != ZERO_ID) {
		size += %s;
		t |= 2;
	}
	if (data) {
		size += data.length;
	}
	var protobuf = new ibelie.tyts.ProtoBuf(new Uint8Array(size));
	protobuf.WriteVarint(t);
	if (entity.ID != ZERO_ID) {
		%s;
	}
	if (entity.Key != ZERO_ID) {
		%s;
	}
	protobuf.WriteVarint(method);
	if (data) {
		protobuf.WriteBytes(data);
	}
	this.socket.send(protobuf.ToBase64());
};

ibelie.rpc.Connection.prototype.disconnect = function() {
	this.socket.close();
};
%s
ibelie.rpc.entities = {%s
};
`, JSID_REQUIRE[ident], strings.Join(requires, ""), JSID_ZERO[ident],
		JSID_BYTESIZE[ident]("this.ID"), JSID_BYTESIZE[ident]("this.Key"),
		JSID_WRITE[ident]("protobuf", "this.ID"), JSID_WRITE[ident]("protobuf", "this.Key"),
		JSID_READ[ident]("protobuf"), JSID_READ[ident]("protobuf"),
		JSID_READ[ident]("protobuf"), JSID_READ[ident]("protobuf"),
		JSID_BYTESIZE[ident]("this.ID"), JSID_BYTESIZE[ident]("this.Key"),
		JSID_WRITE[ident]("protobuf", "entity.ID"), JSID_WRITE[ident]("protobuf", "entity.Key"),
		strings.Join(methods, ""), strings.Join(entcodes, ""))))

	ioutil.WriteFile(path.Join(dir, "rpc.js"), buffer.Bytes(), 0666)
}
<|endoftext|>


<commit_before>package model

import (
	"encoding/json"
	"fmt"

	"github.com/Shopify/sarama"
	"github.com/funkygao/dbus/engine"
)

var (
	_ engine.Payloader = &RowsEvent{}
	_ sarama.Encoder   = &RowsEvent{}
)

// RowsEvent is a structured mysql binlog rows event.
// It implements engine.Payloader interface and can be transferred between plugins.
type RowsEvent struct {
	Log       string `json:"log"`
	Position  uint32 `json:"pos"`
	Schema    string `json:"db"`
	Table     string `json:"tbl"`
	Action    string `json:"dml"`
	Timestamp uint32 `json:"ts"`

	// binlog has three update event version, v0, v1 and v2.
	// for v1 and v2, the rows number must be even.
	// Two rows for one event, format is [before update row, after update row]
	// for update v0, only one row for a event, and we don't support this version.
	Rows [][]interface{} `json:"rows"`
}

// Implements engine.Payloader.
func (r *RowsEvent) String() string {
	return fmt.Sprintf("%s %d %d %s %s/%s %+v", r.Log, r.Position, r.Timestamp, r.Action, r.Schema, r.Table, r.Rows)
}

// Implements engine.Payloader and sarama.Encoder.
func (r *RowsEvent) Encode() ([]byte, error) {
	return json.Marshal(r)
}

// Implements engine.Payloader and sarama.Encoder.
func (r *RowsEvent) Length() int {
	return len(r.Log) + len(r.Schema) + len(r.Table) + 9 // FIXME Rows not counted
}
<commit_msg>RowEvent has correct length<commit_after>package model

import (
	"encoding/json"
	"fmt"

	"github.com/Shopify/sarama"
	"github.com/funkygao/dbus/engine"
)

var (
	_ engine.Payloader = &RowsEvent{}
	_ sarama.Encoder   = &RowsEvent{}
)

// RowsEvent is a structured mysql binlog rows event.
// It implements engine.Payloader interface and can be transferred between plugins.
type RowsEvent struct {
	Log       string `json:"log"`
	Position  uint32 `json:"pos"`
	Schema    string `json:"db"`
	Table     string `json:"tbl"`
	Action    string `json:"dml"`
	Timestamp uint32 `json:"ts"`

	// binlog has three update event version, v0, v1 and v2.
	// for v1 and v2, the rows number must be even.
	// Two rows for one event, format is [before update row, after update row]
	// for update v0, only one row for a event, and we don't support this version.
	Rows [][]interface{} `json:"rows"`

	bytes []byte
}

// Implements engine.Payloader.
func (r *RowsEvent) String() string {
	return fmt.Sprintf("%s %d %d %s %s/%s %+v", r.Log, r.Position, r.Timestamp, r.Action, r.Schema, r.Table, r.Rows)
}

// Implements engine.Payloader and sarama.Encoder.
func (r *RowsEvent) Encode() ([]byte, error) {
	if len(r.bytes) > 0 {
		return r.bytes, nil
	}

	return json.Marshal(r)
}

// Implements engine.Payloader and sarama.Encoder.
func (r *RowsEvent) Length() int {
	if len(r.bytes) == 0 {
		r.bytes, _ = json.Marshal(r)
	}

	return len(r.bytes)
}
<|endoftext|>


<commit_before>/**
 * Tests for OpenSimplex noise, based on the output of
 * the Java implementation.
 *
 * All reference samples were rendered with the default seed (0). Each version
 * of the noise function (2D, 3D and 4D) was run to output 2D samples slicing
 * across two of the function's axes. There is one 2D slice, three 3D slices
 * and 6 4D slices; the 3D slices each pin one axis to the value 3.8; 4D slices
 * pin one axis (the first in the filename) to 3.8 and the second to 2.7. These
 * values were chosen arbitrarily.
 *
 * Each sample is a 512x512 greyscale PNG; each pixel is 1/24 wide in the
 * OpenSimplex's space -- i.e. pixel (24, 24) in the 2D noise sample was
 * computed by evaluating the 2D noise at (1.0, 1.0) and converting from a [-1,
 * +1] scale to [0, +1].
 */
package noise

import (
	"compress/gzip"
	"encoding/json"
	"io"
	"os"
	"path"
	"testing"
)

func loadSamples() <-chan []float64 {
	c := make(chan []float64)
	go func() {
		f, err := os.Open(path.Join("test_files", "samples.json.gz"))
		if err != nil {
			panic(err.Error())
		}
		defer f.Close()

		gz, err := gzip.NewReader(f)
		if err != nil {
			panic(err.Error())
		}

		dec := json.NewDecoder(gz)
		for {
			var sample []float64
			if err := dec.Decode(&sample); err == io.EOF {
				break
			} else if err != nil {
				panic(err.Error())
			} else {
				c <- sample
			}
		}
		close(c)
	}()

	return c
}

const nearlyEqualEpsilon = 0.000000000001

func nearlyEqual(a, b float64) (bool, float64) {
	return a == b, 0
}

func TestSamplesMatch(t *testing.T) {
	samples := loadSamples()
	n := NewOpenSimplexWithSeed(0)

	for s := range samples {
		var expected, actual float64
		switch len(s) {
		case 3:
			expected = s[2]
			actual = n.Eval2(s[0], s[1])
		case 4:
			expected = s[3]
			actual = n.Eval3(s[0], s[1], s[2])
		case 5:
			expected = s[4]
			actual = n.Eval4(s[0], s[1], s[2], s[3])
		default:
			t.Fatalf("Unexpected size sample: %d", len(s))
		}

		if expected != actual {
			t.Fatalf("Expected %v, got %v for %dD sample at %v",
				expected, actual, len(s)-1, s[:len(s)-1])
		}
	}
}
<commit_msg>Remove unused epsilon-based float64 compare fn<commit_after>/**
 * Tests for OpenSimplex noise, based on the output of
 * the Java implementation.
 *
 * All reference samples were rendered with the default seed (0). Each version
 * of the noise function (2D, 3D and 4D) was run to output 2D samples slicing
 * across two of the function's axes. There is one 2D slice, three 3D slices
 * and 6 4D slices; the 3D slices each pin one axis to the value 3.8; 4D slices
 * pin one axis (the first in the filename) to 3.8 and the second to 2.7. These
 * values were chosen arbitrarily.
 *
 * Each sample is a 512x512 greyscale PNG; each pixel is 1/24 wide in the
 * OpenSimplex's space -- i.e. pixel (24, 24) in the 2D noise sample was
 * computed by evaluating the 2D noise at (1.0, 1.0) and converting from a [-1,
 * +1] scale to [0, +1].
 */
package noise

import (
	"compress/gzip"
	"encoding/json"
	"io"
	"os"
	"path"
	"testing"
)

func loadSamples() <-chan []float64 {
	c := make(chan []float64)
	go func() {
		f, err := os.Open(path.Join("test_files", "samples.json.gz"))
		if err != nil {
			panic(err.Error())
		}
		defer f.Close()

		gz, err := gzip.NewReader(f)
		if err != nil {
			panic(err.Error())
		}

		dec := json.NewDecoder(gz)
		for {
			var sample []float64
			if err := dec.Decode(&sample); err == io.EOF {
				break
			} else if err != nil {
				panic(err.Error())
			} else {
				c <- sample
			}
		}
		close(c)
	}()

	return c
}

func TestSamplesMatch(t *testing.T) {
	samples := loadSamples()
	n := NewOpenSimplexWithSeed(0)

	for s := range samples {
		var expected, actual float64
		switch len(s) {
		case 3:
			expected = s[2]
			actual = n.Eval2(s[0], s[1])
		case 4:
			expected = s[3]
			actual = n.Eval3(s[0], s[1], s[2])
		case 5:
			expected = s[4]
			actual = n.Eval4(s[0], s[1], s[2], s[3])
		default:
			t.Fatalf("Unexpected size sample: %d", len(s))
		}

		if expected != actual {
			t.Fatalf("Expected %v, got %v for %dD sample at %v",
				expected, actual, len(s)-1, s[:len(s)-1])
		}
	}
}
<|endoftext|>


<commit_before>package cmd

import (
	"log"
	"x/glog"

	"golang.org/x/net/context"

	"github.com/codegangsta/cli"
	"github.com/crackcomm/ovh"
)

var cmdAuth = cli.Command{
	Name:  "auth",
	Usage: "requests authentication",
	Action: func(c *cli.Context) {
		resp, err := client(c).Authenticate(context.Background())
		if err != nil {
			log.Fatal(err)
		}

		glog.Infof("Validate token: %s", resp.ValidationURL)
		glog.Infof("export OVH_CONSUMER_KEY=%q", resp.ConsumerKey)
	},
}

func client(c *cli.Context) *ovh.Client {
	return ovh.New(&ovh.Options{
		AppKey:      c.GlobalString("app-key"),
		AppSecret:   c.GlobalString("app-secret"),
		ConsumerKey: c.GlobalString("consumer-key"),
	})
}
<commit_msg>Fix log<commit_after>package cmd

import (
	"log"

	"golang.org/x/net/context"

	"github.com/codegangsta/cli"
	"github.com/crackcomm/ovh"
)

var cmdAuth = cli.Command{
	Name:  "auth",
	Usage: "requests authentication",
	Action: func(c *cli.Context) {
		resp, err := client(c).Authenticate(context.Background())
		if err != nil {
			log.Fatal(err)
		}

		log.Printf("Validate token: %s", resp.ValidationURL)
		log.Printf("export OVH_CONSUMER_KEY=%q", resp.ConsumerKey)
	},
}

func client(c *cli.Context) *ovh.Client {
	return ovh.New(&ovh.Options{
		AppKey:      c.GlobalString("app-key"),
		AppSecret:   c.GlobalString("app-secret"),
		ConsumerKey: c.GlobalString("consumer-key"),
	})
}
<|endoftext|>


<commit_before>package daemon

import (
	"bufio"
	"fmt"
	"github.com/subgraph/oz"
	"github.com/subgraph/oz/fs"
	"github.com/subgraph/oz/xpra"
	"io"
	"os"
	"os/exec"
	"os/user"
	"path"
	"sync"
	"syscall"
)

const initPath = "/usr/local/bin/oz-init"

type Sandbox struct {
	daemon  *daemonState
	id      int
	display int
	profile *oz.Profile
	init    *exec.Cmd
	cred    *syscall.Credential
	fs      *fs.Filesystem
	stderr  io.ReadCloser
	addr    string
	xpra    *xpra.Xpra
	ready   sync.WaitGroup
}

/*
func findSandbox(id int) *Sandbox {
	for _, sb := range sandboxes {
		if sb.id == id {
			return sb
		}
	}
	return nil
}
*/
const initCloneFlags = syscall.CLONE_NEWNS | syscall.CLONE_NEWIPC | syscall.CLONE_NEWPID | syscall.CLONE_NEWUTS | syscall.CLONE_NEWNET

func createInitCommand(name, chroot string, uid uint32, display int) *exec.Cmd {
	cmd := exec.Command(initPath)
	cmd.Dir = "/"
	cmd.SysProcAttr = &syscall.SysProcAttr{
		Chroot:     chroot,
		Cloneflags: initCloneFlags,
	}
	cmd.Env = []string{
		"INIT_PROFILE=" + name,
		fmt.Sprintf("INIT_UID=%d", uid),
	}
	if display > 0 {
		cmd.Env = append(cmd.Env, fmt.Sprintf("INIT_DISPLAY=%d", display))
	}
	return cmd
}

func (d *daemonState) launch(p *oz.Profile, uid, gid uint32) (*Sandbox, error) {
	u, err := user.LookupId(fmt.Sprintf("%d", uid))
	if err != nil {
		return nil, fmt.Errorf("failed to lookup user for uid=%d: %v", uid, err)
	}
	fs := fs.NewFromProfile(p, u, d.config.SandboxPath, d.log)
	if err := fs.Setup(); err != nil {
		return nil, err
	}
	display := 0
	if p.XServer.Enabled {
		display = d.nextDisplay
		d.nextDisplay += 1
	}

	cmd := createInitCommand(p.Name, fs.Root(), uid, display)
	pp, err := cmd.StderrPipe()
	if err != nil {
		fs.Cleanup()
		return nil, fmt.Errorf("error creating stderr pipe for init process: %v", err)

	}
	if err := cmd.Start(); err != nil {
		fs.Cleanup()
		return nil, err
	}
	sbox := &Sandbox{
		daemon:  d,
		id:      d.nextSboxId,
		display: display,
		profile: p,
		init:    cmd,
		cred:    &syscall.Credential{Uid: uid, Gid: gid},
		fs:      fs,
		addr:    path.Join(fs.Root(), "tmp", "oz-init-control"),
		stderr:  pp,
	}
	sbox.ready.Add(1)
	go sbox.logMessages()
	if sbox.profile.XServer.Enabled {
		go func() {
			sbox.ready.Wait()
			go sbox.startXpraClient()
		}()
	}
	d.nextSboxId += 1
	d.sandboxes = append(d.sandboxes, sbox)
	return sbox, nil
}

func (sbox *Sandbox) remove() {
	sboxes := []*Sandbox{}
	for _, sb := range sbox.daemon.sandboxes {
		if sb == sbox {
			sb.fs.Cleanup()
		} else {
			sboxes = append(sboxes, sb)
		}
	}
	sbox.daemon.sandboxes = sboxes
}

func (sbox *Sandbox) logMessages() {
	scanner := bufio.NewScanner(sbox.stderr)
	seenOk := false
	for scanner.Scan() {
		line := scanner.Text()
		if line == "OK" && !seenOk {
			sbox.daemon.log.Info("oz-init (%s) is ready", sbox.profile.Name)
			seenOk = true
			sbox.ready.Done()
		} else if len(line) > 1 {
			sbox.logLine(line)
		}
	}
	sbox.stderr.Close()
}

func (sbox *Sandbox) logLine(line string) {
	if len(line) < 2 {
		return
	}
	f := sbox.getLogFunc(line[0])
	msg := line[2:]
	if f != nil {
		f("[%s] %s", sbox.profile.Name, msg)
	} else {
		sbox.daemon.log.Info("[%s] %s", sbox.profile.Name, line)
	}
}

func (sbox *Sandbox) getLogFunc(c byte) func(string, ...interface{}) {
	log := sbox.daemon.log
	switch c {
	case 'D':
		return log.Debug
	case 'I':
		return log.Info
	case 'N':
		return log.Notice
	case 'W':
		return log.Warning
	case 'E':
		return log.Error
	case 'C':
		return log.Critical
	}
	return nil
}

func (sbox *Sandbox) startXpraClient() {
	sbox.xpra = xpra.NewClient(
		&sbox.profile.XServer,
		uint64(sbox.display),
		sbox.cred,
		sbox.fs.Xpra(),
		sbox.profile.Name,
		sbox.daemon.log)
	sbox.xpra.Process.Stdout = os.Stdout
	sbox.xpra.Process.Stderr = os.Stdout
	if err := sbox.xpra.Process.Start(); err != nil {
		sbox.daemon.Warning("Failed to start xpra client: %v", err)
	}
}
<commit_msg>log xpra client output instead of dumping it to stdout<commit_after>package daemon

import (
	"bufio"
	"fmt"
	"github.com/subgraph/oz"
	"github.com/subgraph/oz/fs"
	"github.com/subgraph/oz/xpra"
	"io"
	"os/exec"
	"os/user"
	"path"
	"sync"
	"syscall"
)

const initPath = "/usr/local/bin/oz-init"

type Sandbox struct {
	daemon  *daemonState
	id      int
	display int
	profile *oz.Profile
	init    *exec.Cmd
	cred    *syscall.Credential
	fs      *fs.Filesystem
	stderr  io.ReadCloser
	addr    string
	xpra    *xpra.Xpra
	ready   sync.WaitGroup
}

/*
func findSandbox(id int) *Sandbox {
	for _, sb := range sandboxes {
		if sb.id == id {
			return sb
		}
	}
	return nil
}
*/
const initCloneFlags = syscall.CLONE_NEWNS | syscall.CLONE_NEWIPC | syscall.CLONE_NEWPID | syscall.CLONE_NEWUTS | syscall.CLONE_NEWNET

func createInitCommand(name, chroot string, uid uint32, display int) *exec.Cmd {
	cmd := exec.Command(initPath)
	cmd.Dir = "/"
	cmd.SysProcAttr = &syscall.SysProcAttr{
		Chroot:     chroot,
		Cloneflags: initCloneFlags,
	}
	cmd.Env = []string{
		"INIT_PROFILE=" + name,
		fmt.Sprintf("INIT_UID=%d", uid),
	}
	if display > 0 {
		cmd.Env = append(cmd.Env, fmt.Sprintf("INIT_DISPLAY=%d", display))
	}
	return cmd
}

func (d *daemonState) launch(p *oz.Profile, uid, gid uint32) (*Sandbox, error) {
	u, err := user.LookupId(fmt.Sprintf("%d", uid))
	if err != nil {
		return nil, fmt.Errorf("failed to lookup user for uid=%d: %v", uid, err)
	}
	fs := fs.NewFromProfile(p, u, d.config.SandboxPath, d.log)
	if err := fs.Setup(); err != nil {
		return nil, err
	}
	display := 0
	if p.XServer.Enabled {
		display = d.nextDisplay
		d.nextDisplay += 1
	}

	cmd := createInitCommand(p.Name, fs.Root(), uid, display)
	pp, err := cmd.StderrPipe()
	if err != nil {
		fs.Cleanup()
		return nil, fmt.Errorf("error creating stderr pipe for init process: %v", err)

	}
	if err := cmd.Start(); err != nil {
		fs.Cleanup()
		return nil, err
	}
	sbox := &Sandbox{
		daemon:  d,
		id:      d.nextSboxId,
		display: display,
		profile: p,
		init:    cmd,
		cred:    &syscall.Credential{Uid: uid, Gid: gid},
		fs:      fs,
		addr:    path.Join(fs.Root(), "tmp", "oz-init-control"),
		stderr:  pp,
	}
	sbox.ready.Add(1)
	go sbox.logMessages()
	if sbox.profile.XServer.Enabled {
		go func() {
			sbox.ready.Wait()
			go sbox.startXpraClient()
		}()
	}
	d.nextSboxId += 1
	d.sandboxes = append(d.sandboxes, sbox)
	return sbox, nil
}

func (sbox *Sandbox) remove() {
	sboxes := []*Sandbox{}
	for _, sb := range sbox.daemon.sandboxes {
		if sb == sbox {
			sb.fs.Cleanup()
		} else {
			sboxes = append(sboxes, sb)
		}
	}
	sbox.daemon.sandboxes = sboxes
}

func (sbox *Sandbox) logMessages() {
	scanner := bufio.NewScanner(sbox.stderr)
	seenOk := false
	for scanner.Scan() {
		line := scanner.Text()
		if line == "OK" && !seenOk {
			sbox.daemon.log.Info("oz-init (%s) is ready", sbox.profile.Name)
			seenOk = true
			sbox.ready.Done()
		} else if len(line) > 1 {
			sbox.logLine(line)
		}
	}
	sbox.stderr.Close()
}

func (sbox *Sandbox) logLine(line string) {
	if len(line) < 2 {
		return
	}
	f := sbox.getLogFunc(line[0])
	msg := line[2:]
	if f != nil {
		f("[%s] %s", sbox.profile.Name, msg)
	} else {
		sbox.daemon.log.Info("[%s] %s", sbox.profile.Name, line)
	}
}

func (sbox *Sandbox) getLogFunc(c byte) func(string, ...interface{}) {
	log := sbox.daemon.log
	switch c {
	case 'D':
		return log.Debug
	case 'I':
		return log.Info
	case 'N':
		return log.Notice
	case 'W':
		return log.Warning
	case 'E':
		return log.Error
	case 'C':
		return log.Critical
	}
	return nil
}

func (sbox *Sandbox) startXpraClient() {
	sbox.xpra = xpra.NewClient(
		&sbox.profile.XServer,
		uint64(sbox.display),
		sbox.cred,
		sbox.fs.Xpra(),
		sbox.profile.Name,
		sbox.daemon.log)

	if sbox.daemon.config.LogXpra {
		sbox.setupXpraLogging()
	}
	if err := sbox.xpra.Process.Start(); err != nil {
		sbox.daemon.Warning("Failed to start xpra client: %v", err)
	}
}

func (sbox *Sandbox) setupXpraLogging() {
	stdout,err := sbox.xpra.Process.StdoutPipe()
	if err != nil {
		sbox.daemon.Warning("Failed to create xpra stdout pipe: %v", err)
		return
	}
	stderr,err := sbox.xpra.Process.StderrPipe()
	if err != nil {
		stdout.Close()
		sbox.daemon.Warning("Failed to create xpra stderr pipe: %v", err)
	}
	go sbox.logPipeOutput(stdout, "xpra-stdout")
	go sbox.logPipeOutput(stderr, "xpra-stderr")
}

func (sbox *Sandbox) logPipeOutput(p io.Reader, label string) {
	scanner := bufio.NewScanner(p)
	for scanner.Scan() {
		line := scanner.Text()
		sbox.daemon.log.Info("(%s) %s", label, line)
	}
}
<|endoftext|>


<commit_before>package daemon

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"os/exec"
	"os/user"
	"path"
	"path/filepath"
	"sync"
	"syscall"

	"github.com/subgraph/oz"
	"github.com/subgraph/oz/fs"
	"github.com/subgraph/oz/network"
	"github.com/subgraph/oz/xpra"
	"github.com/subgraph/oz/oz-init"

	"github.com/op/go-logging"
)

type Sandbox struct {
	daemon  *daemonState
	id      int
	display int
	profile *oz.Profile
	init    *exec.Cmd
	cred    *syscall.Credential
	fs      *fs.Filesystem
	stderr  io.ReadCloser
	addr    string
	xpra    *xpra.Xpra
	ready   sync.WaitGroup
	network *network.SandboxNetwork
}

func createInitCommand(initPath, name, chroot string, env []string, uid uint32, display int, stn *network.SandboxNetwork) *exec.Cmd {
	cmd := exec.Command(initPath)
	cmd.Dir = "/"

	cloneFlags := uintptr(syscall.CLONE_NEWNS)
	cloneFlags |= syscall.CLONE_NEWIPC
	cloneFlags |= syscall.CLONE_NEWPID
	cloneFlags |= syscall.CLONE_NEWUTS

	if stn.Nettype != network.TYPE_HOST {
		cloneFlags |= syscall.CLONE_NEWNET
	}

	cmd.SysProcAttr = &syscall.SysProcAttr{
		Chroot:     chroot,
		Cloneflags: cloneFlags,
	}
	cmd.Env = []string{
		"INIT_PROFILE=" + name,
		fmt.Sprintf("INIT_UID=%d", uid),
	}

	if stn.Ip != "" {
		cmd.Env = append(cmd.Env, "INIT_ADDR="+stn.Ip)
		cmd.Env = append(cmd.Env, "INIT_VHOST="+stn.VethHost)
		cmd.Env = append(cmd.Env, "INIT_VGUEST="+stn.VethGuest)
		cmd.Env = append(cmd.Env, "INIT_GATEWAY="+stn.Gateway.String()+"/"+stn.Class)
	}

	cmd.Env = append(cmd.Env, fmt.Sprintf("INIT_DISPLAY=%d", display))

	for _, e := range env {
		cmd.Env = append(cmd.Env, ozinit.EnvPrefix+e)
	}

	return cmd
}

func (d *daemonState) launch(p *oz.Profile, msg *LaunchMsg, uid, gid uint32, log *logging.Logger) (*Sandbox, error) {
	u, err := user.LookupId(fmt.Sprintf("%d", uid))
	if err != nil {
		return nil, fmt.Errorf("failed to lookup user for uid=%d: %v", uid, err)
	}
	fs := fs.NewFromProfile(p, u, d.config.SandboxPath, d.config.UseFullDev, d.log)
	if err := fs.Setup(d.config.ProfileDir); err != nil {
		return nil, err
	}
	display := 0
	if p.XServer.Enabled && p.Networking.Nettype == network.TYPE_HOST {
		display = d.nextDisplay
		d.nextDisplay += 1
	}

	stn := new(network.SandboxNetwork)
	stn.Nettype = p.Networking.Nettype
	if p.Networking.Nettype == network.TYPE_BRIDGE {
		stn, err = network.PrepareSandboxNetwork(d.network, log)
		if err != nil {
			return nil, fmt.Errorf("Unable to prepare veth network: %+v", err)
		}
	}

	cmd := createInitCommand(d.config.InitPath, p.Name, fs.Root(), msg.Env, uid, display, stn)
	log.Debug("Command environment: %+v", cmd.Env)
	pp, err := cmd.StderrPipe()
	if err != nil {
		fs.Cleanup()
		return nil, fmt.Errorf("error creating stderr pipe for init process: %v", err)

	}

	if err := cmd.Start(); err != nil {
		fs.Cleanup()
		return nil, fmt.Errorf("Unable to start process: %+v", err)
	}

	sbox := &Sandbox{
		daemon:  d,
		id:      d.nextSboxId,
		display: display,
		profile: p,
		init:    cmd,
		cred:    &syscall.Credential{Uid: uid, Gid: gid},
		fs:      fs,
		addr:    path.Join(fs.Root(), ozinit.SocketAddress),
		stderr:  pp,
		network: stn,
	}

	wgNet := new(sync.WaitGroup)
	if p.Networking.Nettype == network.TYPE_BRIDGE {
		defer wgNet.Done()
		wgNet.Add(1)
		if err := network.NetInit(stn, d.network, cmd.Process.Pid, log); err != nil {
			cmd.Process.Kill()
			fs.Cleanup()
			return nil, fmt.Errorf("Unable to create veth networking: %+v", err)
		}
	}

	sbox.ready.Add(1)
	go sbox.logMessages()

	if p.Networking.Nettype != network.TYPE_HOST && len(p.Networking.Sockets) > 0 {
		go func() {
			defer wgNet.Done()
			wgNet.Add(1)
			sbox.ready.Wait()
			err := network.ProxySetup(sbox.init.Process.Pid, p.Networking.Sockets, d.log, sbox.ready)
			if err != nil {
				log.Warning("Unable to create connection proxy: %+s", err)
			}
		}()
	}

	if !msg.Noexec {
		go func () {
			sbox.ready.Wait()
			wgNet.Wait()
			go sbox.launchProgram(msg.Path, msg.Pwd, msg.Args, log)
		}()
	}

	if sbox.profile.XServer.Enabled {
		go func() {
			sbox.ready.Wait()
			go sbox.startXpraClient()
		}()
	}

	d.nextSboxId += 1
	d.sandboxes = append(d.sandboxes, sbox)
	return sbox, nil
}

func (sbox *Sandbox) launchProgram(cpath, pwd string, args []string, log *logging.Logger) {
	if sbox.profile.AllowFiles {
		for _, fpath := range args {
			if _, err := os.Stat(fpath); err == nil {
				if filepath.IsAbs(fpath) == false {
					fpath = path.Join(pwd, fpath)
				}
				log.Info("Adding file `%s` to sandbox `%s`.", fpath, sbox.profile.Name)
				if err := sbox.fs.AddBindWhitelist(fpath, fpath, false); err != nil {
					log.Warning("Error adding file `%s`!", fpath)
				}
			}
		}
	}

	err := ozinit.RunProgram(sbox.addr, cpath, pwd, args)
	if err != nil {
		log.Error("start shell command failed: %v", err)
	}
}

func (sbox *Sandbox) remove(log *logging.Logger) {
	sboxes := []*Sandbox{}
	for _, sb := range sbox.daemon.sandboxes {
		if sb == sbox {
			sb.fs.Cleanup()
			if sb.profile.Networking.Nettype == network.TYPE_BRIDGE {
				sb.network.Cleanup(log)
			}
		} else {
			sboxes = append(sboxes, sb)
		}
	}
	sbox.daemon.sandboxes = sboxes
}

func (sbox *Sandbox) logMessages() {
	scanner := bufio.NewScanner(sbox.stderr)
	seenOk := false
	for scanner.Scan() {
		line := scanner.Text()
		if line == "OK" && !seenOk {
			sbox.daemon.log.Info("oz-init (%s) is ready", sbox.profile.Name)
			seenOk = true
			sbox.ready.Done()
		} else if len(line) > 1 {
			sbox.logLine(line)
		}
	}
	sbox.stderr.Close()
}

func (sbox *Sandbox) logLine(line string) {
	if len(line) < 2 {
		return
	}
	f := sbox.getLogFunc(line[0])
	msg := line[2:]
	if f != nil {
		f("[%s] %s", sbox.profile.Name, msg)
	} else {
		sbox.daemon.log.Info("[%s] %s", sbox.profile.Name, line)
	}
}

func (sbox *Sandbox) getLogFunc(c byte) func(string, ...interface{}) {
	log := sbox.daemon.log
	switch c {
	case 'D':
		return log.Debug
	case 'I':
		return log.Info
	case 'N':
		return log.Notice
	case 'W':
		return log.Warning
	case 'E':
		return log.Error
	case 'C':
		return log.Critical
	}
	return nil
}

func (sbox *Sandbox) startXpraClient() {
	sbox.xpra = xpra.NewClient(
		&sbox.profile.XServer,
		uint64(sbox.display),
		sbox.cred,
		sbox.fs.Xpra(),
		sbox.profile.Name,
		sbox.daemon.log)

	if sbox.daemon.config.LogXpra {
		sbox.setupXpraLogging()
	}
	if err := sbox.xpra.Process.Start(); err != nil {
		sbox.daemon.Warning("Failed to start xpra client: %v", err)
	}
}

func (sbox *Sandbox) setupXpraLogging() {
	stdout, err := sbox.xpra.Process.StdoutPipe()
	if err != nil {
		sbox.daemon.Warning("Failed to create xpra stdout pipe: %v", err)
		return
	}
	stderr, err := sbox.xpra.Process.StderrPipe()
	if err != nil {
		stdout.Close()
		sbox.daemon.Warning("Failed to create xpra stderr pipe: %v", err)
	}
	go sbox.logPipeOutput(stdout, "xpra-stdout")
	go sbox.logPipeOutput(stderr, "xpra-stderr")
}

func (sbox *Sandbox) logPipeOutput(p io.Reader, label string) {
	scanner := bufio.NewScanner(p)
	for scanner.Scan() {
		line := scanner.Text()
		sbox.daemon.log.Info("(%s) %s", label, line)
	}
}
<commit_msg>Added waitgroup to connection proxy config to avoid potential race with the program trying to open/access the socket<commit_after>package daemon

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"os/exec"
	"os/user"
	"path"
	"path/filepath"
	"sync"
	"syscall"

	"github.com/subgraph/oz"
	"github.com/subgraph/oz/fs"
	"github.com/subgraph/oz/network"
	"github.com/subgraph/oz/xpra"
	"github.com/subgraph/oz/oz-init"

	"github.com/op/go-logging"
)

type Sandbox struct {
	daemon  *daemonState
	id      int
	display int
	profile *oz.Profile
	init    *exec.Cmd
	cred    *syscall.Credential
	fs      *fs.Filesystem
	stderr  io.ReadCloser
	addr    string
	xpra    *xpra.Xpra
	ready   sync.WaitGroup
	network *network.SandboxNetwork
}

func createInitCommand(initPath, name, chroot string, env []string, uid uint32, display int, stn *network.SandboxNetwork) *exec.Cmd {
	cmd := exec.Command(initPath)
	cmd.Dir = "/"

	cloneFlags := uintptr(syscall.CLONE_NEWNS)
	cloneFlags |= syscall.CLONE_NEWIPC
	cloneFlags |= syscall.CLONE_NEWPID
	cloneFlags |= syscall.CLONE_NEWUTS

	if stn.Nettype != network.TYPE_HOST {
		cloneFlags |= syscall.CLONE_NEWNET
	}

	cmd.SysProcAttr = &syscall.SysProcAttr{
		Chroot:     chroot,
		Cloneflags: cloneFlags,
	}
	cmd.Env = []string{
		"INIT_PROFILE=" + name,
		fmt.Sprintf("INIT_UID=%d", uid),
	}

	if stn.Ip != "" {
		cmd.Env = append(cmd.Env, "INIT_ADDR="+stn.Ip)
		cmd.Env = append(cmd.Env, "INIT_VHOST="+stn.VethHost)
		cmd.Env = append(cmd.Env, "INIT_VGUEST="+stn.VethGuest)
		cmd.Env = append(cmd.Env, "INIT_GATEWAY="+stn.Gateway.String()+"/"+stn.Class)
	}

	cmd.Env = append(cmd.Env, fmt.Sprintf("INIT_DISPLAY=%d", display))

	for _, e := range env {
		cmd.Env = append(cmd.Env, ozinit.EnvPrefix+e)
	}

	return cmd
}

func (d *daemonState) launch(p *oz.Profile, msg *LaunchMsg, uid, gid uint32, log *logging.Logger) (*Sandbox, error) {
	u, err := user.LookupId(fmt.Sprintf("%d", uid))
	if err != nil {
		return nil, fmt.Errorf("failed to lookup user for uid=%d: %v", uid, err)
	}
	fs := fs.NewFromProfile(p, u, d.config.SandboxPath, d.config.UseFullDev, d.log)
	if err := fs.Setup(d.config.ProfileDir); err != nil {
		return nil, err
	}
	display := 0
	if p.XServer.Enabled && p.Networking.Nettype == network.TYPE_HOST {
		display = d.nextDisplay
		d.nextDisplay += 1
	}

	stn := new(network.SandboxNetwork)
	stn.Nettype = p.Networking.Nettype
	if p.Networking.Nettype == network.TYPE_BRIDGE {
		stn, err = network.PrepareSandboxNetwork(d.network, log)
		if err != nil {
			return nil, fmt.Errorf("Unable to prepare veth network: %+v", err)
		}
	}

	cmd := createInitCommand(d.config.InitPath, p.Name, fs.Root(), msg.Env, uid, display, stn)
	log.Debug("Command environment: %+v", cmd.Env)
	pp, err := cmd.StderrPipe()
	if err != nil {
		fs.Cleanup()
		return nil, fmt.Errorf("error creating stderr pipe for init process: %v", err)

	}

	if err := cmd.Start(); err != nil {
		fs.Cleanup()
		return nil, fmt.Errorf("Unable to start process: %+v", err)
	}

	sbox := &Sandbox{
		daemon:  d,
		id:      d.nextSboxId,
		display: display,
		profile: p,
		init:    cmd,
		cred:    &syscall.Credential{Uid: uid, Gid: gid},
		fs:      fs,
		addr:    path.Join(fs.Root(), ozinit.SocketAddress),
		stderr:  pp,
		network: stn,
	}

	if p.Networking.Nettype == network.TYPE_BRIDGE {
		if err := network.NetInit(stn, d.network, cmd.Process.Pid, log); err != nil {
			cmd.Process.Kill()
			fs.Cleanup()
			return nil, fmt.Errorf("Unable to create veth networking: %+v", err)
		}
	}

	sbox.ready.Add(1)
	go sbox.logMessages()

	wgNet := new(sync.WaitGroup)
	if p.Networking.Nettype != network.TYPE_HOST && len(p.Networking.Sockets) > 0 {
		wgNet.Add(1)
		go func() {
			defer wgNet.Done()
			sbox.ready.Wait()
			err := network.ProxySetup(sbox.init.Process.Pid, p.Networking.Sockets, d.log, sbox.ready)
			if err != nil {
				log.Warning("Unable to create connection proxy: %+s", err)
			}
		}()
	}

	if !msg.Noexec {
		go func () {
			sbox.ready.Wait()
			wgNet.Wait()
			go sbox.launchProgram(msg.Path, msg.Pwd, msg.Args, log)
		}()
	}

	if sbox.profile.XServer.Enabled {
		go func() {
			sbox.ready.Wait()
			go sbox.startXpraClient()
		}()
	}

	d.nextSboxId += 1
	d.sandboxes = append(d.sandboxes, sbox)
	return sbox, nil
}

func (sbox *Sandbox) launchProgram(cpath, pwd string, args []string, log *logging.Logger) {
	if sbox.profile.AllowFiles {
		for _, fpath := range args {
			if _, err := os.Stat(fpath); err == nil {
				if filepath.IsAbs(fpath) == false {
					fpath = path.Join(pwd, fpath)
				}
				log.Info("Adding file `%s` to sandbox `%s`.", fpath, sbox.profile.Name)
				if err := sbox.fs.AddBindWhitelist(fpath, fpath, false); err != nil {
					log.Warning("Error adding file `%s`!", fpath)
				}
			}
		}
	}

	err := ozinit.RunProgram(sbox.addr, cpath, pwd, args)
	if err != nil {
		log.Error("start shell command failed: %v", err)
	}
}

func (sbox *Sandbox) remove(log *logging.Logger) {
	sboxes := []*Sandbox{}
	for _, sb := range sbox.daemon.sandboxes {
		if sb == sbox {
			sb.fs.Cleanup()
			if sb.profile.Networking.Nettype == network.TYPE_BRIDGE {
				sb.network.Cleanup(log)
			}
		} else {
			sboxes = append(sboxes, sb)
		}
	}
	sbox.daemon.sandboxes = sboxes
}

func (sbox *Sandbox) logMessages() {
	scanner := bufio.NewScanner(sbox.stderr)
	seenOk := false
	for scanner.Scan() {
		line := scanner.Text()
		if line == "OK" && !seenOk {
			sbox.daemon.log.Info("oz-init (%s) is ready", sbox.profile.Name)
			seenOk = true
			sbox.ready.Done()
		} else if len(line) > 1 {
			sbox.logLine(line)
		}
	}
	sbox.stderr.Close()
}

func (sbox *Sandbox) logLine(line string) {
	if len(line) < 2 {
		return
	}
	f := sbox.getLogFunc(line[0])
	msg := line[2:]
	if f != nil {
		f("[%s] %s", sbox.profile.Name, msg)
	} else {
		sbox.daemon.log.Info("[%s] %s", sbox.profile.Name, line)
	}
}

func (sbox *Sandbox) getLogFunc(c byte) func(string, ...interface{}) {
	log := sbox.daemon.log
	switch c {
	case 'D':
		return log.Debug
	case 'I':
		return log.Info
	case 'N':
		return log.Notice
	case 'W':
		return log.Warning
	case 'E':
		return log.Error
	case 'C':
		return log.Critical
	}
	return nil
}

func (sbox *Sandbox) startXpraClient() {
	sbox.xpra = xpra.NewClient(
		&sbox.profile.XServer,
		uint64(sbox.display),
		sbox.cred,
		sbox.fs.Xpra(),
		sbox.profile.Name,
		sbox.daemon.log)

	if sbox.daemon.config.LogXpra {
		sbox.setupXpraLogging()
	}
	if err := sbox.xpra.Process.Start(); err != nil {
		sbox.daemon.Warning("Failed to start xpra client: %v", err)
	}
}

func (sbox *Sandbox) setupXpraLogging() {
	stdout, err := sbox.xpra.Process.StdoutPipe()
	if err != nil {
		sbox.daemon.Warning("Failed to create xpra stdout pipe: %v", err)
		return
	}
	stderr, err := sbox.xpra.Process.StderrPipe()
	if err != nil {
		stdout.Close()
		sbox.daemon.Warning("Failed to create xpra stderr pipe: %v", err)
	}
	go sbox.logPipeOutput(stdout, "xpra-stdout")
	go sbox.logPipeOutput(stderr, "xpra-stderr")
}

func (sbox *Sandbox) logPipeOutput(p io.Reader, label string) {
	scanner := bufio.NewScanner(p)
	for scanner.Scan() {
		line := scanner.Text()
		sbox.daemon.log.Info("(%s) %s", label, line)
	}
}
<|endoftext|>


<commit_before>package user

import (
	"github.com/cloudfoundry/cli/cf/api"
	"github.com/cloudfoundry/cli/cf/api/feature_flags"
	"github.com/cloudfoundry/cli/cf/command_registry"
	"github.com/cloudfoundry/cli/cf/configuration/core_config"
	. "github.com/cloudfoundry/cli/cf/i18n"
	"github.com/cloudfoundry/cli/cf/models"
	"github.com/cloudfoundry/cli/cf/requirements"
	"github.com/cloudfoundry/cli/cf/terminal"
	"github.com/simonleung8/flags"
)

type SetOrgRole struct {
	ui       terminal.UI
	config   core_config.Reader
	flagRepo feature_flags.FeatureFlagRepository
	userRepo api.UserRepository
	userReq  requirements.UserRequirement
	orgReq   requirements.OrganizationRequirement
}

func init() {
	command_registry.Register(&SetOrgRole{})
}

func (cmd *SetOrgRole) MetaData() command_registry.CommandMetadata {
	return command_registry.CommandMetadata{
		Name:        "set-org-role",
		Description: T("Assign an org role to a user"),
		Usage: T("CF_NAME set-org-role USERNAME ORG ROLE\n\n") +
			T("ROLES:\n") +
			T("   OrgManager - Invite and manage users, select and change plans, and set spending limits\n") +
			T("   BillingManager - Create and manage the billing account and payment info\n") +
			T("   OrgAuditor - Read-only access to org info and reports\n"),
	}
}

func (cmd *SetOrgRole) Requirements(requirementsFactory requirements.Factory, fc flags.FlagContext) ([]requirements.Requirement, error) {
	if len(fc.Args()) != 3 {
		cmd.ui.Failed(T("Incorrect Usage. Requires USERNAME, ORG, ROLE as arguments\n\n") + command_registry.Commands.CommandUsage("set-org-role"))
	}

	var wantGuid bool
	if cmd.config.IsMinApiVersion("2.37.0") {
		setRolesByUsernameFlag, err := cmd.flagRepo.FindByName("set_roles_by_username")
		wantGuid = (err != nil || !setRolesByUsernameFlag.Enabled)
	} else {
		wantGuid = true
	}

	cmd.userReq = requirementsFactory.NewUserRequirement(fc.Args()[0], wantGuid)
	cmd.orgReq = requirementsFactory.NewOrganizationRequirement(fc.Args()[1])

	reqs := []requirements.Requirement{
		requirementsFactory.NewLoginRequirement(),
		cmd.userReq,
		cmd.orgReq,
	}

	return reqs, nil
}

func (cmd *SetOrgRole) SetDependency(deps command_registry.Dependency, pluginCall bool) command_registry.Command {
	cmd.ui = deps.Ui
	cmd.config = deps.Config
	cmd.userRepo = deps.RepoLocator.GetUserRepository()
	cmd.flagRepo = deps.RepoLocator.GetFeatureFlagRepository()
	return cmd
}

func (cmd *SetOrgRole) Execute(c flags.FlagContext) {
	user := cmd.userReq.GetUser()
	org := cmd.orgReq.GetOrganization()
	role := models.UserInputToOrgRole[c.Args()[2]]

	cmd.ui.Say(T("Assigning role {{.Role}} to user {{.TargetUser}} in org {{.TargetOrg}} as {{.CurrentUser}}...",
		map[string]interface{}{
			"Role":        terminal.EntityNameColor(role),
			"TargetUser":  terminal.EntityNameColor(user.Username),
			"TargetOrg":   terminal.EntityNameColor(org.Name),
			"CurrentUser": terminal.EntityNameColor(cmd.config.Username()),
		}))

	var err error
	if len(user.Guid) > 0 {
		err = cmd.userRepo.SetOrgRoleByGuid(user.Guid, org.Guid, role)
	} else {
		err = cmd.userRepo.SetOrgRoleByUsername(user.Username, org.Guid, role)
	}

	if err != nil {
		cmd.ui.Failed(err.Error())
	}

	cmd.ui.Ok()
}
<commit_msg>refactor set_org_role command into interface<commit_after>package user

import (
	"github.com/cloudfoundry/cli/cf/api"
	"github.com/cloudfoundry/cli/cf/api/feature_flags"
	"github.com/cloudfoundry/cli/cf/command_registry"
	"github.com/cloudfoundry/cli/cf/configuration/core_config"
	. "github.com/cloudfoundry/cli/cf/i18n"
	"github.com/cloudfoundry/cli/cf/models"
	"github.com/cloudfoundry/cli/cf/requirements"
	"github.com/cloudfoundry/cli/cf/terminal"
	"github.com/simonleung8/flags"
)

type OrgRoleSetter interface {
	command_registry.Command
	SetOrgRole(orgGuid string, role, userGuid, userName string) error
}

type SetOrgRole struct {
	ui       terminal.UI
	config   core_config.Reader
	flagRepo feature_flags.FeatureFlagRepository
	userRepo api.UserRepository
	userReq  requirements.UserRequirement
	orgReq   requirements.OrganizationRequirement
}

func init() {
	command_registry.Register(&SetOrgRole{})
}

func (cmd *SetOrgRole) MetaData() command_registry.CommandMetadata {
	return command_registry.CommandMetadata{
		Name:        "set-org-role",
		Description: T("Assign an org role to a user"),
		Usage: T("CF_NAME set-org-role USERNAME ORG ROLE\n\n") +
			T("ROLES:\n") +
			T("   OrgManager - Invite and manage users, select and change plans, and set spending limits\n") +
			T("   BillingManager - Create and manage the billing account and payment info\n") +
			T("   OrgAuditor - Read-only access to org info and reports\n"),
	}
}

func (cmd *SetOrgRole) Requirements(requirementsFactory requirements.Factory, fc flags.FlagContext) ([]requirements.Requirement, error) {
	if len(fc.Args()) != 3 {
		cmd.ui.Failed(T("Incorrect Usage. Requires USERNAME, ORG, ROLE as arguments\n\n") + command_registry.Commands.CommandUsage("set-org-role"))
	}

	var wantGuid bool
	if cmd.config.IsMinApiVersion("2.37.0") {
		setRolesByUsernameFlag, err := cmd.flagRepo.FindByName("set_roles_by_username")
		wantGuid = (err != nil || !setRolesByUsernameFlag.Enabled)
	} else {
		wantGuid = true
	}

	cmd.userReq = requirementsFactory.NewUserRequirement(fc.Args()[0], wantGuid)
	cmd.orgReq = requirementsFactory.NewOrganizationRequirement(fc.Args()[1])

	reqs := []requirements.Requirement{
		requirementsFactory.NewLoginRequirement(),
		cmd.userReq,
		cmd.orgReq,
	}

	return reqs, nil
}

func (cmd *SetOrgRole) SetDependency(deps command_registry.Dependency, pluginCall bool) command_registry.Command {
	cmd.ui = deps.Ui
	cmd.config = deps.Config
	cmd.userRepo = deps.RepoLocator.GetUserRepository()
	cmd.flagRepo = deps.RepoLocator.GetFeatureFlagRepository()
	return cmd
}

func (cmd *SetOrgRole) Execute(c flags.FlagContext) {
	user := cmd.userReq.GetUser()
	org := cmd.orgReq.GetOrganization()
	role := models.UserInputToOrgRole[c.Args()[2]]

	cmd.ui.Say(T("Assigning role {{.Role}} to user {{.TargetUser}} in org {{.TargetOrg}} as {{.CurrentUser}}...",
		map[string]interface{}{
			"Role":        terminal.EntityNameColor(role),
			"TargetUser":  terminal.EntityNameColor(user.Username),
			"TargetOrg":   terminal.EntityNameColor(org.Name),
			"CurrentUser": terminal.EntityNameColor(cmd.config.Username()),
		}))

	err := cmd.SetOrgRole(org.Guid, role, user.Guid, user.Username)
	if err != nil {
		cmd.ui.Failed(err.Error())
	}

	cmd.ui.Ok()
}

func (cmd *SetOrgRole) SetOrgRole(orgGuid string, role, userGuid, userName string) error {
	if len(userGuid) > 0 {
		return cmd.userRepo.SetOrgRoleByGuid(userGuid, orgGuid, role)
	}

	return cmd.userRepo.SetOrgRoleByUsername(userName, orgGuid, role)
}
<|endoftext|>


<commit_before>package tasks

import (
	"errors"
	"fmt"
	"github.com/asdine/storm"
	"github.com/asdine/storm/q"
	"github.com/deckarep/gosx-notifier"
	"github.com/fatih/color"
	"github.com/olekukonko/tablewriter"
	"os"
	"strconv"
	"strings"
	"time"
)

var (
	errDuplicateTimerForTask = errors.New("task already has a running timer")
	ticker                   <-chan time.Time
	DB                       *storm.DB
)

type task struct {
	ID       int    `storm:"id,increment"`
	Name     string `storm:"unique"`
	Status   string
	Priority int
}

func (t *task) updateFieldValuePairs(fieldValuePairs []string) {
	for _, pair := range fieldValuePairs {
		arr := strings.Split(pair, ":")
		field, value := arr[0], arr[1]
		if field == "status" {
			value = strings.ToUpper(value)
		}
		t.updateField(field, value)
	}
}

func (t *task) updateField(field, value string) {
	switch field {
	case "name", "n":
		DB.Update(&task{ID: t.ID, Name: value})
	case "status", "st", "s":
		DB.Update(&task{ID: t.ID, Status: strings.ToUpper(value)})
	case "priority", "pri", "p":
		priority, err := strconv.Atoi(value)
		if err != nil {
			panic(err)
		}
		DB.Update(&task{ID: t.ID, Priority: priority})
	}
}

type taskTimer struct {
	ID        int `storm:"id,increment"`
	TaskID    int
	StartedAt time.Time
	ExpiresAt time.Time
	Message   string
	Fired     bool
}

func (tt *taskTimer) trigger() {
	tt.pushNotification()
	err := DB.Update(&taskTimer{ID: tt.ID, Fired: true})
	if err != nil {
		panic(err)
	}
}

func (tt *taskTimer) isExpired() bool {
	return tt.ExpiresAt.Before(time.Now())
}

func (tt *taskTimer) ellapsedTime() time.Duration {
	var finishedAt time.Time
	if tt.unfinished() {
		finishedAt = time.Now()
	} else {
		finishedAt = tt.ExpiresAt
	}
	return finishedAt.Sub(tt.StartedAt)
}

func (timer *taskTimer) unfinished() bool {
	return !timer.Fired
}

func init() {
	d, err := storm.Open("selfcontrol.db")
	DB = d
	if err != nil {
		panic(err)
	}
	startTimersLoop()
}

func startTimersLoop() {
	ticker = time.Tick(1 * time.Second)
	go func() {
		for _ = range ticker {
			var taskTimers []taskTimer
			_ = DB.Find("Fired", false, &taskTimers)
			for _, tt := range taskTimers {
				if tt.isExpired() {
					tt.trigger()
				}
			}
		}
	}()
}

// Add a new task given its name
func Add(name string, fieldValuePairs []string) {
	t := task{
		Name:   name,
		Status: "TODO",
	}
	err := DB.Save(&t)
	if err != nil {
		panic(err)
	}
	t.updateFieldValuePairs(fieldValuePairs)
}

// Print all tasks in a ASCII table
func Print() {
	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"ID", "name", "status", "priority", "total time"})
	table.SetAutoFormatHeaders(false)
	for _, row := range createRows() {
		table.Append(row)
	}
	table.Render()
}

// Delete a task with given id
func Delete(ID int) {
	var t task
	err := DB.One("ID", ID, &t)
	if err != nil {
		panic(err)
	}
	if err = DB.DeleteStruct(&t); err != nil {
		panic(err)
	}
}

//UpdateFields updates the tasks attributes
func UpdateFields(taskID int, fieldValuePairs []string) (bool, error) {
	t, err := findTaskById(taskID)
	if err != nil {
		return false, err
	}
	t.updateFieldValuePairs(fieldValuePairs)
	return true, nil
}

// AddTimerForTask adds a timer for a given task id and duration
func AddTimerForTask(taskID int, d time.Duration) (bool, error) {
	t, err := findTaskById(taskID)
	if err != nil {
		panic(err)
	}
	if hasRunningTimer(taskID) {
		return false, errDuplicateTimerForTask
	}

	startedAt := time.Now()
	expiresAt := startedAt.Add(d)

	DB.Save(&taskTimer{
		TaskID:    taskID,
		Message:   "Timer for '" + t.Name + "' finished!",
		StartedAt: startedAt,
		ExpiresAt: expiresAt,
	})
	return true, nil
}

func findTaskById(id int) (*task, error) {
	var t task
	err := DB.One("ID", id, &t)
	if err != nil {
		return nil, err
	}
	return &t, nil
}

func hasRunningTimer(taskID int) bool {
	var taskTimers []taskTimer
	_ = DB.Select(q.And(q.Eq("TaskID", taskID), q.Eq("Fired", false))).Find(&taskTimers)
	fmt.Println("number of timers: %d", len(taskTimers))
	return len(taskTimers) != 0
}

func (tt *taskTimer)pushNotification() {
	gosxnotifier.NewNotification(tt.Message).Push()
}

func createRows() [][]string {
	var rows = [][]string{}
	var tasks []task
	err := DB.Select(q.True()).OrderBy("Priority").Find(&tasks)
	if err != nil {
		panic(err)
	}
	for _, tt := range tasks {
		row := []string{
			strconv.Itoa(tt.ID),
			tt.Name,
			coloredStatus(tt.Status),
			strconv.Itoa(tt.Priority),
			totalRunningTime(tt.ID).String(),
		}
		rows = append(rows, row)
	}
	return rows
}

func totalRunningTime(taskID int) time.Duration {
	total := time.Duration(0)
	var taskTimers []taskTimer
	err := DB.Find("TaskID", taskID, &taskTimers)
	if err != nil {
		return total
	}
	for _, t := range taskTimers {
		total += t.ellapsedTime()
	}
	return total
}

func coloredStatus(status string) string {
	switch status {
	case "TODO":
		return color.CyanString(status)
	case "DOING":
		return color.YellowString(status)
	case "DONE":
		return color.GreenString(status)
	}
	return ""
}
<commit_msg>Refator<commit_after>package tasks

import (
	"errors"
	"fmt"
	"github.com/asdine/storm"
	"github.com/asdine/storm/q"
	"github.com/deckarep/gosx-notifier"
	"github.com/fatih/color"
	"github.com/olekukonko/tablewriter"
	"os"
	"strconv"
	"strings"
	"time"
)

var (
	errDuplicateTimerForTask = errors.New("task already has a running timer")
	ticker                   <-chan time.Time
	DB                       *storm.DB
)

type task struct {
	ID       int    `storm:"id,increment"`
	Name     string `storm:"unique"`
	Status   string
	Priority int
}

func (t *task) updateFieldValuePairs(fieldValuePairs []string) {
	for _, pair := range fieldValuePairs {
		arr := strings.Split(pair, ":")
		field, value := arr[0], arr[1]
		if field == "status" {
			value = strings.ToUpper(value)
		}
		t.updateField(field, value)
	}
}

func (t *task) updateField(field, value string) {
	switch field {
	case "name", "n":
		DB.Update(&task{ID: t.ID, Name: value})
	case "status", "st", "s":
		DB.Update(&task{ID: t.ID, Status: strings.ToUpper(value)})
	case "priority", "pri", "p":
		priority, err := strconv.Atoi(value)
		if err != nil {
			panic(err)
		}
		DB.Update(&task{ID: t.ID, Priority: priority})
	}
}

type taskTimer struct {
	ID        int `storm:"id,increment"`
	TaskID    int
	StartedAt time.Time
	ExpiresAt time.Time
	Message   string
	Fired     bool
}

func (tt *taskTimer) trigger() {
	tt.pushNotification()
	err := DB.Update(&taskTimer{ID: tt.ID, Fired: true})
	if err != nil {
		panic(err)
	}
}

func (tt *taskTimer) isExpired() bool {
	return tt.ExpiresAt.Before(time.Now())
}

func (tt *taskTimer) ellapsedTime() time.Duration {
	var finishedAt time.Time
	if !tt.Fired {
		finishedAt = time.Now()
	} else {
		finishedAt = tt.ExpiresAt
	}
	return finishedAt.Sub(tt.StartedAt)
}

func init() {
	d, err := storm.Open("selfcontrol.db")
	DB = d
	if err != nil {
		panic(err)
	}
	startTimersLoop()
}

func startTimersLoop() {
	ticker = time.Tick(1 * time.Second)
	go func() {
		for _ = range ticker {
			var taskTimers []taskTimer
			_ = DB.Find("Fired", false, &taskTimers)
			for _, tt := range taskTimers {
				if tt.isExpired() {
					tt.trigger()
				}
			}
		}
	}()
}

// Add a new task given its name
func Add(name string, fieldValuePairs []string) {
	t := task{
		Name:   name,
		Status: "TODO",
	}
	err := DB.Save(&t)
	if err != nil {
		panic(err)
	}
	t.updateFieldValuePairs(fieldValuePairs)
}

// Print all tasks in a ASCII table
func Print() {
	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"ID", "Name", "Status", "Priority", "Total time"})
	table.SetAutoFormatHeaders(false)
	for _, row := range createRows() {
		table.Append(row)
	}
	table.Render()
}

// Delete a task with given id
func Delete(ID int) {
	var t task
	err := DB.One("ID", ID, &t)
	if err != nil {
		panic(err)
	}
	if err = DB.DeleteStruct(&t); err != nil {
		panic(err)
	}
}

//UpdateFields updates the tasks attributes
func UpdateFields(taskID int, fieldValuePairs []string) (bool, error) {
	t, err := findTaskById(taskID)
	if err != nil {
		return false, err
	}
	t.updateFieldValuePairs(fieldValuePairs)
	return true, nil
}

// AddTimerForTask adds a timer for a given task id and duration
func AddTimerForTask(taskID int, d time.Duration) (bool, error) {
	t, err := findTaskById(taskID)
	if err != nil {
		panic(err)
	}
	if hasRunningTimer(taskID) {
		return false, errDuplicateTimerForTask
	}

	startedAt := time.Now()
	expiresAt := startedAt.Add(d)

	DB.Save(&taskTimer{
		TaskID:    taskID,
		Message:   "Timer for '" + t.Name + "' finished!",
		StartedAt: startedAt,
		ExpiresAt: expiresAt,
	})
	return true, nil
}

func findTaskById(id int) (*task, error) {
	var t task
	err := DB.One("ID", id, &t)
	if err != nil {
		return nil, err
	}
	return &t, nil
}

func hasRunningTimer(taskID int) bool {
	var taskTimers []taskTimer
	_ = DB.Select(q.And(q.Eq("TaskID", taskID), q.Eq("Fired", false))).Find(&taskTimers)
	fmt.Println("number of timers: %d", len(taskTimers))
	return len(taskTimers) != 0
}

func (tt *taskTimer)pushNotification() {
	gosxnotifier.NewNotification(tt.Message).Push()
}

func createRows() [][]string {
	var rows = [][]string{}
	var tasks []task
	err := DB.Select(q.True()).OrderBy("Priority").Find(&tasks)
	if err != nil {
		panic(err)
	}
	for _, tt := range tasks {
		row := []string{
			strconv.Itoa(tt.ID),
			tt.Name,
			coloredStatus(tt.Status),
			strconv.Itoa(tt.Priority),
			totalRunningTime(tt.ID).String(),
		}
		rows = append(rows, row)
	}
	return rows
}

func totalRunningTime(taskID int) time.Duration {
	total := time.Duration(0)
	var taskTimers []taskTimer
	err := DB.Find("TaskID", taskID, &taskTimers)
	if err != nil {
		return total
	}
	for _, t := range taskTimers {
		total += t.ellapsedTime()
	}
	return total
}

func coloredStatus(status string) string {
	switch status {
	case "TODO":
		return color.CyanString(status)
	case "DOING":
		return color.YellowString(status)
	case "DONE":
		return color.GreenString(status)
	}
	return ""
}
<|endoftext|>


<commit_before>package rtspclient

func Advance(data []byte, size, n uint) ([]byte, uint) {
	data = data[n:]
	size -= n
	return data, size
}

func SeqNumLT(s1, s2 int) bool {
	// a 'less-than' on 16-bit sequence numbers
	diff := s2 - s1
	if diff > 0 {
		return (diff < 0x8000)
	} else if diff < 0 {
		return (diff < -0x8000)
	} else { // diff == 0
		return false
	}
}
<commit_msg>update utils package<commit_after>package utils

func Advance(data []byte, size, n uint) ([]byte, uint) {
	data = data[n:]
	size -= n
	return data, size
}

func SeqNumLT(s1, s2 int) bool {
	// a 'less-than' on 16-bit sequence numbers
	diff := s2 - s1
	if diff > 0 {
		return (diff < 0x8000)
	} else if diff < 0 {
		return (diff < -0x8000)
	} else { // diff == 0
		return false
	}
}
<|endoftext|>


<commit_before>package postman

import (
	"encoding/json"
	"github.com/stretchr/testify/assert"
	"testing"
	"time"
)

func TestUnmarshalDuration(t *testing.T) {
	var d Duration
	assert.NoError(t, json.Unmarshal([]byte(`12345`), &d))
	assert.Equal(t, Duration(12345*time.Millisecond), d)
}

func TestUnmarshalDurationString(t *testing.T) {
	var d Duration
	assert.NoError(t, json.Unmarshal([]byte(`"12345"`), &d))
	assert.Equal(t, Duration(12345*time.Millisecond), d)
}

func TestUnmarshalDurationStringUnit(t *testing.T) {
	var d Duration
	assert.NoError(t, json.Unmarshal([]byte(`"12345s"`), &d))
	assert.Equal(t, Duration(12345*time.Second), d)
}

func TestUnmarshalDurationStringInvalid(t *testing.T) {
	var d Duration
	assert.Error(t, json.Unmarshal([]byte(`{}`), &d))
}

func TestUnmarshalDurationStringInvalidJSON(t *testing.T) {
	var d Duration
	assert.Error(t, json.Unmarshal([]byte(`e`), &d))
}

func TestUnmarshalTime(t *testing.T) {
	var tm Time
	assert.NoError(t, json.Unmarshal([]byte(`12345`), &tm))
	assert.Equal(t, int64(12345), time.Time(tm).Unix())
}

func TestUnmarshalTimeString(t *testing.T) {
	var tm Time
	assert.NoError(t, json.Unmarshal([]byte(`"12345"`), &tm))
	assert.Equal(t, int64(12345), time.Time(tm).Unix())
}

func TestUnmarshalTimeInvalid(t *testing.T) {
	var tm Time
	assert.Error(t, json.Unmarshal([]byte(`{}`), &tm))
}

func TestUnmarshalTimeInvalidJSON(t *testing.T) {
	var tm Time
	assert.Error(t, json.Unmarshal([]byte(`e`), &tm))
}

func TestUnmarshalInfo(t *testing.T) {
	j := []byte(`{
		"info": { "name": "Name" }
	}`)

	c := Collection{}
	assert.NoError(t, json.Unmarshal(j, &c))
	assert.Equal(t, "Name", c.Info.Name)
}

func TestUnmarshalItem(t *testing.T) {
	j := []byte(`{
		"item": [
			{ "id": "1", "name": "A" },
			{ "id": "2", "name": "B" }
		]
	}`)

	c := Collection{}
	assert.NoError(t, json.Unmarshal(j, &c))
	assert.Len(t, c.Item, 2)
	assert.Equal(t, "1", c.Item[0].ID)
	assert.Equal(t, "A", c.Item[0].Name)
	assert.Equal(t, "2", c.Item[1].ID)
	assert.Equal(t, "B", c.Item[1].Name)
}

func TestUnmarshalItemNested(t *testing.T) {
	j := []byte(`{
		"item": [{
			"name": "Folder",
			"description": "Lorem ipsum",
			"item": [
				{ "id": "1", "name": "A" },
				{ "id": "2", "name": "B" }
			]
		}]
	}`)

	c := Collection{}
	assert.NoError(t, json.Unmarshal(j, &c))
	assert.Len(t, c.Item, 1)
	assert.Equal(t, "Folder", c.Item[0].Name)
	assert.Equal(t, "Lorem ipsum", c.Item[0].Description)
	assert.Len(t, c.Item[0].Item, 2)
	assert.Equal(t, "1", c.Item[0].Item[0].ID)
	assert.Equal(t, "A", c.Item[0].Item[0].Name)
	assert.Equal(t, "2", c.Item[0].Item[1].ID)
	assert.Equal(t, "B", c.Item[0].Item[1].Name)
}

func TestUnmarshalItemRequest(t *testing.T) {
	j := []byte(`{
		"item": [{
			"request": {
				"url": "http://example.com/",
				"method": "POST",
				"header": [{"key": "Content-Type", "value": "text/plain"}],
				"body": "lorem ipsum"
			}
		}]
	}`)

	c := Collection{}
	assert.NoError(t, json.Unmarshal(j, &c))
	assert.Len(t, c.Item, 1)
	assert.Equal(t, "http://example.com/", c.Item[0].Request.URL)
	assert.Equal(t, "POST", c.Item[0].Request.Method)
	assert.Len(t, c.Item[0].Request.Header, 1)
	assert.Equal(t, "Content-Type", c.Item[0].Request.Header[0].Key)
	assert.Equal(t, "text/plain", c.Item[0].Request.Header[0].Value)
	assert.Equal(t, "lorem ipsum", c.Item[0].Request.Body)
}

func TestUnmarshalItemRequestImplicitMethod(t *testing.T) {
	j := []byte(`{
		"item": [{
			"request": {
				"url": "http://example.com/"
			}
		}]
	}`)

	c := Collection{}
	assert.NoError(t, json.Unmarshal(j, &c))
	assert.Len(t, c.Item, 1)
	assert.Equal(t, "http://example.com/", c.Item[0].Request.URL)
	assert.Equal(t, "GET", c.Item[0].Request.Method)
}

func TestUnmarshalItemRequestString(t *testing.T) {
	j := []byte(`{
		"item": [{
			"request": "http://example.com/"
		}]
	}`)

	c := Collection{}
	assert.NoError(t, json.Unmarshal(j, &c))
	assert.Len(t, c.Item, 1)
	assert.Equal(t, "http://example.com/", c.Item[0].Request.URL)
	assert.Equal(t, "GET", c.Item[0].Request.Method)
	assert.Len(t, c.Item[0].Request.Header, 0)
	assert.Equal(t, "", c.Item[0].Request.Body)
}

func TestUnmarshalItemRequestMissingHeaderKey(t *testing.T) {
	j := []byte(`{
		"item": [{
			"request": {
				"url": "http://example.com/",
				"method": "POST",
				"header": [{"value": "text/plain"}]
			}
		}]
	}`)

	c := Collection{}
	assert.Equal(t, ErrMissingHeaderKey, json.Unmarshal(j, &c))
}

func TestUnmarshalItemResponse(t *testing.T) {
	j := []byte(`{
		"item": [{
			"response": [{
				"originalRequest": "http://example.com/",
				"responseTime": 100,
				"header": [{"key": "Content-Type", "value": "text/plain"}],
				"body": "lorem ipsum",
				"status": "200 OK",
				"code": 200
			}]
		}]
	}`)

	c := Collection{}
	assert.NoError(t, json.Unmarshal(j, &c))
	assert.Len(t, c.Item, 1)
	assert.Len(t, c.Item[0].Response, 1)
	assert.Equal(t, "http://example.com/", c.Item[0].Response[0].OriginalRequest.URL)
	assert.Equal(t, "GET", c.Item[0].Response[0].OriginalRequest.Method)
	assert.Equal(t, 100*time.Millisecond, time.Duration(c.Item[0].Response[0].ResponseTime))
	assert.Len(t, c.Item[0].Response[0].Header, 1)
	assert.Equal(t, "Content-Type", c.Item[0].Response[0].Header[0].Key)
	assert.Equal(t, "text/plain", c.Item[0].Response[0].Header[0].Value)
	assert.Equal(t, "lorem ipsum", c.Item[0].Response[0].Body)
	assert.Equal(t, "200 OK", c.Item[0].Response[0].Status)
	assert.Equal(t, 200, c.Item[0].Response[0].Code)
}

func TestUnmarshalItemResponseCookie(t *testing.T) {
	j := []byte(`{
		"item": [{
			"response": [{
				"originalRequest": "http://example.com/",
				"cookie": [{
					"domain": "example.com",
					"expires": 1,
					"maxAge": 123,
					"hostOnly": true,
					"httpOnly": true,
					"name": "name",
					"path": "/",
					"secure": true,
					"session": true,
					"value": "value"
				}]
			}]
		}]
	}`)

	c := Collection{}
	assert.NoError(t, json.Unmarshal(j, &c))
	assert.Len(t, c.Item, 1)
	assert.Len(t, c.Item[0].Response, 1)
	assert.Len(t, c.Item[0].Response[0].Cookie, 1)
	assert.Equal(t, "example.com", c.Item[0].Response[0].Cookie[0].Domain)
	assert.Equal(t, int64(1), time.Time(c.Item[0].Response[0].Cookie[0].Expires).Unix())
	assert.Equal(t, 123*time.Millisecond, time.Duration(c.Item[0].Response[0].Cookie[0].MaxAge))
	assert.Equal(t, true, c.Item[0].Response[0].Cookie[0].HostOnly)
	assert.Equal(t, true, c.Item[0].Response[0].Cookie[0].HTTPOnly)
	assert.Equal(t, "name", c.Item[0].Response[0].Cookie[0].Name)
	assert.Equal(t, "/", c.Item[0].Response[0].Cookie[0].Path)
	assert.Equal(t, true, c.Item[0].Response[0].Cookie[0].Secure)
	assert.Equal(t, true, c.Item[0].Response[0].Cookie[0].Session)
	assert.Equal(t, "value", c.Item[0].Response[0].Cookie[0].Value)
}

func TestUmmarshalEvent(t *testing.T) {
	j := []byte(`{
		"event": [{
			"listen": "test",
			"script": {
				"id": "script1",
				"type": "text/javascript",
				"exec": "var v = 1 + 1;\nconsole.log(v);",
				"name": "script1.js"
			}
		}]
	}`)

	c := Collection{}
	assert.NoError(t, json.Unmarshal(j, &c))
	assert.Len(t, c.Event, 1)
	assert.Equal(t, "test", c.Event[0].Listen)
	assert.Equal(t, "script1", c.Event[0].Script.ID)
	assert.Equal(t, "text/javascript", c.Event[0].Script.Type)
	assert.Equal(t, ScriptExec("var v = 1 + 1;\nconsole.log(v);"), c.Event[0].Script.Exec)
	assert.Equal(t, "script1.js", c.Event[0].Script.Name)
	assert.Equal(t, false, c.Event[0].Disabled)
}

func TestUmmarshalEventArrayExec(t *testing.T) {
	j := []byte(`{
		"event": [{
			"listen": "test",
			"script": {
				"id": "script1",
				"type": "text/javascript",
				"exec": [
					"var v = 1 + 1;",
					"console.log(v);"
				],
				"name": "script1.js"
			}
		}]
	}`)

	c := Collection{}
	assert.NoError(t, json.Unmarshal(j, &c))
	assert.Len(t, c.Event, 1)
	assert.Equal(t, "test", c.Event[0].Listen)
	assert.Equal(t, "script1", c.Event[0].Script.ID)
	assert.Equal(t, "text/javascript", c.Event[0].Script.Type)
	assert.Equal(t, ScriptExec("var v = 1 + 1;\nconsole.log(v);"), c.Event[0].Script.Exec)
	assert.Equal(t, "script1.js", c.Event[0].Script.Name)
	assert.Equal(t, false, c.Event[0].Disabled)
}

func TestUmmarshalEventScriptImplicitType(t *testing.T) {
	j := []byte(`{
		"event": [{
			"listen": "test",
			"script": {
				"exec": "var v = 1 + 1;\nconsole.log(v);"
			}
		}]
	}`)

	c := Collection{}
	assert.NoError(t, json.Unmarshal(j, &c))
	assert.Len(t, c.Event, 1)
	assert.Equal(t, "test", c.Event[0].Listen)
	assert.Equal(t, "text/javascript", c.Event[0].Script.Type)
	assert.Equal(t, ScriptExec("var v = 1 + 1;\nconsole.log(v);"), c.Event[0].Script.Exec)
}

func TestUmmarshalEventWrongScriptType(t *testing.T) {
	j := []byte(`{
		"event": [{
			"listen": "test",
			"script": {
				"type": "text/vbscript",
				"exec": "/* I don't actually know VBScript lol */"
			}
		}]
	}`)

	c := Collection{}
	assert.Equal(t, ErrScriptUnsupportedType, json.Unmarshal(j, &c))
}

func TestUmmarshalEventScriptString(t *testing.T) {
	j := []byte(`{
		"event": [{
			"listen": "test",
			"script": "var v = 1 + 1;\nconsole.log(v);"
		}]
	}`)

	c := Collection{}
	assert.NoError(t, json.Unmarshal(j, &c))
	assert.Len(t, c.Event, 1)
	assert.Equal(t, "test", c.Event[0].Listen)
	assert.Equal(t, "text/javascript", c.Event[0].Script.Type)
	assert.Equal(t, ScriptExec("var v = 1 + 1;\nconsole.log(v);"), c.Event[0].Script.Exec)
}

func TestUmmarshalEventScriptInvalid(t *testing.T) {
	j := []byte(`{
		"event": [{
			"listen": "test",
			"script": 12345
		}]
	}`)

	c := Collection{}
	assert.Error(t, json.Unmarshal(j, &c))
}

func TestUnmarshalVariableNotImplemented(t *testing.T) {
	j := []byte(`{ "variable": [{}] }`)
	c := Collection{}
	assert.Equal(t, ErrVariablesNotSupported, json.Unmarshal(j, &c))
}
<commit_msg>[test] Fixed Postman collection tests<commit_after>package postman

import (
	"encoding/json"
	"github.com/stretchr/testify/assert"
	"testing"
	"time"
)

func TestUnmarshalDuration(t *testing.T) {
	var d Duration
	assert.NoError(t, json.Unmarshal([]byte(`12345`), &d))
	assert.Equal(t, Duration(12345*time.Millisecond), d)
}

func TestUnmarshalDurationString(t *testing.T) {
	var d Duration
	assert.NoError(t, json.Unmarshal([]byte(`"12345"`), &d))
	assert.Equal(t, Duration(12345*time.Millisecond), d)
}

func TestUnmarshalDurationStringUnit(t *testing.T) {
	var d Duration
	assert.NoError(t, json.Unmarshal([]byte(`"12345s"`), &d))
	assert.Equal(t, Duration(12345*time.Second), d)
}

func TestUnmarshalDurationStringInvalid(t *testing.T) {
	var d Duration
	assert.Error(t, json.Unmarshal([]byte(`{}`), &d))
}

func TestUnmarshalDurationStringInvalidJSON(t *testing.T) {
	var d Duration
	assert.Error(t, json.Unmarshal([]byte(`e`), &d))
}

func TestUnmarshalTime(t *testing.T) {
	var tm Time
	assert.NoError(t, json.Unmarshal([]byte(`12345`), &tm))
	assert.Equal(t, int64(12345), time.Time(tm).Unix())
}

func TestUnmarshalTimeString(t *testing.T) {
	var tm Time
	assert.NoError(t, json.Unmarshal([]byte(`"Fri Apr 15 2016 12:54:28 GMT+0200 (CEST)"`), &tm))
	assert.Equal(t, int64(1460717668), time.Time(tm).Unix())
}

func TestUnmarshalTimeInvalid(t *testing.T) {
	var tm Time
	assert.Error(t, json.Unmarshal([]byte(`{}`), &tm))
}

func TestUnmarshalTimeInvalidJSON(t *testing.T) {
	var tm Time
	assert.Error(t, json.Unmarshal([]byte(`e`), &tm))
}

func TestUnmarshalInfo(t *testing.T) {
	j := []byte(`{
		"info": { "name": "Name" }
	}`)

	c := Collection{}
	assert.NoError(t, json.Unmarshal(j, &c))
	assert.Equal(t, "Name", c.Info.Name)
}

func TestUnmarshalItem(t *testing.T) {
	j := []byte(`{
		"item": [
			{ "id": "1", "name": "A" },
			{ "id": "2", "name": "B" }
		]
	}`)

	c := Collection{}
	assert.NoError(t, json.Unmarshal(j, &c))
	assert.Len(t, c.Item, 2)
	assert.Equal(t, "1", c.Item[0].ID)
	assert.Equal(t, "A", c.Item[0].Name)
	assert.Equal(t, "2", c.Item[1].ID)
	assert.Equal(t, "B", c.Item[1].Name)
}

func TestUnmarshalItemNested(t *testing.T) {
	j := []byte(`{
		"item": [{
			"name": "Folder",
			"description": "Lorem ipsum",
			"item": [
				{ "id": "1", "name": "A" },
				{ "id": "2", "name": "B" }
			]
		}]
	}`)

	c := Collection{}
	assert.NoError(t, json.Unmarshal(j, &c))
	assert.Len(t, c.Item, 1)
	assert.Equal(t, "Folder", c.Item[0].Name)
	assert.Equal(t, "Lorem ipsum", c.Item[0].Description)
	assert.Len(t, c.Item[0].Item, 2)
	assert.Equal(t, "1", c.Item[0].Item[0].ID)
	assert.Equal(t, "A", c.Item[0].Item[0].Name)
	assert.Equal(t, "2", c.Item[0].Item[1].ID)
	assert.Equal(t, "B", c.Item[0].Item[1].Name)
}

func TestUnmarshalItemRequest(t *testing.T) {
	j := []byte(`{
		"item": [{
			"request": {
				"url": "http://example.com/",
				"method": "POST",
				"header": [{"key": "Content-Type", "value": "text/plain"}],
				"body": { "mode": "raw", "raw": "lorem ipsum" }
			}
		}]
	}`)

	c := Collection{}
	assert.NoError(t, json.Unmarshal(j, &c))
	assert.Len(t, c.Item, 1)
	assert.Equal(t, "http://example.com/", c.Item[0].Request.URL)
	assert.Equal(t, "POST", c.Item[0].Request.Method)
	assert.Len(t, c.Item[0].Request.Header, 1)
	assert.Equal(t, "Content-Type", c.Item[0].Request.Header[0].Key)
	assert.Equal(t, "text/plain", c.Item[0].Request.Header[0].Value)
	assert.Equal(t, "raw", c.Item[0].Request.Body.Mode)
	assert.Equal(t, "lorem ipsum", c.Item[0].Request.Body.Raw)
}

func TestUnmarshalItemRequestImplicitMethod(t *testing.T) {
	j := []byte(`{
		"item": [{
			"request": {
				"url": "http://example.com/"
			}
		}]
	}`)

	c := Collection{}
	assert.NoError(t, json.Unmarshal(j, &c))
	assert.Len(t, c.Item, 1)
	assert.Equal(t, "http://example.com/", c.Item[0].Request.URL)
	assert.Equal(t, "GET", c.Item[0].Request.Method)
}

func TestUnmarshalItemRequestString(t *testing.T) {
	j := []byte(`{
		"item": [{
			"request": "http://example.com/"
		}]
	}`)

	c := Collection{}
	assert.NoError(t, json.Unmarshal(j, &c))
	assert.Len(t, c.Item, 1)
	assert.Equal(t, "http://example.com/", c.Item[0].Request.URL)
	assert.Equal(t, "GET", c.Item[0].Request.Method)
	assert.Len(t, c.Item[0].Request.Header, 0)
}

func TestUnmarshalItemRequestMissingHeaderKey(t *testing.T) {
	j := []byte(`{
		"item": [{
			"request": {
				"url": "http://example.com/",
				"method": "POST",
				"header": [{"value": "text/plain"}]
			}
		}]
	}`)

	c := Collection{}
	assert.Equal(t, ErrMissingHeaderKey, json.Unmarshal(j, &c))
}

func TestUnmarshalItemResponse(t *testing.T) {
	j := []byte(`{
		"item": [{
			"response": [{
				"originalRequest": "http://example.com/",
				"responseTime": 100,
				"header": [{"key": "Content-Type", "value": "text/plain"}],
				"body": "lorem ipsum",
				"status": "200 OK",
				"code": 200
			}]
		}]
	}`)

	c := Collection{}
	assert.NoError(t, json.Unmarshal(j, &c))
	assert.Len(t, c.Item, 1)
	assert.Len(t, c.Item[0].Response, 1)
	assert.Equal(t, "http://example.com/", c.Item[0].Response[0].OriginalRequest.URL)
	assert.Equal(t, "GET", c.Item[0].Response[0].OriginalRequest.Method)
	assert.Equal(t, 100*time.Millisecond, time.Duration(c.Item[0].Response[0].ResponseTime))
	assert.Len(t, c.Item[0].Response[0].Header, 1)
	assert.Equal(t, "Content-Type", c.Item[0].Response[0].Header[0].Key)
	assert.Equal(t, "text/plain", c.Item[0].Response[0].Header[0].Value)
	assert.Equal(t, "lorem ipsum", c.Item[0].Response[0].Body)
	assert.Equal(t, "200 OK", c.Item[0].Response[0].Status)
	assert.Equal(t, 200, c.Item[0].Response[0].Code)
}

func TestUnmarshalItemResponseCookie(t *testing.T) {
	j := []byte(`{
		"item": [{
			"response": [{
				"originalRequest": "http://example.com/",
				"cookie": [{
					"domain": "example.com",
					"expires": 1,
					"maxAge": 123,
					"hostOnly": true,
					"httpOnly": true,
					"name": "name",
					"path": "/",
					"secure": true,
					"session": true,
					"value": "value"
				}]
			}]
		}]
	}`)

	c := Collection{}
	assert.NoError(t, json.Unmarshal(j, &c))
	assert.Len(t, c.Item, 1)
	assert.Len(t, c.Item[0].Response, 1)
	assert.Len(t, c.Item[0].Response[0].Cookie, 1)
	assert.Equal(t, "example.com", c.Item[0].Response[0].Cookie[0].Domain)
	assert.Equal(t, int64(1), time.Time(c.Item[0].Response[0].Cookie[0].Expires).Unix())
	assert.Equal(t, 123*time.Millisecond, time.Duration(c.Item[0].Response[0].Cookie[0].MaxAge))
	assert.Equal(t, true, c.Item[0].Response[0].Cookie[0].HostOnly)
	assert.Equal(t, true, c.Item[0].Response[0].Cookie[0].HTTPOnly)
	assert.Equal(t, "name", c.Item[0].Response[0].Cookie[0].Name)
	assert.Equal(t, "/", c.Item[0].Response[0].Cookie[0].Path)
	assert.Equal(t, true, c.Item[0].Response[0].Cookie[0].Secure)
	assert.Equal(t, true, c.Item[0].Response[0].Cookie[0].Session)
	assert.Equal(t, "value", c.Item[0].Response[0].Cookie[0].Value)
}

func TestUmmarshalEvent(t *testing.T) {
	j := []byte(`{
		"event": [{
			"listen": "test",
			"script": {
				"id": "script1",
				"type": "text/javascript",
				"exec": "var v = 1 + 1;\nconsole.log(v);",
				"name": "script1.js"
			}
		}]
	}`)

	c := Collection{}
	assert.NoError(t, json.Unmarshal(j, &c))
	assert.Len(t, c.Event, 1)
	assert.Equal(t, "test", c.Event[0].Listen)
	assert.Equal(t, "script1", c.Event[0].Script.ID)
	assert.Equal(t, "text/javascript", c.Event[0].Script.Type)
	assert.Equal(t, ScriptExec("var v = 1 + 1;\nconsole.log(v);"), c.Event[0].Script.Exec)
	assert.Equal(t, "script1.js", c.Event[0].Script.Name)
	assert.Equal(t, false, c.Event[0].Disabled)
}

func TestUmmarshalEventArrayExec(t *testing.T) {
	j := []byte(`{
		"event": [{
			"listen": "test",
			"script": {
				"id": "script1",
				"type": "text/javascript",
				"exec": [
					"var v = 1 + 1;",
					"console.log(v);"
				],
				"name": "script1.js"
			}
		}]
	}`)

	c := Collection{}
	assert.NoError(t, json.Unmarshal(j, &c))
	assert.Len(t, c.Event, 1)
	assert.Equal(t, "test", c.Event[0].Listen)
	assert.Equal(t, "script1", c.Event[0].Script.ID)
	assert.Equal(t, "text/javascript", c.Event[0].Script.Type)
	assert.Equal(t, ScriptExec("var v = 1 + 1;\nconsole.log(v);"), c.Event[0].Script.Exec)
	assert.Equal(t, "script1.js", c.Event[0].Script.Name)
	assert.Equal(t, false, c.Event[0].Disabled)
}

func TestUmmarshalEventScriptImplicitType(t *testing.T) {
	j := []byte(`{
		"event": [{
			"listen": "test",
			"script": {
				"exec": "var v = 1 + 1;\nconsole.log(v);"
			}
		}]
	}`)

	c := Collection{}
	assert.NoError(t, json.Unmarshal(j, &c))
	assert.Len(t, c.Event, 1)
	assert.Equal(t, "test", c.Event[0].Listen)
	assert.Equal(t, "text/javascript", c.Event[0].Script.Type)
	assert.Equal(t, ScriptExec("var v = 1 + 1;\nconsole.log(v);"), c.Event[0].Script.Exec)
}

func TestUmmarshalEventWrongScriptType(t *testing.T) {
	j := []byte(`{
		"event": [{
			"listen": "test",
			"script": {
				"type": "text/vbscript",
				"exec": "/* I don't actually know VBScript lol */"
			}
		}]
	}`)

	c := Collection{}
	assert.Equal(t, ErrScriptUnsupportedType, json.Unmarshal(j, &c))
}

func TestUmmarshalEventScriptString(t *testing.T) {
	j := []byte(`{
		"event": [{
			"listen": "test",
			"script": "var v = 1 + 1;\nconsole.log(v);"
		}]
	}`)

	c := Collection{}
	assert.NoError(t, json.Unmarshal(j, &c))
	assert.Len(t, c.Event, 1)
	assert.Equal(t, "test", c.Event[0].Listen)
	assert.Equal(t, "text/javascript", c.Event[0].Script.Type)
	assert.Equal(t, ScriptExec("var v = 1 + 1;\nconsole.log(v);"), c.Event[0].Script.Exec)
}

func TestUmmarshalEventScriptInvalid(t *testing.T) {
	j := []byte(`{
		"event": [{
			"listen": "test",
			"script": 12345
		}]
	}`)

	c := Collection{}
	assert.Error(t, json.Unmarshal(j, &c))
}

func TestUnmarshalVariableNotImplemented(t *testing.T) {
	j := []byte(`{ "variable": [{}] }`)
	c := Collection{}
	assert.Equal(t, ErrVariablesNotSupported, json.Unmarshal(j, &c))
}
<|endoftext|>


<commit_before>package profiles

import (
	"log"
	"os"
	"strconv"
	"sync"
	"sync/atomic"

	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
)

/*
	basic insert into capped collection only profile, insert a doc of 400 bytes
*/

type cappedCollInsertReadProfile struct {
	UID int64

	indexGroup bool

	initProfile sync.Once

	session *mgo.Session
}

var _cappedCollInsertReadProfile cappedCollInsertReadProfile

// func Int2ObjId(i int64) string {
// 	// return string represenation of UID
// }

func (i cappedCollInsertReadProfile) SendNext(s *mgo.Session, worker_id int) error {
	var err error
	c := s.DB(getDBName(default_db_name_prefix)).C(getCollectionName(default_col_name_prefix))

	// r := rands[worker_id].Int63n(3)

	if worker_id == 1 || worker_id == 2 {

		num := (_cappedCollInsertReadProfile.UID - 10000)

		c.Find(bson.M{"name": &num}).Limit(1)
	} else {
		_u := atomic.AddInt64(&_cappedCollInsertReadProfile.UID, 1) // to make this unique

		doc := bson.M{
			// "_id":      _u,
			"name":     _u,
			"group":    rands[worker_id].Int(),
			"payload":  &Payload,
			"payload1": &Payload1,
			"payload2": &Payload2,
			"payload3": &Payload3,
			"payload4": &Payload4,
			"payload5": &Payload5,
			"payload6": &Payload6}

		if _profile_use_legacy_write {
			err = c.Insert(doc)
		} else {
			var results interface{}

			err = c.Database.Run(bson.D{{"insert", c.Name},
				{"documents", []bson.M{doc}}}, results)
		}
	}

	panicOnError(err)
	return err
}

func initCappedInsertReadTest(session *mgo.Session, _initdb bool) {
	log.Println("Initialize simple DB. with initdb flag ", _initdb)

	ci := new(mgo.CollectionInfo)
	ci.Capped = true
	ci.MaxBytes = 1000000000

	log.Println(". Init DB, drop collections")
	coll := session.DB(default_db_name_prefix).C(default_col_name_prefix)
	coll.DropCollection()
	coll.Create(ci)
	ensureIndexKeysHelper(coll)

	for i := 1; i < _multi_db; i++ {
		for j := 1; j < _multi_col; j++ {
			collection := session.DB(default_db_name_prefix + strconv.Itoa(i)).C(default_col_name_prefix + strconv.Itoa(j))
			collection.Create(ci)
			ensureIndexKeysHelper(collection)
		}
	}

}

func ensureIndexKeysHelper(collection *mgo.Collection) {
	err := collection.EnsureIndexKey("name")
	if err != nil {
		panic(err)
	}

	err = collection.EnsureIndexKey("uid")
	if err != nil {
		panic(err)
	}
}

func (i cappedCollInsertReadProfile) SetupTest(s *mgo.Session, _initdb bool) error {
	i.session = s
	f := func() {
		initCappedInsertReadTest(s, _initdb)
	}

	_cappedCollInsertReadProfile.initProfile.Do(f)
	return nil
}

func (i cappedCollInsertReadProfile) CsvString(total_time float64) string {
	return ""
}

func (i cappedCollInsertReadProfile) CsvHeader() string {
	return ""
}

func init() {
	atomic.StoreInt64(&_cappedCollInsertReadProfile.UID, -1) // UID starts with 1

	registerProfile("CAPPED_COLL_INSERT_READ", func() Profile {
		return Profile(_cappedCollInsertReadProfile) // use the same instance
	})
}
<commit_msg>remove unused package<commit_after>package profiles

import (
	"log"
	"strconv"
	"sync"
	"sync/atomic"

	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
)

/*
	basic insert into capped collection only profile, insert a doc of 400 bytes
*/

type cappedCollInsertReadProfile struct {
	UID int64

	indexGroup bool

	initProfile sync.Once

	session *mgo.Session
}

var _cappedCollInsertReadProfile cappedCollInsertReadProfile

// func Int2ObjId(i int64) string {
// 	// return string represenation of UID
// }

func (i cappedCollInsertReadProfile) SendNext(s *mgo.Session, worker_id int) error {
	var err error
	c := s.DB(getDBName(default_db_name_prefix)).C(getCollectionName(default_col_name_prefix))

	// r := rands[worker_id].Int63n(3)

	if worker_id == 1 || worker_id == 2 {

		num := (_cappedCollInsertReadProfile.UID - 10000)

		c.Find(bson.M{"name": &num}).Limit(1)
	} else {
		_u := atomic.AddInt64(&_cappedCollInsertReadProfile.UID, 1) // to make this unique

		doc := bson.M{
			// "_id":      _u,
			"name":     _u,
			"group":    rands[worker_id].Int(),
			"payload":  &Payload,
			"payload1": &Payload1,
			"payload2": &Payload2,
			"payload3": &Payload3,
			"payload4": &Payload4,
			"payload5": &Payload5,
			"payload6": &Payload6}

		if _profile_use_legacy_write {
			err = c.Insert(doc)
		} else {
			var results interface{}

			err = c.Database.Run(bson.D{{"insert", c.Name},
				{"documents", []bson.M{doc}}}, results)
		}
	}

	panicOnError(err)
	return err
}

func initCappedInsertReadTest(session *mgo.Session, _initdb bool) {
	log.Println("Initialize simple DB. with initdb flag ", _initdb)

	ci := new(mgo.CollectionInfo)
	ci.Capped = true
	ci.MaxBytes = 1000000000

	log.Println(". Init DB, drop collections")
	coll := session.DB(default_db_name_prefix).C(default_col_name_prefix)
	coll.DropCollection()
	coll.Create(ci)
	ensureIndexKeysHelper(coll)

	for i := 1; i < _multi_db; i++ {
		for j := 1; j < _multi_col; j++ {
			collection := session.DB(default_db_name_prefix + strconv.Itoa(i)).C(default_col_name_prefix + strconv.Itoa(j))
			collection.Create(ci)
			ensureIndexKeysHelper(collection)
		}
	}

}

func ensureIndexKeysHelper(collection *mgo.Collection) {
	err := collection.EnsureIndexKey("name")
	if err != nil {
		panic(err)
	}

	err = collection.EnsureIndexKey("uid")
	if err != nil {
		panic(err)
	}
}

func (i cappedCollInsertReadProfile) SetupTest(s *mgo.Session, _initdb bool) error {
	i.session = s
	f := func() {
		initCappedInsertReadTest(s, _initdb)
	}

	_cappedCollInsertReadProfile.initProfile.Do(f)
	return nil
}

func (i cappedCollInsertReadProfile) CsvString(total_time float64) string {
	return ""
}

func (i cappedCollInsertReadProfile) CsvHeader() string {
	return ""
}

func init() {
	atomic.StoreInt64(&_cappedCollInsertReadProfile.UID, -1) // UID starts with 1

	registerProfile("CAPPED_COLL_INSERT_READ", func() Profile {
		return Profile(_cappedCollInsertReadProfile) // use the same instance
	})
}
<|endoftext|>