<commit_before>package util

import (
	"fmt"
	"math/rand"
	"os"
	"path"
	"path/filepath"
	"time"

	kapi "k8s.io/kubernetes/pkg/api"
	kerrs "k8s.io/kubernetes/pkg/api/errors"
	kclientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
	kcoreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
	"k8s.io/kubernetes/pkg/client/restclient"
	"k8s.io/kubernetes/pkg/fields"
	"k8s.io/kubernetes/pkg/quota"
	"k8s.io/kubernetes/pkg/util/wait"

	"github.com/openshift/origin/pkg/client"
	configapi "github.com/openshift/origin/pkg/cmd/server/api"
	"github.com/openshift/origin/pkg/cmd/server/origin"
	cmdutil "github.com/openshift/origin/pkg/cmd/util"
	"github.com/openshift/origin/pkg/cmd/util/clientcmd"
	"github.com/openshift/origin/pkg/cmd/util/tokencmd"
	oauthapi "github.com/openshift/origin/pkg/oauth/api"
	"github.com/openshift/origin/pkg/serviceaccounts"
)

// GetBaseDir returns the base directory used for test.
func GetBaseDir() string {
	return cmdutil.Env("BASETMPDIR", path.Join(os.TempDir(), "openshift-"+Namespace()))
}

func KubeConfigPath() string {
	return filepath.Join(GetBaseDir(), "openshift.local.config", "master", "admin.kubeconfig")
}

func GetClusterAdminKubeClient(adminKubeConfigFile string) (*kclientset.Clientset, error) {
	c, _, err := configapi.GetKubeClient(adminKubeConfigFile, nil)
	if err != nil {
		return nil, err
	}
	return c, nil
}

func GetClusterAdminClient(adminKubeConfigFile string) (*client.Client, error) {
	clientConfig, err := GetClusterAdminClientConfig(adminKubeConfigFile)
	if err != nil {
		return nil, err
	}
	osClient, err := client.New(clientConfig)
	if err != nil {
		return nil, err
	}
	return osClient, nil
}

func GetClusterAdminClientConfig(adminKubeConfigFile string) (*restclient.Config, error) {
	_, conf, err := configapi.GetKubeClient(adminKubeConfigFile, nil)
	if err != nil {
		return nil, err
	}
	return conf, nil
}

func GetClientForUser(clientConfig restclient.Config, username string) (*client.Client, kclientset.Interface, *restclient.Config, error) {
	token, err := tokencmd.RequestToken(&clientConfig, nil, username, "password")
	if err != nil {
		return nil, nil, nil, err
	}

	userClientConfig := clientcmd.AnonymousClientConfig(&clientConfig)
	userClientConfig.BearerToken = token

	kubeClientset, err := kclientset.NewForConfig(&userClientConfig)
	if err != nil {
		return nil, nil, nil, err
	}

	osClient, err := client.New(&userClientConfig)
	if err != nil {
		return nil, nil, nil, err
	}

	return osClient, kubeClientset, &userClientConfig, nil
}

func GetScopedClientForUser(adminClient *client.Client, clientConfig restclient.Config, username string, scopes []string) (*client.Client, kclientset.Interface, *restclient.Config, error) {
	// make sure the user exists
	if _, _, _, err := GetClientForUser(clientConfig, username); err != nil {
		return nil, nil, nil, err
	}
	user, err := adminClient.Users().Get(username)
	if err != nil {
		return nil, nil, nil, err
	}

	token := &oauthapi.OAuthAccessToken{
		ObjectMeta:  kapi.ObjectMeta{Name: fmt.Sprintf("%s-token-plus-some-padding-here-to-make-the-limit-%d", username, rand.Int())},
		ClientName:  origin.OpenShiftCLIClientID,
		ExpiresIn:   86400,
		Scopes:      scopes,
		RedirectURI: "https://127.0.0.1:12000/oauth/token/implicit",
		UserName:    user.Name,
		UserUID:     string(user.UID),
	}
	if _, err := adminClient.OAuthAccessTokens().Create(token); err != nil {
		return nil, nil, nil, err
	}

	scopedConfig := clientcmd.AnonymousClientConfig(&clientConfig)
	scopedConfig.BearerToken = token.Name
	kubeClient, err := kclientset.NewForConfig(&scopedConfig)
	if err != nil {
		return nil, nil, nil, err
	}
	osClient, err := client.New(&scopedConfig)
	if err != nil {
		return nil, nil, nil, err
	}
	return osClient, kubeClient, &scopedConfig, nil
}

func GetClientForServiceAccount(adminClient *kclientset.Clientset, clientConfig restclient.Config, namespace, name string) (*client.Client, *kclientset.Clientset, *restclient.Config, error) {
	_, err := adminClient.Core().Namespaces().Create(&kapi.Namespace{ObjectMeta: kapi.ObjectMeta{Name: namespace}})
	if err != nil && !kerrs.IsAlreadyExists(err) {
		return nil, nil, nil, err
	}

	sa, err := adminClient.Core().ServiceAccounts(namespace).Create(&kapi.ServiceAccount{ObjectMeta: kapi.ObjectMeta{Name: name}})
	if kerrs.IsAlreadyExists(err) {
		sa, err = adminClient.Core().ServiceAccounts(namespace).Get(name)
	}
	if err != nil {
		return nil, nil, nil, err
	}

	token := ""
	err = wait.Poll(time.Second, 30*time.Second, func() (bool, error) {
		selector := fields.OneTermEqualSelector(kapi.SecretTypeField, string(kapi.SecretTypeServiceAccountToken))
		secrets, err := adminClient.Core().Secrets(namespace).List(kapi.ListOptions{FieldSelector: selector})
		if err != nil {
			return false, err
		}
		for _, secret := range secrets.Items {
			if serviceaccounts.IsValidServiceAccountToken(sa, &secret) {
				token = string(secret.Data[kapi.ServiceAccountTokenKey])
				return true, nil
			}
		}
		return false, nil
	})
	if err != nil {
		return nil, nil, nil, err
	}

	saClientConfig := clientcmd.AnonymousClientConfig(&clientConfig)
	saClientConfig.BearerToken = token

	kubeClientset, err := kclientset.NewForConfig(&saClientConfig)
	if err != nil {
		return nil, nil, nil, err
	}

	osClient, err := client.New(&saClientConfig)
	if err != nil {
		return nil, nil, nil, err
	}

	return osClient, kubeClientset, &saClientConfig, nil
}

// WaitForResourceQuotaSync watches given resource quota until its hard limit is updated to match the desired
// spec or timeout occurs.
func WaitForResourceQuotaLimitSync(
	client kcoreclient.ResourceQuotaInterface,
	name string,
	hardLimit kapi.ResourceList,
	timeout time.Duration,
) error {

	startTime := time.Now()
	endTime := startTime.Add(timeout)

	expectedResourceNames := quota.ResourceNames(hardLimit)

	list, err := client.List(kapi.ListOptions{FieldSelector: fields.Set{"metadata.name": name}.AsSelector()})
	if err != nil {
		return err
	}

	for i := range list.Items {
		used := quota.Mask(list.Items[i].Status.Hard, expectedResourceNames)
		if isLimitSynced(used, hardLimit) {
			return nil
		}
	}

	rv := list.ResourceVersion
	w, err := client.Watch(kapi.ListOptions{FieldSelector: fields.Set{"metadata.name": name}.AsSelector(), ResourceVersion: rv})
	if err != nil {
		return err
	}
	defer w.Stop()

	for time.Now().Before(endTime) {
		select {
		case val, ok := <-w.ResultChan():
			if !ok {
				// reget and re-watch
				continue
			}
			if rq, ok := val.Object.(*kapi.ResourceQuota); ok {
				used := quota.Mask(rq.Status.Hard, expectedResourceNames)
				if isLimitSynced(used, hardLimit) {
					return nil
				}
			}
		case <-time.After(endTime.Sub(time.Now())):
			return wait.ErrWaitTimeout
		}
	}
	return wait.ErrWaitTimeout
}

func isLimitSynced(received, expected kapi.ResourceList) bool {
	resourceNames := quota.ResourceNames(expected)
	masked := quota.Mask(received, resourceNames)
	if len(masked) != len(expected) {
		return false
	}
	if le, _ := quota.LessThanOrEqual(masked, expected); !le {
		return false
	}
	if le, _ := quota.LessThanOrEqual(expected, masked); !le {
		return false
	}
	return true
}
<commit_msg>Snip a dependency from the e2e tests<commit_after>package util

import (
	"fmt"
	"math/rand"
	"os"
	"path"
	"path/filepath"
	"time"

	kapi "k8s.io/kubernetes/pkg/api"
	kerrs "k8s.io/kubernetes/pkg/api/errors"
	kclientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
	kcoreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
	"k8s.io/kubernetes/pkg/client/restclient"
	"k8s.io/kubernetes/pkg/fields"
	"k8s.io/kubernetes/pkg/quota"
	"k8s.io/kubernetes/pkg/util/wait"

	"github.com/openshift/origin/pkg/client"
	configapi "github.com/openshift/origin/pkg/cmd/server/api"
	cmdutil "github.com/openshift/origin/pkg/cmd/util"
	"github.com/openshift/origin/pkg/cmd/util/clientcmd"
	"github.com/openshift/origin/pkg/cmd/util/tokencmd"
	oauthapi "github.com/openshift/origin/pkg/oauth/api"
	"github.com/openshift/origin/pkg/serviceaccounts"
)

// GetBaseDir returns the base directory used for test.
func GetBaseDir() string {
	return cmdutil.Env("BASETMPDIR", path.Join(os.TempDir(), "openshift-"+Namespace()))
}

func KubeConfigPath() string {
	return filepath.Join(GetBaseDir(), "openshift.local.config", "master", "admin.kubeconfig")
}

func GetClusterAdminKubeClient(adminKubeConfigFile string) (*kclientset.Clientset, error) {
	c, _, err := configapi.GetKubeClient(adminKubeConfigFile, nil)
	if err != nil {
		return nil, err
	}
	return c, nil
}

func GetClusterAdminClient(adminKubeConfigFile string) (*client.Client, error) {
	clientConfig, err := GetClusterAdminClientConfig(adminKubeConfigFile)
	if err != nil {
		return nil, err
	}
	osClient, err := client.New(clientConfig)
	if err != nil {
		return nil, err
	}
	return osClient, nil
}

func GetClusterAdminClientConfig(adminKubeConfigFile string) (*restclient.Config, error) {
	_, conf, err := configapi.GetKubeClient(adminKubeConfigFile, nil)
	if err != nil {
		return nil, err
	}
	return conf, nil
}

func GetClientForUser(clientConfig restclient.Config, username string) (*client.Client, kclientset.Interface, *restclient.Config, error) {
	token, err := tokencmd.RequestToken(&clientConfig, nil, username, "password")
	if err != nil {
		return nil, nil, nil, err
	}

	userClientConfig := clientcmd.AnonymousClientConfig(&clientConfig)
	userClientConfig.BearerToken = token

	kubeClientset, err := kclientset.NewForConfig(&userClientConfig)
	if err != nil {
		return nil, nil, nil, err
	}

	osClient, err := client.New(&userClientConfig)
	if err != nil {
		return nil, nil, nil, err
	}

	return osClient, kubeClientset, &userClientConfig, nil
}

func GetScopedClientForUser(adminClient *client.Client, clientConfig restclient.Config, username string, scopes []string) (*client.Client, kclientset.Interface, *restclient.Config, error) {
	// make sure the user exists
	if _, _, _, err := GetClientForUser(clientConfig, username); err != nil {
		return nil, nil, nil, err
	}
	user, err := adminClient.Users().Get(username)
	if err != nil {
		return nil, nil, nil, err
	}

	token := &oauthapi.OAuthAccessToken{
		ObjectMeta:  kapi.ObjectMeta{Name: fmt.Sprintf("%s-token-plus-some-padding-here-to-make-the-limit-%d", username, rand.Int())},
		ClientName:  "openshift-challenging-client",
		ExpiresIn:   86400,
		Scopes:      scopes,
		RedirectURI: "https://127.0.0.1:12000/oauth/token/implicit",
		UserName:    user.Name,
		UserUID:     string(user.UID),
	}
	if _, err := adminClient.OAuthAccessTokens().Create(token); err != nil {
		return nil, nil, nil, err
	}

	scopedConfig := clientcmd.AnonymousClientConfig(&clientConfig)
	scopedConfig.BearerToken = token.Name
	kubeClient, err := kclientset.NewForConfig(&scopedConfig)
	if err != nil {
		return nil, nil, nil, err
	}
	osClient, err := client.New(&scopedConfig)
	if err != nil {
		return nil, nil, nil, err
	}
	return osClient, kubeClient, &scopedConfig, nil
}

func GetClientForServiceAccount(adminClient *kclientset.Clientset, clientConfig restclient.Config, namespace, name string) (*client.Client, *kclientset.Clientset, *restclient.Config, error) {
	_, err := adminClient.Core().Namespaces().Create(&kapi.Namespace{ObjectMeta: kapi.ObjectMeta{Name: namespace}})
	if err != nil && !kerrs.IsAlreadyExists(err) {
		return nil, nil, nil, err
	}

	sa, err := adminClient.Core().ServiceAccounts(namespace).Create(&kapi.ServiceAccount{ObjectMeta: kapi.ObjectMeta{Name: name}})
	if kerrs.IsAlreadyExists(err) {
		sa, err = adminClient.Core().ServiceAccounts(namespace).Get(name)
	}
	if err != nil {
		return nil, nil, nil, err
	}

	token := ""
	err = wait.Poll(time.Second, 30*time.Second, func() (bool, error) {
		selector := fields.OneTermEqualSelector(kapi.SecretTypeField, string(kapi.SecretTypeServiceAccountToken))
		secrets, err := adminClient.Core().Secrets(namespace).List(kapi.ListOptions{FieldSelector: selector})
		if err != nil {
			return false, err
		}
		for _, secret := range secrets.Items {
			if serviceaccounts.IsValidServiceAccountToken(sa, &secret) {
				token = string(secret.Data[kapi.ServiceAccountTokenKey])
				return true, nil
			}
		}
		return false, nil
	})
	if err != nil {
		return nil, nil, nil, err
	}

	saClientConfig := clientcmd.AnonymousClientConfig(&clientConfig)
	saClientConfig.BearerToken = token

	kubeClientset, err := kclientset.NewForConfig(&saClientConfig)
	if err != nil {
		return nil, nil, nil, err
	}

	osClient, err := client.New(&saClientConfig)
	if err != nil {
		return nil, nil, nil, err
	}

	return osClient, kubeClientset, &saClientConfig, nil
}

