<commit_before>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package leadership

import (
	"github.com/juju/errors"
)

// token implements leadership.Token.
type token struct {
	leaseName  string
	holderName string
	secretary  Secretary
	checks     chan<- check
	abort      <-chan struct{}
}

// Check is part of the leadership.Token interface.
func (t token) Check(trapdoorKey interface{}) error {

	// This validation, which could be done at Token creation time, is deferred
	// until this point so as not to pollute the LeadershipCheck signature with
	// an error that might cause clients to assume LeadershipCheck actually
	// checked leadership.
	//
	// Um, we should probably name it something different, shouldn't we?
	if err := t.secretary.CheckLease(t.leaseName); err != nil {
		return errors.Annotatef(err, "cannot check lease %q", t.leaseName)
	}
	if err := t.secretary.CheckHolder(t.holderName); err != nil {
		return errors.Annotatef(err, "cannot check holder %q", t.holderName)
	}
	return check{
		leaseName:   t.leaseName,
		holderName:  t.holderName,
		trapdoorKey: trapdoorKey,
		response:    make(chan error),
		abort:       t.abort,
	}.invoke(t.checks)
}

// check is used to deliver leadership-check requests to a manager's loop
// goroutine on behalf of a token (as returned by LeadershipCheck).
type check struct {
	leaseName   string
	holderName  string
	trapdoorKey interface{}
	response    chan error
	abort       <-chan struct{}
}

// invoke sends the check on the supplied channel, waits for a response, and
// returns either a txn.Op that can be used to assert continued leadership in
// the future, or an error.
func (c check) invoke(ch chan<- check) error {
	for {
		select {
		case <-c.abort:
			return errStopped
		case ch <- c:
			ch = nil
		case err := <-c.response:
			if err == ErrLeaseNotHeld {
				return errors.Errorf("%q is not leader of %q", c.holderName, c.leaseName)
			}
			return errors.Trace(err)
		}
	}
}

// respond notifies the originating invoke of completion status.
func (c check) respond(err error) {
	select {
	case <-c.abort:
	case c.response <- err:
	}
}
<commit_msg>fix comment<commit_after>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package leadership

import (
	"github.com/juju/errors"
)

// token implements leadership.Token.
type token struct {
	leaseName  string
	holderName string
	secretary  Secretary
	checks     chan<- check
	abort      <-chan struct{}
}

// Check is part of the leadership.Token interface.
func (t token) Check(trapdoorKey interface{}) error {

	// This validation, which could be done at Token creation time, is deferred
	// until this point so as not to pollute the LeadershipCheck signature with
	// an error that might cause clients to assume LeadershipCheck actually
	// checked leadership.
	//
	// Um, we should probably name it something different, shouldn't we?
	if err := t.secretary.CheckLease(t.leaseName); err != nil {
		return errors.Annotatef(err, "cannot check lease %q", t.leaseName)
	}
	if err := t.secretary.CheckHolder(t.holderName); err != nil {
		return errors.Annotatef(err, "cannot check holder %q", t.holderName)
	}
	return check{
		leaseName:   t.leaseName,
		holderName:  t.holderName,
		trapdoorKey: trapdoorKey,
		response:    make(chan error),
		abort:       t.abort,
	}.invoke(t.checks)
}

// check is used to deliver leadership-check requests to a manager's loop
// goroutine on behalf of a token (as returned by LeadershipCheck).
type check struct {
	leaseName   string
	holderName  string
	trapdoorKey interface{}
	response    chan error
	abort       <-chan struct{}
}

// invoke sends the check on the supplied channel and waits for an error
// response.
func (c check) invoke(ch chan<- check) error {
	for {
		select {
		case <-c.abort:
			return errStopped
		case ch <- c:
			ch = nil
		case err := <-c.response:
			if err == ErrLeaseNotHeld {
				return errors.Errorf("%q is not leader of %q", c.holderName, c.leaseName)
			}
			return errors.Trace(err)
		}
	}
}

// respond notifies the originating invoke of completion status.
func (c check) respond(err error) {
	select {
	case <-c.abort:
	case c.response <- err:
	}
}
<|endoftext|>


<commit_before>package statsd

import (
	"fmt"
	"math/rand"
	"sync"
	"testing"
	"time"

	"github.com/atlassian/gostatsd/types"

	"golang.org/x/net/context"
)

type testAggregator struct {
	agrNumber int
	af        *testAggregatorFactory
	types.MetricMap
}

func (a *testAggregator) Receive(m *types.Metric, t time.Time) {
	a.af.Mutex.Lock()
	defer a.af.Mutex.Unlock()
	a.af.receiveInvocations[a.agrNumber]++
}

func (a *testAggregator) Flush(f func() time.Time) *types.MetricMap {
	a.af.Mutex.Lock()
	defer a.af.Mutex.Unlock()
	a.af.flushInvocations[a.agrNumber]++
	return nil
}

func (a *testAggregator) Process(f ProcessFunc) {
	a.af.Mutex.Lock()
	defer a.af.Mutex.Unlock()
	a.af.processInvocations[a.agrNumber]++
	f(&a.MetricMap)
}

func (a *testAggregator) Reset(t time.Time) {
	a.af.Mutex.Lock()
	defer a.af.Mutex.Unlock()
	a.af.resetInvocations[a.agrNumber]++
}

type testAggregatorFactory struct {
	sync.Mutex
	receiveInvocations map[int]int
	flushInvocations   map[int]int
	processInvocations map[int]int
	resetInvocations   map[int]int
	numAgrs            int
}

func (af *testAggregatorFactory) Create() Aggregator {
	agrNumber := af.numAgrs
	af.numAgrs++
	af.receiveInvocations[agrNumber] = 0
	af.flushInvocations[agrNumber] = 0
	af.processInvocations[agrNumber] = 0
	af.resetInvocations[agrNumber] = 0

	agr := testAggregator{
		agrNumber: agrNumber,
		af:        af,
	}
	agr.Counters = types.Counters{}
	agr.Timers = types.Timers{}
	agr.Gauges = types.Gauges{}
	agr.Sets = types.Sets{}

	return &agr
}

func newTestFactory() *testAggregatorFactory {
	return &testAggregatorFactory{
		receiveInvocations: make(map[int]int),
		flushInvocations:   make(map[int]int),
		processInvocations: make(map[int]int),
		resetInvocations:   make(map[int]int),
	}
}

func TestNewDispatcherShouldCreateCorrectNumberOfWorkers(t *testing.T) {
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	n := r.Intn(5) + 1
	factory := newTestFactory()
	d := NewDispatcher(n, 1, factory).(*dispatcher)
	if len(d.workers) != n {
		t.Errorf("workers: expected %d, got %d", n, len(d.workers))
	}
	if factory.numAgrs != n {
		t.Errorf("aggregators: expected %d, got %d", n, factory.numAgrs)
	}
}

func TestRunShouldReturnWhenContextCancelled(t *testing.T) {
	d := NewDispatcher(5, 1, newTestFactory())
	ctx, cancelFunc := context.WithTimeout(context.Background(), 1*time.Second)
	defer cancelFunc()

	err := d.Run(ctx)
	if err != context.DeadlineExceeded {
		t.Errorf("expected %v, got %v", context.DeadlineExceeded, err)
	}
}

func TestDispatchMetricShouldDistributeMetrics(t *testing.T) {
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	n := r.Intn(5) + 1
	factory := newTestFactory()
	d := NewDispatcher(n, 10, factory).(*dispatcher)
	ctx, cancelFunc := context.WithCancel(context.Background())
	defer cancelFunc()
	var wgFinish sync.WaitGroup
	wgFinish.Add(1)
	go func() {
		defer wgFinish.Done()
		if err := d.Run(ctx); err != context.Canceled {
			t.Errorf("unexpected exit error: %v", err)
		}
	}()
	numMetrics := r.Intn(1000)
	var wg sync.WaitGroup
	wg.Add(numMetrics)
	for i := 0; i < numMetrics; i++ {
		m := &types.Metric{
			Type:  types.COUNTER,
			Name:  fmt.Sprintf("counter.metric.%d", r.Int63()),
			Tags:  nil,
			Value: r.Float64(),
		}
		go func() {
			defer wg.Done()
			if err := d.DispatchMetric(ctx, m); err != nil {
				t.Errorf("unexpected error: %v", err)
			}
		}()
	}
	wg.Wait()       // Wait for all metrics to be dispatched
	cancelFunc()    // After all metrics have been dispatched, we signal dispatcher to shut down
	wgFinish.Wait() // Wait for dispatcher to shutdown

	receiveInvocations := getTotalInvocations(factory.receiveInvocations)
	if numMetrics != receiveInvocations {
		t.Errorf("expected number of receiver metrics: %d, got %d", numMetrics, receiveInvocations)
	}
}

func getTotalInvocations(inv map[int]int) int {
	var counter int
	for _, i := range inv {
		counter += i
	}
	return counter
}
<commit_msg>Dispatcher benchmark<commit_after>package statsd

import (
	"fmt"
	"math/rand"
	"runtime"
	"sync"
	"testing"
	"time"

	"github.com/atlassian/gostatsd/types"

	"golang.org/x/net/context"
)

type testAggregator struct {
	agrNumber int
	af        *testAggregatorFactory
	types.MetricMap
}

func (a *testAggregator) Receive(m *types.Metric, t time.Time) {
	a.af.Mutex.Lock()
	a.af.receiveInvocations[a.agrNumber]++
	a.af.Mutex.Unlock()
}

func (a *testAggregator) Flush(f func() time.Time) *types.MetricMap {
	a.af.Mutex.Lock()
	a.af.flushInvocations[a.agrNumber]++
	a.af.Mutex.Unlock()
	return nil
}

func (a *testAggregator) Process(f ProcessFunc) {
	a.af.Mutex.Lock()
	defer a.af.Mutex.Unlock()
	a.af.processInvocations[a.agrNumber]++
	f(&a.MetricMap)
}

func (a *testAggregator) Reset(t time.Time) {
	a.af.Mutex.Lock()
	a.af.resetInvocations[a.agrNumber]++
	a.af.Mutex.Unlock()
}

type testAggregatorFactory struct {
	sync.Mutex
	receiveInvocations map[int]int
	flushInvocations   map[int]int
	processInvocations map[int]int
	resetInvocations   map[int]int
	numAgrs            int
}

func (af *testAggregatorFactory) Create() Aggregator {
	agrNumber := af.numAgrs
	af.numAgrs++
	af.receiveInvocations[agrNumber] = 0
	af.flushInvocations[agrNumber] = 0
	af.processInvocations[agrNumber] = 0
	af.resetInvocations[agrNumber] = 0

	agr := testAggregator{
		agrNumber: agrNumber,
		af:        af,
	}
	agr.Counters = types.Counters{}
	agr.Timers = types.Timers{}
	agr.Gauges = types.Gauges{}
	agr.Sets = types.Sets{}

	return &agr
}

func newTestFactory() *testAggregatorFactory {
	return &testAggregatorFactory{
		receiveInvocations: make(map[int]int),
		flushInvocations:   make(map[int]int),
		processInvocations: make(map[int]int),
		resetInvocations:   make(map[int]int),
	}
}

func TestNewDispatcherShouldCreateCorrectNumberOfWorkers(t *testing.T) {
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	n := r.Intn(5) + 1
	factory := newTestFactory()
	d := NewDispatcher(n, 1, factory).(*dispatcher)
	if len(d.workers) != n {
		t.Errorf("workers: expected %d, got %d", n, len(d.workers))
	}
	if factory.numAgrs != n {
		t.Errorf("aggregators: expected %d, got %d", n, factory.numAgrs)
	}
}

func TestRunShouldReturnWhenContextCancelled(t *testing.T) {
	d := NewDispatcher(5, 1, newTestFactory())
	ctx, cancelFunc := context.WithTimeout(context.Background(), 1*time.Second)
	defer cancelFunc()

	err := d.Run(ctx)
	if err != context.DeadlineExceeded {
		t.Errorf("expected %v, got %v", context.DeadlineExceeded, err)
	}
}

func TestDispatchMetricShouldDistributeMetrics(t *testing.T) {
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	n := r.Intn(5) + 1
	factory := newTestFactory()
	d := NewDispatcher(n, 10, factory).(*dispatcher)
	ctx, cancelFunc := context.WithCancel(context.Background())
	defer cancelFunc()
	var wgFinish sync.WaitGroup
	wgFinish.Add(1)
	go func() {
		defer wgFinish.Done()
		if err := d.Run(ctx); err != context.Canceled {
			t.Errorf("unexpected exit error: %v", err)
		}
	}()
	numMetrics := r.Intn(1000)
	var wg sync.WaitGroup
	wg.Add(numMetrics)
	for i := 0; i < numMetrics; i++ {
		m := &types.Metric{
			Type:  types.COUNTER,
			Name:  fmt.Sprintf("counter.metric.%d", r.Int63()),
			Tags:  nil,
			Value: r.Float64(),
		}
		go func() {
			defer wg.Done()
			if err := d.DispatchMetric(ctx, m); err != nil {
				t.Errorf("unexpected error: %v", err)
			}
		}()
	}
	wg.Wait()       // Wait for all metrics to be dispatched
	cancelFunc()    // After all metrics have been dispatched, we signal dispatcher to shut down
	wgFinish.Wait() // Wait for dispatcher to shutdown

	receiveInvocations := getTotalInvocations(factory.receiveInvocations)
	if numMetrics != receiveInvocations {
		t.Errorf("expected number of receiver metrics: %d, got %d", numMetrics, receiveInvocations)
	}
}

