<commit_before>// Package ware is a powerful package for easily create middleware layer in Golang.
//
// For a full guide visit https://github.com/futurespaceio/ware
//
// package main
//
// import (
//   "log"
//   "github.com/futurespaceio/ware"
// )
//
// func main() {
//   w := ware.New()
//
//   w.Use(func(c ware.Context, log *log.Logger) {
//     log.Println("before")
//     c.Next()
//     log.Println("after")
//   })
//
//   w.Run()
// }
package ware

import (
  "log"
  "os"
  "reflect"

  "github.com/codegangsta/inject"
)

// Middleware inject.Injector methods can be invoked to map services on a global level.
type Ware struct {
  inject.Injector
  handlers []Handler
  action   Handler
  logger   *log.Logger
}

// New creates a base bones Ware instance. Use this method if you want to have full control over the middleware that is used.
func New() *Ware {
  w := &Ware{Injector: inject.New(), action: func() {}, logger: log.New(os.Stdout, "[ware] ", 0)}
  w.Map(w.logger)
  w.Map(defaultReturnHandler())
  return w
}

// Handlers sets the entire middleware stack with the given Handlers. This will clear any current middleware handlers.
// Will panic if any of the handlers is not a callable function
func (w *Ware) Handlers(handlers ...Handler) {
  w.handlers = make([]Handler, 0)
  for _, handler := range handlers {
    w.Use(handler)
  }
}

// Action sets the handler that will be called after all the middleware has been invoked. This is set to other Ware in a Ware.
func (w *Ware) Action(handler Handler) {
  validateHandler(handler)
  w.action = handler
}

// Use adds a middleware Handler to the stack. Will panic if the handler is not a callable func. Middleware Handlers are invoked in the order that they are added
func (w *Ware) Use(handler Handler) {
  validateHandler(handler)

  w.handlers = append(w.handlers, handler)
}

// Run the ware.
func (w *Ware) Run() {
  w.createContext().run()
}

// Creates a context.
func (w *Ware) createContext() *context {
  c := &context{inject.New(), w.handlers, w.action, nil, 0}
  c.SetParent(w)
  c.MapTo(c, (*Context)(nil))
  return c
}

// Handler can be any callable function. Martini attempts to inject services into the handler's argument list.
// Martini will panic if an argument could not be fullfilled via dependency injection.
type Handler interface{}

func validateHandler(handler Handler) {
  if reflect.TypeOf(handler).Kind() != reflect.Func {
    panic("ware handler must be a callable func")
  }
}

// Context represents a request context. Services can be mapped on the request level from this interface.
type Context interface {
  inject.Injector
  // Next is an optional function that Middleware Handlers can call to yield the until after
  // the other Handlers have been executed. This works really well for any operations that must
  // happen after a request
  Next()
  // Written returns whether or not the response for this context has been written.
  Written() bool
  // The response instance.
  Out(interface{})
}

type context struct {
  inject.Injector
  handlers []Handler
  action   Handler
  out      interface{}
  index    int
}

// Changes the response instance.
func (c *context) Out(o interface{}) {
  c.out = o
}

func (c *context) handler() Handler {
  if c.index < len(c.handlers) {
    return c.handlers[c.index]
  }
  if c.index == len(c.handlers) {
    return c.action
  }
  panic("invalid index for context handler")
}

func (c *context) Next() {
  c.index += 1
  c.run()
}

func (c *context) Written() bool {
  out := reflect.ValueOf(c.out)
  if out.IsValid() {
    // Currently, defaults only mapping Written method.
    f := out.MethodByName("Written")
    if f.IsValid() && f.Kind() == reflect.Func {
      res := f.Call(nil)
      return res[0].Interface().(bool)
    }
  }
  return false
}

func (c *context) run() {
  for c.index <= len(c.handlers) {
    _, err := c.Invoke(c.handler())
    if err != nil {
      panic(err)
    }
    c.index += 1

    // if the handler returned something, write it to the http response
    // TODO
    // if len(vals) > 0 {
    //   ev := c.Get(reflect.TypeOf(ReturnHandler(nil)))
    //   handleReturn := ev.Interface().(ReturnHandler)
    //   handleReturn(c, vals)
    // }

    if c.Written() {
      return
    }
  }
}

<commit_msg>public api<commit_after>// Package ware is a powerful package for easily create middleware layer in Golang.
//
// For a full guide visit https://github.com/futurespaceio/ware
//
// package main
//
// import (
//   "log"
//   "github.com/futurespaceio/ware"
// )
//
// func main() {
//   w := ware.New()
//
//   w.Use(func(c ware.Context, log *log.Logger) {
//     log.Println("before")
//     c.Next()
//     log.Println("after")
//   })
//
//   w.Run()
// }
package ware

import (
  "log"
  "os"
  "reflect"

  "github.com/codegangsta/inject"
)

// Middleware inject.Injector methods can be invoked to map services on a global level.
type Ware struct {
  inject.Injector
  handlers []Handler
  action   Handler
  logger   *log.Logger
}

// New creates a base bones Ware instance. Use this method if you want to have full control over the middleware that is used.
func New() *Ware {
  w := &Ware{Injector: inject.New(), action: func() {}, logger: log.New(os.Stdout, "[ware] ", 0)}
  w.Map(w.logger)
  w.Map(defaultReturnHandler())
  return w
}

// Handlers sets the entire middleware stack with the given Handlers. This will clear any current middleware handlers.
// Will panic if any of the handlers is not a callable function
func (w *Ware) Handlers(handlers ...Handler) {
  w.handlers = make([]Handler, 0)
  for _, handler := range handlers {
    w.Use(handler)
  }
}

// Action sets the handler that will be called after all the middleware has been invoked. This is set to other Ware in a Ware.
func (w *Ware) Action(handler Handler) {
  validateHandler(handler)
  w.action = handler
}

// Use adds a middleware Handler to the stack. Will panic if the handler is not a callable func. Middleware Handlers are invoked in the order that they are added
func (w *Ware) Use(handler Handler) {
  validateHandler(handler)

  w.handlers = append(w.handlers, handler)
}

// Run the ware.
func (w *Ware) Run() {
  w.CreateContext().Run()
}

// Creates a context.
func (w *Ware) CreateContext() *context {
  c := &context{inject.New(), w.handlers, w.action, nil, 0}
  c.SetParent(w)
  c.MapTo(c, (*Context)(nil))
  return c
}

// Handler can be any callable function. Martini attempts to inject services into the handler's argument list.
// Martini will panic if an argument could not be fullfilled via dependency injection.
type Handler interface{}

func validateHandler(handler Handler) {
  if reflect.TypeOf(handler).Kind() != reflect.Func {
    panic("ware handler must be a callable func")
  }
}

// Context represents a request context. Services can be mapped on the request level from this interface.
type Context interface {
  inject.Injector
  // Next is an optional function that Middleware Handlers can call to yield the until after
  // the other Handlers have been executed. This works really well for any operations that must
  // happen after a request
  Next()
  // Written returns whether or not the response for this context has been written.
  Written() bool
  // The response instance.
  Out(interface{})
}

type context struct {
  inject.Injector
  handlers []Handler
  action   Handler
  out      interface{}
  index    int
}

// Changes the response instance.
func (c *context) Out(o interface{}) {
  c.out = o
}

func (c *context) handler() Handler {
  if c.index < len(c.handlers) {
    return c.handlers[c.index]
  }
  if c.index == len(c.handlers) {
    return c.action
  }
  panic("invalid index for context handler")
}

func (c *context) Next() {
  c.index += 1
  c.Run()
}

func (c *context) Written() bool {
  out := reflect.ValueOf(c.out)
  if out.IsValid() {
    // Currently, defaults only mapping Written method.
    f := out.MethodByName("Written")
    if f.IsValid() && f.Kind() == reflect.Func {
      res := f.Call(nil)
      return res[0].Interface().(bool)
    }
  }
  return false
}

func (c *context) Run() {
  for c.index <= len(c.handlers) {
    _, err := c.Invoke(c.handler())
    if err != nil {
      panic(err)
    }
    c.index += 1

    // if the handler returned something, write it to the http response
    // TODO
    // if len(vals) > 0 {
    //   ev := c.Get(reflect.TypeOf(ReturnHandler(nil)))
    //   handleReturn := ev.Interface().(ReturnHandler)
    //   handleReturn(c, vals)
    // }

    if c.Written() {
      return
    }
  }
}

<|endoftext|>


<commit_before>// Copyright 2017-2018 Authors of Cilium
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package k8sTest

import (
	"fmt"

	. "github.com/cilium/cilium/test/ginkgo-ext"
	"github.com/cilium/cilium/test/helpers"

	. "github.com/onsi/gomega"
)

var _ = Describe("K8sChaosTest", func() {

	var (
		kubectl       *helpers.Kubectl
		demoDSPath    = helpers.ManifestGet("demo_ds.yaml")
		testDSService = "testds-service"
	)

	BeforeAll(func() {
		kubectl = helpers.CreateKubectl(helpers.K8s1VMName(), logger)

		err := kubectl.CiliumInstall(helpers.CiliumDSPath)
		Expect(err).To(BeNil(), "Cilium cannot be installed")

		ExpectCiliumReady(kubectl)
		ExpectKubeDNSReady(kubectl)
	})

	BeforeEach(func() {
		kubectl.Apply(demoDSPath).ExpectSuccess("DS deployment cannot be applied")

		err := kubectl.WaitforPods(
			helpers.DefaultNamespace, fmt.Sprintf("-l zgroup=testDS"), 300)
		Expect(err).Should(BeNil(), "Pods are not ready after timeout")
	})

	AfterFailed(func() {
		kubectl.CiliumReport(helpers.KubeSystemNamespace,
			"cilium service list",
			"cilium endpoint list")
	})

	JustAfterEach(func() {
		kubectl.ValidateNoErrorsOnLogs(CurrentGinkgoTestDescription().Duration)
	})

	AfterEach(func() {
		kubectl.Delete(demoDSPath).ExpectSuccess(
			"%s deployment cannot be deleted", demoDSPath)
		ExpectAllPodsTerminated(kubectl)

	})

	PingService := func() {
		pods, err := kubectl.GetPodNames(helpers.DefaultNamespace, "zgroup=testDSClient")
		Expect(err).To(BeNil(), "Cannot get pods names")
		Expect(len(pods)).To(BeNumerically(">", 0), "No pods available to test connectivity")

		dsPods, err := kubectl.GetPodsIPs(helpers.DefaultNamespace, "zgroup=testDS")
		Expect(err).To(BeNil(), "Cannot get daemonset pods IPS")
		Expect(len(pods)).To(BeNumerically(">", 0), "No pods available to test connectivity")

		for _, pod := range pods {
			for _, ip := range dsPods {
				By("Pinging test-ds service pod with IP %q from client pod %q", ip, pod)
				res := kubectl.ExecPodCmd(
					helpers.DefaultNamespace, pod, helpers.Ping(ip))
				log.Debugf("Pod %s ping %v", pod, ip)
				ExpectWithOffset(1, res).To(helpers.CMDSuccess(),
					"Cannot ping from %q to %q", pod, ip)

				By("Waiting for kube-dns entry for service testds-service")
				err = kubectl.WaitForKubeDNSEntry(testDSService, helpers.DefaultNamespace)
				ExpectWithOffset(1, err).To(BeNil(), "DNS entry is not ready after timeout")

				By("Getting ClusterIP For testds-service")
				host, _, err := kubectl.GetServiceHostPort(helpers.DefaultNamespace, "testds-service")
				ExpectWithOffset(1, err).To(BeNil(), "unable to get ClusterIP and port for service testds-service")

				By("Curling testds-service via ClusterIP %q", host)
				res = kubectl.ExecPodCmd(
					helpers.DefaultNamespace, pod, helpers.CurlFail("http://%s:80/", host))
				ExpectWithOffset(1, res).To(helpers.CMDSuccess(),
					"Cannot curl from %q to testds-service via ClusterIP", pod)

				By("Curling testds-service via DNS hostname")
				res = kubectl.ExecPodCmd(
					helpers.DefaultNamespace, pod, helpers.CurlFail("http://%s:80/", testDSService))
				ExpectWithOffset(1, res).To(helpers.CMDSuccess(),
					"Cannot curl from %q to testds-service via DNS hostname", pod)
			}
		}
	}

	It("Endpoint can still connect while Cilium is not running", func() {
		By("Waiting for deployed pods to be ready")
		err := kubectl.WaitforPods(
			helpers.DefaultNamespace,
			fmt.Sprintf("-l zgroup=testDSClient"), 300)
		Expect(err).Should(BeNil(), "Pods are not ready after timeout")

		err = kubectl.CiliumEndpointWaitReady()
		Expect(err).To(BeNil(), "Endpoints are not ready after timeout")

		By("Checking connectivity before restarting Cilium")
		PingService()

		By("Deleting cilium pods")
		res := kubectl.Exec(fmt.Sprintf("%s -n %s delete pods -l k8s-app=cilium",
			helpers.KubectlCmd, helpers.KubeSystemNamespace))
		res.ExpectSuccess()

		ExpectAllPodsTerminated(kubectl)

		ExpectCiliumReady(kubectl)
		err = kubectl.CiliumEndpointWaitReady()
		Expect(err).To(BeNil(), "Endpoints are not ready after Cilium restarts")

		By("Checking connectivity after restarting Cilium")
		PingService()

		By("Uninstall cilium pods")

		res = kubectl.DeleteResource(
			"ds", fmt.Sprintf("-n %s cilium", helpers.KubeSystemNamespace))
		res.ExpectSuccess("Cilium DS cannot be deleted")

		ExpectAllPodsTerminated(kubectl)

		By("Checking connectivity after uninstalling Cilium")
		PingService()

		By("Install cilium pods")

		err = kubectl.CiliumInstall(helpers.CiliumDSPath)
		Expect(err).To(BeNil(), "Cilium cannot be installed")

		ExpectCiliumReady(kubectl)

		err = kubectl.CiliumEndpointWaitReady()
		Expect(err).To(BeNil(), "Endpoints are not ready after timeout")

		By("Checking connectivity after reinstalling Cilium")
		PingService()
	})
})
<commit_msg>test/k8sT: move DNS checks outside of loop<commit_after>// Copyright 2017-2018 Authors of Cilium
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package k8sTest

