<commit_before>package edit

import (
	"os"
	"path"
	"strings"
	"syscall"
)

// This is a reverse-engineered implementation of the parsing and
// interpretation of the LS_COLORS environmental variable used by GNU
// coreutils.

type fileFeature int

const (
	featureInvalid fileFeature = iota

	featureOrphanedSymlink
	featureSymlink

	featureMultiHardLink

	featureNamedPipe
	featureSocket
	featureDoor
	featureBlockDevice
	featureCharDevice

	featureWorldWritableStickyDirectory
	featureWorldWritableDirectory
	featureStickyDirectory
	featureDirectory

	featureCapability

	featureSetuid
	featureSetgid
	featureExecutable

	featureRegular
)

var featureForName = map[string]fileFeature{
	"rs": featureRegular,
	"di": featureDirectory,
	"ln": featureSymlink,
	"mh": featureMultiHardLink,
	"pi": featureNamedPipe,
	"so": featureSocket,
	"do": featureDoor,
	"bd": featureBlockDevice,
	"cd": featureCharDevice,
	"or": featureOrphanedSymlink,
	"su": featureSetuid,
	"sg": featureSetgid,
	"ca": featureCapability,
	"tw": featureWorldWritableStickyDirectory,
	"ow": featureWorldWritableDirectory,
	"st": featureStickyDirectory,
	"ex": featureExecutable,
}

type lsColor struct {
	attrForFeature map[fileFeature]string
	attrForExt     map[string]string
}

const defaultLsColorString = `rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:`

var defaultLsColor *lsColor

// parseLsColor parses a string in the LS_COLORS format into lsColor.
// XXX(xiaq): ignores erroneous fields
func parseLsColor(s string) *lsColor {
	lc := &lsColor{make(map[fileFeature]string), make(map[string]string)}
	for _, spec := range strings.Split(s, ":") {
		words := strings.Split(spec, "=")
		if len(words) != 2 {
			continue
		}
		key, value := words[0], words[1]
		if strings.HasPrefix(key, "*.") {
			lc.attrForExt[key[2:]] = value
		} else {
			feature, ok := featureForName[key]
			if !ok {
				continue
			}
			lc.attrForFeature[feature] = value
		}
	}
	return lc
}

func is(u, p uint32) bool {
	return u&p == p
}

func determineFeature(fname string, mh bool) (fileFeature, error) {
	var stat syscall.Stat_t
	err := syscall.Lstat(fname, &stat)
	if err != nil {
		return 0, err
	}

	// The type of syscall.Stat_t.Mode is uint32 on Linux and uint16 on Mac
	m := (uint32)(stat.Mode)

	// Symlink and OrphanedSymlink has highest precedence
	if is(m, syscall.S_IFLNK) {
		_, err := os.Stat(fname)
		if err == nil {
			return featureSymlink, nil
		} else {
			return featureOrphanedSymlink, nil
		}
	}

	// featureMultiHardLink
	if mh && stat.Nlink > 1 {
		return featureMultiHardLink, nil
	}

	// type bits features
	switch {
	case is(m, syscall.S_IFIFO):
		return featureNamedPipe, nil
	case is(m, syscall.S_IFSOCK):
		return featureSocket, nil
		/*
			case m | syscall.S_IFDOOR != 0:
				return featureDoor, nil
		*/
	case is(m, syscall.S_IFBLK):
		return featureBlockDevice, nil
	case is(m, syscall.S_IFCHR):
		return featureCharDevice, nil
	case is(m, syscall.S_IFDIR):
		// Perm bits features for directory
		switch {
		case is(m, syscall.S_IWOTH|syscall.S_ISVTX):
			return featureWorldWritableStickyDirectory, nil
		case is(m, syscall.S_IWOTH):
			return featureWorldWritableDirectory, nil
		case is(m, syscall.S_ISVTX):
			return featureStickyDirectory, nil
		default:
			return featureDirectory, nil
		}
	}

	// TODO(xiaq): Support featureCapacity

	// Perm bits features for regular files
	switch {
	case is(m, syscall.S_ISUID):
		return featureSetuid, nil
	case is(m, syscall.S_ISGID):
		return featureSetgid, nil
	case m&(syscall.S_IXUSR|syscall.S_IXGRP|syscall.S_IXOTH) != 0:
		return featureExecutable, nil
	}

	// Check extension
	return featureRegular, nil
}

func (lc *lsColor) determineAttr(fname string) string {
	mh := strings.Trim(lc.attrForFeature[featureMultiHardLink], "0") != ""
	// TODO Handle error from determineFeature
	feature, _ := determineFeature(fname, mh)
	if feature == featureRegular {
		if ext := path.Ext(fname); ext != "" {
			if attr, ok := lc.attrForExt[ext]; ok {
				return attr
			}
		}
	}
	return lc.attrForFeature[feature]
}

func init() {
	defaultLsColor = parseLsColor(defaultLsColorString)
}
<commit_msg>FreeBSD compatibility fix.<commit_after>package edit

import (
	"os"
	"path"
	"strings"
	"syscall"
)

// This is a reverse-engineered implementation of the parsing and
// interpretation of the LS_COLORS environmental variable used by GNU
// coreutils.

type fileFeature int

const (
	featureInvalid fileFeature = iota

	featureOrphanedSymlink
	featureSymlink

	featureMultiHardLink

	featureNamedPipe
	featureSocket
	featureDoor
	featureBlockDevice
	featureCharDevice

	featureWorldWritableStickyDirectory
	featureWorldWritableDirectory
	featureStickyDirectory
	featureDirectory

	featureCapability

	featureSetuid
	featureSetgid
	featureExecutable

	featureRegular
)

var featureForName = map[string]fileFeature{
	"rs": featureRegular,
	"di": featureDirectory,
	"ln": featureSymlink,
	"mh": featureMultiHardLink,
	"pi": featureNamedPipe,
	"so": featureSocket,
	"do": featureDoor,
	"bd": featureBlockDevice,
	"cd": featureCharDevice,
	"or": featureOrphanedSymlink,
	"su": featureSetuid,
	"sg": featureSetgid,
	"ca": featureCapability,
	"tw": featureWorldWritableStickyDirectory,
	"ow": featureWorldWritableDirectory,
	"st": featureStickyDirectory,
	"ex": featureExecutable,
}

type lsColor struct {
	attrForFeature map[fileFeature]string
	attrForExt     map[string]string
}

const defaultLsColorString = `rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:`

var defaultLsColor *lsColor

// parseLsColor parses a string in the LS_COLORS format into lsColor.
// XXX(xiaq): ignores erroneous fields
func parseLsColor(s string) *lsColor {
	lc := &lsColor{make(map[fileFeature]string), make(map[string]string)}
	for _, spec := range strings.Split(s, ":") {
		words := strings.Split(spec, "=")
		if len(words) != 2 {
			continue
		}
		key, value := words[0], words[1]
		if strings.HasPrefix(key, "*.") {
			lc.attrForExt[key[2:]] = value
		} else {
			feature, ok := featureForName[key]
			if !ok {
				continue
			}
			lc.attrForFeature[feature] = value
		}
	}
	return lc
}

func is(u, p uint32) bool {
	return u&p == p
}

// Weirdly, permission masks for group and other are missing on platforms other
// than linux, darwin and netbsd. So we replicate some of them here.
const (
	S_IWOTH = 0x2 // Writable by other
	S_IXGRP = 0x8 // Executable by group
	S_IXOTH = 0x1 // Executable by other
)

func determineFeature(fname string, mh bool) (fileFeature, error) {
	var stat syscall.Stat_t
	err := syscall.Lstat(fname, &stat)
	if err != nil {
		return 0, err
	}

	// The type of syscall.Stat_t.Mode is uint32 on Linux and uint16 on Mac
	m := (uint32)(stat.Mode)

	// Symlink and OrphanedSymlink has highest precedence
	if is(m, syscall.S_IFLNK) {
		_, err := os.Stat(fname)
		if err == nil {
			return featureSymlink, nil
		} else {
			return featureOrphanedSymlink, nil
		}
	}

	// featureMultiHardLink
	if mh && stat.Nlink > 1 {
		return featureMultiHardLink, nil
	}

	// type bits features
	switch {
	case is(m, syscall.S_IFIFO):
		return featureNamedPipe, nil
	case is(m, syscall.S_IFSOCK):
		return featureSocket, nil
		/*
			case m | syscall.S_IFDOOR != 0:
				return featureDoor, nil
		*/
	case is(m, syscall.S_IFBLK):
		return featureBlockDevice, nil
	case is(m, syscall.S_IFCHR):
		return featureCharDevice, nil
	case is(m, syscall.S_IFDIR):
		// Perm bits features for directory
		switch {
		case is(m, S_IWOTH|syscall.S_ISVTX):
			return featureWorldWritableStickyDirectory, nil
		case is(m, S_IWOTH):
			return featureWorldWritableDirectory, nil
		case is(m, syscall.S_ISVTX):
			return featureStickyDirectory, nil
		default:
			return featureDirectory, nil
		}
	}

	// TODO(xiaq): Support featureCapacity

	// Perm bits features for regular files
	switch {
	case is(m, syscall.S_ISUID):
		return featureSetuid, nil
	case is(m, syscall.S_ISGID):
		return featureSetgid, nil
	case m&(syscall.S_IXUSR|S_IXGRP|S_IXOTH) != 0:
		return featureExecutable, nil
	}

	// Check extension
	return featureRegular, nil
}

func (lc *lsColor) determineAttr(fname string) string {
	mh := strings.Trim(lc.attrForFeature[featureMultiHardLink], "0") != ""
	// TODO Handle error from determineFeature
	feature, _ := determineFeature(fname, mh)
	if feature == featureRegular {
		if ext := path.Ext(fname); ext != "" {
			if attr, ok := lc.attrForExt[ext]; ok {
				return attr
			}
		}
	}
	return lc.attrForFeature[feature]
}

func init() {
	defaultLsColor = parseLsColor(defaultLsColorString)
}
<|endoftext|>


<commit_before>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 config_test

import (
	. "github.com/jacobsa/ogletest"
	"testing"
)

func TestParse(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

type ParseTest struct {
}

func init() { RegisterTestSuite(&ParseTest{}) }

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *ParseTest) TotalJunk() {
	ExpectEq("TODO", "")
}

func (t *ParseTest) MissingTrailingBrace() {
	ExpectEq("TODO", "")
}

func (t *ParseTest) BasePathIsNumber() {
	ExpectEq("TODO", "")
}

func (t *ParseTest) BasePathIsNull() {
	ExpectEq("TODO", "")
}

func (t *ParseTest) BasePathIsObject() {
	ExpectEq("TODO", "")
}

func (t *ParseTest) EmptyConfig() {
	ExpectEq("TODO", "")
}

func (t *ParseTest) DuplicateJobName() {
	ExpectEq("TODO", "")
}

func (t *ParseTest) StructurallyValid() {
	ExpectEq("TODO", "")
}
<commit_msg>Added more test names.<commit_after>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 config_test

import (
	. "github.com/jacobsa/ogletest"
	"testing"
)

func TestParse(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

type ParseTest struct {
}

func init() { RegisterTestSuite(&ParseTest{}) }

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *ParseTest) TotalJunk() {
	ExpectEq("TODO", "")
}

func (t *ParseTest) MissingTrailingBrace() {
	ExpectEq("TODO", "")
}

func (t *ParseTest) BasePathIsNumber() {
	ExpectEq("TODO", "")
}

func (t *ParseTest) BasePathIsNull() {
	ExpectEq("TODO", "")
}

func (t *ParseTest) BasePathIsObject() {
	ExpectEq("TODO", "")
}

func (t *ParseTest) OneExcludeDoesntCompile() {
	ExpectEq("TODO", "")
}

func (t *ParseTest) EmptyConfig() {
	ExpectEq("TODO", "")
}

func (t *ParseTest) MissingExcludesArray() {
	ExpectEq("TODO", "")
}

func (t *ParseTest) DuplicateJobName() {
	ExpectEq("TODO", "")
}

func (t *ParseTest) StructurallyValid() {
	ExpectEq("TODO", "")
}
<|endoftext|>


<commit_before>package filesystem

import (
	"bufio"
	"fmt"

	"gopkg.in/src-d/go-git.v4/plumbing"
	"gopkg.in/src-d/go-git.v4/storage/filesystem/internal/dotgit"
	"gopkg.in/src-d/go-git.v4/utils/ioutil"
)

