<commit_before>// Package timeout is for handling timeout invocation of external command
package timeout

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os"
	"os/exec"
	"runtime"

	"syscall"
	"time"
)

// Timeout is main struct of timeout package
type Timeout struct {
	PreserveStatus bool
	Duration       time.Duration
	KillAfter      time.Duration
	Signal         os.Signal
	Cmd            *exec.Cmd
}

var defaultSignal os.Signal

func init() {
	switch runtime.GOOS {
	case "windows":
		defaultSignal = os.Interrupt
	default:
		defaultSignal = syscall.SIGTERM
	}
}

// exit statuses are same with GNU timeout
const (
	exitNormal            = 0
	exitTimedOut          = 124
	exitUnknownErr        = 125
	exitCommandNotInvoked = 126
	exitCommandNotFound   = 127
	exitKilled            = 137
)

// Error is error of timeout
type Error struct {
	ExitCode int
	Err      error
}

func (err *Error) Error() string {
	return fmt.Sprintf("exit code: %d, %s", err.ExitCode, err.Err.Error())
}

// ExitStatus stores exit informations of the command
type ExitStatus struct {
	Code int
	Type exitType
}

func (ex ExitStatus) String() string {
	return fmt.Sprintf("exitCode: %d, type: %s", ex.Code, ex.Type)
}

func (ex ExitStatus) IsTimedOut() bool {
	return ex.Type == ExitTypeTimedOut
}

func (ex ExitStatus) IsKilled() bool {
	return ex.Type == ExitTypeKilled
}

type exitType int

// exit types
const (
	ExitTypeNormal exitType = iota + 1
	ExitTypeTimedOut
	ExitTypeKilled
)

func (eTyp exitType) String() string {
	switch eTyp {
	case ExitTypeNormal:
		return "normal"
	case ExitTypeTimedOut:
		return "timeout"
	case ExitTypeKilled:
		return "killed"
	default:
		return "unknown"
	}
}

func (tio *Timeout) signal() os.Signal {
	if tio.Signal == nil {
		return defaultSignal
	}
	return tio.Signal
}

// Run is synchronous interface of exucuting command and returning informations
func (tio *Timeout) Run() (ExitStatus, string, string, error) {
	cmd := tio.Cmd
	var outBuffer, errBuffer bytes.Buffer
	cmd.Stdout = &outBuffer
	cmd.Stderr = &errBuffer

	ch, err := tio.RunCommand()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return ExitStatus{}, string(outBuffer.Bytes()), string(errBuffer.Bytes()), err
	}
	exitSt := <-ch
	return exitSt, string(outBuffer.Bytes()), string(errBuffer.Bytes()), nil
}

// RunSimple execute command and only returns integer as exit code. It is mainly for go-timeout command
func (tio *Timeout) RunSimple() int {
	cmd := tio.Cmd

	stdoutPipe, err := cmd.StdoutPipe()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return exitUnknownErr
	}
	stderrPipe, err := cmd.StderrPipe()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return exitUnknownErr
	}

	ch, err := tio.RunCommand()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return getExitCodeFromErr(err)
	}
	defer func() {
		stdoutPipe.Close()
		stderrPipe.Close()
	}()

	go readAndOut(stdoutPipe, os.Stdout)
	go readAndOut(stderrPipe, os.Stderr)

	exitSt := <-ch
	return exitSt.Code
}

func getExitCodeFromErr(err error) int {
	if err != nil {
		if tmerr, ok := err.(*Error); ok {
			return tmerr.ExitCode
		}
		return -1
	}
	return exitNormal
}

// RunCommand is executing the command and handling timeout. This is primitive interface of Timeout
func (tio *Timeout) RunCommand() (chan ExitStatus, error) {
	cmd := tio.Cmd

	if err := cmd.Start(); err != nil {
		switch {
		case os.IsNotExist(err):
			return nil, &Error{
				ExitCode: exitCommandNotFound,
				Err:      err,
			}
		case os.IsPermission(err):
			return nil, &Error{
				ExitCode: exitCommandNotInvoked,
				Err:      err,
			}
		default:
			return nil, &Error{
				ExitCode: exitUnknownErr,
				Err:      err,
			}
		}
	}

	exitChan := make(chan ExitStatus)
	go func() {
		exitChan <- tio.handleTimeout()
	}()

	return exitChan, nil
}

func (tio *Timeout) handleTimeout() (ex ExitStatus) {
	cmd := tio.Cmd
	exitChan := getExitChan(cmd)
	select {
	case exitCode := <-exitChan:
		ex.Code = exitCode
		ex.Type = ExitTypeNormal
		return ex
	case <-time.After(tio.Duration):
		cmd.Process.Signal(tio.signal()) // XXX error handling
		ex.Code = exitTimedOut
		ex.Type = ExitTypeTimedOut
	}

	tmpExit := exitNormal
	if tio.KillAfter > 0 {
		select {
		case tmpExit = <-exitChan:
		case <-time.After(tio.KillAfter):
			cmd.Process.Kill()
			ex.Code = exitKilled
			ex.Type = ExitTypeKilled
		}
	} else {
		tmpExit = <-exitChan
	}
	if tio.PreserveStatus && !ex.IsKilled() {
		ex.Code = tmpExit
	}

	return ex
}

func getExitChan(cmd *exec.Cmd) chan int {
	ch := make(chan int)
	go func() {
		err := cmd.Wait()
		ch <- resolveCode(err)
	}()
	return ch
}

func resolveCode(err error) int {
	if err != nil {
		if exiterr, ok := err.(*exec.ExitError); ok {
			if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
				return status.ExitStatus()
			}
		}
		// The exit codes in some platforms aren't integer. e.g. plan9.
		return -1
	}
	return exitNormal
}

func readAndOut(r io.Reader, f *os.File) {
	s := bufio.NewScanner(r)
	for s.Scan() {
		fmt.Fprintln(f, s.Text())
	}
}
<commit_msg>remove readAndOut(). use io.Copy<commit_after>// Package timeout is for handling timeout invocation of external command
package timeout

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"os/exec"
	"runtime"

	"syscall"
	"time"
)

// Timeout is main struct of timeout package
type Timeout struct {
	PreserveStatus bool
	Duration       time.Duration
	KillAfter      time.Duration
	Signal         os.Signal
	Cmd            *exec.Cmd
}

var defaultSignal os.Signal

func init() {
	switch runtime.GOOS {
	case "windows":
		defaultSignal = os.Interrupt
	default:
		defaultSignal = syscall.SIGTERM
	}
}

// exit statuses are same with GNU timeout
const (
	exitNormal            = 0
	exitTimedOut          = 124
	exitUnknownErr        = 125
	exitCommandNotInvoked = 126
	exitCommandNotFound   = 127
	exitKilled            = 137
)

// Error is error of timeout
type Error struct {
	ExitCode int
	Err      error
}

func (err *Error) Error() string {
	return fmt.Sprintf("exit code: %d, %s", err.ExitCode, err.Err.Error())
}

// ExitStatus stores exit informations of the command
type ExitStatus struct {
	Code int
	Type exitType
}

func (ex ExitStatus) String() string {
	return fmt.Sprintf("exitCode: %d, type: %s", ex.Code, ex.Type)
}

func (ex ExitStatus) IsTimedOut() bool {
	return ex.Type == ExitTypeTimedOut
}

func (ex ExitStatus) IsKilled() bool {
	return ex.Type == ExitTypeKilled
}

type exitType int

// exit types
const (
	ExitTypeNormal exitType = iota + 1
	ExitTypeTimedOut
	ExitTypeKilled
)

func (eTyp exitType) String() string {
	switch eTyp {
	case ExitTypeNormal:
		return "normal"
	case ExitTypeTimedOut:
		return "timeout"
	case ExitTypeKilled:
		return "killed"
	default:
		return "unknown"
	}
}

func (tio *Timeout) signal() os.Signal {
	if tio.Signal == nil {
		return defaultSignal
	}
	return tio.Signal
}

// Run is synchronous interface of exucuting command and returning informations
func (tio *Timeout) Run() (ExitStatus, string, string, error) {
	cmd := tio.Cmd
	var outBuffer, errBuffer bytes.Buffer
	cmd.Stdout = &outBuffer
	cmd.Stderr = &errBuffer

	ch, err := tio.RunCommand()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return ExitStatus{}, string(outBuffer.Bytes()), string(errBuffer.Bytes()), err
	}
	exitSt := <-ch
	return exitSt, string(outBuffer.Bytes()), string(errBuffer.Bytes()), nil
}

// RunSimple execute command and only returns integer as exit code. It is mainly for go-timeout command
func (tio *Timeout) RunSimple() int {
	cmd := tio.Cmd

	stdoutPipe, err := cmd.StdoutPipe()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return exitUnknownErr
	}
	stderrPipe, err := cmd.StderrPipe()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return exitUnknownErr
	}

	ch, err := tio.RunCommand()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return getExitCodeFromErr(err)
	}

	go func() {
		defer stdoutPipe.Close()
		io.Copy(os.Stdout, stdoutPipe)
	}()

	go func() {
		defer stderrPipe.Close()
		io.Copy(os.Stderr, stderrPipe)
	}()

	exitSt := <-ch
	return exitSt.Code
}

func getExitCodeFromErr(err error) int {
	if err != nil {
		if tmerr, ok := err.(*Error); ok {
			return tmerr.ExitCode
		}
		return -1
	}
	return exitNormal
}

// RunCommand is executing the command and handling timeout. This is primitive interface of Timeout
func (tio *Timeout) RunCommand() (chan ExitStatus, error) {
	cmd := tio.Cmd

	if err := cmd.Start(); err != nil {
		switch {
		case os.IsNotExist(err):
			return nil, &Error{
				ExitCode: exitCommandNotFound,
				Err:      err,
			}
		case os.IsPermission(err):
			return nil, &Error{
				ExitCode: exitCommandNotInvoked,
				Err:      err,
			}
		default:
			return nil, &Error{
				ExitCode: exitUnknownErr,
				Err:      err,
			}
		}
	}

	exitChan := make(chan ExitStatus)
	go func() {
		exitChan <- tio.handleTimeout()
	}()

	return exitChan, nil
}

func (tio *Timeout) handleTimeout() (ex ExitStatus) {
	cmd := tio.Cmd
	exitChan := getExitChan(cmd)
	select {
	case exitCode := <-exitChan:
		ex.Code = exitCode
		ex.Type = ExitTypeNormal
		return ex
	case <-time.After(tio.Duration):
		cmd.Process.Signal(tio.signal()) // XXX error handling
		ex.Code = exitTimedOut
		ex.Type = ExitTypeTimedOut
	}

	tmpExit := exitNormal
	if tio.KillAfter > 0 {
		select {
		case tmpExit = <-exitChan:
		case <-time.After(tio.KillAfter):
			cmd.Process.Kill()
			ex.Code = exitKilled
			ex.Type = ExitTypeKilled
		}
	} else {
		tmpExit = <-exitChan
	}
	if tio.PreserveStatus && !ex.IsKilled() {
		ex.Code = tmpExit
	}

	return ex
}

func getExitChan(cmd *exec.Cmd) chan int {
	ch := make(chan int)
	go func() {
		err := cmd.Wait()
		ch <- resolveCode(err)
	}()
	return ch
}

func resolveCode(err error) int {
	if err != nil {
		if exiterr, ok := err.(*exec.ExitError); ok {
			if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
				return status.ExitStatus()
			}
		}
		// The exit codes in some platforms aren't integer. e.g. plan9.
		return -1
	}
	return exitNormal
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Kubernetes 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 channels

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"strings"

	"k8s.io/klog/v2"
)

// Apply calls kubectl apply to apply the manifest.
// We will likely in future change this to create things directly (or more likely embed this logic into kubectl itself)
func Apply(data []byte) error {
	// We copy the manifest to a temp file because it is likely e.g. an s3 URL, which kubectl can't read
	tmpDir, err := ioutil.TempDir("", "channel")
	if err != nil {
		return fmt.Errorf("error creating temp dir: %v", err)
	}

	defer func() {
		if err := os.RemoveAll(tmpDir); err != nil {
			klog.Warningf("error deleting temp dir %q: %v", tmpDir, err)
		}
	}()

	localManifestFile := path.Join(tmpDir, "manifest.yaml")
	if err := ioutil.WriteFile(localManifestFile, data, 0600); err != nil {
		return fmt.Errorf("error writing temp file: %v", err)
	}

	_, err = execKubectl("apply", "-f", localManifestFile)
	return err
}

