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

package release

import (
	"fmt"
	"strings"

	"code.gitea.io/gitea/models"
	"code.gitea.io/gitea/modules/git"
	"code.gitea.io/gitea/modules/log"
	"code.gitea.io/gitea/modules/notification"
	"code.gitea.io/gitea/modules/repository"
	"code.gitea.io/gitea/modules/storage"
	"code.gitea.io/gitea/modules/timeutil"
)

func createTag(gitRepo *git.Repository, rel *models.Release) error {
	// Only actual create when publish.
	if !rel.IsDraft {
		if !gitRepo.IsTagExist(rel.TagName) {
			commit, err := gitRepo.GetCommit(rel.Target)
			if err != nil {
				return fmt.Errorf("GetCommit: %v", err)
			}

			// Trim '--' prefix to prevent command line argument vulnerability.
			rel.TagName = strings.TrimPrefix(rel.TagName, "--")
			if err = gitRepo.CreateTag(rel.TagName, commit.ID.String()); err != nil {
				if strings.Contains(err.Error(), "is not a valid tag name") {
					return models.ErrInvalidTagName{
						TagName: rel.TagName,
					}
				}
				return err
			}
			rel.LowerTagName = strings.ToLower(rel.TagName)
			// Prepare Notify
			if err := rel.LoadAttributes(); err != nil {
				log.Error("LoadAttributes: %v", err)
				return err
			}
			notification.NotifyPushCommits(
				rel.Publisher, rel.Repo,
				&repository.PushUpdateOptions{
					RefFullName: git.TagPrefix + rel.TagName,
					OldCommitID: git.EmptySHA,
					NewCommitID: commit.ID.String(),
				}, repository.NewPushCommits())
			notification.NotifyCreateRef(rel.Publisher, rel.Repo, "tag", git.TagPrefix+rel.TagName)
			rel.CreatedUnix = timeutil.TimeStampNow()
		}
		commit, err := gitRepo.GetTagCommit(rel.TagName)
		if err != nil {
			return fmt.Errorf("GetTagCommit: %v", err)
		}

		rel.Sha1 = commit.ID.String()
		rel.NumCommits, err = commit.CommitsCount()
		if err != nil {
			return fmt.Errorf("CommitsCount: %v", err)
		}

		u, err := models.GetUserByEmail(commit.Author.Email)
		if err == nil {
			rel.PublisherID = u.ID
		}

	} else {
		rel.CreatedUnix = timeutil.TimeStampNow()
	}
	return nil
}

// CreateRelease creates a new release of repository.
func CreateRelease(gitRepo *git.Repository, rel *models.Release, attachmentUUIDs []string) error {
	isExist, err := models.IsReleaseExist(rel.RepoID, rel.TagName)
	if err != nil {
		return err
	} else if isExist {
		return models.ErrReleaseAlreadyExist{
			TagName: rel.TagName,
		}
	}

	if err = createTag(gitRepo, rel); err != nil {
		return err
	}

	rel.LowerTagName = strings.ToLower(rel.TagName)
	if err = models.InsertRelease(rel); err != nil {
		return err
	}

	if err = models.AddReleaseAttachments(rel.ID, attachmentUUIDs); err != nil {
		return err
	}

	if !rel.IsDraft {
		notification.NotifyNewRelease(rel)
	}

	return nil
}

// UpdateReleaseOrCreatReleaseFromTag updates information of a release or create release from tag.
func UpdateReleaseOrCreatReleaseFromTag(doer *models.User, gitRepo *git.Repository, rel *models.Release, attachmentUUIDs []string, isCreate bool) (err error) {
	if err = createTag(gitRepo, rel); err != nil {
		return err
	}
	rel.LowerTagName = strings.ToLower(rel.TagName)

	if err = models.UpdateRelease(models.DefaultDBContext(), rel); err != nil {
		return err
	}

	if err = models.AddReleaseAttachments(rel.ID, attachmentUUIDs); err != nil {
		log.Error("AddReleaseAttachments: %v", err)
	}

	if !isCreate {
		notification.NotifyUpdateRelease(doer, rel)
		return
	}

	if !rel.IsDraft {
		notification.NotifyNewRelease(rel)
	}

	return err
}

// DeleteReleaseByID deletes a release and corresponding Git tag by given ID.
func DeleteReleaseByID(id int64, doer *models.User, delTag bool) error {
	rel, err := models.GetReleaseByID(id)
	if err != nil {
		return fmt.Errorf("GetReleaseByID: %v", err)
	}

	repo, err := models.GetRepositoryByID(rel.RepoID)
	if err != nil {
		return fmt.Errorf("GetRepositoryByID: %v", err)
	}

	if delTag {
		if stdout, err := git.NewCommand("tag", "-d", rel.TagName).
			SetDescription(fmt.Sprintf("DeleteReleaseByID (git tag -d): %d", rel.ID)).
			RunInDir(repo.RepoPath()); err != nil && !strings.Contains(err.Error(), "not found") {
			log.Error("DeleteReleaseByID (git tag -d): %d in %v Failed:\nStdout: %s\nError: %v", rel.ID, repo, stdout, err)
			return fmt.Errorf("git tag -d: %v", err)
		}

		if err := models.DeleteReleaseByID(id); err != nil {
			return fmt.Errorf("DeleteReleaseByID: %v", err)
		}
	} else {
		rel.IsTag = true

		if err = models.UpdateRelease(models.DefaultDBContext(), rel); err != nil {
			return fmt.Errorf("Update: %v", err)
		}
	}

	rel.Repo = repo
	if err = rel.LoadAttributes(); err != nil {
		return fmt.Errorf("LoadAttributes: %v", err)
	}

	if err := models.DeleteAttachmentsByRelease(rel.ID); err != nil {
		return fmt.Errorf("DeleteAttachments: %v", err)
	}

	for i := range rel.Attachments {
		attachment := rel.Attachments[i]
		if err := storage.Attachments.Delete(attachment.RelativePath()); err != nil {
			log.Error("Delete attachment %s of release %s failed: %v", attachment.UUID, rel.ID, err)
		}
	}

	notification.NotifyDeleteRelease(doer, rel)

	return nil
}
<commit_msg>Send webhook when tag is removed via Web UI (#14015)<commit_after>// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package release

import (
	"fmt"
	"strings"

	"code.gitea.io/gitea/models"
	"code.gitea.io/gitea/modules/git"
	"code.gitea.io/gitea/modules/log"
	"code.gitea.io/gitea/modules/notification"
	"code.gitea.io/gitea/modules/repository"
	"code.gitea.io/gitea/modules/storage"
	"code.gitea.io/gitea/modules/timeutil"
)

func createTag(gitRepo *git.Repository, rel *models.Release) error {
	// Only actual create when publish.
	if !rel.IsDraft {
		if !gitRepo.IsTagExist(rel.TagName) {
			commit, err := gitRepo.GetCommit(rel.Target)
			if err != nil {
				return fmt.Errorf("GetCommit: %v", err)
			}

			// Trim '--' prefix to prevent command line argument vulnerability.
			rel.TagName = strings.TrimPrefix(rel.TagName, "--")
			if err = gitRepo.CreateTag(rel.TagName, commit.ID.String()); err != nil {
				if strings.Contains(err.Error(), "is not a valid tag name") {
					return models.ErrInvalidTagName{
						TagName: rel.TagName,
					}
				}
				return err
			}
			rel.LowerTagName = strings.ToLower(rel.TagName)
			// Prepare Notify
			if err := rel.LoadAttributes(); err != nil {
				log.Error("LoadAttributes: %v", err)
				return err
			}
			notification.NotifyPushCommits(
				rel.Publisher, rel.Repo,
				&repository.PushUpdateOptions{
					RefFullName: git.TagPrefix + rel.TagName,
					OldCommitID: git.EmptySHA,
					NewCommitID: commit.ID.String(),
				}, repository.NewPushCommits())
			notification.NotifyCreateRef(rel.Publisher, rel.Repo, "tag", git.TagPrefix+rel.TagName)
			rel.CreatedUnix = timeutil.TimeStampNow()
		}
		commit, err := gitRepo.GetTagCommit(rel.TagName)
		if err != nil {
			return fmt.Errorf("GetTagCommit: %v", err)
		}

		rel.Sha1 = commit.ID.String()
		rel.NumCommits, err = commit.CommitsCount()
		if err != nil {
			return fmt.Errorf("CommitsCount: %v", err)
		}

		u, err := models.GetUserByEmail(commit.Author.Email)
		if err == nil {
			rel.PublisherID = u.ID
		}

	} else {
		rel.CreatedUnix = timeutil.TimeStampNow()
	}
	return nil
}

// CreateRelease creates a new release of repository.
func CreateRelease(gitRepo *git.Repository, rel *models.Release, attachmentUUIDs []string) error {
	isExist, err := models.IsReleaseExist(rel.RepoID, rel.TagName)
	if err != nil {
		return err
	} else if isExist {
		return models.ErrReleaseAlreadyExist{
			TagName: rel.TagName,
		}
	}

	if err = createTag(gitRepo, rel); err != nil {
		return err
	}

	rel.LowerTagName = strings.ToLower(rel.TagName)
	if err = models.InsertRelease(rel); err != nil {
		return err
	}

	if err = models.AddReleaseAttachments(rel.ID, attachmentUUIDs); err != nil {
		return err
	}

	if !rel.IsDraft {
		notification.NotifyNewRelease(rel)
	}

	return nil
}

// UpdateReleaseOrCreatReleaseFromTag updates information of a release or create release from tag.
func UpdateReleaseOrCreatReleaseFromTag(doer *models.User, gitRepo *git.Repository, rel *models.Release, attachmentUUIDs []string, isCreate bool) (err error) {
	if err = createTag(gitRepo, rel); err != nil {
		return err
	}
	rel.LowerTagName = strings.ToLower(rel.TagName)

	if err = models.UpdateRelease(models.DefaultDBContext(), rel); err != nil {
		return err
	}

	if err = models.AddReleaseAttachments(rel.ID, attachmentUUIDs); err != nil {
		log.Error("AddReleaseAttachments: %v", err)
	}

	if !isCreate {
		notification.NotifyUpdateRelease(doer, rel)
		return
	}

	if !rel.IsDraft {
		notification.NotifyNewRelease(rel)
	}

	return err
}

// DeleteReleaseByID deletes a release and corresponding Git tag by given ID.
func DeleteReleaseByID(id int64, doer *models.User, delTag bool) error {
	rel, err := models.GetReleaseByID(id)
	if err != nil {
		return fmt.Errorf("GetReleaseByID: %v", err)
	}

	repo, err := models.GetRepositoryByID(rel.RepoID)
	if err != nil {
		return fmt.Errorf("GetRepositoryByID: %v", err)
	}

	if delTag {
		if stdout, err := git.NewCommand("tag", "-d", rel.TagName).
			SetDescription(fmt.Sprintf("DeleteReleaseByID (git tag -d): %d", rel.ID)).
			RunInDir(repo.RepoPath()); err != nil && !strings.Contains(err.Error(), "not found") {
			log.Error("DeleteReleaseByID (git tag -d): %d in %v Failed:\nStdout: %s\nError: %v", rel.ID, repo, stdout, err)
			return fmt.Errorf("git tag -d: %v", err)
		}

		notification.NotifyPushCommits(
			doer, repo,
			&repository.PushUpdateOptions{
				RefFullName: git.TagPrefix + rel.TagName,
				OldCommitID: rel.Sha1,
				NewCommitID: git.EmptySHA,
			}, repository.NewPushCommits())
		notification.NotifyDeleteRef(doer, repo, "tag", git.TagPrefix+rel.TagName)

		if err := models.DeleteReleaseByID(id); err != nil {
			return fmt.Errorf("DeleteReleaseByID: %v", err)
		}
	} else {
		rel.IsTag = true

		if err = models.UpdateRelease(models.DefaultDBContext(), rel); err != nil {
			return fmt.Errorf("Update: %v", err)
		}
	}

	rel.Repo = repo
	if err = rel.LoadAttributes(); err != nil {
		return fmt.Errorf("LoadAttributes: %v", err)
	}

	if err := models.DeleteAttachmentsByRelease(rel.ID); err != nil {
		return fmt.Errorf("DeleteAttachments: %v", err)
	}

	for i := range rel.Attachments {
		attachment := rel.Attachments[i]
		if err := storage.Attachments.Delete(attachment.RelativePath()); err != nil {
			log.Error("Delete attachment %s of release %s failed: %v", attachment.UUID, rel.ID, err)
		}
	}

	notification.NotifyDeleteRelease(doer, rel)

	return nil
}
<|endoftext|>


<commit_before>package router

import (
	"encoding/json"
	"sync/atomic"

	. "github.com/onsi/ginkgo"
	"github.com/onsi/ginkgo/config"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gexec"
	"github.com/pivotal-golang/lager"
	"github.com/pivotal-golang/lager/lagertest"

	"testing"

	"github.com/cloudfoundry-incubator/cf-tcp-router-acceptance-tests/helpers"
	"github.com/cloudfoundry-incubator/cf-tcp-router/testutil"
	"github.com/cloudfoundry-incubator/routing-api"
	"github.com/cloudfoundry-incubator/routing-api/db"
	"github.com/cloudfoundry-incubator/uaa-token-fetcher"
)

func TestRouter(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Router Suite")
}

const preallocatedExternalPorts = 100

var (
	sampleReceiverPath string
	externalIP         string
	routerApiConfig    helpers.RouterApiConfig
	logger             lager.Logger
	routingApiClient   routing_api.Client
	externalPort       uint32
	bucketSize         int
	containerPort      uint32
)

func validateTcpRouteMapping(tcpRouteMapping db.TcpRouteMapping) bool {
	if tcpRouteMapping.TcpRoute.RouterGroupGuid == "" {
		return false
	}

	if tcpRouteMapping.TcpRoute.ExternalPort <= 0 {
		return false
	}

	if tcpRouteMapping.HostIP == "" {
		return false
	}

	if tcpRouteMapping.HostPort <= 0 {
		return false
	}

	return true
}

func nextExternalPort() int {
	port := int(atomic.AddUint32(&externalPort, uint32(1))) + (GinkgoParallelNode()-1)*bucketSize
	logger.Info("next-external-port", lager.Data{"ginkgo-parallel-node": GinkgoParallelNode(), "externalPort": port})
	return port
}

func nextContainerPort() int {
	port := int(atomic.AddUint32(&containerPort, uint32(1))) + (GinkgoParallelNode()-1)*bucketSize
	logger.Info("next-container-port", lager.Data{"ginkgo-parallel-node": GinkgoParallelNode(), "containerPort": port})
	return port
}

var _ = SynchronizedBeforeSuite(func() []byte {

	cleanupRoutes()

	sampleReceiver, err := gexec.Build("github.com/cloudfoundry-incubator/cf-tcp-router-acceptance-tests/assets/tcp-sample-receiver", "-race")
	Expect(err).NotTo(HaveOccurred())
	payload, err := json.Marshal(map[string]string{
		"sample-receiver": sampleReceiver,
	})

	Expect(err).NotTo(HaveOccurred())

	return payload
}, func(payload []byte) {
	context := map[string]string{}

	err := json.Unmarshal(payload, &context)
	Expect(err).NotTo(HaveOccurred())

	sampleReceiverPath = context["sample-receiver"]
	externalIP = testutil.GetExternalIP()
	routerApiConfig = helpers.LoadConfig()
	logger = lagertest.NewTestLogger("test")

	routingApiClient = routing_api.NewClient(routerApiConfig.RoutingApiUrl)
	oauth := token_fetcher.OAuthConfig{
		TokenEndpoint: routerApiConfig.OAuth.TokenEndpoint,
		ClientName:    routerApiConfig.OAuth.ClientName,
		ClientSecret:  routerApiConfig.OAuth.ClientSecret,
		Port:          routerApiConfig.OAuth.Port,
	}
	tokenFetcher := token_fetcher.NewTokenFetcher(&oauth)
	token, err := tokenFetcher.FetchToken()
	Expect(err).ToNot(HaveOccurred())
	routingApiClient.SetToken(token.AccessToken)
	externalPort = 59999
	containerPort = 5000
	bucketSize = preallocatedExternalPorts / config.GinkgoConfig.ParallelTotal
})

var _ = SynchronizedAfterSuite(func() {
}, func() {
	gexec.CleanupBuildArtifacts()
})

func cleanupRoutes() {
	routerApiConfig := helpers.LoadConfig()
	routingApiClient := routing_api.NewClient(routerApiConfig.RoutingApiUrl)
	oauth := token_fetcher.OAuthConfig{
		TokenEndpoint: routerApiConfig.OAuth.TokenEndpoint,
		ClientName:    routerApiConfig.OAuth.ClientName,
		ClientSecret:  routerApiConfig.OAuth.ClientSecret,
		Port:          routerApiConfig.OAuth.Port,
	}
	tokenFetcher := token_fetcher.NewTokenFetcher(&oauth)
	token, err := tokenFetcher.FetchToken()
	Expect(err).ToNot(HaveOccurred())
	routingApiClient.SetToken(token.AccessToken)

	// Cleaning up all the pre-existing routes.
	tcpRouteMappings, err := routingApiClient.TcpRouteMappings()
	Expect(err).ToNot(HaveOccurred())
	deleteTcpRouteMappings := make([]db.TcpRouteMapping, 0)
	for _, tcpRouteMapping := range tcpRouteMappings {
		if validateTcpRouteMapping(tcpRouteMapping) {
			deleteTcpRouteMappings = append(deleteTcpRouteMappings, tcpRouteMapping)
		}
	}
	err = routingApiClient.DeleteTcpRouteMappings(deleteTcpRouteMappings)
	Expect(err).ToNot(HaveOccurred())
}
<commit_msg>Changes to use updated token fetcher.<commit_after>package router

import (
	"encoding/json"
	"sync/atomic"
	"time"

	. "github.com/onsi/ginkgo"
	"github.com/onsi/ginkgo/config"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gexec"
	"github.com/pivotal-golang/clock"
	"github.com/pivotal-golang/lager"
	"github.com/pivotal-golang/lager/lagertest"

	"testing"

	"github.com/cloudfoundry-incubator/cf-tcp-router-acceptance-tests/helpers"
	"github.com/cloudfoundry-incubator/cf-tcp-router/testutil"
	"github.com/cloudfoundry-incubator/routing-api"
	"github.com/cloudfoundry-incubator/routing-api/db"
	"github.com/cloudfoundry-incubator/uaa-token-fetcher"
)

func TestRouter(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Router Suite")
}

const preallocatedExternalPorts = 100

var (
	sampleReceiverPath string
	externalIP         string
	routerApiConfig    helpers.RouterApiConfig
	logger             lager.Logger
	routingApiClient   routing_api.Client
	externalPort       uint32
	bucketSize         int
	containerPort      uint32
)

func validateTcpRouteMapping(tcpRouteMapping db.TcpRouteMapping) bool {
	if tcpRouteMapping.TcpRoute.RouterGroupGuid == "" {
		return false
	}

	if tcpRouteMapping.TcpRoute.ExternalPort <= 0 {
		return false
	}

	if tcpRouteMapping.HostIP == "" {
		return false
	}

	if tcpRouteMapping.HostPort <= 0 {
		return false
	}

	return true
}

func nextExternalPort() int {
	port := int(atomic.AddUint32(&externalPort, uint32(1))) + (GinkgoParallelNode()-1)*bucketSize
	logger.Info("next-external-port", lager.Data{"ginkgo-parallel-node": GinkgoParallelNode(), "externalPort": port})
	return port
}

func nextContainerPort() int {
	port := int(atomic.AddUint32(&containerPort, uint32(1))) + (GinkgoParallelNode()-1)*bucketSize
	logger.Info("next-container-port", lager.Data{"ginkgo-parallel-node": GinkgoParallelNode(), "containerPort": port})
	return port
}

var _ = SynchronizedBeforeSuite(func() []byte {
	cleanupRoutes(lagertest.NewTestLogger("cleanup"))

	sampleReceiver, err := gexec.Build("github.com/cloudfoundry-incubator/cf-tcp-router-acceptance-tests/assets/tcp-sample-receiver", "-race")
	Expect(err).NotTo(HaveOccurred())
	payload, err := json.Marshal(map[string]string{
		"sample-receiver": sampleReceiver,
	})

	Expect(err).NotTo(HaveOccurred())

	return payload
}, func(payload []byte) {
	context := map[string]string{}

	err := json.Unmarshal(payload, &context)
	Expect(err).NotTo(HaveOccurred())
	logger = lagertest.NewTestLogger("test")
	sampleReceiverPath = context["sample-receiver"]
	externalIP = testutil.GetExternalIP()
	routerApiConfig = helpers.LoadConfig()

	routingApiClient = routing_api.NewClient(routerApiConfig.RoutingApiUrl)

	tokenFetcher, err := createTokenFetcher(logger, routerApiConfig)
	Expect(err).ToNot(HaveOccurred())

	token, err := tokenFetcher.FetchToken(true)
	Expect(err).ToNot(HaveOccurred())
	routingApiClient.SetToken(token.AccessToken)
	externalPort = 59999
	containerPort = 5000
	bucketSize = preallocatedExternalPorts / config.GinkgoConfig.ParallelTotal
})

var _ = SynchronizedAfterSuite(func() {
}, func() {
	gexec.CleanupBuildArtifacts()
})

func cleanupRoutes(logger lager.Logger) {
	routerApiConfig := helpers.LoadConfig()
	routingApiClient := routing_api.NewClient(routerApiConfig.RoutingApiUrl)

	tokenFetcher, err := createTokenFetcher(logger, routerApiConfig)
	Expect(err).ToNot(HaveOccurred())

	token, err := tokenFetcher.FetchToken(true)
	Expect(err).ToNot(HaveOccurred())
	routingApiClient.SetToken(token.AccessToken)

	// Cleaning up all the pre-existing routes.
	tcpRouteMappings, err := routingApiClient.TcpRouteMappings()
	Expect(err).ToNot(HaveOccurred())
	deleteTcpRouteMappings := make([]db.TcpRouteMapping, 0)
	for _, tcpRouteMapping := range tcpRouteMappings {
		if validateTcpRouteMapping(tcpRouteMapping) {
			deleteTcpRouteMappings = append(deleteTcpRouteMappings, tcpRouteMapping)
		}
	}
	err = routingApiClient.DeleteTcpRouteMappings(deleteTcpRouteMappings)
	Expect(err).ToNot(HaveOccurred())
}

func createTokenFetcher(logger lager.Logger, routerApiConfig helpers.RouterApiConfig) (token_fetcher.TokenFetcher, error) {
	oauth := token_fetcher.OAuthConfig{
		TokenEndpoint: routerApiConfig.OAuth.TokenEndpoint,
		ClientName:    routerApiConfig.OAuth.ClientName,
		ClientSecret:  routerApiConfig.OAuth.ClientSecret,
		Port:          routerApiConfig.OAuth.Port,
	}
	clock := clock.NewClock()

	logger.Debug("creating-uaa-token-fetcher")

	tokenFetcherConfig := token_fetcher.TokenFetcherConfig{
		MaxNumberOfRetries:   uint32(3),
		RetryInterval:        5 * time.Second,
		ExpirationBufferTime: int64(30),
	}
	return token_fetcher.NewTokenFetcher(logger, &oauth, tokenFetcherConfig, clock)
}
<|endoftext|>


<commit_before>package perfTestUtils

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/stretchr/testify/assert"
	"io"
	"math/rand"
	"net/http"
	"os"
	"strings"
	"testing"
	"time"
)

