<commit_before>package action

import (
	bosherr "github.com/cloudfoundry/bosh-utils/errors"

	bslcvm "github.com/maximilien/bosh-softlayer-cpi/softlayer/vm"
)

type ConfigureNetworks struct {
	vmFinder bslcvm.Finder
}

func NewConfigureNetworks(vmFinder bslcvm.Finder) ConfigureNetworks {
	return ConfigureNetworks{
		vmFinder: vmFinder,
	}
}

func (a ConfigureNetworks) Run(vmCID VMCID, networks bslcvm.Networks) (interface{}, error) {
	vm, found, err := a.vmFinder.Find(int(vmCID))
	if err != nil {
		return nil, bosherr.WrapErrorf(err, "Finding vm '%s'", vmCID)
	}

	if found {
		networksSpec := Networks{}
		for netName, network := range networks {
			networksSpec[netName] = Network{
				Type: network.Type,

				IP:      network.IP,
				Netmask: network.Netmask,
				Gateway: network.Gateway,

				DNS:           network.DNS,
				Default:       network.Default,
				Preconfigured: true,

				MAC: "",

				CloudProperties: network.CloudProperties,
			}
		}

		err := vm.ConfigureNetworks(networks)
		if err != nil {
			return nil, bosherr.WrapErrorf(err, "Configuring networks vm '%s'", vmCID)
		}
	}

	return nil, nil
}
<commit_msg>Fixed configure_network issue<commit_after>package action

import (
	bosherr "github.com/cloudfoundry/bosh-utils/errors"

	bslcvm "github.com/maximilien/bosh-softlayer-cpi/softlayer/vm"
)

type ConfigureNetworks struct {
	vmFinder bslcvm.Finder
}

func NewConfigureNetworks(vmFinder bslcvm.Finder) ConfigureNetworks {
	return ConfigureNetworks{
		vmFinder: vmFinder,
	}
}

func (a ConfigureNetworks) Run(vmCID VMCID, networks bslcvm.Networks) (interface{}, error) {
	vm, found, err := a.vmFinder.Find(int(vmCID))
	if err != nil {
		return nil, bosherr.WrapErrorf(err, "Finding vm '%s'", vmCID)
	}

	if found {
		networksSpec := Networks{}
		for netName, network := range networks {
			networksSpec[netName] = Network{
				Type: network.Type,

				IP:      network.IP,
				Netmask: network.Netmask,
				Gateway: network.Gateway,

				DNS:           network.DNS,
				Default:       network.Default,
				Preconfigured: true,

				MAC: "",

				CloudProperties: network.CloudProperties,
			}
		}

		err := vm.ConfigureNetworks(networksSpec)
		if err != nil {
			return nil, bosherr.WrapErrorf(err, "Configuring networks vm '%s'", vmCID)
		}
	}

	return nil, nil
}
<|endoftext|>


<commit_before>package resource_test

import (
	"context"
	"errors"
	"github.com/concourse/concourse/atc"
	"github.com/concourse/concourse/atc/resource"
	"github.com/concourse/concourse/atc/runtime"
	"github.com/concourse/concourse/atc/runtime/runtimefakes"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
)

var _ = Describe("Resource Get", func() {
	var (
		ctx    context.Context
		someProcessSpec runtime.ProcessSpec
		fakeRunnable runtimefakes.FakeRunner

		getVersionResult runtime.VersionResult

		source  atc.Source
		params  atc.Params
		version atc.Version

		resource resource.Resource

		getErr error
	)

	BeforeEach(func() {
		ctx = context.Background()

		source = atc.Source{"some": "source"}
		version = atc.Version{"some": "version"}
		params = atc.Params{"some": "params"}

		someProcessSpec.Path = "some/fake/path"
		someProcessSpec.Args = []string{"first-arg", "some-other-arg"}
		someProcessSpec.StderrWriter = gbytes.NewBuffer()

		resource = resourceFactory.NewResource(source, params, version)

	})

	JustBeforeEach(func() {
		getVersionResult, getErr = resource.Get(ctx, someProcessSpec, &fakeRunnable)
	})

	Context("when Runnable -> RunScript succeeds", func() {
		BeforeEach(func(){
			fakeRunnable.RunScriptReturns(nil)
		})

		It("Invokes Runnable -> RunScript with the correct arguments", func(){
			actualCtx, actualSpecPath, actualSpecArgs,
				actualInputArgs, actualVersionResultRef, actualSpecStdErrWriter,
				actualRecoverableBool :=  fakeRunnable.RunScriptArgsForCall(0)

				signature, err := resource.Signature()
				Expect(err).ToNot(HaveOccurred())

				Expect(actualCtx).To(Equal(ctx))
				Expect(actualSpecPath).To(Equal(someProcessSpec.Path))
				Expect(actualSpecArgs).To(Equal(someProcessSpec.Args))
				Expect(actualInputArgs).To(Equal(signature))
				Expect(actualVersionResultRef).To(Equal(&getVersionResult))
				Expect(actualSpecStdErrWriter).To(Equal(someProcessSpec.StderrWriter))
				Expect(actualRecoverableBool).To(BeTrue())
		})

		It("doesnt return an error", func(){
			Expect(getErr).To(BeNil())
		})
	})

	Context("when Runnable -> RunScript returns an error", func() {
		var disasterErr = errors.New("there was an issue")
		BeforeEach(func(){
			fakeRunnable.RunScriptReturns(disasterErr)
		})
		It("returns the error", func() {
			Expect(getErr).To(Equal(disasterErr))
		})
	})

})
<commit_msg>fmt resource_get_test<commit_after>package resource_test