func execKubectl(args ...string) (string, error) {
	kubectlPath := "kubectl" // Assume in PATH
	cmd := exec.Command(kubectlPath, args...)
	env := os.Environ()
	cmd.Env = env

	human := strings.Join(cmd.Args, " ")
	klog.V(2).Infof("Running command: %s", human)
	output, err := cmd.CombinedOutput()
	if err != nil {
		klog.Infof("error running %s", human)
		klog.Info(string(output))
		return string(output), fmt.Errorf("error running kubectl: %v", err)
	}

	return string(output), err
}
<commit_msg>Use server-side apply for addons. Idenity as kops<commit_after>/*
Copyright 2019 The Kubernetes 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 channels

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"strings"

	"k8s.io/klog/v2"
)

// Apply calls kubectl apply to apply the manifest.
// We will likely in future change this to create things directly (or more likely embed this logic into kubectl itself)
func Apply(data []byte) error {
	// We copy the manifest to a temp file because it is likely e.g. an s3 URL, which kubectl can't read
	tmpDir, err := ioutil.TempDir("", "channel")
	if err != nil {
		return fmt.Errorf("error creating temp dir: %v", err)
	}

	defer func() {
		if err := os.RemoveAll(tmpDir); err != nil {
			klog.Warningf("error deleting temp dir %q: %v", tmpDir, err)
		}
	}()

	localManifestFile := path.Join(tmpDir, "manifest.yaml")
	if err := ioutil.WriteFile(localManifestFile, data, 0600); err != nil {
		return fmt.Errorf("error writing temp file: %v", err)
	}

	_, err = execKubectl("apply", "-f", localManifestFile, "--server-side", "--force-conflicts", "--field-manager=kops")
	return err
}

func execKubectl(args ...string) (string, error) {
	kubectlPath := "kubectl" // Assume in PATH
	cmd := exec.Command(kubectlPath, args...)
	env := os.Environ()
	cmd.Env = env

	human := strings.Join(cmd.Args, " ")
	klog.V(2).Infof("Running command: %s", human)
	output, err := cmd.CombinedOutput()
	if err != nil {
		klog.Infof("error running %s", human)
		klog.Info(string(output))
		return string(output), fmt.Errorf("error running kubectl: %v", err)
	}

	return string(output), err
}
<|endoftext|>


<commit_before>package checkredis

import (
	"errors"
	"fmt"
	"os"
	"regexp"
	"strings"
	"time"

	"github.com/fzzy/radix/redis"
	"github.com/jessevdk/go-flags"
	"github.com/mackerelio/checkers"
)

type redisSetting struct {
	Host    string `short:"H" long:"host" default:"localhost" description:"Hostname"`
	Socket  string `short:"s" long:"socket" default:"" description:"Server socket"`
	Port    string `short:"p" long:"port" default:"6379" description:"Port"`
	Timeout uint64 `short:"t" long:"timeout" default:"5" description:"Dial Timeout in sec"`
}

var commands = map[string](func([]string) *checkers.Checker){
	"reachable":   checkReachable,
	"replication": checkReplication,
	"slave":       checkSlave, // deprecated command
}

func separateSub(argv []string) (string, []string) {
	if len(argv) == 0 || strings.HasPrefix(argv[0], "-") {
		return "", argv
	}
	return argv[0], argv[1:]
}

// Do the plugin
func Do() {
	subCmd, argv := separateSub(os.Args[1:])
	fn, ok := commands[subCmd]
	if !ok {
		fmt.Println(`Usage:
  check-redis [subcommand] [OPTIONS]

SubCommands:`)
		for k := range commands {
			fmt.Printf("  %s\n", k)
		}
		os.Exit(1)
	}
	ckr := fn(argv)
	ckr.Name = fmt.Sprintf("Redis %s", strings.ToUpper(string(subCmd[0]))+subCmd[1:])
	ckr.Exit()
}

func connectRedis(m redisSetting) (*redis.Client, error) {
	network := "tcp"
	target := fmt.Sprintf("%s:%s", m.Host, m.Port)
	if m.Socket != "" {
		target = m.Socket
		network = "unix"
	}
	c, err := redis.DialTimeout(network, target, time.Duration(m.Timeout)*time.Second)
	if err != nil {
		return nil, fmt.Errorf("couldn't connect: %s", err)
	}
	return c, nil
}

func getRedisInfo(c *redis.Client) (*map[string]string, error) {
	info := make(map[string]string)

	r := c.Cmd("info")
	if r.Err != nil {
		return nil, errors.New("couldn't execute query")
	}
	str, err := r.Str()
	if err != nil {
		return nil, errors.New("couldn't execute query")
	}

	for _, line := range strings.Split(str, "\r\n") {
		if line == "" {
			continue
		}
		if re, _ := regexp.MatchString("^#", line); re {
			continue
		}

		record := strings.SplitN(line, ":", 2)
		if len(record) < 2 {
			continue
		}
		key, value := record[0], record[1]
		info[key] = value
	}

	return &info, nil
}

func connectRedisGetInfo(opts redisSetting) (*redis.Client, *map[string]string, error) {
	c, err := connectRedis(opts)
	if err != nil {
		return nil, nil, err
	}

	info, err := getRedisInfo(c)
	if err != nil {
		return nil, nil, err
	}

	return c, info, nil
}

func checkReachable(args []string) *checkers.Checker {
	opts := redisSetting{}
	psr := flags.NewParser(&opts, flags.Default)
	psr.Usage = "reachable [OPTIONS]"
	_, err := psr.ParseArgs(args)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	c, info, err := connectRedisGetInfo(opts)
	if err != nil {
		return checkers.Unknown(err.Error())
	}
	defer c.Close()

	if _, ok := (*info)["redis_version"]; !ok {
		return checkers.Unknown("couldn't get redis_version")
	}

	return checkers.Ok(
		fmt.Sprintf("version: %s", (*info)["redis_version"]),
	)
}

func checkReplication(args []string) *checkers.Checker {
	opts := redisSetting{}
	psr := flags.NewParser(&opts, flags.Default)
	psr.Usage = "replication [OPTIONS]"
	_, err := psr.ParseArgs(args)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	c, info, err := connectRedisGetInfo(opts)
	if err != nil {
		return checkers.Unknown(err.Error())
	}
	defer c.Close()

	if role, ok := (*info)["role"]; ok {
		if role != "slave" {
			return checkers.Ok("role is not slave")
		}
	} else {
		return checkers.Unknown("couldn't get role")
	}

	if status, ok := (*info)["master_link_status"]; ok {
		msg := fmt.Sprintf("master_link_status: %s", status)

		switch status {
		case "up":
			return checkers.Ok(msg)
		case "down":
			return checkers.Critical(msg)
		default:
			return checkers.Unknown(msg)
		}

	} else {
		return checkers.Unknown("couldn't get master_link_status")
	}
}

// Deprecated: For backward compatibility.
func checkSlave(args []string) *checkers.Checker {
	opts := redisSetting{}
	psr := flags.NewParser(&opts, flags.Default)
	psr.Usage = `slave [OPTIONS]

DEPRECATED: For backward compatibility. Use 'replication' command.`
	_, err := psr.ParseArgs(args)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	c, info, err := connectRedisGetInfo(opts)
	if err != nil {
		return checkers.Unknown(err.Error())
	}
	defer c.Close()

	if status, ok := (*info)["master_link_status"]; ok {
		msg := fmt.Sprintf("master_link_status: %s", status)

		switch status {
		case "up":
			return checkers.Ok(msg)
		case "down":
			return checkers.Critical(msg)
		default:
			return checkers.Unknown(msg)
		}

	} else {
		// it may be a master!
		return checkers.Unknown("couldn't get master_link_status")
	}
}
<commit_msg>add --skip-master option<commit_after>package checkredis

import (
	"errors"
	"fmt"
	"os"
	"regexp"
	"strings"
	"time"

	"github.com/fzzy/radix/redis"
	"github.com/jessevdk/go-flags"
	"github.com/mackerelio/checkers"
)

type redisSetting struct {
	Host    string `short:"H" long:"host" default:"localhost" description:"Hostname"`
	Socket  string `short:"s" long:"socket" default:"" description:"Server socket"`
	Port    string `short:"p" long:"port" default:"6379" description:"Port"`
	Timeout uint64 `short:"t" long:"timeout" default:"5" description:"Dial Timeout in sec"`
}

var commands = map[string](func([]string) *checkers.Checker){
	"reachable":   checkReachable,
	"replication": checkReplication,
	"slave":       checkSlave, // deprecated command
}

func separateSub(argv []string) (string, []string) {
	if len(argv) == 0 || strings.HasPrefix(argv[0], "-") {
		return "", argv
	}
	return argv[0], argv[1:]
}

// Do the plugin
func Do() {
	subCmd, argv := separateSub(os.Args[1:])
	fn, ok := commands[subCmd]
	if !ok {
		fmt.Println(`Usage:
  check-redis [subcommand] [OPTIONS]

SubCommands:`)
		for k := range commands {
			fmt.Printf("  %s\n", k)
		}
		os.Exit(1)
	}
	ckr := fn(argv)
	ckr.Name = fmt.Sprintf("Redis %s", strings.ToUpper(string(subCmd[0]))+subCmd[1:])
	ckr.Exit()
}

func connectRedis(m redisSetting) (*redis.Client, error) {
	network := "tcp"
	target := fmt.Sprintf("%s:%s", m.Host, m.Port)
	if m.Socket != "" {
		target = m.Socket
		network = "unix"
	}
	c, err := redis.DialTimeout(network, target, time.Duration(m.Timeout)*time.Second)
	if err != nil {
		return nil, fmt.Errorf("couldn't connect: %s", err)
	}
	return c, nil
}

func getRedisInfo(c *redis.Client) (*map[string]string, error) {
	info := make(map[string]string)

	r := c.Cmd("info")
	if r.Err != nil {
		return nil, errors.New("couldn't execute query")
	}
	str, err := r.Str()
	if err != nil {
		return nil, errors.New("couldn't execute query")
	}

	for _, line := range strings.Split(str, "\r\n") {
		if line == "" {
			continue
		}
		if re, _ := regexp.MatchString("^#", line); re {
			continue
		}

		record := strings.SplitN(line, ":", 2)
		if len(record) < 2 {
			continue
		}
		key, value := record[0], record[1]
		info[key] = value
	}

	return &info, nil
}

func connectRedisGetInfo(opts redisSetting) (*redis.Client, *map[string]string, error) {
	c, err := connectRedis(opts)
	if err != nil {
		return nil, nil, err
	}

	info, err := getRedisInfo(c)
	if err != nil {
		return nil, nil, err
	}

	return c, info, nil
}

func checkReachable(args []string) *checkers.Checker {
	opts := redisSetting{}
	psr := flags.NewParser(&opts, flags.Default)
	psr.Usage = "reachable [OPTIONS]"
	_, err := psr.ParseArgs(args)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	c, info, err := connectRedisGetInfo(opts)
	if err != nil {
		return checkers.Unknown(err.Error())
	}
	defer c.Close()

	if _, ok := (*info)["redis_version"]; !ok {
		return checkers.Unknown("couldn't get redis_version")
	}

	return checkers.Ok(
		fmt.Sprintf("version: %s", (*info)["redis_version"]),
	)
}

type replicationOpts struct {
	redisSetting
	SkipMaster bool `long:"skip-master" description:"return ok if redis role is master"`
}

func checkReplication(args []string) *checkers.Checker {
	opts := replicationOpts{}
	psr := flags.NewParser(&opts, flags.Default)
	psr.Usage = "replication [OPTIONS]"
	_, err := psr.ParseArgs(args)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	c, info, err := connectRedisGetInfo(opts.redisSetting)
	if err != nil {
		return checkers.Unknown(err.Error())
	}
	defer c.Close()

	if role, ok := (*info)["role"]; ok {
		if role != "slave" && opts.SkipMaster {
			return checkers.Ok("role is not slave")
		}
	} else {
		return checkers.Unknown("couldn't get role")
	}

	if status, ok := (*info)["master_link_status"]; ok {
		msg := fmt.Sprintf("master_link_status: %s", status)

		switch status {
		case "up":
			return checkers.Ok(msg)
		case "down":
			return checkers.Critical(msg)
		default:
			return checkers.Unknown(msg)
		}

	} else {
		return checkers.Unknown("couldn't get master_link_status")
	}
}

// Deprecated: For backward compatibility.
func checkSlave(args []string) *checkers.Checker {
	opts := redisSetting{}
	psr := flags.NewParser(&opts, flags.Default)
	psr.Usage = `slave [OPTIONS]

DEPRECATED: For backward compatibility. Use 'replication' command.`
	_, err := psr.ParseArgs(args)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	c, info, err := connectRedisGetInfo(opts)
	if err != nil {
		return checkers.Unknown(err.Error())
	}
	defer c.Close()

	if status, ok := (*info)["master_link_status"]; ok {
		msg := fmt.Sprintf("master_link_status: %s", status)

		switch status {
		case "up":
			return checkers.Ok(msg)
		case "down":
			return checkers.Critical(msg)
		default:
			return checkers.Unknown(msg)
		}

	} else {
		// it may be a master!
		return checkers.Unknown("couldn't get master_link_status")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/fractalcat/nagiosplugin"
	"io/ioutil"
	"math"
	"os"
	"time"
)

func main() {
	c := nagiosplugin.NewCheck()
	defer c.Finish()
	rrd_path := flag.String("rrd-path", "/var/lib/pnp4nagios/perfdata", "Path to directory containing Nagios perfdata")
	warnSec := flag.Int("warn", 300, "Warning threshold (seconds)")
	critSec := flag.Int("crit", 900, "Critical threshold (seconds)")
	warn := time.Duration(*warnSec) * time.Second
	crit := time.Duration(*critSec) * time.Second
	flag.Parse()
	dirInfo, err := os.Stat(*rrd_path)
	if err != nil {
		c.Unknownf("Unable to stat perfdata directory %v: %v", *rrd_path, err)
	}
	if !dirInfo.IsDir() {
		c.Unknownf("Perfdata directory %v is not a directory", *rrd_path)
	}
	var newest, oldest *time.Time
	dents, err := ioutil.ReadDir(*rrd_path)
	if err != nil {
		c.Unknownf("Unable to get directory listing for %v: %v", *rrd_path, err)
	}
	for _, fi := range dents {
		modtime := fi.ModTime()
		if newest == nil {
			newest = &modtime
		}
		if oldest == nil {
			oldest = &modtime
		}
		if modtime.After(*newest) {
			newest = &modtime
		} else if modtime.Before(*oldest) {
			oldest = &modtime
		}
	}
	dNewest := time.Since(*newest)
	dOldest := time.Since(*oldest)
	info := fmt.Sprintf("Newest RRD update is %v old", dNewest)
	if crit < dNewest {
		c.AddResultf(nagiosplugin.CRITICAL, info)
	} else if warn < dNewest {
		c.AddResultf(nagiosplugin.WARNING, info)
	} else {
		c.AddResultf(nagiosplugin.OK, info)
	}
	perfNewest := float64(dNewest) / float64(time.Second)
	perfOldest := float64(dOldest) / float64(time.Second)
	c.AddPerfDatum("newest_update", "s", perfNewest, 0.0, math.Inf(1), *warnSec, *critSec)
	c.AddPerfDatum("oldest_update", "s", perfOldest, 0.0, math.Inf(1))
}
<commit_msg>Those should be floats<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/fractalcat/nagiosplugin"
	"io/ioutil"
	"math"
	"os"
	"time"
)

func main() {
	c := nagiosplugin.NewCheck()
	defer c.Finish()
	rrd_path := flag.String("rrd-path", "/var/lib/pnp4nagios/perfdata", "Path to directory containing Nagios perfdata")
	warnSec := flag.Int("warn", 300, "Warning threshold (seconds)")
	critSec := flag.Int("crit", 900, "Critical threshold (seconds)")
	warn := time.Duration(*warnSec) * time.Second
	crit := time.Duration(*critSec) * time.Second
	flag.Parse()
	dirInfo, err := os.Stat(*rrd_path)
	if err != nil {
		c.Unknownf("Unable to stat perfdata directory %v: %v", *rrd_path, err)
	}
	if !dirInfo.IsDir() {
		c.Unknownf("Perfdata directory %v is not a directory", *rrd_path)
	}
	var newest, oldest *time.Time
	dents, err := ioutil.ReadDir(*rrd_path)
	if err != nil {
		c.Unknownf("Unable to get directory listing for %v: %v", *rrd_path, err)
	}
	for _, fi := range dents {
		modtime := fi.ModTime()
		if newest == nil {
			newest = &modtime
		}
		if oldest == nil {
			oldest = &modtime
		}
		if modtime.After(*newest) {
			newest = &modtime
		} else if modtime.Before(*oldest) {
			oldest = &modtime
		}
	}
	dNewest := time.Since(*newest)
	dOldest := time.Since(*oldest)
	info := fmt.Sprintf("Newest RRD update is %v old", dNewest)
	if crit < dNewest {
		c.AddResultf(nagiosplugin.CRITICAL, info)
	} else if warn < dNewest {
		c.AddResultf(nagiosplugin.WARNING, info)
	} else {
		c.AddResultf(nagiosplugin.OK, info)
	}
	perfNewest := float64(dNewest) / float64(time.Second)
	perfOldest := float64(dOldest) / float64(time.Second)
	c.AddPerfDatum("newest_update", "s", perfNewest, 0.0, math.Inf(1), float64(*warnSec), float64(*critSec))
	c.AddPerfDatum("oldest_update", "s", perfOldest, 0.0, math.Inf(1))
}
<|endoftext|>


<commit_before>package sweep

import (
	"github.com/btcsuite/btcd/blockchain"
	"github.com/btcsuite/btcd/txscript"
	"github.com/btcsuite/btcd/wire"
	"github.com/btcsuite/btcutil"
	"github.com/lightningnetwork/lnd/lnwallet"
)

// UtxoSweeper provides the functionality to generate sweep txes. The plan is to
// extend UtxoSweeper in the future to also manage the actual sweeping process
// by itself.
type UtxoSweeper struct {
	cfg *UtxoSweeperConfig
}

// UtxoSweeperConfig contains dependencies of UtxoSweeper.
type UtxoSweeperConfig struct {
	// GenSweepScript generates a P2WKH script belonging to the wallet where
	// funds can be swept.
	GenSweepScript func() ([]byte, error)

	// Estimator is used when crafting sweep transactions to estimate the
	// necessary fee relative to the expected size of the sweep transaction.
	Estimator lnwallet.FeeEstimator

	// Signer is used by the sweeper to generate valid witnesses at the
	// time the incubated outputs need to be spent.
	Signer lnwallet.Signer

	// ConfTarget specifies a target for the number of blocks until an
	// initial confirmation.
	ConfTarget uint32
}

// New returns a new UtxoSweeper instance.
func New(cfg *UtxoSweeperConfig) *UtxoSweeper {
	return &UtxoSweeper{
		cfg: cfg,
	}
}

// CreateSweepTx accepts a list of outputs and signs and generates a txn that
// spends from them. This method also makes an accurate fee estimate before
// generating the required witnesses.
//
// The value of currentBlockHeight argument will be set as the tx locktime. This
// function assumes that all CLTV inputs will be unlocked after
// currentBlockHeight. Reasons not to use the maximum of all actual CLTV expiry
// values of the inputs:
//
// - Make handling re-orgs easier.
// - Thwart future possible fee sniping attempts.
// - Make us blend in with the bitcoind wallet.
func (s *UtxoSweeper) CreateSweepTx(inputs []Input,
	currentBlockHeight uint32) (*wire.MsgTx, error) {

	// Create a transaction which sweeps all the newly mature outputs into
	// an output controlled by the wallet.

	// TODO(roasbeef): can be more intelligent about buffering outputs to
	// be more efficient on-chain.

	var weightEstimate lnwallet.TxWeightEstimator

	// Our sweep transaction will pay to a single segwit p2wkh address,
	// ensure it contributes to our weight estimate.
	weightEstimate.AddP2WKHOutput()

	// For each output, use its witness type to determine the estimate
	// weight of its witness, and add it to the proper set of spendable
	// outputs.
	csvCount := 0
	cltvCount := 0
	unknownCount := 0
	for i := range inputs {
		input := inputs[i]

		switch input.WitnessType() {

		// Outputs on a remote commitment transaction that pay directly
		// to us.
		case lnwallet.CommitmentNoDelay:
			weightEstimate.AddP2WKHInput()

		// Outputs on a past commitment transaction that pay directly
		// to us.
		case lnwallet.CommitmentTimeLock:
			weightEstimate.AddWitnessInput(
				lnwallet.ToLocalTimeoutWitnessSize,
			)
			csvCount++

		// Outgoing second layer HTLC's that have confirmed within the
		// chain, and the output they produced is now mature enough to
		// sweep.
		case lnwallet.HtlcOfferedTimeoutSecondLevel:
			weightEstimate.AddWitnessInput(
				lnwallet.ToLocalTimeoutWitnessSize,
			)
			csvCount++

		// Incoming second layer HTLC's that have confirmed within the
		// chain, and the output they produced is now mature enough to
		// sweep.
		case lnwallet.HtlcAcceptedSuccessSecondLevel:
			weightEstimate.AddWitnessInput(
				lnwallet.ToLocalTimeoutWitnessSize,
			)
			csvCount++

		// An HTLC on the commitment transaction of the remote party,
		// that has had its absolute timelock expire.
		case lnwallet.HtlcOfferedRemoteTimeout:
			weightEstimate.AddWitnessInput(
				lnwallet.AcceptedHtlcTimeoutWitnessSize,
			)
			cltvCount++

		// An HTLC on the commitment transaction of the remote party,
		// that can be swept with the preimage.
		case lnwallet.HtlcAcceptedRemoteSuccess:
			weightEstimate.AddWitnessInput(
				lnwallet.OfferedHtlcSuccessWitnessSize,
			)

		default:
			unknownCount++
			log.Warnf("kindergarten output in nursery store "+
				"contains unexpected witness type: %v",
				input.WitnessType())
			continue
		}
	}

	log.Infof("Creating sweep transaction for %v inputs (%v CSV, %v CLTV)",
		len(inputs)-unknownCount, csvCount, cltvCount)

	txWeight := int64(weightEstimate.Weight())
	return s.populateSweepTx(txWeight, currentBlockHeight, inputs)
}

// populateSweepTx populate the final sweeping transaction with all witnesses
// in place for all inputs using the provided txn fee. The created transaction
// has a single output sending all the funds back to the source wallet, after
// accounting for the fee estimate.
func (s *UtxoSweeper) populateSweepTx(txWeight int64, currentBlockHeight uint32,
	inputs []Input) (*wire.MsgTx, error) {

	// Generate the receiving script to which the funds will be swept.
	pkScript, err := s.cfg.GenSweepScript()
	if err != nil {
		return nil, err
	}

	// Sum up the total value contained in the inputs.
	var totalSum btcutil.Amount
	for _, o := range inputs {
		totalSum += btcutil.Amount(o.SignDesc().Output.Value)
	}

	// Using the txn weight estimate, compute the required txn fee.
	feePerKw, err := s.cfg.Estimator.EstimateFeePerKW(s.cfg.ConfTarget)
	if err != nil {
		return nil, err
	}

	log.Debugf("Using %v sat/kw for sweep tx", int64(feePerKw))

	txFee := feePerKw.FeeForWeight(txWeight)

	// Sweep as much possible, after subtracting txn fees.
	sweepAmt := int64(totalSum - txFee)

	// Create the sweep transaction that we will be building. We use
	// version 2 as it is required for CSV. The txn will sweep the amount
	// after fees to the pkscript generated above.
	sweepTx := wire.NewMsgTx(2)
	sweepTx.AddTxOut(&wire.TxOut{
		PkScript: pkScript,
		Value:    sweepAmt,
	})

	sweepTx.LockTime = currentBlockHeight

	// Add all inputs to the sweep transaction. Ensure that for each
	// csvInput, we set the sequence number properly.
	for _, input := range inputs {
		sweepTx.AddTxIn(&wire.TxIn{
			PreviousOutPoint: *input.OutPoint(),
			Sequence:         input.BlocksToMaturity(),
		})
	}

	// Before signing the transaction, check to ensure that it meets some
	// basic validity requirements.
	// TODO(conner): add more control to sanity checks, allowing us to delay
	// spending "problem" outputs, e.g. possibly batching with other classes
	// if fees are too low.
	btx := btcutil.NewTx(sweepTx)
	if err := blockchain.CheckTransactionSanity(btx); err != nil {
		return nil, err
	}

	hashCache := txscript.NewTxSigHashes(sweepTx)

	// With all the inputs in place, use each output's unique witness
	// function to generate the final witness required for spending.
	addWitness := func(idx int, tso Input) error {
		witness, err := tso.BuildWitness(
			s.cfg.Signer, sweepTx, hashCache, idx,
		)
		if err != nil {
			return err
		}

		sweepTx.TxIn[idx].Witness = witness

		return nil
	}

	// Finally we'll attach a valid witness to each csv and cltv input
	// within the sweeping transaction.
	for i, input := range inputs {
		if err := addWitness(i, input); err != nil {
			return nil, err
		}
	}

	return sweepTx, nil
}
<commit_msg>sweep: refactor functions and unify tx info logging<commit_after>package sweep

import (
	"github.com/btcsuite/btcd/blockchain"
	"github.com/btcsuite/btcd/txscript"
	"github.com/btcsuite/btcd/wire"
	"github.com/btcsuite/btcutil"
	"github.com/lightningnetwork/lnd/lnwallet"
)

// UtxoSweeper provides the functionality to generate sweep txes. The plan is to
// extend UtxoSweeper in the future to also manage the actual sweeping process
// by itself.
type UtxoSweeper struct {
	cfg *UtxoSweeperConfig
}

// UtxoSweeperConfig contains dependencies of UtxoSweeper.
type UtxoSweeperConfig struct {
	// GenSweepScript generates a P2WKH script belonging to the wallet where
	// funds can be swept.
	GenSweepScript func() ([]byte, error)

	// Estimator is used when crafting sweep transactions to estimate the
	// necessary fee relative to the expected size of the sweep transaction.
	Estimator lnwallet.FeeEstimator

	// Signer is used by the sweeper to generate valid witnesses at the
	// time the incubated outputs need to be spent.
	Signer lnwallet.Signer

	// ConfTarget specifies a target for the number of blocks until an
	// initial confirmation.
	ConfTarget uint32
}

// New returns a new UtxoSweeper instance.
func New(cfg *UtxoSweeperConfig) *UtxoSweeper {
	return &UtxoSweeper{
		cfg: cfg,
	}
}

// CreateSweepTx accepts a list of inputs and signs and generates a txn that
// spends from them. This method also makes an accurate fee estimate before
// generating the required witnesses.
//
// The created transaction has a single output sending all the funds back to the
// source wallet, after accounting for the fee estimate.
//
// The value of currentBlockHeight argument will be set as the tx locktime. This
// function assumes that all CLTV inputs will be unlocked after
// currentBlockHeight. Reasons not to use the maximum of all actual CLTV expiry
// values of the inputs:
//
// - Make handling re-orgs easier.
// - Thwart future possible fee sniping attempts.
// - Make us blend in with the bitcoind wallet.
func (s *UtxoSweeper) CreateSweepTx(inputs []Input,
	currentBlockHeight uint32) (*wire.MsgTx, error) {

	// Generate the receiving script to which the funds will be swept.
	pkScript, err := s.cfg.GenSweepScript()
	if err != nil {
		return nil, err
	}

	txWeight, csvCount, cltvCount := s.getWeightEstimate(inputs)

	// Using the txn weight estimate, compute the required txn fee.
	feePerKw, err := s.cfg.Estimator.EstimateFeePerKW(s.cfg.ConfTarget)
	if err != nil {
		return nil, err
	}

	log.Infof("Creating sweep transaction for %v inputs (%v CSV, %v CLTV) "+
		"using %v sat/kw", len(inputs), csvCount, cltvCount,
		int64(feePerKw))

	txFee := feePerKw.FeeForWeight(txWeight)

	// Sum up the total value contained in the inputs.
	var totalSum btcutil.Amount
	for _, o := range inputs {
		totalSum += btcutil.Amount(o.SignDesc().Output.Value)
	}

	// Sweep as much possible, after subtracting txn fees.
	sweepAmt := int64(totalSum - txFee)

	// Create the sweep transaction that we will be building. We use
	// version 2 as it is required for CSV. The txn will sweep the amount
	// after fees to the pkscript generated above.
	sweepTx := wire.NewMsgTx(2)
	sweepTx.AddTxOut(&wire.TxOut{
		PkScript: pkScript,
		Value:    sweepAmt,
	})

	sweepTx.LockTime = currentBlockHeight

	// Add all inputs to the sweep transaction. Ensure that for each
	// csvInput, we set the sequence number properly.

	for _, input := range inputs {
		sweepTx.AddTxIn(&wire.TxIn{
			PreviousOutPoint: *input.OutPoint(),
			Sequence:         input.BlocksToMaturity(),
		})
	}

	// Before signing the transaction, check to ensure that it meets some
	// basic validity requirements.
	// TODO(conner): add more control to sanity checks, allowing us to delay
	// spending "problem" outputs, e.g. possibly batching with other classes
	// if fees are too low.
	btx := btcutil.NewTx(sweepTx)
	if err := blockchain.CheckTransactionSanity(btx); err != nil {
		return nil, err
	}

	hashCache := txscript.NewTxSigHashes(sweepTx)

	// With all the inputs in place, use each output's unique witness
	// function to generate the final witness required for spending.
	addWitness := func(idx int, tso Input) error {
		witness, err := tso.BuildWitness(
			s.cfg.Signer, sweepTx, hashCache, idx,
		)
		if err != nil {
			return err
		}

		sweepTx.TxIn[idx].Witness = witness

		return nil
	}

	// Finally we'll attach a valid witness to each csv and cltv input
	// within the sweeping transaction.
	for i, input := range inputs {
		if err := addWitness(i, input); err != nil {
			return nil, err
		}
	}

	return sweepTx, nil
}

// getWeightEstimate returns a weight estimate for the given inputs.
// Additionally, it returns counts for the number of csv and cltv inputs.
func (s *UtxoSweeper) getWeightEstimate(inputs []Input) (int64, int, int) {

	// Create a transaction which sweeps all the newly mature outputs into
	// an output controlled by the wallet.

	// TODO(roasbeef): can be more intelligent about buffering outputs to
	// be more efficient on-chain.

	var weightEstimate lnwallet.TxWeightEstimator

	// Our sweep transaction will pay to a single segwit p2wkh address,
	// ensure it contributes to our weight estimate.
	weightEstimate.AddP2WKHOutput()

	// For each output, use its witness type to determine the estimate
	// weight of its witness, and add it to the proper set of spendable
	// outputs.
	csvCount := 0
	cltvCount := 0

	for i := range inputs {
		input := inputs[i]

		switch input.WitnessType() {

		// Outputs on a remote commitment transaction that pay directly
		// to us.
		case lnwallet.CommitmentNoDelay:
			weightEstimate.AddP2WKHInput()

		// Outputs on a past commitment transaction that pay directly
		// to us.
		case lnwallet.CommitmentTimeLock:
			weightEstimate.AddWitnessInput(
				lnwallet.ToLocalTimeoutWitnessSize,
			)
			csvCount++

		// Outgoing second layer HTLC's that have confirmed within the
		// chain, and the output they produced is now mature enough to
		// sweep.
		case lnwallet.HtlcOfferedTimeoutSecondLevel:
			weightEstimate.AddWitnessInput(
				lnwallet.ToLocalTimeoutWitnessSize,
			)
			csvCount++

		// Incoming second layer HTLC's that have confirmed within the
		// chain, and the output they produced is now mature enough to
		// sweep.
		case lnwallet.HtlcAcceptedSuccessSecondLevel:
			weightEstimate.AddWitnessInput(
				lnwallet.ToLocalTimeoutWitnessSize,
			)
			csvCount++

		// An HTLC on the commitment transaction of the remote party,
		// that has had its absolute timelock expire.
		case lnwallet.HtlcOfferedRemoteTimeout:
			weightEstimate.AddWitnessInput(
				lnwallet.AcceptedHtlcTimeoutWitnessSize,
			)
			cltvCount++

		// An HTLC on the commitment transaction of the remote party,
		// that can be swept with the preimage.
		case lnwallet.HtlcAcceptedRemoteSuccess:
			weightEstimate.AddWitnessInput(
				lnwallet.OfferedHtlcSuccessWitnessSize,
			)

		default:
			log.Warnf("kindergarten output in nursery store "+
				"contains unexpected witness type: %v",
				input.WitnessType())
			continue
		}
	}

	txWeight := int64(weightEstimate.Weight())

	return txWeight, csvCount, cltvCount
}
<|endoftext|>


<commit_before>package swgohgg

import (
	"fmt"
	"time"

	"github.com/PuerkitoBio/goquery"
)

// Arena returns basic information about the player Arena team.
// If authorized, attempts to fetch more information from character stats
func (c *Client) Arena() (team []*CharacterStats, lastUpdate time.Time, err error) {
	doc, err := c.Get(fmt.Sprintf("https://swgoh.gg/u/%s/", c.profile))
	if err != nil {
		return
	}
	basicStats := make(map[string]CharacterStats)
	doc.Find(".current-rank-team").First().Find(".static-char-portrait").Each(func(i int, s *goquery.Selection) {
		charName := s.AttrOr("title", "UNKOWN")
		charBasicStats := CharacterStats{
			Name:  charName,
			Level: atoi(s.Find(".char-portrait-full-level").Text()),
			Stars: stars(s),
		}
		basicStats[charName] = charBasicStats
	})
	for name := range basicStats {
		basic := basicStats[name]
		if c.authorized {
			var stat *CharacterStats
			stat, err = c.CharacterStats(name)
			if err != nil {
				return
			}
			if stat.GearLevel < 0 {
				stat.Name = basic.Name
				stat.Level = basic.GearLevel
				stat.Stars = basic.Stars
			}
			team = append(team, stat)
		} else {
			team = append(team, &basic)
		}
	}
	timestamp := doc.Find(".user-last-updated .datetime").First().AttrOr("data-datetime", "0000-00-00T00:00:00Z")
	lastUpdate, err = time.Parse(time.RFC3339, timestamp)
	return
}
<commit_msg>Fixed arena character ordering.<commit_after>package swgohgg

import (
	"fmt"
	"time"

	"github.com/PuerkitoBio/goquery"
)

// Arena returns basic information about the player Arena team.
// If authorized, attempts to fetch more information from character stats
func (c *Client) Arena() (team []*CharacterStats, lastUpdate time.Time, err error) {
	doc, err := c.Get(fmt.Sprintf("https://swgoh.gg/u/%s/", c.profile))
	if err != nil {
		return
	}
	order := make([]string, 0, 5)
	basicStats := make(map[string]CharacterStats)
	doc.Find(".current-rank-team").First().Find(".static-char-portrait").Each(func(i int, s *goquery.Selection) {
		charName := s.AttrOr("title", "UNKOWN")
		charBasicStats := CharacterStats{
			Name:  charName,
			Level: atoi(s.Find(".char-portrait-full-level").Text()),
			Stars: stars(s),
		}
		basicStats[charName] = charBasicStats
		order = append(order, charName)
	})
	for _, name := range order {
		basic := basicStats[name]
		if c.authorized {
			var stat *CharacterStats
			stat, err = c.CharacterStats(name)
			if err != nil {
				return
			}
			if stat.GearLevel < 0 {
				stat.Name = basic.Name
				stat.Level = basic.GearLevel
				stat.Stars = basic.Stars
			}
			team = append(team, stat)
		} else {
			team = append(team, &basic)
		}
	}
	timestamp := doc.Find(".user-last-updated .datetime").First().AttrOr("data-datetime", "0000-00-00T00:00:00Z")
	lastUpdate, err = time.Parse(time.RFC3339, timestamp)
	return
}
<|endoftext|>


<commit_before>// Copyright 2015 sip authors. All rights reserved.
// Use of this source code is governed by a MIT-style license that can be
// found in the LICENSE file.

package sip

import (
	"bufio"
	"bytes"
	"log"
	"net"
)

// StartTCPClient prepares TCP connection and returns inbound/outbound channels
func StartTCPClient(lAddr string, rAddr string) (chan []byte, chan []byte, *net.TCPConn) {
	//var wg sync.WaitGroup
	//wg.Add(2)
	//Resolve local address
	localTcpAddr, err := net.ResolveTCPAddr("tcp4", lAddr)
	CheckConnError(err)

	//Resolve remote address
	remoteTcpAddr, err := net.ResolveTCPAddr("tcp4", rAddr)
	CheckConnError(err)

	//Establish connection to remote address
	conn, err := net.DialTCP("tcp", localTcpAddr, remoteTcpAddr)
	CheckConnError(err)

	// Outbound channel uses connection to send messages
	outbound := make(chan []byte)
	// Inbound channel passes received message to handleIncomingPacket function
	inbound := make(chan []byte)

	// Goroutine for receiving messages and passing them to handleIncomingPacket function
	go recvTCP(conn, inbound)
	// Goroutine for sending messages
	go sendTCP(conn, outbound)

	return inbound, outbound, conn

}

func sendTCP(connection *net.TCPConn, outbound chan []byte) {
	for message := range outbound {
		_, err := connection.Write(message)
		if err != nil {
			log.Println("Error on write: ", err)
			continue
		}
	}
}

func recvTCP(connection *net.TCPConn, inbound chan []byte) {
	for {
		scanner := bufio.NewScanner(connection)
		onSipDelimiter := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
			delim := []byte{'\r', '\n', '\r', '\n'}
			if atEOF && len(data) == 0 {
				return 0, nil, nil
			}
			if i := bytes.Index(data, delim); i > 0 {
				return i + len(delim), data[0:i], nil
			}
			if atEOF {
				return len(data), data, nil
			}
			return 0, nil, nil
		}
		scanner.Split(onSipDelimiter)
		for scanner.Scan() {
			inbound <- scanner.Bytes()
		}
	}
}
<commit_msg>changes in api, adding basic body processing<commit_after>// Copyright 2015 sip authors. All rights reserved.
// Use of this source code is governed by a MIT-style license that can be
// found in the LICENSE file.

package sip

import (
	"bufio"
	"bytes"
	"log"
	"net"
	"strconv"
)

// StartTCPClient prepares TCP connection and returns inbound/outbound channels
func StartTCPClient(lAddr string, rAddr string) (chan SipMessage, chan SipMessage, *net.TCPConn) {
	//Resolve local address
	localTcpAddr, err := net.ResolveTCPAddr("tcp4", lAddr)
	CheckConnError(err)

	//Resolve remote address
	remoteTcpAddr, err := net.ResolveTCPAddr("tcp4", rAddr)
	CheckConnError(err)

	//Establish connection to remote address
	conn, err := net.DialTCP("tcp", localTcpAddr, remoteTcpAddr)
	CheckConnError(err)

	// Outbound channel uses connection to send messages
	outbound := make(chan SipMessage)
	// Inbound channel passes received message to handleIncomingPacket function
	inbound := make(chan SipMessage)

	// Goroutine for receiving messages and passing them to handleIncomingPacket function
	go recvTCP(conn, inbound)
	// Goroutine for sending messages
	go sendTCP(conn, outbound)

	return inbound, outbound, conn

}

func sendTCP(connection *net.TCPConn, outbound chan SipMessage) {
	for message := range outbound {
		_, err := connection.Write(serializeSipMessage(message))
		if err != nil {
			log.Println("Error on write: ", err)
			continue
		}
	}
}

//TODO put mandatory headers first
func serializeSipMessage(sipMessage SipMessage) []byte {
	var serializedMessage bytes.Buffer
	serializedMessage.WriteString(sipMessage.FirstLine)
	serializedMessage.WriteString("\r\n")
	for name, value := range sipMessage.Headers {
		serializedMessage.WriteString(name)
		serializedMessage.WriteString(": ")
		serializedMessage.WriteString(value)
		serializedMessage.WriteString("\r\n")
	}
	serializedMessage.WriteString("\r\n")
	if len(sipMessage.Body) > 0 {
		serializedMessage.WriteString(sipMessage.Body)
		serializedMessage.WriteString("\r\n")
	}
	return serializedMessage.Bytes()
}

func recvTCP(connection *net.TCPConn, inbound chan SipMessage) {
	reader := bufio.NewReader(connection)
	for {
		var buffer bytes.Buffer
		for {
			chunk, err := reader.ReadString('\n')
			if err != nil {
				log.Println(err)
			}
			buffer.WriteString(chunk)
			if len(chunk) == 2 {
				break
			}
		}
		firstLine, sipHeaders, _ := ParseIncomingMessage(buffer.Bytes())
		contentLength, err := strconv.Atoi(sipHeaders["content-length"])
		if err != nil {
			log.Println("Content-Length value cannot be converted to number, setting it to 0")
			contentLength = 0
		}
		if contentLength < 0 {
			log.Println("Content-Length value is less than 0, setting it to 0")
			contentLength = 0
		}
		sipMessageBody := []byte{}
		if contentLength != 0 {
			sipMessageBody = make([]byte, contentLength, contentLength)
			_, err := reader.Read(sipMessageBody)
			if err != nil {
				log.Println(err)
			}
		}
		inbound <- SipMessage{FirstLine: firstLine, Headers: sipHeaders, Body: string(sipMessageBody)}
	}
}
<|endoftext|>


<commit_before>package client

import (
	"fmt"
	"net/url"
	"strconv"
	"strings"
	"text/tabwriter"
	"time"

	"github.com/hyperhq/hyper/engine"

	gflag "github.com/jessevdk/go-flags"
)

func (cli *HyperClient) HyperCmdImages(args ...string) error {
	var opts struct {
		All bool `short:"a" long:"all" default:"false" description:"Show all images (by default filter out the intermediate image layers)"`
		Num bool `short:"q" long:"quiet" default:"false" description:"Only show numeric IDs"`
	}
	var parser = gflag.NewParser(&opts, gflag.Default)

	parser.Usage = "images [OPTIONS] [REPOSITORY]\n\nList images"
	args, err := parser.ParseArgs(args)
	if err != nil {
		if !strings.Contains(err.Error(), "Usage") {
			return err
		} else {
			return nil
		}
	}
	v := url.Values{}
	v.Set("all", "no")
	v.Set("quiet", "no")
	if opts.All == true {
		v.Set("all", "yes")
	}
	if opts.Num == true {
		v.Set("quiet", "yes")
	}
	body, _, err := readBody(cli.call("GET", "/images/get?"+v.Encode(), nil, nil))
	if err != nil {
		return err
	}
	out := engine.NewOutput()
	remoteInfo, err := out.AddEnv()
	if err != nil {
		return err
	}

	if _, err := out.Write(body); err != nil {
		fmt.Printf("Error reading remote info: %s", err)
		return err
	}
	out.Close()

	var (
		imagesList = []string{}
	)
	imagesList = remoteInfo.GetList("imagesList")

	w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
	if opts.Num == false {
		fmt.Fprintln(w, "REPOSITORY\tTAG\tIMAGE ID\tCREATED\tVIRTUAL SIZE")
		for _, item := range imagesList {
			fields := strings.Split(item, ":")
			date, _ := strconv.ParseUint(fields[3], 0, 64)
			fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", fields[0], fields[1], fields[2][:12], time.Unix(int64(date), 0).Format("2006-01-02 15:04:05"), getImageSizeString(fields[4]))
		}
	} else {
		for _, item := range imagesList {
			fields := strings.Split(item, ":")
			fmt.Fprintf(w, "%s\n", fields[2][:12])
		}
	}
	w.Flush()

	return nil
}

func getImageSizeString(size string) string {
	s, err := strconv.Atoi(size)
	if err != nil {
		return ""
	}
	var rtn float64
	if s < 1024 {
		return size + " B"
	} else if s < 1024*1024 {
		rtn = float64(s) / 1024.0
		return fmt.Sprintf("%.1f KB", rtn)
	} else {
		rtn = float64(s) / (1024.0 * 1024.0)
		return fmt.Sprintf("%.1f MB", rtn)
	}
}
<commit_msg>add docker go-units into hyper<commit_after>package client

import (
	"fmt"
	"net/url"
	"strconv"
	"strings"
	"text/tabwriter"
	"time"

	"github.com/docker/go-units"
	"github.com/hyperhq/hyper/engine"

	gflag "github.com/jessevdk/go-flags"
)

func (cli *HyperClient) HyperCmdImages(args ...string) error {
	var opts struct {
		All bool `short:"a" long:"all" default:"false" description:"Show all images (by default filter out the intermediate image layers)"`
		Num bool `short:"q" long:"quiet" default:"false" description:"Only show numeric IDs"`
	}
	var parser = gflag.NewParser(&opts, gflag.Default)

	parser.Usage = "images [OPTIONS] [REPOSITORY]\n\nList images"
	args, err := parser.ParseArgs(args)
	if err != nil {
		if !strings.Contains(err.Error(), "Usage") {
			return err
		} else {
			return nil
		}
	}
	v := url.Values{}
	v.Set("all", "no")
	v.Set("quiet", "no")
	if opts.All == true {
		v.Set("all", "yes")
	}
	if opts.Num == true {
		v.Set("quiet", "yes")
	}
	body, _, err := readBody(cli.call("GET", "/images/get?"+v.Encode(), nil, nil))
	if err != nil {
		return err
	}
	out := engine.NewOutput()
	remoteInfo, err := out.AddEnv()
	if err != nil {
		return err
	}

	if _, err := out.Write(body); err != nil {
		fmt.Printf("Error reading remote info: %s", err)
		return err
	}
	out.Close()

	var (
		imagesList = []string{}
	)
	imagesList = remoteInfo.GetList("imagesList")

	w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
	if opts.Num == false {
		fmt.Fprintln(w, "REPOSITORY\tTAG\tIMAGE ID\tCREATED\tVIRTUAL SIZE")
		for _, item := range imagesList {
			fields := strings.Split(item, ":")
			date, _ := strconv.ParseUint(fields[3], 0, 64)
			fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", fields[0], fields[1], fields[2][:12], time.Unix(int64(date), 0).Format("2006-01-02 15:04:05"), getImageSizeString(fields[4]))
		}
	} else {
		for _, item := range imagesList {
			fields := strings.Split(item, ":")
			fmt.Fprintf(w, "%s\n", fields[2][:12])
		}
	}
	w.Flush()

	return nil
}

func getImageSizeString(size string) string {
	s, err := strconv.Atoi(size)
	if err != nil {
		return ""
	}

	rtn := float64(s)
	return units.HumanSize(rtn)
}
<|endoftext|>


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

package sync

import (
	"errors"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestErrorWaiter(t *testing.T) {
	tests := []struct {
		desc string
		errs []error
		want []error
	}{
		{
			"nothing",
			nil,
			nil,
		},
		{
			"empty list",
			[]error{},
			nil,
		},
		{
			"no errors",
			[]error{nil, nil, nil},
			nil,
		},
		{
			"single error",
			[]error{nil, errors.New("1"), nil},
			[]error{errors.New("1")},
		},
		{
			"multiple errors",
			[]error{nil, errors.New("1"), errors.New("2"), nil},
			[]error{errors.New("1"), errors.New("2")},
		},
	}

	for _, tt := range tests {
		var ew ErrorWaiter
		for _, err := range tt.errs {
			// Need to create a local variable to make sure that the correct
			// value is used by the closure since the value 'err' points to
			// will change between iterations.
			errLocal := err
			ew.Submit(func() error { return errLocal })
		}

		assert.Equal(t, tt.want, ew.Wait(), tt.desc)
	}
}
<commit_msg>sync/error_test: fix flakiness (#116)<commit_after>// Copyright (c) 2016 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package sync

import (
	"errors"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestErrorWaiter(t *testing.T) {
	one := errors.New("1")
	two := errors.New("2")

	tests := []struct {
		desc string
		errs []error
		want []error
	}{
		{
			"nothing",
			nil,
			nil,
		},
		{
			"empty list",
			[]error{},
			nil,
		},
		{
			"no errors",
			[]error{nil, nil, nil},
			nil,
		},
		{
			"single error",
			[]error{nil, one, nil},
			[]error{one},
		},
		{
			"multiple errors",
			[]error{nil, one, two, nil},
			[]error{one, two},
		},
	}

	for _, tt := range tests {
		want := make(map[error]struct{})
		for _, err := range tt.want {
			want[err] = struct{}{}
		}

		var ew ErrorWaiter
		for _, err := range tt.errs {
			// Need to create a local variable to make sure that the correct
			// value is used by the closure since the value 'err' points to
			// will change between iterations.
			errLocal := err
			ew.Submit(func() error { return errLocal })
		}

		got := make(map[error]struct{})
		for _, err := range ew.Wait() {
			got[err] = struct{}{}
		}

		assert.Equal(t, want, got, tt.desc)
	}
}
<|endoftext|>


<commit_before>package sync

import (
	"errors"
	"io"
	"os"
	"path/filepath"

	"github.com/leeola/fixity"
)

type Iter interface {
	Next() (iterHasValue bool)
	Value() (c fixity.Content, err error)
}

type Config struct {
	Path      string
	Folder    string
	Recursive bool
	Fixity    fixity.Fixity
}

type Sync struct {
	config Config
	fixi   fixity.Fixity

	ch  chan walkResult
	c   fixity.Content
	err error
}

type walkResult struct {
	Path string
	Err  error
}

func New(c Config) (*Sync, error) {
	if c.Path == "" {
		return nil, errors.New("missing reqired config: Path")
	}

	if c.Fixity == nil {
		return nil, errors.New("missing reqired config: Fixity")
	}

	if c.Folder == "" {
		if folder := filepath.Base(filepath.Dir(c.Path)); folder != "." {
			c.Folder = folder
		}
	}

	// enforcing relative folders will allow exporting to be a bit easier/safer.
	if filepath.IsAbs(c.Folder) {
		return nil, errors.New("folder must be relative")
	}

	if c.Folder == "" {
		return nil, errors.New("at least one folder is required")
	}

	return &Sync{
		config: c,
		fixi:   c.Fixity,
	}, nil
}

func (s *Sync) walk() {
	if s.config.Recursive {
		s.walkRecursive()
	} else {
		s.walkFlat()
	}
}

func (s *Sync) walkFlat() {
	println("walkFlat not implemented")
	close(s.ch)
}

func (s *Sync) walkRecursive() {
	err := filepath.Walk(s.config.Path, func(path string, fi os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if fi.IsDir() {
			return nil
		}

		s.ch <- walkResult{Path: path}

		return nil
	})
	if err != nil {
		s.ch <- walkResult{Err: err}
	}
	close(s.ch)
}

func (s *Sync) Next() bool {
	if s.ch == nil {
		s.ch = make(chan walkResult)
		go s.walk()
	}

	walkResult, ok := <-s.ch
	if !ok {
		return false
	}

	if walkResult.Err != nil {
		s.c = fixity.Content{}
		s.err = walkResult.Err
		// return true because there is an error that the caller
		// should grab via .Value()
		return true
	}

	s.c, s.err = s.syncFile(walkResult.Path)
	return true
}

func (s *Sync) Value() (fixity.Content, error) {
	return s.c, s.err
}

func (s *Sync) replaceFile(path string, c fixity.Content) error {
	// using O_CREATE just to be safe, in case something external deletes the
	// file, no reason we can't still create it.
	f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
	if err != nil {
		return err
	}
	defer f.Close()

	rc, err := c.Read()
	if err != nil {
		return err
	}
	defer rc.Close()

	if _, err := io.Copy(f, rc); err != nil {
		return err
	}

	return f.Sync()
}

func (s *Sync) syncFile(path string) (fixity.Content, error) {
	c, err := s.uploadFile(s.config.Path)
	if err != nil {
		return fixity.Content{}, err
	}

	switch c.Index {
	case 1:
		// if the index is 1, this content was appended and was not duplicate.
		// Syncing back to the filesystem is not needed, so append it.
		return c, nil
	case 0:
		// if the index is 0, we cannot assert if the file needs to be sync'd
		// or not. Return an error.
		//
		// This ensures in the event that we don't know the file order,
		// we don't overwrite users files.
		return fixity.Content{}, errors.New("syncFile: unable to sync, unknown Content index of 0")
	}

	// if the index was larger than 1, then it's either unknown or an older blob.
	// In that case, read the file from fixity and write to disk.
	if err := s.replaceFile(path, c); err != nil {
		return fixity.Content{}, err
	}

	return c, nil
}

func (s *Sync) uploadFile(path string) (fixity.Content, error) {
	f, err := os.OpenFile(path, os.O_RDONLY, 0644)
	if err != nil {
		return fixity.Content{}, err
	}
	defer f.Close()

	// TODO(leeola): include unix metadata
	req := fixity.NewWrite(path, f)
	req.IgnoreDuplicateBlob = true

	return s.fixi.WriteRequest(req)
}
<commit_msg>fix: uploadFile with the correct path<commit_after>package sync

import (
	"errors"
	"io"
	"os"
	"path/filepath"

	"github.com/leeola/fixity"
)

type Iter interface {
	Next() (iterHasValue bool)
	Value() (c fixity.Content, err error)
}

type Config struct {
	Path      string
	Folder    string
	Recursive bool
	Fixity    fixity.Fixity
}

type Sync struct {
	config Config
	fixi   fixity.Fixity

	ch  chan walkResult
	c   fixity.Content
	err error
}

type walkResult struct {
	Path string
	Err  error
}

func New(c Config) (*Sync, error) {
	if c.Path == "" {
		return nil, errors.New("missing reqired config: Path")
	}

	if c.Fixity == nil {
		return nil, errors.New("missing reqired config: Fixity")
	}

	if c.Folder == "" {
		if folder := filepath.Base(filepath.Dir(c.Path)); folder != "." {
			c.Folder = folder
		}
	}

	// enforcing relative folders will allow exporting to be a bit easier/safer.
	if filepath.IsAbs(c.Folder) {
		return nil, errors.New("folder must be relative")
	}

	if c.Folder == "" {
		return nil, errors.New("at least one folder is required")
	}

	return &Sync{
		config: c,
		fixi:   c.Fixity,
	}, nil
}

func (s *Sync) walk() {
	if s.config.Recursive {
		s.walkRecursive()
	} else {
		s.walkFlat()
	}
}

func (s *Sync) walkFlat() {
	println("walkFlat not implemented")
	close(s.ch)
}

func (s *Sync) walkRecursive() {
	err := filepath.Walk(s.config.Path, func(path string, fi os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if fi.IsDir() {
			return nil
		}

		s.ch <- walkResult{Path: path}

		return nil
	})
	if err != nil {
		s.ch <- walkResult{Err: err}
	}
	close(s.ch)
}

func (s *Sync) Next() bool {
	if s.ch == nil {
		s.ch = make(chan walkResult)
		go s.walk()
	}

	walkResult, ok := <-s.ch
	if !ok {
		return false
	}

	if walkResult.Err != nil {
		s.c = fixity.Content{}
		s.err = walkResult.Err
		// return true because there is an error that the caller
		// should grab via .Value()
		return true
	}

	s.c, s.err = s.syncFile(walkResult.Path)
	return true
}

func (s *Sync) Value() (fixity.Content, error) {
	return s.c, s.err
}

func (s *Sync) replaceFile(path string, c fixity.Content) error {
	// using O_CREATE just to be safe, in case something external deletes the
	// file, no reason we can't still create it.
	f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
	if err != nil {
		return err
	}
	defer f.Close()

	rc, err := c.Read()
	if err != nil {
		return err
	}
	defer rc.Close()

	if _, err := io.Copy(f, rc); err != nil {
		return err
	}

	return f.Sync()
}

func (s *Sync) syncFile(path string) (fixity.Content, error) {
	c, err := s.uploadFile(path)
	if err != nil {
		return fixity.Content{}, err
	}

	switch c.Index {
	case 1:
		// if the index is 1, this content was appended and was not duplicate.
		// Syncing back to the filesystem is not needed, so append it.
		return c, nil
	case 0:
		// if the index is 0, we cannot assert if the file needs to be sync'd
		// or not. Return an error.
		//
		// This ensures in the event that we don't know the file order,
		// we don't overwrite users files.
		return fixity.Content{}, errors.New("syncFile: unable to sync, unknown Content index of 0")
	}

	// if the index was larger than 1, then it's either unknown or an older blob.
	// In that case, read the file from fixity and write to disk.
	if err := s.replaceFile(path, c); err != nil {
		return fixity.Content{}, err
	}

	return c, nil
}

func (s *Sync) uploadFile(path string) (fixity.Content, error) {
	f, err := os.OpenFile(path, os.O_RDONLY, 0644)
	if err != nil {
		return fixity.Content{}, err
	}
	defer f.Close()

	// TODO(leeola): include unix metadata
	req := fixity.NewWrite(path, f)
	req.IgnoreDuplicateBlob = true

	return s.fixi.WriteRequest(req)
}
<|endoftext|>


<commit_before>package sudoku

import (
	"sort"
	"testing"
)

func TestBasicCellList(t *testing.T) {
	grid := NewGrid()
	defer grid.Done()
	grid.Load(SOLVED_TEST_GRID)
	row := CellList(grid.Row(2))
	if !row.SameRow() {
		t.Log("The items of a row were not all of the same row.")
		t.Fail()
	}

	if row.SameCol() {
		t.Log("For some reason we thought all the cells in a row were in the same col")
		t.Fail()
	}

	var refs []cellRef

	for i := 0; i < DIM; i++ {
		refs = append(refs, cellRef{2, i})
	}

	if !row.sameAsRefs(refs) {
		t.Error("sameAsRefs didn't match values for row 2")
	}

	col := CellList(grid.Col(2))
	if !col.SameCol() {
		t.Log("The items in the col were not int he same col.")
		t.Fail()
	}

	if col.SameRow() {
		t.Log("For some reason we thought all the cells in a col were in the same row")
		t.Fail()
	}

	block := CellList(grid.Block(2))
	if !block.SameBlock() {
		t.Log("The items in the block were not int he same block.")
		t.Fail()
	}

	if block.SameRow() {
		t.Log("For some reason we thought all the cells in a col were in the same row")
		t.Fail()
	}

	if block.SameCol() {
		t.Log("For some reason we thought all the cells in a block were in the same col")
		t.Fail()
	}

	nums := row.CollectNums(func(cell *Cell) int {
		return cell.Row
	})

	if !nums.Same() {
		t.Log("Collecting rows gave us different numbers/.")
		t.Fail()
	}

	isZeroRow := func(cell *Cell) bool {
		return cell.Row == 0
	}

	cells := grid.Block(0).Filter(isZeroRow)

	if len(cells) != BLOCK_DIM {
		t.Log("We got back the wrong number of cells when filtering")
		t.Fail()
	}

	if !cells.SameRow() {
		t.Log("We got back cells not inthe same row.")
		t.Fail()
	}

	description := cells.Description()

	if description != "(0,0), (0,1), and (0,2)" {
		t.Log("Got wrong description of cellList: ", description)
		t.Fail()
	}

	unsortedList := CellList{grid.Cell(0, 1), grid.Cell(1, 2), grid.Cell(0, 0)}
	unsortedList.Sort()
	if unsortedList[0].Row != 0 || unsortedList[0].Col != 0 ||
		unsortedList[1].Row != 0 || unsortedList[1].Col != 1 ||
		unsortedList[2].Row != 1 || unsortedList[2].Col != 2 {
		t.Error("Cell List didn't get sorted: ", unsortedList)
	}

}

func TestFilledNums(t *testing.T) {
	grid := NewGrid()
	defer grid.Done()
	if !grid.LoadFromFile(puzzlePath("nakedpairblock1.sdk")) {
		t.Fatal("Couldn't load file")
	}

	filledNums := grid.Row(0).FilledNums()

	if !filledNums.SameContentAs(IntSlice{3, 7, 8, 9}) {
		t.Error("Filled nums had wrong nums", filledNums)
	}

}

func TestIntList(t *testing.T) {
	numArr := [...]int{1, 1, 1}
	if !IntSlice(numArr[:]).Same() {
		t.Log("We didn't think that a num list with all of the same ints was the same.")
		t.Fail()
	}
	differentNumArr := [...]int{1, 2, 1}
	if IntSlice(differentNumArr[:]).Same() {
		t.Log("We thought a list of different ints were the same")
		t.Fail()
	}
	description := IntSlice(numArr[:]).Description()
	if description != "1, 1, and 1" {
		t.Log("Didn't get right description: ", description)
		t.Fail()
	}

	unsortedList := IntSlice{3, 2, 1}
	unsortedList.Sort()
	if !unsortedList.SameAs(IntSlice{1, 2, 3}) {
		t.Error("IntSlice.Sort did not sort the list.")
	}

	oneList := IntSlice{1}

	description = oneList.Description()

	if description != "1" {
		t.Log("Didn't get the right description for a short intlist: ", description)
		t.Fail()
	}

	twoList := IntSlice{1, 1}

	description = twoList.Description()

	if description != "1 and 1" {
		t.Log("Did'get the the right description for a two-item intList: ", description)
		t.Fail()
	}
}

func TestInverseSubset(t *testing.T) {
	grid := NewGrid()
	defer grid.Done()
	cells := grid.Row(0)

	indexes := IntSlice([]int{4, 6, 2})

	subset := cells.InverseSubset(indexes)

	if len(subset) != DIM-3 {
		t.Error("Inverse subset gave wrong number of results")
	}

	for _, cell := range subset {
		if cell.Col == 2 || cell.Col == 4 || cell.Col == 6 {
			t.Error("Inverse subset included cells it shouldn't have.")
		}
	}

}

func TestIntSliceIntersection(t *testing.T) {
	one := IntSlice([]int{1, 3, 2, 5})
	two := IntSlice([]int{2, 7, 6, 5})

	result := one.Intersection(two)

	if len(result) != 2 {
		t.Error("Intersection had wrong number of items")
	}

	sort.Ints(result)

	if result[0] != 2 || result[1] != 5 {
		t.Error("Intersection result was wrong.")
	}
}

func TestIntSliceDifference(t *testing.T) {
	one := IntSlice([]int{1, 2, 3, 4, 5, 6})
	two := IntSlice([]int{3, 4, 7})

	result := one.Difference(two)

	if !result.SameContentAs(IntSlice([]int{1, 2, 5, 6})) {
		t.Error("Int slice difference gave wrong result: ", result)
	}
}

func TestSameContentAs(t *testing.T) {
	one := IntSlice([]int{2, 3, 1})
	two := IntSlice([]int{2, 1, 3})

	if !one.SameContentAs(two) {
		t.Log("Didn't think two equivalent slices were the same.")
		t.Fail()
	}

	if !one.SameAs([]int{2, 3, 1}) {
		t.Log("We mutated one")
		t.Fail()
	}

	if !two.SameAs([]int{2, 1, 3}) {
		t.Log("We mutated two")
		t.Fail()
	}

	onePair := IntSlice([]int{3, 2})
	twoPair := IntSlice([]int{2, 3})

	if !onePair.SameContentAs(twoPair) {
		t.Log("Didn't think two equivalent pairs were the same.")
		t.Fail()
	}

}
<commit_msg>TESTS FAIL. A starter test for ChainDissimilarity already reveals a panic.<commit_after>package sudoku

import (
	"sort"
	"testing"
)

func TestBasicCellList(t *testing.T) {
	grid := NewGrid()
	defer grid.Done()
	grid.Load(SOLVED_TEST_GRID)
	row := CellList(grid.Row(2))
	if !row.SameRow() {
		t.Log("The items of a row were not all of the same row.")
		t.Fail()
	}

	if row.SameCol() {
		t.Log("For some reason we thought all the cells in a row were in the same col")
		t.Fail()
	}

	var refs []cellRef

	for i := 0; i < DIM; i++ {
		refs = append(refs, cellRef{2, i})
	}

	if !row.sameAsRefs(refs) {
		t.Error("sameAsRefs didn't match values for row 2")
	}

	col := CellList(grid.Col(2))
	if !col.SameCol() {
		t.Log("The items in the col were not int he same col.")
		t.Fail()
	}

	if col.SameRow() {
		t.Log("For some reason we thought all the cells in a col were in the same row")
		t.Fail()
	}

	block := CellList(grid.Block(2))
	if !block.SameBlock() {
		t.Log("The items in the block were not int he same block.")
		t.Fail()
	}

	if block.SameRow() {
		t.Log("For some reason we thought all the cells in a col were in the same row")
		t.Fail()
	}

	if block.SameCol() {
		t.Log("For some reason we thought all the cells in a block were in the same col")
		t.Fail()
	}

	nums := row.CollectNums(func(cell *Cell) int {
		return cell.Row
	})

	if !nums.Same() {
		t.Log("Collecting rows gave us different numbers/.")
		t.Fail()
	}

	isZeroRow := func(cell *Cell) bool {
		return cell.Row == 0
	}

	cells := grid.Block(0).Filter(isZeroRow)

	if len(cells) != BLOCK_DIM {
		t.Log("We got back the wrong number of cells when filtering")
		t.Fail()
	}

	if !cells.SameRow() {
		t.Log("We got back cells not inthe same row.")
		t.Fail()
	}

	description := cells.Description()

	if description != "(0,0), (0,1), and (0,2)" {
		t.Log("Got wrong description of cellList: ", description)
		t.Fail()
	}

	unsortedList := CellList{grid.Cell(0, 1), grid.Cell(1, 2), grid.Cell(0, 0)}
	unsortedList.Sort()
	if unsortedList[0].Row != 0 || unsortedList[0].Col != 0 ||
		unsortedList[1].Row != 0 || unsortedList[1].Col != 1 ||
		unsortedList[2].Row != 1 || unsortedList[2].Col != 2 {
		t.Error("Cell List didn't get sorted: ", unsortedList)
	}

}

func TestChainDissimilarity(t *testing.T) {

	type chainTestConfiguration struct {
		name string
		one  []cellRef
		two  []cellRef
	}

	type chainTestResult struct {
		name          string
		originalIndex int
		value         float64
	}

	tests := []chainTestConfiguration{
		{
			"single cell opposite corners",
			[]cellRef{{0, 0}},
			[]cellRef{{DIM, DIM}},
		},
		{
			"same row different blocks",
			[]cellRef{{0, 0}, {0, 1}},
			[]cellRef{{0, 3}, {0, 4}},
		},
	}

	grid := NewGrid()

	var results []chainTestResult

	for i, test := range tests {
		var listOne CellList
		var listTwo CellList
		for _, ref := range test.one {
			listOne = append(listOne, ref.Cell(grid))
		}
		for _, ref := range test.two {
			listTwo = append(listTwo, ref.Cell(grid))
		}
		dissimilarity := listOne.ChainDissimilarity(listTwo)
		if dissimilarity < 0.0 {
			t.Fatal(test.name, "failed with a dissimilarity less than 0.0: ", dissimilarity)
		}
		if dissimilarity > 1.0 {
			t.Fatal(test.name, "failed with a dissimilarity great than 1.0:", dissimilarity)
		}
		result := chainTestResult{test.name, i, dissimilarity}
		results = append(results, result)
	}

	//TODO: sort them and see if their originalIndexes are now now in order.

	//...But for now just spew.
	t.Error(results)

}

func TestFilledNums(t *testing.T) {
	grid := NewGrid()
	defer grid.Done()
	if !grid.LoadFromFile(puzzlePath("nakedpairblock1.sdk")) {
		t.Fatal("Couldn't load file")
	}

	filledNums := grid.Row(0).FilledNums()

	if !filledNums.SameContentAs(IntSlice{3, 7, 8, 9}) {
		t.Error("Filled nums had wrong nums", filledNums)
	}

}

func TestIntList(t *testing.T) {
	numArr := [...]int{1, 1, 1}
	if !IntSlice(numArr[:]).Same() {
		t.Log("We didn't think that a num list with all of the same ints was the same.")
		t.Fail()
	}
	differentNumArr := [...]int{1, 2, 1}
	if IntSlice(differentNumArr[:]).Same() {
		t.Log("We thought a list of different ints were the same")
		t.Fail()
	}
	description := IntSlice(numArr[:]).Description()
	if description != "1, 1, and 1" {
		t.Log("Didn't get right description: ", description)
		t.Fail()
	}

	unsortedList := IntSlice{3, 2, 1}
	unsortedList.Sort()
	if !unsortedList.SameAs(IntSlice{1, 2, 3}) {
		t.Error("IntSlice.Sort did not sort the list.")
	}

	oneList := IntSlice{1}

	description = oneList.Description()

	if description != "1" {
		t.Log("Didn't get the right description for a short intlist: ", description)
		t.Fail()
	}

	twoList := IntSlice{1, 1}

	description = twoList.Description()

	if description != "1 and 1" {
		t.Log("Did'get the the right description for a two-item intList: ", description)
		t.Fail()
	}
}

func TestInverseSubset(t *testing.T) {
	grid := NewGrid()
	defer grid.Done()
	cells := grid.Row(0)

	indexes := IntSlice([]int{4, 6, 2})

	subset := cells.InverseSubset(indexes)

	if len(subset) != DIM-3 {
		t.Error("Inverse subset gave wrong number of results")
	}

	for _, cell := range subset {
		if cell.Col == 2 || cell.Col == 4 || cell.Col == 6 {
			t.Error("Inverse subset included cells it shouldn't have.")
		}
	}

}

func TestIntSliceIntersection(t *testing.T) {
	one := IntSlice([]int{1, 3, 2, 5})
	two := IntSlice([]int{2, 7, 6, 5})

	result := one.Intersection(two)

	if len(result) != 2 {
		t.Error("Intersection had wrong number of items")
	}

	sort.Ints(result)

	if result[0] != 2 || result[1] != 5 {
		t.Error("Intersection result was wrong.")
	}
}

func TestIntSliceDifference(t *testing.T) {
	one := IntSlice([]int{1, 2, 3, 4, 5, 6})
	two := IntSlice([]int{3, 4, 7})

	result := one.Difference(two)

	if !result.SameContentAs(IntSlice([]int{1, 2, 5, 6})) {
		t.Error("Int slice difference gave wrong result: ", result)
	}
}

func TestSameContentAs(t *testing.T) {
	one := IntSlice([]int{2, 3, 1})
	two := IntSlice([]int{2, 1, 3})

	if !one.SameContentAs(two) {
		t.Log("Didn't think two equivalent slices were the same.")
		t.Fail()
	}

	if !one.SameAs([]int{2, 3, 1}) {
		t.Log("We mutated one")
		t.Fail()
	}

	if !two.SameAs([]int{2, 1, 3}) {
		t.Log("We mutated two")
		t.Fail()
	}

	onePair := IntSlice([]int{3, 2})
	twoPair := IntSlice([]int{2, 3})

	if !onePair.SameContentAs(twoPair) {
		t.Log("Didn't think two equivalent pairs were the same.")
		t.Fail()
	}

}
<|endoftext|>


<commit_before>package cephfs

/*
#cgo LDFLAGS: -lcephfs
#cgo CPPFLAGS: -D_FILE_OFFSET_BITS=64
#include <stdlib.h>
#include <cephfs/libcephfs.h>
*/
import "C"