// ShallowStorage where the shallow commits are stored, an internal to
// manipulate the shallow file
type ShallowStorage struct {
	dir *dotgit.DotGit
}

// SetShallow save the shallows in the shallow file in the .git folder as one
// commit per line represented by 40-byte hexadecimal object terminated by a
// newline.
func (s *ShallowStorage) SetShallow(commits []plumbing.Hash) error {
	f, err := s.dir.ShallowWriter()
	if err != nil {
		return err
	}

	defer ioutil.CheckClose(f, &err)
	for _, h := range commits {
		if _, err := fmt.Fprintf(f, "%s\n", h); err != nil {
			return err
		}
	}

	return err
}

// Shallow return the shallow commits reading from shallo file from .git
func (s *ShallowStorage) Shallow() ([]plumbing.Hash, error) {
	f, err := s.dir.Shallow()
	if f == nil || err != nil {
		return nil, err
	}

	var hash []plumbing.Hash

	scn := bufio.NewScanner(f)
	for scn.Scan() {
		hash = append(hash, plumbing.NewHash(scn.Text()))
	}

	return hash, scn.Err()
}
<commit_msg>storage: filesystem, close shallow file when read<commit_after>package filesystem

import (
	"bufio"
	"fmt"

	"gopkg.in/src-d/go-git.v4/plumbing"
	"gopkg.in/src-d/go-git.v4/storage/filesystem/internal/dotgit"
	"gopkg.in/src-d/go-git.v4/utils/ioutil"
)

// ShallowStorage where the shallow commits are stored, an internal to
// manipulate the shallow file
type ShallowStorage struct {
	dir *dotgit.DotGit
}

// SetShallow save the shallows in the shallow file in the .git folder as one
// commit per line represented by 40-byte hexadecimal object terminated by a
// newline.
func (s *ShallowStorage) SetShallow(commits []plumbing.Hash) error {
	f, err := s.dir.ShallowWriter()
	if err != nil {
		return err
	}

	defer ioutil.CheckClose(f, &err)
	for _, h := range commits {
		if _, err := fmt.Fprintf(f, "%s\n", h); err != nil {
			return err
		}
	}

	return err
}

// Shallow return the shallow commits reading from shallo file from .git
func (s *ShallowStorage) Shallow() ([]plumbing.Hash, error) {
	f, err := s.dir.Shallow()
	if f == nil || err != nil {
		return nil, err
	}

	defer ioutil.CheckClose(f, &err)

	var hash []plumbing.Hash

	scn := bufio.NewScanner(f)
	for scn.Scan() {
		hash = append(hash, plumbing.NewHash(scn.Text()))
	}

	return hash, scn.Err()
}
<|endoftext|>


<commit_before>// These integration tests require root as they need access to network devices.
package root

import (
	"github.com/AutoRoute/node"
	integration "github.com/AutoRoute/node/integration_tests"

	"errors"
	"fmt"
	"net"
	"os/exec"
	"strings"
	"testing"
	"time"
)

func BuildListenAddress(i *net.Interface, port int) string {
	ll, err := node.GetLinkLocalAddr(*i)
	if err != nil {
		panic(err)
	}
	return fmt.Sprintf("[%s%%%s]:%d", ll, i.Name, port)
}

func WaitForDevice(s string) (*net.Interface, error) {
	timeout := time.After(1 * time.Second)
	for range time.Tick(10 * time.Millisecond) {
		select {
		case <-timeout:
			return nil, errors.New(fmt.Sprintf("Error waiting for %s to be reachable", s))
		default:
		}
		d, err := net.InterfaceByName(s)
		if err == nil {
			return d, nil
		}
	}
	panic("Unreachable")
}

func WaitForListen(s string) error {
	timeout := time.After(2 * time.Second)
	for range time.Tick(10 * time.Millisecond) {
		select {
		case <-timeout:
			return errors.New(fmt.Sprintf("Error waiting for %s to be reachable", s))
		default:
		}
		_, err := net.Listen("tcp6", s)
		if err == nil {
			return nil
		}
	}
	panic("Unreachable")
}

func TestConnection(t *testing.T) {
	// set -e
	WarnRoot(t)
	// loopback2
	cmd := integration.NewWrappedBinary(GetLoopBack2Path())
	err := cmd.Start()
	if err != nil {
		t.Fatal(err)
	}
	defer cmd.KillAndPrint(t)
	listen_dev, err := WaitForDevice("looptap0-0")
	if err != nil {
		t.Fatal(err)
	}
	connect_dev, err := WaitForDevice("looptap0-1")
	if err != nil {
		t.Fatal(err)
	}
	//  ip link set dev looptap0-0 up
	out, err := exec.Command("ip", strings.Split("link set dev looptap0-0 up", " ")...).CombinedOutput()
	if err != nil {
		t.Fatal(err, string(out))
	}
	// ip link set dev looptap 0-1 up
	out, err = exec.Command("ip", strings.Split("link set dev looptap0-1 up", " ")...).CombinedOutput()
	if err != nil {
		t.Fatal(err, string(out))
	}
	// starts listening on the address
	err = WaitForListen(BuildListenAddress(listen_dev, integration.GetUnusedPort()))
	if err != nil {
		t.Fatal(err)
	}
	err = WaitForListen(BuildListenAddress(connect_dev, integration.GetUnusedPort()))
	if err != nil {
		t.Fatal(err)
	}

	listen_port := integration.GetUnusedPort()
	// autoroute -fake_money -listen "[%ip0%looptap0-0]:31337" -auto=true -devs='looptap0-0'
	listen := integration.NewNodeBinary(integration.BinaryOptions{
		Listen:               BuildListenAddress(listen_dev, listen_port),
		Fake_money:           true,
		Autodiscover:         true,
		Autodiscover_devices: []string{listen_dev.Name},
	})
	listen.Start()
	defer listen.KillAndPrint(t)
    // autoroute -fake_money -listen "[%ip1%looptap0-1]:31337" -auto=true -devs='looptap0-1'
	connect_port := integration.GetUnusedPort()
	connect := integration.NewNodeBinary(integration.BinaryOptions{
		Listen:               BuildListenAddress(connect_dev, connect_port),
		Fake_money:           true,
		Autodiscover:         true,
		Autodiscover_devices: []string{connect_dev.Name},
	})
	connect.Start()
	defer connect.KillAndPrint(t)

	_, err = integration.WaitForID(listen)
	if err != nil {
		t.Fatal(err)
	}
	// get connect ID once it's generated
	connect_id, err := integration.WaitForID(connect)
	if err != nil {
		t.Fatal(err)
	}
	// connect it to the listener
	err = integration.WaitForConnection(listen, connect_id)
	if err != nil {
		t.Fatal(err)
	}
}
<commit_msg>formatting<commit_after>// These integration tests require root as they need access to network devices.
package root

import (
	"github.com/AutoRoute/node"
	integration "github.com/AutoRoute/node/integration_tests"

	"errors"
	"fmt"
	"net"
	"os/exec"
	"strings"
	"testing"
	"time"
)

func BuildListenAddress(i *net.Interface, port int) string {
	ll, err := node.GetLinkLocalAddr(*i)
	if err != nil {
		panic(err)
	}
	return fmt.Sprintf("[%s%%%s]:%d", ll, i.Name, port)
}

func WaitForDevice(s string) (*net.Interface, error) {
	timeout := time.After(1 * time.Second)
	for range time.Tick(10 * time.Millisecond) {
		select {
		case <-timeout:
			return nil, errors.New(fmt.Sprintf("Error waiting for %s to be reachable", s))
		default:
		}
		d, err := net.InterfaceByName(s)
		if err == nil {
			return d, nil
		}
	}
	panic("Unreachable")
}

func WaitForListen(s string) error {
	timeout := time.After(2 * time.Second)
	for range time.Tick(10 * time.Millisecond) {
		select {
		case <-timeout:
			return errors.New(fmt.Sprintf("Error waiting for %s to be reachable", s))
		default:
		}
		_, err := net.Listen("tcp6", s)
		if err == nil {
			return nil
		}
	}
	panic("Unreachable")
}

