<commit_before>package k8s_test

import (
	"time"

	. "github.com/concourse/concourse/topgun"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("external workers through separate deployments", func() {

	const publicKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC496FSYFcBAKgDtMsBAJiF/6/NxlXKP5UZecyEsedYuTt1GOgJTwaA1qZ1LmHsbfLDE68oDdiM4uvxfI4wtLhz57w3u0jOUxZ2JeF7SVwEf1nVqLn4Gh/f8GUNQGSyIp1zUD5Bx9fq0PAyQ47mt7Ufi84rcf8LKl7nzAIHTcdg2BvTkQN9bUGPaq/Pb1W2bKPAQy4OzXTSIyrAJ89TH2jFeaZfyxQFGbD9jVHH/yl0oiMrDeaRYgccE5II+KY7WoLjsBry/9Qf2ERELKTK4UeIGIqWci9lab1ti+GxFPPiC3krNFjo4jShV4eUs4cNIrjwNrxVaKPXmU6o7Y3Hpayx Concourse"

	var (
		atc Endpoint

		workerKey        string
		tsaPort          string
		webDeployArgs    []string
		workerDeployArgs []string
	)

	JustBeforeEach(func() {
		setReleaseNameAndNamespace("xw")

		By("creating a web only deployment in one namespace")
		tsaPort = "2222"
		helmArgs := append(webDeployArgs,
			"--set=worker.enabled=false",
			"--set=web.tsa.bindPort="+tsaPort,
		)
		deployConcourseChart(releaseName+"-web", helmArgs...)

		By("creating a worker only deployment in another namespace")
		helmArgs = append(workerDeployArgs,
			"--set=postgresql.enabled=false",
			"--set=web.enabled=false",
			"--set=worker.replicas=1",
			"--set=concourse.worker.tsa.hosts[0]="+releaseName+"-web-web."+releaseName+"-web.svc.cluster.local:"+tsaPort,
		)
		deployConcourseChart(releaseName+"-worker", helmArgs...)

		waitAllPodsInNamespaceToBeReady(namespace + "-worker")
		waitAllPodsInNamespaceToBeReady(namespace + "-web")

		atc = endpointFactory.NewServiceEndpoint(
			namespace+"-web",
			releaseName+"-web-web",
			"8080",
		)

		fly.Login("test", "test", "http://"+atc.Address())

	})

	var waitForRunningWorker = func() {
		By("waiting for a running worker")
		Eventually(func() []Worker {
			return getRunningWorkers(fly.GetWorkers())
		}, 2*time.Minute, 10*time.Second).
			Should(HaveLen(1))
	}

	var workerDoesntRegister = func() {
		By("worker never registers")
		Consistently(func() []Worker {
			return getRunningWorkers(fly.GetWorkers())
		}, 1*time.Minute, 10*time.Second).
			Should(HaveLen(0))
	}

	AfterEach(func() {
		atc.Close()
		cleanup(releaseName+"-web", namespace+"-web")
		cleanup(releaseName+"-worker", namespace+"-worker")
	})

	Context("main team worker", func() {
		Context("web with correct public key", func() {
			BeforeEach(func() {
				workerKey = publicKey
				webDeployArgs = []string{
					"--set=secrets.teamAuthorizedKeys[0].team=main",
					"--set=secrets.teamAuthorizedKeys[0].key=" + workerKey,
					"--set=web.env[0].name=CONCOURSE_TSA_AUTHORIZED_KEYS",
					"--set=web.env[0].value=",
				}
				workerDeployArgs = []string{
					"--set=concourse.worker.team=main",
				}
			})

			It("worker registers with team main", func() {
				waitForRunningWorker()
				worker := getRunningWorkers(fly.GetWorkers())
				Expect(worker[0].Team).To(Equal("main"))
			})
		})

		Context("web with invalid public key", func() {
			BeforeEach(func() {
				workerKey = "ssh-rsa 1234ABCD Concourse"
				webDeployArgs = []string{
					"--set=secrets.teamAuthorizedKeys[0].team=main",
					"--set=secrets.teamAuthorizedKeys[0].key=" + workerKey,
					"--set=web.env[0].name=CONCOURSE_TSA_AUTHORIZED_KEYS",
					"--set=web.env[0].value=",
				}
				workerDeployArgs = []string{
					"--set=concourse.worker.team=main",
				}
			})

			It("worker doesn't register", func() {
				workerDoesntRegister()
			})
		})
	})

	Context("generic worker", func() {
		Context("web with correct public key", func() {
			BeforeEach(func() {
				workerDeployArgs = []string{}
				webDeployArgs = []string{}
			})

			It("worker registers with atc", func() {
				waitForRunningWorker()
				worker := getRunningWorkers(fly.GetWorkers())
				Expect(worker[0].Team).To(Equal(""))
			})
		})

		Context("web with invalid public key", func() {
			BeforeEach(func() {
				workerKey = "ssh-rsa 1234ABCD Concourse"
				webDeployArgs = []string{
					"--set=secrets.workerKeyPub=" + workerKey,
				}
			})

			It("worker doesn't register", func() {
				workerDoesntRegister()
			})
		})
	})
})
<commit_msg>topgun/k8s: fix env vars in external worker tests<commit_after>package k8s_test

import (
	"time"

	. "github.com/concourse/concourse/topgun"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("external workers through separate deployments", func() {

	const publicKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC496FSYFcBAKgDtMsBAJiF/6/NxlXKP5UZecyEsedYuTt1GOgJTwaA1qZ1LmHsbfLDE68oDdiM4uvxfI4wtLhz57w3u0jOUxZ2JeF7SVwEf1nVqLn4Gh/f8GUNQGSyIp1zUD5Bx9fq0PAyQ47mt7Ufi84rcf8LKl7nzAIHTcdg2BvTkQN9bUGPaq/Pb1W2bKPAQy4OzXTSIyrAJ89TH2jFeaZfyxQFGbD9jVHH/yl0oiMrDeaRYgccE5II+KY7WoLjsBry/9Qf2ERELKTK4UeIGIqWci9lab1ti+GxFPPiC3krNFjo4jShV4eUs4cNIrjwNrxVaKPXmU6o7Y3Hpayx Concourse"

	var (
		atc Endpoint

		workerKey        string
		tsaPort          string
		webDeployArgs    []string
		workerDeployArgs []string
	)

	JustBeforeEach(func() {
		setReleaseNameAndNamespace("xw")

		By("creating a web only deployment in one namespace")
		tsaPort = "2222"
		helmArgs := append(webDeployArgs,
			"--set=worker.enabled=false",
			"--set=web.tsa.bindPort="+tsaPort,
		)
		deployConcourseChart(releaseName+"-web", helmArgs...)

		By("creating a worker only deployment in another namespace")
		helmArgs = append(workerDeployArgs,
			"--set=postgresql.enabled=false",
			"--set=web.enabled=false",
			"--set=worker.replicas=1",
			"--set=concourse.worker.tsa.hosts[0]="+releaseName+"-web-web."+releaseName+"-web.svc.cluster.local:"+tsaPort,
		)
		deployConcourseChart(releaseName+"-worker", helmArgs...)

		waitAllPodsInNamespaceToBeReady(namespace + "-worker")
		waitAllPodsInNamespaceToBeReady(namespace + "-web")

		atc = endpointFactory.NewServiceEndpoint(
			namespace+"-web",
			releaseName+"-web-web",
			"8080",
		)

		fly.Login("test", "test", "http://"+atc.Address())

	})

	var waitForRunningWorker = func() {
		By("waiting for a running worker")
		Eventually(func() []Worker {
			return getRunningWorkers(fly.GetWorkers())
		}, 2*time.Minute, 10*time.Second).
			Should(HaveLen(1))
	}

	var workerDoesntRegister = func() {
		By("worker never registers")
		Consistently(func() []Worker {
			return getRunningWorkers(fly.GetWorkers())
		}, 1*time.Minute, 10*time.Second).
			Should(HaveLen(0))
	}

	AfterEach(func() {
		atc.Close()
		cleanup(releaseName+"-web", namespace+"-web")
		cleanup(releaseName+"-worker", namespace+"-worker")
	})

	Context("main team worker, webs only allow team workers", func() {
		invalidGenericKey := "ssh-rsa ABCD1234 OnlyTeamWorkers"
		Context("web with correct public key", func() {
			BeforeEach(func() {
				workerKey = publicKey
				webDeployArgs = []string{
					"--set=secrets.teamAuthorizedKeys[0].team=main",
					"--set=secrets.teamAuthorizedKeys[0].key=" + workerKey,
					"--set=secrets.workerKeyPub=" + invalidGenericKey,
				}
				workerDeployArgs = []string{
					"--set=concourse.worker.team=main",
				}
			})

			It("worker registers with team main", func() {
				waitForRunningWorker()
				worker := getRunningWorkers(fly.GetWorkers())
				Expect(worker[0].Team).To(Equal("main"))
			})
		})

		Context("web with invalid public key", func() {
			BeforeEach(func() {
				workerKey = "ssh-rsa 1234ABCD Concourse"
				webDeployArgs = []string{
					"--set=secrets.teamAuthorizedKeys[0].team=main",
					"--set=secrets.teamAuthorizedKeys[0].key=" + workerKey,
					"--set=secrets.workerKeyPub=" + invalidGenericKey,
				}
				workerDeployArgs = []string{
					"--set=concourse.worker.team=main",
				}
			})

			It("worker doesn't register", func() {
				workerDoesntRegister()
			})
		})
	})

	Context("generic worker", func() {
		Context("web with correct public key", func() {
			BeforeEach(func() {
				workerDeployArgs = []string{}
				webDeployArgs = []string{}
			})

			It("worker registers with atc", func() {
				waitForRunningWorker()
				worker := getRunningWorkers(fly.GetWorkers())
				Expect(worker[0].Team).To(Equal(""))
			})
		})

		Context("web with invalid public key", func() {
			BeforeEach(func() {
				workerKey = "ssh-rsa 1234ABCD Concourse"
				webDeployArgs = []string{
					"--set=secrets.workerKeyPub=" + workerKey,
				}
			})

			It("worker doesn't register", func() {
				workerDoesntRegister()
			})
		})
	})
})
<|endoftext|>


<commit_before>package kumoru

import (
	"gopkg.in/ini.v1"
)

type Endpoints struct {
	Application   string
	Authorization string
	Pool          string
}

func LoadEndpoints(filename string, section string) (Endpoints, error) {
	config, err := ini.Load(filename)
	if err != nil {
		return Endpoints{}, err
	}

	iniEndpoints, err := config.GetSection(section)
	if err != nil {
		return Endpoints{
			Application:   "https://application.kumoru.io:5000",
			Authorization: "https://authorization.kumoru.io:5000",
			Pool:          "https://pool.kumoru.io:5000",
		}, nil
	}

	return Endpoints{
		Application:   iniEndpoints.Key("kumoru_application_api").String(),
		Authorization: iniEndpoints.Key("kumoru_authorization_api").String(),
		Pool:          iniEndpoints.Key("kumoru_pool_api").String(),
	}, nil

}
<commit_msg>Update production endpoints<commit_after>package kumoru

import (
	"gopkg.in/ini.v1"
)

type Endpoints struct {
	Application   string
	Authorization string
	Pool          string
}

func LoadEndpoints(filename string, section string) (Endpoints, error) {
	config, err := ini.Load(filename)
	if err != nil {
		return Endpoints{}, err
	}

	iniEndpoints, err := config.GetSection(section)
	if err != nil {
		return Endpoints{
			Application:   "https://application.kumoru.io",
			Authorization: "https://authorization.kumoru.io",
			Pool:          "https://pool.kumoru.io",
		}, nil
	}

	return Endpoints{
		Application:   iniEndpoints.Key("kumoru_application_api").String(),
		Authorization: iniEndpoints.Key("kumoru_authorization_api").String(),
		Pool:          iniEndpoints.Key("kumoru_pool_api").String(),
	}, nil

}
<|endoftext|>


<commit_before>package etcd

import "fmt"

// Config holds etcd configuration alongside with configuration related to our higher level interface.
type Config struct {
	Embedded bool `long:"embedded" description:"Use embedded etcd instance instead of the external one. Note: use for testing only."`

	EmbeddedClientPort uint16 `long:"embedded_client_port" description:"Client port to use for the embedded instance. Note: use for testing only."`

	EmbeddedPeerPort uint16 `long:"embedded_peer_port" description:"Peer port to use for the embedded instance. Note: use for testing only."`

	EmbeddedLogFile string `long:"embedded_log_file" description:"Optional log file to use for embedded instance logs. note: use for testing only."`

	Host string `long:"host" description:"Etcd database host."`

	User string `long:"user" description:"Etcd database user."`

	Pass string `long:"pass" description:"Password for the database user."`

	Namespace string `long:"namespace" description:"The etcd namespace to use."`

	DisableTLS bool `long:"disabletls" description:"Disable TLS for etcd connection. Caution: use for development only."`

	CertFile string `long:"cert_file" description:"Path to the TLS certificate for etcd RPC."`

	KeyFile string `long:"key_file" description:"Path to the TLS private key for etcd RPC."`

	InsecureSkipVerify bool `long:"insecure_skip_verify" description:"Whether we intend to skip TLS verification"`

	CollectStats bool `long:"collect_stats" description:"Whether to collect etcd commit stats."`

	MaxMsgSize int `long:"max_msg_size" description:"The maximum message size in bytes that we may send to etcd."`

	// SingleWriter should be set to true if we intend to only allow a
	// single writer to the database at a time.
	SingleWriter bool
}

// CloneWithSubNamespace clones the current configuration and returns a new
// instance with the given sub namespace applied by appending it to the main
// namespace.
func (c *Config) CloneWithSubNamespace(subNamespace string) *Config {
	ns := c.Namespace
	if len(ns) == 0 {
		ns = subNamespace
	} else {
		ns = fmt.Sprintf("%s/%s", ns, subNamespace)
	}

	return &Config{
		Embedded:           c.Embedded,
		EmbeddedClientPort: c.EmbeddedClientPort,
		EmbeddedPeerPort:   c.EmbeddedPeerPort,
		Host:               c.Host,
		User:               c.User,
		Pass:               c.Pass,
		Namespace:          ns,
		DisableTLS:         c.DisableTLS,
		CertFile:           c.CertFile,
		KeyFile:            c.KeyFile,
		InsecureSkipVerify: c.InsecureSkipVerify,
		CollectStats:       c.CollectStats,
		SingleWriter:       c.SingleWriter,
	}
}

// CloneWithSingleWriter clones the current configuration and returns a new
// instance with the single writer property set to true.
func (c *Config) CloneWithSingleWriter() *Config {
	return &Config{
		Embedded:           c.Embedded,
		EmbeddedClientPort: c.EmbeddedClientPort,
		EmbeddedPeerPort:   c.EmbeddedPeerPort,
		Host:               c.Host,
		User:               c.User,
		Pass:               c.Pass,
		Namespace:          c.Namespace,
		DisableTLS:         c.DisableTLS,
		CertFile:           c.CertFile,
		KeyFile:            c.KeyFile,
		InsecureSkipVerify: c.InsecureSkipVerify,
		CollectStats:       c.CollectStats,
		SingleWriter:       true,
	}
}
<commit_msg>etcd: fix config clone<commit_after>package etcd

import "fmt"

// Config holds etcd configuration alongside with configuration related to our higher level interface.
type Config struct {
	Embedded bool `long:"embedded" description:"Use embedded etcd instance instead of the external one. Note: use for testing only."`

	EmbeddedClientPort uint16 `long:"embedded_client_port" description:"Client port to use for the embedded instance. Note: use for testing only."`

	EmbeddedPeerPort uint16 `long:"embedded_peer_port" description:"Peer port to use for the embedded instance. Note: use for testing only."`

	EmbeddedLogFile string `long:"embedded_log_file" description:"Optional log file to use for embedded instance logs. note: use for testing only."`

	Host string `long:"host" description:"Etcd database host."`

	User string `long:"user" description:"Etcd database user."`

	Pass string `long:"pass" description:"Password for the database user."`

	Namespace string `long:"namespace" description:"The etcd namespace to use."`

	DisableTLS bool `long:"disabletls" description:"Disable TLS for etcd connection. Caution: use for development only."`

	CertFile string `long:"cert_file" description:"Path to the TLS certificate for etcd RPC."`

	KeyFile string `long:"key_file" description:"Path to the TLS private key for etcd RPC."`

	InsecureSkipVerify bool `long:"insecure_skip_verify" description:"Whether we intend to skip TLS verification"`

	CollectStats bool `long:"collect_stats" description:"Whether to collect etcd commit stats."`

	MaxMsgSize int `long:"max_msg_size" description:"The maximum message size in bytes that we may send to etcd."`

	// SingleWriter should be set to true if we intend to only allow a
	// single writer to the database at a time.
	SingleWriter bool
}

// CloneWithSubNamespace clones the current configuration and returns a new
// instance with the given sub namespace applied by appending it to the main
// namespace.
func (c *Config) CloneWithSubNamespace(subNamespace string) *Config {
	ns := c.Namespace
	if len(ns) == 0 {
		ns = subNamespace
	} else {
		ns = fmt.Sprintf("%s/%s", ns, subNamespace)
	}

	return &Config{
		Embedded:           c.Embedded,
		EmbeddedClientPort: c.EmbeddedClientPort,
		EmbeddedPeerPort:   c.EmbeddedPeerPort,
		Host:               c.Host,
		User:               c.User,
		Pass:               c.Pass,
		Namespace:          ns,
		DisableTLS:         c.DisableTLS,
		CertFile:           c.CertFile,
		KeyFile:            c.KeyFile,
		InsecureSkipVerify: c.InsecureSkipVerify,
		CollectStats:       c.CollectStats,
		MaxMsgSize:         c.MaxMsgSize,
		SingleWriter:       c.SingleWriter,
	}
}

// CloneWithSingleWriter clones the current configuration and returns a new
// instance with the single writer property set to true.
func (c *Config) CloneWithSingleWriter() *Config {
	return &Config{
		Embedded:           c.Embedded,
		EmbeddedClientPort: c.EmbeddedClientPort,
		EmbeddedPeerPort:   c.EmbeddedPeerPort,
		Host:               c.Host,
		User:               c.User,
		Pass:               c.Pass,
		Namespace:          c.Namespace,
		DisableTLS:         c.DisableTLS,
		CertFile:           c.CertFile,
		KeyFile:            c.KeyFile,
		InsecureSkipVerify: c.InsecureSkipVerify,
		CollectStats:       c.CollectStats,
		MaxMsgSize:         c.MaxMsgSize,
		SingleWriter:       true,
	}
}
<|endoftext|>


<commit_before>package importer

import (
	"crypto/md5"
	"encoding/hex"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"strings"
	"sync"

	"github.com/sgeisbacher/photogallery-api/media"
)

type ImportMediaData struct {
	path        string
	galleryName string
}

type ImportManager struct {
	MediaService   *media.MediaService
	GalleryService *media.GalleryService
}

func (mgr ImportManager) ScanFolder(path string) error {
	var wg sync.WaitGroup
	imagesChan := make(chan ImportMediaData)

	// start worker threads
	go mgr.handleImageFile(imagesChan, &wg)
	go mgr.handleImageFile(imagesChan, &wg)

	path = addSlash(path)

	files, err := ioutil.ReadDir(path)
	if err != nil {
		return errors.New(fmt.Sprintf("error while reading dir: %v", err))
	}
	for _, file := range files {
		if !file.IsDir() {
			fmt.Printf("skipping file '%v' (not allowed here), because its on gallery-folder-level\n", path+file.Name())
			continue
		}
		scanGalleryFolder(file.Name(), addSlash(path+file.Name()), imagesChan, &wg)
	}

	close(imagesChan)
	wg.Wait()

	return nil
}

func scanGalleryFolder(galleryName, path string, imagesChan chan ImportMediaData, wg *sync.WaitGroup) {
	files, err := ioutil.ReadDir(path)
	if err != nil {
		fmt.Printf("error while reading dir: %v\n", err)
		return
	}
	for _, file := range files {
		if file.IsDir() {
			fmt.Printf("skipping directory '%v' (not allowed here), because its on image-level\n", addSlash(path+file.Name()))
			continue
		}
		wg.Add(1)
		importMediaData := ImportMediaData{
			path:        path + file.Name(),
			galleryName: galleryName,
		}
		imagesChan <- importMediaData
	}
}

func (mgr ImportManager) handleImageFile(imagesChan <-chan ImportMediaData, wg *sync.WaitGroup) {
	for importMediaData := range imagesChan {
		fileHash, err := hashFile(importMediaData.path)
		if err != nil {
			fmt.Printf("skipping file '%v' due to an error: %v\n", importMediaData.path, err)
			continue
		}

		media := media.Media{
			Hash: fileHash,
			Path: importMediaData.path,
		}
		mgr.MediaService.Add(media)
		err = mgr.GalleryService.AddMediaToGallery(importMediaData.galleryName, media)
		if err != nil {
			fmt.Printf("error while putting media to gallery '%v': %v\n", importMediaData.galleryName, err)
			// TODO delete media!!!
		}
		wg.Done()
	}
}

func hashFile(filename string) (string, error) {
	var md5ChkSum string
	file, err := os.Open(filename)
	if err != nil {
		fmt.Println("could not open file:", filename)
		return md5ChkSum, err
	}
	defer file.Close()
	hash := md5.New()
	if _, err := io.Copy(hash, file); err != nil {
		fmt.Println("could not hash file:", filename)
		return md5ChkSum, err
	}
	md5ChkSum = hex.EncodeToString(hash.Sum(nil))
	return md5ChkSum, nil
}

func addSlash(path string) string {
	path = strings.TrimSpace(path)
	if !strings.HasSuffix(path, "/") {
		path = path + "/"
	}
	return path
}
<commit_msg>fixed importers orig-path<commit_after>package importer

import (
	"crypto/md5"
	"encoding/hex"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"strings"
	"sync"

	"github.com/sgeisbacher/photogallery-api/media"
)

type ImportMediaData struct {
	path        string
	galleryName string
}

type ImportManager struct {
	MediaService   *media.MediaService
	GalleryService *media.GalleryService
}

func (mgr ImportManager) ScanFolder(path string) error {
	var wg sync.WaitGroup
	imagesChan := make(chan ImportMediaData)

	// start worker threads
	go mgr.handleImageFile(imagesChan, &wg)
	go mgr.handleImageFile(imagesChan, &wg)

	path = addSlash(path)

	files, err := ioutil.ReadDir(path)
	if err != nil {
		return errors.New(fmt.Sprintf("error while reading dir: %v", err))
	}
	for _, file := range files {
		if !file.IsDir() {
			fmt.Printf("skipping file '%v' (not allowed here), because its on gallery-folder-level\n", path+file.Name())
			continue
		}
		scanGalleryFolder(file.Name(), addSlash(path+file.Name()), imagesChan, &wg)
	}

	close(imagesChan)
	wg.Wait()

	return nil
}

func scanGalleryFolder(galleryName, path string, imagesChan chan ImportMediaData, wg *sync.WaitGroup) {
	files, err := ioutil.ReadDir(path)
	if err != nil {
		fmt.Printf("error while reading dir: %v\n", err)
		return
	}
	for _, file := range files {
		if file.IsDir() {
			fmt.Printf("skipping directory '%v' (not allowed here), because its on image-level\n", addSlash(path+file.Name()))
			continue
		}
		wg.Add(1)
		importMediaData := ImportMediaData{
			path:        path + file.Name(),
			galleryName: galleryName,
		}
		imagesChan <- importMediaData
	}
}

func (mgr ImportManager) handleImageFile(imagesChan <-chan ImportMediaData, wg *sync.WaitGroup) {
	for importMediaData := range imagesChan {
		fileHash, err := hashFile(importMediaData.path)
		if err != nil {
			fmt.Printf("skipping file '%v' due to an error: %v\n", importMediaData.path, err)
			continue
		}

		media := media.Media{
			Hash:     fileHash,
			OrigPath: importMediaData.path,
		}
		mgr.MediaService.Add(media)
		err = mgr.GalleryService.AddMediaToGallery(importMediaData.galleryName, media)
		if err != nil {
			fmt.Printf("error while putting media to gallery '%v': %v\n", importMediaData.galleryName, err)
			// TODO delete media!!!
		}
		wg.Done()
	}
}

func hashFile(filename string) (string, error) {
	var md5ChkSum string
	file, err := os.Open(filename)
	if err != nil {
		fmt.Println("could not open file:", filename)
		return md5ChkSum, err
	}
	defer file.Close()
	hash := md5.New()
	if _, err := io.Copy(hash, file); err != nil {
		fmt.Println("could not hash file:", filename)
		return md5ChkSum, err
	}
	md5ChkSum = hex.EncodeToString(hash.Sum(nil))
	return md5ChkSum, nil
}

func addSlash(path string) string {
	path = strings.TrimSpace(path)
	if !strings.HasSuffix(path, "/") {
		path = path + "/"
	}
	return path
}
<|endoftext|>


<commit_before>// Copyright 2015 Luke Shumaker

package httpentity

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

func (req Request) StatusOK(entity NetEntity) Response {
	return Response{
		status:  200,
		Headers: http.Header{},
		entity:  entity,
	}
}

func (req Request) StatusCreated(parent Entity, child_name string) Response {
	child := parent.Subentity(child_name, req)
	if child == nil {
		panic("called StatusCreated, but the subentity doesn't exist")
	}
	handler, ok := child.Methods()["GET"]
	if !ok {
		panic("called StatusCreated, but can't GET the subentity")
	}
	response := handler(req)
	response.Headers.Set("Location", url.QueryEscape(child_name))
	if response.entity == nil {
		panic("called StatusCreated, but GET on subentity doesn't return an entity")
	}
	mimetypes := encoders2mimetypes(response.entity.Encoders())
	u, _ := url.Parse("")
	return Response{
		status:  201,
		Headers: response.Headers,
		// XXX: .entity gets modified by (*Router).route()
		// filled in the rest of the way by Route()
		entity: mimetypes2net(u, mimetypes),
	}
}

func (req Request) StatusNoContent() Response {
	return Response{
		status:  204,
		Headers: http.Header{},
		entity:  nil,
	}
}

func (req Request) statusMultipleChoices(u *url.URL, mimetypes []string) Response {
	return Response{
		status:  300,
		Headers: http.Header{},
		entity:  mimetypes2net(u, mimetypes),
	}
}

func (req Request) StatusMoved(u *url.URL) Response {
	return Response{
		status: 301,
		Headers: http.Header{
			"Location": {u.String()},
		},
		entity: NetString("301: Moved"),
	}
}

func (req Request) StatusFound(u *url.URL) Response {
	return Response{
		status: 302,
		Headers: http.Header{
			"Location": {u.String()},
		},
		entity: NetString("302: Found"),
	}
}

func (req Request) StatusBadRequest(err interface{}) Response {
	return Response{
		status:  400,
		Headers: http.Header{},
		entity:  NetString(fmt.Sprintf("400 Bad Request: %v", err)),
	}
}

func (req Request) StatusUnauthorized(e NetEntity) Response {
	return Response{
		status: 401,
		Headers: http.Header{
			"WWW-Authenticate": {"TODO: long-term"},
		},
		entity: e,
	}
}

func (req Request) statusNotFound() Response {
	return Response{
		status:  404,
		Headers: http.Header{},
		entity:  NetString("404 Not Found"),
	}
}

func (req Request) statusMethodNotAllowed(methods string) Response {
	return Response{
		status:  405,
		Headers: http.Header{},
		entity:  NetString("405 Method Not Allowed"),
	}
}

func (req Request) statusNotAcceptable(u *url.URL, mimetypes []string) Response {
	return Response{
		status:  406,
		Headers: http.Header{},
		entity:  mimetypes2net(u, mimetypes),
	}
}

func (req Request) StatusConflict(entity NetEntity) Response {
	return Response{
		status:  409,
		Headers: http.Header{},
		entity:  entity,
	}
}

func (req Request) statusUnsupportedMediaType() Response {
	return Response{
		status:  415,
		Headers: http.Header{},
		entity:  NetString("415 Unsupported Media Type"),
	}
}

func (req Request) statusInternalServerError(err interface{}) Response {
	return Response{
		status: 500,
		Headers: http.Header{
			"Content-Type": {"text/plain; charset=utf-8"},
		},
		entity: NetString(fmt.Sprintf("500 Internal Server Error: %v", err)),
	}
}
<commit_msg>add some documentation to httpentity<commit_after>// Copyright 2015 Luke Shumaker

package httpentity

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

// For when you're returning a document, with nothing special.
func (req Request) StatusOK(entity NetEntity) Response {
	return Response{
		status:  200,
		Headers: http.Header{},
		entity:  entity,
	}
}

// For when you've created a document with a new URL.
func (req Request) StatusCreated(parent Entity, child_name string) Response {
	child := parent.Subentity(child_name, req)
	if child == nil {
		panic("called StatusCreated, but the subentity doesn't exist")
	}
	handler, ok := child.Methods()["GET"]
	if !ok {
		panic("called StatusCreated, but can't GET the subentity")
	}
	response := handler(req)
	response.Headers.Set("Location", url.QueryEscape(child_name))
	if response.entity == nil {
		panic("called StatusCreated, but GET on subentity doesn't return an entity")
	}
	mimetypes := encoders2mimetypes(response.entity.Encoders())
	u, _ := url.Parse("")
	return Response{
		status:  201,
		Headers: response.Headers,
		// XXX: .entity gets modified by (*Router).route()
		// filled in the rest of the way by Route()
		entity: mimetypes2net(u, mimetypes),
	}
}

// For when you've successfully done something, but have no body to
// return.
func (req Request) StatusNoContent() Response {
	return Response{
		status:  204,
		Headers: http.Header{},
		entity:  nil,
	}
}

// For when you have document in multiple formats, but you're not sure
// which the user wants.
func (req Request) statusMultipleChoices(u *url.URL, mimetypes []string) Response {
	return Response{
		status:  300,
		Headers: http.Header{},
		entity:  mimetypes2net(u, mimetypes),
	}
}

// For when the document the user requested has permantly moved to a
// new address.
func (req Request) StatusMoved(u *url.URL) Response {
	return Response{
		status: 301,
		Headers: http.Header{
			"Location": {u.String()},
		},
		entity: NetString("301: Moved"),
	}
}

// For when the document the user requested is currently found at
// another address, but that may not be the case in the future.
func (req Request) StatusFound(u *url.URL) Response {
	return Response{
		status: 302,
		Headers: http.Header{
			"Location": {u.String()},
		},
		entity: NetString("302: Found"),
	}
}

// For when the *user* has screwed up a request.
func (req Request) StatusBadRequest(err interface{}) Response {
	return Response{
		status:  400,
		Headers: http.Header{},
		entity:  NetString(fmt.Sprintf("400 Bad Request: %v", err)),
	}
}

// For when the user doesn't have permission to see something, either
// because they aren't logged in, or because their account doesn't
// have permission.
func (req Request) StatusUnauthorized(e NetEntity) Response {
	return Response{
		status: 401,
		Headers: http.Header{
			"WWW-Authenticate": {"TODO: long-term"},
		},
		entity: e,
	}
}

func (req Request) statusNotFound() Response {
	return Response{
		status:  404,
		Headers: http.Header{},
		entity:  NetString("404 Not Found"),
	}
}

func (req Request) statusMethodNotAllowed(methods string) Response {
	return Response{
		status:  405,
		Headers: http.Header{},
		entity:  NetString("405 Method Not Allowed"),
	}
}

func (req Request) statusNotAcceptable(u *url.URL, mimetypes []string) Response {
	return Response{
		status:  406,
		Headers: http.Header{},
		entity:  mimetypes2net(u, mimetypes),
	}
}

// For when the user asked us to make a change conflicting with the
// current state of things.
func (req Request) StatusConflict(entity NetEntity) Response {
	return Response{
		status:  409,
		Headers: http.Header{},
		entity:  entity,
	}
}

func (req Request) statusUnsupportedMediaType() Response {
	return Response{
		status:  415,
		Headers: http.Header{},
		entity:  NetString("415 Unsupported Media Type"),
	}
}

func (req Request) statusInternalServerError(err interface{}) Response {
	return Response{
		status: 500,
		Headers: http.Header{
			"Content-Type": {"text/plain; charset=utf-8"},
		},
		entity: NetString(fmt.Sprintf("500 Internal Server Error: %v", err)),
	}
}
<|endoftext|>


<commit_before>package bsw

import (
	"crypto/tls"
	"net/http"
	"net/url"
	"regexp"
)

func Headers(ip string) ([]Result, error) {
	results := make([]Result, 0, 2)
	host, _ := hostnameFromHttpLocationHeader(ip, "http")
	if host != "" {
		results = append(results, Result{Source: "Headers", IP: ip, Hostname: host})
	}
	host, _ = hostnameFromHttpLocationHeader(ip, "https")
	if host != "" {
		results = append(results, Result{Source: "Headers", IP: ip, Hostname: host})
	}
	return results, nil
}

func hostnameFromHttpLocationHeader(ip string, protocol string) (string, error) {
	req, err := http.NewRequest("GET", protocol+"://"+ip, nil)
	if err != nil {
		return "", err
	}
	tr := http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}
	res, err := tr.RoundTrip(req)
	if err != nil {
		return "", err
	}
	location := res.Header["Location"]
	if location != nil {
		u, err := url.Parse(location[0])
		if err != nil {
			return "", err
		}
		host := u.Host
		if m, _ := regexp.Match("[a-zA-Z]+", []byte(host)); m == true {
			return host, nil
		}
		return "", nil
	}
	return "", nil
}
<commit_msg>Use pointer<commit_after>package bsw

import (
	"crypto/tls"
	"net/http"
	"net/url"
	"regexp"
)

func Headers(ip string) ([]Result, error) {
	results := make([]Result, 0, 2)
	host, _ := hostnameFromHttpLocationHeader(ip, "http")
	if host != "" {
		results = append(results, Result{Source: "Headers", IP: ip, Hostname: host})
	}
	host, _ = hostnameFromHttpLocationHeader(ip, "https")
	if host != "" {
		results = append(results, Result{Source: "Headers", IP: ip, Hostname: host})
	}
	return results, nil
}

func hostnameFromHttpLocationHeader(ip string, protocol string) (string, error) {
	req, err := http.NewRequest("GET", protocol+"://"+ip, nil)
	if err != nil {
		return "", err
	}
	tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}
	res, err := tr.RoundTrip(req)
	if err != nil {
		return "", err
	}
	location := res.Header["Location"]
	if location != nil {
		u, err := url.Parse(location[0])
		if err != nil {
			return "", err
		}
		host := u.Host
		if m, _ := regexp.Match("[a-zA-Z]+", []byte(host)); m == true {
			return host, nil
		}
		return "", nil
	}
	return "", nil
}
<|endoftext|>