// WaitForResourceQuotaSync watches given resource quota until its hard limit is updated to match the desired
// spec or timeout occurs.
func WaitForResourceQuotaLimitSync(
	client kcoreclient.ResourceQuotaInterface,
	name string,
	hardLimit kapi.ResourceList,
	timeout time.Duration,
) error {

	startTime := time.Now()
	endTime := startTime.Add(timeout)

	expectedResourceNames := quota.ResourceNames(hardLimit)

	list, err := client.List(kapi.ListOptions{FieldSelector: fields.Set{"metadata.name": name}.AsSelector()})
	if err != nil {
		return err
	}

	for i := range list.Items {
		used := quota.Mask(list.Items[i].Status.Hard, expectedResourceNames)
		if isLimitSynced(used, hardLimit) {
			return nil
		}
	}

	rv := list.ResourceVersion
	w, err := client.Watch(kapi.ListOptions{FieldSelector: fields.Set{"metadata.name": name}.AsSelector(), ResourceVersion: rv})
	if err != nil {
		return err
	}
	defer w.Stop()

	for time.Now().Before(endTime) {
		select {
		case val, ok := <-w.ResultChan():
			if !ok {
				// reget and re-watch
				continue
			}
			if rq, ok := val.Object.(*kapi.ResourceQuota); ok {
				used := quota.Mask(rq.Status.Hard, expectedResourceNames)
				if isLimitSynced(used, hardLimit) {
					return nil
				}
			}
		case <-time.After(endTime.Sub(time.Now())):
			return wait.ErrWaitTimeout
		}
	}
	return wait.ErrWaitTimeout
}

func isLimitSynced(received, expected kapi.ResourceList) bool {
	resourceNames := quota.ResourceNames(expected)
	masked := quota.Mask(received, resourceNames)
	if len(masked) != len(expected) {
		return false
	}
	if le, _ := quota.LessThanOrEqual(masked, expected); !le {
		return false
	}
	if le, _ := quota.LessThanOrEqual(expected, masked); !le {
		return false
	}
	return true
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path"
	"path/filepath"
	"sort"
	"strconv"
	"strings"

	"image"
	"image/draw"
	"image/png"
)

type Size struct {
	x, y int
}

func (a Size) Equal(b Size) bool {
	return a.x == b.x && a.y == b.y
}

func (a Size) Larger(b Size) bool {
	return b.x < a.x && b.y < a.y
}

func (a Size) Smaller(b Size) bool {
	return !a.Larger(b)
}

type sprite struct {
	name string
	img  image.Image
	rect image.Rectangle
	area int
	size Size
}

type ByArea []sprite

func (a ByArea) Len() int           { return len(a) }
func (a ByArea) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByArea) Less(i, j int) bool { return a[i].area < a[j].area }

type Node struct {
	child [2]*Node
	rect  image.Rectangle
	img   *sprite
}

func (n *Node) size() Size {
	return Size{n.rect.Dx(), n.rect.Dy()}
}

func (n *Node) print() {
	fmt.Println(n)
	if n.child[0] != nil {
		n.child[0].print()
	}
	if n.child[1] != nil {
		n.child[1].print()
	}
}

func (n *Node) isLeaf() bool {
	return n.child[0] == nil || n.child[1] == nil
}

func (n *Node) insert(img *sprite) *Node {
	if !n.isLeaf() {
		node := n.child[0].insert(img)

		if node != nil {
			return node
		} else {
			return n.child[1].insert(img)
		}
	}

	// there is already an image in this node
	if n.img != nil {
		return nil
	}

	// space too small
	if n.rect.Dx() < img.size.x || n.rect.Dy() < img.size.y {
		return nil
	}

	// just right
	if n.rect.Dx() == img.size.x && n.rect.Dy() == img.size.y {
		n.img = img
		return n
	}

	// the space that is left will be large enough to split
	n.split(img)

	return n.child[0].insert(img)
}

func (n *Node) split(img *sprite) {
	dx := n.rect.Dx() - img.size.x
	dy := n.rect.Dy() - img.size.y

	if dx > dy {
		n.child[0] = &Node{rect: image.Rect(
			n.rect.Min.X,
			n.rect.Min.Y,
			n.rect.Min.X+img.size.x,
			n.rect.Max.Y)}
		n.child[1] = &Node{rect: image.Rect(
			n.rect.Min.X+img.size.x,
			n.rect.Min.Y,
			n.rect.Max.X,
			n.rect.Max.Y)}
	} else {
		n.child[0] = &Node{rect: image.Rect(
			n.rect.Min.X,
			n.rect.Min.Y,
			n.rect.Max.X,
			n.rect.Min.Y+img.size.y)}
		n.child[1] = &Node{rect: image.Rect(
			n.rect.Min.X,
			n.rect.Min.Y+img.size.y,
			n.rect.Max.X,
			n.rect.Max.Y)}
	}

}

func main() {
	var space int
	var dim string

	flag.IntVar(&space, "space", 1, "space added between images")
	flag.StringVar(&dim, "dimensions", "1024x1024", "atlas size")

	flag.Parse()

	args := flag.Args()

	inputDir := args[0]
	outputName := args[1]

	dimX, dimY, err := parseDimensions(dim)
	if err != nil {
		log.Fatal(err)
	}

	files, _ := ioutil.ReadDir(inputDir)
	sprites := make([]sprite, len(files))

	for i := range sprites {
		s := readSprite(inputDir, files[i].Name(), space)
		sprites[i] = s
	}

	// we want to place the largest sprite first
	sort.Sort(sort.Reverse(ByArea(sprites)))

	// the final image
	dst := image.NewRGBA(image.Rect(0, 0, dimX, dimY))

	n := Node{rect: image.Rect(0, 0, dimX, dimY)}

	for i := range sprites {
		s := &sprites[i]
		node := n.insert(s)
		if node != nil {
			draw.Draw(dst, node.rect, s.img, image.ZP, draw.Src)
		} else {
			log.Fatalf("could not place %s\n", s.name)
		}

	}

	writer, err := os.Create(outputName)
	err = png.Encode(writer, dst)
	if err != nil {
		log.Fatal(err)
	}
}

func parseDimensions(dim string) (dimX, dimY int, err error) {
	dims := strings.Split(dim, "x")
	if len(dims) != 2 {
		err = fmt.Errorf("couldn't parse dimension %s\n", dims)
		return
	}

	dimX, err = strconv.Atoi(dims[0])
	if err != nil {
		return
	}

	dimY, err = strconv.Atoi(dims[1])
	if err != nil {
		return
	}

	return
}

func readSprite(dir, name string, space int) (s sprite) {
	path := path.Join(dir, name)
	reader, err := os.Open(path)
	if err != nil {
		log.Fatal(err)
	}
	defer reader.Close()

	img, _, err := image.Decode(reader)
	if err != nil {
		log.Fatal(err)
	}

	s.name = strings.TrimSuffix(name, filepath.Ext(name))
	s.img = img
	s.rect = img.Bounds()
	s.size = Size{s.rect.Dx() + space, s.rect.Dy() + space}
	s.area = s.size.x * s.size.y
	return
}
<commit_msg>Add offset to sprite<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path"
	"path/filepath"
	"sort"
	"strconv"
	"strings"

	"image"
	"image/draw"
	"image/png"
)

type Size struct {
	x, y int
}

func (a Size) Equal(b Size) bool {
	return a.x == b.x && a.y == b.y
}

func (a Size) Larger(b Size) bool {
	return b.x < a.x && b.y < a.y
}

func (a Size) Smaller(b Size) bool {
	return !a.Larger(b)
}

type sprite struct {
	name   string
	img    image.Image
	area   int
	offset image.Point
	size   Size
}

type ByArea []sprite

func (a ByArea) Len() int           { return len(a) }
func (a ByArea) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByArea) Less(i, j int) bool { return a[i].area < a[j].area }

type Node struct {
	child [2]*Node
	rect  image.Rectangle
	img   *sprite
}

func (n *Node) size() Size {
	return Size{n.rect.Dx(), n.rect.Dy()}
}

func (n *Node) print() {
	fmt.Println(n)
	if n.child[0] != nil {
		n.child[0].print()
	}
	if n.child[1] != nil {
		n.child[1].print()
	}
}

func (n *Node) isLeaf() bool {
	return n.child[0] == nil || n.child[1] == nil
}

func (n *Node) insert(img *sprite) *Node {
	if !n.isLeaf() {
		node := n.child[0].insert(img)

		if node != nil {
			return node
		} else {
			return n.child[1].insert(img)
		}
	}

	// there is already an image in this node
	if n.img != nil {
		return nil
	}

	// space too small
	if n.rect.Dx() < img.size.x || n.rect.Dy() < img.size.y {
		return nil
	}

	// just right
	if n.rect.Dx() == img.size.x && n.rect.Dy() == img.size.y {
		img.offset = n.rect.Min
		n.img = img
		return n
	}

	// the space that is left will be large enough to split
	n.split(img)

	return n.child[0].insert(img)
}

func (n *Node) split(img *sprite) {
	dx := n.rect.Dx() - img.size.x
	dy := n.rect.Dy() - img.size.y

	if dx > dy {
		n.child[0] = &Node{rect: image.Rect(
			n.rect.Min.X,
			n.rect.Min.Y,
			n.rect.Min.X+img.size.x,
			n.rect.Max.Y)}
		n.child[1] = &Node{rect: image.Rect(
			n.rect.Min.X+img.size.x,
			n.rect.Min.Y,
			n.rect.Max.X,
			n.rect.Max.Y)}
	} else {
		n.child[0] = &Node{rect: image.Rect(
			n.rect.Min.X,
			n.rect.Min.Y,
			n.rect.Max.X,
			n.rect.Min.Y+img.size.y)}
		n.child[1] = &Node{rect: image.Rect(
			n.rect.Min.X,
			n.rect.Min.Y+img.size.y,
			n.rect.Max.X,
			n.rect.Max.Y)}
	}

}

func main() {
	var space int
	var dim string

	flag.IntVar(&space, "space", 1, "space added between images")
	flag.StringVar(&dim, "dimensions", "1024x1024", "atlas size")

	flag.Parse()

	args := flag.Args()

	inputDir := args[0]
	outputName := args[1]

	dimX, dimY, err := parseDimensions(dim)
	if err != nil {
		log.Fatal(err)
	}

	files, _ := ioutil.ReadDir(inputDir)
	sprites := make([]sprite, len(files))

	for i := range sprites {
		s := readSprite(inputDir, files[i].Name(), space)
		sprites[i] = s
	}

	// we want to place the largest sprite first
	sort.Sort(sort.Reverse(ByArea(sprites)))

	// the final image
	dst := image.NewRGBA(image.Rect(0, 0, dimX, dimY))

	n := Node{rect: image.Rect(0, 0, dimX, dimY)}

	for i := range sprites {
		s := &sprites[i]
		node := n.insert(s)
		if node != nil {
			draw.Draw(dst, node.rect, s.img, image.ZP, draw.Src)
		} else {
			log.Fatalf("could not place %s\n", s.name)
		}

	}

	writer, err := os.Create(outputName)
	err = png.Encode(writer, dst)
	if err != nil {
		log.Fatal(err)
	}
}

func parseDimensions(dim string) (dimX, dimY int, err error) {
	dims := strings.Split(dim, "x")
	if len(dims) != 2 {
		err = fmt.Errorf("couldn't parse dimension %s\n", dims)
		return
	}

	dimX, err = strconv.Atoi(dims[0])
	if err != nil {
		return
	}

	dimY, err = strconv.Atoi(dims[1])
	if err != nil {
		return
	}

	return
}

func readSprite(dir, name string, space int) (s sprite) {
	path := path.Join(dir, name)
	reader, err := os.Open(path)
	if err != nil {
		log.Fatal(err)
	}
	defer reader.Close()

	img, _, err := image.Decode(reader)
	if err != nil {
		log.Fatal(err)
	}

	s.name = strings.TrimSuffix(name, filepath.Ext(name))
	s.img = img
	rect := img.Bounds()
	s.size = Size{rect.Dx() + space, rect.Dy() + space}
	s.area = s.size.x * s.size.y
	return
}
<|endoftext|>


<commit_before>package radius

import (
	"bytes"
	"crypto/md5"
	"crypto/rand"
	"encoding/binary"
	"errors"
)

// MaxPacketLength is the maximum possible wire length of a RADIUS packet.
const MaxPacketLength = 4095

// Packet is a RADIUS packet.
type Packet struct {
	Code          Code
	Identifier    byte
	Authenticator [16]byte
	Secret        []byte
	Attributes
}

// New creates a new packet with the Code, Secret fields set to the given
// values. The returned packet's Identifier, Authenticator are filled with
// random values.
func New(code Code, secret []byte) *Packet {
	var buff [17]byte
	if _, err := rand.Read(buff[:]); err != nil {
		panic(err)
	}

	packet := &Packet{
		Code:       code,
		Identifier: buff[0],
		Secret:     secret,
		Attributes: make(Attributes),
	}
	copy(packet.Authenticator[:], buff[1:])
	return packet
}

// Parse parses an encoded RADIUS packet b. An error is returned if the packet
// is malformed.
func Parse(b, secret []byte) (*Packet, error) {
	if len(b) < 20 {
		return nil, errors.New("radius: packet not at least 20 bytes long")
	}

	length := int(binary.BigEndian.Uint16(b[2:4]))
	if length < 20 || length > MaxPacketLength || len(b) > length {
		return nil, errors.New("radius: invalid packet length")
	}

	attrs, err := ParseAttributes(b[20:])
	if err != nil {
		return nil, err
	}

	packet := &Packet{
		Code:       Code(b[0]),
		Identifier: b[1],
		Secret:     secret,
		Attributes: attrs,
	}
	copy(packet.Authenticator[:], b[4:20])
	return packet, nil
}

// Response returns a new packet that has the same identifier, secret, and
// authenticator as the current packet.
func (p *Packet) Response(code Code) *Packet {
	q := &Packet{
		Code:       code,
		Identifier: p.Identifier,
		Secret:     p.Secret,
		Attributes: make(Attributes),
	}
	copy(q.Authenticator[:], p.Authenticator[:])
	return q
}