import (
	"fmt"

	. "github.com/cilium/cilium/test/ginkgo-ext"
	"github.com/cilium/cilium/test/helpers"

	. "github.com/onsi/gomega"
)

var _ = Describe("K8sChaosTest", func() {

	var (
		kubectl       *helpers.Kubectl
		demoDSPath    = helpers.ManifestGet("demo_ds.yaml")
		testDSService = "testds-service"
	)

	BeforeAll(func() {
		kubectl = helpers.CreateKubectl(helpers.K8s1VMName(), logger)

		err := kubectl.CiliumInstall(helpers.CiliumDSPath)
		Expect(err).To(BeNil(), "Cilium cannot be installed")

		ExpectCiliumReady(kubectl)
		ExpectKubeDNSReady(kubectl)
	})

	BeforeEach(func() {
		kubectl.Apply(demoDSPath).ExpectSuccess("DS deployment cannot be applied")

		err := kubectl.WaitforPods(
			helpers.DefaultNamespace, fmt.Sprintf("-l zgroup=testDS"), 300)
		Expect(err).Should(BeNil(), "Pods are not ready after timeout")
	})

	AfterFailed(func() {
		kubectl.CiliumReport(helpers.KubeSystemNamespace,
			"cilium service list",
			"cilium endpoint list")
	})

	JustAfterEach(func() {
		kubectl.ValidateNoErrorsOnLogs(CurrentGinkgoTestDescription().Duration)
	})

	AfterEach(func() {
		kubectl.Delete(demoDSPath).ExpectSuccess(
			"%s deployment cannot be deleted", demoDSPath)
		ExpectAllPodsTerminated(kubectl)

	})

	PingService := func() {
		pods, err := kubectl.GetPodNames(helpers.DefaultNamespace, "zgroup=testDSClient")
		Expect(err).To(BeNil(), "Cannot get pods names")
		Expect(len(pods)).To(BeNumerically(">", 0), "No pods available to test connectivity")

		dsPods, err := kubectl.GetPodsIPs(helpers.DefaultNamespace, "zgroup=testDS")
		Expect(err).To(BeNil(), "Cannot get daemonset pods IPS")
		Expect(len(pods)).To(BeNumerically(">", 0), "No pods available to test connectivity")

		By("Waiting for kube-dns entry for service testds-service")
		err = kubectl.WaitForKubeDNSEntry(testDSService, helpers.DefaultNamespace)
		ExpectWithOffset(1, err).To(BeNil(), "DNS entry is not ready after timeout")

		By("Getting ClusterIP For testds-service")
		host, _, err := kubectl.GetServiceHostPort(helpers.DefaultNamespace, "testds-service")
		ExpectWithOffset(1, err).To(BeNil(), "unable to get ClusterIP and port for service testds-service")

		for _, pod := range pods {
			for _, ip := range dsPods {
				By("Pinging test-ds service pod with IP %q from client pod %q", ip, pod)
				res := kubectl.ExecPodCmd(
					helpers.DefaultNamespace, pod, helpers.Ping(ip))
				log.Debugf("Pod %s ping %v", pod, ip)
				ExpectWithOffset(1, res).To(helpers.CMDSuccess(),
					"Cannot ping from %q to %q", pod, ip)

				By("Curling testds-service via ClusterIP %q", host)
				res = kubectl.ExecPodCmd(
					helpers.DefaultNamespace, pod, helpers.CurlFail("http://%s:80/", host))
				ExpectWithOffset(1, res).To(helpers.CMDSuccess(),
					"Cannot curl from %q to testds-service via ClusterIP", pod)

				By("Curling testds-service via DNS hostname")
				res = kubectl.ExecPodCmd(
					helpers.DefaultNamespace, pod, helpers.CurlFail("http://%s:80/", testDSService))
				ExpectWithOffset(1, res).To(helpers.CMDSuccess(),
					"Cannot curl from %q to testds-service via DNS hostname", pod)
			}
		}
	}

	It("Endpoint can still connect while Cilium is not running", func() {
		By("Waiting for deployed pods to be ready")
		err := kubectl.WaitforPods(
			helpers.DefaultNamespace,
			fmt.Sprintf("-l zgroup=testDSClient"), 300)
		Expect(err).Should(BeNil(), "Pods are not ready after timeout")

		err = kubectl.CiliumEndpointWaitReady()
		Expect(err).To(BeNil(), "Endpoints are not ready after timeout")

		By("Checking connectivity before restarting Cilium")
		PingService()

		By("Deleting cilium pods")
		res := kubectl.Exec(fmt.Sprintf("%s -n %s delete pods -l k8s-app=cilium",
			helpers.KubectlCmd, helpers.KubeSystemNamespace))
		res.ExpectSuccess()

		ExpectAllPodsTerminated(kubectl)

		ExpectCiliumReady(kubectl)
		err = kubectl.CiliumEndpointWaitReady()
		Expect(err).To(BeNil(), "Endpoints are not ready after Cilium restarts")

		By("Checking connectivity after restarting Cilium")
		PingService()

		By("Uninstall cilium pods")

		res = kubectl.DeleteResource(
			"ds", fmt.Sprintf("-n %s cilium", helpers.KubeSystemNamespace))
		res.ExpectSuccess("Cilium DS cannot be deleted")

		ExpectAllPodsTerminated(kubectl)

		By("Checking connectivity after uninstalling Cilium")
		PingService()

		By("Install cilium pods")

		err = kubectl.CiliumInstall(helpers.CiliumDSPath)
		Expect(err).To(BeNil(), "Cilium cannot be installed")

		ExpectCiliumReady(kubectl)

		err = kubectl.CiliumEndpointWaitReady()
		Expect(err).To(BeNil(), "Endpoints are not ready after timeout")

		By("Checking connectivity after reinstalling Cilium")
		PingService()
	})
})
<|endoftext|>


<commit_before>package mdb

import (
	"io"
)

type Machine struct {
	Hostname       string
	RequiredImage  string `json:",omitempty"`
	PlannedImage   string `json:",omitempty"`
	DisableUpdates bool   `json:",omitempty"`
	OwnerGroup     string `json:",omitempty"`
}

func (dest *Machine) UpdateFrom(source Machine) {
	dest.updateFrom(source)
}

type Mdb struct {
	Machines []Machine
}

func (mdb *Mdb) DebugWrite(w io.Writer) error {
	return mdb.debugWrite(w)
}

func (mdb *Mdb) Len() int {
	return len(mdb.Machines)
}

func (mdb *Mdb) Less(left, right int) bool {
	if mdb.Machines[left].Hostname < mdb.Machines[right].Hostname {
		return true
	}
	return false
}

func (mdb *Mdb) Swap(left, right int) {
	tmp := mdb.Machines[left]
	mdb.Machines[left] = mdb.Machines[right]
	mdb.Machines[right] = tmp
}
<commit_msg>Add documentation for lib/mdb package.<commit_after>/*
	Package mdb implements a simple in-memory Machine DataBase.
*/
package mdb

import (
	"io"
)

// Machine describes a single machine with a unique Hostname and optional
// metadata about the machine.
type Machine struct {
	Hostname       string
	RequiredImage  string `json:",omitempty"`
	PlannedImage   string `json:",omitempty"`
	DisableUpdates bool   `json:",omitempty"`
	OwnerGroup     string `json:",omitempty"`
}

// UpdateFrom updates dest with data from source.
func (dest *Machine) UpdateFrom(source Machine) {
	dest.updateFrom(source)
}

// Mdb describes a list of Machines. It implements sort.Interface.
type Mdb struct {
	Machines []Machine
}

// DebugWrite writes the JSON representation to w.
func (mdb *Mdb) DebugWrite(w io.Writer) error {
	return mdb.debugWrite(w)
}

// Len returns the number of machines.
func (mdb *Mdb) Len() int {
	return len(mdb.Machines)
}

// Less compares the hostnames of left and right.
func (mdb *Mdb) Less(left, right int) bool {
	if mdb.Machines[left].Hostname < mdb.Machines[right].Hostname {
		return true
	}
	return false
}

// Swap swaps two entries in mdb.
func (mdb *Mdb) Swap(left, right int) {
	tmp := mdb.Machines[left]
	mdb.Machines[left] = mdb.Machines[right]
	mdb.Machines[right] = tmp
}
<|endoftext|>


<commit_before>package common

import (
	"fmt"
	"io"
	"strconv"
)

type Serializer interface {
	SerializePoint(w io.Writer, p *Point) error
	SerializeSize(w io.Writer, points int64, values int64) error
}

func serializeSizeInText(w io.Writer, points int64, values int64) error {
	buf := scratchBufPool.Get().([]byte)
	buf = append(buf, fmt.Sprintf("%d,%d\n", points, values)...)
	_, err := w.Write(buf)
	if err != nil {
		return err
	}
	return nil
}

func fastFormatAppend(v interface{}, buf []byte, singleQuotesForString bool) []byte {
	var quotationChar = "\""
	if singleQuotesForString {
		quotationChar = "'"
	}
	switch v.(type) {
	case int:
		return strconv.AppendInt(buf, int64(v.(int)), 10)
	case int64:
		return strconv.AppendInt(buf, v.(int64), 10)
	case float64:
		return strconv.AppendFloat(buf, v.(float64), 'f', 16, 64)
	case float32:
		return strconv.AppendFloat(buf, float64(v.(float32)), 'f', 16, 32)
	case bool:
		return strconv.AppendBool(buf, v.(bool))
	case []byte:
		buf = append(buf, quotationChar...)
		buf = append(buf, v.([]byte)...)
		buf = append(buf, quotationChar...)
		return buf
	case string:
		buf = append(buf, quotationChar...)
		buf = append(buf, v.(string)...)
		buf = append(buf, quotationChar...)
		return buf
	default:
		panic(fmt.Sprintf("unknown field type for %#v", v))
	}
}
<commit_msg>Support for reading total points and values<commit_after>package common

import (
	"fmt"
	"io"
	"regexp"
	"strconv"
)

type Serializer interface {
	SerializePoint(w io.Writer, p *Point) error
	SerializeSize(w io.Writer, points int64, values int64) error
}

const DatasetSizeMarker = "dataset-size:"

var DatasetSizeMarkerRE = regexp.MustCompile(DatasetSizeMarker + `(\d+),(\d+)`)

func serializeSizeInText(w io.Writer, points int64, values int64) error {
	buf := scratchBufPool.Get().([]byte)
	buf = append(buf, fmt.Sprintf("%s%d,%d\n", DatasetSizeMarker, points, values)...)
	_, err := w.Write(buf)
	if err != nil {
		return err
	}
	return nil
}

func fastFormatAppend(v interface{}, buf []byte, singleQuotesForString bool) []byte {
	var quotationChar = "\""
	if singleQuotesForString {
		quotationChar = "'"
	}
	switch v.(type) {
	case int:
		return strconv.AppendInt(buf, int64(v.(int)), 10)
	case int64:
		return strconv.AppendInt(buf, v.(int64), 10)
	case float64:
		return strconv.AppendFloat(buf, v.(float64), 'f', 16, 64)
	case float32:
		return strconv.AppendFloat(buf, float64(v.(float32)), 'f', 16, 32)
	case bool:
		return strconv.AppendBool(buf, v.(bool))
	case []byte:
		buf = append(buf, quotationChar...)
		buf = append(buf, v.([]byte)...)
		buf = append(buf, quotationChar...)
		return buf
	case string:
		buf = append(buf, quotationChar...)
		buf = append(buf, v.(string)...)
		buf = append(buf, quotationChar...)
		return buf
	default:
		panic(fmt.Sprintf("unknown field type for %#v", v))
	}
}
<|endoftext|>


<commit_before>package libfss

import (
	"crypto/aes"
	"crypto/rand"
	"encoding/binary"
	"fmt"
	"time"
)

type CWLt struct {
	cs [2][]byte
	ct [2]uint8
	cv [2]uint
}

type ServerKeyLt struct {
	s  [2][]byte
	t  [2]uint8
	v  [2]uint
	cw [2][]CWLt // Should be length n
}