<commit_before>package cpu

import (
	"context"
	"errors"
	"fmt"
	"os/exec"
	"regexp"
	"runtime"
	"sort"
	"strconv"
	"strings"

	"github.com/shirou/gopsutil/internal/common"
)

var ClocksPerSec = float64(128)

func init() {
	getconf, err := exec.LookPath("getconf")
	if err != nil {
		return
	}
	out, err := invoke.Command(getconf, "CLK_TCK")
	// ignore errors
	if err == nil {
		i, err := strconv.ParseFloat(strings.TrimSpace(string(out)), 64)
		if err == nil {
			ClocksPerSec = float64(i)
		}
	}
}

func Times(percpu bool) ([]TimesStat, error) {
	return TimesWithContext(context.Background(), percpu)
}

func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
	return []TimesStat{}, common.ErrNotImplementedError
}

func Info() ([]InfoStat, error) {
	return InfoWithContext(context.Background())
}

func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
	psrInfo, err := exec.LookPath("psrinfo")
	if err != nil {
		return nil, fmt.Errorf("cannot find psrinfo: %s", err)
	}
	psrInfoOut, err := invoke.CommandWithContext(ctx, psrInfo, "-p", "-v")
	if err != nil {
		return nil, fmt.Errorf("cannot execute psrinfo: %s", err)
	}

	isaInfo, err := exec.LookPath("isainfo")
	if err != nil {
		return nil, fmt.Errorf("cannot find isainfo: %s", err)
	}
	isaInfoOut, err := invoke.CommandWithContext(ctx, isaInfo, "-b", "-v")
	if err != nil {
		return nil, fmt.Errorf("cannot execute isainfo: %s", err)
	}

	procs, err := parseProcessorInfo(string(psrInfoOut))
	if err != nil {
		return nil, fmt.Errorf("error parsing psrinfo output: %s", err)
	}

	flags, err := parseISAInfo(string(isaInfoOut))
	if err != nil {
		return nil, fmt.Errorf("error parsing isainfo output: %s", err)
	}

	result := make([]InfoStat, 0, len(flags))
	for _, proc := range procs {
		procWithFlags := proc
		procWithFlags.Flags = flags
		result = append(result, procWithFlags)
	}

	return result, nil
}