// Encode encodes the RADIUS packet to wire format. An error is returned if the
// encoded packet is too long (due to its Attributes), or if the packet has an
// unknown Code.
func (p *Packet) Encode() ([]byte, error) {
	size := 20 + p.Attributes.wireSize()
	if size > MaxPacketLength {
		return nil, errors.New("encoded packet is too long")
	}

	b := make([]byte, size)
	b[0] = byte(p.Code)
	b[1] = byte(p.Identifier)
	binary.BigEndian.PutUint16(b[2:4], uint16(size))
	p.Attributes.encodeTo(b[20:])

	switch p.Code {
	case CodeAccessRequest:
		copy(b[4:20], p.Authenticator[:])
	case CodeAccessAccept, CodeAccessReject, CodeAccountingRequest, CodeAccountingResponse, CodeAccessChallenge, CodeDisconnectRequest, CodeCoARequest:
		hash := md5.New()
		hash.Write(b[:4])
		switch p.Code {
		case CodeAccountingRequest, CodeDisconnectRequest, CodeCoARequest:
			var nul [16]byte
			hash.Write(nul[:])
		default:
			hash.Write(p.Authenticator[:])
		}
		hash.Write(b[20:])
		hash.Write(p.Secret)
		hash.Sum(b[4:4:20])
	default:
		return nil, errors.New("radius: unknown Packet Code")
	}

	return b, nil
}

// IsAuthenticResponse returns if the given RADIUS response is an authentic
// response to the given request.
func IsAuthenticResponse(response, request, secret []byte) bool {
	if len(response) < 20 || len(request) < 20 || len(secret) == 0 {
		return false
	}

	hash := md5.New()
	hash.Write(response[:4])
	hash.Write(request[4:20])
	hash.Write(response[20:])
	hash.Write(secret)
	var sum [md5.Size]byte
	return bytes.Equal(hash.Sum(sum[:0]), response[4:20])
}

// IsAuthenticRequest returns if the given RADIUS request is an authentic
// request using the given secret.
func IsAuthenticRequest(request, secret []byte) bool {
	if len(request) < 20 || len(secret) == 0 {
		return false
	}

	switch Code(request[0]) {
	case CodeAccessRequest:
		return true
	case CodeAccountingRequest, CodeDisconnectRequest, CodeCoARequest:
		hash := md5.New()
		hash.Write(request[:4])
		var nul [16]byte
		hash.Write(nul[:])
		hash.Write(request[20:])
		hash.Write(secret)
		var sum [md5.Size]byte
		return bytes.Equal(hash.Sum(sum[:0]), request[4:20])
	default:
		return false
	}
}
<commit_msg>document that New can panic<commit_after>package radius

import (
	"bytes"
	"crypto/md5"
	"crypto/rand"
	"encoding/binary"
	"errors"
)

// MaxPacketLength is the maximum possible wire length of a RADIUS packet.
const MaxPacketLength = 4095

// Packet is a RADIUS packet.
type Packet struct {
	Code          Code
	Identifier    byte
	Authenticator [16]byte
	Secret        []byte
	Attributes
}

// New creates a new packet with the Code, Secret fields set to the given
// values. The returned packet's Identifier and Authenticator fields are filled
// with random values.
//
// The function panics if not enough random data could be generated.
func New(code Code, secret []byte) *Packet {
	var buff [17]byte
	if _, err := rand.Read(buff[:]); err != nil {
		panic(err)
	}

	packet := &Packet{
		Code:       code,
		Identifier: buff[0],
		Secret:     secret,
		Attributes: make(Attributes),
	}
	copy(packet.Authenticator[:], buff[1:])
	return packet
}

// Parse parses an encoded RADIUS packet b. An error is returned if the packet
// is malformed.
func Parse(b, secret []byte) (*Packet, error) {
	if len(b) < 20 {
		return nil, errors.New("radius: packet not at least 20 bytes long")
	}

	length := int(binary.BigEndian.Uint16(b[2:4]))
	if length < 20 || length > MaxPacketLength || len(b) > length {
		return nil, errors.New("radius: invalid packet length")
	}

	attrs, err := ParseAttributes(b[20:])
	if err != nil {
		return nil, err
	}

	packet := &Packet{
		Code:       Code(b[0]),
		Identifier: b[1],
		Secret:     secret,
		Attributes: attrs,
	}
	copy(packet.Authenticator[:], b[4:20])
	return packet, nil
}

// Response returns a new packet that has the same identifier, secret, and
// authenticator as the current packet.
func (p *Packet) Response(code Code) *Packet {
	q := &Packet{
		Code:       code,
		Identifier: p.Identifier,
		Secret:     p.Secret,
		Attributes: make(Attributes),
	}
	copy(q.Authenticator[:], p.Authenticator[:])
	return q
}

// Encode encodes the RADIUS packet to wire format. An error is returned if the
// encoded packet is too long (due to its Attributes), or if the packet has an
// unknown Code.
func (p *Packet) Encode() ([]byte, error) {
	size := 20 + p.Attributes.wireSize()
	if size > MaxPacketLength {
		return nil, errors.New("encoded packet is too long")
	}

	b := make([]byte, size)
	b[0] = byte(p.Code)
	b[1] = byte(p.Identifier)
	binary.BigEndian.PutUint16(b[2:4], uint16(size))
	p.Attributes.encodeTo(b[20:])

	switch p.Code {
	case CodeAccessRequest:
		copy(b[4:20], p.Authenticator[:])
	case CodeAccessAccept, CodeAccessReject, CodeAccountingRequest, CodeAccountingResponse, CodeAccessChallenge, CodeDisconnectRequest, CodeCoARequest:
		hash := md5.New()
		hash.Write(b[:4])
		switch p.Code {
		case CodeAccountingRequest, CodeDisconnectRequest, CodeCoARequest:
			var nul [16]byte
			hash.Write(nul[:])
		default:
			hash.Write(p.Authenticator[:])
		}
		hash.Write(b[20:])
		hash.Write(p.Secret)
		hash.Sum(b[4:4:20])
	default:
		return nil, errors.New("radius: unknown Packet Code")
	}

	return b, nil
}

// IsAuthenticResponse returns if the given RADIUS response is an authentic
// response to the given request.
func IsAuthenticResponse(response, request, secret []byte) bool {
	if len(response) < 20 || len(request) < 20 || len(secret) == 0 {
		return false
	}

	hash := md5.New()
	hash.Write(response[:4])
	hash.Write(request[4:20])
	hash.Write(response[20:])
	hash.Write(secret)
	var sum [md5.Size]byte
	return bytes.Equal(hash.Sum(sum[:0]), response[4:20])
}

// IsAuthenticRequest returns if the given RADIUS request is an authentic
// request using the given secret.
func IsAuthenticRequest(request, secret []byte) bool {
	if len(request) < 20 || len(secret) == 0 {
		return false
	}

	switch Code(request[0]) {
	case CodeAccessRequest:
		return true
	case CodeAccountingRequest, CodeDisconnectRequest, CodeCoARequest:
		hash := md5.New()
		hash.Write(request[:4])
		var nul [16]byte
		hash.Write(nul[:])
		hash.Write(request[20:])
		hash.Write(secret)
		var sum [md5.Size]byte
		return bytes.Equal(hash.Sum(sum[:0]), request[4:20])
	default:
		return false
	}
}
<|endoftext|>


<commit_before>package packit

import (
	"archive/tar"
	"fmt"
	"io"
	"os"
	"strings"
	"sync"

	"github.com/c4milo/fastwalk"
	"github.com/dsnet/compress/bzip2"
	"github.com/klauspost/compress/zip"
	gzip "github.com/klauspost/pgzip"
	"github.com/pkg/errors"
	"github.com/ulikunitz/xz"
)

// Zip walks the file tree rooted at root and archives it into the output stream using zip
// algorithm.
func Zip(root string, out io.ReadWriter) {
	zw := zip.NewWriter(out)
	defer func() {
		if err := zw.Close(); err != nil {
			fmt.Printf("packit/zip: failed closing archive: %v\n", err)
		}
	}()

	sep := string(os.PathSeparator)
	m := &sync.Mutex{}
	fastwalk.Walk(root, func(path string, mode os.FileMode) error {
		// This function gets invoked concurrently for each file or directory found.
		// But, the zip package does not support parallelism, so we need to make sure
		// a file header is followed by its correspondent content.
		m.Lock()
		defer m.Unlock()

		// Appending a final "/" is critical to let the decompressor know this is a directory.
		if mode.IsDir() && !strings.HasSuffix(path, sep) {
			path += sep
		}

		fi, err := os.Lstat(path)
		if err != nil {
			return errors.Wrapf(err, "packit/zip: failed getting file stats for: %s", path)
		}

		fh, err := zip.FileInfoHeader(fi)
		if err != nil {
			return errors.Wrapf(err, "packit/zip: failed populating file header for: %s", path)
		}

		// fi.Name returns the base name and we need the full path.
		fh.Name = path

		fw, err := zw.CreateHeader(fh)
		if err != nil {
			return errors.Wrapf(err, "packit/zip: failed creating header for: %s", path)
		}

		// For directories, we only need to add the header in the zip file.
		if mode.IsDir() {
			return nil
		}

		f, err := os.Open(path)
		if err != nil {
			return errors.Wrapf(err, "packit/zip: failed opening file at: %s", path)
		}

		defer func() {
			if err := f.Close(); err != nil {
				fmt.Printf("packit/zip: failed closing file %q: %v\n", path, err)
			}
		}()

		_, err = io.Copy(fw, f)
		if err != nil {
			return errors.Wrapf(err, "packit/zip: failed packing data from: %s", path)
		}

		return nil
	})
}

// Tar walks the file tree rooted at root and archives it all using Tar.
func Tar(root string, out io.ReadWriter) {
	tw := tar.NewWriter(out)
	defer func() {
		if err := tw.Close(); err != nil {
			fmt.Printf("packit/tar: failed closing archive: %v\n", err)
		}
	}()

	sep := string(os.PathSeparator)
	m := &sync.Mutex{}
	fastwalk.Walk(root, func(path string, mode os.FileMode) error {
		m.Lock()
		defer m.Unlock()

		// Appending a trailing path separator is critical to let the decompressor
		// know this is a directory.
		if mode.IsDir() && !strings.HasSuffix(path, sep) {
			path += sep
		}

		fi, err := os.Lstat(path)
		if err != nil {
			return errors.Wrapf(err, "packit/tar: failed getting file stats for: %s", path)
		}

		fh, err := tar.FileInfoHeader(fi, "")
		if err != nil {
			return errors.Wrapf(err, "packit/tar: failed populating file header for: %s", path)
		}

		// fi.Name returns the base name and we need the full path.
		fh.Name = path

		tw.WriteHeader(fh)
		if err != nil {
			return errors.Wrapf(err, "packit/tar: failed creating header for: %s", path)
		}

		// For directories, we only need to add the header in the tar file.
		if mode.IsDir() {
			return nil
		}

		f, err := os.Open(path)
		if err != nil {
			return errors.Wrapf(err, "packit/tar: failed opening file at: %s", path)
		}

		defer func() {
			if err := f.Close(); err != nil {
				fmt.Printf("packit/tar: failed closing file: %s\n", path)
			}
		}()

		_, err = io.Copy(tw, f)
		if err != nil {
			return errors.Wrapf(err, "packit/tar: failed packing data from: %s", path)
		}
		return nil
	})
}

// Gzip compresses an input stream using gzip.
func Gzip(in io.Reader, out io.ReadWriter) error {
	gw := gzip.NewWriter(out)
	defer func() {
		if err := gw.Close(); err != nil {
			fmt.Printf("packit/gzip: failed closing stream: %v\n", err)
		}
	}()

	if _, err := io.Copy(gw, in); err != nil {
		return err
	}
	return nil
}

// Xz compresses an input stream using xz.
func Xz(in io.Reader, out io.ReadWriter) error {
	xw, err := xz.NewWriter(out)
	if err != nil {
		return err
	}

	defer func() {
		if err := xw.Close(); err != nil {
			fmt.Printf("packit/xz: failed closing stream: %v\n", err)
		}
	}()

	if _, err := io.Copy(xw, in); err != nil {
		return err
	}
	return nil
}

// Bzip2 compresses an input stream using bzip2.
func Bzip2(in io.Reader, out io.ReadWriter) error {
	bw, err := bzip2.NewWriter(out, nil)
	if err != nil {
		return err
	}

	defer func() {
		if err := bw.Close(); err != nil {
			fmt.Printf("packit/bzip2: failed closing stream: %v\n", err)
		}
	}()

	if _, err := io.Copy(bw, in); err != nil {
		return err
	}
	return nil
}
<commit_msg>Use only the io.Writer intarface<commit_after>package packit

import (
	"archive/tar"
	"fmt"
	"io"
	"os"
	"strings"
	"sync"

	"github.com/c4milo/fastwalk"
	"github.com/dsnet/compress/bzip2"
	"github.com/klauspost/compress/zip"
	gzip "github.com/klauspost/pgzip"
	"github.com/pkg/errors"
	"github.com/ulikunitz/xz"
)

// Zip walks the file tree rooted at root and archives it into the output stream using zip
// algorithm.
func Zip(root string, out io.Writer) {
	zw := zip.NewWriter(out)
	defer func() {
		if err := zw.Close(); err != nil {
			fmt.Printf("packit/zip: failed closing archive: %v\n", err)
		}
	}()

	sep := string(os.PathSeparator)
	m := &sync.Mutex{}
	fastwalk.Walk(root, func(path string, mode os.FileMode) error {
		// This function gets invoked concurrently for each file or directory found.
		// But, the zip package does not support parallelism, so we need to make sure
		// a file header is followed by its correspondent content.
		m.Lock()
		defer m.Unlock()

		// Appending a final "/" is critical to let the decompressor know this is a directory.
		if mode.IsDir() && !strings.HasSuffix(path, sep) {
			path += sep
		}

		fi, err := os.Lstat(path)
		if err != nil {
			return errors.Wrapf(err, "packit/zip: failed getting file stats for: %s", path)
		}

		fh, err := zip.FileInfoHeader(fi)
		if err != nil {
			return errors.Wrapf(err, "packit/zip: failed populating file header for: %s", path)
		}

		// fi.Name returns the base name and we need the full path.
		fh.Name = path

		fw, err := zw.CreateHeader(fh)
		if err != nil {
			return errors.Wrapf(err, "packit/zip: failed creating header for: %s", path)
		}

		// For directories, we only need to add the header in the zip file.
		if mode.IsDir() {
			return nil
		}

		f, err := os.Open(path)
		if err != nil {
			return errors.Wrapf(err, "packit/zip: failed opening file at: %s", path)
		}

		defer func() {
			if err := f.Close(); err != nil {
				fmt.Printf("packit/zip: failed closing file %q: %v\n", path, err)
			}
		}()

		_, err = io.Copy(fw, f)
		if err != nil {
			return errors.Wrapf(err, "packit/zip: failed packing data from: %s", path)
		}

		return nil
	})
}

