<commit_before>package fonet

import (
	"bytes"
	"encoding/json"
	"errors"
	"io"
	"log"
	"math/rand"
	"time"
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

var (
	// ErrNotEnoughLayers is returned when trying to create a new network with too few layers.
	ErrNotEnoughLayers = errors.New("too few layers, minimum of 3 required")
)

// Network is containing all the needed settings/variables.
type Network struct {
	// w is the weights of the network.
	w [][][]float64
	// b is the biases of the network.
	b [][]float64
	// d is the delta values for each layer.
	d [][]float64
	// z is the z values for each layer.
	z [][]float64
	// l holds the number of layers in the network.
	l int
	// ls is the number of neurons in each layer.
	ls []int
	// activationID is the ID of the activation function used.  This is stored for serialization purposes.
	activationID ActivationFunction
	// aFunc is the activation function
	aFunc func(z float64) float64
	// daFunc is the derivative of the activation function.
	daFunc func(z float64) float64
}

func (n *Network) MarshalJSON() ([]byte, error) {
	var buf bytes.Buffer
	err := json.NewEncoder(&buf).Encode(struct {
		W            [][][]float64 `json:"W"`
		B            [][]float64   `json:"B"`
		D            [][]float64   `json:"D"`
		Z            [][]float64   `json:"Z"`
		L            int           `json:"L"`
		LS           []int         `json:"LS"`
		ActivationID int           `json:"ActivationID"`
	}{
		W:            n.w,
		B:            n.b,
		D:            n.d,
		Z:            n.z,
		L:            n.l,
		LS:           n.ls,
		ActivationID: int(n.activationID),
	})
	if err != nil {
		return nil, err
	}

	return buf.Bytes(), nil
}

func (n *Network) UnmarshalJSON(data []byte) error {
	var en struct {
		W            [][][]float64 `json:"W"`
		B            [][]float64   `json:"B"`
		D            [][]float64   `json:"D"`
		Z            [][]float64   `json:"Z"`
		L            int           `json:"L"`
		LS           []int         `json:"LS"`
		ActivationID int           `json:"ActivationID"`
	}

	if err := json.Unmarshal(data, &en); err != nil {
		return err
	}

	n.w = en.W
	n.b = en.B
	n.d = en.D
	n.z = en.Z
	n.l = en.L
	n.ls = en.LS
	n.activationID = ActivationFunction(en.ActivationID)
	n.aFunc = functionPairs[n.activationID][0]
	n.daFunc = functionPairs[n.activationID][1]

	return nil
}

// NewNetwork is for creating a new network with the defined layers.
func NewNetwork(ls []int, activationFunc ActivationFunction) (*Network, error) {
	if len(ls) < 3 {
		return nil, ErrNotEnoughLayers
	}

	n := Network{
		l:            len(ls) - 1,
		ls:           ls[1:],
		activationID: activationFunc,
		aFunc:        functionPairs[activationFunc][0],
		daFunc:       functionPairs[activationFunc][1],
	}

	// init weights
	n.w = make([][][]float64, n.l)
	n.w[0] = make([][]float64, ls[0])
	for i := 0; i < ls[0]; i++ {
		n.w[0][i] = make([]float64, n.ls[0])
		for j := 0; j < n.ls[0]; j++ {
			n.w[0][i][j] = rand.Float64()
		}
	}
	for l := 1; l < n.l; l++ {
		n.w[l] = make([][]float64, n.ls[l-1])
		for i := 0; i < n.ls[l-1]; i++ {
			n.w[l][i] = make([]float64, n.ls[l])
			for j := 0; j < n.ls[l]; j++ {
				n.w[l][i][j] = rand.Float64()
			}
		}
	}

	// init biases, deltas, z(s)
	n.b = make([][]float64, n.l)
	n.d = make([][]float64, n.l)
	n.z = make([][]float64, n.l)
	for l := 0; l < n.l; l++ {
		n.b[l] = make([]float64, n.ls[l])
		for i := 0; i < n.ls[l]; i++ {
			n.b[l][i] = rand.Float64()
		}
		n.d[l] = make([]float64, n.ls[l])
		n.z[l] = make([]float64, n.ls[l])
	}

	return &n, nil
}

func (n *Network) dw(l, i, j int, eta float64) float64 {
	return -eta * n.d[l][j] * n.a(l-1, i)
}

func (n *Network) a(l, j int) float64 {
	return n.aFunc(n.z[l][j])
}

// Train is for training the network with the specified dataset, epoch and learning rate. The last bool parameter is for
// tracking where the training is. It'll log each epoch.
func (n *Network) Train(trainingData [][][]float64, epochs int, lrate float64, debug bool) {
	for e := 0; e < epochs; e++ {
		for _, xy := range trainingData {
			n.backpropagate(xy, lrate)
		}
		if debug {
			log.Println("Epoch:", e+1, "/", epochs)
		}
	}
}

func (n *Network) backpropagate(xy [][]float64, eta float64) {
	x := xy[0]
	y := xy[1]
	// define z values
	_ = n.feedforward(x)

	// define the output deltas
	for j := 0; j < len(n.d[len(n.d)-1]); j++ {
		n.d[len(n.d)-1][j] = (n.a(len(n.d)-1, j) - y[j]) * n.daFunc(n.z[len(n.d)-1][j])
	}

	// define the inner deltas
	for l := len(n.d) - 2; l >= 0; l-- {
		for j := 0; j < len(n.d[l]); j++ {
			n.d[l][j] = n.delta(l, j)
		}
	}

	// update weights
	for i := 0; i < len(n.w[0]); i++ {
		for j := 0; j < len(n.w[0][i]); j++ {
			n.w[0][i][j] += -eta * n.d[0][j] * x[i]
		}
	}
	for l := 1; l < len(n.w); l++ {
		for i := 0; i < len(n.w[l]); i++ {
			for j := 0; j < len(n.w[l][i]); j++ {
				n.w[l][i][j] += n.dw(l, i, j, eta)
			}
		}
	}

	// update biases
	for l := 0; l < len(n.b); l++ {
		for j := 0; j < len(n.b[l]); j++ {
			n.b[l][j] += -eta * n.d[l][j]
		}
	}
}

// delta should only use in the back-propagation, otherwise it can return wrong value.
func (n *Network) delta(l, j int) float64 {
	var d float64
	for k := 0; k < n.ls[l+1]; k++ {
		d += n.d[l+1][k] * n.w[l+1][j][k] * n.daFunc(n.z[l][j])
	}
	return d
}

func (n *Network) feedforward(a []float64) []float64 {
	for l := 0; l < n.l; l++ {
		atemp := make([]float64, n.ls[l])
		for j := 0; j < n.ls[l]; j++ {
			n.z[l][j] = 0
			for i := 0; i < len(a); i++ {
				n.z[l][j] += n.w[l][i][j] * a[i]
			}
			n.z[l][j] += n.b[l][j]
			atemp[j] = n.aFunc(n.z[l][j])
		}
		a = atemp
	}
	return a
}

// Predict calculates the output for the given input.
func (n *Network) Predict(input []float64) []float64 {
	return n.feedforward(input)
}

// Export will serialize the network, and write it to the provided writer.
func (n *Network) Export(w io.Writer) error {
	return json.NewEncoder(w).Encode(n)
}

// LoadFrom will load a network from the provided reader.
func Load(r io.Reader) (*Network, error) {
	var n Network
	if err := json.NewDecoder(r).Decode(&n); err != nil {
		return nil, err
	}

	return &n, nil
}

// LoadFrom will load a network from the provided byte slice.
func LoadFrom(bs []byte) (*Network, error) {
	buf := bytes.NewBuffer(bs)
	return Load(buf)
}
<commit_msg>created concrete JSON struct for marshal and unmarshalling<commit_after>package fonet

import (
	"bytes"
	"encoding/json"
	"errors"
	"io"
	"log"
	"math/rand"
	"time"
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

var (
	// ErrNotEnoughLayers is returned when trying to create a new network with too few layers.
	ErrNotEnoughLayers = errors.New("too few layers, minimum of 3 required")
)

// Network is containing all the needed settings/variables.
type Network struct {
	// w is the weights of the network.
	w [][][]float64
	// b is the biases of the network.
	b [][]float64
	// d is the delta values for each layer.
	d [][]float64
	// z is the z values for each layer.
	z [][]float64
	// l holds the number of layers in the network.
	l int
	// ls is the number of neurons in each layer.
	ls []int
	// activationID is the ID of the activation function used.  This is stored for serialization purposes.
	activationID ActivationFunction
	// aFunc is the activation function
	aFunc func(z float64) float64
	// daFunc is the derivative of the activation function.
	daFunc func(z float64) float64
}

type jsonNetwork struct {
	W            [][][]float64 `json:"W"`
	B            [][]float64   `json:"B"`
	D            [][]float64   `json:"D"`
	Z            [][]float64   `json:"Z"`
	L            int           `json:"L"`
	LS           []int         `json:"LS"`
	ActivationID int           `json:"ActivationID"`
}

func (n *Network) MarshalJSON() ([]byte, error) {
	var buf bytes.Buffer
	err := json.NewEncoder(&buf).Encode(jsonNetwork{
		W:            n.w,
		B:            n.b,
		D:            n.d,
		Z:            n.z,
		L:            n.l,
		LS:           n.ls,
		ActivationID: int(n.activationID),
	})
	if err != nil {
		return nil, err
	}

	return buf.Bytes(), nil
}

func (n *Network) UnmarshalJSON(data []byte) error {
	var en jsonNetwork
	if err := json.Unmarshal(data, &en); err != nil {
		return err
	}

	n.w = en.W
	n.b = en.B
	n.d = en.D
	n.z = en.Z
	n.l = en.L
	n.ls = en.LS
	n.activationID = ActivationFunction(en.ActivationID)
	n.aFunc = functionPairs[n.activationID][0]
	n.daFunc = functionPairs[n.activationID][1]

	return nil
}

// NewNetwork is for creating a new network with the defined layers.
func NewNetwork(ls []int, activationFunc ActivationFunction) (*Network, error) {
	if len(ls) < 3 {
		return nil, ErrNotEnoughLayers
	}

	n := Network{
		l:            len(ls) - 1,
		ls:           ls[1:],
		activationID: activationFunc,
		aFunc:        functionPairs[activationFunc][0],
		daFunc:       functionPairs[activationFunc][1],
	}

	// init weights
	n.w = make([][][]float64, n.l)
	n.w[0] = make([][]float64, ls[0])
	for i := 0; i < ls[0]; i++ {
		n.w[0][i] = make([]float64, n.ls[0])
		for j := 0; j < n.ls[0]; j++ {
			n.w[0][i][j] = rand.Float64()
		}
	}
	for l := 1; l < n.l; l++ {
		n.w[l] = make([][]float64, n.ls[l-1])
		for i := 0; i < n.ls[l-1]; i++ {
			n.w[l][i] = make([]float64, n.ls[l])
			for j := 0; j < n.ls[l]; j++ {
				n.w[l][i][j] = rand.Float64()
			}
		}
	}

	// init biases, deltas, z(s)
	n.b = make([][]float64, n.l)
	n.d = make([][]float64, n.l)
	n.z = make([][]float64, n.l)
	for l := 0; l < n.l; l++ {
		n.b[l] = make([]float64, n.ls[l])
		for i := 0; i < n.ls[l]; i++ {
			n.b[l][i] = rand.Float64()
		}
		n.d[l] = make([]float64, n.ls[l])
		n.z[l] = make([]float64, n.ls[l])
	}

	return &n, nil
}

func (n *Network) dw(l, i, j int, eta float64) float64 {
	return -eta * n.d[l][j] * n.a(l-1, i)
}

func (n *Network) a(l, j int) float64 {
	return n.aFunc(n.z[l][j])
}

// Train is for training the network with the specified dataset, epoch and learning rate. The last bool parameter is for
// tracking where the training is. It'll log each epoch.
func (n *Network) Train(trainingData [][][]float64, epochs int, lrate float64, debug bool) {
	for e := 0; e < epochs; e++ {
		for _, xy := range trainingData {
			n.backpropagate(xy, lrate)
		}
		if debug {
			log.Println("Epoch:", e+1, "/", epochs)
		}
	}
}

func (n *Network) backpropagate(xy [][]float64, eta float64) {
	x := xy[0]
	y := xy[1]
	// define z values
	_ = n.feedforward(x)

	// define the output deltas
	for j := 0; j < len(n.d[len(n.d)-1]); j++ {
		n.d[len(n.d)-1][j] = (n.a(len(n.d)-1, j) - y[j]) * n.daFunc(n.z[len(n.d)-1][j])
	}

	// define the inner deltas
	for l := len(n.d) - 2; l >= 0; l-- {
		for j := 0; j < len(n.d[l]); j++ {
			n.d[l][j] = n.delta(l, j)
		}
	}

	// update weights
	for i := 0; i < len(n.w[0]); i++ {
		for j := 0; j < len(n.w[0][i]); j++ {
			n.w[0][i][j] += -eta * n.d[0][j] * x[i]
		}
	}
	for l := 1; l < len(n.w); l++ {
		for i := 0; i < len(n.w[l]); i++ {
			for j := 0; j < len(n.w[l][i]); j++ {
				n.w[l][i][j] += n.dw(l, i, j, eta)
			}
		}
	}

	// update biases
	for l := 0; l < len(n.b); l++ {
		for j := 0; j < len(n.b[l]); j++ {
			n.b[l][j] += -eta * n.d[l][j]
		}
	}
}

// delta should only use in the back-propagation, otherwise it can return wrong value.
func (n *Network) delta(l, j int) float64 {
	var d float64
	for k := 0; k < n.ls[l+1]; k++ {
		d += n.d[l+1][k] * n.w[l+1][j][k] * n.daFunc(n.z[l][j])
	}
	return d
}

func (n *Network) feedforward(a []float64) []float64 {
	for l := 0; l < n.l; l++ {
		atemp := make([]float64, n.ls[l])
		for j := 0; j < n.ls[l]; j++ {
			n.z[l][j] = 0
			for i := 0; i < len(a); i++ {
				n.z[l][j] += n.w[l][i][j] * a[i]
			}
			n.z[l][j] += n.b[l][j]
			atemp[j] = n.aFunc(n.z[l][j])
		}
		a = atemp
	}
	return a
}

// Predict calculates the output for the given input.
func (n *Network) Predict(input []float64) []float64 {
	return n.feedforward(input)
}

// Export will serialize the network, and write it to the provided writer.
func (n *Network) Export(w io.Writer) error {
	return json.NewEncoder(w).Encode(n)
}

// LoadFrom will load a network from the provided reader.
func Load(r io.Reader) (*Network, error) {
	var n Network
	if err := json.NewDecoder(r).Decode(&n); err != nil {
		return nil, err
	}

	return &n, nil
}

// LoadFrom will load a network from the provided byte slice.
func LoadFrom(bs []byte) (*Network, error) {
	buf := bytes.NewBuffer(bs)
	return Load(buf)
}
<|endoftext|>


<commit_before>package wireless

// This file contains components from github.com/brlbil/wpaclient
//
// Copyright (c) 2017 Birol Bilgin
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// nd/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// UT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

// NewNamedNetwork will create a new network with the given parameters
func NewNamedNetwork(name, ssid, psk string) Network {
	return Network{IDStr: name, SSID: ssid, PSK: psk}
}

// NewNetwork will create a new network with the given parameters
func NewNetwork(ssid, psk string) Network {
	return NewNamedNetwork(ssid, ssid, psk)
}

// NewDisabledNetwork will create a new disabled network with the given parameters
func NewDisabledNetwork(ssid, psk string) Network {
	n := NewNamedNetwork(ssid, ssid, psk)
	n.Flags = append(n.Flags, "DISABLED")
	return n
}

// Network represents a known network
type Network struct {
	ID       int      `json:"id"`
	IDStr    string   `json:"id_str"`
	KeyMgmt  string   `json:"key_mgmt"`
	SSID     string   `json:"ssid"`
	BSSID    string   `json:"bssid"`
	ScanSSID bool     `json:"scan_ssid"`
	PSK      string   `json:"psk"`
	Flags    []string `json:"flags"`
}

// Connector is interfce than can connect a network
type Connector interface {
	Connect(Network) error
}

type Connectable interface {
	SetCmds() []string
}

// IsDisabled will return true if the network is disabled
func (net Network) IsDisabled() bool {
	for _, f := range net.Flags {
		if f == "DISABLED" {
			return true
		}
	}
	return false
}

// IsCurrent will return true if the network is the currently active one
func (net Network) IsCurrent() bool {
	for _, f := range net.Flags {
		if f == "CURRENT" {
			return true
		}
	}
	return false
}

type attributeGetter interface {
	GetNetworkAttr(int, string) (string, error)
}

func (net *Network) populateAttrs(cl attributeGetter) error {
	v, err := cl.GetNetworkAttr(net.ID, "ssid")
	if err != nil {
		return err
	}
	net.SSID = unquote(v)

	v, err = cl.GetNetworkAttr(net.ID, "id_str")
	if err != nil {
		return err
	}
	net.IDStr = unquote(v)

	v, err = cl.GetNetworkAttr(net.ID, "key_mgmt")
	if err != nil {
		return err
	}
	net.KeyMgmt = v

	v, err = cl.GetNetworkAttr(net.ID, "scan_ssid")
	if err != nil {
		return err
	}
	if v == "1" {
		net.ScanSSID = true
	}

	v, err = cl.GetNetworkAttr(net.ID, "disabled")
	if err != nil {
		return err
	}
	if v == "1" {
		net.Flags = append(net.Flags, "DISABLED")
	}

	return nil
}

// Disable or enabled the network
func (net Network) Disable(on bool) {
	var idx int
	var found bool
	for i, f := range net.Flags {
		if f == "DISABLED" {
			found = true
			idx = i
			break
		}
	}

	if on && !found {
		net.Flags = append(net.Flags, "DISABLED")
		return
	}

	net.Flags = append(net.Flags[:idx], net.Flags[idx:]...)
}

// Connect will connect the network to the given connector
func (net Network) Connect(cl Connector) error {
	return cl.Connect(net)
}

// Networks models a collection of networks
type Networks []Network

// FindByIDStr will find a network by the given ID Str or return false
func (nets Networks) FindByIDStr(idStr string) (Network, bool) {
	for _, n := range nets {
		if n.IDStr == idStr {
			return n, true
		}
	}

	return Network{}, false
}

// FindBySSID will find a network by the given SSID or return false
func (nets Networks) FindBySSID(ssid string) (Network, bool) {
	for _, n := range nets {
		if n.SSID == ssid {
			return n, true
		}
	}

	return Network{}, false
}

// FindCurrent will find the current network or return false
func (nets Networks) FindCurrent() (Network, bool) {
	for _, n := range nets {
		if n.IsCurrent() {
			return n, true
		}
	}

	return Network{}, false
}

func setCmds(net Network) [][]string {
	cmds := [][]string{}
	cmds = append(cmds, []string{CmdSetNetwork, itoa(net.ID), "ssid", quote(net.SSID)})
	if net.IDStr != "" {
		cmds = append(cmds, []string{CmdSetNetwork, itoa(net.ID), "id_str", quote(net.IDStr)})
	}

	if net.ScanSSID {
		cmds = append(cmds, []string{CmdSetNetwork, itoa(net.ID), "scan_ssid", "1'"})
	}

	for _, f := range net.Flags {
		switch f {
		case "DISABLED":
			cmds = append(cmds, []string{CmdSetNetwork, itoa(net.ID), "disabled", "1"})
		}
	}

	if net.PSK == "" {
		cmds = append(cmds, []string{CmdSetNetwork, itoa(net.ID), "key_mgmt", "None"})
	} else {
		cmds = append(cmds, []string{CmdSetNetwork, itoa(net.ID), "psk", quote(net.PSK)})
	}

	return cmds
}
<commit_msg>remove some redudnant stuff<commit_after>package wireless

// This file contains components from github.com/brlbil/wpaclient
//
// Copyright (c) 2017 Birol Bilgin
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// nd/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// UT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

// NewNamedNetwork will create a new network with the given parameters
func NewNamedNetwork(name, ssid, psk string) Network {
	return Network{IDStr: name, SSID: ssid, PSK: psk}
}

// NewNetwork will create a new network with the given parameters
func NewNetwork(ssid, psk string) Network {
	return NewNamedNetwork(ssid, ssid, psk)
}

// NewDisabledNetwork will create a new disabled network with the given parameters
func NewDisabledNetwork(ssid, psk string) Network {
	n := NewNamedNetwork(ssid, ssid, psk)
	n.Flags = append(n.Flags, "DISABLED")
	return n
}

// Network represents a known network
type Network struct {
	ID       int      `json:"id"`
	IDStr    string   `json:"id_str"`
	KeyMgmt  string   `json:"key_mgmt"`
	SSID     string   `json:"ssid"`
	BSSID    string   `json:"bssid"`
	ScanSSID bool     `json:"scan_ssid"`
	PSK      string   `json:"psk"`
	Flags    []string `json:"flags"`
}

// IsDisabled will return true if the network is disabled
func (net Network) IsDisabled() bool {
	for _, f := range net.Flags {
		if f == "DISABLED" {
			return true
		}
	}
	return false
}

// IsCurrent will return true if the network is the currently active one
func (net Network) IsCurrent() bool {
	for _, f := range net.Flags {
		if f == "CURRENT" {
			return true
		}
	}
	return false
}

type attributeGetter interface {
	GetNetworkAttr(int, string) (string, error)
}

func (net *Network) populateAttrs(cl attributeGetter) error {
	v, err := cl.GetNetworkAttr(net.ID, "ssid")
	if err != nil {
		return err
	}
	net.SSID = unquote(v)

	v, err = cl.GetNetworkAttr(net.ID, "id_str")
	if err != nil {
		return err
	}
	net.IDStr = unquote(v)

	v, err = cl.GetNetworkAttr(net.ID, "key_mgmt")
	if err != nil {
		return err
	}
	net.KeyMgmt = v

	v, err = cl.GetNetworkAttr(net.ID, "scan_ssid")
	if err != nil {
		return err
	}
	if v == "1" {
		net.ScanSSID = true
	}

	v, err = cl.GetNetworkAttr(net.ID, "disabled")
	if err != nil {
		return err
	}
	if v == "1" {
		net.Flags = append(net.Flags, "DISABLED")
	}

	return nil
}

// Disable or enabled the network
func (net Network) Disable(on bool) {
	var idx int
	var found bool
	for i, f := range net.Flags {
		if f == "DISABLED" {
			found = true
			idx = i
			break
		}
	}

	if on && !found {
		net.Flags = append(net.Flags, "DISABLED")
		return
	}

	net.Flags = append(net.Flags[:idx], net.Flags[idx:]...)
}

// Networks models a collection of networks
type Networks []Network

// FindByIDStr will find a network by the given ID Str or return false
func (nets Networks) FindByIDStr(idStr string) (Network, bool) {
	for _, n := range nets {
		if n.IDStr == idStr {
			return n, true
		}
	}

	return Network{}, false
}

// FindBySSID will find a network by the given SSID or return false
func (nets Networks) FindBySSID(ssid string) (Network, bool) {
	for _, n := range nets {
		if n.SSID == ssid {
			return n, true
		}
	}

	return Network{}, false
}

// FindCurrent will find the current network or return false
func (nets Networks) FindCurrent() (Network, bool) {
	for _, n := range nets {
		if n.IsCurrent() {
			return n, true
		}
	}

	return Network{}, false
}

func setCmds(net Network) [][]string {
	cmds := [][]string{}
	cmds = append(cmds, []string{CmdSetNetwork, itoa(net.ID), "ssid", quote(net.SSID)})
	if net.IDStr != "" {
		cmds = append(cmds, []string{CmdSetNetwork, itoa(net.ID), "id_str", quote(net.IDStr)})
	}

	if net.ScanSSID {
		cmds = append(cmds, []string{CmdSetNetwork, itoa(net.ID), "scan_ssid", "1'"})
	}

	for _, f := range net.Flags {
		switch f {
		case "DISABLED":
			cmds = append(cmds, []string{CmdSetNetwork, itoa(net.ID), "disabled", "1"})
		}
	}

	if net.PSK == "" {
		cmds = append(cmds, []string{CmdSetNetwork, itoa(net.ID), "key_mgmt", "None"})
	} else {
		cmds = append(cmds, []string{CmdSetNetwork, itoa(net.ID), "psk", quote(net.PSK)})
	}

	return cmds
}
<|endoftext|>


<commit_before>package git

import (
	"path/filepath"
	"strings"

	"gopkg.in/src-d/go-git.v4/plumbing"
	"gopkg.in/src-d/go-git.v4/plumbing/filemode"
	"gopkg.in/src-d/go-git.v4/plumbing/format/index"
	"gopkg.in/src-d/go-git.v4/plumbing/object"
	"gopkg.in/src-d/go-git.v4/storage"

	"gopkg.in/src-d/go-billy.v3"
)

// Commit stores the current contents of the index in a new commit along with
// a log message from the user describing the changes.
func (w *Worktree) Commit(msg string, opts *CommitOptions) (plumbing.Hash, error) {
	if err := opts.Validate(w.r); err != nil {
		return plumbing.ZeroHash, err
	}

	if opts.All {
		if err := w.autoAddModifiedAndDeleted(); err != nil {
			return plumbing.ZeroHash, err
		}
	}

	idx, err := w.r.Storer.Index()
	if err != nil {
		return plumbing.ZeroHash, err
	}

	h := &buildTreeHelper{
		fs: w.fs,
		s:  w.r.Storer,
	}

	tree, err := h.BuildTree(idx)
	if err != nil {
		return plumbing.ZeroHash, err
	}

	commit, err := w.buildCommitObject(msg, opts, tree)
	if err != nil {
		return plumbing.ZeroHash, err
	}

	return commit, w.updateHEAD(commit)
}

func (w *Worktree) autoAddModifiedAndDeleted() error {
	s, err := w.Status()
	if err != nil {
		return err
	}

	for path, fs := range s {
		if fs.Worktree != Modified && fs.Worktree != Deleted {
			continue
		}

		if _, err := w.Add(path); err != nil {
			return err
		}

	}

	return nil
}

func (w *Worktree) updateHEAD(commit plumbing.Hash) error {
	head, err := w.r.Storer.Reference(plumbing.HEAD)
	if err != nil {
		return err
	}

	name := plumbing.HEAD
	if head.Type() != plumbing.HashReference {
		name = head.Target()
	}

	ref := plumbing.NewHashReference(name, commit)
	return w.r.Storer.SetReference(ref)
}

func (w *Worktree) buildCommitObject(msg string, opts *CommitOptions, tree plumbing.Hash) (plumbing.Hash, error) {
	commit := &object.Commit{
		Author:       *opts.Author,
		Committer:    *opts.Committer,
		Message:      msg,
		TreeHash:     tree,
		ParentHashes: opts.Parents,
	}

	obj := w.r.Storer.NewEncodedObject()
	if err := commit.Encode(obj); err != nil {
		return plumbing.ZeroHash, err
	}
	return w.r.Storer.SetEncodedObject(obj)
}

// buildTreeHelper converts a given index.Index file into multiple git objects
// reading the blobs from the given filesystem and creating the trees from the
// index structure. The created objects are pushed to a given Storer.
type buildTreeHelper struct {
	fs billy.Filesystem
	s  storage.Storer

	trees   map[string]*object.Tree
	entries map[string]*object.TreeEntry
}

// BuildTree builds the tree objects and push its to the storer, the hash
// of the root tree is returned.
func (h *buildTreeHelper) BuildTree(idx *index.Index) (plumbing.Hash, error) {
	const rootNode = ""
	h.trees = map[string]*object.Tree{rootNode: {}}
	h.entries = map[string]*object.TreeEntry{}

	for _, e := range idx.Entries {
		if err := h.commitIndexEntry(e); err != nil {
			return plumbing.ZeroHash, err
		}
	}

	return h.copyTreeToStorageRecursive(rootNode, h.trees[rootNode])
}

func (h *buildTreeHelper) commitIndexEntry(e *index.Entry) error {
	parts := strings.Split(e.Name, string(filepath.Separator))

	var path string
	for _, part := range parts {
		parent := path
		path = filepath.Join(path, part)

		h.doBuildTree(e, parent, path)
	}

	return nil
}

func (h *buildTreeHelper) doBuildTree(e *index.Entry, parent, path string) {
	if _, ok := h.trees[path]; ok {
		return
	}

	if _, ok := h.entries[path]; ok {
		return
	}

	te := object.TreeEntry{Name: filepath.Base(path)}

	if path == e.Name {
		te.Mode = e.Mode
		te.Hash = e.Hash
	} else {
		te.Mode = filemode.Dir
		h.trees[path] = &object.Tree{}
	}

	h.trees[parent].Entries = append(h.trees[parent].Entries, te)
}

func (h *buildTreeHelper) copyTreeToStorageRecursive(parent string, t *object.Tree) (plumbing.Hash, error) {
	for i, e := range t.Entries {
		if e.Mode != filemode.Dir && !e.Hash.IsZero() {
			continue
		}

		path := filepath.Join(parent, e.Name)

		var err error
		e.Hash, err = h.copyTreeToStorageRecursive(path, h.trees[path])
		if err != nil {
			return plumbing.ZeroHash, err
		}

		t.Entries[i] = e
	}

	o := h.s.NewEncodedObject()
	if err := t.Encode(o); err != nil {
		return plumbing.ZeroHash, err
	}

	return h.s.SetEncodedObject(o)
}
<commit_msg>worktree: commit, use path package instead of filepath<commit_after>package git

import (
	"path"
	"strings"

	"gopkg.in/src-d/go-git.v4/plumbing"
	"gopkg.in/src-d/go-git.v4/plumbing/filemode"
	"gopkg.in/src-d/go-git.v4/plumbing/format/index"
	"gopkg.in/src-d/go-git.v4/plumbing/object"
	"gopkg.in/src-d/go-git.v4/storage"

	"gopkg.in/src-d/go-billy.v3"
)

// Commit stores the current contents of the index in a new commit along with
// a log message from the user describing the changes.
func (w *Worktree) Commit(msg string, opts *CommitOptions) (plumbing.Hash, error) {
	if err := opts.Validate(w.r); err != nil {
		return plumbing.ZeroHash, err
	}

	if opts.All {
		if err := w.autoAddModifiedAndDeleted(); err != nil {
			return plumbing.ZeroHash, err
		}
	}

	idx, err := w.r.Storer.Index()
	if err != nil {
		return plumbing.ZeroHash, err
	}

	h := &buildTreeHelper{
		fs: w.fs,
		s:  w.r.Storer,
	}

	tree, err := h.BuildTree(idx)
	if err != nil {
		return plumbing.ZeroHash, err
	}

	commit, err := w.buildCommitObject(msg, opts, tree)
	if err != nil {
		return plumbing.ZeroHash, err
	}

	return commit, w.updateHEAD(commit)
}

func (w *Worktree) autoAddModifiedAndDeleted() error {
	s, err := w.Status()
	if err != nil {
		return err
	}

	for path, fs := range s {
		if fs.Worktree != Modified && fs.Worktree != Deleted {
			continue
		}

		if _, err := w.Add(path); err != nil {
			return err
		}

	}

	return nil
}

func (w *Worktree) updateHEAD(commit plumbing.Hash) error {
	head, err := w.r.Storer.Reference(plumbing.HEAD)
	if err != nil {
		return err
	}

	name := plumbing.HEAD
	if head.Type() != plumbing.HashReference {
		name = head.Target()
	}

	ref := plumbing.NewHashReference(name, commit)
	return w.r.Storer.SetReference(ref)
}

func (w *Worktree) buildCommitObject(msg string, opts *CommitOptions, tree plumbing.Hash) (plumbing.Hash, error) {
	commit := &object.Commit{
		Author:       *opts.Author,
		Committer:    *opts.Committer,
		Message:      msg,
		TreeHash:     tree,
		ParentHashes: opts.Parents,
	}

	obj := w.r.Storer.NewEncodedObject()
	if err := commit.Encode(obj); err != nil {
		return plumbing.ZeroHash, err
	}
	return w.r.Storer.SetEncodedObject(obj)
}

// buildTreeHelper converts a given index.Index file into multiple git objects
// reading the blobs from the given filesystem and creating the trees from the
// index structure. The created objects are pushed to a given Storer.
type buildTreeHelper struct {
	fs billy.Filesystem
	s  storage.Storer

	trees   map[string]*object.Tree
	entries map[string]*object.TreeEntry
}

// BuildTree builds the tree objects and push its to the storer, the hash
// of the root tree is returned.
func (h *buildTreeHelper) BuildTree(idx *index.Index) (plumbing.Hash, error) {
	const rootNode = ""
	h.trees = map[string]*object.Tree{rootNode: {}}
	h.entries = map[string]*object.TreeEntry{}

	for _, e := range idx.Entries {
		if err := h.commitIndexEntry(e); err != nil {
			return plumbing.ZeroHash, err
		}
	}

	return h.copyTreeToStorageRecursive(rootNode, h.trees[rootNode])
}

func (h *buildTreeHelper) commitIndexEntry(e *index.Entry) error {
	parts := strings.Split(e.Name, "/")

	var fullpath string
	for _, part := range parts {
		parent := fullpath
		fullpath = path.Join(fullpath, part)

		h.doBuildTree(e, parent, fullpath)
	}

	return nil
}

func (h *buildTreeHelper) doBuildTree(e *index.Entry, parent, fullpath string) {
	if _, ok := h.trees[fullpath]; ok {
		return
	}

	if _, ok := h.entries[fullpath]; ok {
		return
	}

	te := object.TreeEntry{Name: path.Base(fullpath)}

	if fullpath == e.Name {
		te.Mode = e.Mode
		te.Hash = e.Hash
	} else {
		te.Mode = filemode.Dir
		h.trees[fullpath] = &object.Tree{}
	}

	h.trees[parent].Entries = append(h.trees[parent].Entries, te)
}

func (h *buildTreeHelper) copyTreeToStorageRecursive(parent string, t *object.Tree) (plumbing.Hash, error) {
	for i, e := range t.Entries {
		if e.Mode != filemode.Dir && !e.Hash.IsZero() {
			continue
		}

		path := path.Join(parent, e.Name)

		var err error
		e.Hash, err = h.copyTreeToStorageRecursive(path, h.trees[path])
		if err != nil {
			return plumbing.ZeroHash, err
		}

		t.Entries[i] = e
	}

	o := h.s.NewEncodedObject()
	if err := t.Encode(o); err != nil {
		return plumbing.ZeroHash, err
	}

	return h.s.SetEncodedObject(o)
}
<|endoftext|>


<commit_before>// Copyright 2020 The Knative Authors

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or im
// See the License for the specific language governing permissions and
// limitations under the License.

package test

import (
	"strings"
	"time"

	"k8s.io/apimachinery/pkg/util/wait"
)

// LabelNamespaceForDefaultBroker adds label 'knative-eventing-injection=enabled' to the configured namespace
func LabelNamespaceForDefaultBroker(r *KnRunResultCollector) error {
	_, err := Kubectl{}.Run("label", "namespace", r.KnTest().Kn().Namespace(), "knative-eventing-injection=enabled")

	if err != nil {
		r.T().Fatalf("Error executing 'kubectl label namespace %s knative-eventing-injection=enabled'. Error: %s", r.KnTest().Kn().Namespace(), err.Error())
	}

	return wait.PollImmediate(10*time.Second, 5*time.Minute, func() (bool, error) {
		out, err := NewKubectl(r.KnTest().Kn().Namespace()).Run("get", "broker", "-o=jsonpath='{.items[0].status.conditions[?(@.type==\"Ready\")].status}'")
		if err != nil {
			return false, nil
		}

		return strings.Contains(out, "True"), nil
	})
}

// UnlabelNamespaceForDefaultBroker removes label 'knative-eventing-injection=enabled' from the configured namespace
func UnlabelNamespaceForDefaultBroker(r *KnRunResultCollector) {
	_, err := Kubectl{}.Run("label", "namespace", r.KnTest().Kn().Namespace(), "knative-eventing-injection-")
	if err != nil {
		r.T().Fatalf("Error executing 'kubectl label namespace %s knative-eventing-injection-'. Error: %s", r.KnTest().Kn().Namespace(), err.Error())
	}
}
<commit_msg>Use broker injection label key from trigger types (#917)<commit_after>// Copyright 2020 The Knative Authors

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or im
// See the License for the specific language governing permissions and
// limitations under the License.

package test

import (
	"strings"
	"time"

	"k8s.io/apimachinery/pkg/util/wait"
	"knative.dev/eventing/pkg/apis/eventing/v1beta1"
)

// LabelNamespaceForDefaultBroker adds label 'knative-eventing-injection=enabled' to the configured namespace
func LabelNamespaceForDefaultBroker(r *KnRunResultCollector) error {
	cmd := []string{"label", "namespace", r.KnTest().Kn().Namespace(), v1beta1.InjectionAnnotation + "=enabled"}
	_, err := Kubectl{}.Run(cmd...)

	if err != nil {
		r.T().Fatalf("error executing '%s': %s", strings.Join(cmd, " "), err.Error())
	}

	return wait.PollImmediate(10*time.Second, 5*time.Minute, func() (bool, error) {
		out, err := NewKubectl(r.KnTest().Kn().Namespace()).Run("get", "broker", "-o=jsonpath='{.items[0].status.conditions[?(@.type==\"Ready\")].status}'")
		if err != nil {
			return false, nil
		}

		return strings.Contains(out, "True"), nil
	})
}

// UnlabelNamespaceForDefaultBroker removes label 'knative-eventing-injection=enabled' from the configured namespace
func UnlabelNamespaceForDefaultBroker(r *KnRunResultCollector) {
	cmd := []string{"label", "namespace", r.KnTest().Kn().Namespace(), v1beta1.InjectionAnnotation + "-"}
	_, err := Kubectl{}.Run(cmd...)
	if err != nil {
		r.T().Fatalf("error executing '%s': %s", strings.Join(cmd, " "), err.Error())
	}
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package note provides types and functions for interacting with a note maps
// data storage system.
package note

import (
	"math/rand"
	"strconv"
)

//go:generate go run generate_id_ot.go

type String []rune

func (xs String) String() string { return string(xs) }

// ID is the type of values that identify note.
type ID string

// RandomID returns a pseudo-random ID using package math/rand.
func RandomID() ID {
	return ID(strconv.FormatUint(rand.Uint64(), 10))
}

func (x ID) String() string { return string(x) }

type IDSlice []ID

func (ids IDSlice) String() string {
	s := "["
	for i, id := range ids {
		if i > 0 {
			s += ","
		}
		s += string(id)
	}
	return s + "]"
}
<commit_msg>note: remove the String type<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package note provides types and functions for interacting with a note maps
// data storage system.
package note

import (
	"math/rand"
	"strconv"
)

//go:generate go run generate_id_ot.go

// ID is the type of values that identify note.
type ID string

// RandomID returns a pseudo-random ID using package math/rand.
func RandomID() ID {
	return ID(strconv.FormatUint(rand.Uint64(), 10))
}

func (x ID) String() string { return string(x) }

type IDSlice []ID

func (ids IDSlice) String() string {
	s := "["
	for i, id := range ids {
		if i > 0 {
			s += ","
		}
		s += string(id)
	}
	return s + "]"
}
<|endoftext|>


<commit_before>package is

import (
	"path/filepath"
	"reflect"
	"runtime"
	"testing"
)

type benchmarkCase struct {
	function func(string) bool
	caseName string
	param    string
}

var (
	benchmarkFuncs = []benchmarkCase{
		// Alpha
		benchmarkCase{Alpha, "Empty", ""},
		benchmarkCase{Alpha, "Space", " "},
		benchmarkCase{Alpha, "False", "abc!!!"},
		benchmarkCase{Alpha, "True", "abc"},
		//UTFLetter
		benchmarkCase{UTFLetter, "Empty", ""},
		benchmarkCase{UTFLetter, "Space", " "},
		benchmarkCase{UTFLetter, "False", "\u0026"}, //UTF-8(ASCII): &
		benchmarkCase{UTFLetter, "True", "abc"},
		// Alphanumeric
		benchmarkCase{Alphanumeric, "Empty", ""},
		benchmarkCase{Alphanumeric, "Space", " "},
		benchmarkCase{Alphanumeric, "False", "\u0026"}, //UTF-8(ASCII): &
		benchmarkCase{Alphanumeric, "True", "abc123"},
		// UTFLetterNumeric
		benchmarkCase{UTFLetterNumeric, "Empty", ""},
		benchmarkCase{UTFLetterNumeric, "Space", " "},
		benchmarkCase{UTFLetterNumeric, "False", "abc!!!"},
		benchmarkCase{UTFLetterNumeric, "True", "abc1"},
		// Numeric
		benchmarkCase{Numeric, "Empty", ""},
		benchmarkCase{Numeric, "Space", " "},
		benchmarkCase{Numeric, "False", "abc!!!"},
		benchmarkCase{Numeric, "True", "0123"},
		// UTFNumeric
		benchmarkCase{UTFNumeric, "Empty", ""},
		benchmarkCase{UTFNumeric, "Space", " "},
		benchmarkCase{UTFNumeric, "False", "abc!!!"},
		benchmarkCase{UTFNumeric, "True", "\u0030"}, //UTF-8(ASCII): 0
		// UTFDigit
		benchmarkCase{UTFDigit, "Empty", ""},
		benchmarkCase{UTFDigit, "Space", " "},
		benchmarkCase{UTFDigit, "False", "abc!!!"},
		benchmarkCase{UTFDigit, "True", "\u0030"}, //UTF-8(ASCII): 0
		// LowerCase
		benchmarkCase{LowerCase, "Empty", ""},
		benchmarkCase{LowerCase, "Space", " "},
		benchmarkCase{LowerCase, "False", "ABC"},
		benchmarkCase{LowerCase, "True", "abc"},
		// UpperCase
		benchmarkCase{UpperCase, "Empty", ""},
		benchmarkCase{UpperCase, "Space", " "},
		benchmarkCase{UpperCase, "False", "abc"},
		benchmarkCase{UpperCase, "True", "ABC"},
		// Int
		benchmarkCase{Int, "Empty", ""},
		benchmarkCase{Int, "Space", " "},
		benchmarkCase{Int, "False", "abc"},
		benchmarkCase{Int, "True", "000"},
		// Email
		benchmarkCase{Email, "Empty", ""},
		benchmarkCase{Email, "Space", " "},
		benchmarkCase{Email, "False", "@invalid.com"},
		benchmarkCase{Email, "True", "foo@bar.com"},
		// URL
		benchmarkCase{URL, "Empty", ""},
		benchmarkCase{URL, "Space", " "},
		benchmarkCase{URL, "False", "./rel/test/dir"},
		benchmarkCase{URL, "True", "http://foobar.org/"},
		// RequestURL
		benchmarkCase{RequestURL, "Empty", ""},
		benchmarkCase{RequestURL, "Space", " "},
		benchmarkCase{RequestURL, "False", "invalid."},
		benchmarkCase{RequestURL, "True", "http://foobar.org/"},
		// RequestURI
		benchmarkCase{RequestURI, "Empty", ""},
		benchmarkCase{RequestURI, "Space", " "},
		benchmarkCase{RequestURI, "False", "invalid."},
		benchmarkCase{RequestURI, "True", "http://foobar.org/"},
		// Float
		benchmarkCase{Float, "Empty", ""},
		benchmarkCase{Float, "Space", " "},
		benchmarkCase{Float, "False", "+1f"},
		benchmarkCase{Float, "True", "123.123"},
		// Hexadecimal
		benchmarkCase{Hexadecimal, "Empty", ""},
		benchmarkCase{Hexadecimal, "Space", " "},
		benchmarkCase{Hexadecimal, "False", ".."},
		benchmarkCase{Hexadecimal, "True", "deadBEEF"},
		// Hexcolor
		benchmarkCase{Hexcolor, "Empty", ""},
		benchmarkCase{Hexcolor, "Space", " "},
		benchmarkCase{Hexcolor, "False", "#ff12FG"},
		benchmarkCase{Hexcolor, "True", "#f00"},
		// RGBcolor
		benchmarkCase{RGBcolor, "Empty", ""},
		benchmarkCase{RGBcolor, "Space", " "},
		benchmarkCase{RGBcolor, "False", "rgba(0,31,255)"},
		benchmarkCase{RGBcolor, "True", "rgb(0,31,255)"},
	}
)

func getFuncName(f interface{}) string {
	n := runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()
	return filepath.Base(n)
}

func Benchmark(b *testing.B) {
	for _, bencCase := range benchmarkFuncs {
		name := getFuncName(bencCase.function) + "." + bencCase.caseName
		b.Run(name, func(b *testing.B) {
			b.ReportAllocs()
			b.ResetTimer()
			for i := 0; i < b.N; i++ {
				bencCase.function(bencCase.param)
			}
		})
	}
}
<commit_msg>Added build flag<commit_after>// +build go1.7

package is

import (
	"path/filepath"
	"reflect"
	"runtime"
	"testing"
)

type benchmarkCase struct {
	function func(string) bool
	caseName string
	param    string
}

var (
	benchmarkFuncs = []benchmarkCase{
		// Alpha
		benchmarkCase{Alpha, "Empty", ""},
		benchmarkCase{Alpha, "Space", " "},
		benchmarkCase{Alpha, "False", "abc!!!"},
		benchmarkCase{Alpha, "True", "abc"},
		//UTFLetter
		benchmarkCase{UTFLetter, "Empty", ""},
		benchmarkCase{UTFLetter, "Space", " "},
		benchmarkCase{UTFLetter, "False", "\u0026"}, //UTF-8(ASCII): &
		benchmarkCase{UTFLetter, "True", "abc"},
		// Alphanumeric
		benchmarkCase{Alphanumeric, "Empty", ""},
		benchmarkCase{Alphanumeric, "Space", " "},
		benchmarkCase{Alphanumeric, "False", "\u0026"}, //UTF-8(ASCII): &
		benchmarkCase{Alphanumeric, "True", "abc123"},
		// UTFLetterNumeric
		benchmarkCase{UTFLetterNumeric, "Empty", ""},
		benchmarkCase{UTFLetterNumeric, "Space", " "},
		benchmarkCase{UTFLetterNumeric, "False", "abc!!!"},
		benchmarkCase{UTFLetterNumeric, "True", "abc1"},
		// Numeric
		benchmarkCase{Numeric, "Empty", ""},
		benchmarkCase{Numeric, "Space", " "},
		benchmarkCase{Numeric, "False", "abc!!!"},
		benchmarkCase{Numeric, "True", "0123"},
		// UTFNumeric
		benchmarkCase{UTFNumeric, "Empty", ""},
		benchmarkCase{UTFNumeric, "Space", " "},
		benchmarkCase{UTFNumeric, "False", "abc!!!"},
		benchmarkCase{UTFNumeric, "True", "\u0030"}, //UTF-8(ASCII): 0
		// UTFDigit
		benchmarkCase{UTFDigit, "Empty", ""},
		benchmarkCase{UTFDigit, "Space", " "},
		benchmarkCase{UTFDigit, "False", "abc!!!"},
		benchmarkCase{UTFDigit, "True", "\u0030"}, //UTF-8(ASCII): 0
		// LowerCase
		benchmarkCase{LowerCase, "Empty", ""},
		benchmarkCase{LowerCase, "Space", " "},
		benchmarkCase{LowerCase, "False", "ABC"},
		benchmarkCase{LowerCase, "True", "abc"},
		// UpperCase
		benchmarkCase{UpperCase, "Empty", ""},
		benchmarkCase{UpperCase, "Space", " "},
		benchmarkCase{UpperCase, "False", "abc"},
		benchmarkCase{UpperCase, "True", "ABC"},
		// Int
		benchmarkCase{Int, "Empty", ""},
		benchmarkCase{Int, "Space", " "},
		benchmarkCase{Int, "False", "abc"},
		benchmarkCase{Int, "True", "000"},
		// Email
		benchmarkCase{Email, "Empty", ""},
		benchmarkCase{Email, "Space", " "},
		benchmarkCase{Email, "False", "@invalid.com"},
		benchmarkCase{Email, "True", "foo@bar.com"},
		// URL
		benchmarkCase{URL, "Empty", ""},
		benchmarkCase{URL, "Space", " "},
		benchmarkCase{URL, "False", "./rel/test/dir"},
		benchmarkCase{URL, "True", "http://foobar.org/"},
		// RequestURL
		benchmarkCase{RequestURL, "Empty", ""},
		benchmarkCase{RequestURL, "Space", " "},
		benchmarkCase{RequestURL, "False", "invalid."},
		benchmarkCase{RequestURL, "True", "http://foobar.org/"},
		// RequestURI
		benchmarkCase{RequestURI, "Empty", ""},
		benchmarkCase{RequestURI, "Space", " "},
		benchmarkCase{RequestURI, "False", "invalid."},
		benchmarkCase{RequestURI, "True", "http://foobar.org/"},
		// Float
		benchmarkCase{Float, "Empty", ""},
		benchmarkCase{Float, "Space", " "},
		benchmarkCase{Float, "False", "+1f"},
		benchmarkCase{Float, "True", "123.123"},
		// Hexadecimal
		benchmarkCase{Hexadecimal, "Empty", ""},
		benchmarkCase{Hexadecimal, "Space", " "},
		benchmarkCase{Hexadecimal, "False", ".."},
		benchmarkCase{Hexadecimal, "True", "deadBEEF"},
		// Hexcolor
		benchmarkCase{Hexcolor, "Empty", ""},
		benchmarkCase{Hexcolor, "Space", " "},
		benchmarkCase{Hexcolor, "False", "#ff12FG"},
		benchmarkCase{Hexcolor, "True", "#f00"},
		// RGBcolor
		benchmarkCase{RGBcolor, "Empty", ""},
		benchmarkCase{RGBcolor, "Space", " "},
		benchmarkCase{RGBcolor, "False", "rgba(0,31,255)"},
		benchmarkCase{RGBcolor, "True", "rgb(0,31,255)"},
	}
)

func getFuncName(f interface{}) string {
	n := runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()
	return filepath.Base(n)
}

func Benchmark(b *testing.B) {
	for _, bencCase := range benchmarkFuncs {
		name := getFuncName(bencCase.function) + "." + bencCase.caseName
		b.Run(name, func(b *testing.B) {
			b.ReportAllocs()
			b.ResetTimer()
			for i := 0; i < b.N; i++ {
				bencCase.function(bencCase.param)
			}
		})
	}
}
<|endoftext|>


<commit_before><commit_msg>Update compose.go<commit_after><|endoftext|>


<commit_before>package queue

import (
	"time"

	"github.com/gophergala2016/goad/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws"
)

// AggData type
type AggData struct {
	TotalReqs            int            `json:"total-reqs"`
	TotalTimedOut        int            `json:"total-timed-out"`
	TotalConnectionError int            `json:"total-conn-error"`
	AveTimeToFirst       int64          `json:"ave-time-to-first"`
	TotBytesRead         int            `json:"tot-bytes-read"`
	Statuses             map[string]int `json:"statuses"`
	AveTimeForReq        int64          `json:"ave-time-for-req"`
	AveReqPerSec         float32        `json:"ave-req-per-sec"`
	AveKBytesPerSec      float32        `json:"ave-kbytes-per-sec"`
	Slowest              int64          `json:"slowest"`
	Fastest              int64          `json:"fastest"`
	Region               string         `json:"region"`
	FatalError           string         `json:"fatal-error"`
}

// RegionsAggData type
type RegionsAggData struct {
	Regions               map[string]AggData
	TotalExpectedRequests uint
}

func addResult(data *AggData, result *AggData) {
	initialDataTot := data.TotalReqs
	initialDataTot64 := int64(data.TotalReqs)
	data.TotalReqs += result.TotalReqs
	data.TotalTimedOut += result.TotalTimedOut
	dataTot64 := int64(data.TotalReqs)
	resultTot64 := int64(result.TotalReqs)
	if dataTot64 > 0 {
		data.AveTimeToFirst = (data.AveTimeToFirst*initialDataTot64 + result.AveTimeToFirst*resultTot64) / dataTot64
		data.AveTimeForReq = (data.AveTimeForReq*initialDataTot64 + result.AveTimeForReq*resultTot64) / dataTot64
		data.AveReqPerSec = (data.AveReqPerSec*float32(initialDataTot) + result.AveReqPerSec*float32(result.TotalReqs)) / float32(data.TotalReqs)
	}
	data.TotBytesRead += result.TotBytesRead

	for key, value := range result.Statuses {
		data.Statuses[key] += value
	}

	if result.Slowest > data.Slowest {
		data.Slowest = result.Slowest
	}
	if data.Fastest == 0 || result.Fastest < data.Fastest {
		data.Fastest = result.Fastest
	}
}

// Aggregate listens for results and sends totals, closing the channel when done
func Aggregate(awsConfig *aws.Config, queueURL string, totalExpectedRequests uint) chan RegionsAggData {
	results := make(chan RegionsAggData)
	go aggregate(results, awsConfig, queueURL, totalExpectedRequests)
	return results
}

func aggregate(results chan RegionsAggData, awsConfig *aws.Config, queueURL string, totalExpectedRequests uint) {
	defer close(results)
	data := RegionsAggData{make(map[string]AggData), totalExpectedRequests}

	adaptor := NewSQSAdaptor(awsConfig, queueURL)
	timeoutStart := time.Now()
	for {
		result := adaptor.Receive()
		if result != nil {
			regionData, ok := data.Regions[result.Region]
			if !ok {
				regionData.Statuses = make(map[string]int)
				regionData.Region = result.Region
			}
			addResult(&regionData, result)
			data.Regions[result.Region] = regionData
			results <- data
			timeoutStart = time.Now()
		} else {
			waited := time.Since(timeoutStart)
			if waited.Seconds() > 20 {
				break
			}
		}
	}
}
<commit_msg>Quick fix to exit ASAP<commit_after>package queue

import (
	"time"

	"github.com/gophergala2016/goad/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws"
)

// AggData type
type AggData struct {
	TotalReqs            int            `json:"total-reqs"`
	TotalTimedOut        int            `json:"total-timed-out"`
	TotalConnectionError int            `json:"total-conn-error"`
	AveTimeToFirst       int64          `json:"ave-time-to-first"`
	TotBytesRead         int            `json:"tot-bytes-read"`
	Statuses             map[string]int `json:"statuses"`
	AveTimeForReq        int64          `json:"ave-time-for-req"`
	AveReqPerSec         float32        `json:"ave-req-per-sec"`
	AveKBytesPerSec      float32        `json:"ave-kbytes-per-sec"`
	Slowest              int64          `json:"slowest"`
	Fastest              int64          `json:"fastest"`
	Region               string         `json:"region"`
	FatalError           string         `json:"fatal-error"`
}

// RegionsAggData type
type RegionsAggData struct {
	Regions               map[string]AggData
	TotalExpectedRequests uint
}

func addResult(data *AggData, result *AggData) {
	initialDataTot := data.TotalReqs
	initialDataTot64 := int64(data.TotalReqs)
	data.TotalReqs += result.TotalReqs
	data.TotalTimedOut += result.TotalTimedOut
	dataTot64 := int64(data.TotalReqs)
	resultTot64 := int64(result.TotalReqs)
	if dataTot64 > 0 {
		data.AveTimeToFirst = (data.AveTimeToFirst*initialDataTot64 + result.AveTimeToFirst*resultTot64) / dataTot64
		data.AveTimeForReq = (data.AveTimeForReq*initialDataTot64 + result.AveTimeForReq*resultTot64) / dataTot64
		data.AveReqPerSec = (data.AveReqPerSec*float32(initialDataTot) + result.AveReqPerSec*float32(result.TotalReqs)) / float32(data.TotalReqs)
	}
	data.TotBytesRead += result.TotBytesRead

	for key, value := range result.Statuses {
		data.Statuses[key] += value
	}

	if result.Slowest > data.Slowest {
		data.Slowest = result.Slowest
	}
	if data.Fastest == 0 || result.Fastest < data.Fastest {
		data.Fastest = result.Fastest
	}
}

// Aggregate listens for results and sends totals, closing the channel when done
func Aggregate(awsConfig *aws.Config, queueURL string, totalExpectedRequests uint) chan RegionsAggData {
	results := make(chan RegionsAggData)
	go aggregate(results, awsConfig, queueURL, totalExpectedRequests)
	return results
}

func aggregate(results chan RegionsAggData, awsConfig *aws.Config, queueURL string, totalExpectedRequests uint) {
	defer close(results)
	data := RegionsAggData{make(map[string]AggData), totalExpectedRequests}

	adaptor := NewSQSAdaptor(awsConfig, queueURL)
	timeoutStart := time.Now()
	for {
		result := adaptor.Receive()
		if result != nil {
			regionData, ok := data.Regions[result.Region]
			if !ok {
				regionData.Statuses = make(map[string]int)
				regionData.Region = result.Region
			}
			addResult(&regionData, result)
			data.Regions[result.Region] = regionData
			results <- data
			if uint(regionData.TotalReqs) == totalExpectedRequests {
				break
			}
			timeoutStart = time.Now()
		} else {
			waited := time.Since(timeoutStart)
			if waited.Seconds() > 20 {
				break
			}
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2014 Jarmo Puttonen <jarmo.puttonen@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT-style
// licence that can be found in the LICENCE file.

/*Package paparazzogo implements a caching proxy for
serving MJPEG-stream as JPG-images.
*/
package paparazzogo

/*
Test coverage: 86.4% of statements.
*/

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
	"time"
)

//Multipart body for testing.
var firstPart = "01234567890"
var secondPart = "abcdefgh"
var thirdPart = "!#¤%&/<>"
var boundary = "MyBoundary"
var validBody = `
Content-type: multipart/x-mixed-replace;boundary=` + boundary + `

--` + boundary + `
Content-type: text/plain

` + firstPart + `

--` + boundary + `--
   `
var invalidBody = `
Content-type: multipart/x-mixed-replace;boundary=` + boundary + `
--` + boundary + `
Content-type: text/plain
` + firstPart + `
--` + boundary + `--
   `
var malformedPart = `
Content-type: multipart/x-mixed-replace;boundary=` + boundary + `

--` + boundary + `
Content-type: text/plain

` + firstPart + `

--` + boundary + `
   `

var streamBody = `
--` + boundary + `
Content-type: text/plain

` + firstPart + `

--` + boundary + `--
   `

func Test_NewMjpegproxy(t *testing.T) {
	mp := NewMjpegproxy()
	if mp.running != false {
		t.Fatal("Could not create Mjpegproxy!")
	}
}

func Test_CloseStream(t *testing.T) {
	mp := NewMjpegproxy()
	mp.CloseStream()
	if mp.running != false {
		t.Fatalf("Wrong run state: %s", mp.running)
	}
}

func Test_setRunning(t *testing.T) {
	mp := NewMjpegproxy()
	mp.setRunning(true)
	if mp.running != true {
		t.Fatalf("Wrong run state: expected true, got %s", mp.running)
	}
	mp.setRunning(false)
	if mp.running != false {
		t.Fatalf("Wrong run state: expected false, got %s", mp.running)
	}
}

func Test_GetRunning(t *testing.T) {
	mp := NewMjpegproxy()
	mp.setRunning(true)
	if mp.GetRunning() != true {
		t.Fatalf("Wrong run state: expected true, got %s", mp.GetRunning())
	}
	mp.setRunning(false)
	if mp.running != false {
		t.Fatalf("Wrong run state: expected false, got %s", mp.GetRunning())
	}
}

func Test_getresponse_valid(t *testing.T) {
	msg := "Test string"
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintln(w, msg)
	}))
	defer ts.Close()
	mp := NewMjpegproxy()
	request, err := http.NewRequest("GET", ts.URL, nil)
	if err != nil {
		t.Fatal("Failed to create request.")
	}
	res, err := mp.getresponse(request)
	if err != nil {
		t.Fatal(err)
	}
	responsebody, err := ioutil.ReadAll(res.Body)
	res.Body.Close()
	if err != nil {
		t.Fatal(err)
	}
	if !strings.Contains(string(responsebody), msg) {
		t.Fatalf("Response body mismatch: %s vs %s", msg, string(responsebody))
	}
}

func Test_getresponse_invalid_status(t *testing.T) {
	invalidstatus := 418
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		http.Error(w, "", invalidstatus)
	}))
	defer ts.Close()
	mp := NewMjpegproxy()
	request, err := http.NewRequest("GET", ts.URL, nil)
	if err != nil {
		t.Fatal("Failed to create request.")
	}
	_, err = mp.getresponse(request)
	if strings.Contains(string(invalidstatus), err.Error()) {
		t.Fatalf("Wrong status code: %s vs %s", err.Error(), string(invalidstatus))
	}
}
func Test_getresponse_noconnection(t *testing.T) {
	mp := NewMjpegproxy()
	request, err := http.NewRequest("GET", "http://127.0.0.1:99999/", nil)
	if err != nil {
		t.Fatal("Failed to create request.")
	}
	_, err = mp.getresponse(request)
	if !strings.Contains(err.Error(), "invalid port 99999") {
		t.Fatalf("Wrong error on connection refuse: %s", err.Error())
	}
}