var flagsMatch = regexp.MustCompile(`[\w\.]+`)

func parseISAInfo(cmdOutput string) ([]string, error) {
	words := flagsMatch.FindAllString(cmdOutput, -1)

	// Sanity check the output
	if len(words) < 4 || words[1] != "bit" || words[3] != "applications" {
		return nil, errors.New("attempted to parse invalid isainfo output")
	}

	flags := make([]string, len(words)-4)
	for i, val := range words[4:] {
		flags[i] = val
	}
	sort.Strings(flags)

	return flags, nil
}

var psrInfoMatch = regexp.MustCompile(`The physical processor has (?:([\d]+) virtual processor \(([\d]+)\)|([\d]+) cores and ([\d]+) virtual processors[^\n]+)\n(?:\s+ The core has.+\n)*\s+.+ \((\w+) ([\S]+) family (.+) model (.+) step (.+) clock (.+) MHz\)\n[\s]*(.*)`)

const (
	psrNumCoresOffset   = 1
	psrNumCoresHTOffset = 3
	psrNumHTOffset      = 4
	psrVendorIDOffset   = 5
	psrFamilyOffset     = 7
	psrModelOffset      = 8
	psrStepOffset       = 9
	psrClockOffset      = 10
	psrModelNameOffset  = 11
)

func parseProcessorInfo(cmdOutput string) ([]InfoStat, error) {
	matches := psrInfoMatch.FindAllStringSubmatch(cmdOutput, -1)

	var infoStatCount int32
	result := make([]InfoStat, 0, len(matches))
	for physicalIndex, physicalCPU := range matches {
		var step int32
		var clock float64

		if physicalCPU[psrStepOffset] != "" {
			stepParsed, err := strconv.ParseInt(physicalCPU[psrStepOffset], 10, 32)
			if err != nil {
				return nil, fmt.Errorf("cannot parse value %q for step as 32-bit integer: %s", physicalCPU[9], err)
			}
			step = int32(stepParsed)
		}

		if physicalCPU[psrClockOffset] != "" {
			clockParsed, err := strconv.ParseInt(physicalCPU[psrClockOffset], 10, 64)
			if err != nil {
				return nil, fmt.Errorf("cannot parse value %q for clock as 32-bit integer: %s", physicalCPU[10], err)
			}
			clock = float64(clockParsed)
		}

		var err error
		var numCores int64
		var numHT int64
		switch {
		case physicalCPU[psrNumCoresOffset] != "":
			numCores, err = strconv.ParseInt(physicalCPU[psrNumCoresOffset], 10, 32)
			if err != nil {
				return nil, fmt.Errorf("cannot parse value %q for core count as 32-bit integer: %s", physicalCPU[1], err)
			}

			for i := 0; i < int(numCores); i++ {
				result = append(result, InfoStat{
					CPU:        infoStatCount,
					PhysicalID: strconv.Itoa(physicalIndex),
					CoreID:     strconv.Itoa(i),
					Cores:      1,
					VendorID:   physicalCPU[psrVendorIDOffset],
					ModelName:  physicalCPU[psrModelNameOffset],
					Family:     physicalCPU[psrFamilyOffset],
					Model:      physicalCPU[psrModelOffset],
					Stepping:   step,
					Mhz:        clock,
				})
				infoStatCount++
			}
		case physicalCPU[psrNumCoresHTOffset] != "":
			numCores, err = strconv.ParseInt(physicalCPU[psrNumCoresHTOffset], 10, 32)
			if err != nil {
				return nil, fmt.Errorf("cannot parse value %q for core count as 32-bit integer: %s", physicalCPU[3], err)
			}

			numHT, err = strconv.ParseInt(physicalCPU[psrNumHTOffset], 10, 32)
			if err != nil {
				return nil, fmt.Errorf("cannot parse value %q for hyperthread count as 32-bit integer: %s", physicalCPU[4], err)
			}

			for i := 0; i < int(numCores); i++ {
				result = append(result, InfoStat{
					CPU:        infoStatCount,
					PhysicalID: strconv.Itoa(physicalIndex),
					CoreID:     strconv.Itoa(i),
					Cores:      int32(numHT) / int32(numCores),
					VendorID:   physicalCPU[psrVendorIDOffset],
					ModelName:  physicalCPU[psrModelNameOffset],
					Family:     physicalCPU[psrFamilyOffset],
					Model:      physicalCPU[psrModelOffset],
					Stepping:   step,
					Mhz:        clock,
				})
				infoStatCount++
			}
		default:
			return nil, errors.New("values for cores with and without hyperthreading are both set")
		}
	}
	return result, nil
}