import (
	"fmt"
	"unsafe"

	"github.com/ceph/go-ceph/errutil"
)

type CephFSError int

func (e CephFSError) Error() string {
	errno, s := errutil.FormatErrno(int(e))
	if s == "" {
		return fmt.Sprintf("cephfs: ret=%d", errno)
	}
	return fmt.Sprintf("cephfs: ret=%d, %s", errno, s)
}

func getError(e C.int) error {
	if e == 0 {
		return nil
	}
	return CephFSError(e)
}

// MountInfo exports ceph's ceph_mount_info from libcephfs.cc
type MountInfo struct {
	mount *C.struct_ceph_mount_info
}

// CreateMount creates a mount handle for interacting with Ceph.
func CreateMount() (*MountInfo, error) {
	mount := &MountInfo{}
	ret := C.ceph_create(&mount.mount, nil)
	if ret != 0 {
		return nil, getError(ret)
	}
	return mount, nil
}

// ReadDefaultConfigFile loads the ceph configuration from the specified config file.
func (mount *MountInfo) ReadDefaultConfigFile() error {
	ret := C.ceph_conf_read_file(mount.mount, nil)
	return getError(ret)
}

// Mount mounts the mount handle.
func (mount *MountInfo) Mount() error {
	ret := C.ceph_mount(mount.mount, nil)
	return getError(ret)
}

