<commit_before>package containerd

import (
	"fmt"
	"os"
	"path/filepath"
	"sort"
	"strings"

	"github.com/Sirupsen/logrus"
	"github.com/containerd/containerd"
	containersapi "github.com/containerd/containerd/api/services/containers"
	"github.com/containerd/containerd/api/services/execution"
	"github.com/containerd/containerd/api/types/task"
	dockermount "github.com/docker/docker/pkg/mount"
	"github.com/docker/swarmkit/agent/exec"
	"github.com/docker/swarmkit/api"
	"github.com/docker/swarmkit/api/naming"
	"github.com/docker/swarmkit/log"
	"github.com/opencontainers/runtime-spec/specs-go"
	"github.com/pkg/errors"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
)

var (
	devNull                    *os.File
	mountPropagationReverseMap = map[api.Mount_BindOptions_MountPropagation]string{
		api.MountPropagationPrivate:  "private",
		api.MountPropagationRPrivate: "rprivate",
		api.MountPropagationShared:   "shared",
		api.MountPropagationRShared:  "rshared",
		api.MountPropagationRSlave:   "slave",
		api.MountPropagationSlave:    "rslave",
	}
)

// containerAdapter conducts remote operations for a container. All calls
// are mostly naked calls to the client API, seeded with information from
// containerConfig.
type containerAdapter struct {
	client         *containerd.Client
	spec           *api.ContainerSpec
	secrets        exec.SecretGetter
	name           string
	image          containerd.Image // Pulled image
	container      containerd.Container
	task           containerd.Task
	deleteResponse *execution.DeleteResponse
}

func newContainerAdapter(client *containerd.Client, task *api.Task, secrets exec.SecretGetter) (*containerAdapter, error) {
	spec := task.Spec.GetContainer()
	if spec == nil {
		return nil, exec.ErrRuntimeUnsupported
	}

	return &containerAdapter{
		client:  client,
		spec:    spec,
		secrets: secrets,
		name:    naming.Task(task),
	}, nil
}

func (c *containerAdapter) pullImage(ctx context.Context) error {
	image, err := c.client.Pull(ctx, c.spec.Image, containerd.WithPullUnpack)
	if err != nil {
		return errors.Wrap(err, "pulling container image")
	}
	c.image = image

	return nil
}

func withMounts(ctx context.Context, ms []api.Mount) containerd.SpecOpts {
	sort.Sort(mounts(ms))

	return func(s *specs.Spec) error {
		for _, m := range ms {
			if !filepath.IsAbs(m.Target) {
				return errors.Errorf("mount %s is not absolute", m.Target)
			}

			switch m.Type {
			case api.MountTypeTmpfs:
				opts := []string{"noexec", "nosuid", "nodev", "rprivate"}
				if m.TmpfsOptions != nil {
					if m.TmpfsOptions.SizeBytes <= 0 {
						return errors.New("invalid tmpfs size give")
					}
					opts = append(opts, fmt.Sprintf("size=%d", m.TmpfsOptions.SizeBytes))
					opts = append(opts, fmt.Sprintf("mode=%o", m.TmpfsOptions.Mode))
				}
				if m.ReadOnly {
					opts = append(opts, "ro")
				} else {
					opts = append(opts, "rw")
				}

				opts, err := dockermount.MergeTmpfsOptions(opts)
				if err != nil {
					return err
				}

				s.Mounts = append(s.Mounts, specs.Mount{
					Destination: m.Target,
					Type:        "tmpfs",
					Source:      "tmpfs",
					Options:     opts,
				})

			case api.MountTypeVolume:
				return errors.Errorf("volume mounts not implemented, ignoring %v", m)

			case api.MountTypeBind:
				opts := []string{"rbind"}
				if m.ReadOnly {
					opts = append(opts, "ro")
				} else {
					opts = append(opts, "rw")
				}

				propagation := "rprivate"
				if m.BindOptions != nil {
					if p, ok := mountPropagationReverseMap[m.BindOptions.Propagation]; ok {
						propagation = p
					} else {
						log.G(ctx).Warningf("unknown bind mount propagation, using %q", propagation)
					}
				}
				opts = append(opts, propagation)

				s.Mounts = append(s.Mounts, specs.Mount{
					Destination: m.Target,
					Type:        "bind",
					Source:      m.Source,
					Options:     opts,
				})
			}
		}
		return nil
	}
}

func (c *containerAdapter) prepare(ctx context.Context) error {
	if c.image == nil {
		return errors.New("image has not been pulled")
	}

	specOpts := []containerd.SpecOpts{
		containerd.WithImageConfig(ctx, c.image),
		withMounts(ctx, c.spec.Mounts),
	}

	// spec.Process.Args is config.Entrypoint + config.Cmd at this
	// point from WithImageConfig above. If the ContainerSpec
	// specifies a Command then we can completely override. If it
	// does not then all we can do is append our Args and hope
	// they do not conflict.
	// TODO(ijc) Improve this
	if len(c.spec.Command) > 0 {
		args := append(c.spec.Command, c.spec.Args...)
		specOpts = append(specOpts, containerd.WithProcessArgs(args...))
	} else {
		specOpts = append(specOpts, func(s *specs.Spec) error {
			s.Process.Args = append(s.Process.Args, c.spec.Args...)
			return nil
		})
	}

	spec, err := containerd.GenerateSpec(specOpts...)
	if err != nil {
		return err
	}

	// TODO(ijc) Consider an addition to container library which
	// directly attaches stdin to /dev/null.
	if devNull == nil {
		if devNull, err = os.Open(os.DevNull); err != nil {
			return errors.Wrap(err, "opening null device")
		}
	}

	c.container, err = c.client.NewContainer(ctx, c.name,
		containerd.WithSpec(spec),
		containerd.WithNewRootFS(c.name, c.image))
	if err != nil {
		return errors.Wrap(err, "creating container")
	}

	// TODO(ijc) support ControllerLogs interface.
	io := containerd.NewIOWithTerminal(devNull, os.Stdout, os.Stderr, spec.Process.Terminal)

	c.task, err = c.container.NewTask(ctx, io)
	if err != nil {
		return errors.Wrap(err, "creating task")
	}

	return nil
}

func (c *containerAdapter) start(ctx context.Context) error {
	tasks := c.client.TaskService()

	_, err := tasks.Start(ctx, &execution.StartRequest{
		ContainerID: c.name,
	})
	return err
}

func (c *containerAdapter) eventStream(ctx context.Context, id string) (<-chan task.Event, <-chan error, error) {

	var (
		evtch = make(chan task.Event)
		errch = make(chan error)
	)

	return evtch, errch, nil
}

// events issues a call to the events API and returns a channel with all
// events. The stream of events can be shutdown by cancelling the context.
//
// A chan struct{} is returned that will be closed if the event processing
// fails and needs to be restarted.
func (c *containerAdapter) events(ctx context.Context, opts ...grpc.CallOption) (<-chan task.Event, <-chan struct{}, error) {
	l := log.G(ctx).WithFields(logrus.Fields{
		"ID": c.name,
	})

	// TODO(stevvooe): Move this to a single, global event dispatch. For
	// now, we create a connection per container.
	var (
		eventsq = make(chan task.Event)
		closed  = make(chan struct{})
	)

	l.Debugf("waiting on events")

	tasks := c.client.TaskService()
	cl, err := tasks.Events(ctx, &execution.EventsRequest{}, opts...)
	if err != nil {
		l.WithError(err).Errorf("failed to start event stream")
		return nil, nil, err
	}

	go func() {
		defer close(closed)

		for {
			evt, err := cl.Recv()
			if err != nil {
				l.WithError(err).Error("fatal error from events stream")
				return
			}
			if evt.ID != c.name {
				l.Debugf("Event for a different container %s", evt.ID)
				continue
			}

			select {
			case eventsq <- *evt:
			case <-ctx.Done():
				return
			}
		}
	}()

	return eventsq, closed, nil
}

func (c *containerAdapter) inspect(ctx context.Context) (task.Task, error) {
	tasks := c.client.TaskService()
	rsp, err := tasks.Info(ctx, &execution.InfoRequest{ContainerID: c.name})
	if err != nil {
		return task.Task{}, err
	}
	return *rsp.Task, nil
}

func (c *containerAdapter) shutdown(ctx context.Context) (uint32, error) {
	l := log.G(ctx).WithFields(logrus.Fields{
		"ID": c.name,
	})

	if c.deleteResponse == nil {
		var err error
		l.Debug("Deleting")

		tasks := c.client.TaskService()
		rsp, err := tasks.Delete(ctx, &execution.DeleteRequest{ContainerID: c.name})
		if err != nil {
			return 0, err
		}
		l.Debugf("Status=%d", rsp.ExitStatus)
		c.deleteResponse = rsp

		containers := c.client.ContainerService()
		_, err = containers.Delete(ctx, &containersapi.DeleteContainerRequest{
			ID: c.name,
		})
		if err != nil {
			l.WithError(err).Warnf("failed to delete container")
		}
	}

	return c.deleteResponse.ExitStatus, nil
}

func (c *containerAdapter) terminate(ctx context.Context) error {
	l := log.G(ctx).WithFields(logrus.Fields{
		"ID": c.name,
	})
	l.Debug("Terminate")
	return errors.New("terminate not implemented")
}

func (c *containerAdapter) remove(ctx context.Context) error {
	l := log.G(ctx).WithFields(logrus.Fields{
		"ID": c.name,
	})
	l.Debug("Remove")
	return nil
}

func isContainerCreateNameConflict(err error) bool {
	// container ".*" already exists
	splits := strings.SplitN(err.Error(), "\"", 3)
	return splits[0] == "container " && splits[2] == " already exists"
}

func isUnknownContainer(err error) bool {
	return strings.Contains(err.Error(), "container does not exist")
}

// For sort.Sort
type mounts []api.Mount

// Len returns the number of mounts. Used in sorting.
func (m mounts) Len() int {
	return len(m)
}

// Less returns true if the number of parts (a/b/c would be 3 parts) in the
// mount indexed by parameter 1 is less than that of the mount indexed by
// parameter 2. Used in sorting.
func (m mounts) Less(i, j int) bool {
	return m.parts(i) < m.parts(j)
}

// Swap swaps two items in an array of mounts. Used in sorting
func (m mounts) Swap(i, j int) {
	m[i], m[j] = m[j], m[i]
}

// parts returns the number of parts in the destination of a mount. Used in sorting.
func (m mounts) parts(i int) int {
	return strings.Count(filepath.Clean(m[i].Target), string(os.PathSeparator))
}
<commit_msg>containerd: Check that the adapter has been "prepared" at entry points<commit_after>package containerd

import (
	"fmt"
	"os"
	"path/filepath"
	"sort"
	"strings"

	"github.com/Sirupsen/logrus"
	"github.com/containerd/containerd"
	containersapi "github.com/containerd/containerd/api/services/containers"
	"github.com/containerd/containerd/api/services/execution"
	"github.com/containerd/containerd/api/types/task"
	dockermount "github.com/docker/docker/pkg/mount"
	"github.com/docker/swarmkit/agent/exec"
	"github.com/docker/swarmkit/api"
	"github.com/docker/swarmkit/api/naming"
	"github.com/docker/swarmkit/log"
	"github.com/opencontainers/runtime-spec/specs-go"
	"github.com/pkg/errors"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
)

var (
	devNull                    *os.File
	errAdapterNotPrepared      = errors.New("container adapter not prepared")
	mountPropagationReverseMap = map[api.Mount_BindOptions_MountPropagation]string{
		api.MountPropagationPrivate:  "private",
		api.MountPropagationRPrivate: "rprivate",
		api.MountPropagationShared:   "shared",
		api.MountPropagationRShared:  "rshared",
		api.MountPropagationRSlave:   "slave",
		api.MountPropagationSlave:    "rslave",
	}
)

// containerAdapter conducts remote operations for a container. All calls
// are mostly naked calls to the client API, seeded with information from
// containerConfig.
type containerAdapter struct {
	client         *containerd.Client
	spec           *api.ContainerSpec
	secrets        exec.SecretGetter
	name           string
	image          containerd.Image // Pulled image
	container      containerd.Container
	task           containerd.Task
	deleteResponse *execution.DeleteResponse
}

func newContainerAdapter(client *containerd.Client, task *api.Task, secrets exec.SecretGetter) (*containerAdapter, error) {
	spec := task.Spec.GetContainer()
	if spec == nil {
		return nil, exec.ErrRuntimeUnsupported
	}

	return &containerAdapter{
		client:  client,
		spec:    spec,
		secrets: secrets,
		name:    naming.Task(task),
	}, nil
}

func (c *containerAdapter) pullImage(ctx context.Context) error {
	image, err := c.client.Pull(ctx, c.spec.Image, containerd.WithPullUnpack)
	if err != nil {
		return errors.Wrap(err, "pulling container image")
	}
	c.image = image

	return nil
}