func Test_getmultipart_valid(t *testing.T) {
	mp := NewMjpegproxy()
	response := &http.Response{
		Status:     "200 OK",
		StatusCode: 200,
		Proto:      "HTTP/1.0",
		Header: http.Header{
			"Content-Type": []string{"multipart/x-mixed-replace; boundary=" + boundary},
		},
		Body:          ioutil.NopCloser(bytes.NewBufferString(validBody)),
		ContentLength: int64(len(validBody)),
	}
	_, _, err := mp.getmultipart(response)
	if err != nil {
		t.Fatal(err)
	}
}

func Test_getmultipart_noboundary(t *testing.T) {
	mp := NewMjpegproxy()
	response := &http.Response{
		Status:     "200 OK",
		StatusCode: 200,
		Proto:      "HTTP/1.0",
		Header: http.Header{
			"Content-Type": []string{"multipart/x-mixed-replace"},
		},
		Body:          ioutil.NopCloser(bytes.NewBufferString(validBody)),
		ContentLength: int64(len(validBody)),
	}
	_, _, err := mp.getmultipart(response)
	if err == nil {
		t.Fatal("Failed!")
	}
	if !strings.Contains(err.Error(), "No multipart boundary param in Content-Type!") {
		t.Fatalf("Wrong error: %s", err.Error())
	}
}