func getTotalInvocations(inv map[int]int) int {
	var counter int
	for _, i := range inv {
		counter += i
	}
	return counter
}

func BenchmarkDispatcher(b *testing.B) {
	rand.Seed(time.Now().UnixNano())
	factory := newTestFactory()
	d := NewDispatcher(runtime.NumCPU(), 10, factory).(*dispatcher)
	ctx, cancelFunc := context.WithCancel(context.Background())
	defer cancelFunc()
	var wgFinish sync.WaitGroup
	wgFinish.Add(1)
	go func() {
		defer wgFinish.Done()
		if err := d.Run(ctx); err != context.Canceled {
			b.Errorf("unexpected exit error: %v", err)
		}
	}()
	b.ReportAllocs()
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			m := &types.Metric{
				Type:  types.COUNTER,
				Name:  fmt.Sprintf("counter.metric.%d", rand.Int63()),
				Tags:  nil,
				Value: rand.Float64(),
			}
			if err := d.DispatchMetric(ctx, m); err != nil {
				b.Errorf("unexpected error: %v", err)
			}
		}
	})
	cancelFunc()    // After all metrics have been dispatched, we signal dispatcher to shut down
	wgFinish.Wait() // Wait for dispatcher to shutdown
}
<|endoftext|>


<commit_before>package models

import (
	"errors"
	"fmt"
	"log"
	"reflect"
	"strings"

	"github.com/astaxie/beego/orm"
	"github.com/astaxie/beego/validation"
)

type Isla struct {
	Id          int        `orm:"column(id);pk;auto"`
	Ocupado     bool       `orm:"column(ocupado)"`
	IdVehiculo  *Vehiculo  `orm:"column(id_vehiculo);rel(fk)"`
	Geometria   string     `orm:"column(geometria)"`
	IdGrupoIsla *GrupoIsla `orm:"column(id_grupo_isla);rel(fk)"`
}

func (t *Isla) TableName() string {
	return "isla"
}

func init() {
	orm.RegisterModel(new(Isla))
}

// AddIsla insert a new Isla into database and returns
// last inserted Id on success.
func AddIsla(m *Isla) (id int64, err error) {
	o := orm.NewOrm()
	valid := validation.Validation{}
	valid.Required(m.Ocupado, "Ocupado")
	valid.Required(m.Geometria, "Geometria")
	if valid.HasErrors() {
		for _, err := range valid.Errors {
			log.Println(err.Key, err.Message)
		}
	} else {
		log.Println("Insert New Register")
		m.IdGrupoIsla, _ = GetGrupoIslaById(m.IdGrupoIsla.Id)
		id, err = o.Insert(m)
	}
	return
}

// GetIslaById retrieves Isla by Id. Returns error if
// Id doesn't exist
func GetIslaById(id int) (v *Isla, err error) {
	o := orm.NewOrm()
	v = &Isla{Id: id}
	if err = o.Read(v); err == nil {
		v.IdGrupoIsla, _ = GetGrupoIslaById(v.IdGrupoIsla.Id)
		return v, nil
	}
	return nil, err
}

// GetAllIsla retrieves all Isla matches certain condition. Returns empty list if
// no records exist
func GetAllIsla(query map[string]string, fields []string, sortby []string, order []string,
	offset int64, limit int64) (ml []interface{}, err error) {
	o := orm.NewOrm()
	qs := o.QueryTable(new(Isla))
	// query k=v
	for k, v := range query {
		// rewrite dot-notation to Object__Attribute
		k = strings.Replace(k, ".", "__", -1)
		qs = qs.Filter(k, v)
	}
	// order by:
	var sortFields []string
	if len(sortby) != 0 {
		if len(sortby) == len(order) {
			// 1) for each sort field, there is an associated order
			for i, v := range sortby {
				orderby := ""
				if order[i] == "desc" {
					orderby = "-" + v
				} else if order[i] == "asc" {
					orderby = v
				} else {
					return nil, errors.New("Error: Invalid order. Must be either [asc|desc]")
				}
				sortFields = append(sortFields, orderby)
			}
			qs = qs.OrderBy(sortFields...)
		} else if len(sortby) != len(order) && len(order) == 1 {
			// 2) there is exactly one order, all the sorted fields will be sorted by this order
			for _, v := range sortby {
				orderby := ""
				if order[0] == "desc" {
					orderby = "-" + v
				} else if order[0] == "asc" {
					orderby = v
				} else {
					return nil, errors.New("Error: Invalid order. Must be either [asc|desc]")
				}
				sortFields = append(sortFields, orderby)
			}
		} else if len(sortby) != len(order) && len(order) != 1 {
			return nil, errors.New("Error: 'sortby', 'order' sizes mismatch or 'order' size is not 1")
		}
	} else {
		if len(order) != 0 {
			return nil, errors.New("Error: unused 'order' fields")
		}
	}

	var l []Isla
	qs = qs.OrderBy("id")
	if _, err := qs.Limit(limit, offset).All(&l, fields...); err == nil {
		if len(fields) == 0 {
			for _, v := range l {
				v.IdGrupoIsla, _ = GetGrupoIslaById(v.IdGrupoIsla.Id)
				ml = append(ml, v)
			}
		} else {
			// trim unused fields
			for _, v := range l {
				m := make(map[string]interface{})
				val := reflect.ValueOf(v)
				for _, fname := range fields {
					m[fname] = val.FieldByName(fname).Interface()
				}
				ml = append(ml, m)
			}
		}
		return ml, nil
	}
	return nil, err
}

// UpdateIsla updates Isla by Id and returns error if
// the record to be updated doesn't exist
func UpdateIslaById(m *Isla) (err error) {
	o := orm.NewOrm()
	v := Isla{Id: m.Id}
	// ascertain id exists in the database
	if err = o.Read(&v); err == nil {
		var num int64
		if num, err = o.Update(m); err == nil {
			fmt.Println("Number of records updated in database:", num)
		}
	}
	return
}

// DeleteIsla deletes Isla by Id and returns error if
// the record to be deleted doesn't exist
func DeleteIsla(id int) (err error) {
	o := orm.NewOrm()
	v := Isla{Id: id}
	// ascertain id exists in the database
	if err = o.Read(&v); err == nil {
		var num int64
		if num, err = o.Delete(&Isla{Id: id}); err == nil {
			fmt.Println("Number of records deleted in database:", num)
		}
	}
	return
}
<commit_msg>Se actualiza el ORM de isla con la gestion de los datos que corresponden a esta tabla<commit_after>package models

import (
	"errors"
	"fmt"
	"log"
	"reflect"
	"strings"

	"github.com/astaxie/beego/orm"
	"github.com/astaxie/beego/validation"
)

type Isla struct {
	Id          int        `orm:"column(id);pk;auto"`
	Ocupado     bool       `orm:"column(ocupado)"`
	Geometria   string     `orm:"column(geometria)"`
	IdGrupoIsla *GrupoIsla `orm:"column(id_grupo_isla);rel(fk)"`
}

func (t *Isla) TableName() string {
	return "isla"
}

func init() {
	orm.RegisterModel(new(Isla))
}

// AddIsla insert a new Isla into database and returns
// last inserted Id on success.
func AddIsla(m *Isla) (id int64, err error) {
	o := orm.NewOrm()
	valid := validation.Validation{}
	valid.Required(m.Ocupado, "Ocupado")
	valid.Required(m.Geometria, "Geometria")
	if valid.HasErrors() {
		for _, err := range valid.Errors {
			log.Println(err.Key, err.Message)
		}
	} else {
		log.Println("Insert New Register")
		m.IdGrupoIsla, _ = GetGrupoIslaById(m.IdGrupoIsla.Id)
		id, err = o.Insert(m)
	}
	return
}

// GetIslaById retrieves Isla by Id. Returns error if
// Id doesn't exist
func GetIslaById(id int) (v *Isla, err error) {
	o := orm.NewOrm()
	v = &Isla{Id: id}
	if err = o.Read(v); err == nil {
		v.IdGrupoIsla, _ = GetGrupoIslaById(v.IdGrupoIsla.Id)
		return v, nil
	}
	return nil, err
}

// GetAllIsla retrieves all Isla matches certain condition. Returns empty list if
// no records exist
func GetAllIsla(query map[string]string, fields []string, sortby []string, order []string,
	offset int64, limit int64) (ml []interface{}, err error) {
	o := orm.NewOrm()
	qs := o.QueryTable(new(Isla))
	// query k=v
	for k, v := range query {
		// rewrite dot-notation to Object__Attribute
		k = strings.Replace(k, ".", "__", -1)
		qs = qs.Filter(k, v)
	}
	// order by:
	var sortFields []string
	if len(sortby) != 0 {
		if len(sortby) == len(order) {
			// 1) for each sort field, there is an associated order
			for i, v := range sortby {
				orderby := ""
				if order[i] == "desc" {
					orderby = "-" + v
				} else if order[i] == "asc" {
					orderby = v
				} else {
					return nil, errors.New("Error: Invalid order. Must be either [asc|desc]")
				}
				sortFields = append(sortFields, orderby)
			}
			qs = qs.OrderBy(sortFields...)
		} else if len(sortby) != len(order) && len(order) == 1 {
			// 2) there is exactly one order, all the sorted fields will be sorted by this order
			for _, v := range sortby {
				orderby := ""
				if order[0] == "desc" {
					orderby = "-" + v
				} else if order[0] == "asc" {
					orderby = v
				} else {
					return nil, errors.New("Error: Invalid order. Must be either [asc|desc]")
				}
				sortFields = append(sortFields, orderby)
			}
		} else if len(sortby) != len(order) && len(order) != 1 {
			return nil, errors.New("Error: 'sortby', 'order' sizes mismatch or 'order' size is not 1")
		}
	} else {
		if len(order) != 0 {
			return nil, errors.New("Error: unused 'order' fields")
		}
	}

	var l []Isla
	qs = qs.OrderBy("id")
	if _, err := qs.Limit(limit, offset).All(&l, fields...); err == nil {
		if len(fields) == 0 {
			for _, v := range l {
				v.IdGrupoIsla, _ = GetGrupoIslaById(v.IdGrupoIsla.Id)
				ml = append(ml, v)
			}
		} else {
			// trim unused fields
			for _, v := range l {
				m := make(map[string]interface{})
				val := reflect.ValueOf(v)
				for _, fname := range fields {
					m[fname] = val.FieldByName(fname).Interface()
				}
				ml = append(ml, m)
			}
		}
		return ml, nil
	}
	return nil, err
}

// UpdateIsla updates Isla by Id and returns error if
// the record to be updated doesn't exist
func UpdateIslaById(m *Isla) (err error) {
	o := orm.NewOrm()
	v := Isla{Id: m.Id}
	// ascertain id exists in the database
	if err = o.Read(&v); err == nil {
		var num int64
		if num, err = o.Update(m); err == nil {
			fmt.Println("Number of records updated in database:", num)
		}
	}
	return
}

// DeleteIsla deletes Isla by Id and returns error if
// the record to be deleted doesn't exist
func DeleteIsla(id int) (err error) {
	o := orm.NewOrm()
	v := Isla{Id: id}
	// ascertain id exists in the database
	if err = o.Read(&v); err == nil {
		var num int64
		if num, err = o.Delete(&Isla{Id: id}); err == nil {
			fmt.Println("Number of records deleted in database:", num)
		}
	}
	return
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"os"
	"os/signal"
	"syscall"
	"time"

	newrelic "github.com/svdberg/syncmysport-runkeeper/Godeps/_workspace/src/github.com/newrelic/go-agent"
	rk "github.com/svdberg/syncmysport-runkeeper/runkeeper"
	stv "github.com/svdberg/syncmysport-runkeeper/strava"
	sync "github.com/svdberg/syncmysport-runkeeper/sync"
	shared "github.com/svdberg/syncmysport-runkeeper/syncmysport-shared"

	log "github.com/svdberg/syncmysport-runkeeper/Godeps/_workspace/src/github.com/Sirupsen/logrus"
	"github.com/svdberg/syncmysport-runkeeper/Godeps/_workspace/src/github.com/bgentry/que-go"
	"github.com/svdberg/syncmysport-runkeeper/Godeps/_workspace/src/github.com/jackc/pgx"
)

var (
	qc      *que.Client
	pgxpool *pgx.ConnPool
	app     newrelic.Application
)

const tsDelta = -45 //minutes
const maxRetriesForJob = 2

func init() {
	key := os.Getenv("NEW_RELIC_KEY")
	if key != "" {
		config := newrelic.NewConfig("SyncMySport-worker", key)
		var err error
		app, err = newrelic.NewApplication(config)
		if err != nil {
			log.Info("Error creating New Relic app instance, continuing...")
		}
	}
}

