<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"math/rand"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"strings"
	"time"
	"bytes"

	"github.com/JustinBeckwith/go-yelp/yelp"
	//"github.com/guregu/null"
	"github.com/line/line-bot-sdk-go/linebot"
)

var o *yelp.AuthOptions

type UrlShortener struct {
	ShortUrl    string
	OriginalUrl string
}

func yelp_init() {
	rand.Seed(time.Now().UnixNano())

	// check environment variables
	o = &yelp.AuthOptions{
		ConsumerKey:       os.Getenv("CONSUMER_KEY"),
		ConsumerSecret:    os.Getenv("CONSUMER_SECRET"),
		AccessToken:       os.Getenv("ACCESS_TOKEN"),
		AccessTokenSecret: os.Getenv("ACCESS_TOKEN_SECRET"),
	}

	if o.ConsumerKey == "" || o.ConsumerSecret == "" || o.AccessToken == "" || o.AccessTokenSecret == "" {
		log.Fatal("Wrong environment setting about yelp-api-keys")
	}
}

func yelp_parse(bot *linebot.Client, token string, loc *linebot.LocationMessage, food string) {
	var err error

	// create a new yelp client with the auth keys
	client := yelp.New(o, nil)

	if loc == nil {
		// make a simple query for food and location
		results, err := client.DoSimpleSearch(food, "台北市大安區")
		if err == nil {
			log.Println("loc nil")
			yelp_parse_result(bot, token, results)
		}
	} else {
		// Build an advanced set of search criteria that include
		// general options, and coordinate options.
		s := yelp.SearchOptions{
			GeneralOptions: &yelp.GeneralOptions{
				Term: food,
			},
			Location: loc.Address,
			CoordinateOptions: &yelp.CoordinateOptions{
				Latitude:  null.FloatFrom(loc.Latitude),
				Longitude: null.FloatFrom(loc.Longitude),
			},
		}

		// Perform the search using the search options
		results, err := client.DoSearch(s)
		if err == nil {
			log.Println(fmt.Sprintf("loc:(%f, %f)", loc.Latitude, loc.Longitude))
			yelp_parse_result(bot, token, results)
		}
	}
	if err != nil {
		log.Println(err)
		_, err = bot.ReplyMessage(token, linebot.NewTextMessage("查無資料！")).Do()
	}
}

func yelp_parse_result(bot *linebot.Client, token string, results yelp.SearchResult) {
	var err error
//	var msgs []linebot.Message
	var outmsg bytes.Buffer

	for i := 0; i < 3; i++ {
		//i := 0
		//if results.Total >= 20 {
		//	i = rand.Intn(20)
		//} else if results.Total >= 10 {
		//	i = rand.Intn(10)
		//} else if results.Total > j {
		//	i = j
		//} else if results.Total <= j && results.Total != 0 {
		if ( results.Total <= i) {
			_, err = bot.ReplyMessage(token, linebot.NewTextMessage("已無更多資料！")).Do()
			break
		}
		urlOrig := UrlShortener{}
		urlOrig.short(results.Businesses[i].MobileURL)
		address := strings.Join(results.Businesses[i].Location.DisplayAddress, ",")
		//var largeImageURL = strings.Replace(results.Businesses[i].ImageURL, "ms.jpg", "l.jpg", 1)

		outmsg.WriteString("店名："+results.Businesses[i].Name+"\n電話："+results.Businesses[i].Phone+"\n評比："+strconv.FormatFloat(float64(results.Businesses[i].Rating), 'f', 1, 64)+"\n地址："+address+"\n更多資訊："+urlOrig.ShortUrl+"\n")

//		_, err = bot.ReplyMessage(token, linebot.NewImageMessage(largeImageURL, largeImageURL), linebot.NewTextMessage("店名："+results.Businesses[i].Name+"\n電話："+results.Businesses[i].Phone+"\n評比："+strconv.FormatFloat(float64(results.Businesses[i].Rating), 'f', 1, 64)+"\n更多資訊："+urlOrig.ShortUrl), linebot.NewLocationMessage(results.Businesses[i].Name+"\n", address, float64(results.Businesses[i].Location.Coordinate.Latitude), float64(results.Businesses[i].Location.Coordinate.Longitude)) ).Do()
//		msgs = append(msgs, linebot.NewImageMessage(largeImageURL, largeImageURL))
//		msgs = append(msgs, linebot.NewTextMessage("店名："+results.Businesses[i].Name+"\n電話："+results.Businesses[i].Phone+"\n評比："+strconv.FormatFloat(float64(results.Businesses[i].Rating), 'f', 1, 64)+"\n更多資訊："+urlOrig.ShortUrl))
//		msgs = append(msgs, linebot.NewLocationMessage(results.Businesses[i].Name+"\n", address, float64(results.Businesses[i].Location.Coordinate.Latitude), float64(results.Businesses[i].Location.Coordinate.Longitude)))
//		_, err = bot.ReplyMessage(token, linebot.NewImageMessage(largeImageURL, largeImageURL)).Do()
//		_, err = bot.ReplyMessage(token, linebot.NewTextMessage("店名："+results.Businesses[i].Name+"\n電話："+results.Businesses[i].Phone+"\n評比："+strconv.FormatFloat(float64(results.Businesses[i].Rating), 'f', 1, 64)+"\n更多資訊："+urlOrig.ShortUrl)).Do()
//		_, err = bot.ReplyMessage(token, linebot.NewLocationMessage(results.Businesses[i].Name+"\n", address, float64(results.Businesses[i].Location.Coordinate.Latitude), float64(results.Businesses[i].Location.Coordinate.Longitude))).Do()
	}

	if outmsg.String() != "" {
		_, err = bot.ReplyMessage(token, linebot.NewTextMessage(outmsg.String())).Do()
	}
	if err != nil {
		log.Println(err)
	}
}

func getResponseData(urlOrig string) string {
	response, err := http.Get(urlOrig)
	if err != nil {
		log.Println(err)
	}
	defer response.Body.Close()
	contents, err := ioutil.ReadAll(response.Body)
	return string(contents)
}

func isGdShortener(urlOrig string) (string, string) {
	escapedUrl := url.QueryEscape(urlOrig)
	isGdUrl := fmt.Sprintf("http://is.gd/create.php?url=%s&format=simple", escapedUrl)
	return getResponseData(isGdUrl), urlOrig
}

func (u *UrlShortener) short(urlOrig string) *UrlShortener {
	shortUrl, originalUrl := isGdShortener(urlOrig)
	u.ShortUrl = shortUrl
	u.OriginalUrl = originalUrl
	return u
}
<commit_msg>test location<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"math/rand"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"strings"
	"time"
	"bytes"

	"github.com/JustinBeckwith/go-yelp/yelp"
	"github.com/guregu/null"
	"github.com/line/line-bot-sdk-go/linebot"
)

var o *yelp.AuthOptions

type UrlShortener struct {
	ShortUrl    string
	OriginalUrl string
}

func yelp_init() {
	rand.Seed(time.Now().UnixNano())

	// check environment variables
	o = &yelp.AuthOptions{
		ConsumerKey:       os.Getenv("CONSUMER_KEY"),
		ConsumerSecret:    os.Getenv("CONSUMER_SECRET"),
		AccessToken:       os.Getenv("ACCESS_TOKEN"),
		AccessTokenSecret: os.Getenv("ACCESS_TOKEN_SECRET"),
	}

	if o.ConsumerKey == "" || o.ConsumerSecret == "" || o.AccessToken == "" || o.AccessTokenSecret == "" {
		log.Fatal("Wrong environment setting about yelp-api-keys")
	}
}

func yelp_parse(bot *linebot.Client, token string, loc *linebot.LocationMessage, food string) {
	var err error

	// create a new yelp client with the auth keys
	client := yelp.New(o, nil)

	if loc == nil {
		// make a simple query for food and location
		results, err := client.DoSimpleSearch(food, "台北市大安區")
		if err == nil {
			log.Println("loc nil")
			yelp_parse_result(bot, token, results)
		}
	} else {
		// Build an advanced set of search criteria that include
		// general options, and coordinate options.
		s := yelp.SearchOptions{
			GeneralOptions: &yelp.GeneralOptions{
				Term: food,
			},
			Location: loc.Address,
			CoordinateOptions: &yelp.CoordinateOptions{
				Latitude:  null.FloatFrom(loc.Latitude),
				Longitude: null.FloatFrom(loc.Longitude),
			},
		}

		// Perform the search using the search options
		results, err := client.DoSearch(s)
		if err == nil {
			log.Println(fmt.Sprintf("loc:(%f, %f)", loc.Latitude, loc.Longitude))
			yelp_parse_result(bot, token, results)
		}
	}
	if err != nil {
		log.Println(err)
		_, err = bot.ReplyMessage(token, linebot.NewTextMessage("查無資料！")).Do()
	}
}

func yelp_parse_result(bot *linebot.Client, token string, results yelp.SearchResult) {
	var err error
//	var msgs []linebot.Message
	var outmsg bytes.Buffer

	for i := 0; i < 3; i++ {
		//i := 0
		//if results.Total >= 20 {
		//	i = rand.Intn(20)
		//} else if results.Total >= 10 {
		//	i = rand.Intn(10)
		//} else if results.Total > j {
		//	i = j
		//} else if results.Total <= j && results.Total != 0 {
		if ( results.Total <= i) {
			_, err = bot.ReplyMessage(token, linebot.NewTextMessage("已無更多資料！")).Do()
			break
		}
		urlOrig := UrlShortener{}
		urlOrig.short(results.Businesses[i].MobileURL)
		address := strings.Join(results.Businesses[i].Location.DisplayAddress, ",")
		//var largeImageURL = strings.Replace(results.Businesses[i].ImageURL, "ms.jpg", "l.jpg", 1)

		outmsg.WriteString("店名："+results.Businesses[i].Name+"\n電話："+results.Businesses[i].Phone+"\n評比："+strconv.FormatFloat(float64(results.Businesses[i].Rating), 'f', 1, 64)+"\n地址："+address+"\n更多資訊："+urlOrig.ShortUrl+"\n")

//		_, err = bot.ReplyMessage(token, linebot.NewImageMessage(largeImageURL, largeImageURL), linebot.NewTextMessage("店名："+results.Businesses[i].Name+"\n電話："+results.Businesses[i].Phone+"\n評比："+strconv.FormatFloat(float64(results.Businesses[i].Rating), 'f', 1, 64)+"\n更多資訊："+urlOrig.ShortUrl), linebot.NewLocationMessage(results.Businesses[i].Name+"\n", address, float64(results.Businesses[i].Location.Coordinate.Latitude), float64(results.Businesses[i].Location.Coordinate.Longitude)) ).Do()
//		msgs = append(msgs, linebot.NewImageMessage(largeImageURL, largeImageURL))
//		msgs = append(msgs, linebot.NewTextMessage("店名："+results.Businesses[i].Name+"\n電話："+results.Businesses[i].Phone+"\n評比："+strconv.FormatFloat(float64(results.Businesses[i].Rating), 'f', 1, 64)+"\n更多資訊："+urlOrig.ShortUrl))
//		msgs = append(msgs, linebot.NewLocationMessage(results.Businesses[i].Name+"\n", address, float64(results.Businesses[i].Location.Coordinate.Latitude), float64(results.Businesses[i].Location.Coordinate.Longitude)))
//		_, err = bot.ReplyMessage(token, linebot.NewImageMessage(largeImageURL, largeImageURL)).Do()
//		_, err = bot.ReplyMessage(token, linebot.NewTextMessage("店名："+results.Businesses[i].Name+"\n電話："+results.Businesses[i].Phone+"\n評比："+strconv.FormatFloat(float64(results.Businesses[i].Rating), 'f', 1, 64)+"\n更多資訊："+urlOrig.ShortUrl)).Do()
//		_, err = bot.ReplyMessage(token, linebot.NewLocationMessage(results.Businesses[i].Name+"\n", address, float64(results.Businesses[i].Location.Coordinate.Latitude), float64(results.Businesses[i].Location.Coordinate.Longitude))).Do()
	}

	if outmsg.String() != "" {
		_, err = bot.ReplyMessage(token, linebot.NewTextMessage(outmsg.String())).Do()
	}
	if err != nil {
		log.Println(err)
	}
}

func getResponseData(urlOrig string) string {
	response, err := http.Get(urlOrig)
	if err != nil {
		log.Println(err)
	}
	defer response.Body.Close()
	contents, err := ioutil.ReadAll(response.Body)
	return string(contents)
}

func isGdShortener(urlOrig string) (string, string) {
	escapedUrl := url.QueryEscape(urlOrig)
	isGdUrl := fmt.Sprintf("http://is.gd/create.php?url=%s&format=simple", escapedUrl)
	return getResponseData(isGdUrl), urlOrig
}

func (u *UrlShortener) short(urlOrig string) *UrlShortener {
	shortUrl, originalUrl := isGdShortener(urlOrig)
	u.ShortUrl = shortUrl
	u.OriginalUrl = originalUrl
	return u
}
<|endoftext|>