func Test_getmultipart_invalid(t *testing.T) {
	mp := NewMjpegproxy()
	response := &http.Response{
		Status:     "200 OK",
		StatusCode: 200,
		Proto:      "HTTP/1.0",
		Header: http.Header{
			"Content-Type": []string{"multipart/form-data"},
		},
		Body:          ioutil.NopCloser(bytes.NewBufferString(validBody)),
		ContentLength: int64(len(validBody)),
	}
	_, _, err := mp.getmultipart(response)
	if err == nil {
		t.Fatal("Failed!")
	}
	if !strings.Contains(err.Error(), "Wrong Content-Type: expected multipart/x-mixed-replace!, got multipart/form-data") {
		t.Fatalf("Wrong error: %s", err.Error())
	}

}

func Test_getmultipart_noCT(t *testing.T) {
	mp := NewMjpegproxy()
	response := &http.Response{
		Status:        "200 OK",
		StatusCode:    200,
		Proto:         "HTTP/1.0",
		Header:        http.Header{},
		Body:          ioutil.NopCloser(bytes.NewBufferString(validBody)),
		ContentLength: int64(len(validBody)),
	}
	_, _, err := mp.getmultipart(response)
	if err == nil {
		t.Fatal("Failed!")
	}
	if !strings.Contains(err.Error(), "Content-Type isn't specified!") {
		t.Fatalf("Wrong error: %s", err.Error())
	}

}