// Tar walks the file tree rooted at root and archives it all using Tar.
func Tar(root string, out io.Writer) {
	tw := tar.NewWriter(out)
	defer func() {
		if err := tw.Close(); err != nil {
			fmt.Printf("packit/tar: failed closing archive: %v\n", err)
		}
	}()

	sep := string(os.PathSeparator)
	m := &sync.Mutex{}
	fastwalk.Walk(root, func(path string, mode os.FileMode) error {
		m.Lock()
		defer m.Unlock()

		// Appending a trailing path separator is critical to let the decompressor
		// know this is a directory.
		if mode.IsDir() && !strings.HasSuffix(path, sep) {
			path += sep
		}

		fi, err := os.Lstat(path)
		if err != nil {
			return errors.Wrapf(err, "packit/tar: failed getting file stats for: %s", path)
		}

		fh, err := tar.FileInfoHeader(fi, "")
		if err != nil {
			return errors.Wrapf(err, "packit/tar: failed populating file header for: %s", path)
		}

		// fi.Name returns the base name and we need the full path.
		fh.Name = path

		tw.WriteHeader(fh)
		if err != nil {
			return errors.Wrapf(err, "packit/tar: failed creating header for: %s", path)
		}

		// For directories, we only need to add the header in the tar file.
		if mode.IsDir() {
			return nil
		}

		f, err := os.Open(path)
		if err != nil {
			return errors.Wrapf(err, "packit/tar: failed opening file at: %s", path)
		}

		defer func() {
			if err := f.Close(); err != nil {
				fmt.Printf("packit/tar: failed closing file: %s\n", path)
			}
		}()

		_, err = io.Copy(tw, f)
		if err != nil {
			return errors.Wrapf(err, "packit/tar: failed packing data from: %s", path)
		}
		return nil
	})
}

// Gzip compresses an input stream using gzip.
func Gzip(in io.Reader, out io.Writer) error {
	gw := gzip.NewWriter(out)
	defer func() {
		if err := gw.Close(); err != nil {
			fmt.Printf("packit/gzip: failed closing stream: %v\n", err)
		}
	}()

	if _, err := io.Copy(gw, in); err != nil {
		return err
	}
	return nil
}

// Xz compresses an input stream using xz.
func Xz(in io.Reader, out io.Writer) error {
	xw, err := xz.NewWriter(out)
	if err != nil {
		return err
	}

	defer func() {
		if err := xw.Close(); err != nil {
			fmt.Printf("packit/xz: failed closing stream: %v\n", err)
		}
	}()

	if _, err := io.Copy(xw, in); err != nil {
		return err
	}
	return nil
}