func withMounts(ctx context.Context, ms []api.Mount) containerd.SpecOpts {
	sort.Sort(mounts(ms))

	return func(s *specs.Spec) error {
		for _, m := range ms {
			if !filepath.IsAbs(m.Target) {
				return errors.Errorf("mount %s is not absolute", m.Target)
			}

			switch m.Type {
			case api.MountTypeTmpfs:
				opts := []string{"noexec", "nosuid", "nodev", "rprivate"}
				if m.TmpfsOptions != nil {
					if m.TmpfsOptions.SizeBytes <= 0 {
						return errors.New("invalid tmpfs size give")
					}
					opts = append(opts, fmt.Sprintf("size=%d", m.TmpfsOptions.SizeBytes))
					opts = append(opts, fmt.Sprintf("mode=%o", m.TmpfsOptions.Mode))
				}
				if m.ReadOnly {
					opts = append(opts, "ro")
				} else {
					opts = append(opts, "rw")
				}

				opts, err := dockermount.MergeTmpfsOptions(opts)
				if err != nil {
					return err
				}

				s.Mounts = append(s.Mounts, specs.Mount{
					Destination: m.Target,
					Type:        "tmpfs",
					Source:      "tmpfs",
					Options:     opts,
				})

			case api.MountTypeVolume:
				return errors.Errorf("volume mounts not implemented, ignoring %v", m)

			case api.MountTypeBind:
				opts := []string{"rbind"}
				if m.ReadOnly {
					opts = append(opts, "ro")
				} else {
					opts = append(opts, "rw")
				}

				propagation := "rprivate"
				if m.BindOptions != nil {
					if p, ok := mountPropagationReverseMap[m.BindOptions.Propagation]; ok {
						propagation = p
					} else {
						log.G(ctx).Warningf("unknown bind mount propagation, using %q", propagation)
					}
				}
				opts = append(opts, propagation)

				s.Mounts = append(s.Mounts, specs.Mount{
					Destination: m.Target,
					Type:        "bind",
					Source:      m.Source,
					Options:     opts,
				})
			}
		}
		return nil
	}
}

func (c *containerAdapter) isPrepared() bool {
	return c.container != nil && c.task != nil
}

func (c *containerAdapter) prepare(ctx context.Context) error {
	if c.isPrepared() {
		return errors.New("adapter already prepared")
	}
	if c.image == nil {
		return errors.New("image has not been pulled")
	}

	specOpts := []containerd.SpecOpts{
		containerd.WithImageConfig(ctx, c.image),
		withMounts(ctx, c.spec.Mounts),
	}

	// spec.Process.Args is config.Entrypoint + config.Cmd at this
	// point from WithImageConfig above. If the ContainerSpec
	// specifies a Command then we can completely override. If it
	// does not then all we can do is append our Args and hope
	// they do not conflict.
	// TODO(ijc) Improve this
	if len(c.spec.Command) > 0 {
		args := append(c.spec.Command, c.spec.Args...)
		specOpts = append(specOpts, containerd.WithProcessArgs(args...))
	} else {
		specOpts = append(specOpts, func(s *specs.Spec) error {
			s.Process.Args = append(s.Process.Args, c.spec.Args...)
			return nil
		})
	}

	spec, err := containerd.GenerateSpec(specOpts...)
	if err != nil {
		return err
	}

	// TODO(ijc) Consider an addition to container library which
	// directly attaches stdin to /dev/null.
	if devNull == nil {
		if devNull, err = os.Open(os.DevNull); err != nil {
			return errors.Wrap(err, "opening null device")
		}
	}

	c.container, err = c.client.NewContainer(ctx, c.name,
		containerd.WithSpec(spec),
		containerd.WithNewRootFS(c.name, c.image))
	if err != nil {
		return errors.Wrap(err, "creating container")
	}

	// TODO(ijc) support ControllerLogs interface.
	io := containerd.NewIOWithTerminal(devNull, os.Stdout, os.Stderr, spec.Process.Terminal)

	c.task, err = c.container.NewTask(ctx, io)
	if err != nil {
		return errors.Wrap(err, "creating task")
	}

	return nil
}

func (c *containerAdapter) start(ctx context.Context) error {
	if !c.isPrepared() {
		return errAdapterNotPrepared
	}

	tasks := c.client.TaskService()

	_, err := tasks.Start(ctx, &execution.StartRequest{
		ContainerID: c.name,
	})
	return err
}

func (c *containerAdapter) eventStream(ctx context.Context, id string) (<-chan task.Event, <-chan error, error) {

	var (
		evtch = make(chan task.Event)
		errch = make(chan error)
	)

	return evtch, errch, nil
}

// events issues a call to the events API and returns a channel with all
// events. The stream of events can be shutdown by cancelling the context.
//
// A chan struct{} is returned that will be closed if the event processing
// fails and needs to be restarted.
func (c *containerAdapter) events(ctx context.Context, opts ...grpc.CallOption) (<-chan task.Event, <-chan struct{}, error) {
	if !c.isPrepared() {
		return nil, nil, errAdapterNotPrepared
	}

	l := log.G(ctx).WithFields(logrus.Fields{
		"ID": c.name,
	})

	// TODO(stevvooe): Move this to a single, global event dispatch. For
	// now, we create a connection per container.
	var (
		eventsq = make(chan task.Event)
		closed  = make(chan struct{})
	)

	l.Debugf("waiting on events")

	tasks := c.client.TaskService()
	cl, err := tasks.Events(ctx, &execution.EventsRequest{}, opts...)
	if err != nil {
		l.WithError(err).Errorf("failed to start event stream")
		return nil, nil, err
	}

	go func() {
		defer close(closed)

		for {
			evt, err := cl.Recv()
			if err != nil {
				l.WithError(err).Error("fatal error from events stream")
				return
			}
			if evt.ID != c.name {
				l.Debugf("Event for a different container %s", evt.ID)
				continue
			}

			select {
			case eventsq <- *evt:
			case <-ctx.Done():
				return
			}
		}
	}()

	return eventsq, closed, nil
}

func (c *containerAdapter) inspect(ctx context.Context) (task.Task, error) {
	if !c.isPrepared() {
		return task.Task{}, errAdapterNotPrepared
	}

	tasks := c.client.TaskService()
	rsp, err := tasks.Info(ctx, &execution.InfoRequest{ContainerID: c.name})
	if err != nil {
		return task.Task{}, err
	}
	return *rsp.Task, nil
}

func (c *containerAdapter) shutdown(ctx context.Context) (uint32, error) {
	if !c.isPrepared() {
		return 0, errAdapterNotPrepared
	}

	l := log.G(ctx).WithFields(logrus.Fields{
		"ID": c.name,
	})

	if c.deleteResponse == nil {
		var err error
		l.Debug("Deleting")

		tasks := c.client.TaskService()
		rsp, err := tasks.Delete(ctx, &execution.DeleteRequest{ContainerID: c.name})
		if err != nil {
			return 0, err
		}
		l.Debugf("Status=%d", rsp.ExitStatus)
		c.deleteResponse = rsp

		containers := c.client.ContainerService()
		_, err = containers.Delete(ctx, &containersapi.DeleteContainerRequest{
			ID: c.name,
		})
		if err != nil {
			l.WithError(err).Warnf("failed to delete container")
		}
	}

	return c.deleteResponse.ExitStatus, nil
}

func (c *containerAdapter) terminate(ctx context.Context) error {
	if !c.isPrepared() {
		return errAdapterNotPrepared
	}

	l := log.G(ctx).WithFields(logrus.Fields{
		"ID": c.name,
	})
	l.Debug("Terminate")
	return errors.New("terminate not implemented")
}

func (c *containerAdapter) remove(ctx context.Context) error {
	if !c.isPrepared() {
		return errAdapterNotPrepared
	}

	l := log.G(ctx).WithFields(logrus.Fields{
		"ID": c.name,
	})
	l.Debug("Remove")
	return nil
}

func isContainerCreateNameConflict(err error) bool {
	// container ".*" already exists
	splits := strings.SplitN(err.Error(), "\"", 3)
	return splits[0] == "container " && splits[2] == " already exists"
}

func isUnknownContainer(err error) bool {
	return strings.Contains(err.Error(), "container does not exist")
}

// For sort.Sort
type mounts []api.Mount

// Len returns the number of mounts. Used in sorting.
func (m mounts) Len() int {
	return len(m)
}

// Less returns true if the number of parts (a/b/c would be 3 parts) in the
// mount indexed by parameter 1 is less than that of the mount indexed by
// parameter 2. Used in sorting.
func (m mounts) Less(i, j int) bool {
	return m.parts(i) < m.parts(j)
}

// Swap swaps two items in an array of mounts. Used in sorting
func (m mounts) Swap(i, j int) {
	m[i], m[j] = m[j], m[i]
}

// parts returns the number of parts in the destination of a mount. Used in sorting.
func (m mounts) parts(i int) int {
	return strings.Count(filepath.Clean(m[i].Target), string(os.PathSeparator))
}
<|endoftext|>


<commit_before>package tmo

import (
	"fmt"
	"image"
	"math"
	"sort"
)

const (
	// RangeMin is the LDR lower boundary.
	RangeMin = 0
	// RangeMax is the LDR higher boundary.
	RangeMax = 65535 // max uint16
	// LumSize defines the luminance range [0, LumSize]
	LumSize = RangeMax + 3
)

var (
	// LumPixFloor is the default lunMap maping for LinearInversePixelMapping func.
	LumPixFloor []float64
)

func init() {
	LumPixFloor = make([]float64, LumSize)
	for p := 1; p < LumSize; p++ {
		LumPixFloor[p] = float64(p-1) / RangeMax
	}
}

// A ToneMappingOperator is an algorithm that converts hdr.Image to image.Image.
//
//
// HDR is a high dynamic range (HDR) technique used in imaging and photography
// to reproduce a greater dynamic range of luminosity than is possible
// with standard digital imaging or photographic techniques.
// The aim is to present a similar range of luminance to that experienced
// through the human visual system.
// The human eye, through adaptation of the iris and other methods,
// adjusts constantly to adapt to a broad range of luminance present in the environment.
// The brain continuously interprets this information so that a viewer can see in a wide range of light conditions.
type ToneMappingOperator interface {
	// Perform runs the TMO mapping.
	Perform() (image.Image, error)
}

// LinearInversePixelMapping is an linear inverse pixel mapping.
// It is preference to have slightly more solid black 0 and solid white RangeMax in spectrum
// by stretching a mapping.
func LinearInversePixelMapping(lum float64, lumMap []float64, lumSize int) float64 {
	rangeLow, rangeUp := 0, lumSize

	for {
		rangeMid := (rangeLow + rangeUp) / 2

		if rangeMid == rangeLow {
			return float64(rangeLow) // Avoid conversion by the caller.
		}

		if lum < lumMap[rangeMid] {
			rangeUp = rangeMid
		} else {
			rangeLow = rangeMid
		}
	}
}

// Clamp to solid black and solid white.
func Clamp(channel float64) float64 {
	if channel < RangeMin {
		channel = RangeMin
	}
	if channel > RangeMax {
		channel = RangeMax
	}
	return channel
}

// WoB returns 1.0 if b is true, else 0.0
func WoB(b bool) float64 {
	if b {
		return 1
	}
	return 0
}

//--------------------------------------//
// MinMax data                          //
//--------------------------------------//

type minmax struct {
	min float64
	max float64
}

func newMinMax() *minmax {
	return &minmax{
		min: math.Inf(1),
		max: math.Inf(-1),
	}
}

func (mm *minmax) update(v float64) {
	mm.min = math.Min(mm.min, v)
	mm.max = math.Max(mm.max, v)
}

func (mm *minmax) String() string {
	return fmt.Sprintf("min: %f, max: %f", mm.min, mm.max)
}

//-----------------//
// Percentile      //
//-----------------//

type percentiles []float64

func (p percentiles) sort() {
	sort.Sort(p)
}

func (p percentiles) percentile(clipping float64) float64 {
	n := float64(len(p))
	i := int(clipping * n)
	return float64(p[i])
}

func (p percentiles) Len() int {
	return len(p)
}

func (p percentiles) Less(i, j int) bool {
	return p[i] < p[j]
}

func (p percentiles) Swap(i, j int) {
	p[i], p[j] = p[j], p[i]
}
<commit_msg>Fix ToneMappingOperator interface signature<commit_after>package tmo

import (
	"fmt"
	"image"
	"math"
	"sort"
)

const (
	// RangeMin is the LDR lower boundary.
	RangeMin = 0
	// RangeMax is the LDR higher boundary.
	RangeMax = 65535 // max uint16
	// LumSize defines the luminance range [0, LumSize]
	LumSize = RangeMax + 3
)

var (
	// LumPixFloor is the default lunMap maping for LinearInversePixelMapping func.
	LumPixFloor []float64
)

func init() {
	LumPixFloor = make([]float64, LumSize)
	for p := 1; p < LumSize; p++ {
		LumPixFloor[p] = float64(p-1) / RangeMax
	}
}

// A ToneMappingOperator is an algorithm that converts hdr.Image to image.Image.
//
//
// HDR is a high dynamic range (HDR) technique used in imaging and photography
// to reproduce a greater dynamic range of luminosity than is possible
// with standard digital imaging or photographic techniques.
// The aim is to present a similar range of luminance to that experienced
// through the human visual system.
// The human eye, through adaptation of the iris and other methods,
// adjusts constantly to adapt to a broad range of luminance present in the environment.
// The brain continuously interprets this information so that a viewer can see in a wide range of light conditions.
type ToneMappingOperator interface {
	// Perform runs the TMO mapping.
	Perform() image.Image
}

// LinearInversePixelMapping is an linear inverse pixel mapping.
// It is preference to have slightly more solid black 0 and solid white RangeMax in spectrum
// by stretching a mapping.
func LinearInversePixelMapping(lum float64, lumMap []float64, lumSize int) float64 {
	rangeLow, rangeUp := 0, lumSize

	for {
		rangeMid := (rangeLow + rangeUp) / 2

		if rangeMid == rangeLow {
			return float64(rangeLow) // Avoid conversion by the caller.
		}

		if lum < lumMap[rangeMid] {
			rangeUp = rangeMid
		} else {
			rangeLow = rangeMid
		}
	}
}

// Clamp to solid black and solid white.
func Clamp(channel float64) float64 {
	if channel < RangeMin {
		channel = RangeMin
	}
	if channel > RangeMax {
		channel = RangeMax
	}
	return channel
}

// WoB returns 1.0 if b is true, else 0.0
func WoB(b bool) float64 {
	if b {
		return 1
	}
	return 0
}

//--------------------------------------//
// MinMax data                          //
//--------------------------------------//