func (f Fss) generateTreeLt(a, b uint) []ServerKeyLt {
	k := make([]ServerKeyLt, 2)

	k[0].cw[0] = make([]CWLt, f.NumBits)
	k[0].cw[1] = make([]CWLt, f.NumBits)
	k[1].cw[0] = make([]CWLt, f.NumBits)
	k[1].cw[1] = make([]CWLt, f.NumBits)

	k[0].s[0] = make([]byte, aes.BlockSize)
	k[0].s[1] = make([]byte, aes.BlockSize)
	k[1].s[0] = make([]byte, aes.BlockSize)
	k[1].s[1] = make([]byte, aes.BlockSize)

	// Figure out first bit
	aBit := getBit(a, (f.N - f.NumBits + 1), f.N)
	naBit := aBit ^ 1

	// Initialize seeds (store as an array for each server)
	// The first AES_SIZE bits are for the 0 bit
	// The second AES_SIZE bits are for the 1 bit
	s0 := make([]byte, aes.BlockSize*2)
	s1 := make([]byte, aes.BlockSize*2)
	aStart := int(aes.BlockSize * aBit)
	naStart := int(aes.BlockSize * naBit)

	rand.Read(s0[aStart : aStart+aes.BlockSize])
	rand.Read(s1[aStart : aStart+aes.BlockSize])
	rand.Read(s0[naStart : naStart+aes.BlockSize])
	// Ensure the "not a" bits are the same
	copy(s1[naStart:naStart+aes.BlockSize], s0[naStart:naStart+aes.BlockSize])

	// Set initial "t" bits
	t0 := make([]uint8, 2)
	t1 := make([]uint8, 2)
	temp := make([]byte, 2)
	_, err = rand.Read(temp)
	if err != nil {
		panic(err)
	}
	// Make sure t0a and t1a are different
	t0[aBit] = uint8(temp[0]) % 2
	t1[aBit] = (t0[aBit] + 1) % 2

	// Make sure t0na = t1na
	t0[naBit] = uint8(temp[1]) % 2
	t1[naBit] = t0[naBit]

	// Generate random Vs
	v0 := make([]uint, 2)
	v1 := make([]uint, 2)

	// make sure v0a + -v1a = 0
	v0[aBit], err = uint(rand.Int())
	if err != nil {
		panic(err)
	}
	v1[aBit] = -v0[aBit]

	// make sure v0na + -v1na = a1 * b
	v0[naBit], err = uint(rand.Int())
	if err != nil {
		panic(err)
	}
	v1[naBit] = v0[naBit] - b*uint(aBit)

	// Store generated values into the key
	copy(k[0].s[0], s0[0:aes.BlockSize])
	copy(k[0].s[1], s0[aes.BlockSize:aes.BlockSize*2])
	copy(k[1].s[0], s1[0:aes.BlockSize])
	copy(k[1].s[1], s1[aes.BlockSize:aes.BlockSize*2])
	k[0].t[0] = t0[0]
	k[0].t[1] = t0[1]
	k[1].t[0] = t1[0]
	k[1].t[1] = t1[1]
	k[0].v[0] = v0[0]
	k[0].v[1] = v0[1]
	k[1].v[0] = v1[0]
	k[1].v[1] = v1[1]

	// Assign keys and start cipher
	key0, key1 := s0[aStart:aStart+aes.BlockSize], s1[aStart:aStart+aes.BlockSize]
	tbit0, tbit1 := t0[aBit], t1[aBit]

	cs0 := make([]byte, aes.BlockSize*2)
	cs1 := make([]byte, aes.BlockSize*2)
	ct0 := make([]uint8, 2)
	ct1 := make([]uint8, 2)

	var cv [][]uint
	cv = make([][]uint, 2)
	cv[0] = make([]uint, 2)
	cv[1] = make([]uint, 2)

	for i := 0; i < f.N-1; i++ {
		// Figure out next bit
		aBit = getBit(a, (f.N - f.NumBits + i + 2), f.N)
		naBit = aBit ^ 1

		prf(key0, f.FixedBlocks, 4, f.Temp, f.Out)
		copy(s0, f.Out[:aes.BlockSize*2])
		t0[0] = f.Out[aes.BlockSize*2] % 2
		t0[1] = f.Out[aes.BlockSize*2+1] % 2
		v0[0], _ = uint(binary.Uvarint(f.Out[aes.BlockSize*2+8 : aes.BlockSize*2+16]))
		v0[1], _ = uint(binary.Uvarint(f.Out[aes.BlockSize*2+16 : aes.BlockSize*2+24]))

		prf(key1, f.FixedBlocks, 4, f.Temp, f.Out)
		copy(s1, f.Out[:aes.BlockSize*2])
		t1[0] = f.Out[aes.BlockSize*2] % 2
		t1[1] = f.Out[aes.BlockSize*2+1] % 2
		v1[0], _ = uint(binary.Uvarint(f.Out[aes.BlockSize*2+8 : aes.BlockSize*2+16]))
		v1[1], _ = uint(binary.Uvarint(f.Out[aes.BlockSize*2+16 : aes.BlockSize*2+24]))

		// Redefine aStart and naStart based on new a's
		aStart = int(aes.BlockSize * aBit)
		naStart = int(aes.BlockSize * naBit)

		// Create cs and ct for next bit
		rand.Read(cs0[aStart : aStart+aes.BlockSize])
		rand.Read(cs1[aStart : aStart+aes.BlockSize])

		// Pick random cs0na and pick cs1na s.t.
		// cs0na xor cs1na xor s0na xor s1na = 0
		rand.Read(cs0[naStart : naStart+aes.BlockSize])

		for j := 0; j < aes.BlockSize; j++ {
			cs1[naStart+j] = s0[naStart+j] ^ s1[naStart+j] ^ cs0[naStart+j]
		}

		rand.Read(temp)
		// Set ct0a and ct1a s.t.
		// ct0a xor ct1a xor t0a xor t1a = 1
		ct0[aBit] = uint8(temp[0]) % 2
		ct1[aBit] = ct0[aBit] ^ t0[aBit] ^ t1[aBit] ^ 1

		// Set ct0na and ct1na s.t.
		// ct0na xor ct1na xor t0na xor t1na = 0
		ct0[naBit] = uint8(temp[1]) % 2
		ct1[naBit] = ct0[naBit] ^ t0[naBit] ^ t1[naBit]

		cv[tbit0][a], err = uint(rand.Int())
		if err != nil {
			panic(err)
		}

		cv[tbit1][a] = new(big.Int)
		cv[tbit1][a].Add(cv[tbit0][a], v0[a])
		cv[tbit1][a].Sub(cv[tbit1][a], v1[a])
		cv[tbit1][a].Mod(cv[tbit1][a], prime)

		cv[tbit0][na], err = rand.Int(rand.Reader, prime)
		if err != nil {
			panic(err)
		}

		cv[tbit1][na] = new(big.Int)
		cv[tbit1][na].Add(cv[tbit0][na], v0[na])
		cv[tbit1][na].Sub(cv[tbit1][na], v1[na])
		cv[tbit1][na].Sub(cv[tbit1][na], new(big.Int).SetUint64(b_input*uint64(a)))
		cv[tbit1][na].Mod(cv[tbit1][na], prime)

		k0.cw[0][i].cs[0] = make([]byte, AES_SIZE)
		k0.cw[0][i].cs[1] = make([]byte, AES_SIZE)
		k0.cw[1][i].cs[0] = make([]byte, AES_SIZE)
		k0.cw[1][i].cs[1] = make([]byte, AES_SIZE)

		copy(k0.cw[0][i].cs[0], cs0[0:AES_SIZE])
		copy(k0.cw[0][i].cs[1], cs0[AES_SIZE:AES_SIZE*2])
		k0.cw[0][i].ct[0] = ct0[0]
		k0.cw[0][i].ct[1] = ct0[1]
		copy(k0.cw[1][i].cs[0], cs1[0:AES_SIZE])
		copy(k0.cw[1][i].cs[1], cs1[AES_SIZE:AES_SIZE*2])
		k0.cw[1][i].ct[0] = ct1[0]
		k0.cw[1][i].ct[1] = ct1[1]

		k0.cw[0][i].cv[0] = cv[0][0]
		k0.cw[0][i].cv[1] = cv[0][1]
		k0.cw[1][i].cv[0] = cv[1][0]
		k0.cw[1][i].cv[1] = cv[1][1]

		k1.cw[0][i].cs[0] = make([]byte, AES_SIZE)
		k1.cw[0][i].cs[1] = make([]byte, AES_SIZE)
		k1.cw[1][i].cs[0] = make([]byte, AES_SIZE)
		k1.cw[1][i].cs[1] = make([]byte, AES_SIZE)

		copy(k1.cw[0][i].cs[0], cs0[0:AES_SIZE])
		copy(k1.cw[0][i].cs[1], cs0[AES_SIZE:AES_SIZE*2])
		k1.cw[0][i].ct[0] = ct0[0]
		k1.cw[0][i].ct[1] = ct0[1]
		copy(k1.cw[1][i].cs[0], cs1[0:AES_SIZE])
		copy(k1.cw[1][i].cs[1], cs1[AES_SIZE:AES_SIZE*2])
		k1.cw[1][i].ct[0] = ct1[0]
		k1.cw[1][i].ct[1] = ct1[1]

		k1.cw[0][i].cv[0] = cv[0][0]
		k1.cw[0][i].cv[1] = cv[0][1]
		k1.cw[1][i].cv[0] = cv[1][0]
		k1.cw[1][i].cv[1] = cv[1][1]

		// Find correct cs and ct
		var cs, ct []byte

		// Set next seeds and ts
		if tbit0 == 1 {
			cs = cs1
			ct = ct1
		} else {
			cs = cs0
			ct = ct0
		}
		for j := 0; j < len(key0); j++ {
			key0[j] = s0[aStart+j] ^ cs[aStart+j]
		}
		tbit0 = t0[a] ^ ct[a]
		if tbit1 == 1 {
			cs = cs1
			ct = ct1
		} else {
			cs = cs0
			ct = ct0
		}

		for j := 0; j < len(key1); j++ {
			key1[j] = s1[aStart+j] ^ cs[aStart+j]
		}

		tbit1 = t1[a] ^ ct[a]
	}

	return k0, k1
}

func evaluateLt(k *ServerKeyLt, x uint64) uint {
	xi := getBit(x, 1)
	s := k.s[xi]
	t := k.t[xi]
	v := new(big.Int).Set(k.v[xi])

	// Use these plaintexts to get values from PRF
	sArray := make([]byte, AES_SIZE*2)
	temp := make([]uint8, AES_SIZE)

	vByte := make([]byte, AES_SIZE)
	for i := 1; i < N; i++ {
		// Get current bit
		xi = getBit(x, uint(i+1))

		block, err := aes.NewCipher(s)
		if err != nil {
			panic(err)
		}

		block.Encrypt(sArray[0:AES_SIZE], pt0)
		block.Encrypt(sArray[AES_SIZE:AES_SIZE*2], pt1)
		block.Encrypt(temp, pt2)
		block.Encrypt(vByte, pt3)

		for j := 0; j < AES_SIZE; j++ {
			sArray[j] = sArray[j] ^ pt0[j]
			sArray[AES_SIZE+j] = sArray[AES_SIZE+j] ^ pt1[j]
			temp[j] = temp[j] ^ pt2[j]
			vByte[j] = vByte[j] ^ pt3[j]
		}
		// Pick the right values to use based on bit of x
		xStart := int(AES_SIZE * xi)
		s = sArray[xStart : xStart+AES_SIZE]
		for j := 0; j < AES_SIZE; j++ {
			s[j] = s[j] ^ k.cw[t][i-1].cs[xi][j]
		}
		vStart := int(N / 8 * xi)
		v.Add(v, new(big.Int).SetBytes(vByte[vStart:vStart+N/8]))
		v.Add(v, k.cw[t][i-1].cv[xi])
		v.Mod(v, prime)
		t = (uint8(temp[xi]) % 2) ^ k.cw[t][i-1].ct[xi]

	}

	return v
}
<commit_msg>finished cleaning up generateTree for interval functions. Cleaning up evaluate function for interval functions.<commit_after>package libfss

import (
	"crypto/aes"
	"crypto/rand"
	"encoding/binary"
	"fmt"
	"time"
)

type CWLt struct {
	cs [2][]byte
	ct [2]uint8
	cv [2]uint
}

type ServerKeyLt struct {
	s  [2][]byte
	t  [2]uint8
	v  [2]uint
	cw [2][]CWLt // Should be length n
}