// Unmount unmounts the mount handle.
func (mount *MountInfo) Unmount() error {
	ret := C.ceph_unmount(mount.mount)
	return getError(ret)
}

// Release destroys the mount handle.
func (mount *MountInfo) Release() error {
	ret := C.ceph_release(mount.mount)
	return getError(ret)
}

// SyncFs synchronizes all filesystem data to persistent media.
func (mount *MountInfo) SyncFs() error {
	ret := C.ceph_sync_fs(mount.mount)
	return getError(ret)
}

// CurrentDir gets the current working directory.
func (mount *MountInfo) CurrentDir() string {
	cDir := C.ceph_getcwd(mount.mount)
	return C.GoString(cDir)
}

// ChangeDir changes the current working directory.
func (mount *MountInfo) ChangeDir(path string) error {
	cPath := C.CString(path)
	defer C.free(unsafe.Pointer(cPath))

	ret := C.ceph_chdir(mount.mount, cPath)
	return getError(ret)
}

// MakeDir creates a directory.
func (mount *MountInfo) MakeDir(path string, mode uint32) error {
	cPath := C.CString(path)
	defer C.free(unsafe.Pointer(cPath))

	ret := C.ceph_mkdir(mount.mount, cPath, C.mode_t(mode))
	return getError(ret)
}