type minmax struct {
	min float64
	max float64
}

func newMinMax() *minmax {
	return &minmax{
		min: math.Inf(1),
		max: math.Inf(-1),
	}
}

func (mm *minmax) update(v float64) {
	mm.min = math.Min(mm.min, v)
	mm.max = math.Max(mm.max, v)
}

func (mm *minmax) String() string {
	return fmt.Sprintf("min: %f, max: %f", mm.min, mm.max)
}

//-----------------//
// Percentile      //
//-----------------//

type percentiles []float64

func (p percentiles) sort() {
	sort.Sort(p)
}

func (p percentiles) percentile(clipping float64) float64 {
	n := float64(len(p))
	i := int(clipping * n)
	return float64(p[i])
}

func (p percentiles) Len() int {
	return len(p)
}

func (p percentiles) Less(i, j int) bool {
	return p[i] < p[j]
}

func (p percentiles) Swap(i, j int) {
	p[i], p[j] = p[j], p[i]
}
<|endoftext|>


<commit_before>package as3

import (
	"io/ioutil"

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

var configPath = "../../test/configs/"

func readConfigFile(path string) string {
	defer GinkgoRecover()
	data, err := ioutil.ReadFile(path)
	RegisterFailHandler(Fail)
	Expect(err).To(BeNil(), "Configuration files should be located in pkg/test/configs.")
	return string(data)
}

var _ = Describe("Override Simple Config Map", func() {
	It("TestValidateJSONStringAndFetchObject", func() {
		srcCfgMapData := readConfigFile(configPath + "as3config_override_cfgmap.json")
		dstCfgMapData := readConfigFile(configPath + "as3config_simple_cfgmap_resource.json")

		overrideData := ValidateAndOverrideAS3JsonData(srcCfgMapData, dstCfgMapData)

		Expect(overrideData != "").To(Equal(true))
	})

	It("Override Invalid AS3 Override Config Map", func() {
		srcCfgMapData := readConfigFile(configPath + "as3config_without_adc.json")
		dstCfgMapData := readConfigFile(configPath + "as3config_simple_cfgmap_resource.json")

		overrideData := ValidateAndOverrideAS3JsonData(srcCfgMapData, dstCfgMapData)
		Expect(overrideData == "").To(Equal(true))
	})

	It("Override Invalid AS3 Config Map", func() {
		srcCfgMapData := readConfigFile(configPath + "as3config_override_cfgmap.json")
		dstCfgMapData := readConfigFile(configPath + "as3config_invalid_JSON.json")

		overrideData := ValidateAndOverrideAS3JsonData(srcCfgMapData, dstCfgMapData)
		Expect(overrideData == "").To(Equal(true))
	})
})

var _ = Describe("JSON comparision of AS3 declaration", func() {
	It("Verify with two empty declarations", func() {
		ok := DeepEqualJSON("", "")
		Expect(ok).To(BeTrue(), "Failed to compare empty declarations")
	})
	It("Verify with empty and non empty declarations", func() {
		cmcfg1 := readConfigFile(configPath + "as3config_valid_1.json")
		ok := DeepEqualJSON("", as3Declaration(cmcfg1))
		Expect(ok).To(BeFalse())
		ok = DeepEqualJSON(as3Declaration(cmcfg1), "")
		Expect(ok).To(BeFalse())
	})
})

var _ = Describe("Tenant parsing in AS3 declaration", func() {
	It("Get Tenants from a declaration", func() {
		cmcfg1 := readConfigFile(configPath + "as3config_multi_cm_unified.json")
		tenants := getTenants(as3Declaration(cmcfg1), true)
		Expect(tenants).To(Equal([]string{"Tenant1", "Tenant2"}), "Failed to get tenants")
	})
})
<commit_msg>Unit Test Fix<commit_after>package as3

import (
	"io/ioutil"
	"sort"

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

var configPath = "../../test/configs/"

func readConfigFile(path string) string {
	defer GinkgoRecover()
	data, err := ioutil.ReadFile(path)
	RegisterFailHandler(Fail)
	Expect(err).To(BeNil(), "Configuration files should be located in pkg/test/configs.")
	return string(data)
}

var _ = Describe("Override Simple Config Map", func() {
	It("TestValidateJSONStringAndFetchObject", func() {
		srcCfgMapData := readConfigFile(configPath + "as3config_override_cfgmap.json")
		dstCfgMapData := readConfigFile(configPath + "as3config_simple_cfgmap_resource.json")

		overrideData := ValidateAndOverrideAS3JsonData(srcCfgMapData, dstCfgMapData)

		Expect(overrideData != "").To(Equal(true))
	})

	It("Override Invalid AS3 Override Config Map", func() {
		srcCfgMapData := readConfigFile(configPath + "as3config_without_adc.json")
		dstCfgMapData := readConfigFile(configPath + "as3config_simple_cfgmap_resource.json")

		overrideData := ValidateAndOverrideAS3JsonData(srcCfgMapData, dstCfgMapData)
		Expect(overrideData == "").To(Equal(true))
	})

	It("Override Invalid AS3 Config Map", func() {
		srcCfgMapData := readConfigFile(configPath + "as3config_override_cfgmap.json")
		dstCfgMapData := readConfigFile(configPath + "as3config_invalid_JSON.json")

		overrideData := ValidateAndOverrideAS3JsonData(srcCfgMapData, dstCfgMapData)
		Expect(overrideData == "").To(Equal(true))
	})
})

var _ = Describe("JSON comparision of AS3 declaration", func() {
	It("Verify with two empty declarations", func() {
		ok := DeepEqualJSON("", "")
		Expect(ok).To(BeTrue(), "Failed to compare empty declarations")
	})
	It("Verify with empty and non empty declarations", func() {
		cmcfg1 := readConfigFile(configPath + "as3config_valid_1.json")
		ok := DeepEqualJSON("", as3Declaration(cmcfg1))
		Expect(ok).To(BeFalse())
		ok = DeepEqualJSON(as3Declaration(cmcfg1), "")
		Expect(ok).To(BeFalse())
	})
})

var _ = Describe("Tenant parsing in AS3 declaration", func() {
	It("Get Tenants from a declaration", func() {
		cmcfg1 := readConfigFile(configPath + "as3config_multi_cm_unified.json")
		tenants := getTenants(as3Declaration(cmcfg1), true)
		sort.Strings(tenants)
		Expect(tenants).To(Equal([]string{"Tenant1", "Tenant2"}), "Failed to get tenants")
	})
})
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package fuzzer

import (
	"fmt"
	"math/rand"
	"sort"
	"strconv"
	"strings"

	fuzz "github.com/google/gofuzz"

	apitesting "k8s.io/apimachinery/pkg/api/apitesting"
	"k8s.io/apimachinery/pkg/api/apitesting/fuzzer"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
	"k8s.io/apimachinery/pkg/runtime"
	runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
	"k8s.io/apimachinery/pkg/types"
)

func genericFuzzerFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
	return []interface{}{
		func(q *resource.Quantity, c fuzz.Continue) {
			*q = *resource.NewQuantity(c.Int63n(1000), resource.DecimalExponent)
		},
		func(j *int, c fuzz.Continue) {
			*j = int(c.Int31())
		},
		func(j **int, c fuzz.Continue) {
			if c.RandBool() {
				i := int(c.Int31())
				*j = &i
			} else {
				*j = nil
			}
		},
		func(j *runtime.TypeMeta, c fuzz.Continue) {
			// We have to customize the randomization of TypeMetas because their
			// APIVersion and Kind must remain blank in memory.
			j.APIVersion = ""
			j.Kind = ""
		},
		func(j *runtime.Object, c fuzz.Continue) {
			// TODO: uncomment when round trip starts from a versioned object
			if true { //c.RandBool() {
				*j = &runtime.Unknown{
					// We do not set TypeMeta here because it is not carried through a round trip
					Raw:         []byte(`{"apiVersion":"unknown.group/unknown","kind":"Something","someKey":"someValue"}`),
					ContentType: runtime.ContentTypeJSON,
				}
			} else {
				types := []runtime.Object{&metav1.Status{}, &metav1.APIGroup{}}
				t := types[c.Rand.Intn(len(types))]
				c.Fuzz(t)
				*j = t
			}
		},
		func(r *runtime.RawExtension, c fuzz.Continue) {
			// Pick an arbitrary type and fuzz it
			types := []runtime.Object{&metav1.Status{}, &metav1.APIGroup{}}
			obj := types[c.Rand.Intn(len(types))]
			c.Fuzz(obj)

			// Find a codec for converting the object to raw bytes.  This is necessary for the
			// api version and kind to be correctly set be serialization.
			var codec = apitesting.TestCodec(codecs, metav1.SchemeGroupVersion)

			// Convert the object to raw bytes
			bytes, err := runtime.Encode(codec, obj)
			if err != nil {
				panic(fmt.Sprintf("Failed to encode object: %v", err))
			}

			// strip trailing newlines which do not survive roundtrips
			for len(bytes) >= 1 && bytes[len(bytes)-1] == 10 {
				bytes = bytes[:len(bytes)-1]
			}

			// Set the bytes field on the RawExtension
			r.Raw = bytes
		},
	}
}

// taken from gofuzz internals for RandString
type charRange struct {
	first, last rune
}

func (c *charRange) choose(r *rand.Rand) rune {
	count := int64(c.last - c.first + 1)
	ch := c.first + rune(r.Int63n(count))

	return ch
}

// randomLabelPart produces a valid random label value or name-part
// of a label key.
func randomLabelPart(c fuzz.Continue, canBeEmpty bool) string {
	validStartEnd := []charRange{{'0', '9'}, {'a', 'z'}, {'A', 'Z'}}
	validMiddle := []charRange{{'0', '9'}, {'a', 'z'}, {'A', 'Z'},
		{'.', '.'}, {'-', '-'}, {'_', '_'}}

	partLen := c.Rand.Intn(64) // len is [0, 63]
	if !canBeEmpty {
		partLen = c.Rand.Intn(63) + 1 // len is [1, 63]
	}

	runes := make([]rune, partLen)
	if partLen == 0 {
		return string(runes)
	}

	runes[0] = validStartEnd[c.Rand.Intn(len(validStartEnd))].choose(c.Rand)
	for i := range runes[1:] {
		runes[i+1] = validMiddle[c.Rand.Intn(len(validMiddle))].choose(c.Rand)
	}
	runes[len(runes)-1] = validStartEnd[c.Rand.Intn(len(validStartEnd))].choose(c.Rand)

	return string(runes)
}

func randomDNSLabel(c fuzz.Continue) string {
	validStartEnd := []charRange{{'0', '9'}, {'a', 'z'}}
	validMiddle := []charRange{{'0', '9'}, {'a', 'z'}, {'-', '-'}}

	partLen := c.Rand.Intn(63) + 1 // len is [1, 63]
	runes := make([]rune, partLen)

	runes[0] = validStartEnd[c.Rand.Intn(len(validStartEnd))].choose(c.Rand)
	for i := range runes[1:] {
		runes[i+1] = validMiddle[c.Rand.Intn(len(validMiddle))].choose(c.Rand)
	}
	runes[len(runes)-1] = validStartEnd[c.Rand.Intn(len(validStartEnd))].choose(c.Rand)

	return string(runes)
}

func randomLabelKey(c fuzz.Continue) string {
	namePart := randomLabelPart(c, false)
	prefixPart := ""

	usePrefix := c.RandBool()
	if usePrefix {
		// we can fit, with dots, at most 3 labels in the 253 allotted characters
		prefixPartsLen := c.Rand.Intn(2) + 1
		prefixParts := make([]string, prefixPartsLen)
		for i := range prefixParts {
			prefixParts[i] = randomDNSLabel(c)
		}
		prefixPart = strings.Join(prefixParts, ".") + "/"
	}

	return prefixPart + namePart
}

func v1FuzzerFuncs(codecs runtimeserializer.CodecFactory) []interface{} {

	return []interface{}{
		func(j *metav1.TypeMeta, c fuzz.Continue) {
			// We have to customize the randomization of TypeMetas because their
			// APIVersion and Kind must remain blank in memory.
			j.APIVersion = ""
			j.Kind = ""
		},
		func(j *metav1.ObjectMeta, c fuzz.Continue) {
			c.FuzzNoCustom(j)

			j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10)
			j.UID = types.UID(c.RandString())

			var sec, nsec int64
			c.Fuzz(&sec)
			c.Fuzz(&nsec)
			j.CreationTimestamp = metav1.Unix(sec, nsec).Rfc3339Copy()

			if j.DeletionTimestamp != nil {
				c.Fuzz(&sec)
				c.Fuzz(&nsec)
				t := metav1.Unix(sec, nsec).Rfc3339Copy()
				j.DeletionTimestamp = &t
			}

			if len(j.Labels) == 0 {
				j.Labels = nil
			} else {
				delete(j.Labels, "")
			}
			if len(j.Annotations) == 0 {
				j.Annotations = nil
			} else {
				delete(j.Annotations, "")
			}
			if len(j.OwnerReferences) == 0 {
				j.OwnerReferences = nil
			}
			if len(j.Finalizers) == 0 {
				j.Finalizers = nil
			}
		},
		func(j *metav1.Initializers, c fuzz.Continue) {
			j = nil
		},
		func(j *metav1.ListMeta, c fuzz.Continue) {
			j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10)
			j.SelfLink = c.RandString()
		},
		func(j *metav1.LabelSelector, c fuzz.Continue) {
			c.FuzzNoCustom(j)
			// we can't have an entirely empty selector, so force
			// use of MatchExpression if necessary
			if len(j.MatchLabels) == 0 && len(j.MatchExpressions) == 0 {
				j.MatchExpressions = make([]metav1.LabelSelectorRequirement, c.Rand.Intn(2)+1)
			}

			if j.MatchLabels != nil {
				fuzzedMatchLabels := make(map[string]string, len(j.MatchLabels))
				for i := 0; i < len(j.MatchLabels); i++ {
					fuzzedMatchLabels[randomLabelKey(c)] = randomLabelPart(c, true)
				}
				j.MatchLabels = fuzzedMatchLabels
			}

			validOperators := []metav1.LabelSelectorOperator{
				metav1.LabelSelectorOpIn,
				metav1.LabelSelectorOpNotIn,
				metav1.LabelSelectorOpExists,
				metav1.LabelSelectorOpDoesNotExist,
			}

			if j.MatchExpressions != nil {
				// NB: the label selector parser code sorts match expressions by key, and sorts the values,
				// so we need to make sure ours are sorted as well here to preserve round-trip comparison.
				// In practice, not sorting doesn't hurt anything...

				for i := range j.MatchExpressions {
					req := metav1.LabelSelectorRequirement{}
					c.Fuzz(&req)
					req.Key = randomLabelKey(c)
					req.Operator = validOperators[c.Rand.Intn(len(validOperators))]
					if req.Operator == metav1.LabelSelectorOpIn || req.Operator == metav1.LabelSelectorOpNotIn {
						if len(req.Values) == 0 {
							// we must have some values here, so randomly choose a short length
							req.Values = make([]string, c.Rand.Intn(2)+1)
						}
						for i := range req.Values {
							req.Values[i] = randomLabelPart(c, true)
						}
						sort.Strings(req.Values)
					} else {
						req.Values = nil
					}
					j.MatchExpressions[i] = req
				}

				sort.Slice(j.MatchExpressions, func(a, b int) bool { return j.MatchExpressions[a].Key < j.MatchExpressions[b].Key })
			}
		},
		func(j *metav1.ManagedFieldsEntry, c fuzz.Continue) {
			c.FuzzNoCustom(j)
			if j.Fields != nil && len(j.Fields.Map) == 0 {
				j.Fields = nil
			}
		},
	}
}