import (
	"context"
	"errors"

	"github.com/concourse/concourse/atc"
	"github.com/concourse/concourse/atc/resource"
	"github.com/concourse/concourse/atc/runtime"
	"github.com/concourse/concourse/atc/runtime/runtimefakes"

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

var _ = Describe("Resource Get", func() {
	var (
		ctx             context.Context
		someProcessSpec runtime.ProcessSpec
		fakeRunnable    runtimefakes.FakeRunner

		getVersionResult runtime.VersionResult

		source  atc.Source
		params  atc.Params
		version atc.Version

		resource resource.Resource

		getErr error
	)

	BeforeEach(func() {
		ctx = context.Background()

		source = atc.Source{"some": "source"}
		version = atc.Version{"some": "version"}
		params = atc.Params{"some": "params"}

		someProcessSpec.Path = "some/fake/path"
		someProcessSpec.Args = []string{"first-arg", "some-other-arg"}
		someProcessSpec.StderrWriter = gbytes.NewBuffer()

		resource = resourceFactory.NewResource(source, params, version)

	})

	JustBeforeEach(func() {
		getVersionResult, getErr = resource.Get(ctx, someProcessSpec, &fakeRunnable)
	})

	Context("when Runnable -> RunScript succeeds", func() {
		BeforeEach(func() {
			fakeRunnable.RunScriptReturns(nil)
		})

		It("Invokes Runnable -> RunScript with the correct arguments", func() {
			actualCtx, actualSpecPath, actualSpecArgs,
				actualInputArgs, actualVersionResultRef, actualSpecStdErrWriter,
				actualRecoverableBool := fakeRunnable.RunScriptArgsForCall(0)

			signature, err := resource.Signature()
			Expect(err).ToNot(HaveOccurred())

			Expect(actualCtx).To(Equal(ctx))
			Expect(actualSpecPath).To(Equal(someProcessSpec.Path))
			Expect(actualSpecArgs).To(Equal(someProcessSpec.Args))
			Expect(actualInputArgs).To(Equal(signature))
			Expect(actualVersionResultRef).To(Equal(&getVersionResult))
			Expect(actualSpecStdErrWriter).To(Equal(someProcessSpec.StderrWriter))
			Expect(actualRecoverableBool).To(BeTrue())
		})

		It("doesnt return an error", func() {
			Expect(getErr).To(BeNil())
		})
	})

	Context("when Runnable -> RunScript returns an error", func() {
		var disasterErr = errors.New("there was an issue")
		BeforeEach(func() {
			fakeRunnable.RunScriptReturns(disasterErr)
		})
		It("returns the error", func() {
			Expect(getErr).To(Equal(disasterErr))
		})
	})

})
<|endoftext|>


<commit_before>package in

import (
	"fmt"
	"time"

	"github.com/grafana/grafana/pkg/log"
	"github.com/raintank/met"
	"github.com/raintank/raintank-metric/metric_tank/defcache"
	"github.com/raintank/raintank-metric/metric_tank/mdata"
	"github.com/raintank/raintank-metric/metric_tank/usage"
	"github.com/raintank/raintank-metric/msg"
	"github.com/raintank/raintank-metric/schema"
)

type In struct {
	metricsPerMessage met.Meter
	metricsReceived   met.Count
	msgsAge           met.Meter // in ms
	tmp               msg.MetricData

	metrics  mdata.Metrics
	defCache *defcache.DefCache
	usage    *usage.Usage
}

func New(metrics mdata.Metrics, defCache *defcache.DefCache, usage *usage.Usage, input string, stats met.Backend) In {
	return In{
		metricsPerMessage: stats.NewMeter(fmt.Sprintf("%s.metrics_per_message", input), 0),
		metricsReceived:   stats.NewCount(fmt.Sprintf("%s.metrics_received", input)),
		msgsAge:           stats.NewMeter(fmt.Sprintf("%s.message_age", input), 0),
		tmp:               msg.MetricData{Metrics: make([]*schema.MetricData, 1)},

		metrics:  metrics,
		defCache: defCache,
		usage:    usage,
	}
}

func (in In) Handle(data []byte) {
	err := in.tmp.InitFromMsg(data)
	if err != nil {
		log.Error(3, "skipping message. %s", err)
		return
	}
	in.msgsAge.Value(time.Now().Sub(in.tmp.Produced).Nanoseconds() / 1000)

	err = in.tmp.DecodeMetricData() // reads metrics from in.tmp.Msg and unsets it
	if err != nil {
		log.Error(3, "skipping message. %s", err)
		return
	}
	in.metricsPerMessage.Value(int64(len(in.tmp.Metrics)))
	in.metricsReceived.Inc(int64(len(in.tmp.Metrics)))

	for _, metric := range in.tmp.Metrics {
		if metric == nil {
			continue
		}
		if metric.Id == "" {
			log.Error(3, "empty metric.Id - fix your datastream")
			continue
		}
		if metric.Time == 0 {
			log.Warn("invalid metric. metric.Time is 0. %s", metric.Id)
		} else {
			in.defCache.Add(metric)
			m := in.metrics.GetOrCreate(metric.Id)
			m.Add(uint32(metric.Time), metric.Value)
			if in.usage != nil {
				in.usage.Add(metric.OrgId, metric.Id)
			}
		}
	}
}
<commit_msg>clarify<commit_after>package in

import (
	"fmt"
	"time"

	"github.com/grafana/grafana/pkg/log"
	"github.com/raintank/met"
	"github.com/raintank/raintank-metric/metric_tank/defcache"
	"github.com/raintank/raintank-metric/metric_tank/mdata"
	"github.com/raintank/raintank-metric/metric_tank/usage"
	"github.com/raintank/raintank-metric/msg"
	"github.com/raintank/raintank-metric/schema"
)

// In is a base handler for a metrics packet, aimed to be embedded by concrete implementations
type In struct {
	metricsPerMessage met.Meter
	metricsReceived   met.Count
	msgsAge           met.Meter // in ms
	tmp               msg.MetricData

	metrics  mdata.Metrics
	defCache *defcache.DefCache
	usage    *usage.Usage
}

func New(metrics mdata.Metrics, defCache *defcache.DefCache, usage *usage.Usage, input string, stats met.Backend) In {
	return In{
		metricsPerMessage: stats.NewMeter(fmt.Sprintf("%s.metrics_per_message", input), 0),
		metricsReceived:   stats.NewCount(fmt.Sprintf("%s.metrics_received", input)),
		msgsAge:           stats.NewMeter(fmt.Sprintf("%s.message_age", input), 0),
		tmp:               msg.MetricData{Metrics: make([]*schema.MetricData, 1)},

		metrics:  metrics,
		defCache: defCache,
		usage:    usage,
	}
}

func (in In) Handle(data []byte) {
	err := in.tmp.InitFromMsg(data)
	if err != nil {
		log.Error(3, "skipping message. %s", err)
		return
	}
	in.msgsAge.Value(time.Now().Sub(in.tmp.Produced).Nanoseconds() / 1000)

	err = in.tmp.DecodeMetricData() // reads metrics from in.tmp.Msg and unsets it
	if err != nil {
		log.Error(3, "skipping message. %s", err)
		return
	}
	in.metricsPerMessage.Value(int64(len(in.tmp.Metrics)))
	in.metricsReceived.Inc(int64(len(in.tmp.Metrics)))

	for _, metric := range in.tmp.Metrics {
		if metric == nil {
			continue
		}
		if metric.Id == "" {
			log.Error(3, "empty metric.Id - fix your datastream")
			continue
		}
		if metric.Time == 0 {
			log.Warn("invalid metric. metric.Time is 0. %s", metric.Id)
		} else {
			in.defCache.Add(metric)
			m := in.metrics.GetOrCreate(metric.Id)
			m.Add(uint32(metric.Time), metric.Value)
			if in.usage != nil {
				in.usage.Add(metric.OrgId, metric.Id)
			}
		}
	}
}
<|endoftext|>


<commit_before>package middleware

import (
	"github.com/andviro/noodle"
	"golang.org/x/net/context"
	"log"
	"net/http"
	"sync"
	"time"
)

var writers sync.Pool

// logWriter mimics http.ResponseWriter functionality while storing
// HTTP status code for later logging
type logWriter struct {
	code          int
	headerWritten bool
	http.ResponseWriter
}

func (l *logWriter) WriteHeader(code int) {
	l.ResponseWriter.WriteHeader(code)
	if !l.headerWritten {
		l.code = code
		l.headerWritten = true
	}
}

func (l *logWriter) Write(buf []byte) (int, error) {
	l.headerWritten = true
	return l.ResponseWriter.Write(buf)
}

func (l *logWriter) Code() int {
	if l.code == 0 {
		return 200
	}
	return l.code
}

func init() {
	writers.New = func() interface{} {
		return &logWriter{}
	}
}

// Logger is a middleware that logs requests, along with
// request URI, HTTP status code, handler return value and request timing
func Logger(next noodle.Handler) noodle.Handler {
	return func(c context.Context, w http.ResponseWriter, r *http.Request) (err error) {
		lw := writers.Get().(*logWriter)
		lw.ResponseWriter = w
		lw.code = 0
		lw.headerWritten = false
		defer writers.Put(lw)

		start := time.Now()
		err = next(c, lw, r)
		end := time.Now()
		log.Printf("%s %s (%d) from %s [%s] error = %v", r.Method, r.URL.String(), lw.Code(), r.RemoteAddr, end.Sub(start), err)
		return
	}
}
<commit_msg>minor precaution<commit_after>package middleware

import (
	"github.com/andviro/noodle"
	"golang.org/x/net/context"
	"log"
	"net/http"
	"sync"
	"time"
)

var writers sync.Pool

// logWriter mimics http.ResponseWriter functionality while storing
// HTTP status code for later logging
type logWriter struct {
	code          int
	headerWritten bool
	http.ResponseWriter
}

func (l *logWriter) WriteHeader(code int) {
	l.ResponseWriter.WriteHeader(code)
	if !l.headerWritten {
		l.code = code
		l.headerWritten = true
	}
}

func (l *logWriter) Write(buf []byte) (int, error) {
	l.headerWritten = true
	return l.ResponseWriter.Write(buf)
}

func (l *logWriter) Code() int {
	if l.code == 0 {
		return 200
	}
	return l.code
}

func init() {
	writers.New = func() interface{} {
		return &logWriter{}
	}
}

// Logger is a middleware that logs requests, along with
// request URI, HTTP status code, handler return value and request timing
func Logger(next noodle.Handler) noodle.Handler {
	return func(c context.Context, w http.ResponseWriter, r *http.Request) (err error) {
		lw := writers.Get().(*logWriter)
		lw.ResponseWriter = w
		lw.code = 0
		lw.headerWritten = false
		defer writers.Put(lw)

		url := r.URL.String() // further calls may modify request URL
		start := time.Now()
		err = next(c, lw, r)
		end := time.Now()
		log.Printf("%s %s (%d) from %s [%s] error = %v", r.Method, url, lw.Code(), r.RemoteAddr, end.Sub(start), err)
		return
	}
}
<|endoftext|>


<commit_before>package grpcHandlers

import (
	"reflect"
	"testing"
	"time"

	"github.com/golang/protobuf/proto"
	"golang.org/x/net/context"
	"google.golang.org/grpc"

	"github.com/seadsystem/Backend/DB/landingzone/constants"
	"github.com/seadsystem/Backend/DB/landingzone/database"
	"github.com/seadsystem/Backend/DB/landingzone/decoders/grpcDecoders"

	sqlmock "github.com/DATA-DOG/go-sqlmock"
	pb "github.com/seadsystem/Backend/DB/landingzone/proto/packet"
)

func TestHandle(t *testing.T) {
	ctx := context.Background()

	db, mock, err := database.NewMock()
	if err != nil {
		t.Fatalf("Creating mock DB: %v", err)
	}

	mock.ExpectBegin()
	query := "COPY \\\"data_raw\\\" \\(\\\"serial\\\", \\\"type\\\", \\\"data\\\", \\\"time\\\", \\\"device\\\"\\) FROM STDIN"
	stmt := mock.ExpectPrepare(query)
	stmt.ExpectExec().WithArgs(64, "T", 0, time.Unix(500, 0), "fooo").WillReturnResult(sqlmock.NewResult(0, 1))
	stmt.ExpectExec().WithArgs(64, "T", 1, time.Unix(501, 0), "fooo").WillReturnResult(sqlmock.NewResult(0, 1))
	stmt.ExpectExec().WithArgs(64, "T", 2, time.Unix(502, 0), "fooo").WillReturnResult(sqlmock.NewResult(0, 1))
	stmt.ExpectExec().WillReturnResult(sqlmock.NewResult(0, 0))
	mock.ExpectCommit()

	in := &pb.Packet{
		Serial: 64,
		Time:   &pb.Timestamp{Seconds: 500},
		Delta:  int64(time.Second),
		Type:   "T",
		Device: "fooo",
		Data:   []int64{0, 1, 2},
	}
	wantStatus := &pb.Status{Success: true}

	s := &server{db}
	if status, err := s.SendPacket(ctx, in); err != nil || !proto.Equal(status, wantStatus) {
		t.Errorf(
			"got s.SendPacket(ctx, %s) = %s, %v, want = %s, %v",
			proto.MarshalTextString(in),
			proto.MarshalTextString(status),
			err,
			proto.MarshalTextString(wantStatus),
			nil,
		)
	}

	if err := mock.ExpectationsWereMet(); err != nil {
		t.Error("mock expectations were not met")
	}
}

func TestHandleError(t *testing.T) {
	ctx := context.Background()

	tests := []struct {
		name   string
		in     *pb.Packet
		status *pb.Status
		err    error
	}{
		{"nil packet", nil, &pb.Status{Success: false, Msg: grpcDecoders.NillPacket.Error()}, nil},
		{"nil Time", &pb.Packet{}, &pb.Status{Success: false, Msg: grpcDecoders.NillPacket.Error()}, nil},
		{"too short type", &pb.Packet{Time: &pb.Timestamp{}}, &pb.Status{Success: false, Msg: grpcDecoders.InvalidType.Error()}, nil},
		{"too long type", &pb.Packet{Type: "fo", Time: &pb.Timestamp{}}, &pb.Status{Success: false, Msg: grpcDecoders.InvalidType.Error()}, nil},
		{"?", &pb.Packet{Type: "T", Time: &pb.Timestamp{}}, &pb.Status{Success: false, Msg: "call to database transaction Begin, was not expected, next expectation is: ExpectedClose => expecting database Close"}, nil},
	}
	for _, test := range tests {
		db, mock, err := database.NewMock()
		if err != nil {
			t.Fatalf("Creating mock DB: %v", err)
		}
		mock.ExpectClose()

		s := &server{db}
		if status, err := s.SendPacket(ctx, test.in); !reflect.DeepEqual(err, test.err) || !proto.Equal(status, test.status) {
			t.Errorf(
				"%s: got SendPacket(ctx, %s) = %s, %v, want = %s, %v",
				test.name,
				proto.MarshalTextString(test.in),
				proto.MarshalTextString(status),
				err,
				proto.MarshalTextString(test.status),
				test.err,
			)
		}

		if err := db.Close(); err != nil {
			t.Errorf("%s: got db.Close() = %v, want = nil", test.name, err)
		}
	}
}

func TestRegister(t *testing.T) {
	db, mock, err := database.NewMock()
	if err != nil {
		t.Fatalf("Creating mock DB: %v", err)
	}
	mock.ExpectClose()

	s := grpc.NewServer()
	Register(s, db)

	s.Stop()

	if err := db.Close(); err != nil {
		t.Fatalf("got db.Close() = %v, want = nil", err)
	}
}

func TestHandleVerbose(t *testing.T) {
	oldVerbosity := constants.Verbose
	constants.Verbose = true
	defer func() { constants.Verbose = oldVerbosity }()

	t.Log("TestHandle")
	TestHandle(t)

	t.Log("TestHandleError")
	TestHandleError(t)

	t.Log("TestRegister")
	TestRegister(t)
}
<commit_msg>Filled in test case name<commit_after>package grpcHandlers

import (
	"reflect"
	"testing"
	"time"

	"github.com/golang/protobuf/proto"
	"golang.org/x/net/context"
	"google.golang.org/grpc"

	"github.com/seadsystem/Backend/DB/landingzone/constants"
	"github.com/seadsystem/Backend/DB/landingzone/database"
	"github.com/seadsystem/Backend/DB/landingzone/decoders/grpcDecoders"

	sqlmock "github.com/DATA-DOG/go-sqlmock"
	pb "github.com/seadsystem/Backend/DB/landingzone/proto/packet"
)

func TestHandle(t *testing.T) {
	ctx := context.Background()

	db, mock, err := database.NewMock()
	if err != nil {
		t.Fatalf("Creating mock DB: %v", err)
	}

	mock.ExpectBegin()
	query := "COPY \\\"data_raw\\\" \\(\\\"serial\\\", \\\"type\\\", \\\"data\\\", \\\"time\\\", \\\"device\\\"\\) FROM STDIN"
	stmt := mock.ExpectPrepare(query)
	stmt.ExpectExec().WithArgs(64, "T", 0, time.Unix(500, 0), "fooo").WillReturnResult(sqlmock.NewResult(0, 1))
	stmt.ExpectExec().WithArgs(64, "T", 1, time.Unix(501, 0), "fooo").WillReturnResult(sqlmock.NewResult(0, 1))
	stmt.ExpectExec().WithArgs(64, "T", 2, time.Unix(502, 0), "fooo").WillReturnResult(sqlmock.NewResult(0, 1))
	stmt.ExpectExec().WillReturnResult(sqlmock.NewResult(0, 0))
	mock.ExpectCommit()

	in := &pb.Packet{
		Serial: 64,
		Time:   &pb.Timestamp{Seconds: 500},
		Delta:  int64(time.Second),
		Type:   "T",
		Device: "fooo",
		Data:   []int64{0, 1, 2},
	}
	wantStatus := &pb.Status{Success: true}

	s := &server{db}
	if status, err := s.SendPacket(ctx, in); err != nil || !proto.Equal(status, wantStatus) {
		t.Errorf(
			"got s.SendPacket(ctx, %s) = %s, %v, want = %s, %v",
			proto.MarshalTextString(in),
			proto.MarshalTextString(status),
			err,
			proto.MarshalTextString(wantStatus),
			nil,
		)
	}

	if err := mock.ExpectationsWereMet(); err != nil {
		t.Error("mock expectations were not met")
	}
}

func TestHandleError(t *testing.T) {
	ctx := context.Background()

	tests := []struct {
		name   string
		in     *pb.Packet
		status *pb.Status
		err    error
	}{
		{"nil packet", nil, &pb.Status{Success: false, Msg: grpcDecoders.NillPacket.Error()}, nil},
		{"nil Time", &pb.Packet{}, &pb.Status{Success: false, Msg: grpcDecoders.NillPacket.Error()}, nil},
		{"too short type", &pb.Packet{Time: &pb.Timestamp{}}, &pb.Status{Success: false, Msg: grpcDecoders.InvalidType.Error()}, nil},
		{"too long type", &pb.Packet{Type: "fo", Time: &pb.Timestamp{}}, &pb.Status{Success: false, Msg: grpcDecoders.InvalidType.Error()}, nil},
		{"valid packet", &pb.Packet{Type: "T", Time: &pb.Timestamp{}}, &pb.Status{Success: false, Msg: "call to database transaction Begin, was not expected, next expectation is: ExpectedClose => expecting database Close"}, nil},
	}
	for _, test := range tests {
		db, mock, err := database.NewMock()
		if err != nil {
			t.Fatalf("Creating mock DB: %v", err)
		}
		mock.ExpectClose()

		s := &server{db}
		if status, err := s.SendPacket(ctx, test.in); !reflect.DeepEqual(err, test.err) || !proto.Equal(status, test.status) {
			t.Errorf(
				"%s: got SendPacket(ctx, %s) = %s, %v, want = %s, %v",
				test.name,
				proto.MarshalTextString(test.in),
				proto.MarshalTextString(status),
				err,
				proto.MarshalTextString(test.status),
				test.err,
			)
		}

		if err := db.Close(); err != nil {
			t.Errorf("%s: got db.Close() = %v, want = nil", test.name, err)
		}
	}
}

func TestRegister(t *testing.T) {
	db, mock, err := database.NewMock()
	if err != nil {
		t.Fatalf("Creating mock DB: %v", err)
	}
	mock.ExpectClose()

	s := grpc.NewServer()
	Register(s, db)

	s.Stop()

	if err := db.Close(); err != nil {
		t.Fatalf("got db.Close() = %v, want = nil", err)
	}
}

func TestHandleVerbose(t *testing.T) {
	oldVerbosity := constants.Verbose
	constants.Verbose = true
	defer func() { constants.Verbose = oldVerbosity }()

	t.Log("TestHandle")
	TestHandle(t)

	t.Log("TestHandleError")
	TestHandleError(t)

	t.Log("TestRegister")
	TestRegister(t)
}
<|endoftext|>


<commit_before>package singleflightcache

import (
	"errors"
	"sync"
	"sync/atomic"
	"testing"
)

const (
	key1 = "key1"
	key2 = "key2"
	val1 = "val1"
	val2 = "val2"
	key3 = "key3"
	val3 = "val3"
)

func TestSimpleValueStore(t *testing.T) {
	c := &Cache{}
	val, err := c.LoadOrStore(key1, func() (interface{}, error) { return val1, nil })
	if err != nil {
		t.Errorf("LoadOrStore(%v) failed: %v", key1, err)
	}
	if val != val1 {
		t.Errorf("LoadOrStore(%v) loaded wrong value: got %v, want %v", key1, val, val1)
	}

	val, err = c.LoadOrStore(key2, func() (interface{}, error) { return val2, nil })
	if err != nil {
		t.Errorf("LoadOrStore(%v) failed: %v", key2, err)
	}
	if val != val2 {
		t.Errorf("LoadOrStore(%v) loaded wrong value: got %v, want %v", key2, val, val2)
	}
}

func TestSingleFlightStore(t *testing.T) {
	c := &Cache{}
	var ops uint64
	loadFn := func() (interface{}, error) {
		atomic.AddUint64(&ops, 1)
		return val1, nil
	}
	wg := &sync.WaitGroup{}
	load := func() {
		val, err := c.LoadOrStore(key1, loadFn)
		if err != nil {
			t.Errorf("LoadOrStore(%v) failed: %v", key1, err)
		}
		if val != val1 {
			t.Errorf("LoadOrStore(%v) loaded wrong value: got %v, want %v", key1, val, val1)
		}
		wg.Done()
	}
	wg.Add(50)
	for i := 0; i < 50; i++ {
		go load()
	}
	wg.Wait()

	if ops != 1 {
		t.Errorf("Wrong number of loads executed: got %v, want 1", ops)
	}
}

func TestValFnFailure(t *testing.T) {
	c := &Cache{}
	val, err := c.LoadOrStore(key1, func() (interface{}, error) { return nil, errors.New("error") })
	if err == nil {
		t.Errorf("LoadOrStore(%v) failed: %v", key1, err)
	}

	val, err = c.LoadOrStore(key1, func() (interface{}, error) { return val1, nil })
	if err != nil {
		t.Errorf("LoadOrStore(%v) failed: %v", key1, err)
	}
	if val != val1 {
		t.Errorf("LoadOrStore(%v) loaded wrong value: got %v, want %v", key1, val, val1)
	}
}

func TestValFnMultipleFailure(t *testing.T) {
	c := &Cache{}

	wg := &sync.WaitGroup{}
	want := errors.New("error")
	var ops uint64
	load := func() {
		_, got := c.LoadOrStore(key1, func() (interface{}, error) {
			atomic.AddUint64(&ops, 1)
			return nil, want
		})
		if want != got {
			t.Errorf("LoadOrStore(%v) = _,%v, want _,%v", key1, got, want)
		}
		wg.Done()
	}
	for i := 0; i < 50; i++ {
		wg.Add(1)
		go load()
	}
	wg.Wait()

	if ops != 50 {
		t.Errorf("Wrong number of loads executed: got %v, want 50", ops)
	}
}

func TestDelete(t *testing.T) {
	c := &Cache{}
	val, err := c.LoadOrStore(key1, func() (interface{}, error) { return val1, nil })
	if err != nil {
		t.Fatalf("LoadOrStore(%v) failed: %v", key1, err)
	}
	if val != val1 {
		t.Fatalf("LoadOrStore(%v) loaded wrong value: got %v, want %v", key1, val, val1)
	}

	c.Delete(key1)

	val, err = c.LoadOrStore(key1, func() (interface{}, error) { return val2, nil })
	if err != nil {
		t.Errorf("LoadOrStore(%v) failed: %v", key1, err)
	}
	if val != val2 {
		t.Errorf("LoadOrStore(%v) loaded wrong value: got %v, want %v", key1, val, val2)
	}
}

// This test launches several concurrent goroutines to load/store and delete keys from the map. The
// purpose of the test is to expose whether a race condition would result in an inconsistent state
// of the internal maps of the cache, which would result in an error reported by LoadOrStore.
func TestLoadDelete(t *testing.T) {
	c := &Cache{}
	wg := &sync.WaitGroup{}
	load := func() {
		val, err := c.LoadOrStore(key1, func() (interface{}, error) { return val1, nil })
		if err != nil {
			t.Errorf("LoadOrStore(%v) failed: %v", key1, err)
		}
		if val != val1 {
			t.Errorf("LoadOrStore(%v) loaded wrong value: got %v, want %v", key1, val, val1)
		}
		val, err = c.LoadOrStore(key2, func() (interface{}, error) { return val2, nil })
		if err != nil {
			t.Errorf("LoadOrStore(%v) failed: %v", key2, err)
		}
		if val != val2 {
			t.Errorf("LoadOrStore(%v) loaded wrong value: got %v, want %v", key2, val, val2)
		}
		wg.Done()
	}
	del := func() {
		c.Delete(key1)
		c.Delete(key2)
		wg.Done()
	}
	wg.Add(100)
	for i := 0; i < 50; i++ {
		go load()
		go del()
	}
	wg.Wait()
}

func TestStore(t *testing.T) {
	c := &Cache{}
	wg := &sync.WaitGroup{}
	load := func() {
		if err := c.Store(key3, val3); err != nil {
			t.Errorf("Store(%v) failed: %v", key3, err)
		}
		// LoadOrStore should load the already loaded value "val3" and shouldn't
		// overwrite "val1" to "key3".
		val, err := c.LoadOrStore(key3, func() (interface{}, error) { return val1, nil })
		if err != nil {
			t.Errorf("LoadOrStore(%v) failed: %v", key3, err)
		}
		if val != val3 {
			t.Errorf("LoadOrStore(%v) = %v, want %v", key3, val, val3)
		}
		wg.Done()
	}
	del := func() {
		c.Delete(key3)
		wg.Done()
	}
	wg.Add(100)
	for i := 0; i < 50; i++ {
		go load()
		go del()
	}
	wg.Wait()
}

func TestStoreOverwrite(t *testing.T) {
	c := &Cache{}

	val, err := c.LoadOrStore(key3, func() (interface{}, error) { return val1, nil })
	if err != nil {
		t.Errorf("LoadOrStore(%v) failed: %v", key3, err)
	}
	if val != val1 {
		t.Errorf("LoadOrStore(%v) = %v, want %v", key3, val, val1)
	}

	if err := c.Store(key3, val3); err != nil {
		t.Errorf("Store(%v) failed: %v", key3, err)
	}

	// LoadOrStore should load the already loaded value "val3" and shouldn't
	// overwrite "val1" to "key3".
	val, err = c.LoadOrStore(key3, func() (interface{}, error) { return val1, nil })
	if err != nil {
		t.Errorf("LoadOrStore(%v) failed: %v", key3, err)
	}
	if val != val3 {
		t.Errorf("LoadOrStore(%v) = %v, want %v", key3, val, val3)
	}
}
<commit_msg>Add a test for testing race conditions in LoadOrStore (#144)<commit_after>package singleflightcache

import (
	"errors"
	"sync"
	"sync/atomic"
	"testing"
)

const (
	key1 = "key1"
	key2 = "key2"
	val1 = "val1"
	val2 = "val2"
	key3 = "key3"
	val3 = "val3"
)

func TestSimpleValueStore(t *testing.T) {
	c := &Cache{}
	val, err := c.LoadOrStore(key1, func() (interface{}, error) { return val1, nil })
	if err != nil {
		t.Errorf("LoadOrStore(%v) failed: %v", key1, err)
	}
	if val != val1 {
		t.Errorf("LoadOrStore(%v) loaded wrong value: got %v, want %v", key1, val, val1)
	}

	val, err = c.LoadOrStore(key2, func() (interface{}, error) { return val2, nil })
	if err != nil {
		t.Errorf("LoadOrStore(%v) failed: %v", key2, err)
	}
	if val != val2 {
		t.Errorf("LoadOrStore(%v) loaded wrong value: got %v, want %v", key2, val, val2)
	}
}

func TestSingleFlightStore(t *testing.T) {
	c := &Cache{}
	var ops uint64
	loadFn := func() (interface{}, error) {
		atomic.AddUint64(&ops, 1)
		return val1, nil
	}
	wg := &sync.WaitGroup{}
	load := func() {
		val, err := c.LoadOrStore(key1, loadFn)
		if err != nil {
			t.Errorf("LoadOrStore(%v) failed: %v", key1, err)
		}
		if val != val1 {
			t.Errorf("LoadOrStore(%v) loaded wrong value: got %v, want %v", key1, val, val1)
		}
		wg.Done()
	}
	wg.Add(50)
	for i := 0; i < 50; i++ {
		go load()
	}
	wg.Wait()

	if ops != 1 {
		t.Errorf("Wrong number of loads executed: got %v, want 1", ops)
	}
}

func TestValFnFailure(t *testing.T) {
	c := &Cache{}
	val, err := c.LoadOrStore(key1, func() (interface{}, error) { return nil, errors.New("error") })
	if err == nil {
		t.Errorf("LoadOrStore(%v) failed: %v", key1, err)
	}

	val, err = c.LoadOrStore(key1, func() (interface{}, error) { return val1, nil })
	if err != nil {
		t.Errorf("LoadOrStore(%v) failed: %v", key1, err)
	}
	if val != val1 {
		t.Errorf("LoadOrStore(%v) loaded wrong value: got %v, want %v", key1, val, val1)
	}
}

func TestValFnMultipleFailure(t *testing.T) {
	c := &Cache{}

	wg := &sync.WaitGroup{}
	want := errors.New("error")
	var ops uint64
	load := func() {
		_, got := c.LoadOrStore(key1, func() (interface{}, error) {
			atomic.AddUint64(&ops, 1)
			return nil, want
		})
		if want != got {
			t.Errorf("LoadOrStore(%v) = _,%v, want _,%v", key1, got, want)
		}
		wg.Done()
	}
	for i := 0; i < 50; i++ {
		wg.Add(1)
		go load()
	}
	wg.Wait()

	if ops != 50 {
		t.Errorf("Wrong number of loads executed: got %v, want 50", ops)
	}
}

func TestDelete(t *testing.T) {
	c := &Cache{}
	val, err := c.LoadOrStore(key1, func() (interface{}, error) { return val1, nil })
	if err != nil {
		t.Fatalf("LoadOrStore(%v) failed: %v", key1, err)
	}
	if val != val1 {
		t.Fatalf("LoadOrStore(%v) loaded wrong value: got %v, want %v", key1, val, val1)
	}

	c.Delete(key1)

	val, err = c.LoadOrStore(key1, func() (interface{}, error) { return val2, nil })
	if err != nil {
		t.Errorf("LoadOrStore(%v) failed: %v", key1, err)
	}
	if val != val2 {
		t.Errorf("LoadOrStore(%v) loaded wrong value: got %v, want %v", key1, val, val2)
	}
}

// This test launches several concurrent goroutines to load/store and delete keys from the map. The
// purpose of the test is to expose whether a race condition would result in an inconsistent state
// of the internal maps of the cache, which would result in an error reported by LoadOrStore.
func TestLoadDelete(t *testing.T) {
	c := &Cache{}
	wg := &sync.WaitGroup{}
	load := func() {
		val, err := c.LoadOrStore(key1, func() (interface{}, error) { return val1, nil })
		if err != nil {
			t.Errorf("LoadOrStore(%v) failed: %v", key1, err)
		}
		if val != val1 {
			t.Errorf("LoadOrStore(%v) loaded wrong value: got %v, want %v", key1, val, val1)
		}
		val, err = c.LoadOrStore(key2, func() (interface{}, error) { return val2, nil })
		if err != nil {
			t.Errorf("LoadOrStore(%v) failed: %v", key2, err)
		}
		if val != val2 {
			t.Errorf("LoadOrStore(%v) loaded wrong value: got %v, want %v", key2, val, val2)
		}
		wg.Done()
	}
	del := func() {
		c.Delete(key1)
		c.Delete(key2)
		wg.Done()
	}
	wg.Add(100)
	for i := 0; i < 50; i++ {
		go load()
		go del()
	}
	wg.Wait()
}

func TestStore(t *testing.T) {
	c := &Cache{}
	wg := &sync.WaitGroup{}
	load := func() {
		if err := c.Store(key3, val3); err != nil {
			t.Errorf("Store(%v) failed: %v", key3, err)
		}
		// LoadOrStore should load the already loaded value "val3" and shouldn't
		// overwrite "val1" to "key3".
		val, err := c.LoadOrStore(key3, func() (interface{}, error) { return val1, nil })
		if err != nil {
			t.Errorf("LoadOrStore(%v) failed: %v", key3, err)
		}
		if val != val3 {
			t.Errorf("LoadOrStore(%v) = %v, want %v", key3, val, val3)
		}
		wg.Done()
	}
	del := func() {
		c.Delete(key3)
		wg.Done()
	}
	wg.Add(100)
	for i := 0; i < 50; i++ {
		go load()
		go del()
	}
	wg.Wait()
}

func TestStoreOverwrite(t *testing.T) {
	c := &Cache{}

	val, err := c.LoadOrStore(key3, func() (interface{}, error) { return val1, nil })
	if err != nil {
		t.Errorf("LoadOrStore(%v) failed: %v", key3, err)
	}
	if val != val1 {
		t.Errorf("LoadOrStore(%v) = %v, want %v", key3, val, val1)
	}

	if err := c.Store(key3, val3); err != nil {
		t.Errorf("Store(%v) failed: %v", key3, err)
	}

	// LoadOrStore should load the already loaded value "val3" and shouldn't
	// overwrite "val1" to "key3".
	val, err = c.LoadOrStore(key3, func() (interface{}, error) { return val1, nil })
	if err != nil {
		t.Errorf("LoadOrStore(%v) failed: %v", key3, err)
	}
	if val != val3 {
		t.Errorf("LoadOrStore(%v) = %v, want %v", key3, val, val3)
	}
}

// This test purposefully tests if there is a race condition in concurrent
// go-routines writing / deleting to the same key value - it is not expected
// that the end result of the key in the cache is a specific value which is why
// the output of LoadOrStore is not tested for correctness. You can run the race
// detector using: "bazelisk test --features race //go/pkg/cache/..."
func TestRacedValueStore(t *testing.T) {
	c := &Cache{}
	wg := &sync.WaitGroup{}
	load := func() {
		if _, err := c.LoadOrStore(key1, func() (interface{}, error) { return val1, nil }); err != nil {
			t.Errorf("LoadOrStore(%v) failed: %v", key1, err)
		}
		wg.Done()
	}
	load2 := func() {
		if _, err := c.LoadOrStore(key1, func() (interface{}, error) { return val2, nil }); err != nil {
			t.Errorf("LoadOrStore(%v) failed: %v", key1, err)
		}
		wg.Done()
	}
	del := func() {
		c.Delete(key1)
		wg.Done()
	}
	wg.Add(150)
	for i := 0; i < 50; i++ {
		go load()
		go load2()
		go del()
	}
	wg.Wait()
}
<|endoftext|>


<commit_before>// Copyright 2015 Dorival de Moraes Pedroso. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package goga

import (
	"bytes"
	"math"
	"math/rand"
	"reflect"
	"runtime"
	"sort"

	"github.com/cpmech/gosl/chk"
	"github.com/cpmech/gosl/io"
	"github.com/cpmech/gosl/la"
	"github.com/cpmech/gosl/rnd"
)

// OpsData holds data for crossover and mutation operators
type OpsData struct {

	// input
	Pc        float64 // probability of crossover
	Pm        float64 // probability of mutation
	Ncuts     int     // number of cuts during crossover
	Nchanges  int     // number of changes during mutation
	MwiczB    float64 // Michalewicz' power coefficient
	BlxAlp    float64 // BLX-α coefficient
	Mmax      float64 // multiplier for mutation
	Cuts      []int   // specified cuts for crossover. can be <nil>
	OrdSti    []int   // {start, end, insertPoint}. can be <nil>
	EnfRange  bool    // do enforce range
	DebEtac   float64 // Deb's SBX crossover parameter
	DebEtam   float64 // Deb's parameter-based mutation parameter
	DEpc      float64 // differential-evolution crossover probability
	DEmult    float64 // differential-evolution multiplier
	FltCxName string  // crossover function name. ""=default; "mw"=BLX-α evolution; "db"=Deb's SBX; "de"=differential; "cl"=classic
	FltMtName string  // mutation function name. ""=default; "mw"=Michaelewicz; "db"=Deb's parameter-based

	// derived
	Use4inds bool        // crossover needs 4 individuals (A,B,C,D); e.g. with differential evolution (de)
	Tmax     float64     // max number of generations
	Xrange   [][]float64 // [ngenes][2] genes minimum and maximum values

	// crossover functions
	CxInt CxIntFunc_t // int crossover function
	CxFlt CxFltFunc_t // flt crossover function
	CxStr CxStrFunc_t // str crossover function
	CxKey CxKeyFunc_t // key crossover function
	CxByt CxBytFunc_t // byt crossover function
	CxFun CxFunFunc_t // fun crossover function

	// mutation functions
	MtInt MtIntFunc_t // int mutation function
	MtFlt MtFltFunc_t // flt mutation function
	MtStr MtStrFunc_t // str mutation function
	MtKey MtKeyFunc_t // key mutation function
	MtByt MtBytFunc_t // byt mutation function
	MtFun MtFunFunc_t // fun mutation function
}

// SetDefault sets default values
func (o *OpsData) SetDefault() {

	// input
	o.Pc = 0.8
	o.Pm = 0.01
	o.Ncuts = 2
	o.Nchanges = 1
	o.MwiczB = 2.0
	o.BlxAlp = 0.5
	o.Mmax = 2
	o.EnfRange = true
	o.DebEtac = 1
	o.DebEtam = 1
	o.DEpc = 0.9
	o.DEmult = 0.1

	// crossover functions
	o.CxInt = IntCrossover
	o.CxFlt = FltCrossoverDB
	o.CxStr = StrCrossover
	o.CxKey = KeyCrossover
	o.CxByt = BytCrossover
	o.CxFun = FunCrossover

	// mutation functions
	o.MtInt = IntMutation
	o.MtFlt = FltMutationDB
	o.MtStr = StrMutation
	o.MtKey = KeyMutation
	o.MtByt = BytMutation
	o.MtFun = FunMutation
}

// CalcDerived sets derived quantities
func (o *OpsData) CalcDerived(Tf int, xrange [][]float64) {
	o.Tmax = float64(Tf)
	o.Xrange = xrange
	switch o.FltCxName {
	case "mw":
		o.CxFlt = FltCrossoverMW
	case "db":
		o.CxFlt = FltCrossoverDB
	case "de":
		o.CxFlt = FltCrossoverDE
		o.Use4inds = true
	case "cl":
		o.CxFlt = FltCrossover
	}
	switch o.FltMtName {
	case "mw":
		o.MtFlt = FltMutationMW
	case "db":
		o.MtFlt = FltMutationDB
	case "cl":
		o.MtFlt = FltMutation
	}
}

// MwiczDelta computes Michalewicz' Δ function
func (o *OpsData) MwiczDelta(t, x float64) float64 {
	r := rand.Float64()
	return (1.0 - math.Pow(r, math.Pow(1.0-t/o.Tmax, o.MwiczB))) * x
}

// EnforceRange makes sure x is within given range
func (o *OpsData) EnforceRange(igene int, x float64) float64 {
	if !o.EnfRange {
		return x
	}
	if x < o.Xrange[igene][0] {
		return o.Xrange[igene][0]
	}
	if x > o.Xrange[igene][1] {
		return o.Xrange[igene][1]
	}
	return x
}

func GetFunctionName(i interface{}) string {
	return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
}

// Report generates report
func (o *OpsData) Report(buf *bytes.Buffer) {
	io.Ff(buf, `
# input
Pc        = %v # probability of crossover
Pm        = %v # probability of mutation
Ncuts     = %v # number of cuts during crossover
Nchanges  = %v # number of changes during mutation
MwiczB    = %v # Michalewicz' power coefficient
BlxAlp    = %v # BLX-α coefficient
Mmax      = %v # multiplier for mutation
Cuts      = %v # specified cuts for crossover. can be <nil>
OrdSti    = %v # {start, end, insertPoint}. can be <nil>
EnfRange  = %v # do enforce range
DebEtac   = %v # Deb's SBX crossover parameter
DebEtam   = %v # Deb's parameter-based mutation parameter
DEpc      = %v # differential-evolution crossover probability
DEmult    = %v # differential-evolution multiplier
FltCxName = %q # crossover function name. ""=default; "deb"=Deb's SBX; "de"=differential; "blx"=BLX-α evolution; "classic"=classic
FltMtName = %q # mutation function name. ""=default; "mw"=Michaelewicz; "deb"=Deb's parameter-based

# derived
Use4inds = %v # crossover needs 4 individuals (A,B,C,D); e.g. with differential evolution (de)
Tmax     = %v # max number of generations
Xrange   = %v # [ngenes][2] genes minimum and maximum values

# crossover functions
CxInt = %v # int crossover function
CxFlt = %v # flt crossover function
CxStr = %v # str crossover function
CxKey = %v # key crossover function
CxByt = %v # byt crossover function
CxFun = %v # fun crossover function

# mutation functions
MtInt = %v # int mutation function
MtFlt = %v # flt mutation function
MtStr = %v # str mutation function
MtKey = %v # key mutation function
MtByt = %v # byt mutation function
MtFun = %v # fun mutation function
`, o.Pc, o.Pm, o.Ncuts, o.Nchanges, o.MwiczB, o.BlxAlp, o.Mmax, o.Cuts, o.OrdSti, o.EnfRange,
		o.DebEtac, o.DebEtam, o.DEpc, o.DEmult, o.FltCxName, o.FltMtName,
		o.Use4inds, o.Tmax, o.Xrange,
		chk.GetFunctionName(o.CxInt), chk.GetFunctionName(o.CxFlt), chk.GetFunctionName(o.CxStr),
		chk.GetFunctionName(o.CxKey), chk.GetFunctionName(o.CxByt), chk.GetFunctionName(o.CxFun),
		chk.GetFunctionName(o.MtInt), chk.GetFunctionName(o.MtFlt), chk.GetFunctionName(o.MtStr),
		chk.GetFunctionName(o.MtKey), chk.GetFunctionName(o.MtByt), chk.GetFunctionName(o.MtFun))
}

// auxiliary ///////////////////////////////////////////////////////////////////////////////////////

// SimpleChromo splits 'genes' into 'nbases' unequal parts
//  Input:
//    genes  -- a slice whose size equals to the number of genes
//    nbases -- number of bases used to split 'genes'
//  Output:
//    chromo -- the chromosome
//
//  Example:
//
//    genes = [0, 1, 2, ... nbases-1,  0, 1, 2, ... nbases-1]
//             \___________________/   \___________________/
//                    gene # 0               gene # 1
//
func SimpleChromo(genes []float64, nbases int) (chromo []float64) {
	ngenes := len(genes)
	chromo = make([]float64, ngenes*nbases)
	values := make([]float64, nbases)
	var sumv float64
	for i, g := range genes {
		rnd.Float64s(values, 0, 1)
		sumv = la.VecAccum(values)
		for j := 0; j < nbases; j++ {
			chromo[i*nbases+j] = g * values[j] / sumv
		}
	}
	return
}

// GenerateCxEnds randomly computes the end positions of cuts in chromosomes
//  Input:
//   size  -- size of chromosome
//   ncuts -- number of cuts to be used, unless cuts != nil
//   cuts  -- cut positions. can be nil => use ncuts instead
//  Output:
//   ends -- end positions where the last one equals size
//  Example:
//        0 1 2 3 4 5 6 7
//    A = a b c d e f g h    size = 8
//         ↑       ↑     ↑   cuts = [1, 5]
//         1       5     8   ends = [1, 5, 8]
func GenerateCxEnds(size, ncuts int, cuts []int) (ends []int) {

	// handle small slices
	if size < 2 {
		return
	}
	if size == 2 {
		return []int{1, size}
	}

	// cuts slice is given
	if len(cuts) > 0 {
		ncuts = len(cuts)
		ends = make([]int, ncuts+1)
		ends[ncuts] = size
		for i, cut := range cuts {
			if cut < 1 || cut >= size {
				chk.Panic("cut=%d is outside the allowed range: 1 ≤ cut ≤ size-1", cut)
			}
			if i > 0 {
				if cut == cuts[i-1] {
					chk.Panic("repeated cut values are not allowed: cuts=%v", cuts)
				}
			}
			ends[i] = cut
		}
		sort.Ints(ends)
		return
	}

	// randomly generate cuts
	if ncuts < 1 {
		ncuts = 1
	}
	if ncuts >= size {
		ncuts = size - 1
	}
	ends = make([]int, ncuts+1)
	ends[ncuts] = size

	// pool of values for selections
	pool := rnd.IntGetUniqueN(1, size, ncuts)
	sort.Ints(pool)
	for i := 0; i < ncuts; i++ {
		ends[i] = pool[i]
	}
	return
}
<commit_msg>report fixed<commit_after>// Copyright 2015 Dorival de Moraes Pedroso. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package goga

import (
	"bytes"
	"math"
	"math/rand"
	"reflect"
	"runtime"
	"sort"

	"github.com/cpmech/gosl/chk"
	"github.com/cpmech/gosl/io"
	"github.com/cpmech/gosl/la"
	"github.com/cpmech/gosl/rnd"
)

// OpsData holds data for crossover and mutation operators
type OpsData struct {

	// input
	Pc        float64 // probability of crossover
	Pm        float64 // probability of mutation
	Ncuts     int     // number of cuts during crossover
	Nchanges  int     // number of changes during mutation
	MwiczB    float64 // Michalewicz' power coefficient
	BlxAlp    float64 // BLX-α coefficient
	Mmax      float64 // multiplier for mutation
	Cuts      []int   // specified cuts for crossover. can be <nil>
	OrdSti    []int   // {start, end, insertPoint}. can be <nil>
	EnfRange  bool    // do enforce range
	DebEtac   float64 // Deb's SBX crossover parameter
	DebEtam   float64 // Deb's parameter-based mutation parameter
	DEpc      float64 // differential-evolution crossover probability
	DEmult    float64 // differential-evolution multiplier
	FltCxName string  // crossover function name. ""=default; "mw"=BLX-α evolution; "db"=Deb's SBX; "de"=differential; "cl"=classic
	FltMtName string  // mutation function name. ""=default; "mw"=Michaelewicz; "db"=Deb's parameter-based

	// derived
	Use4inds bool        // crossover needs 4 individuals (A,B,C,D); e.g. with differential evolution (de)
	Tmax     float64     // max number of generations
	Xrange   [][]float64 // [ngenes][2] genes minimum and maximum values

	// crossover functions
	CxInt CxIntFunc_t // int crossover function
	CxFlt CxFltFunc_t // flt crossover function
	CxStr CxStrFunc_t // str crossover function
	CxKey CxKeyFunc_t // key crossover function
	CxByt CxBytFunc_t // byt crossover function
	CxFun CxFunFunc_t // fun crossover function

	// mutation functions
	MtInt MtIntFunc_t // int mutation function
	MtFlt MtFltFunc_t // flt mutation function
	MtStr MtStrFunc_t // str mutation function
	MtKey MtKeyFunc_t // key mutation function
	MtByt MtBytFunc_t // byt mutation function
	MtFun MtFunFunc_t // fun mutation function
}

// SetDefault sets default values
func (o *OpsData) SetDefault() {

	// input
	o.Pc = 0.8
	o.Pm = 0.01
	o.Ncuts = 2
	o.Nchanges = 1
	o.MwiczB = 2.0
	o.BlxAlp = 0.5
	o.Mmax = 2
	o.EnfRange = true
	o.DebEtac = 1
	o.DebEtam = 1
	o.DEpc = 0.9
	o.DEmult = 0.1

	// crossover functions
	o.CxInt = IntCrossover
	o.CxFlt = FltCrossoverDB
	o.CxStr = StrCrossover
	o.CxKey = KeyCrossover
	o.CxByt = BytCrossover
	o.CxFun = FunCrossover

	// mutation functions
	o.MtInt = IntMutation
	o.MtFlt = FltMutationDB
	o.MtStr = StrMutation
	o.MtKey = KeyMutation
	o.MtByt = BytMutation
	o.MtFun = FunMutation
}

// CalcDerived sets derived quantities
func (o *OpsData) CalcDerived(Tf int, xrange [][]float64) {
	o.Tmax = float64(Tf)
	o.Xrange = xrange
	switch o.FltCxName {
	case "mw":
		o.CxFlt = FltCrossoverMW
	case "db":
		o.CxFlt = FltCrossoverDB
	case "de":
		o.CxFlt = FltCrossoverDE
		o.Use4inds = true
	case "cl":
		o.CxFlt = FltCrossover
	}
	switch o.FltMtName {
	case "mw":
		o.MtFlt = FltMutationMW
	case "db":
		o.MtFlt = FltMutationDB
	case "cl":
		o.MtFlt = FltMutation
	}
}

// MwiczDelta computes Michalewicz' Δ function
func (o *OpsData) MwiczDelta(t, x float64) float64 {
	r := rand.Float64()
	return (1.0 - math.Pow(r, math.Pow(1.0-t/o.Tmax, o.MwiczB))) * x
}

// EnforceRange makes sure x is within given range
func (o *OpsData) EnforceRange(igene int, x float64) float64 {
	if !o.EnfRange {
		return x
	}
	if x < o.Xrange[igene][0] {
		return o.Xrange[igene][0]
	}
	if x > o.Xrange[igene][1] {
		return o.Xrange[igene][1]
	}
	return x
}

func GetFunctionName(i interface{}) string {
	return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
}

// Report generates report
func (o *OpsData) Report(buf *bytes.Buffer) {
	io.Ff(buf, `
# input
Pc        = %v # probability of crossover
Pm        = %v # probability of mutation
Ncuts     = %v # number of cuts during crossover
Nchanges  = %v # number of changes during mutation
MwiczB    = %v # Michalewicz' power coefficient
BlxAlp    = %v # BLX-α coefficient
Mmax      = %v # multiplier for mutation
Cuts      = %v # specified cuts for crossover. can be <nil>
OrdSti    = %v # {start, end, insertPoint}. can be <nil>
EnfRange  = %v # do enforce range
DebEtac   = %v # Deb's SBX crossover parameter
DebEtam   = %v # Deb's parameter-based mutation parameter
DEpc      = %v # differential-evolution crossover probability
DEmult    = %v # differential-evolution multiplier
FltCxName = %v # crossover function name. ""=default; "mw"=BLX-α evolution; "db"=Deb's SBX; "de"=differential; "cl"=classic
FltMtName = %v # mutation function name. ""=default; "mw"=Michaelewicz; "db"=Deb's parameter-based

# derived
Use4inds = %v # crossover needs 4 individuals (A,B,C,D); e.g. with differential evolution (de)
Tmax     = %v # max number of generations
Xrange   = %v # [ngenes][2] genes minimum and maximum values

# crossover functions
CxInt = %v # int crossover function
CxFlt = %v # flt crossover function
CxStr = %v # str crossover function
CxKey = %v # key crossover function
CxByt = %v # byt crossover function
CxFun = %v # fun crossover function

# mutation functions
MtInt = %v # int mutation function
MtFlt = %v # flt mutation function
MtStr = %v # str mutation function
MtKey = %v # key mutation function
MtByt = %v # byt mutation function
MtFun = %v # fun mutation function
`, o.Pc, o.Pm, o.Ncuts, o.Nchanges, o.MwiczB, o.BlxAlp, o.Mmax, o.Cuts, o.OrdSti, o.EnfRange,
		o.DebEtac, o.DebEtam, o.DEpc, o.DEmult, o.FltCxName, o.FltMtName,
		o.Use4inds, o.Tmax, o.Xrange,
		chk.GetFunctionName(o.CxInt), chk.GetFunctionName(o.CxFlt), chk.GetFunctionName(o.CxStr),
		chk.GetFunctionName(o.CxKey), chk.GetFunctionName(o.CxByt), chk.GetFunctionName(o.CxFun),
		chk.GetFunctionName(o.MtInt), chk.GetFunctionName(o.MtFlt), chk.GetFunctionName(o.MtStr),
		chk.GetFunctionName(o.MtKey), chk.GetFunctionName(o.MtByt), chk.GetFunctionName(o.MtFun))
}

// auxiliary ///////////////////////////////////////////////////////////////////////////////////////

// SimpleChromo splits 'genes' into 'nbases' unequal parts
//  Input:
//    genes  -- a slice whose size equals to the number of genes
//    nbases -- number of bases used to split 'genes'
//  Output:
//    chromo -- the chromosome
//
//  Example:
//
//    genes = [0, 1, 2, ... nbases-1,  0, 1, 2, ... nbases-1]
//             \___________________/   \___________________/
//                    gene # 0               gene # 1
//
func SimpleChromo(genes []float64, nbases int) (chromo []float64) {
	ngenes := len(genes)
	chromo = make([]float64, ngenes*nbases)
	values := make([]float64, nbases)
	var sumv float64
	for i, g := range genes {
		rnd.Float64s(values, 0, 1)
		sumv = la.VecAccum(values)
		for j := 0; j < nbases; j++ {
			chromo[i*nbases+j] = g * values[j] / sumv
		}
	}
	return
}

// GenerateCxEnds randomly computes the end positions of cuts in chromosomes
//  Input:
//   size  -- size of chromosome
//   ncuts -- number of cuts to be used, unless cuts != nil
//   cuts  -- cut positions. can be nil => use ncuts instead
//  Output:
//   ends -- end positions where the last one equals size
//  Example:
//        0 1 2 3 4 5 6 7
//    A = a b c d e f g h    size = 8
//         ↑       ↑     ↑   cuts = [1, 5]
//         1       5     8   ends = [1, 5, 8]
func GenerateCxEnds(size, ncuts int, cuts []int) (ends []int) {

	// handle small slices
	if size < 2 {
		return
	}
	if size == 2 {
		return []int{1, size}
	}

	// cuts slice is given
	if len(cuts) > 0 {
		ncuts = len(cuts)
		ends = make([]int, ncuts+1)
		ends[ncuts] = size
		for i, cut := range cuts {
			if cut < 1 || cut >= size {
				chk.Panic("cut=%d is outside the allowed range: 1 ≤ cut ≤ size-1", cut)
			}
			if i > 0 {
				if cut == cuts[i-1] {
					chk.Panic("repeated cut values are not allowed: cuts=%v", cuts)
				}
			}
			ends[i] = cut
		}
		sort.Ints(ends)
		return
	}

	// randomly generate cuts
	if ncuts < 1 {
		ncuts = 1
	}
	if ncuts >= size {
		ncuts = size - 1
	}
	ends = make([]int, ncuts+1)
	ends[ncuts] = size

	// pool of values for selections
	pool := rnd.IntGetUniqueN(1, size, ncuts)
	sort.Ints(pool)
	for i := 0; i < ncuts; i++ {
		ends[i] = pool[i]
	}
	return
}
<|endoftext|>


<commit_before>package sqlhooks

import (
	"context"
	"database/sql"
	"database/sql/driver"
	"errors"
	"fmt"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

type testHooks struct {
	before  Hook
	after   Hook
	onError ErrorHook
}

func (h *testHooks) noop() {
	noop := func(ctx context.Context, query string, args ...interface{}) (context.Context, error) {
		return ctx, nil
	}

	h.before, h.after = noop, noop
}

func (h *testHooks) Before(ctx context.Context, query string, args ...interface{}) (context.Context, error) {
	return h.before(ctx, query, args...)
}

func (h *testHooks) After(ctx context.Context, query string, args ...interface{}) (context.Context, error) {
	return h.after(ctx, query, args...)
}

func (h *testHooks) ErrHook(ctx context.Context, err error, query string, args ...interface{}) error {
	return h.onError(ctx, err, query, args...)
}

type suite struct {
	db    *sql.DB
	hooks *testHooks
}

func newSuite(t *testing.T, driver driver.Driver, dsn string) *suite {
	hooks := &testHooks{}
	driverName := fmt.Sprintf("sqlhooks-%s", time.Now().String())
	sql.Register(driverName, Wrap(driver, hooks))

	db, err := sql.Open(driverName, dsn)
	require.NoError(t, err)
	require.NoError(t, db.Ping())

	return &suite{db, hooks}
}

func (s *suite) TestHooksExecution(t *testing.T, query string, args ...interface{}) {
	var before, after bool

	s.hooks.before = func(ctx context.Context, q string, a ...interface{}) (context.Context, error) {
		before = true
		return ctx, nil
	}
	s.hooks.after = func(ctx context.Context, q string, a ...interface{}) (context.Context, error) {
		after = true
		return ctx, nil
	}

	t.Run("Query", func(t *testing.T) {
		before, after = false, false
		_, err := s.db.Query(query, args...)
		require.NoError(t, err)
		assert.True(t, before, "Before Hook did not run for query: "+query)
		assert.True(t, after, "After Hook did not run for query:  "+query)
	})

	t.Run("QueryContext", func(t *testing.T) {
		before, after = false, false
		_, err := s.db.QueryContext(context.Background(), query, args...)
		require.NoError(t, err)
		assert.True(t, before, "Before Hook did not run for query: "+query)
		assert.True(t, after, "After Hook did not run for query:  "+query)
	})

	t.Run("Exec", func(t *testing.T) {
		before, after = false, false
		_, err := s.db.Exec(query, args...)
		require.NoError(t, err)
		assert.True(t, before, "Before Hook did not run for query: "+query)
		assert.True(t, after, "After Hook did not run for query:  "+query)
	})

	t.Run("ExecContext", func(t *testing.T) {
		before, after = false, false
		_, err := s.db.ExecContext(context.Background(), query, args...)
		require.NoError(t, err)
		assert.True(t, before, "Before Hook did not run for query: "+query)
		assert.True(t, after, "After Hook did not run for query:  "+query)
	})

	t.Run("Statements", func(t *testing.T) {
		before, after = false, false
		stmt, err := s.db.Prepare(query)
		require.NoError(t, err)

		// Hooks just run when the stmt is executed (Query or Exec)
		assert.False(t, before, "Before Hook run before execution: "+query)
		assert.False(t, after, "After Hook run before execution:  "+query)

		stmt.Query(args...)
		assert.True(t, before, "Before Hook did not run for query: "+query)
		assert.True(t, after, "After Hook did not run for query:  "+query)
	})
}

func (s *suite) testHooksArguments(t *testing.T, query string, args ...interface{}) {
	hook := func(ctx context.Context, q string, a ...interface{}) (context.Context, error) {
		assert.Equal(t, query, q)
		assert.Equal(t, args, a)
		assert.Equal(t, "val", ctx.Value("key").(string))
		return ctx, nil
	}
	s.hooks.before = hook
	s.hooks.after = hook

	ctx := context.WithValue(context.Background(), "key", "val")
	{
		_, err := s.db.QueryContext(ctx, query, args...)
		require.NoError(t, err)
	}

	{
		_, err := s.db.ExecContext(ctx, query, args...)
		require.NoError(t, err)
	}
}

func (s *suite) TestHooksArguments(t *testing.T, query string, args ...interface{}) {
	t.Run("TestHooksArguments", func(t *testing.T) { s.testHooksArguments(t, query, args...) })
}

func (s *suite) testHooksErrors(t *testing.T, query string) {
	boom := errors.New("boom")
	s.hooks.before = func(ctx context.Context, query string, args ...interface{}) (context.Context, error) {
		return ctx, boom
	}

	s.hooks.after = func(ctx context.Context, query string, args ...interface{}) (context.Context, error) {
		assert.False(t, true, "this should not run")
		return ctx, nil
	}

	_, err := s.db.Query(query)
	assert.Equal(t, boom, err)
}

func (s *suite) TestHooksErrors(t *testing.T, query string) {
	t.Run("TestHooksErrors", func(t *testing.T) { s.testHooksErrors(t, query) })
}

func (s *suite) testErrHookHook(t *testing.T, query string, args ...interface{}) {
	s.hooks.before = func(ctx context.Context, query string, args ...interface{}) (context.Context, error) {
		return ctx, nil
	}

	s.hooks.after = func(ctx context.Context, query string, args ...interface{}) (context.Context, error) {
		assert.False(t, true, "after hook should not run")
		return ctx, nil
	}

	s.hooks.onError = func(ctx context.Context, err error, query string, args ...interface{}) error {
		assert.True(t, true, "onError hook should run")
		return err
	}

	s.db.Query(query)
}

func (s *suite) TestErrHookHook(t *testing.T, query string, args ...interface{}) {
	t.Run("TestErrHookHook", func(t *testing.T) { s.testErrHookHook(t, query, args...) })
}

func TestNamedValueToValue(t *testing.T) {
	named := []driver.NamedValue{
		{Ordinal: 1, Value: "foo"},
		{Ordinal: 2, Value: 42},
	}
	want := []driver.Value{"foo", 42}
	dargs, err := namedValueToValue(named)
	require.NoError(t, err)
	assert.Equal(t, want, dargs)
}
<commit_msg>make testHooks implement OnErrorer<commit_after>package sqlhooks

import (
	"context"
	"database/sql"
	"database/sql/driver"
	"errors"
	"fmt"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

type testHooks struct {
	before  Hook
	after   Hook
	onError ErrorHook
}

func (h *testHooks) noop() {
	noop := func(ctx context.Context, query string, args ...interface{}) (context.Context, error) {
		return ctx, nil
	}

	h.before, h.after = noop, noop
}

func (h *testHooks) Before(ctx context.Context, query string, args ...interface{}) (context.Context, error) {
	return h.before(ctx, query, args...)
}

func (h *testHooks) After(ctx context.Context, query string, args ...interface{}) (context.Context, error) {
	return h.after(ctx, query, args...)
}

func (h *testHooks) OnError(ctx context.Context, err error, query string, args ...interface{}) error {
	return h.onError(ctx, err, query, args...)
}

type suite struct {
	db    *sql.DB
	hooks *testHooks
}

func newSuite(t *testing.T, driver driver.Driver, dsn string) *suite {
	hooks := &testHooks{}
	driverName := fmt.Sprintf("sqlhooks-%s", time.Now().String())
	sql.Register(driverName, Wrap(driver, hooks))

	db, err := sql.Open(driverName, dsn)
	require.NoError(t, err)
	require.NoError(t, db.Ping())

	return &suite{db, hooks}
}

func (s *suite) TestHooksExecution(t *testing.T, query string, args ...interface{}) {
	var before, after bool

	s.hooks.before = func(ctx context.Context, q string, a ...interface{}) (context.Context, error) {
		before = true
		return ctx, nil
	}
	s.hooks.after = func(ctx context.Context, q string, a ...interface{}) (context.Context, error) {
		after = true
		return ctx, nil
	}

	t.Run("Query", func(t *testing.T) {
		before, after = false, false
		_, err := s.db.Query(query, args...)
		require.NoError(t, err)
		assert.True(t, before, "Before Hook did not run for query: "+query)
		assert.True(t, after, "After Hook did not run for query:  "+query)
	})

	t.Run("QueryContext", func(t *testing.T) {
		before, after = false, false
		_, err := s.db.QueryContext(context.Background(), query, args...)
		require.NoError(t, err)
		assert.True(t, before, "Before Hook did not run for query: "+query)
		assert.True(t, after, "After Hook did not run for query:  "+query)
	})

	t.Run("Exec", func(t *testing.T) {
		before, after = false, false
		_, err := s.db.Exec(query, args...)
		require.NoError(t, err)
		assert.True(t, before, "Before Hook did not run for query: "+query)
		assert.True(t, after, "After Hook did not run for query:  "+query)
	})

	t.Run("ExecContext", func(t *testing.T) {
		before, after = false, false
		_, err := s.db.ExecContext(context.Background(), query, args...)
		require.NoError(t, err)
		assert.True(t, before, "Before Hook did not run for query: "+query)
		assert.True(t, after, "After Hook did not run for query:  "+query)
	})

	t.Run("Statements", func(t *testing.T) {
		before, after = false, false
		stmt, err := s.db.Prepare(query)
		require.NoError(t, err)

		// Hooks just run when the stmt is executed (Query or Exec)
		assert.False(t, before, "Before Hook run before execution: "+query)
		assert.False(t, after, "After Hook run before execution:  "+query)

		stmt.Query(args...)
		assert.True(t, before, "Before Hook did not run for query: "+query)
		assert.True(t, after, "After Hook did not run for query:  "+query)
	})
}

func (s *suite) testHooksArguments(t *testing.T, query string, args ...interface{}) {
	hook := func(ctx context.Context, q string, a ...interface{}) (context.Context, error) {
		assert.Equal(t, query, q)
		assert.Equal(t, args, a)
		assert.Equal(t, "val", ctx.Value("key").(string))
		return ctx, nil
	}
	s.hooks.before = hook
	s.hooks.after = hook

	ctx := context.WithValue(context.Background(), "key", "val")
	{
		_, err := s.db.QueryContext(ctx, query, args...)
		require.NoError(t, err)
	}

	{
		_, err := s.db.ExecContext(ctx, query, args...)
		require.NoError(t, err)
	}
}

func (s *suite) TestHooksArguments(t *testing.T, query string, args ...interface{}) {
	t.Run("TestHooksArguments", func(t *testing.T) { s.testHooksArguments(t, query, args...) })
}

func (s *suite) testHooksErrors(t *testing.T, query string) {
	boom := errors.New("boom")
	s.hooks.before = func(ctx context.Context, query string, args ...interface{}) (context.Context, error) {
		return ctx, boom
	}

	s.hooks.after = func(ctx context.Context, query string, args ...interface{}) (context.Context, error) {
		assert.False(t, true, "this should not run")
		return ctx, nil
	}

	_, err := s.db.Query(query)
	assert.Equal(t, boom, err)
}

func (s *suite) TestHooksErrors(t *testing.T, query string) {
	t.Run("TestHooksErrors", func(t *testing.T) { s.testHooksErrors(t, query) })
}

func (s *suite) testErrHookHook(t *testing.T, query string, args ...interface{}) {
	s.hooks.before = func(ctx context.Context, query string, args ...interface{}) (context.Context, error) {
		return ctx, nil
	}

	s.hooks.after = func(ctx context.Context, query string, args ...interface{}) (context.Context, error) {
		assert.False(t, true, "after hook should not run")
		return ctx, nil
	}

	s.hooks.onError = func(ctx context.Context, err error, query string, args ...interface{}) error {
		assert.True(t, true, "onError hook should run")
		return err
	}

	s.db.Query(query)
}

func (s *suite) TestErrHookHook(t *testing.T, query string, args ...interface{}) {
	t.Run("TestErrHookHook", func(t *testing.T) { s.testErrHookHook(t, query, args...) })
}

func TestNamedValueToValue(t *testing.T) {
	named := []driver.NamedValue{
		{Ordinal: 1, Value: "foo"},
		{Ordinal: 2, Value: 42},
	}
	want := []driver.Value{"foo", 42}
	dargs, err := namedValueToValue(named)
	require.NoError(t, err)
	assert.Equal(t, want, dargs)
}
<|endoftext|>


<commit_before>package sqls

import (
	"github.com/wanderself/commons/conf"
	"github.com/wanderself/commons/errs"
	"log"
)

var conn *Conns

func Connect(user, pwd, host, database string, MaxOpenConns, MaxIdleConns int) error {
	conn = new(Conns)
	if err := conn.NewDataSource(user, pwd, host, database, MaxOpenConns, MaxIdleConns); err != nil {
		errs.ErrCheck(err, "Connect() conn.NewDataSource: ")
		return err
	}

	if err := conn.DB.Ping(); err != nil {
		errs.ErrCheck(err, "Connect() conn.DB.Ping: ")
		return err
	} else {
		log.Println("mysql connection established!	Database:", conf.GetConf().Database)
		return nil
	}
}

func Ins(sql string, args ...interface{}) error {
	stmtIns, err := conn.DB.Prepare(sql)
	if err != nil {
		errs.ErrCheck(err, "Ins() conn.DB.Prepare: ")
		return err
	}
	defer stmtIns.Close()

	if _, err := stmtIns.Exec(args ...); err != nil {
		return err
	}

	return nil
}
<commit_msg>errCheck updated<commit_after>package sqls

import (
	"github.com/wanderself/commons/conf"
	"github.com/wanderself/commons/errs"
	"log"
)

var conn *Conns

func Connect(user, pwd, host, database string, MaxOpenConns, MaxIdleConns int) error {
	conn = new(Conns)
	if err := conn.NewDataSource(user, pwd, host, database, MaxOpenConns, MaxIdleConns); err != nil {
		errs.ErrCheck(err, "Connect() conn.NewDataSource: ")
		return err
	}

	if err := conn.DB.Ping(); err != nil {
		errs.ErrCheck(err, "Connect() conn.DB.Ping: ")
		return err
	} else {
		log.Println("mysql connection established!	Database:", conf.GetConf().Database)
		return nil
	}
}

func Ins(sql string, args ...interface{}) error {
	stmtIns, err := conn.DB.Prepare(sql)
	if err != nil {
		errs.ErrCheck(err, "Ins() conn.DB.Prepare: ")
		return err
	}
	defer stmtIns.Close()

	if _, err := stmtIns.Exec(args ...); err != nil {
		errs.ErrCheck(err, "Ins() stmtIns.Exec: ")
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package workertest

import (
	"encoding/json"
	"fmt"
	"net/http/httptest"
	"os"
	"path"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"github.com/taskcluster/slugid-go/slugid"
	tcclient "github.com/taskcluster/taskcluster-client-go"
	"github.com/taskcluster/taskcluster-client-go/tcqueue"
	"github.com/taskcluster/taskcluster-worker/runtime"
	"github.com/taskcluster/taskcluster-worker/runtime/atomics"
	"github.com/taskcluster/taskcluster-worker/runtime/util"
	"github.com/taskcluster/taskcluster-worker/worker"
	"github.com/taskcluster/taskcluster-worker/worker/workertest/fakequeue"
)

const defaultTestCaseTimeout = 8 * time.Minute // as go test limits to 10 min by default

// Case is a worker test case
type Case struct {
	Engine            string        // Engine to be used
	EngineConfig      string        // Engine configuration as JSON
	PluginConfig      string        // Configuration of plugins, see plugins.PluginManagerConfigSchema()
	Setup             SetupFunc     // Function to setup local environment, return a cleanup function
	Tasks             TasksFunc     // Function that returns a list of tasks to create and associated assertions
	Concurrency       int           // Worker concurrency, if zero defaulted to 1 and tasks will sequantially dependent
	StoppedGracefully bool          // True, if worker is expected to stop gracefully
	StoppedNow        bool          // True, if worker is expected to stop now
	Timeout           time.Duration // Test timeout, defaults to 8 Minutes
	EnableSuperseding bool          // Enable superseding in the worker
}

// Environment holds values that can be accessed in callbacks
type Environment struct {
	Worker   runtime.Stoppable
	Queue    *tcqueue.Queue
	Listener fakequeue.Listener
}

// A SetupFunc callback can setup the local environment, this includes starting
// servers running on localhost. The SetupFunc callback returns a cleanup function
// that will be invoked when tests are done.
type SetupFunc func(t *testing.T, env Environment) func()

// A TasksFunc callback returns the tasks to be created and associated assertions.
//
// For test cases that uses a static list of tasks, Tasks([]task{...}) function
// can be used to wrap a static []Task list.
type TasksFunc func(t *testing.T, env Environment) []Task

// Tasks is a quick wrapper for constructing a TasksFunc that always returns
// a static list of tasks.
func Tasks(tasks []Task) TasksFunc {
	return func(*testing.T, Environment) []Task {
		return tasks
	}
}

// A Task to be included in a worker test case
type Task struct {
	TaskID          string                  // Optional taskID (use slugid.Nice())
	Title           string                  // Optional title (for debugging)
	Scopes          []string                // Task scopes
	Payload         string                  // Task payload as JSON
	IgnoreState     bool                    // Ignore Success and Exception
	Success         bool                    // True, if task should be successfully
	Exception       runtime.ExceptionReason // Reason, if exception is expected
	Artifacts       ArtifactAssertions      // Mapping from artifact name to assertion
	AllowAdditional bool                    // True, if additional artifacts is allowed
	Status          StatusAssertion         // Optional, custom assertion on status and queue
}

// A StatusAssertion is a function that can make an assertion on a task status
type StatusAssertion func(t *testing.T, q *tcqueue.Queue, status tcqueue.TaskStatusStructure)

// An ArtifactAssertions is a mapping from artifact name to assertion for the
// artifact. If mapping to nil value, any artifact will be permitted.
type ArtifactAssertions map[string]func(t *testing.T, a Artifact)

// Artifact contains artifact meta-data.
type Artifact struct {
	ContentType     string
	Expires         time.Time
	Name            string
	StorageType     string
	Data            []byte
	ContentEncoding string
}

// provisionerId/workerType for test cases, access granted by role:
//   assume:project:taskcluster:worker-test-scopes
var dummyProvisionerID = "test-dummy-provisioner"

func dummyWorkerType() string {
	return "dummy-worker-" + slugid.V4()[:9]
}

// TestWithFakeQueue runs integration tests against FakeQueue
func (c Case) TestWithFakeQueue(t *testing.T) {
	// Create FakeQueue
	fq := fakequeue.New()
	s := httptest.NewServer(fq)
	defer s.Close()

	// Create listener
	l := fakequeue.NewFakeQueueListener(fq)

	// Create queue client
	q := tcqueue.New(&tcclient.Credentials{
		// Long enough to pass schema validation
		ClientID:    "dummy-test-client-id",
		AccessToken: "non-secret-dummy-test-access-token",
	})
	q.BaseURL = s.URL

	c.testWithQueue(t, q, l)
}

// TestWithRealQueue runs integration tests against production queue
func (c Case) TestWithRealQueue(t *testing.T) {
	u := os.Getenv("PULSE_USERNAME")
	p := os.Getenv("PULSE_PASSWORD")
	if u == "" || p == "" {
		t.Skip("Skipping integration tests, because PULSE_USERNAME and PULSE_PASSWORD are not specified")
	}

	if testing.Short() {
		t.Skip("Skipping integration tests in short mode")
	}

	// Create listener
	l, err := fakequeue.NewPulseListener(u, p)
	require.NoError(t, err, "Failed to create PulseListener")

	// Create queue client
	q := tcqueue.New(&tcclient.Credentials{
		ClientID:    os.Getenv("TASKCLUSTER_CLIENT_ID"),
		AccessToken: os.Getenv("TASKCLUSTER_ACCESS_TOKEN"),
		Certificate: os.Getenv("TASKCLUSTER_CERTIFICATE"),
	})
	if os.Getenv("QUEUE_BASE_URL") != "" {
		q.BaseURL = os.Getenv("QUEUE_BASE_URL")
	}

	c.testWithQueue(t, q, l)
}

// Test runs the test case
func (c Case) Test(t *testing.T) {
	passedFake := t.Run("FakeQueue", c.TestWithFakeQueue)
	// We don't run real integration tests if the FakeQueue tests fails
	// This is aimed to avoid polluting the queue and reducing feedback cycle.
	// You can manually call TestWithRealQueue(t), if you want to debug it.
	if passedFake {
		t.Run("RealQueue", c.TestWithRealQueue)
	} else {
		t.Run("RealQueue", func(t *testing.T) {
			t.Skip("Skipping integration tests, because FakeQueue tests failed")
		})
	}
}

func mustUnmarshalJSON(data string) interface{} {
	var v interface{}
	err := json.Unmarshal([]byte(data), &v)
	if err != nil {
		panic(fmt.Sprintf("Failed to parse JSON, error: %s, json: '%s'", err, data))
	}
	return v
}

func (c Case) testWithQueue(t *testing.T, q *tcqueue.Queue, l fakequeue.Listener) {
	// Run initial config
	if c.Setup != nil {
		cleanup := c.Setup(t, Environment{
			Listener: l,
			Queue:    q,
			Worker:   nil, // not available in the setup stage
		})
		if cleanup != nil {
			defer cleanup()
		}
	}

	// Create config
	tempFolder := path.Join(os.TempDir(), slugid.Nice())
	defer os.RemoveAll(tempFolder)
	concurrency := c.Concurrency
	if concurrency == 0 {
		concurrency = 1
	}
	creds := map[string]interface{}{
		"clientId":    q.Credentials.ClientID,
		"accessToken": q.Credentials.AccessToken,
	}
	if q.Credentials.Certificate != "" {
		creds["certificate"] = q.Credentials.Certificate
	}
	workerID := "dummy-worker-" + slugid.V4()[:9]
	workerType := dummyWorkerType()
	config := map[string]interface{}{
		"credentials": creds,
		"engine":      c.Engine,
		"engines": map[string]interface{}{
			c.Engine: mustUnmarshalJSON(c.EngineConfig),
		},
		"minimumDiskSpace": 0,
		"minimumMemory":    0,
		"monitor":          mustUnmarshalJSON(`{"panicOnError": false, "type": "mock"}`),
		"plugins":          mustUnmarshalJSON(c.PluginConfig),
		"queueBaseUrl":     q.BaseURL,
		"temporaryFolder":  tempFolder,
		"webHookServer":    mustUnmarshalJSON(`{"provider": "localhost"}`),
		"worker": map[string]interface{}{
			"concurrency":         concurrency,
			"minimumReclaimDelay": 30,
			"pollingInterval":     1,
			"reclaimOffset":       30,
			"workerGroup":         "test-dummy-workers",
			"workerId":            workerID,
			"provisionerId":       dummyProvisionerID,
			"workerType":          workerType,
			"enableSuperseding":   c.EnableSuperseding,
		},
	}
	err := worker.ConfigSchema().Validate(config)
	require.NoError(t, err, "Failed to validate worker config against schema")

	// Create worker
	w, err := worker.New(config)
	require.NoError(t, err, "Failed to create worker")

	// Generate the tasks
	require.NotNil(t, c.Tasks, "Case.Tasks must be defined")
	tasks := c.Tasks(t, Environment{
		Listener: l,
		Queue:    q,
		Worker:   w,
	})

	// Create taskIDs
	taskIDs := make([]string, len(tasks))
	for i := range taskIDs {
		if tasks[i].TaskID != "" {
			taskIDs[i] = tasks[i].TaskID
		} else {
			taskIDs[i] = slugid.Nice()
		}
	}

	// Setup event listeners
	events := make([]<-chan error, len(tasks))
	util.Spawn(len(tasks), func(i int) {
		events[i] = l.WaitForTask(taskIDs[i])
	})

	// Wait for tasks to be resolved
	var tasksResolved atomics.Once
	go tasksResolved.Do(func() {
		// Wait for events
		debug("Waiting for tasks to be resolved")
		util.Spawn(len(tasks), func(i int) {
			err := <-events[i]
			assert.NoError(t, err, "Failed to listen for task %d", i)
			debug("Finished waiting for %s", taskIDs[i])
			if err != nil {
				debug("Error '%s' waiting for %s", taskIDs[i], err)
			}
		})
	})

	// Create task definitions
	tdefs := make([]*tcqueue.TaskDefinitionRequest, len(taskIDs))
	for i, task := range tasks {
		tdefs[i] = &tcqueue.TaskDefinitionRequest{
			ProvisionerID: dummyProvisionerID,
			WorkerType:    workerType,
			Created:       tcclient.Time(time.Now()),
			Deadline:      tcclient.Time(time.Now().Add(60 * time.Minute)),
			Expires:       tcclient.Time(time.Now().Add(31 * 24 * 60 * time.Minute)),
			Payload:       json.RawMessage(task.Payload),
		}
		// If tasks are to run sequantially, we'll make them dependent
		if c.Concurrency == 0 && i > 0 {
			tdefs[i].Dependencies = []string{taskIDs[i-1]}
			tdefs[i].Requires = "all-resolved"
		}
		title := task.Title
		if title == "" {
			title = fmt.Sprintf("Task %d", i)
		}
		tdefs[i].Scopes = task.Scopes
		tdefs[i].Metadata.Name = title
		tdefs[i].Metadata.Description = "Task from taskcluster-worker integration tests"
		tdefs[i].Metadata.Source = "https://github.com/taskcluster/taskcluster-worker/tree/master/worker/workertest/workertest.go"
		tdefs[i].Metadata.Owner = "jonasfj@mozilla.com"
	}

	// Create tasks asynchronously with a limit of 10 concurrent calls to make
	// that it goes fairly faster, when there is a lot of tasks.
	limit := 10
	if c.Concurrency == 0 {
		limit = 1
	}
	errs := make([]error, len(taskIDs))
	util.SpawnWithLimit(len(taskIDs), limit, func(i int) {
		debug("creating task '%s' as taskId: %s", tdefs[i].Metadata.Name, taskIDs[i])
		_, errs[i] = q.CreateTask(taskIDs[i], tdefs[i])
	})
	// Check error status for all tasks
	for i, tdef := range tdefs {
		require.NoError(t, errs[i], "Failed to create task: %s", tdef.Metadata.Name)
	}

	// Start worker
	var serr error
	var stopped atomics.Once
	go stopped.Do(func() {
		debug("starting worker with workerType: %s and workerID: %s", workerType, workerID)
		serr = w.Start()
		debug("worker stopped")
	})

	// Wait for events to have been handled
	timeout := c.Timeout
	if timeout == 0 {
		timeout = defaultTestCaseTimeout
	}
	select {
	case <-tasksResolved.Done():
	case <-time.After(timeout):
		assert.Fail(t, "Test case timed out, see workertest.Case.Timeout Property!")
		debug("worker.StopNow() because of test case timeout")
		w.StopNow()
		// We give it 30s to stop now, otherwise we end the test-case
		select {
		case <-stopped.Done():
		case <-time.After(30 * time.Second):
			debug("worker.StopNow() didn't stop after 30s")
		}
		return
	}

	// if we expect the worker to stop then we don't want to stop it here
	if !c.StoppedGracefully && !c.StoppedNow {
		// Stop worker
		debug("gracefully stopping worker (since test-case isn't stopping the worker)")
		w.StopGracefully()
	}

	// Wait for the worker to stop
	select {
	case <-stopped.Done():
	case <-time.After(30 * time.Second):
		assert.Fail(t, "Expected worker to stop")
	}

	// Verify assertions
	// We must do this after the worker has stopped, since tasks resolved
	// with exception can have artifacts added after resolution.
	debug("Verifying task assertions")
	// We could run these in parallel, but debugging is easier if we don't...
	for i, task := range tasks {
		title := task.Title
		if title == "" {
			title = fmt.Sprintf("Task %d", i)
		}
		t.Run(title, func(t *testing.T) {
			verifyAssertions(t, title, taskIDs[i], task, q)
		})
	}

	// Check the stopping condition
	if c.StoppedNow {
		assert.Exactly(t, worker.ErrWorkerStoppedNow, serr, "Expected StoppedNow!")
	} else {
		assert.NoError(t, serr, "Expected worker to stop gracefully")
	}
}
<commit_msg>use webhooktunnel for integration tests when credentials are present<commit_after>package workertest

import (
	"encoding/json"
	"fmt"
	"net/http/httptest"
	"os"
	"path"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"github.com/taskcluster/slugid-go/slugid"
	tcclient "github.com/taskcluster/taskcluster-client-go"
	"github.com/taskcluster/taskcluster-client-go/tcqueue"
	"github.com/taskcluster/taskcluster-worker/runtime"
	"github.com/taskcluster/taskcluster-worker/runtime/atomics"
	"github.com/taskcluster/taskcluster-worker/runtime/util"
	"github.com/taskcluster/taskcluster-worker/worker"
	"github.com/taskcluster/taskcluster-worker/worker/workertest/fakequeue"
)

const defaultTestCaseTimeout = 8 * time.Minute // as go test limits to 10 min by default

// Case is a worker test case
type Case struct {
	Engine            string        // Engine to be used
	EngineConfig      string        // Engine configuration as JSON
	PluginConfig      string        // Configuration of plugins, see plugins.PluginManagerConfigSchema()
	Setup             SetupFunc     // Function to setup local environment, return a cleanup function
	Tasks             TasksFunc     // Function that returns a list of tasks to create and associated assertions
	Concurrency       int           // Worker concurrency, if zero defaulted to 1 and tasks will sequantially dependent
	StoppedGracefully bool          // True, if worker is expected to stop gracefully
	StoppedNow        bool          // True, if worker is expected to stop now
	Timeout           time.Duration // Test timeout, defaults to 8 Minutes
	EnableSuperseding bool          // Enable superseding in the worker
}

// Environment holds values that can be accessed in callbacks
type Environment struct {
	Worker   runtime.Stoppable
	Queue    *tcqueue.Queue
	Listener fakequeue.Listener
}

// A SetupFunc callback can setup the local environment, this includes starting
// servers running on localhost. The SetupFunc callback returns a cleanup function
// that will be invoked when tests are done.
type SetupFunc func(t *testing.T, env Environment) func()

// A TasksFunc callback returns the tasks to be created and associated assertions.
//
// For test cases that uses a static list of tasks, Tasks([]task{...}) function
// can be used to wrap a static []Task list.
type TasksFunc func(t *testing.T, env Environment) []Task

// Tasks is a quick wrapper for constructing a TasksFunc that always returns
// a static list of tasks.
func Tasks(tasks []Task) TasksFunc {
	return func(*testing.T, Environment) []Task {
		return tasks
	}
}

// A Task to be included in a worker test case
type Task struct {
	TaskID          string                  // Optional taskID (use slugid.Nice())
	Title           string                  // Optional title (for debugging)
	Scopes          []string                // Task scopes
	Payload         string                  // Task payload as JSON
	IgnoreState     bool                    // Ignore Success and Exception
	Success         bool                    // True, if task should be successfully
	Exception       runtime.ExceptionReason // Reason, if exception is expected
	Artifacts       ArtifactAssertions      // Mapping from artifact name to assertion
	AllowAdditional bool                    // True, if additional artifacts is allowed
	Status          StatusAssertion         // Optional, custom assertion on status and queue
}

// A StatusAssertion is a function that can make an assertion on a task status
type StatusAssertion func(t *testing.T, q *tcqueue.Queue, status tcqueue.TaskStatusStructure)

// An ArtifactAssertions is a mapping from artifact name to assertion for the
// artifact. If mapping to nil value, any artifact will be permitted.
type ArtifactAssertions map[string]func(t *testing.T, a Artifact)

// Artifact contains artifact meta-data.
type Artifact struct {
	ContentType     string
	Expires         time.Time
	Name            string
	StorageType     string
	Data            []byte
	ContentEncoding string
}

// provisionerId/workerType for test cases, access granted by role:
//   assume:project:taskcluster:worker-test-scopes
var dummyProvisionerID = "test-dummy-provisioner"

func dummyWorkerType() string {
	return "dummy-worker-" + slugid.V4()[:9]
}

// TestWithFakeQueue runs integration tests against FakeQueue
func (c Case) TestWithFakeQueue(t *testing.T) {
	// Create FakeQueue
	fq := fakequeue.New()
	s := httptest.NewServer(fq)
	defer s.Close()

	// Create listener
	l := fakequeue.NewFakeQueueListener(fq)

	// Create queue client
	q := tcqueue.New(&tcclient.Credentials{
		// Long enough to pass schema validation
		ClientID:    "dummy-test-client-id",
		AccessToken: "non-secret-dummy-test-access-token",
	})
	q.BaseURL = s.URL

	// Use localhost for webhookserver
	webHookServerConfig := `{
		"provider": "localhost"
	}`

	c.testWithQueue(t, q, l, webHookServerConfig)
}

// TestWithRealQueue runs integration tests against production queue
func (c Case) TestWithRealQueue(t *testing.T) {
	u := os.Getenv("PULSE_USERNAME")
	p := os.Getenv("PULSE_PASSWORD")
	if u == "" || p == "" {
		t.Skip("Skipping integration tests, because PULSE_USERNAME and PULSE_PASSWORD are not specified")
	}

	if testing.Short() {
		t.Skip("Skipping integration tests in short mode")
	}

	// Create listener
	l, err := fakequeue.NewPulseListener(u, p)
	require.NoError(t, err, "Failed to create PulseListener")

	// Create queue client
	q := tcqueue.New(&tcclient.Credentials{
		ClientID:    os.Getenv("TASKCLUSTER_CLIENT_ID"),
		AccessToken: os.Getenv("TASKCLUSTER_ACCESS_TOKEN"),
		Certificate: os.Getenv("TASKCLUSTER_CERTIFICATE"),
	})
	if os.Getenv("QUEUE_BASE_URL") != "" {
		q.BaseURL = os.Getenv("QUEUE_BASE_URL")
	}

	// Use webhooktunnel for webhookserver
	webHookServerConfig := `{
		"provider": "webhooktunnel"
	}`

	c.testWithQueue(t, q, l, webHookServerConfig)
}

// Test runs the test case
func (c Case) Test(t *testing.T) {
	passedFake := t.Run("FakeQueue", c.TestWithFakeQueue)
	// We don't run real integration tests if the FakeQueue tests fails
	// This is aimed to avoid polluting the queue and reducing feedback cycle.
	// You can manually call TestWithRealQueue(t), if you want to debug it.
	if passedFake {
		t.Run("RealQueue", c.TestWithRealQueue)
	} else {
		t.Run("RealQueue", func(t *testing.T) {
			t.Skip("Skipping integration tests, because FakeQueue tests failed")
		})
	}
}

func mustUnmarshalJSON(data string) interface{} {
	var v interface{}
	err := json.Unmarshal([]byte(data), &v)
	if err != nil {
		panic(fmt.Sprintf("Failed to parse JSON, error: %s, json: '%s'", err, data))
	}
	return v
}

func (c Case) testWithQueue(t *testing.T, q *tcqueue.Queue, l fakequeue.Listener, webHookServerConfig string) {
	// Run initial config
	if c.Setup != nil {
		cleanup := c.Setup(t, Environment{
			Listener: l,
			Queue:    q,
			Worker:   nil, // not available in the setup stage
		})
		if cleanup != nil {
			defer cleanup()
		}
	}

	// Create config
	tempFolder := path.Join(os.TempDir(), slugid.Nice())
	defer os.RemoveAll(tempFolder)
	concurrency := c.Concurrency
	if concurrency == 0 {
		concurrency = 1
	}
	creds := map[string]interface{}{
		"clientId":    q.Credentials.ClientID,
		"accessToken": q.Credentials.AccessToken,
	}
	if q.Credentials.Certificate != "" {
		creds["certificate"] = q.Credentials.Certificate
	}
	workerID := "dummy-worker-" + slugid.V4()[:9]
	workerType := dummyWorkerType()
	config := map[string]interface{}{
		"credentials": creds,
		"engine":      c.Engine,
		"engines": map[string]interface{}{
			c.Engine: mustUnmarshalJSON(c.EngineConfig),
		},
		"minimumDiskSpace": 0,
		"minimumMemory":    0,
		"monitor":          mustUnmarshalJSON(`{"panicOnError": false, "type": "mock"}`),
		"plugins":          mustUnmarshalJSON(c.PluginConfig),
		"queueBaseUrl":     q.BaseURL,
		"temporaryFolder":  tempFolder,
		"webHookServer":    mustUnmarshalJSON(webHookServerConfig),
		"worker": map[string]interface{}{
			"concurrency":         concurrency,
			"minimumReclaimDelay": 30,
			"pollingInterval":     1,
			"reclaimOffset":       30,
			"workerGroup":         "test-dummy-workers",
			"workerId":            workerID,
			"provisionerId":       dummyProvisionerID,
			"workerType":          workerType,
			"enableSuperseding":   c.EnableSuperseding,
		},
	}
	err := worker.ConfigSchema().Validate(config)
	require.NoError(t, err, "Failed to validate worker config against schema")

	// Create worker
	w, err := worker.New(config)
	require.NoError(t, err, "Failed to create worker")

	// Generate the tasks
	require.NotNil(t, c.Tasks, "Case.Tasks must be defined")
	tasks := c.Tasks(t, Environment{
		Listener: l,
		Queue:    q,
		Worker:   w,
	})

	// Create taskIDs
	taskIDs := make([]string, len(tasks))
	for i := range taskIDs {
		if tasks[i].TaskID != "" {
			taskIDs[i] = tasks[i].TaskID
		} else {
			taskIDs[i] = slugid.Nice()
		}
	}

	// Setup event listeners
	events := make([]<-chan error, len(tasks))
	util.Spawn(len(tasks), func(i int) {
		events[i] = l.WaitForTask(taskIDs[i])
	})

	// Wait for tasks to be resolved
	var tasksResolved atomics.Once
	go tasksResolved.Do(func() {
		// Wait for events
		debug("Waiting for tasks to be resolved")
		util.Spawn(len(tasks), func(i int) {
			err := <-events[i]
			assert.NoError(t, err, "Failed to listen for task %d", i)
			debug("Finished waiting for %s", taskIDs[i])
			if err != nil {
				debug("Error '%s' waiting for %s", taskIDs[i], err)
			}
		})
	})

	// Create task definitions
	tdefs := make([]*tcqueue.TaskDefinitionRequest, len(taskIDs))
	for i, task := range tasks {
		tdefs[i] = &tcqueue.TaskDefinitionRequest{
			ProvisionerID: dummyProvisionerID,
			WorkerType:    workerType,
			Created:       tcclient.Time(time.Now()),
			Deadline:      tcclient.Time(time.Now().Add(60 * time.Minute)),
			Expires:       tcclient.Time(time.Now().Add(31 * 24 * 60 * time.Minute)),
			Payload:       json.RawMessage(task.Payload),
		}
		// If tasks are to run sequantially, we'll make them dependent
		if c.Concurrency == 0 && i > 0 {
			tdefs[i].Dependencies = []string{taskIDs[i-1]}
			tdefs[i].Requires = "all-resolved"
		}
		title := task.Title
		if title == "" {
			title = fmt.Sprintf("Task %d", i)
		}
		tdefs[i].Scopes = task.Scopes
		tdefs[i].Metadata.Name = title
		tdefs[i].Metadata.Description = "Task from taskcluster-worker integration tests"
		tdefs[i].Metadata.Source = "https://github.com/taskcluster/taskcluster-worker/tree/master/worker/workertest/workertest.go"
		tdefs[i].Metadata.Owner = "jonasfj@mozilla.com"
	}

	// Create tasks asynchronously with a limit of 10 concurrent calls to make
	// that it goes fairly faster, when there is a lot of tasks.
	limit := 10
	if c.Concurrency == 0 {
		limit = 1
	}
	errs := make([]error, len(taskIDs))
	util.SpawnWithLimit(len(taskIDs), limit, func(i int) {
		debug("creating task '%s' as taskId: %s", tdefs[i].Metadata.Name, taskIDs[i])
		_, errs[i] = q.CreateTask(taskIDs[i], tdefs[i])
	})
	// Check error status for all tasks
	for i, tdef := range tdefs {
		require.NoError(t, errs[i], "Failed to create task: %s", tdef.Metadata.Name)
	}

	// Start worker
	var serr error
	var stopped atomics.Once
	go stopped.Do(func() {
		debug("starting worker with workerType: %s and workerID: %s", workerType, workerID)
		serr = w.Start()
		debug("worker stopped")
	})

	// Wait for events to have been handled
	timeout := c.Timeout
	if timeout == 0 {
		timeout = defaultTestCaseTimeout
	}
	select {
	case <-tasksResolved.Done():
	case <-time.After(timeout):
		assert.Fail(t, "Test case timed out, see workertest.Case.Timeout Property!")
		debug("worker.StopNow() because of test case timeout")
		w.StopNow()
		// We give it 30s to stop now, otherwise we end the test-case
		select {
		case <-stopped.Done():
		case <-time.After(30 * time.Second):
			debug("worker.StopNow() didn't stop after 30s")
		}
		return
	}

	// if we expect the worker to stop then we don't want to stop it here
	if !c.StoppedGracefully && !c.StoppedNow {
		// Stop worker
		debug("gracefully stopping worker (since test-case isn't stopping the worker)")
		w.StopGracefully()
	}

	// Wait for the worker to stop
	select {
	case <-stopped.Done():
	case <-time.After(30 * time.Second):
		assert.Fail(t, "Expected worker to stop")
	}

	// Verify assertions
	// We must do this after the worker has stopped, since tasks resolved
	// with exception can have artifacts added after resolution.
	debug("Verifying task assertions")
	// We could run these in parallel, but debugging is easier if we don't...
	for i, task := range tasks {
		title := task.Title
		if title == "" {
			title = fmt.Sprintf("Task %d", i)
		}
		t.Run(title, func(t *testing.T) {
			verifyAssertions(t, title, taskIDs[i], task, q)
		})
	}

	// Check the stopping condition
	if c.StoppedNow {
		assert.Exactly(t, worker.ErrWorkerStoppedNow, serr, "Expected StoppedNow!")
	} else {
		assert.NoError(t, serr, "Expected worker to stop gracefully")
	}
}
<|endoftext|>