// RemoveDir removes a directory.
func (mount *MountInfo) RemoveDir(path string) error {
	cPath := C.CString(path)
	defer C.free(unsafe.Pointer(cPath))

	ret := C.ceph_rmdir(mount.mount, cPath)
	return getError(ret)
}

// Chmod changes the mode bits (permissions) of a file/directory.
func (mount *MountInfo) Chmod(path string, mode uint32) error {
	cPath := C.CString(path)
	defer C.free(unsafe.Pointer(cPath))

	ret := C.ceph_chmod(mount.mount, cPath, C.mode_t(mode))
	return getError(ret)
}

// Chown changes the ownership of a file/directory.
func (mount *MountInfo) Chown(path string, user uint32, group uint32) error {
	cPath := C.CString(path)
	defer C.free(unsafe.Pointer(cPath))

	ret := C.ceph_chown(mount.mount, cPath, C.int(user), C.int(group))
	return getError(ret)
}

// IsMounted checks mount status.
func (mount *MountInfo) IsMounted() bool {
	ret := C.ceph_is_mounted(mount.mount)
	return ret == 1
}
<commit_msg>cephfs: wrap ceph_create_from_rados function<commit_after>package cephfs

/*
#cgo LDFLAGS: -lcephfs
#cgo CPPFLAGS: -D_FILE_OFFSET_BITS=64
#include <stdlib.h>
#include <cephfs/libcephfs.h>
*/
import "C"