// syncTaskJob would do whatever syncing is necessary in the background
func syncTaskJob(j *que.Job) error {

	//don't retry forever, this will only increase the database size and not solve anything
	if j.ErrorCount > maxRetriesForJob {
		log.WithField("jobId", string(j.ID)).WithField("errorCount", string(j.ErrorCount)).WithField("lastError", j.LastError).Error("Ignoring job because of too high error count.")
		return nil //signal job completed, even though we did nothing
	}

	dbConnectionString := os.Getenv("CLEARDB_DATABASE_URL")
	log.Debugf("syntask connection string: %s", dbConnectionString)
	repo := sync.CreateSyncDbRepo(dbConnectionString)

	var txn newrelic.Transaction
	if app != nil {
		txn = app.StartTransaction("sync-task", nil, nil)
		txn.SetName("sync job")
		defer txn.End()
	}

	var synctask sync.SyncTask
	err := json.Unmarshal(j.Args, &synctask)
	if err != nil {
		log.WithField("args", string(j.Args)).Error("Unable to unmarshal job arguments into SyncTask")
		return err
	}

	log.WithField("SyncTask", synctask).Info("Processing Synctask!")

	stvClientImpl := stv.CreateStravaClientWithSecretAndId(synctask.StravaToken, 9667, os.Getenv("STRAVA_SECRET"))
	rkClientImpl := rk.CreateRKClient(synctask.RunkeeperToken)

	//update the accesstoken if needed
	if !stvClientImpl.ValidateToken(synctask.StravaToken) {
		log.WithField("SyncTask", synctask).Info("Updating access token using refresh token...")
		access_token, refresh_token, err := stvClientImpl.RefreshToken(synctask.StravaRefreshToken)
		if err != nil {
			log.WithField("args", string(j.Args)).WithField("QueId", j.ID).Error("Error while updating access token for strava.")
			return err
		}
		synctask.StravaToken = access_token
		synctask.StravaRefreshToken = refresh_token
		repo.UpdateSyncTask(synctask)
		//re-create the client, so we use the new tokens..
		stvClientImpl = stv.CreateStravaClientWithSecretAndId(access_token, 9667, os.Getenv("STRAVA_SECRET"))
	}

	itemsCreatedRk, totalItems, err := synctask.Sync(stvClientImpl, rkClientImpl, txn)
	if err != nil {
		if app != nil {
			app.RecordCustomEvent("sync_error_event", map[string]interface{}{"error": err})
		}
		if txn != nil {
			txn.NoticeError(err)
		}
		log.WithField("args", string(j.Args)).WithField("QueId", j.ID).Error("Error while syncing synctask.")
		return err //don't update Timestamp, so we will retry
	}

	//update last executed timestamp
	log.Print("Updating last seen timestamp")
	//subtract 45 minutes to prevent activites being missed
	synctask.LastSeenTimestamp = int(time.Now().Add(time.Duration(tsDelta) * time.Minute).Unix())
	rowsUpdated, err := repo.UpdateSyncTask(synctask)
	if err != nil || rowsUpdated != 1 {
		log.Errorf("Error updating the SyncTask record with a new timestamp: %e", err)
		return err
	}

	if app != nil {
		app.RecordCustomEvent("sync_items_created", map[string]interface{}{
			"rk-items-created": itemsCreatedRk,
			"total-items":      totalItems})
	}

	log.Infof("Executed synctask %d, now deleting it.", synctask.Uid)
	return nil
}

func main() {
	log.Print("Starting worker")

	var err error
	dbURL := os.Getenv("DATABASE_URL")
	pgxpool, qc, err = shared.Setup(dbURL)
	if err != nil {
		log.WithField("DATABASE_URL", dbURL).Fatal("Errors setting up the queue / database: ", err)
	}
	defer pgxpool.Close()

	wm := que.WorkMap{
		shared.SyncTaskJob: syncTaskJob,
	}

	// 2 worker go routines
	// LIMITED to 1 per worker.. otherwise we overload Runkeeper
	// and I guess create activties twice.
	workers := que.NewWorkerPool(qc, wm, 1)

	// Catch signal so we can shutdown gracefully
	sigCh := make(chan os.Signal)
	signal.Notify(sigCh, syscall.SIGTERM, syscall.SIGINT)

	go workers.Start()

	// Wait for a signal
	sig := <-sigCh
	log.WithField("signal", sig).Info("Signal received. Shutting down.")

	workers.Shutdown()
}
<commit_msg>Fix the logging output on job retry error<commit_after>package main

import (
	"encoding/json"
	"os"
	"os/signal"
	"syscall"
	"time"

	newrelic "github.com/svdberg/syncmysport-runkeeper/Godeps/_workspace/src/github.com/newrelic/go-agent"
	rk "github.com/svdberg/syncmysport-runkeeper/runkeeper"
	stv "github.com/svdberg/syncmysport-runkeeper/strava"
	sync "github.com/svdberg/syncmysport-runkeeper/sync"
	shared "github.com/svdberg/syncmysport-runkeeper/syncmysport-shared"

	log "github.com/svdberg/syncmysport-runkeeper/Godeps/_workspace/src/github.com/Sirupsen/logrus"
	"github.com/svdberg/syncmysport-runkeeper/Godeps/_workspace/src/github.com/bgentry/que-go"
	"github.com/svdberg/syncmysport-runkeeper/Godeps/_workspace/src/github.com/jackc/pgx"
)

var (
	qc      *que.Client
	pgxpool *pgx.ConnPool
	app     newrelic.Application
)

const tsDelta = -45 //minutes
const maxRetriesForJob = 2

func init() {
	key := os.Getenv("NEW_RELIC_KEY")
	if key != "" {
		config := newrelic.NewConfig("SyncMySport-worker", key)
		var err error
		app, err = newrelic.NewApplication(config)
		if err != nil {
			log.Info("Error creating New Relic app instance, continuing...")
		}
	}
}

// syncTaskJob would do whatever syncing is necessary in the background
func syncTaskJob(j *que.Job) error {

	//don't retry forever, this will only increase the database size and not solve anything
	if j.ErrorCount > maxRetriesForJob {
		log.WithField("jobId", j.ID).WithField("errorCount", j.ErrorCount).WithField("lastError", j.LastError.String).Error("Ignoring job because of too high error count.")
		return nil //signal job completed, even though we did nothing
	}

	dbConnectionString := os.Getenv("CLEARDB_DATABASE_URL")
	log.Debugf("syntask connection string: %s", dbConnectionString)
	repo := sync.CreateSyncDbRepo(dbConnectionString)

	var txn newrelic.Transaction
	if app != nil {
		txn = app.StartTransaction("sync-task", nil, nil)
		txn.SetName("sync job")
		defer txn.End()
	}

	var synctask sync.SyncTask
	err := json.Unmarshal(j.Args, &synctask)
	if err != nil {
		log.WithField("args", string(j.Args)).Error("Unable to unmarshal job arguments into SyncTask")
		return err
	}

	log.WithField("SyncTask", synctask).Info("Processing Synctask!")

	stvClientImpl := stv.CreateStravaClientWithSecretAndId(synctask.StravaToken, 9667, os.Getenv("STRAVA_SECRET"))
	rkClientImpl := rk.CreateRKClient(synctask.RunkeeperToken)

	//update the accesstoken if needed
	if !stvClientImpl.ValidateToken(synctask.StravaToken) {
		log.WithField("SyncTask", synctask).Info("Updating access token using refresh token...")
		access_token, refresh_token, err := stvClientImpl.RefreshToken(synctask.StravaRefreshToken)
		if err != nil {
			log.WithField("args", string(j.Args)).WithField("QueId", j.ID).Error("Error while updating access token for strava.")
			return err
		}
		synctask.StravaToken = access_token
		synctask.StravaRefreshToken = refresh_token
		repo.UpdateSyncTask(synctask)
		//re-create the client, so we use the new tokens..
		stvClientImpl = stv.CreateStravaClientWithSecretAndId(access_token, 9667, os.Getenv("STRAVA_SECRET"))
	}

	itemsCreatedRk, totalItems, err := synctask.Sync(stvClientImpl, rkClientImpl, txn)
	if err != nil {
		if app != nil {
			app.RecordCustomEvent("sync_error_event", map[string]interface{}{"error": err})
		}
		if txn != nil {
			txn.NoticeError(err)
		}
		log.WithField("args", string(j.Args)).WithField("QueId", j.ID).Error("Error while syncing synctask.")
		return err //don't update Timestamp, so we will retry
	}

	//update last executed timestamp
	log.Print("Updating last seen timestamp")
	//subtract 45 minutes to prevent activites being missed
	synctask.LastSeenTimestamp = int(time.Now().Add(time.Duration(tsDelta) * time.Minute).Unix())
	rowsUpdated, err := repo.UpdateSyncTask(synctask)
	if err != nil || rowsUpdated != 1 {
		log.Errorf("Error updating the SyncTask record with a new timestamp: %e", err)
		return err
	}

	if app != nil {
		app.RecordCustomEvent("sync_items_created", map[string]interface{}{
			"rk-items-created": itemsCreatedRk,
			"total-items":      totalItems})
	}

	log.Infof("Executed synctask %d, now deleting it.", synctask.Uid)
	return nil
}

func main() {
	log.Print("Starting worker")

	var err error
	dbURL := os.Getenv("DATABASE_URL")
	pgxpool, qc, err = shared.Setup(dbURL)
	if err != nil {
		log.WithField("DATABASE_URL", dbURL).Fatal("Errors setting up the queue / database: ", err)
	}
	defer pgxpool.Close()

	wm := que.WorkMap{
		shared.SyncTaskJob: syncTaskJob,
	}

	// 2 worker go routines
	// LIMITED to 1 per worker.. otherwise we overload Runkeeper
	// and I guess create activties twice.
	workers := que.NewWorkerPool(qc, wm, 1)

	// Catch signal so we can shutdown gracefully
	sigCh := make(chan os.Signal)
	signal.Notify(sigCh, syscall.SIGTERM, syscall.SIGINT)

	go workers.Start()

	// Wait for a signal
	sig := <-sigCh
	log.WithField("signal", sig).Info("Signal received. Shutting down.")

	workers.Shutdown()
}
<|endoftext|>


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

// Changes copyright ©2012 The bíogo.bam Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package bgzf

import (
	"bytes"
	"compress/gzip"
	"flag"
	"io"
	"io/ioutil"
	"os"
	"testing"
	"time"
)

var conc = flag.Int("conc", 1, "sets the level of concurrency for compression")

type countWriter struct {
	bytes int64
	w     io.Writer
}

func (cw *countWriter) Write(p []byte) (n int, err error) {
	n, err = cw.w.Write(p)
	cw.bytes += int64(n)
	return
}

// TestEmpty tests that an empty payload still forms a valid GZIP stream.
func TestEmpty(t *testing.T) {
	buf := new(bytes.Buffer)

	if err := NewWriter(buf, *conc).Close(); err != nil {
		t.Fatalf("Writer.Close: %v", err)
	}

	r, err := NewReader(buf)
	if err != nil {
		t.Fatalf("NewReader: %v", err)
	}
	b, err := ioutil.ReadAll(r)
	if err != nil {
		t.Fatalf("ReadAll: %v", err)
	}
	if len(b) != 0 {
		t.Fatalf("got %d bytes, want 0", len(b))
	}
	if err := r.Close(); err != nil {
		t.Fatalf("Reader.Close: %v", err)
	}
}

// TestEOF tests CheckEOF can find the EOF magic block.
func TestEOF(t *testing.T) {
	f, err := ioutil.TempFile(os.TempDir(), "bgzf_EOF_test_")
	if err != nil {
		t.Fatalf("Create temp file: %v", err)
	}
	fname := f.Name()

	if err := NewWriter(f, *conc).Close(); err != nil {
		t.Fatalf("Writer.Close: %v", err)
	}

	f, err = os.Open(fname)
	if err != nil {
		t.Fatalf("Open temp file: %v", err)
	}
	ok, err := CheckEOF(f)
	if err != nil {
		t.Fatalf("CheckEOF: %v", err)
	}
	if !ok {
		t.Fatal("Expected EOF: not found.")
	}

	os.Remove(fname)
}

// TestRoundTrip tests that bgzipping and then bgunzipping is the identity
// function.
func TestRoundTrip(t *testing.T) {
	buf := new(bytes.Buffer)

	w := NewWriter(buf, *conc)
	w.Comment = "comment"
	w.Extra = []byte("extra")
	w.ModTime = time.Unix(1e8, 0)
	w.Name = "name"
	if _, err := w.Write([]byte("payload")); err != nil {
		t.Fatalf("Write: %v", err)
	}
	if err := w.Close(); err != nil {
		t.Fatalf("Writer.Close: %v", err)
	}
	// FIXME(kortschak) The magic block is written on close,
	// so we need to discount that until we have the capacity
	// to see every header again.
	wbl := buf.Len() - len(magicBlock)

	r, err := NewReader(buf)
	if err != nil {
		t.Fatalf("NewReader: %v", err)
	}
	if bl := r.BlockSize(); bl != wbl {
		t.Errorf("BlockSize() is %d, want %d", bl, wbl)
	}
	blEnc := string([]byte{byte(wbl - 1), byte((wbl - 1) >> 8)})
	if string(r.Extra) != "BC\x02\x00"+blEnc+"extra" {
		t.Errorf("extra is %q, want %q", r.Extra, "BC\x02\x00"+blEnc+"extra")
	}
	b, err := ioutil.ReadAll(r)
	if err != nil {
		t.Fatalf("ReadAll: %v", err)
	}
	if string(b) != "payload" {
		t.Fatalf("payload is %q, want %q", string(b), "payload")
	}
	if r.Comment != "comment" {
		t.Errorf("comment is %q, want %q", r.Comment, "comment")
	}
	if bl := r.BlockSize(); bl != wbl {
		t.Errorf("BlockSize() is %d, want %d", bl, wbl)
	}
	if string(r.Extra) != "BC\x02\x008\x00extra" {
		t.Errorf("extra is %q, want %q", r.Extra, "BC\x02\x008\x00extra")
	}
	if r.ModTime.Unix() != 1e8 {
		t.Errorf("mtime is %d, want %d", r.ModTime.Unix(), uint32(1e8))
	}
	if r.Name != "name" {
		t.Errorf("name is %q, want %q", r.Name, "name")
	}
	if err := r.Close(); err != nil {
		t.Errorf("Reader.Close: %v", err)
	}
}