func (f Fss) generateTreeLt(a, b uint) []ServerKeyLt {
	k := make([]ServerKeyLt, 2)

	k[0].cw[0] = make([]CWLt, f.NumBits)
	k[0].cw[1] = make([]CWLt, f.NumBits)
	k[1].cw[0] = make([]CWLt, f.NumBits)
	k[1].cw[1] = make([]CWLt, f.NumBits)

	k[0].s[0] = make([]byte, aes.BlockSize)
	k[0].s[1] = make([]byte, aes.BlockSize)
	k[1].s[0] = make([]byte, aes.BlockSize)
	k[1].s[1] = make([]byte, aes.BlockSize)

	// Figure out first bit
	aBit := getBit(a, (f.N - f.NumBits + 1), f.N)
	naBit := aBit ^ 1

	// Initialize seeds (store as an array for each server)
	// The first AES_SIZE bits are for the 0 bit
	// The second AES_SIZE bits are for the 1 bit
	s0 := make([]byte, aes.BlockSize*2)
	s1 := make([]byte, aes.BlockSize*2)
	aStart := int(aes.BlockSize * aBit)
	naStart := int(aes.BlockSize * naBit)

	rand.Read(s0[aStart : aStart+aes.BlockSize])
	rand.Read(s1[aStart : aStart+aes.BlockSize])
	rand.Read(s0[naStart : naStart+aes.BlockSize])
	// Ensure the "not a" bits are the same
	copy(s1[naStart:naStart+aes.BlockSize], s0[naStart:naStart+aes.BlockSize])

	// Set initial "t" bits
	t0 := make([]uint8, 2)
	t1 := make([]uint8, 2)
	temp := make([]byte, 2)
	_, err = rand.Read(temp)
	if err != nil {
		panic(err)
	}
	// Make sure t0a and t1a are different
	t0[aBit] = uint8(temp[0]) % 2
	t1[aBit] = (t0[aBit] + 1) % 2

	// Make sure t0na = t1na
	t0[naBit] = uint8(temp[1]) % 2
	t1[naBit] = t0[naBit]

	// Generate random Vs
	v0 := make([]uint, 2)
	v1 := make([]uint, 2)

	// make sure v0a + -v1a = 0
	v0[aBit], err = uint(rand.Int())
	if err != nil {
		panic(err)
	}
	v1[aBit] = -v0[aBit]

	// make sure v0na + -v1na = a1 * b
	v0[naBit], err = uint(rand.Int())
	if err != nil {
		panic(err)
	}
	v1[naBit] = v0[naBit] - b*uint(aBit)

	// Store generated values into the key
	copy(k[0].s[0], s0[0:aes.BlockSize])
	copy(k[0].s[1], s0[aes.BlockSize:aes.BlockSize*2])
	copy(k[1].s[0], s1[0:aes.BlockSize])
	copy(k[1].s[1], s1[aes.BlockSize:aes.BlockSize*2])
	k[0].t[0] = t0[0]
	k[0].t[1] = t0[1]
	k[1].t[0] = t1[0]
	k[1].t[1] = t1[1]
	k[0].v[0] = v0[0]
	k[0].v[1] = v0[1]
	k[1].v[0] = v1[0]
	k[1].v[1] = v1[1]

	// Assign keys and start cipher
	key0, key1 := s0[aStart:aStart+aes.BlockSize], s1[aStart:aStart+aes.BlockSize]
	tbit0, tbit1 := t0[aBit], t1[aBit]

	cs0 := make([]byte, aes.BlockSize*2)
	cs1 := make([]byte, aes.BlockSize*2)
	ct0 := make([]uint8, 2)
	ct1 := make([]uint8, 2)

	var cv [][]uint
	cv = make([][]uint, 2)
	cv[0] = make([]uint, 2)
	cv[1] = make([]uint, 2)

	for i := 0; i < f.N-1; i++ {
		// Figure out next bit
		aBit = getBit(a, (f.N - f.NumBits + i + 2), f.N)
		naBit = aBit ^ 1

		prf(key0, f.FixedBlocks, 4, f.Temp, f.Out)
		copy(s0, f.Out[:aes.BlockSize*2])
		t0[0] = f.Out[aes.BlockSize*2] % 2
		t0[1] = f.Out[aes.BlockSize*2+1] % 2
		v0[0], _ = uint(binary.Uvarint(f.Out[aes.BlockSize*2+8 : aes.BlockSize*2+16]))
		v0[1], _ = uint(binary.Uvarint(f.Out[aes.BlockSize*2+16 : aes.BlockSize*2+24]))

		prf(key1, f.FixedBlocks, 4, f.Temp, f.Out)
		copy(s1, f.Out[:aes.BlockSize*2])
		t1[0] = f.Out[aes.BlockSize*2] % 2
		t1[1] = f.Out[aes.BlockSize*2+1] % 2
		v1[0], _ = uint(binary.Uvarint(f.Out[aes.BlockSize*2+8 : aes.BlockSize*2+16]))
		v1[1], _ = uint(binary.Uvarint(f.Out[aes.BlockSize*2+16 : aes.BlockSize*2+24]))

		// Redefine aStart and naStart based on new a's
		aStart = int(aes.BlockSize * aBit)
		naStart = int(aes.BlockSize * naBit)

		// Create cs and ct for next bit
		rand.Read(cs0[aStart : aStart+aes.BlockSize])
		rand.Read(cs1[aStart : aStart+aes.BlockSize])

		// Pick random cs0na and pick cs1na s.t.
		// cs0na xor cs1na xor s0na xor s1na = 0
		rand.Read(cs0[naStart : naStart+aes.BlockSize])

		for j := 0; j < aes.BlockSize; j++ {
			cs1[naStart+j] = s0[naStart+j] ^ s1[naStart+j] ^ cs0[naStart+j]
		}

		rand.Read(temp)
		// Set ct0a and ct1a s.t.
		// ct0a xor ct1a xor t0a xor t1a = 1
		ct0[aBit] = uint8(temp[0]) % 2
		ct1[aBit] = ct0[aBit] ^ t0[aBit] ^ t1[aBit] ^ 1

		// Set ct0na and ct1na s.t.
		// ct0na xor ct1na xor t0na xor t1na = 0
		ct0[naBit] = uint8(temp[1]) % 2
		ct1[naBit] = ct0[naBit] ^ t0[naBit] ^ t1[naBit]

		cv[tbit0][aBit], err = uint(rand.Int())
		if err != nil {
			panic(err)
		}
		cv[tbit1][aBit] = v0[a] + cv[tbit0][aBit] - v1[aBit]

		cv[tbit0][naBit], err = uint(rand.Int())
		if err != nil {
			panic(err)
		}

		cv[tbit1][naBit] = cv[tbit0][naBit] + v0[naBit] - v1[naBit] - b*aBit

		k[0].cw[0][i].cs[0] = make([]byte, aes.BlockSize)
		k[0].cw[0][i].cs[1] = make([]byte, aes.BlockSize)
		k[0].cw[1][i].cs[0] = make([]byte, aes.BlockSize)
		k[0].cw[1][i].cs[1] = make([]byte, aes.BlockSize)

		copy(k[0].cw[0][i].cs[0], cs0[0:aes.BlockSize])
		copy(k[0].cw[0][i].cs[1], cs0[aes.BlockSize:aes.BlockSize*2])
		k[0].cw[0][i].ct[0] = ct0[0]
		k[0].cw[0][i].ct[1] = ct0[1]
		copy(k[0].cw[1][i].cs[0], cs1[0:aes.BlockSize])
		copy(k[0].cw[1][i].cs[1], cs1[aes.BlockSize:aes.BlockSize*2])
		k[0].cw[1][i].ct[0] = ct1[0]
		k[0].cw[1][i].ct[1] = ct1[1]

		k[0].cw[0][i].cv[0] = cv[0][0]
		k[0].cw[0][i].cv[1] = cv[0][1]
		k[0].cw[1][i].cv[0] = cv[1][0]
		k[0].cw[1][i].cv[1] = cv[1][1]

		k[1].cw[0][i].cs[0] = make([]byte, aes.BlockSize)
		k[1].cw[0][i].cs[1] = make([]byte, aes.BlockSize)
		k[1].cw[1][i].cs[0] = make([]byte, aes.BlockSize)
		k[1].cw[1][i].cs[1] = make([]byte, aes.BlockSize)

		copy(k[1].cw[0][i].cs[0], cs0[0:aes.BlockSize])
		copy(k[1].cw[0][i].cs[1], cs0[aes.BlockSize:aes.BlockSize*2])
		k[1].cw[0][i].ct[0] = ct0[0]
		k[1].cw[0][i].ct[1] = ct0[1]
		copy(k[1].cw[1][i].cs[0], cs1[0:aes.BlockSize])
		copy(k[1].cw[1][i].cs[1], cs1[aes.BlockSize:aes.BlockSize*2])
		k[1].cw[1][i].ct[0] = ct1[0]
		k[1].cw[1][i].ct[1] = ct1[1]

		k[1].cw[0][i].cv[0] = cv[0][0]
		k[1].cw[0][i].cv[1] = cv[0][1]
		k[1].cw[1][i].cv[0] = cv[1][0]
		k[1].cw[1][i].cv[1] = cv[1][1]

		// Find correct cs and ct
		var cs, ct []byte

		// Set next seeds and ts
		if tbit0 == 1 {
			cs = cs1
			ct = ct1
		} else {
			cs = cs0
			ct = ct0
		}
		for j := 0; j < len(key0); j++ {
			key0[j] = s0[aStart+j] ^ cs[aStart+j]
		}
		tbit0 = t0[aBit] ^ ct[aBit]
		if tbit1 == 1 {
			cs = cs1
			ct = ct1
		} else {
			cs = cs0
			ct = ct0
		}

		for j := 0; j < len(key1); j++ {
			key1[j] = s1[aStart+j] ^ cs[aStart+j]
		}

		tbit1 = t1[aBit] ^ ct[aBit]
	}

	return k
}

func (Fss f) evaluateLt(k ServerKeyLt, x uint) uint {
	xi := getBit(x, (f.N - f.numBits + 1))
	s := k.s[xi]
	t := k.t[xi]
	v := k.v[xi]

	// Use these plaintexts to get values from PRF
	sArray := make([]byte, AES_SIZE*2)
	temp := make([]uint8, AES_SIZE)

	vByte := make([]byte, AES_SIZE)
	for i := 1; i < N; i++ {
		// Get current bit
		xi = getBit(x, uint(i+1))

		block, err := aes.NewCipher(s)
		if err != nil {
			panic(err)
		}

		block.Encrypt(sArray[0:AES_SIZE], pt0)
		block.Encrypt(sArray[AES_SIZE:AES_SIZE*2], pt1)
		block.Encrypt(temp, pt2)
		block.Encrypt(vByte, pt3)

		for j := 0; j < AES_SIZE; j++ {
			sArray[j] = sArray[j] ^ pt0[j]
			sArray[AES_SIZE+j] = sArray[AES_SIZE+j] ^ pt1[j]
			temp[j] = temp[j] ^ pt2[j]
			vByte[j] = vByte[j] ^ pt3[j]
		}
		// Pick the right values to use based on bit of x
		xStart := int(AES_SIZE * xi)
		s = sArray[xStart : xStart+AES_SIZE]
		for j := 0; j < AES_SIZE; j++ {
			s[j] = s[j] ^ k.cw[t][i-1].cs[xi][j]
		}
		vStart := int(N / 8 * xi)
		v.Add(v, new(big.Int).SetBytes(vByte[vStart:vStart+N/8]))
		v.Add(v, k.cw[t][i-1].cv[xi])
		v.Mod(v, prime)
		t = (uint8(temp[xi]) % 2) ^ k.cw[t][i-1].ct[xi]

	}

	return v
}
<|endoftext|>


<commit_before>// Package lib is exposing parsers and output generation
package lib

import (
	"fmt"
	"io"
	"regexp"
	"strings"
)

var (
	matchDatarace = regexp.MustCompile("^WARNING: DATA RACE$").MatchString
)

// hasDatarace checks if there's a data race warning in the line
func hasDatarace(lines []string) bool {
	for _, line := range lines {
		if matchDatarace(line) {
			return true
		}
	}
	return false
}

// Token2Status return matching status for token
func Token2Status(token string) Status {
	switch token {
	case "FAIL", "PANIC":
		return Failed
	case "PASS":
		return Passed
	case "SKIP", "MISS":
		return Skipped
	}
	return UnknownStatus
}

// ParseGocheck parses output of "go test -gocheck.vv", returns a list of tests
// See data/gocheck.out for an example
// TODO: Refactor to shorter ones
func ParseGocheck(rd io.Reader, suitePrefix string) (Suites, error) {
	findStart := gcStartRE.FindStringSubmatch
	findEnd := gcEndRE.FindStringSubmatch
	findSuite := gcSuiteRE.FindStringSubmatch

	scanner := NewLineScanner(rd)
	var suites = make([]*Suite, 0)
	var suiteName string
	var suite *Suite

	var testName string
	var out []string

	for scanner.Scan() {
		line := scanner.Text()

		tokens := findStart(line)
		if len(tokens) > 0 {
			if tokens[2] == "SetUpTest" || tokens[2] == "TearDownTest" {
				continue
			}
			if testName != "" {
				return nil, fmt.Errorf("%d: start in middle of test", scanner.Line())
			}
			suiteName = tokens[1]
			testName = tokens[2]
			out = []string{}
			continue
		}

		tokens = findEnd(line)
		if len(tokens) > 0 {
			if tokens[3] == "SetUpTest" || tokens[3] == "TearDownTest" {
				continue
			}
			if testName == "" {
				return nil, fmt.Errorf("%d: orphan end", scanner.Line())
			}
			if (tokens[2] != suiteName) || (tokens[3] != testName) {
				return nil, fmt.Errorf("%d: suite/name mismatch", scanner.Line())
			}
			test := &Test{Name: testName}
			test.Message = strings.Join(out, "\n")
			test.Time = tokens[4]
			test.Status = Token2Status(tokens[1])
			if test.Status == UnknownStatus {
				return nil, fmt.Errorf("%d: unknown status %s", scanner.Line(), tokens[1])
			}

			if suite == nil || suite.Name != suiteName {
				suite = &Suite{Name: suitePrefix + suiteName}
				suites = append(suites, suite)
			}
			suite.Tests = append(suite.Tests, test)

			testName = ""
			suiteName = ""
			out = []string{}

			continue
		}

		// last "suite" is test summary
		tokens = findSuite(line)
		if tokens != nil {
			if suite == nil {
				suite = &Suite{Name: tokens[2], Status: tokens[1], Time: tokens[3]}
				suites = append(suites, suite)
			} else {
				suite.Status = tokens[1]
				suite.Time = tokens[3]
			}

			testName = ""
			suiteName = ""
			out = []string{}

			continue
		}

		if testName != "" {
			out = append(out, line)
		}
	}

	if err := scanner.Err(); err != nil {
		return nil, err
	}

	return Suites(suites), nil
}