import (
	"fmt"
	"unsafe"

	"github.com/ceph/go-ceph/errutil"
	"github.com/ceph/go-ceph/rados"
)

type CephFSError int

func (e CephFSError) Error() string {
	errno, s := errutil.FormatErrno(int(e))
	if s == "" {
		return fmt.Sprintf("cephfs: ret=%d", errno)
	}
	return fmt.Sprintf("cephfs: ret=%d, %s", errno, s)
}

func getError(e C.int) error {
	if e == 0 {
		return nil
	}
	return CephFSError(e)
}

// MountInfo exports ceph's ceph_mount_info from libcephfs.cc
type MountInfo struct {
	mount *C.struct_ceph_mount_info
}

// CreateMount creates a mount handle for interacting with Ceph.
func CreateMount() (*MountInfo, error) {
	mount := &MountInfo{}
	ret := C.ceph_create(&mount.mount, nil)
	if ret != 0 {
		return nil, getError(ret)
	}
	return mount, nil
}

// CreateFromRados creates a mount handle using an existing rados cluster
// connection.
//
// Implements:
//  int ceph_create_from_rados(struct ceph_mount_info **cmount, rados_t cluster);
func CreateFromRados(conn *rados.Conn) (*MountInfo, error) {
	mount := &MountInfo{}
	ret := C.ceph_create_from_rados(&mount.mount, C.rados_t(conn.Cluster()))
	if ret != 0 {
		return nil, getError(ret)
	}
	return mount, nil
}