// TestRoundTripMulti tests that bgzipping and then bgunzipping is the identity
// function for a multiple member bgzf.
func TestRoundTripMulti(t *testing.T) {
	var wbl [2]int
	buf := new(bytes.Buffer)

	w := NewWriter(buf, *conc)
	w.Comment = "comment"
	w.Extra = []byte("extra")
	w.ModTime = time.Unix(1e8, 0)
	w.Name = "name"
	if _, err := w.Write([]byte("payload1")); err != nil {
		t.Fatalf("Write: %v", err)
	}
	if err := w.Flush(); err != nil {
		t.Fatalf("Flush: %v", err)
	}
	if err := w.Wait(); err != nil {
		t.Fatalf("Wait: %v", err)
	}
	wbl[0] = buf.Len()
	o := int64(buf.Len())
	if _, err := w.Write([]byte("payloadTwo")); err != nil {
		t.Fatalf("Write: %v", err)
	}
	if err := w.Close(); err != nil {
		t.Fatalf("Writer.Close: %v", err)
	}
	wbl[1] = buf.Len() - wbl[0] - len(magicBlock)

	var (
		b     []byte
		bl, n int
		err   error
	)
	r, err := NewReader(buf)
	if err != nil {
		t.Fatalf("NewReader: %v", err)
	}
	if r.Comment != "comment" {
		t.Errorf("comment is %q, want %q", r.Comment, "comment")
	}
	blEnc := string([]byte{byte(wbl[0] - 1), byte((wbl[0] - 1) >> 8)})
	if string(r.Extra) != "BC\x02\x00"+blEnc+"extra" {
		t.Errorf("extra is %q, want %q", r.Extra, "BC\x02\x00"+blEnc+"extra")
	}
	if r.ModTime.Unix() != 1e8 {
		t.Errorf("mtime is %d, want %d", r.ModTime.Unix(), uint32(1e8))
	}
	if r.Name != "name" {
		t.Errorf("name is %q, want %q", r.Name, "name")
	}

	bl = r.BlockSize()
	if bl != wbl[0] {
		t.Errorf("BlockSize() is %d, want %d", bl, wbl[0])
	}
	b = make([]byte, len("payload1payloadTwo"))
	n, err = r.Read(b)
	if string(b[:n]) != "payload1payloadTwo" {
		t.Errorf("payload is %q, want %q", string(b[:n]), "payload1")
	}
	if err != nil {
		t.Errorf("Read: %v", err)
	}

	bl = r.BlockSize()
	if bl != wbl[0] {
		t.Errorf("BlockSize() is %d, want %d", bl, wbl[0])
	}
	b = make([]byte, 1)
	n, err = r.Read(b)
	if string(b[:n]) != "" {
		t.Errorf("payload is %q, want %q", string(b[:n]), "")
	}
	if err != io.EOF {
		t.Errorf("Read: %v", err)
	}

	if r.Seek(Offset{o, 0}, 1) == nil {
		t.Fatal("expected seek failure")
	}
	n, err = r.Read(b)
	if err == nil {
		t.Fatal("expected read failure")
	}
}

// TestRoundTripMultiSeek tests that bgzipping and then bgunzipping is the identity
// function for a multiple member bgzf with an underlying Seeker.
func TestRoundTripMultiSeek(t *testing.T) {
	f, err := ioutil.TempFile(os.TempDir(), "bgzf_test_")
	if err != nil {
		t.Fatalf("Create temp file: %v", err)
	}
	fname := f.Name()

	var wbl [2]int
	cw := &countWriter{w: f}
	w := NewWriter(cw, *conc)
	w.Comment = "comment"
	w.Extra = []byte("extra")
	w.ModTime = time.Unix(1e8, 0)
	w.Name = "name"
	if _, err := w.Write([]byte("payload1")); err != nil {
		t.Fatalf("Write: %v", err)
	}
	if err := w.Flush(); err != nil {
		t.Fatalf("Flush: %v", err)
	}
	if err := w.Wait(); err != nil {
		t.Fatalf("Wait: %v", err)
	}
	offset := cw.bytes
	wbl[0] = int(offset)
	if _, err := w.Write([]byte("payloadTwo")); err != nil {
		t.Fatalf("Write: %v", err)
	}
	if err := w.Close(); err != nil {
		t.Fatalf("Writer.Close: %v", err)
	}
	wbl[1] = int(cw.bytes-offset) - len(magicBlock)

	var (
		b     []byte
		bl, n int
	)

	f, err = os.Open(fname)
	if err != nil {
		t.Fatalf("Reopen temp file: %v", err)
	}
	r, err := NewReader(f)
	if err != nil {
		t.Fatalf("NewReader: %v", err)
	}
	if r.Comment != "comment" {
		t.Errorf("comment is %q, want %q", r.Comment, "comment")
	}
	blEnc := string([]byte{byte(wbl[0] - 1), byte((wbl[0] - 1) >> 8)})
	if string(r.Extra) != "BC\x02\x00"+blEnc+"extra" {
		t.Errorf("extra is %q, want %q", r.Extra, "BC\x02\x00"+blEnc+"extra")
	}
	if r.ModTime.Unix() != 1e8 {
		t.Errorf("mtime is %d, want %d", r.ModTime.Unix(), uint32(1e8))
	}
	if r.Name != "name" {
		t.Errorf("name is %q, want %q", r.Name, "name")
	}
	bl = r.BlockSize()
	if bl != wbl[0] {
		t.Errorf("BlockSize() is %d, want %d", bl, wbl[0])
	}
	b = make([]byte, len("payload1payloadTwo")+1)
	n, err = r.Read(b)
	if err != io.EOF {
		t.Errorf("Read: %v", err)
	}
	if bl := r.BlockSize(); bl != wbl[1] {
		t.Errorf("BlockSize() is %d, want %d", bl, wbl[1])
	}
	blEnc = string([]byte{byte(wbl[1] - 1), byte((wbl[1] - 1) >> 8)})
	if string(r.Extra) != "BC\x02\x00"+blEnc+"extra" {
		t.Errorf("extra is %q, want %q", r.Extra, "BC\x02\x00"+blEnc+"extra")
	}
	if string(b[:n]) != "payload1payloadTwo" {
		t.Errorf("payload is %q, want %q", string(b[:n]), "payload1payloadTwo")
	}
	if err := r.Seek(Offset{}, 0); err != nil {
		t.Errorf("Seek: %v", err)
	}
	n, err = r.Read(b)
	if err != io.EOF {
		t.Errorf("Read: %v", err)
	}
	if string(b[:n]) != "payload1payloadTwo" {
		t.Errorf("payload is %q, want %q", string(b[:n]), "payload1payloadTwo")
	}
	if err := r.Seek(Offset{File: offset}, 0); err != nil {
		t.Fatalf("Seek: %v", err)
	}
	bl = r.BlockSize()
	if bl != wbl[1] {
		t.Errorf("BlockSize() is %d, want %d", bl, wbl[1])
	}
	b = make([]byte, bl+1)
	n, err = r.Read(b)
	if err != io.EOF {
		t.Errorf("Read: %v", err)
	}
	if string(b[:n]) != "payloadTwo" {
		t.Errorf("payload is %q, want %q", string(b[:n]), "payloadTwo")
	}
	os.Remove(fname)
}

type zero struct{}

func (z zero) Read(p []byte) (int, error) {
	for i := range p {
		p[i] = 0
	}
	return len(p), nil
}

func TestWriteByteCount(t *testing.T) {
	cw := NewWriterLevel(ioutil.Discard, gzip.BestCompression, 4)
	defer cw.Close()
	n, err := io.Copy(cw, &io.LimitedReader{R: new(zero), N: 100000})
	if n != 100000 {
		t.Errorf("Unexpected number of bytes, got:%d, want:%d", n, 100000)
	}
	if err != nil {
		t.Errorf("Unexpected error got:%v", err)
	}
}

func BenchmarkWrite(b *testing.B) {
	bg := NewWriter(ioutil.Discard, *conc)
	block := bytes.Repeat([]byte("repeated"), 50)
	for i := 0; i < b.N; i++ {
		for j := 0; j < 1000000; j++ {
			bg.Write(block)
		}
	}
}
<commit_msg>Add explicit close of temporary file<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the Go LICENSE file.

// Changes copyright ©2012 The bíogo.bam Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package bgzf

import (
	"bytes"
	"compress/gzip"
	"flag"
	"io"
	"io/ioutil"
	"os"
	"testing"
	"time"
)

var conc = flag.Int("conc", 1, "sets the level of concurrency for compression")

type countWriter struct {
	bytes int64
	w     io.Writer
}

func (cw *countWriter) Write(p []byte) (n int, err error) {
	n, err = cw.w.Write(p)
	cw.bytes += int64(n)
	return
}

// TestEmpty tests that an empty payload still forms a valid GZIP stream.
func TestEmpty(t *testing.T) {
	buf := new(bytes.Buffer)

	if err := NewWriter(buf, *conc).Close(); err != nil {
		t.Fatalf("Writer.Close: %v", err)
	}

	r, err := NewReader(buf)
	if err != nil {
		t.Fatalf("NewReader: %v", err)
	}
	b, err := ioutil.ReadAll(r)
	if err != nil {
		t.Fatalf("ReadAll: %v", err)
	}
	if len(b) != 0 {
		t.Fatalf("got %d bytes, want 0", len(b))
	}
	if err := r.Close(); err != nil {
		t.Fatalf("Reader.Close: %v", err)
	}
}

// TestEOF tests CheckEOF can find the EOF magic block.
func TestEOF(t *testing.T) {
	f, err := ioutil.TempFile(os.TempDir(), "bgzf_EOF_test_")
	if err != nil {
		t.Fatalf("Create temp file: %v", err)
	}
	fname := f.Name()

	if err := NewWriter(f, *conc).Close(); err != nil {
		t.Fatalf("Writer.Close: %v", err)
	}

	f, err = os.Open(fname)
	if err != nil {
		t.Fatalf("Open temp file: %v", err)
	}
	ok, err := CheckEOF(f)
	if err != nil {
		t.Fatalf("CheckEOF: %v", err)
	}
	if !ok {
		t.Fatal("Expected EOF: not found.")
	}

	os.Remove(fname)
}

// TestRoundTrip tests that bgzipping and then bgunzipping is the identity
// function.
func TestRoundTrip(t *testing.T) {
	buf := new(bytes.Buffer)

	w := NewWriter(buf, *conc)
	w.Comment = "comment"
	w.Extra = []byte("extra")
	w.ModTime = time.Unix(1e8, 0)
	w.Name = "name"
	if _, err := w.Write([]byte("payload")); err != nil {
		t.Fatalf("Write: %v", err)
	}
	if err := w.Close(); err != nil {
		t.Fatalf("Writer.Close: %v", err)
	}
	// FIXME(kortschak) The magic block is written on close,
	// so we need to discount that until we have the capacity
	// to see every header again.
	wbl := buf.Len() - len(magicBlock)

	r, err := NewReader(buf)
	if err != nil {
		t.Fatalf("NewReader: %v", err)
	}
	if bl := r.BlockSize(); bl != wbl {
		t.Errorf("BlockSize() is %d, want %d", bl, wbl)
	}
	blEnc := string([]byte{byte(wbl - 1), byte((wbl - 1) >> 8)})
	if string(r.Extra) != "BC\x02\x00"+blEnc+"extra" {
		t.Errorf("extra is %q, want %q", r.Extra, "BC\x02\x00"+blEnc+"extra")
	}
	b, err := ioutil.ReadAll(r)
	if err != nil {
		t.Fatalf("ReadAll: %v", err)
	}
	if string(b) != "payload" {
		t.Fatalf("payload is %q, want %q", string(b), "payload")
	}
	if r.Comment != "comment" {
		t.Errorf("comment is %q, want %q", r.Comment, "comment")
	}
	if bl := r.BlockSize(); bl != wbl {
		t.Errorf("BlockSize() is %d, want %d", bl, wbl)
	}
	if string(r.Extra) != "BC\x02\x008\x00extra" {
		t.Errorf("extra is %q, want %q", r.Extra, "BC\x02\x008\x00extra")
	}
	if r.ModTime.Unix() != 1e8 {
		t.Errorf("mtime is %d, want %d", r.ModTime.Unix(), uint32(1e8))
	}
	if r.Name != "name" {
		t.Errorf("name is %q, want %q", r.Name, "name")
	}
	if err := r.Close(); err != nil {
		t.Errorf("Reader.Close: %v", err)
	}
}

