<commit_before>/*
 *
 * k6 - a next-generation load testing tool
 * Copyright (C) 2016 Load Impact
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package lib

import (
	"context"
	"errors"
	"github.com/loadimpact/k6/stats"
	"sync"
	"time"
)

const (
	TickRate          = 1 * time.Millisecond
	ThresholdTickRate = 2 * time.Second
	ShutdownTimeout   = 10 * time.Second
)

// Special error used to signal that a VU wants a taint, without logging an error.
var ErrVUWantsTaint = errors.New("test is tainted")

type vuEntry struct {
	VU     VU
	Cancel context.CancelFunc
}

// The Engine is the beating heart of K6.
type Engine struct {
	Runner  Runner
	Options Options

	Metrics    map[*stats.Metric]stats.Sink
	Thresholds map[string]Thresholds

	atTime    time.Duration
	vuEntries []*vuEntry
	vuMutex   sync.Mutex

	// Stubbing these out to pass tests.
	running bool
	paused  bool
	vus     int64
	vusMax  int64

	// Subsystem-related.
	subctx    context.Context
	subcancel context.CancelFunc
	submutex  sync.Mutex
	subwg     sync.WaitGroup
}

func NewEngine(r Runner, o Options) (*Engine, error) {
	e := &Engine{
		Runner:  r,
		Options: o,

		Metrics:    make(map[*stats.Metric]stats.Sink),
		Thresholds: make(map[string]Thresholds),
	}
	e.clearSubcontext()

	if o.VUsMax.Valid {
		if err := e.SetVUsMax(o.VUsMax.Int64); err != nil {
			return nil, err
		}
	}
	if o.VUs.Valid {
		if err := e.SetVUs(o.VUs.Int64); err != nil {
			return nil, err
		}
	}
	if o.Paused.Valid {
		e.SetPaused(o.Paused.Bool)
	}

	return e, nil
}

func (e *Engine) Run(ctx context.Context) error {
	e.clearSubcontext()

	e.running = true
	<-ctx.Done()
	e.running = false

	e.clearSubcontext()
	e.subwg.Wait()

	return nil
}

func (e *Engine) IsRunning() bool {
	return e.running
}

func (e *Engine) SetPaused(v bool) {
	e.paused = v
}

func (e *Engine) IsPaused() bool {
	return e.paused
}

func (e *Engine) SetVUs(v int64) error {
	if v < 0 {
		return errors.New("vus can't be negative")
	}
	if v > e.vusMax {
		return errors.New("more vus than allocated requested")
	}

	e.vuMutex.Lock()
	defer e.vuMutex.Unlock()

	// Scale up
	for i := e.vus; i < v; i++ {
		vu := e.vuEntries[i]
		if vu.Cancel != nil {
			panic(errors.New("fatal miscalculation: attempted to re-schedule active VU"))
		}

		ctx, cancel := context.WithCancel(e.subctx)
		vu.Cancel = cancel

		e.subwg.Add(1)
		go func() {
			e.subwg.Done()
			e.runVU(ctx, vu)
		}()
	}

	// Scale down
	for i := e.vus - 1; i >= v; i-- {
		vu := e.vuEntries[i]
		vu.Cancel()
		vu.Cancel = nil
	}

	e.vus = v
	return nil
}

func (e *Engine) GetVUs() int64 {
	return e.vus
}

func (e *Engine) SetVUsMax(v int64) error {
	if v < 0 {
		return errors.New("vus-max can't be negative")
	}
	if v < e.vus {
		return errors.New("can't reduce vus-max below vus")
	}

	e.vuMutex.Lock()
	defer e.vuMutex.Unlock()

	// Scale up
	for len(e.vuEntries) < int(v) {
		var entry vuEntry
		if e.Runner != nil {
			vu, err := e.Runner.NewVU()
			if err != nil {
				return err
			}
			entry.VU = vu
		}
		e.vuEntries = append(e.vuEntries, &entry)
	}

	// Scale down
	if len(e.vuEntries) > int(v) {
		e.vuEntries = e.vuEntries[:int(v)]
	}

	e.vusMax = v
	return nil
}

func (e *Engine) GetVUsMax() int64 {
	return e.vusMax
}

func (e *Engine) IsTainted() bool {
	return false
}

func (e *Engine) AtTime() time.Duration {
	return e.atTime
}

func (e *Engine) TotalTime() (time.Duration, bool) {
	return 0, false
}

func (e *Engine) clearSubcontext() {
	e.submutex.Lock()
	defer e.submutex.Unlock()

	if e.subcancel != nil {
		e.subcancel()
	}
	subctx, subcancel := context.WithCancel(context.Background())
	e.subctx = subctx
	e.subcancel = subcancel
}

func (e *Engine) runVU(ctx context.Context, vu *vuEntry) {
	// nil runners that produce nil VUs are used for testing.
	if vu.VU == nil {
		<-ctx.Done()
		return
	}

	for {
		_, _ = vu.VU.RunOnce(ctx)

		select {
		case <-ctx.Done():
			return
		default:
		}
	}
}
<commit_msg>[fix] Don't start VUs with terminated contexts<commit_after>/*
 *
 * k6 - a next-generation load testing tool
 * Copyright (C) 2016 Load Impact
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package lib

import (
	"context"
	"errors"
	"github.com/loadimpact/k6/stats"
	"sync"
	"time"
)

const (
	TickRate          = 1 * time.Millisecond
	ThresholdTickRate = 2 * time.Second
	ShutdownTimeout   = 10 * time.Second
)

// Special error used to signal that a VU wants a taint, without logging an error.
var ErrVUWantsTaint = errors.New("test is tainted")

type vuEntry struct {
	VU     VU
	Cancel context.CancelFunc
}

// The Engine is the beating heart of K6.
type Engine struct {
	Runner  Runner
	Options Options

	Metrics    map[*stats.Metric]stats.Sink
	Thresholds map[string]Thresholds

	atTime    time.Duration
	vuEntries []*vuEntry
	vuMutex   sync.Mutex

	// Stubbing these out to pass tests.
	running bool
	paused  bool
	vus     int64
	vusMax  int64

	// Subsystem-related.
	subctx    context.Context
	subcancel context.CancelFunc
	submutex  sync.Mutex
	subwg     sync.WaitGroup
}

func NewEngine(r Runner, o Options) (*Engine, error) {
	e := &Engine{
		Runner:  r,
		Options: o,

		Metrics:    make(map[*stats.Metric]stats.Sink),
		Thresholds: make(map[string]Thresholds),
	}
	e.clearSubcontext()

	if o.VUsMax.Valid {
		if err := e.SetVUsMax(o.VUsMax.Int64); err != nil {
			return nil, err
		}
	}
	if o.VUs.Valid {
		if err := e.SetVUs(o.VUs.Int64); err != nil {
			return nil, err
		}
	}
	if o.Paused.Valid {
		e.SetPaused(o.Paused.Bool)
	}

	return e, nil
}

func (e *Engine) Run(ctx context.Context) error {
	e.running = true
	<-ctx.Done()
	e.running = false

	e.clearSubcontext()
	e.subwg.Wait()

	return nil
}

func (e *Engine) IsRunning() bool {
	return e.running
}

func (e *Engine) SetPaused(v bool) {
	e.paused = v
}

func (e *Engine) IsPaused() bool {
	return e.paused
}

func (e *Engine) SetVUs(v int64) error {
	if v < 0 {
		return errors.New("vus can't be negative")
	}
	if v > e.vusMax {
		return errors.New("more vus than allocated requested")
	}

	e.vuMutex.Lock()
	defer e.vuMutex.Unlock()

	// Scale up
	for i := e.vus; i < v; i++ {
		vu := e.vuEntries[i]
		if vu.Cancel != nil {
			panic(errors.New("fatal miscalculation: attempted to re-schedule active VU"))
		}

		ctx, cancel := context.WithCancel(e.subctx)
		vu.Cancel = cancel

		e.subwg.Add(1)
		go func() {
			e.subwg.Done()
			e.runVU(ctx, vu)
		}()
	}

	// Scale down
	for i := e.vus - 1; i >= v; i-- {
		vu := e.vuEntries[i]
		vu.Cancel()
		vu.Cancel = nil
	}

	e.vus = v
	return nil
}

func (e *Engine) GetVUs() int64 {
	return e.vus
}

func (e *Engine) SetVUsMax(v int64) error {
	if v < 0 {
		return errors.New("vus-max can't be negative")
	}
	if v < e.vus {
		return errors.New("can't reduce vus-max below vus")
	}

	e.vuMutex.Lock()
	defer e.vuMutex.Unlock()

	// Scale up
	for len(e.vuEntries) < int(v) {
		var entry vuEntry
		if e.Runner != nil {
			vu, err := e.Runner.NewVU()
			if err != nil {
				return err
			}
			entry.VU = vu
		}
		e.vuEntries = append(e.vuEntries, &entry)
	}

	// Scale down
	if len(e.vuEntries) > int(v) {
		e.vuEntries = e.vuEntries[:int(v)]
	}

	e.vusMax = v
	return nil
}

func (e *Engine) GetVUsMax() int64 {
	return e.vusMax
}

func (e *Engine) IsTainted() bool {
	return false
}

func (e *Engine) AtTime() time.Duration {
	return e.atTime
}

func (e *Engine) TotalTime() (time.Duration, bool) {
	return 0, false
}

func (e *Engine) clearSubcontext() {
	e.submutex.Lock()
	defer e.submutex.Unlock()

	if e.subcancel != nil {
		e.subcancel()
	}
	subctx, subcancel := context.WithCancel(context.Background())
	e.subctx = subctx
	e.subcancel = subcancel
}

func (e *Engine) runVU(ctx context.Context, vu *vuEntry) {
	// nil runners that produce nil VUs are used for testing.
	if vu.VU == nil {
		<-ctx.Done()
		return
	}

	for {
		_, _ = vu.VU.RunOnce(ctx)

		select {
		case <-ctx.Done():
			return
		default:
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/xml"
	"fmt"
	"os/exec"
	"strings"
)

type Executable struct {
	Title            string           `xml:"title"`
	Description      string           `xml:"description"`
	Version          string           `xml:"version"`
	DocumentationURL string           `xml:"documentation-url"`
	License          string           `xml:"license"`
	Contributor      string           `xml:"contributor"`
	Acknowledgements string           `xml:"acknowledgements"`
	ParameterGroups  []ParameterGroup `xml:"parameters"`
}

type ParameterGroup struct {
	Parameters []Parameter `xml:",any"`
}

type Parameter struct {
	Name        string `xml:"name"`
	Longflag    string `xml:"longflag"`
	Flag        string `xml:"flag"`
	Description string `xml:"description"`
	Default     string `xml:"default"`
	Index       int    `xml:"index"`
	Channel     string `xml:"channel"`
}

// Run the executable at path, and return a service
func CreateService(path string) (*Service, error) {
	out, err := exec.Command(path, "--xml").Output()
	if err != nil {
		return nil, fmt.Errorf("failed to execute %v: %v", path, err.Error())
	}

	return CreateServiceFromXML(path, string(out))
}

func CreateServiceFromXML(path string, out string) (*Service, error) {

	var executable Executable
	parser := xml.NewDecoder(strings.NewReader(out))
	err := parser.Decode(&executable)
	if err != nil {
		return nil, fmt.Errorf("failed to parse %v", err.Error())
	}

	service := NewService()

	service.Description = executable.Description

	positional := make([]string, 20, 20)

	// Parse all the arguments
	for _, group := range executable.ParameterGroups {
		for _, p := range group.Parameters {

			// Not valid
			if p.Name == "" {
				continue
			}

			// Positional argument
			if p.Longflag == "" && p.Flag == "" {
				n := p.Name
				if p.Channel == "input" {
					n = "<" + n
				}
				if p.Channel == "output" {
					n = ">" + n
				}
				if p.Default != "" {
					service.Defaults[n] = p.Default
				}
				positional[p.Index] = n
			} else {
				// Flag
				n := "#" + p.Name
				if p.Channel == "output" {
					n = ">" + p.Name
				}
				if p.Channel == "input" {
					n = "<" + p.Name
				}
				f := ""
				if p.Longflag != "" {
					f = "--" + p.Longflag
				}
				if p.Flag != "" {
					f = "-" + p.Flag
				}
				if p.Default != "" {
					service.Defaults[p.Name] = p.Default
				}
				service.CommandLine = append(service.CommandLine, f, n)
			}
		}
	}

	// Prepend the path, append the positional arguments
	service.CommandLine = append([]string{path}, service.CommandLine...)
	for _, arg := range positional {
		if arg != "" {
			service.CommandLine = append(service.CommandLine, arg)
		}
	}

	service.setup()
	return service, nil
}
<commit_msg>Fixes double dash in Slicer XML from CLI modules<commit_after>package main

import (
	"encoding/xml"
	"fmt"
	"os/exec"
	"strings"
)

type Executable struct {
	Title            string           `xml:"title"`
	Description      string           `xml:"description"`
	Version          string           `xml:"version"`
	DocumentationURL string           `xml:"documentation-url"`
	License          string           `xml:"license"`
	Contributor      string           `xml:"contributor"`
	Acknowledgements string           `xml:"acknowledgements"`
	ParameterGroups  []ParameterGroup `xml:"parameters"`
}

type ParameterGroup struct {
	Parameters []Parameter `xml:",any"`
}

type Parameter struct {
	Name        string `xml:"name"`
	Longflag    string `xml:"longflag"`
	Flag        string `xml:"flag"`
	Description string `xml:"description"`
	Default     string `xml:"default"`
	Index       int    `xml:"index"`
	Channel     string `xml:"channel"`
}

// Run the executable at path, and return a service
func CreateService(path string) (*Service, error) {
	out, err := exec.Command(path, "--xml").Output()
	if err != nil {
		return nil, fmt.Errorf("failed to execute %v: %v", path, err.Error())
	}

	return CreateServiceFromXML(path, string(out))
}

func CreateServiceFromXML(path string, out string) (*Service, error) {

	var executable Executable
	parser := xml.NewDecoder(strings.NewReader(out))
	err := parser.Decode(&executable)
	if err != nil {
		return nil, fmt.Errorf("failed to parse %v", err.Error())
	}

	service := NewService()

	service.Description = executable.Description

	positional := make([]string, 20, 20)

	// Parse all the arguments
	for _, group := range executable.ParameterGroups {
		for _, p := range group.Parameters {

			// Not valid
			if p.Name == "" {
				continue
			}

			// Positional argument
			if p.Longflag == "" && p.Flag == "" {
				n := p.Name
				if p.Channel == "input" {
					n = "<" + n
				}
				if p.Channel == "output" {
					n = ">" + n
				}
				if p.Default != "" {
					service.Defaults[n] = p.Default
				}
				positional[p.Index] = n
			} else {
				// Flag
				n := "#" + p.Name
				if p.Channel == "output" {
					n = ">" + p.Name
				}
				if p.Channel == "input" {
					n = "<" + p.Name
				}
				f := ""
				if p.Longflag != "" {
					// Sometimes, the "--" is left on long flags...
					p.Longflag = strings.TrimPrefix(p.Longflag, "--")
					f = "--" + p.Longflag
				}
				if p.Flag != "" {
					// Sometimes, the "-" is left on flags...
					p.Flag = strings.TrimPrefix(p.Flag, "-")
					f = "-" + p.Flag
				}
				if p.Default != "" {
					service.Defaults[p.Name] = p.Default
				}
				service.CommandLine = append(service.CommandLine, f, n)
			}
		}
	}

	// Prepend the path, append the positional arguments
	service.CommandLine = append([]string{path}, service.CommandLine...)
	for _, arg := range positional {
		if arg != "" {
			service.CommandLine = append(service.CommandLine, arg)
		}
	}

	service.setup()
	return service, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"os/user"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
)

const (
	corednsImage = "k8s.gcr.io/coredns:1.6.2"
	testerImage  = "c.txtdirect.org/tester:dirty"
)

var txtdirectImage = fmt.Sprintf("c.txtdirect.org/txtdirect:%s", os.Getenv("VERSION"))

var resultRegex = regexp.MustCompile("Total:+\\s(\\d+),\\sPassed:+\\s(\\d+),\\sFailed:+\\s(\\d+)")

type dockerManager struct {
	dir       string
	cdir      string
	gomodpath string

	testerContainerLogs map[string][]byte

	stats struct {
		total  int
		passed int
		failed int
	}
}

func main() {
	d := dockerManager{
		testerContainerLogs: make(map[string][]byte),
	}

	if err := d.CheckClient(); err != nil {
		log.Fatalf("[txtdirect_e2e]: Docker daemon didn't respond to client: %s", err)
	}

	var directories []string
	if err := listDirectories(&directories); err != nil {
		log.Printf("[txtdirect_e2e]: Couldn't list the test directories: %s", err.Error())
	}

	if err := d.CreateNetwork(); err != nil {
		log.Fatalf("[txtdirect_e2e]: Couldn't create the network adaptor: %s", err.Error())
	}

	// Run the tests for each test-case
	for _, directory := range directories {
		// Start the CoreDNS and TXTDirect containers for test-case
		d.dir = directory

		if err := d.StartContainers(); err != nil {
			log.Fatalf("[txtdirect_e2e]: Couldn't start containers: %s", err.Error())
		}

		if err := d.RunTesterContainer(); err != nil {
			log.Fatalf("[txtdirect_e2e]: Couldn't run the tests in container: %s", err.Error())
		}

		if err := d.StopContainers(); err != nil {
			log.Fatalf("[txtdirect_e2e]: Couldn't stop containers: %s", err.Error())
		}
	}

	if err := d.ExamineLogs(); err != nil {
		log.Fatalf("[txtdirect_e2e]: Couldn't examine the logs and count the stats: %s", err.Error())
	}

	if err := d.RemoveNetwork(); err != nil {
		log.Fatalf("[txtdirect_e2e]: Couldn't remove the network adaptor: %s", err.Error())
	}

	if d.stats.failed != 0 {
		log.Fatalf("[txtdirect_e2e]: Tests failed because there were %d failed tests.", d.stats.failed)
	}
}

func listDirectories(directories *[]string) error {
	return filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return fmt.Errorf("Couldn't find the directory %q: %s", path, err.Error())
		}
		if info.IsDir() && path != "." {
			*directories = append(*directories, path)
			return filepath.SkipDir
		}
		return nil
	})
}

// CheckClient calls the "docker info" command to check if Docker daemon and CLI exist
func (d *dockerManager) CheckClient() error {
	_, err := exec.Command("docker", "info").CombinedOutput()
	if err != nil {
		return fmt.Errorf("Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?")
	}

	return nil
}

// StartContainers starts a CoreDNS and a TXTDirect container for each test-case
func (d *dockerManager) StartContainers() error {
	// Get current working directory to create mountpoint to containers for test-case data
	var err error
	d.cdir, err = os.Getwd()
	if err != nil {
		return fmt.Errorf("Couldn't get the current working directory: %s", err.Error())
	}

	// Fetch GOPATH for mounting /go/pkg/mod volumes
	if os.Getenv("GOPATH") == "" {
		return fmt.Errorf("$GOPATH is empty")
	}
	d.gomodpath = fmt.Sprintf("%s/pkg/mod", os.Getenv("GOPATH"))

	// Create the CoreDNS container
	_, err = exec.Command("docker",
		"container", "run",
		"-d",
		// Exposed Ports
		"-p", "53:53",
		// Mounted volumes
		"-v", fmt.Sprintf("%s/%s:/e2e", d.cdir, d.dir),
		"-v", fmt.Sprintf("%s:/go/pkg/mod", d.gomodpath),
		// Network
		"--network", "coretxtd",
		// Container Name
		"--name", "e2e_coredns_container",
		corednsImage,
		// CMD
		"-conf",
		"/e2e/Corefile",
	).CombinedOutput()
	if err != nil {
		return fmt.Errorf("Couldn't create the CoreDNS container: %s", err.Error())
	}

	// Create the TXTDirect container
	_, err = exec.Command("docker",
		"container", "run",
		"-d",
		// Exposed Ports
		"-p", "80:80",
		// Mounted volumes
		"-v", fmt.Sprintf("%s/%s:/e2e", d.cdir, d.dir),
		"-v", fmt.Sprintf("%s:/go/pkg/mod", d.gomodpath),
		// Network
		"--network", "coretxtd",
		// Container Name
		"--name", "e2e_txtdirect_container",
		txtdirectImage,
		// CMD
		"-conf",
		"/e2e/txtdirect.config",
	).CombinedOutput()
	if err != nil {
		return fmt.Errorf("Couldn't create the TXTDirect container: %s", err.Error())
	}

	// Push the test image to the testing Docker registry
	if strings.Contains(d.dir, "dockerv2") {
		if err := d.PushTestImage(); err != nil {
			return err
		}
	}

	return nil
}

func (d *dockerManager) StopContainers() error {
	if strings.Contains(d.dir, "path") {
		logs, err := exec.Command("docker",
			"logs",
			"e2e_txtdirect_container",
		).CombinedOutput()
		if err != nil {
			return err
		}
		fmt.Println(string(logs))
	}
	_, err := exec.Command("docker",
		"container", "rm", "-f",
		"e2e_coredns_container",
	).CombinedOutput()
	if err != nil {
		return fmt.Errorf("Couldn't remove the CoreDNS container: %s", err.Error())
	}

	_, err = exec.Command("docker",
		"container", "rm", "-f",
		"e2e_txtdirect_container",
	).CombinedOutput()
	if err != nil {
		return fmt.Errorf("Couldn't remove the TXTDirect container: %s", err.Error())
	}

	_, err = exec.Command("docker",
		"container", "rm", "-f",
		fmt.Sprintf("e2e_%s_container", d.dir),
	).CombinedOutput()
	if err != nil {
		return fmt.Errorf("Couldn't remove the tester container: %s", err.Error())
	}

	if strings.Contains(d.dir, "dockerv2") {
		_, err = exec.Command("docker",
			"network", "disconnect",
			"coretxtd",
			"registry",
		).CombinedOutput()
		if err != nil {
			return fmt.Errorf("Couldn't disconnect the Docker registry container: %s", err.Error())
		}
	}

	return nil
}

func (d *dockerManager) RunTesterContainer() error {
	_, err := user.Current()
	if err != nil {
		return fmt.Errorf("Couldn't get the current user: %s", err.Error())
	}

	// Create the tester container
	d.testerContainerLogs[d.dir], err = exec.Command("docker",
		"container", "run",
		// Mounted volumes
		"-v", fmt.Sprintf("%s/%s:/e2e", d.cdir, d.dir),
		"-v", fmt.Sprintf("%s:/go/pkg/mod", d.gomodpath),
		// DNS
		"--dns", "172.20.10.1",
		// Network
		"--network", "coretxtd",
		// Container Name
		"--name", fmt.Sprintf("e2e_%s_container", d.dir),
		testerImage,
		// CMD
		"go", "run", "main.go",
	).CombinedOutput()
	if err != nil {
		return fmt.Errorf("Couldn't create the tester container: %s", err.Error())
	}

	return nil
}

// ExamineLogs reads each tester container's logs and counts the failed and passed tests
func (d *dockerManager) ExamineLogs() error {
	for testCase, logs := range d.testerContainerLogs {
		log.Println(string(logs))
		// Stats slice order: [0: Full Log, 1: Total, 2: Passed, 3: Failed]
		stats := resultRegex.FindAllStringSubmatch(string(logs), -1)[0]
		if err := d.CountStats(stats); err != nil {
			return fmt.Errorf("Couldn't count the stats for \"%s\" test-case: %s", testCase, err.Error())
		}
	}
	log.Printf("Total Tests: %d, Total Passed Tests: %d, Total Failed Tests: %d", d.stats.total, d.stats.passed, d.stats.failed)
	return nil
}

func (d *dockerManager) CountStats(stats []string) error {
	total, err := strconv.Atoi(stats[1])
	if err != nil {
		return fmt.Errorf("Couldn't conver count of tests to int: %s", err.Error())
	}
	d.stats.total += total

	passed, err := strconv.Atoi(stats[2])
	if err != nil {
		return fmt.Errorf("Couldn't convert count of passed tests to int: %s", err.Error())
	}
	d.stats.passed += passed

	failed, err := strconv.Atoi(stats[3])
	if err != nil {
		return fmt.Errorf("Couldn't convert count of failed tests to int: %s", err.Error())
	}
	d.stats.failed += failed

	return nil
}

func (d *dockerManager) RemoveNetwork() error {
	_, err := exec.Command("docker",
		"network", "rm",
		"coretxtd",
	).CombinedOutput()
	if err != nil {
		return fmt.Errorf("Couldn't remove the network adaptor: %s", err.Error())
	}
	return nil
}

func (d *dockerManager) CreateNetwork() error {
	// Create a Docker network for containers
	_, err := exec.Command("docker", "network", "create", "--ip-range=\"172.20.10.0/24\"", "--subnet=\"172.20.0.0/16\"", "coretxtd").CombinedOutput()
	if err != nil {
		return fmt.Errorf("Couldn't create the network adaptor: %s", err.Error())
	}
	return nil
}

// PushTestImage connects the registry to network adaptor and pushes
// a testing image to the registry
func (d *dockerManager) PushTestImage() error {
	// Connect registry to the network adaptor
	_, err := exec.Command("docker", "network", "connect", "coretxtd", "registry").CombinedOutput()
	if err != nil {
		return fmt.Errorf("Couldn't connect Docker registry the network adaptor: %s", err.Error())
	}

	// Tag TXTDirect's image to use in custom registry
	_, err = exec.Command("docker", "tag", txtdirectImage, "172.20.10.3:5000/txtdirect").CombinedOutput()
	if err != nil {
		return fmt.Errorf("Couldn't tag image to use in custom Docker registry: %s", err.Error())
	}

	// Export the image to a tarball
	_, err = exec.Command("docker", "save", "172.20.10.3:5000/txtdirect:latest", "-o", "txtdirect.tar").CombinedOutput()
	if err != nil {
		return fmt.Errorf("Couldn't export the image into a tarball: %s", err.Error())
	}

	// Push the TXTDirect image to the custom registry
	_, err = exec.Command("crane", "push", "txtdirect.tar", "172.20.10.3:5000/txtdirect").CombinedOutput()
	if err != nil {
		return fmt.Errorf("Couldn't push the image to the custom Docker registry: %s", err.Error())
	}

	// Remove the tarball after the push
	_, err = exec.Command("rm", "./txtdirect.tar").CombinedOutput()
	if err != nil {
		return fmt.Errorf("Couldn't remove the image tarball: %s", err.Error())
	}

	return nil
}
<commit_msg>(e2e): Remove debugging logs<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"os/user"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
)

const (
	corednsImage = "k8s.gcr.io/coredns:1.6.2"
	testerImage  = "c.txtdirect.org/tester:dirty"
)

var txtdirectImage = fmt.Sprintf("c.txtdirect.org/txtdirect:%s", os.Getenv("VERSION"))

var resultRegex = regexp.MustCompile("Total:+\\s(\\d+),\\sPassed:+\\s(\\d+),\\sFailed:+\\s(\\d+)")

type dockerManager struct {
	dir       string
	cdir      string
	gomodpath string

	testerContainerLogs map[string][]byte

	stats struct {
		total  int
		passed int
		failed int
	}
}

func main() {
	d := dockerManager{
		testerContainerLogs: make(map[string][]byte),
	}

	if err := d.CheckClient(); err != nil {
		log.Fatalf("[txtdirect_e2e]: Docker daemon didn't respond to client: %s", err)
	}

	var directories []string
	if err := listDirectories(&directories); err != nil {
		log.Printf("[txtdirect_e2e]: Couldn't list the test directories: %s", err.Error())
	}

	if err := d.CreateNetwork(); err != nil {
		log.Fatalf("[txtdirect_e2e]: Couldn't create the network adaptor: %s", err.Error())
	}

	// Run the tests for each test-case
	for _, directory := range directories {
		// Start the CoreDNS and TXTDirect containers for test-case
		d.dir = directory

		if err := d.StartContainers(); err != nil {
			log.Fatalf("[txtdirect_e2e]: Couldn't start containers: %s", err.Error())
		}

		if err := d.RunTesterContainer(); err != nil {
			log.Fatalf("[txtdirect_e2e]: Couldn't run the tests in container: %s", err.Error())
		}

		if err := d.StopContainers(); err != nil {
			log.Fatalf("[txtdirect_e2e]: Couldn't stop containers: %s", err.Error())
		}
	}

	if err := d.ExamineLogs(); err != nil {
		log.Fatalf("[txtdirect_e2e]: Couldn't examine the logs and count the stats: %s", err.Error())
	}

	if err := d.RemoveNetwork(); err != nil {
		log.Fatalf("[txtdirect_e2e]: Couldn't remove the network adaptor: %s", err.Error())
	}

	if d.stats.failed != 0 {
		log.Fatalf("[txtdirect_e2e]: Tests failed because there were %d failed tests.", d.stats.failed)
	}
}

func listDirectories(directories *[]string) error {
	return filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return fmt.Errorf("Couldn't find the directory %q: %s", path, err.Error())
		}
		if info.IsDir() && path != "." {
			*directories = append(*directories, path)
			return filepath.SkipDir
		}
		return nil
	})
}

// CheckClient calls the "docker info" command to check if Docker daemon and CLI exist
func (d *dockerManager) CheckClient() error {
	_, err := exec.Command("docker", "info").CombinedOutput()
	if err != nil {
		return fmt.Errorf("Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?")
	}

	return nil
}

// StartContainers starts a CoreDNS and a TXTDirect container for each test-case
func (d *dockerManager) StartContainers() error {
	// Get current working directory to create mountpoint to containers for test-case data
	var err error
	d.cdir, err = os.Getwd()
	if err != nil {
		return fmt.Errorf("Couldn't get the current working directory: %s", err.Error())
	}

	// Fetch GOPATH for mounting /go/pkg/mod volumes
	if os.Getenv("GOPATH") == "" {
		return fmt.Errorf("$GOPATH is empty")
	}
	d.gomodpath = fmt.Sprintf("%s/pkg/mod", os.Getenv("GOPATH"))

	// Create the CoreDNS container
	_, err = exec.Command("docker",
		"container", "run",
		"-d",
		// Exposed Ports
		"-p", "53:53",
		// Mounted volumes
		"-v", fmt.Sprintf("%s/%s:/e2e", d.cdir, d.dir),
		"-v", fmt.Sprintf("%s:/go/pkg/mod", d.gomodpath),
		// Network
		"--network", "coretxtd",
		// Container Name
		"--name", "e2e_coredns_container",
		corednsImage,
		// CMD
		"-conf",
		"/e2e/Corefile",
	).CombinedOutput()
	if err != nil {
		return fmt.Errorf("Couldn't create the CoreDNS container: %s", err.Error())
	}

	// Create the TXTDirect container
	_, err = exec.Command("docker",
		"container", "run",
		"-d",
		// Exposed Ports
		"-p", "80:80",
		// Mounted volumes
		"-v", fmt.Sprintf("%s/%s:/e2e", d.cdir, d.dir),
		"-v", fmt.Sprintf("%s:/go/pkg/mod", d.gomodpath),
		// Network
		"--network", "coretxtd",
		// Container Name
		"--name", "e2e_txtdirect_container",
		txtdirectImage,
		// CMD
		"-conf",
		"/e2e/txtdirect.config",
	).CombinedOutput()
	if err != nil {
		return fmt.Errorf("Couldn't create the TXTDirect container: %s", err.Error())
	}

	// Push the test image to the testing Docker registry
	if strings.Contains(d.dir, "dockerv2") {
		if err := d.PushTestImage(); err != nil {
			return err
		}
	}

	return nil
}

func (d *dockerManager) StopContainers() error {
	_, err := exec.Command("docker",
		"container", "rm", "-f",
		"e2e_coredns_container",
	).CombinedOutput()
	if err != nil {
		return fmt.Errorf("Couldn't remove the CoreDNS container: %s", err.Error())
	}

	_, err = exec.Command("docker",
		"container", "rm", "-f",
		"e2e_txtdirect_container",
	).CombinedOutput()
	if err != nil {
		return fmt.Errorf("Couldn't remove the TXTDirect container: %s", err.Error())
	}

	_, err = exec.Command("docker",
		"container", "rm", "-f",
		fmt.Sprintf("e2e_%s_container", d.dir),
	).CombinedOutput()
	if err != nil {
		return fmt.Errorf("Couldn't remove the tester container: %s", err.Error())
	}

	if strings.Contains(d.dir, "dockerv2") {
		_, err = exec.Command("docker",
			"network", "disconnect",
			"coretxtd",
			"registry",
		).CombinedOutput()
		if err != nil {
			return fmt.Errorf("Couldn't disconnect the Docker registry container: %s", err.Error())
		}
	}

	return nil
}

func (d *dockerManager) RunTesterContainer() error {
	_, err := user.Current()
	if err != nil {
		return fmt.Errorf("Couldn't get the current user: %s", err.Error())
	}

	// Create the tester container
	d.testerContainerLogs[d.dir], err = exec.Command("docker",
		"container", "run",
		// Mounted volumes
		"-v", fmt.Sprintf("%s/%s:/e2e", d.cdir, d.dir),
		"-v", fmt.Sprintf("%s:/go/pkg/mod", d.gomodpath),
		// DNS
		"--dns", "172.20.10.1",
		// Network
		"--network", "coretxtd",
		// Container Name
		"--name", fmt.Sprintf("e2e_%s_container", d.dir),
		testerImage,
		// CMD
		"go", "run", "main.go",
	).CombinedOutput()
	if err != nil {
		return fmt.Errorf("Couldn't create the tester container: %s", err.Error())
	}

	return nil
}

// ExamineLogs reads each tester container's logs and counts the failed and passed tests
func (d *dockerManager) ExamineLogs() error {
	for testCase, logs := range d.testerContainerLogs {
		log.Println(string(logs))
		// Stats slice order: [0: Full Log, 1: Total, 2: Passed, 3: Failed]
		stats := resultRegex.FindAllStringSubmatch(string(logs), -1)[0]
		if err := d.CountStats(stats); err != nil {
			return fmt.Errorf("Couldn't count the stats for \"%s\" test-case: %s", testCase, err.Error())
		}
	}
	log.Printf("Total Tests: %d, Total Passed Tests: %d, Total Failed Tests: %d", d.stats.total, d.stats.passed, d.stats.failed)
	return nil
}

func (d *dockerManager) CountStats(stats []string) error {
	total, err := strconv.Atoi(stats[1])
	if err != nil {
		return fmt.Errorf("Couldn't conver count of tests to int: %s", err.Error())
	}
	d.stats.total += total

	passed, err := strconv.Atoi(stats[2])
	if err != nil {
		return fmt.Errorf("Couldn't convert count of passed tests to int: %s", err.Error())
	}
	d.stats.passed += passed

	failed, err := strconv.Atoi(stats[3])
	if err != nil {
		return fmt.Errorf("Couldn't convert count of failed tests to int: %s", err.Error())
	}
	d.stats.failed += failed

	return nil
}

func (d *dockerManager) RemoveNetwork() error {
	_, err := exec.Command("docker",
		"network", "rm",
		"coretxtd",
	).CombinedOutput()
	if err != nil {
		return fmt.Errorf("Couldn't remove the network adaptor: %s", err.Error())
	}
	return nil
}

func (d *dockerManager) CreateNetwork() error {
	// Create a Docker network for containers
	_, err := exec.Command("docker", "network", "create", "--ip-range=\"172.20.10.0/24\"", "--subnet=\"172.20.0.0/16\"", "coretxtd").CombinedOutput()
	if err != nil {
		return fmt.Errorf("Couldn't create the network adaptor: %s", err.Error())
	}
	return nil
}

// PushTestImage connects the registry to network adaptor and pushes
// a testing image to the registry
func (d *dockerManager) PushTestImage() error {
	// Connect registry to the network adaptor
	_, err := exec.Command("docker", "network", "connect", "coretxtd", "registry").CombinedOutput()
	if err != nil {
		return fmt.Errorf("Couldn't connect Docker registry the network adaptor: %s", err.Error())
	}

	// Tag TXTDirect's image to use in custom registry
	_, err = exec.Command("docker", "tag", txtdirectImage, "172.20.10.3:5000/txtdirect").CombinedOutput()
	if err != nil {
		return fmt.Errorf("Couldn't tag image to use in custom Docker registry: %s", err.Error())
	}

	// Export the image to a tarball
	_, err = exec.Command("docker", "save", "172.20.10.3:5000/txtdirect:latest", "-o", "txtdirect.tar").CombinedOutput()
	if err != nil {
		return fmt.Errorf("Couldn't export the image into a tarball: %s", err.Error())
	}

	// Push the TXTDirect image to the custom registry
	_, err = exec.Command("crane", "push", "txtdirect.tar", "172.20.10.3:5000/txtdirect").CombinedOutput()
	if err != nil {
		return fmt.Errorf("Couldn't push the image to the custom Docker registry: %s", err.Error())
	}

	// Remove the tarball after the push
	_, err = exec.Command("rm", "./txtdirect.tar").CombinedOutput()
	if err != nil {
		return fmt.Errorf("Couldn't remove the image tarball: %s", err.Error())
	}

	return nil
}
<|endoftext|>


<commit_before>package cc1101

import (
	"bytes"
	"log"

	"github.com/ecc1/radio"
)

const (
	hwVersion = 0x0014
)

type hwFlavor struct{}

// Name returns the radio's name.
func (f hwFlavor) Name() string {
	return "CC1101"
}

// SPIDevice returns the pathname of the radio's SPI device.
func (f hwFlavor) SPIDevice() string {
	return spiDevice
}

// Speed returns the radio's SPI speed.
func (f hwFlavor) Speed() int {
	return spiSpeed
}

// CustomCS returns the GPIO pin number to use as a custom chip-select for the radio.
func (f hwFlavor) CustomCS() int {
	return customCS
}

// InterruptPin returns the GPIO pin number to use for receive interrupts.
func (f hwFlavor) InterruptPin() int {
	return interruptPin
}

// ReadSingleAddress returns the encoding of an address for SPI read operations.
func (f hwFlavor) ReadSingleAddress(addr byte) byte {
	return READ_MODE | addr
}

// ReadBurstAddress returns the encoding of an address for SPI burst-read operations.
func (f hwFlavor) ReadBurstAddress(addr byte) byte {
	reg := addr & 0x3F
	if 0x30 <= reg && reg <= 0x3D {
		log.Panicf("no burst access for CC1101 status register %02X", reg)
	}
	return READ_MODE | BURST_MODE | addr
}

// WriteSingleAddress returns the (identity) encoding of an address for SPI write operations.
func (f hwFlavor) WriteSingleAddress(addr byte) byte {
	return addr
}

// WriteBurstAddress returns the encoding of an address for SPI burst-write operations.
func (f hwFlavor) WriteBurstAddress(addr byte) byte {
	return BURST_MODE | addr
}

// Radio represents an open radio device.
type Radio struct {
	hw            *radio.Hardware
	receiveBuffer bytes.Buffer
	stats         radio.Statistics
	err           error
}

// Open opens the radio device.
func Open() *Radio {
	r := &Radio{hw: radio.Open(hwFlavor{})}
	v := r.Version()
	if r.Error() != nil {
		return r
	}
	if v != hwVersion {
		r.hw.Close()
		r.SetError(radio.HardwareVersionError{Actual: v, Expected: hwVersion})
		return r
	}
	return r
}

// Close closes the radio device.
func (r *Radio) Close() {
	r.changeState(SIDLE, STATE_IDLE)
	r.hw.Close()
}

// Version returns the radio's hardware version.
func (r *Radio) Version() uint16 {
	p := r.hw.ReadRegister(PARTNUM)
	v := r.hw.ReadRegister(VERSION)
	return uint16(p)<<8 | uint16(v)
}

// Strobe writes the given command to the radio.
func (r *Radio) Strobe(cmd byte) byte {
	if verbose && cmd != SNOP {
		log.Printf("issuing %s command", strobeName(cmd))
	}
	buf := []byte{cmd}
	r.err = r.hw.SPIDevice().Transfer(buf)
	return buf[0]
}

// Reset resets the radio device.
func (r *Radio) Reset() {
	r.Strobe(SRES)
}

// Init initializes the radio device.
func (r *Radio) Init(frequency uint32) {
	r.Reset()
	r.InitRF(frequency)
}

// Statistics returns the byte and packet counts for the radio device.
func (r *Radio) Statistics() radio.Statistics {
	return r.stats
}

// Error returns the error state of the radio device.
func (r *Radio) Error() error {
	err := r.hw.Error()
	if err != nil {
		return err
	}
	return r.err
}

// SetError sets the error state of the radio device.
func (r *Radio) SetError(err error) {
	r.hw.SetError(err)
	r.err = err
}

// Hardware returns the radio's hardware information.
func (r *Radio) Hardware() *radio.Hardware {
	return r.hw
}
<commit_msg>Add Name and Device methods<commit_after>package cc1101

import (
	"bytes"
	"log"

	"github.com/ecc1/radio"
)

const (
	hwVersion = 0x0014
)

type hwFlavor struct{}

// SPIDevice returns the pathname of the radio's SPI device.
func (f hwFlavor) SPIDevice() string {
	return spiDevice
}

// Speed returns the radio's SPI speed.
func (f hwFlavor) Speed() int {
	return spiSpeed
}

// CustomCS returns the GPIO pin number to use as a custom chip-select for the radio.
func (f hwFlavor) CustomCS() int {
	return customCS
}

// InterruptPin returns the GPIO pin number to use for receive interrupts.
func (f hwFlavor) InterruptPin() int {
	return interruptPin
}

// ReadSingleAddress returns the encoding of an address for SPI read operations.
func (f hwFlavor) ReadSingleAddress(addr byte) byte {
	return READ_MODE | addr
}

// ReadBurstAddress returns the encoding of an address for SPI burst-read operations.
func (f hwFlavor) ReadBurstAddress(addr byte) byte {
	reg := addr & 0x3F
	if 0x30 <= reg && reg <= 0x3D {
		log.Panicf("no burst access for CC1101 status register %02X", reg)
	}
	return READ_MODE | BURST_MODE | addr
}

// WriteSingleAddress returns the (identity) encoding of an address for SPI write operations.
func (f hwFlavor) WriteSingleAddress(addr byte) byte {
	return addr
}

// WriteBurstAddress returns the encoding of an address for SPI burst-write operations.
func (f hwFlavor) WriteBurstAddress(addr byte) byte {
	return BURST_MODE | addr
}

// Radio represents an open radio device.
type Radio struct {
	hw            *radio.Hardware
	receiveBuffer bytes.Buffer
	stats         radio.Statistics
	err           error
}

// Open opens the radio device.
func Open() *Radio {
	r := &Radio{hw: radio.Open(hwFlavor{})}
	v := r.Version()
	if r.Error() != nil {
		return r
	}
	if v != hwVersion {
		r.hw.Close()
		r.SetError(radio.HardwareVersionError{Actual: v, Expected: hwVersion})
		return r
	}
	return r
}

// Close closes the radio device.
func (r *Radio) Close() {
	r.changeState(SIDLE, STATE_IDLE)
	r.hw.Close()
}

// Version returns the radio's hardware version.
func (r *Radio) Version() uint16 {
	p := r.hw.ReadRegister(PARTNUM)
	v := r.hw.ReadRegister(VERSION)
	return uint16(p)<<8 | uint16(v)
}

// Name returns the radio's name.
func (r *Radio) Name() string {
	return "CC1101"
}

// Device returns the pathname of the radio's device.
func (r *Radio) Device() string {
	return spiDevice
}

// Strobe writes the given command to the radio.
func (r *Radio) Strobe(cmd byte) byte {
	if verbose && cmd != SNOP {
		log.Printf("issuing %s command", strobeName(cmd))
	}
	buf := []byte{cmd}
	r.err = r.hw.SPIDevice().Transfer(buf)
	return buf[0]
}

// Reset resets the radio device.
func (r *Radio) Reset() {
	r.Strobe(SRES)
}

// Init initializes the radio device.
func (r *Radio) Init(frequency uint32) {
	r.Reset()
	r.InitRF(frequency)
}

// Statistics returns the byte and packet counts for the radio device.
func (r *Radio) Statistics() radio.Statistics {
	return r.stats
}

// Error returns the error state of the radio device.
func (r *Radio) Error() error {
	err := r.hw.Error()
	if err != nil {
		return err
	}
	return r.err
}

// SetError sets the error state of the radio device.
func (r *Radio) SetError(err error) {
	r.hw.SetError(err)
	r.err = err
}

// Hardware returns the radio's hardware information.
func (r *Radio) Hardware() *radio.Hardware {
	return r.hw
}
<|endoftext|>


<commit_before>package ike

import (
	"context"
	"net"
	"testing"

	"github.com/msgboxio/ike/platform"
)

var pskId = &PskIdentities{
	Primary: "ak@msgbox.io",
	Ids:     map[string][]byte{"ak@msgbox.io": []byte("foo")},
}

var cfg = DefaultConfig()
var localAddr, remoteAddr net.Addr

func saInstaller(ch chan *platform.SaParams) SaCallback {
	return func(sa *platform.SaParams) error {
		ch <- sa
		return nil
	}
}
func saRemover(sa *platform.SaParams) error {
	return nil
}
func packetWriter(ch chan []byte) WriteData {
	return func(reply []byte) error {
		ch <- reply
		return nil
	}
}

func TestIntPsk(t *testing.T) {
	testWithIdentity(t, pskId, pskId)
}

func TestIntCert(t *testing.T) {
	roots, err := LoadRoot("test/cert/cacert.pem")
	if err != nil {
		t.Fatal(err)
	}
	certs, err := LoadCerts("test/cert/hostcert.der")
	if err != nil {
		t.Fatalf("Cert: %s", err)
	}
	key, err := LoadKey("test/cert/hostkey.der")
	if err != nil {
		t.Fatalf("Key: %s", err)
	}

	localID := &CertIdentity{
		Certificate: certs[0],
		PrivateKey:  key,
	}
	remoteID := &CertIdentity{
		Roots: roots,
	}
	testWithIdentity(t, localID, remoteID)
}

func testWithIdentity(t *testing.T, locid, remid Identity) {
	_, net, _ := net.ParseCIDR("192.0.2.0/24")
	cfg.AddSelector(net, net)
	chi := make(chan []byte, 1)
	chr := make(chan []byte, 1)
	sa := make(chan *platform.SaParams, 1)

	// create initiator
	initiator := NewInitiator(context.Background(), locid, remid, remoteAddr, localAddr, cfg)
	go initiator.Run(packetWriter(chi), saInstaller(sa), saRemover)
	initI, err := DecodeMessage(<-chi)
	if err != nil {
		t.Fatal(err)
	}
	// create responder
	responder, err := NewResponder(context.Background(), locid, remid, cfg, initI)
	if err != nil {
		t.Fatal(err)
	}
	go responder.Run(packetWriter(chr), saInstaller(sa), saRemover)
	// init to responder
	responder.PostMessage(initI)
	initR, err := DecodeMessage(<-chr)
	if err != nil {
		t.Fatal(err)
	}
	// init to initiator
	SetInitiatorParameters(initiator, initR)
	initiator.PostMessage(initR)
	authI, err := DecodeMessage(<-chi)
	if err != nil {
		t.Fatal(err)
	}
	// auth to responder
	responder.PostMessage(authI)
	authR, err := DecodeMessage(<-chr)
	if err != nil {
		t.Fatal(err)
	}
	// auth to initiator
	initiator.PostMessage(authR)
	// receive the 2 sa
	sa1 := <-sa
	sa2 := <-sa
	t.Logf("sa1: %+v", *sa1)
	t.Logf("sa2: %+v", *sa2)
}

// server, serverIP := test.SetupContainer(t, "min", 5000, 100, func() (string, error) {
// return test.RunContainer("--rm", "--privileged", "--name", "cli", "-v",
// dir+"/server:/server", "min", "/server", "-local", "0.0.0.0:500", "-v", "2", "-tunnel")
// })
<commit_msg>seperated initiator & responder machines for test<commit_after>package ike

import (
	"context"
	"net"
	"testing"

	"github.com/msgboxio/ike/platform"
)

var pskId = &PskIdentities{
	Primary: "ak@msgbox.io",
	Ids:     map[string][]byte{"ak@msgbox.io": []byte("foo")},
}

var cfg = DefaultConfig()
var localAddr, remoteAddr net.Addr

func saInstaller(ch chan *platform.SaParams) SaCallback {
	return func(sa *platform.SaParams) error {
		ch <- sa
		return nil
	}
}
func saRemover(sa *platform.SaParams) error {
	return nil
}
func packetWriter(ch chan []byte) WriteData {
	return func(reply []byte) error {
		ch <- reply
		return nil
	}
}

func TestIntPsk(t *testing.T) {
	testWithIdentity(t, pskId, pskId)
}

func TestIntCert(t *testing.T) {
	roots, err := LoadRoot("test/cert/cacert.pem")
	if err != nil {
		t.Fatal(err)
	}
	certs, err := LoadCerts("test/cert/hostcert.der")
	if err != nil {
		t.Fatalf("Cert: %s", err)
	}
	key, err := LoadKey("test/cert/hostkey.der")
	if err != nil {
		t.Fatalf("Key: %s", err)
	}

	localID := &CertIdentity{
		Certificate: certs[0],
		PrivateKey:  key,
	}
	remoteID := &CertIdentity{
		Roots: roots,
	}
	testWithIdentity(t, localID, remoteID)
}

func runInitiator(t *testing.T, readFrom <-chan []byte, locid, remid Identity, onSa SaCallback, writeTo WriteData) {
	initiator := NewInitiator(context.Background(), locid, remid, remoteAddr, localAddr, cfg)
	initiator.AddSaHandlers(onSa, saRemover)
	// run state machine, will send initI on given channel
	go initiator.Run(writeTo)
	// wait for initR
	initR, err := DecodeMessage(<-readFrom)
	if err != nil {
		t.Fatal(err)
	}
	// use initR
	SetInitiatorParameters(initiator, initR)
	// process initR, send authI
	initiator.PostMessage(initR)
	// wait for auhtR
	authR, err := DecodeMessage(<-readFrom)
	if err != nil {
		t.Fatal(err)
	}
	// process authR
	initiator.PostMessage(authR)
}

func runResponder(t *testing.T, readFrom <-chan []byte, locid, remid Identity, onSa SaCallback, writeTo WriteData) {
	// wait for initI
	initI, err := DecodeMessage(<-readFrom)
	if err != nil {
		t.Fatal(err)
	}
	// create responder
	responder, err := NewResponder(context.Background(), locid, remid, cfg, initI)
	if err != nil {
		t.Fatal(err)
	}
	go responder.Run(writeTo)
	responder.AddSaHandlers(onSa, saRemover)
	// initI to responder, will send initR
	responder.PostMessage(initI)
	// wait for authI
	authI, err := DecodeMessage(<-readFrom)
	if err != nil {
		t.Fatal(err)
	}
	// authI to responder, will send authR
	responder.PostMessage(authI)
}

func testWithIdentity(t *testing.T, locid, remid Identity) {
	_, net, _ := net.ParseCIDR("192.0.2.0/24")
	cfg.AddSelector(net, net)
	chi := make(chan []byte, 1)
	chr := make(chan []byte, 1)
	sa := make(chan *platform.SaParams, 1)

	go runInitiator(t, chi, locid, remid, saInstaller(sa), packetWriter(chr))
	go runResponder(t, chr, locid, remid, saInstaller(sa), packetWriter(chi))

	// receive the 2 sa
	sa1 := <-sa
	sa2 := <-sa
	t.Logf("sa1: %+v", *sa1)
	t.Logf("sa2: %+v", *sa2)
}

// server, serverIP := test.SetupContainer(t, "min", 5000, 100, func() (string, error) {
// return test.RunContainer("--rm", "--privileged", "--name", "cli", "-v",
// dir+"/server:/server", "min", "/server", "-local", "0.0.0.0:500", "-v", "2", "-tunnel")
// })
<|endoftext|>


<commit_before>package logreg

import "testing"

func TestNewLogisticRegression(t *testing.T) {
	if lr := NewLogisticRegression(); lr == nil {
		t.Errorf("got nil linear regression")
	}
}
<commit_msg>add logreg initialize 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])
		}
	}
}
<|endoftext|>


<commit_before>package id3v2

import (
	xencoding "golang.org/x/text/encoding"
	"golang.org/x/text/encoding/charmap"
	"golang.org/x/text/encoding/unicode"
)

// Encoding is a struct for encodings.
type Encoding struct {
	Name             string
	Key              byte
	TerminationBytes []byte
}

func (e Encoding) Equals(other Encoding) bool {
	return e.Key == other.Key
}

func (e Encoding) String() string {
	return e.Name
}

// Available encodings.
var (
	// EncodingISO is ISO-8859-1 encoding.
	EncodingISO = Encoding{
		Name:             "ISO-8859-1",
		Key:              0,
		TerminationBytes: []byte{0},
	}

	// EncodingUTF16 is UTF-16 encoded Unicode with BOM.
	EncodingUTF16 = Encoding{
		Name:             "UTF-16 encoded Unicode with BOM",
		Key:              1,
		TerminationBytes: []byte{0, 0},
	}

	// EncodingUTF16BE is UTF-16BE encoded Unicode without BOM.
	EncodingUTF16BE = Encoding{
		Name:             "UTF-16BE encoded Unicode without BOM",
		Key:              2,
		TerminationBytes: []byte{0, 0},
	}

	// EncodingUTF8 is UTF-8 encoded Unicode.
	EncodingUTF8 = Encoding{
		Name:             "UTF-8 encoded Unicode",
		Key:              3,
		TerminationBytes: []byte{0},
	}

	encodings = []Encoding{EncodingISO, EncodingUTF16, EncodingUTF16BE, EncodingUTF8}
)

// getEncoding returns Encoding in accordance with ID3v2 key.
func getEncoding(key byte) Encoding {
	if key > 3 {
		return EncodingUTF8
	}
	return encodings[key]
}

// encodedSize counts length of UTF-8 src if it's encoded to enc.
func encodedSize(src string, enc Encoding) int {
	if enc.Equals(EncodingUTF8) {
		return len(src)
	}

	toXEncoding := resolveXEncoding(nil, enc)
	encoded, _ := toXEncoding.NewEncoder().String(src)
	return len(encoded)
}

// decodeText decodes src from "from" encoding to UTF-8.
func decodeText(src []byte, from Encoding) string {
	if from.Equals(EncodingUTF8) {
		return string(src)
	}

	fromXEncoding := resolveXEncoding(src, from)
	dst, err := fromXEncoding.NewDecoder().Bytes(src)
	if err != nil {
		return string(src)
	}

	return string(dst)
}

// encodeWriteText encodes src from UTF-8 to "to" encoding and writes to bw.
func encodeWriteText(bw *bufWriter, src string, to Encoding) error {
	if to.Equals(EncodingUTF8) {
		bw.WriteString(src)
		return nil
	}

	toXEncoding := resolveXEncoding(nil, to)
	encoded, err := toXEncoding.NewEncoder().String(src)
	if err != nil {
		return err
	}
	bw.WriteString(encoded)
	return nil
}

// resolveXEncoding returns golang.org/x/text/encoding encoding
// from src and encoding.
func resolveXEncoding(src []byte, encoding Encoding) xencoding.Encoding {
	switch encoding.Key {
	case 0: // ISO-8859-1
		return charmap.ISO8859_1
	case 1: // UTF-16 With BOM
		if len(src) < 2 {
			return unicode.UTF16(unicode.BigEndian, unicode.ExpectBOM)
		} else if src[0] == 0xFE && src[1] == 0xFF {
			return unicode.UTF16(unicode.BigEndian, unicode.ExpectBOM)
		} else if src[0] == 0xFF && src[1] == 0xFE {
			return unicode.UTF16(unicode.LittleEndian, unicode.ExpectBOM)
		}
		return unicode.UTF16(unicode.BigEndian, unicode.ExpectBOM)
	case 2: // UTF-16BE without BOM
		return unicode.UTF16(unicode.BigEndian, unicode.IgnoreBOM)
	case 3: // UTF-8
		return unicode.UTF8
	}

	return unicode.UTF8
}
<commit_msg>Reduce memory allocations in encoding operations<commit_after>package id3v2

import (
	xencoding "golang.org/x/text/encoding"
	"golang.org/x/text/encoding/charmap"
	"golang.org/x/text/encoding/unicode"
)

// Encoding is a struct for encodings.
type Encoding struct {
	Name             string
	Key              byte
	TerminationBytes []byte
}

func (e Encoding) Equals(other Encoding) bool {
	return e.Key == other.Key
}

func (e Encoding) String() string {
	return e.Name
}

// xencodingWrapper is a convient wrapper for xencoding.Encoding.
type xencodingWrapper struct {
	e       xencoding.Encoding
	decoder *xencoding.Decoder
	encoder *xencoding.Encoder
}

func newXEncodingWrapper(e xencoding.Encoding) xencodingWrapper {
	return xencodingWrapper{
		e:       e,
		decoder: e.NewDecoder(),
		encoder: e.NewEncoder(),
	}
}

func (e *xencodingWrapper) Decoder() *xencoding.Decoder {
	return e.decoder
}

func (e *xencodingWrapper) Encoder() *xencoding.Encoder {
	return e.encoder
}

// Available encodings.
var (
	// EncodingISO is ISO-8859-1 encoding.
	EncodingISO = Encoding{
		Name:             "ISO-8859-1",
		Key:              0,
		TerminationBytes: []byte{0},
	}

	// EncodingUTF16 is UTF-16 encoded Unicode with BOM.
	EncodingUTF16 = Encoding{
		Name:             "UTF-16 encoded Unicode with BOM",
		Key:              1,
		TerminationBytes: []byte{0, 0},
	}

	// EncodingUTF16BE is UTF-16BE encoded Unicode without BOM.
	EncodingUTF16BE = Encoding{
		Name:             "UTF-16BE encoded Unicode without BOM",
		Key:              2,
		TerminationBytes: []byte{0, 0},
	}

	// EncodingUTF8 is UTF-8 encoded Unicode.
	EncodingUTF8 = Encoding{
		Name:             "UTF-8 encoded Unicode",
		Key:              3,
		TerminationBytes: []byte{0},
	}

	encodings = []Encoding{EncodingISO, EncodingUTF16, EncodingUTF16BE, EncodingUTF8}

	xencodingISO        = newXEncodingWrapper(charmap.ISO8859_1)
	xencodingUTF16BEBOM = newXEncodingWrapper(unicode.UTF16(unicode.BigEndian, unicode.ExpectBOM))
	xencodingUTF16LEBOM = newXEncodingWrapper(unicode.UTF16(unicode.LittleEndian, unicode.ExpectBOM))
	xencodingUTF16BE    = newXEncodingWrapper(unicode.UTF16(unicode.BigEndian, unicode.IgnoreBOM))
	xencodingUTF8       = newXEncodingWrapper(unicode.UTF8)
)

// getEncoding returns Encoding in accordance with ID3v2 key.
func getEncoding(key byte) Encoding {
	if key > 3 {
		return EncodingUTF8
	}
	return encodings[key]
}

// encodedSize counts length of UTF-8 src if it's encoded to enc.
func encodedSize(src string, enc Encoding) int {
	if enc.Equals(EncodingUTF8) {
		return len(src)
	}

	toXEncoding := resolveXEncoding(nil, enc)
	encoded, _ := toXEncoding.Encoder().String(src)
	return len(encoded)
}

// decodeText decodes src from "from" encoding to UTF-8.
func decodeText(src []byte, from Encoding) string {
	if from.Equals(EncodingUTF8) {
		return string(src)
	}

	fromXEncoding := resolveXEncoding(src, from)
	result, err := fromXEncoding.Decoder().Bytes(src)
	if err != nil {
		return string(src)
	}
	return string(result)
}

// encodeWriteText encodes src from UTF-8 to "to" encoding and writes to bw.
func encodeWriteText(bw *bufWriter, src string, to Encoding) error {
	if to.Equals(EncodingUTF8) {
		bw.WriteString(src)
		return nil
	}

	toXEncoding := resolveXEncoding(nil, to)
	encoded, err := toXEncoding.Encoder().String(src)
	if err != nil {
		return err
	}
	bw.WriteString(encoded)
	return nil
}

func resolveXEncoding(src []byte, encoding Encoding) xencodingWrapper {
	switch encoding.Key {
	case 0:
		return xencodingISO
	case 1:
		if len(src) > 2 && src[0] == 0xFF && src[1] == 0xFE {
			return xencodingUTF16LEBOM
		}
		return xencodingUTF16BEBOM
	case 2:
		return xencodingUTF16BE
	}

	return xencodingUTF8
}
<|endoftext|>


<commit_before>package logredis

import (
	"encoding/json"
	"fmt"
	"time"

	"github.com/garyburd/redigo/redis"
	"github.com/sirupsen/logrus"
)

// HookConfig stores configuration needed to setup the hook
type HookConfig struct {
	Key      string
	Format   string
	App      string
	Host     string
	Password string
	Hostname string
	Port     int
	DB       int
	TTL      int
}

// RedisHook to sends logs to Redis server
type RedisHook struct {
	RedisPool      *redis.Pool
	RedisHost      string
	RedisKey       string
	LogstashFormat string
	AppName        string
	Hostname       string
	RedisPort      int
	TTL            int
	DialOptions    []redis.DialOption
}

// NewHook creates a hook to be added to an instance of logger
func NewHook(config HookConfig, options ...redis.DialOption) (*RedisHook, error) {
	pool := newRedisConnectionPool(config.Host, config.Password, config.Port, config.DB, options...)

	if config.Format != "v0" && config.Format != "v1" && config.Format != "access" {
		return nil, fmt.Errorf("unknown message format")
	}

	// test if connection with REDIS can be established
	conn := pool.Get()
	defer conn.Close()

	// check connection
	_, err := conn.Do("PING")
	if err != nil {
		return nil, fmt.Errorf("unable to connect to REDIS: %s", err)
	}

	return &RedisHook{
		RedisHost:      config.Host,
		RedisPool:      pool,
		RedisKey:       config.Key,
		LogstashFormat: config.Format,
		AppName:        config.App,
		Hostname:       config.Hostname,
		TTL:            config.TTL,
		DialOptions:    options,
	}, nil

}

// Fire is called when a log event is fired.
func (hook *RedisHook) Fire(entry *logrus.Entry) error {
	var msg interface{}

	switch hook.LogstashFormat {
	case "v0":
		msg = createV0Message(entry, hook.AppName, hook.Hostname)
	case "v1":
		msg = createV1Message(entry, hook.AppName, hook.Hostname)
	case "access":
		msg = createAccessLogMessage(entry, hook.AppName, hook.Hostname)
	default:
		fmt.Println("Invalid LogstashFormat")
	}

	// Marshal into json message
	js, err := json.Marshal(msg)
	if err != nil {
		return fmt.Errorf("error creating message for REDIS: %s", err)
	}

	// get connection from pool
	conn := hook.RedisPool.Get()
	defer conn.Close()

	// send message
	_, err = conn.Do("RPUSH", hook.RedisKey, js)
	if err != nil {
		return fmt.Errorf("error sending message to REDIS: %s", err)
	}

	if hook.TTL != 0 {
		_, err = conn.Do("EXPIRE", hook.RedisKey, hook.TTL)
		if err != nil {
			return fmt.Errorf("error setting TTL to key: %s, %s", hook.RedisKey, err)
		}
	}

	return nil
}

// Levels returns the available logging levels.
func (hook *RedisHook) Levels() []logrus.Level {
	return []logrus.Level{
		logrus.TraceLevel,
		logrus.DebugLevel,
		logrus.InfoLevel,
		logrus.WarnLevel,
		logrus.ErrorLevel,
		logrus.FatalLevel,
		logrus.PanicLevel,
	}
}

func createV0Message(entry *logrus.Entry, appName, hostname string) map[string]interface{} {
	m := make(map[string]interface{})
	m["@timestamp"] = entry.Time.UTC().Format(time.RFC3339Nano)
	m["@source_host"] = hostname
	m["@message"] = entry.Message

	fields := make(map[string]interface{})
	fields["level"] = entry.Level.String()
	fields["application"] = appName

	for k, v := range entry.Data {
		fields[k] = v
	}
	m["@fields"] = fields

	return m
}

func createV1Message(entry *logrus.Entry, appName, hostname string) map[string]interface{} {
	m := make(map[string]interface{})
	m["@timestamp"] = entry.Time.UTC().Format(time.RFC3339Nano)
	m["host"] = hostname
	m["message"] = entry.Message
	m["level"] = entry.Level.String()
	m["application"] = appName
	for k, v := range entry.Data {
		m[k] = v
	}

	return m
}

func createAccessLogMessage(entry *logrus.Entry, appName, hostname string) map[string]interface{} {
	m := make(map[string]interface{})
	m["message"] = entry.Message
	m["@source_host"] = hostname

	fields := make(map[string]interface{})
	fields["application"] = appName

	for k, v := range entry.Data {
		fields[k] = v
	}
	m["@fields"] = fields

	return m
}

func newRedisConnectionPool(server, password string, port int, db int, options ...redis.DialOption) *redis.Pool {
	hostPort := fmt.Sprintf("%s:%d", server, port)
	return &redis.Pool{
		MaxIdle:     3,
		IdleTimeout: 240 * time.Second,
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial("tcp", hostPort, redis.DialDatabase(db), redis.DialPassword(password), options...)
			if err != nil {
				return nil, err
			}
			return c, err
		},
		TestOnBorrow: func(c redis.Conn, t time.Time) error {
			_, err := c.Do("PING")
			return err
		},
	}
}
<commit_msg>redis tls support<commit_after>package logredis

import (
	"encoding/json"
	"fmt"
	"time"

	"github.com/garyburd/redigo/redis"
	"github.com/sirupsen/logrus"
)

// HookConfig stores configuration needed to setup the hook
type HookConfig struct {
	Key      string
	Format   string
	App      string
	Host     string
	Password string
	Hostname string
	Port     int
	DB       int
	TTL      int
}

// RedisHook to sends logs to Redis server
type RedisHook struct {
	RedisPool      *redis.Pool
	RedisHost      string
	RedisKey       string
	LogstashFormat string
	AppName        string
	Hostname       string
	RedisPort      int
	TTL            int
	DialOptions    []redis.DialOption
}

// NewHook creates a hook to be added to an instance of logger
func NewHook(config HookConfig, options ...redis.DialOption) (*RedisHook, error) {
	pool := newRedisConnectionPool(config.Host, config.Password, config.Port, config.DB, options...)

	if config.Format != "v0" && config.Format != "v1" && config.Format != "access" {
		return nil, fmt.Errorf("unknown message format")
	}

	// test if connection with REDIS can be established
	conn := pool.Get()
	defer conn.Close()

	// check connection
	_, err := conn.Do("PING")
	if err != nil {
		return nil, fmt.Errorf("unable to connect to REDIS: %s", err)
	}

	return &RedisHook{
		RedisHost:      config.Host,
		RedisPool:      pool,
		RedisKey:       config.Key,
		LogstashFormat: config.Format,
		AppName:        config.App,
		Hostname:       config.Hostname,
		TTL:            config.TTL,
		DialOptions:    options,
	}, nil

}

// Fire is called when a log event is fired.
func (hook *RedisHook) Fire(entry *logrus.Entry) error {
	var msg interface{}

	switch hook.LogstashFormat {
	case "v0":
		msg = createV0Message(entry, hook.AppName, hook.Hostname)
	case "v1":
		msg = createV1Message(entry, hook.AppName, hook.Hostname)
	case "access":
		msg = createAccessLogMessage(entry, hook.AppName, hook.Hostname)
	default:
		fmt.Println("Invalid LogstashFormat")
	}

	// Marshal into json message
	js, err := json.Marshal(msg)
	if err != nil {
		return fmt.Errorf("error creating message for REDIS: %s", err)
	}

	// get connection from pool
	conn := hook.RedisPool.Get()
	defer conn.Close()

	// send message
	_, err = conn.Do("RPUSH", hook.RedisKey, js)
	if err != nil {
		return fmt.Errorf("error sending message to REDIS: %s", err)
	}

	if hook.TTL != 0 {
		_, err = conn.Do("EXPIRE", hook.RedisKey, hook.TTL)
		if err != nil {
			return fmt.Errorf("error setting TTL to key: %s, %s", hook.RedisKey, err)
		}
	}

	return nil
}

// Levels returns the available logging levels.
func (hook *RedisHook) Levels() []logrus.Level {
	return []logrus.Level{
		logrus.TraceLevel,
		logrus.DebugLevel,
		logrus.InfoLevel,
		logrus.WarnLevel,
		logrus.ErrorLevel,
		logrus.FatalLevel,
		logrus.PanicLevel,
	}
}

func createV0Message(entry *logrus.Entry, appName, hostname string) map[string]interface{} {
	m := make(map[string]interface{})
	m["@timestamp"] = entry.Time.UTC().Format(time.RFC3339Nano)
	m["@source_host"] = hostname
	m["@message"] = entry.Message

	fields := make(map[string]interface{})
	fields["level"] = entry.Level.String()
	fields["application"] = appName

	for k, v := range entry.Data {
		fields[k] = v
	}
	m["@fields"] = fields

	return m
}

func createV1Message(entry *logrus.Entry, appName, hostname string) map[string]interface{} {
	m := make(map[string]interface{})
	m["@timestamp"] = entry.Time.UTC().Format(time.RFC3339Nano)
	m["host"] = hostname
	m["message"] = entry.Message
	m["level"] = entry.Level.String()
	m["application"] = appName
	for k, v := range entry.Data {
		m[k] = v
	}

	return m
}

func createAccessLogMessage(entry *logrus.Entry, appName, hostname string) map[string]interface{} {
	m := make(map[string]interface{})
	m["message"] = entry.Message
	m["@source_host"] = hostname

	fields := make(map[string]interface{})
	fields["application"] = appName

	for k, v := range entry.Data {
		fields[k] = v
	}
	m["@fields"] = fields

	return m
}

func newRedisConnectionPool(server, password string, port int, db int, options ...redis.DialOption) *redis.Pool {
	hostPort := fmt.Sprintf("%s:%d", server, port)
	return &redis.Pool{
		MaxIdle:     3,
		IdleTimeout: 240 * time.Second,
		Dial: func() (redis.Conn, error) {
			dialOptions := append([]redis.DialOption{
				redis.DialDatabase(db),
				redis.DialPassword(password),
			}, options...)
			c, err := redis.Dial("tcp", hostPort, dialOptions...)
			if err != nil {
				return nil, err
			}
			return c, err
		},
		TestOnBorrow: func(c redis.Conn, t time.Time) error {
			_, err := c.Do("PING")
			return err
		},
	}
}
<|endoftext|>


<commit_before>package logutil

import (
	"fmt"
	"github.com/johnnylee/goutil/fileutil"
	"log"
	"os"
	"path/filepath"
)

type UtilLogger struct {
	msgLog *log.Logger
	errLog *log.Logger
}

func New(prefix string, pathElem ...string) (UtilLogger, error) {
	l := UtilLogger{
		log.New(os.Stderr, "", log.Ldate|log.Ltime),
		log.New(os.Stderr, "", log.Ldate|log.Ltime),
	}

	l.SetPrefix(prefix)
	err := l.UseFiles(pathElem...)
	return l, err
}

func (l UtilLogger) SetPrefix(prefix string) {
	l.msgLog.SetPrefix(prefix)
	l.errLog.SetPrefix(prefix)
}

func (l UtilLogger) UseFiles(pathElem ...string) (err error) {
	pathPrefix := fileutil.ExpandPath(pathElem...)

	// Make sure the directory exists.
	logDir := filepath.Dir(pathPrefix)
	if err = os.MkdirAll(logDir, 0777); err != nil {
		return err
	}

	// Output file paths.
	msgPath := pathPrefix + ".err.log"
	errPath := pathPrefix + ".msg.log"

	// Open the files.
	fMsg, err := os.OpenFile(msgPath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		return err
	}
	fErr, err := os.OpenFile(errPath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		return err
	}

	// Set output.
	l.msgLog.SetOutput(fMsg)
	l.errLog.SetOutput(fErr)
	return nil
}

func (l UtilLogger) LogMsg(format string, v ...interface{}) {
	l.msgLog.Printf(format, v...)
}

func (l UtilLogger) LogErr(err error, format string, v ...interface{}) {
	msg := fmt.Sprintf(format, v...)
	l.errLog.Printf("ERROR: %v:\n    %v\n", msg, err)
}
<commit_msg>Modified logging interface.<commit_after>package logutil

import (
	"fmt"
	"github.com/johnnylee/goutil/fileutil"
	"gopkg.in/natefinch/lumberjack.v2"
	"log"
	"os"
	"path/filepath"
)

func SetFilePath(pathElem ...string) (err error) {
	path := fileutil.ExpandPath(pathElem...)

	// Make sure the directory exists.
	logDir := filepath.Dir(path)
	if err = os.MkdirAll(logDir, 0777); err != nil {
		return err
	}

	// Set the output.
	log.SetOutput(&lumberjack.Logger{
		Filename: path,
		MaxSize:  100,
	})

	return nil
}

type Logger struct {
	prefix string
}

func New(prefix string) Logger {
	log.SetFlags(log.Ldate | log.Ltime)
	return Logger{fmt.Sprintf("[%v] ", prefix)}
}

func (l Logger) Msg(format string, v ...interface{}) {
	log.Printf(l.prefix+format+"\n", v...)
}

func (l Logger) Err(err error, format string, v ...interface{}) {
	msg := fmt.Sprintf(format, v...)
	if err != nil {
		log.Printf(l.prefix+"ERROR: %v:\n%v\n", msg, err)
	} else {
		log.Printf(l.prefix+"ERROR: %v\n", msg)
	}
}
<|endoftext|>


<commit_before>// Copyright Istio 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 manifests

import (
	"embed"
	"io/fs"
	"os"
)

// FS embeds the manifests
//go:embed charts/* profiles/*
//go:embed charts/gateways/istio-egress/templates/_affinity.tpl
//go:embed charts/gateways/istio-ingress/templates/_affinity.tpl
var FS embed.FS

var (
	_ fs.FS         = FS
	_ fs.ReadFileFS = FS
	_ fs.ReadDirFS  = FS
)

// BuiltinOrDir returns a FS for the provided directory. If no directory is passed, the compiled in
// FS will be used
func BuiltinOrDir(dir string) fs.FS {
	if dir == "" {
		return FS
	}
	return os.DirFS(dir)
}
<commit_msg>remove unnecessary type checks (#36787)<commit_after>// Copyright Istio 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 manifests

import (
	"embed"
	"io/fs"
	"os"
)

// FS embeds the manifests
//go:embed charts/* profiles/*
//go:embed charts/gateways/istio-egress/templates/_affinity.tpl
//go:embed charts/gateways/istio-ingress/templates/_affinity.tpl
var FS embed.FS

// BuiltinOrDir returns a FS for the provided directory. If no directory is passed, the compiled in
// FS will be used
func BuiltinOrDir(dir string) fs.FS {
	if dir == "" {
		return FS
	}
	return os.DirFS(dir)
}
<|endoftext|>


<commit_before>package smd

import (
	"math"
	"os"
	"time"

	"github.com/ChristopherRabotin/gokalman"
	"github.com/ChristopherRabotin/ode"
	kitlog "github.com/go-kit/kit/log"
	"github.com/gonum/matrix/mat64"
)

const (
	transitionPhiOnly = false
)

// OrbitEstimate is an ode.Integrable which allows to propagate an orbit via its initial estimate.
type OrbitEstimate struct {
	Φ      *mat64.Dense  // STM
	Orbit  Orbit         // estimated orbit
	Perts  Perturbations // perturbations to account for
	StopDT time.Time     // end time of te integration
	dt     time.Time     // current time of the integration
	step   time.Duration // time step
	logger kitlog.Logger // logger
}

// GetState gets the state.
func (e *OrbitEstimate) GetState() []float64 {
	rΦ, cΦ := e.Φ.Dims()
	s := make([]float64, 6+rΦ*cΦ)
	R, V := e.Orbit.RV()
	s[0] = R[0]
	s[1] = R[1]
	s[2] = R[2]
	s[3] = V[0]
	s[4] = V[1]
	s[5] = V[2]
	// Add the components of Φ
	sIdx := 6
	for i := 0; i < rΦ; i++ {
		for j := 0; j < cΦ; j++ {
			s[sIdx] = e.Φ.At(i, j)
			sIdx++
		}
	}
	return s
}

// SetState sets the next state at time t.
func (e *OrbitEstimate) SetState(t float64, s []float64) {
	R := []float64{s[0], s[1], s[2]}
	V := []float64{s[3], s[4], s[5]}
	e.Orbit = *NewOrbitFromRV(R, V, e.Orbit.Origin)
	// Extract the components of Φ
	sIdx := 6
	rΦ, cΦ := e.Φ.Dims()
	Φk20 := mat64.NewDense(rΦ, cΦ, nil)
	for i := 0; i < rΦ; i++ {
		for j := 0; j < cΦ; j++ {
			Φk20.Set(i, j, s[sIdx])
			sIdx++
		}
	}
	if transitionPhiOnly {
		// Compute the Φ for this transition
		var Φinv mat64.Dense
		if err := Φinv.Inverse(e.Φ); err != nil {
			panic("could not invert e.Φ")
		}
		e.Φ.Mul(Φk20, &Φinv)
	} else {
		e.Φ = Φk20
	}
	// Increment the time.
	e.dt = e.dt.Add(e.step)
}

// Stop returns whether we should stop the integration.
func (e *OrbitEstimate) Stop(t float64) bool {
	return e.dt.After(e.StopDT)
}

// State returns the latest state
func (e *OrbitEstimate) State() State {
	return State{e.dt, Spacecraft{}, e.Orbit, nil, nil}
}

// Func does the math. Returns a new state.
func (e *OrbitEstimate) Func(t float64, f []float64) (fDot []float64) {
	// XXX: Note that this function is very similar to Mission.Func for a Cartesian propagation.
	// *BUT* we need to add in all the components of Φ, since they have to be integrated too.
	rΦ, cΦ := e.Φ.Dims()
	fDot = make([]float64, 6+rΦ*cΦ) // init return vector
	// Re-create the orbit from the state.
	R := []float64{f[0], f[1], f[2]}
	V := []float64{f[3], f[4], f[5]}
	orbit := NewOrbitFromRV(R, V, e.Orbit.Origin)
	bodyAcc := -orbit.Origin.μ / math.Pow(orbit.RNorm(), 3)
	// d\vec{R}/dt
	fDot[0] = f[3]
	fDot[1] = f[4]
	fDot[2] = f[5]
	// d\vec{V}/dt
	fDot[3] = bodyAcc * f[0]
	fDot[4] = bodyAcc * f[1]
	fDot[5] = bodyAcc * f[2]

	pert := e.Perts.Perturb(*orbit, e.dt)
	for i := 0; i < 6; i++ {
		fDot[i] += pert[i]
	}

	// Extract the components of Φ
	fIdx := 6
	Φ := mat64.NewDense(rΦ, cΦ, nil)
	ΦDot := mat64.NewDense(rΦ, cΦ, nil)
	for i := 0; i < rΦ; i++ {
		for j := 0; j < cΦ; j++ {
			Φ.Set(i, j, f[fIdx])
			fIdx++
		}
	}

	// Compute the STM.
	A := mat64.NewDense(6, 6, nil)
	// Top right is Identity 3x3
	A.Set(0, 3, 1)
	A.Set(1, 4, 1)
	A.Set(2, 5, 1)
	// Bottom left is where the magix is.
	x := R[0]
	y := R[1]
	z := R[2]
	x2 := math.Pow(R[0], 2)
	y2 := math.Pow(R[1], 2)
	z2 := math.Pow(R[2], 2)
	r2 := x2 + y2 + z2
	r232 := math.Pow(r2, 3/2.)
	r252 := math.Pow(r2, 5/2.)
	// Add the body perturbations

	dAxDx := 3*e.Orbit.Origin.μ*x2/r252 - e.Orbit.Origin.μ/r232
	dAxDy := 3 * e.Orbit.Origin.μ * x * y / r252
	dAxDz := 3 * e.Orbit.Origin.μ * x * z / r252
	dAyDx := 3 * e.Orbit.Origin.μ * x * y / r252
	dAyDy := 3*e.Orbit.Origin.μ*y2/r252 - e.Orbit.Origin.μ/r232
	dAyDz := 3 * e.Orbit.Origin.μ * y * z / r252
	dAzDx := 3 * e.Orbit.Origin.μ * x * z / r252
	dAzDy := 3 * e.Orbit.Origin.μ * y * z / r252
	dAzDz := 3*e.Orbit.Origin.μ*z2/r252 - e.Orbit.Origin.μ/r232

	A.Set(3, 0, dAxDx)
	A.Set(4, 0, dAyDx)
	A.Set(5, 0, dAzDx)
	A.Set(3, 1, dAxDy)
	A.Set(4, 1, dAyDy)
	A.Set(5, 1, dAzDy)
	A.Set(3, 2, dAxDz)
	A.Set(4, 2, dAyDz)
	A.Set(5, 2, dAzDz)

	// Jn perturbations:
	if e.Perts.Jn > 1 {
		// Ai0 = \frac{\partial a}{\partial x}
		// Ai1 = \frac{\partial a}{\partial y}
		// Ai2 = \frac{\partial a}{\partial z}
		A30 := A.At(3, 0)
		A40 := A.At(4, 0)
		A50 := A.At(5, 0)
		A31 := A.At(3, 1)
		A41 := A.At(4, 1)
		A51 := A.At(5, 1)
		A32 := A.At(3, 2)
		A42 := A.At(4, 2)
		A52 := A.At(5, 2)

		// Notation simplification
		z3 := math.Pow(R[2], 3)
		z4 := math.Pow(R[2], 4)
		// Adding those fractions to avoid forgetting the trailing period which makes them floats.
		f32 := 3 / 2.
		f152 := 15 / 2.
		r272 := math.Pow(r2, 7/2.)
		r292 := math.Pow(r2, 9/2.)
		// J2
		j2fact := e.Orbit.Origin.J(2) * math.Pow(e.Orbit.Origin.Radius, 2) * e.Orbit.Origin.μ
		A30 += -f32 * j2fact * (35*x2*z2/r292 - 5*x2/r272 - 5*z2/r272 + 1/r252) //dAxDx
		A40 += -f152 * j2fact * (7*x*y*z2/r292 - x*y/r272)                      //dAyDx
		A50 += -f152 * j2fact * (7*x*z3/r292 - 3*x*z/r272)                      //dAzDx

		A31 += -f152 * j2fact * (7*x*y*z2/r292 - x*y/r272)                      //dAxDy
		A41 += -f32 * j2fact * (35*y2*z2/r292 - 5*y2/r272 - 5*z2/r272 + 1/r252) // dAyDy
		A51 += -f152 * j2fact * (7*y*z3/r292 - 3*y*z/r272)                      // dAzDy

		A32 += -f152 * j2fact * (7*x*z3/r292 - 3*x*z/r272)        //dAxDz
		A42 += -f152 * j2fact * (7*y*z3/r292 - 3*y*z/r272)        //dAyDz
		A52 += -f32 * j2fact * (35*z4/r292 - 30*z2/r272 + 3/r252) // dAzDz

		// J3
		if e.Perts.Jn > 2 {
			z5 := math.Pow(R[2], 5)
			r2112 := math.Pow(r2, 11/2.)
			f52 := 5 / 2.
			f1052 := 105 / 2.
			j3fact := e.Orbit.Origin.J(3) * math.Pow(e.Orbit.Origin.Radius, 3) * e.Orbit.Origin.μ
			A30 += -f52 * j3fact * (63*x2*z3/r2112 - 21*x2*z/r292 - 7*z3/r292 + 3*z/r272) //dAxDx
			A40 += -f1052 * j3fact * (3*x*y*z3/r2112 - x*y*z/r292)                        //dAyDx
			A50 += -f152 * j3fact * (21*x*z4/r2112 - 14*x*z2/r292 + x/r272)               //dAzDx

			A31 += -f1052 * j3fact * (3*x*y*z3/r2112 - x*y*z/r292)                        //dAxDy
			A41 += -f52 * j3fact * (63*y2*z3/r2112 - 21*y2*z/r292 - 7*z3/r292 + 3*z/r272) // dAyDy
			A51 += -f152 * j3fact * (21*y*z4/r2112 - 14*y*z2/r292 + y/r272)               // dAzDy

			A32 += -f152 * j3fact * (21*x*z4/r2112 - 14*x*z2/r292 + x/r272) //dAxDz
			A42 += -f152 * j3fact * (21*y*z4/r2112 - 14*y*z2/r292 + y/r272) //dAyDz
			A52 += -f52 * j3fact * (63*z5/r2112 - 70*z3/r292 + 15*z/r272)   // dAzDz
		}
		// \frac{\partial a}{\partial x}
		A.Set(3, 0, A30)
		A.Set(4, 0, A40)
		A.Set(5, 0, A50)
		// \partial a/\partial y
		A.Set(3, 1, A31)
		A.Set(4, 1, A41)
		A.Set(5, 1, A51)
		// \partial a/\partial z
		A.Set(3, 2, A32)
		A.Set(4, 2, A42)
		A.Set(5, 2, A52)
	}
	ΦDot.Mul(A, Φ)

	// Store ΦDot in fDot
	fIdx = 6
	for i := 0; i < rΦ; i++ {
		for j := 0; j < cΦ; j++ {
			fDot[fIdx] = ΦDot.At(i, j)
			fIdx++
		}
	}
	return fDot
}

// PropagateUntil propagates until the given time is reached.
func (e *OrbitEstimate) PropagateUntil(dt time.Time) {
	e.StopDT = dt
	ode.NewRK4(0, e.step.Seconds(), e).Solve() // Blocking.
}

// NewOrbitEstimate returns a new Estimate of an orbit given the perturbations to be taken into account.
// The only supported state is [\vec{r} \vec{v}]T (for now at least).
func NewOrbitEstimate(n string, o Orbit, p Perturbations, epoch time.Time, step time.Duration) *OrbitEstimate {
	// The initial previous STM is identity.
	klog := kitlog.NewLogfmtLogger(kitlog.NewSyncWriter(os.Stdout))
	klog = kitlog.With(klog, "estimate", n)
	stopDT := epoch
	// XXX: We add the step for consistency with Mission. Mission is broken: it skips the first step because the time addition
	// happens in the Stop function instead of the SetState function, the former being called at the start of the integration.
	return &OrbitEstimate{gokalman.DenseIdentity(6), o, p, stopDT, epoch.Add(step), step, klog}
}
<commit_msg>Remove dependency on gokalman (needed for tests in https://github.com/ChristopherRabotin/gokalman/issues/43)<commit_after>package smd

import (
	"math"
	"os"
	"time"

	"github.com/ChristopherRabotin/ode"
	kitlog "github.com/go-kit/kit/log"
	"github.com/gonum/matrix/mat64"
)

const (
	transitionPhiOnly = false
)

// OrbitEstimate is an ode.Integrable which allows to propagate an orbit via its initial estimate.
type OrbitEstimate struct {
	Φ      *mat64.Dense  // STM
	Orbit  Orbit         // estimated orbit
	Perts  Perturbations // perturbations to account for
	StopDT time.Time     // end time of te integration
	dt     time.Time     // current time of the integration
	step   time.Duration // time step
	logger kitlog.Logger // logger
}

// GetState gets the state.
func (e *OrbitEstimate) GetState() []float64 {
	rΦ, cΦ := e.Φ.Dims()
	s := make([]float64, 6+rΦ*cΦ)
	R, V := e.Orbit.RV()
	s[0] = R[0]
	s[1] = R[1]
	s[2] = R[2]
	s[3] = V[0]
	s[4] = V[1]
	s[5] = V[2]
	// Add the components of Φ
	sIdx := 6
	for i := 0; i < rΦ; i++ {
		for j := 0; j < cΦ; j++ {
			s[sIdx] = e.Φ.At(i, j)
			sIdx++
		}
	}
	return s
}

// SetState sets the next state at time t.
func (e *OrbitEstimate) SetState(t float64, s []float64) {
	R := []float64{s[0], s[1], s[2]}
	V := []float64{s[3], s[4], s[5]}
	e.Orbit = *NewOrbitFromRV(R, V, e.Orbit.Origin)
	// Extract the components of Φ
	sIdx := 6
	rΦ, cΦ := e.Φ.Dims()
	Φk20 := mat64.NewDense(rΦ, cΦ, nil)
	for i := 0; i < rΦ; i++ {
		for j := 0; j < cΦ; j++ {
			Φk20.Set(i, j, s[sIdx])
			sIdx++
		}
	}
	if transitionPhiOnly {
		// Compute the Φ for this transition
		var Φinv mat64.Dense
		if err := Φinv.Inverse(e.Φ); err != nil {
			panic("could not invert e.Φ")
		}
		e.Φ.Mul(Φk20, &Φinv)
	} else {
		e.Φ = Φk20
	}
	// Increment the time.
	e.dt = e.dt.Add(e.step)
}

// Stop returns whether we should stop the integration.
func (e *OrbitEstimate) Stop(t float64) bool {
	return e.dt.After(e.StopDT)
}

// State returns the latest state
func (e *OrbitEstimate) State() State {
	return State{e.dt, Spacecraft{}, e.Orbit, nil, nil}
}

// Func does the math. Returns a new state.
func (e *OrbitEstimate) Func(t float64, f []float64) (fDot []float64) {
	// XXX: Note that this function is very similar to Mission.Func for a Cartesian propagation.
	// *BUT* we need to add in all the components of Φ, since they have to be integrated too.
	rΦ, cΦ := e.Φ.Dims()
	fDot = make([]float64, 6+rΦ*cΦ) // init return vector
	// Re-create the orbit from the state.
	R := []float64{f[0], f[1], f[2]}
	V := []float64{f[3], f[4], f[5]}
	orbit := NewOrbitFromRV(R, V, e.Orbit.Origin)
	bodyAcc := -orbit.Origin.μ / math.Pow(orbit.RNorm(), 3)
	// d\vec{R}/dt
	fDot[0] = f[3]
	fDot[1] = f[4]
	fDot[2] = f[5]
	// d\vec{V}/dt
	fDot[3] = bodyAcc * f[0]
	fDot[4] = bodyAcc * f[1]
	fDot[5] = bodyAcc * f[2]

	pert := e.Perts.Perturb(*orbit, e.dt)
	for i := 0; i < 6; i++ {
		fDot[i] += pert[i]
	}

	// Extract the components of Φ
	fIdx := 6
	Φ := mat64.NewDense(rΦ, cΦ, nil)
	ΦDot := mat64.NewDense(rΦ, cΦ, nil)
	for i := 0; i < rΦ; i++ {
		for j := 0; j < cΦ; j++ {
			Φ.Set(i, j, f[fIdx])
			fIdx++
		}
	}

	// Compute the STM.
	A := mat64.NewDense(6, 6, nil)
	// Top right is Identity 3x3
	A.Set(0, 3, 1)
	A.Set(1, 4, 1)
	A.Set(2, 5, 1)
	// Bottom left is where the magix is.
	x := R[0]
	y := R[1]
	z := R[2]
	x2 := math.Pow(R[0], 2)
	y2 := math.Pow(R[1], 2)
	z2 := math.Pow(R[2], 2)
	r2 := x2 + y2 + z2
	r232 := math.Pow(r2, 3/2.)
	r252 := math.Pow(r2, 5/2.)
	// Add the body perturbations

	dAxDx := 3*e.Orbit.Origin.μ*x2/r252 - e.Orbit.Origin.μ/r232
	dAxDy := 3 * e.Orbit.Origin.μ * x * y / r252
	dAxDz := 3 * e.Orbit.Origin.μ * x * z / r252
	dAyDx := 3 * e.Orbit.Origin.μ * x * y / r252
	dAyDy := 3*e.Orbit.Origin.μ*y2/r252 - e.Orbit.Origin.μ/r232
	dAyDz := 3 * e.Orbit.Origin.μ * y * z / r252
	dAzDx := 3 * e.Orbit.Origin.μ * x * z / r252
	dAzDy := 3 * e.Orbit.Origin.μ * y * z / r252
	dAzDz := 3*e.Orbit.Origin.μ*z2/r252 - e.Orbit.Origin.μ/r232

	A.Set(3, 0, dAxDx)
	A.Set(4, 0, dAyDx)
	A.Set(5, 0, dAzDx)
	A.Set(3, 1, dAxDy)
	A.Set(4, 1, dAyDy)
	A.Set(5, 1, dAzDy)
	A.Set(3, 2, dAxDz)
	A.Set(4, 2, dAyDz)
	A.Set(5, 2, dAzDz)

	// Jn perturbations:
	if e.Perts.Jn > 1 {
		// Ai0 = \frac{\partial a}{\partial x}
		// Ai1 = \frac{\partial a}{\partial y}
		// Ai2 = \frac{\partial a}{\partial z}
		A30 := A.At(3, 0)
		A40 := A.At(4, 0)
		A50 := A.At(5, 0)
		A31 := A.At(3, 1)
		A41 := A.At(4, 1)
		A51 := A.At(5, 1)
		A32 := A.At(3, 2)
		A42 := A.At(4, 2)
		A52 := A.At(5, 2)

		// Notation simplification
		z3 := math.Pow(R[2], 3)
		z4 := math.Pow(R[2], 4)
		// Adding those fractions to avoid forgetting the trailing period which makes them floats.
		f32 := 3 / 2.
		f152 := 15 / 2.
		r272 := math.Pow(r2, 7/2.)
		r292 := math.Pow(r2, 9/2.)
		// J2
		j2fact := e.Orbit.Origin.J(2) * math.Pow(e.Orbit.Origin.Radius, 2) * e.Orbit.Origin.μ
		A30 += -f32 * j2fact * (35*x2*z2/r292 - 5*x2/r272 - 5*z2/r272 + 1/r252) //dAxDx
		A40 += -f152 * j2fact * (7*x*y*z2/r292 - x*y/r272)                      //dAyDx
		A50 += -f152 * j2fact * (7*x*z3/r292 - 3*x*z/r272)                      //dAzDx

		A31 += -f152 * j2fact * (7*x*y*z2/r292 - x*y/r272)                      //dAxDy
		A41 += -f32 * j2fact * (35*y2*z2/r292 - 5*y2/r272 - 5*z2/r272 + 1/r252) // dAyDy
		A51 += -f152 * j2fact * (7*y*z3/r292 - 3*y*z/r272)                      // dAzDy

		A32 += -f152 * j2fact * (7*x*z3/r292 - 3*x*z/r272)        //dAxDz
		A42 += -f152 * j2fact * (7*y*z3/r292 - 3*y*z/r272)        //dAyDz
		A52 += -f32 * j2fact * (35*z4/r292 - 30*z2/r272 + 3/r252) // dAzDz

		// J3
		if e.Perts.Jn > 2 {
			z5 := math.Pow(R[2], 5)
			r2112 := math.Pow(r2, 11/2.)
			f52 := 5 / 2.
			f1052 := 105 / 2.
			j3fact := e.Orbit.Origin.J(3) * math.Pow(e.Orbit.Origin.Radius, 3) * e.Orbit.Origin.μ
			A30 += -f52 * j3fact * (63*x2*z3/r2112 - 21*x2*z/r292 - 7*z3/r292 + 3*z/r272) //dAxDx
			A40 += -f1052 * j3fact * (3*x*y*z3/r2112 - x*y*z/r292)                        //dAyDx
			A50 += -f152 * j3fact * (21*x*z4/r2112 - 14*x*z2/r292 + x/r272)               //dAzDx

			A31 += -f1052 * j3fact * (3*x*y*z3/r2112 - x*y*z/r292)                        //dAxDy
			A41 += -f52 * j3fact * (63*y2*z3/r2112 - 21*y2*z/r292 - 7*z3/r292 + 3*z/r272) // dAyDy
			A51 += -f152 * j3fact * (21*y*z4/r2112 - 14*y*z2/r292 + y/r272)               // dAzDy

			A32 += -f152 * j3fact * (21*x*z4/r2112 - 14*x*z2/r292 + x/r272) //dAxDz
			A42 += -f152 * j3fact * (21*y*z4/r2112 - 14*y*z2/r292 + y/r272) //dAyDz
			A52 += -f52 * j3fact * (63*z5/r2112 - 70*z3/r292 + 15*z/r272)   // dAzDz
		}
		// \frac{\partial a}{\partial x}
		A.Set(3, 0, A30)
		A.Set(4, 0, A40)
		A.Set(5, 0, A50)
		// \partial a/\partial y
		A.Set(3, 1, A31)
		A.Set(4, 1, A41)
		A.Set(5, 1, A51)
		// \partial a/\partial z
		A.Set(3, 2, A32)
		A.Set(4, 2, A42)
		A.Set(5, 2, A52)
	}
	ΦDot.Mul(A, Φ)

	// Store ΦDot in fDot
	fIdx = 6
	for i := 0; i < rΦ; i++ {
		for j := 0; j < cΦ; j++ {
			fDot[fIdx] = ΦDot.At(i, j)
			fIdx++
		}
	}
	return fDot
}

// PropagateUntil propagates until the given time is reached.
func (e *OrbitEstimate) PropagateUntil(dt time.Time) {
	e.StopDT = dt
	ode.NewRK4(0, e.step.Seconds(), e).Solve() // Blocking.
}

// NewOrbitEstimate returns a new Estimate of an orbit given the perturbations to be taken into account.
// The only supported state is [\vec{r} \vec{v}]T (for now at least).
func NewOrbitEstimate(n string, o Orbit, p Perturbations, epoch time.Time, step time.Duration) *OrbitEstimate {
	// The initial previous STM is identity.
	klog := kitlog.NewLogfmtLogger(kitlog.NewSyncWriter(os.Stdout))
	klog = kitlog.With(klog, "estimate", n)
	stopDT := epoch
	// XXX: We add the step for consistency with Mission. Mission is broken: it skips the first step because the time addition
	// happens in the Stop function instead of the SetState function, the former being called at the start of the integration.
	return &OrbitEstimate{DenseIdentity(6), o, p, stopDT, epoch.Add(step), step, klog}
}
<|endoftext|>


<commit_before>package ipc

import (
	"fmt"
	log "github.com/GameGophers/nsq-logger"
	nsq "github.com/bitly/go-nsq"
	"golang.org/x/net/context"
	"gopkg.in/vmihailenco/msgpack.v2"
	"os"
	"strings"
)

import (
	"registry"
	"services"
	"services/proto"
	. "types"
)

const (
	DEFAULT_NSQLOOKUPD = "127.0.0.1:4160"
	ENV_NSQLOOKUPD     = "NSQLOOKUPD_HOST"
	NSQ_IN_FLIGHT      = 128
)

const (
	UNICAST   = "unicast"
	MULTICAST = "multicast"
	BROADCAST = "broadcast"
)

func init() {
	ic := IPCConsumer{}
	ic.init()
}

type IPCConsumer struct{}

func (ic *IPCConsumer) init() {
	// rank change subscriber
	channel := ic.create_ephermal_channel()
	ic.init_subscriber(UNICAST, channel)
	ic.init_subscriber(MULTICAST, channel)
	ic.init_subscriber(BROADCAST, channel)
}

func (ic *IPCConsumer) create_ephermal_channel() string {
	c, err := services.GetService(services.SERVICE_SNOWFLAKE)
	if err != nil {
		log.Critical(err)
		os.Exit(-1)
	}
	service, ok := c.(proto.SnowflakeServiceClient)
	if !ok {
		log.Critical("internal error:", c)
		os.Exit(-1)
	}

	r, err := service.GetUUID(context.Background(), &proto.Snowflake_NullRequest{})
	if err != nil {
		log.Critical(err)
		os.Exit(-1)
	}
	return fmt.Sprintf("IPC%v#ephemeral", r.Uuid)
}

func (ic *IPCConsumer) init_subscriber(topic, channel string) {
	cfg := nsq.NewConfig()
	cfg.MaxInFlight = NSQ_IN_FLIGHT
	consumer, err := nsq.NewConsumer(topic, channel, cfg)
	if err != nil {
		log.Critical(err)
		os.Exit(-1)
	}

	// message process
	consumer.AddHandler(nsq.HandlerFunc(func(msg *nsq.Message) error {
		switch topic {
		case UNICAST:
			ic.unicast(msg)
		case MULTICAST:
			ic.multicast(msg)
		case BROADCAST:
			ic.broadcast(msg)
		}
		return nil
	}))

	// read environtment variable
	addresses := []string{DEFAULT_NSQLOOKUPD}
	if env := os.Getenv(ENV_NSQLOOKUPD); env != "" {
		addresses = strings.Split(env, ";")
	}

	// connect to nsqlookupd
	log.Trace("connect to nsqlookupds ip:", addresses)
	if err := consumer.ConnectToNSQLookupds(addresses); err != nil {
		log.Critical(err)
		return
	}
	log.Info("nsqlookupd connected for unicast")
}

func (ic *IPCConsumer) unicast(msg *nsq.Message) {
	// 解包
	obj := IPCObject{}
	err := msgpack.Unmarshal(msg.Body, &obj)
	if err != nil {
		log.Error(err)
		return
	}

	// 投递
	registry.Deliver(obj.DestId, obj)
}

func (ic *IPCConsumer) multicast(msg *nsq.Message) {
	// 解包
	obj := IPCObject{}
	err := msgpack.Unmarshal(msg.Body, &obj)
	if err != nil {
		log.Error(err)
		return
	}

	// 循环投递
	for _, id := range obj.AuxIds {
		registry.Deliver(id, obj)
	}
}

func (ic *IPCConsumer) broadcast(msg *nsq.Message) {
	// 解包
	obj := IPCObject{}
	err := msgpack.Unmarshal(msg.Body, &obj)
	if err != nil {
		log.Error(err)
		return
	}

	// 循环投递
	users := registry.ListAll()
	for _, v := range users {
		registry.Deliver(v, obj)
	}
}
<commit_msg>update print<commit_after>package ipc

import (
	"fmt"
	log "github.com/GameGophers/nsq-logger"
	nsq "github.com/bitly/go-nsq"
	"golang.org/x/net/context"
	"gopkg.in/vmihailenco/msgpack.v2"
	"os"
	"strings"
)

import (
	"registry"
	"services"
	"services/proto"
	. "types"
)

const (
	DEFAULT_NSQLOOKUPD = "127.0.0.1:4160"
	ENV_NSQLOOKUPD     = "NSQLOOKUPD_HOST"
	NSQ_IN_FLIGHT      = 128
)

const (
	UNICAST   = "unicast"
	MULTICAST = "multicast"
	BROADCAST = "broadcast"
)

func init() {
	ic := IPCConsumer{}
	ic.init()
}

type IPCConsumer struct{}

func (ic *IPCConsumer) init() {
	// rank change subscriber
	channel := ic.create_ephermal_channel()
	ic.init_subscriber(UNICAST, channel)
	ic.init_subscriber(MULTICAST, channel)
	ic.init_subscriber(BROADCAST, channel)
}

func (ic *IPCConsumer) create_ephermal_channel() string {
	c, err := services.GetService(services.SERVICE_SNOWFLAKE)
	if err != nil {
		log.Critical(err)
		os.Exit(-1)
	}
	service, ok := c.(proto.SnowflakeServiceClient)
	if !ok {
		log.Critical("internal error:", c)
		os.Exit(-1)
	}

	r, err := service.GetUUID(context.Background(), &proto.Snowflake_NullRequest{})
	if err != nil {
		log.Critical(err)
		os.Exit(-1)
	}
	return fmt.Sprintf("IPC%v#ephemeral", r.Uuid)
}

func (ic *IPCConsumer) init_subscriber(topic, channel string) {
	cfg := nsq.NewConfig()
	cfg.MaxInFlight = NSQ_IN_FLIGHT
	consumer, err := nsq.NewConsumer(topic, channel, cfg)
	if err != nil {
		log.Critical(err)
		os.Exit(-1)
	}

	// message process
	consumer.AddHandler(nsq.HandlerFunc(func(msg *nsq.Message) error {
		switch topic {
		case UNICAST:
			ic.unicast(msg)
		case MULTICAST:
			ic.multicast(msg)
		case BROADCAST:
			ic.broadcast(msg)
		}
		return nil
	}))

	// read environtment variable
	addresses := []string{DEFAULT_NSQLOOKUPD}
	if env := os.Getenv(ENV_NSQLOOKUPD); env != "" {
		addresses = strings.Split(env, ";")
	}

	// connect to nsqlookupd
	log.Trace("connect to nsqlookupds ip:", addresses)
	if err := consumer.ConnectToNSQLookupds(addresses); err != nil {
		log.Critical(err)
		return
	}
	log.Info("nsqlookupd connected")
}

func (ic *IPCConsumer) unicast(msg *nsq.Message) {
	// 解包
	obj := IPCObject{}
	err := msgpack.Unmarshal(msg.Body, &obj)
	if err != nil {
		log.Error(err)
		return
	}

	// 投递
	registry.Deliver(obj.DestId, obj)
}

func (ic *IPCConsumer) multicast(msg *nsq.Message) {
	// 解包
	obj := IPCObject{}
	err := msgpack.Unmarshal(msg.Body, &obj)
	if err != nil {
		log.Error(err)
		return
	}

	// 循环投递
	for _, id := range obj.AuxIds {
		registry.Deliver(id, obj)
	}
}

func (ic *IPCConsumer) broadcast(msg *nsq.Message) {
	// 解包
	obj := IPCObject{}
	err := msgpack.Unmarshal(msg.Body, &obj)
	if err != nil {
		log.Error(err)
		return
	}

	// 循环投递
	users := registry.ListAll()
	for _, v := range users {
		registry.Deliver(v, obj)
	}
}
<|endoftext|>