// ParseGotest parser output of gotest
// TODO: Make it shorter
func ParseGotest(rd io.Reader, suitePrefix string) (Suites, error) {
	findStart := gtStartRE.FindStringSubmatch
	findEnd := gtEndRE.FindStringSubmatch
	findSuite := gtSuiteRE.FindStringSubmatch
	isNoFiles := gtNoFilesRE.MatchString
	isBuildFailed := gtBuildFailedRE.MatchString
	isExit := gtExitRE.MatchString

	suites := []*Suite{}
	subTests := map[string]*Test{}
	var parentTest *Test
	var curTest *Test
	var curSuite *Suite
	var out []string
	suiteStack := SuiteStack{}
	// Handles a test that ended with a panic.
	handlePanic := func() {
		curTest.Status = Failed
		curTest.Time = "0"
		curSuite.Tests = append(curSuite.Tests, curTest)
		curTest = nil
	}

	// Appends output to the last test.
	appendError := func() {
		if len(out) > 0 && curSuite != nil && len(curSuite.Tests) > 0 {
			message := strings.Join(out, "\n")
			if curSuite.Tests[len(curSuite.Tests)-1].Message == "" {
				curSuite.Tests[len(curSuite.Tests)-1].Message = message
			} else {
				curSuite.Tests[len(curSuite.Tests)-1].Message += "\n" + message
			}
		}
		out = []string{}
	}

	scanner := NewLineScanner(rd)
	for scanner.Scan() {
		line := scanner.Text()

		// TODO: Only outside a suite/test, report as empty suite?
		if isNoFiles(line) {
			continue
		}

		if isBuildFailed(line) {
			return nil, fmt.Errorf("%d: package build failed: %s", scanner.Line(), line)
		}

		if curSuite == nil {
			curSuite = &Suite{}
		}

		tokens := findStart(line)
		if tokens != nil {
			subTest := false
			if curTest != nil {
				// This occurs when the last test ended with a panic, or when subtests are found
				if parentTest == nil && strings.HasPrefix(tokens[1], curTest.Name+"/") {
					// First subtest after parent
					parentTest = curTest
					curSuite.Tests = append(curSuite.Tests, curTest)
					subTests = map[string]*Test{}
					subTest = true
				} else if parentTest != nil && strings.HasPrefix(tokens[1], parentTest.Name+"/") {
					subTest = true
				} else if suiteStack.count == 0 {
					suiteStack.Push(curSuite)
					curSuite = &Suite{Name: curTest.Name}
				} else {
					handlePanic()
				}
			}
			appendError()
			curTest = &Test{
				Name: tokens[1],
			}
			if subTest {
				curSuite.Tests = append(curSuite.Tests, curTest)
				subTests[curTest.Name] = curTest
			}
			continue
		}

		tokens = findEnd(line)
		if tokens != nil {
			appendTest := true
			if parentTest != nil && tokens[2] == parentTest.Name {
				curTest = parentTest
				parentTest = nil
				appendTest = false
			} else if subTest, ok := subTests[tokens[2]]; ok {
				curTest = subTest
				appendTest = false
			} else {
				parentTest = nil
				subTests = map[string]*Test{}
				if curTest == nil {
					if suiteStack.count > 0 {
						prevSuite := suiteStack.Pop()
						suites = append(suites, curSuite)
						curSuite = prevSuite
						continue
					} else {
						return nil, fmt.Errorf("%d: orphan end test", scanner.Line())
					}
				}
				if tokens[2] != curTest.Name {
					err := fmt.Errorf("%d: name mismatch (try disabling parallel mode)", scanner.Line())
					return nil, err
				}
			}
			curTest.Status = Token2Status(tokens[1])
			if curTest.Status == UnknownStatus {
				return nil, fmt.Errorf("%d: unknown status - %s", scanner.Line(), tokens[1])
			}
			if Options.FailOnRace && hasDatarace(out) {
				curTest.Status = Failed
			}
			curTest.Time = tokens[3]
			curTest.Message = strings.Join(out, "\n")
			if appendTest {
				curSuite.Tests = append(curSuite.Tests, curTest)
			}
			curTest = nil
			out = []string{}
			continue
		}

		tokens = findSuite(line)
		if tokens != nil {
			if curTest != nil {
				// This occurs when the last test ended with a panic.
				handlePanic()
			}
			appendError()
			curSuite.Name = suitePrefix + tokens[2]
			curSuite.Time = tokens[3]
			suites = append(suites, curSuite)
			curSuite = nil
			continue
		}

		if isExit(line) || (line == "FAIL") || (line == "PASS") {
			continue
		}

		out = append(out, line)
	}

	if err := scanner.Err(); err != nil {
		return nil, err
	}

	if curTest != nil {
		// This occurs when the last test fatal'd outside of the `go test` runner.
		handlePanic()
	}

	// If there were no suites found, but everything else went OK, return a
	// generic suite.
	if len(suites) == 0 && curSuite != nil {
		if curSuite.Name == "" {
			curSuite.Name = suitePrefix
		}
		// Catch any post-failure messages from the last test
		appendError()
		suites = append(suites, curSuite)
	}

	return Suites(suites), nil
}
<commit_msg>Create a function that returns previous test. And error message, if exists, to previous test not the current one.<commit_after>// Package lib is exposing parsers and output generation
package lib

import (
	"fmt"
	"io"
	"regexp"
	"strings"
)

var (
	matchDatarace = regexp.MustCompile("^WARNING: DATA RACE$").MatchString
)

// hasDatarace checks if there's a data race warning in the line
func hasDatarace(lines []string) bool {
	for _, line := range lines {
		if matchDatarace(line) {
			return true
		}
	}
	return false
}

// Token2Status return matching status for token
func Token2Status(token string) Status {
	switch token {
	case "FAIL", "PANIC":
		return Failed
	case "PASS":
		return Passed
	case "SKIP", "MISS":
		return Skipped
	}
	return UnknownStatus
}

// Returns previous test in a suite, for a given test. Returns error if previous
// test doesn't exist.
func getPreviousTest(suite *Suite, curTest *Test) (*Test, error) {
	previousTestIndex := -1
	for test_index, test := range suite.Tests {
		if test.Name == curTest.Name {
			previousTestIndex = test_index - 1
			break
		}
	}

	if previousTestIndex >= 0 {
		return suite.Tests[previousTestIndex], nil
	}
	return nil, fmt.Errorf("Not found previous test of %s in suite %s", curTest.Name, suite.Name)
}

// ParseGocheck parses output of "go test -gocheck.vv", returns a list of tests
// See data/gocheck.out for an example
// TODO: Refactor to shorter ones
func ParseGocheck(rd io.Reader, suitePrefix string) (Suites, error) {
	findStart := gcStartRE.FindStringSubmatch
	findEnd := gcEndRE.FindStringSubmatch
	findSuite := gcSuiteRE.FindStringSubmatch

	scanner := NewLineScanner(rd)
	var suites = make([]*Suite, 0)
	var suiteName string
	var suite *Suite

	var testName string
	var out []string

	for scanner.Scan() {
		line := scanner.Text()

		tokens := findStart(line)
		if len(tokens) > 0 {
			if tokens[2] == "SetUpTest" || tokens[2] == "TearDownTest" {
				continue
			}
			if testName != "" {
				return nil, fmt.Errorf("%d: start in middle of test", scanner.Line())
			}
			suiteName = tokens[1]
			testName = tokens[2]
			out = []string{}
			continue
		}

		tokens = findEnd(line)
		if len(tokens) > 0 {
			if tokens[3] == "SetUpTest" || tokens[3] == "TearDownTest" {
				continue
			}
			if testName == "" {
				return nil, fmt.Errorf("%d: orphan end", scanner.Line())
			}
			if (tokens[2] != suiteName) || (tokens[3] != testName) {
				return nil, fmt.Errorf("%d: suite/name mismatch", scanner.Line())
			}
			test := &Test{Name: testName}
			test.Message = strings.Join(out, "\n")
			test.Time = tokens[4]
			test.Status = Token2Status(tokens[1])
			if test.Status == UnknownStatus {
				return nil, fmt.Errorf("%d: unknown status %s", scanner.Line(), tokens[1])
			}

			if suite == nil || suite.Name != suiteName {
				suite = &Suite{Name: suitePrefix + suiteName}
				suites = append(suites, suite)
			}
			suite.Tests = append(suite.Tests, test)

			testName = ""
			suiteName = ""
			out = []string{}

			continue
		}

		// last "suite" is test summary
		tokens = findSuite(line)
		if tokens != nil {
			if suite == nil {
				suite = &Suite{Name: tokens[2], Status: tokens[1], Time: tokens[3]}
				suites = append(suites, suite)
			} else {
				suite.Status = tokens[1]
				suite.Time = tokens[3]
			}

			testName = ""
			suiteName = ""
			out = []string{}

			continue
		}

		if testName != "" {
			out = append(out, line)
		}
	}

	if err := scanner.Err(); err != nil {
		return nil, err
	}

	return Suites(suites), nil
}

// ParseGotest parser output of gotest
// TODO: Make it shorter
func ParseGotest(rd io.Reader, suitePrefix string) (Suites, error) {
	findStart := gtStartRE.FindStringSubmatch
	findEnd := gtEndRE.FindStringSubmatch
	findSuite := gtSuiteRE.FindStringSubmatch
	isNoFiles := gtNoFilesRE.MatchString
	isBuildFailed := gtBuildFailedRE.MatchString
	isExit := gtExitRE.MatchString

	suites := []*Suite{}
	subTests := map[string]*Test{}
	var parentTest *Test
	var curTest *Test
	var curSuite *Suite
	var out []string
	suiteStack := SuiteStack{}
	// Handles a test that ended with a panic.
	handlePanic := func() {
		curTest.Status = Failed
		curTest.Time = "0"
		curSuite.Tests = append(curSuite.Tests, curTest)
		curTest = nil
	}

	// Appends output to the last test.
	appendError := func() {
		if len(out) > 0 && curSuite != nil && len(curSuite.Tests) > 0 {
			message := strings.Join(out, "\n")
			if curSuite.Tests[len(curSuite.Tests)-1].Message == "" {
				curSuite.Tests[len(curSuite.Tests)-1].Message = message
			} else {
				curSuite.Tests[len(curSuite.Tests)-1].Message += "\n" + message
			}
		}
		out = []string{}
	}

	scanner := NewLineScanner(rd)
	for scanner.Scan() {
		line := scanner.Text()

		// TODO: Only outside a suite/test, report as empty suite?
		if isNoFiles(line) {
			continue
		}

		if isBuildFailed(line) {
			return nil, fmt.Errorf("%d: package build failed: %s", scanner.Line(), line)
		}

		if curSuite == nil {
			curSuite = &Suite{}
		}

		tokens := findStart(line)
		if tokens != nil {
			subTest := false
			if curTest != nil {
				// This occurs when the last test ended with a panic, or when subtests are found
				if parentTest == nil && strings.HasPrefix(tokens[1], curTest.Name+"/") {
					// First subtest after parent
					parentTest = curTest
					curSuite.Tests = append(curSuite.Tests, curTest)
					subTests = map[string]*Test{}
					subTest = true
				} else if parentTest != nil && strings.HasPrefix(tokens[1], parentTest.Name+"/") {
					subTest = true
				} else if suiteStack.count == 0 {
					suiteStack.Push(curSuite)
					curSuite = &Suite{Name: curTest.Name}
				} else {
					handlePanic()
				}
			}
			appendError()
			curTest = &Test{
				Name: tokens[1],
			}
			if subTest {
				curSuite.Tests = append(curSuite.Tests, curTest)
				subTests[curTest.Name] = curTest
			}
			continue
		}

		tokens = findEnd(line)
		if tokens != nil {
			appendTest := true
			if parentTest != nil && tokens[2] == parentTest.Name {
				curTest = parentTest
				parentTest = nil
				appendTest = false
			} else if subTest, ok := subTests[tokens[2]]; ok {
				curTest = subTest
				appendTest = false
			} else {
				parentTest = nil
				subTests = map[string]*Test{}
				if curTest == nil {
					if suiteStack.count > 0 {
						prevSuite := suiteStack.Pop()
						suites = append(suites, curSuite)
						curSuite = prevSuite
						continue
					} else {
						return nil, fmt.Errorf("%d: orphan end test", scanner.Line())
					}
				}
				if tokens[2] != curTest.Name {
					err := fmt.Errorf("%d: name mismatch (try disabling parallel mode)", scanner.Line())
					return nil, err
				}
			}
			curTest.Status = Token2Status(tokens[1])
			if curTest.Status == UnknownStatus {
				return nil, fmt.Errorf("%d: unknown status - %s", scanner.Line(), tokens[1])
			}
			if Options.FailOnRace && hasDatarace(out) {
				curTest.Status = Failed
			}
			curTest.Time = tokens[3]
			if len(out) > 0 {
				prevTest, err := getPreviousTest(curSuite, curTest)
				if err == nil {
					var test *Test
					if prevTest.Status == Failed {
						test = prevTest
					} else {
						test = curTest
					}
					test.Message = strings.Join(out, "\n")
				} else {
					curTest.Message = strings.Join(out, "\n")
				}
			}

			if appendTest {
				curSuite.Tests = append(curSuite.Tests, curTest)
			}
			curTest = nil
			out = []string{}
			continue
		}

		tokens = findSuite(line)
		if tokens != nil {
			if curTest != nil {
				// This occurs when the last test ended with a panic.
				handlePanic()
			}
			appendError()
			curSuite.Name = suitePrefix + tokens[2]
			curSuite.Time = tokens[3]
			suites = append(suites, curSuite)
			curSuite = nil
			continue
		}

		if isExit(line) || (line == "FAIL") || (line == "PASS") {
			continue
		}

		out = append(out, line)
	}

	if err := scanner.Err(); err != nil {
		return nil, err
	}

	if curTest != nil {
		// This occurs when the last test fatal'd outside of the `go test` runner.
		handlePanic()
	}

	// If there were no suites found, but everything else went OK, return a
	// generic suite.
	if len(suites) == 0 && curSuite != nil {
		if curSuite.Name == "" {
			curSuite.Name = suitePrefix
		}
		// Catch any post-failure messages from the last test
		appendError()
		suites = append(suites, curSuite)
	}

	return Suites(suites), nil
}
<|endoftext|>


<commit_before>// Copyright 2015 Matthew Holt and The Caddy Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package caddyfile

import (
	"errors"
	"fmt"
	"io"
	"log"
	"strings"
)

// Dispenser is a type that dispenses tokens, similarly to a lexer,
// except that it can do so with some notion of structure. An empty
// Dispenser is invalid; call NewDispenser to make a proper instance.
type Dispenser struct {
	tokens  []Token
	cursor  int
	nesting int
}

