<commit_before>package jiraui

import (
	"encoding/json"
	"testing"
)

func TestCountLabelsFromQueryData(t *testing.T) {
	var data interface{}
	inputJSON := []byte(`{
		  "issues": [
				{ "fields": { "labels": [ "wibble", "bibble" ] } },
				{ "fields": { "labels": [ "wibble", "bibble" ] } },
				{ "fields": { "labels": [ "bibble" ] } }
			]
		}`)

	expected := make(map[string]int)
	expected["wibble"] = 2
	expected["bibble"] = 3

	err := json.Unmarshal(inputJSON, &data)
	if err != nil {
		t.Fatal(err)
	}

	actual := countLabelsFromQueryData(data)
	if expected["wibble"] != actual["wibble"] {
		t.Fatalf("wibble: expected %q, got %q", expected, actual)
	}
	if expected["bibble"] != actual["bibble"] {
		t.Fatalf("bibble: expected %q, got %q", expected, actual)
	}
}

func TestFindTicketIdInString(t *testing.T) {
	var match string
	match = findTicketIdInString("  relates: BLAH-123[Done]  ")
	if match != "BLAH-123" {
		t.Fatalf("expected BLAH-123, got %s", match)
	}
	match = findTicketIdInString("  wibble: xxBLAH-123[Done]  ")
	if match != "BLAH-123" {
		t.Fatalf("expected %q, got %q", "", match)
	}
	match = findTicketIdInString("  wibble: xxBL-1[Done]  ")
	if match != "" {
		t.Fatalf("expected %q, got %q", "", match)
	}
	match = findTicketIdInString("  wibble: xxBLAH-1[Done]  ")
	if match != "BLAH-1" {
		t.Fatalf("expected %q, got %q", "", match)
	}
	match = findTicketIdInString("  wibble: xxTOOLONGPROJECT-1[Done]  ")
	if match != "" {
		t.Skip("This fails, TODO fixing!")
	}
}

func TestWrapText(t *testing.T) {
	input := []string{
		"",
		"wibble:        hello",
		"longfield:     1234567890123456789012345678901234567890",
		"1234567890123456789012345678901234567890",
		"12345678901234567890123456789012345678901234567890",
		"      {code}   ",
		"      # This is code it should not be wrapped at all herpdy derp",
		"      # weoijwefoi wpeifjwoiejf pwjefoijwefij wefjowiejf wefwefwefijwe",
		"      {code}   ",
		"      {code:bash}   ",
		"      # This is code it should not be wrapped at all herpdy derp",
		"      # weoijwefoi wpeifjwoiejf pwjefoijwefij wefjowiejf wefwefwefijwe",
		"      {code}   ",
		"      {noformat}   ",
		"      # This is noformat it should not be wrapped at all herpdy derp",
		"      # weoijwefoi wpeifjwoiejf pwjefoijwefij wefjowiejf wefwefwefijwe",
		"      {noformat}   ",
		"body: |",
		"   hello there I am a line that is longer than 40 chars yes I am oh aye.",
	}
	expected := []string{
		"",
		"wibble:        hello",
		"longfield:     1234567890123456789012345678901234567890",
		"1234567890123456789012345678901234567890",
		"1234567890123456789012345678901234567890",
		"1234567890",
		"      {code}   ",
		"      # This is code it should not be wrapped at all herpdy derp",
		"      # weoijwefoi wpeifjwoiejf pwjefoijwefij wefjowiejf wefwefwefijwe",
		"      {code}   ",
		"      {code:bash}   ",
		"      # This is code it should not be wrapped at all herpdy derp",
		"      # weoijwefoi wpeifjwoiejf pwjefoijwefij wefjowiejf wefwefwefijwe",
		"      {code}   ",
		"      {noformat}   ",
		"      # This is noformat it should not be wrapped at all herpdy derp",
		"      # weoijwefoi wpeifjwoiejf pwjefoijwefij wefjowiejf wefwefwefijwe",
		"      {noformat}   ",
		"body: |",
		"   hello there I am a line that is longe",
		"r than 40 chars yes I am oh aye.",
	}
	match := WrapText(input, 40)
	for i, _ := range expected {
		if i > len(match)-1 {
			t.Fatalf("expected %d lines, got %d", len(expected), len(match))
		} else if match[i] != expected[i] {
			t.Fatalf("line %d - expected %q, got %q", i, expected[i], match[i])
		}
	}
}
<commit_msg>Fix text wrapping tests, to reflect improved behaviour<commit_after>package jiraui

import (
	"encoding/json"
	"testing"
)

func TestCountLabelsFromQueryData(t *testing.T) {
	var data interface{}
	inputJSON := []byte(`{
		  "issues": [
				{ "fields": { "labels": [ "wibble", "bibble" ] } },
				{ "fields": { "labels": [ "wibble", "bibble" ] } },
				{ "fields": { "labels": [ "bibble" ] } }
			]
		}`)

	expected := make(map[string]int)
	expected["wibble"] = 2
	expected["bibble"] = 3

	err := json.Unmarshal(inputJSON, &data)
	if err != nil {
		t.Fatal(err)
	}

	actual := countLabelsFromQueryData(data)
	if expected["wibble"] != actual["wibble"] {
		t.Fatalf("wibble: expected %q, got %q", expected, actual)
	}
	if expected["bibble"] != actual["bibble"] {
		t.Fatalf("bibble: expected %q, got %q", expected, actual)
	}
}

func TestFindTicketIdInString(t *testing.T) {
	var match string
	match = findTicketIdInString("  relates: BLAH-123[Done]  ")
	if match != "BLAH-123" {
		t.Fatalf("expected BLAH-123, got %s", match)
	}
	match = findTicketIdInString("  wibble: xxBLAH-123[Done]  ")
	if match != "BLAH-123" {
		t.Fatalf("expected %q, got %q", "", match)
	}
	match = findTicketIdInString("  wibble: xxBL-1[Done]  ")
	if match != "" {
		t.Fatalf("expected %q, got %q", "", match)
	}
	match = findTicketIdInString("  wibble: xxBLAH-1[Done]  ")
	if match != "BLAH-1" {
		t.Fatalf("expected %q, got %q", "", match)
	}
	match = findTicketIdInString("  wibble: xxTOOLONGPROJECT-1[Done]  ")
	if match != "" {
		t.Skip("This fails, TODO fixing!")
	}
}

func TestWrapText(t *testing.T) {
	input := []string{
		"",
		"wibble:        hello",
		"longfield:     1234567890123456789012345678901234567890",
		"1234567890123456789012345678901234567890",
		"12345678901234567890123456789012345678901234567890",
		"      {code}   ",
		"      # This is code it should not be wrapped at all herpdy derp",
		"      # weoijwefoi wpeifjwoiejf pwjefoijwefij wefjowiejf wefwefwefijwe",
		"      {code}   ",
		"      {code:bash}   ",
		"      # This is code it should not be wrapped at all herpdy derp",
		"      # weoijwefoi wpeifjwoiejf pwjefoijwefij wefjowiejf wefwefwefijwe",
		"      {code}   ",
		"      {noformat}   ",
		"      # This is noformat it should not be wrapped at all herpdy derp",
		"      # weoijwefoi wpeifjwoiejf pwjefoijwefij wefjowiejf wefwefwefijwe",
		"      {noformat}   ",
		"body: |",
		"   hello there I am a line that is longer than 40 chars yes I am oh aye.",
	}
	expected := []string{
		"",
		"wibble:        hello",
		"longfield:     1234567890123456789012345678901234567890",
		"1234567890123456789012345678901234567890",
		"12345678901234567890123456789012345678901234567890",
		"      {code}   ",
		"      # This is code it should not be wrapped at all herpdy derp",
		"      # weoijwefoi wpeifjwoiejf pwjefoijwefij wefjowiejf wefwefwefijwe",
		"      {code}   ",
		"      {code:bash}   ",
		"      # This is code it should not be wrapped at all herpdy derp",
		"      # weoijwefoi wpeifjwoiejf pwjefoijwefij wefjowiejf wefwefwefijwe",
		"      {code}   ",
		"      {noformat}   ",
		"      # This is noformat it should not be wrapped at all herpdy derp",
		"      # weoijwefoi wpeifjwoiejf pwjefoijwefij wefjowiejf wefwefwefijwe",
		"      {noformat}   ",
		"body: |",
		"   hello there I am a line that is",
		"   longer than 40 chars yes I am oh aye.",
	}
	match := WrapText(input, 40)
	for i, _ := range expected {
		if i > len(match)-1 {
			t.Fatalf("expected %d lines, got %d", len(expected), len(match))
		} else if match[i] != expected[i] {
			t.Fatalf("line %d - expected %q, got %q", i, expected[i], match[i])
		}
	}
}
<|endoftext|>