func v1beta1FuzzerFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
	return []interface{}{
		func(r *metav1beta1.TableOptions, c fuzz.Continue) {
			c.FuzzNoCustom(r)
			// NoHeaders is not serialized to the wire but is allowed within the versioned
			// type because we don't use meta internal types in the client and API server.
			r.NoHeaders = false
		},
		func(r *metav1beta1.TableRow, c fuzz.Continue) {
			c.Fuzz(&r.Object)
			c.Fuzz(&r.Conditions)
			if len(r.Conditions) == 0 {
				r.Conditions = nil
			}
			n := c.Intn(10)
			if n > 0 {
				r.Cells = make([]interface{}, n)
			}
			for i := range r.Cells {
				t := c.Intn(6)
				switch t {
				case 0:
					r.Cells[i] = c.RandString()
				case 1:
					r.Cells[i] = c.Int63()
				case 2:
					r.Cells[i] = c.RandBool()
				case 3:
					x := map[string]interface{}{}
					for j := c.Intn(10) + 1; j >= 0; j-- {
						x[c.RandString()] = c.RandString()
					}
					r.Cells[i] = x
				case 4:
					x := make([]interface{}, c.Intn(10))
					for i := range x {
						x[i] = c.Int63()
					}
					r.Cells[i] = x
				default:
					r.Cells[i] = nil
				}
			}
		},
	}
}

var Funcs = fuzzer.MergeFuzzerFuncs(
	genericFuzzerFuncs,
	v1FuzzerFuncs,
	v1beta1FuzzerFuncs,
)
<commit_msg>Don't fuzz deprecated initializers field<commit_after>/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package fuzzer

import (
	"fmt"
	"math/rand"
	"sort"
	"strconv"
	"strings"

	fuzz "github.com/google/gofuzz"

	apitesting "k8s.io/apimachinery/pkg/api/apitesting"
	"k8s.io/apimachinery/pkg/api/apitesting/fuzzer"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
	"k8s.io/apimachinery/pkg/runtime"
	runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
	"k8s.io/apimachinery/pkg/types"
)

func genericFuzzerFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
	return []interface{}{
		func(q *resource.Quantity, c fuzz.Continue) {
			*q = *resource.NewQuantity(c.Int63n(1000), resource.DecimalExponent)
		},
		func(j *int, c fuzz.Continue) {
			*j = int(c.Int31())
		},
		func(j **int, c fuzz.Continue) {
			if c.RandBool() {
				i := int(c.Int31())
				*j = &i
			} else {
				*j = nil
			}
		},
		func(j *runtime.TypeMeta, c fuzz.Continue) {
			// We have to customize the randomization of TypeMetas because their
			// APIVersion and Kind must remain blank in memory.
			j.APIVersion = ""
			j.Kind = ""
		},
		func(j *runtime.Object, c fuzz.Continue) {
			// TODO: uncomment when round trip starts from a versioned object
			if true { //c.RandBool() {
				*j = &runtime.Unknown{
					// We do not set TypeMeta here because it is not carried through a round trip
					Raw:         []byte(`{"apiVersion":"unknown.group/unknown","kind":"Something","someKey":"someValue"}`),
					ContentType: runtime.ContentTypeJSON,
				}
			} else {
				types := []runtime.Object{&metav1.Status{}, &metav1.APIGroup{}}
				t := types[c.Rand.Intn(len(types))]
				c.Fuzz(t)
				*j = t
			}
		},
		func(r *runtime.RawExtension, c fuzz.Continue) {
			// Pick an arbitrary type and fuzz it
			types := []runtime.Object{&metav1.Status{}, &metav1.APIGroup{}}
			obj := types[c.Rand.Intn(len(types))]
			c.Fuzz(obj)

			// Find a codec for converting the object to raw bytes.  This is necessary for the
			// api version and kind to be correctly set be serialization.
			var codec = apitesting.TestCodec(codecs, metav1.SchemeGroupVersion)

			// Convert the object to raw bytes
			bytes, err := runtime.Encode(codec, obj)
			if err != nil {
				panic(fmt.Sprintf("Failed to encode object: %v", err))
			}

			// strip trailing newlines which do not survive roundtrips
			for len(bytes) >= 1 && bytes[len(bytes)-1] == 10 {
				bytes = bytes[:len(bytes)-1]
			}

			// Set the bytes field on the RawExtension
			r.Raw = bytes
		},
	}
}

// taken from gofuzz internals for RandString
type charRange struct {
	first, last rune
}

func (c *charRange) choose(r *rand.Rand) rune {
	count := int64(c.last - c.first + 1)
	ch := c.first + rune(r.Int63n(count))

	return ch
}

// randomLabelPart produces a valid random label value or name-part
// of a label key.
func randomLabelPart(c fuzz.Continue, canBeEmpty bool) string {
	validStartEnd := []charRange{{'0', '9'}, {'a', 'z'}, {'A', 'Z'}}
	validMiddle := []charRange{{'0', '9'}, {'a', 'z'}, {'A', 'Z'},
		{'.', '.'}, {'-', '-'}, {'_', '_'}}

	partLen := c.Rand.Intn(64) // len is [0, 63]
	if !canBeEmpty {
		partLen = c.Rand.Intn(63) + 1 // len is [1, 63]
	}

	runes := make([]rune, partLen)
	if partLen == 0 {
		return string(runes)
	}

	runes[0] = validStartEnd[c.Rand.Intn(len(validStartEnd))].choose(c.Rand)
	for i := range runes[1:] {
		runes[i+1] = validMiddle[c.Rand.Intn(len(validMiddle))].choose(c.Rand)
	}
	runes[len(runes)-1] = validStartEnd[c.Rand.Intn(len(validStartEnd))].choose(c.Rand)

	return string(runes)
}

func randomDNSLabel(c fuzz.Continue) string {
	validStartEnd := []charRange{{'0', '9'}, {'a', 'z'}}
	validMiddle := []charRange{{'0', '9'}, {'a', 'z'}, {'-', '-'}}

	partLen := c.Rand.Intn(63) + 1 // len is [1, 63]
	runes := make([]rune, partLen)

	runes[0] = validStartEnd[c.Rand.Intn(len(validStartEnd))].choose(c.Rand)
	for i := range runes[1:] {
		runes[i+1] = validMiddle[c.Rand.Intn(len(validMiddle))].choose(c.Rand)
	}
	runes[len(runes)-1] = validStartEnd[c.Rand.Intn(len(validStartEnd))].choose(c.Rand)

	return string(runes)
}

func randomLabelKey(c fuzz.Continue) string {
	namePart := randomLabelPart(c, false)
	prefixPart := ""

	usePrefix := c.RandBool()
	if usePrefix {
		// we can fit, with dots, at most 3 labels in the 253 allotted characters
		prefixPartsLen := c.Rand.Intn(2) + 1
		prefixParts := make([]string, prefixPartsLen)
		for i := range prefixParts {
			prefixParts[i] = randomDNSLabel(c)
		}
		prefixPart = strings.Join(prefixParts, ".") + "/"
	}

	return prefixPart + namePart
}

func v1FuzzerFuncs(codecs runtimeserializer.CodecFactory) []interface{} {

	return []interface{}{
		func(j *metav1.TypeMeta, c fuzz.Continue) {
			// We have to customize the randomization of TypeMetas because their
			// APIVersion and Kind must remain blank in memory.
			j.APIVersion = ""
			j.Kind = ""
		},
		func(j *metav1.ObjectMeta, c fuzz.Continue) {
			c.FuzzNoCustom(j)

			j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10)
			j.UID = types.UID(c.RandString())

			var sec, nsec int64
			c.Fuzz(&sec)
			c.Fuzz(&nsec)
			j.CreationTimestamp = metav1.Unix(sec, nsec).Rfc3339Copy()

			if j.DeletionTimestamp != nil {
				c.Fuzz(&sec)
				c.Fuzz(&nsec)
				t := metav1.Unix(sec, nsec).Rfc3339Copy()
				j.DeletionTimestamp = &t
			}

			if len(j.Labels) == 0 {
				j.Labels = nil
			} else {
				delete(j.Labels, "")
			}
			if len(j.Annotations) == 0 {
				j.Annotations = nil
			} else {
				delete(j.Annotations, "")
			}
			if len(j.OwnerReferences) == 0 {
				j.OwnerReferences = nil
			}
			if len(j.Finalizers) == 0 {
				j.Finalizers = nil
			}
			j.Initializers = nil
		},
		func(j *metav1.Initializers, c fuzz.Continue) {
			j = nil
		},
		func(j *metav1.ListMeta, c fuzz.Continue) {
			j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10)
			j.SelfLink = c.RandString()
		},
		func(j *metav1.LabelSelector, c fuzz.Continue) {
			c.FuzzNoCustom(j)
			// we can't have an entirely empty selector, so force
			// use of MatchExpression if necessary
			if len(j.MatchLabels) == 0 && len(j.MatchExpressions) == 0 {
				j.MatchExpressions = make([]metav1.LabelSelectorRequirement, c.Rand.Intn(2)+1)
			}

			if j.MatchLabels != nil {
				fuzzedMatchLabels := make(map[string]string, len(j.MatchLabels))
				for i := 0; i < len(j.MatchLabels); i++ {
					fuzzedMatchLabels[randomLabelKey(c)] = randomLabelPart(c, true)
				}
				j.MatchLabels = fuzzedMatchLabels
			}

			validOperators := []metav1.LabelSelectorOperator{
				metav1.LabelSelectorOpIn,
				metav1.LabelSelectorOpNotIn,
				metav1.LabelSelectorOpExists,
				metav1.LabelSelectorOpDoesNotExist,
			}

			if j.MatchExpressions != nil {
				// NB: the label selector parser code sorts match expressions by key, and sorts the values,
				// so we need to make sure ours are sorted as well here to preserve round-trip comparison.
				// In practice, not sorting doesn't hurt anything...

				for i := range j.MatchExpressions {
					req := metav1.LabelSelectorRequirement{}
					c.Fuzz(&req)
					req.Key = randomLabelKey(c)
					req.Operator = validOperators[c.Rand.Intn(len(validOperators))]
					if req.Operator == metav1.LabelSelectorOpIn || req.Operator == metav1.LabelSelectorOpNotIn {
						if len(req.Values) == 0 {
							// we must have some values here, so randomly choose a short length
							req.Values = make([]string, c.Rand.Intn(2)+1)
						}
						for i := range req.Values {
							req.Values[i] = randomLabelPart(c, true)
						}
						sort.Strings(req.Values)
					} else {
						req.Values = nil
					}
					j.MatchExpressions[i] = req
				}

				sort.Slice(j.MatchExpressions, func(a, b int) bool { return j.MatchExpressions[a].Key < j.MatchExpressions[b].Key })
			}
		},
		func(j *metav1.ManagedFieldsEntry, c fuzz.Continue) {
			c.FuzzNoCustom(j)
			if j.Fields != nil && len(j.Fields.Map) == 0 {
				j.Fields = nil
			}
		},
	}
}

func v1beta1FuzzerFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
	return []interface{}{
		func(r *metav1beta1.TableOptions, c fuzz.Continue) {
			c.FuzzNoCustom(r)
			// NoHeaders is not serialized to the wire but is allowed within the versioned
			// type because we don't use meta internal types in the client and API server.
			r.NoHeaders = false
		},
		func(r *metav1beta1.TableRow, c fuzz.Continue) {
			c.Fuzz(&r.Object)
			c.Fuzz(&r.Conditions)
			if len(r.Conditions) == 0 {
				r.Conditions = nil
			}
			n := c.Intn(10)
			if n > 0 {
				r.Cells = make([]interface{}, n)
			}
			for i := range r.Cells {
				t := c.Intn(6)
				switch t {
				case 0:
					r.Cells[i] = c.RandString()
				case 1:
					r.Cells[i] = c.Int63()
				case 2:
					r.Cells[i] = c.RandBool()
				case 3:
					x := map[string]interface{}{}
					for j := c.Intn(10) + 1; j >= 0; j-- {
						x[c.RandString()] = c.RandString()
					}
					r.Cells[i] = x
				case 4:
					x := make([]interface{}, c.Intn(10))
					for i := range x {
						x[i] = c.Int63()
					}
					r.Cells[i] = x
				default:
					r.Cells[i] = nil
				}
			}
		},
	}
}