func TestConnection(t *testing.T) {
	// set -e
	WarnRoot(t)
	// loopback2
	cmd := integration.NewWrappedBinary(GetLoopBack2Path())
	err := cmd.Start()
	if err != nil {
		t.Fatal(err)
	}
	defer cmd.KillAndPrint(t)
	listen_dev, err := WaitForDevice("looptap0-0")
	if err != nil {
		t.Fatal(err)
	}
	connect_dev, err := WaitForDevice("looptap0-1")
	if err != nil {
		t.Fatal(err)
	}
	//  ip link set dev looptap0-0 up
	out, err := exec.Command("ip", strings.Split("link set dev looptap0-0 up", " ")...).CombinedOutput()
	if err != nil {
		t.Fatal(err, string(out))
	}
	// ip link set dev looptap 0-1 up
	out, err = exec.Command("ip", strings.Split("link set dev looptap0-1 up", " ")...).CombinedOutput()
	if err != nil {
		t.Fatal(err, string(out))
	}
	// starts listening on the address
	err = WaitForListen(BuildListenAddress(listen_dev, integration.GetUnusedPort()))
	if err != nil {
		t.Fatal(err)
	}
	err = WaitForListen(BuildListenAddress(connect_dev, integration.GetUnusedPort()))
	if err != nil {
		t.Fatal(err)
	}

	listen_port := integration.GetUnusedPort()
	// autoroute -fake_money -listen "[%ip0%looptap0-0]:31337" -auto=true -devs='looptap0-0'
	listen := integration.NewNodeBinary(integration.BinaryOptions{
		Listen:               BuildListenAddress(listen_dev, listen_port),
		Fake_money:           true,
		Autodiscover:         true,
		Autodiscover_devices: []string{listen_dev.Name},
	})
	listen.Start()
	defer listen.KillAndPrint(t)
	// autoroute -fake_money -listen "[%ip1%looptap0-1]:31337" -auto=true -devs='looptap0-1'
	connect_port := integration.GetUnusedPort()
	connect := integration.NewNodeBinary(integration.BinaryOptions{
		Listen:               BuildListenAddress(connect_dev, connect_port),
		Fake_money:           true,
		Autodiscover:         true,
		Autodiscover_devices: []string{connect_dev.Name},
	})
	connect.Start()
	defer connect.KillAndPrint(t)

	_, err = integration.WaitForID(listen)
	if err != nil {
		t.Fatal(err)
	}
	// get connect ID once it's generated
	connect_id, err := integration.WaitForID(connect)
	if err != nil {
		t.Fatal(err)
	}
	// connect it to the listener
	err = integration.WaitForConnection(listen, connect_id)
	if err != nil {
		t.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package events

import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"io"
	"strconv"
	"strings"
)

// Event represents a Supervisor event. An event consists of a header, metadata (meta) and an optional payload.
type Event struct {
	Header  map[string]string
	Meta    map[string]string
	Payload []byte
}

// getHeaderString returns the requested header value as a string or an empty string if missing.
func (event Event) getHeaderString(key string) string {
	if value, ok := event.Header[key]; ok {
		return value
	} else {
		return ""
	}
}

// getHeaderInt returns the requested header value as an int or 0 if missing.
func (event Event) getHeaderInt(key string) int {
	strval, ok := event.Header[key]
	if !ok {
		return 0
	}

	intval, err := strconv.Atoi(strval)
	if err != nil {
		return 0
	}

	return intval
}

// String returns the event as a human readable string.
func (event Event) String() string {
	return fmt.Sprintf("Event{%d:%s}", event.Serial(), event.Name())
}

// Name returns the name of the event.
func (event Event) Name() string {
	return event.getHeaderString("eventname")
}

// Serial returns the event serial number.
func (event Event) Serial() int {
	return event.getHeaderInt("serial")
}

// Pool returns the event pool where the event originated.
func (event Event) Pool() string {
	return event.getHeaderString("pool")
}

// PoolSerial returns the serial of the event in the event pool where the event originated.
func (event Event) PoolSerial() int {
	return event.getHeaderInt("poolserial")
}

// Version returns the version of the Supervisor instance that sent the event.
func (event Event) Version() string {
	return event.getHeaderString("ver")
}

// ToBytes converts the event to a byte array suitable for parsing.
func (event Event) ToBytes() []byte {
	mapser := func(data map[string]string) []byte {
		parts := make([]string, 0, len(data))
		for k, v := range data {
			parts = append(parts, fmt.Sprintf("%v:%v", k, v))
		}
		return []byte(strings.Join(parts, " "))
	}

	meta := mapser(event.Meta)
	payload := make([]byte, 0, len(meta)+len(event.Payload)+1)
	payload = append(payload, meta...)
	if event.Payload == nil || len(event.Payload) > 0 {
		payload = append(payload, '\n')
		payload = append(payload, event.Payload...)
	}

	event.Header["len"] = strconv.Itoa(len(payload))
	header := mapser(event.Header)
	message := make([]byte, 0, len(header)+len(payload))
	message = append(message, header...)
	message = append(message, '\n')
	message = append(message, payload...)
	return message
}

// parseMap parses a header or metadata string into a string/string map.
func parseMap(data []byte) map[string]string {
	str := strings.TrimSpace(string(data))
	mapping := make(map[string]string)
	for _, token := range strings.Split(str, " ") {
		if token == "" {
			continue
		}
		pair := strings.SplitN(token, ":", 2)
		switch len(pair) {
		case 2:
			mapping[pair[0]] = pair[1]
		case 1:
			mapping[pair[0]] = ""
		}
	}
	return mapping
}

// parsePayload parses a raw event payload into a metadata and payload.
func parsePayload(data []byte) (meta map[string]string, payload []byte) {
	if index := bytes.IndexByte(data, '\n'); index > 0 {
		meta = parseMap(data[:index])
		payload = data[index+1:]
	} else {
		meta = parseMap(data)
	}
	return
}

// ReadEvent waits for a Supervisor event and returns the parsed event. The err
// will be non-nil if an error occurred. This may include io.EOF which should
// preceed closing of the reader.
func ReadEvent(reader io.Reader) (event *Event, err error) {
	buf := bufio.NewReader(reader)
	data, err := buf.ReadBytes('\n')
	if err != nil {
		return
	}

	header := parseMap(data)
	length, err := strconv.Atoi(header["len"])
	if err != nil {
		return
	}

	rawPayload := make([]byte, length)
	_, err = buf.Read(rawPayload)
	if err != nil {
		return
	}

	event = new(Event)
	event.Header = header
	event.Meta, event.Payload = parsePayload(rawPayload)
	return
}

// WriteResult writes an event result to the stream and returns the number of
// byte written and an error if one occurs.
func WriteResult(writer io.Writer, result []byte) (n int, err error) {
	n, err = fmt.Fprintf(writer, "RESULT %v\n", len(result))
	if err != nil {
		return
	}

	n2, err := writer.Write(result)
	n += n2
	return
}

// WriteResultOK is a shortcut to write an OK result to the stream.
func WriteResultOK(writer io.Writer) (n int, err error) {
	return WriteResult(writer, []byte("OK"))
}

// WriteResultFail is a shortcut to write a Fail result to the stream.
func WriteResultFail(writer io.Writer) (n int, err error) {
	return WriteResult(writer, []byte("FAIL"))
}

// ReadResult reads an event result and returns the payload.
func ReadResult(reader io.Reader) (payload []byte, err error) {
	buf := bufio.NewReader(reader)
	header, err := buf.ReadBytes('\n')
	if err != nil {
		return
	}

	tokens := strings.SplitN(string(header), " ", 2)
	if len(tokens) != 2 || tokens[0] != "RESULT" {
		err = errors.New(fmt.Sprintf("result header invalid: %s", header))
		return
	}

	length, err := strconv.Atoi(strings.TrimRight(tokens[1], "\n"))
	if err != nil {
		return
	}

	payload = make([]byte, length)
	_, err = buf.Read(payload)
	return
}

// Listen is a simple Supervisor event listener that sends received events over
// the provided channel. It responds to Supervisor with an OK after queuing an
// event in the channel. It returns an error if one occurs or nil if the reader
// encounters an EOF.
func Listen(in io.Reader, out io.Writer, ch chan *Event) error {
	var event *Event
	var err error

	fmt.Print("READY\n")
	for {
		event, err = ReadEvent(in)
		if err != nil {
			break
		}
		ch <- event
		WriteResultOK(out)
		fmt.Print("READY\n")
	}

	if err == io.EOF {
		err = nil
	}
	return err
}
<commit_msg>Add Parent and State methods to listener event.<commit_after>package events

import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"io"
	"strconv"
	"strings"
)

var (
	parentEvents []string = []string{
		"PROCESS_COMMUNICATION",
		"PROCESS_LOG",
		"PROCESS_STATE",
		"SUPERVISOR_STATE_CHANGE",
		"TICK",
	}
)

// Event represents a Supervisor event. An event consists of a header, metadata (meta) and an optional payload.
type Event struct {
	Header  map[string]string
	Meta    map[string]string
	Payload []byte
}

// getHeaderString returns the requested header value as a string or an empty string if missing.
func (event Event) getHeaderString(key string) string {
	if value, ok := event.Header[key]; ok {
		return value
	} else {
		return ""
	}
}

// getHeaderInt returns the requested header value as an int or 0 if missing.
func (event Event) getHeaderInt(key string) int {
	strval, ok := event.Header[key]
	if !ok {
		return 0
	}

	intval, err := strconv.Atoi(strval)
	if err != nil {
		return 0
	}

	return intval
}

// String returns the event as a human readable string.
func (event Event) String() string {
	return fmt.Sprintf("Event{%d:%s}", event.Serial(), event.Name())
}

// Name returns the name of the event.
func (event Event) Name() string {
	return event.getHeaderString("eventname")
}

// Parent returns the parent type of the event or an empty string if it has none.
func (event Event) Parent() string {
	name := event.Name()
	for _, parent := range parentEvents {
		prefix := parent + "_"
		if len(prefix) <= len(name) && prefix == name[:len(prefix)] {
			return parent
		}
	}
	return ""
}

// State determines the state of the process or supervisor instance based on the name.
func (event Event) State() string {
	parent := event.Parent()
	switch parent {
	case "PROCESS_STATE":
		fallthrough
	case "SUPERVISOR_STATE_CHANGE":
		return event.Name()[len(parent)+1:]
	}
	return ""
}

// Serial returns the event serial number.
func (event Event) Serial() int {
	return event.getHeaderInt("serial")
}

// Pool returns the event pool where the event originated.
func (event Event) Pool() string {
	return event.getHeaderString("pool")
}

// PoolSerial returns the serial of the event in the event pool where the event originated.
func (event Event) PoolSerial() int {
	return event.getHeaderInt("poolserial")
}

// Version returns the version of the Supervisor instance that sent the event.
func (event Event) Version() string {
	return event.getHeaderString("ver")
}

// ToBytes converts the event to a byte array suitable for parsing.
func (event Event) ToBytes() []byte {
	mapser := func(data map[string]string) []byte {
		parts := make([]string, 0, len(data))
		for k, v := range data {
			parts = append(parts, fmt.Sprintf("%v:%v", k, v))
		}
		return []byte(strings.Join(parts, " "))
	}

	meta := mapser(event.Meta)
	payload := make([]byte, 0, len(meta)+len(event.Payload)+1)
	payload = append(payload, meta...)
	if event.Payload == nil || len(event.Payload) > 0 {
		payload = append(payload, '\n')
		payload = append(payload, event.Payload...)
	}

	event.Header["len"] = strconv.Itoa(len(payload))
	header := mapser(event.Header)
	message := make([]byte, 0, len(header)+len(payload))
	message = append(message, header...)
	message = append(message, '\n')
	message = append(message, payload...)
	return message
}

// parseMap parses a header or metadata string into a string/string map.
func parseMap(data []byte) map[string]string {
	str := strings.TrimSpace(string(data))
	mapping := make(map[string]string)
	for _, token := range strings.Split(str, " ") {
		if token == "" {
			continue
		}
		pair := strings.SplitN(token, ":", 2)
		switch len(pair) {
		case 2:
			mapping[pair[0]] = pair[1]
		case 1:
			mapping[pair[0]] = ""
		}
	}
	return mapping
}

// parsePayload parses a raw event payload into a metadata and payload.
func parsePayload(data []byte) (meta map[string]string, payload []byte) {
	if index := bytes.IndexByte(data, '\n'); index > 0 {
		meta = parseMap(data[:index])
		payload = data[index+1:]
	} else {
		meta = parseMap(data)
	}
	return
}

// ReadEvent waits for a Supervisor event and returns the parsed event. The err
// will be non-nil if an error occurred. This may include io.EOF which should
// preceed closing of the reader.
func ReadEvent(reader io.Reader) (event *Event, err error) {
	buf := bufio.NewReader(reader)
	data, err := buf.ReadBytes('\n')
	if err != nil {
		return
	}

	header := parseMap(data)
	length, err := strconv.Atoi(header["len"])
	if err != nil {
		return
	}

	rawPayload := make([]byte, length)
	_, err = buf.Read(rawPayload)
	if err != nil {
		return
	}

	event = new(Event)
	event.Header = header
	event.Meta, event.Payload = parsePayload(rawPayload)
	return
}

// WriteResult writes an event result to the stream and returns the number of
// byte written and an error if one occurs.
func WriteResult(writer io.Writer, result []byte) (n int, err error) {
	n, err = fmt.Fprintf(writer, "RESULT %v\n", len(result))
	if err != nil {
		return
	}

	n2, err := writer.Write(result)
	n += n2
	return
}

// WriteResultOK is a shortcut to write an OK result to the stream.
func WriteResultOK(writer io.Writer) (n int, err error) {
	return WriteResult(writer, []byte("OK"))
}

// WriteResultFail is a shortcut to write a Fail result to the stream.
func WriteResultFail(writer io.Writer) (n int, err error) {
	return WriteResult(writer, []byte("FAIL"))
}

// ReadResult reads an event result and returns the payload.
func ReadResult(reader io.Reader) (payload []byte, err error) {
	buf := bufio.NewReader(reader)
	header, err := buf.ReadBytes('\n')
	if err != nil {
		return
	}

	tokens := strings.SplitN(string(header), " ", 2)
	if len(tokens) != 2 || tokens[0] != "RESULT" {
		err = errors.New(fmt.Sprintf("result header invalid: %s", header))
		return
	}

	length, err := strconv.Atoi(strings.TrimRight(tokens[1], "\n"))
	if err != nil {
		return
	}

	payload = make([]byte, length)
	_, err = buf.Read(payload)
	return
}

// Listen is a simple Supervisor event listener that sends received events over
// the provided channel. It responds to Supervisor with an OK after queuing an
// event in the channel. It returns an error if one occurs or nil if the reader
// encounters an EOF.
func Listen(in io.Reader, out io.Writer, ch chan *Event) error {
	var event *Event
	var err error

	fmt.Print("READY\n")
	for {
		event, err = ReadEvent(in)
		if err != nil {
			break
		}
		ch <- event
		WriteResultOK(out)
		fmt.Print("READY\n")
	}

	if err == io.EOF {
		err = nil
	}
	return err
}
<|endoftext|>


<commit_before>/*
	Package server implements the mix server.
*/
package server

import (
	"anonymous-messaging/config"
	"anonymous-messaging/helpers"
	"anonymous-messaging/logging"
	"anonymous-messaging/networker"
	"anonymous-messaging/node"
	"anonymous-messaging/sphinx"

	"github.com/protobuf/proto"

	"net"
)

var logLocal = logging.PackageLogger()

type MixServerIt interface {
	networker.NetworkServer
	networker.NetworkClient
}

type MixServer struct {
	Id       string
	Host     string
	Port     string
	Listener *net.TCPListener
	node.Mix

	Config config.MixConfig
}

func (m *MixServer) ReceivedPacket(packet []byte) error {
	logLocal.Info("Received new sphinx packet")

	c := make(chan []byte)
	cAdr := make(chan sphinx.Hop)
	cFlag := make(chan string)
	errCh := make(chan error)

	go m.ProcessPacket(packet, c, cAdr, cFlag, errCh)
	dePacket := <-c
	nextHop := <-cAdr
	flag := <-cFlag
	err := <-errCh

	if err != nil {
		return err
	}

	if flag == "\xF1" {
		m.ForwardPacket(dePacket, nextHop.Address)
	} else {
		logLocal.Info("Packet has non-forward flag. Packet dropped")
	}
	return nil
}