<commit_before>/*
Copyright 2020 The Jetstack cert-manager contributors.

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 issuing

import (
	"context"
	"fmt"
	"time"

	"github.com/go-logr/logr"
	corev1 "k8s.io/api/core/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/client-go/informers"
	"k8s.io/client-go/kubernetes"
	corelisters "k8s.io/client-go/listers/core/v1"
	"k8s.io/client-go/tools/cache"
	"k8s.io/client-go/tools/record"
	"k8s.io/client-go/util/workqueue"
	"k8s.io/utils/clock"

	apiutil "github.com/jetstack/cert-manager/pkg/api/util"
	cmapi "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha2"
	cmmeta "github.com/jetstack/cert-manager/pkg/apis/meta/v1"
	cmclient "github.com/jetstack/cert-manager/pkg/client/clientset/versioned"
	cminformers "github.com/jetstack/cert-manager/pkg/client/informers/externalversions"
	cmlisters "github.com/jetstack/cert-manager/pkg/client/listers/certmanager/v1alpha2"
	controllerpkg "github.com/jetstack/cert-manager/pkg/controller"
	certificates "github.com/jetstack/cert-manager/pkg/controller/expcertificates"
	"github.com/jetstack/cert-manager/pkg/controller/expcertificates/internal/predicate"
	logf "github.com/jetstack/cert-manager/pkg/logs"
	utilkube "github.com/jetstack/cert-manager/pkg/util/kube"
	utilpki "github.com/jetstack/cert-manager/pkg/util/pki"
)

const (
	ControllerName = "CertificateIssuing"

	ctxTimeout = time.Second * 10
)

var (
	certificateGvk = cmapi.SchemeGroupVersion.WithKind("Certificate")
)

// This controller observes the state of the certificate's 'Issuing' condition,
// which will then copy the singed certificates and private key to the target
// Secret resource.
type controller struct {
	certificateLister        cmlisters.CertificateLister
	certificateRequestLister cmlisters.CertificateRequestLister
	secretLister             corelisters.SecretLister
	recorder                 record.EventRecorder
	clock                    clock.Clock

	client cmclient.Interface

	// secretManager is used to create and update Secrets with certificate and key data
	secretsManager *secretsManager
}

func NewController(
	log logr.Logger,
	kubeClient kubernetes.Interface,
	client cmclient.Interface,
	factory informers.SharedInformerFactory,
	cmFactory cminformers.SharedInformerFactory,
	recorder record.EventRecorder,
	clock clock.Clock,
	certificateControllerOptions controllerpkg.CertificateOptions,
) (*controller, workqueue.RateLimitingInterface, []cache.InformerSynced) {

	// create a queue used to queue up items to be processed
	queue := workqueue.NewNamedRateLimitingQueue(workqueue.NewItemExponentialFailureRateLimiter(time.Second*1, time.Second*30), ControllerName)

	// obtain references to all the informers used by this controller
	certificateInformer := cmFactory.Certmanager().V1alpha2().Certificates()
	certificateRequestInformer := cmFactory.Certmanager().V1alpha2().CertificateRequests()
	secretsInformer := factory.Core().V1().Secrets()

	certificateInformer.Informer().AddEventHandler(&controllerpkg.QueuingEventHandler{Queue: queue})
	certificateRequestInformer.Informer().AddEventHandler(&controllerpkg.BlockingEventHandler{
		WorkFunc: certificates.EnqueueCertificatesForResourceUsingPredicates(log, queue, certificateInformer.Lister(), labels.Everything(), predicate.ResourceOwnerOf),
	})
	secretsInformer.Informer().AddEventHandler(&controllerpkg.BlockingEventHandler{
		// Issuer reconciles on changes to the Secret named `spec.nextPrivateKeySecretName`
		WorkFunc: certificates.EnqueueCertificatesForResourceUsingPredicates(log, queue, certificateInformer.Lister(), labels.Everything(),
			predicate.ExtractResourceName(predicate.CertificateNextPrivateKeySecretName)),
	})

	// build a list of InformerSynced functions that will be returned by the Register method.
	// the controller will only begin processing items once all of these informers have synced.
	mustSync := []cache.InformerSynced{
		certificateRequestInformer.Informer().HasSynced,
		secretsInformer.Informer().HasSynced,
		certificateInformer.Informer().HasSynced,
	}

	secretsManager := newSecretsManager(
		kubeClient,
		secretsInformer.Lister(),
		certificateControllerOptions,
	)

	return &controller{
		certificateLister:        certificateInformer.Lister(),
		certificateRequestLister: certificateRequestInformer.Lister(),
		secretLister:             secretsInformer.Lister(),
		client:                   client,
		recorder:                 recorder,
		clock:                    clock,

		secretsManager: secretsManager,
	}, queue, mustSync
}

func (c *controller) ProcessItem(ctx context.Context, key string) error {
	// Set context deadline for full sync in 10 seconds
	ctx, cancel := context.WithTimeout(ctx, time.Second*10)
	defer cancel()

	log := logf.FromContext(ctx).WithValues("key", key)
	namespace, name, err := cache.SplitMetaNamespaceKey(key)
	if err != nil {
		return nil
	}

	crt, err := c.certificateLister.Certificates(namespace).Get(name)
	if apierrors.IsNotFound(err) {
		log.Error(err, "certificate not found for key")
		return nil
	}
	if err != nil {
		return err
	}

	log = logf.WithResource(log, crt)
	ctx = logf.NewContext(ctx, log)

	if !apiutil.CertificateHasCondition(crt, cmapi.CertificateCondition{
		Type:   cmapi.CertificateConditionIssuing,
		Status: cmmeta.ConditionTrue,
	}) {
		// Do nothing if an issuance is not in progress.
		return nil
	}

	if crt.Status.NextPrivateKeySecretName == nil ||
		len(*crt.Status.NextPrivateKeySecretName) == 0 {
		// Do nothing if the next private key secret name is not set
		return nil
	}

	// CertificateRequest revisions begin from 1. If no revision is set on the
	// status then assume no revision yet set.
	nextRevision := 1
	if crt.Status.Revision != nil {
		nextRevision = *crt.Status.Revision + 1
	}

	reqs, err := certificates.ListCertificateRequestsMatchingPredicates(c.certificateRequestLister.CertificateRequests(crt.Namespace),
		labels.Everything(),
		predicate.CertificateRequestRevision(nextRevision),
		predicate.ResourceOwnedBy(crt),
	)
	if err != nil || len(reqs) != 1 {
		// If error return.
		// if no error but none exist do nothing.
		// If no error but multiple exist, then leave to requestmanager controller
		// to clean up.
		return err
	}

	req := reqs[0]
	log = logf.WithResource(log, req)

	reqReason := apiutil.GetCertificateRequestCondition(req, cmapi.CertificateRequestConditionReady).Reason
	switch reqReason {
	// If the certificate request has failed, set the last failure time to now,
	// and set the Issuing status condition to False with reason.
	case cmapi.CertificateRequestReasonFailed:
		return c.failIssueCertificate(ctx, log, crt, req)

		// If the CertificateRequest is valid, verify its status and update
		// accordingly.
	case cmapi.CertificateRequestReasonIssued:
		return c.issueCertificate(ctx, log, nextRevision, crt, req)

	// CertificateRequest is not in a final state so do nothing.
	default:
		log.V(4).Info("CertificateRequest not in final state")
		return nil
	}
}

// failIssueCertificate will mark the condition Issuing of this Certificate as failed, and log an appropriate event
func (c *controller) failIssueCertificate(ctx context.Context, log logr.Logger, crt *cmapi.Certificate, req *cmapi.CertificateRequest) error {
	nowTime := metav1.NewTime(c.clock.Now())
	crt.Status.LastFailureTime = &nowTime

	log.Info("CertificateRequest in failed state so retrying issuance later")

	var reason, message string
	condition := apiutil.GetCertificateRequestCondition(req, cmapi.CertificateRequestConditionReady)

	reason = condition.Reason
	message = fmt.Sprintf("The certificate request has failed to complete and will be retried: %s",
		condition.Message)

	crt = crt.DeepCopy()
	apiutil.SetCertificateCondition(crt, cmapi.CertificateConditionIssuing, cmmeta.ConditionFalse, reason, message)

	_, err := c.client.CertmanagerV1alpha2().Certificates(crt.Namespace).UpdateStatus(ctx, crt, metav1.UpdateOptions{})
	if err != nil {
		return err
	}

	c.recorder.Event(crt, corev1.EventTypeWarning, reason, message)

	return nil
}

// issueCertificate will ensure the public key of the CSR matches the signed
// certificate, and then store the certificate, CA and private key into the
// Secret in the appropriate format type.
func (c *controller) issueCertificate(ctx context.Context, log logr.Logger, nextRevision int, crt *cmapi.Certificate, req *cmapi.CertificateRequest) error {
	csr, err := utilpki.DecodeX509CertificateRequestBytes(req.Spec.CSRPEM)
	if err != nil {
		return err
	}

	//Encode and issue the key-pair (store it in the Secret)
	nextPrivateKeySecret, err := c.secretLister.Secrets(crt.Namespace).Get(*crt.Status.NextPrivateKeySecretName)
	if apierrors.IsNotFound(err) {
		// If secret does not exist, do nothing (keymanager will handle this).
		return nil
	}
	if err != nil {
		return err
	}

	key, keyData, err := utilkube.ParseTLSKeyFromSecret(nextPrivateKeySecret, corev1.TLSPrivateKeyKey)
	if err != nil {
		// If the private key cannot be parsed here, do nothing as the key manager will handle this.
		logf.WithResource(log, nextPrivateKeySecret).Info("failed to parse next private key")
		return nil
	}

	publicKeyMatches, err := utilpki.PublicKeyMatchesCSR(key.Public(), csr)
	if err != nil {
		return err
	}

	// If public key does not match, do nothing (keymanager will handle this).
	if !publicKeyMatches {
		logf.WithResource(log, nextPrivateKeySecret).Info("next private key does not match CSR public key")
		return nil
	}

	// Verify the CSR options match what is requested in certificate.spec.
	violations, err := certificates.RequestMatchesSpec(req, crt.Spec)
	if err != nil {
		return err
	}

	// If there are violations in the spec, then the requestmanager will handle this.
	if len(violations) > 0 {
		log.Info("CertificateRequest does not match Certificate")
		return nil
	}

	signedCertificate := req.Status.Certificate
	ca := req.Status.CA

	err = c.secretsManager.updateData(ctx, crt, secretData{sk: keyData, cert: signedCertificate, ca: ca})
	if err != nil {
		return err
	}

	crt = crt.DeepCopy()

	//Set status.revision to revision of the CertificateRequest
	crt.Status.Revision = &nextRevision

	// Remove Issuing status condition
	apiutil.RemoveCertificateCondition(crt, cmapi.CertificateConditionIssuing)

	//Clear status.lastFailureTime (if set)
	crt.Status.LastFailureTime = nil

	_, err = c.client.CertmanagerV1alpha2().Certificates(crt.Namespace).UpdateStatus(ctx, crt, metav1.UpdateOptions{})
	if err != nil {
		return err
	}

	message := "The certificate has been successfully issued"
	c.recorder.Event(crt, corev1.EventTypeNormal, "Issuing", message)

	return nil
}

// controllerWrapper wraps the `controller` structure to make it implement
// the controllerpkg.queueingController interface
type controllerWrapper struct {
	*controller
}

func (c *controllerWrapper) Register(ctx *controllerpkg.Context) (workqueue.RateLimitingInterface, []cache.InformerSynced, error) {
	// construct a new named logger to be reused throughout the controller
	log := logf.FromContext(ctx.RootContext, ControllerName)

	ctrl, queue, mustSync := NewController(log,
		ctx.Client,
		ctx.CMClient,
		ctx.KubeSharedInformerFactory,
		ctx.SharedInformerFactory,
		ctx.Recorder,
		ctx.Clock,
		ctx.CertificateOptions,
	)
	c.controller = ctrl

	return queue, mustSync, nil
}

func init() {
	controllerpkg.Register(ControllerName, func(ctx *controllerpkg.Context) (controllerpkg.Interface, error) {
		return controllerpkg.NewBuilder(ctx, ControllerName).
			For(&controllerWrapper{}).
			Complete()
	})
}
<commit_msg>Register additional event handlers in issuing controller<commit_after>/*
Copyright 2020 The Jetstack cert-manager contributors.

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 issuing

import (
	"context"
	"fmt"
	"time"

	"github.com/go-logr/logr"
	corev1 "k8s.io/api/core/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/client-go/informers"
	"k8s.io/client-go/kubernetes"
	corelisters "k8s.io/client-go/listers/core/v1"
	"k8s.io/client-go/tools/cache"
	"k8s.io/client-go/tools/record"
	"k8s.io/client-go/util/workqueue"
	"k8s.io/utils/clock"

	apiutil "github.com/jetstack/cert-manager/pkg/api/util"
	cmapi "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha2"
	cmmeta "github.com/jetstack/cert-manager/pkg/apis/meta/v1"
	cmclient "github.com/jetstack/cert-manager/pkg/client/clientset/versioned"
	cminformers "github.com/jetstack/cert-manager/pkg/client/informers/externalversions"
	cmlisters "github.com/jetstack/cert-manager/pkg/client/listers/certmanager/v1alpha2"
	controllerpkg "github.com/jetstack/cert-manager/pkg/controller"
	certificates "github.com/jetstack/cert-manager/pkg/controller/expcertificates"
	"github.com/jetstack/cert-manager/pkg/controller/expcertificates/internal/predicate"
	logf "github.com/jetstack/cert-manager/pkg/logs"
	utilkube "github.com/jetstack/cert-manager/pkg/util/kube"
	utilpki "github.com/jetstack/cert-manager/pkg/util/pki"
)

const (
	ControllerName = "CertificateIssuing"

	ctxTimeout = time.Second * 10
)

var (
	certificateGvk = cmapi.SchemeGroupVersion.WithKind("Certificate")
)

// This controller observes the state of the certificate's 'Issuing' condition,
// which will then copy the singed certificates and private key to the target
// Secret resource.
type controller struct {
	certificateLister        cmlisters.CertificateLister
	certificateRequestLister cmlisters.CertificateRequestLister
	secretLister             corelisters.SecretLister
	recorder                 record.EventRecorder
	clock                    clock.Clock

	client cmclient.Interface

	// secretManager is used to create and update Secrets with certificate and key data
	secretsManager *secretsManager
}

func NewController(
	log logr.Logger,
	kubeClient kubernetes.Interface,
	client cmclient.Interface,
	factory informers.SharedInformerFactory,
	cmFactory cminformers.SharedInformerFactory,
	recorder record.EventRecorder,
	clock clock.Clock,
	certificateControllerOptions controllerpkg.CertificateOptions,
) (*controller, workqueue.RateLimitingInterface, []cache.InformerSynced) {

	// create a queue used to queue up items to be processed
	queue := workqueue.NewNamedRateLimitingQueue(workqueue.NewItemExponentialFailureRateLimiter(time.Second*1, time.Second*30), ControllerName)

	// obtain references to all the informers used by this controller
	certificateInformer := cmFactory.Certmanager().V1alpha2().Certificates()
	certificateRequestInformer := cmFactory.Certmanager().V1alpha2().CertificateRequests()
	secretsInformer := factory.Core().V1().Secrets()

	certificateInformer.Informer().AddEventHandler(&controllerpkg.QueuingEventHandler{Queue: queue})
	certificateRequestInformer.Informer().AddEventHandler(&controllerpkg.BlockingEventHandler{
		WorkFunc: certificates.EnqueueCertificatesForResourceUsingPredicates(log, queue, certificateInformer.Lister(), labels.Everything(), predicate.ResourceOwnerOf),
	})
	secretsInformer.Informer().AddEventHandler(&controllerpkg.BlockingEventHandler{
		// Issuer reconciles on changes to the Secret named `spec.nextPrivateKeySecretName`
		WorkFunc: certificates.EnqueueCertificatesForResourceUsingPredicates(log, queue, certificateInformer.Lister(), labels.Everything(),
			predicate.ResourceOwnerOf,
			predicate.ExtractResourceName(predicate.CertificateNextPrivateKeySecretName)),
	})
	secretsInformer.Informer().AddEventHandler(&controllerpkg.BlockingEventHandler{
		// Issuer reconciles on changes to the Secret named `spec.secretName`
		WorkFunc: certificates.EnqueueCertificatesForResourceUsingPredicates(log, queue, certificateInformer.Lister(), labels.Everything(),
			predicate.ExtractResourceName(predicate.CertificateSecretName)),
	})

	// build a list of InformerSynced functions that will be returned by the Register method.
	// the controller will only begin processing items once all of these informers have synced.
	mustSync := []cache.InformerSynced{
		certificateRequestInformer.Informer().HasSynced,
		secretsInformer.Informer().HasSynced,
		certificateInformer.Informer().HasSynced,
	}

	secretsManager := newSecretsManager(
		kubeClient,
		secretsInformer.Lister(),
		certificateControllerOptions,
	)

	return &controller{
		certificateLister:        certificateInformer.Lister(),
		certificateRequestLister: certificateRequestInformer.Lister(),
		secretLister:             secretsInformer.Lister(),
		client:                   client,
		recorder:                 recorder,
		clock:                    clock,

		secretsManager: secretsManager,
	}, queue, mustSync
}

func (c *controller) ProcessItem(ctx context.Context, key string) error {
	// Set context deadline for full sync in 10 seconds
	ctx, cancel := context.WithTimeout(ctx, time.Second*10)
	defer cancel()

	log := logf.FromContext(ctx).WithValues("key", key)
	namespace, name, err := cache.SplitMetaNamespaceKey(key)
	if err != nil {
		return nil
	}

	crt, err := c.certificateLister.Certificates(namespace).Get(name)
	if apierrors.IsNotFound(err) {
		log.Error(err, "certificate not found for key")
		return nil
	}
	if err != nil {
		return err
	}

	log = logf.WithResource(log, crt)
	ctx = logf.NewContext(ctx, log)

	if !apiutil.CertificateHasCondition(crt, cmapi.CertificateCondition{
		Type:   cmapi.CertificateConditionIssuing,
		Status: cmmeta.ConditionTrue,
	}) {
		// Do nothing if an issuance is not in progress.
		return nil
	}

	if crt.Status.NextPrivateKeySecretName == nil ||
		len(*crt.Status.NextPrivateKeySecretName) == 0 {
		// Do nothing if the next private key secret name is not set
		return nil
	}

	// CertificateRequest revisions begin from 1. If no revision is set on the
	// status then assume no revision yet set.
	nextRevision := 1
	if crt.Status.Revision != nil {
		nextRevision = *crt.Status.Revision + 1
	}

	reqs, err := certificates.ListCertificateRequestsMatchingPredicates(c.certificateRequestLister.CertificateRequests(crt.Namespace),
		labels.Everything(),
		predicate.CertificateRequestRevision(nextRevision),
		predicate.ResourceOwnedBy(crt),
	)
	if err != nil || len(reqs) != 1 {
		// If error return.
		// if no error but none exist do nothing.
		// If no error but multiple exist, then leave to requestmanager controller
		// to clean up.
		return err
	}

	req := reqs[0]
	log = logf.WithResource(log, req)

	reqReason := apiutil.GetCertificateRequestCondition(req, cmapi.CertificateRequestConditionReady).Reason
	switch reqReason {
	// If the certificate request has failed, set the last failure time to now,
	// and set the Issuing status condition to False with reason.
	case cmapi.CertificateRequestReasonFailed:
		return c.failIssueCertificate(ctx, log, crt, req)

		// If the CertificateRequest is valid, verify its status and update
		// accordingly.
	case cmapi.CertificateRequestReasonIssued:
		return c.issueCertificate(ctx, log, nextRevision, crt, req)

	// CertificateRequest is not in a final state so do nothing.
	default:
		log.V(4).Info("CertificateRequest not in final state")
		return nil
	}
}

// failIssueCertificate will mark the condition Issuing of this Certificate as failed, and log an appropriate event
func (c *controller) failIssueCertificate(ctx context.Context, log logr.Logger, crt *cmapi.Certificate, req *cmapi.CertificateRequest) error {
	nowTime := metav1.NewTime(c.clock.Now())
	crt.Status.LastFailureTime = &nowTime

	log.Info("CertificateRequest in failed state so retrying issuance later")

	var reason, message string
	condition := apiutil.GetCertificateRequestCondition(req, cmapi.CertificateRequestConditionReady)

	reason = condition.Reason
	message = fmt.Sprintf("The certificate request has failed to complete and will be retried: %s",
		condition.Message)

	crt = crt.DeepCopy()
	apiutil.SetCertificateCondition(crt, cmapi.CertificateConditionIssuing, cmmeta.ConditionFalse, reason, message)

	_, err := c.client.CertmanagerV1alpha2().Certificates(crt.Namespace).UpdateStatus(ctx, crt, metav1.UpdateOptions{})
	if err != nil {
		return err
	}

	c.recorder.Event(crt, corev1.EventTypeWarning, reason, message)

	return nil
}

// issueCertificate will ensure the public key of the CSR matches the signed
// certificate, and then store the certificate, CA and private key into the
// Secret in the appropriate format type.
func (c *controller) issueCertificate(ctx context.Context, log logr.Logger, nextRevision int, crt *cmapi.Certificate, req *cmapi.CertificateRequest) error {
	csr, err := utilpki.DecodeX509CertificateRequestBytes(req.Spec.CSRPEM)
	if err != nil {
		return err
	}

	//Encode and issue the key-pair (store it in the Secret)
	nextPrivateKeySecret, err := c.secretLister.Secrets(crt.Namespace).Get(*crt.Status.NextPrivateKeySecretName)
	if apierrors.IsNotFound(err) {
		// If secret does not exist, do nothing (keymanager will handle this).
		return nil
	}
	if err != nil {
		return err
	}

	key, keyData, err := utilkube.ParseTLSKeyFromSecret(nextPrivateKeySecret, corev1.TLSPrivateKeyKey)
	if err != nil {
		// If the private key cannot be parsed here, do nothing as the key manager will handle this.
		logf.WithResource(log, nextPrivateKeySecret).Info("failed to parse next private key")
		return nil
	}

	publicKeyMatches, err := utilpki.PublicKeyMatchesCSR(key.Public(), csr)
	if err != nil {
		return err
	}

	// If public key does not match, do nothing (keymanager will handle this).
	if !publicKeyMatches {
		logf.WithResource(log, nextPrivateKeySecret).Info("next private key does not match CSR public key")
		return nil
	}

	// Verify the CSR options match what is requested in certificate.spec.
	violations, err := certificates.RequestMatchesSpec(req, crt.Spec)
	if err != nil {
		return err
	}

	// If there are violations in the spec, then the requestmanager will handle this.
	if len(violations) > 0 {
		log.Info("CertificateRequest does not match Certificate")
		return nil
	}

	signedCertificate := req.Status.Certificate
	ca := req.Status.CA

	err = c.secretsManager.updateData(ctx, crt, secretData{sk: keyData, cert: signedCertificate, ca: ca})
	if err != nil {
		return err
	}

	crt = crt.DeepCopy()

	//Set status.revision to revision of the CertificateRequest
	crt.Status.Revision = &nextRevision

	// Remove Issuing status condition
	apiutil.RemoveCertificateCondition(crt, cmapi.CertificateConditionIssuing)

	//Clear status.lastFailureTime (if set)
	crt.Status.LastFailureTime = nil

	_, err = c.client.CertmanagerV1alpha2().Certificates(crt.Namespace).UpdateStatus(ctx, crt, metav1.UpdateOptions{})
	if err != nil {
		return err
	}

	message := "The certificate has been successfully issued"
	c.recorder.Event(crt, corev1.EventTypeNormal, "Issuing", message)

	return nil
}

// controllerWrapper wraps the `controller` structure to make it implement
// the controllerpkg.queueingController interface
type controllerWrapper struct {
	*controller
}

func (c *controllerWrapper) Register(ctx *controllerpkg.Context) (workqueue.RateLimitingInterface, []cache.InformerSynced, error) {
	// construct a new named logger to be reused throughout the controller
	log := logf.FromContext(ctx.RootContext, ControllerName)

	ctrl, queue, mustSync := NewController(log,
		ctx.Client,
		ctx.CMClient,
		ctx.KubeSharedInformerFactory,
		ctx.SharedInformerFactory,
		ctx.Recorder,
		ctx.Clock,
		ctx.CertificateOptions,
	)
	c.controller = ctrl

	return queue, mustSync, nil
}

func init() {
	controllerpkg.Register(ControllerName, func(ctx *controllerpkg.Context) (controllerpkg.Interface, error) {
		return controllerpkg.NewBuilder(ctx, ControllerName).
			For(&controllerWrapper{}).
			Complete()
	})
}
<|endoftext|>


<commit_before>package rabbus

import (
	"sync"
	"testing"
	"time"
)

func TestRabbusListen(t *testing.T) {
	r, err := NewRabbus(Config{
		Dsn:      "amqp://guest:guest@localhost:5672",
		Attempts: 1,
		Timeout:  time.Second * 2,
	})
	if err != nil {
		t.Fail()
	}

	var wg sync.WaitGroup
	wg.Add(1)

	handler := func(d *Delivery) {
		d.Ack(true)
		wg.Done()
	}

	if err := r.Listen(ListenConfig{
		ExchangeName: "test_ex",
		ExchangeType: "topic",
		RoutingKey:   "test_key",
		QueueName:    "test_q",
		HandlerFunc:  handler,
	}); err != nil {
		t.Fail()
	}

	r.Emit() <- &Message{
		ExchangeName: "test_ex",
		ExchangeType: "topic",
		RoutingKey:   "test_key",
		Payload:      []byte(`foo`),
		DeliveryMode: Transient,
	}

	go func() {
		for {
			select {
			case <-r.EmitOk():
			case <-r.EmitErr():
				t.Errorf("Expected to emit message")
				wg.Done()
			}
		}
	}()

	wg.Wait()
}

func TestRabbusListen_Validate(t *testing.T) {
	r, err := NewRabbus(Config{
		Dsn:      "amqp://guest:guest@localhost:5672",
		Attempts: 1,
		Timeout:  time.Second * 2,
	})
	if err != nil {
		t.Fail()
	}

	if err := r.Listen(ListenConfig{}); err == nil {
		t.Errorf("Expected to validate ExchangeName")
	}

	if err = r.Listen(ListenConfig{ExchangeName: "foo"}); err == nil {
		t.Errorf("Expected to validate ExchangeType")
	}

	if err = r.Listen(ListenConfig{
		ExchangeName: "foo",
		ExchangeType: "foo",
	}); err == nil {
		t.Errorf("Expected to validate QueueName")
	}

	if err = r.Listen(ListenConfig{
		ExchangeName: "foo",
		ExchangeType: "foo",
		QueueName:    "foo",
	}); err == nil {
		t.Errorf("Expected to validate HandlerFunc")
	}
}

func TestRabbusClose(t *testing.T) {
	r, err := NewRabbus(Config{
		Dsn:      "amqp://guest:guest@localhost:5672",
		Attempts: 1,
		Timeout:  time.Second * 2,
	})
	if err != nil {
		t.Fail()
	}

	r.Close()
}

func TestRabbus_reconnect(t *testing.T) {
	r, err := NewRabbus(Config{
		Dsn:      "amqp://guest:guest@localhost:5672",
		Attempts: 1,
		Timeout:  time.Second * 2,
	})
	if err != nil {
		t.Fail()
	}

	r.reconnect()
}
<commit_msg>Naming error<commit_after>package rabbus

import (
	"sync"
	"testing"
	"time"
)

func TestRabbusListen(t *testing.T) {
	r, err := NewRabbus(Config{
		Dsn:      "amqp://guest:guest@localhost:5672",
		Attempts: 1,
		Timeout:  time.Second * 2,
	})
	if err != nil {
		t.Fail()
	}

	var wg sync.WaitGroup
	wg.Add(1)

	handler := func(d *Delivery) {
		d.Ack(true)
		wg.Done()
	}

	if err := r.Listen(ListenConfig{
		ExchangeName: "test_ex",
		ExchangeType: "topic",
		RoutingKey:   "test_key",
		QueueName:    "test_q",
		HandlerFunc:  handler,
	}); err != nil {
		t.Errorf("Expected to listen message %s", err)
	}

	r.Emit() <- &Message{
		ExchangeName: "test_ex",
		ExchangeType: "topic",
		RoutingKey:   "test_key",
		Payload:      []byte(`foo`),
		DeliveryMode: Transient,
	}

	go func() {
		for {
			select {
			case <-r.EmitOk():
			case <-r.EmitErr():
				t.Errorf("Expected to emit message")
				wg.Done()
			}
		}
	}()

	wg.Wait()
}

func TestRabbusListen_Validate(t *testing.T) {
	r, err := NewRabbus(Config{
		Dsn:      "amqp://guest:guest@localhost:5672",
		Attempts: 1,
		Timeout:  time.Second * 2,
	})
	if err != nil {
		t.Fail()
	}

	if err := r.Listen(ListenConfig{}); err == nil {
		t.Errorf("Expected to validate ExchangeName")
	}

	if err = r.Listen(ListenConfig{ExchangeName: "foo"}); err == nil {
		t.Errorf("Expected to validate ExchangeType")
	}

	if err = r.Listen(ListenConfig{
		ExchangeName: "foo",
		ExchangeType: "foo",
	}); err == nil {
		t.Errorf("Expected to validate QueueName")
	}

	if err = r.Listen(ListenConfig{
		ExchangeName: "foo",
		ExchangeType: "foo",
		QueueName:    "foo",
	}); err == nil {
		t.Errorf("Expected to validate HandlerFunc")
	}
}

func TestRabbusClose(t *testing.T) {
	r, err := NewRabbus(Config{
		Dsn:      "amqp://guest:guest@localhost:5672",
		Attempts: 1,
		Timeout:  time.Second * 2,
	})
	if err != nil {
		t.Fail()
	}

	r.Close()
}

func TestRabbus_reconnect(t *testing.T) {
	r, err := NewRabbus(Config{
		Dsn:      "amqp://guest:guest@localhost:5672",
		Attempts: 1,
		Timeout:  time.Second * 2,
	})
	if err != nil {
		t.Fail()
	}

	r.reconnect()
}
<|endoftext|>


<commit_before>package token

import (
	"bytes"
	"crypto/hmac"
	"encoding/binary"
	"hash"
	"time"

	"github.com/cosiner/gohper/encoding"
	"github.com/cosiner/gohper/errors"
	"github.com/cosiner/gohper/time2"
)

const (
	ErrBadKey           = errors.Err("bad key")
	ErrExpiredKey       = errors.Err("expired key")
	ErrInvalidSignature = errors.Err("invalid signature")
)

type Cipher struct {
	signKey []byte
	ttl     time.Duration
	hash    func() hash.Hash
	sigLen  int
	hdrLen  int
}

func NewCipher(signKey []byte, ttl time.Duration, hash func() hash.Hash, encs ...encoding.Encoding) encoding.Encoding {
	sigLen := hash().Size() / 3
	return encoding.Pipe(encs).Prepend(&Cipher{
		signKey: signKey,
		ttl:     ttl,
		hash:    hash,
		sigLen:  sigLen,
		hdrLen:  sigLen + 8,
	})
}

// | signature | deadline | str
func (c *Cipher) encrypt(deadline uint64, b []byte) []byte {
	result := make([]byte, c.hdrLen+len(b))
	binary.BigEndian.PutUint64(result[c.sigLen:c.hdrLen], deadline)
	copy(result[c.hdrLen:], b)

	hash := hmac.New(c.hash, c.signKey)
	hash.Write(b)
	hash.Write(result[c.sigLen : c.hdrLen])
	copy(result, hash.Sum(nil)[:c.sigLen])

	return result
}

func (c *Cipher) Encode(b []byte) []byte {
	deadline := uint64(time2.Now().Add(c.ttl).Unix())
	return c.encrypt(deadline, b)
}

func (c *Cipher) Decode(b []byte) ([]byte, error) {
	if len(b) < c.hdrLen {
		return nil, ErrBadKey
	}

	deadline := binary.BigEndian.Uint64(b[c.sigLen:c.hdrLen])
	if c.ttl != 0 && uint64(time2.Now().Unix()) > deadline {
		return nil, ErrExpiredKey
	}

	data := b[c.hdrLen:]
	encData := c.encrypt(deadline, data)
	if !bytes.Equal(encData, b) {
		return nil, ErrInvalidSignature
	}

	return data, nil
}
<commit_msg>utils/token: using normal length signature<commit_after>package token

import (
	"bytes"
	"crypto/hmac"
	"encoding/binary"
	"hash"
	"time"

	"github.com/cosiner/gohper/encoding"
	"github.com/cosiner/gohper/errors"
	"github.com/cosiner/gohper/time2"
)

const (
	ErrBadKey           = errors.Err("bad key")
	ErrExpiredKey       = errors.Err("expired key")
	ErrInvalidSignature = errors.Err("invalid signature")
)

type Cipher struct {
	signKey []byte
	ttl     time.Duration
	hash    func() hash.Hash
	sigLen  int
	hdrLen  int
}

func newCipher(signKey []byte, ttl time.Duration, hash func() hash.Hash) *Cipher {
	sigLen := hash().Size()
	return &Cipher{
		signKey: signKey,
		ttl:     ttl,
		hash:    hash,
		sigLen:  sigLen,
		hdrLen:  sigLen + 8,
	}
}

func NewCipher(signKey []byte, ttl time.Duration, hash func() hash.Hash, encs ...encoding.Encoding) encoding.Encoding {
	return encoding.Pipe(encs).Prepend(newCipher(signKey, ttl, hash))
}

// | signature | deadline | str
func (c *Cipher) encrypt(deadline uint64, b []byte) []byte {
	result := make([]byte, c.hdrLen+len(b))
	binary.BigEndian.PutUint64(result[c.sigLen:c.hdrLen], deadline)
	copy(result[c.hdrLen:], b)

	hash := hmac.New(c.hash, c.signKey)
	hash.Write(b)
	hash.Write(result[c.sigLen:c.hdrLen])
	copy(result, hash.Sum(nil)[:c.sigLen])

	return result
}

func (c *Cipher) Encode(b []byte) []byte {
	deadline := uint64(time2.Now().Add(c.ttl).Unix())
	return c.encrypt(deadline, b)
}

func (c *Cipher) Decode(b []byte) ([]byte, error) {
	if len(b) < c.hdrLen {
		return nil, ErrBadKey
	}

	deadline := binary.BigEndian.Uint64(b[c.sigLen:c.hdrLen])
	if c.ttl != 0 && uint64(time2.Now().Unix()) > deadline {
		return nil, ErrExpiredKey
	}

	data := b[c.hdrLen:]
	encData := c.encrypt(deadline, data)
	if !bytes.Equal(encData, b) {
		return nil, ErrInvalidSignature
	}

	return data, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package cache

import (
	"time"

	"k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	"k8s.io/apimachinery/pkg/fields"
	"k8s.io/apimachinery/pkg/labels"
	clientset "k8s.io/client-go/kubernetes"
	corev1 "k8s.io/client-go/listers/core/v1"
	clientcache "k8s.io/client-go/tools/cache"

	arbv1 "github.com/kubernetes-incubator/kube-arbitrator/pkg/apis/v1"
)

// TODO some operation for map[arbv1.ResourceName]resource.Quantity, it is better to enhance it in resource_info.go

func ResourcesAdd(res1 map[arbv1.ResourceName]resource.Quantity, res2 map[arbv1.ResourceName]resource.Quantity) map[arbv1.ResourceName]resource.Quantity {
	cpu1 := res1["cpu"].DeepCopy()
	cpu2 := res2["cpu"].DeepCopy()
	mem1 := res1["memory"].DeepCopy()
	mem2 := res2["memory"].DeepCopy()

	cpu1.Add(cpu2)
	mem1.Add(mem2)

	return map[arbv1.ResourceName]resource.Quantity{
		"cpu":    cpu1,
		"memory": mem1,
	}
}

func ResourcesSub(res1 map[arbv1.ResourceName]resource.Quantity, res2 map[arbv1.ResourceName]resource.Quantity) map[arbv1.ResourceName]resource.Quantity {
	cpu1 := res1["cpu"].DeepCopy()
	cpu2 := res2["cpu"].DeepCopy()
	mem1 := res1["memory"].DeepCopy()
	mem2 := res2["memory"].DeepCopy()

	if cpu1.Cmp(cpu2) <= 0 {
		cpu1 = resource.MustParse("0")
	} else {
		cpu1.Sub(cpu2)
	}
	if mem1.Cmp(mem2) <= 0 {
		mem1 = resource.MustParse("0")
	} else {
		mem1.Sub(mem2)
	}

	return map[arbv1.ResourceName]resource.Quantity{
		"cpu":    cpu1,
		"memory": mem1,
	}
}

func ResourcesIsZero(res map[arbv1.ResourceName]resource.Quantity) bool {
	cpu := res["cpu"].DeepCopy()
	mem := res["memory"].DeepCopy()

	if cpu.IsZero() && mem.IsZero() {
		return true
	}

	return false
}

// -1  - if res1 < res2
// 0   - if res1 = res2
// 1   - if not belong above cases
func CompareResources(res1 map[arbv1.ResourceName]resource.Quantity, res2 map[arbv1.ResourceName]resource.Quantity) int {
	cpu1 := res1["cpu"].DeepCopy()
	cpu2 := res2["cpu"].DeepCopy()
	memory1 := res1["memory"].DeepCopy()
	memory2 := res2["memory"].DeepCopy()

	if cpu1.Cmp(cpu2) <= 0 && memory1.Cmp(memory2) <= 0 {
		if cpu1.Cmp(cpu2) == 0 && memory1.Cmp(memory2) == 0 {
			return 0
		} else {
			return -1
		}
	} else {
		return 1
	}
}

func NodeLister(client clientset.Interface, stopChannel <-chan struct{}) ([]*v1.Node, error) {
	nl := GetNodeLister(client, stopChannel)
	nodes, err := nl.List(labels.Everything())
	if err != nil {
		return []*v1.Node{}, err
	}
	return nodes, err
}

func GetNodeLister(client clientset.Interface, stopChannel <-chan struct{}) corev1.NodeLister {
	listWatcher := clientcache.NewListWatchFromClient(client.Core().RESTClient(), "nodes", v1.NamespaceAll, fields.Everything())
	store := clientcache.NewIndexer(clientcache.MetaNamespaceKeyFunc, clientcache.Indexers{clientcache.NamespaceIndex: clientcache.MetaNamespaceIndexFunc})
	nodeLister := corev1.NewNodeLister(store)
	reflector := clientcache.NewReflector(listWatcher, &v1.Node{}, store, time.Hour)
	reflector.Run(stopChannel)

	return nodeLister
}

// podKey returns the string key of a pod.
func podKey(pod *v1.Pod) (string, error) {
	return clientcache.MetaNamespaceKeyFunc(pod)
}
<commit_msg>Removed unused util funcs.<commit_after>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package cache

import (
	"k8s.io/api/core/v1"
	clientcache "k8s.io/client-go/tools/cache"
)

// podKey returns the string key of a pod.
func podKey(pod *v1.Pod) (string, error) {
	return clientcache.MetaNamespaceKeyFunc(pod)
}
<|endoftext|>


<commit_before>package flake

// OvertoneEpochMs represents the number of milliseconds that elapsed between the
// UnixEpoch (1/1/1970) and the Overtone Epoch, Sunday, January 1st, 2017
// (2017-01-01 00:00:00 +0000 UTC)
//
// This is the default epoch used by overt-flake
const OvertoneEpochMs = int64(1483228800000)

// UnixEpochMs is the number of milliseconds elapsed since the Unix Epoch
// (which is none)
const UnixEpochMs = int64(0)

// SnowflakeEpochMs is the number of milliseconds elapsed between the Unix Epoch
// (1/1/19070) and the Twitter Snowflake Epoch (2010-11-04 01:42:54 +0000 UTC ??)
const SnowflakeEpochMs = int64(1288834974657)
<commit_msg>added the length of an over-flake id as a constant<commit_after>package flake

// OvertoneEpochMs represents the number of milliseconds that elapsed between the
// UnixEpoch (1/1/1970) and the Overtone Epoch, Sunday, January 1st, 2017
// (2017-01-01 00:00:00 +0000 UTC)
//
// This is the default epoch used by overt-flake
const OvertoneEpochMs = int64(1483228800000)

// UnixEpochMs is the number of milliseconds elapsed since the Unix Epoch
// (which is none)
const UnixEpochMs = int64(0)

// SnowflakeEpochMs is the number of milliseconds elapsed between the Unix Epoch
// (1/1/19070) and the Twitter Snowflake Epoch (2010-11-04 01:42:54 +0000 UTC ??)
const SnowflakeEpochMs = int64(1288834974657)

// OvertFlakeIDLength is the length, in bytes, of an Overt-flake ID
const OvertFlakeIDLength = 16
<|endoftext|>


<commit_before>package dispatcher

import "github.com/abhinavdahiya/go-messenger-bot"

type MockState struct {
	IsMoved bool
	Chain   string
}

func (m *MockState) Name() string {
	return "mock"
}

func (m *MockState) Transit(s string) {
	m.IsMoved = true
	m.Chain = s
}

func (m *MockState) Next() string {
	return m.Chain
}

func (m *MockState) Flush() {
	m.IsMoved = false
	m.Chain = ""
}

func mockEnter(state *State, c mbotapi.Callback, bot *mbotapi.BotAPI) error {
	msg := mbotapi.NewMessage("HI boss!!")
	bot.Send(c.Sender, msg, mbotapi.RegularNotif)
	return nil
}

func mockLeave(state *State, c mbotapi.Callback, bot *mbotapi.BotAPI) error {
	msg := mbotapi.NewMessage("To the next step boss!!")
	bot.Send(c.Sender, msg, mbotapi.RegularNotif)
	return nil
}

func (m *MockState) Actions() (Action, Action) {
	return mockEnter, mockLeave
}
<commit_msg>action update<commit_after>package dispatcher

import "github.com/abhinavdahiya/go-messenger-bot"

type MockState struct {
	IsMoved bool
	Chain   string
}

func (m *MockState) Name() string {
	return "mock"
}

func (m *MockState) Transit(s string) {
	m.IsMoved = true
	m.Chain = s
}

func (m *MockState) Next() string {
	return m.Chain
}

func (m *MockState) Flush() {
	m.IsMoved = false
	m.Chain = ""
}

func mockEnter(state State, c mbotapi.Callback, bot *mbotapi.BotAPI) error {
	msg := mbotapi.NewMessage("HI boss!!")
	bot.Send(c.Sender, msg, mbotapi.RegularNotif)
	return nil
}

func mockLeave(state State, c mbotapi.Callback, bot *mbotapi.BotAPI) error {
	msg := mbotapi.NewMessage("To the next step boss!!")
	bot.Send(c.Sender, msg, mbotapi.RegularNotif)
	return nil
}

func (m *MockState) Actions() (Action, Action) {
	return mockEnter, mockLeave
}
<|endoftext|>


<commit_before>package fuse

import (
	. "github.com/smartystreets/goconvey/convey"
	"testing"
)

func TestVersion(t *testing.T) {
	version := Version()
	Convey("Fuse version", t, func() {
		So(version, ShouldBeGreaterThanOrEqualTo, 26)
	})
}

func TestLookup(t *testing.T) {
	fs := NewMemFs()
	fsId := RegisterRawFs(fs)
	defer DeregisterRawFs(fsId)
	fileEnt, _ := fs.Mknod(1, "exists", 0444, 0)

	Convey("Lookup invalid inode", t, func() {
		BridgeLookup(fsId, 1000, "test", func(id int, r interface{}) int {
			switch r := r.(type) {
			case *ReplyErr:
				So(r.err, ShouldEqual, ENOENT)

			default:
				t.Errorf("Unexpected reply: %#v", r)
			}
			return int(OK)
		})
	})

	Convey("Lookup invalid file", t, func() {
		BridgeLookup(fsId, 1, "test", func(id int, r interface{}) int {
			switch r := r.(type) {
			case *ReplyErr:
				So(r.err, ShouldEqual, ENOENT)

			default:
				t.Errorf("Unexpected reply: %#v", r)
			}
			return int(OK)
		})
	})

	Convey("Lookup valid file", t, func() {
		BridgeLookup(fsId, 1, "exists", func(id int, r interface{}) int {
			So(r, ShouldHaveSameTypeAs, &ReplyEntry{})
			return int(OK)
		})
	})

	Convey("Lookup invalid node type", t, func() {
		// Pass a file inode as the directory.
		BridgeLookup(fsId, fileEnt.Ino, "test", func(id int, r interface{}) int {
			switch r := r.(type) {
			case *ReplyErr:
				So(r.err, ShouldEqual, ENOTDIR)

			default:
				t.Errorf("Unexpected reply: %#v", r)
			}
			return int(OK)
		})
	})
}

func TestForget(t *testing.T) {
	fs := NewMemFs()
	fsId := RegisterRawFs(fs)
	defer DeregisterRawFs(fsId)

	Convey("Forget uses reply_none", t, func() {
		BridgeForget(fsId, 100, 1, func(id int, r interface{}) int {
			So(r, ShouldHaveSameTypeAs, &ReplyNone{})
			return int(OK)
		})
	})
}

func TestGetAttr(t *testing.T) {
	fs := NewMemFs()
	fsId := RegisterRawFs(fs)
	defer DeregisterRawFs(fsId)

	Convey("GetAttr on existing directory", t, func() {
		BridgeGetAttr(fsId, 1, func(id int, r interface{}) int {
			So(r, ShouldHaveSameTypeAs, &ReplyAttr{})
			a := r.(*ReplyAttr)
			stat := a.attr
			So(stat, ShouldNotBeNil)
			So(stat.st_ino, ShouldEqual, 1)
			return int(OK)
		})
	})

	Convey("GetAttr on nonexistant node", t, func() {
		BridgeGetAttr(fsId, 1000, func(id int, r interface{}) int {
			switch r := r.(type) {
			case *ReplyErr:
				So(r.err, ShouldEqual, ENOENT)

			default:
				t.Errorf("Unexpected reply: %#v", r)
			}
			return int(OK)
		})
	})
}

func TestStatFs(t *testing.T) {
	fs := NewMemFs()
	fsId := RegisterRawFs(fs)
	defer DeregisterRawFs(fsId)

	Convey("StatFs on undefined inode", t, func() {
		BridgeStatFs(fsId, 0, func(id int, r interface{}) int {
			So(r, ShouldHaveSameTypeAs, &ReplyStatFs{})
			return int(OK)
		})
	})
}
<commit_msg>move common test setup to TestMain<commit_after>package fuse

import (
	. "github.com/smartystreets/goconvey/convey"
	"os"
	"testing"
)

var fs RawFileSystem
var fsId int

func TestMain(m *testing.M) {
	fs = NewMemFs()
	fsId = RegisterRawFs(fs)

	r := m.Run()

	DeregisterRawFs(fsId)
	os.Exit(r)
}

func TestVersion(t *testing.T) {
	version := Version()
	Convey("Fuse version", t, func() {
		So(version, ShouldBeGreaterThanOrEqualTo, 26)
	})
}

func TestLookup(t *testing.T) {
	fileEnt, _ := fs.Mknod(1, "exists", 0444, 0)

	Convey("Lookup invalid inode", t, func() {
		BridgeLookup(fsId, 1000, "test", func(id int, r interface{}) int {
			switch r := r.(type) {
			case *ReplyErr:
				So(r.err, ShouldEqual, ENOENT)

			default:
				t.Errorf("Unexpected reply: %#v", r)
			}
			return int(OK)
		})
	})

	Convey("Lookup invalid file", t, func() {
		BridgeLookup(fsId, 1, "test", func(id int, r interface{}) int {
			switch r := r.(type) {
			case *ReplyErr:
				So(r.err, ShouldEqual, ENOENT)

			default:
				t.Errorf("Unexpected reply: %#v", r)
			}
			return int(OK)
		})
	})

	Convey("Lookup valid file", t, func() {
		BridgeLookup(fsId, 1, "exists", func(id int, r interface{}) int {
			So(r, ShouldHaveSameTypeAs, &ReplyEntry{})
			return int(OK)
		})
	})

	Convey("Lookup invalid node type", t, func() {
		// Pass a file inode as the directory.
		BridgeLookup(fsId, fileEnt.Ino, "test", func(id int, r interface{}) int {
			switch r := r.(type) {
			case *ReplyErr:
				So(r.err, ShouldEqual, ENOTDIR)

			default:
				t.Errorf("Unexpected reply: %#v", r)
			}
			return int(OK)
		})
	})
}

func TestForget(t *testing.T) {
	Convey("Forget uses reply_none", t, func() {
		BridgeForget(fsId, 100, 1, func(id int, r interface{}) int {
			So(r, ShouldHaveSameTypeAs, &ReplyNone{})
			return int(OK)
		})
	})
}

func TestGetAttr(t *testing.T) {
	Convey("GetAttr on existing directory", t, func() {
		BridgeGetAttr(fsId, 1, func(id int, r interface{}) int {
			So(r, ShouldHaveSameTypeAs, &ReplyAttr{})
			a := r.(*ReplyAttr)
			stat := a.attr
			So(stat, ShouldNotBeNil)
			So(stat.st_ino, ShouldEqual, 1)
			return int(OK)
		})
	})

	Convey("GetAttr on nonexistant node", t, func() {
		BridgeGetAttr(fsId, 1000, func(id int, r interface{}) int {
			switch r := r.(type) {
			case *ReplyErr:
				So(r.err, ShouldEqual, ENOENT)

			default:
				t.Errorf("Unexpected reply: %#v", r)
			}
			return int(OK)
		})
	})
}

func TestStatFs(t *testing.T) {
	Convey("StatFs on undefined inode", t, func() {
		BridgeStatFs(fsId, 0, func(id int, r interface{}) int {
			So(r, ShouldHaveSameTypeAs, &ReplyStatFs{})
			return int(OK)
		})
	})
}
<|endoftext|>


<commit_before>package fusefs

import (
	"crypto/rand"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"io/ioutil"
	"os"
	"testing"
	"time"

	"github.com/asjoyner/shade"
	"github.com/asjoyner/shade/cache"
	"github.com/asjoyner/shade/drive"
	"github.com/asjoyner/shade/drive/memory"

	"bazil.org/fuse"
)

func TestFuseRead(t *testing.T) {
	mountPoint, err := ioutil.TempDir("", "fusefsTest")
	fmt.Println("testing at: ", mountPoint)
	if err != nil {
		t.Fatalf("could not acquire TempDir: %s", err)
	}
	defer tearDownDir(mountPoint)

	client, err := setupFuse(t, mountPoint)
	if err != nil {
		t.Fatalf("could not mount fuse: %s", err)
	}
	defer tearDownFuse(t, mountPoint)

	chunkSize := 100 * 256

	// Generate some random file contents
	testChunks := make(map[string][]byte, 10)
	for _ = range testChunks {
		n := make([]byte, chunkSize)
		rand.Read(n)
		s := sha256.Sum256(n)
		chunkSum := string(s[:])
		testChunks[chunkSum] = n
	}

	// Populate test chunks into the client
	for stringSum, chunk := range testChunks {
		err := client.PutChunk([]byte(stringSum), chunk)
		if err != nil {
			t.Fatalf("Failed to put chunk \"%x\": %s", stringSum, err)
		}
	}

	// Populate files, referencing those chunks, into the client
	// the directory scheme is to break apart the shasum into dirs:
	// deadbeef == de/ad/be/ff/deadbeef
	// .. unless it starts with 0, so we exercise files at / too.
	for chunkStringSum := range testChunks {
		chs := hex.EncodeToString([]byte(chunkStringSum))
		var filename string
		if chs[0] == 0 {
			filename = chs
		} else {
			for i := 0; i >= len(chs); i += 2 {
				filename = fmt.Sprintf("%s/%s", filename, chs[i:2])
			}
		}
		file := shade.File{
			Filename: "",
			Filesize: int64(len(chunkStringSum)),
			Chunks: []shade.Chunk{{
				Index:  0,
				Sha256: []byte(chunkStringSum),
			}},
			Chunksize: chunkSize,
		}
		fj, err := file.ToJSON()
		if err != nil {
			t.Fatalf("test data is broken, could not marshal File: %s", err)
		}
		fileSum := sha256.Sum256(fj)
		client.PutFile(fileSum[:], fj)
	}
	time.Sleep(1)
	// TODO(asjoyner): test that the files are visible via fuse
}

// setup returns the absolute path to a mountpoint for a fuse FS, and the
// memory-backed drive.Client which it is following.  The Client is configured
// to refresh once per second, tests should sleep after PutFile / PutChunk.
// TODO(asjoyner): refresh the cache on demand
func setupFuse(t *testing.T, mountPoint string) (drive.Client, error) {
	options := []fuse.MountOption{
		fuse.FSName("Shade"),
		fuse.NoAppleDouble(),
	}
	conn, err := fuse.Mount(mountPoint, options...)
	if err != nil {
		// often means the mountpoint is busy... but it's a TempDir...
		return nil, fmt.Errorf("could not setup Fuse mount: %s", err)
	}

	mc, err := memory.NewClient(drive.Config{Provider: "memory"})
	if err != nil {
		return nil, fmt.Errorf("NewClient() for test config failed: %s", err)
	}

	refresh := time.NewTicker(1 * time.Second)
	r, err := cache.NewReader([]drive.Client{mc}, refresh)
	if err != nil {
		return nil, fmt.Errorf("could not initialize cache: %s", err)
	}

	ffs := New(r, conn)
	go func() {
		err = ffs.Serve()
		if err != nil {
			t.Errorf("fuse server initialization failed: %s", err)
		}
	}()

	<-conn.Ready // returns when the FS is usable
	if conn.MountError != nil {
		return nil, fmt.Errorf("fuse exited with an error: %s", err)
	}
	return mc, nil
}

func tearDownFuse(t *testing.T, dir string) {
	if err := fuse.Unmount(dir); err != nil {
		t.Fatalf("could not Unmount test dir: %s", err)
	}
}

func tearDownDir(dir string) {
	if err := os.RemoveAll(dir); err != nil {
		fmt.Printf("Could not clean up: %s", err)
	}
}
<commit_msg>Fix filename handling in fusefs_test.go<commit_after>package fusefs

import (
	"crypto/rand"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"testing"
	"time"

	"github.com/asjoyner/shade"
	"github.com/asjoyner/shade/cache"
	"github.com/asjoyner/shade/drive"
	"github.com/asjoyner/shade/drive/memory"

	"bazil.org/fuse"
)

func TestFuseRead(t *testing.T) {
	mountPoint, err := ioutil.TempDir("", "fusefsTest")
	//fmt.Println("testing at: ", mountPoint)
	if err != nil {
		t.Fatalf("could not acquire TempDir: %s", err)
	}
	defer tearDownDir(mountPoint)

	client, err := setupFuse(t, mountPoint)
	if err != nil {
		t.Fatalf("could not mount fuse: %s", err)
	}
	defer tearDownFuse(t, mountPoint)

	chunkSize := 100 * 256 // in bytes
	nc := 4                // number of chunks

	// Generate some random file contents
	testChunks := make(map[string][]byte, nc)
	for i := 0; i < nc; i++ {
		n := make([]byte, chunkSize)
		rand.Read(n)
		s := sha256.Sum256(n)
		chunkSum := string(s[:])
		testChunks[chunkSum] = n
	}

	// Populate test chunks into the client
	for stringSum, chunk := range testChunks {
		err := client.PutChunk([]byte(stringSum), chunk)
		if err != nil {
			t.Fatalf("Failed to put chunk \"%x\": %s", stringSum, err)
		}
	}

	// Populate files, referencing those chunks, into the client
	// the directory scheme is to break apart the shasum into dirs:
	// deadbeef == de/ad/be/ff/deadbeef
	// .. unless it starts with 0, so we exercise files at / too.
	for chunkStringSum := range testChunks {
		chs := hex.EncodeToString([]byte(chunkStringSum))
		var filename string
		if strings.HasPrefix(chs, "0") {
			filename = chs
		} else {
			for i := 0; i <= len(chs)-8; i += 8 {
				filename = fmt.Sprintf("%s/%s", filename, chs[i:i+8])
			}
		}
		file := shade.File{
			Filename: filename,
			Filesize: int64(len(chunkStringSum)),
			Chunks: []shade.Chunk{{
				Index:  0,
				Sha256: []byte(chunkStringSum),
			}},
			Chunksize: chunkSize,
		}
		fj, err := file.ToJSON()
		if err != nil {
			t.Fatalf("test data is broken, could not marshal File: %s", err)
		}
		fileSum := sha256.Sum256(fj)
		if err := client.PutFile(fileSum[:], fj); err != nil {
			t.Errorf("failed to PutFile \"%x\": %s", fileSum[:], err)
		}
	}
	time.Sleep(1 * time.Second)

	visit := func(path string, f os.FileInfo, err error) error {
		// TODO(asjoyner): validate paths visited
		fmt.Printf("Visited: %s\n", path)
		return nil
	}

	if err := filepath.Walk(mountPoint, visit); err != nil {
		t.Fatalf("filepath.Walk() returned %v\n", err)
	}
}

// setup returns the absolute path to a mountpoint for a fuse FS, and the
// memory-backed drive.Client which it is following.  The Client is configured
// to refresh once per second, tests should sleep after PutFile / PutChunk.
// TODO(asjoyner): refresh the cache on demand
func setupFuse(t *testing.T, mountPoint string) (drive.Client, error) {
	options := []fuse.MountOption{
		fuse.FSName("Shade"),
		fuse.NoAppleDouble(),
	}
	conn, err := fuse.Mount(mountPoint, options...)
	if err != nil {
		// often means the mountpoint is busy... but it's a TempDir...
		return nil, fmt.Errorf("could not setup Fuse mount: %s", err)
	}

	mc, err := memory.NewClient(drive.Config{Provider: "memory"})
	if err != nil {
		return nil, fmt.Errorf("NewClient() for test config failed: %s", err)
	}

	refresh := time.NewTicker(1 * time.Second)
	r, err := cache.NewReader([]drive.Client{mc}, refresh)
	if err != nil {
		return nil, fmt.Errorf("could not initialize cache: %s", err)
	}

	ffs := New(r, conn)
	go func() {
		err = ffs.Serve()
		if err != nil {
			t.Errorf("fuse server initialization failed: %s", err)
		}
	}()

	<-conn.Ready // returns when the FS is usable
	if conn.MountError != nil {
		return nil, fmt.Errorf("fuse exited with an error: %s", err)
	}
	return mc, nil
}

func tearDownFuse(t *testing.T, dir string) {
	if err := fuse.Unmount(dir); err != nil {
		t.Fatalf("could not Unmount test dir: %s", err)
	}
}

func tearDownDir(dir string) {
	if err := os.RemoveAll(dir); err != nil {
		fmt.Printf("Could not clean up: %s", err)
	}
}
<|endoftext|>


<commit_before>package lnwire

import (
	"bytes"
	"fmt"
	"image/color"
	"io"
	"net"
	"unicode/utf8"
)

var (
	startPort uint16 = 1024
	endPort   uint16 = 49151
)

// NodeAlias a hex encoded UTF-8 string that may be displayed as an alternative
// to the node's ID. Notice that aliases are not unique and may be freely
// chosen by the node operators.
type NodeAlias [32]byte

// NewNodeAlias creates a new instance of a NodeAlias. Verification is
// performed on the passed string to ensure it meets the alias requirements.
func NewNodeAlias(s string) (NodeAlias, error) {
	var n NodeAlias

	if len(s) > 32 {
		return n, fmt.Errorf("alias too large: max is %v, got %v", 32, len(s))
	}

	if !utf8.ValidString(s) {
		return n, fmt.Errorf("invalid utf8 string")
	}

	copy(n[:], []byte(s))
	return n, nil
}

// String returns a utf8 string representation of the alias bytes.
func (n NodeAlias) String() string {
	// Trim trailing zero-bytes for presentation
	return string(bytes.Trim(n[:], "\x00"))
}

// NodeAnnouncement message is used to announce the presence of a Lightning
// node and also to signal that the node is accepting incoming connections.
// Each NodeAnnouncement authenticating the advertised information within the
// announcement via a signature using the advertised node pubkey.
type NodeAnnouncement struct {
	// Signature is used to prove the ownership of node id.
	Signature Sig

	// Features is the list of protocol features this node supports.
	Features *RawFeatureVector

	// Timestamp allows ordering in the case of multiple announcements.
	Timestamp uint32

	// NodeID is a public key which is used as node identification.
	NodeID [33]byte

	// RGBColor is used to customize their node's appearance in maps and
	// graphs
	RGBColor color.RGBA

	// Alias is used to customize their node's appearance in maps and
	// graphs
	Alias NodeAlias

	// Address includes two specification fields: 'ipv6' and 'port' on
	// which the node is accepting incoming connections.
	Addresses []net.Addr
}

// A compile time check to ensure NodeAnnouncement implements the
// lnwire.Message interface.
var _ Message = (*NodeAnnouncement)(nil)

// Decode deserializes a serialized NodeAnnouncement stored in the passed
// io.Reader observing the specified protocol version.
//
// This is part of the lnwire.Message interface.
func (a *NodeAnnouncement) Decode(r io.Reader, pver uint32) error {
	return readElements(r,
		&a.Signature,
		&a.Features,
		&a.Timestamp,
		&a.NodeID,
		&a.RGBColor,
		a.Alias[:],
		&a.Addresses,
	)
}

// Encode serializes the target NodeAnnouncement into the passed io.Writer
// observing the protocol version specified.
//
func (a *NodeAnnouncement) Encode(w io.Writer, pver uint32) error {
	return writeElements(w,
		a.Signature,
		a.Features,
		a.Timestamp,
		a.NodeID,
		a.RGBColor,
		a.Alias[:],
		a.Addresses,
	)
}

// MsgType returns the integer uniquely identifying this message type on the
// wire.
//
// This is part of the lnwire.Message interface.
func (a *NodeAnnouncement) MsgType() MessageType {
	return MsgNodeAnnouncement
}

// MaxPayloadLength returns the maximum allowed payload size for this message
// observing the specified protocol version.
//
// This is part of the lnwire.Message interface.
func (a *NodeAnnouncement) MaxPayloadLength(pver uint32) uint32 {
	return 65533
}

// DataToSign returns the part of the message that should be signed.
func (a *NodeAnnouncement) DataToSign() ([]byte, error) {

	// We should not include the signatures itself.
	var w bytes.Buffer
	err := writeElements(&w,
		a.Features,
		a.Timestamp,
		a.NodeID,
		a.RGBColor,
		a.Alias[:],
		a.Addresses,
	)
	if err != nil {
		return nil, err
	}

	// TODO(roasbeef): also capture the excess bytes in msg padded out?

	return w.Bytes(), nil
}
<commit_msg>lnwire: add new ErrUnknownAddrType for unknown addr types during parsing<commit_after>package lnwire

import (
	"bytes"
	"fmt"
	"image/color"
	"io"
	"net"
	"unicode/utf8"
)

var (
	startPort uint16 = 1024
	endPort   uint16 = 49151
)

// ErrUnknownAddrType is an error returned if we encounter an unknown address type
// when parsing addresses.
type ErrUnknownAddrType struct {
	addrType addressType
}

// Error returns a human readable string describing the error.
//
// NOTE: implements the error interface.
func (e ErrUnknownAddrType) Error() string {
	return fmt.Sprintf("unknown address type: %v", e.addrType)
}

// NodeAlias a hex encoded UTF-8 string that may be displayed as an alternative
// to the node's ID. Notice that aliases are not unique and may be freely
// chosen by the node operators.
type NodeAlias [32]byte

// NewNodeAlias creates a new instance of a NodeAlias. Verification is
// performed on the passed string to ensure it meets the alias requirements.
func NewNodeAlias(s string) (NodeAlias, error) {
	var n NodeAlias

	if len(s) > 32 {
		return n, fmt.Errorf("alias too large: max is %v, got %v", 32, len(s))
	}

	if !utf8.ValidString(s) {
		return n, fmt.Errorf("invalid utf8 string")
	}

	copy(n[:], []byte(s))
	return n, nil
}

// String returns a utf8 string representation of the alias bytes.
func (n NodeAlias) String() string {
	// Trim trailing zero-bytes for presentation
	return string(bytes.Trim(n[:], "\x00"))
}

// NodeAnnouncement message is used to announce the presence of a Lightning
// node and also to signal that the node is accepting incoming connections.
// Each NodeAnnouncement authenticating the advertised information within the
// announcement via a signature using the advertised node pubkey.
type NodeAnnouncement struct {
	// Signature is used to prove the ownership of node id.
	Signature Sig

	// Features is the list of protocol features this node supports.
	Features *RawFeatureVector

	// Timestamp allows ordering in the case of multiple announcements.
	Timestamp uint32

	// NodeID is a public key which is used as node identification.
	NodeID [33]byte

	// RGBColor is used to customize their node's appearance in maps and
	// graphs
	RGBColor color.RGBA

	// Alias is used to customize their node's appearance in maps and
	// graphs
	Alias NodeAlias

	// Address includes two specification fields: 'ipv6' and 'port' on
	// which the node is accepting incoming connections.
	Addresses []net.Addr
}

// A compile time check to ensure NodeAnnouncement implements the
// lnwire.Message interface.
var _ Message = (*NodeAnnouncement)(nil)

// Decode deserializes a serialized NodeAnnouncement stored in the passed
// io.Reader observing the specified protocol version.
//
// This is part of the lnwire.Message interface.
func (a *NodeAnnouncement) Decode(r io.Reader, pver uint32) error {
	return readElements(r,
		&a.Signature,
		&a.Features,
		&a.Timestamp,
		&a.NodeID,
		&a.RGBColor,
		a.Alias[:],
		&a.Addresses,
	)
}

// Encode serializes the target NodeAnnouncement into the passed io.Writer
// observing the protocol version specified.
//
func (a *NodeAnnouncement) Encode(w io.Writer, pver uint32) error {
	return writeElements(w,
		a.Signature,
		a.Features,
		a.Timestamp,
		a.NodeID,
		a.RGBColor,
		a.Alias[:],
		a.Addresses,
	)
}

// MsgType returns the integer uniquely identifying this message type on the
// wire.
//
// This is part of the lnwire.Message interface.
func (a *NodeAnnouncement) MsgType() MessageType {
	return MsgNodeAnnouncement
}

// MaxPayloadLength returns the maximum allowed payload size for this message
// observing the specified protocol version.
//
// This is part of the lnwire.Message interface.
func (a *NodeAnnouncement) MaxPayloadLength(pver uint32) uint32 {
	return 65533
}

// DataToSign returns the part of the message that should be signed.
func (a *NodeAnnouncement) DataToSign() ([]byte, error) {

	// We should not include the signatures itself.
	var w bytes.Buffer
	err := writeElements(&w,
		a.Features,
		a.Timestamp,
		a.NodeID,
		a.RGBColor,
		a.Alias[:],
		a.Addresses,
	)
	if err != nil {
		return nil, err
	}

	// TODO(roasbeef): also capture the excess bytes in msg padded out?

	return w.Bytes(), nil
}
<|endoftext|>


<commit_before>// Copyright (C) 2015 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.

// +build integration

package integration

import (
	"bytes"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"testing"
	"time"

	"github.com/syncthing/syncthing/lib/rc"
)

func TestConflictsDefault(t *testing.T) {
	log.Println("Cleaning...")
	err := removeAll("s1", "s2", "h1/index*", "h2/index*")
	if err != nil {
		t.Fatal(err)
	}

	log.Println("Generating files...")
	err = generateFiles("s1", 100, 20, "../LICENSE")
	if err != nil {
		t.Fatal(err)
	}

	fd, err := os.Create("s1/testfile.txt")
	if err != nil {
		t.Fatal(err)
	}
	_, err = fd.WriteString("hello\n")
	if err != nil {
		t.Fatal(err)
	}
	err = fd.Close()
	if err != nil {
		t.Fatal(err)
	}

	expected, err := directoryContents("s1")
	if err != nil {
		t.Fatal(err)
	}

	sender := startInstance(t, 1)
	defer checkedStop(t, sender)
	receiver := startInstance(t, 2)
	defer checkedStop(t, receiver)

	sender.ResumeAll()
	receiver.ResumeAll()

	// Rescan with a delay on the next one, so we are not surprised by a
	// sudden rescan while we're trying to introduce conflicts.

	if err := sender.RescanDelay("default", 86400); err != nil {
		t.Fatal(err)
	}
	if err := receiver.RescanDelay("default", 86400); err != nil {
		t.Fatal(err)
	}
	rc.AwaitSync("default", sender, receiver)

	log.Println("Verifying...")

	actual, err := directoryContents("s2")
	if err != nil {
		t.Fatal(err)
	}
	err = compareDirectoryContents(actual, expected)
	if err != nil {
		t.Fatal(err)
	}

	log.Println("Introducing a conflict (simultaneous edit)...")

	if err := sender.PauseDevice(receiver.ID()); err != nil {
		t.Fatal(err)
	}

	fd, err = os.OpenFile("s1/testfile.txt", os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		t.Fatal(err)
	}
	_, err = fd.WriteString("text added to s1\n")
	if err != nil {
		t.Fatal(err)
	}
	err = fd.Close()
	if err != nil {
		t.Fatal(err)
	}

	fd, err = os.OpenFile("s2/testfile.txt", os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		t.Fatal(err)
	}
	_, err = fd.WriteString("text added to s2\n")
	if err != nil {
		t.Fatal(err)
	}
	err = fd.Close()
	if err != nil {
		t.Fatal(err)
	}

	if err := sender.ResumeDevice(receiver.ID()); err != nil {
		t.Fatal(err)
	}

	log.Println("Syncing...")

	if err := sender.RescanDelay("default", 86400); err != nil {
		t.Fatal(err)
	}
	if err := receiver.RescanDelay("default", 86400); err != nil {
		t.Fatal(err)
	}
	rc.AwaitSync("default", sender, receiver)

	// The conflict is expected on the s2 side due to how we calculate which
	// file is the winner (based on device ID)

	files, err := filepath.Glob("s2/*sync-conflict*")
	if err != nil {
		t.Fatal(err)
	}
	if len(files) != 1 {
		t.Errorf("Expected 1 conflicted files instead of %d", len(files))
	}

	log.Println("Introducing a conflict (edit plus delete)...")

	if err := sender.PauseDevice(receiver.ID()); err != nil {
		t.Fatal(err)
	}

	err = os.Remove("s1/testfile.txt")
	if err != nil {
		t.Fatal(err)
	}

	fd, err = os.OpenFile("s2/testfile.txt", os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		t.Fatal(err)
	}
	_, err = fd.WriteString("more text added to s2\n")
	if err != nil {
		t.Fatal(err)
	}
	err = fd.Close()
	if err != nil {
		t.Fatal(err)
	}

	if err := sender.ResumeDevice(receiver.ID()); err != nil {
		t.Fatal(err)
	}

	log.Println("Syncing...")

	if err := sender.RescanDelay("default", 86400); err != nil {
		t.Fatal(err)
	}
	if err := receiver.RescanDelay("default", 86400); err != nil {
		t.Fatal(err)
	}
	rc.AwaitSync("default", sender, receiver)

	// The conflict is resolved to the advantage of the edit over the delete.
	// As such, we get the edited content synced back to s1 where it was
	// removed.

	files, err = filepath.Glob("s2/*sync-conflict*")
	if err != nil {
		t.Fatal(err)
	}
	if len(files) != 1 {
		t.Errorf("Expected 1 conflicted files instead of %d", len(files))
	}
	bs, err := ioutil.ReadFile("s1/testfile.txt")
	if err != nil {
		t.Error("reading file:", err)
	}
	if !bytes.Contains(bs, []byte("more text added to s2")) {
		t.Error("s1/testfile.txt should contain data added in s2")
	}
}

func TestConflictsInitialMerge(t *testing.T) {
	log.Println("Cleaning...")
	err := removeAll("s1", "s2", "h1/index*", "h2/index*")
	if err != nil {
		t.Fatal(err)
	}

	err = os.Mkdir("s1", 0755)
	if err != nil {
		t.Fatal(err)
	}
	err = os.Mkdir("s2", 0755)
	if err != nil {
		t.Fatal(err)
	}

	// File 1 is a conflict

	err = ioutil.WriteFile("s1/file1", []byte("hello\n"), 0644)
	if err != nil {
		t.Fatal(err)
	}

	err = ioutil.WriteFile("s2/file1", []byte("goodbye\n"), 0644)
	if err != nil {
		t.Fatal(err)
	}

	// File 2 exists on s1 only

	err = ioutil.WriteFile("s1/file2", []byte("hello\n"), 0644)
	if err != nil {
		t.Fatal(err)
	}

	// File 3 exists on s2 only

	err = ioutil.WriteFile("s2/file3", []byte("goodbye\n"), 0644)
	if err != nil {
		t.Fatal(err)
	}

	// Let them sync

	sender := startInstance(t, 1)
	defer checkedStop(t, sender)
	receiver := startInstance(t, 2)
	defer checkedStop(t, receiver)

	sender.ResumeAll()
	receiver.ResumeAll()

	log.Println("Syncing...")

	rc.AwaitSync("default", sender, receiver)

	checkedStop(t, sender)
	checkedStop(t, receiver)

	log.Println("Verifying...")

	// s1 should have three-four files (there's a conflict from s2 which may or may not have synced yet)

	files, err := filepath.Glob("s1/file*")
	if err != nil {
		t.Fatal(err)
	}
	if len(files) < 3 || len(files) > 4 {
		t.Errorf("Expected 3-4 files in s1 instead of %d", len(files))
	}

	// s2 should have four files (there's a conflict)

	files, err = filepath.Glob("s2/file*")
	if err != nil {
		t.Fatal(err)
	}
	if len(files) != 4 {
		t.Errorf("Expected 4 files in s2 instead of %d", len(files))
	}

	// file1 is in conflict, so there's two versions of that one

	files, err = filepath.Glob("s2/file1*")
	if err != nil {
		t.Fatal(err)
	}
	if len(files) != 2 {
		t.Errorf("Expected 2 'file1' files in s2 instead of %d", len(files))
	}
}

func TestConflictsIndexReset(t *testing.T) {
	log.Println("Cleaning...")
	err := removeAll("s1", "s2", "h1/index*", "h2/index*")
	if err != nil {
		t.Fatal(err)
	}

	err = os.Mkdir("s1", 0755)
	if err != nil {
		t.Fatal(err)
	}
	err = os.Mkdir("s2", 0755)
	if err != nil {
		t.Fatal(err)
	}

	// Three files on s1

	err = ioutil.WriteFile("s1/file1", []byte("hello\n"), 0644)
	if err != nil {
		t.Fatal(err)
	}
	err = ioutil.WriteFile("s1/file2", []byte("hello\n"), 0644)
	if err != nil {
		t.Fatal(err)
	}
	err = ioutil.WriteFile("s2/file3", []byte("hello\n"), 0644)
	if err != nil {
		t.Fatal(err)
	}

	// Let them sync

	sender := startInstance(t, 1)
	defer checkedStop(t, sender)
	receiver := startInstance(t, 2)
	defer checkedStop(t, receiver)

	sender.ResumeAll()
	receiver.ResumeAll()

	log.Println("Syncing...")

	rc.AwaitSync("default", sender, receiver)

	log.Println("Verifying...")

	// s1 should have three files

	files, err := filepath.Glob("s1/file*")
	if err != nil {
		t.Fatal(err)
	}
	if len(files) != 3 {
		t.Errorf("Expected 3 files in s1 instead of %d", len(files))
	}

	// s2 should have three

	files, err = filepath.Glob("s2/file*")
	if err != nil {
		t.Fatal(err)
	}
	if len(files) != 3 {
		t.Errorf("Expected 3 files in s2 instead of %d", len(files))
	}

	log.Println("Updating...")

	// change s2/file2 a few times, so that its version counter increases.
	// This will make the file on the cluster look newer than what we have
	// locally after we rest the index, unless we have a fix for that.

	for i := 0; i < 5; i++ {
		err = ioutil.WriteFile("s2/file2", []byte("hello1\n"), 0644)
		if err != nil {
			t.Fatal(err)
		}
		err = receiver.Rescan("default")
		if err != nil {
			t.Fatal(err)
		}
		time.Sleep(time.Second)
	}

	rc.AwaitSync("default", sender, receiver)

	// Now nuke the index

	log.Println("Resetting...")

	checkedStop(t, receiver)
	removeAll("h2/index*")

	// s1/file1 (remote) changes while receiver is down

	err = ioutil.WriteFile("s1/file1", []byte("goodbye\n"), 0644)
	if err != nil {
		t.Fatal(err)
	}

	// s1 must know about it
	err = sender.Rescan("default")
	if err != nil {
		t.Fatal(err)
	}

	// s2/file2 (local) changes while receiver is down

	err = ioutil.WriteFile("s2/file2", []byte("goodbye\n"), 0644)
	if err != nil {
		t.Fatal(err)
	}

	receiver = startInstance(t, 2)
	defer checkedStop(t, receiver)

	log.Println("Syncing...")

	rc.AwaitSync("default", sender, receiver)

	// s2 should have five files (three plus two conflicts)

	files, err = filepath.Glob("s2/file*")
	if err != nil {
		t.Fatal(err)
	}
	if len(files) != 5 {
		t.Errorf("Expected 5 files in s2 instead of %d", len(files))
	}

	// file1 is in conflict, so there's two versions of that one

	files, err = filepath.Glob("s2/file1*")
	if err != nil {
		t.Fatal(err)
	}
	if len(files) != 2 {
		t.Errorf("Expected 2 'file1' files in s2 instead of %d", len(files))
	}

	// file2 is in conflict, so there's two versions of that one

	files, err = filepath.Glob("s2/file2*")
	if err != nil {
		t.Fatal(err)
	}
	if len(files) != 2 {
		t.Errorf("Expected 2 'file2' files in s2 instead of %d", len(files))
	}
}
<commit_msg>test: Forgot a resume<commit_after>// Copyright (C) 2015 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.

// +build integration

package integration

import (
	"bytes"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"testing"
	"time"

	"github.com/syncthing/syncthing/lib/rc"
)

func TestConflictsDefault(t *testing.T) {
	log.Println("Cleaning...")
	err := removeAll("s1", "s2", "h1/index*", "h2/index*")
	if err != nil {
		t.Fatal(err)
	}

	log.Println("Generating files...")
	err = generateFiles("s1", 100, 20, "../LICENSE")
	if err != nil {
		t.Fatal(err)
	}

	fd, err := os.Create("s1/testfile.txt")
	if err != nil {
		t.Fatal(err)
	}
	_, err = fd.WriteString("hello\n")
	if err != nil {
		t.Fatal(err)
	}
	err = fd.Close()
	if err != nil {
		t.Fatal(err)
	}

	expected, err := directoryContents("s1")
	if err != nil {
		t.Fatal(err)
	}

	sender := startInstance(t, 1)
	defer checkedStop(t, sender)
	receiver := startInstance(t, 2)
	defer checkedStop(t, receiver)

	sender.ResumeAll()
	receiver.ResumeAll()

	// Rescan with a delay on the next one, so we are not surprised by a
	// sudden rescan while we're trying to introduce conflicts.

	if err := sender.RescanDelay("default", 86400); err != nil {
		t.Fatal(err)
	}
	if err := receiver.RescanDelay("default", 86400); err != nil {
		t.Fatal(err)
	}
	rc.AwaitSync("default", sender, receiver)

	log.Println("Verifying...")

	actual, err := directoryContents("s2")
	if err != nil {
		t.Fatal(err)
	}
	err = compareDirectoryContents(actual, expected)
	if err != nil {
		t.Fatal(err)
	}

	log.Println("Introducing a conflict (simultaneous edit)...")

	if err := sender.PauseDevice(receiver.ID()); err != nil {
		t.Fatal(err)
	}

	fd, err = os.OpenFile("s1/testfile.txt", os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		t.Fatal(err)
	}
	_, err = fd.WriteString("text added to s1\n")
	if err != nil {
		t.Fatal(err)
	}
	err = fd.Close()
	if err != nil {
		t.Fatal(err)
	}

	fd, err = os.OpenFile("s2/testfile.txt", os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		t.Fatal(err)
	}
	_, err = fd.WriteString("text added to s2\n")
	if err != nil {
		t.Fatal(err)
	}
	err = fd.Close()
	if err != nil {
		t.Fatal(err)
	}

	if err := sender.ResumeDevice(receiver.ID()); err != nil {
		t.Fatal(err)
	}

	log.Println("Syncing...")

	if err := sender.RescanDelay("default", 86400); err != nil {
		t.Fatal(err)
	}
	if err := receiver.RescanDelay("default", 86400); err != nil {
		t.Fatal(err)
	}
	rc.AwaitSync("default", sender, receiver)

	// The conflict is expected on the s2 side due to how we calculate which
	// file is the winner (based on device ID)

	files, err := filepath.Glob("s2/*sync-conflict*")
	if err != nil {
		t.Fatal(err)
	}
	if len(files) != 1 {
		t.Errorf("Expected 1 conflicted files instead of %d", len(files))
	}

	log.Println("Introducing a conflict (edit plus delete)...")

	if err := sender.PauseDevice(receiver.ID()); err != nil {
		t.Fatal(err)
	}

	err = os.Remove("s1/testfile.txt")
	if err != nil {
		t.Fatal(err)
	}

	fd, err = os.OpenFile("s2/testfile.txt", os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		t.Fatal(err)
	}
	_, err = fd.WriteString("more text added to s2\n")
	if err != nil {
		t.Fatal(err)
	}
	err = fd.Close()
	if err != nil {
		t.Fatal(err)
	}

	if err := sender.ResumeDevice(receiver.ID()); err != nil {
		t.Fatal(err)
	}

	log.Println("Syncing...")

	if err := sender.RescanDelay("default", 86400); err != nil {
		t.Fatal(err)
	}
	if err := receiver.RescanDelay("default", 86400); err != nil {
		t.Fatal(err)
	}
	rc.AwaitSync("default", sender, receiver)

	// The conflict is resolved to the advantage of the edit over the delete.
	// As such, we get the edited content synced back to s1 where it was
	// removed.

	files, err = filepath.Glob("s2/*sync-conflict*")
	if err != nil {
		t.Fatal(err)
	}
	if len(files) != 1 {
		t.Errorf("Expected 1 conflicted files instead of %d", len(files))
	}
	bs, err := ioutil.ReadFile("s1/testfile.txt")
	if err != nil {
		t.Error("reading file:", err)
	}
	if !bytes.Contains(bs, []byte("more text added to s2")) {
		t.Error("s1/testfile.txt should contain data added in s2")
	}
}

func TestConflictsInitialMerge(t *testing.T) {
	log.Println("Cleaning...")
	err := removeAll("s1", "s2", "h1/index*", "h2/index*")
	if err != nil {
		t.Fatal(err)
	}

	err = os.Mkdir("s1", 0755)
	if err != nil {
		t.Fatal(err)
	}
	err = os.Mkdir("s2", 0755)
	if err != nil {
		t.Fatal(err)
	}

	// File 1 is a conflict

	err = ioutil.WriteFile("s1/file1", []byte("hello\n"), 0644)
	if err != nil {
		t.Fatal(err)
	}

	err = ioutil.WriteFile("s2/file1", []byte("goodbye\n"), 0644)
	if err != nil {
		t.Fatal(err)
	}

	// File 2 exists on s1 only

	err = ioutil.WriteFile("s1/file2", []byte("hello\n"), 0644)
	if err != nil {
		t.Fatal(err)
	}

	// File 3 exists on s2 only

	err = ioutil.WriteFile("s2/file3", []byte("goodbye\n"), 0644)
	if err != nil {
		t.Fatal(err)
	}

	// Let them sync

	sender := startInstance(t, 1)
	defer checkedStop(t, sender)
	receiver := startInstance(t, 2)
	defer checkedStop(t, receiver)

	sender.ResumeAll()
	receiver.ResumeAll()

	log.Println("Syncing...")

	rc.AwaitSync("default", sender, receiver)

	checkedStop(t, sender)
	checkedStop(t, receiver)

	log.Println("Verifying...")

	// s1 should have three-four files (there's a conflict from s2 which may or may not have synced yet)

	files, err := filepath.Glob("s1/file*")
	if err != nil {
		t.Fatal(err)
	}
	if len(files) < 3 || len(files) > 4 {
		t.Errorf("Expected 3-4 files in s1 instead of %d", len(files))
	}

	// s2 should have four files (there's a conflict)

	files, err = filepath.Glob("s2/file*")
	if err != nil {
		t.Fatal(err)
	}
	if len(files) != 4 {
		t.Errorf("Expected 4 files in s2 instead of %d", len(files))
	}

	// file1 is in conflict, so there's two versions of that one

	files, err = filepath.Glob("s2/file1*")
	if err != nil {
		t.Fatal(err)
	}
	if len(files) != 2 {
		t.Errorf("Expected 2 'file1' files in s2 instead of %d", len(files))
	}
}

func TestConflictsIndexReset(t *testing.T) {
	log.Println("Cleaning...")
	err := removeAll("s1", "s2", "h1/index*", "h2/index*")
	if err != nil {
		t.Fatal(err)
	}

	err = os.Mkdir("s1", 0755)
	if err != nil {
		t.Fatal(err)
	}
	err = os.Mkdir("s2", 0755)
	if err != nil {
		t.Fatal(err)
	}

	// Three files on s1

	err = ioutil.WriteFile("s1/file1", []byte("hello\n"), 0644)
	if err != nil {
		t.Fatal(err)
	}
	err = ioutil.WriteFile("s1/file2", []byte("hello\n"), 0644)
	if err != nil {
		t.Fatal(err)
	}
	err = ioutil.WriteFile("s2/file3", []byte("hello\n"), 0644)
	if err != nil {
		t.Fatal(err)
	}

	// Let them sync

	sender := startInstance(t, 1)
	defer checkedStop(t, sender)
	receiver := startInstance(t, 2)
	defer checkedStop(t, receiver)

	sender.ResumeAll()
	receiver.ResumeAll()

	log.Println("Syncing...")

	rc.AwaitSync("default", sender, receiver)

	log.Println("Verifying...")

	// s1 should have three files

	files, err := filepath.Glob("s1/file*")
	if err != nil {
		t.Fatal(err)
	}
	if len(files) != 3 {
		t.Errorf("Expected 3 files in s1 instead of %d", len(files))
	}

	// s2 should have three

	files, err = filepath.Glob("s2/file*")
	if err != nil {
		t.Fatal(err)
	}
	if len(files) != 3 {
		t.Errorf("Expected 3 files in s2 instead of %d", len(files))
	}

	log.Println("Updating...")

	// change s2/file2 a few times, so that its version counter increases.
	// This will make the file on the cluster look newer than what we have
	// locally after we rest the index, unless we have a fix for that.

	for i := 0; i < 5; i++ {
		err = ioutil.WriteFile("s2/file2", []byte("hello1\n"), 0644)
		if err != nil {
			t.Fatal(err)
		}
		err = receiver.Rescan("default")
		if err != nil {
			t.Fatal(err)
		}
		time.Sleep(time.Second)
	}

	rc.AwaitSync("default", sender, receiver)

	// Now nuke the index

	log.Println("Resetting...")

	checkedStop(t, receiver)
	removeAll("h2/index*")

	// s1/file1 (remote) changes while receiver is down

	err = ioutil.WriteFile("s1/file1", []byte("goodbye\n"), 0644)
	if err != nil {
		t.Fatal(err)
	}

	// s1 must know about it
	err = sender.Rescan("default")
	if err != nil {
		t.Fatal(err)
	}

	// s2/file2 (local) changes while receiver is down

	err = ioutil.WriteFile("s2/file2", []byte("goodbye\n"), 0644)
	if err != nil {
		t.Fatal(err)
	}

	receiver = startInstance(t, 2)
	defer checkedStop(t, receiver)
	receiver.ResumeAll()

	log.Println("Syncing...")

	rc.AwaitSync("default", sender, receiver)

	// s2 should have five files (three plus two conflicts)

	files, err = filepath.Glob("s2/file*")
	if err != nil {
		t.Fatal(err)
	}
	if len(files) != 5 {
		t.Errorf("Expected 5 files in s2 instead of %d", len(files))
	}

	// file1 is in conflict, so there's two versions of that one

	files, err = filepath.Glob("s2/file1*")
	if err != nil {
		t.Fatal(err)
	}
	if len(files) != 2 {
		t.Errorf("Expected 2 'file1' files in s2 instead of %d", len(files))
	}

	// file2 is in conflict, so there's two versions of that one

	files, err = filepath.Glob("s2/file2*")
	if err != nil {
		t.Fatal(err)
	}
	if len(files) != 2 {
		t.Errorf("Expected 2 'file2' files in s2 instead of %d", len(files))
	}
}
<|endoftext|>


<commit_before>package kite

import (
	"fmt"
	"testing"
	"time"
)

// Test 2 way communication between kites.
func TestKite(t *testing.T) {
	mathKite := mathWorker()
	mathKite.Start()

	exp2Kite := exp2()
	exp2Kite.Start()

	fooChan := make(chan string)
	handleFoo := func(r *Request) (interface{}, error) {
		s := r.Args.One().MustString()
		fmt.Printf("Message received: %s\n", s)
		fooChan <- s
		return nil, nil
	}

	exp2Kite.HandleFunc("foo", handleFoo)

	// Use the kodingKey auth type since they are on same host.
	auth := Authentication{
		Type: "kodingKey",
		Key:  exp2Kite.KodingKey,
	}
	remote := exp2Kite.NewRemoteKite(mathKite.Kite, auth)

	err := remote.Dial()
	if err != nil {
		t.Errorf(err.Error())
		return
	}

	result, err := remote.Tell("square", 2)
	if err != nil {
		t.Errorf(err.Error())
		return
	}

	number := result.MustFloat64()

	fmt.Printf("rpc result: %f\n", number)

	if number != 4 {
		t.Errorf("Invalid result: %d", number)
	}

	select {
	case s := <-fooChan:
		if s != "bar" {
			t.Errorf("Invalid message: %s", s)
			return
		}
	case <-time.After(100 * time.Millisecond):
		t.Errorf("Did not get the message")
		return
	}

	resultChan := make(chan float64, 1)
	resultCallback := func(r *Request) {
		fmt.Printf("Request: %#v\n", r)
		n := r.Args.One().MustFloat64()
		resultChan <- n
	}

	result, err = remote.Tell("square2", 3, Callback(resultCallback))
	if err != nil {
		t.Errorf(err.Error())
	}

	select {
	case n := <-resultChan:
		if n != 9.0 {
			t.Errorf("Unexpected result: %f", n)
			return
		}
	case <-time.After(100 * time.Millisecond):
		t.Errorf("Did not get the message")
		return
	}
}

func exp2() *Kite {
	options := &Options{
		Kitename:    "exp2",
		Version:     "0.0.1",
		Port:        "3637",
		Region:      "localhost",
		Environment: "development",
	}

	k := New(options)
	k.KontrolEnabled = false
	return k
}

func mathWorker() *Kite {
	options := &Options{
		Kitename:    "mathworker",
		Version:     "0.0.1",
		Port:        "3636",
		Region:      "localhost",
		Environment: "development",
	}

	k := New(options)
	k.KontrolEnabled = false
	k.HandleFunc("square", Square)
	k.HandleFunc("square2", Square2)
	return k
}

// Returns the result. Also tests reverse call.
func Square(r *Request) (interface{}, error) {
	a := r.Args[0].MustFloat64()
	result := a * a

	fmt.Printf("Kite call, sending result '%f' back\n", result)

	// Reverse method call
	r.RemoteKite.Go("foo", "bar")

	return result, nil
}

// Calls the callback with the result. For testing requests from Callback.
func Square2(r *Request) (interface{}, error) {
	args := r.Args.MustSliceOfLength(2)
	a := args[0].MustFloat64()
	cb := args[1].MustFunction()

	result := a * a

	fmt.Printf("Kite call, sending result '%f' back\n", result)

	// Send the result.
	err := cb(result)
	if err != nil {
		return nil, err
	}

	return nil, nil
}
<commit_msg>kite/test: just a small formatting fix<commit_after>package kite

import (
	"fmt"
	"testing"
	"time"
)

// Test 2 way communication between kites.
func TestKite(t *testing.T) {
	mathKite := mathWorker()
	mathKite.Start()

	exp2Kite := exp2()
	exp2Kite.Start()

	fooChan := make(chan string)
	handleFoo := func(r *Request) (interface{}, error) {
		s := r.Args.One().MustString()
		fmt.Printf("Message received: %s\n", s)
		fooChan <- s
		return nil, nil
	}

	exp2Kite.HandleFunc("foo", handleFoo)

	// Use the kodingKey auth type since they are on same host.
	auth := Authentication{
		Type: "kodingKey",
		Key:  exp2Kite.KodingKey,
	}
	remote := exp2Kite.NewRemoteKite(mathKite.Kite, auth)

	err := remote.Dial()
	if err != nil {
		t.Errorf(err.Error())
		return
	}

	result, err := remote.Tell("square", 2)
	if err != nil {
		t.Errorf(err.Error())
		return
	}

	number := result.MustFloat64()

	fmt.Printf("rpc result: %f\n", number)

	if number != 4 {
		t.Errorf("Invalid result: %f", number)
	}

	select {
	case s := <-fooChan:
		if s != "bar" {
			t.Errorf("Invalid message: %s", s)
			return
		}
	case <-time.After(100 * time.Millisecond):
		t.Errorf("Did not get the message")
		return
	}

	resultChan := make(chan float64, 1)
	resultCallback := func(r *Request) {
		fmt.Printf("Request: %#v\n", r)
		n := r.Args.One().MustFloat64()
		resultChan <- n
	}

	result, err = remote.Tell("square2", 3, Callback(resultCallback))
	if err != nil {
		t.Errorf(err.Error())
	}

	select {
	case n := <-resultChan:
		if n != 9.0 {
			t.Errorf("Unexpected result: %f", n)
			return
		}
	case <-time.After(100 * time.Millisecond):
		t.Errorf("Did not get the message")
		return
	}
}

func exp2() *Kite {
	options := &Options{
		Kitename:    "exp2",
		Version:     "0.0.1",
		Port:        "3637",
		Region:      "localhost",
		Environment: "development",
	}

	k := New(options)
	k.KontrolEnabled = false
	return k
}

func mathWorker() *Kite {
	options := &Options{
		Kitename:    "mathworker",
		Version:     "0.0.1",
		Port:        "3636",
		Region:      "localhost",
		Environment: "development",
	}

	k := New(options)
	k.KontrolEnabled = false
	k.HandleFunc("square", Square)
	k.HandleFunc("square2", Square2)
	return k
}

// Returns the result. Also tests reverse call.
func Square(r *Request) (interface{}, error) {
	a := r.Args[0].MustFloat64()
	result := a * a

	fmt.Printf("Kite call, sending result '%f' back\n", result)

	// Reverse method call
	r.RemoteKite.Go("foo", "bar")

	return result, nil
}

// Calls the callback with the result. For testing requests from Callback.
func Square2(r *Request) (interface{}, error) {
	args := r.Args.MustSliceOfLength(2)
	a := args[0].MustFloat64()
	cb := args[1].MustFunction()

	result := a * a

	fmt.Printf("Kite call, sending result '%f' back\n", result)

	// Send the result.
	err := cb(result)
	if err != nil {
		return nil, err
	}

	return nil, nil
}
<|endoftext|>