// NewDispenser returns a Dispenser filled with the given tokens.
func NewDispenser(tokens []Token) *Dispenser {
	return &Dispenser{
		tokens: tokens,
		cursor: -1,
	}
}

// NewTestDispenser parses input into tokens and creates a new
// Disenser for test purposes only; any errors are fatal.
func NewTestDispenser(input string) *Dispenser {
	tokens, err := allTokens("Testfile", []byte(input))
	if err != nil && err != io.EOF {
		log.Fatalf("getting all tokens from input: %v", err)
	}
	return NewDispenser(tokens)
}

// Next loads the next token. Returns true if a token
// was loaded; false otherwise. If false, all tokens
// have been consumed.
func (d *Dispenser) Next() bool {
	if d.cursor < len(d.tokens)-1 {
		d.cursor++
		return true
	}
	return false
}

// Prev moves to the previous token. It does the inverse
// of Next(), except this function may decrement the cursor
// to -1 so that the next call to Next() points to the
// first token; this allows dispensing to "start over". This
// method returns true if the cursor ends up pointing to a
// valid token.
func (d *Dispenser) Prev() bool {
	if d.cursor > -1 {
		d.cursor--
		return d.cursor > -1
	}
	return false
}

// NextArg loads the next token if it is on the same
// line and if it is not a block opening (open curly
// brace). Returns true if an argument token was
// loaded; false otherwise. If false, all tokens on
// the line have been consumed except for potentially
// a block opening. It handles imported tokens
// correctly.
func (d *Dispenser) NextArg() bool {
	if !d.nextOnSameLine() {
		return false
	}
	if d.Val() == "{" {
		// roll back; a block opening is not an argument
		d.cursor--
		return false
	}
	return true
}

// nextOnSameLine advances the cursor if the next
// token is on the same line of the same file.
func (d *Dispenser) nextOnSameLine() bool {
	if d.cursor < 0 {
		d.cursor++
		return true
	}
	if d.cursor >= len(d.tokens) {
		return false
	}
	if d.cursor < len(d.tokens)-1 &&
		d.tokens[d.cursor].File == d.tokens[d.cursor+1].File &&
		d.tokens[d.cursor].Line+d.numLineBreaks(d.cursor) == d.tokens[d.cursor+1].Line {
		d.cursor++
		return true
	}
	return false
}

// NextLine loads the next token only if it is not on the same
// line as the current token, and returns true if a token was
// loaded; false otherwise. If false, there is not another token
// or it is on the same line. It handles imported tokens correctly.
func (d *Dispenser) NextLine() bool {
	if d.cursor < 0 {
		d.cursor++
		return true
	}
	if d.cursor >= len(d.tokens) {
		return false
	}
	if d.cursor < len(d.tokens)-1 &&
		(d.tokens[d.cursor].File != d.tokens[d.cursor+1].File ||
			d.tokens[d.cursor].Line+d.numLineBreaks(d.cursor) < d.tokens[d.cursor+1].Line) {
		d.cursor++
		return true
	}
	return false
}

// NextBlock can be used as the condition of a for loop
// to load the next token as long as it opens a block or
// is already in a block nested more than initialNestingLevel.
// In other words, a loop over NextBlock() will iterate
// all tokens in the block assuming the next token is an
// open curly brace, until the matching closing brace.
// The open and closing brace tokens for the outer-most
// block will be consumed internally and omitted from
// the iteration.
//
// Proper use of this method looks like this:
//
//     for nesting := d.Nesting(); d.NextBlock(nesting); {
//     }
//
// However, in simple cases where it is known that the
// Dispenser is new and has not already traversed state
// by a loop over NextBlock(), this will do:
//
//     for d.NextBlock(0) {
//     }
//
// As with other token parsing logic, a loop over
// NextBlock() should be contained within a loop over
// Next(), as it is usually prudent to skip the initial
// token.
func (d *Dispenser) NextBlock(initialNestingLevel int) bool {
	if d.nesting > initialNestingLevel {
		if !d.Next() {
			return false // should be EOF error
		}
		if d.Val() == "}" && !d.nextOnSameLine() {
			d.nesting--
		} else if d.Val() == "{" && !d.nextOnSameLine() {
			d.nesting++
		}
		return d.nesting > initialNestingLevel
	}
	if !d.nextOnSameLine() { // block must open on same line
		return false
	}
	if d.Val() != "{" {
		d.cursor-- // roll back if not opening brace
		return false
	}
	d.Next() // consume open curly brace
	if d.Val() == "}" {
		return false // open and then closed right away
	}
	d.nesting++
	return true
}

// Nesting returns the current nesting level. Necessary
// if using NextBlock()
func (d *Dispenser) Nesting() int {
	return d.nesting
}

// Val gets the text of the current token. If there is no token
// loaded, it returns empty string.
func (d *Dispenser) Val() string {
	if d.cursor < 0 || d.cursor >= len(d.tokens) {
		return ""
	}
	return d.tokens[d.cursor].Text
}

// Line gets the line number of the current token.
// If there is no token loaded, it returns 0.
func (d *Dispenser) Line() int {
	if d.cursor < 0 || d.cursor >= len(d.tokens) {
		return 0
	}
	return d.tokens[d.cursor].Line
}

// File gets the filename where the current token originated.
func (d *Dispenser) File() string {
	if d.cursor < 0 || d.cursor >= len(d.tokens) {
		return ""
	}
	return d.tokens[d.cursor].File
}

// Args is a convenience function that loads the next arguments
// (tokens on the same line) into an arbitrary number of strings
// pointed to in targets. If there are not enough argument tokens
// available to fill targets, false is returned and the remaining
// targets are left unchanged. If all the targets are filled,
// then true is returned.
func (d *Dispenser) Args(targets ...*string) bool {
	for i := 0; i < len(targets); i++ {
		if !d.NextArg() {
			return false
		}
		*targets[i] = d.Val()
	}
	return true
}

// AllArgs is like Args, but if there are more argument tokens
// available than there are targets, false is returned. The
// number of available argument tokens must match the number of
// targets exactly to return true.
func (d *Dispenser) AllArgs(targets ...*string) bool {
	if !d.Args(targets...) {
		return false
	}
	if d.NextArg() {
		d.Prev()
		return false
	}
	return true
}

// RemainingArgs loads any more arguments (tokens on the same line)
// into a slice and returns them. Open curly brace tokens also indicate
// the end of arguments, and the curly brace is not included in
// the return value nor is it loaded.
func (d *Dispenser) RemainingArgs() []string {
	var args []string
	for d.NextArg() {
		args = append(args, d.Val())
	}
	return args
}

// NewFromNextSegment returns a new dispenser with a copy of
// the tokens from the current token until the end of the
// "directive" whether that be to the end of the line or
// the end of a block that starts at the end of the line;
// in other words, until the end of the segment.
func (d *Dispenser) NewFromNextSegment() *Dispenser {
	return NewDispenser(d.NextSegment())
}

// NextSegment returns a copy of the tokens from the current
// token until the end of the line or block that starts at
// the end of the line.
func (d *Dispenser) NextSegment() Segment {
	tkns := Segment{d.Token()}
	for d.NextArg() {
		tkns = append(tkns, d.Token())
	}
	var openedBlock bool
	for nesting := d.Nesting(); d.NextBlock(nesting); {
		if !openedBlock {
			// because NextBlock() consumes the initial open
			// curly brace, we rewind here to append it, since
			// our case is special in that we want the new
			// dispenser to have all the tokens including
			// surrounding curly braces
			d.Prev()
			tkns = append(tkns, d.Token())
			d.Next()
			openedBlock = true
		}
		tkns = append(tkns, d.Token())
	}
	if openedBlock {
		// include closing brace
		tkns = append(tkns, d.Token())

		// do not consume the closing curly brace; the
		// next iteration of the enclosing loop will
		// call Next() and consume it
	}
	return tkns
}

// Token returns the current token.
func (d *Dispenser) Token() Token {
	if d.cursor < 0 || d.cursor >= len(d.tokens) {
		return Token{}
	}
	return d.tokens[d.cursor]
}

// Reset sets d's cursor to the beginning, as
// if this was a new and unused dispenser.
func (d *Dispenser) Reset() {
	d.cursor = -1
	d.nesting = 0
}

// ArgErr returns an argument error, meaning that another
// argument was expected but not found. In other words,
// a line break or open curly brace was encountered instead of
// an argument.
func (d *Dispenser) ArgErr() error {
	if d.Val() == "{" {
		return d.Err("Unexpected token '{', expecting argument")
	}
	return d.Errf("Wrong argument count or unexpected line ending after '%s'", d.Val())
}

// SyntaxErr creates a generic syntax error which explains what was
// found and what was expected.
func (d *Dispenser) SyntaxErr(expected string) error {
	msg := fmt.Sprintf("%s:%d - Syntax error: Unexpected token '%s', expecting '%s'", d.File(), d.Line(), d.Val(), expected)
	return errors.New(msg)
}

// EOFErr returns an error indicating that the dispenser reached
// the end of the input when searching for the next token.
func (d *Dispenser) EOFErr() error {
	return d.Errf("Unexpected EOF")
}

// Err generates a custom parse-time error with a message of msg.
func (d *Dispenser) Err(msg string) error {
	msg = fmt.Sprintf("%s:%d - Error during parsing: %s", d.File(), d.Line(), msg)
	return errors.New(msg)
}

// Errf is like Err, but for formatted error messages
func (d *Dispenser) Errf(format string, args ...interface{}) error {
	return d.Err(fmt.Sprintf(format, args...))
}

// Delete deletes the current token and returns the updated slice
// of tokens. The cursor is not advanced to the next token.
// Because deletion modifies the underlying slice, this method
// should only be called if you have access to the original slice
// of tokens and/or are using the slice of tokens outside this
// Dispenser instance. If you do not re-assign the slice with the
// return value of this method, inconsistencies in the token
// array will become apparent (or worse, hide from you like they
// did me for 3 and a half freaking hours late one night).
func (d *Dispenser) Delete() []Token {
	if d.cursor >= 0 && d.cursor <= len(d.tokens)-1 {
		d.tokens = append(d.tokens[:d.cursor], d.tokens[d.cursor+1:]...)
		d.cursor--
	}
	return d.tokens
}

// numLineBreaks counts how many line breaks are in the token
// value given by the token index tknIdx. It returns 0 if the
// token does not exist or there are no line breaks.
func (d *Dispenser) numLineBreaks(tknIdx int) int {
	if tknIdx < 0 || tknIdx >= len(d.tokens) {
		return 0
	}
	return strings.Count(d.tokens[tknIdx].Text, "\n")
}