var Funcs = fuzzer.MergeFuzzerFuncs(
	genericFuzzerFuncs,
	v1FuzzerFuncs,
	v1beta1FuzzerFuncs,
)
<|endoftext|>


<commit_before>package todotxt

import (
        "time"
        "os"
        "bufio"
        "strings"
        "regexp"
)

type Task struct {
        todo string
        priority byte
        create_date time.Time
        contexts []string
        projects []string
        raw_todo string
}

type TaskList []Task

func LoadTaskList (filename string) (TaskList) {

        var f, err = os.Open(filename)

        if err != nil {
                panic(err)
        }

        defer f.Close()

        var tasklist = TaskList{}

        scanner := bufio.NewScanner(f)

        for scanner.Scan() {
                var task = Task{}
                text := scanner.Text()
                task.raw_todo = text

                splits := strings.Split(text, " ")

                head := splits[0]

                if (len(head) == 3) &&
                   (head[0] == '(') &&
                   (head[2] == ')') {
                        task.priority = head[1]
                        splits = splits[1:]
                }

                date_regexp := "([\\d]{4})-([\\d]{2})-([\\d]{2})"
                if match, _ := regexp.MatchString(date_regexp, splits[0]); match {
                        if date, e := time.Parse("2006-01-02", splits[0]); e != nil {
                                panic(e)
                        } else {
                                task.create_date = date
                        }

                        task.todo = strings.Join(splits[1:], " ")
                } else {
                        task.todo = strings.Join(splits[0:], " ")
                }

                context_regexp, _ := regexp.Compile("@[[:word:]]+")
                contexts := context_regexp.FindAllStringSubmatch(text, -1)
                if len(contexts) != 0 {
                        task.contexts = contexts[0]
                }

                project_regexp, _ := regexp.Compile("\\+[[:word:]]+")
                projects := project_regexp.FindAllStringSubmatch(text, -1)
                if len(projects) != 0 {
                        task.projects = projects[0]
                }

                tasklist = append(tasklist, task)
        }

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

        return tasklist
}

func (tasks TaskList) Len() int {
        return len(tasks)
}

func (tasks TaskList) Swap(i, j int) {
        tasks[i], tasks[j] = tasks[j], tasks[i]
}

func (tasks TaskList) Less(i, j int) bool {
        return tasks[i].Priority() < tasks[j].Priority()
}

func (task Task) Text() string {
        return task.todo
}

func (task Task) RawText() string {
        return task.raw_todo
}

func (task Task) Priority() byte {
        return task.priority
}

func (task Task) Contexts() []string {
        return task.contexts
}

func (task Task) Projects() []string {
        return task.projects
}

func (task Task) CreateDate() time.Time {
        return task.create_date
}
<commit_msg>some priority stuff<commit_after>package todotxt

import (
        "fmt"
        "time"
        "os"
        "bufio"
        "strings"
        "regexp"
        "sort"
)

type Task struct {
        todo string
        priority byte
        create_date time.Time
        contexts []string
        projects []string
        raw_todo string
}

type TaskList []Task

func LoadTaskList (filename string) (TaskList) {

        var f, err = os.Open(filename)

        if err != nil {
                panic(err)
        }

        defer f.Close()

        var tasklist = TaskList{}

        scanner := bufio.NewScanner(f)

        for scanner.Scan() {
                var task = Task{}
                text := scanner.Text()
                task.raw_todo = text

                splits := strings.Split(text, " ")

                head := splits[0]

                if (len(head) == 3) &&
                   (head[0] == '(') &&
                   (head[2] == ')') {
                        task.priority = head[1]
                        splits = splits[1:]
                }

                date_regexp := "([\\d]{4})-([\\d]{2})-([\\d]{2})"
                if match, _ := regexp.MatchString(date_regexp, splits[0]); match {
                        if date, e := time.Parse("2006-01-02", splits[0]); e != nil {
                                panic(e)
                        } else {
                                task.create_date = date
                        }

                        task.todo = strings.Join(splits[1:], " ")
                } else {
                        task.todo = strings.Join(splits[0:], " ")
                }

                context_regexp, _ := regexp.Compile("@[[:word:]]+")
                contexts := context_regexp.FindAllStringSubmatch(text, -1)
                if len(contexts) != 0 {
                        task.contexts = contexts[0]
                }

                project_regexp, _ := regexp.Compile("\\+[[:word:]]+")
                projects := project_regexp.FindAllStringSubmatch(text, -1)
                if len(projects) != 0 {
                        task.projects = projects[0]
                }

                tasklist = append(tasklist, task)
        }

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

        return tasklist
}

func (tasks TaskList) Len() int {
        return len(tasks)
}

type ByPriority TaskList

func (tasks ByPriority) Len() int {
        return len(tasks)
}

func (tasks ByPriority) Swap(i, j int) {
        tasks[i], tasks[j] = tasks[j], tasks[i]
}

func (tasks ByPriority) Less(i, j int) bool {
        return tasks[i].Priority() > tasks[j].Priority()
}

func (tasks TaskList) Sort() {
        sort.Sort(ByPriority(tasks))
}

func (task Task) Text() string {
        return task.todo
}

func (task Task) RawText() string {
        return task.raw_todo
}

func (task Task) Priority() byte {
        if task.priority < 65 || task.priority > 90 {
                return 94 // you know, ^
        } else {
                return task.priority
        }
}

func (task Task) Contexts() []string {
        return task.contexts
}

func (task Task) Projects() []string {
        return task.projects
}

func (task Task) CreateDate() time.Time {
        return task.create_date
}
<|endoftext|>


<commit_before>// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of Hubble

//go:build !privileged_tests
// +build !privileged_tests

package filters

import (
	"context"
	"testing"

	flowpb "github.com/cilium/cilium/api/v1/flow"
	v1 "github.com/cilium/cilium/pkg/hubble/api/v1"
)

func TestFlowTCPFilter(t *testing.T) {
	var argsfilter []*flowpb.FlowFilter
	var argsevent *v1.Event
	testflags := []struct {
		name   string
		argsf  []*flowpb.TCPFlags
		argsev *flowpb.TCPFlags
		want   bool
	}{
		{
			name:   "filterSYNACK___eventSYNACK",
			argsf:  []*flowpb.TCPFlags{{SYN: true, ACK: true}},
			argsev: &flowpb.TCPFlags{SYN: true, ACK: true},
			want:   true,
		},
		{
			name:   "filterSYNACK___eventSYN",
			argsf:  []*flowpb.TCPFlags{{SYN: true, ACK: true}},
			argsev: &flowpb.TCPFlags{SYN: true},
			want:   false,
		},
		{
			name:   "filterSYN_OR_filterACK___eventSYN",
			argsf:  []*flowpb.TCPFlags{{SYN: true}, {ACK: true}},
			argsev: &flowpb.TCPFlags{SYN: true},
			want:   true,
		},
		{
			name:   "filterSYN_OR_filterACK___eventSYNACK",
			argsf:  []*flowpb.TCPFlags{{SYN: true}, {ACK: true}},
			argsev: &flowpb.TCPFlags{SYN: true, ACK: true},
			want:   true,
		},
		{
			name:   "filterSYN_OR_filterACK___eventPSHACK",
			argsf:  []*flowpb.TCPFlags{{SYN: true}, {ACK: true}},
			argsev: &flowpb.TCPFlags{PSH: true, ACK: true},
			want:   true,
		},
		{
			name:   "filterSYN___eventSYN",
			argsf:  []*flowpb.TCPFlags{{SYN: true}},
			argsev: &flowpb.TCPFlags{SYN: true},
			want:   true,
		},
		{
			name:   "filterSYN___eventSYNACK",
			argsf:  []*flowpb.TCPFlags{{SYN: true}},
			argsev: &flowpb.TCPFlags{SYN: true, ACK: true},
			want:   true,
		},
		{
			name:   "filterFIN___eventRST",
			argsf:  []*flowpb.TCPFlags{{FIN: true}},
			argsev: &flowpb.TCPFlags{RST: true},
			want:   false,
		},
		{
			name:   "filterSYN___eventPSH",
			argsf:  []*flowpb.TCPFlags{{SYN: true}},
			argsev: &flowpb.TCPFlags{PSH: true},
			want:   false,
		},
		{
			name:   "filterURG___eventPSH",
			argsf:  []*flowpb.TCPFlags{{URG: true}},
			argsev: &flowpb.TCPFlags{PSH: true},
			want:   false,
		},
		{
			name:   "filterRST___eventRST",
			argsf:  []*flowpb.TCPFlags{{RST: true}},
			argsev: &flowpb.TCPFlags{RST: true},
			want:   true,
		},
		{
			name:   "filterFIN___eventFIN",
			argsf:  []*flowpb.TCPFlags{{FIN: true}},
			argsev: &flowpb.TCPFlags{FIN: true},
			want:   true,
		},
		{
			name:   "filterPSH___eventPSHACK",
			argsf:  []*flowpb.TCPFlags{{PSH: true}},
			argsev: &flowpb.TCPFlags{PSH: true, ACK: true},
			want:   true,
		},
	}

	for _, tt := range testflags {
		argsfilter = []*flowpb.FlowFilter{{TcpFlags: tt.argsf}}
		argsevent = &v1.Event{Event: &flowpb.Flow{
			L4: &flowpb.Layer4{Protocol: &flowpb.Layer4_TCP{TCP: &flowpb.TCP{Flags: tt.argsev}}}}}
		t.Run(tt.name, func(t *testing.T) {
			fl, err := BuildFilterList(context.Background(), argsfilter, []OnBuildFilter{&TCPFilter{}})
			if err != nil {
				return
			}
			if got := fl.MatchOne(argsevent); got != tt.want {
				t.Errorf("%s: got %v, want %v", tt.name, got, tt.want)
			}
		})
	}
}
<commit_msg>hubble/filters: add a unit test for TCP flows without flags<commit_after>// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of Hubble

//go:build !privileged_tests
// +build !privileged_tests

package filters

import (
	"context"
	"testing"

	flowpb "github.com/cilium/cilium/api/v1/flow"
	v1 "github.com/cilium/cilium/pkg/hubble/api/v1"
)

func TestFlowTCPFilter(t *testing.T) {
	var argsfilter []*flowpb.FlowFilter
	var argsevent *v1.Event
	testflags := []struct {
		name   string
		argsf  []*flowpb.TCPFlags
		argsev *flowpb.TCPFlags
		want   bool
	}{
		{
			name:   "filterSYNACK___eventSYNACK",
			argsf:  []*flowpb.TCPFlags{{SYN: true, ACK: true}},
			argsev: &flowpb.TCPFlags{SYN: true, ACK: true},
			want:   true,
		},
		{
			name:   "filterSYNACK___eventSYN",
			argsf:  []*flowpb.TCPFlags{{SYN: true, ACK: true}},
			argsev: &flowpb.TCPFlags{SYN: true},
			want:   false,
		},
		{
			name:   "filterSYN_OR_filterACK___eventSYN",
			argsf:  []*flowpb.TCPFlags{{SYN: true}, {ACK: true}},
			argsev: &flowpb.TCPFlags{SYN: true},
			want:   true,
		},
		{
			name:   "filterSYN_OR_filterACK___eventSYNACK",
			argsf:  []*flowpb.TCPFlags{{SYN: true}, {ACK: true}},
			argsev: &flowpb.TCPFlags{SYN: true, ACK: true},
			want:   true,
		},
		{
			name:   "filterSYN_OR_filterACK___eventPSHACK",
			argsf:  []*flowpb.TCPFlags{{SYN: true}, {ACK: true}},
			argsev: &flowpb.TCPFlags{PSH: true, ACK: true},
			want:   true,
		},
		{
			name:   "filterSYN___eventSYN",
			argsf:  []*flowpb.TCPFlags{{SYN: true}},
			argsev: &flowpb.TCPFlags{SYN: true},
			want:   true,
		},
		{
			name:   "filterSYN___eventSYNACK",
			argsf:  []*flowpb.TCPFlags{{SYN: true}},
			argsev: &flowpb.TCPFlags{SYN: true, ACK: true},
			want:   true,
		},
		{
			name:   "filterFIN___eventRST",
			argsf:  []*flowpb.TCPFlags{{FIN: true}},
			argsev: &flowpb.TCPFlags{RST: true},
			want:   false,
		},
		{
			name:   "filterSYN___eventPSH",
			argsf:  []*flowpb.TCPFlags{{SYN: true}},
			argsev: &flowpb.TCPFlags{PSH: true},
			want:   false,
		},
		{
			name:   "filterURG___eventPSH",
			argsf:  []*flowpb.TCPFlags{{URG: true}},
			argsev: &flowpb.TCPFlags{PSH: true},
			want:   false,
		},
		{
			name:   "filterRST___eventRST",
			argsf:  []*flowpb.TCPFlags{{RST: true}},
			argsev: &flowpb.TCPFlags{RST: true},
			want:   true,
		},
		{
			name:   "filterFIN___eventFIN",
			argsf:  []*flowpb.TCPFlags{{FIN: true}},
			argsev: &flowpb.TCPFlags{FIN: true},
			want:   true,
		},
		{
			name:   "filterPSH___eventPSHACK",
			argsf:  []*flowpb.TCPFlags{{PSH: true}},
			argsev: &flowpb.TCPFlags{PSH: true, ACK: true},
			want:   true,
		},
		// regression test for GH-18830
		{
			name:   "TCP flow without flags",
			argsf:  []*flowpb.TCPFlags{{SYN: true}},
			argsev: nil,
			want:   false,
		},
	}

	for _, tt := range testflags {
		argsfilter = []*flowpb.FlowFilter{{TcpFlags: tt.argsf}}
		argsevent = &v1.Event{Event: &flowpb.Flow{
			L4: &flowpb.Layer4{Protocol: &flowpb.Layer4_TCP{TCP: &flowpb.TCP{Flags: tt.argsev}}}}}
		t.Run(tt.name, func(t *testing.T) {
			fl, err := BuildFilterList(context.Background(), argsfilter, []OnBuildFilter{&TCPFilter{}})
			if err != nil {
				t.Errorf("unexpected filter build error: %s", err)
			} else if got := fl.MatchOne(argsevent); got != tt.want {
				t.Errorf("%s: got %v, want %v", tt.name, got, tt.want)
			}
		})
	}
}
<|endoftext|>