// ReadDefaultConfigFile loads the ceph configuration from the specified config file.
func (mount *MountInfo) ReadDefaultConfigFile() error {
	ret := C.ceph_conf_read_file(mount.mount, nil)
	return getError(ret)
}

// Mount mounts the mount handle.
func (mount *MountInfo) Mount() error {
	ret := C.ceph_mount(mount.mount, nil)
	return getError(ret)
}

// Unmount unmounts the mount handle.
func (mount *MountInfo) Unmount() error {
	ret := C.ceph_unmount(mount.mount)
	return getError(ret)
}

// Release destroys the mount handle.
func (mount *MountInfo) Release() error {
	ret := C.ceph_release(mount.mount)
	return getError(ret)
}

// SyncFs synchronizes all filesystem data to persistent media.
func (mount *MountInfo) SyncFs() error {
	ret := C.ceph_sync_fs(mount.mount)
	return getError(ret)
}

// CurrentDir gets the current working directory.
func (mount *MountInfo) CurrentDir() string {
	cDir := C.ceph_getcwd(mount.mount)
	return C.GoString(cDir)
}

// ChangeDir changes the current working directory.
func (mount *MountInfo) ChangeDir(path string) error {
	cPath := C.CString(path)
	defer C.free(unsafe.Pointer(cPath))

	ret := C.ceph_chdir(mount.mount, cPath)
	return getError(ret)
}