func (m *MixServer) ForwardPacket(sphinxPacket []byte, address string) error {
	packetBytes, err := config.WrapWithFlag(commFlag, sphinxPacket)
	if err != nil {
		return err
	}
	err = m.Send(packetBytes, address)
	if err != nil {
		return err
	}

	return nil
}

func (m *MixServer) Send(packet []byte, address string) error {

	conn, err := net.Dial("tcp", address)
	if err != nil {
		return err
	}
	defer conn.Close()

	_, err = conn.Write(packet)
	if err != nil {
		return err
	}
	return nil
}

func (m *MixServer) Start() error {
	defer m.Run()

	return nil
}

func (m *MixServer) Run() {

	defer m.Listener.Close()
	finish := make(chan bool)

	go func() {
		logLocal.Infof("Listening on %s", m.Host+":"+m.Port)
		m.ListenForIncomingConnections()
	}()

	<-finish
}

func (m *MixServer) ListenForIncomingConnections() {
	for {
		conn, err := m.Listener.Accept()

		if err != nil {
			logLocal.WithError(err).Error(err)
		} else {
			logLocal.Infof("Received connection from %s", conn.RemoteAddr())
			errs := make(chan error, 1)
			go m.HandleConnection(conn, errs)
			err = <-errs
			if err != nil {
				logLocal.WithError(err).Error(err)
			}
		}
	}
}

func (m *MixServer) HandleConnection(conn net.Conn, errs chan<- error) {
	defer conn.Close()

	buff := make([]byte, 1024)
	reqLen, err := conn.Read(buff)
	if err != nil {
		errs <- err
	}

	var packet config.GeneralPacket
	err = proto.Unmarshal(buff[:reqLen], &packet)
	if err != nil {
		errs <- err
	}

	switch packet.Flag {
	case commFlag:
		err = m.ReceivedPacket(packet.Data)
		if err != nil {
			errs <- err
		}
	default:
		logLocal.Infof("Packet flag %s not recognised. Packet dropped", packet.Flag)
	}
}

func NewMixServer(id, host, port string, pubKey []byte, prvKey []byte, pkiPath string) (*MixServer, error) {
	node := node.Mix{Id: id, PubKey: pubKey, PrvKey: prvKey}
	mixServer := MixServer{Id: id, Host: host, Port: port, Mix: node, Listener: nil}
	mixServer.Config = config.MixConfig{Id: mixServer.Id, Host: mixServer.Host, Port: mixServer.Port, PubKey: mixServer.PubKey}

	configBytes, err := proto.Marshal(&mixServer.Config)
	if err != nil {
		return nil, err
	}
	err = helpers.AddToDatabase(pkiPath, "Pki", mixServer.Id, "Mix", configBytes)
	if err != nil {
		return nil, err
	}

	addr, err := helpers.ResolveTCPAddress(mixServer.Host, mixServer.Port)

	if err != nil {
		return nil, err
	}
	mixServer.Listener, err = net.ListenTCP("tcp", addr)

	if err != nil {
		return nil, err
	}

	return &mixServer, nil
}
<commit_msg>Change mixServer functions to private<commit_after>/*
	Package server implements the mix server.
*/
package server

import (
	"anonymous-messaging/config"
	"anonymous-messaging/helpers"
	"anonymous-messaging/logging"
	"anonymous-messaging/networker"
	"anonymous-messaging/node"
	"anonymous-messaging/sphinx"

	"github.com/protobuf/proto"

	"net"
)

var logLocal = logging.PackageLogger()

type MixServerIt interface {
	networker.NetworkServer
	networker.NetworkClient
}

type MixServer struct {
	Id       string
	Host     string
	Port     string
	Listener *net.TCPListener
	node.Mix

	Config config.MixConfig
}

func (m *MixServer) receivedPacket(packet []byte) error {
	logLocal.Info("Received new sphinx packet")

	c := make(chan []byte)
	cAdr := make(chan sphinx.Hop)
	cFlag := make(chan string)
	errCh := make(chan error)

	go m.ProcessPacket(packet, c, cAdr, cFlag, errCh)
	dePacket := <-c
	nextHop := <-cAdr
	flag := <-cFlag
	err := <-errCh

	if err != nil {
		return err
	}

	if flag == "\xF1" {
		m.forwardPacket(dePacket, nextHop.Address)
	} else {
		logLocal.Info("Packet has non-forward flag. Packet dropped")
	}
	return nil
}

func (m *MixServer) forwardPacket(sphinxPacket []byte, address string) error {
	packetBytes, err := config.WrapWithFlag(commFlag, sphinxPacket)
	if err != nil {
		return err
	}
	err = m.send(packetBytes, address)
	if err != nil {
		return err
	}

	return nil
}

func (m *MixServer) send(packet []byte, address string) error {

	conn, err := net.Dial("tcp", address)
	if err != nil {
		return err
	}
	defer conn.Close()

	_, err = conn.Write(packet)
	if err != nil {
		return err
	}
	return nil
}

func (m *MixServer) Start() error {
	defer m.run()

	return nil
}

func (m *MixServer) run() {

	defer m.Listener.Close()
	finish := make(chan bool)

	go func() {
		logLocal.Infof("Listening on %s", m.Host+":"+m.Port)
		m.listenForIncomingConnections()
	}()

	<-finish
}

func (m *MixServer) listenForIncomingConnections() {
	for {
		conn, err := m.Listener.Accept()

		if err != nil {
			logLocal.WithError(err).Error(err)
		} else {
			logLocal.Infof("Received connection from %s", conn.RemoteAddr())
			errs := make(chan error, 1)
			go m.handleConnection(conn, errs)
			err = <-errs
			if err != nil {
				logLocal.WithError(err).Error(err)
			}
		}
	}
}

func (m *MixServer) handleConnection(conn net.Conn, errs chan<- error) {
	defer conn.Close()

	buff := make([]byte, 1024)
	reqLen, err := conn.Read(buff)
	if err != nil {
		errs <- err
	}

	var packet config.GeneralPacket
	err = proto.Unmarshal(buff[:reqLen], &packet)
	if err != nil {
		errs <- err
	}

	switch packet.Flag {
	case commFlag:
		err = m.receivedPacket(packet.Data)
		if err != nil {
			errs <- err
		}
	default:
		logLocal.Infof("Packet flag %s not recognised. Packet dropped", packet.Flag)
	}
}

func NewMixServer(id, host, port string, pubKey []byte, prvKey []byte, pkiPath string) (*MixServer, error) {
	node := node.Mix{Id: id, PubKey: pubKey, PrvKey: prvKey}
	mixServer := MixServer{Id: id, Host: host, Port: port, Mix: node, Listener: nil}
	mixServer.Config = config.MixConfig{Id: mixServer.Id, Host: mixServer.Host, Port: mixServer.Port, PubKey: mixServer.PubKey}

	configBytes, err := proto.Marshal(&mixServer.Config)
	if err != nil {
		return nil, err
	}
	err = helpers.AddToDatabase(pkiPath, "Pki", mixServer.Id, "Mix", configBytes)
	if err != nil {
		return nil, err
	}

	addr, err := helpers.ResolveTCPAddress(mixServer.Host, mixServer.Port)

	if err != nil {
		return nil, err
	}
	mixServer.Listener, err = net.ListenTCP("tcp", addr)

	if err != nil {
		return nil, err
	}

	return &mixServer, nil
}
<|endoftext|>


<commit_before>package jwd_test

import (
	"fmt"
	"github.com/9uuso/go-jaro-winkler-distance"
)

func main() {
	res := jwd.Calculate("DIXON", "DICKSONX")
	fmt.Println(res)
}
<commit_msg>no message<commit_after>package jwd_test

import (
	"fmt"
	"github.com/9uuso/go-jaro-winkler-distance"
)

func Example() {
	res := jwd.Calculate("DIXON", "DICKSONX")
	fmt.Println(res)
}
<|endoftext|>


<commit_before>package nlp

import "fmt"

func Example() {
	testCorpus := []string{
		"The quick brown fox jumped over the lazy dog",
		"hey diddle diddle, the cat and the fiddle",
		"the cow jumped over the moon",
		"the little dog laughed to see such fun",
		"and the dish ran away with the spoon",
	}

	query := "the brown fox ran around the dog"

	tokeniser := NewCountVectoriser()
	transformer := NewTfidfTransformer()

	// set k (the number of dimensions following truncation) to 2
	reducer := NewTruncatedSVD(2)

	// Transform the corpus into an LSI fitting the model to the documents in the process
	mat, _ := tokeniser.FitTransform(testCorpus...)
	mat, _ = transformer.FitTransform(mat)
	lsi, _ := reducer.FitTransform(mat)

	// run the query through the same pipeline that was fitted to the corpus and
	// to project it into the same dimensional space
	mat, _ = tokeniser.Transform(query)
	mat, _ = transformer.Transform(mat)
	queryVector, _ := reducer.Transform(mat)

	// iterate over document feature vectors (columns) in the LSI and compare with the
	// query vector for similarity.  Similarity is determined by the difference between
	// the angles of the vectors known as the cosine similarity
	highestSimilarity := -1.0
	var matched int
	_, docs := lsi.Dims()
	for i := 0; i < docs; i++ {
		similarity := CosineSimilarity(queryVector.ColView(0), lsi.ColView(i))
		if similarity > highestSimilarity {
			matched = i
			highestSimilarity = similarity
		}
	}

	fmt.Printf("Matched %s with a Cosine Similarity of %f", testCorpus[matched], highestSimilarity)
}
<commit_msg>increased k to 4 to improve results<commit_after>package nlp

import "fmt"

func Example() {
	testCorpus := []string{
		"The quick brown fox jumped over the lazy dog",
		"hey diddle diddle, the cat and the fiddle",
		"the cow jumped over the moon",
		"the little dog laughed to see such fun",
		"and the dish ran away with the spoon",
	}

	query := "the brown fox ran around the dog"

	tokeniser := NewCountVectoriser()
	transformer := NewTfidfTransformer()

	// set k (the number of dimensions following truncation) to 4
	reducer := NewTruncatedSVD(4)

	// Transform the corpus into an LSI fitting the model to the documents in the process
	mat, _ := tokeniser.FitTransform(testCorpus...)
	mat, _ = transformer.FitTransform(mat)
	lsi, _ := reducer.FitTransform(mat)

	// run the query through the same pipeline that was fitted to the corpus and
	// to project it into the same dimensional space
	mat, _ = tokeniser.Transform(query)
	mat, _ = transformer.Transform(mat)
	queryVector, _ := reducer.Transform(mat)

	// iterate over document feature vectors (columns) in the LSI and compare with the
	// query vector for similarity.  Similarity is determined by the difference between
	// the angles of the vectors known as the cosine similarity
	highestSimilarity := -1.0
	var matched int
	_, docs := lsi.Dims()
	for i := 0; i < docs; i++ {
		similarity := CosineSimilarity(queryVector.ColView(0), lsi.ColView(i))
		fmt.Printf("Comparing '%s' = %f\n", testCorpus[i], similarity)
		if similarity > highestSimilarity {
			matched = i
			highestSimilarity = similarity
		}
	}

	fmt.Printf("Matched '%s' with a Cosine Similarity of %f\n", testCorpus[matched], highestSimilarity)
}
<|endoftext|>


<commit_before>package goquery_test

import (
	"fmt"
	"log"
	"net/http"

	"github.com/PuerkitoBio/goquery"
)

// This example scrapes the reviews shown on the home page of metalsucks.net.
func Example() {
	// Request the HTML page.
	res, err := http.Get("http://metalsucks.net")
	if err != nil {
		log.Fatal(err)
	}
	defer res.Body.Close()
	if res.StatusCode != 200 {
		log.Fatalf("status code error: %d %s", res.StatusCode, res.Status)
	}

	// Load the HTML document
	doc, err := goquery.NewDocumentFromReader(res.Body)
	if err != nil {
		log.Fatal(err)
	}

	// Find the review items
	doc.Find(".sidebar-reviews article .content-block").Each(func(i int, s *goquery.Selection) {
		// For each item found, get the band and title
		band := s.Find("a").Text()
		title := s.Find("i").Text()
		fmt.Printf("Review %d: %s - %s\n", i, band, title)
	})
	// To see the output of the Example while running the test suite (go test), simply
	// remove the leading "x" before Output on the next line. This will cause the
	// example to fail (all the "real" tests should pass).

	// xOutput: voluntarily fail the Example output.
}
<commit_msg>add examples for NewDocumentFromReader (#254)<commit_after>package goquery_test

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"strings"

	"github.com/PuerkitoBio/goquery"
)