<commit_before>/*
   Copyright The containerd 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 implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

package v2

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"math"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"syscall"
	"time"

	"golang.org/x/sys/unix"

	"github.com/containerd/cgroups/v2/stats"
	"github.com/pkg/errors"
)

const (
	subtreeControl  = "cgroup.subtree_control"
	controllersFile = "cgroup.controllers"
)

var oomEventCount = 0

type cgValuer interface {
	Values() []Value
}

type Event struct {
	Low     uint64
	High    uint64
	Max     uint64
	OOM     uint64
	OOMKill uint64
}

// Resources for a cgroups v2 unified hierarchy
type Resources struct {
	CPU    *CPU
	Memory *Memory
	Pids   *Pids
	IO     *IO
}

// Values returns the raw filenames and values that
// can be written to the unified hierarchy
func (r *Resources) Values() (o []Value) {
	values := []cgValuer{
		r.CPU,
		r.Memory,
		r.Pids,
		r.IO,
	}
	for _, v := range values {
		if v == nil {
			continue
		}
		o = append(o, v.Values()...)
	}
	return o
}

// Value of a cgroup setting
type Value struct {
	filename string
	value    interface{}
}

// write the value to the full, absolute path, of a unified hierarchy
func (c *Value) write(path string, perm os.FileMode) error {
	var data []byte
	switch t := c.value.(type) {
	case uint64:
		data = []byte(strconv.FormatUint(t, 10))
	case uint16:
		data = []byte(strconv.FormatUint(uint64(t), 10))
	case int64:
		data = []byte(strconv.FormatInt(t, 10))
	case []byte:
		data = t
	case string:
		data = []byte(t)
	default:
		return ErrInvalidFormat
	}
	return ioutil.WriteFile(
		filepath.Join(path, c.filename),
		data,
		perm,
	)
}

func writeValues(path string, values []Value) error {
	for _, o := range values {
		if err := o.write(path, defaultFilePerm); err != nil {
			return err
		}
	}
	return nil
}

func NewManager(mountpoint string, group string, resources *Resources) (*Manager, error) {
	if err := VerifyGroupPath(group); err != nil {
		return nil, err
	}
	path := filepath.Join(mountpoint, group)
	if err := os.MkdirAll(path, defaultDirPerm); err != nil {
		return nil, err
	}
	if resources != nil {
		if err := writeValues(path, resources.Values()); err != nil {
			// clean up cgroup dir on failure
			os.Remove(path)
			return nil, err
		}
	}
	return &Manager{
		unifiedMountpoint: mountpoint,
		path:              path,
	}, nil
}

func LoadManager(mountpoint string, group string) (*Manager, error) {
	if err := VerifyGroupPath(group); err != nil {
		return nil, err
	}
	path := filepath.Join(mountpoint, group)
	return &Manager{
		unifiedMountpoint: mountpoint,
		path:              path,
	}, nil
}

type Manager struct {
	unifiedMountpoint string
	path              string
}

func (c *Manager) ListControllers() ([]string, error) {
	f, err := os.Open(filepath.Join(c.path, controllersFile))
	if err != nil {
		return nil, err
	}
	defer f.Close()

	var (
		out []string
		s   = bufio.NewScanner(f)
	)
	s.Split(bufio.ScanWords)
	for s.Scan() {
		if err := s.Err(); err != nil {
			return nil, err
		}
		out = append(out, s.Text())
	}
	return out, nil
}

type ControllerToggle int

const (
	Enable ControllerToggle = iota + 1
	Disable
)

func toggleFunc(controllers []string, prefix string) []string {
	out := make([]string, len(controllers))
	for i, c := range controllers {
		out[i] = prefix + c
	}
	return out
}

func (c *Manager) ToggleControllers(controllers []string, t ControllerToggle) error {
	f, err := os.OpenFile(filepath.Join(c.path, subtreeControl), os.O_WRONLY, 0)
	if err != nil {
		return err
	}
	defer f.Close()
	switch t {
	case Enable:
		controllers = toggleFunc(controllers, "+")
	case Disable:
		controllers = toggleFunc(controllers, "-")
	}
	_, err = f.WriteString(strings.Join(controllers, " "))
	return err
}

func (c *Manager) NewChild(name string, resources *Resources) (*Manager, error) {
	if strings.HasPrefix(name, "/") {
		return nil, errors.New("name must be relative")
	}
	path := filepath.Join(c.path, name)
	if err := os.MkdirAll(path, defaultDirPerm); err != nil {
		return nil, err
	}
	if err := writeValues(path, resources.Values()); err != nil {
		// clean up cgroup dir on failure
		os.Remove(path)
		return nil, err
	}
	return &Manager{
		unifiedMountpoint: c.unifiedMountpoint,
		path:              path,
	}, nil
}

func (c *Manager) AddProc(pid uint64) error {
	v := Value{
		filename: cgroupProcs,
		value:    pid,
	}
	return writeValues(c.path, []Value{v})
}

func (c *Manager) Delete() error {
	return remove(c.path)
}

func (c *Manager) Procs(recursive bool) ([]uint64, error) {
	var processes []uint64
	err := filepath.Walk(c.path, func(p string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if !recursive && info.IsDir() {
			if p == c.path {
				return nil
			}
			return filepath.SkipDir
		}
		_, name := filepath.Split(p)
		if name != cgroupProcs {
			return nil
		}
		procs, err := parseCgroupProcsFile(p)
		if err != nil {
			return err
		}
		processes = append(processes, procs...)
		return nil
	})
	return processes, err
}

var singleValueFiles = []string{
	"pids.current",
	"pids.max",
}

func (c *Manager) Stat() (*stats.Metrics, error) {
	controllers, err := c.ListControllers()
	if err != nil {
		return nil, err
	}
	out := make(map[string]interface{})
	for _, controller := range controllers {
		filename := fmt.Sprintf("%s.stat", controller)
		if err := readStatsFile(c.path, filename, out); err != nil {
			if os.IsNotExist(err) {
				continue
			}
			return nil, err
		}
	}
	for _, name := range singleValueFiles {
		if err := readSingleFile(c.path, name, out); err != nil {
			if os.IsNotExist(err) {
				continue
			}
			return nil, err
		}
	}
	var metrics stats.Metrics

	metrics.Pids = &stats.PidsStat{
		Current: getPidValue("pids.current", out),
		Limit:   getPidValue("pids.max", out),
	}
	metrics.CPU = &stats.CPUStat{
		UsageUsec:     out["usage_usec"].(uint64),
		UserUsec:      out["user_usec"].(uint64),
		SystemUsec:    out["system_usec"].(uint64),
		NrPeriods:     out["nr_periods"].(uint64),
		NrThrottled:   out["nr_throttled"].(uint64),
		ThrottledUsec: out["throttled_usec"].(uint64),
	}
	metrics.Memory = &stats.MemoryStat{
		Anon:                  out["anon"].(uint64),
		File:                  out["file"].(uint64),
		KernelStack:           out["kernel_stack"].(uint64),
		Slab:                  out["slab"].(uint64),
		Sock:                  out["sock"].(uint64),
		Shmem:                 out["shmem"].(uint64),
		FileMapped:            out["file_mapped"].(uint64),
		FileDirty:             out["file_dirty"].(uint64),
		FileWriteback:         out["file_writeback"].(uint64),
		AnonThp:               out["anon_thp"].(uint64),
		InactiveAnon:          out["inactive_anon"].(uint64),
		ActiveAnon:            out["active_anon"].(uint64),
		InactiveFile:          out["inactive_file"].(uint64),
		ActiveFile:            out["active_file"].(uint64),
		Unevictable:           out["unevictable"].(uint64),
		SlabReclaimable:       out["slab_reclaimable"].(uint64),
		SlabUnreclaimable:     out["slab_unreclaimable"].(uint64),
		Pgfault:               out["pgfault"].(uint64),
		Pgmajfault:            out["pgmajfault"].(uint64),
		WorkingsetRefault:     out["workingset_refault"].(uint64),
		WorkingsetActivate:    out["workingset_activate"].(uint64),
		WorkingsetNodereclaim: out["workingset_nodereclaim"].(uint64),
		Pgrefill:              out["pgrefill"].(uint64),
		Pgscan:                out["pgscan"].(uint64),
		Pgsteal:               out["pgsteal"].(uint64),
		Pgactivate:            out["pgactivate"].(uint64),
		Pgdeactivate:          out["pgdeactivate"].(uint64),
		Pglazyfree:            out["pglazyfree"].(uint64),
		Pglazyfreed:           out["pglazyfreed"].(uint64),
		ThpFaultAlloc:         out["thp_fault_alloc"].(uint64),
		ThpCollapseAlloc:      out["thp_collapse_alloc"].(uint64),
	}
	return &metrics, nil
}

func getPidValue(key string, out map[string]interface{}) uint64 {
	v, ok := out[key]
	if !ok {
		return 0
	}
	switch t := v.(type) {
	case uint64:
		return t
	case string:
		if t == "max" {
			return math.MaxUint64
		}
	}
	return 0
}

func readSingleFile(path string, file string, out map[string]interface{}) error {
	f, err := os.Open(filepath.Join(path, file))
	if err != nil {
		return err
	}
	defer f.Close()
	data, err := ioutil.ReadAll(f)
	if err != nil {
		return err
	}
	s := string(data)
	v, err := parseUint(s, 10, 64)
	if err != nil {
		// if we cannot parse as a uint, parse as a string
		out[file] = s
		return nil
	}
	out[file] = v
	return nil
}

func readStatsFile(path string, file string, out map[string]interface{}) error {
	f, err := os.Open(filepath.Join(path, file))
	if err != nil {
		return err
	}
	defer f.Close()

	s := bufio.NewScanner(f)
	for s.Scan() {
		if err := s.Err(); err != nil {
			return err
		}
		name, value, err := parseKV(s.Text())
		if err != nil {
			return err
		}
		out[name] = value
	}
	return nil
}

func (c *Manager) Freeze() error {
	return c.freeze(c.path, Frozen)
}

func (c *Manager) Thaw() error {
	return c.freeze(c.path, Thawed)
}

func (c *Manager) freeze(path string, state State) error {
	values := state.Values()
	for {
		if err := writeValues(path, values); err != nil {
			return err
		}
		current, err := fetchState(path)
		if err != nil {
			return err
		}
		if current == state {
			return nil
		}
		time.Sleep(1 * time.Millisecond)
	}
}

func (c *Manager) MemoryEventFD() (uintptr, error) {
	fpath := filepath.Join(c.path, "memory.events")
	fd, err := syscall.InotifyInit()
	if err != nil {
		return 0, errors.Errorf("Failed to create inotify fd")
	}
	defer syscall.Close(fd)
	wd, err := syscall.InotifyAddWatch(fd, fpath, unix.IN_MODIFY)
	if wd < 0 {
		return 0, errors.Errorf("Failed to add inotify watch for %q", fpath)
	}
	defer syscall.InotifyRmWatch(fd, uint32(wd))

	return uintptr(fd), nil
}

func (c *Manager) EventChan() (<-chan Event, <-chan error) {
	ec := make(chan Event)
	errCh := make(chan error)
	go c.waitForEvents(ec, errCh)

	return ec, nil
}

func (c *Manager) waitForEvents(ec chan<- Event, errCh chan<- error) {
	fd, err := c.MemoryEventFD()
	if err != nil {
		errCh <- errors.Errorf("Failed to create memory event fd")
	}
	for {
		buffer := make([]byte, syscall.SizeofInotifyEvent*10)
		bytesRead, err := syscall.Read(int(fd), buffer)
		if err != nil {
			errCh <- err
		}
		var out map[string]interface{}
		if bytesRead >= syscall.SizeofInotifyEvent {
			if err := readStatsFile(c.path, "memory.events", out); err != nil {
				e := Event{
					High:    out["high"].(uint64),
					Low:     out["low"].(uint64),
					Max:     out["max"].(uint64),
					OOM:     out["oom"].(uint64),
					OOMKill: out["oom_kill"].(uint64),
				}
				ec <- e
			}
		}
	}
}
<commit_msg>Remove global var<commit_after>/*
   Copyright The containerd 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 implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

package v2

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"math"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"syscall"
	"time"

	"golang.org/x/sys/unix"

	"github.com/containerd/cgroups/v2/stats"
	"github.com/pkg/errors"
)

const (
	subtreeControl  = "cgroup.subtree_control"
	controllersFile = "cgroup.controllers"
)

type cgValuer interface {
	Values() []Value
}

type Event struct {
	Low     uint64
	High    uint64
	Max     uint64
	OOM     uint64
	OOMKill uint64
}

// Resources for a cgroups v2 unified hierarchy
type Resources struct {
	CPU    *CPU
	Memory *Memory
	Pids   *Pids
	IO     *IO
}

// Values returns the raw filenames and values that
// can be written to the unified hierarchy
func (r *Resources) Values() (o []Value) {
	values := []cgValuer{
		r.CPU,
		r.Memory,
		r.Pids,
		r.IO,
	}
	for _, v := range values {
		if v == nil {
			continue
		}
		o = append(o, v.Values()...)
	}
	return o
}

// Value of a cgroup setting
type Value struct {
	filename string
	value    interface{}
}

// write the value to the full, absolute path, of a unified hierarchy
func (c *Value) write(path string, perm os.FileMode) error {
	var data []byte
	switch t := c.value.(type) {
	case uint64:
		data = []byte(strconv.FormatUint(t, 10))
	case uint16:
		data = []byte(strconv.FormatUint(uint64(t), 10))
	case int64:
		data = []byte(strconv.FormatInt(t, 10))
	case []byte:
		data = t
	case string:
		data = []byte(t)
	default:
		return ErrInvalidFormat
	}
	return ioutil.WriteFile(
		filepath.Join(path, c.filename),
		data,
		perm,
	)
}

func writeValues(path string, values []Value) error {
	for _, o := range values {
		if err := o.write(path, defaultFilePerm); err != nil {
			return err
		}
	}
	return nil
}

func NewManager(mountpoint string, group string, resources *Resources) (*Manager, error) {
	if err := VerifyGroupPath(group); err != nil {
		return nil, err
	}
	path := filepath.Join(mountpoint, group)
	if err := os.MkdirAll(path, defaultDirPerm); err != nil {
		return nil, err
	}
	if resources != nil {
		if err := writeValues(path, resources.Values()); err != nil {
			// clean up cgroup dir on failure
			os.Remove(path)
			return nil, err
		}
	}
	return &Manager{
		unifiedMountpoint: mountpoint,
		path:              path,
	}, nil
}

func LoadManager(mountpoint string, group string) (*Manager, error) {
	if err := VerifyGroupPath(group); err != nil {
		return nil, err
	}
	path := filepath.Join(mountpoint, group)
	return &Manager{
		unifiedMountpoint: mountpoint,
		path:              path,
	}, nil
}

type Manager struct {
	unifiedMountpoint string
	path              string
}

func (c *Manager) ListControllers() ([]string, error) {
	f, err := os.Open(filepath.Join(c.path, controllersFile))
	if err != nil {
		return nil, err
	}
	defer f.Close()

	var (
		out []string
		s   = bufio.NewScanner(f)
	)
	s.Split(bufio.ScanWords)
	for s.Scan() {
		if err := s.Err(); err != nil {
			return nil, err
		}
		out = append(out, s.Text())
	}
	return out, nil
}

type ControllerToggle int

const (
	Enable ControllerToggle = iota + 1
	Disable
)

func toggleFunc(controllers []string, prefix string) []string {
	out := make([]string, len(controllers))
	for i, c := range controllers {
		out[i] = prefix + c
	}
	return out
}

func (c *Manager) ToggleControllers(controllers []string, t ControllerToggle) error {
	f, err := os.OpenFile(filepath.Join(c.path, subtreeControl), os.O_WRONLY, 0)
	if err != nil {
		return err
	}
	defer f.Close()
	switch t {
	case Enable:
		controllers = toggleFunc(controllers, "+")
	case Disable:
		controllers = toggleFunc(controllers, "-")
	}
	_, err = f.WriteString(strings.Join(controllers, " "))
	return err
}

func (c *Manager) NewChild(name string, resources *Resources) (*Manager, error) {
	if strings.HasPrefix(name, "/") {
		return nil, errors.New("name must be relative")
	}
	path := filepath.Join(c.path, name)
	if err := os.MkdirAll(path, defaultDirPerm); err != nil {
		return nil, err
	}
	if err := writeValues(path, resources.Values()); err != nil {
		// clean up cgroup dir on failure
		os.Remove(path)
		return nil, err
	}
	return &Manager{
		unifiedMountpoint: c.unifiedMountpoint,
		path:              path,
	}, nil
}

func (c *Manager) AddProc(pid uint64) error {
	v := Value{
		filename: cgroupProcs,
		value:    pid,
	}
	return writeValues(c.path, []Value{v})
}

func (c *Manager) Delete() error {
	return remove(c.path)
}

func (c *Manager) Procs(recursive bool) ([]uint64, error) {
	var processes []uint64
	err := filepath.Walk(c.path, func(p string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if !recursive && info.IsDir() {
			if p == c.path {
				return nil
			}
			return filepath.SkipDir
		}
		_, name := filepath.Split(p)
		if name != cgroupProcs {
			return nil
		}
		procs, err := parseCgroupProcsFile(p)
		if err != nil {
			return err
		}
		processes = append(processes, procs...)
		return nil
	})
	return processes, err
}

var singleValueFiles = []string{
	"pids.current",
	"pids.max",
}

func (c *Manager) Stat() (*stats.Metrics, error) {
	controllers, err := c.ListControllers()
	if err != nil {
		return nil, err
	}
	out := make(map[string]interface{})
	for _, controller := range controllers {
		filename := fmt.Sprintf("%s.stat", controller)
		if err := readStatsFile(c.path, filename, out); err != nil {
			if os.IsNotExist(err) {
				continue
			}
			return nil, err
		}
	}
	for _, name := range singleValueFiles {
		if err := readSingleFile(c.path, name, out); err != nil {
			if os.IsNotExist(err) {
				continue
			}
			return nil, err
		}
	}
	var metrics stats.Metrics

	metrics.Pids = &stats.PidsStat{
		Current: getPidValue("pids.current", out),
		Limit:   getPidValue("pids.max", out),
	}
	metrics.CPU = &stats.CPUStat{
		UsageUsec:     out["usage_usec"].(uint64),
		UserUsec:      out["user_usec"].(uint64),
		SystemUsec:    out["system_usec"].(uint64),
		NrPeriods:     out["nr_periods"].(uint64),
		NrThrottled:   out["nr_throttled"].(uint64),
		ThrottledUsec: out["throttled_usec"].(uint64),
	}
	metrics.Memory = &stats.MemoryStat{
		Anon:                  out["anon"].(uint64),
		File:                  out["file"].(uint64),
		KernelStack:           out["kernel_stack"].(uint64),
		Slab:                  out["slab"].(uint64),
		Sock:                  out["sock"].(uint64),
		Shmem:                 out["shmem"].(uint64),
		FileMapped:            out["file_mapped"].(uint64),
		FileDirty:             out["file_dirty"].(uint64),
		FileWriteback:         out["file_writeback"].(uint64),
		AnonThp:               out["anon_thp"].(uint64),
		InactiveAnon:          out["inactive_anon"].(uint64),
		ActiveAnon:            out["active_anon"].(uint64),
		InactiveFile:          out["inactive_file"].(uint64),
		ActiveFile:            out["active_file"].(uint64),
		Unevictable:           out["unevictable"].(uint64),
		SlabReclaimable:       out["slab_reclaimable"].(uint64),
		SlabUnreclaimable:     out["slab_unreclaimable"].(uint64),
		Pgfault:               out["pgfault"].(uint64),
		Pgmajfault:            out["pgmajfault"].(uint64),
		WorkingsetRefault:     out["workingset_refault"].(uint64),
		WorkingsetActivate:    out["workingset_activate"].(uint64),
		WorkingsetNodereclaim: out["workingset_nodereclaim"].(uint64),
		Pgrefill:              out["pgrefill"].(uint64),
		Pgscan:                out["pgscan"].(uint64),
		Pgsteal:               out["pgsteal"].(uint64),
		Pgactivate:            out["pgactivate"].(uint64),
		Pgdeactivate:          out["pgdeactivate"].(uint64),
		Pglazyfree:            out["pglazyfree"].(uint64),
		Pglazyfreed:           out["pglazyfreed"].(uint64),
		ThpFaultAlloc:         out["thp_fault_alloc"].(uint64),
		ThpCollapseAlloc:      out["thp_collapse_alloc"].(uint64),
	}
	return &metrics, nil
}

func getPidValue(key string, out map[string]interface{}) uint64 {
	v, ok := out[key]
	if !ok {
		return 0
	}
	switch t := v.(type) {
	case uint64:
		return t
	case string:
		if t == "max" {
			return math.MaxUint64
		}
	}
	return 0
}

func readSingleFile(path string, file string, out map[string]interface{}) error {
	f, err := os.Open(filepath.Join(path, file))
	if err != nil {
		return err
	}
	defer f.Close()
	data, err := ioutil.ReadAll(f)
	if err != nil {
		return err
	}
	s := string(data)
	v, err := parseUint(s, 10, 64)
	if err != nil {
		// if we cannot parse as a uint, parse as a string
		out[file] = s
		return nil
	}
	out[file] = v
	return nil
}

func readStatsFile(path string, file string, out map[string]interface{}) error {
	f, err := os.Open(filepath.Join(path, file))
	if err != nil {
		return err
	}
	defer f.Close()

	s := bufio.NewScanner(f)
	for s.Scan() {
		if err := s.Err(); err != nil {
			return err
		}
		name, value, err := parseKV(s.Text())
		if err != nil {
			return err
		}
		out[name] = value
	}
	return nil
}

func (c *Manager) Freeze() error {
	return c.freeze(c.path, Frozen)
}

func (c *Manager) Thaw() error {
	return c.freeze(c.path, Thawed)
}

func (c *Manager) freeze(path string, state State) error {
	values := state.Values()
	for {
		if err := writeValues(path, values); err != nil {
			return err
		}
		current, err := fetchState(path)
		if err != nil {
			return err
		}
		if current == state {
			return nil
		}
		time.Sleep(1 * time.Millisecond)
	}
}

func (c *Manager) MemoryEventFD() (uintptr, error) {
	fpath := filepath.Join(c.path, "memory.events")
	fd, err := syscall.InotifyInit()
	if err != nil {
		return 0, errors.Errorf("Failed to create inotify fd")
	}
	defer syscall.Close(fd)
	wd, err := syscall.InotifyAddWatch(fd, fpath, unix.IN_MODIFY)
	if wd < 0 {
		return 0, errors.Errorf("Failed to add inotify watch for %q", fpath)
	}
	defer syscall.InotifyRmWatch(fd, uint32(wd))

	return uintptr(fd), nil
}

func (c *Manager) EventChan() (<-chan Event, <-chan error) {
	ec := make(chan Event)
	errCh := make(chan error)
	go c.waitForEvents(ec, errCh)

	return ec, nil
}

func (c *Manager) waitForEvents(ec chan<- Event, errCh chan<- error) {
	fd, err := c.MemoryEventFD()
	if err != nil {
		errCh <- errors.Errorf("Failed to create memory event fd")
	}
	for {
		buffer := make([]byte, syscall.SizeofInotifyEvent*10)
		bytesRead, err := syscall.Read(int(fd), buffer)
		if err != nil {
			errCh <- err
		}
		var out map[string]interface{}
		if bytesRead >= syscall.SizeofInotifyEvent {
			if err := readStatsFile(c.path, "memory.events", out); err != nil {
				e := Event{
					High:    out["high"].(uint64),
					Low:     out["low"].(uint64),
					Max:     out["max"].(uint64),
					OOM:     out["oom"].(uint64),
					OOMKill: out["oom_kill"].(uint64),
				}
				ec <- e
			}
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2016-2020 The Libsacloud 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 implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package libsacloud

// Version バージョン
const Version = "2.9.1"
<commit_msg>Bump to v2.9.2<commit_after>// Copyright 2016-2020 The Libsacloud 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 implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package libsacloud

// Version バージョン
const Version = "2.9.2"
<|endoftext|>


<commit_before>package otp

import (
	"encoding/base32"
	"strings"
)

func (k Key) hasValidMethod() error {
	if !stringInSlice(k.Method, METHODS) {
		return KeyError{"Method", "Invalid value"}
	}
	return nil
}

func (k Key) hasValidLabel() error {
	if len(k.Label) == 0 {
		return KeyError{"Label", "Missing value"}
	}

	if strings.ContainsRune(k.Label, '/') {
		return KeyError{"Label", "Contains '/'"}
	}

	return nil
}

func (k Key) hasValidSecret() error {
	if len(k.Secret) == 0 {
		return KeyError{"Secret", "Missing value"}
	}

	if _, err := base32.StdEncoding.DecodeString(k.Secret); err != nil {
		return KeyError{"Secret", "Invalid Base32"}
	}

	return nil
}

func (k Key) hasValidIssuer() error {
	if strings.ContainsRune(k.Issuer, '/') {
		return KeyError{"Issuer", "Contains '/'"}
	}
	return nil
}

func (k Key) hasValidAlgo() error {
	if !hashInSlice(k.Algo, HASHES) {
		return KeyError{"Algo", "Invalid hashing algorithm"}
	}
	return nil
}

func (k Key) hasValidDigits() error {
	if !(k.Digits == 6 || k.Digits == 8) {
		return KeyError{"Digits", "Not equal to 6 or 8"}
	}
	return nil
}

func (k Key) hasValidPeriod() error {
	if k.Method == "totp" && k.Period < 1 {
		return KeyError{"Period", "Negative value"}
	}
	return nil
}

func (k Key) Validate() error {

	// check method
	if err := k.hasValidMethod(); err != nil {
		return err
	}

	//check label
	if err := k.hasValidLabel(); err != nil {
		return err
	}

	// check secret
	if err := k.hasValidSecret(); err != nil {
		return err
	}

	// check issuer
	if err := k.hasValidIssuer(); err != nil {
		return err
	}

	// check algo
	if err := k.hasValidAlgo(); err != nil {
		return err
	}

	// check digits
	if err := k.hasValidDigits(); err != nil {
		return err
	}

	// check period
	if err := k.hasValidPeriod(); err != nil {
		return err
	}

	return nil
}
<commit_msg>leniency<commit_after>package otp

import (
	"encoding/base32"
)

func (k Key) hasValidMethod() error {
	if !stringInSlice(k.Method, METHODS) {
		return KeyError{"Method", "Invalid value"}
	}
	return nil
}

func (k Key) hasValidLabel() error {
	if len(k.Label) == 0 {
		return KeyError{"Label", "Missing value"}
	}
	return nil
}

func (k Key) hasValidSecret() error {
	if len(k.Secret) == 0 {
		return KeyError{"Secret", "Missing value"}
	}

	if _, err := base32.StdEncoding.DecodeString(k.Secret); err != nil {
		return KeyError{"Secret", "Invalid Base32"}
	}

	return nil
}

func (k Key) hasValidAlgo() error {
	if !hashInSlice(k.Algo, HASHES) {
		return KeyError{"Algo", "Invalid hashing algorithm"}
	}
	return nil
}

func (k Key) hasValidDigits() error {
	if !(k.Digits == 6 || k.Digits == 8) {
		return KeyError{"Digits", "Not equal to 6 or 8"}
	}
	return nil
}

func (k Key) hasValidPeriod() error {
	if k.Method == "totp" && k.Period < 1 {
		return KeyError{"Period", "Negative value"}
	}
	return nil
}

func (k Key) Validate() error {

	// check method
	if err := k.hasValidMethod(); err != nil {
		return err
	}

	//check label
	if err := k.hasValidLabel(); err != nil {
		return err
	}

	// check secret
	if err := k.hasValidSecret(); err != nil {
		return err
	}

	// check algo
	if err := k.hasValidAlgo(); err != nil {
		return err
	}

	// check digits
	if err := k.hasValidDigits(); err != nil {
		return err
	}

	// check period
	if err := k.hasValidPeriod(); err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package vow

import (
	"fmt"
	"os"
)

// Result represents the outcome of the Vow that was run
type Result struct {
	// Failed will be true if any command was not successful
	Failed bool

	results  []cmdResult
	executed int
}

type cmdResult struct {
	command string
	args    []string

	ps     *os.ProcessState
	output []byte
	failed bool
}

func (r *Result) String() string {
	s := "To Result:\n"
	s += fmt.Sprintf("\tRan %d of %d commands\n", r.executed, len(r.results))

	for i := 0; i < len(r.results); i++ {
		cmdrslt := r.results[i]

		var outcome string
		switch {
		case i < r.executed-1 ||
			(i == r.executed-1 && !cmdrslt.failed):
			outcome = "SUCCESS - "
		case i >= r.executed:
			outcome = "SKIPPED - "
		case i == r.executed-1:
			outcome = "FAILED  - "
		}

		s += fmt.Sprintf("\t%s%s - %v\n", outcome, cmdrslt.command, cmdrslt.args)

		if cmdrslt.failed {
			s += fmt.Sprintf("Output:\n%s\n", cmdrslt.output)
		}
	}
	return s
}
<commit_msg>removing result.String() function until it's actually needed<commit_after>package vow

import "os"

// Result represents the outcome of the Vow that was run
type Result struct {
	// Failed will be true if any command was not successful
	Failed bool

	results  []cmdResult
	executed int
}

type cmdResult struct {
	command string
	args    []string

	ps     *os.ProcessState
	output []byte
	failed bool
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/sha256"
	"encoding/hex"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"syscall"
	"time"
)

// Command holds all data needed to start a command.
type Command struct {
	Name     string
	Run      string
	Filter   []string
	Interval int

	statefile string
	start     time.Time
}

// Execute runs the command with the given filter functions.
func (c Command) Execute(statedir string) ([]byte, error) {
	V("execute command %q\n", c.Run)

	c.statefile = filepath.Join(statedir, c.stateFilename())

	last := time.Now().Sub(c.lastRun())
	interval := time.Duration(c.Interval) * time.Second
	if last < interval {
		V("command has been run only %v ago, which is less than %v\n", last, interval)
		return nil, nil
	}

	cmd := exec.Command("sh", "-c", c.Run)
	cmd.Stderr = os.Stderr

	state, err := c.loadOldState()
	if err != nil {
		E("unable to read old state file: %v\n", err)
	}

	output, err := cmd.Output()
	if err != nil {
		return nil, err
	}

	diff, err := Compare(state, output)
	if err != nil {
		V("return error %#v\n", err)
	}

	return diff, c.saveNewState(output)
}

func (c Command) loadOldState() (state []byte, err error) {
	f, err := os.Open(c.statefile)
	if os.IsNotExist(err) {
		return nil, nil
	}
	defer func() {
		e := f.Close()
		if err == nil && e != nil {
			err = e
		}
	}()

	return ioutil.ReadAll(f)
}

func (c Command) saveNewState(state []byte) (err error) {
	f, err := os.Create(c.statefile)
	if err != nil {
		return err
	}
	defer func() {
		e := f.Close()
		if err == nil {
			err = e
		}
	}()

	_, err = f.Write(state)
	return err
}

func (c Command) stateFilename() string {
	hash := sha256.Sum256([]byte(c.Run))
	return hex.EncodeToString(hash[:])
}

func (c Command) lastRun() time.Time {
	fi, err := os.Stat(c.statefile)
	if os.IsNotExist(err) {
		return time.Unix(0, 0)
	}

	return fi.ModTime()
}

func writeToFile(filename string, content []byte) error {
	file, err := os.Create(filename)
	if err != nil {
		return err
	}

	_, err = file.Write(content)
	if err != nil {
		return err
	}

	return file.Close()
}

func diff(dir, file1, file2 string) ([]byte, error) {
	V("compare %v and %v\n", file1, file2)
	cmd := exec.Command("git", "diff", "--", file1, file2)
	cmd.Dir = dir
	cmd.Stderr = os.Stderr
	buf, err := cmd.Output()

	if e, ok := err.(*exec.ExitError); ok {
		s := e.ProcessState.Sys().(syscall.WaitStatus)

		// ignore exit code 1, this just means there were differences
		if s.ExitStatus() == 1 {
			return buf, nil
		}
	}

	return buf, err
}

// Compare compares the output to the old output by running `git diff`.
func Compare(oldOutput, newOutput []byte) (output []byte, err error) {
	V("compare output to old output\n")

	tempdir, err := ioutil.TempDir("", "dachs-compare-")
	defer func() {
		// e := os.RemoveAll(tempdir)
		// if err != nil {
		// 	err = e
		// }
	}()

	err = writeToFile(filepath.Join(tempdir, "new"), newOutput)
	if err != nil {
		return nil, err
	}

	err = writeToFile(filepath.Join(tempdir, "old"), oldOutput)
	if err != nil {
		return nil, err
	}

	return diff(tempdir, "old", "new")
}
<commit_msg>Remove tempdir after execution<commit_after>package main

import (
	"crypto/sha256"
	"encoding/hex"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"syscall"
	"time"
)

// Command holds all data needed to start a command.
type Command struct {
	Name     string
	Run      string
	Filter   []string
	Interval int

	statefile string
	start     time.Time
}

// Execute runs the command with the given filter functions.
func (c Command) Execute(statedir string) ([]byte, error) {
	V("execute command %q\n", c.Run)

	c.statefile = filepath.Join(statedir, c.stateFilename())

	last := time.Now().Sub(c.lastRun())
	interval := time.Duration(c.Interval) * time.Second
	if last < interval {
		V("command has been run only %v ago, which is less than %v\n", last, interval)
		return nil, nil
	}

	cmd := exec.Command("sh", "-c", c.Run)
	cmd.Stderr = os.Stderr

	state, err := c.loadOldState()
	if err != nil {
		E("unable to read old state file: %v\n", err)
	}

	output, err := cmd.Output()
	if err != nil {
		return nil, err
	}

	diff, err := Compare(state, output)
	if err != nil {
		V("return error %#v\n", err)
	}

	return diff, c.saveNewState(output)
}

func (c Command) loadOldState() (state []byte, err error) {
	f, err := os.Open(c.statefile)
	if os.IsNotExist(err) {
		return nil, nil
	}
	defer func() {
		e := f.Close()
		if err == nil && e != nil {
			err = e
		}
	}()

	return ioutil.ReadAll(f)
}

func (c Command) saveNewState(state []byte) (err error) {
	f, err := os.Create(c.statefile)
	if err != nil {
		return err
	}
	defer func() {
		e := f.Close()
		if err == nil {
			err = e
		}
	}()

	_, err = f.Write(state)
	return err
}

func (c Command) stateFilename() string {
	hash := sha256.Sum256([]byte(c.Run))
	return hex.EncodeToString(hash[:])
}

func (c Command) lastRun() time.Time {
	fi, err := os.Stat(c.statefile)
	if os.IsNotExist(err) {
		return time.Unix(0, 0)
	}

	return fi.ModTime()
}

func writeToFile(filename string, content []byte) error {
	file, err := os.Create(filename)
	if err != nil {
		return err
	}

	_, err = file.Write(content)
	if err != nil {
		return err
	}

	return file.Close()
}

func diff(dir, file1, file2 string) ([]byte, error) {
	V("compare %v and %v\n", file1, file2)
	cmd := exec.Command("git", "diff", "--", file1, file2)
	cmd.Dir = dir
	cmd.Stderr = os.Stderr
	buf, err := cmd.Output()

	if e, ok := err.(*exec.ExitError); ok {
		s := e.ProcessState.Sys().(syscall.WaitStatus)

		// ignore exit code 1, this just means there were differences
		if s.ExitStatus() == 1 {
			return buf, nil
		}
	}

	return buf, err
}

// Compare compares the output to the old output by running `git diff`.
func Compare(oldOutput, newOutput []byte) (output []byte, err error) {
	V("compare output to old output\n")

	tempdir, err := ioutil.TempDir("", "dachs-compare-")
	defer func() {
		e := os.RemoveAll(tempdir)
		if err != nil {
			err = e
		}
	}()

	err = writeToFile(filepath.Join(tempdir, "new"), newOutput)
	if err != nil {
		return nil, err
	}

	err = writeToFile(filepath.Join(tempdir, "old"), oldOutput)
	if err != nil {
		return nil, err
	}

	return diff(tempdir, "old", "new")
}
<|endoftext|>


<commit_before>package main

import (
  "log"
  "os"
  "path/filepath"
  "sync"
)

type UpdateFileInfo struct {
  Filepath string `json:"path"`
  Sha1 string `json:"sha1"`
  FileSize int64 `json:"size"`
}

type UpdateFilesProvider interface {
  FilesToAdd() []*UpdateFileInfo
  FilesToRemove() []*UpdateFileInfo
  FilesToUpdate() []*UpdateFileInfo
}

type DiffGenerator struct {
  filesToAdd []*UpdateFileInfo
  filesToRemove []*UpdateFileInfo
  filesToUpdate []*UpdateFileInfo
  filesToAddQueue chan *UpdateFileInfo
  filesToRemoveQueue chan *UpdateFileInfo
  filesToUpdateQueue chan *UpdateFileInfo
  errors chan error
  installDirHashes map[string]string
  packageDirHashes map[string]string
  installDirPath string
  packageDirPath string
  keepMissing bool
  forceUpdate bool
}

func (df DiffGenerator) FilesToAdd() []*UpdateFileInfo {
  return df.filesToAdd
}

func (df DiffGenerator) FilesToUpdate() []*UpdateFileInfo {
  return df.filesToUpdate
}

func (df DiffGenerator) FilesToRemove() []*UpdateFileInfo {
  return df.filesToRemove
}

func (df *DiffGenerator) GenerateDiffs() error {
  err := df.calculateHashes()
  if err != nil {
    return err
  }

  var wg sync.WaitGroup

  wg.Add(1)
  go func() {
    for fi := range df.filesToAddQueue {
      df.filesToAdd = append(df.filesToAdd, fi)
    }

    log.Printf("Found %v files to add", len(df.filesToAdd))
    wg.Done()
  }()

  wg.Add(1)
  go func() {
    for fi := range df.filesToRemoveQueue {
      df.filesToRemove = append(df.filesToRemove, fi)
    }

    log.Printf("Found %v files to remove", len(df.filesToRemove))
    wg.Done()
  }()

  wg.Add(1)
  go func() {
    for fi := range df.filesToUpdateQueue {
      df.filesToUpdate = append(df.filesToUpdate, fi)
    }

    log.Printf("Found %v files to update", len(df.filesToUpdate))
    wg.Done()
  }()

  go df.generateDirectoryDiff(df.installDirPath, df.packageDirPath)
  go func() {
    wg.Wait()
    df.errors <- nil
  }()

  if err := <- df.errors; err != nil {
    return err
  }

  return nil
}

func (df *DiffGenerator) calculateHashes() error {
  log.Println("Calculating hashes...")

  ierrc := make(chan error, 1)
  perrc := make(chan error, 1)

  go func() {
    var err error
    df.installDirHashes, err = CalculateHashes(df.installDirPath)
    ierrc <- err
  }()

  go func() {
    var err error
    df.packageDirHashes, err = CalculateHashes(df.packageDirPath)
    perrc <- err
  }()

  defer log.Println("Hashes calculated")

  if err := <- ierrc; err != nil { return err }
  if err := <- perrc; err != nil { return err }

  return nil
}

func (df *DiffGenerator) generateDirectoryDiff(installDir, packageDir string) {
  log.Printf("Install dir: %v, packageDir: %v", installDir, packageDir);

  go df.findFilesToRemoveOrUpdate(installDir, packageDir)
  go df.findFilesToAdd(installDir, packageDir)
}

func (df *DiffGenerator) findFilesToRemoveOrUpdate(installDir, packageDir string) {
  var wg sync.WaitGroup

  err := filepath.Walk(installDir, func(path string, info os.FileInfo, err error) error {
    if err != nil {
      return err
    }

    if !info.Mode().IsRegular() {
      return nil
    }

    wg.Add(1)

    go func() {
      relativePath, err := filepath.Rel(df.installDirPath, path)
      if err != nil { log.Fatal(err) }
      relativePath = filepath.ToSlash(relativePath)
      packagePath := filepath.Join(df.packageDirPath, relativePath)
      installFileHash := df.installDirHashes[relativePath]

      ufi := &UpdateFileInfo{
        Filepath: relativePath,
        Sha1: installFileHash }

      if pfi, err := os.Stat(packagePath); os.IsNotExist(err) {
        if !df.keepMissing {
          efi, _ := os.Stat(path)
          ufi.FileSize = efi.Size()
          df.filesToRemoveQueue <- ufi
        }
      } else {
        packageFileHash := df.packageDirHashes[relativePath]

        if (packageFileHash != installFileHash) || (df.forceUpdate) {
          ufi.FileSize = pfi.Size()
          df.filesToUpdateQueue <- ufi
        }
      }

      wg.Done()
    }()

    return nil
  })

  go func() {
    wg.Wait()
    close(df.filesToRemoveQueue)
    close(df.filesToUpdateQueue)
  }()

  if err != nil {
    df.errors <- err
  }
}

func (df *DiffGenerator) findFilesToAdd(installDir, packageDir string) {
  var wg sync.WaitGroup
  err := filepath.Walk(packageDir, func(path string, info os.FileInfo, err error) error {
    if err != nil {
      return err
    }

    if !info.Mode().IsRegular() {
      return nil
    }

    wg.Add(1)

    go func() {
      relativePath, err := filepath.Rel(df.packageDirPath, path)
      if err != nil { log.Fatal(err) }
      relativePath = filepath.ToSlash(relativePath)
      installPath := filepath.Join(df.installDirPath, relativePath)

      if pfi, err := os.Stat(installPath); os.IsNotExist(err) {
        packageFileHash := df.packageDirHashes[relativePath]

        df.filesToAddQueue <- &UpdateFileInfo{
          Filepath: relativePath,
          Sha1: packageFileHash,
          FileSize: pfi.Size(),
        }
      }

      wg.Done()
    }()

    return nil
  })

  go func() {
    wg.Wait()
    close(df.filesToAddQueue)
  }()

  if err != nil {
    df.errors <- err
  }
}
<commit_msg>Fixes typo<commit_after>package main

import (
  "log"
  "os"
  "path/filepath"
  "sync"
)

type UpdateFileInfo struct {
  Filepath string `json:"path"`
  Sha1 string `json:"sha1"`
  FileSize int64 `json:"size"`
}

type UpdateFilesProvider interface {
  FilesToAdd() []*UpdateFileInfo
  FilesToRemove() []*UpdateFileInfo
  FilesToUpdate() []*UpdateFileInfo
}

type DiffGenerator struct {
  filesToAdd []*UpdateFileInfo
  filesToRemove []*UpdateFileInfo
  filesToUpdate []*UpdateFileInfo
  filesToAddQueue chan *UpdateFileInfo
  filesToRemoveQueue chan *UpdateFileInfo
  filesToUpdateQueue chan *UpdateFileInfo
  errors chan error
  installDirHashes map[string]string
  packageDirHashes map[string]string
  installDirPath string
  packageDirPath string
  keepMissing bool
  forceUpdate bool
}

func (df DiffGenerator) FilesToAdd() []*UpdateFileInfo {
  return df.filesToAdd
}

func (df DiffGenerator) FilesToUpdate() []*UpdateFileInfo {
  return df.filesToUpdate
}

func (df DiffGenerator) FilesToRemove() []*UpdateFileInfo {
  return df.filesToRemove
}

func (df *DiffGenerator) GenerateDiffs() error {
  err := df.calculateHashes()
  if err != nil {
    return err
  }

  var wg sync.WaitGroup

  wg.Add(1)
  go func() {
    for fi := range df.filesToAddQueue {
      df.filesToAdd = append(df.filesToAdd, fi)
    }

    log.Printf("Found %v files to add", len(df.filesToAdd))
    wg.Done()
  }()

  wg.Add(1)
  go func() {
    for fi := range df.filesToRemoveQueue {
      df.filesToRemove = append(df.filesToRemove, fi)
    }

    log.Printf("Found %v files to remove", len(df.filesToRemove))
    wg.Done()
  }()

  wg.Add(1)
  go func() {
    for fi := range df.filesToUpdateQueue {
      df.filesToUpdate = append(df.filesToUpdate, fi)
    }

    log.Printf("Found %v files to update", len(df.filesToUpdate))
    wg.Done()
  }()

  go df.generateDirectoryDiff(df.installDirPath, df.packageDirPath)
  go func() {
    wg.Wait()
    df.errors <- nil
  }()

  if err := <- df.errors; err != nil {
    return err
  }

  return nil
}

func (df *DiffGenerator) calculateHashes() error {
  log.Println("Calculating hashes...")

  ierrc := make(chan error, 1)
  perrc := make(chan error, 1)

  go func() {
    var err error
    df.installDirHashes, err = CalculateHashes(df.installDirPath)
    ierrc <- err
  }()

  go func() {
    var err error
    df.packageDirHashes, err = CalculateHashes(df.packageDirPath)
    perrc <- err
  }()

  defer log.Println("Hashes calculated")

  if err := <- ierrc; err != nil { return err }
  if err := <- perrc; err != nil { return err }

  return nil
}

func (df *DiffGenerator) generateDirectoryDiff(installDir, packageDir string) {
  log.Printf("Install dir: %v, packageDir: %v", installDir, packageDir);

  go df.findFilesToRemoveOrUpdate(installDir, packageDir)
  go df.findFilesToAdd(installDir, packageDir)
}

func (df *DiffGenerator) findFilesToRemoveOrUpdate(installDir, packageDir string) {
  var wg sync.WaitGroup

  err := filepath.Walk(installDir, func(path string, info os.FileInfo, err error) error {
    if err != nil {
      return err
    }

    if !info.Mode().IsRegular() {
      return nil
    }

    wg.Add(1)

    go func() {
      relativePath, err := filepath.Rel(df.installDirPath, path)
      if err != nil { log.Fatal(err) }
      relativePath = filepath.ToSlash(relativePath)
      packagePath := filepath.Join(df.packageDirPath, relativePath)
      installFileHash := df.installDirHashes[relativePath]

      ufi := &UpdateFileInfo{
        Filepath: relativePath,
        Sha1: installFileHash }

      if pfi, err := os.Stat(packagePath); os.IsNotExist(err) {
        if !df.keepMissing {
          efi, _ := os.Stat(path)
          ufi.FileSize = efi.Size()
          df.filesToRemoveQueue <- ufi
        }
      } else {
        packageFileHash := df.packageDirHashes[relativePath]

        if (packageFileHash != installFileHash) || (df.forceUpdate) {
          ufi.FileSize = pfi.Size()
          df.filesToUpdateQueue <- ufi
        }
      }

      wg.Done()
    }()

    return nil
  })

  go func() {
    wg.Wait()
    close(df.filesToRemoveQueue)
    close(df.filesToUpdateQueue)
  }()

  if err != nil {
    df.errors <- err
  }
}

func (df *DiffGenerator) findFilesToAdd(installDir, packageDir string) {
  var wg sync.WaitGroup
  err := filepath.Walk(packageDir, func(path string, info os.FileInfo, err error) error {
    if err != nil {
      return err
    }

    if !info.Mode().IsRegular() {
      return nil
    }

    wg.Add(1)

    go func() {
      relativePath, err := filepath.Rel(df.packageDirPath, path)
      if err != nil { log.Fatal(err) }
      relativePath = filepath.ToSlash(relativePath)
      installPath := filepath.Join(df.installDirPath, relativePath)

      if pfi, err := os.Stat(installPath); os.IsNotExist(err) {
        packageFileHash := df.packageDirHashes[relativePath]
        efi, _ := os.Stat(path)

        df.filesToAddQueue <- &UpdateFileInfo{
          Filepath: relativePath,
          Sha1: packageFileHash,
          FileSize: efi.Size(),
        }
      }

      wg.Done()
    }()

    return nil
  })

  go func() {
    wg.Wait()
    close(df.filesToAddQueue)
  }()

  if err != nil {
    df.errors <- err
  }
}
<|endoftext|>


<commit_before>// +build unit

package image

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

	"testing"
)

func TestValidation(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Validation Suite")
}
<commit_msg>Removed empty validation test suite (#264)<commit_after><|endoftext|>


<commit_before>package nlp

import (
	"io"
	"math"

	"github.com/james-bowman/sparse"
	"gonum.org/v1/gonum/mat"
)

// TfidfTransformer takes a raw term document matrix and weights each raw term frequency
// value depending upon how commonly it occurs across all documents within the corpus.
// For example a very commonly occurring word like `the` is likely to occur in all documents
// and so would be weighted down.
// More precisely, TfidfTransformer applies a tf-idf algorithm to the matrix where each
// term frequency is multiplied by the inverse document frequency.  Inverse document
// frequency is calculated as log(n/df) where df is the number of documents in which the
// term occurs and n is the total number of documents within the corpus.  We add 1 to both n
// and df before division to prevent division by zero.
type TfidfTransformer struct {
	transform *sparse.DIA
}

// NewTfidfTransformer constructs a new TfidfTransformer.
func NewTfidfTransformer() *TfidfTransformer {
	return &TfidfTransformer{}
}

// Fit takes a training term document matrix, counts term occurrences across all documents
// and constructs an inverse document frequency transform to apply to matrices in subsequent
// calls to Transform().
func (t *TfidfTransformer) Fit(matrix mat.Matrix) Transformer {
	if t, isTypeConv := matrix.(sparse.TypeConverter); isTypeConv {
		matrix = t.ToCSR()
	}
	m, n := matrix.Dims()

	weights := make([]float64, m)
	csr, ok := matrix.(*sparse.CSR)

	for i := 0; i < m; i++ {
		df := 0
		if ok {
			df = csr.RowNNZ(i)
		} else {
			for j := 0; j < n; j++ {
				if matrix.At(i, j) != 0 {
					df++
				}
			}
		}
		idf := math.Log(float64(1+n) / float64(1+df))
		weights[i] = idf
	}

	// build a diagonal matrix from array of term weighting values for subsequent
	// multiplication with term document matrics
	t.transform = sparse.NewDIA(m, m, weights)

	return t
}

// Transform applies the inverse document frequency (IDF) transform by multiplying
// each term frequency by its corresponding IDF value.  This has the effect of weighting
// each term frequency according to how often it appears across the whole document corpus
// so that naturally frequent occurring words are given less weight than uncommon ones.
// The returned matrix is a sparse matrix type.
func (t *TfidfTransformer) Transform(matrix mat.Matrix) (mat.Matrix, error) {
	if t, isTypeConv := matrix.(sparse.TypeConverter); isTypeConv {
		matrix = t.ToCSR()
	}
	var product sparse.CSR

	// simply multiply the matrix by our idf transform (the diagonal matrix of term weights)
	product.Mul(t.transform, matrix)

	// todo: possibly L2 norm matrix to remove any bias caused by documents of different
	// lengths where longer documents naturally have more words and so higher word counts

	return &product, nil
}

// FitTransform is exactly equivalent to calling Fit() followed by Transform() on the
// same matrix.  This is a convenience where separate training data is not being
// used to fit the model i.e. the model is fitted on the fly to the test data.
// The returned matrix is a sparse matrix type.
func (t *TfidfTransformer) FitTransform(matrix mat.Matrix) (mat.Matrix, error) {
	if t, isTypeConv := matrix.(sparse.TypeConverter); isTypeConv {
		matrix = t.ToCSR()
	}
	return t.Fit(matrix).Transform(matrix)
}

// Save binary serialises the model and writes it into w.  This is useful for persisting
// a trained model to disk so that it may be loaded (using the Load() method)in another
// context (e.g. production) for reproducible results.
func (t TfidfTransformer) Save(w io.Writer) error {
	_, err := t.transform.MarshalBinaryTo(w)

	return err
}

// Load binary deserialises the previously serialised model into the receiver.  This is
// useful for loading a previously trained and saved model from another context
// (e.g. offline training) for use within another context (e.g. production) for
// reproducible results.  Load should only be performed with trusted data.
func (t *TfidfTransformer) Load(r io.Reader) error {
	var model sparse.DIA

	if _, err := model.UnmarshalBinaryFrom(r); err != nil {
		return err
	}
	t.transform = &model

	return nil
}
<commit_msg>Moved conditional branch to outside of loop<commit_after>package nlp

import (
	"io"
	"math"

	"github.com/james-bowman/sparse"
	"gonum.org/v1/gonum/mat"
)

// TfidfTransformer takes a raw term document matrix and weights each raw term frequency
// value depending upon how commonly it occurs across all documents within the corpus.
// For example a very commonly occurring word like `the` is likely to occur in all documents
// and so would be weighted down.
// More precisely, TfidfTransformer applies a tf-idf algorithm to the matrix where each
// term frequency is multiplied by the inverse document frequency.  Inverse document
// frequency is calculated as log(n/df) where df is the number of documents in which the
// term occurs and n is the total number of documents within the corpus.  We add 1 to both n
// and df before division to prevent division by zero.
type TfidfTransformer struct {
	transform *sparse.DIA
}

// NewTfidfTransformer constructs a new TfidfTransformer.
func NewTfidfTransformer() *TfidfTransformer {
	return &TfidfTransformer{}
}

// Fit takes a training term document matrix, counts term occurrences across all documents
// and constructs an inverse document frequency transform to apply to matrices in subsequent
// calls to Transform().
func (t *TfidfTransformer) Fit(matrix mat.Matrix) Transformer {
	if t, isTypeConv := matrix.(sparse.TypeConverter); isTypeConv {
		matrix = t.ToCSR()
	}
	m, n := matrix.Dims()

	weights := make([]float64, m)
	var df int
	if csr, ok := matrix.(*sparse.CSR); ok {
		for i := 0; i < m; i++ {
			weights[i] = math.Log(float64(1+n) / float64(1+csr.RowNNZ(i)))
		}
	} else {
		for i := 0; i < m; i++ {
			df = 0
			for j := 0; j < n; j++ {
				if matrix.At(i, j) != 0 {
					df++
				}
			}
			weights[i] = math.Log(float64(1+n) / float64(1+df))
		}
	}

	// build a diagonal matrix from array of term weighting values for subsequent
	// multiplication with term document matrics
	t.transform = sparse.NewDIA(m, m, weights)

	return t
}

// Transform applies the inverse document frequency (IDF) transform by multiplying
// each term frequency by its corresponding IDF value.  This has the effect of weighting
// each term frequency according to how often it appears across the whole document corpus
// so that naturally frequent occurring words are given less weight than uncommon ones.
// The returned matrix is a sparse matrix type.
func (t *TfidfTransformer) Transform(matrix mat.Matrix) (mat.Matrix, error) {
	if t, isTypeConv := matrix.(sparse.TypeConverter); isTypeConv {
		matrix = t.ToCSR()
	}
	var product sparse.CSR

	// simply multiply the matrix by our idf transform (the diagonal matrix of term weights)
	product.Mul(t.transform, matrix)

	// todo: possibly L2 norm matrix to remove any bias caused by documents of different
	// lengths where longer documents naturally have more words and so higher word counts

	return &product, nil
}

// FitTransform is exactly equivalent to calling Fit() followed by Transform() on the
// same matrix.  This is a convenience where separate training data is not being
// used to fit the model i.e. the model is fitted on the fly to the test data.
// The returned matrix is a sparse matrix type.
func (t *TfidfTransformer) FitTransform(matrix mat.Matrix) (mat.Matrix, error) {
	if t, isTypeConv := matrix.(sparse.TypeConverter); isTypeConv {
		matrix = t.ToCSR()
	}
	return t.Fit(matrix).Transform(matrix)
}

// Save binary serialises the model and writes it into w.  This is useful for persisting
// a trained model to disk so that it may be loaded (using the Load() method)in another
// context (e.g. production) for reproducible results.
func (t TfidfTransformer) Save(w io.Writer) error {
	_, err := t.transform.MarshalBinaryTo(w)

	return err
}

// Load binary deserialises the previously serialised model into the receiver.  This is
// useful for loading a previously trained and saved model from another context
// (e.g. offline training) for use within another context (e.g. production) for
// reproducible results.  Load should only be performed with trusted data.
func (t *TfidfTransformer) Load(r io.Reader) error {
	var model sparse.DIA

	if _, err := model.UnmarshalBinaryFrom(r); err != nil {
		return err
	}
	t.transform = &model

	return nil
}
<|endoftext|>


<commit_before>package drawing

import (
	"image"
	"image/color"
	"image/png"
	"math"
	"net/http"
)

type Circle struct {
	X, Y, R float64
}

var Inside = func(c Circle, x, y int) bool {
	// sqrt((x-a)^2 + (y-b)^2) は二点(x, y), (a, b)間の距離
	// これが(x, y)を中心とする円の半径r以内の長さであれば円の内側

	xx, yy := c.X-float64(x), c.Y-float64(y)
	return math.Sqrt(xx*xx+yy*yy) <= c.R
}

func NewImage() *image.RGBA {
	var w, h int = 280, 240
	m := image.NewRGBA(image.Rect(0, 0, w, h))

	large := Circle{140, 240, 80}
	middle := Circle{140, 180, 50}
	small := Circle{140, 120, 20}

	white := color.RGBA{
		255,
		255,
		255,
		255,
	}
	another := color.RGBA{
		170,
		179,
		0,
		255,
	}
	orange := color.RGBA{
		255,
		102,
		0,
		255,
	}

	for x := 0; x < w; x++ {
		for y := 0; y < h; y++ {
			var c color.RGBA
			if Inside(small, x, y) {
				// ちっちゃい円の中にある座標はオレンジ色(橙の絵)
				c = orange
			} else if Inside(large, x, y) || Inside(middle, x, y) {
				// 大きい円、または中くらいの円の中にある座標は白(お餅の絵)
				c = white
			} else {
				// それ以外は背景とする
				c = another
			}
			m.Set(x, y, c)
		}
	}
	return m
}

func DrawingHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "image/png")
	img := NewImage()
	png.Encode(w, img)
}
<commit_msg>Insideをトップレベルに移動したので、メソッドに定義を変えた。<commit_after>package drawing

import (
	"image"
	"image/color"
	"image/png"
	"math"
	"net/http"
)

type Circle struct {
	X, Y, R float64
}

func (c *Circle) Inside(x, y int) bool {
	// sqrt((x-a)^2 + (y-b)^2) は二点(x, y), (a, b)間の距離
	// これが(x, y)を中心とする円の半径r以内の長さであれば円の内側

	xx, yy := c.X-float64(x), c.Y-float64(y)
	return math.Sqrt(xx*xx+yy*yy) <= c.R
}

func NewImage() *image.RGBA {
	var w, h int = 280, 240
	m := image.NewRGBA(image.Rect(0, 0, w, h))

	large := Circle{140, 240, 80}
	middle := Circle{140, 180, 50}
	small := Circle{140, 120, 20}

	white := color.RGBA{
		255,
		255,
		255,
		255,
	}
	another := color.RGBA{
		170,
		179,
		0,
		255,
	}
	orange := color.RGBA{
		255,
		102,
		0,
		255,
	}

	for x := 0; x < w; x++ {
		for y := 0; y < h; y++ {
			var c color.RGBA
			if small.Inside(x, y) {
				// ちっちゃい円の中にある座標はオレンジ色(橙の絵)
				c = orange
			} else if large.Inside(x, y) || middle.Inside(x, y) {
				// 大きい円、または中くらいの円の中にある座標は白(お餅の絵)
				c = white
			} else {
				// それ以外は背景とする
				c = another
			}
			m.Set(x, y, c)
		}
	}
	return m
}

func DrawingHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "image/png")
	img := NewImage()
	png.Encode(w, img)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"github.com/BurntSushi/xgbutil"
	"github.com/BurntSushi/xgbutil/keybind"
	"github.com/BurntSushi/xgbutil/xevent"
	"io"
	"os"
	"os/exec"
)

type SourceType float64

const (
	Clipboard = iota
	Selection = iota
)

func main() {

	X, _ := xgbutil.NewConn()
	keybind.Initialize(X)

	cb1 := keybind.KeyPressFun(
		func(X *xgbutil.XUtil, e xevent.KeyPressEvent) {
			read(Selection)
		})
	cb1.Connect(X, X.RootWin(), "control-z", true)

	cb2 := keybind.KeyPressFun(
		func(X *xgbutil.XUtil, e xevent.KeyPressEvent) {
			read(Clipboard)
		})
	cb2.Connect(X, X.RootWin(), "control-q", true)

	fmt.Printf("Listening for Crtl-z ...(Read Selected Text)\n")
	fmt.Printf("Listening for Crtl-q ...(Read Clipboard Text)\n")
	xevent.Main(X)

}

var player (exec.Cmd)

func read(source SourceType) {
	_, err := exec.LookPath("swift")
	if err == nil {
		swift_read(source)
	} else {
		festival_read(source)
	}
}

func festival_read(source SourceType) {
	if player.Process != nil {
		player.Process.Kill()
		player.Process.Wait()
	}
	xsel := build_xsel_command(source)
	tts_engine := exec.Command("text2wave", "-o", "/dev/stdout", "/dev/stdin")
	player = *exec.Command("aplay", "/dev/stdin")
	xsel_pipe, _ := xsel.StdoutPipe()
	tts_engine.Stdin = xsel_pipe
	tts_engine_pipe, _ := tts_engine.StdoutPipe()
	player.Stdin = tts_engine_pipe
	xsel.Start()
	tts_engine.Start()
	player.Start()
}

func swift_read(source SourceType) {
	if player.Process != nil {
		player.Process.Kill()
		player.Process.Wait()
	}
	write_sel_to_temp_file(source)
	tts_engine := exec.Command("swift", "-o", "/tmp/light_read.wav", "-f", "/tmp/light_read.txt")
	tts_engine.Run()
	os.Remove("/tmp/light_read.txt")
	player = *exec.Command("aplay", "/tmp/light_read.wav")
	player.Start()
}

func build_xsel_command(source SourceType) exec.Cmd {

	switch {
	case source == Selection:
		return *exec.Command("xsel")
	case source == Clipboard:
		return *exec.Command("xsel", "-b")
	}
	return *exec.Command("xsel")
}

func write_sel_to_temp_file(source SourceType) {
	text, _ := os.Create("/tmp/light_read.txt")
	w := bufio.NewWriter(text)
	buf := make([]byte, 1024)
	xsel := build_xsel_command(source)
	r, _ := xsel.StdoutPipe()
	xsel.Start()
	for {
		n, err := r.Read(buf)
		if err != nil && err != io.EOF {
			panic(err)
		}
		if n == 0 {
			break
		}
		if _, err := w.Write(buf[:n]); err != nil {
			panic(err)
		}
	}
	w.Flush()
	text.Close()
}
<commit_msg>cleanup workers<commit_after>package main

import (
	"bufio"
	"fmt"
	"github.com/BurntSushi/xgbutil"
	"github.com/BurntSushi/xgbutil/keybind"
	"github.com/BurntSushi/xgbutil/xevent"
	"io"
	"os"
	"os/exec"
)

type SourceType float64

const (
	Clipboard = iota
	Selection = iota
)

func main() {

	X, _ := xgbutil.NewConn()
	keybind.Initialize(X)

	cb1 := keybind.KeyPressFun(
		func(X *xgbutil.XUtil, e xevent.KeyPressEvent) {
			read(Selection)
		})
	cb1.Connect(X, X.RootWin(), "control-z", true)

	cb2 := keybind.KeyPressFun(
		func(X *xgbutil.XUtil, e xevent.KeyPressEvent) {
			read(Clipboard)
		})
	cb2.Connect(X, X.RootWin(), "control-q", true)

	fmt.Printf("Listening for Crtl-z ...(Read Selected Text)\n")
	fmt.Printf("Listening for Crtl-q ...(Read Clipboard Text)\n")
	xevent.Main(X)

}

var player (exec.Cmd)
var tts_engine (exec.Cmd)
var xsel (exec.Cmd)

func read(source SourceType) {
	_, err := exec.LookPath("swift")
	if err == nil {
		swift_read(source)
	} else {
		festival_read(source)
	}
}

func kill_all_the_things(){
	if player.Process != nil {
		player.Process.Kill()
		player.Process.Wait()
	}
	if tts_engine.Process != nil {
		tts_engine.Process.Kill()
		tts_engine.Process.Wait()
	}
	if xsel.Process != nil {
		xsel.Process.Kill()
		xsel.Process.Wait()
	}
}

func festival_read(source SourceType) {
  kill_all_the_things()
	xsel = *build_xsel_command(source)
	tts_engine = *exec.Command("text2wave", "-o", "/dev/stdout", "/dev/stdin")
	player = *exec.Command("aplay", "/dev/stdin")
	xsel_pipe, _ := xsel.StdoutPipe()
	tts_engine.Stdin = xsel_pipe
	tts_engine_pipe, _ := tts_engine.StdoutPipe()
	player.Stdin = tts_engine_pipe
	xsel.Start()
	tts_engine.Start()
	player.Start()
}

func swift_read(source SourceType) {
	if player.Process != nil {
		player.Process.Kill()
		player.Process.Wait()
	}
	write_sel_to_temp_file(source)
	tts_engine := exec.Command("swift", "-o", "/tmp/light_read.wav", "-f", "/tmp/light_read.txt")
	tts_engine.Run()
	os.Remove("/tmp/light_read.txt")
	player = *exec.Command("aplay", "/tmp/light_read.wav")
	player.Start()
}

func build_xsel_command(source SourceType) *exec.Cmd {

	switch {
	case source == Selection:
		return exec.Command("xsel")
	case source == Clipboard:
		return exec.Command("xsel", "-b")
	}
	return exec.Command("xsel")
}

func write_sel_to_temp_file(source SourceType) {
	text, _ := os.Create("/tmp/light_read.txt")
	w := bufio.NewWriter(text)
	buf := make([]byte, 1024)
	xsel := build_xsel_command(source)
	r, _ := xsel.StdoutPipe()
	xsel.Start()
	for {
		n, err := r.Read(buf)
		if err != nil && err != io.EOF {
			panic(err)
		}
		if n == 0 {
			break
		}
		if _, err := w.Write(buf[:n]); err != nil {
			panic(err)
		}
	}
	w.Flush()
	text.Close()
}
<|endoftext|>


<commit_before>package tenus

import (
	"fmt"
	"net"
	"os"
	"syscall"

	"github.com/opencontainers/runc/libcontainer/netlink"
	"github.com/opencontainers/runc/libcontainer/system"
)

// LinkOptions allows you to specify network link options.
type LinkOptions struct {
	// MAC address
	MacAddr string
	// Maximum Transmission Unit
	MTU int
	// Link network flags i.e. FlagUp, FlagLoopback, FlagMulticast
	Flags net.Flags
	// Network namespace in which the network link should be created
	Ns int
}

// Linker is a generic Linux network link
type Linker interface {
	// NetInterface returns the link's logical network interface
	NetInterface() *net.Interface
	// DeleteLink deletes the link from Linux host
	DeleteLink() error
	// SetLinkMTU sets the link's MTU.
	SetLinkMTU(int) error
	// SetLinkMacAddress sets the link's MAC address.
	SetLinkMacAddress(string) error
	// SetLinkUp brings the link up
	SetLinkUp() error
	// SetLinkDown brings the link down
	SetLinkDown() error
	// SetLinkIp configures the link's IP address
	SetLinkIp(net.IP, *net.IPNet) error
	// SetLinkDefaultGw configures the link's default gateway
	SetLinkDefaultGw(*net.IP) error
	// SetLinkNetNsPid moves the link to network namespace specified by PID
	SetLinkNetNsPid(int) error
	// SetLinkNetInNs configures network settings of the link in network namespace
	SetLinkNetInNs(int, net.IP, *net.IPNet, *net.IP) error
}

// Link has a logical network interface
type Link struct {
	ifc *net.Interface
}

// NewLink creates new network link on Linux host.
//
// It is equivalent of running: ip link add name ${ifcName} type dummy
// NewLink returns Linker which is initialized to a pointer of type Link if the
// link was created successfully on the Linux host.
// It returns error if the network link could not be created on Linux host.
func NewLink(ifcName string) (Linker, error) {
	if ok, err := NetInterfaceNameValid(ifcName); !ok {
		return nil, err
	}

	if _, err := net.InterfaceByName(ifcName); err == nil {
		return nil, fmt.Errorf("Interface name %s already assigned on the host", ifcName)
	}

	if err := netlink.NetworkLinkAdd(ifcName, "dummy"); err != nil {
		return nil, fmt.Errorf("Could not create new link %s: %s", ifcName, err)
	}

	newIfc, err := net.InterfaceByName(ifcName)
	if err != nil {
		return nil, fmt.Errorf("Could not find the new interface: %s", err)
	}

	return &Link{
		ifc: newIfc,
	}, nil
}

// NewLinkWithOptions creates new network link on Linux host and sets some of its network
// parameters passed in as LinkOptions
//
// Calling NewLinkWithOptions is equivalent of running following commands one after another if
// particular option is passed in as a parameter:
// 		ip link add name ${ifcName} type dummy
// 		ip link set dev ${ifcName} address ${MAC address}
//		ip link set dev ${ifcName} mtu ${MTU value}
//		ip link set dev ${ifcName} up
// NewLinkWithOptions returns Linker which is initialized to a pointer of type Link if the network
// link with given LinkOptions was created successfully on the Linux host.
// It attempts to delete the link if any of the LinkOptions are incorrect or if setting the options
// failed and returns error.
func NewLinkWithOptions(ifcName string, opts LinkOptions) (Linker, error) {
	if ok, err := NetInterfaceNameValid(ifcName); !ok {
		return nil, err
	}

	if _, err := net.InterfaceByName(ifcName); err == nil {
		return nil, fmt.Errorf("Interface name %s already assigned on the host", ifcName)
	}

	if err := netlink.NetworkLinkAdd(ifcName, "dummy"); err != nil {
		return nil, fmt.Errorf("Could not create new link %s: %s", ifcName, err)
	}

	newIfc, err := net.InterfaceByName(ifcName)
	if err != nil {
		return nil, fmt.Errorf("Could not find the new interface: %s", err)
	}

	if (opts != LinkOptions{}) {
		errOpts := setLinkOptions(newIfc, opts)
		if errOpts != nil {
			if errDel := DeleteLink(newIfc.Name); err != nil {
				return nil, fmt.Errorf("Incorrect options specified: %s. Attempt to delete the link failed: %s",
					errOpts, errDel)
			}
			return nil, fmt.Errorf("Could not set link options: %s", errOpts)
		}
	}

	return &Link{
		ifc: newIfc,
	}, nil
}

// DeleteLink deletes netowrk link from Linux Host
// It is equivalent of running: ip link delete dev ${name}
func DeleteLink(name string) error {
	return netlink.NetworkLinkDel(name)
}

// NetInterface returns link's logical network interface.
func (l *Link) NetInterface() *net.Interface {
	return l.ifc
}

// DeleteLink deletes link interface on Linux host.
// It is equivalent of running: ip link delete dev ${interface name}
func (l *Link) DeleteLink() error {
	return netlink.NetworkLinkDel(l.NetInterface().Name)
}

// SetLinkMTU sets link's MTU.
// It is equivalent of running: ip link set dev ${interface name} mtu ${MTU value}
func (l *Link) SetLinkMTU(mtu int) error {
	return netlink.NetworkSetMTU(l.NetInterface(), mtu)
}

// SetLinkMacAddress sets link's MAC address.
// It is equivalent of running: ip link set dev ${interface name} address ${address}
func (l *Link) SetLinkMacAddress(macaddr string) error {
	return netlink.NetworkSetMacAddress(l.NetInterface(), macaddr)
}

// SetLinkUp brings the link up.
// It is equivalent of running: ip link set dev ${interface name} up
func (l *Link) SetLinkUp() error {
	return netlink.NetworkLinkUp(l.NetInterface())
}

// SetLinkDown brings the link down.
// It is equivalent of running: ip link set dev ${interface name} down
func (l *Link) SetLinkDown() error {
	return netlink.NetworkLinkDown(l.NetInterface())
}

// SetLinkIp configures the link's IP address.
// It is equivalent of running: ip address add ${address}/${mask} dev ${interface name}
func (l *Link) SetLinkIp(ip net.IP, network *net.IPNet) error {
	return netlink.NetworkLinkAddIp(l.NetInterface(), ip, network)
}

// SetLinkDefaultGw configures the link's default Gateway.
// It is equivalent of running: ip route add default via ${ip address}
func (l *Link) SetLinkDefaultGw(gw *net.IP) error {
	return netlink.AddDefaultGw(gw.String(), l.NetInterface().Name)
}

// SetLinkNetNsPid moves the link to Network namespace specified by PID.
func (l *Link) SetLinkNetNsPid(nspid int) error {
	return netlink.NetworkSetNsPid(l.NetInterface(), nspid)
}

// SetLinkNetInNs configures network settings of the link in network namespace specified by PID.
func (l *Link) SetLinkNetInNs(nspid int, ip net.IP, network *net.IPNet, gw *net.IP) error {
	origNs, _ := NetNsHandle(os.Getpid())
	defer syscall.Close(int(origNs))
	defer system.Setns(origNs, syscall.CLONE_NEWNET)

	if err := SetNetNsToPid(nspid); err != nil {
		return fmt.Errorf("Setting network namespace failed: %s", err)
	}

	if err := netlink.NetworkLinkAddIp(l.NetInterface(), ip, network); err != nil {
		return fmt.Errorf("Unable to set IP: %s in pid: %d network namespace", ip.String(), nspid)
	}

	if err := netlink.NetworkLinkUp(l.ifc); err != nil {
		return fmt.Errorf("Unable to bring %s interface UP: %s", l.ifc.Name, nspid)
	}

	if gw != nil {
		if err := netlink.AddDefaultGw(gw.String(), l.NetInterface().Name); err != nil {
			return fmt.Errorf("Unable to set Default gateway: %s in pid: %d network namespace", gw.String(), nspid)
		}
	}

	return nil
}

// SetLinkNsFd sets the link's Linux namespace to the one specified by filesystem path.
func (l *Link) SetLinkNsFd(nspath string) error {
	fd, err := syscall.Open(nspath, syscall.O_RDONLY, 0)
	if err != nil {
		return fmt.Errorf("Could not attach to Network namespace: %s", err)
	}

	return netlink.NetworkSetNsFd(l.NetInterface(), fd)
}

// SetLinkNsToDocker sets the link's Linux namespace to a running Docker one specified by Docker name.
func (l *Link) SetLinkNsToDocker(name string, dockerHost string) error {
	pid, err := DockerPidByName(name, dockerHost)
	if err != nil {
		return fmt.Errorf("Failed to find docker %s :  %s", name, err)
	}

	return l.SetLinkNetNsPid(pid)
}

// setLinkOptions validates and sets link's various options passed in as LinkOptions.
func setLinkOptions(ifc *net.Interface, opts LinkOptions) error {
	macaddr, mtu, flags, ns := opts.MacAddr, opts.MTU, opts.Flags, opts.Ns

	// if MTU is passed in LinkOptions
	if mtu != 0 {
		if err := validMtu(mtu); err != nil {
			return err
		}

		if err := netlink.NetworkSetMTU(ifc, mtu); err != nil {
			return fmt.Errorf("Unable to set MTU: %s", err)
		}
	}

	// if MacAddress is passed in LinkOptions
	if macaddr != "" {
		if err := validMacAddress(macaddr); err != nil {
			return err
		}

		if err := netlink.NetworkSetMacAddress(ifc, macaddr); err != nil {
			return fmt.Errorf("Unable to set MAC Address: %s", err)
		}
	}

	// if ns is passed in LinkOptions
	if ns != 0 {
		if err := validNs(ns); err != nil {
			return err
		}

		if err := netlink.NetworkSetNsPid(ifc, ns); err != nil {
			return fmt.Errorf("Unable to set Network namespace: %s", err)
		}
	}

	// if flags is passed in LinkOptions
	if flags != 0 {
		if err := validFlags(flags); err != nil {
			return err
		}

		if ns != 0 && (ns != 1 || ns != os.Getpid()) {
			if (flags & syscall.IFF_UP) == syscall.IFF_UP {
				origNs, _ := NetNsHandle(os.Getpid())
				defer syscall.Close(int(origNs))
				defer system.Setns(origNs, syscall.CLONE_NEWNET)

				if err := SetNetNsToPid(ns); err != nil {
					return fmt.Errorf("Switching to %d network namespace failed: %s", ns, err)
				}

				if err := netlink.NetworkLinkUp(ifc); err != nil {
					return fmt.Errorf("Unable to bring %s interface UP: %s", ifc.Name, ns)
				}
			}
		} else {
			if err := netlink.NetworkLinkUp(ifc); err != nil {
				return fmt.Errorf("Could not bring up network link %s: %s", ifc.Name, err)
			}
		}
	}

	return nil
}
<commit_msg>Adding ready status when 1st ip is set before continue<commit_after>package tenus

import (
	"fmt"
	"log"
	"net"
	"os"
	"syscall"
	"time"

	"github.com/opencontainers/runc/libcontainer/netlink"
	"github.com/opencontainers/runc/libcontainer/system"
)

// LinkOptions allows you to specify network link options.
type LinkOptions struct {
	// MAC address
	MacAddr string
	// Maximum Transmission Unit
	MTU int
	// Link network flags i.e. FlagUp, FlagLoopback, FlagMulticast
	Flags net.Flags
	// Network namespace in which the network link should be created
	Ns int
}

// Linker is a generic Linux network link
type Linker interface {
	// NetInterface returns the link's logical network interface
	NetInterface() *net.Interface
	// DeleteLink deletes the link from Linux host
	DeleteLink() error
	// SetLinkMTU sets the link's MTU.
	SetLinkMTU(int) error
	// SetLinkMacAddress sets the link's MAC address.
	SetLinkMacAddress(string) error
	// SetLinkUp brings the link up
	SetLinkUp() error
	// SetLinkDown brings the link down
	SetLinkDown() error
	// SetLinkIp configures the link's IP address
	SetLinkIp(net.IP, *net.IPNet) error
	// SetLinkDefaultGw configures the link's default gateway
	SetLinkDefaultGw(*net.IP) error
	// SetLinkNetNsPid moves the link to network namespace specified by PID
	SetLinkNetNsPid(int) error
	// SetLinkNetInNs configures network settings of the link in network namespace
	SetLinkNetInNs(int, net.IP, *net.IPNet, *net.IP) error
}

// Link has a logical network interface
type Link struct {
	ifc *net.Interface
}

// NewLink creates new network link on Linux host.
//
// It is equivalent of running: ip link add name ${ifcName} type dummy
// NewLink returns Linker which is initialized to a pointer of type Link if the
// link was created successfully on the Linux host.
// It returns error if the network link could not be created on Linux host.
func NewLink(ifcName string) (Linker, error) {
	if ok, err := NetInterfaceNameValid(ifcName); !ok {
		return nil, err
	}

	if _, err := net.InterfaceByName(ifcName); err == nil {
		return nil, fmt.Errorf("Interface name %s already assigned on the host", ifcName)
	}

	if err := netlink.NetworkLinkAdd(ifcName, "dummy"); err != nil {
		return nil, fmt.Errorf("Could not create new link %s: %s", ifcName, err)
	}

	newIfc, err := net.InterfaceByName(ifcName)
	if err != nil {
		return nil, fmt.Errorf("Could not find the new interface: %s", err)
	}

	return &Link{
		ifc: newIfc,
	}, nil
}

// NewLinkWithOptions creates new network link on Linux host and sets some of its network
// parameters passed in as LinkOptions
//
// Calling NewLinkWithOptions is equivalent of running following commands one after another if
// particular option is passed in as a parameter:
// 		ip link add name ${ifcName} type dummy
// 		ip link set dev ${ifcName} address ${MAC address}
//		ip link set dev ${ifcName} mtu ${MTU value}
//		ip link set dev ${ifcName} up
// NewLinkWithOptions returns Linker which is initialized to a pointer of type Link if the network
// link with given LinkOptions was created successfully on the Linux host.
// It attempts to delete the link if any of the LinkOptions are incorrect or if setting the options
// failed and returns error.
func NewLinkWithOptions(ifcName string, opts LinkOptions) (Linker, error) {
	if ok, err := NetInterfaceNameValid(ifcName); !ok {
		return nil, err
	}

	if _, err := net.InterfaceByName(ifcName); err == nil {
		return nil, fmt.Errorf("Interface name %s already assigned on the host", ifcName)
	}

	if err := netlink.NetworkLinkAdd(ifcName, "dummy"); err != nil {
		return nil, fmt.Errorf("Could not create new link %s: %s", ifcName, err)
	}

	newIfc, err := net.InterfaceByName(ifcName)
	if err != nil {
		return nil, fmt.Errorf("Could not find the new interface: %s", err)
	}

	if (opts != LinkOptions{}) {
		errOpts := setLinkOptions(newIfc, opts)
		if errOpts != nil {
			if errDel := DeleteLink(newIfc.Name); err != nil {
				return nil, fmt.Errorf("Incorrect options specified: %s. Attempt to delete the link failed: %s",
					errOpts, errDel)
			}
			return nil, fmt.Errorf("Could not set link options: %s", errOpts)
		}
	}

	return &Link{
		ifc: newIfc,
	}, nil
}

// DeleteLink deletes netowrk link from Linux Host
// It is equivalent of running: ip link delete dev ${name}
func DeleteLink(name string) error {
	return netlink.NetworkLinkDel(name)
}

// NetInterface returns link's logical network interface.
func (l *Link) NetInterface() *net.Interface {
	return l.ifc
}

// DeleteLink deletes link interface on Linux host.
// It is equivalent of running: ip link delete dev ${interface name}
func (l *Link) DeleteLink() error {
	return netlink.NetworkLinkDel(l.NetInterface().Name)
}

// SetLinkMTU sets link's MTU.
// It is equivalent of running: ip link set dev ${interface name} mtu ${MTU value}
func (l *Link) SetLinkMTU(mtu int) error {
	return netlink.NetworkSetMTU(l.NetInterface(), mtu)
}

// SetLinkMacAddress sets link's MAC address.
// It is equivalent of running: ip link set dev ${interface name} address ${address}
func (l *Link) SetLinkMacAddress(macaddr string) error {
	return netlink.NetworkSetMacAddress(l.NetInterface(), macaddr)
}

// SetLinkUp brings the link up.
// It is equivalent of running: ip link set dev ${interface name} up
func (l *Link) SetLinkUp() error {
	return netlink.NetworkLinkUp(l.NetInterface())
}

// SetLinkDown brings the link down.
// It is equivalent of running: ip link set dev ${interface name} down
func (l *Link) SetLinkDown() error {
	return netlink.NetworkLinkDown(l.NetInterface())
}

// SetLinkIp configures the link's IP address.
// It is equivalent of running: ip address add ${address}/${mask} dev ${interface name}
func (l *Link) SetLinkIp(ip net.IP, network *net.IPNet) error {
	errToReturn := netlink.NetworkLinkAddIp(l.NetInterface(), ip, network)
	// Nécéssaire car il semble y avoir un «Race condition»
	inter, err := net.InterfaceByName(l.NetInterface().Name)
	if err != nil {
		log.Fatal(err)
	}
	addrs, _ := inter.Addrs()
	i := 0
	for len(addrs) == 0 && i <= 10 {
		addrs, _ = inter.Addrs()
		fmt.Println("Waiting this interface : ", l.NetInterface().Name)
		time.Sleep(time.Millisecond * 100)
		i++
	}

	return errToReturn
}

// SetLinkDefaultGw configures the link's default Gateway.
// It is equivalent of running: ip route add default via ${ip address}
func (l *Link) SetLinkDefaultGw(gw *net.IP) error {
	return netlink.AddDefaultGw(gw.String(), l.NetInterface().Name)
}

// SetLinkNetNsPid moves the link to Network namespace specified by PID.
func (l *Link) SetLinkNetNsPid(nspid int) error {
	return netlink.NetworkSetNsPid(l.NetInterface(), nspid)
}

// SetLinkNetInNs configures network settings of the link in network namespace specified by PID.
func (l *Link) SetLinkNetInNs(nspid int, ip net.IP, network *net.IPNet, gw *net.IP) error {
	origNs, _ := NetNsHandle(os.Getpid())
	defer syscall.Close(int(origNs))
	defer system.Setns(origNs, syscall.CLONE_NEWNET)

	if err := SetNetNsToPid(nspid); err != nil {
		return fmt.Errorf("Setting network namespace failed: %s", err)
	}

	if err := netlink.NetworkLinkAddIp(l.NetInterface(), ip, network); err != nil {
		return fmt.Errorf("Unable to set IP: %s in pid: %d network namespace", ip.String(), nspid)
	}

	if err := netlink.NetworkLinkUp(l.ifc); err != nil {
		return fmt.Errorf("Unable to bring %s interface UP: %s", l.ifc.Name, nspid)
	}

	if gw != nil {
		if err := netlink.AddDefaultGw(gw.String(), l.NetInterface().Name); err != nil {
			return fmt.Errorf("Unable to set Default gateway: %s in pid: %d network namespace", gw.String(), nspid)
		}
	}

	return nil
}

// SetLinkNsFd sets the link's Linux namespace to the one specified by filesystem path.
func (l *Link) SetLinkNsFd(nspath string) error {
	fd, err := syscall.Open(nspath, syscall.O_RDONLY, 0)
	if err != nil {
		return fmt.Errorf("Could not attach to Network namespace: %s", err)
	}

	return netlink.NetworkSetNsFd(l.NetInterface(), fd)
}

// SetLinkNsToDocker sets the link's Linux namespace to a running Docker one specified by Docker name.
func (l *Link) SetLinkNsToDocker(name string, dockerHost string) error {
	pid, err := DockerPidByName(name, dockerHost)
	if err != nil {
		return fmt.Errorf("Failed to find docker %s :  %s", name, err)
	}

	return l.SetLinkNetNsPid(pid)
}

// setLinkOptions validates and sets link's various options passed in as LinkOptions.
func setLinkOptions(ifc *net.Interface, opts LinkOptions) error {
	macaddr, mtu, flags, ns := opts.MacAddr, opts.MTU, opts.Flags, opts.Ns

	// if MTU is passed in LinkOptions
	if mtu != 0 {
		if err := validMtu(mtu); err != nil {
			return err
		}

		if err := netlink.NetworkSetMTU(ifc, mtu); err != nil {
			return fmt.Errorf("Unable to set MTU: %s", err)
		}
	}

	// if MacAddress is passed in LinkOptions
	if macaddr != "" {
		if err := validMacAddress(macaddr); err != nil {
			return err
		}

		if err := netlink.NetworkSetMacAddress(ifc, macaddr); err != nil {
			return fmt.Errorf("Unable to set MAC Address: %s", err)
		}
	}

	// if ns is passed in LinkOptions
	if ns != 0 {
		if err := validNs(ns); err != nil {
			return err
		}

		if err := netlink.NetworkSetNsPid(ifc, ns); err != nil {
			return fmt.Errorf("Unable to set Network namespace: %s", err)
		}
	}

	// if flags is passed in LinkOptions
	if flags != 0 {
		if err := validFlags(flags); err != nil {
			return err
		}

		if ns != 0 && (ns != 1 || ns != os.Getpid()) {
			if (flags & syscall.IFF_UP) == syscall.IFF_UP {
				origNs, _ := NetNsHandle(os.Getpid())
				defer syscall.Close(int(origNs))
				defer system.Setns(origNs, syscall.CLONE_NEWNET)

				if err := SetNetNsToPid(ns); err != nil {
					return fmt.Errorf("Switching to %d network namespace failed: %s", ns, err)
				}

				if err := netlink.NetworkLinkUp(ifc); err != nil {
					return fmt.Errorf("Unable to bring %s interface UP: %s", ifc.Name, ns)
				}
			}
		} else {
			if err := netlink.NetworkLinkUp(ifc); err != nil {
				return fmt.Errorf("Could not bring up network link %s: %s", ifc.Name, err)
			}
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package vegeta

import (
	"errors"
	"testing"
	"time"
)

func TestNewMetrics(t *testing.T) {
	m := NewMetrics([]Result{
		Result{500, time.Now(), 100 * time.Millisecond, 10, 30, errors.New("Internal server error")},
		Result{200, time.Now(), 20 * time.Millisecond, 20, 20, nil},
		Result{200, time.Now(), 30 * time.Millisecond, 30, 10, nil},
	})

	for field, values := range map[string][]float64{
		"MeanBytesIn":  []float64{m.MeanBytesIn, 20.0},
		"MeanBytesOut": []float64{m.MeanBytesOut, 20.0},
		"MeanSuccess":  []float64{m.MeanSuccess, 0.6666666666666666},
	} {
		if values[0] != values[1] {
			t.Errorf("%s: want: %f, got: %f", field, values[1], values[0])
		}
	}

	for field, values := range map[string][]time.Duration{
		"TotalTiming": []time.Duration{m.TotalTiming, 150 * time.Millisecond},
		"MeanTiming":  []time.Duration{m.MeanTiming, 50 * time.Millisecond},
	} {
		if values[0] != values[1] {
			t.Errorf("%s: want: %s, got: %s", field, values[1], values[0])
		}
	}

	for field, values := range map[string][]uint64{
		"TotalSuccess":  []uint64{m.TotalSuccess, 2},
		"TotalBytesOut": []uint64{m.TotalBytesOut, 60},
		"TotalRequests": []uint64{m.TotalRequests, 3},
		"TotalBytesIn":  []uint64{m.TotalBytesIn, 60},
	} {
		if values[0] != values[1] {
			t.Errorf("%s: want: %d, got: %d", field, values[1], values[0])
		}
	}

	if len(m.StatusCodes) != 2 || m.StatusCodes[200] != 2 || m.StatusCodes[500] != 1 {
		t.Errorf("StatusCodes: want: %v, got: %v", map[int]int{200: 2, 500: 1}, m.StatusCodes)
	}

	err := "Internal server error"
	if len(m.Errors) != 1 || m.Errors[0] != err {
		t.Errorf("Errors: want: %v, got: %v", []string{err}, m.Errors)
	}
}
<commit_msg>Fix metrics.StatusCode test<commit_after>package vegeta

import (
	"errors"
	"testing"
	"time"
)

func TestNewMetrics(t *testing.T) {
	m := NewMetrics([]Result{
		Result{500, time.Now(), 100 * time.Millisecond, 10, 30, errors.New("Internal server error")},
		Result{200, time.Now(), 20 * time.Millisecond, 20, 20, nil},
		Result{200, time.Now(), 30 * time.Millisecond, 30, 10, nil},
	})

	for field, values := range map[string][]float64{
		"MeanBytesIn":  []float64{m.MeanBytesIn, 20.0},
		"MeanBytesOut": []float64{m.MeanBytesOut, 20.0},
		"MeanSuccess":  []float64{m.MeanSuccess, 0.6666666666666666},
	} {
		if values[0] != values[1] {
			t.Errorf("%s: want: %f, got: %f", field, values[1], values[0])
		}
	}

	for field, values := range map[string][]time.Duration{
		"TotalTiming": []time.Duration{m.TotalTiming, 150 * time.Millisecond},
		"MeanTiming":  []time.Duration{m.MeanTiming, 50 * time.Millisecond},
	} {
		if values[0] != values[1] {
			t.Errorf("%s: want: %s, got: %s", field, values[1], values[0])
		}
	}

	for field, values := range map[string][]uint64{
		"TotalSuccess":  []uint64{m.TotalSuccess, 2},
		"TotalBytesOut": []uint64{m.TotalBytesOut, 60},
		"TotalRequests": []uint64{m.TotalRequests, 3},
		"TotalBytesIn":  []uint64{m.TotalBytesIn, 60},
	} {
		if values[0] != values[1] {
			t.Errorf("%s: want: %d, got: %d", field, values[1], values[0])
		}
	}

	if len(m.StatusCodes) != 2 || m.StatusCodes["200"] != 2 || m.StatusCodes["500"] != 1 {
		t.Errorf("StatusCodes: want: %v, got: %v", map[int]int{200: 2, 500: 1}, m.StatusCodes)
	}

	err := "Internal server error"
	if len(m.Errors) != 1 || m.Errors[0] != err {
		t.Errorf("Errors: want: %v, got: %v", []string{err}, m.Errors)
	}
}
<|endoftext|>