func CountsWithContext(ctx context.Context, logical bool) (int, error) {
	return runtime.NumCPU(), nil
}
<commit_msg>Add support for Solaris CPU times<commit_after>package cpu

import (
	"bytes"
	"context"
	"errors"
	"fmt"
	"os/exec"
	"regexp"
	"runtime"
	"sort"
	"strconv"
	"strings"
)

var ClocksPerSec = float64(128)

func init() {
	getconf, err := exec.LookPath("getconf")
	if err != nil {
		return
	}
	out, err := invoke.Command(getconf, "CLK_TCK")
	// ignore errors
	if err == nil {
		i, err := strconv.ParseFloat(strings.TrimSpace(string(out)), 64)
		if err == nil {
			ClocksPerSec = float64(i)
		}
	}
}

//sum all values in a float64 map with float64 keys
func msum(x map[float64]float64) float64 {
	total := 0.0
	for _, y := range x {
		total += y
	}
	return total
}

func Times(percpu bool) ([]TimesStat, error) {
	return TimesWithContext(context.Background(), percpu)
}

func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
	kstatSys, err := exec.LookPath("kstat")
	if err != nil {
		return nil, fmt.Errorf("cannot find kstat: %s", err)
	}
	cpu := make(map[float64]float64)
	idle := make(map[float64]float64)
	user := make(map[float64]float64)
	kern := make(map[float64]float64)
	iowt := make(map[float64]float64)
	//swap := make(map[float64]float64)
	kstatSysOut, err := invoke.CommandWithContext(ctx, kstatSys, "-C", "cpu_stat:*:*:/^idle$|^user$|^kernel$|^iowait$|^swap$/")
	if err != nil {
		return nil, fmt.Errorf("cannot execute kstat: %s", err)
	}
	for _, line := range strings.Split(bytes.NewBuffer(kstatSysOut).String(), "\n") {
		fields := strings.Split(line, ":")
		if fields[0] != "cpu_stat" {
			continue
		}
		cpuNumber, err := strconv.ParseFloat(fields[1], 64)
		if err != nil {
			return nil, fmt.Errorf("cannot parse cpu number: %s", err)
		}
		cpu[cpuNumber] = cpuNumber
		switch fields[3] {
		case "idle":
			idle[cpuNumber], err = strconv.ParseFloat(fields[4], 64)
			if err != nil {
				return nil, fmt.Errorf("cannot parse idle: %s", err)
			}
		case "user":
			user[cpuNumber], err = strconv.ParseFloat(fields[4], 64)
			if err != nil {
				return nil, fmt.Errorf("cannot parse user: %s", err)
			}
		case "kernel":
			kern[cpuNumber], err = strconv.ParseFloat(fields[4], 64)
			if err != nil {
				return nil, fmt.Errorf("cannot parse kernel: %s", err)
			}
		case "iowait":
			iowt[cpuNumber], err = strconv.ParseFloat(fields[4], 64)
			if err != nil {
				return nil, fmt.Errorf("cannot parse iowait: %s", err)
			}
			//not sure how this translates, don't report, add to kernel, something else?
			/*case "swap":
			swap[cpuNumber], err = strconv.ParseFloat(fields[4], 64)
			if err != nil {
				return nil, fmt.Errorf("cannot parse swap: %s", err)
			} */
		}
	}
	ret := make([]TimesStat, 0, len(cpu))
	if percpu {
		for _, c := range cpu {
			ct := &TimesStat{
				CPU:    fmt.Sprintf("cpu%d", int(cpu[c])),
				Idle:   idle[c] / ClocksPerSec,
				User:   user[c] / ClocksPerSec,
				System: kern[c] / ClocksPerSec,
				Iowait: iowt[c] / ClocksPerSec,
			}
			ret = append(ret, *ct)
		}
	} else {
		ct := &TimesStat{
			CPU:    "cpu-total",
			Idle:   msum(idle) / ClocksPerSec,
			User:   msum(user) / ClocksPerSec,
			System: msum(kern) / ClocksPerSec,
			Iowait: msum(iowt) / ClocksPerSec,
		}
		ret = append(ret, *ct)
	}
	return ret, nil
}

func Info() ([]InfoStat, error) {
	return InfoWithContext(context.Background())
}

func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
	psrInfo, err := exec.LookPath("psrinfo")
	if err != nil {
		return nil, fmt.Errorf("cannot find psrinfo: %s", err)
	}
	psrInfoOut, err := invoke.CommandWithContext(ctx, psrInfo, "-p", "-v")
	if err != nil {
		return nil, fmt.Errorf("cannot execute psrinfo: %s", err)
	}

	isaInfo, err := exec.LookPath("isainfo")
	if err != nil {
		return nil, fmt.Errorf("cannot find isainfo: %s", err)
	}
	isaInfoOut, err := invoke.CommandWithContext(ctx, isaInfo, "-b", "-v")
	if err != nil {
		return nil, fmt.Errorf("cannot execute isainfo: %s", err)
	}

	procs, err := parseProcessorInfo(string(psrInfoOut))
	if err != nil {
		return nil, fmt.Errorf("error parsing psrinfo output: %s", err)
	}

	flags, err := parseISAInfo(string(isaInfoOut))
	if err != nil {
		return nil, fmt.Errorf("error parsing isainfo output: %s", err)
	}

	result := make([]InfoStat, 0, len(flags))
	for _, proc := range procs {
		procWithFlags := proc
		procWithFlags.Flags = flags
		result = append(result, procWithFlags)
	}

	return result, nil
}

var flagsMatch = regexp.MustCompile(`[\w\.]+`)

func parseISAInfo(cmdOutput string) ([]string, error) {
	words := flagsMatch.FindAllString(cmdOutput, -1)

	// Sanity check the output
	if len(words) < 4 || words[1] != "bit" || words[3] != "applications" {
		return nil, errors.New("attempted to parse invalid isainfo output")
	}

	flags := make([]string, len(words)-4)
	for i, val := range words[4:] {
		flags[i] = val
	}
	sort.Strings(flags)

	return flags, nil
}

var psrInfoMatch = regexp.MustCompile(`The physical processor has (?:([\d]+) virtual processor \(([\d]+)\)|([\d]+) cores and ([\d]+) virtual processors[^\n]+)\n(?:\s+ The core has.+\n)*\s+.+ \((\w+) ([\S]+) family (.+) model (.+) step (.+) clock (.+) MHz\)\n[\s]*(.*)`)

const (
	psrNumCoresOffset   = 1
	psrNumCoresHTOffset = 3
	psrNumHTOffset      = 4
	psrVendorIDOffset   = 5
	psrFamilyOffset     = 7
	psrModelOffset      = 8
	psrStepOffset       = 9
	psrClockOffset      = 10
	psrModelNameOffset  = 11
)

func parseProcessorInfo(cmdOutput string) ([]InfoStat, error) {
	matches := psrInfoMatch.FindAllStringSubmatch(cmdOutput, -1)

	var infoStatCount int32
	result := make([]InfoStat, 0, len(matches))
	for physicalIndex, physicalCPU := range matches {
		var step int32
		var clock float64

		if physicalCPU[psrStepOffset] != "" {
			stepParsed, err := strconv.ParseInt(physicalCPU[psrStepOffset], 10, 32)
			if err != nil {
				return nil, fmt.Errorf("cannot parse value %q for step as 32-bit integer: %s", physicalCPU[9], err)
			}
			step = int32(stepParsed)
		}

		if physicalCPU[psrClockOffset] != "" {
			clockParsed, err := strconv.ParseInt(physicalCPU[psrClockOffset], 10, 64)
			if err != nil {
				return nil, fmt.Errorf("cannot parse value %q for clock as 32-bit integer: %s", physicalCPU[10], err)
			}
			clock = float64(clockParsed)
		}

		var err error
		var numCores int64
		var numHT int64
		switch {
		case physicalCPU[psrNumCoresOffset] != "":
			numCores, err = strconv.ParseInt(physicalCPU[psrNumCoresOffset], 10, 32)
			if err != nil {
				return nil, fmt.Errorf("cannot parse value %q for core count as 32-bit integer: %s", physicalCPU[1], err)
			}

			for i := 0; i < int(numCores); i++ {
				result = append(result, InfoStat{
					CPU:        infoStatCount,
					PhysicalID: strconv.Itoa(physicalIndex),
					CoreID:     strconv.Itoa(i),
					Cores:      1,
					VendorID:   physicalCPU[psrVendorIDOffset],
					ModelName:  physicalCPU[psrModelNameOffset],
					Family:     physicalCPU[psrFamilyOffset],
					Model:      physicalCPU[psrModelOffset],
					Stepping:   step,
					Mhz:        clock,
				})
				infoStatCount++
			}
		case physicalCPU[psrNumCoresHTOffset] != "":
			numCores, err = strconv.ParseInt(physicalCPU[psrNumCoresHTOffset], 10, 32)
			if err != nil {
				return nil, fmt.Errorf("cannot parse value %q for core count as 32-bit integer: %s", physicalCPU[3], err)
			}

			numHT, err = strconv.ParseInt(physicalCPU[psrNumHTOffset], 10, 32)
			if err != nil {
				return nil, fmt.Errorf("cannot parse value %q for hyperthread count as 32-bit integer: %s", physicalCPU[4], err)
			}

			for i := 0; i < int(numCores); i++ {
				result = append(result, InfoStat{
					CPU:        infoStatCount,
					PhysicalID: strconv.Itoa(physicalIndex),
					CoreID:     strconv.Itoa(i),
					Cores:      int32(numHT) / int32(numCores),
					VendorID:   physicalCPU[psrVendorIDOffset],
					ModelName:  physicalCPU[psrModelNameOffset],
					Family:     physicalCPU[psrFamilyOffset],
					Model:      physicalCPU[psrModelOffset],
					Stepping:   step,
					Mhz:        clock,
				})
				infoStatCount++
			}
		default:
			return nil, errors.New("values for cores with and without hyperthreading are both set")
		}
	}
	return result, nil
}

func CountsWithContext(ctx context.Context, logical bool) (int, error) {
	return runtime.NumCPU(), nil
}
<|endoftext|>


<commit_before>// Copyright © 2014 Steve Francia <spf@spf13.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

package viper