// This example scrapes the reviews shown on the home page of metalsucks.net.
func Example() {
	// Request the HTML page.
	res, err := http.Get("http://metalsucks.net")
	if err != nil {
		log.Fatal(err)
	}
	defer res.Body.Close()
	if res.StatusCode != 200 {
		log.Fatalf("status code error: %d %s", res.StatusCode, res.Status)
	}

	// Load the HTML document
	doc, err := goquery.NewDocumentFromReader(res.Body)
	if err != nil {
		log.Fatal(err)
	}

	// Find the review items
	doc.Find(".sidebar-reviews article .content-block").Each(func(i int, s *goquery.Selection) {
		// For each item found, get the band and title
		band := s.Find("a").Text()
		title := s.Find("i").Text()
		fmt.Printf("Review %d: %s - %s\n", i, band, title)
	})
	// To see the output of the Example while running the test suite (go test), simply
	// remove the leading "x" before Output on the next line. This will cause the
	// example to fail (all the "real" tests should pass).

	// xOutput: voluntarily fail the Example output.
}

// This example shows how to use NewDocumentFromReader from a file.
func ExampleNewDocumentFromReader_file() {
	// create from a file
	f, err := os.Open("some/file.html")
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()
	doc, err := goquery.NewDocumentFromReader(f)
	if err != nil {
		log.Fatal(err)
	}
	// use the goquery document...
	_ = doc.Find("h1")
}

// This example shows how to use NewDocumentFromReader from a string.
func ExampleNewDocumentFromReader_string() {
	// create from a string
	data := `

		<title>My document</title>

Header

`

	doc, err := goquery.NewDocumentFromReader(strings.NewReader(data))
	if err != nil {
		log.Fatal(err)
	}
	header := doc.Find("h1").Text()
	fmt.Println(header)

	// Output: Header
}
<|endoftext|>


<commit_before>package devastator_test

// import "github.com/nbusy/devastator"
//
// // todo: add server.go setup example
//
// // Example demonstrating the use of Devastator server.
// func Example() {
// 	s := devastator.NewServer(nil, nil, "", false)
// }
<commit_msg>fix example<commit_after>package devastator_test

import (
	"log"

	"github.com/nbusy/devastator"
)

// todo: add server.go setup example

// Example demonstrating the use of Devastator server.
func Example() {
	s, err := devastator.NewServer(nil, nil, "", false)
	if err == nil && s != nil {
		log.Println("Connected")
	}
}
<|endoftext|>


<commit_before>package evaluation

import (
	"bufio"
	"bytes"
	"fmt"
	"os"
	"os/user"
	"path/filepath"

	"github.com/Zac-Garby/pluto/ast"
)

type Context struct {
	Store     map[string]Object
	Functions []*Function
	Packages  map[string]Package

	Outer *Context
}

func NewContext() *Context {
	return &Context{
		Store:    make(map[string]Object),
		Packages: make(map[string]Package),
	}
}

func (c *Context) Enclose() *Context {
	return &Context{
		Outer:    c,
		Packages: make(map[string]Package),
	}
}

func (c *Context) EncloseWith(args map[string]Object) *Context {
	return &Context{
		Store:    args,
		Outer:    c,
		Packages: make(map[string]Package),
	}
}

func (c *Context) Get(key string) Object {
	if obj, ok := c.Store[key]; ok {
		return obj
	} else if c.Outer != nil {
		return c.Outer.Get(key)
	} else {
		return nil
	}
}

func (c *Context) Assign(key string, obj Object) {
	if c.Outer != nil {
		if v := c.Outer.Get(key); v != nil {
			c.Outer.Assign(key, obj)
			return
		}
	}

	c.Store[key] = obj
}

func (c *Context) Declare(key string, obj Object) {
	c.Store[key] = obj
}

func (c *Context) Import(name string) Object {
	var root string

	if r, exists := os.LookupEnv("PLUTO"); exists {
		root = r
	} else {
		usr, err := user.Current()
		if err != nil {
			panic(err)
		}

		root = filepath.Join(usr.HomeDir, "pluto")
	}

	var pkg *os.File

	path := filepath.Join(root, "libraries", name)

	// if the package can be found in $PLUTO/libraries
	if _, err := os.Stat(path); err != nil {
		return Err(c, "package '%s' not found in %s", "ImportError", name, filepath.Join(root, "libraries"))
	} else {
		metaPath := filepath.Join(path, fmt.Sprintf("%s.yaml", name))
		pkg, err = os.Open(metaPath)

		if err != nil {
			return Err(c, "'%s' not found in %s", "ImportError", name+".yaml", path)
		}
	}

	pkgReader := bufio.NewReader(pkg)

	buf := new(bytes.Buffer)
	buf.ReadFrom(pkgReader)

	fmt.Println(buf.String())

	return O_NULL
}

func (c *Context) AddFunction(fn Object) {
	if _, ok := fn.(*Function); !ok {
		panic("Not a function!")
	}

	c.Functions = append(c.Functions, fn.(*Function))
}

func (c *Context) GetFunction(pattern []ast.Expression) interface{} {
	for _, fn := range c.Functions {
		if len(pattern) != len(fn.Pattern) {
			continue
		}

		matched := true

		for i, item := range pattern {
			fItem := fn.Pattern[i]

			if itemID, ok := item.(*ast.Identifier); ok {
				if fItemID, ok := fItem.(*ast.Identifier); ok {
					if itemID.Value != fItemID.Value {
						matched = false
					}
				}
			} else if _, ok := item.(*ast.Argument); !ok {
				matched = false
			} else if _, ok := fItem.(*ast.Parameter); !ok {
				matched = false
			}
		}

		if matched {
			return fn
		}
	}

	if c.Outer != nil {
		return c.Outer.GetFunction(pattern)
	}

	for _, fn := range GetBuiltins() {
		if len(pattern) != len(fn.Pattern) {
			continue
		}

		matched := true

		for i, item := range pattern {
			fItem := fn.Pattern[i]

			if itemID, ok := item.(*ast.Identifier); ok {
				if fItem[0] != '$' {
					if itemID.Value != fItem {
						matched = false
					}
				}
			} else if _, ok := item.(*ast.Argument); !ok {
				matched = false
			} else if !(fItem[0] == '$') {
				matched = false
			}
		}

		if matched {
			return fn
		}
	}

	return nil
}
<commit_msg>Read and unmarshall <pkg id>.yaml<commit_after>package evaluation

import (
	"bufio"
	"bytes"
	"fmt"
	"os"
	"os/user"
	"path/filepath"

	"github.com/Zac-Garby/pluto/ast"

	"gopkg.in/yaml.v2"
)

type Context struct {
	Store     map[string]Object
	Functions []*Function
	Packages  map[string]Package

	Outer *Context
}

func NewContext() *Context {
	return &Context{
		Store:    make(map[string]Object),
		Packages: make(map[string]Package),
	}
}

func (c *Context) Enclose() *Context {
	return &Context{
		Outer:    c,
		Packages: make(map[string]Package),
	}
}

func (c *Context) EncloseWith(args map[string]Object) *Context {
	return &Context{
		Store:    args,
		Outer:    c,
		Packages: make(map[string]Package),
	}
}

func (c *Context) Get(key string) Object {
	if obj, ok := c.Store[key]; ok {
		return obj
	} else if c.Outer != nil {
		return c.Outer.Get(key)
	} else {
		return nil
	}
}

func (c *Context) Assign(key string, obj Object) {
	if c.Outer != nil {
		if v := c.Outer.Get(key); v != nil {
			c.Outer.Assign(key, obj)
			return
		}
	}

	c.Store[key] = obj
}

func (c *Context) Declare(key string, obj Object) {
	c.Store[key] = obj
}

func (c *Context) Import(name string) Object {
	var root string

	if r, exists := os.LookupEnv("PLUTO"); exists {
		root = r
	} else {
		usr, err := user.Current()
		if err != nil {
			panic(err)
		}

		root = filepath.Join(usr.HomeDir, "pluto")
	}

	var pkgFile *os.File

	path := filepath.Join(root, "libraries", name)

	// if the package can be found in $PLUTO/libraries
	if _, err := os.Stat(path); err != nil {
		return Err(c, "package '%s' not found in %s", "ImportError", name, filepath.Join(root, "libraries"))
	} else {
		metaPath := filepath.Join(path, fmt.Sprintf("%s.yaml", name))
		pkgFile, err = os.Open(metaPath)

		if err != nil {
			return Err(c, "'%s' not found in %s", "ImportError", name+".yaml", path)
		}
	}

	pkgReader := bufio.NewReader(pkgFile)

	buf := new(bytes.Buffer)
	if _, err := buf.ReadFrom(pkgReader); err != nil {
		panic(err)
	}

	pkgData := buf.String()

	pkg := &Package{
		Context: c,
		Used:    false,
	}

	yaml.Unmarshal([]byte(pkgData), &pkg.Meta)

	return O_NULL
}

func (c *Context) AddFunction(fn Object) {
	if _, ok := fn.(*Function); !ok {
		panic("Not a function!")
	}

	c.Functions = append(c.Functions, fn.(*Function))
}