func Test_readpart_valid(t *testing.T) {
	mp := NewMjpegproxy()
	mp.setRunning(true)
	reader := io.ReadCloser(ioutil.NopCloser(bytes.NewBufferString(validBody)))
	mpart := multipart.NewReader(reader, boundary)

	bytes, err := mp.readpart(mpart)
	if err != nil {
		t.Fatal(err)
	}
	if !strings.Contains(bytes.String(), firstPart) {
		t.Fatalf("Bad part: %s vs %s", bytes.String(), firstPart)
	}
}

func Test_readpart_invalid(t *testing.T) {
	mp := NewMjpegproxy()
	mp.setRunning(true)
	reader := io.ReadCloser(ioutil.NopCloser(bytes.NewBufferString(invalidBody)))
	mpart := multipart.NewReader(reader, boundary)

	_, err := mp.readpart(mpart)
	if !strings.Contains(err.Error(), "malformed MIME header line:") {
		t.Fatal(err)
	}
}

func Test_readpart_parterror(t *testing.T) {
	mp := NewMjpegproxy()
	mp.setRunning(true)
	reader := io.ReadCloser(ioutil.NopCloser(bytes.NewBufferString(malformedPart)))
	mpart := multipart.NewReader(reader, boundary)

	_, err := mp.readpart(mpart)
	if err != nil {
		t.Fatal(err)
	}
	_, err = mp.readpart(mpart)
	if err.Error() != "unexpected EOF" && err != nil {
		t.Fatal(err)
	}
}