var mockedFs FileSystem = mockFs{}

type mockFs struct{}

func (mockFs) Open(name string) (File, error) { return &mockedFile{}, nil }
func (mockFs) Create(name string) (File, error) {
	if strings.Contains(name, "FAIL") {
		return nil, fmt.Errorf("requested mock FAIL!")
	}
	return &mockedFile{}, nil
}

type mockedFile struct {
	Content []byte
	r       *strings.Reader
}

func (mockedFile) Readdir(n int) (fi []os.FileInfo, err error) {
	if n == -1 {
		return make([]os.FileInfo, 10), nil
	} else {
		return nil, fmt.Errorf("Mock dir error!")
	}
}
func (mockedFile) Close() error { return nil }

func (mockedFile) Write(p []byte) (n int, err error) { return io.WriteString(os.Stdout, string(p)) }
func (m *mockedFile) Read(p []byte) (n int, err error) {
	if m.r == nil {
		m.r = strings.NewReader(string(m.Content))
	}
	return m.r.Read(p)
}

func TestReadBasePerfFile(t *testing.T) {
	bs := &BasePerfStats{
		BasePeakMemory: 10e6 - 10e3,
	}
	bma := make([]uint64, 0)
	for i := 0; i < 100; i++ {
		bma = append(bma, bs.BasePeakMemory+uint64(10e5*rand.Int()))
	}
	bs.MemoryAudit = bma
	bsrt := make(map[string]int64)
	bsrt["service 1"] = 3e6
	bsrt["service 2"] = 2e6
	bsrt["service 3"] = 4e6
	bs.BaseServiceResponseTimes = bsrt

	b, err := json.Marshal(bs)
	if err != nil {
		t.Errorf("expected to be nil: %v\n", err)
	}
	t.Logf("%s\n", b)
	toTest, err := ReadBasePerfFile(bytes.NewReader(b))
	assert.Nil(t, err)
	assert.NotNil(t, toTest)
	assert.IsType(t, new(BasePerfStats), toTest)
	assert.Equal(t, 100, len(toTest.MemoryAudit))
}

func TestReadBasePerfFileErrUnmarshal(t *testing.T) {
	toTest, err := ReadBasePerfFile(bytes.NewReader([]byte("test")))
	assert.NotNil(t, err)
	assert.NotNil(t, toTest)
	assert.IsType(t, new(BasePerfStats), toTest)
	assert.Equal(t, 0, len(toTest.MemoryAudit))
	assert.Equal(t, `invalid character 'e' in literal true (expecting 'r')`, err.Error())
}

func TestCalcPeakMemoryVariancePercentage(t *testing.T) {
	vp := CalcPeakMemoryVariancePercentage(100, 110)
	assert.Equal(t, float64(10), vp)

	vp = CalcPeakMemoryVariancePercentage(100, 90)
	assert.Equal(t, float64(-10), vp)
}

func BenchmarkCalcPeakMemoryVariancePercentage(t *testing.B) {
	for i := 0; i < t.N; i++ {
		CalcPeakMemoryVariancePercentage(100, 90)
	}
}

func TestCalcAverageResponseTime(t *testing.T) {
	times := make([]int64, 0)
	for i := int64(200); i >= 0; i-- {
		times = append(times, i*1243)
	}
	avg := CalcAverageResponseTime(times, 2)
	assert.Equal(t, int64(111870), avg)
}

func TestCalcAverageResponseVariancePercentage(t *testing.T) {
	vp := CalcAverageResponseVariancePercentage(110, 100)
	assert.Equal(t, float64(10), vp)

	vp = CalcAverageResponseVariancePercentage(90, 100)
	assert.Equal(t, float64(-10), vp)
}

func BenchmarkCalcAverageResponseVariancePercentage(t *testing.B) {
	for i := 0; i < t.N; i++ {
		CalcAverageResponseVariancePercentage(100, 90)
	}
}

func TestPopulateBasePerfStats(t *testing.T) {
	ps := &PerfStats{
		TestTimeStart:   time.Now(),
		PeakMemory: 10e6,
	}

	bs := &BasePerfStats{
		BaseServiceResponseTimes: make(map[string]int64),
	}

	pma := make([]uint64, 0)
	for i := 0; i < 100; i++ {
		pma = append(pma, ps.PeakMemory+uint64(5e5*rand.Int()))
	}
	ps.MemoryAudit = pma

	ps.TestPartitions = []TestPartition{TestPartition{Count: 0, TestName: "StartUp"}, TestPartition{Count: 30, TestName: "service 1"}, TestPartition{Count: 60, TestName: "service 2"}, TestPartition{Count: 90, TestName: "service 3"}}

	psrt := make(map[string]int64)
	psrt["service 1"] = 3e5
	psrt["service 2"] = 2e5
	ps.ServiceResponseTimes = psrt

	populateBasePerfStats(ps, bs, false)
	assert.Equal(t, bs.BasePeakMemory, ps.PeakMemory)
	assert.Equal(t, bs.MemoryAudit, ps.MemoryAudit)
	assert.Equal(t, bs.BaseServiceResponseTimes, ps.ServiceResponseTimes)
	assert.Equal(t, bs.ModifiedDate, bs.GenerationDate)
}

func TestValidateResponseStatusCode(t *testing.T) {
	assert.True(t, ValidateResponseStatusCode(http.StatusOK, http.StatusOK, "test"))
	assert.False(t, ValidateResponseStatusCode(http.StatusOK, http.StatusInternalServerError, "test"))
}