<commit_before>package suggestion

import (
	"context"
	"fmt"
	"log"
	"strconv"

	"github.com/kubeflow/katib/pkg"
	"github.com/kubeflow/katib/pkg/api"

	"google.golang.org/grpc"
)

type GridSuggestParameters struct {
	defaultGridNum int
	gridConfig     map[string]int
	MaxParallel    int
}

type GridSuggestService struct {
}

func NewGridSuggestService() *GridSuggestService {
	return &GridSuggestService{}
}

func (s *GridSuggestService) allocInt(min int, max int, reqnum int) []string {
	ret := make([]string, reqnum)
	if reqnum == 1 {
		ret[0] = strconv.Itoa(min)
	} else {
		for i := 0; i < reqnum; i++ {
			ret[i] = strconv.Itoa(min + ((max - min) * i / (reqnum - 1)))
		}
	}
	return ret
}

func (s *GridSuggestService) allocFloat(min float64, max float64, reqnum int) []string {
	ret := make([]string, reqnum)
	if reqnum == 1 {
		ret[0] = strconv.FormatFloat(min, 'f', 4, 64)
	} else {
		for i := 0; i < reqnum; i++ {
			ret[i] = strconv.FormatFloat(min+(((max-min)/float64(reqnum-1))*float64(i)), 'f', 4, 64)
		}
	}
	return ret
}

func (s *GridSuggestService) allocCat(list []string, reqnum int) []string {
	ret := make([]string, reqnum)
	if reqnum == 1 {
		ret[0] = list[0]
	} else {
		for i := 0; i < reqnum; i++ {
			ret[i] = list[(((len(list) - 1) * i) / (reqnum - 1))]
			fmt.Printf("ret %v %v\n", i, ret[i])
		}
	}
	return ret
}

func (s *GridSuggestService) setP(gci int, p [][]*api.Parameter, pg [][]string, pcs []*api.ParameterConfig) {
	if gci == len(pg)-1 {
		for i := range pg[gci] {
			p[i] = append(p[i], &api.Parameter{
				Name:          pcs[gci].Name,
				ParameterType: pcs[gci].ParameterType,
				Value:         pg[gci][i],
			})

		}
		return
	} else {
		d := len(p) / len(pg[gci])
		for i := range pg[gci] {
			for j := d * i; j < d*(i+1); j++ {
				p[j] = append(p[j], &api.Parameter{
					Name:          pcs[gci].Name,
					ParameterType: pcs[gci].ParameterType,
					Value:         pg[gci][i],
				})
			}
			s.setP(gci+1, p[d*i:d*(i+1)], pg, pcs)
		}
	}
}

func (s *GridSuggestService) parseSuggestParam(suggestParam []*api.SuggestionParameter) (int, int, map[string]int) {
	ret := make(map[string]int)
	defaultGrid := 0
	i := 0
	for _, sp := range suggestParam {
		switch sp.Name {
		case "DefaultGrid":
			defaultGrid, _ = strconv.Atoi(sp.Value)
		case "Iteration":
			i, _ = strconv.Atoi(sp.Value)
		default:
			ret[sp.Name], _ = strconv.Atoi(sp.Value)
		}
	}
	if defaultGrid <= 0 {
		defaultGrid = 1
	}
	return defaultGrid, i, ret
}
func (s *GridSuggestService) genGrids(studyID string, pcs []*api.ParameterConfig, df int, glist map[string]int) [][]*api.Parameter {
	var pg [][]string
	var holenum = 1
	gcl := make([]int, len(pcs))
	for i, pc := range pcs {
		gc, ok := glist[pc.Name]
		if !ok {
			gc = df
		}
		holenum *= gc
		gcl[i] = gc
		switch pc.ParameterType {
		case api.ParameterType_INT:
			imin, _ := strconv.Atoi(pc.Feasible.Min)
			imax, _ := strconv.Atoi(pc.Feasible.Max)
			pg = append(pg, s.allocInt(imin, imax, gc))
		case api.ParameterType_DOUBLE:
			dmin, _ := strconv.ParseFloat(pc.Feasible.Min, 64)
			dmax, _ := strconv.ParseFloat(pc.Feasible.Max, 64)
			pg = append(pg, s.allocFloat(dmin, dmax, gc))
		case api.ParameterType_CATEGORICAL:
			pg = append(pg, s.allocCat(pc.Feasible.List, gc))
		}
	}
	ret := make([][]*api.Parameter, holenum)
	s.setP(0, ret, pg, pcs)
	log.Printf("Study %v : %v parameters generated", studyID, holenum)
	return ret
}