// TestRoundTripMulti tests that bgzipping and then bgunzipping is the identity
// function for a multiple member bgzf.
func TestRoundTripMulti(t *testing.T) {
	var wbl [2]int
	buf := new(bytes.Buffer)

	w := NewWriter(buf, *conc)
	w.Comment = "comment"
	w.Extra = []byte("extra")
	w.ModTime = time.Unix(1e8, 0)
	w.Name = "name"
	if _, err := w.Write([]byte("payload1")); err != nil {
		t.Fatalf("Write: %v", err)
	}
	if err := w.Flush(); err != nil {
		t.Fatalf("Flush: %v", err)
	}
	if err := w.Wait(); err != nil {
		t.Fatalf("Wait: %v", err)
	}
	wbl[0] = buf.Len()
	o := int64(buf.Len())
	if _, err := w.Write([]byte("payloadTwo")); err != nil {
		t.Fatalf("Write: %v", err)
	}
	if err := w.Close(); err != nil {
		t.Fatalf("Writer.Close: %v", err)
	}
	wbl[1] = buf.Len() - wbl[0] - len(magicBlock)

	var (
		b     []byte
		bl, n int
		err   error
	)
	r, err := NewReader(buf)
	if err != nil {
		t.Fatalf("NewReader: %v", err)
	}
	if r.Comment != "comment" {
		t.Errorf("comment is %q, want %q", r.Comment, "comment")
	}
	blEnc := string([]byte{byte(wbl[0] - 1), byte((wbl[0] - 1) >> 8)})
	if string(r.Extra) != "BC\x02\x00"+blEnc+"extra" {
		t.Errorf("extra is %q, want %q", r.Extra, "BC\x02\x00"+blEnc+"extra")
	}
	if r.ModTime.Unix() != 1e8 {
		t.Errorf("mtime is %d, want %d", r.ModTime.Unix(), uint32(1e8))
	}
	if r.Name != "name" {
		t.Errorf("name is %q, want %q", r.Name, "name")
	}

	bl = r.BlockSize()
	if bl != wbl[0] {
		t.Errorf("BlockSize() is %d, want %d", bl, wbl[0])
	}
	b = make([]byte, len("payload1payloadTwo"))
	n, err = r.Read(b)
	if string(b[:n]) != "payload1payloadTwo" {
		t.Errorf("payload is %q, want %q", string(b[:n]), "payload1")
	}
	if err != nil {
		t.Errorf("Read: %v", err)
	}

	bl = r.BlockSize()
	if bl != wbl[0] {
		t.Errorf("BlockSize() is %d, want %d", bl, wbl[0])
	}
	b = make([]byte, 1)
	n, err = r.Read(b)
	if string(b[:n]) != "" {
		t.Errorf("payload is %q, want %q", string(b[:n]), "")
	}
	if err != io.EOF {
		t.Errorf("Read: %v", err)
	}

	if r.Seek(Offset{o, 0}, 1) == nil {
		t.Fatal("expected seek failure")
	}
	n, err = r.Read(b)
	if err == nil {
		t.Fatal("expected read failure")
	}
}

// TestRoundTripMultiSeek tests that bgzipping and then bgunzipping is the identity
// function for a multiple member bgzf with an underlying Seeker.
func TestRoundTripMultiSeek(t *testing.T) {
	f, err := ioutil.TempFile(os.TempDir(), "bgzf_test_")
	if err != nil {
		t.Fatalf("Create temp file: %v", err)
	}
	fname := f.Name()

	var wbl [2]int
	cw := &countWriter{w: f}
	w := NewWriter(cw, *conc)
	w.Comment = "comment"
	w.Extra = []byte("extra")
	w.ModTime = time.Unix(1e8, 0)
	w.Name = "name"
	if _, err := w.Write([]byte("payload1")); err != nil {
		t.Fatalf("Write: %v", err)
	}
	if err := w.Flush(); err != nil {
		t.Fatalf("Flush: %v", err)
	}
	if err := w.Wait(); err != nil {
		t.Fatalf("Wait: %v", err)
	}
	offset := cw.bytes
	wbl[0] = int(offset)
	if _, err := w.Write([]byte("payloadTwo")); err != nil {
		t.Fatalf("Write: %v", err)
	}
	if err := w.Close(); err != nil {
		t.Fatalf("Writer.Close: %v", err)
	}
	if err := f.Close(); err != nil {
		t.Fatalf("os.File.Close: %v", err)
	}
	wbl[1] = int(cw.bytes-offset) - len(magicBlock)

	var (
		b     []byte
		bl, n int
	)

	f, err = os.Open(fname)
	if err != nil {
		t.Fatalf("Reopen temp file: %v", err)
	}
	r, err := NewReader(f)
	if err != nil {
		t.Fatalf("NewReader: %v", err)
	}
	if r.Comment != "comment" {
		t.Errorf("comment is %q, want %q", r.Comment, "comment")
	}
	blEnc := string([]byte{byte(wbl[0] - 1), byte((wbl[0] - 1) >> 8)})
	if string(r.Extra) != "BC\x02\x00"+blEnc+"extra" {
		t.Errorf("extra is %q, want %q", r.Extra, "BC\x02\x00"+blEnc+"extra")
	}
	if r.ModTime.Unix() != 1e8 {
		t.Errorf("mtime is %d, want %d", r.ModTime.Unix(), uint32(1e8))
	}
	if r.Name != "name" {
		t.Errorf("name is %q, want %q", r.Name, "name")
	}
	bl = r.BlockSize()
	if bl != wbl[0] {
		t.Errorf("BlockSize() is %d, want %d", bl, wbl[0])
	}
	b = make([]byte, len("payload1payloadTwo")+1)
	n, err = r.Read(b)
	if err != io.EOF {
		t.Errorf("Read: %v", err)
	}
	if bl := r.BlockSize(); bl != wbl[1] {
		t.Errorf("BlockSize() is %d, want %d", bl, wbl[1])
	}
	blEnc = string([]byte{byte(wbl[1] - 1), byte((wbl[1] - 1) >> 8)})
	if string(r.Extra) != "BC\x02\x00"+blEnc+"extra" {
		t.Errorf("extra is %q, want %q", r.Extra, "BC\x02\x00"+blEnc+"extra")
	}
	if string(b[:n]) != "payload1payloadTwo" {
		t.Errorf("payload is %q, want %q", string(b[:n]), "payload1payloadTwo")
	}
	if err := r.Seek(Offset{}, 0); err != nil {
		t.Errorf("Seek: %v", err)
	}
	n, err = r.Read(b)
	if err != io.EOF {
		t.Errorf("Read: %v", err)
	}
	if string(b[:n]) != "payload1payloadTwo" {
		t.Errorf("payload is %q, want %q", string(b[:n]), "payload1payloadTwo")
	}
	if err := r.Seek(Offset{File: offset}, 0); err != nil {
		t.Fatalf("Seek: %v", err)
	}
	bl = r.BlockSize()
	if bl != wbl[1] {
		t.Errorf("BlockSize() is %d, want %d", bl, wbl[1])
	}
	b = make([]byte, bl+1)
	n, err = r.Read(b)
	if err != io.EOF {
		t.Errorf("Read: %v", err)
	}
	if string(b[:n]) != "payloadTwo" {
		t.Errorf("payload is %q, want %q", string(b[:n]), "payloadTwo")
	}
	os.Remove(fname)
}

type zero struct{}

func (z zero) Read(p []byte) (int, error) {
	for i := range p {
		p[i] = 0
	}
	return len(p), nil
}

func TestWriteByteCount(t *testing.T) {
	cw := NewWriterLevel(ioutil.Discard, gzip.BestCompression, 4)
	defer cw.Close()
	n, err := io.Copy(cw, &io.LimitedReader{R: new(zero), N: 100000})
	if n != 100000 {
		t.Errorf("Unexpected number of bytes, got:%d, want:%d", n, 100000)
	}
	if err != nil {
		t.Errorf("Unexpected error got:%v", err)
	}
}