func TestValidateServiceResponseTime(t *testing.T) {
	assert.True(t, ValidateServiceResponseTime(10, "test"))
	assert.False(t, ValidateServiceResponseTime(-10, "test"))
	assert.False(t, ValidateServiceResponseTime(0, "test"))
}

func TestValidatePeakMemoryVariance(t *testing.T) {
	assert.True(t, ValidatePeakMemoryVariance(15, 0.1))
	assert.False(t, ValidatePeakMemoryVariance(15, 16.5))
	assert.True(t, ValidatePeakMemoryVariance(15, 15))
}

func TestValidateAverageServiceResponeTimeVariance(t *testing.T) {
	assert.True(t, ValidateAverageServiceResponseTimeVariance(15, 10))
	assert.True(t, ValidateAverageServiceResponseTimeVariance(15, 15))
	assert.False(t, ValidateAverageServiceResponseTimeVariance(15, 16))
}

func TestGenerateEnvBasePerfOutputFile(t *testing.T) {
	ps := &PerfStats{
		TestTimeStart:   time.Now(),
		PeakMemory: 10e6,
	}

	bs := &BasePerfStats{
		BaseServiceResponseTimes: make(map[string]int64),
	}

	pma := make([]uint64, 0)
	for i := 0; i < 100; i++ {
		pma = append(pma, ps.PeakMemory+uint64(5e5*rand.Int()))
	}
	ps.MemoryAudit = pma

	ps.TestPartitions = []TestPartition{TestPartition{Count: 0, TestName: "StartUp"}, TestPartition{Count: 30, TestName: "service 1"}, TestPartition{Count: 60, TestName: "service 2"}, TestPartition{Count: 90, TestName: "service 3"}}

	psrt := make(map[string]int64)
	psrt["service 1"] = 3e5
	psrt["service 2"] = 2e5
	ps.ServiceResponseTimes = psrt

	willCallOsExit := false
	exit := func(i int) { willCallOsExit = true }

	GenerateEnvBasePerfOutputFile(ps, bs, &Config{ReBaseMemory: true, BaseStatsOutputDir: "env", TargetHost: "localhost"}, exit, mockedFs)
	assert.False(t, willCallOsExit)
}

func TestGenerateEnvBasePerfOutputFileFailCreate(t *testing.T) {
	ps := &PerfStats{
		TestTimeStart:   time.Now(),
		PeakMemory: 10e6,
	}

	bs := &BasePerfStats{
		BaseServiceResponseTimes: make(map[string]int64),
	}

	pma := make([]uint64, 0)
	for i := 0; i < 100; i++ {
		pma = append(pma, ps.PeakMemory+uint64(5e5*rand.Int()))
	}
	ps.MemoryAudit = pma

	ps.TestPartitions = []TestPartition{TestPartition{Count: 0, TestName: "StartUp"}, TestPartition{Count: 30, TestName: "service 1"}, TestPartition{Count: 60, TestName: "service 2"}, TestPartition{Count: 90, TestName: "service 3"}}

	psrt := make(map[string]int64)
	psrt["service 1"] = 3e5
	psrt["service 2"] = 2e5
	ps.ServiceResponseTimes = psrt

	willCallOsExit := false
	exit := func(i int) { willCallOsExit = true }

	GenerateEnvBasePerfOutputFile(ps, bs, &Config{ReBaseMemory: true, BaseStatsOutputDir: "env", ExecutionHost: "FAIL"}, exit, mockedFs)
	assert.True(t, willCallOsExit)
}

func TestValidateBasePerfStat(t *testing.T) {
	bs := &BasePerfStats{}
	assert.False(t, validateBasePerfStat(bs))

	bs.BaseServiceResponseTimes = map[string]int64{"service 1": 123, "service 2": -1}
	assert.False(t, validateBasePerfStat(bs))

	bs.BaseServiceResponseTimes = map[string]int64{"service 1": 123, "service 2": 321}
	bs.BasePeakMemory = 12
	bs.GenerationDate = "aaa"
	bs.ModifiedDate = "bbb"
	bs.MemoryAudit = []uint64{1, 2, 3}
	assert.True(t, validateBasePerfStat(bs))
}
<commit_msg>Updated unit tests to reflect skipMemCheck option.<commit_after>package perfTestUtils

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/stretchr/testify/assert"
	"io"
	"math/rand"
	"net/http"
	"os"
	"strings"
	"testing"
	"time"
)

var mockedFs FileSystem = mockFs{}

type mockFs struct{}

func (mockFs) Open(name string) (File, error) { return &mockedFile{}, nil }
func (mockFs) Create(name string) (File, error) {
	if strings.Contains(name, "FAIL") {
		return nil, fmt.Errorf("requested mock FAIL!")
	}
	return &mockedFile{}, nil
}

type mockedFile struct {
	Content []byte
	r       *strings.Reader
}

func (mockedFile) Readdir(n int) (fi []os.FileInfo, err error) {
	if n == -1 {
		return make([]os.FileInfo, 10), nil
	} else {
		return nil, fmt.Errorf("Mock dir error!")
	}
}
func (mockedFile) Close() error { return nil }

func (mockedFile) Write(p []byte) (n int, err error) { return io.WriteString(os.Stdout, string(p)) }
func (m *mockedFile) Read(p []byte) (n int, err error) {
	if m.r == nil {
		m.r = strings.NewReader(string(m.Content))
	}
	return m.r.Read(p)
}

func TestReadBasePerfFile(t *testing.T) {
	bs := &BasePerfStats{
		BasePeakMemory: 10e6 - 10e3,
	}
	bma := make([]uint64, 0)
	for i := 0; i < 100; i++ {
		bma = append(bma, bs.BasePeakMemory+uint64(10e5*rand.Int()))
	}
	bs.MemoryAudit = bma
	bsrt := make(map[string]int64)
	bsrt["service 1"] = 3e6
	bsrt["service 2"] = 2e6
	bsrt["service 3"] = 4e6
	bs.BaseServiceResponseTimes = bsrt

	b, err := json.Marshal(bs)
	if err != nil {
		t.Errorf("expected to be nil: %v\n", err)
	}
	t.Logf("%s\n", b)
	toTest, err := ReadBasePerfFile(bytes.NewReader(b))
	assert.Nil(t, err)
	assert.NotNil(t, toTest)
	assert.IsType(t, new(BasePerfStats), toTest)
	assert.Equal(t, 100, len(toTest.MemoryAudit))
}

func TestReadBasePerfFileErrUnmarshal(t *testing.T) {
	toTest, err := ReadBasePerfFile(bytes.NewReader([]byte("test")))
	assert.NotNil(t, err)
	assert.NotNil(t, toTest)
	assert.IsType(t, new(BasePerfStats), toTest)
	assert.Equal(t, 0, len(toTest.MemoryAudit))
	assert.Equal(t, `invalid character 'e' in literal true (expecting 'r')`, err.Error())
}

func TestCalcPeakMemoryVariancePercentage(t *testing.T) {
	vp := CalcPeakMemoryVariancePercentage(100, 110)
	assert.Equal(t, float64(10), vp)

	vp = CalcPeakMemoryVariancePercentage(100, 90)
	assert.Equal(t, float64(-10), vp)
}

func BenchmarkCalcPeakMemoryVariancePercentage(t *testing.B) {
	for i := 0; i < t.N; i++ {
		CalcPeakMemoryVariancePercentage(100, 90)
	}
}

func TestCalcAverageResponseTime(t *testing.T) {
	times := make([]int64, 0)
	for i := int64(200); i >= 0; i-- {
		times = append(times, i*1243)
	}
	avg := CalcAverageResponseTime(times, 2)
	assert.Equal(t, int64(111870), avg)
}

func TestCalcAverageResponseVariancePercentage(t *testing.T) {
	vp := CalcAverageResponseVariancePercentage(110, 100)
	assert.Equal(t, float64(10), vp)

	vp = CalcAverageResponseVariancePercentage(90, 100)
	assert.Equal(t, float64(-10), vp)
}

func BenchmarkCalcAverageResponseVariancePercentage(t *testing.B) {
	for i := 0; i < t.N; i++ {
		CalcAverageResponseVariancePercentage(100, 90)
	}
}

func TestPopulateBasePerfStats(t *testing.T) {
	ps := &PerfStats{
		TestTimeStart:   time.Now(),
		PeakMemory: 10e6,
	}

	bs := &BasePerfStats{
		BaseServiceResponseTimes: make(map[string]int64),
	}

	pma := make([]uint64, 0)
	for i := 0; i < 100; i++ {
		pma = append(pma, ps.PeakMemory+uint64(5e5*rand.Int()))
	}
	ps.MemoryAudit = pma

	ps.TestPartitions = []TestPartition{TestPartition{Count: 0, TestName: "StartUp"}, TestPartition{Count: 30, TestName: "service 1"}, TestPartition{Count: 60, TestName: "service 2"}, TestPartition{Count: 90, TestName: "service 3"}}

	psrt := make(map[string]int64)
	psrt["service 1"] = 3e5
	psrt["service 2"] = 2e5
	ps.ServiceResponseTimes = psrt

	populateBasePerfStats(ps, bs, false)
	assert.Equal(t, bs.BasePeakMemory, ps.PeakMemory)
	assert.Equal(t, bs.MemoryAudit, ps.MemoryAudit)
	assert.Equal(t, bs.BaseServiceResponseTimes, ps.ServiceResponseTimes)
	assert.Equal(t, bs.ModifiedDate, bs.GenerationDate)
}

func TestValidateResponseStatusCode(t *testing.T) {
	assert.True(t, ValidateResponseStatusCode(http.StatusOK, http.StatusOK, "test"))
	assert.False(t, ValidateResponseStatusCode(http.StatusOK, http.StatusInternalServerError, "test"))
}

func TestValidateServiceResponseTime(t *testing.T) {
	assert.True(t, ValidateServiceResponseTime(10, "test"))
	assert.False(t, ValidateServiceResponseTime(-10, "test"))
	assert.False(t, ValidateServiceResponseTime(0, "test"))
}

func TestValidatePeakMemoryVariance(t *testing.T) {
	assert.True(t, ValidatePeakMemoryVariance(15, 0.1))
	assert.False(t, ValidatePeakMemoryVariance(15, 16.5))
	assert.True(t, ValidatePeakMemoryVariance(15, 15))
}

func TestValidateAverageServiceResponeTimeVariance(t *testing.T) {
	assert.True(t, ValidateAverageServiceResponseTimeVariance(15, 10))
	assert.True(t, ValidateAverageServiceResponseTimeVariance(15, 15))
	assert.False(t, ValidateAverageServiceResponseTimeVariance(15, 16))
}

func TestGenerateEnvBasePerfOutputFile(t *testing.T) {
	ps := &PerfStats{
		TestTimeStart:   time.Now(),
		PeakMemory: 10e6,
	}

	bs := &BasePerfStats{
		BaseServiceResponseTimes: make(map[string]int64),
	}

	pma := make([]uint64, 0)
	for i := 0; i < 100; i++ {
		pma = append(pma, ps.PeakMemory+uint64(5e5*rand.Int()))
	}
	ps.MemoryAudit = pma

	ps.TestPartitions = []TestPartition{TestPartition{Count: 0, TestName: "StartUp"}, TestPartition{Count: 30, TestName: "service 1"}, TestPartition{Count: 60, TestName: "service 2"}, TestPartition{Count: 90, TestName: "service 3"}}

	psrt := make(map[string]int64)
	psrt["service 1"] = 3e5
	psrt["service 2"] = 2e5
	ps.ServiceResponseTimes = psrt

	willCallOsExit := false
	exit := func(i int) { willCallOsExit = true }

	GenerateEnvBasePerfOutputFile(ps, bs, &Config{ReBaseMemory: true, BaseStatsOutputDir: "env", TargetHost: "localhost"}, exit, mockedFs)
	assert.False(t, willCallOsExit)
}

func TestGenerateEnvBasePerfOutputFileFailCreate(t *testing.T) {
	ps := &PerfStats{
		TestTimeStart:   time.Now(),
		PeakMemory: 10e6,
	}

	bs := &BasePerfStats{
		BaseServiceResponseTimes: make(map[string]int64),
	}

	pma := make([]uint64, 0)
	for i := 0; i < 100; i++ {
		pma = append(pma, ps.PeakMemory+uint64(5e5*rand.Int()))
	}
	ps.MemoryAudit = pma

	ps.TestPartitions = []TestPartition{TestPartition{Count: 0, TestName: "StartUp"}, TestPartition{Count: 30, TestName: "service 1"}, TestPartition{Count: 60, TestName: "service 2"}, TestPartition{Count: 90, TestName: "service 3"}}

	psrt := make(map[string]int64)
	psrt["service 1"] = 3e5
	psrt["service 2"] = 2e5
	ps.ServiceResponseTimes = psrt

	willCallOsExit := false
	exit := func(i int) { willCallOsExit = true }

	GenerateEnvBasePerfOutputFile(ps, bs, &Config{ReBaseMemory: true, BaseStatsOutputDir: "env", ExecutionHost: "FAIL"}, exit, mockedFs)
	assert.True(t, willCallOsExit)
}

func TestValidateBasePerfStat(t *testing.T) {
	c := &Config{}
	c.SetDefaults()

	bs := &BasePerfStats{}
	assert.False(t, validateBasePerfStat(bs, c))

	bs.BaseServiceResponseTimes = map[string]int64{"service 1": 123, "service 2": -1}
	assert.False(t, validateBasePerfStat(bs, c))

	bs.BaseServiceResponseTimes = map[string]int64{"service 1": 123, "service 2": 321}
	bs.BasePeakMemory = 12
	bs.GenerationDate = "aaa"
	bs.ModifiedDate = "bbb"
	bs.MemoryAudit = []uint64{1, 2, 3}
	assert.True(t, validateBasePerfStat(bs, c))
}
<|endoftext|>


<commit_before>// Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.

package main

import (
	"fmt"
	"log"
	"strings"

	"github.com/MustWin/baremetal-sdk-go"
	"github.com/hashicorp/terraform/helper/schema"

	"github.com/oracle/terraform-provider-baremetal/client"
	"github.com/oracle/terraform-provider-baremetal/crud"
)