// isNewLine determines whether the current token is on a different
// line (higher line number) than the previous token. It handles imported
// tokens correctly. If there isn't a previous token, it returns true.
func (d *Dispenser) isNewLine() bool {
	if d.cursor < 1 {
		return true
	}
	if d.cursor > len(d.tokens)-1 {
		return false
	}
	return d.tokens[d.cursor-1].File != d.tokens[d.cursor].File ||
		d.tokens[d.cursor-1].Line+d.numLineBreaks(d.cursor-1) < d.tokens[d.cursor].Line
}
<commit_msg>chore: Fix typo in dispenser.go (#3456)<commit_after>// Copyright 2015 Matthew Holt and The Caddy Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package caddyfile

import (
	"errors"
	"fmt"
	"io"
	"log"
	"strings"
)

// Dispenser is a type that dispenses tokens, similarly to a lexer,
// except that it can do so with some notion of structure. An empty
// Dispenser is invalid; call NewDispenser to make a proper instance.
type Dispenser struct {
	tokens  []Token
	cursor  int
	nesting int
}

// NewDispenser returns a Dispenser filled with the given tokens.
func NewDispenser(tokens []Token) *Dispenser {
	return &Dispenser{
		tokens: tokens,
		cursor: -1,
	}
}

// NewTestDispenser parses input into tokens and creates a new
// Dispenser for test purposes only; any errors are fatal.
func NewTestDispenser(input string) *Dispenser {
	tokens, err := allTokens("Testfile", []byte(input))
	if err != nil && err != io.EOF {
		log.Fatalf("getting all tokens from input: %v", err)
	}
	return NewDispenser(tokens)
}

// Next loads the next token. Returns true if a token
// was loaded; false otherwise. If false, all tokens
// have been consumed.
func (d *Dispenser) Next() bool {
	if d.cursor < len(d.tokens)-1 {
		d.cursor++
		return true
	}
	return false
}

// Prev moves to the previous token. It does the inverse
// of Next(), except this function may decrement the cursor
// to -1 so that the next call to Next() points to the
// first token; this allows dispensing to "start over". This
// method returns true if the cursor ends up pointing to a
// valid token.
func (d *Dispenser) Prev() bool {
	if d.cursor > -1 {
		d.cursor--
		return d.cursor > -1
	}
	return false
}

// NextArg loads the next token if it is on the same
// line and if it is not a block opening (open curly
// brace). Returns true if an argument token was
// loaded; false otherwise. If false, all tokens on
// the line have been consumed except for potentially
// a block opening. It handles imported tokens
// correctly.
func (d *Dispenser) NextArg() bool {
	if !d.nextOnSameLine() {
		return false
	}
	if d.Val() == "{" {
		// roll back; a block opening is not an argument
		d.cursor--
		return false
	}
	return true
}

// nextOnSameLine advances the cursor if the next
// token is on the same line of the same file.
func (d *Dispenser) nextOnSameLine() bool {
	if d.cursor < 0 {
		d.cursor++
		return true
	}
	if d.cursor >= len(d.tokens) {
		return false
	}
	if d.cursor < len(d.tokens)-1 &&
		d.tokens[d.cursor].File == d.tokens[d.cursor+1].File &&
		d.tokens[d.cursor].Line+d.numLineBreaks(d.cursor) == d.tokens[d.cursor+1].Line {
		d.cursor++
		return true
	}
	return false
}

// NextLine loads the next token only if it is not on the same
// line as the current token, and returns true if a token was
// loaded; false otherwise. If false, there is not another token
// or it is on the same line. It handles imported tokens correctly.
func (d *Dispenser) NextLine() bool {
	if d.cursor < 0 {
		d.cursor++
		return true
	}
	if d.cursor >= len(d.tokens) {
		return false
	}
	if d.cursor < len(d.tokens)-1 &&
		(d.tokens[d.cursor].File != d.tokens[d.cursor+1].File ||
			d.tokens[d.cursor].Line+d.numLineBreaks(d.cursor) < d.tokens[d.cursor+1].Line) {
		d.cursor++
		return true
	}
	return false
}

// NextBlock can be used as the condition of a for loop
// to load the next token as long as it opens a block or
// is already in a block nested more than initialNestingLevel.
// In other words, a loop over NextBlock() will iterate
// all tokens in the block assuming the next token is an
// open curly brace, until the matching closing brace.
// The open and closing brace tokens for the outer-most
// block will be consumed internally and omitted from
// the iteration.
//
// Proper use of this method looks like this:
//
//     for nesting := d.Nesting(); d.NextBlock(nesting); {
//     }
//
// However, in simple cases where it is known that the
// Dispenser is new and has not already traversed state
// by a loop over NextBlock(), this will do:
//
//     for d.NextBlock(0) {
//     }
//
// As with other token parsing logic, a loop over
// NextBlock() should be contained within a loop over
// Next(), as it is usually prudent to skip the initial
// token.
func (d *Dispenser) NextBlock(initialNestingLevel int) bool {
	if d.nesting > initialNestingLevel {
		if !d.Next() {
			return false // should be EOF error
		}
		if d.Val() == "}" && !d.nextOnSameLine() {
			d.nesting--
		} else if d.Val() == "{" && !d.nextOnSameLine() {
			d.nesting++
		}
		return d.nesting > initialNestingLevel
	}
	if !d.nextOnSameLine() { // block must open on same line
		return false
	}
	if d.Val() != "{" {
		d.cursor-- // roll back if not opening brace
		return false
	}
	d.Next() // consume open curly brace
	if d.Val() == "}" {
		return false // open and then closed right away
	}
	d.nesting++
	return true
}

// Nesting returns the current nesting level. Necessary
// if using NextBlock()
func (d *Dispenser) Nesting() int {
	return d.nesting
}

// Val gets the text of the current token. If there is no token
// loaded, it returns empty string.
func (d *Dispenser) Val() string {
	if d.cursor < 0 || d.cursor >= len(d.tokens) {
		return ""
	}
	return d.tokens[d.cursor].Text
}

// Line gets the line number of the current token.
// If there is no token loaded, it returns 0.
func (d *Dispenser) Line() int {
	if d.cursor < 0 || d.cursor >= len(d.tokens) {
		return 0
	}
	return d.tokens[d.cursor].Line
}

// File gets the filename where the current token originated.
func (d *Dispenser) File() string {
	if d.cursor < 0 || d.cursor >= len(d.tokens) {
		return ""
	}
	return d.tokens[d.cursor].File
}

// Args is a convenience function that loads the next arguments
// (tokens on the same line) into an arbitrary number of strings
// pointed to in targets. If there are not enough argument tokens
// available to fill targets, false is returned and the remaining
// targets are left unchanged. If all the targets are filled,
// then true is returned.
func (d *Dispenser) Args(targets ...*string) bool {
	for i := 0; i < len(targets); i++ {
		if !d.NextArg() {
			return false
		}
		*targets[i] = d.Val()
	}
	return true
}

// AllArgs is like Args, but if there are more argument tokens
// available than there are targets, false is returned. The
// number of available argument tokens must match the number of
// targets exactly to return true.
func (d *Dispenser) AllArgs(targets ...*string) bool {
	if !d.Args(targets...) {
		return false
	}
	if d.NextArg() {
		d.Prev()
		return false
	}
	return true
}

// RemainingArgs loads any more arguments (tokens on the same line)
// into a slice and returns them. Open curly brace tokens also indicate
// the end of arguments, and the curly brace is not included in
// the return value nor is it loaded.
func (d *Dispenser) RemainingArgs() []string {
	var args []string
	for d.NextArg() {
		args = append(args, d.Val())
	}
	return args
}

// NewFromNextSegment returns a new dispenser with a copy of
// the tokens from the current token until the end of the
// "directive" whether that be to the end of the line or
// the end of a block that starts at the end of the line;
// in other words, until the end of the segment.
func (d *Dispenser) NewFromNextSegment() *Dispenser {
	return NewDispenser(d.NextSegment())
}

// NextSegment returns a copy of the tokens from the current
// token until the end of the line or block that starts at
// the end of the line.
func (d *Dispenser) NextSegment() Segment {
	tkns := Segment{d.Token()}
	for d.NextArg() {
		tkns = append(tkns, d.Token())
	}
	var openedBlock bool
	for nesting := d.Nesting(); d.NextBlock(nesting); {
		if !openedBlock {
			// because NextBlock() consumes the initial open
			// curly brace, we rewind here to append it, since
			// our case is special in that we want the new
			// dispenser to have all the tokens including
			// surrounding curly braces
			d.Prev()
			tkns = append(tkns, d.Token())
			d.Next()
			openedBlock = true
		}
		tkns = append(tkns, d.Token())
	}
	if openedBlock {
		// include closing brace
		tkns = append(tkns, d.Token())

		// do not consume the closing curly brace; the
		// next iteration of the enclosing loop will
		// call Next() and consume it
	}
	return tkns
}

// Token returns the current token.
func (d *Dispenser) Token() Token {
	if d.cursor < 0 || d.cursor >= len(d.tokens) {
		return Token{}
	}
	return d.tokens[d.cursor]
}

// Reset sets d's cursor to the beginning, as
// if this was a new and unused dispenser.
func (d *Dispenser) Reset() {
	d.cursor = -1
	d.nesting = 0
}

// ArgErr returns an argument error, meaning that another
// argument was expected but not found. In other words,
// a line break or open curly brace was encountered instead of
// an argument.
func (d *Dispenser) ArgErr() error {
	if d.Val() == "{" {
		return d.Err("Unexpected token '{', expecting argument")
	}
	return d.Errf("Wrong argument count or unexpected line ending after '%s'", d.Val())
}

// SyntaxErr creates a generic syntax error which explains what was
// found and what was expected.
func (d *Dispenser) SyntaxErr(expected string) error {
	msg := fmt.Sprintf("%s:%d - Syntax error: Unexpected token '%s', expecting '%s'", d.File(), d.Line(), d.Val(), expected)
	return errors.New(msg)
}

// EOFErr returns an error indicating that the dispenser reached
// the end of the input when searching for the next token.
func (d *Dispenser) EOFErr() error {
	return d.Errf("Unexpected EOF")
}

// Err generates a custom parse-time error with a message of msg.
func (d *Dispenser) Err(msg string) error {
	msg = fmt.Sprintf("%s:%d - Error during parsing: %s", d.File(), d.Line(), msg)
	return errors.New(msg)
}

// Errf is like Err, but for formatted error messages
func (d *Dispenser) Errf(format string, args ...interface{}) error {
	return d.Err(fmt.Sprintf(format, args...))
}

// Delete deletes the current token and returns the updated slice
// of tokens. The cursor is not advanced to the next token.
// Because deletion modifies the underlying slice, this method
// should only be called if you have access to the original slice
// of tokens and/or are using the slice of tokens outside this
// Dispenser instance. If you do not re-assign the slice with the
// return value of this method, inconsistencies in the token
// array will become apparent (or worse, hide from you like they
// did me for 3 and a half freaking hours late one night).
func (d *Dispenser) Delete() []Token {
	if d.cursor >= 0 && d.cursor <= len(d.tokens)-1 {
		d.tokens = append(d.tokens[:d.cursor], d.tokens[d.cursor+1:]...)
		d.cursor--
	}
	return d.tokens
}

// numLineBreaks counts how many line breaks are in the token
// value given by the token index tknIdx. It returns 0 if the
// token does not exist or there are no line breaks.
func (d *Dispenser) numLineBreaks(tknIdx int) int {
	if tknIdx < 0 || tknIdx >= len(d.tokens) {
		return 0
	}
	return strings.Count(d.tokens[tknIdx].Text, "\n")
}

// isNewLine determines whether the current token is on a different
// line (higher line number) than the previous token. It handles imported
// tokens correctly. If there isn't a previous token, it returns true.
func (d *Dispenser) isNewLine() bool {
	if d.cursor < 1 {
		return true
	}
	if d.cursor > len(d.tokens)-1 {
		return false
	}
	return d.tokens[d.cursor-1].File != d.tokens[d.cursor].File ||
		d.tokens[d.cursor-1].Line+d.numLineBreaks(d.cursor-1) < d.tokens[d.cursor].Line
}
<|endoftext|>


<commit_before>package machine_test

import (
	stdtesting "testing"

	. "launchpad.net/gocheck"

	"launchpad.net/juju-core/juju/testing"
	"launchpad.net/juju-core/state"
	"launchpad.net/juju-core/state/apiserver/common"
	apiservertesting "launchpad.net/juju-core/state/apiserver/testing"
	coretesting "launchpad.net/juju-core/testing"
)

func Test(t *stdtesting.T) {
	coretesting.MgoTestPackage(t)
}

type commonSuite struct {
	testing.JujuConnSuite

	authorizer apiservertesting.FakeAuthorizer
	resources  *common.Resources

	machine0 *state.Machine
	machine1 *state.Machine
}

func (s *commonSuite) SetUpTest(c *C) {
	s.JujuConnSuite.SetUpTest(c)

	var err error
	s.machine0, err = s.State.AddMachine("series", state.JobManageEnviron, state.JobManageState)
	c.Assert(err, IsNil)

	s.machine1, err = s.State.AddMachine("series", state.JobHostUnits)
	c.Assert(err, IsNil)

	// Create the resource registry separately to track invocations to
	// Register.
	s.resources = common.NewResources()

	// Create a FakeAuthorizer so we can check permissions,
	// set up assuming machine 1 has logged in.
	s.authorizer = apiservertesting.FakeAuthorizer{
		Tag:          s.machine1.Tag(),
		LoggedIn:     true,
		Manager:      false,
		MachineAgent: true,
	}
}
<commit_msg>Removed redundant code<commit_after>package machine_test

import (
	stdtesting "testing"

	. "launchpad.net/gocheck"

	"launchpad.net/juju-core/juju/testing"
	"launchpad.net/juju-core/state"
	apiservertesting "launchpad.net/juju-core/state/apiserver/testing"
	coretesting "launchpad.net/juju-core/testing"
)

func Test(t *stdtesting.T) {
	coretesting.MgoTestPackage(t)
}

type commonSuite struct {
	testing.JujuConnSuite

	authorizer apiservertesting.FakeAuthorizer

	machine0 *state.Machine
	machine1 *state.Machine
}

func (s *commonSuite) SetUpTest(c *C) {
	s.JujuConnSuite.SetUpTest(c)

	var err error
	s.machine0, err = s.State.AddMachine("series", state.JobManageEnviron, state.JobManageState)
	c.Assert(err, IsNil)

	s.machine1, err = s.State.AddMachine("series", state.JobHostUnits)
	c.Assert(err, IsNil)

	// Create a FakeAuthorizer so we can check permissions,
	// set up assuming machine 1 has logged in.
	s.authorizer = apiservertesting.FakeAuthorizer{
		Tag:          s.machine1.Tag(),
		LoggedIn:     true,
		Manager:      false,
		MachineAgent: true,
	}
}
<|endoftext|>


<commit_before>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package networker

import (
	"github.com/juju/loggo"
	"github.com/juju/names"

	"github.com/juju/juju/network"
	"github.com/juju/juju/state"
	"github.com/juju/juju/state/api/params"
	"github.com/juju/juju/state/apiserver/common"
)

func init() {
	// TODO: When the client can handle new versions, this should really be
	// registered as version 1, since it was not present in the API in Juju
	// 1.18
	common.RegisterStandardFacade("Networker", 0, NewNetworkerAPI)
}

var logger = loggo.GetLogger("juju.state.apiserver.networker")

// NetworkerAPI provides access to the Networker API facade.
type NetworkerAPI struct {
	st          *state.State
	authorizer  common.Authorizer
	getAuthFunc common.GetAuthFunc
}

// NewNetworkerAPI creates a new client-side Networker API facade.
func NewNetworkerAPI(
	st *state.State,
	_ *common.Resources,
	authorizer common.Authorizer,
) (*NetworkerAPI, error) {
	if !authorizer.AuthMachineAgent() {
		return nil, common.ErrPerm
	}
	getAuthFunc := func() (common.AuthFunc, error) {
		authEntityTag := authorizer.GetAuthTag()

		return func(tag string) bool {
			if tag == authEntityTag.String() {
				// A machine agent can always access its own machine.
				return true
			}
			t, err := names.ParseMachineTag(tag)
			if err != nil {
				// Only machine tags are allowed.
				return false
			}
			id := t.Id()
			for parentId := state.ParentId(id); parentId != ""; parentId = state.ParentId(parentId) {
				// Until a top-level machine is reached.
				if names.NewMachineTag(parentId) == authEntityTag {
					// All containers with the authenticated machine as a
					// parent are accessible by it.
					return true
				}
			}
			// Not found authorized machine agent among ancestors of the current one.
			return false
		}, nil
	}

	return &NetworkerAPI{
		st:          st,
		authorizer:  authorizer,
		getAuthFunc: getAuthFunc,
	}, nil
}

func (n *NetworkerAPI) oneMachineInfo(id string) ([]network.Info, error) {
	machine, err := n.st.Machine(id)
	if err != nil {
		return nil, err
	}
	ifaces, err := machine.NetworkInterfaces()
	if err != nil {
		return nil, err
	}
	info := make([]network.Info, len(ifaces))
	for i, iface := range ifaces {
		nw, err := n.st.Network(iface.NetworkName())
		if err != nil {
			return nil, err
		}
		info[i] = network.Info{
			MACAddress:    iface.MACAddress(),
			CIDR:          nw.CIDR(),
			NetworkName:   iface.NetworkName(),
			ProviderId:    nw.ProviderId(),
			VLANTag:       nw.VLANTag(),
			InterfaceName: iface.RawInterfaceName(),
		}
	}
	return info, nil
}

// Networks returns the list of networks with related interfaces for a given set of machines.
func (n *NetworkerAPI) MachineNetworkInfo(args params.Entities) (params.MachineNetworkInfoResults, error) {
	result := params.MachineNetworkInfoResults{
		Results: make([]params.MachineNetworkInfoResult, len(args.Entities)),
	}
	canAccess, err := n.getAuthFunc()
	if err != nil {
		return result, err
	}
	var tag names.Tag
	for i, entity := range args.Entities {
		if !canAccess(entity.Tag) {
			err = common.ErrPerm
		} else {
			tag, err = names.ParseMachineTag(entity.Tag)
			if err == nil {
				id := tag.Id()
				result.Results[i].Info, err = n.oneMachineInfo(id)
			}
		}
		result.Results[i].Error = common.ServerError(err)
	}
	return result, nil
}
<commit_msg>Fix compiler crash<commit_after>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package networker

import (
	"github.com/juju/loggo"
	"github.com/juju/names"

	"github.com/juju/juju/network"
	"github.com/juju/juju/state"
	"github.com/juju/juju/state/api/params"
	"github.com/juju/juju/state/apiserver/common"
)

func init() {
	// TODO: When the client can handle new versions, this should really be
	// registered as version 1, since it was not present in the API in Juju
	// 1.18
	common.RegisterStandardFacade("Networker", 0, NewNetworkerAPI)
}

var logger = loggo.GetLogger("juju.state.apiserver.networker")

// NetworkerAPI provides access to the Networker API facade.
type NetworkerAPI struct {
	st          *state.State
	authorizer  common.Authorizer
	getAuthFunc common.GetAuthFunc
}

// NewNetworkerAPI creates a new client-side Networker API facade.
func NewNetworkerAPI(
	st *state.State,
	_ *common.Resources,
	authorizer common.Authorizer,
) (*NetworkerAPI, error) {
	if !authorizer.AuthMachineAgent() {
		return nil, common.ErrPerm
	}
	getAuthFunc := func() (common.AuthFunc, error) {
		authEntityTag := authorizer.GetAuthTag().String()

		return func(tag string) bool {
			if tag == authEntityTag {
				// A machine agent can always access its own machine.
				return true
			}
			t, err := names.ParseMachineTag(tag)
			if err != nil {
				// Only machine tags are allowed.
				return false
			}
			id := t.Id()
			for parentId := state.ParentId(id); parentId != ""; parentId = state.ParentId(parentId) {
				// Until a top-level machine is reached.
				// TODO(dfc) comparing the two interfaces caused a compiler crash with
				// gcc version 4.9.0 (Ubuntu 4.9.0-7ubuntu1). Work around the issue
				// by comparing by string value.
				if names.NewMachineTag(parentId).String() == authEntityTag {
					// All containers with the authenticated machine as a
					// parent are accessible by it.
					return true
				}
			}
			// Not found authorized machine agent among ancestors of the current one.
			return false
		}, nil
	}

	return &NetworkerAPI{
		st:          st,
		authorizer:  authorizer,
		getAuthFunc: getAuthFunc,
	}, nil
}

func (n *NetworkerAPI) oneMachineInfo(id string) ([]network.Info, error) {
	machine, err := n.st.Machine(id)
	if err != nil {
		return nil, err
	}
	ifaces, err := machine.NetworkInterfaces()
	if err != nil {
		return nil, err
	}
	info := make([]network.Info, len(ifaces))
	for i, iface := range ifaces {
		nw, err := n.st.Network(iface.NetworkName())
		if err != nil {
			return nil, err
		}
		info[i] = network.Info{
			MACAddress:    iface.MACAddress(),
			CIDR:          nw.CIDR(),
			NetworkName:   iface.NetworkName(),
			ProviderId:    nw.ProviderId(),
			VLANTag:       nw.VLANTag(),
			InterfaceName: iface.RawInterfaceName(),
		}
	}
	return info, nil
}

// Networks returns the list of networks with related interfaces for a given set of machines.
func (n *NetworkerAPI) MachineNetworkInfo(args params.Entities) (params.MachineNetworkInfoResults, error) {
	result := params.MachineNetworkInfoResults{
		Results: make([]params.MachineNetworkInfoResult, len(args.Entities)),
	}
	canAccess, err := n.getAuthFunc()
	if err != nil {
		return result, err
	}
	var tag names.Tag
	for i, entity := range args.Entities {
		if !canAccess(entity.Tag) {
			err = common.ErrPerm
		} else {
			tag, err = names.ParseMachineTag(entity.Tag)
			if err == nil {
				id := tag.Id()
				result.Results[i].Info, err = n.oneMachineInfo(id)
			}
		}
		result.Results[i].Error = common.ServerError(err)
	}
	return result, nil
}
<|endoftext|>


<commit_before>// +build linux
// +build amd64 arm64

package xchg

import (
	"golang.org/x/sys/unix"
	"unsafe"
)

const (
	// These values were pulled from here
	// http://lxr.free-electrons.com/source/include/uapi/linux/fs.h#L38

	// Don't overwrite target
	NOREPLACE = 1
	// Exchange source and destination
	EXCHANGE = 2
	// Whiteout source
	WHITEOUT = 4
)

// XXX This is a trick that is used in the Go syscall library to trick
// the compiler into keeping an object alive for the length of a
// syscall. It shouldn't be nessecary for Go 1.6 so we should consider
// removing this around Go 1.7. See accompanying 'use.s' assembly file
// as well as the following commit message for the technical details.
// The tl;dr is that our unsafe.Pointer could be garbage collected right
// after we get its location via the `uintptr` call which means we'd be
// passing garbage to kernel for the syscall.
//
// https://github.com/golang/go/commit/cf622d758cd51cfa09f5b503d323c81ed3a5541e#diff-264325f3e02feb10326578a776808fb7
func use(p unsafe.Pointer)

func Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) {
	oldPtr, err := unix.BytePtrFromString(oldpath)
	if err != nil {
		return
	}
	newPtr, err := unix.BytePtrFromString(newpath)
	if err != nil {
		return
	}
	_, _, errno := unix.Syscall6(
		SYS_RENAMEAT2,
		uintptr(olddirfd),
		uintptr(unsafe.Pointer(oldPtr)),
		uintptr(newdirfd),
		uintptr(unsafe.Pointer(newPtr)),
		uintptr(flags),
		0,
	)
	use(unsafe.Pointer(oldPtr))
	use(unsafe.Pointer(newPtr))

	if errno != 0 {
		// In the syscall module the authors box a couple of common errors
		// (i.e EAGAIN, EINVAL, and ENOENT). Is that worth doing here?
		err = errno
	}

	return
}