// Bzip2 compresses an input stream using bzip2.
func Bzip2(in io.Reader, out io.Writer) error {
	bw, err := bzip2.NewWriter(out, nil)
	if err != nil {
		return err
	}

	defer func() {
		if err := bw.Close(); err != nil {
			fmt.Printf("packit/bzip2: failed closing stream: %v\n", err)
		}
	}()

	if _, err := io.Copy(bw, in); err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>/*
Copyright 2018 Gravitational, Inc.

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

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

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

package backend

import (
	"context"
	"os"
	"testing"
	"time"

	"github.com/gravitational/teleport/api/types"
	"github.com/gravitational/teleport/lib/utils"
	"github.com/gravitational/trace"
	"github.com/jonboulle/clockwork"
	log "github.com/sirupsen/logrus"
	"gopkg.in/check.v1"
)

func TestInit(t *testing.T) { check.TestingT(t) }

type BufferSuite struct{}

var _ = check.Suite(&BufferSuite{})

func (s *BufferSuite) SetUpSuite(_ *check.C) {
	log.StandardLogger().Hooks = make(log.LevelHooks)
	log.SetFormatter(utils.NewDefaultTextFormatter(trace.IsTerminal(os.Stderr)))
	if testing.Verbose() {
		log.SetLevel(log.DebugLevel)
		log.SetOutput(os.Stdout)
	}
}

func (s *BufferSuite) list(c *check.C, bufferSize int, listSize int) {
	b := NewCircularBuffer(
		BufferCapacity(bufferSize),
	)
	defer b.Close()
	b.SetInit()
	s.listWithBuffer(c, b, bufferSize, listSize)
}

func (s *BufferSuite) listWithBuffer(c *check.C, b *CircularBuffer, bufferSize int, listSize int) {
	// empty by default
	expectEvents(c, b, nil)

	elements := makeIDs(listSize)

	// push through all elements of the list and make sure
	// the slice always matches
	for i := 0; i < len(elements); i++ {
		b.Emit(Event{Item: Item{ID: elements[i]}})
		sliceEnd := i + 1 - bufferSize
		if sliceEnd < 0 {
			sliceEnd = 0
		}
		expectEvents(c, b, elements[sliceEnd:i+1])
	}

}

// TestBufferSizes tests various combinations of various
// buffer sizes and lists
func (s *BufferSuite) TestBufferSizes(c *check.C) {
	s.list(c, 1, 100)
	s.list(c, 2, 100)
	s.list(c, 3, 100)
	s.list(c, 4, 100)
}

// TestBufferSizesReset tests various combinations of various
// buffer sizes and lists with clear.
func (s *BufferSuite) TestBufferSizesReset(c *check.C) {
	b := NewCircularBuffer(
		BufferCapacity(1),
	)
	defer b.Close()
	b.SetInit()

	s.listWithBuffer(c, b, 1, 100)
	b.Clear()
	s.listWithBuffer(c, b, 1, 100)
}

// TestWatcherSimple tests scenarios with watchers
func (s *BufferSuite) TestWatcherSimple(c *check.C) {
	ctx := context.Background()
	b := NewCircularBuffer(
		BufferCapacity(3),
	)
	defer b.Close()
	b.SetInit()

	w, err := b.NewWatcher(ctx, Watch{})
	c.Assert(err, check.IsNil)
	defer w.Close()

	select {
	case e := <-w.Events():
		c.Assert(e.Type, check.Equals, types.OpInit)
	case <-time.After(100 * time.Millisecond):
		c.Fatalf("Timeout waiting for event.")
	}

	b.Emit(Event{Item: Item{Key: []byte{Separator}, ID: 1}})

	select {
	case e := <-w.Events():
		c.Assert(e.Item.ID, check.Equals, int64(1))
	case <-time.After(100 * time.Millisecond):
		c.Fatalf("Timeout waiting for event.")
	}

	b.Close()
	b.Emit(Event{Item: Item{ID: 2}})

	select {
	case <-w.Done():
		// expected
	case <-w.Events():
		c.Fatalf("unexpected event")
	case <-time.After(100 * time.Millisecond):
		c.Fatalf("Timeout waiting for event.")
	}
}

// TestWatcherCapacity checks various watcher capacity scenarios
func (s *BufferSuite) TestWatcherCapacity(c *check.C) {
	const gracePeriod = time.Second
	clock := clockwork.NewFakeClock()

	ctx := context.Background()
	b := NewCircularBuffer(
		BufferCapacity(1),
		BufferClock(clock),
		BacklogGracePeriod(gracePeriod),
	)
	defer b.Close()
	b.SetInit()

	w, err := b.NewWatcher(ctx, Watch{
		QueueSize: 1,
	})
	c.Assert(err, check.IsNil)
	defer w.Close()

	select {
	case e := <-w.Events():
		c.Assert(e.Type, check.Equals, types.OpInit)
	default:
		c.Fatalf("Expected immediate OpInit.")
	}

	// emit and then consume 10 events.  this is much larger than our queue size,
	// but should succeed since we consume within our grace period.
	for i := 0; i < 10; i++ {
		b.Emit(Event{Item: Item{Key: []byte{Separator}, ID: int64(i + 1)}})
	}
	for i := 0; i < 10; i++ {
		select {
		case e := <-w.Events():
			c.Assert(e.Item.ID, check.Equals, int64(i+1))
		default:
			c.Fatalf("Expected events to be immediately available")
		}
	}

	// advance further than grace period.
	clock.Advance(gracePeriod + time.Second)

	// emit another event, which will cause buffer to reevaluate the grace period.
	b.Emit(Event{Item: Item{Key: []byte{Separator}, ID: int64(11)}})

	// ensure that buffer did not close watcher, since previously created backlog
	// was drained within grace period.
	select {
	case <-w.Done():
		c.Fatalf("Watcher should not have backlog, but was closed anyway")
	default:
	}

	// create backlog again, and this time advance past grace period without draining it.
	for i := 0; i < 10; i++ {
		b.Emit(Event{Item: Item{Key: []byte{Separator}, ID: int64(i + 12)}})
	}
	clock.Advance(gracePeriod + time.Second)

	// emit another event, which will cause buffer to realize that watcher is past
	// its grace period.
	b.Emit(Event{Item: Item{Key: []byte{Separator}, ID: int64(22)}})

	select {
	case <-w.Done():
	default:
		c.Fatalf("buffer did not close watcher that was past grace period")
	}
}

// TestWatcherClose makes sure that closed watcher
// will be removed
func (s *BufferSuite) TestWatcherClose(c *check.C) {
	b := NewCircularBuffer(
		BufferCapacity(3),
	)
	defer b.Close()
	b.SetInit()

	w, err := b.NewWatcher(context.TODO(), Watch{})
	c.Assert(err, check.IsNil)

	select {
	case e := <-w.Events():
		c.Assert(e.Type, check.Equals, types.OpInit)
	case <-time.After(100 * time.Millisecond):
		c.Fatalf("Timeout waiting for event.")
	}

	c.Assert(b.watchers.Len(), check.Equals, 1)
	w.(*BufferWatcher).closeAndRemove(removeSync)
	c.Assert(b.watchers.Len(), check.Equals, 0)
}

// TestRemoveRedundantPrefixes removes redundant prefixes
func (s *BufferSuite) TestRemoveRedundantPrefixes(c *check.C) {
	type tc struct {
		in  [][]byte
		out [][]byte
	}
	tcs := []tc{
		{
			in:  [][]byte{},
			out: [][]byte{},
		},
		{
			in:  [][]byte{[]byte("/a")},
			out: [][]byte{[]byte("/a")},
		},
		{
			in:  [][]byte{[]byte("/a"), []byte("/")},
			out: [][]byte{[]byte("/")},
		},
		{
			in:  [][]byte{[]byte("/b"), []byte("/a")},
			out: [][]byte{[]byte("/a"), []byte("/b")},
		},
		{
			in:  [][]byte{[]byte("/a/b"), []byte("/a"), []byte("/a/b/c"), []byte("/d")},
			out: [][]byte{[]byte("/a"), []byte("/d")},
		},
	}
	for _, tc := range tcs {
		c.Assert(removeRedundantPrefixes(tc.in), check.DeepEquals, tc.out)
	}
}

// TestWatcherMulti makes sure that watcher
// with multiple matching prefixes will get an event only once
func (s *BufferSuite) TestWatcherMulti(c *check.C) {
	b := NewCircularBuffer(
		BufferCapacity(3),
	)
	defer b.Close()
	b.SetInit()

	w, err := b.NewWatcher(context.TODO(), Watch{Prefixes: [][]byte{[]byte("/a"), []byte("/a/b")}})
	c.Assert(err, check.IsNil)
	defer w.Close()

	select {
	case e := <-w.Events():
		c.Assert(e.Type, check.Equals, types.OpInit)
	case <-time.After(100 * time.Millisecond):
		c.Fatalf("Timeout waiting for event.")
	}

	b.Emit(Event{Item: Item{Key: []byte("/a/b/c"), ID: 1}})

	select {
	case e := <-w.Events():
		c.Assert(e.Item.ID, check.Equals, int64(1))
	case <-time.After(100 * time.Millisecond):
		c.Fatalf("Timeout waiting for event.")
	}

	c.Assert(len(w.Events()), check.Equals, 0)

}

// TestWatcherReset tests scenarios with watchers and buffer resets
func (s *BufferSuite) TestWatcherReset(c *check.C) {
	b := NewCircularBuffer(
		BufferCapacity(3),
	)
	defer b.Close()
	b.SetInit()

	w, err := b.NewWatcher(context.TODO(), Watch{})
	c.Assert(err, check.IsNil)
	defer w.Close()

	select {
	case e := <-w.Events():
		c.Assert(e.Type, check.Equals, types.OpInit)
	case <-time.After(100 * time.Millisecond):
		c.Fatalf("Timeout waiting for event.")
	}

	b.Emit(Event{Item: Item{Key: []byte{Separator}, ID: 1}})
	b.Clear()

	// make sure watcher has been closed
	select {
	case <-w.Done():
	case <-time.After(100 * time.Millisecond):
		c.Fatalf("Timeout waiting for close event.")
	}

	w2, err := b.NewWatcher(context.TODO(), Watch{})
	c.Assert(err, check.IsNil)
	defer w2.Close()

	select {
	case e := <-w2.Events():
		c.Assert(e.Type, check.Equals, types.OpInit)
	case <-time.After(100 * time.Millisecond):
		c.Fatalf("Timeout waiting for event.")
	}

	b.Emit(Event{Item: Item{Key: []byte{Separator}, ID: 2}})

	select {
	case e := <-w2.Events():
		c.Assert(e.Item.ID, check.Equals, int64(2))
	case <-time.After(100 * time.Millisecond):
		c.Fatalf("Timeout waiting for event.")
	}
}

// TestWatcherTree tests buffer watcher tree
func (s *BufferSuite) TestWatcherTree(c *check.C) {
	t := newWatcherTree()
	c.Assert(t.rm(nil), check.Equals, false)

	w1 := &BufferWatcher{Watch: Watch{Prefixes: [][]byte{[]byte("/a"), []byte("/a/a1"), []byte("/c")}}}
	c.Assert(t.rm(w1), check.Equals, false)

	w2 := &BufferWatcher{Watch: Watch{Prefixes: [][]byte{[]byte("/a")}}}

	t.add(w1)
	t.add(w2)

	var out []*BufferWatcher
	t.walk(func(w *BufferWatcher) {
		out = append(out, w)
	})
	c.Assert(out, check.HasLen, 4)

	var matched []*BufferWatcher
	t.walkPath("/c", func(w *BufferWatcher) {
		matched = append(matched, w)
	})
	c.Assert(matched, check.HasLen, 1)
	c.Assert(matched[0], check.Equals, w1)

	matched = nil
	t.walkPath("/a", func(w *BufferWatcher) {
		matched = append(matched, w)
	})
	c.Assert(matched, check.HasLen, 2)
	c.Assert(matched[0], check.Equals, w1)
	c.Assert(matched[1], check.Equals, w2)

	c.Assert(t.rm(w1), check.Equals, true)
	c.Assert(t.rm(w1), check.Equals, false)

	matched = nil
	t.walkPath("/a", func(w *BufferWatcher) {
		matched = append(matched, w)
	})
	c.Assert(matched, check.HasLen, 1)
	c.Assert(matched[0], check.Equals, w2)

	c.Assert(t.rm(w2), check.Equals, true)
}

func makeIDs(size int) []int64 {
	out := make([]int64, size)
	for i := 0; i < size; i++ {
		out[i] = int64(i)
	}
	return out
}

func expectEvents(c *check.C, b *CircularBuffer, ids []int64) {
	events := b.Events()
	if len(ids) == 0 {
		c.Assert(len(events), check.Equals, 0)
		return
	}
	c.Assert(toIDs(events), check.DeepEquals, ids)
}

func toIDs(e []Event) []int64 {
	var out []int64
	for i := 0; i < len(e); i++ {
		out = append(out, e[i].Item.ID)
	}
	return out
}
<commit_msg>Refactor tests under backend package.<commit_after>/*
Copyright 2018 Gravitational, Inc.

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

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

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

package backend

import (
	"context"
	"testing"
	"time"

	"github.com/google/go-cmp/cmp"
	"github.com/gravitational/teleport/api/types"
	"github.com/jonboulle/clockwork"
	"github.com/stretchr/testify/require"
)

// TestBufferSizes tests various combinations of various
// buffer sizes and lists
func TestBufferSizes(t *testing.T) {
	list(t, 1, 100)
	list(t, 2, 100)
	list(t, 3, 100)
	list(t, 4, 100)
}

// TestBufferSizesReset tests various combinations of various
// buffer sizes and lists with clear.
func TestBufferSizesReset(t *testing.T) {
	b := NewCircularBuffer(
		BufferCapacity(1),
	)
	defer b.Close()
	b.SetInit()

	listWithBuffer(t, b, 1, 100)
	b.Clear()
	listWithBuffer(t, b, 1, 100)
}

// TestWatcherSimple tests scenarios with watchers
func TestWatcherSimple(t *testing.T) {
	ctx := context.Background()
	b := NewCircularBuffer(
		BufferCapacity(3),
	)
	defer b.Close()
	b.SetInit()

	w, err := b.NewWatcher(ctx, Watch{})
	require.NoError(t, err)
	defer w.Close()

	select {
	case e := <-w.Events():
		require.Equal(t, e.Type, types.OpInit)
	case <-time.After(100 * time.Millisecond):
		t.Fatalf("Timeout waiting for event.")
	}

	b.Emit(Event{Item: Item{Key: []byte{Separator}, ID: 1}})

	select {
	case e := <-w.Events():
		require.Equal(t, e.Item.ID, int64(1))
	case <-time.After(100 * time.Millisecond):
		t.Fatalf("Timeout waiting for event.")
	}

	b.Close()
	b.Emit(Event{Item: Item{ID: 2}})

	select {
	case <-w.Done():
		// expected
	case <-w.Events():
		t.Fatalf("unexpected event")
	case <-time.After(100 * time.Millisecond):
		t.Fatalf("Timeout waiting for event.")
	}
}

// TestWatcherCapacity checks various watcher capacity scenarios
func TestWatcherCapacity(t *testing.T) {
	const gracePeriod = time.Second
	clock := clockwork.NewFakeClock()

	ctx := context.Background()
	b := NewCircularBuffer(
		BufferCapacity(1),
		BufferClock(clock),
		BacklogGracePeriod(gracePeriod),
	)
	defer b.Close()
	b.SetInit()

	w, err := b.NewWatcher(ctx, Watch{
		QueueSize: 1,
	})
	require.NoError(t, err)
	defer w.Close()

	select {
	case e := <-w.Events():
		require.Equal(t, e.Type, types.OpInit)
	default:
		t.Fatalf("Expected immediate OpInit.")
	}

	// emit and then consume 10 events.  this is much larger than our queue size,
	// but should succeed since we consume within our grace period.
	for i := 0; i < 10; i++ {
		b.Emit(Event{Item: Item{Key: []byte{Separator}, ID: int64(i + 1)}})
	}
	for i := 0; i < 10; i++ {
		select {
		case e := <-w.Events():
			require.Equal(t, e.Item.ID, int64(i+1))
		default:
			t.Fatalf("Expected events to be immediately available")
		}
	}

	// advance further than grace period.
	clock.Advance(gracePeriod + time.Second)

	// emit another event, which will cause buffer to reevaluate the grace period.
	b.Emit(Event{Item: Item{Key: []byte{Separator}, ID: int64(11)}})

	// ensure that buffer did not close watcher, since previously created backlog
	// was drained within grace period.
	select {
	case <-w.Done():
		t.Fatalf("Watcher should not have backlog, but was closed anyway")
	default:
	}

	// create backlog again, and this time advance past grace period without draining it.
	for i := 0; i < 10; i++ {
		b.Emit(Event{Item: Item{Key: []byte{Separator}, ID: int64(i + 12)}})
	}
	clock.Advance(gracePeriod + time.Second)

	// emit another event, which will cause buffer to realize that watcher is past
	// its grace period.
	b.Emit(Event{Item: Item{Key: []byte{Separator}, ID: int64(22)}})

	select {
	case <-w.Done():
	default:
		t.Fatalf("buffer did not close watcher that was past grace period")
	}
}

// TestWatcherClose makes sure that closed watcher
// will be removed
func TestWatcherClose(t *testing.T) {
	b := NewCircularBuffer(
		BufferCapacity(3),
	)
	defer b.Close()
	b.SetInit()

	w, err := b.NewWatcher(context.TODO(), Watch{})
	require.NoError(t, err)

	select {
	case e := <-w.Events():
		require.Equal(t, e.Type, types.OpInit)
	case <-time.After(100 * time.Millisecond):
		t.Fatalf("Timeout waiting for event.")
	}

	require.Equal(t, b.watchers.Len(), 1)
	w.(*BufferWatcher).closeAndRemove(removeSync)
	require.Equal(t, b.watchers.Len(), 0)
}

// TestRemoveRedundantPrefixes removes redundant prefixes
func TestRemoveRedundantPrefixes(t *testing.T) {
	type tc struct {
		in  [][]byte
		out [][]byte
	}
	tcs := []tc{
		{
			in:  [][]byte{},
			out: [][]byte{},
		},
		{
			in:  [][]byte{[]byte("/a")},
			out: [][]byte{[]byte("/a")},
		},
		{
			in:  [][]byte{[]byte("/a"), []byte("/")},
			out: [][]byte{[]byte("/")},
		},
		{
			in:  [][]byte{[]byte("/b"), []byte("/a")},
			out: [][]byte{[]byte("/a"), []byte("/b")},
		},
		{
			in:  [][]byte{[]byte("/a/b"), []byte("/a"), []byte("/a/b/c"), []byte("/d")},
			out: [][]byte{[]byte("/a"), []byte("/d")},
		},
	}
	for _, tc := range tcs {
		require.Empty(t, cmp.Diff(removeRedundantPrefixes(tc.in), tc.out))
	}
}

// TestWatcherMulti makes sure that watcher
// with multiple matching prefixes will get an event only once
func TestWatcherMulti(t *testing.T) {
	b := NewCircularBuffer(
		BufferCapacity(3),
	)
	defer b.Close()
	b.SetInit()

	w, err := b.NewWatcher(context.TODO(), Watch{Prefixes: [][]byte{[]byte("/a"), []byte("/a/b")}})
	require.NoError(t, err)
	defer w.Close()

	select {
	case e := <-w.Events():
		require.Equal(t, e.Type, types.OpInit)
	case <-time.After(100 * time.Millisecond):
		t.Fatalf("Timeout waiting for event.")
	}

	b.Emit(Event{Item: Item{Key: []byte("/a/b/c"), ID: 1}})

	select {
	case e := <-w.Events():
		require.Equal(t, e.Item.ID, int64(1))
	case <-time.After(100 * time.Millisecond):
		t.Fatalf("Timeout waiting for event.")
	}

	require.Equal(t, len(w.Events()), 0)

}

// TestWatcherReset tests scenarios with watchers and buffer resets
func TestWatcherReset(t *testing.T) {
	b := NewCircularBuffer(
		BufferCapacity(3),
	)
	defer b.Close()
	b.SetInit()

	w, err := b.NewWatcher(context.TODO(), Watch{})
	require.NoError(t, err)
	defer w.Close()

	select {
	case e := <-w.Events():
		require.Equal(t, e.Type, types.OpInit)
	case <-time.After(100 * time.Millisecond):
		t.Fatalf("Timeout waiting for event.")
	}

	b.Emit(Event{Item: Item{Key: []byte{Separator}, ID: 1}})
	b.Clear()

	// make sure watcher has been closed
	select {
	case <-w.Done():
	case <-time.After(100 * time.Millisecond):
		t.Fatalf("Timeout waiting for close event.")
	}

	w2, err := b.NewWatcher(context.TODO(), Watch{})
	require.NoError(t, err)
	defer w2.Close()

	select {
	case e := <-w2.Events():
		require.Equal(t, e.Type, types.OpInit)
	case <-time.After(100 * time.Millisecond):
		t.Fatalf("Timeout waiting for event.")
	}

	b.Emit(Event{Item: Item{Key: []byte{Separator}, ID: 2}})

	select {
	case e := <-w2.Events():
		require.Equal(t, e.Item.ID, int64(2))
	case <-time.After(100 * time.Millisecond):
		t.Fatalf("Timeout waiting for event.")
	}
}

// TestWatcherTree tests buffer watcher tree
func TestWatcherTree(t *testing.T) {
	wt := newWatcherTree()
	require.Equal(t, wt.rm(nil), false)

	w1 := &BufferWatcher{Watch: Watch{Prefixes: [][]byte{[]byte("/a"), []byte("/a/a1"), []byte("/c")}}}
	require.Equal(t, wt.rm(w1), false)

	w2 := &BufferWatcher{Watch: Watch{Prefixes: [][]byte{[]byte("/a")}}}

	wt.add(w1)
	wt.add(w2)

	var out []*BufferWatcher
	wt.walk(func(w *BufferWatcher) {
		out = append(out, w)
	})
	require.Len(t, out, 4)

	var matched []*BufferWatcher
	wt.walkPath("/c", func(w *BufferWatcher) {
		matched = append(matched, w)
	})
	require.Len(t, matched, 1)
	require.Equal(t, matched[0], w1)

	matched = nil
	wt.walkPath("/a", func(w *BufferWatcher) {
		matched = append(matched, w)
	})
	require.Len(t, matched, 2)
	require.Equal(t, matched[0], w1)
	require.Equal(t, matched[1], w2)

	require.Equal(t, wt.rm(w1), true)
	require.Equal(t, wt.rm(w1), false)

	matched = nil
	wt.walkPath("/a", func(w *BufferWatcher) {
		matched = append(matched, w)
	})
	require.Len(t, matched, 1)
	require.Equal(t, matched[0], w2)

	require.Equal(t, wt.rm(w2), true)
}

func makeIDs(size int) []int64 {
	out := make([]int64, size)
	for i := 0; i < size; i++ {
		out[i] = int64(i)
	}
	return out
}

func expectEvents(t *testing.T, b *CircularBuffer, ids []int64) {
	events := b.Events()
	if len(ids) == 0 {
		require.Equal(t, len(events), 0)
		return
	}
	require.Empty(t, cmp.Diff(toIDs(events), ids))
}

func toIDs(e []Event) []int64 {
	var out []int64
	for i := 0; i < len(e); i++ {
		out = append(out, e[i].Item.ID)
	}
	return out
}

func list(t *testing.T, bufferSize int, listSize int) {
	b := NewCircularBuffer(
		BufferCapacity(bufferSize),
	)
	defer b.Close()
	b.SetInit()
	listWithBuffer(t, b, bufferSize, listSize)
}

func listWithBuffer(t *testing.T, b *CircularBuffer, bufferSize int, listSize int) {
	// empty by default
	expectEvents(t, b, nil)

	elements := makeIDs(listSize)

	// push through all elements of the list and make sure
	// the slice always matches
	for i := 0; i < len(elements); i++ {
		b.Emit(Event{Item: Item{ID: elements[i]}})
		sliceEnd := i + 1 - bufferSize
		if sliceEnd < 0 {
			sliceEnd = 0
		}
		expectEvents(t, b, elements[sliceEnd:i+1])
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 Steven Oud. All rights reserved.
// Use of this source code is governed by a MIT-style license that can be found
// in the LICENSE file.

package mathcat

import (
	"errors"
	"fmt"
	"math"
	"strconv"
	"strings"
)

// Parser holds the lexed tokens, token position and declared variables. By
// default, variables always contains the constants defined below. These can
// however be overwritten.
type Parser struct {
	tokens    []*Token
	pos       int
	Variables map[string]float64
	tok       *Token
}

var (
	errDivionByZero         = errors.New("Divison by zero")
	errUnmatchedParentheses = errors.New("Unmatched parentheses")
	errInvalidSyntax        = errors.New("Invalid syntax")
)

// Some useful predefined variables that can be used in expressions. These
// can be overwritten.
var constants = map[string]float64{
	"pi":  math.Pi,
	"tau": math.Pi / 2,
	"phi": math.Phi,
	"e":   math.E,
}

// New initializes a new Parser instance, useful when you want to run multiple
// expression and/or use variables.
func New() *Parser {
	return &Parser{
		pos:       0,
		Variables: constants,
	}
}

// Eval evaluates an expression and returns its result and any errors found.
//
// Example:
//     res, err := mathcat.Eval("2 * 2 * 2") // 8
func Eval(expr string) (float64, error) {
	tokens, err := Lex(expr)

	// If a lexer error occured don't parse
	if err != nil {
		return -1, err
	}

	p := &Parser{
		tokens:    tokens,
		pos:       0,
		Variables: constants,
	}

	return p.parse()
}

// Run executes an expression on an existing parser instance. Useful for
// variable assignment.
//
// Example:
//     p.Run("a = 555")
//     p.Run("a += 45")
//     res, err := p.Run("a + a") // 1200
func (p *Parser) Run(expr string) (float64, error) {
	tokens, err := Lex(expr)

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

	p.reset()
	p.tokens = tokens

	return p.parse()
}

// Exec executes an expression with a given map of variables.
//
// Example:
//     res, err := mathcat.Exec("a + b * b", map[string]float64{
//         "a": 1,
//         "b": 3,
//     }) // 10
func Exec(expr string, vars map[string]float64) (float64, error) {
	tokens, err := Lex(expr)

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

	p := &Parser{
		tokens:    tokens,
		pos:       0,
		Variables: constants,
	}

	isValidIdent := func(c rune) bool { return isIdent(c) || isNumber(c) }

	for k, v := range vars {
		if !isIdent(rune(k[0])) || strings.IndexFunc(k, isValidIdent) == -1 {
			return -1, fmt.Errorf("Invalid variable name: '%s'")
		}
		p.Variables[k] = v
	}

	p.tokens = tokens

	return p.parse()
}

// GetVar gets an existing variable.
func (p *Parser) GetVar(index string) (float64, error) {
	if val, ok := p.Variables[index]; ok {
		return val, nil
	}

	return -1, fmt.Errorf("Undefined variable '%s'", index)
}

func (p *Parser) parse() (float64, error) {
	var (
		operands, operators stack
		o1, o2              *operator
	)

	p.tok = p.tokens[0]

	for p.eat().Type != EOL {
		switch {
		case p.tok.IsLiteral():
			if p.peek().Type == LPAREN {
				// It's a function call, push to operators stack instead
				operators.Push(p.tok)
				break
			}
			operands.Push(p.tok)
		case p.tok.Type == LPAREN:
			operators.Push(p.tok)
		case p.tok.Type == COMMA:
			for {
				if operators.Empty() {
					return -1, errors.New("Misplaced ','")
				}

				if operators.Top().(*Token).Type == LPAREN {
					break
				}

				val, err := p.evaluate(operators.Pop().(*Token), &operands)
				if err != nil {
					return -1, err
				}

				operands.Push(val)
			}
		case p.tok.IsOperator():
			o1 = ops[p.tok.Type]

			if !operators.Empty() {
				var ok bool
				if o2, ok = ops[operators.Top().(*Token).Type]; !ok {
					operators.Push(p.tok)
					break
				}

				if o2.hasHigherPrecThan(o1) {
					operator := operators.Pop().(*Token)
					val, err := p.evaluateOp(operator, &operands)
					if err != nil {
						return -1, err
					}
					operands.Push(val)
				}
			}
			operators.Push(p.tok)
		case p.tok.Type == RPAREN:
			for {
				if operators.Empty() {
					return -1, errUnmatchedParentheses
				}

				top := operators.Pop().(*Token)
				if top.Type == LPAREN {
					break
				}

				val, err := p.evaluate(top, &operands)
				if err != nil {
					return -1, err
				}

				operands.Push(val)
			}
		}
	}

	// Evaluate remaining operators
	for !operators.Empty() {
		top := operators.Pop().(*Token)

		if top.Type == LPAREN {
			return -1, errUnmatchedParentheses
		}

		val, err := p.evaluate(top, &operands)
		if err != nil {
			return -1, err
		}

		operands.Push(val)
	}

	// If there are no operands, the expression is useless and doesn't do
	// anything, for example `()` or an empty string
	if operands.Empty() {
		return 0, nil
	}

	// Single operand left means the expression was evaluated successful
	if len(operands) == 1 {
		return p.lookup(operands[0])
	}

	// Leftover token on operand stack indicates invalid syntax
	return -1, errInvalidSyntax
}

// Evaluate gets called when an operator or function call has to be evaluated
// for a result. In case of a function, evaluateFunc is called and in case of
// an operator evaluateOp is called.
func (p *Parser) evaluate(tok *Token, operands *stack) (float64, error) {
	var err error
	var val float64

	if tok.Type == IDENT {
		// Function call
		val, err = p.evaluateFunc(tok, operands)
		if err != nil {
			return -1, err
		}
	} else {
		// Operator
		val, err = p.evaluateOp(tok, operands)
		if err != nil {
			return -1, err
		}
	}

	return val, nil
}

func (p *Parser) evaluateFunc(tok *Token, operands *stack) (float64, error) {
	var function *function
	var ok bool
	var i int

	if function, ok = functions[tok.Value]; !ok {
		return -1, fmt.Errorf("Undefined function '%s'", tok.Value)
	}

	// Start popping off arguments for the function call
	args := make([]float64, function.nargs)
	for i = 0; i < function.nargs; i++ {
		if operands.Empty() {
			return -1, fmt.Errorf("Invalid argument count for '%s' (expected %d, got %d)", function.name, function.nargs, i)
		}

		arg, err := p.lookup(operands.Pop())
		if err != nil {
			return -1, err
		}

		args[i] = arg
	}

	if len(*operands) > 1 {
		return -1, fmt.Errorf("Invalid argument count for '%s' (expected %d, got %d)", function.name, function.nargs, i+1)
	}

	return function.operation(args), nil
}

func (p *Parser) evaluateOp(operator *Token, operands *stack) (float64, error) {
	var (
		result      float64
		left, right float64
		err         error
		lhsToken    interface{}
	)

	if operands.Empty() {
		return -1, fmt.Errorf("Unexpected '%s'", operator.Type)
	}

	if right, err = p.lookup(operands.Pop()); err != nil {
		return -1, err
	}

	// Unary operators have no left hand side
	if op := ops[operator.Type]; !op.unary {
		if operands.Empty() {
			return -1, errInvalidSyntax
		}
		// Save the token in case of a assignment variable is used and we need to
		// save the result in a variable
		lhsToken = operands.Pop()

		// Don't lookup the left hand side if = is used so we can do initial
		// assignment
		if operator.Type != EQ {
			left, err = p.lookup(lhsToken)
			if err != nil {
				return -1, err
			}
		}
	}

	result, err = execute(operator, left, right)
	if err != nil {
		return -1, err
	}

	switch operator.Type {
	case EQ, ADD_EQ, SUB_EQ, DIV_EQ, MUL_EQ, POW_EQ, REM_EQ, AND_EQ, OR_EQ, XOR_EQ, LSH_EQ, RSH_EQ:
		// Save result in variable
		if lhsToken.(*Token).Type != IDENT {
			return -1, errors.New("Can't assign to literal")
		}
		p.Variables[lhsToken.(*Token).Value] = result
	}

	return result, nil
}

func execute(operator *Token, lhs, rhs float64) (float64, error) {
	var result float64

	// Both lhs and rhs have to be whole numbers for bitwise operations
	if operator.IsBitwise() && (!IsWholeNumber(lhs) || !IsWholeNumber(rhs)) {
		return -1, fmt.Errorf("Unsupported type (float) for '%s'", operator.Type)
	}

	switch operator.Type {
	case ADD, ADD_EQ:
		result = lhs + rhs
	case SUB, SUB_EQ:
		result = lhs - rhs
	case UNARY_MIN:
		result = -rhs
	case DIV, DIV_EQ:
		if rhs == 0 {
			return -1, errDivionByZero
		}
		result = lhs / rhs
	case MUL, MUL_EQ:
		result = lhs * rhs
	case POW, POW_EQ:
		result = math.Pow(lhs, rhs)
	case REM, REM_EQ:
		if rhs == 0 {
			return -1, errDivionByZero
		}
		result = math.Mod(lhs, rhs)
	case AND, AND_EQ:
		result = float64(int64(lhs) & int64(rhs))
	case OR, OR_EQ:
		result = float64(int64(lhs) | int64(rhs))
	case XOR, XOR_EQ:
		result = float64(int64(lhs) ^ int64(rhs))
	case LSH, LSH_EQ:
		result = float64(uint64(lhs) << uint64(rhs))
	case RSH, RSH_EQ:
		result = float64(uint64(lhs) >> uint64(rhs))
	case NOT:
		result = float64(^int64(rhs))
	case EQ:
		result = rhs
	case EQ_EQ:
		result = bool2float(lhs == rhs)
	case GT:
		result = bool2float(lhs > rhs)
	case GT_EQ:
		result = bool2float(lhs >= rhs)
	case LT:
		result = bool2float(lhs < rhs)
	case LT_EQ:
		result = bool2float(lhs <= rhs)
	default:
		return -1, fmt.Errorf("Invalid operator '%s'", operator.Type)
	}

	return result, nil
}

// Look up a literal. If it's an identifier, check the parser's variables map,
// otherwise convert the tokenized string to a float64.
func (p *Parser) lookup(val interface{}) (float64, error) {
	// val can be a token or a float64, if it's a float64 it has been already
	// evaluated and we don't need to do anything
	if v, ok := val.(float64); ok {
		return v, nil
	}

	tok := val.(*Token)
	switch tok.Type {
	case NUMBER:
		res, err := strconv.ParseFloat(tok.Value, 64)
		if err != nil {
			return -1, fmt.Errorf("Error parsing '%s': invalid syntax", tok.Value)
		}

		return res, nil
	case HEX:
		// Remove 0x part of hex literal and convert to uint first
		res, err := strconv.ParseUint(tok.Value[2:], 16, 64)
		if err != nil {
			return -1, fmt.Errorf("Error parsing '%s': invalid syntax", tok.Value)
		}

		// Then convert to float
		return float64(res), nil
	case BINARY:
		// Remove 0b part of binary literal and convert to uint first
		res, err := strconv.ParseUint(tok.Value[2:], 2, 64)
		if err != nil {
			return -1, fmt.Errorf("Error parsing '%s': invalid syntax", tok.Value)
		}

		// Then convert to float
		return float64(res), nil
	case IDENT:
		res, err := p.GetVar(tok.Value)
		if err != nil {
			return -1, err
		}

		return res, nil
	}

	return -1, fmt.Errorf("Invalid lookup type: %s", tok.Type)
}

func (p *Parser) reset() {
	p.tokens = nil
	p.pos = 0
}

func (p *Parser) peek() *Token {
	return p.tokens[p.pos]
}

func (p *Parser) eat() *Token {
	p.tok = p.peek()
	p.pos++
	return p.tok
}

// IsWholeNumber checks if a float is a whole number
func IsWholeNumber(n float64) bool {
	epsilon := 1e-9
	_, frac := math.Modf(math.Abs(n))

	return frac < epsilon || frac > 1.0-epsilon
}

func bool2float(b bool) float64 {
	if b {
		return 1
	}
	return 0
}
<commit_msg>Use var block if there are more than 2<commit_after>// Copyright 2016 Steven Oud. All rights reserved.
// Use of this source code is governed by a MIT-style license that can be found
// in the LICENSE file.

package mathcat

import (
	"errors"
	"fmt"
	"math"
	"strconv"
	"strings"
)

// Parser holds the lexed tokens, token position and declared variables. By
// default, variables always contains the constants defined below. These can
// however be overwritten.
type Parser struct {
	tokens    []*Token
	pos       int
	Variables map[string]float64
	tok       *Token
}

var (
	errDivionByZero         = errors.New("Divison by zero")
	errUnmatchedParentheses = errors.New("Unmatched parentheses")
	errInvalidSyntax        = errors.New("Invalid syntax")
)

// Some useful predefined variables that can be used in expressions. These
// can be overwritten.
var constants = map[string]float64{
	"pi":  math.Pi,
	"tau": math.Pi / 2,
	"phi": math.Phi,
	"e":   math.E,
}

// New initializes a new Parser instance, useful when you want to run multiple
// expression and/or use variables.
func New() *Parser {
	return &Parser{
		pos:       0,
		Variables: constants,
	}
}

// Eval evaluates an expression and returns its result and any errors found.
//
// Example:
//     res, err := mathcat.Eval("2 * 2 * 2") // 8
func Eval(expr string) (float64, error) {
	tokens, err := Lex(expr)

	// If a lexer error occured don't parse
	if err != nil {
		return -1, err
	}

	p := &Parser{
		tokens:    tokens,
		pos:       0,
		Variables: constants,
	}

	return p.parse()
}

// Run executes an expression on an existing parser instance. Useful for
// variable assignment.
//
// Example:
//     p.Run("a = 555")
//     p.Run("a += 45")
//     res, err := p.Run("a + a") // 1200
func (p *Parser) Run(expr string) (float64, error) {
	tokens, err := Lex(expr)

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

	p.reset()
	p.tokens = tokens

	return p.parse()
}

// Exec executes an expression with a given map of variables.
//
// Example:
//     res, err := mathcat.Exec("a + b * b", map[string]float64{
//         "a": 1,
//         "b": 3,
//     }) // 10
func Exec(expr string, vars map[string]float64) (float64, error) {
	tokens, err := Lex(expr)

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

	p := &Parser{
		tokens:    tokens,
		pos:       0,
		Variables: constants,
	}

	isValidIdent := func(c rune) bool { return isIdent(c) || isNumber(c) }

	for k, v := range vars {
		if !isIdent(rune(k[0])) || strings.IndexFunc(k, isValidIdent) == -1 {
			return -1, fmt.Errorf("Invalid variable name: '%s'")
		}
		p.Variables[k] = v
	}

	p.tokens = tokens

	return p.parse()
}

// GetVar gets an existing variable.
func (p *Parser) GetVar(index string) (float64, error) {
	if val, ok := p.Variables[index]; ok {
		return val, nil
	}

	return -1, fmt.Errorf("Undefined variable '%s'", index)
}

func (p *Parser) parse() (float64, error) {
	var (
		operands, operators stack
		o1, o2              *operator
	)

	p.tok = p.tokens[0]

	for p.eat().Type != EOL {
		switch {
		case p.tok.IsLiteral():
			if p.peek().Type == LPAREN {
				// It's a function call, push to operators stack instead
				operators.Push(p.tok)
				break
			}
			operands.Push(p.tok)
		case p.tok.Type == LPAREN:
			operators.Push(p.tok)
		case p.tok.Type == COMMA:
			for {
				if operators.Empty() {
					return -1, errors.New("Misplaced ','")
				}

				if operators.Top().(*Token).Type == LPAREN {
					break
				}

				val, err := p.evaluate(operators.Pop().(*Token), &operands)
				if err != nil {
					return -1, err
				}

				operands.Push(val)
			}
		case p.tok.IsOperator():
			o1 = ops[p.tok.Type]

			if !operators.Empty() {
				var ok bool
				if o2, ok = ops[operators.Top().(*Token).Type]; !ok {
					operators.Push(p.tok)
					break
				}

				if o2.hasHigherPrecThan(o1) {
					operator := operators.Pop().(*Token)
					val, err := p.evaluateOp(operator, &operands)
					if err != nil {
						return -1, err
					}
					operands.Push(val)
				}
			}
			operators.Push(p.tok)
		case p.tok.Type == RPAREN:
			for {
				if operators.Empty() {
					return -1, errUnmatchedParentheses
				}

				top := operators.Pop().(*Token)
				if top.Type == LPAREN {
					break
				}

				val, err := p.evaluate(top, &operands)
				if err != nil {
					return -1, err
				}

				operands.Push(val)
			}
		}
	}

	// Evaluate remaining operators
	for !operators.Empty() {
		top := operators.Pop().(*Token)

		if top.Type == LPAREN {
			return -1, errUnmatchedParentheses
		}

		val, err := p.evaluate(top, &operands)
		if err != nil {
			return -1, err
		}

		operands.Push(val)
	}

	// If there are no operands, the expression is useless and doesn't do
	// anything, for example `()` or an empty string
	if operands.Empty() {
		return 0, nil
	}

	// Single operand left means the expression was evaluated successful
	if len(operands) == 1 {
		return p.lookup(operands[0])
	}

	// Leftover token on operand stack indicates invalid syntax
	return -1, errInvalidSyntax
}

// Evaluate gets called when an operator or function call has to be evaluated
// for a result. In case of a function, evaluateFunc is called and in case of
// an operator evaluateOp is called.
func (p *Parser) evaluate(tok *Token, operands *stack) (float64, error) {
	var err error
	var val float64

	if tok.Type == IDENT {
		// Function call
		val, err = p.evaluateFunc(tok, operands)
		if err != nil {
			return -1, err
		}
	} else {
		// Operator
		val, err = p.evaluateOp(tok, operands)
		if err != nil {
			return -1, err
		}
	}

	return val, nil
}

func (p *Parser) evaluateFunc(tok *Token, operands *stack) (float64, error) {
	var (
		function *function
		ok       bool
		i        int
	)

	if function, ok = functions[tok.Value]; !ok {
		return -1, fmt.Errorf("Undefined function '%s'", tok.Value)
	}

	// Start popping off arguments for the function call
	args := make([]float64, function.nargs)
	for i = 0; i < function.nargs; i++ {
		if operands.Empty() {
			return -1, fmt.Errorf("Invalid argument count for '%s' (expected %d, got %d)", function.name, function.nargs, i)
		}

		arg, err := p.lookup(operands.Pop())
		if err != nil {
			return -1, err
		}

		args[i] = arg
	}

	if len(*operands) > 1 {
		return -1, fmt.Errorf("Invalid argument count for '%s' (expected %d, got %d)", function.name, function.nargs, i+1)
	}

	return function.operation(args), nil
}

func (p *Parser) evaluateOp(operator *Token, operands *stack) (float64, error) {
	var (
		result      float64
		left, right float64
		err         error
		lhsToken    interface{}
	)

	if operands.Empty() {
		return -1, fmt.Errorf("Unexpected '%s'", operator.Type)
	}

	if right, err = p.lookup(operands.Pop()); err != nil {
		return -1, err
	}

	// Unary operators have no left hand side
	if op := ops[operator.Type]; !op.unary {
		if operands.Empty() {
			return -1, errInvalidSyntax
		}
		// Save the token in case of a assignment variable is used and we need to
		// save the result in a variable
		lhsToken = operands.Pop()

		// Don't lookup the left hand side if = is used so we can do initial
		// assignment
		if operator.Type != EQ {
			left, err = p.lookup(lhsToken)
			if err != nil {
				return -1, err
			}
		}
	}

	result, err = execute(operator, left, right)
	if err != nil {
		return -1, err
	}

	switch operator.Type {
	case EQ, ADD_EQ, SUB_EQ, DIV_EQ, MUL_EQ, POW_EQ, REM_EQ, AND_EQ, OR_EQ, XOR_EQ, LSH_EQ, RSH_EQ:
		// Save result in variable
		if lhsToken.(*Token).Type != IDENT {
			return -1, errors.New("Can't assign to literal")
		}
		p.Variables[lhsToken.(*Token).Value] = result
	}

	return result, nil
}

func execute(operator *Token, lhs, rhs float64) (float64, error) {
	var result float64

	// Both lhs and rhs have to be whole numbers for bitwise operations
	if operator.IsBitwise() && (!IsWholeNumber(lhs) || !IsWholeNumber(rhs)) {
		return -1, fmt.Errorf("Unsupported type (float) for '%s'", operator.Type)
	}

	switch operator.Type {
	case ADD, ADD_EQ:
		result = lhs + rhs
	case SUB, SUB_EQ:
		result = lhs - rhs
	case UNARY_MIN:
		result = -rhs
	case DIV, DIV_EQ:
		if rhs == 0 {
			return -1, errDivionByZero
		}
		result = lhs / rhs
	case MUL, MUL_EQ:
		result = lhs * rhs
	case POW, POW_EQ:
		result = math.Pow(lhs, rhs)
	case REM, REM_EQ:
		if rhs == 0 {
			return -1, errDivionByZero
		}
		result = math.Mod(lhs, rhs)
	case AND, AND_EQ:
		result = float64(int64(lhs) & int64(rhs))
	case OR, OR_EQ:
		result = float64(int64(lhs) | int64(rhs))
	case XOR, XOR_EQ:
		result = float64(int64(lhs) ^ int64(rhs))
	case LSH, LSH_EQ:
		result = float64(uint64(lhs) << uint64(rhs))
	case RSH, RSH_EQ:
		result = float64(uint64(lhs) >> uint64(rhs))
	case NOT:
		result = float64(^int64(rhs))
	case EQ:
		result = rhs
	case EQ_EQ:
		result = bool2float(lhs == rhs)
	case GT:
		result = bool2float(lhs > rhs)
	case GT_EQ:
		result = bool2float(lhs >= rhs)
	case LT:
		result = bool2float(lhs < rhs)
	case LT_EQ:
		result = bool2float(lhs <= rhs)
	default:
		return -1, fmt.Errorf("Invalid operator '%s'", operator.Type)
	}

	return result, nil
}

// Look up a literal. If it's an identifier, check the parser's variables map,
// otherwise convert the tokenized string to a float64.
func (p *Parser) lookup(val interface{}) (float64, error) {
	// val can be a token or a float64, if it's a float64 it has been already
	// evaluated and we don't need to do anything
	if v, ok := val.(float64); ok {
		return v, nil
	}

	tok := val.(*Token)
	switch tok.Type {
	case NUMBER:
		res, err := strconv.ParseFloat(tok.Value, 64)
		if err != nil {
			return -1, fmt.Errorf("Error parsing '%s': invalid syntax", tok.Value)
		}

		return res, nil
	case HEX:
		// Remove 0x part of hex literal and convert to uint first
		res, err := strconv.ParseUint(tok.Value[2:], 16, 64)
		if err != nil {
			return -1, fmt.Errorf("Error parsing '%s': invalid syntax", tok.Value)
		}

		// Then convert to float
		return float64(res), nil
	case BINARY:
		// Remove 0b part of binary literal and convert to uint first
		res, err := strconv.ParseUint(tok.Value[2:], 2, 64)
		if err != nil {
			return -1, fmt.Errorf("Error parsing '%s': invalid syntax", tok.Value)
		}

		// Then convert to float
		return float64(res), nil
	case IDENT:
		res, err := p.GetVar(tok.Value)
		if err != nil {
			return -1, err
		}

		return res, nil
	}

	return -1, fmt.Errorf("Invalid lookup type: %s", tok.Type)
}

func (p *Parser) reset() {
	p.tokens = nil
	p.pos = 0
}

func (p *Parser) peek() *Token {
	return p.tokens[p.pos]
}

func (p *Parser) eat() *Token {
	p.tok = p.peek()
	p.pos++
	return p.tok
}

// IsWholeNumber checks if a float is a whole number
func IsWholeNumber(n float64) bool {
	epsilon := 1e-9
	_, frac := math.Modf(math.Abs(n))

	return frac < epsilon || frac > 1.0-epsilon
}

func bool2float(b bool) float64 {
	if b {
		return 1
	}
	return 0
}
<|endoftext|>


<commit_before>package toscalib

import (
	"io"
	"io/ioutil"
	//"regexp"

	"github.com/gonum/matrix/mat64"
	"gopkg.in/yaml.v2"
)

// NodeGap is the gap between each node see @FillAdjacencyMatrix for explanation
const nodeGap int = 10

// GetInitialIndex return the index of the initial state of the node in the AdjacencyMatrix
func (nodeTemplate *NodeTemplate) GetInitialIndex() int { return nodeTemplate.Id }

// GetCreateIndex return the index of the Create state of the node in the AdjacencyMatrix
func (nodeTemplate *NodeTemplate) GetCreateIndex() int { return nodeTemplate.Id + 1 }

// GetPreConfigureSourceIndex return the index of the pre_configure_source state of the node in the AdjacencyMatrix
func (nodeTemplate *NodeTemplate) GetPreConfigureSourceIndex() int  { return nodeTemplate.Id + 2 }
func (nodeTemplate *NodeTemplate) GetPreConfigureTargetIndex() int  { return nodeTemplate.Id + 3 }
func (nodeTemplate *NodeTemplate) GetConfigureIndex() int           { return nodeTemplate.Id + 4 }
func (nodeTemplate *NodeTemplate) GetPostConfigureSourceIndex() int { return nodeTemplate.Id + 5 }
func (nodeTemplate *NodeTemplate) GetPostConfigureTargetIndex() int { return nodeTemplate.Id + 6 }
func (nodeTemplate *NodeTemplate) GetStartIndex() int               { return nodeTemplate.Id + 7 }
func (nodeTemplate *NodeTemplate) GetStopIndex() int                { return nodeTemplate.Id + 8 }
func (nodeTemplate *NodeTemplate) GetDeleteIndex() int              { return nodeTemplate.Id + 9 }

func (nodeTemplate *NodeTemplate) SetName(name string) {
	nodeTemplate.Name = name
}

// GetNodeTemplate returns a pointer to a node template given its name
// its returns nil if not found
func (toscaStructure *ToscaDefinition) GetNodeTemplate(nodeName string) *NodeTemplate {
	for name, nodeTemplate := range toscaStructure.TopologyTemplate.NodeTemplates {
		if name == nodeName {
			return &nodeTemplate
		}
	}
	return nil
}

// GetNodeTemplate returns a pointer to a node template given its id
// the ID may be the initial index or whatever index of the lifecycle operation
// its returns nil if not found
func (toscaStructure *ToscaDefinition) GetNodeTemplateFromId(nodeId int) *NodeTemplate {
	for _, nodeTemplate := range toscaStructure.TopologyTemplate.NodeTemplates {
		if nodeTemplate.Id == nodeId-(nodeId%nodeGap)+1 {
			return &nodeTemplate
		}
	}
	return nil
}

// FillAdjacencyMatrix fills the adjacency matrix AdjacencyMatrix in the current ToscaDefinition structure
// for more information, see doc/node_instanciation_lifecycle.md
func (toscaStructure *ToscaDefinition) FillAdjacencyMatrix() error {
	// Get the number of nodes
	numberOfNodes := len(toscaStructure.TopologyTemplate.NodeTemplates)
	// Initialize the AdjacencyMatrix
	adjacencyMatrix := mat64.NewDense(numberOfNodes*nodeGap, numberOfNodes*nodeGap, nil)
	index := 1
	for i, nodeDetail := range toscaStructure.TopologyTemplate.NodeTemplates {
		// Set the Id of the node
		nodeDetail.Id = index
		toscaStructure.TopologyTemplate.NodeTemplates[i] = nodeDetail
		index = index + nodeGap
	}
	// Then set the matrix
	for nodeAName, nodeDetail := range toscaStructure.TopologyTemplate.NodeTemplates {
		// Check if the current node has at least one requirement with an interface of type tosca.interfaces.relationship.Configure
		var res1 bool
		var res2 bool
		if nodeDetail.Requirements != nil {
			for _, requirementAssignements := range nodeDetail.Requirements {
				for _, requirementAssignement := range requirementAssignements {
					nodeBName := requirementAssignement.Node
					// Check if we have a requirement type that is .*Configure of if we have an Interface key that is .*Configure
					/*
						res1, _ = regexp.MatchString(".*Configure", requirementAssignement.Relationship.Type)
						for inter := range requirementAssignement.Relationship.Interfaces {
							res2, _ = regexp.MatchString(".*Configure", inter)
							if res2 == true {
								break
							}
						}
					*/
					// We have a Configure relationship
					if res1 == true || res2 == true {
						//log.Printf("%v Special workflow with %v", nodeAName, nodeBName)
						nodeA := toscaStructure.GetNodeTemplate(nodeAName)
						nodeB := toscaStructure.GetNodeTemplate(nodeBName)
						//nodeB:Create() -> nodeA:Create()
						adjacencyMatrix.Set(nodeB.GetCreateIndex(), nodeA.GetCreateIndex(), 1)
						//nodeA:Create() -> nodeA:PreConfigureSource()
						adjacencyMatrix.Set(nodeA.GetCreateIndex(), nodeA.GetPreConfigureSourceIndex(), 1)
						//nodeA:PreConfigureSource -> nodeB:PreConfigureTarget()
						adjacencyMatrix.Set(nodeA.GetPreConfigureSourceIndex(), nodeB.GetPreConfigureTargetIndex(), 1)
						//nodeB:PreConfigureTarget -> nodeA:Configure()
						adjacencyMatrix.Set(nodeB.GetPreConfigureTargetIndex(), nodeA.GetConfigureIndex(), 1)
						//nodeB:PreConfigureTarget -> nodeB:Configure()
						adjacencyMatrix.Set(nodeB.GetPreConfigureTargetIndex(), nodeB.GetConfigureIndex(), 1)
						//nodeA:Configure() -> nodeA:PostConfigureSource()
						adjacencyMatrix.Set(nodeA.GetConfigureIndex(), nodeA.GetPostConfigureSourceIndex(), 1)
						//nodeB:Configure() -> nodeB:PostConfigureTarget()
						adjacencyMatrix.Set(nodeB.GetConfigureIndex(), nodeB.GetPostConfigureTargetIndex(), 1)
						//nodeA:PostConfigureSource() -> nodeA:Start()
						adjacencyMatrix.Set(nodeA.GetPostConfigureSourceIndex(), nodeA.GetStartIndex(), 1)
						//nodeB:PostConfigureTarget() -> nodeB:Start()
						adjacencyMatrix.Set(nodeB.GetPostConfigureTargetIndex(), nodeB.GetStartIndex(), 1)
						//nodeB:Start() -> nodeA:Start()
						adjacencyMatrix.Set(nodeA.GetStartIndex(), nodeA.GetStartIndex(), 1)
					} else {
						//log.Printf("%v normal workflow with %v", nodeAName, nodeBName)
						nodeA := toscaStructure.GetNodeTemplate(nodeAName)
						nodeB := toscaStructure.GetNodeTemplate(nodeBName)
						// nodeB:Create() -> nodeB:Configure() -> nodeB:Start() -> nodeA:Create() -> nodeA:Configure() -> nodeA:Start()
						adjacencyMatrix.Set(nodeB.GetCreateIndex(), nodeB.GetConfigureIndex(), 1)
						adjacencyMatrix.Set(nodeB.GetConfigureIndex(), nodeB.GetStartIndex(), 1)
						adjacencyMatrix.Set(nodeB.GetStartIndex(), nodeA.GetCreateIndex(), 1)
						adjacencyMatrix.Set(nodeA.GetCreateIndex(), nodeA.GetConfigureIndex(), 1)
						adjacencyMatrix.Set(nodeA.GetConfigureIndex(), nodeA.GetStartIndex(), 1)
					}
				}

			}
		}
		index = index + nodeGap
	}
	toscaStructure.AdjacencyMatrix = *adjacencyMatrix
	return nil
}