func Test_ServeHTTP(t *testing.T) {
	mp := NewMjpegproxy()
	req := &http.Request{}
	testString := []byte("Test String")
	mp.curImg.Write(testString)
	recorder := httptest.NewRecorder()
	mp.ServeHTTP(recorder, req)

	if !bytes.Equal(mp.curImg.Bytes(), testString) {
		t.Fatalf("Content mismatch: expected %s, got %s", string(testString), string(mp.curImg.Bytes()))
	}

}

func Test_OpenStream_logic(t *testing.T) {
	user := "user"
	pass := "pass"
	mp := NewMjpegproxy()
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "multipart/x-mixed-replace;boundary="+boundary)
		fmt.Fprintln(w, streamBody)
	}))
	defer ts.Close()
	mp.setRunning(true)
	mp.OpenStream(ts.URL, user, pass, time.Second)
	defer mp.CloseStream()
	mp.conChan <- time.Now()
	time.Sleep(time.Millisecond)
	if !strings.Contains(mp.curImg.String(), firstPart) {
		t.Fatalf("Wrong response: expected %s, got %s", firstPart, mp.curImg.String())
	}
	mp.setRunning(false)
}
<commit_msg>Fix brain melt<commit_after>// Copyright 2014 Jarmo Puttonen <jarmo.puttonen@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT-style
// licence that can be found in the LICENCE file.

/*Package paparazzogo implements a caching proxy for
serving MJPEG-stream as JPG-images.
*/
package paparazzogo

/*
Test coverage: 86.4% of statements.
*/

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
	"time"
)

//Multipart body for testing.
var firstPart = "01234567890"
var secondPart = "abcdefgh"
var thirdPart = "!#¤%&/<>"
var boundary = "MyBoundary"
var validBody = `
Content-type: multipart/x-mixed-replace;boundary=` + boundary + `

--` + boundary + `
Content-type: text/plain

` + firstPart + `

--` + boundary + `--
   `
var invalidBody = `
Content-type: multipart/x-mixed-replace;boundary=` + boundary + `
--` + boundary + `
Content-type: text/plain
` + firstPart + `
--` + boundary + `--
   `
var malformedPart = `
Content-type: multipart/x-mixed-replace;boundary=` + boundary + `

--` + boundary + `
Content-type: text/plain

` + firstPart + `

--` + boundary + `
   `

var streamBody = `
--` + boundary + `
Content-type: text/plain

` + firstPart + `

--` + boundary + `--
   `