func LoadBalancerResource() *schema.Resource {
	return &schema.Resource{
		Create: createLoadBalancer,
		Read:   readLoadBalancer,
		Update: updateLoadBalancer,
		Delete: deleteLoadBalancer,
		Schema: map[string]*schema.Schema{
			// Required {
			"compartment_id": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"shape": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"subnet_ids": {
				Type:     schema.TypeList,
				Required: true,
				ForceNew: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"display_name": {
				Type:     schema.TypeString,
				Required: true,
			},
			// }
			// Computed {
			"id": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"ip_addresses": {
				Type:     schema.TypeList,
				Computed: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"state": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"time_created": {
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func createLoadBalancer(d *schema.ResourceData, m interface{}) (e error) {
	sync := &LoadBalancerResourceCrud{}
	sync.D = d
	sync.Client = m.(client.BareMetalClient)
	return crud.CreateResource(d, sync)
}

func readLoadBalancer(d *schema.ResourceData, m interface{}) (e error) {
	sync := &LoadBalancerResourceCrud{}
	sync.D = d
	sync.Client = m.(client.BareMetalClient)
	return crud.ReadResource(sync)
}

func updateLoadBalancer(d *schema.ResourceData, m interface{}) (e error) {
	sync := &LoadBalancerResourceCrud{}
	sync.D = d
	sync.Client = m.(client.BareMetalClient)
	return crud.UpdateResource(d, sync)
}

func deleteLoadBalancer(d *schema.ResourceData, m interface{}) (e error) {
	sync := &LoadBalancerResourceCrud{}
	sync.D = d
	sync.Client = m.(client.BareMetalClient)
	return crud.DeleteResource(d, sync)
}

// LoadBalancerResourceCrud wraps a baremetal.LoadBalancer to support crud
type LoadBalancerResourceCrud struct {
	crud.BaseCrud
	WorkRequest *baremetal.WorkRequest
	Resource    *baremetal.LoadBalancer
}

// ID delegates to the load balancer ID, falling back to the work request ID
func (s *LoadBalancerResourceCrud) ID() string {
	log.Printf("[DEBUG] lb.LoadBalancerResourceCrud.ID()")
	log.Printf("[DEBUG] lb.LoadBalancerResourceCrud.ID: Resource: %#v", s.Resource)
	if s.Resource != nil && s.Resource.ID != "" {
		log.Printf("[DEBUG] lb.LoadBalancerResourceCrud.ID: Resource.ID: %#v", s.Resource.ID)
		return s.Resource.ID
	}
	log.Printf("[DEBUG] lb.LoadBalancerResourceCrud.ID: WorkRequest: %#v", s.WorkRequest)
	if s.WorkRequest != nil {
		log.Printf("[DEBUG] lb.LoadBalancerResourceCrud.ID: WorkRequest.State: %s", s.WorkRequest.State)
		if s.WorkRequest.State == baremetal.WorkRequestSucceeded {
			log.Printf("[DEBUG] lb.LoadBalancerResourceCrud.ID: WorkRequest.LoadBalancerID: %#v", s.WorkRequest.LoadBalancerID)
			return s.WorkRequest.LoadBalancerID
		} else {
			log.Printf("[DEBUG] lb.LoadBalancerResourceCrud.ID: WorkRequest.ID: %s", s.WorkRequest.ID)
			return s.WorkRequest.ID
		}
	}
	log.Printf("[DEBUG] lb.LoadBalancerResourceCrud.ID: Resource & WorkRequest are nil, returning \"\"")
	return ""
}

// RefreshWorkRequest returns the last updated workRequest
func (s *LoadBalancerResourceCrud) RefreshWorkRequest() (*baremetal.WorkRequest, error) {
	if s.WorkRequest == nil {
		return nil, nil
	}
	wr, err := s.Client.GetWorkRequest(s.WorkRequest.ID, nil)
	if err != nil {
		return nil, err
	}
	s.WorkRequest = wr
	return wr, nil
}

// CreatedPending returns the resource states which qualify as "creating"
func (s *LoadBalancerResourceCrud) CreatedPending() []string {
	return []string{
		baremetal.ResourceWaitingForWorkRequest,
		baremetal.ResourceCreating,
	}
}

// CreatedTarget returns the resource states which qualify as "created"
func (s *LoadBalancerResourceCrud) CreatedTarget() []string {
	return []string{
		baremetal.ResourceActive,
	}
}

// DeletedPending returns the resource states which qualify as "deleting"
func (s *LoadBalancerResourceCrud) DeletedPending() []string {
	return []string{
		baremetal.ResourceWaitingForWorkRequest,
		baremetal.ResourceDeleting,
	}
}

// DeletedTarget returns the resource states which qualify as "deleted"
func (s *LoadBalancerResourceCrud) DeletedTarget() []string {
	return []string{baremetal.ResourceDeleted}
}

// Create makes a request to create a new load balancer from the resourceData
// It should leave the work request set up
func (s *LoadBalancerResourceCrud) Create() (e error) {
	sns := []string{}
	for _, v := range s.D.Get("subnet_ids").([]interface{}) {
		sns = append(sns, v.(string))
	}

	opts := &baremetal.CreateOptions{}
	opts.DisplayName = s.D.Get("display_name").(string)

	workReqID, e := s.Client.CreateLoadBalancer(
		nil,
		nil,
		s.D.Get("compartment_id").(string),
		nil,
		s.D.Get("shape").(string),
		sns,
		opts)

	if e != nil {
		return
	}
	s.WorkRequest, e = s.Client.GetWorkRequest(workReqID, nil)
	s.D.Set("state", s.WorkRequest.State)
	return
}

// Get makes a request to get the load balancer, populating s.Resource.
func (s *LoadBalancerResourceCrud) Get() (e error) {
	// key: {workRequestID} || {loadBalancerID}
	id := s.D.Id()
	log.Printf("[DEBUG] lb.LoadBalancerBackendResource.Get: ID: %#v", id)
	if id == "" {
		panic(fmt.Sprintf("LoadBalancer had empty ID: %#v Resource: %#V", s, s.Resource))
	}
	wr := s.WorkRequest
	log.Printf("[DEBUG] lb.LoadBalancerBackendResource.Get: WorkRequest: %#v", wr)
	state := s.D.Get("state").(string)
	log.Printf("[DEBUG] lb.LoadBalancerBackendResource.Get: State: %#v", state)

	// NOTE: if the id is for a work request, refresh its state and loadBalancerID. then refresh the load balancer
	if strings.HasPrefix(id, "ocid1.loadbalancerworkrequest.") {
		log.Printf("[DEBUG] lb.LoadBalancerBackendResource.Get: ID is for WorkRequest, refreshing")
		s.WorkRequest, e = s.Client.GetWorkRequest(id, nil)
		log.Printf("[DEBUG] lb.LoadBalancerBackendResource.Get: WorkRequest: %#v", s.WorkRequest)
		s.D.Set("state", s.WorkRequest.State)
		if s.WorkRequest.State == baremetal.WorkRequestSucceeded {
			id = s.WorkRequest.LoadBalancerID
			if id == "" {
				panic(fmt.Sprintf("WorkRequest had empty LoadBalancerID: %#v", s.WorkRequest))
			}
			s.D.SetId(id)
			// unset work request on success
			s.WorkRequest = nil
		} else {
			// We do not have a LoadBalancerID, so we short-circuit out
			return

		}
	}

	if !strings.HasPrefix(id, "ocid1.loadbalancer.") {
		panic(fmt.Sprintf("Cannot request loadbalancer with this ID, expected it to begin with \"ocid1.loadbalancer.\", but was: %#v", id))
	}
	log.Printf("[DEBUG] lb.LoadBalancerBackendResource.Get: ID: %#v", id)
	if id == "" {
		panic(fmt.Sprintf("LoadBalancer had empty ID: %#v Resource: %#V", s, s.Resource))
	}
	s.Resource, e = s.Client.GetLoadBalancer(id, nil)

	return
}

// Update makes a request to update the load balancer
func (s *LoadBalancerResourceCrud) Update() (e error) {
	opts := &baremetal.UpdateOptions{}
	if displayName, ok := s.D.GetOk("display_name"); ok {
		opts.DisplayName = displayName.(string)
	}

	var workReqID string
	workReqID, e = s.Client.UpdateLoadBalancer(s.D.Id(), opts)
	if e != nil {
		return
	}
	s.WorkRequest, e = s.Client.GetWorkRequest(workReqID, nil)
	return
}

// SetData populates the resourceData from the model
func (s *LoadBalancerResourceCrud) SetData() {
	// The first time this is called, we haven't actually fetched the resource yet, we just got a work request
	if s.Resource != nil && s.Resource.ID != "" {
		s.D.SetId(s.Resource.ID)
		s.D.Set("compartment_id", s.Resource.CompartmentID)
		s.D.Set("display_name", s.Resource.DisplayName)
		s.D.Set("shape", s.Resource.Shape)
		s.D.Set("subnet_ids", s.Resource.SubnetIDs)
		// Computed
		s.D.Set("id", s.Resource.ID)
		s.D.Set("state", s.Resource.State)
		s.D.Set("time_created", s.Resource.TimeCreated.String())
		ip_addresses := make([]string, len(s.Resource.IPAddresses))
		for i, ad := range s.Resource.IPAddresses {
			ip_addresses[i] = ad.IPAddress
		}
		s.D.Set("ip_addresses", ip_addresses)
	}
}

// Delete makes a request to delete the load balancer
func (s *LoadBalancerResourceCrud) Delete() (e error) {
	var workReqID string
	workReqID, e = s.Client.DeleteLoadBalancer(s.D.Id(), nil)
	if e != nil {
		return
	}
	s.WorkRequest, e = s.Client.GetWorkRequest(workReqID, nil)
	return
}
<commit_msg>Fix state transitions for load balancers. Closes #84.<commit_after>// Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.

package main

import (
	"fmt"
	"log"
	"strings"

	"github.com/MustWin/baremetal-sdk-go"
	"github.com/hashicorp/terraform/helper/schema"

	"github.com/oracle/terraform-provider-baremetal/client"
	"github.com/oracle/terraform-provider-baremetal/crud"
)

func LoadBalancerResource() *schema.Resource {
	return &schema.Resource{
		Create: createLoadBalancer,
		Read:   readLoadBalancer,
		Update: updateLoadBalancer,
		Delete: deleteLoadBalancer,
		Schema: map[string]*schema.Schema{
			// Required {
			"compartment_id": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"shape": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"subnet_ids": {
				Type:     schema.TypeList,
				Required: true,
				ForceNew: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"display_name": {
				Type:     schema.TypeString,
				Required: true,
			},
			// }
			// Computed {
			"id": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"ip_addresses": {
				Type:     schema.TypeList,
				Computed: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"state": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"time_created": {
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func createLoadBalancer(d *schema.ResourceData, m interface{}) (e error) {
	sync := &LoadBalancerResourceCrud{}
	sync.D = d
	sync.Client = m.(client.BareMetalClient)
	return crud.CreateResource(d, sync)
}

func readLoadBalancer(d *schema.ResourceData, m interface{}) (e error) {
	sync := &LoadBalancerResourceCrud{}
	sync.D = d
	sync.Client = m.(client.BareMetalClient)
	return crud.ReadResource(sync)
}

func updateLoadBalancer(d *schema.ResourceData, m interface{}) (e error) {
	sync := &LoadBalancerResourceCrud{}
	sync.D = d
	sync.Client = m.(client.BareMetalClient)
	return crud.UpdateResource(d, sync)
}

func deleteLoadBalancer(d *schema.ResourceData, m interface{}) (e error) {
	sync := &LoadBalancerResourceCrud{}
	sync.D = d
	sync.Client = m.(client.BareMetalClient)
	return crud.DeleteResource(d, sync)
}

// LoadBalancerResourceCrud wraps a baremetal.LoadBalancer to support crud
type LoadBalancerResourceCrud struct {
	crud.BaseCrud
	WorkRequest *baremetal.WorkRequest
	Resource    *baremetal.LoadBalancer
}

// ID delegates to the load balancer ID, falling back to the work request ID
func (s *LoadBalancerResourceCrud) ID() string {
	log.Printf("[DEBUG] lb.LoadBalancerResourceCrud.ID()")
	log.Printf("[DEBUG] lb.LoadBalancerResourceCrud.ID: Resource: %#v", s.Resource)
	if s.Resource != nil && s.Resource.ID != "" {
		log.Printf("[DEBUG] lb.LoadBalancerResourceCrud.ID: Resource.ID: %#v", s.Resource.ID)
		return s.Resource.ID
	}
	log.Printf("[DEBUG] lb.LoadBalancerResourceCrud.ID: WorkRequest: %#v", s.WorkRequest)
	if s.WorkRequest != nil {
		log.Printf("[DEBUG] lb.LoadBalancerResourceCrud.ID: WorkRequest.State: %s", s.WorkRequest.State)
		if s.WorkRequest.State == baremetal.WorkRequestSucceeded {
			log.Printf("[DEBUG] lb.LoadBalancerResourceCrud.ID: WorkRequest.LoadBalancerID: %#v", s.WorkRequest.LoadBalancerID)
			return s.WorkRequest.LoadBalancerID
		} else {
			log.Printf("[DEBUG] lb.LoadBalancerResourceCrud.ID: WorkRequest.ID: %s", s.WorkRequest.ID)
			return s.WorkRequest.ID
		}
	}
	log.Printf("[DEBUG] lb.LoadBalancerResourceCrud.ID: Resource & WorkRequest are nil, returning \"\"")
	return ""
}

// RefreshWorkRequest returns the last updated workRequest
func (s *LoadBalancerResourceCrud) RefreshWorkRequest() (*baremetal.WorkRequest, error) {
	if s.WorkRequest == nil {
		return nil, nil
	}
	wr, err := s.Client.GetWorkRequest(s.WorkRequest.ID, nil)
	if err != nil {
		return nil, err
	}
	s.WorkRequest = wr
	return wr, nil
}

// CreatedPending returns the resource states which qualify as "creating"
func (s *LoadBalancerResourceCrud) CreatedPending() []string {
	return []string{
		baremetal.ResourceWaitingForWorkRequest,
		baremetal.ResourceCreating,
		baremetal.WorkRequestAccepted,
		baremetal.WorkRequestInProgress,
	}
}

// CreatedTarget returns the resource states which qualify as "created"
func (s *LoadBalancerResourceCrud) CreatedTarget() []string {
	return []string{
		baremetal.ResourceActive,
	}
}

// DeletedPending returns the resource states which qualify as "deleting"
func (s *LoadBalancerResourceCrud) DeletedPending() []string {
	return []string{
		baremetal.ResourceWaitingForWorkRequest,
		baremetal.ResourceDeleting,
		baremetal.WorkRequestAccepted,
		baremetal.WorkRequestInProgress,
	}
}

// DeletedTarget returns the resource states which qualify as "deleted"
func (s *LoadBalancerResourceCrud) DeletedTarget() []string {
	return []string{baremetal.ResourceDeleted}
}

// Create makes a request to create a new load balancer from the resourceData
// It should leave the work request set up
func (s *LoadBalancerResourceCrud) Create() (e error) {
	sns := []string{}
	for _, v := range s.D.Get("subnet_ids").([]interface{}) {
		sns = append(sns, v.(string))
	}

	opts := &baremetal.CreateOptions{}
	opts.DisplayName = s.D.Get("display_name").(string)

	workReqID, e := s.Client.CreateLoadBalancer(
		nil,
		nil,
		s.D.Get("compartment_id").(string),
		nil,
		s.D.Get("shape").(string),
		sns,
		opts)

	if e != nil {
		return
	}
	s.WorkRequest, e = s.Client.GetWorkRequest(workReqID, nil)
	s.D.Set("state", s.WorkRequest.State)
	return
}

// Get makes a request to get the load balancer, populating s.Resource.
func (s *LoadBalancerResourceCrud) Get() (e error) {
	// key: {workRequestID} || {loadBalancerID}
	id := s.D.Id()
	log.Printf("[DEBUG] lb.LoadBalancerBackendResource.Get: ID: %#v", id)
	if id == "" {
		panic(fmt.Sprintf("LoadBalancer had empty ID: %#v Resource: %#V", s, s.Resource))
	}
	wr := s.WorkRequest
	log.Printf("[DEBUG] lb.LoadBalancerBackendResource.Get: WorkRequest: %#v", wr)
	state := s.D.Get("state").(string)
	log.Printf("[DEBUG] lb.LoadBalancerBackendResource.Get: State: %#v", state)

	// NOTE: if the id is for a work request, refresh its state and loadBalancerID. then refresh the load balancer
	if strings.HasPrefix(id, "ocid1.loadbalancerworkrequest.") {
		log.Printf("[DEBUG] lb.LoadBalancerBackendResource.Get: ID is for WorkRequest, refreshing")
		s.WorkRequest, e = s.Client.GetWorkRequest(id, nil)
		log.Printf("[DEBUG] lb.LoadBalancerBackendResource.Get: WorkRequest: %#v", s.WorkRequest)
		s.D.Set("state", s.WorkRequest.State)
		if s.WorkRequest.State == baremetal.WorkRequestSucceeded {
			id = s.WorkRequest.LoadBalancerID
			if id == "" {
				panic(fmt.Sprintf("WorkRequest had empty LoadBalancerID: %#v", s.WorkRequest))
			}
			s.D.SetId(id)
			// unset work request on success
			s.WorkRequest = nil
		} else {
			// We do not have a LoadBalancerID, so we short-circuit out
			return

		}
	}

	if !strings.HasPrefix(id, "ocid1.loadbalancer.") {
		panic(fmt.Sprintf("Cannot request loadbalancer with this ID, expected it to begin with \"ocid1.loadbalancer.\", but was: %#v", id))
	}
	log.Printf("[DEBUG] lb.LoadBalancerBackendResource.Get: ID: %#v", id)
	if id == "" {
		panic(fmt.Sprintf("LoadBalancer had empty ID: %#v Resource: %#V", s, s.Resource))
	}
	s.Resource, e = s.Client.GetLoadBalancer(id, nil)

	return
}

// Update makes a request to update the load balancer
func (s *LoadBalancerResourceCrud) Update() (e error) {
	opts := &baremetal.UpdateOptions{}
	if displayName, ok := s.D.GetOk("display_name"); ok {
		opts.DisplayName = displayName.(string)
	}

	var workReqID string
	workReqID, e = s.Client.UpdateLoadBalancer(s.D.Id(), opts)
	if e != nil {
		return
	}
	s.WorkRequest, e = s.Client.GetWorkRequest(workReqID, nil)
	return
}

// SetData populates the resourceData from the model
func (s *LoadBalancerResourceCrud) SetData() {
	// The first time this is called, we haven't actually fetched the resource yet, we just got a work request
	if s.Resource != nil && s.Resource.ID != "" {
		s.D.SetId(s.Resource.ID)
		s.D.Set("compartment_id", s.Resource.CompartmentID)
		s.D.Set("display_name", s.Resource.DisplayName)
		s.D.Set("shape", s.Resource.Shape)
		s.D.Set("subnet_ids", s.Resource.SubnetIDs)
		// Computed
		s.D.Set("id", s.Resource.ID)
		s.D.Set("state", s.Resource.State)
		s.D.Set("time_created", s.Resource.TimeCreated.String())
		ip_addresses := make([]string, len(s.Resource.IPAddresses))
		for i, ad := range s.Resource.IPAddresses {
			ip_addresses[i] = ad.IPAddress
		}
		s.D.Set("ip_addresses", ip_addresses)
	}
}

// Delete makes a request to delete the load balancer
func (s *LoadBalancerResourceCrud) Delete() (e error) {
	var workReqID string
	workReqID, e = s.Client.DeleteLoadBalancer(s.D.Id(), nil)
	if e != nil {
		return
	}
	s.WorkRequest, e = s.Client.GetWorkRequest(workReqID, nil)
	return
}
<|endoftext|>


<commit_before>// +build linux

package shadowsocks

import (
	"encoding/binary"
	"net"
	"syscall"
	"unsafe"
)

const SO_ORIGINAL_DST = 80

func ntohs(in uint16) (out uint16) {
	data := [2]byte{}
	binary.LittleEndian.PutUint16(data[:], in)
	if uint16(data[0]) == in&0xff { // LE
		return binary.BigEndian.Uint16(data[:])
	} else { // BE
		return in
	}
}

func getOrigAddr(conn *net.TCPConn) (*net.TCPAddr, error) {
	f, err := conn.File()
	if err != nil {
		return nil, err
	}
	fd := f.Fd()
	syscall.SetNonblock(int(fd), true)

	saddr := syscall.RawSockaddrInet4{}
	size := unsafe.Sizeof(saddr)
	_, _, errno := syscall.Syscall6(syscall.SYS_GETSOCKOPT, uintptr(fd), syscall.SOL_IP, SO_ORIGINAL_DST, uintptr(unsafe.Pointer(&saddr)), uintptr(unsafe.Pointer(&size)), 0)
	if errno == 0 {
		res := &net.TCPAddr{
			IP:   net.IPv4(saddr.Addr[0], saddr.Addr[1], saddr.Addr[2], saddr.Addr[3]),
			Port: int(ntohs(saddr.Port)),
		}
		return res, nil
	}

	saddr6 := syscall.RawSockaddrInet6{}
	size6 := unsafe.Sizeof(saddr6)
	_, _, errno6 := syscall.Syscall6(syscall.SYS_GETSOCKOPT, uintptr(fd), syscall.SOL_IPV6, SO_ORIGINAL_DST, uintptr(unsafe.Pointer(&saddr6)), uintptr(unsafe.Pointer(&size6)), 0)
	if errno6 == 0 {
		res := &net.TCPAddr{
			IP:   net.IP(append([]byte(nil), saddr6.Addr[:]...)),
			Port: int(ntohs(saddr6.Port)),
		}
		return res, nil
	}
	return nil, nil
}

func DetectRedir(tconn SSConn) bool {
	c := tconn.(PlainConn).TCPConn
	addr := c.LocalAddr().(*net.TCPAddr)
	orig, err := getOrigAddr(c)
	if err != nil {
		return false
	}
	if orig.IP.Equal(addr.IP) && orig.Port == addr.Port {
		return false
	}
	return true
}

func (ctx *ClientContext) HandleRedir(tconn SSConn, buf *SSBuffer) error {
	return nil
}
<commit_msg>handle redir<commit_after>// +build linux

package shadowsocks

import (
	"bytes"
	"encoding/binary"
	"net"
	"syscall"
	"unsafe"
)

const SO_ORIGINAL_DST = 80

func ntohs(in uint16) (out uint16) {
	data := [2]byte{}
	binary.LittleEndian.PutUint16(data[:], in)
	if uint16(data[0]) == in&0xff { // LE
		return binary.BigEndian.Uint16(data[:])
	} else { // BE
		return in
	}
}

func getOrigAddr(conn *net.TCPConn) (*net.TCPAddr, error) {
	f, err := conn.File()
	if err != nil {
		return nil, err
	}
	defer f.Close()
	fd := f.Fd()
	syscall.SetNonblock(int(fd), true)

	saddr := syscall.RawSockaddrInet4{}
	size := unsafe.Sizeof(saddr)
	_, _, errno := syscall.Syscall6(syscall.SYS_GETSOCKOPT, uintptr(fd), syscall.SOL_IP, SO_ORIGINAL_DST, uintptr(unsafe.Pointer(&saddr)), uintptr(unsafe.Pointer(&size)), 0)
	if errno == 0 {
		res := &net.TCPAddr{
			IP:   net.IPv4(saddr.Addr[0], saddr.Addr[1], saddr.Addr[2], saddr.Addr[3]),
			Port: int(ntohs(saddr.Port)),
		}
		return res, nil
	}

	saddr6 := syscall.RawSockaddrInet6{}
	size6 := unsafe.Sizeof(saddr6)
	_, _, errno6 := syscall.Syscall6(syscall.SYS_GETSOCKOPT, uintptr(fd), syscall.SOL_IPV6, SO_ORIGINAL_DST, uintptr(unsafe.Pointer(&saddr6)), uintptr(unsafe.Pointer(&size6)), 0)
	if errno6 == 0 {
		res := &net.TCPAddr{
			IP:   net.IP(append([]byte(nil), saddr6.Addr[:]...)),
			Port: int(ntohs(saddr6.Port)),
		}
		return res, nil
	}
	return nil, nil
}

func DetectRedir(tconn SSConn) bool {
	c := tconn.(PlainConn).TCPConn
	addr := c.LocalAddr().(*net.TCPAddr)
	orig, err := getOrigAddr(c)
	if err != nil {
		return false
	}
	if orig == nil || orig.IP.Equal(addr.IP) && orig.Port == addr.Port {
		return false
	}
	return true
}

func (ctx *ClientContext) HandleRedir(tconn SSConn, buf *SSBuffer) (err error) {
	rbuf := NewBuffer()
	addr, _ := getOrigAddr(tconn.(PlainConn).TCPConn)
	if bytes.Equal(addr.IP[:12], v4InV6Prefix) {
		buf.buf = buf.buf[:7]
		buf.buf[0] = 0x01
		copy(buf.buf[1:5], addr.IP[12:])
		binary.BigEndian.PutUint16(buf.buf[5:], uint16(addr.Port))
	} else {
		buf.buf = buf.buf[:19]
		buf.buf[0] = 0x04
		copy(buf.buf[1:17], addr.IP[:])
		binary.BigEndian.PutUint16(buf.buf[17:], uint16(addr.Port))
	}

	var rconn net.Conn
	rconn, err = net.Dial("tcp", ctx.serverAddr)
	if err != nil {
		return
	}
	defer rconn.Close()
	rconn.(*net.TCPConn).SetNoDelay(true)
	trconn := PlainConn{rconn.(*net.TCPConn)}
	wrconn := ctx.cipherFactory.Wrap(trconn)

	res := make(chan error, 1)
	rres := make(chan error, 1)
	go Pipe(tconn, wrconn, buf, res)
	go Pipe(wrconn, tconn, rbuf, rres)

	select {
	case err = <-res:
	case err = <-rres:
	}
	return
}
<|endoftext|>


<commit_before>/*
   Copyright 2016 Vastech SA (PTY) LTD

   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 report

import (
	"bytes"
	"io"
	"io/ioutil"
	"os"
	"testing"

	"github.com/izakmarais/reporter/grafana"
	. "github.com/smartystreets/goconvey/convey"
)

const dashJSON = `
{"Dashboard":
	{
		"Title":"My first dashboard",
		"Rows":
		[{"Panels":
			[{"Type":"singlestat", "Id":1},
			 {"Type":"graph", "Id":22}]
		},
		{"Panels":
			[{"Type":"singlestat", "Id":33}]
		}]
	},
"Meta":
	{"Slug":"testDash"}
}`

type mockGrafanaClient struct {
}

func (m mockGrafanaClient) GetDashboard(dashName string) (grafana.Dashboard, error) {
	return grafana.NewDashboard([]byte(dashJSON)), nil
}

func (m mockGrafanaClient) GetPanelPng(p grafana.Panel, dashName string, t grafana.TimeRange) (io.ReadCloser, error) {
	return ioutil.NopCloser(bytes.NewBuffer([]byte("Not actually a png"))), nil
}

func TestReport(t *testing.T) {
	Convey("When generating a report", t, func() {
		var gClient mockGrafanaClient
		rep := New(gClient, "testDash", grafana.TimeRange{"1453206447000", "1453213647000"})
		defer rep.Clean()

		Convey("When rendering images", func() {
			dashboard,_ := gClient.GetDashboard("")
			rep.renderPNGsParallel(dashboard)

			Convey("It should create a temporary folder", func() {
				_, err := os.Stat(rep.tmpDir)
				So(err, ShouldBeNil)
			})

			Convey("It should copy the file to the image folder", func() {
				_, err := os.Stat(rep.imgDirPath() + "/image1.png")
				So(err, ShouldBeNil)
			})

			Convey("It should create one file per panel", func() {
				f, err := os.Open(rep.imgDirPath())
				defer f.Close()
				files, err := f.Readdir(0)
				So(files, ShouldHaveLength, 3)
				So(err, ShouldBeNil)
			})
		})

		Convey("When genereting the Tex file", func() {
			dashboard,_ := gClient.GetDashboard("")
			template_file := "templates/default.tex"
			rep.generateTeXFile(dashboard, template_file)
			f, err := os.Open(rep.texPath())
			defer f.Close()

			Convey("It should create a file in the temporary folder", func() {
				So(err, ShouldBeNil)
			})

			Convey("The file should contain reference to the template data", func() {
				var buf bytes.Buffer
				io.Copy(&buf, f)
				s := string(buf.Bytes())

				So(err, ShouldBeNil)
				Convey("Including the Title", func() {
					So(s, ShouldContainSubstring, "My first dashboard")

				})
				Convey("and the images", func() {
					So(s, ShouldContainSubstring, "image1")
					So(s, ShouldContainSubstring, "image22")
					So(s, ShouldContainSubstring, "image33")

				})
				Convey("and the time range", func() {
					So(s, ShouldContainSubstring, "Tue Jan 19 12:27:27 UTC 2016")
					So(s, ShouldContainSubstring, "Tue Jan 19 14:27:27 UTC 2016")
				})
			})
		})

		Convey("Clean() should remove the temporary folder", func() {
			rep.Clean()

			_, err := os.Stat(rep.tmpDir)
			So(os.IsNotExist(err), ShouldBeTrue)
		})
	})

}
<commit_msg>fixed test<commit_after>/*
   Copyright 2016 Vastech SA (PTY) LTD

   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 report

import (
	"bytes"
	"io"
	"io/ioutil"
	"os"
	"testing"

	"github.com/izakmarais/reporter/grafana"
	. "github.com/smartystreets/goconvey/convey"
)

const dashJSON = `
{"Dashboard":
	{
		"Title":"My first dashboard",
		"Rows":
		[{"Panels":
			[{"Type":"singlestat", "Id":1},
			 {"Type":"graph", "Id":22}]
		},
		{"Panels":
			[{"Type":"singlestat", "Id":33}]
		}]
	},
"Meta":
	{"Slug":"testDash"}
}`

type mockGrafanaClient struct {
}

func (m mockGrafanaClient) GetDashboard(dashName string) (grafana.Dashboard, error) {
	return grafana.NewDashboard([]byte(dashJSON)), nil
}

func (m mockGrafanaClient) GetPanelPng(p grafana.Panel, dashName string, t grafana.TimeRange) (io.ReadCloser, error) {
	return ioutil.NopCloser(bytes.NewBuffer([]byte("Not actually a png"))), nil
}

func TestReport(t *testing.T) {
	Convey("When generating a report", t, func() {
		var gClient mockGrafanaClient
		rep := New(gClient, "testDash", grafana.TimeRange{"1453206447000", "1453213647000"}, "")
		defer rep.Clean()

		Convey("When rendering images", func() {
			dashboard, _ := gClient.GetDashboard("")
			rep.renderPNGsParallel(dashboard)

			Convey("It should create a temporary folder", func() {
				_, err := os.Stat(rep.tmpDir)
				So(err, ShouldBeNil)
			})

			Convey("It should copy the file to the image folder", func() {
				_, err := os.Stat(rep.imgDirPath() + "/image1.png")
				So(err, ShouldBeNil)
			})

			Convey("It should create one file per panel", func() {
				f, err := os.Open(rep.imgDirPath())
				defer f.Close()
				files, err := f.Readdir(0)
				So(files, ShouldHaveLength, 3)
				So(err, ShouldBeNil)
			})
		})

		Convey("When genereting the Tex file", func() {
			dashboard, _ := gClient.GetDashboard("")
			rep.generateTeXFile(dashboard)
			f, err := os.Open(rep.texPath())
			defer f.Close()

			Convey("It should create a file in the temporary folder", func() {
				So(err, ShouldBeNil)
			})

			Convey("The file should contain reference to the template data", func() {
				var buf bytes.Buffer
				io.Copy(&buf, f)
				s := string(buf.Bytes())

				So(err, ShouldBeNil)
				Convey("Including the Title", func() {
					So(s, ShouldContainSubstring, "My first dashboard")

				})
				Convey("and the images", func() {
					So(s, ShouldContainSubstring, "image1")
					So(s, ShouldContainSubstring, "image22")
					So(s, ShouldContainSubstring, "image33")

				})
				Convey("and the time range", func() {
					So(s, ShouldContainSubstring, "Tue Jan 19 12:27:27 UTC 2016")
					So(s, ShouldContainSubstring, "Tue Jan 19 14:27:27 UTC 2016")
				})
			})
		})

		Convey("Clean() should remove the temporary folder", func() {
			rep.Clean()

			_, err := os.Stat(rep.tmpDir)
			So(os.IsNotExist(err), ShouldBeTrue)
		})
	})

}
<|endoftext|>


<commit_before>package vsolver

import (
	"fmt"
	"os"
	"path"
	"testing"

	"github.com/Masterminds/semver"
)

var basicResult Result

func init() {
	sv1, _ := semver.NewVersion("1.0.0")
	basicResult = Result{
		Attempts: 1,
		Projects: []ProjectAtom{
			ProjectAtom{
				Name: "github.com/sdboyer/testrepo",
				Version: Version{
					Type:       V_Branch,
					Info:       "master",
					Underlying: "4d59fb584b15a94d7401e356d2875c472d76ef45",
				},
			},
			ProjectAtom{
				Name: "github.com/Masterminds/VCSTestRepo",
				Version: Version{
					Type:       V_Semver,
					Info:       "1.0.0",
					Underlying: "30605f6ac35fcb075ad0bfa9296f90a7d891523e",
					SemVer:     sv1,
				},
			},
		},
	}
}

func TestResultCreateVendorTree(t *testing.T) {
	r := basicResult
	r.SolveFailure = fmt.Errorf("dummy error")

	tmp := path.Join(os.TempDir(), "vsolvtest")
	os.RemoveAll(tmp)
	//fmt.Println(tmp)

	sm, err := NewSourceManager(path.Join(tmp, "cache"), path.Join(tmp, "base"), true, false, dummyAnalyzer{})
	if err != nil {
		t.Errorf("NewSourceManager errored unexpectedly: %q", err)
	}

	err = r.CreateVendorTree(path.Join(tmp, "export"), sm)
	if err == fmt.Errorf("Cannot create vendor tree from failed solution. Failure was dummy error") {
		if err == nil {
			t.Errorf("Expected error due to result having solve failure, but no error")
		} else {
			t.Errorf("Expected error due to result having solve failure, but got %s", err)
		}
	}

	r.SolveFailure = nil
	err = r.CreateVendorTree(path.Join(tmp, "export"), sm)
	if err != nil {
		t.Errorf("Unexpected error while creating vendor tree: %s", err)
	}

	// TODO add more checks
}
<commit_msg>Add CreateVendorTree benchmark<commit_after>package vsolver

import (
	"fmt"
	"go/build"
	"os"
	"path"
	"testing"

	"github.com/Masterminds/semver"
)

var basicResult Result
var kub ProjectAtom

// An analyzer that passes nothing back, but doesn't error. This expressly
// creates a situation that shouldn't be able to happen from a general solver
// perspective, so it's only useful for particular situations in tests
type passthruAnalyzer struct{}

func (passthruAnalyzer) GetInfo(ctx build.Context, p ProjectName) (ProjectInfo, error) {
	return ProjectInfo{}, nil
}

func init() {
	sv1, _ := semver.NewVersion("1.0.0")
	basicResult = Result{
		Attempts: 1,
		Projects: []ProjectAtom{
			ProjectAtom{
				Name: "github.com/sdboyer/testrepo",
				Version: Version{
					Type:       V_Branch,
					Info:       "master",
					Underlying: "4d59fb584b15a94d7401e356d2875c472d76ef45",
				},
			},
			ProjectAtom{
				Name: "github.com/Masterminds/VCSTestRepo",
				Version: Version{
					Type:       V_Semver,
					Info:       "1.0.0",
					Underlying: "30605f6ac35fcb075ad0bfa9296f90a7d891523e",
					SemVer:     sv1,
				},
			},
		},
	}

	// just in case something needs punishing, kubernetes is happy to oblige
	sv2, _ := semver.NewVersion("v1.2.2")
	kub = ProjectAtom{
		Name: "github.com/kubernetes/kubernetes",
		Version: Version{
			Type:       V_Semver,
			Info:       "v1.2.2",
			Underlying: "528f879e7d3790ea4287687ef0ab3f2a01cc2718",
			SemVer:     sv2,
		},
	}
}

func TestResultCreateVendorTree(t *testing.T) {
	r := basicResult
	r.SolveFailure = fmt.Errorf("dummy error")

	tmp := path.Join(os.TempDir(), "vsolvtest")
	os.RemoveAll(tmp)

	sm, err := NewSourceManager(path.Join(tmp, "cache"), path.Join(tmp, "base"), true, false, passthruAnalyzer{})
	if err != nil {
		t.Errorf("NewSourceManager errored unexpectedly: %q", err)
	}

	err = r.CreateVendorTree(path.Join(tmp, "export"), sm)
	if err == fmt.Errorf("Cannot create vendor tree from failed solution. Failure was dummy error") {
		if err == nil {
			t.Errorf("Expected error due to result having solve failure, but no error")
		} else {
			t.Errorf("Expected error due to result having solve failure, but got %s", err)
		}
	}

	r.SolveFailure = nil
	err = r.CreateVendorTree(path.Join(tmp, "export"), sm)
	if err != nil {
		t.Errorf("Unexpected error while creating vendor tree: %s", err)
	}

	// TODO add more checks
}

func BenchmarkCreateVendorTree(b *testing.B) {
	// We're fs-bound here, so restrict to single parallelism
	b.SetParallelism(1)

	r := basicResult
	tmp := path.Join(os.TempDir(), "vsolvtest")

	clean := true
	sm, err := NewSourceManager(path.Join(tmp, "cache"), path.Join(tmp, "base"), true, true, passthruAnalyzer{})
	if err != nil {
		b.Errorf("NewSourceManager errored unexpectedly: %q", err)
		clean = false
	}

	// Prefetch the projects before timer starts
	for _, pa := range r.Projects {
		_, err := sm.GetProjectInfo(pa)
		if err != nil {
			b.Errorf("failed getting project info during prefetch: %s", err)
			clean = false
		}
	}

	if clean {
		b.ResetTimer()
		b.StopTimer()
		exp := path.Join(tmp, "export")
		for i := 0; i < b.N; i++ {
			// Order the loop this way to make it easy to disable final cleanup, to
			// ease manual inspection
			os.RemoveAll(exp)
			b.StartTimer()
			err = r.CreateVendorTree(exp, sm)
			b.StopTimer()
			if err != nil {
				b.Errorf("unexpected error after %v iterations: %s", i, err)
				break
			}
		}
	}

	sm.Release()
	os.RemoveAll(tmp) // comment this to leave temp dir behind for inspection
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/koding/kite"
	"fmt"
	"os"
	"sync"
	"log"
	"github.com/bitly/go-nsq"
	"runtime"
        "github.com/nsabine/microservices/controller/controllerlib"

)

var client *kite.Client
var k 	   *kite.Kite

func main() {
	fmt.Println("Starting Robber")

	k = kite.New("robber", "1.0.0")
	k.Config.Port = 6001
	k.Config.DisableAuthentication = true

        client = k.NewClient("http://" + os.Getenv("CONTROLLER_SERVICE_HOST")  + ":" + os.Getenv("CONTROLLER_SERVICE_PORT") + "/kite")
        connected, err := client.DialForever()
        if err != nil {
                k.Log.Fatal(err.Error())
        }

        // Wait until connected
        <-connected

	runtime.GOMAXPROCS(2)
	wg := &sync.WaitGroup{}
	wg.Add(2)
	go startKite()
	go startMessaging()
	wg.Wait()
}

func startKite() {
	k.HandleFunc("hello", hello)
	fmt.Println("Robber starting kite")
	k.Run()
}

func startMessaging() {
	fmt.Println("Robber configuring NSQ")

	config := nsq.NewConfig()
	q, _ := nsq.NewConsumer("tick", "ch", config)
	q.AddHandler(nsq.HandlerFunc(func(message *nsq.Message) error {
		log.Printf("Got a message: %s", string(message.Body[:]))
		tick()
		return nil
	}))

	fmt.Println("Trying to connect to NSQ: " + os.Getenv("MESSAGING_SERVICE_HOST") + ":4150")

	err := q.ConnectToNSQD(os.Getenv("MESSAGING_SERVICE_HOST") + ":4150")
	if err != nil {
		log.Panic("Could not connect")
	}
	fmt.Println("Robber starting NSQ")
}

func hello(r *kite.Request) (interface{}, error) {

	fmt.Println("Robber got hello")

	// You can return anything as result, as long as it is JSON marshalable.
	return nil, nil
}

func tick() {
	response, err := client.Tell("update", &controllerlib.UpdateRequest{
		Id: 1,
		Type: "robber",
		XPos: 1,
		YPos: 2,
	})
	if err != nil {
		panic(err)
	}
}
<commit_msg>fixing syntax<commit_after>package main

import (
	"github.com/koding/kite"
	"fmt"
	"os"
	"sync"
	"log"
	"github.com/bitly/go-nsq"
	"runtime"
        "github.com/nsabine/microservices/controller/controllerlib"

)

var client *kite.Client
var k 	   *kite.Kite

func main() {
	fmt.Println("Starting Robber")

	k = kite.New("robber", "1.0.0")
	k.Config.Port = 6001
	k.Config.DisableAuthentication = true

        client = k.NewClient("http://" + os.Getenv("CONTROLLER_SERVICE_HOST")  + ":" + os.Getenv("CONTROLLER_SERVICE_PORT") + "/kite")
        connected, err := client.DialForever()
        if err != nil {
                k.Log.Fatal(err.Error())
        }

        // Wait until connected
        <-connected

	runtime.GOMAXPROCS(2)
	wg := &sync.WaitGroup{}
	wg.Add(2)
	go startKite()
	go startMessaging()
	wg.Wait()
}

func startKite() {
	k.HandleFunc("hello", hello)
	fmt.Println("Robber starting kite")
	k.Run()
}

func startMessaging() {
	fmt.Println("Robber configuring NSQ")

	config := nsq.NewConfig()
	q, _ := nsq.NewConsumer("tick", "ch", config)
	q.AddHandler(nsq.HandlerFunc(func(message *nsq.Message) error {
		log.Printf("Got a message: %s", string(message.Body[:]))
		tick()
		return nil
	}))

	fmt.Println("Trying to connect to NSQ: " + os.Getenv("MESSAGING_SERVICE_HOST") + ":4150")

	err := q.ConnectToNSQD(os.Getenv("MESSAGING_SERVICE_HOST") + ":4150")
	if err != nil {
		log.Panic("Could not connect")
	}
	fmt.Println("Robber starting NSQ")
}

func hello(r *kite.Request) (interface{}, error) {

	fmt.Println("Robber got hello")

	// You can return anything as result, as long as it is JSON marshalable.
	return nil, nil
}

func tick() {
	_, err := client.Tell("update", &controllerlib.UpdateRequest{
		Id: 1,
		Type: "robber",
		XPos: 1,
		YPos: 2,
	})
	if err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>package tview

import (
	"github.com/gdamore/tcell"
)

// Box implements Primitive with a background and optional elements such as a
// border and a title. Most subclasses keep their content contained in the box
// but don't necessarily have to.
//
// Note that all classes which subclass from Box will also have access to its
// functions.
//
// See https://github.com/rivo/tview/wiki/Box for an example.
type Box struct {
	// The position of the rect.
	x, y, width, height int

	// The inner rect reserved for the box's content.
	innerX, innerY, innerWidth, innerHeight int

	// Border padding.
	paddingTop, paddingBottom, paddingLeft, paddingRight int

	// The box's background color.
	backgroundColor tcell.Color

	// Whether or not a border is drawn, reducing the box's space for content by
	// two in width and height.
	border bool

	// The color of the border.
	borderColor tcell.Color

	// The style attributes of the border.
	borderAttributes tcell.AttrMask

	// The title. Only visible if there is a border, too.
	title string

	// The color of the title.
	titleColor tcell.Color

	// The alignment of the title.
	titleAlign int

	// Provides a way to find out if this box has focus. We always go through
	// this interface because it may be overridden by implementing classes.
	focus Focusable

	// Whether or not this box has focus.
	hasFocus bool

	// An optional capture function which receives a key event and returns the
	// event to be forwarded to the primitive's default input handler (nil if
	// nothing should be forwarded).
	inputCapture func(event *tcell.EventKey) *tcell.EventKey

	// An optional function which is called before the box is drawn.
	draw func(screen tcell.Screen, x, y, width, height int) (int, int, int, int)
}

// NewBox returns a Box without a border.
func NewBox() *Box {
	b := &Box{
		width:           15,
		height:          10,
		innerX:          -1, // Mark as uninitialized.
		backgroundColor: Styles.PrimitiveBackgroundColor,
		borderColor:     Styles.BorderColor,
		titleColor:      Styles.TitleColor,
		titleAlign:      AlignCenter,
	}
	b.focus = b
	return b
}

// SetBorderPadding sets the size of the borders around the box content.
func (b *Box) SetBorderPadding(top, bottom, left, right int) *Box {
	b.paddingTop, b.paddingBottom, b.paddingLeft, b.paddingRight = top, bottom, left, right
	return b
}

// GetRect returns the current position of the rectangle, x, y, width, and
// height.
func (b *Box) GetRect() (int, int, int, int) {
	return b.x, b.y, b.width, b.height
}

// GetInnerRect returns the position of the inner rectangle (x, y, width,
// height), without the border and without any padding. Width and height values
// will clamp to 0 and thus never be negative.
func (b *Box) GetInnerRect() (int, int, int, int) {
	if b.innerX >= 0 {
		return b.innerX, b.innerY, b.innerWidth, b.innerHeight
	}
	x, y, width, height := b.GetRect()
	if b.border {
		x++
		y++
		width -= 2
		height -= 2
	}
	x, y, width, height = x+b.paddingLeft,
		y+b.paddingTop,
		width-b.paddingLeft-b.paddingRight,
		height-b.paddingTop-b.paddingBottom
	if width < 0 {
		width = 0
	}
	if height < 0 {
		height = 0
	}
	return x, y, width, height
}

// SetRect sets a new position of the primitive. Note that this has no effect
// if this primitive is part of a layout (e.g. Flex, Grid) or if it was added
// like this:
//
//   application.SetRoot(b, true)
func (b *Box) SetRect(x, y, width, height int) {
	b.x = x
	b.y = y
	b.width = width
	b.height = height
	b.innerX = -1 // Mark inner rect as uninitialized.
}

// SetDrawFunc sets a callback function which is invoked after the box primitive
// has been drawn. This allows you to add a more individual style to the box
// (and all primitives which extend it).
//
// The function is provided with the box's dimensions (set via SetRect()). It
// must return the box's inner dimensions (x, y, width, height) which will be
// returned by GetInnerRect(), used by descendent primitives to draw their own
// content.
func (b *Box) SetDrawFunc(handler func(screen tcell.Screen, x, y, width, height int) (int, int, int, int)) *Box {
	b.draw = handler
	return b
}

// GetDrawFunc returns the callback function which was installed with
// SetDrawFunc() or nil if no such function has been installed.
func (b *Box) GetDrawFunc() func(screen tcell.Screen, x, y, width, height int) (int, int, int, int) {
	return b.draw
}

// WrapInputHandler wraps an input handler (see InputHandler()) with the
// functionality to capture input (see SetInputCapture()) before passing it
// on to the provided (default) input handler.
//
// This is only meant to be used by subclassing primitives.
func (b *Box) WrapInputHandler(inputHandler func(*tcell.EventKey, func(p Primitive))) func(*tcell.EventKey, func(p Primitive)) {
	return func(event *tcell.EventKey, setFocus func(p Primitive)) {
		if b.inputCapture != nil {
			event = b.inputCapture(event)
		}
		if event != nil && inputHandler != nil {
			inputHandler(event, setFocus)
		}
	}
}

// InputHandler returns nil.
func (b *Box) InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) {
	return b.WrapInputHandler(nil)
}

// SetInputCapture installs a function which captures key events before they are
// forwarded to the primitive's default key event handler. This function can
// then choose to forward that key event (or a different one) to the default
// handler by returning it. If nil is returned, the default handler will not
// be called.
//
// Providing a nil handler will remove a previously existing handler.
//
// Note that this function will not have an effect on primitives composed of
// other primitives, such as Form, Flex, or Grid. Key events are only captured
// by the primitives that have focus (e.g. InputField) and only one primitive
// can have focus at a time. Composing primitives such as Form pass the focus on
// to their contained primitives and thus never receive any key events
// themselves. Therefore, they cannot intercept key events.
func (b *Box) SetInputCapture(capture func(event *tcell.EventKey) *tcell.EventKey) *Box {
	b.inputCapture = capture
	return b
}

// GetInputCapture returns the function installed with SetInputCapture() or nil
// if no such function has been installed.
func (b *Box) GetInputCapture() func(event *tcell.EventKey) *tcell.EventKey {
	return b.inputCapture
}

// SetBackgroundColor sets the box's background color.
func (b *Box) SetBackgroundColor(color tcell.Color) *Box {
	b.backgroundColor = color
	return b
}

// SetBorder sets the flag indicating whether or not the box should have a
// border.
func (b *Box) SetBorder(show bool) *Box {
	b.border = show
	return b
}

// SetBorderColor sets the box's border color.
func (b *Box) SetBorderColor(color tcell.Color) *Box {
	b.borderColor = color
	return b
}

// SetBorderAttributes sets the border's style attributes. You can combine
// different attributes using bitmask operations:
//
//   box.SetBorderAttributes(tcell.AttrUnderline | tcell.AttrBold)
func (b *Box) SetBorderAttributes(attr tcell.AttrMask) *Box {
	b.borderAttributes = attr
	return b
}

// SetTitle sets the box's title.
func (b *Box) SetTitle(title string) *Box {
	b.title = title
	return b
}

// GetTitle returns the box's current title.
func (b *Box) GetTitle() string {
	return b.title
}

// SetTitleColor sets the box's title color.
func (b *Box) SetTitleColor(color tcell.Color) *Box {
	b.titleColor = color
	return b
}

// SetTitleAlign sets the alignment of the title, one of AlignLeft, AlignCenter,
// or AlignRight.
func (b *Box) SetTitleAlign(align int) *Box {
	b.titleAlign = align
	return b
}

// Draw draws this primitive onto the screen.
func (b *Box) Draw(screen tcell.Screen) {
	// Don't draw anything if there is no space.
	if b.width <= 0 || b.height <= 0 {
		return
	}

	def := tcell.StyleDefault

	// Fill background.
	background := def.Background(b.backgroundColor)
	if b.backgroundColor != tcell.ColorDefault {
		for y := b.y; y < b.y+b.height; y++ {
			for x := b.x; x < b.x+b.width; x++ {
				screen.SetContent(x, y, ' ', nil, background)
			}
		}
	}

	// Draw border.
	if b.border && b.width >= 2 && b.height >= 2 {
		border := background.Foreground(b.borderColor) | tcell.Style(b.borderAttributes)
		var vertical, horizontal, topLeft, topRight, bottomLeft, bottomRight rune
		if b.focus.HasFocus() {
			horizontal = Borders.HorizontalFocus
			vertical = Borders.VerticalFocus
			topLeft = Borders.TopLeftFocus
			topRight = Borders.TopRightFocus
			bottomLeft = Borders.BottomLeftFocus
			bottomRight = Borders.BottomRightFocus
		} else {
			horizontal = Borders.Horizontal
			vertical = Borders.Vertical
			topLeft = Borders.TopLeft
			topRight = Borders.TopRight
			bottomLeft = Borders.BottomLeft
			bottomRight = Borders.BottomRight
		}
		for x := b.x + 1; x < b.x+b.width-1; x++ {
			screen.SetContent(x, b.y, horizontal, nil, border)
			screen.SetContent(x, b.y+b.height-1, horizontal, nil, border)
		}
		for y := b.y + 1; y < b.y+b.height-1; y++ {
			screen.SetContent(b.x, y, vertical, nil, border)
			screen.SetContent(b.x+b.width-1, y, vertical, nil, border)
		}
		screen.SetContent(b.x, b.y, topLeft, nil, border)
		screen.SetContent(b.x+b.width-1, b.y, topRight, nil, border)
		screen.SetContent(b.x, b.y+b.height-1, bottomLeft, nil, border)
		screen.SetContent(b.x+b.width-1, b.y+b.height-1, bottomRight, nil, border)

		// Draw title.
		if b.title != "" && b.width >= 4 {
			printed, _ := Print(screen, b.title, b.x+1, b.y, b.width-2, b.titleAlign, b.titleColor)
			if len(b.title)-printed > 0 && printed > 0 {
				_, _, style, _ := screen.GetContent(b.x+b.width-2, b.y)
				fg, _, _ := style.Decompose()
				Print(screen, string(SemigraphicsHorizontalEllipsis), b.x+b.width-2, b.y, 1, AlignLeft, fg)
			}
		}
	}

	// Call custom draw function.
	if b.draw != nil {
		b.innerX, b.innerY, b.innerWidth, b.innerHeight = b.draw(screen, b.x, b.y, b.width, b.height)
	} else {
		// Remember the inner rect.
		b.innerX = -1
		b.innerX, b.innerY, b.innerWidth, b.innerHeight = b.GetInnerRect()
	}
}

// Focus is called when this primitive receives focus.
func (b *Box) Focus(delegate func(p Primitive)) {
	b.hasFocus = true
}

// Blur is called when this primitive loses focus.
func (b *Box) Blur() {
	b.hasFocus = false
}

// HasFocus returns whether or not this primitive has focus.
func (b *Box) HasFocus() bool {
	return b.hasFocus
}

// GetFocusable returns the item's Focusable.
func (b *Box) GetFocusable() Focusable {
	return b.focus
}
<commit_msg>Clarifying the role of the Box class better. Resolves #373<commit_after>package tview

import (
	"github.com/gdamore/tcell"
)

// Box implements the Primitive interface with an empty background and optional
// elements such as a border and a title. Box itself does not hold any content
// but serves as the superclass of all other primitives. Subclasses add their
// own content, typically (but not necessarily) keeping their content within the
// box's rectangle.
//
// Box provides a number of utility functions available to all primitives.
//
// See https://github.com/rivo/tview/wiki/Box for an example.
type Box struct {
	// The position of the rect.
	x, y, width, height int

	// The inner rect reserved for the box's content.
	innerX, innerY, innerWidth, innerHeight int

	// Border padding.
	paddingTop, paddingBottom, paddingLeft, paddingRight int

	// The box's background color.
	backgroundColor tcell.Color

	// Whether or not a border is drawn, reducing the box's space for content by
	// two in width and height.
	border bool

	// The color of the border.
	borderColor tcell.Color

	// The style attributes of the border.
	borderAttributes tcell.AttrMask

	// The title. Only visible if there is a border, too.
	title string

	// The color of the title.
	titleColor tcell.Color

	// The alignment of the title.
	titleAlign int

	// Provides a way to find out if this box has focus. We always go through
	// this interface because it may be overridden by implementing classes.
	focus Focusable

	// Whether or not this box has focus.
	hasFocus bool

	// An optional capture function which receives a key event and returns the
	// event to be forwarded to the primitive's default input handler (nil if
	// nothing should be forwarded).
	inputCapture func(event *tcell.EventKey) *tcell.EventKey

	// An optional function which is called before the box is drawn.
	draw func(screen tcell.Screen, x, y, width, height int) (int, int, int, int)
}

// NewBox returns a Box without a border.
func NewBox() *Box {
	b := &Box{
		width:           15,
		height:          10,
		innerX:          -1, // Mark as uninitialized.
		backgroundColor: Styles.PrimitiveBackgroundColor,
		borderColor:     Styles.BorderColor,
		titleColor:      Styles.TitleColor,
		titleAlign:      AlignCenter,
	}
	b.focus = b
	return b
}

// SetBorderPadding sets the size of the borders around the box content.
func (b *Box) SetBorderPadding(top, bottom, left, right int) *Box {
	b.paddingTop, b.paddingBottom, b.paddingLeft, b.paddingRight = top, bottom, left, right
	return b
}

// GetRect returns the current position of the rectangle, x, y, width, and
// height.
func (b *Box) GetRect() (int, int, int, int) {
	return b.x, b.y, b.width, b.height
}

// GetInnerRect returns the position of the inner rectangle (x, y, width,
// height), without the border and without any padding. Width and height values
// will clamp to 0 and thus never be negative.
func (b *Box) GetInnerRect() (int, int, int, int) {
	if b.innerX >= 0 {
		return b.innerX, b.innerY, b.innerWidth, b.innerHeight
	}
	x, y, width, height := b.GetRect()
	if b.border {
		x++
		y++
		width -= 2
		height -= 2
	}
	x, y, width, height = x+b.paddingLeft,
		y+b.paddingTop,
		width-b.paddingLeft-b.paddingRight,
		height-b.paddingTop-b.paddingBottom
	if width < 0 {
		width = 0
	}
	if height < 0 {
		height = 0
	}
	return x, y, width, height
}

// SetRect sets a new position of the primitive. Note that this has no effect
// if this primitive is part of a layout (e.g. Flex, Grid) or if it was added
// like this:
//
//   application.SetRoot(b, true)
func (b *Box) SetRect(x, y, width, height int) {
	b.x = x
	b.y = y
	b.width = width
	b.height = height
	b.innerX = -1 // Mark inner rect as uninitialized.
}

// SetDrawFunc sets a callback function which is invoked after the box primitive
// has been drawn. This allows you to add a more individual style to the box
// (and all primitives which extend it).
//
// The function is provided with the box's dimensions (set via SetRect()). It
// must return the box's inner dimensions (x, y, width, height) which will be
// returned by GetInnerRect(), used by descendent primitives to draw their own
// content.
func (b *Box) SetDrawFunc(handler func(screen tcell.Screen, x, y, width, height int) (int, int, int, int)) *Box {
	b.draw = handler
	return b
}

// GetDrawFunc returns the callback function which was installed with
// SetDrawFunc() or nil if no such function has been installed.
func (b *Box) GetDrawFunc() func(screen tcell.Screen, x, y, width, height int) (int, int, int, int) {
	return b.draw
}

// WrapInputHandler wraps an input handler (see InputHandler()) with the
// functionality to capture input (see SetInputCapture()) before passing it
// on to the provided (default) input handler.
//
// This is only meant to be used by subclassing primitives.
func (b *Box) WrapInputHandler(inputHandler func(*tcell.EventKey, func(p Primitive))) func(*tcell.EventKey, func(p Primitive)) {
	return func(event *tcell.EventKey, setFocus func(p Primitive)) {
		if b.inputCapture != nil {
			event = b.inputCapture(event)
		}
		if event != nil && inputHandler != nil {
			inputHandler(event, setFocus)
		}
	}
}

// InputHandler returns nil.
func (b *Box) InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) {
	return b.WrapInputHandler(nil)
}

// SetInputCapture installs a function which captures key events before they are
// forwarded to the primitive's default key event handler. This function can
// then choose to forward that key event (or a different one) to the default
// handler by returning it. If nil is returned, the default handler will not
// be called.
//
// Providing a nil handler will remove a previously existing handler.
//
// Note that this function will not have an effect on primitives composed of
// other primitives, such as Form, Flex, or Grid. Key events are only captured
// by the primitives that have focus (e.g. InputField) and only one primitive
// can have focus at a time. Composing primitives such as Form pass the focus on
// to their contained primitives and thus never receive any key events
// themselves. Therefore, they cannot intercept key events.
func (b *Box) SetInputCapture(capture func(event *tcell.EventKey) *tcell.EventKey) *Box {
	b.inputCapture = capture
	return b
}

// GetInputCapture returns the function installed with SetInputCapture() or nil
// if no such function has been installed.
func (b *Box) GetInputCapture() func(event *tcell.EventKey) *tcell.EventKey {
	return b.inputCapture
}

// SetBackgroundColor sets the box's background color.
func (b *Box) SetBackgroundColor(color tcell.Color) *Box {
	b.backgroundColor = color
	return b
}

// SetBorder sets the flag indicating whether or not the box should have a
// border.
func (b *Box) SetBorder(show bool) *Box {
	b.border = show
	return b
}

// SetBorderColor sets the box's border color.
func (b *Box) SetBorderColor(color tcell.Color) *Box {
	b.borderColor = color
	return b
}

// SetBorderAttributes sets the border's style attributes. You can combine
// different attributes using bitmask operations:
//
//   box.SetBorderAttributes(tcell.AttrUnderline | tcell.AttrBold)
func (b *Box) SetBorderAttributes(attr tcell.AttrMask) *Box {
	b.borderAttributes = attr
	return b
}

// SetTitle sets the box's title.
func (b *Box) SetTitle(title string) *Box {
	b.title = title
	return b
}

// GetTitle returns the box's current title.
func (b *Box) GetTitle() string {
	return b.title
}

// SetTitleColor sets the box's title color.
func (b *Box) SetTitleColor(color tcell.Color) *Box {
	b.titleColor = color
	return b
}

// SetTitleAlign sets the alignment of the title, one of AlignLeft, AlignCenter,
// or AlignRight.
func (b *Box) SetTitleAlign(align int) *Box {
	b.titleAlign = align
	return b
}

// Draw draws this primitive onto the screen.
func (b *Box) Draw(screen tcell.Screen) {
	// Don't draw anything if there is no space.
	if b.width <= 0 || b.height <= 0 {
		return
	}

	def := tcell.StyleDefault

	// Fill background.
	background := def.Background(b.backgroundColor)
	if b.backgroundColor != tcell.ColorDefault {
		for y := b.y; y < b.y+b.height; y++ {
			for x := b.x; x < b.x+b.width; x++ {
				screen.SetContent(x, y, ' ', nil, background)
			}
		}
	}

	// Draw border.
	if b.border && b.width >= 2 && b.height >= 2 {
		border := background.Foreground(b.borderColor) | tcell.Style(b.borderAttributes)
		var vertical, horizontal, topLeft, topRight, bottomLeft, bottomRight rune
		if b.focus.HasFocus() {
			horizontal = Borders.HorizontalFocus
			vertical = Borders.VerticalFocus
			topLeft = Borders.TopLeftFocus
			topRight = Borders.TopRightFocus
			bottomLeft = Borders.BottomLeftFocus
			bottomRight = Borders.BottomRightFocus
		} else {
			horizontal = Borders.Horizontal
			vertical = Borders.Vertical
			topLeft = Borders.TopLeft
			topRight = Borders.TopRight
			bottomLeft = Borders.BottomLeft
			bottomRight = Borders.BottomRight
		}
		for x := b.x + 1; x < b.x+b.width-1; x++ {
			screen.SetContent(x, b.y, horizontal, nil, border)
			screen.SetContent(x, b.y+b.height-1, horizontal, nil, border)
		}
		for y := b.y + 1; y < b.y+b.height-1; y++ {
			screen.SetContent(b.x, y, vertical, nil, border)
			screen.SetContent(b.x+b.width-1, y, vertical, nil, border)
		}
		screen.SetContent(b.x, b.y, topLeft, nil, border)
		screen.SetContent(b.x+b.width-1, b.y, topRight, nil, border)
		screen.SetContent(b.x, b.y+b.height-1, bottomLeft, nil, border)
		screen.SetContent(b.x+b.width-1, b.y+b.height-1, bottomRight, nil, border)

		// Draw title.
		if b.title != "" && b.width >= 4 {
			printed, _ := Print(screen, b.title, b.x+1, b.y, b.width-2, b.titleAlign, b.titleColor)
			if len(b.title)-printed > 0 && printed > 0 {
				_, _, style, _ := screen.GetContent(b.x+b.width-2, b.y)
				fg, _, _ := style.Decompose()
				Print(screen, string(SemigraphicsHorizontalEllipsis), b.x+b.width-2, b.y, 1, AlignLeft, fg)
			}
		}
	}

	// Call custom draw function.
	if b.draw != nil {
		b.innerX, b.innerY, b.innerWidth, b.innerHeight = b.draw(screen, b.x, b.y, b.width, b.height)
	} else {
		// Remember the inner rect.
		b.innerX = -1
		b.innerX, b.innerY, b.innerWidth, b.innerHeight = b.GetInnerRect()
	}
}

// Focus is called when this primitive receives focus.
func (b *Box) Focus(delegate func(p Primitive)) {
	b.hasFocus = true
}

// Blur is called when this primitive loses focus.
func (b *Box) Blur() {
	b.hasFocus = false
}

// HasFocus returns whether or not this primitive has focus.
func (b *Box) HasFocus() bool {
	return b.hasFocus
}

// GetFocusable returns the item's Focusable.
func (b *Box) GetFocusable() Focusable {
	return b.focus
}
<|endoftext|>


<commit_before>// Copyright 2015 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
)

func buy(args []string) error {
	os.Args = args

	var (
		amt  string = "0"
		serv        = flag.String("s", "localhost:8088", "path to the factomclient")
	)
	flag.Parse()
	args = flag.Args()
	if len(args) < 1 {
		return man("buy")
	}
	server := "http://" + *serv + "/v1/buycredit"
	data := url.Values{
		"to":     {"wallet"},
		"amount": {amt},
	}

	resp, err := http.PostForm(server, data)
	if err != nil {
		return err
	}
	p, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()
	fmt.Println(string(p))

	return nil
}
<commit_msg>argument parsing for buy.go<commit_after>// Copyright 2015 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
)

func buy(args []string) error {
	os.Args = args

	var (
		amt, addr string = "0", "wallet"
		serv             = flag.String("s", "localhost:8088", "path to the factomclient")
	)
	flag.Parse()
	args = flag.Args()
	if len(args) < 1 {
		return man("buy")
	}
	amt = args[0]
	if len(args) > 1 {
		addr = args[1]
	}

	server := "http://" + *serv + "/v1/buycredit"
	data := url.Values{
		"to":     {addr},
		"amount": {amt},
	}

	resp, err := http.PostForm(server, data)
	if err != nil {
		return err
	}
	p, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()
	fmt.Println(string(p))

	return nil
}
<|endoftext|>


<commit_before>package bwt

import (
	"errors"
	"sort"

	"github.com/shenwei356/util/byteutil"
)

// ErrEndSymbolExisted means you should choose another EndSymbol
var ErrEndSymbolExisted = errors.New("bwt: end-symbol existed in string")

// Transform returns Burrows–Wheeler transform  of a byte slice.
// See https://en.wikipedia.org/wiki/Burrows%E2%80%93Wheeler_transform
func Transform(s []byte, es byte) ([]byte, [][]byte, error) {
	count := byteutil.CountOfByte(s)
	if _, ok := count[es]; ok {
		return nil, nil, ErrEndSymbolExisted
	}
	s = append(s, es)
	n := len(s)

	rotations := make([][]byte, n)
	i := 0
	for j := 0; j < n; j++ {
		rotations[i] = append(s[n-j:], s[0:n-j]...)
		i++
	}
	sort.Sort(byteutil.SliceOfByteSlice(rotations))

	bwt := make([]byte, n)
	i = 0
	for _, t := range rotations {
		bwt[i] = t[n-1]
		i++
	}
	return bwt, rotations, nil
}

// InverseTransform reverses the bwt to original byte slice
func InverseTransform(t []byte, es byte) []byte {
	n := len(t)
	lines := make([][]byte, n)
	for i := 0; i < n; i++ {
		lines[i] = make([]byte, n)
	}

	for i := 0; i < n; i++ {
		for j := 0; j < n; j++ {
			lines[j][n-1-i] = t[j]
		}
		sort.Sort(byteutil.SliceOfByteSlice(lines))
	}

	s := make([]byte, n-1)
	for _, line := range lines {
		if line[n-1] == es {
			s = line[0 : n-1]
			break
		}
	}
	return s
}

// SuffixArray returns the suffix array of s
func SuffixArray(s []byte) []int {
	n := len(s)
	suffixMap := make(map[string]int, n)
	for i := 0; i < n; i++ {
		suffixMap[string(s[i:])] = i
	}
	suffixes := make([]string, n)
	i := 0
	for suffix := range suffixMap {
		suffixes[i] = suffix
		i++
	}
	indice := make([]int, n+1)
	indice[0] = n
	i = 1
	sort.Strings(suffixes)
	for _, suffix := range suffixes {
		indice[i] = suffixMap[suffix]
		i++
	}
	return indice
}

// ErrInvalidSuffixArray means length of sa is not equal to 1+len(s)
var ErrInvalidSuffixArray = errors.New("bwt: invalid suffix array")

// FromSuffixArray compute BWT from sa
func FromSuffixArray(s []byte, sa []int, es byte) ([]byte, error) {
	if len(s)+1 != len(sa) || sa[0] != len(s) {
		return nil, ErrInvalidSuffixArray
	}
	bwt := make([]byte, len(sa))
	bwt[0] = s[len(s)-1]
	for i := 1; i < len(sa); i++ {
		if sa[i] == 0 {
			bwt[i] = es
		} else {
			bwt[i] = s[sa[i]-1]
		}
	}
	return bwt, nil
}
<commit_msg>optimize SuffixArray<commit_after>package bwt

import (
	"bytes"
	"errors"
	"sort"

	"github.com/shenwei356/util/byteutil"
)

// ErrEndSymbolExisted means you should choose another EndSymbol
var ErrEndSymbolExisted = errors.New("bwt: end-symbol existed in string")

// Transform returns Burrows–Wheeler transform  of a byte slice.
// See https://en.wikipedia.org/wiki/Burrows%E2%80%93Wheeler_transform
func Transform(s []byte, es byte) ([]byte, [][]byte, error) {
	count := byteutil.CountOfByte(s)
	if _, ok := count[es]; ok {
		return nil, nil, ErrEndSymbolExisted
	}
	s = append(s, es)
	n := len(s)

	rotations := make([][]byte, n)
	i := 0
	for j := 0; j < n; j++ {
		rotations[i] = append(s[n-j:], s[0:n-j]...)
		i++
	}
	sort.Sort(byteutil.SliceOfByteSlice(rotations))

	bwt := make([]byte, n)
	i = 0
	for _, t := range rotations {
		bwt[i] = t[n-1]
		i++
	}
	return bwt, rotations, nil
}

// InverseTransform reverses the bwt to original byte slice
func InverseTransform(t []byte, es byte) []byte {
	n := len(t)
	lines := make([][]byte, n)
	for i := 0; i < n; i++ {
		lines[i] = make([]byte, n)
	}

	for i := 0; i < n; i++ {
		for j := 0; j < n; j++ {
			lines[j][n-1-i] = t[j]
		}
		sort.Sort(byteutil.SliceOfByteSlice(lines))
	}

	s := make([]byte, n-1)
	for _, line := range lines {
		if line[n-1] == es {
			s = line[0 : n-1]
			break
		}
	}
	return s
}

// SuffixArray returns the suffix array of s
func SuffixArray(s []byte) []int {
	sa := make([]int, len(s)+1)
	sa[0] = len(s)

	for i := 0; i < len(s); i++ {
		sa[i+1] = i
	}
	sort.Slice(sa[1:], func(i, j int) bool {
		return bytes.Compare(s[sa[i+1]:], s[sa[j+1]:]) < 0
	})
	return sa
}

// ErrInvalidSuffixArray means length of sa is not equal to 1+len(s)
var ErrInvalidSuffixArray = errors.New("bwt: invalid suffix array")

// FromSuffixArray compute BWT from sa
func FromSuffixArray(s []byte, sa []int, es byte) ([]byte, error) {
	if len(s)+1 != len(sa) || sa[0] != len(s) {
		return nil, ErrInvalidSuffixArray
	}
	bwt := make([]byte, len(sa))
	bwt[0] = s[len(s)-1]
	for i := 1; i < len(sa); i++ {
		if sa[i] == 0 {
			bwt[i] = es
		} else {
			bwt[i] = s[sa[i]-1]
		}
	}
	return bwt, nil
}
<|endoftext|>