func Exchange(oldpath string, newpath string) (err error) {
	// TODO Should we return an os.LinkError on error? What about on ENOSYS?
	return Renameat2(unix.AT_FDCWD, oldpath, unix.AT_FDCWD, newpath, EXCHANGE)
}
<commit_msg>Cleanup function definition<commit_after>// +build linux
// +build amd64 arm64

package xchg

import (
	"golang.org/x/sys/unix"
	"unsafe"
)

const (
	// These values were pulled from here
	// http://lxr.free-electrons.com/source/include/uapi/linux/fs.h#L38

	// Don't overwrite target
	NOREPLACE = 1
	// Exchange source and destination
	EXCHANGE = 2
	// Whiteout source
	WHITEOUT = 4
)

// XXX This is a trick that is used in the Go syscall library to trick
// the compiler into keeping an object alive for the length of a
// syscall. It shouldn't be nessecary for Go 1.6 so we should consider
// removing this around Go 1.7. See accompanying 'use.s' assembly file
// as well as the following commit message for the technical details.
// The tl;dr is that our unsafe.Pointer could be garbage collected right
// after we get its location via the `uintptr` call which means we'd be
// passing garbage to kernel for the syscall.
//
// https://github.com/golang/go/commit/cf622d758cd51cfa09f5b503d323c81ed3a5541e#diff-264325f3e02feb10326578a776808fb7
func use(p unsafe.Pointer)

func Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) {
	oldPtr, err := unix.BytePtrFromString(oldpath)
	if err != nil {
		return
	}
	newPtr, err := unix.BytePtrFromString(newpath)
	if err != nil {
		return
	}
	_, _, errno := unix.Syscall6(
		SYS_RENAMEAT2,
		uintptr(olddirfd),
		uintptr(unsafe.Pointer(oldPtr)),
		uintptr(newdirfd),
		uintptr(unsafe.Pointer(newPtr)),
		uintptr(flags),
		0,
	)
	use(unsafe.Pointer(oldPtr))
	use(unsafe.Pointer(newPtr))

	if errno != 0 {
		// In the syscall module the authors box a couple of common errors
		// (i.e EAGAIN, EINVAL, and ENOENT). Is that worth doing here?
		err = errno
	}

	return
}

func Exchange(oldpath, newpath string) error {
	// TODO Should we return an os.LinkError on error? What about on ENOSYS?
	return Renameat2(unix.AT_FDCWD, oldpath, unix.AT_FDCWD, newpath, EXCHANGE)
}
<|endoftext|>


<commit_before>package librariesio

import (
	"context"
	"fmt"
	"net/http"
	"time"
)

// Project represents a project on libraries.io
type Project struct {
	Description              string    `json:"description,omitempty"`
	Forks                    int       `json:"forks,omitempty"`
	Homepage                 string    `json:"homepage,omitempty"`
	Keywords                 []string  `json:"keywords,omitempty"`
	Language                 string    `json:"language,omitempty"`
	LatestReleaseNumber      string    `json:"latest_release_number,omitempty"`
	LatestReleasePublishedAt time.Time `json:"latest_release_published_at,omitempty"`
	LatestStableRelease      Release   `json:"latest_stable_release,omitempty"`
	Name                     string    `json:"name,omitempty"`
	NormalizedLicenses       []string  `json:"normalized_licenses,omitempty"`
	PackageManagerURL        string    `json:"package_manager_url,omitempty"`
	Platform                 string    `json:"platform,omitempty"`
	Rank                     int       `json:"rank,omitempty"`
	Stars                    int       `json:"stars,omitempty"`
	Status                   string    `json:"status,omitempty"`
	Versions                 []Release `json:"versions,omitempty"`
}

// Release represents a release of the project
type Release struct {
	Number      string    `json:"number,omitempty"`
	PublishedAt time.Time `json:"published_at,omitempty"`
}

// GetProject returns information about a project and it's versions.
// GET https://libraries.io/api/:platform/:name
func (c *Client) GetProject(ctx context.Context, platform string, name string) (*Project, *http.Response, error) {
	urlStr := fmt.Sprintf("%v/%v", platform, name)

	request, err := c.NewRequest("GET", urlStr, nil)

	if err != nil {
		return nil, nil, err
	}

	project := new(Project)
	response, err := c.Do(ctx, request, project)
	if err != nil {
		return nil, response, err
	}

	return project, response, nil
}
<commit_msg>Change Project fields to pointers<commit_after>package librariesio

import (
	"context"
	"fmt"
	"net/http"
	"time"
)

// Project represents a project on libraries.io
type Project struct {
	Description              *string    `json:"description,omitempty"`
	Forks                    *int       `json:"forks,omitempty"`
	Homepage                 *string    `json:"homepage,omitempty"`
	Keywords                 []*string  `json:"keywords,omitempty"`
	Language                 *string    `json:"language,omitempty"`
	LatestReleaseNumber      *string    `json:"latest_release_number,omitempty"`
	LatestReleasePublishedAt *time.Time `json:"latest_release_published_at,omitempty"`
	LatestStableRelease      *Release   `json:"latest_stable_release,omitempty"`
	Name                     *string    `json:"name,omitempty"`
	NormalizedLicenses       []*string  `json:"normalized_licenses,omitempty"`
	PackageManagerURL        *string    `json:"package_manager_url,omitempty"`
	Platform                 *string    `json:"platform,omitempty"`
	Rank                     *int       `json:"rank,omitempty"`
	Stars                    *int       `json:"stars,omitempty"`
	Status                   *string    `json:"status,omitempty"`
	Versions                 []*Release `json:"versions,omitempty"`
}

// Release represents a release of the project
type Release struct {
	Number      string    `json:"number,omitempty"`
	PublishedAt time.Time `json:"published_at,omitempty"`
}

// GetProject returns information about a project and it's versions.
// GET https://libraries.io/api/:platform/:name
func (c *Client) GetProject(ctx context.Context, platform string, name string) (*Project, *http.Response, error) {
	urlStr := fmt.Sprintf("%v/%v", platform, name)

	request, err := c.NewRequest("GET", urlStr, nil)

	if err != nil {
		return nil, nil, err
	}

	project := new(Project)
	response, err := c.Do(ctx, request, project)
	if err != nil {
		return nil, response, err
	}

	return project, response, nil
}
<|endoftext|>