func Test_NewMjpegproxy(t *testing.T) {
	mp := NewMjpegproxy()
	if mp.running != false {
		t.Fatal("Could not create Mjpegproxy!")
	}
}

func Test_CloseStream(t *testing.T) {
	mp := NewMjpegproxy()
	mp.CloseStream()
	if mp.running != false {
		t.Fatalf("Wrong run state: %s", mp.running)
	}
}

func Test_setRunning(t *testing.T) {
	mp := NewMjpegproxy()
	mp.setRunning(true)
	if mp.running != true {
		t.Fatalf("Wrong run state: expected true, got %s", mp.running)
	}
	mp.setRunning(false)
	if mp.running != false {
		t.Fatalf("Wrong run state: expected false, got %s", mp.running)
	}
}

func Test_GetRunning(t *testing.T) {
	mp := NewMjpegproxy()
	mp.setRunning(true)
	if mp.GetRunning() != true {
		t.Fatalf("Wrong run state: expected true, got %s", mp.GetRunning())
	}
	mp.setRunning(false)
	if mp.running != false {
		t.Fatalf("Wrong run state: expected false, got %s", mp.GetRunning())
	}
}

func Test_getresponse_valid(t *testing.T) {
	msg := "Test string"
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintln(w, msg)
	}))
	defer ts.Close()
	mp := NewMjpegproxy()
	request, err := http.NewRequest("GET", ts.URL, nil)
	if err != nil {
		t.Fatal("Failed to create request.")
	}
	res, err := mp.getresponse(request)
	if err != nil {
		t.Fatal(err)
	}
	responsebody, err := ioutil.ReadAll(res.Body)
	res.Body.Close()
	if err != nil {
		t.Fatal(err)
	}
	if !strings.Contains(string(responsebody), msg) {
		t.Fatalf("Response body mismatch: %s vs %s", msg, string(responsebody))
	}
}

func Test_getresponse_invalid_status(t *testing.T) {
	invalidstatus := 418
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		http.Error(w, "", invalidstatus)
	}))
	defer ts.Close()
	mp := NewMjpegproxy()
	request, err := http.NewRequest("GET", ts.URL, nil)
	if err != nil {
		t.Fatal("Failed to create request.")
	}
	_, err = mp.getresponse(request)
	if strings.Contains(string(invalidstatus), err.Error()) {
		t.Fatalf("Wrong status code: %s vs %s", err.Error(), string(invalidstatus))
	}
}
func Test_getresponse_noconnection(t *testing.T) {
	mp := NewMjpegproxy()
	request, err := http.NewRequest("GET", "http://127.0.0.1:99999/", nil)
	if err != nil {
		t.Fatal("Failed to create request.")
	}
	_, err = mp.getresponse(request)
	if !strings.Contains(err.Error(), "invalid port 99999") {
		t.Fatalf("Wrong error on connection refuse: %s", err.Error())
	}
}

func Test_getmultipart_valid(t *testing.T) {
	mp := NewMjpegproxy()
	response := &http.Response{
		Status:     "200 OK",
		StatusCode: 200,
		Proto:      "HTTP/1.0",
		Header: http.Header{
			"Content-Type": []string{"multipart/x-mixed-replace; boundary=" + boundary},
		},
		Body:          ioutil.NopCloser(bytes.NewBufferString(validBody)),
		ContentLength: int64(len(validBody)),
	}
	_, _, err := mp.getmultipart(response)
	if err != nil {
		t.Fatal(err)
	}
}

func Test_getmultipart_noboundary(t *testing.T) {
	mp := NewMjpegproxy()
	response := &http.Response{
		Status:     "200 OK",
		StatusCode: 200,
		Proto:      "HTTP/1.0",
		Header: http.Header{
			"Content-Type": []string{"multipart/x-mixed-replace"},
		},
		Body:          ioutil.NopCloser(bytes.NewBufferString(validBody)),
		ContentLength: int64(len(validBody)),
	}
	_, _, err := mp.getmultipart(response)
	if err == nil {
		t.Fatal("Failed!")
	}
	if !strings.Contains(err.Error(), "No multipart boundary param in Content-Type!") {
		t.Fatalf("Wrong error: %s", err.Error())
	}
}

func Test_getmultipart_invalid(t *testing.T) {
	mp := NewMjpegproxy()
	response := &http.Response{
		Status:     "200 OK",
		StatusCode: 200,
		Proto:      "HTTP/1.0",
		Header: http.Header{
			"Content-Type": []string{"multipart/form-data"},
		},
		Body:          ioutil.NopCloser(bytes.NewBufferString(validBody)),
		ContentLength: int64(len(validBody)),
	}
	_, _, err := mp.getmultipart(response)
	if err == nil {
		t.Fatal("Failed!")
	}
	if !strings.Contains(err.Error(), "Wrong Content-Type: expected multipart/x-mixed-replace!, got multipart/form-data") {
		t.Fatalf("Wrong error: %s", err.Error())
	}

}

func Test_getmultipart_noCT(t *testing.T) {
	mp := NewMjpegproxy()
	response := &http.Response{
		Status:        "200 OK",
		StatusCode:    200,
		Proto:         "HTTP/1.0",
		Header:        http.Header{},
		Body:          ioutil.NopCloser(bytes.NewBufferString(validBody)),
		ContentLength: int64(len(validBody)),
	}
	_, _, err := mp.getmultipart(response)
	if err == nil {
		t.Fatal("Failed!")
	}
	if !strings.Contains(err.Error(), "Content-Type isn't specified!") {
		t.Fatalf("Wrong error: %s", err.Error())
	}

}

func Test_readpart_valid(t *testing.T) {
	mp := NewMjpegproxy()
	mp.setRunning(true)
	reader := io.ReadCloser(ioutil.NopCloser(bytes.NewBufferString(validBody)))
	mpart := multipart.NewReader(reader, boundary)

	bytes, err := mp.readpart(mpart)
	if err != nil {
		t.Fatal(err)
	}
	if !strings.Contains(bytes.String(), firstPart) {
		t.Fatalf("Bad part: %s vs %s", bytes.String(), firstPart)
	}
}

func Test_readpart_invalid(t *testing.T) {
	mp := NewMjpegproxy()
	mp.setRunning(true)
	reader := io.ReadCloser(ioutil.NopCloser(bytes.NewBufferString(invalidBody)))
	mpart := multipart.NewReader(reader, boundary)

	_, err := mp.readpart(mpart)
	if !strings.Contains(err.Error(), "malformed MIME header line:") {
		t.Fatal(err)
	}
}

func Test_readpart_parterror(t *testing.T) {
	mp := NewMjpegproxy()
	mp.setRunning(true)
	reader := io.ReadCloser(ioutil.NopCloser(bytes.NewBufferString(malformedPart)))
	mpart := multipart.NewReader(reader, boundary)

	_, err := mp.readpart(mpart)
	if err != nil {
		t.Fatal(err)
	}
	_, err = mp.readpart(mpart)
	if err.Error() != "unexpected EOF" && err != nil {
		t.Fatal(err)
	}
}

func Test_ServeHTTP(t *testing.T) {
	mp := NewMjpegproxy()
	req := &http.Request{}
	testString := []byte("Test String")
	mp.curImg.Write(testString)
	recorder := httptest.NewRecorder()
	mp.ServeHTTP(recorder, req)
	if time.Since(mp.lastConn) > time.Second {
		t.Fatal("Unexpected lastconn value!")
	}
	if !bytes.Equal(recorder.Body.Bytes(), testString) {
		t.Fatalf("Content mismatch: expected %s, got %s", string(testString), string(mp.curImg.Bytes()))
	}

}

func Test_OpenStream_logic(t *testing.T) {
	user := "user"
	pass := "pass"
	mp := NewMjpegproxy()
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "multipart/x-mixed-replace;boundary="+boundary)
		fmt.Fprintln(w, streamBody)
	}))
	defer ts.Close()
	mp.setRunning(true)
	mp.OpenStream(ts.URL, user, pass, time.Second)
	defer mp.CloseStream()
	mp.conChan <- time.Now()
	time.Sleep(time.Millisecond)
	if !strings.Contains(mp.curImg.String(), firstPart) {
		t.Fatalf("Wrong response: expected %s, got %s", firstPart, mp.curImg.String())
	}
	mp.setRunning(false)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"github.com/codegangsta/cli"
	W "github.com/jpellerin/wordmaker/wordmaker"
	"log"
	"os"
)

func init() {
	cli.AppHelpTemplate = `NAME:
   {{.Name}} - {{.Usage}}

USAGE:
   {{.Name}} [rulefile] [options] command

   The default rulefile is "rules.aw"

VERSION:
   {{.Version}}

OPTIONS:
   {{range .Flags}}{{.}}
   {{end}}

RULE FILE FORMAT:
   * Lines starting with an uppercase character define word parts
   * Lines starting with r define word patterns
   * Slashes (/) separate options, which are in order of descending weight
   * Parentheses may be used to group a set of options

   Example:

   V:a/i/u/ei/ao/ia/ai
   C:p/t/k/s/m/n/b/w/x/y/ts/l/sh/ch
   T:p/t/k
   F:s
   N:m/n/rn/rl/nd/ng
   r:CV(N/-CV/-CVN/)
`
}

func main() {
	app := cli.NewApp()
	app.Name = "mkwords"
	app.Usage = "Make some fake words using awkwords-like rules"
	app.Version = "0.1.1"

	app.Flags = []cli.Flag{
		cli.IntFlag{"words", 100, "number of words to generate"},
		cli.Float64Flag{"dropoff", 0.7, "rate of dropoff in choice lists"},
		cli.BoolFlag{"one-per-line", "output one word per line"},
	}
	app.Action = func(c *cli.Context) {
		rulefile := "rules.aw"
		words := c.Int("words")
		dropoff := c.Float64("dropoff")
		sep := " "
		if c.Bool("one-per-line") {
			sep = "\n"
		}
		if len(c.Args()) > 0 {
			rulefile = c.Args()[0]
		}
		input, err := readlines(rulefile)
		if err != nil {
			log.Fatalf("Error reading rules file %v: %v", rulefile, err)
		}
		cfg, err := W.Parse("mkwords", input, dropoff)
		if err != nil {
			log.Fatalf("Failed to parse rules file %v: %v", rulefile, err)
		}
		for i := 0; i < words; i++ {
			w, err := cfg.Word()
			if err != nil {
				log.Fatalf("Word generation failure: %v", err)
			}
			fmt.Printf("%v", w)
			fmt.Print(sep)
		}
		fmt.Print("\n")
	}
	app.Run(os.Args)
}

func readlines(filename string) ([]string, error) {
	lines := []string{}
	ff, err := os.Open(filename)
	if err != nil {
		return lines, err
	}
	defer ff.Close()
	scanner := bufio.NewScanner(ff)
	for scanner.Scan() {
		lines = append(lines, scanner.Text())
	}

	return lines, scanner.Err()
}
<commit_msg>Bump cli version number<commit_after>package main

import (
	"bufio"
	"fmt"
	"github.com/codegangsta/cli"
	W "github.com/jpellerin/wordmaker/wordmaker"
	"log"
	"os"
)

func init() {
	cli.AppHelpTemplate = `NAME:
   {{.Name}} - {{.Usage}}

USAGE:
   {{.Name}} [rulefile] [options] command

   The default rulefile is "rules.aw"

VERSION:
   {{.Version}}

OPTIONS:
   {{range .Flags}}{{.}}
   {{end}}

RULE FILE FORMAT:
   * Lines starting with an uppercase character define word parts
   * Lines starting with r define word patterns
   * Slashes (/) separate options, which are in order of descending weight
   * Parentheses may be used to group a set of options

   Example:

   V:a/i/u/ei/ao/ia/ai
   C:p/t/k/s/m/n/b/w/x/y/ts/l/sh/ch
   T:p/t/k
   F:s
   N:m/n/rn/rl/nd/ng
   r:CV(N/-CV/-CVN/)
`
}

func main() {
	app := cli.NewApp()
	app.Name = "mkwords"
	app.Usage = "Make some fake words using awkwords-like rules"
	app.Version = "0.1.2"

	app.Flags = []cli.Flag{
		cli.IntFlag{"words", 100, "number of words to generate"},
		cli.Float64Flag{"dropoff", 0.7, "rate of dropoff in choice lists"},
		cli.BoolFlag{"one-per-line", "output one word per line"},
	}
	app.Action = func(c *cli.Context) {
		rulefile := "rules.aw"
		words := c.Int("words")
		dropoff := c.Float64("dropoff")
		sep := " "
		if c.Bool("one-per-line") {
			sep = "\n"
		}
		if len(c.Args()) > 0 {
			rulefile = c.Args()[0]
		}
		input, err := readlines(rulefile)
		if err != nil {
			log.Fatalf("Error reading rules file %v: %v", rulefile, err)
		}
		cfg, err := W.Parse("mkwords", input, dropoff)
		if err != nil {
			log.Fatalf("Failed to parse rules file %v: %v", rulefile, err)
		}
		for i := 0; i < words; i++ {
			w, err := cfg.Word()
			if err != nil {
				log.Fatalf("Word generation failure: %v", err)
			}
			fmt.Printf("%v", w)
			fmt.Print(sep)
		}
		fmt.Print("\n")
	}
	app.Run(os.Args)
}

func readlines(filename string) ([]string, error) {
	lines := []string{}
	ff, err := os.Open(filename)
	if err != nil {
		return lines, err
	}
	defer ff.Close()
	scanner := bufio.NewScanner(ff)
	for scanner.Scan() {
		lines = append(lines, scanner.Text())
	}

	return lines, scanner.Err()
}
<|endoftext|>