// MakeDir creates a directory.
func (mount *MountInfo) MakeDir(path string, mode uint32) error {
	cPath := C.CString(path)
	defer C.free(unsafe.Pointer(cPath))

	ret := C.ceph_mkdir(mount.mount, cPath, C.mode_t(mode))
	return getError(ret)
}

// RemoveDir removes a directory.
func (mount *MountInfo) RemoveDir(path string) error {
	cPath := C.CString(path)
	defer C.free(unsafe.Pointer(cPath))

	ret := C.ceph_rmdir(mount.mount, cPath)
	return getError(ret)
}

// Chmod changes the mode bits (permissions) of a file/directory.
func (mount *MountInfo) Chmod(path string, mode uint32) error {
	cPath := C.CString(path)
	defer C.free(unsafe.Pointer(cPath))

	ret := C.ceph_chmod(mount.mount, cPath, C.mode_t(mode))
	return getError(ret)
}

// Chown changes the ownership of a file/directory.
func (mount *MountInfo) Chown(path string, user uint32, group uint32) error {
	cPath := C.CString(path)
	defer C.free(unsafe.Pointer(cPath))

	ret := C.ceph_chown(mount.mount, cPath, C.int(user), C.int(group))
	return getError(ret)
}

// IsMounted checks mount status.
func (mount *MountInfo) IsMounted() bool {
	ret := C.ceph_is_mounted(mount.mount)
	return ret == 1
}
<|endoftext|>


<commit_before>package logreg

import "testing"

func TestNewLogisticRegression(t *testing.T) {
	if lr := NewLogisticRegression(); lr == nil {
		t.Errorf("got nil linear regression")
	}
}

func TestInitialize(t *testing.T) {
	lr := NewLogisticRegression()
	lr.Initialize()

	if len(lr.Xn) != len(lr.Yn) {
		t.Errorf("got different size of vectors Xn Yn, wants same size")
	}

	if len(lr.Xn[0]) != len(lr.Wn) {
		t.Errorf("got different size of vectors Xn Wn, wants same size")
	}

	if len(lr.Xn) != lr.TrainingPoints {
		t.Errorf("got different size of vectors Xn and training points, wants same number")
	}

	for i := 0; i < len(lr.Xn); i++ {
		for j := 0; j < len(lr.Xn[0]); j++ {
			if lr.Xn[i][j] < lr.Interval.Min ||
				lr.Xn[i][j] > lr.Interval.Max {
				t.Errorf("got value of Xn[%d][%d] = %v, want it between %v and %v", i, j, lr.Xn[i][j], lr.Interval.Min, lr.Interval.Max)
			}
		}
	}

	for i := 0; i < len(lr.Yn); i++ {
		if lr.Yn[i] != float64(-1) && lr.Yn[i] != float64(1) {
			t.Errorf("got value of Yn[%v] = %v, want it equal to -1 or 1", i, lr.Yn[i])
		}
	}
}

func TestInitializeFromData(t *testing.T) {
	data := [][]float64{
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
	}
	lr := NewLogisticRegression()
	if err := lr.InitializeFromData(data); err != nil {
		t.Errorf("%v", err)
	}
	if len(lr.Xn) != len(data) || len(lr.Yn) != len(data) {
		t.Errorf("got difference in size of Xn or Yn and data")
	}

	if len(lr.Xn) != lr.TrainingPoints {
		t.Errorf("got difference in size of Xn or TrainingPoints and data")
	}

	if len(lr.Xn[0]) != len(lr.Wn) {
		t.Errorf("got different size of vectors Xn Wn, wants same size")
	}

	if len(lr.Xn[0]) != lr.VectorSize || len(data[0]) != lr.VectorSize {
		t.Errorf("got difference in size of Xn[0] or data[0] with VectorSize")
	}
}
<commit_msg>logreg - add learn test<commit_after>package logreg

import "testing"

func TestNewLogisticRegression(t *testing.T) {
	if lr := NewLogisticRegression(); lr == nil {
		t.Errorf("got nil linear regression")
	}
}

func TestInitialize(t *testing.T) {
	lr := NewLogisticRegression()
	lr.Initialize()

	if len(lr.Xn) != len(lr.Yn) {
		t.Errorf("got different size of vectors Xn Yn, wants same size")
	}

	if len(lr.Xn[0]) != len(lr.Wn) {
		t.Errorf("got different size of vectors Xn Wn, wants same size")
	}

	if len(lr.Xn) != lr.TrainingPoints {
		t.Errorf("got different size of vectors Xn and training points, wants same number")
	}

	for i := 0; i < len(lr.Xn); i++ {
		for j := 0; j < len(lr.Xn[0]); j++ {
			if lr.Xn[i][j] < lr.Interval.Min ||
				lr.Xn[i][j] > lr.Interval.Max {
				t.Errorf("got value of Xn[%d][%d] = %v, want it between %v and %v", i, j, lr.Xn[i][j], lr.Interval.Min, lr.Interval.Max)
			}
		}
	}

	for i := 0; i < len(lr.Yn); i++ {
		if lr.Yn[i] != float64(-1) && lr.Yn[i] != float64(1) {
			t.Errorf("got value of Yn[%v] = %v, want it equal to -1 or 1", i, lr.Yn[i])
		}
	}
}

func TestInitializeFromData(t *testing.T) {
	data := [][]float64{
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
	}

	lr := NewLogisticRegression()
	if err := lr.InitializeFromData(data); err != nil {
		t.Errorf("%v", err)
	}
	if len(lr.Xn) != len(data) || len(lr.Yn) != len(data) {
		t.Errorf("got difference in size of Xn or Yn and data")
	}

	if len(lr.Xn) != lr.TrainingPoints {
		t.Errorf("got difference in size of Xn or TrainingPoints and data")
	}

	if len(lr.Xn[0]) != len(lr.Wn) {
		t.Errorf("got different size of vectors Xn Wn, wants same size")
	}

	if len(lr.Xn[0]) != lr.VectorSize || len(data[0]) != lr.VectorSize {
		t.Errorf("got difference in size of Xn[0] or data[0] with VectorSize")
	}
}

func TestLearn(t *testing.T) {
	lr := NewLogisticRegression()
	data := [][]float64{
		{0.1, 1, 1},
		{0.2, 1, 1},
		{0.3, 1, 1},
		{1, 0.5, -1},
		{1, 0.6, -1},
		{1, 0.7, -1},
	}

	lr.InitializeFromData(data)
	lr.Learn()
	expectedWn := []float64{0.06586, -0.99194, 0.56851}
	if !equal(expectedWn, lr.Wn) {
		t.Errorf("Weight vector is not correct: got %v, want %v", lr.Wn, expectedWn)
	}
}

const epsilon float64 = 0.001

func equal(a, b []float64) bool {
	if len(a) != len(b) {
		return false
	}
	for i := range a {
		if (a[i] - b[i]) > epsilon {
			return false
		}
	}
	return true
}
<|endoftext|>