// Parse a TOSCA document and fill in the structure
func (toscaStructure *ToscaDefinition) Parse(r io.Reader) error {
	var tempStruct ToscaDefinition
	tempStruct.NodeTypes = make(map[string]NodeType)
	data, err := ioutil.ReadAll(r)
	if err != nil {
		return err
	}

	// Unmarshal the data in an interface
	err = yaml.Unmarshal(data, &tempStruct)
	if err != nil {
		return err
	}
	// Sets the initial state
	for _, nodeTemplate := range tempStruct.TopologyTemplate.NodeTemplates {
		nodeTemplate.RunChan = make(chan int)
		nodeTemplate.State = StateInitial
	}
	/*
		// for each node, add its corresponding notetype definition to the structure
		// if not present yet

		// index is the node name and nodeTemplate is the corresponding NodeTemplate
		for _, nodeTemplate := range tempStruct.TopologyTemplate.NodeTemplates {
			// nodeType is he node type of the current NodeTemplate
			nodeType := nodeTemplate.Type
			if _, typeIsPresent := tempStruct.NodeTypes[nodeType]; typeIsPresent == false {
				// Get the corresponding asset and add it to the global structure
				data, err := Asset(nodeType)
				if err != nil {
					//  For debuging purpode
					log.Printf("Cannot find the NodeType definition for %v", nodeType)
				}
				var nt map[string]NodeType
				// Unmarshal the data in an interface
				err = yaml.Unmarshal(data, &nt)
				if err != nil {
					return errors.New(fmt.Sprintf("cannot unmarshal %v (%v)", nodeType, err))
				}
				tempStruct.NodeTypes[nodeType] = nt[nodeType]
			}
		}
	*/
	// TODO: deal with the import files
	*toscaStructure = tempStruct
	err = toscaStructure.FillAdjacencyMatrix()
	// Fill in the name of the template inside the template itself
	for n, _ := range toscaStructure.TopologyTemplate.NodeTemplates {
		nt := toscaStructure.GetNodeTemplate(n)
		nt.SetName(n)
		toscaStructure.TopologyTemplate.NodeTemplates[n] = *nt

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

}
<commit_msg>[Enhancement] Dealing with imports<commit_after>package toscalib

import (
	"io"
	"io/ioutil"
	//"regexp"
	"os"

	"github.com/gonum/matrix/mat64"
	"gopkg.in/yaml.v2"
)

// NodeGap is the gap between each node see @FillAdjacencyMatrix for explanation
const nodeGap int = 10

// GetInitialIndex return the index of the initial state of the node in the AdjacencyMatrix
func (nodeTemplate *NodeTemplate) GetInitialIndex() int { return nodeTemplate.Id }

// GetCreateIndex return the index of the Create state of the node in the AdjacencyMatrix
func (nodeTemplate *NodeTemplate) GetCreateIndex() int { return nodeTemplate.Id + 1 }

// GetPreConfigureSourceIndex return the index of the pre_configure_source state of the node in the AdjacencyMatrix
func (nodeTemplate *NodeTemplate) GetPreConfigureSourceIndex() int  { return nodeTemplate.Id + 2 }
func (nodeTemplate *NodeTemplate) GetPreConfigureTargetIndex() int  { return nodeTemplate.Id + 3 }
func (nodeTemplate *NodeTemplate) GetConfigureIndex() int           { return nodeTemplate.Id + 4 }
func (nodeTemplate *NodeTemplate) GetPostConfigureSourceIndex() int { return nodeTemplate.Id + 5 }
func (nodeTemplate *NodeTemplate) GetPostConfigureTargetIndex() int { return nodeTemplate.Id + 6 }
func (nodeTemplate *NodeTemplate) GetStartIndex() int               { return nodeTemplate.Id + 7 }
func (nodeTemplate *NodeTemplate) GetStopIndex() int                { return nodeTemplate.Id + 8 }
func (nodeTemplate *NodeTemplate) GetDeleteIndex() int              { return nodeTemplate.Id + 9 }

func (nodeTemplate *NodeTemplate) SetName(name string) {
	nodeTemplate.Name = name
}

// GetNodeTemplate returns a pointer to a node template given its name
// its returns nil if not found
func (toscaStructure *ServiceTemplateDefinition) GetNodeTemplate(nodeName string) *NodeTemplate {
	for name, nodeTemplate := range toscaStructure.TopologyTemplate.NodeTemplates {
		if name == nodeName {
			return &nodeTemplate
		}
	}
	return nil
}

// GetNodeTemplate returns a pointer to a node template given its id
// the ID may be the initial index or whatever index of the lifecycle operation
// its returns nil if not found
func (toscaStructure *ServiceTemplateDefinition) GetNodeTemplateFromId(nodeId int) *NodeTemplate {
	for _, nodeTemplate := range toscaStructure.TopologyTemplate.NodeTemplates {
		if nodeTemplate.Id == nodeId-(nodeId%nodeGap)+1 {
			return &nodeTemplate
		}
	}
	return nil
}

// FillAdjacencyMatrix fills the adjacency matrix AdjacencyMatrix in the current ServiceTemplateDefinition structure
// for more information, see doc/node_instanciation_lifecycle.md
func (toscaStructure *ServiceTemplateDefinition) FillAdjacencyMatrix() error {
	// Get the number of nodes
	numberOfNodes := len(toscaStructure.TopologyTemplate.NodeTemplates)
	// Initialize the AdjacencyMatrix
	adjacencyMatrix := mat64.NewDense(numberOfNodes*nodeGap, numberOfNodes*nodeGap, nil)
	index := 1
	for i, nodeDetail := range toscaStructure.TopologyTemplate.NodeTemplates {
		// Set the Id of the node
		nodeDetail.Id = index
		toscaStructure.TopologyTemplate.NodeTemplates[i] = nodeDetail
		index = index + nodeGap
	}
	// Then set the matrix
	for nodeAName, nodeDetail := range toscaStructure.TopologyTemplate.NodeTemplates {
		// Check if the current node has at least one requirement with an interface of type tosca.interfaces.relationship.Configure
		var res1 bool
		var res2 bool
		if nodeDetail.Requirements != nil {
			for _, requirementAssignements := range nodeDetail.Requirements {
				for _, requirementAssignement := range requirementAssignements {
					nodeBName := requirementAssignement.Node
					// Check if we have a requirement type that is .*Configure of if we have an Interface key that is .*Configure
					/*
						res1, _ = regexp.MatchString(".*Configure", requirementAssignement.Relationship.Type)
						for inter := range requirementAssignement.Relationship.Interfaces {
							res2, _ = regexp.MatchString(".*Configure", inter)
							if res2 == true {
								break
							}
						}
					*/
					// We have a Configure relationship
					if res1 == true || res2 == true {
						//log.Printf("%v Special workflow with %v", nodeAName, nodeBName)
						nodeA := toscaStructure.GetNodeTemplate(nodeAName)
						nodeB := toscaStructure.GetNodeTemplate(nodeBName)
						//nodeB:Create() -> nodeA:Create()
						adjacencyMatrix.Set(nodeB.GetCreateIndex(), nodeA.GetCreateIndex(), 1)
						//nodeA:Create() -> nodeA:PreConfigureSource()
						adjacencyMatrix.Set(nodeA.GetCreateIndex(), nodeA.GetPreConfigureSourceIndex(), 1)
						//nodeA:PreConfigureSource -> nodeB:PreConfigureTarget()
						adjacencyMatrix.Set(nodeA.GetPreConfigureSourceIndex(), nodeB.GetPreConfigureTargetIndex(), 1)
						//nodeB:PreConfigureTarget -> nodeA:Configure()
						adjacencyMatrix.Set(nodeB.GetPreConfigureTargetIndex(), nodeA.GetConfigureIndex(), 1)
						//nodeB:PreConfigureTarget -> nodeB:Configure()
						adjacencyMatrix.Set(nodeB.GetPreConfigureTargetIndex(), nodeB.GetConfigureIndex(), 1)
						//nodeA:Configure() -> nodeA:PostConfigureSource()
						adjacencyMatrix.Set(nodeA.GetConfigureIndex(), nodeA.GetPostConfigureSourceIndex(), 1)
						//nodeB:Configure() -> nodeB:PostConfigureTarget()
						adjacencyMatrix.Set(nodeB.GetConfigureIndex(), nodeB.GetPostConfigureTargetIndex(), 1)
						//nodeA:PostConfigureSource() -> nodeA:Start()
						adjacencyMatrix.Set(nodeA.GetPostConfigureSourceIndex(), nodeA.GetStartIndex(), 1)
						//nodeB:PostConfigureTarget() -> nodeB:Start()
						adjacencyMatrix.Set(nodeB.GetPostConfigureTargetIndex(), nodeB.GetStartIndex(), 1)
						//nodeB:Start() -> nodeA:Start()
						adjacencyMatrix.Set(nodeA.GetStartIndex(), nodeA.GetStartIndex(), 1)
					} else {
						//log.Printf("%v normal workflow with %v", nodeAName, nodeBName)
						nodeA := toscaStructure.GetNodeTemplate(nodeAName)
						nodeB := toscaStructure.GetNodeTemplate(nodeBName)
						// nodeB:Create() -> nodeB:Configure() -> nodeB:Start() -> nodeA:Create() -> nodeA:Configure() -> nodeA:Start()
						adjacencyMatrix.Set(nodeB.GetCreateIndex(), nodeB.GetConfigureIndex(), 1)
						adjacencyMatrix.Set(nodeB.GetConfigureIndex(), nodeB.GetStartIndex(), 1)
						adjacencyMatrix.Set(nodeB.GetStartIndex(), nodeA.GetCreateIndex(), 1)
						adjacencyMatrix.Set(nodeA.GetCreateIndex(), nodeA.GetConfigureIndex(), 1)
						adjacencyMatrix.Set(nodeA.GetConfigureIndex(), nodeA.GetStartIndex(), 1)
					}
				}

			}
		}
		index = index + nodeGap
	}
	toscaStructure.AdjacencyMatrix = *adjacencyMatrix
	return nil
}

// Parse a TOSCA document and fill in the structure
func (t *ServiceTemplateDefinition) Parse(r io.Reader) error {
	var tempStruct ServiceTemplateDefinition
	tempStruct.NodeTypes = make(map[string]NodeType)
	data, err := ioutil.ReadAll(r)
	if err != nil {
		return err
	}

	// Unmarshal the data in an interface
	err = yaml.Unmarshal(data, &tempStruct)
	if err != nil {
		return err
	}
	// Sets the initial state
	for _, nt := range tempStruct.TopologyTemplate.NodeTemplates {
		nt.RunChan = make(chan int)
		nt.State = StateInitial
	}
	// Deal with the imports
	imports := make([]ServiceTemplateDefinition, 0)
	for _, im := range tempStruct.Imports {
		var tt ServiceTemplateDefinition
		r, err := os.Open(im)
		if err != nil {
			return err
		}
		err = tt.Parse(r)
		r.Close()
		if err != nil {
			return err
		}
		imports = append(imports, tt)
	}

	// Now reconstruct the global definition (only the types by now)
	for _, i := range imports {
		for key, m := range i.NodeTypes {
			if _, ok := tempStruct.NodeTypes[key]; !ok {
				tempStruct.NodeTypes[key] = m
			}
		}
	}

	*t = tempStruct
	err = t.FillAdjacencyMatrix()
	// Fill in the name of the template inside the template itself
	for n, _ := range t.TopologyTemplate.NodeTemplates {
		nt := t.GetNodeTemplate(n)
		nt.SetName(n)
		t.TopologyTemplate.NodeTemplates[n] = *nt

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

}
<|endoftext|>