<commit_before>// Package docker provides a Pipe that creates and pushes a Docker image
package docker

import (
	"fmt"
	"os"
	"os/exec"
	"path/filepath"

	"github.com/goreleaser/goreleaser/config"
	"github.com/goreleaser/goreleaser/context"
	"github.com/goreleaser/goreleaser/pipeline"

	"github.com/apex/log"

	"github.com/pkg/errors"
)

// ErrNoDocker is shown when docker cannot be found in $PATH
var ErrNoDocker = errors.New("docker not present in $PATH")

// Pipe for docker
type Pipe struct{}

// Description of the pipe
func (Pipe) Description() string {
	return "Creating Docker images"
}

// Run the pipe
func (Pipe) Run(ctx *context.Context) error {
	if len(ctx.Config.Dockers) == 0 || ctx.Config.Dockers[0].Image == "" {
		return pipeline.Skip("docker section is not configured")
	}
	_, err := exec.LookPath("docker")
	if err != nil {
		return ErrNoDocker
	}
	for _, docker := range ctx.Config.Dockers {
		var imagePlatform = docker.Goos + docker.Goarch + docker.Goarm
		for platform, groups := range ctx.Binaries {
			if platform != imagePlatform {
				continue
			}
			for folder, binaries := range groups {
				for _, binary := range binaries {
					if binary.Name != docker.Binary {
						continue
					}
					var err = doRun(ctx, folder, docker, binary)
					if err != nil && !pipeline.IsSkip(err) {
						return err
					}
				}
			}
		}
	}
	return nil
}

func doRun(ctx *context.Context, folder string, docker config.Docker, binary context.Binary) error {
	var root = filepath.Join(ctx.Config.Dist, folder)
	var dockerfile = filepath.Join(root, filepath.Base(docker.Dockerfile))
	var image = fmt.Sprintf("%s:%s", docker.Image, ctx.Version)
	var latest = fmt.Sprintf("%s:latest", docker.Image)

	if err := os.Link(docker.Dockerfile, dockerfile); err != nil {
		return errors.Wrap(err, "failed to link dockerfile")
	}
	if err := dockerBuild(root, dockerfile, image); err != nil {
		return err
	}
	if docker.Latest {
		if err := dockerTag(image, latest); err != nil {
			return err
		}
	}

	// TODO: improve this so it can log into to stdout
	if !ctx.Publish {
		return pipeline.Skip("--skip-publish is set")
	}
	if ctx.Config.Release.Draft {
		return pipeline.Skip("release is marked as draft")
	}
	if err := dockerPush(image); err != nil {
		return err
	}
	if docker.Latest {
		if err := dockerTag(image, latest); err != nil {
			return err
		}
	}
	return nil
}

func dockerBuild(root, dockerfile, image string) error {
	log.WithField("image", image).Info("building docker image")
	var cmd = exec.Command("docker", "build", "-f", dockerfile, "-t", image, root)
	log.WithField("cmd", cmd).Debug("executing")
	out, err := cmd.CombinedOutput()
	if err != nil {
		return errors.Wrapf(err, "failed to build docker image: \n%s", string(out))
	}
	log.Debugf("docker build output: \n%s", string(out))
	return nil
}

func dockerTag(image, tag string) error {
	log.WithField("image", image).WithField("tag", tag).Info("building docker image")
	var cmd = exec.Command("docker", "tag", image, tag)
	log.WithField("cmd", cmd).Debug("executing")
	out, err := cmd.CombinedOutput()
	if err != nil {
		return errors.Wrapf(err, "failed to tag docker image: \n%s", string(out))
	}
	log.Debugf("docker tag output: \n%s", string(out))
	return nil
}

func dockerPush(image string) error {
	log.WithField("image", image).Info("pushing docker image")
	var cmd = exec.Command("docker", "push", image)
	log.WithField("cmd", cmd).Debug("executing")
	out, err := cmd.CombinedOutput()
	if err != nil {
		return errors.Wrapf(err, "failed to push docker image: \n%s", string(out))
	}
	log.Debugf("docker push output: \n%s", string(out))
	return nil
}
<commit_msg>fixed log msg<commit_after>// Package docker provides a Pipe that creates and pushes a Docker image
package docker

import (
	"fmt"
	"os"
	"os/exec"
	"path/filepath"

	"github.com/goreleaser/goreleaser/config"
	"github.com/goreleaser/goreleaser/context"
	"github.com/goreleaser/goreleaser/pipeline"

	"github.com/apex/log"

	"github.com/pkg/errors"
)

// ErrNoDocker is shown when docker cannot be found in $PATH
var ErrNoDocker = errors.New("docker not present in $PATH")

// Pipe for docker
type Pipe struct{}

// Description of the pipe
func (Pipe) Description() string {
	return "Creating Docker images"
}

// Run the pipe
func (Pipe) Run(ctx *context.Context) error {
	if len(ctx.Config.Dockers) == 0 || ctx.Config.Dockers[0].Image == "" {
		return pipeline.Skip("docker section is not configured")
	}
	_, err := exec.LookPath("docker")
	if err != nil {
		return ErrNoDocker
	}
	for _, docker := range ctx.Config.Dockers {
		var imagePlatform = docker.Goos + docker.Goarch + docker.Goarm
		for platform, groups := range ctx.Binaries {
			if platform != imagePlatform {
				continue
			}
			for folder, binaries := range groups {
				for _, binary := range binaries {
					if binary.Name != docker.Binary {
						continue
					}
					var err = doRun(ctx, folder, docker, binary)
					if err != nil && !pipeline.IsSkip(err) {
						return err
					}
				}
			}
		}
	}
	return nil
}

func doRun(ctx *context.Context, folder string, docker config.Docker, binary context.Binary) error {
	var root = filepath.Join(ctx.Config.Dist, folder)
	var dockerfile = filepath.Join(root, filepath.Base(docker.Dockerfile))
	var image = fmt.Sprintf("%s:%s", docker.Image, ctx.Version)
	var latest = fmt.Sprintf("%s:latest", docker.Image)

	if err := os.Link(docker.Dockerfile, dockerfile); err != nil {
		return errors.Wrap(err, "failed to link dockerfile")
	}
	if err := dockerBuild(root, dockerfile, image); err != nil {
		return err
	}
	if docker.Latest {
		if err := dockerTag(image, latest); err != nil {
			return err
		}
	}

	// TODO: improve this so it can log into to stdout
	if !ctx.Publish {
		return pipeline.Skip("--skip-publish is set")
	}
	if ctx.Config.Release.Draft {
		return pipeline.Skip("release is marked as draft")
	}
	if err := dockerPush(image); err != nil {
		return err
	}
	if docker.Latest {
		if err := dockerTag(image, latest); err != nil {
			return err
		}
	}
	return nil
}

func dockerBuild(root, dockerfile, image string) error {
	log.WithField("image", image).Info("building docker image")
	var cmd = exec.Command("docker", "build", "-f", dockerfile, "-t", image, root)
	log.WithField("cmd", cmd).Debug("executing")
	out, err := cmd.CombinedOutput()
	if err != nil {
		return errors.Wrapf(err, "failed to build docker image: \n%s", string(out))
	}
	log.Debugf("docker build output: \n%s", string(out))
	return nil
}

func dockerTag(image, tag string) error {
	log.WithField("image", image).WithField("tag", tag).Info("tagging docker image")
	var cmd = exec.Command("docker", "tag", image, tag)
	log.WithField("cmd", cmd).Debug("executing")
	out, err := cmd.CombinedOutput()
	if err != nil {
		return errors.Wrapf(err, "failed to tag docker image: \n%s", string(out))
	}
	log.Debugf("docker tag output: \n%s", string(out))
	return nil
}

func dockerPush(image string) error {
	log.WithField("image", image).Info("pushing docker image")
	var cmd = exec.Command("docker", "push", image)
	log.WithField("cmd", cmd).Debug("executing")
	out, err := cmd.CombinedOutput()
	if err != nil {
		return errors.Wrapf(err, "failed to push docker image: \n%s", string(out))
	}
	log.Debugf("docker push output: \n%s", string(out))
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"testing"
)

var nodefmt = []struct {
	node Node
	str  string
}{
	// ArrayAccessNode
	{ArrayAccessNode{IdentNode{"abc"}, IntegerNode{"2"}}, "abc[2]"},

	// BinaryNode
	{BinaryNode{IdentNode{"a"}, "==", IdentNode{"b"}}, "a == b"},

	// IdentNode
	{IdentNode{"abcd"}, "abcd"},

	// IntegerNode
	{IntegerNode{"1234567890"}, "1234567890"},

	// CharacterNode
	{CharacterNode{""}, "''"},
	{CharacterNode{"1"}, "'1'"},
	{CharacterNode{"1234"}, "'1234'"},

	// FunctionNode
	{FunctionNode{"fn", []string{"a", "b", "c"}, BlockNode{}},
		"fn(a, b, c) {\n}"},
	{FunctionNode{"fn", []string{}, BlockNode{}}, "fn() {\n}"},

	// FunctionCallNode
	{FunctionCallNode{IdentNode{"fn"}, []Node{IntegerNode{"1"},
		CharacterNode{"123"}}},
		"fn(1, '123')"},

	// BlockNode
	{BlockNode{[]Node{IntegerNode{"1"}, IntegerNode{"2"},
		IntegerNode{"3"}}},
		"{\n\t1\n\t2\n\t3\n}"},

	// ExternVarInitNode
	{ExternVarInitNode{"var", IntegerNode{"2"}}, "var 2;"},

	// ExternVarDeclNode
	{ExternVarDeclNode{[]string{"a", "b", "c"}}, "extrn a, b, c;"},

	// UnaryNode
	{UnaryNode{"++", IntegerNode{"1"}, false}, "++1"},
	{UnaryNode{"++", IntegerNode{"1"}, true}, "1++"},

	// VarDeclNode
	{VarDeclNode{[]string{"a", "b", "c"}}, "auto a, b, c;"},
}

func TestNodeString(t *testing.T) {
	for _, test := range nodefmt {
		str := fmt.Sprintf("%v", test.node)
		if str != test.str {
			t.Errorf("expected <%s>, got <%s>", test.str, str)
		}
	}
}
<commit_msg>Add simple StatementNode test<commit_after>package main

import (
	"fmt"
	"testing"
)

var nodefmt = []struct {
	node Node
	str  string
}{
	// ArrayAccessNode
	{ArrayAccessNode{IdentNode{"abc"}, IntegerNode{"2"}}, "abc[2]"},

	// BinaryNode
	{BinaryNode{IdentNode{"a"}, "==", IdentNode{"b"}}, "a == b"},

	// IdentNode
	{IdentNode{"abcd"}, "abcd"},

	// IntegerNode
	{IntegerNode{"1234567890"}, "1234567890"},

	// CharacterNode
	{CharacterNode{""}, "''"},
	{CharacterNode{"1"}, "'1'"},
	{CharacterNode{"1234"}, "'1234'"},

	// FunctionNode
	{FunctionNode{"fn", []string{"a", "b", "c"}, BlockNode{}},
		"fn(a, b, c) {\n}"},
	{FunctionNode{"fn", []string{}, BlockNode{}}, "fn() {\n}"},

	// FunctionCallNode
	{FunctionCallNode{IdentNode{"fn"}, []Node{IntegerNode{"1"},
		CharacterNode{"123"}}},
		"fn(1, '123')"},

	// BlockNode
	{BlockNode{[]Node{IntegerNode{"1"}, IntegerNode{"2"},
		IntegerNode{"3"}}},
		"{\n\t1\n\t2\n\t3\n}"},

	// ExternVarInitNode
	{ExternVarInitNode{"var", IntegerNode{"2"}}, "var 2;"},

	// ExternVarDeclNode
	{ExternVarDeclNode{[]string{"a", "b", "c"}}, "extrn a, b, c;"},

	// StatementNode
	{StatementNode{IntegerNode{"1"}}, "1;"},

	// UnaryNode
	{UnaryNode{"++", IntegerNode{"1"}, false}, "++1"},
	{UnaryNode{"++", IntegerNode{"1"}, true}, "1++"},

	// VarDeclNode
	{VarDeclNode{[]string{"a", "b", "c"}}, "auto a, b, c;"},
}

func TestNodeString(t *testing.T) {
	for _, test := range nodefmt {
		str := fmt.Sprintf("%v", test.node)
		if str != test.str {
			t.Errorf("expected <%s>, got <%s>", test.str, str)
		}
	}
}
<|endoftext|>


<commit_before>package recovery

import (
    "os"
    "io"
    "fmt"
    "net"
    "sync"
    "strconv"
    "os/signal"
    "encoding/csv"
    "github/paxoscluster/proposal"
)

type Manager struct {
    sigint chan os.Signal
    exclude sync.Mutex
}

// Creates disk access manager for backup & recovery files
func ConstructManager() (*Manager, error) {
    _, err := os.Stat("coldstorage")
    if err != nil { return nil, err }

    newManager := Manager {
        sigint: make(chan os.Signal, 1),
    }
    signal.Notify(newManager.sigint, os.Interrupt)
    go newManager.finalize()

    return &newManager, nil
}

// Finishes all writes and permanently locks in preparation for shutdown
func (this *Manager) finalize() {
    <- this.sigint
    fmt.Println("[ DISK ] Clearing writes before shutdown")
    this.exclude.Lock()
    os.Exit(0)
}