func BenchmarkWrite(b *testing.B) {
	bg := NewWriter(ioutil.Discard, *conc)
	block := bytes.Repeat([]byte("repeated"), 50)
	for i := 0; i < b.N; i++ {
		for j := 0; j < 1000000; j++ {
			bg.Write(block)
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2013 SteelSeries ApS. All rights reserved.
// No license is given for the use of this source code.

// This package impliments a basic LISP interpretor for embedding in a go program for scripting.
// This file inmpliments data elements
package golisp

import (
    "errors"
    "fmt"
    "strings"
    "unsafe"
)

const (
    ConsCellType = iota
    AlistType
    AlistCellType
    NumberType
    BooleanType
    StringType
    SymbolType
    FunctionType
    PrimitiveType
    ObjectType
)

type Data struct {
    Type    int                // data type
    Car     *Data              // ConsCellType & AlistType
    Cdr     *Data              // ConsCellType & AlistType
    String  string             // StringType & SymbolType
    Number  uint32             // NumberType & BooleanType
    Func    *Function          // FunctionType
    Prim    *PrimitiveFunction // PrimitiveType
    ObjType string             // ObjectType
    Obj     unsafe.Pointer     // ObjectType
}

// Boolean constants

var True *Data = BooleanWithValue(true)
var False *Data = BooleanWithValue(false)

func TypeOf(d *Data) int {
    return d.Type
}

func NilP(d *Data) bool {
    if d == nil {
        return true
    }
    if (PairP(d) || AlistP(d) || DottedPairP(d)) && Car(d) == nil && Cdr(d) == nil {
        return true
    }
    return false
}

func NotNilP(d *Data) bool {
    return !NilP(d)
}

func PairP(d *Data) bool {
    return d == nil || TypeOf(d) == ConsCellType
}

func DottedPairP(d *Data) bool {
    return d == nil || TypeOf(d) == AlistCellType
}

func AlistP(d *Data) bool {
    return d == nil || TypeOf(d) == AlistType
}

func SymbolP(d *Data) bool {
    return d != nil && TypeOf(d) == SymbolType
}

func StringP(d *Data) bool {
    return d != nil && TypeOf(d) == StringType
}

func NumberP(d *Data) bool {
    return d != nil && TypeOf(d) == NumberType
}

func ObjectP(d *Data) bool {
    return d != nil && TypeOf(d) == ObjectType
}

func FunctionP(d *Data) bool {
    return d != nil && TypeOf(d) == FunctionType || TypeOf(d) == PrimitiveType
}

func Cons(car *Data, cdr *Data) *Data {
    return &Data{Type: ConsCellType, Car: car, Cdr: cdr, String: "", Number: 0, Func: nil, Prim: nil}
}

func AppendBang(l *Data, value *Data) *Data {
    if NilP(l) {
        return Cons(value, nil)
    }

    if Cdr(l) == nil {
        l.Cdr = Cons(value, nil)
    } else {
        AppendBang(Cdr(l), value)
    }

    return l
}

func AppendBangList(l *Data, otherList *Data) *Data {
    if NilP(l) {
        return otherList
    }

    var c *Data
    for c = l; NotNilP(c.Cdr); c = Cdr(c) {
    }

    c.Cdr = otherList

    return l
}

func Acons(car *Data, cdr *Data, alist *Data) *Data {
    pair, _ := Assoc(car, alist)
    if NilP(pair) {
        cell := &Data{Type: AlistCellType, Car: car, Cdr: cdr, String: "", Number: 0, Func: nil, Prim: nil}
        return &Data{Type: AlistType, Car: cell, Cdr: alist, String: "", Number: 0, Func: nil, Prim: nil}
    } else {
        pair.Cdr = cdr
        return alist
    }
}

func Alist(d *Data) *Data {
    if NilP(d) {
        return nil
    }

    if PairP(d) {
        return Acons(Caar(d), Cdar(d), Alist(Cdr(d)))
    }

    return d
}

func InternalMakeList(c ...*Data) *Data {
    return ArrayToList(c)
}

func EmptyCons() *Data {
    return Cons(nil, nil)
}

func NumberWithValue(n uint32) *Data {
    return &Data{Type: NumberType, Car: nil, Cdr: nil, String: "", Number: n, Func: nil, Prim: nil}
}

func BooleanWithValue(b bool) *Data {
    var num int = 0
    if b {
        num = 1
    }
    return &Data{Type: BooleanType, Car: nil, Cdr: nil, String: "", Number: uint32(num), Func: nil, Prim: nil}
}

func StringWithValue(s string) *Data {
    return &Data{Type: StringType, Car: nil, Cdr: nil, String: s, Number: 0, Func: nil, Prim: nil}
}

func SymbolWithName(s string) *Data {
    return &Data{Type: SymbolType, Car: nil, Cdr: nil, String: s, Number: 0, Func: nil, Prim: nil}
}

func FunctionWithNameParamsBodyAndParent(name string, params *Data, body *Data, parentEnv *SymbolTableFrame) *Data {
    return &Data{Type: FunctionType, Car: nil, Cdr: nil, String: "", Number: 0, Func: MakeFunction(name, params, body, parentEnv), Prim: nil}
}

func PrimitiveWithNameAndFunc(name string, f *PrimitiveFunction) *Data {
    return &Data{Type: PrimitiveType, Car: nil, Cdr: nil, String: "", Number: 0, Func: nil, Prim: f}
}

func ObjectWithTypeAndValue(typeName string, o unsafe.Pointer) *Data {
    return &Data{Type: ObjectType, Car: nil, Cdr: nil, String: "", Number: 0, Func: nil, Prim: nil, ObjType: typeName, Obj: o}
}

func NumericValue(d *Data) uint32 {
    if d == nil {
        return 0
    }

    if d.Type == NumberType {
        return d.Number
    }

    return 0
}

func StringValue(d *Data) string {
    if d == nil {
        return ""
    }

    if d.Type == StringType || d.Type == SymbolType {
        return d.String
    }

    return ""
}

func BooleanValue(d *Data) bool {
    if d == nil {
        return false
    }

    if d.Type == BooleanType {
        if d.Number == 0 {
            return false
        } else {
            return true
        }
    }

    return true
}

func TypeOfObject(d *Data) (oType string) {
    if d == nil {
        return
    }

    if d.Type == ObjectType {
        return d.ObjType
    }

    return
}

func ObjectValue(d *Data) (p unsafe.Pointer) {
    if d == nil {
        return
    }

    if d.Type == ObjectType {
        return d.Obj
    }

    return
}

func Length(d *Data) int {
    if d == nil {
        return 0
    }

    if d.Type == ConsCellType || d.Type == AlistType {
        return 1 + Length(d.Cdr)
    }

    return 0
}

func Reverse(d *Data) (result *Data) {
    if d == nil {
        return nil
    }

    if !PairP(d) {
        return d
    }

    var l *Data = nil
    for c := d; NotNilP(c); c = Cdr(c) {
        l = Cons(Car(c), l)
    }

    return l
}

func Assoc(key *Data, alist *Data) (result *Data, err error) {
    for c := alist; NotNilP(c); c = Cdr(c) {
        pair := Car(c)
        if !DottedPairP(pair) && !PairP(pair) {
            err = errors.New("Alist key can not be a list")
            return
        }
        if IsEqual(Car(pair), key) {
            result = pair
            return
        }
    }
    return
}

func Copy(d *Data) *Data {
    if d == nil {
        return d
    }

    switch d.Type {
    case AlistType:
        {
            alist := Acons(Copy(Caar(d)), Copy(Cdar(d)), nil)
            for c := Cdr(d); NotNilP(c); c = Cdr(c) {
                alist = Acons(Copy(Caar(c)), Copy(Cdar(c)), alist)
            }
            return alist
        }
    case ConsCellType:
        {
            if NilP(d) {
                return d
            }

            return Cons(Copy(Car(d)), Copy(Cdr(d)))
        }
    }

    return d
}

func IsEqual(d *Data, o *Data) bool {
    if d == o {
        return true
    }

    if d == nil || o == nil {
        return false
    }

    if AlistP(d) {
        if !AlistP(o) && !PairP(o) {
            return false
        }
    } else if TypeOf(d) == AlistCellType {
        if TypeOf(o) != ConsCellType && TypeOf(o) != AlistCellType {
            return false
        }
    } else if TypeOf(o) != TypeOf(d) {
        return false
    }

    if PairP(d) {
        if Length(d) != Length(o) {
            return false
        }
        for a1, a2 := d, o; NotNilP(a1); a1, a2 = Cdr(a1), Cdr(a2) {
            if !IsEqual(Car(a1), Car(a2)) {
                return false
            }
        }
        return true
    }

    if AlistP(d) {
        if Length(d) != Length(o) {
            return false
        }
        for c := d; NotNilP(c); c = Cdr(c) {
            otherPair, err := Assoc(Caar(c), o)
            if err != nil || NilP(otherPair) || !IsEqual(Cdar(c), Cdr(otherPair)) {
                return false
            }
        }
        return true
    }

    if TypeOf(d) == AlistCellType {
        return IsEqual(Car(d), Car(o)) && IsEqual(Cdr(d), Cdr(o))
    }

    return *d == *o
}

func escapeQuotes(str string) string {
    buffer := make([]rune, 0, 10)
    for _, ch := range str {
        if rune(ch) == '"' {
            buffer = append(buffer, '\\')
        }
        buffer = append(buffer, rune(ch))
    }
    return string(buffer)
}

func String(d *Data) string {
    if d == nil {
        return "()"
    }

    switch d.Type {
    case ConsCellType:
        {
            if NilP(Car(d)) && NilP(Cdr(d)) {
                return "()"
            }
            var c *Data = d

            contents := make([]string, 0, Length(d))
            for NotNilP(c) && PairP(c) {
                contents = append(contents, String(Car(c)))
                c = Cdr(c)
            }
            if c == nil {
                if SymbolP(Car(d)) && StringValue(Car(d)) == "quote" {
                    if len(contents) == 1 {
                        return fmt.Sprintf("'()")
                    } else {
                        return fmt.Sprintf("'%s", contents[1])
                    }
                } else {
                    return fmt.Sprintf("(%s)", strings.Join(contents, " "))
                }
            } else {
                return fmt.Sprintf("(%s . %s)", strings.Join(contents, " "), String(c))
            }
        }
    case AlistType:
        {
            if NilP(Car(d)) && NilP(Cdr(d)) {
                return "()"
            }
            contents := make([]string, 0, Length(d))
            for c := d; NotNilP(c); c = Cdr(c) {
                contents = append(contents, String(Car(c)))
            }
            return fmt.Sprintf("(%s)", strings.Join(contents, " "))
        }
    case AlistCellType:
        return fmt.Sprintf("(%s . %s)", String(Car(d)), String(Cdr(d)))
    case NumberType:
        return fmt.Sprintf("%d", d.Number)
    case BooleanType:
        if d.Number == 0 {
            return "#f"
        } else {
            return "#t"
        }
    case StringType:
        return fmt.Sprintf(`"%s"`, escapeQuotes(d.String))
    case SymbolType:
        return d.String
    case FunctionType:
        return fmt.Sprintf("<function: %s>", d.Func.Name)
    case PrimitiveType:
        return d.Prim.String()
    case ObjectType:
        return fmt.Sprintf("<opaque Go object of type %s : 0x%x>", d.ObjType, (*uint64)(d.Obj))
    }

    return ""
}

func Eval(d *Data, env *SymbolTableFrame) (result *Data, err error) {
    if d == nil {
        return
    }

    switch d.Type {
    case ConsCellType:
        {
            var function *Data
            function, err = Eval(Car(d), env)
            if err != nil {
                return
            }
            args := Cdr(d)
            result, err = Apply(function, args, env)
            if err != nil {
                err = errors.New(fmt.Sprintf("Evaling %s. %s", String(d), err))
                return
            }
            return
        }
    case SymbolType:
        result = env.ValueOf(d)
        return
    }

    return d, nil
}

func Apply(function *Data, args *Data, env *SymbolTableFrame) (result *Data, err error) {
    if function == nil {
        err = errors.New("Nil when function expected.")
        return
    }
    switch function.Type {
    case FunctionType:
        return function.Func.Apply(args, env)
    case PrimitiveType:
        return function.Prim.Apply(args, env)
    }
    return
}
<commit_msg>Added non-destructive append.<commit_after>// Copyright 2013 SteelSeries ApS. All rights reserved.
// No license is given for the use of this source code.

// This package impliments a basic LISP interpretor for embedding in a go program for scripting.
// This file inmpliments data elements
package golisp

import (
    "errors"
    "fmt"
    "strings"
    "unsafe"
)

const (
    ConsCellType = iota
    AlistType
    AlistCellType
    NumberType
    BooleanType
    StringType
    SymbolType
    FunctionType
    PrimitiveType
    ObjectType
)

type Data struct {
    Type    int                // data type
    Car     *Data              // ConsCellType & AlistType
    Cdr     *Data              // ConsCellType & AlistType
    String  string             // StringType & SymbolType
    Number  uint32             // NumberType & BooleanType
    Func    *Function          // FunctionType
    Prim    *PrimitiveFunction // PrimitiveType
    ObjType string             // ObjectType
    Obj     unsafe.Pointer     // ObjectType
}

// Boolean constants

var True *Data = BooleanWithValue(true)
var False *Data = BooleanWithValue(false)

func TypeOf(d *Data) int {
    return d.Type
}

func NilP(d *Data) bool {
    if d == nil {
        return true
    }
    if (PairP(d) || AlistP(d) || DottedPairP(d)) && Car(d) == nil && Cdr(d) == nil {
        return true
    }
    return false
}

func NotNilP(d *Data) bool {
    return !NilP(d)
}

func PairP(d *Data) bool {
    return d == nil || TypeOf(d) == ConsCellType
}

func DottedPairP(d *Data) bool {
    return d == nil || TypeOf(d) == AlistCellType
}

func AlistP(d *Data) bool {
    return d == nil || TypeOf(d) == AlistType
}

func SymbolP(d *Data) bool {
    return d != nil && TypeOf(d) == SymbolType
}

func StringP(d *Data) bool {
    return d != nil && TypeOf(d) == StringType
}

func NumberP(d *Data) bool {
    return d != nil && TypeOf(d) == NumberType
}

func ObjectP(d *Data) bool {
    return d != nil && TypeOf(d) == ObjectType
}

func FunctionP(d *Data) bool {
    return d != nil && TypeOf(d) == FunctionType || TypeOf(d) == PrimitiveType
}

func Cons(car *Data, cdr *Data) *Data {
    return &Data{Type: ConsCellType, Car: car, Cdr: cdr, String: "", Number: 0, Func: nil, Prim: nil}
}

func AppendBang(l *Data, value *Data) *Data {
    if NilP(l) {
        return Cons(value, nil)
    }

    var c *Data
    for c = l; NotNilP(c.Cdr); c = Cdr(c) {
    }

    c.Cdr = Cons(value, nil)

    return l
}

func AppendBangList(l *Data, otherList *Data) *Data {
    if NilP(l) {
        return otherList
    }

    var c *Data
    for c = l; NotNilP(c.Cdr); c = Cdr(c) {
    }

    c.Cdr = otherList

    return l
}

func Append(l *Data, value *Data) *Data {
    if NilP(l) {
        return Cons(value, nil)
    }

    var newList = Copy(l)
    var c *Data
    for c = newList; NotNilP(c.Cdr); c = Cdr(c) {
    }

    c.Cdr = Cons(value, nil)

    return newList
}

func AppendList(l *Data, otherList *Data) *Data {
    if NilP(l) {
        return otherList
    }

    var newList = Copy(l)
    var c *Data
    for c = newList; NotNilP(c.Cdr); c = Cdr(c) {
    }

    c.Cdr = otherList

    return newList
}

func Acons(car *Data, cdr *Data, alist *Data) *Data {
    pair, _ := Assoc(car, alist)
    if NilP(pair) {
        cell := &Data{Type: AlistCellType, Car: car, Cdr: cdr, String: "", Number: 0, Func: nil, Prim: nil}
        return &Data{Type: AlistType, Car: cell, Cdr: alist, String: "", Number: 0, Func: nil, Prim: nil}
    } else {
        pair.Cdr = cdr
        return alist
    }
}

func Alist(d *Data) *Data {
    if NilP(d) {
        return nil
    }

    if PairP(d) {
        return Acons(Caar(d), Cdar(d), Alist(Cdr(d)))
    }

    return d
}

func InternalMakeList(c ...*Data) *Data {
    return ArrayToList(c)
}

func EmptyCons() *Data {
    return Cons(nil, nil)
}

func NumberWithValue(n uint32) *Data {
    return &Data{Type: NumberType, Car: nil, Cdr: nil, String: "", Number: n, Func: nil, Prim: nil}
}

func BooleanWithValue(b bool) *Data {
    var num int = 0
    if b {
        num = 1
    }
    return &Data{Type: BooleanType, Car: nil, Cdr: nil, String: "", Number: uint32(num), Func: nil, Prim: nil}
}

func StringWithValue(s string) *Data {
    return &Data{Type: StringType, Car: nil, Cdr: nil, String: s, Number: 0, Func: nil, Prim: nil}
}

func SymbolWithName(s string) *Data {
    return &Data{Type: SymbolType, Car: nil, Cdr: nil, String: s, Number: 0, Func: nil, Prim: nil}
}

func FunctionWithNameParamsBodyAndParent(name string, params *Data, body *Data, parentEnv *SymbolTableFrame) *Data {
    return &Data{Type: FunctionType, Car: nil, Cdr: nil, String: "", Number: 0, Func: MakeFunction(name, params, body, parentEnv), Prim: nil}
}

func PrimitiveWithNameAndFunc(name string, f *PrimitiveFunction) *Data {
    return &Data{Type: PrimitiveType, Car: nil, Cdr: nil, String: "", Number: 0, Func: nil, Prim: f}
}

func ObjectWithTypeAndValue(typeName string, o unsafe.Pointer) *Data {
    return &Data{Type: ObjectType, Car: nil, Cdr: nil, String: "", Number: 0, Func: nil, Prim: nil, ObjType: typeName, Obj: o}
}

func NumericValue(d *Data) uint32 {
    if d == nil {
        return 0
    }

    if d.Type == NumberType {
        return d.Number
    }

    return 0
}

func StringValue(d *Data) string {
    if d == nil {
        return ""
    }

    if d.Type == StringType || d.Type == SymbolType {
        return d.String
    }

    return ""
}

func BooleanValue(d *Data) bool {
    if d == nil {
        return false
    }

    if d.Type == BooleanType {
        if d.Number == 0 {
            return false
        } else {
            return true
        }
    }

    return true
}

func TypeOfObject(d *Data) (oType string) {
    if d == nil {
        return
    }

    if d.Type == ObjectType {
        return d.ObjType
    }

    return
}

func ObjectValue(d *Data) (p unsafe.Pointer) {
    if d == nil {
        return
    }

    if d.Type == ObjectType {
        return d.Obj
    }

    return
}

func Length(d *Data) int {
    if d == nil {
        return 0
    }

    if d.Type == ConsCellType || d.Type == AlistType {
        return 1 + Length(d.Cdr)
    }

    return 0
}

func Reverse(d *Data) (result *Data) {
    if d == nil {
        return nil
    }

    if !PairP(d) {
        return d
    }

    var l *Data = nil
    for c := d; NotNilP(c); c = Cdr(c) {
        l = Cons(Car(c), l)
    }

    return l
}

func Assoc(key *Data, alist *Data) (result *Data, err error) {
    for c := alist; NotNilP(c); c = Cdr(c) {
        pair := Car(c)
        if !DottedPairP(pair) && !PairP(pair) {
            err = errors.New("Alist key can not be a list")
            return
        }
        if IsEqual(Car(pair), key) {
            result = pair
            return
        }
    }
    return
}

func Copy(d *Data) *Data {
    if d == nil {
        return d
    }

    switch d.Type {
    case AlistType:
        {
            alist := Acons(Copy(Caar(d)), Copy(Cdar(d)), nil)
            for c := Cdr(d); NotNilP(c); c = Cdr(c) {
                alist = Acons(Copy(Caar(c)), Copy(Cdar(c)), alist)
            }
            return alist
        }
    case ConsCellType:
        {
            if NilP(d) {
                return d
            }

            return Cons(Copy(Car(d)), Copy(Cdr(d)))
        }
    }

    return d
}

func IsEqual(d *Data, o *Data) bool {
    if d == o {
        return true
    }

    if d == nil || o == nil {
        return false
    }

    if AlistP(d) {
        if !AlistP(o) && !PairP(o) {
            return false
        }
    } else if TypeOf(d) == AlistCellType {
        if TypeOf(o) != ConsCellType && TypeOf(o) != AlistCellType {
            return false
        }
    } else if TypeOf(o) != TypeOf(d) {
        return false
    }

    if PairP(d) {
        if Length(d) != Length(o) {
            return false
        }
        for a1, a2 := d, o; NotNilP(a1); a1, a2 = Cdr(a1), Cdr(a2) {
            if !IsEqual(Car(a1), Car(a2)) {
                return false
            }
        }
        return true
    }

    if AlistP(d) {
        if Length(d) != Length(o) {
            return false
        }
        for c := d; NotNilP(c); c = Cdr(c) {
            otherPair, err := Assoc(Caar(c), o)
            if err != nil || NilP(otherPair) || !IsEqual(Cdar(c), Cdr(otherPair)) {
                return false
            }
        }
        return true
    }

    if TypeOf(d) == AlistCellType {
        return IsEqual(Car(d), Car(o)) && IsEqual(Cdr(d), Cdr(o))
    }

    return *d == *o
}

func escapeQuotes(str string) string {
    buffer := make([]rune, 0, 10)
    for _, ch := range str {
        if rune(ch) == '"' {
            buffer = append(buffer, '\\')
        }
        buffer = append(buffer, rune(ch))
    }
    return string(buffer)
}

func String(d *Data) string {
    if d == nil {
        return "()"
    }

    switch d.Type {
    case ConsCellType:
        {
            if NilP(Car(d)) && NilP(Cdr(d)) {
                return "()"
            }
            var c *Data = d

            contents := make([]string, 0, Length(d))
            for NotNilP(c) && PairP(c) {
                contents = append(contents, String(Car(c)))
                c = Cdr(c)
            }
            if c == nil {
                if SymbolP(Car(d)) && StringValue(Car(d)) == "quote" {
                    if len(contents) == 1 {
                        return fmt.Sprintf("'()")
                    } else {
                        return fmt.Sprintf("'%s", contents[1])
                    }
                } else {
                    return fmt.Sprintf("(%s)", strings.Join(contents, " "))
                }
            } else {
                return fmt.Sprintf("(%s . %s)", strings.Join(contents, " "), String(c))
            }
        }
    case AlistType:
        {
            if NilP(Car(d)) && NilP(Cdr(d)) {
                return "()"
            }
            contents := make([]string, 0, Length(d))
            for c := d; NotNilP(c); c = Cdr(c) {
                contents = append(contents, String(Car(c)))
            }
            return fmt.Sprintf("(%s)", strings.Join(contents, " "))
        }
    case AlistCellType:
        return fmt.Sprintf("(%s . %s)", String(Car(d)), String(Cdr(d)))
    case NumberType:
        return fmt.Sprintf("%d", d.Number)
    case BooleanType:
        if d.Number == 0 {
            return "#f"
        } else {
            return "#t"
        }
    case StringType:
        return fmt.Sprintf(`"%s"`, escapeQuotes(d.String))
    case SymbolType:
        return d.String
    case FunctionType:
        return fmt.Sprintf("<function: %s>", d.Func.Name)
    case PrimitiveType:
        return d.Prim.String()
    case ObjectType:
        return fmt.Sprintf("<opaque Go object of type %s : 0x%x>", d.ObjType, (*uint64)(d.Obj))
    }

    return ""
}

func Eval(d *Data, env *SymbolTableFrame) (result *Data, err error) {
    if d == nil {
        return
    }

    switch d.Type {
    case ConsCellType:
        {
            var function *Data
            function, err = Eval(Car(d), env)
            if err != nil {
                return
            }
            args := Cdr(d)
            result, err = Apply(function, args, env)
            if err != nil {
                err = errors.New(fmt.Sprintf("Evaling %s. %s", String(d), err))
                return
            }
            return
        }
    case SymbolType:
        result = env.ValueOf(d)
        return
    }

    return d, nil
}

func Apply(function *Data, args *Data, env *SymbolTableFrame) (result *Data, err error) {
    if function == nil {
        err = errors.New("Nil when function expected.")
        return
    }
    switch function.Type {
    case FunctionType:
        return function.Func.Apply(args, env)
    case PrimitiveType:
        return function.Prim.Apply(args, env)
    }
    return
}
<|endoftext|>


<commit_before>package main

import (
    "log"
    "menteslibres.net/gosexy/redis"
)

type Storage struct {
    memory      MemoryStore
    redis       RedisStore
    StorageType string
}

func initStore(Config *Configuration) Storage{
    var Store = Storage{
        MemoryStore{make(map[string]*Socket), 0},
        RedisStore{
            ClientsKey,

            "localhost",
            6379,

            redisPool{
                connections: make([] *redis.Client, 6),
                maxIdle:     6,

                connFn:      func () (*redis.Client, error) {
                    client := redis.New()
                    err := client.Connect("localhost", 6379)

                    if err != nil {
                        log.Fatalf("Connect failed: %s\n", err.Error())
                        return nil, err
                    }

                    return client, nil
                },
            },

        },

        "redis",
    }

    return Store
}

func (this *Storage) Save(UID string, s *Socket) (error) {
    this.memory.Save(UID, s)

    if this.StorageType == "redis" {
        if err := this.redis.Save(UID); err != nil {
            return err
        }
    }

    return nil
}

func (this *Storage) Remove(UID string) (error) {
    this.memory.Remove(UID)

    if this.StorageType == "redis" {
        if err := this.redis.Remove(UID); err != nil {
            return err
        }
    }

    return nil
}

func (this *Storage) Client(UID string) (*Socket, error) {
    return this.memory.Client(UID)
}

func (this *Storage) Clients() (map[string] *Socket, error) {
    return this.memory.Clients()
}

func (this *Storage) ClientList() ([]string, error) {
    if this.StorageType == "redis" {
        return this.redis.Clients()
    }

    return nil, nil
}

func (this *Storage) Count() (int64, error) {
    if this.StorageType == "redis" {
        return this.redis.Count()
    }

    return this.memory.Count()
}
<commit_msg>fix for allocating connection array, don't specify array size<commit_after>package main

import (
    "log"
    "menteslibres.net/gosexy/redis"
)

type Storage struct {
    memory      MemoryStore
    redis       RedisStore
    StorageType string
}

func initStore(Config *Configuration) Storage{
    var Store = Storage{
        MemoryStore{make(map[string]*Socket), 0},
        RedisStore{
            ClientsKey,

            "localhost",
            6379,

            redisPool{
                connections: []*redis.Client{},
                maxIdle:     6,

                connFn:      func () (*redis.Client, error) {
                    client := redis.New()
                    err := client.Connect("localhost", 6379)

                    if err != nil {
                        log.Fatalf("Connect failed: %s\n", err.Error())
                        return nil, err
                    }

                    return client, nil
                },
            },

        },

        "redis",
    }

    return Store
}

func (this *Storage) Save(UID string, s *Socket) (error) {
    this.memory.Save(UID, s)

    if this.StorageType == "redis" {
        if err := this.redis.Save(UID); err != nil {
            return err
        }
    }

    return nil
}

func (this *Storage) Remove(UID string) (error) {
    this.memory.Remove(UID)

    if this.StorageType == "redis" {
        if err := this.redis.Remove(UID); err != nil {
            return err
        }
    }

    return nil
}

func (this *Storage) Client(UID string) (*Socket, error) {
    return this.memory.Client(UID)
}

func (this *Storage) Clients() (map[string] *Socket, error) {
    return this.memory.Clients()
}

func (this *Storage) ClientList() ([]string, error) {
    if this.StorageType == "redis" {
        return this.redis.Clients()
    }

    return nil, nil
}

func (this *Storage) Count() (int64, error) {
    if this.StorageType == "redis" {
        return this.redis.Count()
    }

    return this.memory.Count()
}
<|endoftext|>


<commit_before>package sudoku

import (
	"testing"
)

func TestBasic(t *testing.T) {
	stack := NewSyncedStack()
	if stack == nil {
		t.Log("Didn't get a stack back.")
		t.Fail()
	}
	if stack.Length() != 0 {
		t.Log("A new stack did not have a length of one")
		t.Fail()
	}
	item := map[string]int{"a": 1}
	secondItem := map[string]int{"b": 2}
	stack.Insert(item)
	if stack.Length() != 1 {
		t.Log("We inserted an item but the length did not go up by one.")
		t.Fail()
	}
	rawResult := stack.Pop()
	if rawResult == nil {
		t.Log("We didn't get back an item from a queue with one item.")
		t.Fail()
	}
	result := rawResult.(map[string]int)
	if _, ok := result["a"]; !ok {
		t.Log("We didn't get back the item we put in.")
		t.Fail()
	}
	if stack.Length() != 0 {
		t.Log("We removed an item but the stack still has one.")
		t.Fail()
	}
	if stack.Pop() != nil {
		t.Log("We were able to get another item out of the stack even though there should have only been one.")
		t.Fail()
	}
	stack.Insert(item)
	stack.Insert(secondItem)
	rawResult = stack.Pop()
	if rawResult == nil {
		t.Log("We didn't get back an item from a queue with two items")
		t.Fail()
	}
	result = rawResult.(map[string]int)
	if _, ok := result["b"]; !ok {
		t.Log("We got the wrong item back from a two item queue.")
		t.Fail()
	}
	stack.Insert(secondItem)
	//This should always be the last item.
	rawResult = stack.Get(0.0)
	if rawResult == nil {
		t.Log("We didn't get back the first item with probability 0")
		t.Fail()
	}
	result = rawResult.(map[string]int)
	if _, ok := result["a"]; !ok {
		t.Log("We didn't get back the first item")
		t.Fail()
	}
	if stack.Length() != 1 {
		t.Log("We got back wrong length for a queue with one item")
		t.Fail()
	}
	rawResult = stack.Get(0.0)
	if rawResult == nil {
		t.Log("We didn't get back the only item with probability 0.0")
		t.Fail()
	}
	result = rawResult.(map[string]int)
	if _, ok := result["b"]; !ok {
		t.Log("We got the wrong item out of a queue with one item")
		t.Fail()
	}
}
<commit_msg>Renamed the test func for SyncedStack to be more descriptive.<commit_after>package sudoku

import (
	"testing"
)

func TestBasicSyncedStack(t *testing.T) {
	stack := NewSyncedStack()
	if stack == nil {
		t.Log("Didn't get a stack back.")
		t.Fail()
	}
	if stack.Length() != 0 {
		t.Log("A new stack did not have a length of one")
		t.Fail()
	}
	item := map[string]int{"a": 1}
	secondItem := map[string]int{"b": 2}
	stack.Insert(item)
	if stack.Length() != 1 {
		t.Log("We inserted an item but the length did not go up by one.")
		t.Fail()
	}
	rawResult := stack.Pop()
	if rawResult == nil {
		t.Log("We didn't get back an item from a queue with one item.")
		t.Fail()
	}
	result := rawResult.(map[string]int)
	if _, ok := result["a"]; !ok {
		t.Log("We didn't get back the item we put in.")
		t.Fail()
	}
	if stack.Length() != 0 {
		t.Log("We removed an item but the stack still has one.")
		t.Fail()
	}
	if stack.Pop() != nil {
		t.Log("We were able to get another item out of the stack even though there should have only been one.")
		t.Fail()
	}
	stack.Insert(item)
	stack.Insert(secondItem)
	rawResult = stack.Pop()
	if rawResult == nil {
		t.Log("We didn't get back an item from a queue with two items")
		t.Fail()
	}
	result = rawResult.(map[string]int)
	if _, ok := result["b"]; !ok {
		t.Log("We got the wrong item back from a two item queue.")
		t.Fail()
	}
	stack.Insert(secondItem)
	//This should always be the last item.
	rawResult = stack.Get(0.0)
	if rawResult == nil {
		t.Log("We didn't get back the first item with probability 0")
		t.Fail()
	}
	result = rawResult.(map[string]int)
	if _, ok := result["a"]; !ok {
		t.Log("We didn't get back the first item")
		t.Fail()
	}
	if stack.Length() != 1 {
		t.Log("We got back wrong length for a queue with one item")
		t.Fail()
	}
	rawResult = stack.Get(0.0)
	if rawResult == nil {
		t.Log("We didn't get back the only item with probability 0.0")
		t.Fail()
	}
	result = rawResult.(map[string]int)
	if _, ok := result["b"]; !ok {
		t.Log("We got the wrong item out of a queue with one item")
		t.Fail()
	}
}
<|endoftext|>


<commit_before>/*
 * This file is part of the KubeVirt project
 *
 * 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.
 *
 * Copyright 2020 Red Hat, Inc.
 *
 */

package network

import (
	"time"

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

	"kubevirt.io/kubevirt/tests/util"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	v1 "kubevirt.io/api/core/v1"
	"kubevirt.io/client-go/kubecli"

	"kubevirt.io/kubevirt/tests"
	"kubevirt.io/kubevirt/tests/console"
	"kubevirt.io/kubevirt/tests/libnet"
	"kubevirt.io/kubevirt/tests/libvmi"
)

var _ = SIGDescribe("Primary Pod Network", func() {
	var virtClient kubecli.KubevirtClient
	BeforeEach(func() {
		var err error
		virtClient, err = kubecli.GetKubevirtClient()
		Expect(err).NotTo(HaveOccurred(), "Should successfully initialize an API client")
	})

	Describe("Status", func() {
		AssertReportedIP := func(vmi *v1.VirtualMachineInstance) {
			By("Getting pod of the VMI")
			vmiPod := tests.GetRunningPodByVirtualMachineInstance(vmi, util.NamespaceTestDefault)

			By("Making sure IP/s reported on the VMI matches the ones on the pod")
			Expect(libnet.ValidateVMIandPodIPMatch(vmi, vmiPod)).To(Succeed(), "Should have matching IP/s between pod and vmi")
		}

		Context("VMI connected to the pod network using the default (implicit) binding", func() {
			var vmi *v1.VirtualMachineInstance

			BeforeEach(func() {
				vmi = setupVMI(virtClient, libvmi.NewAlpine())
			})

			It("should report PodIP as its own on interface status", func() { AssertReportedIP(vmi) })
		})

		Context("VMI connected to the pod network using bridge binding", func() {
			When("Guest Agent exists", func() {
				var (
					vmi   *v1.VirtualMachineInstance
					vmiIP = func() string {
						var err error
						vmi, err = virtClient.VirtualMachineInstance(vmi.Namespace).Get(vmi.Name, &metav1.GetOptions{})
						ExpectWithOffset(1, err).ToNot(HaveOccurred(), "should success retrieving VMI to get IP")
						return vmi.Status.Interfaces[0].IP
					}

					vmiIPs = func() []string {
						var err error
						vmi, err = virtClient.VirtualMachineInstance(vmi.Namespace).Get(vmi.Name, &metav1.GetOptions{})
						ExpectWithOffset(1, err).ToNot(HaveOccurred(), "should success retrieving VMI to get IPs")
						return vmi.Status.Interfaces[0].IPs
					}
				)
				BeforeEach(func() {
					libnet.SkipWhenClusterNotSupportIpv4(virtClient)
					var err error

					vmi, err = newFedoraWithGuestAgentAndDefaultInterface(libvmi.InterfaceDeviceWithBridgeBinding(libvmi.DefaultInterfaceName))
					Expect(err).NotTo(HaveOccurred())

					vmi, err = virtClient.VirtualMachineInstance(util.NamespaceTestDefault).Create(vmi)
					Expect(err).NotTo(HaveOccurred())
					tests.WaitForSuccessfulVMIStart(vmi)
					tests.WaitAgentConnected(virtClient, vmi)
				})

				It("should report PodIP/s IPv4 as its own on interface status", func() {
					vmiPod := tests.GetRunningPodByVirtualMachineInstance(vmi, vmi.Namespace)
					Eventually(vmiIP).Should(Equal(vmiPod.Status.PodIP), "should contain VMI Status IP as Pod status ip")
					Eventually(vmiIPs).Should(ContainElement(vmiPod.Status.PodIP), "should contain IPv4 reported by guest agent")
				})

				It("should report VMIs static IPv6 at interface status", func() {
					Eventually(vmiIPs).Should(ContainElement(libnet.DefaultIPv6Address), "should contain IPv6 address set by cloud-init and reported by guest agent")
				})
			})
			When("no Guest Agent exists", func() {
				var vmi *v1.VirtualMachineInstance

				BeforeEach(func() {
					vmi = setupVMI(
						virtClient,
						libvmi.NewAlpine(
							libvmi.WithInterface(*v1.DefaultBridgeNetworkInterface()),
							libvmi.WithNetwork(v1.DefaultPodNetwork()),
						),
					)
				})

				It("should report PodIP as its own on interface status", func() { AssertReportedIP(vmi) })
			})
		})

		Context("VMI connected to the pod network using masquerade binding", func() {
			When("Guest Agent exists", func() {
				var vmi *v1.VirtualMachineInstance

				BeforeEach(func() {
					tmpVmi, err := newFedoraWithGuestAgentAndDefaultInterface(libvmi.InterfaceDeviceWithMasqueradeBinding())
					Expect(err).NotTo(HaveOccurred())

					tmpVmi, err = virtClient.VirtualMachineInstance(util.NamespaceTestDefault).Create(tmpVmi)
					Expect(err).NotTo(HaveOccurred())
					vmi = tests.WaitUntilVMIReady(tmpVmi, console.LoginToFedora)

					tests.WaitAgentConnected(virtClient, vmi)
				})

				It("[test_id:4153]should report PodIP/s as its own on interface status", func() {
					vmiPod := tests.GetRunningPodByVirtualMachineInstance(vmi, vmi.Namespace)
					Consistently(func() error {
						vmi, err := virtClient.VirtualMachineInstance(vmi.Namespace).Get(vmi.Name, &metav1.GetOptions{})
						if err != nil {
							return err
						}
						return libnet.ValidateVMIandPodIPMatch(vmi, vmiPod)
					}, 5*time.Second, time.Second).Should(Succeed())
				})

			})

			When("no Guest Agent exists", func() {
				var vmi *v1.VirtualMachineInstance

				BeforeEach(func() {
					vmi = setupVMI(
						virtClient,
						libvmi.NewAlpine(
							libvmi.WithInterface(*v1.DefaultMasqueradeNetworkInterface()),
							libvmi.WithNetwork(v1.DefaultPodNetwork()),
						),
					)
				})

				It("[Conformance] should report PodIP as its own on interface status", func() { AssertReportedIP(vmi) })
			})
		})
	})
})

func setupVMI(virtClient kubecli.KubevirtClient, vmi *v1.VirtualMachineInstance) *v1.VirtualMachineInstance {
	By("Creating the VMI")
	var err error
	vmi, err = virtClient.VirtualMachineInstance(util.NamespaceTestDefault).Create(vmi)
	Expect(err).NotTo(HaveOccurred(), "VMI should be successfully created")

	By("Waiting until the VMI gets ready")
	vmi = tests.WaitUntilVMIReady(vmi, console.LoginToAlpine)

	return vmi
}

func newFedoraWithGuestAgentAndDefaultInterface(iface v1.Interface) (*v1.VirtualMachineInstance, error) {
	networkData := libnet.CreateDefaultCloudInitNetworkData()

	vmi := libvmi.NewFedora(
		libvmi.WithInterface(iface),
		libvmi.WithNetwork(v1.DefaultPodNetwork()),
		libvmi.WithCloudInitNoCloudNetworkData(networkData),
	)
	return vmi, nil
}
<commit_msg>guest-agent, tests: Increase timeout fetching pod IPs<commit_after>/*
 * This file is part of the KubeVirt project
 *
 * 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.
 *
 * Copyright 2020 Red Hat, Inc.
 *
 */

package network

import (
	"time"

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

	"kubevirt.io/kubevirt/tests/util"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	v1 "kubevirt.io/api/core/v1"
	"kubevirt.io/client-go/kubecli"

	"kubevirt.io/kubevirt/tests"
	"kubevirt.io/kubevirt/tests/console"
	"kubevirt.io/kubevirt/tests/libnet"
	"kubevirt.io/kubevirt/tests/libvmi"
)

var _ = SIGDescribe("Primary Pod Network", func() {
	var virtClient kubecli.KubevirtClient
	BeforeEach(func() {
		var err error
		virtClient, err = kubecli.GetKubevirtClient()
		Expect(err).NotTo(HaveOccurred(), "Should successfully initialize an API client")
	})

	Describe("Status", func() {
		AssertReportedIP := func(vmi *v1.VirtualMachineInstance) {
			By("Getting pod of the VMI")
			vmiPod := tests.GetRunningPodByVirtualMachineInstance(vmi, util.NamespaceTestDefault)

			By("Making sure IP/s reported on the VMI matches the ones on the pod")
			Expect(libnet.ValidateVMIandPodIPMatch(vmi, vmiPod)).To(Succeed(), "Should have matching IP/s between pod and vmi")
		}

		Context("VMI connected to the pod network using the default (implicit) binding", func() {
			var vmi *v1.VirtualMachineInstance

			BeforeEach(func() {
				vmi = setupVMI(virtClient, libvmi.NewAlpine())
			})

			It("should report PodIP as its own on interface status", func() { AssertReportedIP(vmi) })
		})

		Context("VMI connected to the pod network using bridge binding", func() {
			When("Guest Agent exists", func() {
				var (
					vmi   *v1.VirtualMachineInstance
					vmiIP = func() string {
						var err error
						vmi, err = virtClient.VirtualMachineInstance(vmi.Namespace).Get(vmi.Name, &metav1.GetOptions{})
						ExpectWithOffset(1, err).ToNot(HaveOccurred(), "should success retrieving VMI to get IP")
						return vmi.Status.Interfaces[0].IP
					}

					vmiIPs = func() []string {
						var err error
						vmi, err = virtClient.VirtualMachineInstance(vmi.Namespace).Get(vmi.Name, &metav1.GetOptions{})
						ExpectWithOffset(1, err).ToNot(HaveOccurred(), "should success retrieving VMI to get IPs")
						return vmi.Status.Interfaces[0].IPs
					}
				)
				BeforeEach(func() {
					libnet.SkipWhenClusterNotSupportIpv4(virtClient)
					var err error

					vmi, err = newFedoraWithGuestAgentAndDefaultInterface(libvmi.InterfaceDeviceWithBridgeBinding(libvmi.DefaultInterfaceName))
					Expect(err).NotTo(HaveOccurred())

					vmi, err = virtClient.VirtualMachineInstance(util.NamespaceTestDefault).Create(vmi)
					Expect(err).NotTo(HaveOccurred())
					tests.WaitForSuccessfulVMIStart(vmi)
					tests.WaitAgentConnected(virtClient, vmi)
				})

				It("should report PodIP/s IPv4 as its own on interface status", func() {
					vmiPod := tests.GetRunningPodByVirtualMachineInstance(vmi, vmi.Namespace)
					Eventually(vmiIP, 2*time.Minute, 5*time.Second).Should(Equal(vmiPod.Status.PodIP), "should contain VMI Status IP as Pod status ip")
					Eventually(vmiIPs, 2*time.Minute, 5*time.Second).Should(ContainElement(vmiPod.Status.PodIP), "should contain IPv4 reported by guest agent")
				})

				It("should report VMIs static IPv6 at interface status", func() {
					Eventually(vmiIPs, 2*time.Minute, 5*time.Second).Should(ContainElement(libnet.DefaultIPv6Address), "should contain IPv6 address set by cloud-init and reported by guest agent")
				})
			})
			When("no Guest Agent exists", func() {
				var vmi *v1.VirtualMachineInstance

				BeforeEach(func() {
					vmi = setupVMI(
						virtClient,
						libvmi.NewAlpine(
							libvmi.WithInterface(*v1.DefaultBridgeNetworkInterface()),
							libvmi.WithNetwork(v1.DefaultPodNetwork()),
						),
					)
				})

				It("should report PodIP as its own on interface status", func() { AssertReportedIP(vmi) })
			})
		})

		Context("VMI connected to the pod network using masquerade binding", func() {
			When("Guest Agent exists", func() {
				var vmi *v1.VirtualMachineInstance

				BeforeEach(func() {
					tmpVmi, err := newFedoraWithGuestAgentAndDefaultInterface(libvmi.InterfaceDeviceWithMasqueradeBinding())
					Expect(err).NotTo(HaveOccurred())

					tmpVmi, err = virtClient.VirtualMachineInstance(util.NamespaceTestDefault).Create(tmpVmi)
					Expect(err).NotTo(HaveOccurred())
					vmi = tests.WaitUntilVMIReady(tmpVmi, console.LoginToFedora)

					tests.WaitAgentConnected(virtClient, vmi)
				})

				It("[test_id:4153]should report PodIP/s as its own on interface status", func() {
					vmiPod := tests.GetRunningPodByVirtualMachineInstance(vmi, vmi.Namespace)
					Consistently(func() error {
						vmi, err := virtClient.VirtualMachineInstance(vmi.Namespace).Get(vmi.Name, &metav1.GetOptions{})
						if err != nil {
							return err
						}
						return libnet.ValidateVMIandPodIPMatch(vmi, vmiPod)
					}, 5*time.Second, time.Second).Should(Succeed())
				})

			})

			When("no Guest Agent exists", func() {
				var vmi *v1.VirtualMachineInstance

				BeforeEach(func() {
					vmi = setupVMI(
						virtClient,
						libvmi.NewAlpine(
							libvmi.WithInterface(*v1.DefaultMasqueradeNetworkInterface()),
							libvmi.WithNetwork(v1.DefaultPodNetwork()),
						),
					)
				})

				It("[Conformance] should report PodIP as its own on interface status", func() { AssertReportedIP(vmi) })
			})
		})
	})
})

func setupVMI(virtClient kubecli.KubevirtClient, vmi *v1.VirtualMachineInstance) *v1.VirtualMachineInstance {
	By("Creating the VMI")
	var err error
	vmi, err = virtClient.VirtualMachineInstance(util.NamespaceTestDefault).Create(vmi)
	Expect(err).NotTo(HaveOccurred(), "VMI should be successfully created")

	By("Waiting until the VMI gets ready")
	vmi = tests.WaitUntilVMIReady(vmi, console.LoginToAlpine)

	return vmi
}

func newFedoraWithGuestAgentAndDefaultInterface(iface v1.Interface) (*v1.VirtualMachineInstance, error) {
	networkData := libnet.CreateDefaultCloudInitNetworkData()

	vmi := libvmi.NewFedora(
		libvmi.WithInterface(iface),
		libvmi.WithNetwork(v1.DefaultPodNetwork()),
		libvmi.WithCloudInitNoCloudNetworkData(networkData),
	)
	return vmi, nil
}
<|endoftext|>


<commit_before><commit_msg>test(outputs.sql): wait for db dump file to exist (#12149)<commit_after><|endoftext|>