func (c *Context) GetFunction(pattern []ast.Expression) interface{} {
	for _, fn := range c.Functions {
		if len(pattern) != len(fn.Pattern) {
			continue
		}

		matched := true

		for i, item := range pattern {
			fItem := fn.Pattern[i]

			if itemID, ok := item.(*ast.Identifier); ok {
				if fItemID, ok := fItem.(*ast.Identifier); ok {
					if itemID.Value != fItemID.Value {
						matched = false
					}
				}
			} else if _, ok := item.(*ast.Argument); !ok {
				matched = false
			} else if _, ok := fItem.(*ast.Parameter); !ok {
				matched = false
			}
		}

		if matched {
			return fn
		}
	}

	if c.Outer != nil {
		return c.Outer.GetFunction(pattern)
	}

	for _, fn := range GetBuiltins() {
		if len(pattern) != len(fn.Pattern) {
			continue
		}

		matched := true

		for i, item := range pattern {
			fItem := fn.Pattern[i]

			if itemID, ok := item.(*ast.Identifier); ok {
				if fItem[0] != '$' {
					if itemID.Value != fItem {
						matched = false
					}
				}
			} else if _, ok := item.(*ast.Argument); !ok {
				matched = false
			} else if !(fItem[0] == '$') {
				matched = false
			}
		}

		if matched {
			return fn
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package eveConsumer

import (
	"fmt"
	"strconv"
	"strings"
	"time"

	"github.com/antihax/evedata/models"
	"github.com/garyburd/redigo/redis"
)

func init() {

	addConsumer("market", marketHistoryConsumer, "EVEDATA_marketHistory")
	addConsumer("market", marketRegionConsumer, "")

	addTrigger("market", marketMaintTrigger)
	addTrigger("market", marketHistoryTrigger)

}

// Add market history items to the queue
func marketMaintTrigger(c *EVEConsumer) (bool, error) {

	// Skip if we are not ready
	cacheUntilTime, _, err := models.GetServiceState("marketMaint")
	if err != nil {
		return false, err
	}

	// Check if it is time to update the market history
	curTime := time.Now().UTC()
	if cacheUntilTime.Before(curTime) {
		newTime := curTime.Add(time.Hour * 1)

		err = models.SetServiceState("marketMaint", newTime, 1)
		if err != nil {
			return false, err
		}

		err = models.MaintMarket()
	}
	return true, err
}

// Add market history items to the queue
func marketHistoryTrigger(c *EVEConsumer) (bool, error) {

	// Skip if we are not ready
	cacheUntilTime, _, err := models.GetServiceState("marketHistory")
	if err != nil {
		return false, err
	}

	// Check if it is time to update the market history
	curTime := time.Now().UTC()
	if cacheUntilTime.Before(curTime) {
		// We wont repeat this for 24 hours just after it updates.
		curTime = curTime.Add(time.Hour * 24)
		newTime := time.Date(curTime.Year(), curTime.Month(), curTime.Day(), 0, 30, 0, 0, time.UTC)

		err = models.SetServiceState("marketHistory", newTime, 1)
		if err != nil {
			return false, err
		}

		// Get lists to build our requests
		regions, err := models.GetMarketRegions()
		if err != nil {
			return false, err
		}
		types, err := models.GetMarketTypes()
		if err != nil {
			return false, err
		}

		// Get a redis connection from the pool
		red := c.ctx.Cache.Get()
		defer red.Close()

		// Load types into redis queue
		// Build a pipeline request to add the region IDs to redis
		for _, r := range regions {
			// Add regions into marketOrders just in case they disapear.
			// NX = Don't update score if element exists
			red.Send("ZADD", "EVEDATA_marketRegions", "NX", time.Now().UTC().Unix(), r.RegionID)
			for _, t := range types {
				red.Send("SADD", "EVEDATA_marketHistory", fmt.Sprintf("%d:%d", r.RegionID, t.TypeID))
			}
		}

		// Send the request to add
		red.Flush()
	}
	return true, err
}

func (c *EVEConsumer) marketRegionAddRegion(v int, t int64, redisPtr *redis.Conn) {
	r := *redisPtr
	r.Do("ZADD", "EVEDATA_marketRegions", t, v)
}

func marketHistoryConsumer(c *EVEConsumer, redisPtr *redis.Conn) (bool, error) {
	r := *redisPtr
	ret, err := r.Do("SPOP", "EVEDATA_marketHistory")
	if err != nil {
		return false, err
	} else if ret == nil {
		return false, nil
	}
	v, err := redis.String(ret, err)
	if err != nil {
		return false, err
	}

	data := strings.Split(v, ":")
	regionID, err := strconv.Atoi(data[0])
	typeID, err := strconv.Atoi(data[1])

	// Process Market History
	h, res, err := c.ctx.ESI.ESI.MarketApi.GetMarketsRegionIdHistory(nil, (int32)(regionID), (int32)(typeID), nil)
	if err != nil {
		if res.StatusCode >= 500 {
			// Something went wrong... let's try again..
			r.Do("SADD", "EVEDATA_marketHistory", v)
		}
		return false, err
	}

	// There is nothing.
	if len(h) == 0 {
		return false, nil
	}

	var values []string

	ignoreBefore := time.Now().UTC().Add(time.Hour * 24 * -2)

	for _, e := range h {
		orderDate, err := time.Parse("2006-01-02", e.Date)
		if err != nil {
			return false, err
		}

		if orderDate.After(ignoreBefore) {
			values = append(values, fmt.Sprintf("(%q,%f,%f,%f,%d,%d,%d,%d)",
				e.Date, e.Lowest, e.Highest, e.Average,
				e.Volume, e.OrderCount, typeID, regionID))
		}
	}

	if len(values) == 0 {
		return false, nil
	}

	stmt := fmt.Sprintf("INSERT INTO evedata.market_history (date, low, high, mean, quantity, orders, itemID, regionID) VALUES \n%s ON DUPLICATE KEY UPDATE date=date", strings.Join(values, ",\n"))

	tx, err := models.Begin()
	if err != nil {
		return false, err
	}
	_, err = tx.Exec(stmt)
	if err != nil {
		tx.Rollback()
		return false, err
	}

	err = models.RetryTransaction(tx)
	if err != nil {
		return false, err
	}

	return true, nil
}

// Check the regions for their cache time to expire
func marketRegionConsumer(c *EVEConsumer, redisPtr *redis.Conn) (bool, error) {
	r := *redisPtr
	t := time.Now().UTC().Unix()

	// Get a list of regions by expired keys.
	if arr, err := redis.MultiBulk(r.Do("ZRANGEBYSCORE", "EVEDATA_marketRegions", 0, t)); err != nil {
		return false, err
	} else {
		// Add the region to the queue
		idList, _ := redis.Strings(arr, nil)
		for _, id := range idList {
			id, err := strconv.Atoi(id)
			if err != nil {
				return false, nil
			}
			if err := r.Send("SADD", "EVEDATA_marketOrders", id); err != nil {
				return false, err
			}
		}
	}

	// Removed the expired keys
	if err := r.Send("ZREMRANGEBYSCORE", "EVEDATA_marketRegions", 0, t); err != nil {
		return false, err
	}

	// Run the commands.
	err := r.Flush()

	return true, err
}
<commit_msg>disable market history consumer<commit_after>package eveConsumer

import (
	"fmt"
	"strconv"
	"strings"
	"time"

	"github.com/antihax/evedata/models"
	"github.com/garyburd/redigo/redis"
)

func init() {

	//addConsumer("market", marketHistoryConsumer, "EVEDATA_marketHistory")
	//addConsumer("market", marketRegionConsumer, "")

	addTrigger("market", marketMaintTrigger)
	//addTrigger("market", marketHistoryTrigger)

}

// Add market history items to the queue
func marketMaintTrigger(c *EVEConsumer) (bool, error) {

	// Skip if we are not ready
	cacheUntilTime, _, err := models.GetServiceState("marketMaint")
	if err != nil {
		return false, err
	}

	// Check if it is time to update the market history
	curTime := time.Now().UTC()
	if cacheUntilTime.Before(curTime) {
		newTime := curTime.Add(time.Hour * 1)

		err = models.SetServiceState("marketMaint", newTime, 1)
		if err != nil {
			return false, err
		}

		err = models.MaintMarket()
	}
	return true, err
}

// Add market history items to the queue
func marketHistoryTrigger(c *EVEConsumer) (bool, error) {

	// Skip if we are not ready
	cacheUntilTime, _, err := models.GetServiceState("marketHistory")
	if err != nil {
		return false, err
	}

	// Check if it is time to update the market history
	curTime := time.Now().UTC()
	if cacheUntilTime.Before(curTime) {
		// We wont repeat this for 24 hours just after it updates.
		curTime = curTime.Add(time.Hour * 24)
		newTime := time.Date(curTime.Year(), curTime.Month(), curTime.Day(), 0, 30, 0, 0, time.UTC)

		err = models.SetServiceState("marketHistory", newTime, 1)
		if err != nil {
			return false, err
		}

		// Get lists to build our requests
		regions, err := models.GetMarketRegions()
		if err != nil {
			return false, err
		}
		types, err := models.GetMarketTypes()
		if err != nil {
			return false, err
		}

		// Get a redis connection from the pool
		red := c.ctx.Cache.Get()
		defer red.Close()

		// Load types into redis queue
		// Build a pipeline request to add the region IDs to redis
		for _, r := range regions {
			// Add regions into marketOrders just in case they disapear.
			// NX = Don't update score if element exists
			red.Send("ZADD", "EVEDATA_marketRegions", "NX", time.Now().UTC().Unix(), r.RegionID)
			for _, t := range types {
				red.Send("SADD", "EVEDATA_marketHistory", fmt.Sprintf("%d:%d", r.RegionID, t.TypeID))
			}
		}

		// Send the request to add
		red.Flush()
	}
	return true, err
}

func (c *EVEConsumer) marketRegionAddRegion(v int, t int64, redisPtr *redis.Conn) {
	r := *redisPtr
	r.Do("ZADD", "EVEDATA_marketRegions", t, v)
}

func marketHistoryConsumer(c *EVEConsumer, redisPtr *redis.Conn) (bool, error) {
	r := *redisPtr
	ret, err := r.Do("SPOP", "EVEDATA_marketHistory")
	if err != nil {
		return false, err
	} else if ret == nil {
		return false, nil
	}
	v, err := redis.String(ret, err)
	if err != nil {
		return false, err
	}

	data := strings.Split(v, ":")
	regionID, err := strconv.Atoi(data[0])
	typeID, err := strconv.Atoi(data[1])

	// Process Market History
	h, res, err := c.ctx.ESI.ESI.MarketApi.GetMarketsRegionIdHistory(nil, (int32)(regionID), (int32)(typeID), nil)
	if err != nil {
		if res.StatusCode >= 500 {
			// Something went wrong... let's try again..
			r.Do("SADD", "EVEDATA_marketHistory", v)
		}
		return false, err
	}

	// There is nothing.
	if len(h) == 0 {
		return false, nil
	}

	var values []string

	ignoreBefore := time.Now().UTC().Add(time.Hour * 24 * -2)

	for _, e := range h {
		orderDate, err := time.Parse("2006-01-02", e.Date)
		if err != nil {
			return false, err
		}

		if orderDate.After(ignoreBefore) {
			values = append(values, fmt.Sprintf("(%q,%f,%f,%f,%d,%d,%d,%d)",
				e.Date, e.Lowest, e.Highest, e.Average,
				e.Volume, e.OrderCount, typeID, regionID))
		}
	}

	if len(values) == 0 {
		return false, nil
	}

	stmt := fmt.Sprintf("INSERT INTO evedata.market_history (date, low, high, mean, quantity, orders, itemID, regionID) VALUES \n%s ON DUPLICATE KEY UPDATE date=date", strings.Join(values, ",\n"))

	tx, err := models.Begin()
	if err != nil {
		return false, err
	}
	_, err = tx.Exec(stmt)
	if err != nil {
		tx.Rollback()
		return false, err
	}

	err = models.RetryTransaction(tx)
	if err != nil {
		return false, err
	}

	return true, nil
}

// Check the regions for their cache time to expire
func marketRegionConsumer(c *EVEConsumer, redisPtr *redis.Conn) (bool, error) {
	r := *redisPtr
	t := time.Now().UTC().Unix()

	// Get a list of regions by expired keys.
	if arr, err := redis.MultiBulk(r.Do("ZRANGEBYSCORE", "EVEDATA_marketRegions", 0, t)); err != nil {
		return false, err
	} else {
		// Add the region to the queue
		idList, _ := redis.Strings(arr, nil)
		for _, id := range idList {
			id, err := strconv.Atoi(id)
			if err != nil {
				return false, nil
			}
			if err := r.Send("SADD", "EVEDATA_marketOrders", id); err != nil {
				return false, err
			}
		}
	}

	// Removed the expired keys
	if err := r.Send("ZREMRANGEBYSCORE", "EVEDATA_marketRegions", 0, t); err != nil {
		return false, err
	}

	// Run the commands.
	err := r.Flush()

	return true, err
}
<|endoftext|>


<commit_before>// Copyright 2016 CoreOS, Inc.
//
// 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 types

import (
	"errors"
	"path/filepath"

	"github.com/coreos/ignition/config/validate/report"
)

var (
	ErrPathRelative = errors.New("path not absolute")
)

type Path string

func (p Path) MarshalJSON() ([]byte, error) {
	return []byte(`"` + string(p) + `"`), nil
}

func (p Path) Validate() report.Report {
	if !filepath.IsAbs(string(p)) {
		return report.ReportFromError(ErrPathRelative, report.EntryError)
	}
	return report.Report{}
}
<commit_msg>type/path: Fix isAbs() validation on Windows.<commit_after>// Copyright 2016 CoreOS, Inc.
//
// 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 types

import (
	"errors"
	"path"

	"github.com/coreos/ignition/config/validate/report"
)

var (
	ErrPathRelative = errors.New("path not absolute")
)

type Path string

func (p Path) MarshalJSON() ([]byte, error) {
	return []byte(`"` + string(p) + `"`), nil
}

func (p Path) Validate() report.Report {
	if !path.IsAbs(string(p)) {
		return report.ReportFromError(ErrPathRelative, report.EntryError)
	}
	return report.Report{}
}
<|endoftext|>


<commit_before>package config

import (
	"fmt"
	"net/url"
	"strings"
)

type URLConfig struct {
	git Environment
}

func NewURLConfig(git Environment) *URLConfig {
	return &URLConfig{
		git: git,
	}
}

// Get retrieves a `http.{url}.{key}` for the given key and urls, following the
// rules in https://git-scm.com/docs/git-config#git-config-httplturlgt.
// The value for `http.{key}` is returned as a fallback if no config keys are
// set for the given urls.
func (c *URLConfig) Get(prefix, key string, rawurl string) (string, bool) {
	key = strings.ToLower(key)
	prefix = strings.ToLower(prefix)
	if v := c.getAll(key, rawurl); len(v) > 0 {
		return v[0], true
	}
	return c.git.Get(strings.Join([]string{prefix, key}, "."))
}

func (c *URLConfig) GetAll(prefix, key string, rawurl string) []string {
	key = strings.ToLower(key)
	prefix = strings.ToLower(prefix)
	if v := c.getAll(key, rawurl); len(v) > 0 {
		return v
	}
	return c.git.GetAll(strings.Join([]string{prefix, key}, "."))
}

func (c *URLConfig) getAll(key, rawurl string) []string {
	hosts, paths := c.hostsAndPaths(rawurl)

	for i := len(paths); i > 0; i-- {
		for _, host := range hosts {
			path := strings.Join(paths[:i], "/")
			if v := c.git.GetAll(fmt.Sprintf("http.%s/%s.%s", host, path, key)); len(v) > 0 {
				return v
			}
			if v := c.git.GetAll(fmt.Sprintf("http.%s/%s/.%s", host, path, key)); len(v) > 0 {
				return v
			}
		}
	}

	for _, host := range hosts {
		if v := c.git.GetAll(fmt.Sprintf("http.%s.%s", host, key)); len(v) > 0 {
			return v
		}
		if v := c.git.GetAll(fmt.Sprintf("http.%s/.%s", host, key)); len(v) > 0 {
			return v
		}
	}
	return nil

}
func (c *URLConfig) hostsAndPaths(rawurl string) (hosts, paths []string) {
	u, err := url.Parse(rawurl)
	if err != nil {
		return nil, nil
	}

	return c.hosts(u), c.paths(u.Path)
}

func (c *URLConfig) hosts(u *url.URL) []string {
	hosts := make([]string, 0, 1)

	if u.User != nil {
		hosts = append(hosts, fmt.Sprintf("%s://%s@%s", u.Scheme, u.User.Username(), u.Host))
	}
	hosts = append(hosts, fmt.Sprintf("%s://%s", u.Scheme, u.Host))

	return hosts
}

func (c *URLConfig) paths(path string) []string {
	pLen := len(path)
	if pLen <= 2 {
		return nil
	}

	end := pLen
	if strings.HasSuffix(path, "/") {
		end -= 1
	}
	return strings.Split(path[1:end], "/")
}
<commit_msg>config/url_config: return last gitconfig value, not first<commit_after>package config

import (
	"fmt"
	"net/url"
	"strings"
)

type URLConfig struct {
	git Environment
}

func NewURLConfig(git Environment) *URLConfig {
	return &URLConfig{
		git: git,
	}
}

// Get retrieves a `http.{url}.{key}` for the given key and urls, following the
// rules in https://git-scm.com/docs/git-config#git-config-httplturlgt.
// The value for `http.{key}` is returned as a fallback if no config keys are
// set for the given urls.
func (c *URLConfig) Get(prefix, key string, rawurl string) (string, bool) {
	key = strings.ToLower(key)
	prefix = strings.ToLower(prefix)
	if v := c.getAll(key, rawurl); len(v) > 0 {
		return v[len(v)-1], true
	}
	return c.git.Get(strings.Join([]string{prefix, key}, "."))
}

func (c *URLConfig) GetAll(prefix, key string, rawurl string) []string {
	key = strings.ToLower(key)
	prefix = strings.ToLower(prefix)
	if v := c.getAll(key, rawurl); len(v) > 0 {
		return v
	}
	return c.git.GetAll(strings.Join([]string{prefix, key}, "."))
}

func (c *URLConfig) getAll(key, rawurl string) []string {
	hosts, paths := c.hostsAndPaths(rawurl)

	for i := len(paths); i > 0; i-- {
		for _, host := range hosts {
			path := strings.Join(paths[:i], "/")
			if v := c.git.GetAll(fmt.Sprintf("http.%s/%s.%s", host, path, key)); len(v) > 0 {
				return v
			}
			if v := c.git.GetAll(fmt.Sprintf("http.%s/%s/.%s", host, path, key)); len(v) > 0 {
				return v
			}
		}
	}

	for _, host := range hosts {
		if v := c.git.GetAll(fmt.Sprintf("http.%s.%s", host, key)); len(v) > 0 {
			return v
		}
		if v := c.git.GetAll(fmt.Sprintf("http.%s/.%s", host, key)); len(v) > 0 {
			return v
		}
	}
	return nil

}
func (c *URLConfig) hostsAndPaths(rawurl string) (hosts, paths []string) {
	u, err := url.Parse(rawurl)
	if err != nil {
		return nil, nil
	}

	return c.hosts(u), c.paths(u.Path)
}

func (c *URLConfig) hosts(u *url.URL) []string {
	hosts := make([]string, 0, 1)

	if u.User != nil {
		hosts = append(hosts, fmt.Sprintf("%s://%s@%s", u.Scheme, u.User.Username(), u.Host))
	}
	hosts = append(hosts, fmt.Sprintf("%s://%s", u.Scheme, u.Host))

	return hosts
}

func (c *URLConfig) paths(path string) []string {
	pLen := len(path)
	if pLen <= 2 {
		return nil
	}

	end := pLen
	if strings.HasSuffix(path, "/") {
		end -= 1
	}
	return strings.Split(path[1:end], "/")
}
<|endoftext|>


<commit_before>package btf

import (
	"bytes"
	"compress/gzip"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"os"
	"testing"

	"github.com/cilium/ebpf/internal"
	"github.com/cilium/ebpf/internal/testutils"
)

func parseVMLinuxBTF(tb testing.TB) (*Spec, error) {
	fh, err := os.Open("testdata/vmlinux-btf.gz")
	if err != nil {
		tb.Fatal(err)
	}
	defer fh.Close()

	rd, err := gzip.NewReader(fh)
	if err != nil {
		tb.Fatal(err)
	}

	spec, err := loadRawSpec(rd, binary.LittleEndian, nil, nil)
	if err != nil {
		tb.Fatal("Can't load BTF:", err)
	}

	return spec, nil
}

func parseELFBTF(tb testing.TB, file string) *Spec {
	fh, err := os.Open(file)
	if err != nil {
		tb.Fatal(err)
	}
	defer fh.Close()

	spec, err := LoadSpecFromReader(fh)
	if err != nil {
		tb.Fatal("Can't load BTF:", err)
	}

	return spec
}

func TestAnyTypesByName(t *testing.T) {
	testutils.Files(t, testutils.Glob(t, "testdata/relocs-*.elf"), func(t *testing.T, file string) {
		spec := parseELFBTF(t, file)

		types, err := spec.AnyTypesByName("ambiguous")
		if err != nil {
			t.Fatal(err)
		}

		if len(types) != 2 {
			t.Fatalf("expected to receive exactly 2 types from querying ambiguous type, got: %v", types)
		}

		types, err = spec.AnyTypesByName("ambiguous___flavour")
		if err != nil {
			t.Fatal(err)
		}

		if len(types) != 1 {
			t.Fatalf("expected to receive exactly 1 type from querying ambiguous flavour, got: %v", types)
		}
	})
}

func TestTypeByName(t *testing.T) {
	spec, err := parseVMLinuxBTF(t)
	if err != nil {
		t.Fatal(err)
	}

	// spec.TypeByName MUST fail if typ is a nil btf.Type.
	i := 0
	p := &i
	for _, typ := range []interface{}{
		nil,
		Struct{},
		&Struct{},
		[]Struct{},
		&[]Struct{},
		map[int]Struct{},
		&map[int]Struct{},
		p,
		&p,
	} {
		if err := spec.TypeByName("iphdr", typ); err == nil {
			t.Fatalf("TypeByName does not fail with type %T", typ)
		}
	}

	// spec.TypeByName MUST return the same address for multiple calls with the same type name.
	var iphdr1, iphdr2 *Struct
	if err := spec.TypeByName("iphdr", &iphdr1); err != nil {
		t.Fatal(err)
	}
	if err := spec.TypeByName("iphdr", &iphdr2); err != nil {
		t.Fatal(err)
	}

	if iphdr1 != iphdr2 {
		t.Fatal("multiple TypeByName calls for `iphdr` name do not return the same addresses")
	}
}

func TestTypeByNameAmbiguous(t *testing.T) {
	testutils.Files(t, testutils.Glob(t, "testdata/relocs-*.elf"), func(t *testing.T, file string) {
		spec := parseELFBTF(t, file)

		var typ *Struct
		if err := spec.TypeByName("ambiguous", &typ); err != nil {
			t.Fatal(err)
		}

		if name := typ.TypeName(); name != "ambiguous" {
			t.Fatal("expected type name 'ambiguous', got:", name)
		}

		if err := spec.TypeByName("ambiguous___flavour", &typ); err != nil {
			t.Fatal(err)
		}

		if name := typ.TypeName(); name != "ambiguous___flavour" {
			t.Fatal("expected type name 'ambiguous___flavour', got:", name)
		}
	})
}

func TestParseVmlinux(t *testing.T) {
	spec, err := parseVMLinuxBTF(t)
	if err != nil {
		t.Fatal(err)
	}

	var iphdr *Struct
	err = spec.TypeByName("iphdr", &iphdr)
	if err != nil {
		t.Fatalf("unable to find `iphdr` struct: %s", err)
	}
	for _, m := range iphdr.Members {
		if m.Name == "version" {
			// __u8 is a typedef
			td, ok := m.Type.(*Typedef)
			if !ok {
				t.Fatalf("version member of iphdr should be a __u8 typedef: actual: %T", m.Type)
			}
			u8int, ok := td.Type.(*Int)
			if !ok {
				t.Fatalf("__u8 typedef should point to an Int type: actual: %T", td.Type)
			}
			if u8int.Bits != 8 {
				t.Fatalf("incorrect bit size of an __u8 int: expected: 8 actual: %d", u8int.Bits)
			}
			if u8int.Encoding != 0 {
				t.Fatalf("incorrect encoding of an __u8 int: expected: 0 actual: %x", u8int.Encoding)
			}
			if u8int.OffsetBits != 0 {
				t.Fatalf("incorrect int offset of an __u8 int: expected: 0 actual: %d", u8int.OffsetBits)
			}
			break
		}
	}
}

func BenchmarkParseVmlinux(b *testing.B) {
	fh, err := os.Open("testdata/vmlinux-btf.gz")
	if err != nil {
		b.Fatal(err)
	}
	defer fh.Close()

	gr, err := gzip.NewReader(fh)
	if err != nil {
		b.Fatal(err)
	}

	var buf bytes.Buffer
	if _, err := buf.ReadFrom(gr); err != nil {
		b.Fatal(err)
	}
	rd := bytes.NewReader(buf.Bytes())

	b.ResetTimer()

	for n := 0; n < b.N; n++ {
		if _, err := rd.Seek(0, io.SeekStart); err != nil {
			b.Fatal(err)
		}

		if _, err := loadRawSpec(rd, binary.LittleEndian, nil, nil); err != nil {
			b.Fatal("Can't load BTF:", err)
		}
	}
}

func TestParseCurrentKernelBTF(t *testing.T) {
	spec, err := loadKernelSpec()
	testutils.SkipIfNotSupported(t, err)
	if err != nil {
		t.Fatal("Can't load BTF:", err)
	}

	if len(spec.namedTypes) == 0 {
		t.Fatal("Empty kernel BTF")
	}
}

func TestLoadSpecFromElf(t *testing.T) {
	testutils.Files(t, testutils.Glob(t, "../../testdata/loader-e*.elf"), func(t *testing.T, file string) {
		spec := parseELFBTF(t, file)

		if sec, err := spec.Program("xdp", 1); err != nil {
			t.Error("Can't get BTF for the xdp section:", err)
		} else if sec == nil {
			t.Error("Missing BTF for the xdp section")
		}

		if sec, err := spec.Program("socket", 1); err != nil {
			t.Error("Can't get BTF for the socket section:", err)
		} else if sec == nil {
			t.Error("Missing BTF for the socket section")
		}

		vt, err := spec.TypeByID(0)
		if err != nil {
			t.Error("Can't retrieve void type by ID:", err)
		}
		if _, ok := vt.(*Void); !ok {
			t.Errorf("Expected Void for type id 0, but got: %T", vt)
		}

		var bpfMapDef *Struct
		if err := spec.TypeByName("bpf_map_def", &bpfMapDef); err != nil {
			t.Error("Can't find bpf_map_def:", err)
		}

		var tmp *Void
		if err := spec.TypeByName("totally_bogus_type", &tmp); !errors.Is(err, ErrNotFound) {
			t.Error("TypeByName doesn't return ErrNotFound:", err)
		}

		var fn *Func
		if err := spec.TypeByName("global_fn", &fn); err != nil {
			t.Error("Can't find global_fn():", err)
		} else {
			if fn.Linkage != GlobalFunc {
				t.Error("Expected global linkage:", fn)
			}
		}

		var v *Var
		if err := spec.TypeByName("key3", &v); err != nil {
			t.Error("Cant find key3:", err)
		} else {
			if v.Linkage != GlobalVar {
				t.Error("Expected global linkage:", v)
			}
		}

		if spec.byteOrder != internal.NativeEndian {
			return
		}

		t.Run("Handle", func(t *testing.T) {
			btf, err := NewHandle(spec)
			testutils.SkipIfNotSupported(t, err)
			if err != nil {
				t.Fatal("Can't load BTF:", err)
			}
			defer btf.Close()
		})
	})
}

func TestLoadKernelSpec(t *testing.T) {
	if _, err := os.Stat("/sys/kernel/btf/vmlinux"); os.IsNotExist(err) {
		t.Skip("/sys/kernel/btf/vmlinux not present")
	}

	_, err := LoadKernelSpec()
	if err != nil {
		t.Fatal("Can't load kernel spec:", err)
	}
}

func TestSpecCopy(t *testing.T) {
	spec := parseELFBTF(t, "../../testdata/loader-el.elf")

	if len(spec.types) < 1 {
		t.Fatal("Not enough types")
	}

	cpy := spec.Copy()
	for i := range cpy.types {
		if _, ok := cpy.types[i].(*Void); ok {
			// Since Void is an empty struct, a Type interface value containing
			// &Void{} stores (*Void, nil). Since interface equality first compares
			// the type and then the concrete value, Void is always equal.
			continue
		}

		if cpy.types[i] == spec.types[i] {
			t.Fatalf("Type at index %d is not a copy: %T == %T", i, cpy.types[i], spec.types[i])
		}
	}
}

func TestHaveBTF(t *testing.T) {
	testutils.CheckFeatureTest(t, haveBTF)
}

func TestHaveFuncLinkage(t *testing.T) {
	testutils.CheckFeatureTest(t, haveFuncLinkage)
}

func ExampleSpec_TypeByName() {
	// Acquire a Spec via one of its constructors.
	spec := new(Spec)

	// Declare a variable of the desired type
	var foo *Struct

	if err := spec.TypeByName("foo", &foo); err != nil {
		// There is no struct with name foo, or there
		// are multiple possibilities.
	}

	// We've found struct foo
	fmt.Println(foo.Name)
}
<commit_msg>btf: merge TestFindType and TestParseVmlinux<commit_after>package btf

import (
	"bytes"
	"compress/gzip"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"os"
	"testing"

	"github.com/cilium/ebpf/internal"
	"github.com/cilium/ebpf/internal/testutils"
)

func parseVMLinuxBTF(tb testing.TB) (*Spec, error) {
	fh, err := os.Open("testdata/vmlinux-btf.gz")
	if err != nil {
		tb.Fatal(err)
	}
	defer fh.Close()

	rd, err := gzip.NewReader(fh)
	if err != nil {
		tb.Fatal(err)
	}

	spec, err := loadRawSpec(rd, binary.LittleEndian, nil, nil)
	if err != nil {
		tb.Fatal("Can't load BTF:", err)
	}

	return spec, nil
}

func parseELFBTF(tb testing.TB, file string) *Spec {
	fh, err := os.Open(file)
	if err != nil {
		tb.Fatal(err)
	}
	defer fh.Close()

	spec, err := LoadSpecFromReader(fh)
	if err != nil {
		tb.Fatal("Can't load BTF:", err)
	}

	return spec
}

func TestAnyTypesByName(t *testing.T) {
	testutils.Files(t, testutils.Glob(t, "testdata/relocs-*.elf"), func(t *testing.T, file string) {
		spec := parseELFBTF(t, file)

		types, err := spec.AnyTypesByName("ambiguous")
		if err != nil {
			t.Fatal(err)
		}

		if len(types) != 2 {
			t.Fatalf("expected to receive exactly 2 types from querying ambiguous type, got: %v", types)
		}

		types, err = spec.AnyTypesByName("ambiguous___flavour")
		if err != nil {
			t.Fatal(err)
		}

		if len(types) != 1 {
			t.Fatalf("expected to receive exactly 1 type from querying ambiguous flavour, got: %v", types)
		}
	})
}

func TestTypeByNameAmbiguous(t *testing.T) {
	testutils.Files(t, testutils.Glob(t, "testdata/relocs-*.elf"), func(t *testing.T, file string) {
		spec := parseELFBTF(t, file)

		var typ *Struct
		if err := spec.TypeByName("ambiguous", &typ); err != nil {
			t.Fatal(err)
		}

		if name := typ.TypeName(); name != "ambiguous" {
			t.Fatal("expected type name 'ambiguous', got:", name)
		}

		if err := spec.TypeByName("ambiguous___flavour", &typ); err != nil {
			t.Fatal(err)
		}

		if name := typ.TypeName(); name != "ambiguous___flavour" {
			t.Fatal("expected type name 'ambiguous___flavour', got:", name)
		}
	})
}

func TestTypeByName(t *testing.T) {
	spec, err := parseVMLinuxBTF(t)
	if err != nil {
		t.Fatal(err)
	}

	for _, typ := range []interface{}{
		nil,
		Struct{},
		&Struct{},
		[]Struct{},
		&[]Struct{},
		map[int]Struct{},
		&map[int]Struct{},
		int(0),
		new(int),
	} {
		t.Run(fmt.Sprintf("%T", typ), func(t *testing.T) {
			// spec.TypeByName MUST fail if typ is a nil btf.Type.
			if err := spec.TypeByName("iphdr", typ); err == nil {
				t.Fatalf("FindType does not fail with type %T", typ)
			}
		})
	}

	// spec.TypeByName MUST return the same address for multiple calls with the same type name.
	var iphdr1, iphdr2 *Struct
	if err := spec.TypeByName("iphdr", &iphdr1); err != nil {
		t.Fatal(err)
	}
	if err := spec.TypeByName("iphdr", &iphdr2); err != nil {
		t.Fatal(err)
	}

	if iphdr1 != iphdr2 {
		t.Fatal("multiple TypeByName calls for `iphdr` name do not return the same addresses")
	}

	for _, m := range iphdr1.Members {
		if m.Name == "version" {
			// __u8 is a typedef
			td, ok := m.Type.(*Typedef)
			if !ok {
				t.Fatalf("version member of iphdr should be a __u8 typedef: actual: %T", m.Type)
			}
			u8int, ok := td.Type.(*Int)
			if !ok {
				t.Fatalf("__u8 typedef should point to an Int type: actual: %T", td.Type)
			}
			if u8int.Bits != 8 {
				t.Fatalf("incorrect bit size of an __u8 int: expected: 8 actual: %d", u8int.Bits)
			}
			if u8int.Encoding != 0 {
				t.Fatalf("incorrect encoding of an __u8 int: expected: 0 actual: %x", u8int.Encoding)
			}
			if u8int.OffsetBits != 0 {
				t.Fatalf("incorrect int offset of an __u8 int: expected: 0 actual: %d", u8int.OffsetBits)
			}
			break
		}
	}
}

func BenchmarkParseVmlinux(b *testing.B) {
	fh, err := os.Open("testdata/vmlinux-btf.gz")
	if err != nil {
		b.Fatal(err)
	}
	defer fh.Close()

	gr, err := gzip.NewReader(fh)
	if err != nil {
		b.Fatal(err)
	}

	var buf bytes.Buffer
	if _, err := buf.ReadFrom(gr); err != nil {
		b.Fatal(err)
	}
	rd := bytes.NewReader(buf.Bytes())

	b.ResetTimer()

	for n := 0; n < b.N; n++ {
		if _, err := rd.Seek(0, io.SeekStart); err != nil {
			b.Fatal(err)
		}

		if _, err := loadRawSpec(rd, binary.LittleEndian, nil, nil); err != nil {
			b.Fatal("Can't load BTF:", err)
		}
	}
}

func TestParseCurrentKernelBTF(t *testing.T) {
	spec, err := loadKernelSpec()
	testutils.SkipIfNotSupported(t, err)
	if err != nil {
		t.Fatal("Can't load BTF:", err)
	}

	if len(spec.namedTypes) == 0 {
		t.Fatal("Empty kernel BTF")
	}
}

func TestLoadSpecFromElf(t *testing.T) {
	testutils.Files(t, testutils.Glob(t, "../../testdata/loader-e*.elf"), func(t *testing.T, file string) {
		spec := parseELFBTF(t, file)

		if sec, err := spec.Program("xdp", 1); err != nil {
			t.Error("Can't get BTF for the xdp section:", err)
		} else if sec == nil {
			t.Error("Missing BTF for the xdp section")
		}

		if sec, err := spec.Program("socket", 1); err != nil {
			t.Error("Can't get BTF for the socket section:", err)
		} else if sec == nil {
			t.Error("Missing BTF for the socket section")
		}

		vt, err := spec.TypeByID(0)
		if err != nil {
			t.Error("Can't retrieve void type by ID:", err)
		}
		if _, ok := vt.(*Void); !ok {
			t.Errorf("Expected Void for type id 0, but got: %T", vt)
		}

		var bpfMapDef *Struct
		if err := spec.TypeByName("bpf_map_def", &bpfMapDef); err != nil {
			t.Error("Can't find bpf_map_def:", err)
		}

		var tmp *Void
		if err := spec.TypeByName("totally_bogus_type", &tmp); !errors.Is(err, ErrNotFound) {
			t.Error("TypeByName doesn't return ErrNotFound:", err)
		}

		var fn *Func
		if err := spec.TypeByName("global_fn", &fn); err != nil {
			t.Error("Can't find global_fn():", err)
		} else {
			if fn.Linkage != GlobalFunc {
				t.Error("Expected global linkage:", fn)
			}
		}

		var v *Var
		if err := spec.TypeByName("key3", &v); err != nil {
			t.Error("Cant find key3:", err)
		} else {
			if v.Linkage != GlobalVar {
				t.Error("Expected global linkage:", v)
			}
		}

		if spec.byteOrder != internal.NativeEndian {
			return
		}

		t.Run("Handle", func(t *testing.T) {
			btf, err := NewHandle(spec)
			testutils.SkipIfNotSupported(t, err)
			if err != nil {
				t.Fatal("Can't load BTF:", err)
			}
			defer btf.Close()
		})
	})
}

func TestLoadKernelSpec(t *testing.T) {
	if _, err := os.Stat("/sys/kernel/btf/vmlinux"); os.IsNotExist(err) {
		t.Skip("/sys/kernel/btf/vmlinux not present")
	}

	_, err := LoadKernelSpec()
	if err != nil {
		t.Fatal("Can't load kernel spec:", err)
	}
}

func TestSpecCopy(t *testing.T) {
	spec := parseELFBTF(t, "../../testdata/loader-el.elf")

	if len(spec.types) < 1 {
		t.Fatal("Not enough types")
	}

	cpy := spec.Copy()
	for i := range cpy.types {
		if _, ok := cpy.types[i].(*Void); ok {
			// Since Void is an empty struct, a Type interface value containing
			// &Void{} stores (*Void, nil). Since interface equality first compares
			// the type and then the concrete value, Void is always equal.
			continue
		}

		if cpy.types[i] == spec.types[i] {
			t.Fatalf("Type at index %d is not a copy: %T == %T", i, cpy.types[i], spec.types[i])
		}
	}
}

func TestHaveBTF(t *testing.T) {
	testutils.CheckFeatureTest(t, haveBTF)
}

func TestHaveFuncLinkage(t *testing.T) {
	testutils.CheckFeatureTest(t, haveFuncLinkage)
}

func ExampleSpec_TypeByName() {
	// Acquire a Spec via one of its constructors.
	spec := new(Spec)

	// Declare a variable of the desired type
	var foo *Struct

	if err := spec.TypeByName("foo", &foo); err != nil {
		// There is no struct with name foo, or there
		// are multiple possibilities.
	}

	// We've found struct foo
	fmt.Println(foo.Name)
}
<|endoftext|>