// Reads the list of peers from a file on disk
func (this *Manager) RetrieveAddresses() (map[uint64]string, error) {
    this.exclude.Lock()
    defer this.exclude.Unlock()

    addresses := make(map[uint64]string)

    // Checks for existence of peers file
    _, err := os.Stat("coldstorage/peers.csv")
    if err != nil { return nil, err }

    // Opens & reads peers file
    peersFile, err := os.Open("coldstorage/peers.csv")
    if err != nil { return nil, err }
    peersFileReader := csv.NewReader(peersFile)
    records, err := peersFileReader.ReadAll()
    peersFile.Close()
    if err != nil { return nil, err }

    // Reads from & parses peers.csv file
    for _, record := range records {
        if len(record) != 3 { return addresses, fmt.Errorf("Invalid record length in peers file") }
        roleId, err := strconv.ParseUint(record[0], 10, 64)
        if err != nil { return nil, err }
        ipAddress := record[1]
        port := record[2]
        addresses[roleId] = net.JoinHostPort(ipAddress, port)
    }

    return addresses, nil
}

func (this *Manager) RecoverMinProposalId(roleId uint64) (proposal.Id, error) {
    this.exclude.Lock()
    defer this.exclude.Unlock()

    // Checks for existence of directory
    _, err := os.Stat(fmt.Sprintf("coldstorage/%d", roleId))
    if os.IsNotExist(err) {
        return proposal.Default(), nil
    } else if err != nil { return proposal.Default(), err }

    // Checks for existence of file
    proposalFileName := fmt.Sprintf("coldstorage/%d/minproposalid.csv", roleId)
    _, err = os.Stat(proposalFileName)
    if os.IsNotExist(err) {
        return proposal.Default(), nil
    } else if err != nil { return proposal.Default(), err }

    // File exists, therefore read from it
    proposalFile, err := os.Open(proposalFileName)
    if err != nil { return proposal.Default(), err }
    proposalFileReader := csv.NewReader(proposalFile)
    record, err := proposalFileReader.Read()
    proposalFile.Close()
    if err != nil && err != io.EOF { return proposal.Default(), err }
    proposalRole, err := strconv.ParseUint(record[0], 10, 64)
    if err != nil { return proposal.Default(), err }
    sequence, err := strconv.ParseInt(record[1], 10, 64)
    if err != nil { return proposal.Default(), err }

    return proposal.Id{proposalRole, sequence}, nil
}

func (this *Manager) UpdateMinProposalId(roleId uint64, id proposal.Id) error {
    this.exclude.Lock()
    defer this.exclude.Unlock()

    // Ensures existence of directory, creating it if necessary
    _, err := os.Stat(fmt.Sprintf("coldstorage/%d", roleId))
    if os.IsNotExist(err) {
        err = os.Mkdir(fmt.Sprintf("coldstorage/%d", roleId), os.ModeDir)
        if err != nil { return err }
    } else if err != nil { return err }

    // Creates file (automatic overwrite)
    proposalFileName := fmt.Sprintf("coldstorage/%d/minproposalid.csv", roleId)
    proposalFile, err := os.Create(proposalFileName)
    if err != nil { return err }
    defer proposalFile.Close()

    // Writes data to file
    record := []string{strconv.FormatUint(id.RoleId, 10), strconv.FormatInt(id.Sequence, 10)}
    proposalFileWriter := csv.NewWriter(proposalFile)
    err = proposalFileWriter.Write(record)
    if err != nil { return err }
    proposalFileWriter.Flush()
    return nil
}

func (this *Manager) RecoverLog(roleId uint64) ([]string, []proposal.Id, error) {
    this.exclude.Lock()
    defer this.exclude.Unlock()

    // Checks for existence of log file directory
    _, err := os.Stat(fmt.Sprintf("coldstorage/%d", roleId))
    if os.IsNotExist(err) {
        return nil, nil, nil
    } else if err != nil { return nil, nil, err }

    // Checks for existence of log file
    logFileName := fmt.Sprintf("coldstorage/%d/log.csv", roleId)
    _, err = os.Stat(logFileName)
    if os.IsNotExist(err) {
        return nil, nil, nil
    } else if err != nil { return nil, nil, err }

    // Log file exists, therefore read from it
    logFile, err := os.Open(logFileName)
    if err != nil { return nil, nil, err }
    logFileReader := csv.NewReader(logFile)
    records, err := logFileReader.ReadAll()
    logFile.Close()
    if err != nil { return nil, nil, err }

    // Parse records
    var values []string = nil
    var proposals []proposal.Id = nil
    for _, record := range records {
        if len(record) != 3 { return nil, nil, fmt.Errorf("Invalid record length in log file %d", roleId) }
        values = append(values, record[0])
        proposalRole, err := strconv.ParseUint(record[1], 10, 64)
        if err != nil { return nil, nil, err }
        sequence, err := strconv.ParseInt(record[2], 10, 64)
        if err != nil { return nil, nil, err }
        proposals = append(proposals, proposal.Id{proposalRole, sequence})
    }

    return values, proposals, nil
}

// Updates a record in the log file
func (this *Manager) UpdateLogRecord(roleId uint64, index int, value string, id proposal.Id) error {
    this.exclude.Lock()
    defer this.exclude.Unlock()

    // Ensures existence of directory, creating it if necessary
    _, err := os.Stat(fmt.Sprintf("coldstorage/%d", roleId))
    if os.IsNotExist(err) {
        err = os.Mkdir(fmt.Sprintf("coldstorage/%d", roleId), os.ModeDir)
        if err != nil { return err }
    } else if err != nil { return err }

    // If log file exists, read from it
    logFileName := fmt.Sprintf("coldstorage/%d/log.csv", roleId)
    var records [][]string = nil
    _, err = os.Stat(logFileName)
    if err == nil {
        logFile, err := os.Open(logFileName)
        if err != nil { return err }
        logFileReader := csv.NewReader(logFile)
        records, err = logFileReader.ReadAll()
        logFile.Close()
        if err != nil { return err }
    } else if err != nil && !os.IsNotExist(err) { return err }

    // Modifies record
    blank := []string{"", "0", "0"}
    record := []string{value, strconv.FormatUint(id.RoleId, 10), strconv.FormatInt(id.Sequence, 10)}
    for recordCount := len(records); recordCount <= index; recordCount++ {
        records = append(records, blank)
    }
    records[index] = record

    // Writes out log contents
    modifiedLogFile, err := os.Create(logFileName)
    if err != nil { return err }
    defer modifiedLogFile.Close()
    logFileWriter := csv.NewWriter(modifiedLogFile)
    return logFileWriter.WriteAll(records)
}
<commit_msg>Fixed directory permission issue on Linux<commit_after>package recovery

import (
    "os"
    "io"
    "fmt"
    "net"
    "sync"
    "strconv"
    "os/signal"
    "encoding/csv"
    "github/paxoscluster/proposal"
)

type Manager struct {
    sigint chan os.Signal
    exclude sync.Mutex
}

// Creates disk access manager for backup & recovery files
func ConstructManager() (*Manager, error) {
    _, err := os.Stat("coldstorage")
    if err != nil { return nil, err }

    newManager := Manager {
        sigint: make(chan os.Signal, 1),
    }
    signal.Notify(newManager.sigint, os.Interrupt)
    go newManager.finalize()

    return &newManager, nil
}

// Finishes all writes and permanently locks in preparation for shutdown
func (this *Manager) finalize() {
    <- this.sigint
    fmt.Println("[ DISK ] Clearing writes before shutdown")
    this.exclude.Lock()
    os.Exit(0)
}

// Reads the list of peers from a file on disk
func (this *Manager) RetrieveAddresses() (map[uint64]string, error) {
    this.exclude.Lock()
    defer this.exclude.Unlock()

    addresses := make(map[uint64]string)

    // Checks for existence of peers file
    _, err := os.Stat("coldstorage/peers.csv")
    if err != nil { return nil, err }

    // Opens & reads peers file
    peersFile, err := os.Open("coldstorage/peers.csv")
    if err != nil { return nil, err }
    peersFileReader := csv.NewReader(peersFile)
    records, err := peersFileReader.ReadAll()
    peersFile.Close()
    if err != nil { return nil, err }

    // Reads from & parses peers.csv file
    for _, record := range records {
        if len(record) != 3 { return addresses, fmt.Errorf("Invalid record length in peers file") }
        roleId, err := strconv.ParseUint(record[0], 10, 64)
        if err != nil { return nil, err }
        ipAddress := record[1]
        port := record[2]
        addresses[roleId] = net.JoinHostPort(ipAddress, port)
    }

    return addresses, nil
}

func (this *Manager) RecoverMinProposalId(roleId uint64) (proposal.Id, error) {
    this.exclude.Lock()
    defer this.exclude.Unlock()

    // Checks for existence of directory
    _, err := os.Stat(fmt.Sprintf("coldstorage/%d", roleId))
    if os.IsNotExist(err) {
        return proposal.Default(), nil
    } else if err != nil { return proposal.Default(), err }

    // Checks for existence of file
    proposalFileName := fmt.Sprintf("coldstorage/%d/minproposalid.csv", roleId)
    _, err = os.Stat(proposalFileName)
    if os.IsNotExist(err) {
        return proposal.Default(), nil
    } else if err != nil { return proposal.Default(), err }

    // File exists, therefore read from it
    proposalFile, err := os.Open(proposalFileName)
    if err != nil { return proposal.Default(), err }
    proposalFileReader := csv.NewReader(proposalFile)
    record, err := proposalFileReader.Read()
    proposalFile.Close()
    if err != nil && err != io.EOF { return proposal.Default(), err }
    proposalRole, err := strconv.ParseUint(record[0], 10, 64)
    if err != nil { return proposal.Default(), err }
    sequence, err := strconv.ParseInt(record[1], 10, 64)
    if err != nil { return proposal.Default(), err }

    return proposal.Id{proposalRole, sequence}, nil
}

func (this *Manager) UpdateMinProposalId(roleId uint64, id proposal.Id) error {
    this.exclude.Lock()
    defer this.exclude.Unlock()

    // Ensures existence of directory, creating it if necessary
    _, err := os.Stat(fmt.Sprintf("coldstorage/%d", roleId))
    if os.IsNotExist(err) {
        err = os.Mkdir(fmt.Sprintf("coldstorage/%d", roleId), 0700)
        if err != nil { return err }
    } else if err != nil { return err }

    // Creates file (automatic overwrite)
    proposalFileName := fmt.Sprintf("coldstorage/%d/minproposalid.csv", roleId)
    proposalFile, err := os.Create(proposalFileName)
    if err != nil { return err }
    defer proposalFile.Close()

    // Writes data to file
    record := []string{strconv.FormatUint(id.RoleId, 10), strconv.FormatInt(id.Sequence, 10)}
    proposalFileWriter := csv.NewWriter(proposalFile)
    err = proposalFileWriter.Write(record)
    if err != nil { return err }
    proposalFileWriter.Flush()
    return nil
}

func (this *Manager) RecoverLog(roleId uint64) ([]string, []proposal.Id, error) {
    this.exclude.Lock()
    defer this.exclude.Unlock()

    // Checks for existence of log file directory
    _, err := os.Stat(fmt.Sprintf("coldstorage/%d", roleId))
    if os.IsNotExist(err) {
        return nil, nil, nil
    } else if err != nil { return nil, nil, err }

    // Checks for existence of log file
    logFileName := fmt.Sprintf("coldstorage/%d/log.csv", roleId)
    _, err = os.Stat(logFileName)
    if os.IsNotExist(err) {
        return nil, nil, nil
    } else if err != nil { return nil, nil, err }

    // Log file exists, therefore read from it
    logFile, err := os.Open(logFileName)
    if err != nil { return nil, nil, err }
    logFileReader := csv.NewReader(logFile)
    records, err := logFileReader.ReadAll()
    logFile.Close()
    if err != nil { return nil, nil, err }

    // Parse records
    var values []string = nil
    var proposals []proposal.Id = nil
    for _, record := range records {
        if len(record) != 3 { return nil, nil, fmt.Errorf("Invalid record length in log file %d", roleId) }
        values = append(values, record[0])
        proposalRole, err := strconv.ParseUint(record[1], 10, 64)
        if err != nil { return nil, nil, err }
        sequence, err := strconv.ParseInt(record[2], 10, 64)
        if err != nil { return nil, nil, err }
        proposals = append(proposals, proposal.Id{proposalRole, sequence})
    }

    return values, proposals, nil
}

// Updates a record in the log file
func (this *Manager) UpdateLogRecord(roleId uint64, index int, value string, id proposal.Id) error {
    this.exclude.Lock()
    defer this.exclude.Unlock()

    // Ensures existence of directory, creating it if necessary
    _, err := os.Stat(fmt.Sprintf("coldstorage/%d", roleId))
    if os.IsNotExist(err) {
        err = os.Mkdir(fmt.Sprintf("coldstorage/%d", roleId), 0700)
        if err != nil { return err }
    } else if err != nil { return err }

    // If log file exists, read from it
    logFileName := fmt.Sprintf("coldstorage/%d/log.csv", roleId)
    var records [][]string = nil
    _, err = os.Stat(logFileName)
    if err == nil {
        logFile, err := os.Open(logFileName)
        if err != nil { return err }
        logFileReader := csv.NewReader(logFile)
        records, err = logFileReader.ReadAll()
        logFile.Close()
        if err != nil { return err }
    } else if err != nil && !os.IsNotExist(err) { return err }

    // Modifies record
    blank := []string{"", "0", "0"}
    record := []string{value, strconv.FormatUint(id.RoleId, 10), strconv.FormatInt(id.Sequence, 10)}
    for recordCount := len(records); recordCount <= index; recordCount++ {
        records = append(records, blank)
    }
    records[index] = record

    // Writes out log contents
    modifiedLogFile, err := os.Create(logFileName)
    if err != nil { return err }
    defer modifiedLogFile.Close()
    logFileWriter := csv.NewWriter(modifiedLogFile)
    return logFileWriter.WriteAll(records)
}
<|endoftext|>