import (
	"bytes"
	"testing"

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

var yamlExample = []byte(`Hacker: true
name: steve
hobbies:
- skateboarding
- snowboarding
- go
clothing:
  jacket: leather
  trousers: denim
age: 35`)

var tomlExample = []byte(`
title = "TOML Example"

[owner]
organization = "MongoDB"
Bio = "MongoDB Chief Developer Advocate & Hacker at Large"
dob = 1979-05-27T07:32:00Z # First class dates? Why not?`)

var jsonExample = []byte(`{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters": {
        "batter": [
                { "type": "Regular" },
                { "type": "Chocolate" },
                { "type": "Blueberry" },
                { "type": "Devil's Food" }
            ]
    }
}`)

func TestBasics(t *testing.T) {
	SetConfigFile("/tmp/config.yaml")
	assert.Equal(t, "/tmp/config.yaml", getConfigFile())
}

func TestDefault(t *testing.T) {
	SetDefault("age", 45)
	assert.Equal(t, 45, Get("age"))
}

func TestMarshalling(t *testing.T) {
	SetConfigType("yaml")
	r := bytes.NewReader(yamlExample)

	MarshallReader(r)
	assert.True(t, InConfig("name"))
	assert.False(t, InConfig("state"))
	assert.Equal(t, "steve", Get("name"))
	assert.Equal(t, []interface{}{"skateboarding", "snowboarding", "go"}, Get("hobbies"))
	assert.Equal(t, map[interface{}]interface{}{"jacket": "leather", "trousers": "denim"}, Get("clothing"))
	assert.Equal(t, 35, Get("age"))
}

func TestOverrides(t *testing.T) {
	Set("age", 40)
	assert.Equal(t, 40, Get("age"))
}

func TestDefaultPost(t *testing.T) {
	assert.NotEqual(t, "NYC", Get("state"))
	SetDefault("state", "NYC")
	assert.Equal(t, "NYC", Get("state"))
}

func TestAliases(t *testing.T) {
	RegisterAlias("years", "age")
	assert.Equal(t, 40, Get("years"))
	Set("years", 45)
	assert.Equal(t, 45, Get("age"))
}

func TestYML(t *testing.T) {
	Reset()
	SetConfigType("yml")
	r := bytes.NewReader(yamlExample)

	MarshallReader(r)
	assert.Equal(t, "steve", Get("name"))
}

func TestJSON(t *testing.T) {
	SetConfigType("json")
	r := bytes.NewReader(jsonExample)

	MarshallReader(r)
	assert.Equal(t, "0001", Get("id"))
}

func TestTOML(t *testing.T) {
	SetConfigType("toml")
	r := bytes.NewReader(tomlExample)

	MarshallReader(r)
	assert.Equal(t, "TOML Example", Get("title"))
}

func TestCaseInSensitive(t *testing.T) {
	assert.Equal(t, true, Get("hacker"))
	Set("Title", "Checking Case")
	assert.Equal(t, "Checking Case", Get("tItle"))
}

func TestAliasesOfAliases(t *testing.T) {
	RegisterAlias("Foo", "Bar")
	RegisterAlias("Bar", "Title")
	assert.Equal(t, "Checking Case", Get("FOO"))
}

func TestRecursiveAliases(t *testing.T) {
	RegisterAlias("Baz", "Roo")
	RegisterAlias("Roo", "baz")
}

func TestIntoStruct(t *testing.T) {
	SetDefault("port", 1313)
	Set("name", "Steve")

	type config struct {
		Port int
		Name string
	}

	var C config

	err := GetAllIntoStruct(&C)
	if err != nil {
		t.Fatalf("unable to decode into struct, %v", err)
	}

	assert.Equal(t, &C, &config{Name: "Steve", Port: 1313})

	Set("port", 1234)
	err = GetAllIntoStruct(&C)
	if err != nil {
		t.Fatalf("unable to decode into struct, %v", err)
	}
	assert.Equal(t, &C, &config{Name: "Steve", Port: 1234})
}
<commit_msg>fix test after function rename<commit_after>// Copyright © 2014 Steve Francia <spf@spf13.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

package viper

import (
	"bytes"
	"testing"

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

var yamlExample = []byte(`Hacker: true
name: steve
hobbies:
- skateboarding
- snowboarding
- go
clothing:
  jacket: leather
  trousers: denim
age: 35`)

var tomlExample = []byte(`
title = "TOML Example"

[owner]
organization = "MongoDB"
Bio = "MongoDB Chief Developer Advocate & Hacker at Large"
dob = 1979-05-27T07:32:00Z # First class dates? Why not?`)

var jsonExample = []byte(`{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters": {
        "batter": [
                { "type": "Regular" },
                { "type": "Chocolate" },
                { "type": "Blueberry" },
                { "type": "Devil's Food" }
            ]
    }
}`)

func TestBasics(t *testing.T) {
	SetConfigFile("/tmp/config.yaml")
	assert.Equal(t, "/tmp/config.yaml", getConfigFile())
}

func TestDefault(t *testing.T) {
	SetDefault("age", 45)
	assert.Equal(t, 45, Get("age"))
}

func TestMarshalling(t *testing.T) {
	SetConfigType("yaml")
	r := bytes.NewReader(yamlExample)

	MarshallReader(r)
	assert.True(t, InConfig("name"))
	assert.False(t, InConfig("state"))
	assert.Equal(t, "steve", Get("name"))
	assert.Equal(t, []interface{}{"skateboarding", "snowboarding", "go"}, Get("hobbies"))
	assert.Equal(t, map[interface{}]interface{}{"jacket": "leather", "trousers": "denim"}, Get("clothing"))
	assert.Equal(t, 35, Get("age"))
}

func TestOverrides(t *testing.T) {
	Set("age", 40)
	assert.Equal(t, 40, Get("age"))
}

func TestDefaultPost(t *testing.T) {
	assert.NotEqual(t, "NYC", Get("state"))
	SetDefault("state", "NYC")
	assert.Equal(t, "NYC", Get("state"))
}

func TestAliases(t *testing.T) {
	RegisterAlias("years", "age")
	assert.Equal(t, 40, Get("years"))
	Set("years", 45)
	assert.Equal(t, 45, Get("age"))
}

func TestYML(t *testing.T) {
	Reset()
	SetConfigType("yml")
	r := bytes.NewReader(yamlExample)

	MarshallReader(r)
	assert.Equal(t, "steve", Get("name"))
}

func TestJSON(t *testing.T) {
	SetConfigType("json")
	r := bytes.NewReader(jsonExample)

	MarshallReader(r)
	assert.Equal(t, "0001", Get("id"))
}

func TestTOML(t *testing.T) {
	SetConfigType("toml")
	r := bytes.NewReader(tomlExample)

	MarshallReader(r)
	assert.Equal(t, "TOML Example", Get("title"))
}

func TestCaseInSensitive(t *testing.T) {
	assert.Equal(t, true, Get("hacker"))
	Set("Title", "Checking Case")
	assert.Equal(t, "Checking Case", Get("tItle"))
}

func TestAliasesOfAliases(t *testing.T) {
	RegisterAlias("Foo", "Bar")
	RegisterAlias("Bar", "Title")
	assert.Equal(t, "Checking Case", Get("FOO"))
}

func TestRecursiveAliases(t *testing.T) {
	RegisterAlias("Baz", "Roo")
	RegisterAlias("Roo", "baz")
}

func TestMarshal(t *testing.T) {
	SetDefault("port", 1313)
	Set("name", "Steve")

	type config struct {
		Port int
		Name string
	}

	var C config

	err := Marshal(&C)
	if err != nil {
		t.Fatalf("unable to decode into struct, %v", err)
	}

	assert.Equal(t, &C, &config{Name: "Steve", Port: 1313})

	Set("port", 1234)
	err = Marshal(&C)
	if err != nil {
		t.Fatalf("unable to decode into struct, %v", err)
	}
	assert.Equal(t, &C, &config{Name: "Steve", Port: 1234})
}
<|endoftext|>


<commit_before>package common

import (
	"net"
	"os"
	"testing"
	"time"
)

const (
	confFile = "../bin/quantum-test.yml"
)

var (
	testPacket []byte
)

func init() {
	testPacket = make([]byte, 18)
	// IP (1.1.1.1)
	testPacket[0] = 1
	testPacket[1] = 1
	testPacket[2] = 1
	testPacket[3] = 1

	// Nonce
	testPacket[4] = 2
	testPacket[5] = 2
	testPacket[6] = 2
	testPacket[7] = 2
	testPacket[8] = 2
	testPacket[9] = 2
	testPacket[10] = 2
	testPacket[11] = 2
	testPacket[12] = 2
	testPacket[13] = 2
	testPacket[14] = 2
	testPacket[15] = 2

	// Packet data
	testPacket[16] = 3
	testPacket[17] = 3
}

func testEq(a, b []byte) bool {

	if a == nil && b == nil {
		return true
	}

	if a == nil || b == nil {
		return false
	}

	if len(a) != len(b) {
		return false
	}

	for i := range a {
		if a[i] != b[i] {
			return false
		}
	}

	return true
}

func TestArrayEquals(t *testing.T) {
	if !ArrayEquals(nil, nil) {
		t.Fatal("ArrayEquals returned false comparing nil/nil")
	}
	if ArrayEquals([]byte{0}, nil) {
		t.Fatal("ArrayEquals returned true comparing nil/non-nil")
	}
	if ArrayEquals([]byte{0, 1}, []byte{0}) {
		t.Fatal("ArrayEquals returned true comparing mismatched lengths")
	}
	if !ArrayEquals([]byte{0, 1}, []byte{0, 1}) {
		t.Fatal("ArrayEquals returned false for equal arrays")
	}
}

func TestIPtoInt(t *testing.T) {
	var expected uint32
	actual := IPtoInt(net.ParseIP("0.0.0.0"))
	if expected != actual {
		t.Fatalf("IPtoInt did not return the right value, got: %d, expected: %d", actual, expected)
	}
}

func TestIncrementIP(t *testing.T) {
	expected := net.ParseIP("10.0.0.1")

	actual := net.ParseIP("10.0.0.0")
	IncrementIP(actual)

	if !testEq(expected, actual) {
		t.Fatalf("IncrementIP did not return the right value, got: %s, expected: %s", actual, expected)
	}
}

func TestNewConfig(t *testing.T) {
	os.Setenv("QUANTUM_DEVICE_NAME", "different")
	os.Setenv("QUANTUM_LISTEN_PORT", "1")
	os.Setenv("QUANTUM_CONF_FILE", confFile)
	os.Setenv("QUANTUM_PID_FILE", "../quantum.pid")
	os.Setenv("_QUANTUM_REAL_DEVICE_NAME_", "quantum0")

	os.Args = append(os.Args, "-n", "100", "--prefix", "woot", "--tls-skip-verify", "-6", "fd00:dead:beef::2")
	cfg, err := NewConfig()
	if err != nil {
		t.Fatalf("NewConfig returned an error, %s", err)
	}
	t.Log(cfg)
	if cfg == nil {
		t.Fatal("NewConfig returned a blank config")
	}
	if cfg.DeviceName != "different" {
		t.Fatalf("NewConfig didn't pick up the environment variable replacement for DeviceName")
	}
	if cfg.ListenPort != 1 {
		t.Fatalf("NewConfig didn't pick up the environment variable replacement for ListenPort")
	}
	if cfg.Password != "Password1" {
		t.Fatalf("NewConfig didn't pick up the config file replacement for Password")
	}
	if cfg.Prefix != "woot" {
		t.Fatal("NewConfig didn't pick up the cli replacement for Prefix")
	}
	if cfg.NumWorkers != 1 {
		t.Fatal("NewConfig didn't pick up the cli replacement for NumWorkers")
	}
	if !cfg.TLSSkipVerify {
		t.Fatal("NewConfig didn't pick up the cli replacement for TLSSkipVerify")
	}

	cfg.usage(false)
	cfg.version(false)
}

func TestEcdh(t *testing.T) {
	pub, priv := GenerateECKeyPair()
	if len(pub) != keyLength {
		t.Fatalf("GenerateECKeyPair did not return the right length for the public key,\nactual: %d, expected: %d", len(pub), keyLength)
	}
	if len(priv) != keyLength {
		t.Fatalf("GenerateECKeyPair did not return the right length for the private key,\nactual: %d, expected: %d", len(priv), keyLength)
	}
	if testEq(pub, priv) {
		t.Fatalf("GenerateECKeyPair returned identical pub/priv keys this can't possibly happen:\npub: %v, priv: %v", pub, priv)
	}
	secret := GenerateSharedSecret(pub, priv)
	if len(secret) != keyLength {
		t.Fatalf("GenerateECKeyPair did not return the right length for the shared secret,\nactual: %d, expected: %d", len(secret), keyLength)
	}
	if testEq(secret, pub) || testEq(secret, priv) {
		t.Fatalf("GenerateECKeyPair returned identical secret and pub/priv keys this can't possibly happen:\npub: %v, priv: %v, secret: %v", pub, priv, secret)
	}
}

func TestNewMapping(t *testing.T) {
	privateIP := net.ParseIP("0.0.0.0")
	publicip := net.ParseIP("1.1.1.1")
	publicip6 := net.ParseIP("dead::beef")
	publicport := 80
	publicKey := make([]byte, 32)
	machineID := "123456"

	actual := NewMapping(machineID, privateIP, publicip, publicip6, publicport, publicKey)
	if !testEq(actual.IPv4, publicip) || !testEq(actual.IPv6, publicip6) || actual.Port != publicport || !testEq(actual.PrivateIP, privateIP) || !testEq(actual.PublicKey, publicKey) {
		t.Fatalf("NewMapping did not return the right value, got: %v", actual)
	}
}

func TestParseMapping(t *testing.T) {
	privateIP := net.ParseIP("0.0.0.0")
	publicip := net.ParseIP("1.1.1.1")
	publicip6 := net.ParseIP("dead::beef")
	publicport := 80
	publicKey := make([]byte, 32)
	machineID := "123456"

	expected := NewMapping(machineID, privateIP, publicip, publicip6, publicport, publicKey)
	actual, err := ParseMapping(expected.String(), make([]byte, 32))
	if err != nil {
		t.Fatalf("Error occured during test: %s", err)
	}
	if !testEq(actual.IPv4, expected.IPv4) || actual.Port != expected.Port || !testEq(actual.PrivateIP, expected.PrivateIP) || !testEq(actual.PublicKey, expected.PublicKey) {
		t.Fatalf("ParseMapping did not return the right value, got: %v, expected: %v", actual, expected)
	}
}

func TestParseNetworkConfig(t *testing.T) {
	actual, err := ParseNetworkConfig(DefaultNetworkConfig.Bytes())
	if err != nil {
		t.Fatal("ParseNetworkConfig returned an error:", err)
	}
	if actual.Network != DefaultNetworkConfig.Network || actual.LeaseTime != DefaultNetworkConfig.LeaseTime {
		t.Fatalf("ParseNetworkConfig returned the wrong value, got: %v, expected: %v", actual, DefaultNetworkConfig)
	}
}

func TestParseNetworkConfigOnlyNetwork(t *testing.T) {
	netCfg := &NetworkConfig{Network: "10.10.0.0/16"}
	actual, err := ParseNetworkConfig(netCfg.Bytes())
	if err != nil {
		t.Fatal("ParseNetworkConfig returned an error:", err)
	}
	if actual.Network != netCfg.Network || actual.LeaseTime != 48*time.Hour {
		t.Fatalf("ParseNetworkConfig returned the wrong value, got: %v, expected: %v", actual, netCfg)
	}
}

func TestParseNetworkConfigIncorrectFormat(t *testing.T) {
	netCfg := &NetworkConfig{Network: "10.10.0."}
	_, err := ParseNetworkConfig(netCfg.Bytes())
	if err == nil {
		t.Fatal("ParseNetworkConfig should have errored")
	}

	netCfg.Network = "10.10.0.0/16"
	netCfg.StaticRange = "10.10.0./23"

	_, err = ParseNetworkConfig(netCfg.Bytes())
	if err == nil {
		t.Fatal("ParseNetworkConfig should have errored")
	}

	netCfg.StaticRange = "10.20.0.0/23"
	_, err = ParseNetworkConfig(netCfg.Bytes())
	if err == nil {
		t.Fatal("ParseNetworkConfig should have errored")
	}
}

func TestNewTunPayload(t *testing.T) {
	payload := NewTunPayload(testPacket, 2)
	for i := 0; i < 4; i++ {
		if payload.IPAddress[i] != 1 {
			t.Fatal("NewTunPayload returned an incorrect IP address mapping.")
		}
	}

	for i := 0; i < 12; i++ {
		if payload.Nonce[i] != 2 {
			t.Fatal("NewTunPayload returned an incorrect Nonce mapping.")
		}
	}

	for i := 0; i < 2; i++ {
		if payload.Packet[i] != 3 {
			t.Fatal("NewTunPayload returned an incorrect Packet mapping.")
		}
	}
}

func TestNewSockPayload(t *testing.T) {
	payload := NewSockPayload(testPacket, 18)
	for i := 0; i < 4; i++ {
		if payload.IPAddress[i] != 1 {
			t.Fatal("NewTunPayload returned an incorrect IP address mapping.")
		}
	}

	for i := 0; i < 12; i++ {
		if payload.Nonce[i] != 2 {
			t.Fatal("NewTunPayload returned an incorrect Nonce mapping.")
		}
	}

	for i := 0; i < 2; i++ {
		if payload.Packet[i] != 3 {
			t.Fatal("NewTunPayload returned an incorrect Packet mapping.")
		}
	}
}

func TestNewStats(t *testing.T) {
	stats := NewStats(1)
	if stats.Packets != 0 {
		t.Fatalf("NewStats did not return the correct default for Packets, got: %d, expected: %d", stats.Packets, 0)
	}
	if stats.Bytes != 0 {
		t.Fatalf("NewStats did not return the correct default for Bytes, got: %d, expected: %d", stats.Bytes, 0)
	}
	if stats.Links == nil {
		t.Fatalf("NewStats did not return the correct default for Links, got: %v, expected: %v", stats.Links, make(map[string]*Stats))
	}
	str := stats.String()
	if str == "" {
		t.Fatalf("String didn't return the correct value.")
	}
}

func TestNewLogger(t *testing.T) {
	log := NewLogger()
	if log.Error == nil {
		t.Fatal("NewLogger returned a nil Error log.")
	}
	if log.Info == nil {
		t.Fatal("NewLogger returned a nil Error log.")
	}
}

func TestGenerateLocalMapping(t *testing.T) {
	cfg := &Config{
		PrivateIP:     net.ParseIP("10.10.0.1"),
		PublicIPv4:    net.ParseIP("192.167.0.1"),
		PublicIPv6:    net.ParseIP("fd00:dead:beef::2"),
		ListenPort:    1099,
		PublicKey:     make([]byte, 32),
		NetworkConfig: DefaultNetworkConfig,
		MachineID:     "123",
	}

	mappings := make(map[uint32]*Mapping)
	mapping, err := GenerateLocalMapping(cfg, mappings)
	if err != nil {
		t.Fatal(err)
	}

	if !testEq(mapping.PrivateIP.To4(), cfg.PrivateIP.To4()) {
		t.Fatal("GenerateLocalMapping created the wrong mapping.")
	}

	mappings[IPtoInt(cfg.PrivateIP)] = mapping

	_, err = GenerateLocalMapping(cfg, mappings)
	if err != nil {
		t.Fatal(err)
	}

	mapping.MachineID = "456"

	_, err = GenerateLocalMapping(cfg, mappings)
	if err == nil {
		t.Fatal("GenerateLocalMapping failed to properly handle an existing ip address")
	}

	cfg.PrivateIP = nil
	mapping.MachineID = "123"

	_, err = GenerateLocalMapping(cfg, mappings)
	if err != nil {
		t.Fatal(err)
	}

	cfg.PrivateIP = nil
	_, err = GenerateLocalMapping(cfg, make(map[uint32]*Mapping))
	if err != nil {
		t.Fatal(err)
	}
}
<commit_msg>Removed a debug line<commit_after>package common

import (
	"net"
	"os"
	"testing"
	"time"
)

const (
	confFile = "../bin/quantum-test.yml"
)

var (
	testPacket []byte
)

func init() {
	testPacket = make([]byte, 18)
	// IP (1.1.1.1)
	testPacket[0] = 1
	testPacket[1] = 1
	testPacket[2] = 1
	testPacket[3] = 1

	// Nonce
	testPacket[4] = 2
	testPacket[5] = 2
	testPacket[6] = 2
	testPacket[7] = 2
	testPacket[8] = 2
	testPacket[9] = 2
	testPacket[10] = 2
	testPacket[11] = 2
	testPacket[12] = 2
	testPacket[13] = 2
	testPacket[14] = 2
	testPacket[15] = 2

	// Packet data
	testPacket[16] = 3
	testPacket[17] = 3
}

func testEq(a, b []byte) bool {

	if a == nil && b == nil {
		return true
	}

	if a == nil || b == nil {
		return false
	}

	if len(a) != len(b) {
		return false
	}

	for i := range a {
		if a[i] != b[i] {
			return false
		}
	}

	return true
}

func TestArrayEquals(t *testing.T) {
	if !ArrayEquals(nil, nil) {
		t.Fatal("ArrayEquals returned false comparing nil/nil")
	}
	if ArrayEquals([]byte{0}, nil) {
		t.Fatal("ArrayEquals returned true comparing nil/non-nil")
	}
	if ArrayEquals([]byte{0, 1}, []byte{0}) {
		t.Fatal("ArrayEquals returned true comparing mismatched lengths")
	}
	if !ArrayEquals([]byte{0, 1}, []byte{0, 1}) {
		t.Fatal("ArrayEquals returned false for equal arrays")
	}
}

func TestIPtoInt(t *testing.T) {
	var expected uint32
	actual := IPtoInt(net.ParseIP("0.0.0.0"))
	if expected != actual {
		t.Fatalf("IPtoInt did not return the right value, got: %d, expected: %d", actual, expected)
	}
}

func TestIncrementIP(t *testing.T) {
	expected := net.ParseIP("10.0.0.1")

	actual := net.ParseIP("10.0.0.0")
	IncrementIP(actual)

	if !testEq(expected, actual) {
		t.Fatalf("IncrementIP did not return the right value, got: %s, expected: %s", actual, expected)
	}
}

func TestNewConfig(t *testing.T) {
	os.Setenv("QUANTUM_DEVICE_NAME", "different")
	os.Setenv("QUANTUM_LISTEN_PORT", "1")
	os.Setenv("QUANTUM_CONF_FILE", confFile)
	os.Setenv("QUANTUM_PID_FILE", "../quantum.pid")
	os.Setenv("_QUANTUM_REAL_DEVICE_NAME_", "quantum0")

	os.Args = append(os.Args, "-n", "100", "--prefix", "woot", "--tls-skip-verify", "-6", "fd00:dead:beef::2")
	cfg, err := NewConfig()
	if err != nil {
		t.Fatalf("NewConfig returned an error, %s", err)
	}
	if cfg == nil {
		t.Fatal("NewConfig returned a blank config")
	}
	if cfg.DeviceName != "different" {
		t.Fatalf("NewConfig didn't pick up the environment variable replacement for DeviceName")
	}
	if cfg.ListenPort != 1 {
		t.Fatalf("NewConfig didn't pick up the environment variable replacement for ListenPort")
	}
	if cfg.Password != "Password1" {
		t.Fatalf("NewConfig didn't pick up the config file replacement for Password")
	}
	if cfg.Prefix != "woot" {
		t.Fatal("NewConfig didn't pick up the cli replacement for Prefix")
	}
	if cfg.NumWorkers != 1 {
		t.Fatal("NewConfig didn't pick up the cli replacement for NumWorkers")
	}
	if !cfg.TLSSkipVerify {
		t.Fatal("NewConfig didn't pick up the cli replacement for TLSSkipVerify")
	}

	cfg.usage(false)
	cfg.version(false)
}

func TestEcdh(t *testing.T) {
	pub, priv := GenerateECKeyPair()
	if len(pub) != keyLength {
		t.Fatalf("GenerateECKeyPair did not return the right length for the public key,\nactual: %d, expected: %d", len(pub), keyLength)
	}
	if len(priv) != keyLength {
		t.Fatalf("GenerateECKeyPair did not return the right length for the private key,\nactual: %d, expected: %d", len(priv), keyLength)
	}
	if testEq(pub, priv) {
		t.Fatalf("GenerateECKeyPair returned identical pub/priv keys this can't possibly happen:\npub: %v, priv: %v", pub, priv)
	}
	secret := GenerateSharedSecret(pub, priv)
	if len(secret) != keyLength {
		t.Fatalf("GenerateECKeyPair did not return the right length for the shared secret,\nactual: %d, expected: %d", len(secret), keyLength)
	}
	if testEq(secret, pub) || testEq(secret, priv) {
		t.Fatalf("GenerateECKeyPair returned identical secret and pub/priv keys this can't possibly happen:\npub: %v, priv: %v, secret: %v", pub, priv, secret)
	}
}

func TestNewMapping(t *testing.T) {
	privateIP := net.ParseIP("0.0.0.0")
	publicip := net.ParseIP("1.1.1.1")
	publicip6 := net.ParseIP("dead::beef")
	publicport := 80
	publicKey := make([]byte, 32)
	machineID := "123456"

	actual := NewMapping(machineID, privateIP, publicip, publicip6, publicport, publicKey)
	if !testEq(actual.IPv4, publicip) || !testEq(actual.IPv6, publicip6) || actual.Port != publicport || !testEq(actual.PrivateIP, privateIP) || !testEq(actual.PublicKey, publicKey) {
		t.Fatalf("NewMapping did not return the right value, got: %v", actual)
	}
}

func TestParseMapping(t *testing.T) {
	privateIP := net.ParseIP("0.0.0.0")
	publicip := net.ParseIP("1.1.1.1")
	publicip6 := net.ParseIP("dead::beef")
	publicport := 80
	publicKey := make([]byte, 32)
	machineID := "123456"

	expected := NewMapping(machineID, privateIP, publicip, publicip6, publicport, publicKey)
	actual, err := ParseMapping(expected.String(), make([]byte, 32))
	if err != nil {
		t.Fatalf("Error occured during test: %s", err)
	}
	if !testEq(actual.IPv4, expected.IPv4) || actual.Port != expected.Port || !testEq(actual.PrivateIP, expected.PrivateIP) || !testEq(actual.PublicKey, expected.PublicKey) {
		t.Fatalf("ParseMapping did not return the right value, got: %v, expected: %v", actual, expected)
	}
}

func TestParseNetworkConfig(t *testing.T) {
	actual, err := ParseNetworkConfig(DefaultNetworkConfig.Bytes())
	if err != nil {
		t.Fatal("ParseNetworkConfig returned an error:", err)
	}
	if actual.Network != DefaultNetworkConfig.Network || actual.LeaseTime != DefaultNetworkConfig.LeaseTime {
		t.Fatalf("ParseNetworkConfig returned the wrong value, got: %v, expected: %v", actual, DefaultNetworkConfig)
	}
}

func TestParseNetworkConfigOnlyNetwork(t *testing.T) {
	netCfg := &NetworkConfig{Network: "10.10.0.0/16"}
	actual, err := ParseNetworkConfig(netCfg.Bytes())
	if err != nil {
		t.Fatal("ParseNetworkConfig returned an error:", err)
	}
	if actual.Network != netCfg.Network || actual.LeaseTime != 48*time.Hour {
		t.Fatalf("ParseNetworkConfig returned the wrong value, got: %v, expected: %v", actual, netCfg)
	}
}

func TestParseNetworkConfigIncorrectFormat(t *testing.T) {
	netCfg := &NetworkConfig{Network: "10.10.0."}
	_, err := ParseNetworkConfig(netCfg.Bytes())
	if err == nil {
		t.Fatal("ParseNetworkConfig should have errored")
	}

	netCfg.Network = "10.10.0.0/16"
	netCfg.StaticRange = "10.10.0./23"

	_, err = ParseNetworkConfig(netCfg.Bytes())
	if err == nil {
		t.Fatal("ParseNetworkConfig should have errored")
	}

	netCfg.StaticRange = "10.20.0.0/23"
	_, err = ParseNetworkConfig(netCfg.Bytes())
	if err == nil {
		t.Fatal("ParseNetworkConfig should have errored")
	}
}

func TestNewTunPayload(t *testing.T) {
	payload := NewTunPayload(testPacket, 2)
	for i := 0; i < 4; i++ {
		if payload.IPAddress[i] != 1 {
			t.Fatal("NewTunPayload returned an incorrect IP address mapping.")
		}
	}

	for i := 0; i < 12; i++ {
		if payload.Nonce[i] != 2 {
			t.Fatal("NewTunPayload returned an incorrect Nonce mapping.")
		}
	}

	for i := 0; i < 2; i++ {
		if payload.Packet[i] != 3 {
			t.Fatal("NewTunPayload returned an incorrect Packet mapping.")
		}
	}
}

func TestNewSockPayload(t *testing.T) {
	payload := NewSockPayload(testPacket, 18)
	for i := 0; i < 4; i++ {
		if payload.IPAddress[i] != 1 {
			t.Fatal("NewTunPayload returned an incorrect IP address mapping.")
		}
	}

	for i := 0; i < 12; i++ {
		if payload.Nonce[i] != 2 {
			t.Fatal("NewTunPayload returned an incorrect Nonce mapping.")
		}
	}

	for i := 0; i < 2; i++ {
		if payload.Packet[i] != 3 {
			t.Fatal("NewTunPayload returned an incorrect Packet mapping.")
		}
	}
}

func TestNewStats(t *testing.T) {
	stats := NewStats(1)
	if stats.Packets != 0 {
		t.Fatalf("NewStats did not return the correct default for Packets, got: %d, expected: %d", stats.Packets, 0)
	}
	if stats.Bytes != 0 {
		t.Fatalf("NewStats did not return the correct default for Bytes, got: %d, expected: %d", stats.Bytes, 0)
	}
	if stats.Links == nil {
		t.Fatalf("NewStats did not return the correct default for Links, got: %v, expected: %v", stats.Links, make(map[string]*Stats))
	}
	str := stats.String()
	if str == "" {
		t.Fatalf("String didn't return the correct value.")
	}
}

func TestNewLogger(t *testing.T) {
	log := NewLogger()
	if log.Error == nil {
		t.Fatal("NewLogger returned a nil Error log.")
	}
	if log.Info == nil {
		t.Fatal("NewLogger returned a nil Error log.")
	}
}

func TestGenerateLocalMapping(t *testing.T) {
	cfg := &Config{
		PrivateIP:     net.ParseIP("10.10.0.1"),
		PublicIPv4:    net.ParseIP("192.167.0.1"),
		PublicIPv6:    net.ParseIP("fd00:dead:beef::2"),
		ListenPort:    1099,
		PublicKey:     make([]byte, 32),
		NetworkConfig: DefaultNetworkConfig,
		MachineID:     "123",
	}

	mappings := make(map[uint32]*Mapping)
	mapping, err := GenerateLocalMapping(cfg, mappings)
	if err != nil {
		t.Fatal(err)
	}

	if !testEq(mapping.PrivateIP.To4(), cfg.PrivateIP.To4()) {
		t.Fatal("GenerateLocalMapping created the wrong mapping.")
	}

	mappings[IPtoInt(cfg.PrivateIP)] = mapping

	_, err = GenerateLocalMapping(cfg, mappings)
	if err != nil {
		t.Fatal(err)
	}

	mapping.MachineID = "456"

	_, err = GenerateLocalMapping(cfg, mappings)
	if err == nil {
		t.Fatal("GenerateLocalMapping failed to properly handle an existing ip address")
	}

	cfg.PrivateIP = nil
	mapping.MachineID = "123"

	_, err = GenerateLocalMapping(cfg, mappings)
	if err != nil {
		t.Fatal(err)
	}

	cfg.PrivateIP = nil
	_, err = GenerateLocalMapping(cfg, make(map[uint32]*Mapping))
	if err != nil {
		t.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package common

import (
	"fmt"
	"github.com/mikeyhu/glipso/interfaces"
)

// Environment Provides a mechanism for creating and resolving variables
type Environment struct {
	variables map[string]interfaces.Type
	parent    *Environment
}

// ResolveRef will try to resolve a provided reference to a value in this or parent scope
func (env Environment) ResolveRef(ref interfaces.Type) (interfaces.Type, bool) {
	if result, ok := env.variables[ref.(REF).String()]; ok {
		return result, true
	}
	if env.parent != nil {
		return env.parent.ResolveRef(ref)
	}
	return nil, false
}

// CreateRef will create a variable in this scope
func (env Environment) CreateRef(name interfaces.Type, arg interfaces.Type) interfaces.Type {
	env.variables[name.(REF).String()] = arg
	return name
}

// NewChildScope creates new scope that inherits from this one
func (env Environment) NewChildScope() interfaces.Scope {
	return Environment{
		map[string]interfaces.Type{},
		&env,
	}
}

// DisplayEnvironment is used to display environment information for internal debugging
func (env Environment) DisplayEnvironment() {
	env.displayEnvironment(0)
}

func (env Environment) displayEnvironment(i int) {
	for k := range env.variables {
		fmt.Printf("Scope[%d] %v := %v\n", i, k, env.variables[k])
	}
	if env.parent != nil {
		env.parent.displayEnvironment(i + 1)
	}
}

// GlobalEnvironment acts as the global scope for variables
var GlobalEnvironment Environment

func init() {
	GlobalEnvironment = Environment{
		variables: map[string]interfaces.Type{},
	}
}
<commit_msg>Give each scope an unique identifier<commit_after>package common

import (
	"fmt"
	"github.com/mikeyhu/glipso/interfaces"
)

// Environment Provides a mechanism for creating and resolving variables
type Environment struct {
	id        int
	variables map[string]interfaces.Type
	parent    *Environment
}

// ResolveRef will try to resolve a provided reference to a value in this or parent scope
func (env Environment) ResolveRef(ref interfaces.Type) (interfaces.Type, bool) {
	if result, ok := env.variables[ref.(REF).String()]; ok {
		return result, true
	}
	if env.parent != nil {
		return env.parent.ResolveRef(ref)
	}
	return nil, false
}

// CreateRef will create a variable in this scope
func (env Environment) CreateRef(name interfaces.Type, arg interfaces.Type) interfaces.Type {
	env.variables[name.(REF).String()] = arg
	return name
}

// NewChildScope creates new scope that inherits from this one
func (env Environment) NewChildScope() interfaces.Scope {
	return Environment{
		NextScopeId(),
		map[string]interfaces.Type{},
		&env,
	}
}

// DisplayEnvironment is used to display environment information for internal debugging
func (env Environment) DisplayEnvironment() {
	env.displayEnvironment(0)
}

func (env Environment) displayEnvironment(i int) {
	for k := range env.variables {
		fmt.Printf("Scope[%d %d] %v := %v\n", env.id, i, k, env.variables[k])
	}
	if env.parent != nil {
		env.parent.displayEnvironment(i + 1)
	}
}

// GlobalEnvironment acts as the global scope for variables
var GlobalEnvironment Environment

func init() {
	GlobalEnvironment = Environment{
		id:        NextScopeId(),
		variables: map[string]interfaces.Type{},
	}
}

var scopeId = 0

func NextScopeId() int {
	scopeId = scopeId + 1
	return scopeId
}
<|endoftext|>


<commit_before>// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package adb

import (
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strconv"
	"sync"
	"time"

	"github.com/google/syzkaller/vm"
)

func init() {
	vm.Register("adb", ctor)
}

type instance struct {
	cfg     *vm.Config
	console string
	closed  chan bool
}

func ctor(cfg *vm.Config) (vm.Instance, error) {
	inst := &instance{
		cfg:    cfg,
		closed: make(chan bool),
	}
	closeInst := inst
	defer func() {
		if closeInst != nil {
			closeInst.Close()
		}
	}()
	if err := validateConfig(cfg); err != nil {
		return nil, err
	}
	if err := inst.findConsole(); err != nil {
		return nil, err
	}
	if err := inst.repair(); err != nil {
		return nil, err
	}
	// Remove temp files from previous runs.
	inst.adb("shell", "rm -Rf /data/syzkaller*")
	closeInst = nil
	return inst, nil
}

func validateConfig(cfg *vm.Config) error {
	if cfg.Bin == "" {
		cfg.Bin = "adb"
	}
	if !regexp.MustCompile("[0-9A-F]+").MatchString(cfg.Device) {
		return fmt.Errorf("invalid adb device id '%v'", cfg.Device)
	}
	return nil
}

var (
	consoleCacheMu sync.Mutex
	consoleCache   = make(map[string]string)
)

func (inst *instance) findConsole() error {
	// Case Closed Debugging using Suzy-Q:
	// https://chromium.googlesource.com/chromiumos/platform/ec/+/master/docs/case_closed_debugging.md
	consoleCacheMu.Lock()
	defer consoleCacheMu.Unlock()
	if inst.console = consoleCache[inst.cfg.Device]; inst.console != "" {
		return nil
	}
	out, err := exec.Command(inst.cfg.Bin, "devices", "-l").CombinedOutput()
	if err != nil {
		return fmt.Errorf("failed to execute 'adb devices -l': %v\n%v\n", err, string(out))
	}
	re := regexp.MustCompile(fmt.Sprintf("%v +device usb:([0-9]+)-([0-9]+)\\.([0-9]+) ", inst.cfg.Device))
	match := re.FindAllStringSubmatch(string(out), 1)
	if match == nil {
		return fmt.Errorf("can't find adb device '%v' in 'adb devices' output:\n%v\n", inst.cfg.Device, string(out))
	}
	bus, _ := strconv.ParseUint(match[0][1], 10, 64)
	port, _ := strconv.ParseUint(match[0][2], 10, 64)
	files, err := filepath.Glob(fmt.Sprintf("/sys/bus/usb/devices/%v-%v.2:1.1/ttyUSB*", bus, port))
	if err != nil || len(files) == 0 {
		return fmt.Errorf("can't find any ttyUDB devices for adb device '%v' on bus %v-%v", inst.cfg.Device, bus, port)
	}
	inst.console = "/dev/" + filepath.Base(files[0])
	consoleCache[inst.cfg.Device] = inst.console
	log.Printf("associating adb device %v with console %v", inst.cfg.Device, inst.console)
	return nil
}

func (inst *instance) Forward(port int) (string, error) {
	// If 35099 turns out to be busy, try to forward random ports several times.
	devicePort := 35099
	if err := inst.adb("reverse", fmt.Sprintf("tcp:%v", devicePort), fmt.Sprintf("tcp:%v", port)); err != nil {
		return "", err
	}
	return fmt.Sprintf("127.0.0.1:%v", devicePort), nil
}

func (inst *instance) adb(args ...string) error {
	if inst.cfg.Debug {
		log.Printf("executing adb %+v", args)
	}
	rpipe, wpipe, err := os.Pipe()
	if err != nil {
		return fmt.Errorf("failed to create pipe: %v", err)
	}
	defer wpipe.Close()
	defer rpipe.Close()
	cmd := exec.Command(inst.cfg.Bin, append([]string{"-s", inst.cfg.Device}, args...)...)
	cmd.Stdout = wpipe
	cmd.Stderr = wpipe
	if err := cmd.Start(); err != nil {
		return err
	}
	wpipe.Close()
	done := make(chan bool)
	go func() {
		select {
		case <-time.After(time.Minute):
			if inst.cfg.Debug {
				log.Printf("adb hanged")
			}
			cmd.Process.Kill()
		case <-done:
		}
	}()
	if err := cmd.Wait(); err != nil {
		close(done)
		out, _ := ioutil.ReadAll(rpipe)
		if inst.cfg.Debug {
			log.Printf("adb failed: %v\n%s", err, out)
		}
		return fmt.Errorf("adb %+v failed: %v\n%s", args, err, out)
	}
	close(done)
	if inst.cfg.Debug {
		log.Printf("adb returned")
	}
	return nil
}

func (inst *instance) repair() error {
	// Give the device up to 5 minutes to come up (it can be rebooting after a previous crash).
	time.Sleep(3 * time.Second)
	for i := 0; i < 300; i++ {
		time.Sleep(time.Second)
		if inst.adb("shell", "pwd") == nil {
			return nil
		}
	}
	// If it does not help, reboot.
	// adb reboot episodically hangs, so we use a more reliable way.
	// Ignore errors because all other adb commands hang as well
	// and the binary can already be on the device.
	inst.adb("push", inst.cfg.Executor, "/data/syz-executor")
	if err := inst.adb("shell", "/data/syz-executor", "reboot"); err != nil {
		return err
	}
	// Now give it another 5 minutes.
	time.Sleep(10 * time.Second)
	var err error
	for i := 0; i < 300; i++ {
		time.Sleep(time.Second)
		if err = inst.adb("shell", "pwd"); err == nil {
			return nil
		}
	}
	return fmt.Errorf("instance is dead and unrepairable: %v", err)
}

func (inst *instance) Close() {
	close(inst.closed)
	os.RemoveAll(inst.cfg.Workdir)
}

func (inst *instance) Copy(hostSrc string) (string, error) {
	vmDst := filepath.Join("/data", filepath.Base(hostSrc))
	if err := inst.adb("push", hostSrc, vmDst); err != nil {
		return "", err
	}
	return vmDst, nil
}

func (inst *instance) Run(timeout time.Duration, command string) (<-chan []byte, <-chan error, error) {
	catRpipe, catWpipe, err := vm.LongPipe()
	if err != nil {
		return nil, nil, err
	}

	cat := exec.Command("cat", inst.console)
	cat.Stdout = catWpipe
	cat.Stderr = catWpipe
	if err := cat.Start(); err != nil {
		catRpipe.Close()
		catWpipe.Close()
		return nil, nil, fmt.Errorf("failed to start cat %v: %v", inst.console, err)

	}
	catWpipe.Close()
	catDone := make(chan error, 1)
	go func() {
		err := cat.Wait()
		if inst.cfg.Debug {
			log.Printf("cat exited: %v", err)
		}
		catDone <- fmt.Errorf("cat exited: %v", err)
	}()

	adbRpipe, adbWpipe, err := vm.LongPipe()
	if err != nil {
		cat.Process.Kill()
		catRpipe.Close()
		return nil, nil, err
	}
	if inst.cfg.Debug {
		log.Printf("starting: adb shell %v", command)
	}
	adb := exec.Command(inst.cfg.Bin, "-s", inst.cfg.Device, "shell", "cd /data; "+command)
	adb.Stdout = adbWpipe
	adb.Stderr = adbWpipe
	if err := adb.Start(); err != nil {
		cat.Process.Kill()
		catRpipe.Close()
		adbRpipe.Close()
		adbWpipe.Close()
		return nil, nil, fmt.Errorf("failed to start adb: %v", err)
	}
	adbWpipe.Close()
	adbDone := make(chan error, 1)
	go func() {
		err := adb.Wait()
		if inst.cfg.Debug {
			log.Printf("adb exited: %v", err)
		}
		adbDone <- fmt.Errorf("adb exited: %v", err)
	}()

	var tee io.Writer
	if inst.cfg.Debug {
		tee = os.Stdout
	}
	merger := vm.NewOutputMerger(tee)
	merger.Add(catRpipe)
	merger.Add(adbRpipe)

	errc := make(chan error, 1)
	signal := func(err error) {
		select {
		case errc <- err:
		default:
		}
	}

	go func() {
		select {
		case <-time.After(timeout):
			signal(vm.TimeoutErr)
			cat.Process.Kill()
			adb.Process.Kill()
		case <-inst.closed:
			if inst.cfg.Debug {
				log.Printf("instance closed")
			}
			signal(fmt.Errorf("instance closed"))
			cat.Process.Kill()
			adb.Process.Kill()
		case err := <-catDone:
			signal(err)
			adb.Process.Kill()
		case err := <-adbDone:
			signal(err)
			cat.Process.Kill()
		}
		merger.Wait()
	}()
	return merger.Output, errc, nil
}
<commit_msg>Improve Case Closed Debugging Port Detection.<commit_after>// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package adb

import (
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"sync"
	"time"

	"github.com/google/syzkaller/vm"
)

func init() {
	vm.Register("adb", ctor)
}

type instance struct {
	cfg     *vm.Config
	console string
	closed  chan bool
}

func ctor(cfg *vm.Config) (vm.Instance, error) {
	inst := &instance{
		cfg:    cfg,
		closed: make(chan bool),
	}
	closeInst := inst
	defer func() {
		if closeInst != nil {
			closeInst.Close()
		}
	}()
	if err := validateConfig(cfg); err != nil {
		return nil, err
	}
	if err := inst.findConsole(); err != nil {
		return nil, err
	}
	if err := inst.repair(); err != nil {
		return nil, err
	}
	// Remove temp files from previous runs.
	inst.adb("shell", "rm -Rf /data/syzkaller*")
	closeInst = nil
	return inst, nil
}

func validateConfig(cfg *vm.Config) error {
	if cfg.Bin == "" {
		cfg.Bin = "adb"
	}
	if !regexp.MustCompile("[0-9A-F]+").MatchString(cfg.Device) {
		return fmt.Errorf("invalid adb device id '%v'", cfg.Device)
	}
	return nil
}

var (
	consoleCacheMu sync.Mutex
	consoleCache   = make(map[string]string)
)

func (inst *instance) findConsole() error {
	// Case Closed Debugging using Suzy-Q:
	// https://chromium.googlesource.com/chromiumos/platform/ec/+/master/docs/case_closed_debugging.md
	consoleCacheMu.Lock()
	defer consoleCacheMu.Unlock()
	if inst.console = consoleCache[inst.cfg.Device]; inst.console != "" {
		return nil
	}
	out, err := exec.Command(inst.cfg.Bin, "devices", "-l").CombinedOutput()
	if err != nil {
		return fmt.Errorf("failed to execute 'adb devices -l': %v\n%v\n", err, string(out))
	}
	// The regexp matches devices strings of the form usb:a-b.c.d....x, and
	// then treats everything but the final .x as the bus/port combo to look
	// for the ttyUSB number
	re := regexp.MustCompile(fmt.Sprintf("%v +device usb:([0-9]+-[0-9]+.*)(\\.[0-9]+) product.*\n", inst.cfg.Device))
	match := re.FindAllStringSubmatch(string(out), 1)
	if match == nil {
		return fmt.Errorf("can't find adb device '%v' in 'adb devices' output:\n%v\n", inst.cfg.Device, string(out))
	}
	busAndPort := match[0][1]
	files, err := filepath.Glob(fmt.Sprintf("/sys/bus/usb/devices/%v.2:1.1/ttyUSB*", busAndPort))
	if err != nil || len(files) == 0 {
		return fmt.Errorf("can't find any ttyUSB devices for adb device '%v' on bus/port %v", inst.cfg.Device, busAndPort)
	}
	inst.console = "/dev/" + filepath.Base(files[0])
	consoleCache[inst.cfg.Device] = inst.console
	log.Printf("associating adb device %v with console %v", inst.cfg.Device, inst.console)
	return nil
}

func (inst *instance) Forward(port int) (string, error) {
	// If 35099 turns out to be busy, try to forward random ports several times.
	devicePort := 35099
	if err := inst.adb("reverse", fmt.Sprintf("tcp:%v", devicePort), fmt.Sprintf("tcp:%v", port)); err != nil {
		return "", err
	}
	return fmt.Sprintf("127.0.0.1:%v", devicePort), nil
}

func (inst *instance) adb(args ...string) error {
	if inst.cfg.Debug {
		log.Printf("executing adb %+v", args)
	}
	rpipe, wpipe, err := os.Pipe()
	if err != nil {
		return fmt.Errorf("failed to create pipe: %v", err)
	}
	defer wpipe.Close()
	defer rpipe.Close()
	cmd := exec.Command(inst.cfg.Bin, append([]string{"-s", inst.cfg.Device}, args...)...)
	cmd.Stdout = wpipe
	cmd.Stderr = wpipe
	if err := cmd.Start(); err != nil {
		return err
	}
	wpipe.Close()
	done := make(chan bool)
	go func() {
		select {
		case <-time.After(time.Minute):
			if inst.cfg.Debug {
				log.Printf("adb hanged")
			}
			cmd.Process.Kill()
		case <-done:
		}
	}()
	if err := cmd.Wait(); err != nil {
		close(done)
		out, _ := ioutil.ReadAll(rpipe)
		if inst.cfg.Debug {
			log.Printf("adb failed: %v\n%s", err, out)
		}
		return fmt.Errorf("adb %+v failed: %v\n%s", args, err, out)
	}
	close(done)
	if inst.cfg.Debug {
		log.Printf("adb returned")
	}
	return nil
}

func (inst *instance) repair() error {
	// Give the device up to 5 minutes to come up (it can be rebooting after a previous crash).
	time.Sleep(3 * time.Second)
	for i := 0; i < 300; i++ {
		time.Sleep(time.Second)
		if inst.adb("shell", "pwd") == nil {
			return nil
		}
	}
	// If it does not help, reboot.
	// adb reboot episodically hangs, so we use a more reliable way.
	// Ignore errors because all other adb commands hang as well
	// and the binary can already be on the device.
	inst.adb("push", inst.cfg.Executor, "/data/syz-executor")
	if err := inst.adb("shell", "/data/syz-executor", "reboot"); err != nil {
		return err
	}
	// Now give it another 5 minutes.
	time.Sleep(10 * time.Second)
	var err error
	for i := 0; i < 300; i++ {
		time.Sleep(time.Second)
		if err = inst.adb("shell", "pwd"); err == nil {
			return nil
		}
	}
	return fmt.Errorf("instance is dead and unrepairable: %v", err)
}

func (inst *instance) Close() {
	close(inst.closed)
	os.RemoveAll(inst.cfg.Workdir)
}

func (inst *instance) Copy(hostSrc string) (string, error) {
	vmDst := filepath.Join("/data", filepath.Base(hostSrc))
	if err := inst.adb("push", hostSrc, vmDst); err != nil {
		return "", err
	}
	return vmDst, nil
}

func (inst *instance) Run(timeout time.Duration, command string) (<-chan []byte, <-chan error, error) {
	catRpipe, catWpipe, err := vm.LongPipe()
	if err != nil {
		return nil, nil, err
	}

	cat := exec.Command("cat", inst.console)
	cat.Stdout = catWpipe
	cat.Stderr = catWpipe
	if err := cat.Start(); err != nil {
		catRpipe.Close()
		catWpipe.Close()
		return nil, nil, fmt.Errorf("failed to start cat %v: %v", inst.console, err)

	}
	catWpipe.Close()
	catDone := make(chan error, 1)
	go func() {
		err := cat.Wait()
		if inst.cfg.Debug {
			log.Printf("cat exited: %v", err)
		}
		catDone <- fmt.Errorf("cat exited: %v", err)
	}()

	adbRpipe, adbWpipe, err := vm.LongPipe()
	if err != nil {
		cat.Process.Kill()
		catRpipe.Close()
		return nil, nil, err
	}
	if inst.cfg.Debug {
		log.Printf("starting: adb shell %v", command)
	}
	adb := exec.Command(inst.cfg.Bin, "-s", inst.cfg.Device, "shell", "cd /data; "+command)
	adb.Stdout = adbWpipe
	adb.Stderr = adbWpipe
	if err := adb.Start(); err != nil {
		cat.Process.Kill()
		catRpipe.Close()
		adbRpipe.Close()
		adbWpipe.Close()
		return nil, nil, fmt.Errorf("failed to start adb: %v", err)
	}
	adbWpipe.Close()
	adbDone := make(chan error, 1)
	go func() {
		err := adb.Wait()
		if inst.cfg.Debug {
			log.Printf("adb exited: %v", err)
		}
		adbDone <- fmt.Errorf("adb exited: %v", err)
	}()

	var tee io.Writer
	if inst.cfg.Debug {
		tee = os.Stdout
	}
	merger := vm.NewOutputMerger(tee)
	merger.Add(catRpipe)
	merger.Add(adbRpipe)

	errc := make(chan error, 1)
	signal := func(err error) {
		select {
		case errc <- err:
		default:
		}
	}

	go func() {
		select {
		case <-time.After(timeout):
			signal(vm.TimeoutErr)
			cat.Process.Kill()
			adb.Process.Kill()
		case <-inst.closed:
			if inst.cfg.Debug {
				log.Printf("instance closed")
			}
			signal(fmt.Errorf("instance closed"))
			cat.Process.Kill()
			adb.Process.Kill()
		case err := <-catDone:
			signal(err)
			adb.Process.Kill()
		case err := <-adbDone:
			signal(err)
			cat.Process.Kill()
		}
		merger.Wait()
	}()
	return merger.Output, errc, nil
}
<|endoftext|>


<commit_before>package cas

import (
	"os"
	"path"
	"github.com/s3git/s3git-go/internal/config"
)

// Upon writing, make sure the size of the repository does not exceed the max local size,
// prune stale chunks otherwise
func checkRepoSize() {
	// TODO: Implement
}

// Get the filepath for a given hash
func getBlobPath(hash string) string {

	// Check if in stage directory
	nameInStage := getBlobPathWithinArea(hash, stageDir)
	if _, err := os.Stat(nameInStage); err == nil {
		return nameInStage
	}

	// Check if in cache directory
	nameInCache := getBlobPathWithinArea(hash, cacheDir)
	if _, err := os.Stat(nameInCache); err == nil {
		return nameInCache
	}

	// Check size of repo, prune stale chunks if necessary
	checkRepoSize()

	// TODO: Chunk is not in cache, download from upstream

	return nameInCache
}

// Get the filepath for a given hash in either the .stage or .cache area
func getBlobPathWithinArea(hash, area string) string {
	return path.Join(config.Config.S3gitCasPath, area, hash[0:2], hash[2:4], hash[4:])
}

// Move underlying chunks for a hash from .stage area to .cache area
func moveBlobToCache(hash string) error {

	leaves, err := openRoot(hash)
	if err != nil {
		return err
	}

	for _, l := range leaves {
		leaveHash := l.String()

		oldPath := getBlobPathWithinArea(leaveHash, stageDir)
		if _, err := os.Stat(oldPath); os.IsNotExist(err) {
			return err
		}

		hashDir := path.Join(config.Config.S3gitCasPath, cacheDir, leaveHash[0:2], leaveHash[2:4]) + "/"
		err := os.MkdirAll(hashDir, os.ModePerm)
		if err != nil {
			return err
		}
		newPath := hashDir + leaveHash[4:]

		err = os.Rename(oldPath, newPath)
		if err != nil {
			return err
		}
	}

	// TODO: Consider removing directories that are left empty in the .stage area
	//   However be aware of files moving in at potentially the same time (in a seperate process)
	//   Maybe do in separate maintenance step???
	return nil
}
<commit_msg>Make function publicly accessible<commit_after>package cas

import (
	"os"
	"path"
	"github.com/s3git/s3git-go/internal/config"
)

// Upon writing, make sure the size of the repository does not exceed the max local size,
// prune stale chunks otherwise
func checkRepoSize() {
	// TODO: Implement
}

// Get the filepath for a given hash
func getBlobPath(hash string) string {

	// Check if in stage directory
	nameInStage := getBlobPathWithinArea(hash, stageDir)
	if _, err := os.Stat(nameInStage); err == nil {
		return nameInStage
	}

	// Check if in cache directory
	nameInCache := getBlobPathWithinArea(hash, cacheDir)
	if _, err := os.Stat(nameInCache); err == nil {
		return nameInCache
	}

	// Check size of repo, prune stale chunks if necessary
	checkRepoSize()

	// TODO: Chunk is not in cache, download from upstream

	return nameInCache
}

// Get the filepath for a given hash in either the .stage or .cache area
func getBlobPathWithinArea(hash, area string) string {
	return path.Join(config.Config.S3gitCasPath, area, hash[0:2], hash[2:4], hash[4:])
}

// Move underlying chunks for a hash from .stage area to .cache area
func MoveBlobToCache(hash string) error {

	leaves, err := openRoot(hash)
	if err != nil {
		return err
	}

	for _, l := range leaves {
		leaveHash := l.String()

		oldPath := getBlobPathWithinArea(leaveHash, stageDir)
		if _, err := os.Stat(oldPath); os.IsNotExist(err) {
			return err
		}

		hashDir := path.Join(config.Config.S3gitCasPath, cacheDir, leaveHash[0:2], leaveHash[2:4]) + "/"
		err := os.MkdirAll(hashDir, os.ModePerm)
		if err != nil {
			return err
		}
		newPath := hashDir + leaveHash[4:]

		err = os.Rename(oldPath, newPath)
		if err != nil {
			return err
		}
	}

	// TODO: Consider removing directories that are left empty in the .stage area
	//   However be aware of files moving in at potentially the same time (in a seperate process)
	//   Maybe do in separate maintenance step???
	return nil
}
<|endoftext|>