func (s *GridSuggestService) GetSuggestions(ctx context.Context, in *api.GetSuggestionsRequest) (*api.GetSuggestionsReply, error) {
	conn, err := grpc.Dial(pkg.ManagerAddr, grpc.WithInsecure())
	if err != nil {
		log.Printf("could not connect: %v", err)
		return &api.GetSuggestionsReply{}, err
	}
	defer conn.Close()
	c := api.NewManagerClient(conn)
	screq := &api.GetStudyRequest{
		StudyId: in.StudyId,
	}
	scr, err := c.GetStudy(ctx, screq)
	if err != nil {
		log.Printf("GetStudyConf failed: %v", err)
		return &api.GetSuggestionsReply{}, err
	}
	spreq := &api.GetSuggestionParametersRequest{
		ParamId: in.ParamId,
	}
	spr, err := c.GetSuggestionParameters(ctx, spreq)
	if err != nil {
		log.Printf("GetParameter failed: %v", err)
		return &api.GetSuggestionsReply{}, err
	}
	df, iteration, glist := s.parseSuggestParam(spr.SuggestionParameters)
	log.Printf("Study %s iteration %d DefaltGrid %d Grids %v", in.StudyId, iteration, df, glist)
	grids := s.genGrids(in.StudyId, scr.StudyConfig.ParameterConfigs.Configs, df, glist)
	var reqnum = int(in.RequestNumber)
	if reqnum == 0 {
		reqnum = len(grids)
	}
	trials := make([]*api.Trial, reqnum)
	if iteration+reqnum > len(grids) {
		reqnum = len(grids) - iteration
	}
	if reqnum <= 0 {
		return &api.GetSuggestionsReply{Trials: []*api.Trial{}}, err
	}
	for i := 0; i < int(reqnum); i++ {
		trials[i] = &api.Trial{
			StudyId:      in.StudyId,
			ParameterSet: grids[iteration+i],
		}
	}
	iteration += reqnum
	sspreq := &api.SetSuggestionParametersRequest{
		StudyId:             in.StudyId,
		SuggestionAlgorithm: in.SuggestionAlgorithm,
		ParamId:             in.ParamId,
	}
	sp := []*api.SuggestionParameter{}
	sp = append(sp, &api.SuggestionParameter{
		Name:  "DefaultGrid",
		Value: strconv.Itoa(df),
	})
	sp = append(sp, &api.SuggestionParameter{
		Name:  "Iteration",
		Value: strconv.Itoa(iteration),
	})
	for gn, gv := range glist {
		sp = append(sp, &api.SuggestionParameter{
			Name:  gn,
			Value: strconv.Itoa(gv),
		})
	}
	sspreq.SuggestionParameters = sp
	_, err = c.SetSuggestionParameters(ctx, sspreq)
	if err != nil {
		log.Printf("Save Parameters Failed %v", err)
		return &api.GetSuggestionsReply{}, err
	}
	for i, t := range trials {
		req := &api.CreateTrialRequest{
			Trial: t,
		}
		ret, err := c.CreateTrial(ctx, req)
		if err != nil {
			return &api.GetSuggestionsReply{Trials: []*api.Trial{}}, err
		}
		trials[i].TrialId = ret.TrialId
	}
	return &api.GetSuggestionsReply{Trials: trials}, nil
}
<commit_msg>fix make timing (#271)<commit_after>package suggestion

import (
	"context"
	"fmt"
	"log"
	"strconv"

	"github.com/kubeflow/katib/pkg"
	"github.com/kubeflow/katib/pkg/api"

	"google.golang.org/grpc"
)

type GridSuggestParameters struct {
	defaultGridNum int
	gridConfig     map[string]int
	MaxParallel    int
}

type GridSuggestService struct {
}

func NewGridSuggestService() *GridSuggestService {
	return &GridSuggestService{}
}

func (s *GridSuggestService) allocInt(min int, max int, reqnum int) []string {
	ret := make([]string, reqnum)
	if reqnum == 1 {
		ret[0] = strconv.Itoa(min)
	} else {
		for i := 0; i < reqnum; i++ {
			ret[i] = strconv.Itoa(min + ((max - min) * i / (reqnum - 1)))
		}
	}
	return ret
}

func (s *GridSuggestService) allocFloat(min float64, max float64, reqnum int) []string {
	ret := make([]string, reqnum)
	if reqnum == 1 {
		ret[0] = strconv.FormatFloat(min, 'f', 4, 64)
	} else {
		for i := 0; i < reqnum; i++ {
			ret[i] = strconv.FormatFloat(min+(((max-min)/float64(reqnum-1))*float64(i)), 'f', 4, 64)
		}
	}
	return ret
}

func (s *GridSuggestService) allocCat(list []string, reqnum int) []string {
	ret := make([]string, reqnum)
	if reqnum == 1 {
		ret[0] = list[0]
	} else {
		for i := 0; i < reqnum; i++ {
			ret[i] = list[(((len(list) - 1) * i) / (reqnum - 1))]
			fmt.Printf("ret %v %v\n", i, ret[i])
		}
	}
	return ret
}

func (s *GridSuggestService) setP(gci int, p [][]*api.Parameter, pg [][]string, pcs []*api.ParameterConfig) {
	if gci == len(pg)-1 {
		for i := range pg[gci] {
			p[i] = append(p[i], &api.Parameter{
				Name:          pcs[gci].Name,
				ParameterType: pcs[gci].ParameterType,
				Value:         pg[gci][i],
			})

		}
		return
	} else {
		d := len(p) / len(pg[gci])
		for i := range pg[gci] {
			for j := d * i; j < d*(i+1); j++ {
				p[j] = append(p[j], &api.Parameter{
					Name:          pcs[gci].Name,
					ParameterType: pcs[gci].ParameterType,
					Value:         pg[gci][i],
				})
			}
			s.setP(gci+1, p[d*i:d*(i+1)], pg, pcs)
		}
	}
}

func (s *GridSuggestService) parseSuggestParam(suggestParam []*api.SuggestionParameter) (int, int, map[string]int) {
	ret := make(map[string]int)
	defaultGrid := 0
	i := 0
	for _, sp := range suggestParam {
		switch sp.Name {
		case "DefaultGrid":
			defaultGrid, _ = strconv.Atoi(sp.Value)
		case "Iteration":
			i, _ = strconv.Atoi(sp.Value)
		default:
			ret[sp.Name], _ = strconv.Atoi(sp.Value)
		}
	}
	if defaultGrid <= 0 {
		defaultGrid = 1
	}
	return defaultGrid, i, ret
}
func (s *GridSuggestService) genGrids(studyID string, pcs []*api.ParameterConfig, df int, glist map[string]int) [][]*api.Parameter {
	var pg [][]string
	var holenum = 1
	gcl := make([]int, len(pcs))
	for i, pc := range pcs {
		gc, ok := glist[pc.Name]
		if !ok {
			gc = df
		}
		holenum *= gc
		gcl[i] = gc
		switch pc.ParameterType {
		case api.ParameterType_INT:
			imin, _ := strconv.Atoi(pc.Feasible.Min)
			imax, _ := strconv.Atoi(pc.Feasible.Max)
			pg = append(pg, s.allocInt(imin, imax, gc))
		case api.ParameterType_DOUBLE:
			dmin, _ := strconv.ParseFloat(pc.Feasible.Min, 64)
			dmax, _ := strconv.ParseFloat(pc.Feasible.Max, 64)
			pg = append(pg, s.allocFloat(dmin, dmax, gc))
		case api.ParameterType_CATEGORICAL:
			pg = append(pg, s.allocCat(pc.Feasible.List, gc))
		}
	}
	ret := make([][]*api.Parameter, holenum)
	s.setP(0, ret, pg, pcs)
	log.Printf("Study %v : %v parameters generated", studyID, holenum)
	return ret
}

func (s *GridSuggestService) GetSuggestions(ctx context.Context, in *api.GetSuggestionsRequest) (*api.GetSuggestionsReply, error) {
	conn, err := grpc.Dial(pkg.ManagerAddr, grpc.WithInsecure())
	if err != nil {
		log.Printf("could not connect: %v", err)
		return &api.GetSuggestionsReply{}, err
	}
	defer conn.Close()
	c := api.NewManagerClient(conn)
	screq := &api.GetStudyRequest{
		StudyId: in.StudyId,
	}
	scr, err := c.GetStudy(ctx, screq)
	if err != nil {
		log.Printf("GetStudyConf failed: %v", err)
		return &api.GetSuggestionsReply{}, err
	}
	spreq := &api.GetSuggestionParametersRequest{
		ParamId: in.ParamId,
	}
	spr, err := c.GetSuggestionParameters(ctx, spreq)
	if err != nil {
		log.Printf("GetParameter failed: %v", err)
		return &api.GetSuggestionsReply{}, err
	}
	df, iteration, glist := s.parseSuggestParam(spr.SuggestionParameters)
	log.Printf("Study %s iteration %d DefaltGrid %d Grids %v", in.StudyId, iteration, df, glist)
	grids := s.genGrids(in.StudyId, scr.StudyConfig.ParameterConfigs.Configs, df, glist)
	var reqnum = int(in.RequestNumber)
	if reqnum == 0 {
		reqnum = len(grids)
	}
	if iteration+reqnum > len(grids) {
		reqnum = len(grids) - iteration
	}
	trials := make([]*api.Trial, reqnum)
	if reqnum <= 0 {
		return &api.GetSuggestionsReply{Trials: []*api.Trial{}}, err
	}
	for i := 0; i < int(reqnum); i++ {
		trials[i] = &api.Trial{
			StudyId:      in.StudyId,
			ParameterSet: grids[iteration+i],
		}
	}
	iteration += reqnum
	sspreq := &api.SetSuggestionParametersRequest{
		StudyId:             in.StudyId,
		SuggestionAlgorithm: in.SuggestionAlgorithm,
		ParamId:             in.ParamId,
	}
	sp := []*api.SuggestionParameter{}
	sp = append(sp, &api.SuggestionParameter{
		Name:  "DefaultGrid",
		Value: strconv.Itoa(df),
	})
	sp = append(sp, &api.SuggestionParameter{
		Name:  "Iteration",
		Value: strconv.Itoa(iteration),
	})
	for gn, gv := range glist {
		sp = append(sp, &api.SuggestionParameter{
			Name:  gn,
			Value: strconv.Itoa(gv),
		})
	}
	sspreq.SuggestionParameters = sp
	_, err = c.SetSuggestionParameters(ctx, sspreq)
	if err != nil {
		log.Printf("Save Parameters Failed %v", err)
		return &api.GetSuggestionsReply{}, err
	}
	for i, t := range trials {
		req := &api.CreateTrialRequest{
			Trial: t,
		}
		ret, err := c.CreateTrial(ctx, req)
		if err != nil {
			return &api.GetSuggestionsReply{Trials: []*api.Trial{}}, err
		}
		trials[i].TrialId = ret.TrialId
	}
	return &api.GetSuggestionsReply{Trials: trials}, nil
}
<|endoftext|>


<commit_before>/* Package trigram is a dumb trigram index */
package trigram

type tri uint32

type Index map[tri][]int

func MakeTrigrams(s string) []tri {

	var trigrams []tri

	for i := 0; i <= len(s)-3; i++ {
		t := tri(uint32(s[i])<<16 | uint32(s[i+1])<<8 | uint32(s[i+2]))
		trigrams = appendIfUnique(trigrams, t)
	}

	return trigrams
}

func appendIfUnique(t []tri, n tri) []tri {
	for _, v := range t {
		if v == n {
			return t
		}
	}

	return append(t, n)
}

func NewIndex(docs []string) Index {

	idx := make(Index)

	for id, d := range docs {
		ts := MakeTrigrams(d)
		for _, t := range ts {
			idx[t] = append(idx[t], id)
		}
	}

	return idx
}

func (idx Index) Add(s string) {

	id := len(idx)

	ts := MakeTrigrams(s)
	for _, t := range ts {
		idx[t] = append(idx[t], id)
	}
}

func (idx Index) Query(s string) []int {

	ts := MakeTrigrams(s)

	// TODO(dgryski): start with the rarest trigram

	return idx.Filter(idx[ts[0]], ts[1:]...)
}

func (idx Index) Filter(docs []int, ts ...tri) []int {
	for _, t := range ts {
		docs = intersect(docs, idx[t])
	}

	return docs
}

func intersect(a, b []int) []int {

	// TODO(dgryski): reduce allocations by reusing A

	var aidx, bidx int

	var result []int

	for aidx < len(a) && bidx < len(b) {
		switch {
		case a[aidx] == b[bidx]:
			result = append(result, a[aidx])
			aidx++
			bidx++
		case a[aidx] < b[bidx]:
			aidx++
		case a[aidx] > b[bidx]:
			bidx++
		}
	}

	return result
}
<commit_msg>Add QueryTrigrams()<commit_after>/* Package trigram is a dumb trigram index */
package trigram

type tri uint32

type Index map[tri][]int

func MakeTrigrams(s string) []tri {

	var trigrams []tri

	for i := 0; i <= len(s)-3; i++ {
		t := tri(uint32(s[i])<<16 | uint32(s[i+1])<<8 | uint32(s[i+2]))
		trigrams = appendIfUnique(trigrams, t)
	}

	return trigrams
}

func appendIfUnique(t []tri, n tri) []tri {
	for _, v := range t {
		if v == n {
			return t
		}
	}

	return append(t, n)
}

func NewIndex(docs []string) Index {

	idx := make(Index)

	for id, d := range docs {
		ts := MakeTrigrams(d)
		for _, t := range ts {
			idx[t] = append(idx[t], id)
		}
	}

	return idx
}

func (idx Index) Add(s string) {

	id := len(idx)

	ts := MakeTrigrams(s)
	for _, t := range ts {
		idx[t] = append(idx[t], id)
	}
}

func (idx Index) Query(s string) []int {
	ts := MakeTrigrams(s)
	return idx.QueryTrigrams(ts)
}

func (idx Index) QueryTrigrams(ts []tri) []int {

	midx := 0
	mtri := ts[midx]

	for i, t := range ts {
		if len(idx[t]) < len(idx[mtri]) {
			midx = i
			mtri = t
		}
	}

	ts[0], ts[midx] = ts[midx], ts[0]

	return idx.Filter(idx[mtri], ts[1:]...)
}

func (idx Index) Filter(docs []int, ts ...tri) []int {
	for _, t := range ts {
		docs = intersect(docs, idx[t])
	}

	return docs
}

func intersect(a, b []int) []int {

	// TODO(dgryski): reduce allocations by reusing A

	var aidx, bidx int

	var result []int

	for aidx < len(a) && bidx < len(b) {
		switch {
		case a[aidx] == b[bidx]:
			result = append(result, a[aidx])
			aidx++
			bidx++
		case a[aidx] < b[bidx]:
			aidx++
		case a[aidx] > b[bidx]:
			bidx++
		}
	}

	return result
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/x509"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"math/big"
	"net/http"
	"net/url"
	"time"

	"gopkg.in/mgo.v2/bson"

	"github.com/dgrijalva/jwt-go"
)

type VAPIDKey struct {
	PrivateKeyX *big.Int
	PrivateKeyY *big.Int
	PrivateKeyD *big.Int
}

func (k VAPIDKey) GetBSON() (interface{}, error) {
	return bson.D{{"x", k.PrivateKeyX.Bytes()}, {"y", k.PrivateKeyY.Bytes()}, {"d", k.PrivateKeyD.Bytes()}}, nil
}

func (k *VAPIDKey) SetBSON(raw bson.Raw) error {
	var out bson.M
	if err := raw.Unmarshal(&out); err != nil {
		return err
	}
	var tmp big.Int
	var tmpBytes []byte
	var ok bool
	if tmpBytes, ok = out["x"].([]byte); !ok {
		return errors.New("Unable to convert x")
	}
	k.PrivateKeyX = tmp.SetBytes(tmpBytes)
	if tmpBytes, ok = out["y"].([]byte); !ok {
		return errors.New("Unable to convert y")
	}
	k.PrivateKeyY = tmp.SetBytes(tmpBytes)
	if tmpBytes, ok = out["d"].([]byte); !ok {
		return errors.New("Unable to convert d")
	}
	k.PrivateKeyD = tmp.SetBytes(tmpBytes)
	return nil
}

func (k *VAPIDKey) ToElliptic() *ecdsa.PrivateKey {
	return &ecdsa.PrivateKey{
		PublicKey: ecdsa.PublicKey{
			Curve: elliptic.P256(),
			X:     k.PrivateKeyX,
			Y:     k.PrivateKeyY,
		},
		D: k.PrivateKeyD,
	}
}

func PushSubHandler(w http.ResponseWriter, req *http.Request) {
	w.Header().Add("Access-Control-Allow-Origin", "*")
	w.Header().Add("Access-Control-Allow-Methods", "GET")
	w.Header().Add("Access-Control-Allow-Headers", "Content-Type")

	var data map[string]interface{}
	err := json.NewDecoder(req.Body).Decode(&data)
	if err != nil {
		log.Println(err)
	}
	log.Printf("Push, endpoint: %v+", data)
}

func PushToAllHandler(w http.ResponseWriter, req *http.Request) {
	w.Header().Add("Access-Control-Allow-Origin", "*")
	w.Header().Add("Access-Control-Allow-Methods", "GET")
	w.Header().Add("Access-Control-Allow-Headers", "Content-Type")

	vapid := getOrCreateVAPIDKey()
	signedJWT, err := createSignedJWT("https://fcm.googleapis.com/fcm/send/not-the-right-url")
	if err != nil {
		log.Printf("Error while creating signed JWT: %v\n", err)
		return
	}
	private := vapid.ToElliptic()
	encodedKey, err := x509.MarshalPKIXPublicKey(&private.PublicKey)
	if err != nil {
		log.Printf("Error encoding key: %v\n", err)
		return
	}
	b64Key := base64.RawURLEncoding.EncodeToString(encodedKey)
	log.Println(fmt.Sprintf("vapid t=%s,k=%s", signedJWT, b64Key))
}

func createSignedJWT(endpoint string) (string, error) {
	endpointUrl, err := url.Parse(endpoint)
	if err != nil {
		return "", err
	}
	endpointUrl.Path = ""
	endpointUrl.RawQuery = ""
	endpointUrl.Fragment = ""
	key := getOrCreateVAPIDKey()
	token := jwt.NewWithClaims(jwt.SigningMethodES256, jwt.StandardClaims{
		Audience:  endpointUrl.String(),
		Subject:   "mailto:foo@bar.fr",
		ExpiresAt: time.Now().Add(time.Duration(12) * time.Hour).Unix(),
	})
	log.Println(key)
	privKey := key.ToElliptic()
	return token.SignedString(privKey)
}

func VAPIDHandler(w http.ResponseWriter, req *http.Request) {
	w.Header().Add("Access-Control-Allow-Origin", "*")
	w.Header().Add("Access-Control-Allow-Methods", "GET")
	w.Header().Add("Access-Control-Allow-Headers", "Content-Type")
	w.Header().Set("Cache-control", "public, max-age=86400")

	keyPair := getOrCreateVAPIDKey()

	json.NewEncoder(w).Encode(&keyPair)
}

func getOrCreateVAPIDKey() *VAPIDKey {
	c := session.DB("dispotrains").C("pushKey")
	var keyPair VAPIDKey
	err := c.Find(nil).One(&keyPair)
	if err != nil {
		c.DropCollection()
		keyPair = createKeyPair()
		c.Insert(keyPair)
	}
	return &keyPair
}

func createKeyPair() VAPIDKey {
	curve := elliptic.P256()
	// priv
	priv, err := ecdsa.GenerateKey(curve, rand.Reader)
	if err != nil {
		log.Fatalln(err)
	}
	// pub
	return VAPIDKey{
		PrivateKeyX: priv.X,
		PrivateKeyY: priv.Y,
		PrivateKeyD: priv.D,
	}
}
<commit_msg>Store registered clients<commit_after>package main

import (
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/x509"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"math/big"
	"net/http"
	"net/url"
	"time"

	"gopkg.in/mgo.v2/bson"

	"github.com/dgrijalva/jwt-go"
)

type VAPIDKey struct {
	PrivateKeyX *big.Int
	PrivateKeyY *big.Int
	PrivateKeyD *big.Int
}

func (k VAPIDKey) GetBSON() (interface{}, error) {
	return bson.D{{"x", k.PrivateKeyX.Bytes()}, {"y", k.PrivateKeyY.Bytes()}, {"d", k.PrivateKeyD.Bytes()}}, nil
}

func (k *VAPIDKey) SetBSON(raw bson.Raw) error {
	var out bson.M
	if err := raw.Unmarshal(&out); err != nil {
		return err
	}
	var tmp big.Int
	var tmpBytes []byte
	var ok bool
	if tmpBytes, ok = out["x"].([]byte); !ok {
		return errors.New("Unable to convert x")
	}
	k.PrivateKeyX = tmp.SetBytes(tmpBytes)
	if tmpBytes, ok = out["y"].([]byte); !ok {
		return errors.New("Unable to convert y")
	}
	k.PrivateKeyY = tmp.SetBytes(tmpBytes)
	if tmpBytes, ok = out["d"].([]byte); !ok {
		return errors.New("Unable to convert d")
	}
	k.PrivateKeyD = tmp.SetBytes(tmpBytes)
	return nil
}

func (k *VAPIDKey) ToElliptic() *ecdsa.PrivateKey {
	return &ecdsa.PrivateKey{
		PublicKey: ecdsa.PublicKey{
			Curve: elliptic.P256(),
			X:     k.PrivateKeyX,
			Y:     k.PrivateKeyY,
		},
		D: k.PrivateKeyD,
	}
}

func PushSubHandler(w http.ResponseWriter, req *http.Request) {
	w.Header().Add("Access-Control-Allow-Origin", "*")
	w.Header().Add("Access-Control-Allow-Methods", "GET")
	w.Header().Add("Access-Control-Allow-Headers", "Content-Type")

	if req.Method != "POST" {
		return
	}

	var data map[string]interface{}
	err := json.NewDecoder(req.Body).Decode(&data)
	if err != nil {
		log.Println(err)
	}
	c := session.DB("dispotrains").C("pushSubscribers")
	_, err = c.Upsert(data, data)
	if err != nil {
		log.Println(err)
	}
}

func PushToAllHandler(w http.ResponseWriter, req *http.Request) {
	w.Header().Add("Access-Control-Allow-Origin", "*")
	w.Header().Add("Access-Control-Allow-Methods", "GET")
	w.Header().Add("Access-Control-Allow-Headers", "Content-Type")

	vapid := getOrCreateVAPIDKey()
	signedJWT, err := createSignedJWT("https://fcm.googleapis.com/fcm/send/not-the-right-url")
	if err != nil {
		log.Printf("Error while creating signed JWT: %v\n", err)
		return
	}
	private := vapid.ToElliptic()
	encodedKey, err := x509.MarshalPKIXPublicKey(&private.PublicKey)
	if err != nil {
		log.Printf("Error encoding key: %v\n", err)
		return
	}
	b64Key := base64.RawURLEncoding.EncodeToString(encodedKey)
	log.Println(fmt.Sprintf("vapid t=%s,k=%s", signedJWT, b64Key))
}

func createSignedJWT(endpoint string) (string, error) {
	endpointUrl, err := url.Parse(endpoint)
	if err != nil {
		return "", err
	}
	endpointUrl.Path = ""
	endpointUrl.RawQuery = ""
	endpointUrl.Fragment = ""
	key := getOrCreateVAPIDKey()
	token := jwt.NewWithClaims(jwt.SigningMethodES256, jwt.StandardClaims{
		Audience:  endpointUrl.String(),
		Subject:   "mailto:foo@bar.fr",
		ExpiresAt: time.Now().Add(time.Duration(12) * time.Hour).Unix(),
	})
	log.Println(key)
	privKey := key.ToElliptic()
	return token.SignedString(privKey)
}

func VAPIDHandler(w http.ResponseWriter, req *http.Request) {
	w.Header().Add("Access-Control-Allow-Origin", "*")
	w.Header().Add("Access-Control-Allow-Methods", "GET")
	w.Header().Add("Access-Control-Allow-Headers", "Content-Type")
	w.Header().Set("Cache-control", "public, max-age=86400")

	keyPair := getOrCreateVAPIDKey()

	json.NewEncoder(w).Encode(&keyPair)
}

func getOrCreateVAPIDKey() *VAPIDKey {
	c := session.DB("dispotrains").C("pushKey")
	var keyPair VAPIDKey
	err := c.Find(nil).One(&keyPair)
	if err != nil {
		c.DropCollection()
		keyPair = createKeyPair()
		c.Insert(keyPair)
	}
	return &keyPair
}

func createKeyPair() VAPIDKey {
	curve := elliptic.P256()
	// priv
	priv, err := ecdsa.GenerateKey(curve, rand.Reader)
	if err != nil {
		log.Fatalln(err)
	}
	// pub
	return VAPIDKey{
		PrivateKeyX: priv.X,
		PrivateKeyY: priv.Y,
		PrivateKeyD: priv.D,
	}
}
<|endoftext|>


<commit_before>package polytonicchar

type PolytonicChar struct {
	name            Char
	capital         bool
	iotaSubscriptum bool
	variant         bool
	spiritus        Spiritus
	accent          Accent
}

func New(n Char, c bool) *PolytonicChar {
	return &PolytonicChar{name: n, capital: c}
}

func Name(c *PolytonicChar) Char {
	return c.name
}

func SetVariant(char *PolytonicChar, in bool) {
	char.variant = in
}

func SetIota(char *PolytonicChar, in bool) {
	char.iotaSubscriptum = in
}

func SetSpiritus(char *PolytonicChar, in Spiritus) {
	char.spiritus = in
}

func SetAccent(char *PolytonicChar, in Accent) {
	char.accent = in
}

func AreEqual(char1 *PolytonicChar, char2 *PolytonicChar, exact bool) bool {
	if exact {
		return *char1 == *char2
	}
	return char1.name == char2.name
}

func (c *PolytonicChar) String() string {
	if c.variant && c.name == Space {
		return "\n"
	}
	if c.name > Omega {
		letterOrder := map[Char]string{
			Space:      " ",
			Comma:      ",",
			Dot:        ".",
			Apostrophe: "'",
			Interpunct: "\u0387",
			Question:   ";",
		}
		if val, ok := letterOrder[c.name]; ok {
			return val
		}
		return string(replacementChar)
	}
	if c.variant && c.name == Sigma && !c.capital {
		return "\u03C2"
	}
	if c.spiritus != None {
		s := greekExtended
		if c.spiritus == Asper {
			s += asperOffset
		}
		if c.capital {
			s += capitalOffset
		}
		s += accentOffset * int(c.accent)
		if c.iotaSubscriptum {
			s += iotaOffset
			letterOrder := map[Char]int{
				Alpha: 0,
				Eta:   1,
				Omega: 2,
			}
			if val, ok := letterOrder[c.name]; ok {
				s += val * letterOffset
				return string(s)
			}
			return string(replacementChar)
		}
		letterOrder := map[Char]int{
			Alpha:   0,
			Epsilon: 1,
			Eta:     2,
			Iota:    3,
			Omicron: 4,
			Upsilon: 5,
			Omega:   6,
		}
		if val, ok := letterOrder[c.name]; ok {
			s += val * letterOffset
			return string(s)
		}
		if c.name == Rho {
			s += rhoOffset
			if c.capital {
				s -= 1 //it works: https://en.wikipedia.org/wiki/Greek_diacritics
				if c.spiritus == Lenis {
					return string(replacementChar) //not possible
				}
			}
			return string(s)
		}
		return string(replacementChar)
	}
	if c.accent == Circumflex {
		s := circumflexWithoutSpiritus
		if c.iotaSubscriptum {
			s += iotaWithCircumflexWithoutSpiritusOffset
		}
		letterOrder := map[Char]int{
			Alpha:   0,
			Eta:     1,
			Iota:    2,
			Upsilon: 3,
			Omega:   4,
		}
		if val, ok := letterOrder[c.name]; ok {
			s += val * letterOffset
			return string(s)
		}
		return string(replacementChar)
	}
	if c.iotaSubscriptum {
		s := iotaSubscriptumWithoutSpiritus
		letterOrder := map[Char]int{
			Alpha: 0,
			Eta:   1,
			Omega: 4,
		}
		if val, ok := letterOrder[c.name]; ok {
			s += val * letterOffset
		} else {
			return string(replacementChar)
		}
		if c.capital {
			s += 10
			return string(s)
		}
		accentOrder := map[Accent]int{
			Grave: 0,
			None:  1,
			Acute: 2,
		}
		if val, ok := accentOrder[c.accent]; ok {
			s += val
			return string(s)
		}
		return string(replacementChar)
	}
	if c.accent != None {
		if c.capital {
			s := accentendUpperCaseWithoutSpiritus
			letterOrder := map[Char]int{
				Alpha:   0,
				Epsilon: 1,
				Eta:     1,
				Iota:    2,
				Upsilon: 3,
				Omicron: 4,
				Omega:   4,
			}
			if val, ok := letterOrder[c.name]; ok {
				s += val * letterOffset
			} else {
				return string(replacementChar)
			}
			if c.name == Epsilon || c.name == Omicron {
				s -= 2
			}
			accentOrder := map[Accent]int{
				Grave: 0,
				Acute: 1,
			}
			if val, ok := accentOrder[c.accent]; ok {
				s += val
				return string(s)
			}
			return string(replacementChar)
		}
		s := accentendLowerCaseWithoutSpiritus
		letterOrder := map[Char]int{
			Alpha:   0,
			Epsilon: 1,
			Eta:     2,
			Iota:    3,
			Omicron: 4,
			Upsilon: 5,
			Omega:   6,
		}
		if val, ok := letterOrder[c.name]; ok {
			s += val * 2
		} else {
			return string(replacementChar)
		}
		accentOrder := map[Accent]int{
			Grave: 0,
			Acute: 1,
		}
		if val, ok := accentOrder[c.accent]; ok {
			s += val
			return string(s)
		}
		return string(replacementChar)
	}
	if c.capital {
		return string(upperCaseAlpha + c.name)
	}
	return string(lowerCaseAlpha + c.name)
}
<commit_msg>add getter for diacritics<commit_after>package polytonicchar

type PolytonicChar struct {
	name            Char
	capital         bool
	iotaSubscriptum bool
	variant         bool
	spiritus        Spiritus
	accent          Accent
}

func New(n Char, c bool) *PolytonicChar {
	return &PolytonicChar{name: n, capital: c}
}

func Name(c *PolytonicChar) Char {
	return c.name
}

func Diacritics(c *PolytonicChar) (bool, Spiritus, Accent) {
	return c.iotaSubscriptum, c.spiritus, c.accent
}

func SetVariant(char *PolytonicChar, in bool) {
	char.variant = in
}

func SetIota(char *PolytonicChar, in bool) {
	char.iotaSubscriptum = in
}

func SetSpiritus(char *PolytonicChar, in Spiritus) {
	char.spiritus = in
}

func SetAccent(char *PolytonicChar, in Accent) {
	char.accent = in
}

func AreEqual(char1 *PolytonicChar, char2 *PolytonicChar, exact bool) bool {
	if exact {
		return *char1 == *char2
	}
	return char1.name == char2.name
}

func (c *PolytonicChar) String() string {
	if c.variant && c.name == Space {
		return "\n"
	}
	if c.name > Omega {
		letterOrder := map[Char]string{
			Space:      " ",
			Comma:      ",",
			Dot:        ".",
			Apostrophe: "'",
			Interpunct: "\u0387",
			Question:   ";",
		}
		if val, ok := letterOrder[c.name]; ok {
			return val
		}
		return string(replacementChar)
	}
	if c.variant && c.name == Sigma && !c.capital {
		return "\u03C2"
	}
	if c.spiritus != None {
		s := greekExtended
		if c.spiritus == Asper {
			s += asperOffset
		}
		if c.capital {
			s += capitalOffset
		}
		s += accentOffset * int(c.accent)
		if c.iotaSubscriptum {
			s += iotaOffset
			letterOrder := map[Char]int{
				Alpha: 0,
				Eta:   1,
				Omega: 2,
			}
			if val, ok := letterOrder[c.name]; ok {
				s += val * letterOffset
				return string(s)
			}
			return string(replacementChar)
		}
		letterOrder := map[Char]int{
			Alpha:   0,
			Epsilon: 1,
			Eta:     2,
			Iota:    3,
			Omicron: 4,
			Upsilon: 5,
			Omega:   6,
		}
		if val, ok := letterOrder[c.name]; ok {
			s += val * letterOffset
			return string(s)
		}
		if c.name == Rho {
			s += rhoOffset
			if c.capital {
				s -= 1 //it works: https://en.wikipedia.org/wiki/Greek_diacritics
				if c.spiritus == Lenis {
					return string(replacementChar) //not possible
				}
			}
			return string(s)
		}
		return string(replacementChar)
	}
	if c.accent == Circumflex {
		s := circumflexWithoutSpiritus
		if c.iotaSubscriptum {
			s += iotaWithCircumflexWithoutSpiritusOffset
		}
		letterOrder := map[Char]int{
			Alpha:   0,
			Eta:     1,
			Iota:    2,
			Upsilon: 3,
			Omega:   4,
		}
		if val, ok := letterOrder[c.name]; ok {
			s += val * letterOffset
			return string(s)
		}
		return string(replacementChar)
	}
	if c.iotaSubscriptum {
		s := iotaSubscriptumWithoutSpiritus
		letterOrder := map[Char]int{
			Alpha: 0,
			Eta:   1,
			Omega: 4,
		}
		if val, ok := letterOrder[c.name]; ok {
			s += val * letterOffset
		} else {
			return string(replacementChar)
		}
		if c.capital {
			s += 10
			return string(s)
		}
		accentOrder := map[Accent]int{
			Grave: 0,
			None:  1,
			Acute: 2,
		}
		if val, ok := accentOrder[c.accent]; ok {
			s += val
			return string(s)
		}
		return string(replacementChar)
	}
	if c.accent != None {
		if c.capital {
			s := accentendUpperCaseWithoutSpiritus
			letterOrder := map[Char]int{
				Alpha:   0,
				Epsilon: 1,
				Eta:     1,
				Iota:    2,
				Upsilon: 3,
				Omicron: 4,
				Omega:   4,
			}
			if val, ok := letterOrder[c.name]; ok {
				s += val * letterOffset
			} else {
				return string(replacementChar)
			}
			if c.name == Epsilon || c.name == Omicron {
				s -= 2
			}
			accentOrder := map[Accent]int{
				Grave: 0,
				Acute: 1,
			}
			if val, ok := accentOrder[c.accent]; ok {
				s += val
				return string(s)
			}
			return string(replacementChar)
		}
		s := accentendLowerCaseWithoutSpiritus
		letterOrder := map[Char]int{
			Alpha:   0,
			Epsilon: 1,
			Eta:     2,
			Iota:    3,
			Omicron: 4,
			Upsilon: 5,
			Omega:   6,
		}
		if val, ok := letterOrder[c.name]; ok {
			s += val * 2
		} else {
			return string(replacementChar)
		}
		accentOrder := map[Accent]int{
			Grave: 0,
			Acute: 1,
		}
		if val, ok := accentOrder[c.accent]; ok {
			s += val
			return string(s)
		}
		return string(replacementChar)
	}
	if c.capital {
		return string(upperCaseAlpha + c.name)
	}
	return string(lowerCaseAlpha + c.name)
}
<|endoftext|>