<commit_before>package ifsc

import (
	"bytes"
	"encoding/json"
	"errors"
	"io/ioutil"
	"net/http"
	"testing"

	"github.com/razorpay/ifsc/v2/src/go/mocks"
	"github.com/stretchr/testify/assert"
)

func getIfscResponse() *IFSCResponse {
	bytes := []byte(`{"micr":"560226263",
		"branch":"THE AGS EMPLOYEES COOP BANK LTD",
		"address":"SANGMESH BIRADAR BANGALORE",
		"state":"KARNATAKA",
		"contact":"+91802265658",
		"upi":true,
		"rtgs":true,
		"city":"BANGALORE",
		"centre":"BANGALORE URBAN",
		"district":"BANGALORE URBAN",
		"neft":true,"imps":true,
		"swift":"HDFCINBB",
		"bank":"HDFC Bank",
		"bank_code":"HDFC",
		"ifsc":"HDFC0CAGSBK"}`)
	var response IFSCResponse
	if err := json.Unmarshal(bytes, &response); err != nil {
		return nil
	}
	return &response
}
func TestLookUP(t *testing.T) {
	client = &mocks.Client{}
	type args struct {
		ifsc string
	}
	tests := []struct {
		name         string
		args         args
		IfscResponse *IFSCResponse
		mockedClient func()
		wantErr      bool
		err          error
	}{
		{
			"success",
			args{"HDFC0CAGSBK"},
			getIfscResponse(),
			GetSuccessMockResponse,
			false,
			nil,
		},
		{
			"failure, invalid code",
			args{"KKB0000abc1"},
			nil,
			GetInvalidCodeMockResponse,
			true,
			ErrInvalidCode,
		},
		{
			"failure, invalid Response",
			args{"AIRP0000001"},
			nil,
			GetFailureMockResponse,
			true,
			ErrInvalidResponse,
		},
		{
			"timeout error",
			args{"abcd"},
			nil,
			GetUrlError,
			true,
			http.ErrHandlerTimeout,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			var err error
			var got *IFSCResponse
			tt.mockedClient()
			got, err = LookUP(tt.args.ifsc)
			if (err != nil) != tt.wantErr {
				t.Errorf("LookUP() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if tt.wantErr {
				if !errors.Is(tt.err, err) {
					t.Errorf("error is not equal. want()=%v, got()=%v", tt.err, err)
				}
			} else {
				assert.Equal(t, tt.IfscResponse.Bank, got.Bank)
				assert.Equal(t, tt.IfscResponse.Branch, got.Branch)
				assert.Equal(t, tt.IfscResponse.Centre, got.Centre)
				assert.Equal(t, tt.IfscResponse.District, got.District)
				assert.Equal(t, tt.IfscResponse.State, got.State)
				assert.Equal(t, tt.IfscResponse.Address, got.Address)
				assert.Equal(t, tt.IfscResponse.Contact, got.Contact)
				assert.Equal(t, tt.IfscResponse.City, got.City)
				assert.Equal(t, tt.IfscResponse.IFSC, got.IFSC)
				assert.Equal(t, tt.IfscResponse.UPI, got.UPI)
				assert.Equal(t, tt.IfscResponse.RTGS, got.RTGS)
				assert.Equal(t, tt.IfscResponse.MICR, got.MICR)
				assert.Equal(t, tt.IfscResponse.NEFT, got.NEFT)
				assert.Equal(t, tt.IfscResponse.SWIFT, got.SWIFT)
				assert.Equal(t, tt.IfscResponse.IMPS, got.IMPS)
				// assert.Equal(t, tt.IfscResponse.BankCode, got.BankCode)
			}
		})
	}
}
func GetFailureMockResponse() {
	mocks.GetFuncVar = func(url string) (resp *http.Response, err error) {
		return &http.Response{
			StatusCode: http.StatusInternalServerError,
		}, nil
	}

}
func GetInvalidCodeMockResponse() {
	mocks.GetFuncVar = func(url string) (resp *http.Response, err error) {
		return &http.Response{
			StatusCode: http.StatusNotFound,
		}, nil
	}

}

func GetUrlError() {
	mocks.GetFuncVar = func(url string) (resp *http.Response, err error) {
		return nil, http.ErrHandlerTimeout
	}
}

func GetSuccessMockResponse() {
	mocks.GetFuncVar = func(url string) (resp *http.Response, err error) {
		var successJson = `{
			"MICR":"560226263",
			"BRANCH":"THE AGS EMPLOYEES COOP BANK LTD",
			"ADDRESS":"SANGMESH BIRADAR BANGALORE",
			"STATE":"KARNATAKA",
			"CONTACT":"+91802265658",
			"UPI":true,
			"RTGS":true,
			"CITY":"BANGALORE",
			"CENTRE":"BANGALORE URBAN",
			"DISTRICT":"BANGALORE URBAN",
			"NEFT":true,"IMPS":true,
			"SWIFT":"HDFCINBB",
			"BANK":"HDFC Bank",
			"BANKCODE":"HDFC",
			"IFSC":"HDFC0CAGSBK"
		}`
		r := ioutil.NopCloser(bytes.NewReader([]byte(successJson)))
		return &http.Response{
			StatusCode: http.StatusOK,
			Body:       r,
		}, nil
	}

}

func TestIFSCResponse_GetBankName(t *testing.T) {
	type fields struct {
		Bank     string
		Branch   string
		Address  string
		Contact  string
		City     string
		District string
		State    string
		BankCode string
		IFSC     string
	}
	tests := []struct {
		name   string
		fields fields
		want   string
	}{
		{
			"success",
			fields{
				IFSC: "HDFC0CADARS",
			},
			"HDFC Bank",
		},
		{
			"failure",
			fields{
				IFSC: "12 B",
			},
			"",
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			expected := &IFSCResponse{
				Bank:     &tt.fields.Bank,
				Branch:   &tt.fields.Branch,
				Address:  &tt.fields.Address,
				Contact:  &tt.fields.Contact,
				City:     &tt.fields.City,
				District: &tt.fields.District,
				State:    &tt.fields.State,
				BankCode: &tt.fields.BankCode,
				IFSC:     &tt.fields.IFSC,
			}
			if got := expected.GetBankName(); got != tt.want {
				t.Errorf("IFSCResponse.GetBankName() = %v, want %v", got, tt.want)
			}
		})
	}
}
<commit_msg>[go] Uncomment test<commit_after>package ifsc

import (
	"bytes"
	"encoding/json"
	"errors"
	"io/ioutil"
	"net/http"
	"testing"

	"github.com/razorpay/ifsc/v2/src/go/mocks"
	"github.com/stretchr/testify/assert"
)

func getIfscResponse() *IFSCResponse {
	bytes := []byte(`{"micr":"560226263",
		"branch":"THE AGS EMPLOYEES COOP BANK LTD",
		"address":"SANGMESH BIRADAR BANGALORE",
		"state":"KARNATAKA",
		"contact":"+91802265658",
		"upi":true,
		"rtgs":true,
		"city":"BANGALORE",
		"centre":"BANGALORE URBAN",
		"district":"BANGALORE URBAN",
		"neft":true,"imps":true,
		"swift":"HDFCINBB",
		"bank":"HDFC Bank",
		"bank_code":"HDFC",
		"ifsc":"HDFC0CAGSBK"}`)
	var response IFSCResponse
	if err := json.Unmarshal(bytes, &response); err != nil {
		return nil
	}
	return &response
}
func TestLookUP(t *testing.T) {
	client = &mocks.Client{}
	type args struct {
		ifsc string
	}
	tests := []struct {
		name         string
		args         args
		IfscResponse *IFSCResponse
		mockedClient func()
		wantErr      bool
		err          error
	}{
		{
			"success",
			args{"HDFC0CAGSBK"},
			getIfscResponse(),
			GetSuccessMockResponse,
			false,
			nil,
		},
		{
			"failure, invalid code",
			args{"KKB0000abc1"},
			nil,
			GetInvalidCodeMockResponse,
			true,
			ErrInvalidCode,
		},
		{
			"failure, invalid Response",
			args{"AIRP0000001"},
			nil,
			GetFailureMockResponse,
			true,
			ErrInvalidResponse,
		},
		{
			"timeout error",
			args{"abcd"},
			nil,
			GetUrlError,
			true,
			http.ErrHandlerTimeout,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			var err error
			var got *IFSCResponse
			tt.mockedClient()
			got, err = LookUP(tt.args.ifsc)
			if (err != nil) != tt.wantErr {
				t.Errorf("LookUP() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if tt.wantErr {
				if !errors.Is(tt.err, err) {
					t.Errorf("error is not equal. want()=%v, got()=%v", tt.err, err)
				}
			} else {
				assert.Equal(t, tt.IfscResponse.Bank, got.Bank)
				assert.Equal(t, tt.IfscResponse.Branch, got.Branch)
				assert.Equal(t, tt.IfscResponse.Centre, got.Centre)
				assert.Equal(t, tt.IfscResponse.District, got.District)
				assert.Equal(t, tt.IfscResponse.State, got.State)
				assert.Equal(t, tt.IfscResponse.Address, got.Address)
				assert.Equal(t, tt.IfscResponse.Contact, got.Contact)
				assert.Equal(t, tt.IfscResponse.City, got.City)
				assert.Equal(t, tt.IfscResponse.IFSC, got.IFSC)
				assert.Equal(t, tt.IfscResponse.UPI, got.UPI)
				assert.Equal(t, tt.IfscResponse.RTGS, got.RTGS)
				assert.Equal(t, tt.IfscResponse.MICR, got.MICR)
				assert.Equal(t, tt.IfscResponse.NEFT, got.NEFT)
				assert.Equal(t, tt.IfscResponse.SWIFT, got.SWIFT)
				assert.Equal(t, tt.IfscResponse.IMPS, got.IMPS)
				assert.Equal(t, tt.IfscResponse.BankCode, got.BankCode)
			}
		})
	}
}
func GetFailureMockResponse() {
	mocks.GetFuncVar = func(url string) (resp *http.Response, err error) {
		return &http.Response{
			StatusCode: http.StatusInternalServerError,
		}, nil
	}

}
func GetInvalidCodeMockResponse() {
	mocks.GetFuncVar = func(url string) (resp *http.Response, err error) {
		return &http.Response{
			StatusCode: http.StatusNotFound,
		}, nil
	}

}

func GetUrlError() {
	mocks.GetFuncVar = func(url string) (resp *http.Response, err error) {
		return nil, http.ErrHandlerTimeout
	}
}

func GetSuccessMockResponse() {
	mocks.GetFuncVar = func(url string) (resp *http.Response, err error) {
		var successJson = `{
			"MICR":"560226263",
			"BRANCH":"THE AGS EMPLOYEES COOP BANK LTD",
			"ADDRESS":"SANGMESH BIRADAR BANGALORE",
			"STATE":"KARNATAKA",
			"CONTACT":"+91802265658",
			"UPI":true,
			"RTGS":true,
			"CITY":"BANGALORE",
			"CENTRE":"BANGALORE URBAN",
			"DISTRICT":"BANGALORE URBAN",
			"NEFT":true,"IMPS":true,
			"SWIFT":"HDFCINBB",
			"BANK":"HDFC Bank",
			"BANKCODE":"HDFC",
			"IFSC":"HDFC0CAGSBK"
		}`
		r := ioutil.NopCloser(bytes.NewReader([]byte(successJson)))
		return &http.Response{
			StatusCode: http.StatusOK,
			Body:       r,
		}, nil
	}

}

func TestIFSCResponse_GetBankName(t *testing.T) {
	type fields struct {
		Bank     string
		Branch   string
		Address  string
		Contact  string
		City     string
		District string
		State    string
		BankCode string
		IFSC     string
	}
	tests := []struct {
		name   string
		fields fields
		want   string
	}{
		{
			"success",
			fields{
				IFSC: "HDFC0CADARS",
			},
			"HDFC Bank",
		},
		{
			"failure",
			fields{
				IFSC: "12 B",
			},
			"",
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			expected := &IFSCResponse{
				Bank:     &tt.fields.Bank,
				Branch:   &tt.fields.Branch,
				Address:  &tt.fields.Address,
				Contact:  &tt.fields.Contact,
				City:     &tt.fields.City,
				District: &tt.fields.District,
				State:    &tt.fields.State,
				BankCode: &tt.fields.BankCode,
				IFSC:     &tt.fields.IFSC,
			}
			if got := expected.GetBankName(); got != tt.want {
				t.Errorf("IFSCResponse.GetBankName() = %v, want %v", got, tt.want)
			}
		})
	}
}
<|endoftext|>


<commit_before>package softlayer

import (
	datatypes "github.com/TheWeatherCompany/softlayer-go/data_types"
)

type SoftLayer_Dns_Domain_Record_Service interface {
	Service

	CreateObject(template datatypes.SoftLayer_Dns_Domain_Record_Template) (datatypes.SoftLayer_Dns_Domain_Record, error)
	GetObject(recordId int) (datatypes.SoftLayer_Dns_Domain_Record, error)
	DeleteObject(recordId int) (bool, error)
	EditObject(recordId int, template datatypes.SoftLayer_Dns_Domain_Record) (bool, error)
}
<commit_msg>#8 CreateObjects method implemented for bulk records creation. It needs for re-create DNS to keep existing records.<commit_after>package softlayer

import (
	datatypes "github.com/TheWeatherCompany/softlayer-go/data_types"
)

type SoftLayer_Dns_Domain_Record_Service interface {
	Service

	CreateObject(template datatypes.SoftLayer_Dns_Domain_Record_Template) (datatypes.SoftLayer_Dns_Domain_Record, error)
	CreateObjects(template []datatypes.SoftLayer_Dns_Domain_Record_Template) ([]datatypes.SoftLayer_Dns_Domain_Record, error)
	GetObject(recordId int) (datatypes.SoftLayer_Dns_Domain_Record, error)
	DeleteObject(recordId int) (bool, error)
	EditObject(recordId int, template datatypes.SoftLayer_Dns_Domain_Record) (bool, error)
}
<|endoftext|>


<commit_before>// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package client

import (
	"crypto/rand"
	"errors"
	"fmt"
	"io"
	"sync"
	"time"

	"context"

	log "github.com/golang/glog"
	"github.com/golang/protobuf/proto"
	"github.com/google/fleetspeak/fleetspeak/src/client/service"
	"github.com/google/fleetspeak/fleetspeak/src/common"

	fspb "github.com/google/fleetspeak/fleetspeak/src/common/proto/fleetspeak"
)

// A serviceConfiguration manages and communicates the services installed on a
// client. In normal use it is a singleton.
type serviceConfiguration struct {
	services  map[string]*serviceData
	lock      sync.RWMutex // Protects the structure of services.
	client    *Client
	factories map[string]service.Factory // Used to look up correct factory when configuring services.
}

func (c *serviceConfiguration) ProcessMessage(ctx context.Context, m *fspb.Message) error {
	c.lock.RLock()
	target := c.services[m.Destination.ServiceName]
	c.lock.RUnlock()

	if target == nil {
		return fmt.Errorf("Destination service not installed.")
	}
	select {
	case target.inbox <- m:
		return nil
	case <-ctx.Done():
		return ctx.Err()
	}
}

func (c *serviceConfiguration) InstallSignedService(sd *fspb.SignedClientServiceConfig) error {
	if err := c.client.config.ValidateServiceConfig(sd); err != nil {
		return fmt.Errorf("Unable to verify signature of service config %v, ignoring: %v", sd.Signature, err)
	}

	var cfg fspb.ClientServiceConfig
	if err := proto.Unmarshal(sd.ServiceConfig, &cfg); err != nil {
		return fmt.Errorf("Unable to parse service config [%v], ignoring: %v", sd.Signature, err)
	}

ll:
	for _, l := range cfg.RequiredLabels {
		if l.ServiceName == "client" {
			for _, cl := range c.client.cfg.ClientLabels {
				if cl.Label == l.Label {
					continue ll
				}
			}
			return fmt.Errorf("Service config requires label %v.", l)
		}
	}

	return c.InstallService(&cfg, sd.Signature)
}

func (c *serviceConfiguration) InstallService(cfg *fspb.ClientServiceConfig, sig []byte) error {

	if cfg.Name == "" || cfg.Name == "system" || cfg.Name == "client" {
		return fmt.Errorf("illegal service name [%v]", cfg.Name)
	}

	f := c.factories[cfg.Factory]
	if f == nil {
		return fmt.Errorf("factory not found [%v]", cfg.Factory)
	}
	s, err := f(cfg)
	if err != nil {
		return fmt.Errorf("unable to create service: %v", err)
	}

	d := serviceData{
		config:  c,
		name:    cfg.Name,
		service: s,
		inbox:   make(chan *fspb.Message, 5),
	}
	if err := d.start(); err != nil {
		return fmt.Errorf("unable to start service: %v", err)
	}

	d.working.Add(1)
	go d.processingLoop()

	c.lock.Lock()
	old := c.services[cfg.Name]
	c.services[cfg.Name] = &d
	c.client.config.RecordRunningService(cfg.Name, sig)
	c.lock.Unlock()

	if old != nil {
		old.stop()
	}

	log.Infof("Started service %v with config:\n%v", cfg.Name, cfg)
	return nil
}

func (c *serviceConfiguration) Stop() {
	c.lock.Lock()
	defer c.lock.Unlock()
	for _, sd := range c.services {
		sd.stop()
	}
	c.services = make(map[string]*serviceData)
}

// A serviceData contains the data we have about a configured service, wrapping
// a Service interface and mediating communication between it and the rest of
// the Fleetspeak client.
type serviceData struct {
	config  *serviceConfiguration
	name    string
	working sync.WaitGroup
	service service.Service
	inbox   chan *fspb.Message
}

// Send implements service.Context.
func (d *serviceData) Send(ctx context.Context, am service.AckMessage) error {
	m := am.M
	id := d.config.client.config.ClientID().Bytes()

	m.Source = &fspb.Address{
		ClientId:    id,
		ServiceName: d.name,
	}

	if len(m.SourceMessageId) == 0 {
		b := make([]byte, 16)
		if _, err := rand.Read(b); err != nil {
			return fmt.Errorf("unable to create random source message id: %v", err)
		}
		m.SourceMessageId = b
	}

	return d.config.client.ProcessMessage(ctx, am)
}

// GetLocalInfo implements service.Context.
func (d *serviceData) GetLocalInfo() *service.LocalInfo {
	ret := &service.LocalInfo{
		ClientID: d.config.client.config.ClientID(),
		Labels:   d.config.client.config.Labels(),
	}

	d.config.lock.RLock()
	defer d.config.lock.RUnlock()
	for s := range d.config.services {
		if s != "system" {
			ret.Services = append(ret.Services, s)
		}
	}
	return ret
}

// GetFileIfModified implements service.Context.
func (d *serviceData) GetFileIfModified(ctx context.Context, name string, modSince time.Time) (io.ReadCloser, time.Time, error) {
	if d.config.client.com == nil {
		// happens during tests
		return nil, time.Time{}, errors.New("file not found")
	}
	return d.config.client.com.GetFileIfModified(ctx, d.name, name, modSince)
}

func (d *serviceData) processingLoop() {
	// TODO: Kill misbehaving processes, limit processes'
	//       memory quota and niceness.

	for {
		m, ok := <-d.inbox
		if !ok {
			d.working.Done()
			return
		}
		id, err := common.BytesToMessageID(m.MessageId)
		if err != nil {
			log.Errorf("ignoring message with bad message id: [%v]", m.MessageId)
			continue
		}
		if err := d.service.ProcessMessage(context.TODO(), m); err != nil {
			d.config.client.errs <- &fspb.MessageErrorData{
				MessageId: id.Bytes(),
				Error:     err.Error(),
			}
		} else {
			d.config.client.acks <- id
		}
	}
}

func (d *serviceData) start() error {
	return d.service.Start(d)
}

func (d *serviceData) stop() {
	close(d.inbox)
	d.working.Wait()
	d.service.Stop()
}
<commit_msg>Fix error format.<commit_after>// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package client

import (
	"crypto/rand"
	"errors"
	"fmt"
	"io"
	"sync"
	"time"

	"context"

	log "github.com/golang/glog"
	"github.com/golang/protobuf/proto"
	"github.com/google/fleetspeak/fleetspeak/src/client/service"
	"github.com/google/fleetspeak/fleetspeak/src/common"

	fspb "github.com/google/fleetspeak/fleetspeak/src/common/proto/fleetspeak"
)

// A serviceConfiguration manages and communicates the services installed on a
// client. In normal use it is a singleton.
type serviceConfiguration struct {
	services  map[string]*serviceData
	lock      sync.RWMutex // Protects the structure of services.
	client    *Client
	factories map[string]service.Factory // Used to look up correct factory when configuring services.
}

func (c *serviceConfiguration) ProcessMessage(ctx context.Context, m *fspb.Message) error {
	c.lock.RLock()
	target := c.services[m.Destination.ServiceName]
	c.lock.RUnlock()

	if target == nil {
		return fmt.Errorf("Destination service not installed.")
	}
	select {
	case target.inbox <- m:
		return nil
	case <-ctx.Done():
		return ctx.Err()
	}
}

func (c *serviceConfiguration) InstallSignedService(sd *fspb.SignedClientServiceConfig) error {
	if err := c.client.config.ValidateServiceConfig(sd); err != nil {
		return fmt.Errorf("Unable to verify signature of service config %v, ignoring: %v", sd.Signature, err)
	}

	var cfg fspb.ClientServiceConfig
	if err := proto.Unmarshal(sd.ServiceConfig, &cfg); err != nil {
		return fmt.Errorf("Unable to parse service config [%v], ignoring: %v", sd.Signature, err)
	}

ll:
	for _, l := range cfg.RequiredLabels {
		if l.ServiceName == "client" {
			for _, cl := range c.client.cfg.ClientLabels {
				if cl.Label == l.Label {
					continue ll
				}
			}
			return fmt.Errorf("service config requires label %v", l)
		}
	}

	return c.InstallService(&cfg, sd.Signature)
}

func (c *serviceConfiguration) InstallService(cfg *fspb.ClientServiceConfig, sig []byte) error {

	if cfg.Name == "" || cfg.Name == "system" || cfg.Name == "client" {
		return fmt.Errorf("illegal service name [%v]", cfg.Name)
	}

	f := c.factories[cfg.Factory]
	if f == nil {
		return fmt.Errorf("factory not found [%v]", cfg.Factory)
	}
	s, err := f(cfg)
	if err != nil {
		return fmt.Errorf("unable to create service: %v", err)
	}

	d := serviceData{
		config:  c,
		name:    cfg.Name,
		service: s,
		inbox:   make(chan *fspb.Message, 5),
	}
	if err := d.start(); err != nil {
		return fmt.Errorf("unable to start service: %v", err)
	}

	d.working.Add(1)
	go d.processingLoop()

	c.lock.Lock()
	old := c.services[cfg.Name]
	c.services[cfg.Name] = &d
	c.client.config.RecordRunningService(cfg.Name, sig)
	c.lock.Unlock()

	if old != nil {
		old.stop()
	}

	log.Infof("Started service %v with config:\n%v", cfg.Name, cfg)
	return nil
}

func (c *serviceConfiguration) Stop() {
	c.lock.Lock()
	defer c.lock.Unlock()
	for _, sd := range c.services {
		sd.stop()
	}
	c.services = make(map[string]*serviceData)
}

// A serviceData contains the data we have about a configured service, wrapping
// a Service interface and mediating communication between it and the rest of
// the Fleetspeak client.
type serviceData struct {
	config  *serviceConfiguration
	name    string
	working sync.WaitGroup
	service service.Service
	inbox   chan *fspb.Message
}

// Send implements service.Context.
func (d *serviceData) Send(ctx context.Context, am service.AckMessage) error {
	m := am.M
	id := d.config.client.config.ClientID().Bytes()

	m.Source = &fspb.Address{
		ClientId:    id,
		ServiceName: d.name,
	}

	if len(m.SourceMessageId) == 0 {
		b := make([]byte, 16)
		if _, err := rand.Read(b); err != nil {
			return fmt.Errorf("unable to create random source message id: %v", err)
		}
		m.SourceMessageId = b
	}

	return d.config.client.ProcessMessage(ctx, am)
}

// GetLocalInfo implements service.Context.
func (d *serviceData) GetLocalInfo() *service.LocalInfo {
	ret := &service.LocalInfo{
		ClientID: d.config.client.config.ClientID(),
		Labels:   d.config.client.config.Labels(),
	}

	d.config.lock.RLock()
	defer d.config.lock.RUnlock()
	for s := range d.config.services {
		if s != "system" {
			ret.Services = append(ret.Services, s)
		}
	}
	return ret
}

// GetFileIfModified implements service.Context.
func (d *serviceData) GetFileIfModified(ctx context.Context, name string, modSince time.Time) (io.ReadCloser, time.Time, error) {
	if d.config.client.com == nil {
		// happens during tests
		return nil, time.Time{}, errors.New("file not found")
	}
	return d.config.client.com.GetFileIfModified(ctx, d.name, name, modSince)
}

func (d *serviceData) processingLoop() {
	// TODO: Kill misbehaving processes, limit processes'
	//       memory quota and niceness.

	for {
		m, ok := <-d.inbox
		if !ok {
			d.working.Done()
			return
		}
		id, err := common.BytesToMessageID(m.MessageId)
		if err != nil {
			log.Errorf("ignoring message with bad message id: [%v]", m.MessageId)
			continue
		}
		if err := d.service.ProcessMessage(context.TODO(), m); err != nil {
			d.config.client.errs <- &fspb.MessageErrorData{
				MessageId: id.Bytes(),
				Error:     err.Error(),
			}
		} else {
			d.config.client.acks <- id
		}
	}
}

func (d *serviceData) start() error {
	return d.service.Start(d)
}

func (d *serviceData) stop() {
	close(d.inbox)
	d.working.Wait()
	d.service.Stop()
}
<|endoftext|>


<commit_before>package integration_test

import (
	"fmt"
	"net/http"
	"os"
	"os/exec"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/gexec"
	"github.com/onsi/gomega/ghttp"

	"github.com/concourse/concourse/atc"
)

var _ = Describe("Fly CLI", func() {
	Describe("checklist", func() {
		var (
			config atc.Config
			home   string
		)

		BeforeEach(func() {
			config = atc.Config{
				Groups: atc.GroupConfigs{
					{
						Name:      "some-group",
						Jobs:      []string{"job-1", "job-2"},
						Resources: []string{"resource-1", "resource-2"},
					},
					{
						Name:      "some-other-group",
						Jobs:      []string{"job-3", "job-4"},
						Resources: []string{"resource-6", "resource-4"},
					},
				},

				Jobs: atc.JobConfigs{
					{
						Name: "some-orphaned-job",
					},
				},
			}
		})

		AfterEach(func() {
			err := os.RemoveAll(home)
			Expect(err).NotTo(HaveOccurred())
		})

		Context("when a pipeline name is not specified", func() {
			It("errors", func() {
				flyCmd := exec.Command(flyPath, "-t", targetName, "checklist")

				sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
				Expect(err).NotTo(HaveOccurred())

				<-sess.Exited
				Expect(sess.ExitCode()).To(Equal(1))
			})
		})

		Context("when the pipeline flag is invalid", func() {
			It("fails and print invalid flag error", func() {
				flyCmd := exec.Command(flyPath, "-t", targetName, "checklist", "-p", "forbidden/pipelinename")

				sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
				Expect(err).NotTo(HaveOccurred())

				<-sess.Exited
				Expect(sess.ExitCode()).To(Equal(1))

				Expect(sess.Err).To(gbytes.Say("error: invalid argument for flag `" + osFlag("p", "pipeline")))
			})
		})

		Context("when a pipeline name is specified", func() {
			JustBeforeEach(func() {
				atcServer.AppendHandlers(
					ghttp.CombineHandlers(
						ghttp.VerifyRequest("GET", "/api/v1/teams/main/pipelines/some-pipeline/config", "vars.branch=%22master%22"),
						ghttp.RespondWithJSONEncoded(200, atc.ConfigResponse{Config: config}, http.Header{atc.ConfigVersionHeader: {"42"}}),
					),
				)
			})

			Context("when there are groups", func() {
				It("prints the config as yaml to stdout", func() {
					flyCmd := exec.Command(flyPath, "-t", targetName, "checklist", "-p", "some-pipeline/branch:master")

					sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
					Expect(err).NotTo(HaveOccurred())

					<-sess.Exited
					Expect(sess.ExitCode()).To(Equal(0))

					Expect(string(sess.Out.Contents())).To(Equal(fmt.Sprintf(
						`#- some-group
job-1: concourse.check %s main some-pipeline/branch:master job-1
job-2: concourse.check %s main some-pipeline/branch:master job-2

#- some-other-group
job-3: concourse.check %s main some-pipeline/branch:master job-3
job-4: concourse.check %s main some-pipeline/branch:master job-4

#- misc
some-orphaned-job: concourse.check %s main some-pipeline/branch:master some-orphaned-job

`, atcServer.URL(), atcServer.URL(), atcServer.URL(), atcServer.URL(), atcServer.URL())))
				})
			})

			Context("when there are no groups", func() {
				BeforeEach(func() {
					config = atc.Config{
						Jobs: atc.JobConfigs{
							{
								Name: "job-1",
							},
							{
								Name: "job-2",
							},
						},
					}

				})

				It("prints the config as yaml to stdout, and uses the pipeline name as header", func() {
					flyCmd := exec.Command(flyPath, "-t", targetName, "checklist", "-p", "some-pipeline/branch:master")

					sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
					Expect(err).NotTo(HaveOccurred())

					<-sess.Exited
					Expect(sess.ExitCode()).To(Equal(0))

					Expect(string(sess.Out.Contents())).To(Equal(fmt.Sprintf(
						`#- some-pipeline/branch:master
job-1: concourse.check %s main some-pipeline/branch:master job-1
job-2: concourse.check %s main some-pipeline/branch:master job-2

`, atcServer.URL(), atcServer.URL())))
				})
			})
		})

		Context("when a team name is specified alongwith pipeline name", func() {
			JustBeforeEach(func() {
				atcServer.AppendHandlers(
					ghttp.CombineHandlers(
						ghttp.VerifyRequest("GET", "/api/v1/teams/other-team"),
						ghttp.RespondWithJSONEncoded(http.StatusOK, atc.Team{
							Name: "other-team",
						}),
					),
					ghttp.CombineHandlers(
						ghttp.VerifyRequest("GET", "/api/v1/teams/other-team/pipelines/some-pipeline/config"),
						ghttp.RespondWithJSONEncoded(http.StatusOK, atc.ConfigResponse{Config: config}, http.Header{atc.ConfigVersionHeader: {"42"}}),
					),
					ghttp.CombineHandlers(
						ghttp.VerifyRequest("PUT", "/api/v1/teams/other-team/pipelines/some-pipeline/config"),
						ghttp.RespondWithJSONEncoded(http.StatusOK, atc.ConfigResponse{Config: config}, http.Header{atc.ConfigVersionHeader: {"42"}}),
					),
				)
			})

			Context("when there are no groups", func() {
				BeforeEach(func() {
					config = atc.Config{
						Jobs: atc.JobConfigs{
							{
								Name: "job-1",
							},
							{
								Name: "job-2",
							},
						},
					}

				})

				It("prints the config as yaml to stdout, and uses the pipeline name as header", func() {
					flyCmd := exec.Command(flyPath, "-t", targetName, "checklist", "-p", "some-pipeline/branch:master", "--team", "other-team")

					sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
					Expect(err).NotTo(HaveOccurred())

					<-sess.Exited
					Expect(sess.ExitCode()).To(Equal(0))

					Expect(string(sess.Out.Contents())).To(Equal(fmt.Sprintf(
						`#- some-pipeline/branch:master
job-1: concourse.check %s other-team some-pipeline/branch:master job-1
job-2: concourse.check %s other-team some-pipeline/branch:master job-2

`, atcServer.URL(), atcServer.URL())))
				})
			})
		})
	})
})
<commit_msg>Update integration test as per review comments<commit_after>package integration_test

import (
	"fmt"
	"net/http"
	"os"
	"os/exec"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/gexec"
	"github.com/onsi/gomega/ghttp"

	"github.com/concourse/concourse/atc"
)

var _ = Describe("Fly CLI", func() {
	Describe("checklist", func() {
		var (
			config atc.Config
			home   string
		)

		BeforeEach(func() {
			config = atc.Config{
				Groups: atc.GroupConfigs{
					{
						Name:      "some-group",
						Jobs:      []string{"job-1", "job-2"},
						Resources: []string{"resource-1", "resource-2"},
					},
					{
						Name:      "some-other-group",
						Jobs:      []string{"job-3", "job-4"},
						Resources: []string{"resource-6", "resource-4"},
					},
				},

				Jobs: atc.JobConfigs{
					{
						Name: "some-orphaned-job",
					},
				},
			}
		})

		AfterEach(func() {
			err := os.RemoveAll(home)
			Expect(err).NotTo(HaveOccurred())
		})

		Context("when a pipeline name is not specified", func() {
			It("errors", func() {
				flyCmd := exec.Command(flyPath, "-t", targetName, "checklist")

				sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
				Expect(err).NotTo(HaveOccurred())

				<-sess.Exited
				Expect(sess.ExitCode()).To(Equal(1))
			})
		})

		Context("when the pipeline flag is invalid", func() {
			It("fails and print invalid flag error", func() {
				flyCmd := exec.Command(flyPath, "-t", targetName, "checklist", "-p", "forbidden/pipelinename")

				sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
				Expect(err).NotTo(HaveOccurred())

				<-sess.Exited
				Expect(sess.ExitCode()).To(Equal(1))

				Expect(sess.Err).To(gbytes.Say("error: invalid argument for flag `" + osFlag("p", "pipeline")))
			})
		})

		Context("when a pipeline name is specified", func() {
			JustBeforeEach(func() {
				atcServer.AppendHandlers(
					ghttp.CombineHandlers(
						ghttp.VerifyRequest("GET", "/api/v1/teams/main/pipelines/some-pipeline/config", "vars.branch=%22master%22"),
						ghttp.RespondWithJSONEncoded(200, atc.ConfigResponse{Config: config}, http.Header{atc.ConfigVersionHeader: {"42"}}),
					),
				)
			})

			Context("when there are groups", func() {
				It("prints the config as yaml to stdout", func() {
					flyCmd := exec.Command(flyPath, "-t", targetName, "checklist", "-p", "some-pipeline/branch:master")

					sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
					Expect(err).NotTo(HaveOccurred())

					<-sess.Exited
					Expect(sess.ExitCode()).To(Equal(0))

					Expect(string(sess.Out.Contents())).To(Equal(fmt.Sprintf(
						`#- some-group
job-1: concourse.check %s main some-pipeline/branch:master job-1
job-2: concourse.check %s main some-pipeline/branch:master job-2

#- some-other-group
job-3: concourse.check %s main some-pipeline/branch:master job-3
job-4: concourse.check %s main some-pipeline/branch:master job-4

#- misc
some-orphaned-job: concourse.check %s main some-pipeline/branch:master some-orphaned-job

`, atcServer.URL(), atcServer.URL(), atcServer.URL(), atcServer.URL(), atcServer.URL())))
				})
			})

			Context("when there are no groups", func() {
				BeforeEach(func() {
					config = atc.Config{
						Jobs: atc.JobConfigs{
							{
								Name: "job-1",
							},
							{
								Name: "job-2",
							},
						},
					}

				})

				It("prints the config as yaml to stdout, and uses the pipeline name as header", func() {
					flyCmd := exec.Command(flyPath, "-t", targetName, "checklist", "-p", "some-pipeline/branch:master")

					sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
					Expect(err).NotTo(HaveOccurred())

					<-sess.Exited
					Expect(sess.ExitCode()).To(Equal(0))

					Expect(string(sess.Out.Contents())).To(Equal(fmt.Sprintf(
						`#- some-pipeline/branch:master
job-1: concourse.check %s main some-pipeline/branch:master job-1
job-2: concourse.check %s main some-pipeline/branch:master job-2

`, atcServer.URL(), atcServer.URL())))
				})
			})
		})

		Context("when a team name is specified alongwith pipeline name", func() {
			JustBeforeEach(func() {
				config = atc.Config{
					Jobs: atc.JobConfigs{
						{
							Name: "job-1",
						},
						{
							Name: "job-2",
						},
					},
				}

				atcServer.AppendHandlers(
					ghttp.CombineHandlers(
						ghttp.VerifyRequest("GET", "/api/v1/teams/other-team"),
						ghttp.RespondWithJSONEncoded(http.StatusOK, atc.Team{
							Name: "other-team",
						}),
					),
					ghttp.CombineHandlers(
						ghttp.VerifyRequest("GET", "/api/v1/teams/other-team/pipelines/some-pipeline/config"),
						ghttp.RespondWithJSONEncoded(http.StatusOK, atc.ConfigResponse{Config: config}, http.Header{atc.ConfigVersionHeader: {"42"}}),
					),
					ghttp.CombineHandlers(
						ghttp.VerifyRequest("PUT", "/api/v1/teams/other-team/pipelines/some-pipeline/config"),
						ghttp.RespondWithJSONEncoded(http.StatusOK, atc.ConfigResponse{Config: config}, http.Header{atc.ConfigVersionHeader: {"42"}}),
					),
				)
			})

			It("prints the config as yaml to stdout, and uses the pipeline name and the specified team as header", func() {
				flyCmd := exec.Command(flyPath, "-t", targetName, "checklist", "-p", "some-pipeline/branch:master", "--team", "other-team")

				sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
				Expect(err).NotTo(HaveOccurred())

				<-sess.Exited
				Expect(sess.ExitCode()).To(Equal(0))

				Expect(string(sess.Out.Contents())).To(Equal(fmt.Sprintf(
					`#- some-pipeline/branch:master
job-1: concourse.check %s other-team some-pipeline/branch:master job-1
job-2: concourse.check %s other-team some-pipeline/branch:master job-2

`, atcServer.URL(), atcServer.URL())))
			})
		})
	})
})
<|endoftext|>


<commit_before>package main

import (
	"context"
	"fmt"
	"math/rand"
	"os"
	"runtime"
	"sort"
	"strconv"
	"sync"

	"fiber/src/templates"

	"github.com/gofiber/fiber"
	pgx "github.com/jackc/pgx/v4"
	"github.com/jackc/pgx/v4/pgxpool"
)

var (
	child bool
	db    *pgxpool.Pool
)

const (
	queryparam       = "q"
	worldcount       = 10000
	helloworld       = "Hello, World!"
	worldselectsql   = "SELECT id, randomNumber FROM World WHERE id = $1"
	worldupdatesql   = "UPDATE World SET randomNumber = $1 WHERE id = $2"
	worldcachesql    = "SELECT * FROM World"
	fortuneselectsql = "SELECT id, message FROM Fortune"
)

func main() {
	for _, arg := range os.Args[1:] {
		if arg == "-child" {
			child = true
		}
	}

	initDatabase()

	app := fiber.New(&fiber.Settings{
		CaseSensitive:            true,
		StrictRouting:            true,
		DisableHeaderNormalizing: true,
		ServerHeader:             "go",
	})

	app.Get("/plaintext", plaintextHandler)
	app.Get("/json", jsonHandler)
	app.Get("/db", dbHandler)
	app.Get("/update", updateHandler)
	app.Get("/queries", queriesHandler)
	app.Get("/fortune", templateHandler)
	app.Get("/cached-worlds", cachedHandler)
	app.Listen(8080)
}

// Message ...
type Message struct {
	Message string `json:"message"`
}

// Worlds ...
type Worlds []World

// World ...
type World struct {
	ID           int32 `json:"id"`
	RandomNumber int32 `json:"randomNumber"`
}

// JSONpool ...
var JSONpool = sync.Pool{
	New: func() interface{} {
		return new(Message)
	},
}

// AcquireJSON ...
func AcquireJSON() *Message {
	return JSONpool.Get().(*Message)
}

// ReleaseJSON ...
func ReleaseJSON(json *Message) {
	json.Message = ""
	JSONpool.Put(json)
}

// WorldPool ...
var WorldPool = sync.Pool{
	New: func() interface{} {
		return new(World)
	},
}

// AcquireWorld ...
func AcquireWorld() *World {
	return WorldPool.Get().(*World)
}

// ReleaseWorld ...
func ReleaseWorld(w *World) {
	w.ID = 0
	w.RandomNumber = 0
	WorldPool.Put(w)
}

// WorldsPool ...
var WorldsPool = sync.Pool{
	New: func() interface{} {
		return make(Worlds, 0, 512)
	},
}

// AcquireWorlds ...
func AcquireWorlds() Worlds {
	return WorldsPool.Get().(Worlds)
}

// ReleaseWorlds ...ReleaseWorlds
func ReleaseWorlds(w Worlds) {
	w = w[:0]
	WorldsPool.Put(w)
}

// initDatabase :
func initDatabase() {
	maxConn := runtime.NumCPU()
	if maxConn == 0 {
		maxConn = 8
	}
	if child {
		maxConn = maxConn
	} else {
		maxConn = maxConn * 4
	}

	var err error
	db, err = pgxpool.Connect(context.Background(), fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s pool_max_conns=%d", "tfb-database", 5432, "benchmarkdbuser", "benchmarkdbpass", "hello_world", maxConn))
	if err != nil {
		panic(err)
	}
}

// jsonHandler :
func jsonHandler(c *fiber.Ctx) {
	m := AcquireJSON()
	m.Message = helloworld
	c.JSON(m)
	ReleaseJSON(m)
}

// dbHandler :
func dbHandler(c *fiber.Ctx) {
	w := AcquireWorld()
	db.QueryRow(context.Background(), worldselectsql, RandomWorld()).Scan(&w.ID, &w.RandomNumber)
	c.JSON(w)
	ReleaseWorld(w)
}

// Frameworks/Go/fasthttp/src/server-postgresql/server.go#104
func templateHandler(c *fiber.Ctx) {
	rows, _ := db.Query(context.Background(), fortuneselectsql)

	var f templates.Fortune
	fortunes := make([]templates.Fortune, 0, 16)
	for rows.Next() {
		_ = rows.Scan(&f.ID, &f.Message)
		fortunes = append(fortunes, f)
	}
	rows.Close()
	fortunes = append(fortunes, templates.Fortune{
		Message: "Additional fortune added at request time.",
	})

	sort.Slice(fortunes, func(i, j int) bool {
		return fortunes[i].Message < fortunes[j].Message
	})

	c.Set(fiber.HeaderContentType, fiber.MIMETextHTMLCharsetUTF8)

	templates.WriteFortunePage(c.Fasthttp, fortunes)
}

// queriesHandler :
func queriesHandler(c *fiber.Ctx) {
	n := QueriesCount(c)
	worlds := AcquireWorlds()[:n]
	for i := 0; i < n; i++ {
		w := &worlds[i]
		db.QueryRow(context.Background(), worldselectsql, RandomWorld()).Scan(&w.ID, &w.RandomNumber)
	}
	c.JSON(worlds)
	ReleaseWorlds(worlds)
}

// updateHandler :
func updateHandler(c *fiber.Ctx) {
	n := QueriesCount(c)
	worlds := AcquireWorlds()[:n]
	for i := 0; i < n; i++ {
		w := &worlds[i]
		db.QueryRow(context.Background(), worldselectsql, RandomWorld()).Scan(&w.ID, &w.RandomNumber)
		w.RandomNumber = int32(RandomWorld())
	}
	// sorting is required for insert deadlock prevention.
	sort.Slice(worlds, func(i, j int) bool {
		return worlds[i].ID < worlds[j].ID
	})

	batch := pgx.Batch{}
	for _, w := range worlds {
		batch.Queue(worldupdatesql, w.RandomNumber, w.ID)
	}
	db.SendBatch(context.Background(), &batch).Close()
	c.JSON(worlds)
	ReleaseWorlds(worlds)
}

// plaintextHandler :
func plaintextHandler(c *fiber.Ctx) {
	c.SendString(helloworld)
}

var cachePopulated = false
var catchedWorlds []World

func populateCache() {
	worlds := AcquireWorlds()[:500]
	for i := 0; i < 500; i++ {
		w := &worlds[i]
		db.QueryRow(context.Background(), worldselectsql, RandomWorld()).Scan(&w.ID, &w.RandomNumber)
	}
	catchedWorlds = worlds
	cachePopulated = true
}

// cachedHandler :
func cachedHandler(c *fiber.Ctx) {
	if !cachePopulated {
		populateCache()
	}
	n := QueriesCount(c)
	c.JSON(catchedWorlds[:n])
}

// RandomWorld :
func RandomWorld() int {
	return rand.Intn(worldcount) + 1
}

// QueriesCount :
func QueriesCount(c *fiber.Ctx) int {
	n, _ := strconv.Atoi(c.Query(queryparam))
	if n < 1 {
		n = 1
	} else if n > 500 {
		n = 500
	}
	return n
}
<commit_msg>Fix cache test (Fiber v1.12) (#5816)<commit_after>package main

import (
	"context"
	"fmt"
	"math/rand"
	"os"
	"runtime"
	"sort"
	"strconv"
	"sync"

	"fiber/src/templates"

	"github.com/gofiber/fiber"
	pgx "github.com/jackc/pgx/v4"
	"github.com/jackc/pgx/v4/pgxpool"
)

var (
	child        bool
	db           *pgxpool.Pool
	cachedWorlds Worlds
)

const (
	queryparam       = "q"
	worldcount       = 10000
	helloworld       = "Hello, World!"
	worldselectsql   = "SELECT id, randomNumber FROM World WHERE id = $1"
	worldupdatesql   = "UPDATE World SET randomNumber = $1 WHERE id = $2"
	worldcachesql    = "SELECT * FROM World LIMIT $1"
	fortuneselectsql = "SELECT id, message FROM Fortune"
)

func main() {
	for _, arg := range os.Args[1:] {
		if arg == "-child" {
			child = true
		}
	}

	initDatabase()

	app := fiber.New(&fiber.Settings{
		CaseSensitive:            true,
		StrictRouting:            true,
		DisableHeaderNormalizing: true,
		ServerHeader:             "go",
	})

	app.Get("/plaintext", plaintextHandler)
	app.Get("/json", jsonHandler)
	app.Get("/db", dbHandler)
	app.Get("/update", updateHandler)
	app.Get("/queries", queriesHandler)
	app.Get("/fortune", templateHandler)
	app.Get("/cached-worlds", cachedHandler)
	app.Listen(8080)
}

// Message ...
type Message struct {
	Message string `json:"message"`
}

// Worlds ...
type Worlds []World

// World ...
type World struct {
	ID           int32 `json:"id"`
	RandomNumber int32 `json:"randomNumber"`
}

// JSONpool ...
var JSONpool = sync.Pool{
	New: func() interface{} {
		return new(Message)
	},
}

// AcquireJSON ...
func AcquireJSON() *Message {
	return JSONpool.Get().(*Message)
}

// ReleaseJSON ...
func ReleaseJSON(json *Message) {
	json.Message = ""
	JSONpool.Put(json)
}

// WorldPool ...
var WorldPool = sync.Pool{
	New: func() interface{} {
		return new(World)
	},
}

// AcquireWorld ...
func AcquireWorld() *World {
	return WorldPool.Get().(*World)
}

// ReleaseWorld ...
func ReleaseWorld(w *World) {
	w.ID = 0
	w.RandomNumber = 0
	WorldPool.Put(w)
}

// WorldsPool ...
var WorldsPool = sync.Pool{
	New: func() interface{} {
		return make(Worlds, 0, 500)
	},
}

// AcquireWorlds ...
func AcquireWorlds() Worlds {
	return WorldsPool.Get().(Worlds)
}

// ReleaseWorlds ...ReleaseWorlds
func ReleaseWorlds(w Worlds) {
	w = w[:0]
	WorldsPool.Put(w)
}

// initDatabase :
func initDatabase() {
	maxConn := runtime.NumCPU()
	if maxConn == 0 {
		maxConn = 8
	}
	if child {
		maxConn = maxConn
	} else {
		maxConn = maxConn * 4
	}

	var err error
	db, err = pgxpool.Connect(context.Background(), fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s pool_max_conns=%d", "tfb-database", 5432, "benchmarkdbuser", "benchmarkdbpass", "hello_world", maxConn))
	if err != nil {
		panic(err)
	}
	populateCache()
}

// this will populate the cached worlds for the cache test
func populateCache() {
	worlds := make(Worlds, worldcount)
	rows, err := db.Query(context.Background(), worldcachesql, worldcount)
	if err != nil {
		panic(err)
	}
	for i := 0; i < worldcount; i++ {
		w := &worlds[i]
		if !rows.Next() {
			break
		}
		if err := rows.Scan(&w.ID, &w.RandomNumber); err != nil {
			panic(err)
		}
		//db.QueryRow(context.Background(), worldselectsql, RandomWorld()).Scan(&w.ID, &w.RandomNumber)
	}
	cachedWorlds = worlds
}

// jsonHandler :
func jsonHandler(c *fiber.Ctx) {
	m := AcquireJSON()
	m.Message = helloworld
	c.JSON(m)
	ReleaseJSON(m)
}

// dbHandler :
func dbHandler(c *fiber.Ctx) {
	w := AcquireWorld()
	db.QueryRow(context.Background(), worldselectsql, RandomWorld()).Scan(&w.ID, &w.RandomNumber)
	c.JSON(w)
	ReleaseWorld(w)
}

// Frameworks/Go/fasthttp/src/server-postgresql/server.go#104
func templateHandler(c *fiber.Ctx) {
	rows, _ := db.Query(context.Background(), fortuneselectsql)

	var f templates.Fortune
	fortunes := make([]templates.Fortune, 0, 16)
	for rows.Next() {
		_ = rows.Scan(&f.ID, &f.Message)
		fortunes = append(fortunes, f)
	}
	rows.Close()
	fortunes = append(fortunes, templates.Fortune{
		Message: "Additional fortune added at request time.",
	})

	sort.Slice(fortunes, func(i, j int) bool {
		return fortunes[i].Message < fortunes[j].Message
	})

	c.Set(fiber.HeaderContentType, fiber.MIMETextHTMLCharsetUTF8)

	templates.WriteFortunePage(c.Fasthttp, fortunes)
}

// queriesHandler :
func queriesHandler(c *fiber.Ctx) {
	n := QueriesCount(c)
	worlds := AcquireWorlds()[:n]
	for i := 0; i < n; i++ {
		w := &worlds[i]
		db.QueryRow(context.Background(), worldselectsql, RandomWorld()).Scan(&w.ID, &w.RandomNumber)
	}
	c.JSON(worlds)
	ReleaseWorlds(worlds)
}

// updateHandler :
func updateHandler(c *fiber.Ctx) {
	n := QueriesCount(c)
	worlds := AcquireWorlds()[:n]
	for i := 0; i < n; i++ {
		w := &worlds[i]
		db.QueryRow(context.Background(), worldselectsql, RandomWorld()).Scan(&w.ID, &w.RandomNumber)
		w.RandomNumber = int32(RandomWorld())
	}
	// sorting is required for insert deadlock prevention.
	sort.Slice(worlds, func(i, j int) bool {
		return worlds[i].ID < worlds[j].ID
	})

	batch := pgx.Batch{}
	for _, w := range worlds {
		batch.Queue(worldupdatesql, w.RandomNumber, w.ID)
	}
	db.SendBatch(context.Background(), &batch).Close()
	c.JSON(worlds)
	ReleaseWorlds(worlds)
}

// plaintextHandler :
func plaintextHandler(c *fiber.Ctx) {
	c.SendString(helloworld)
}

// cachedHandler :
func cachedHandler(c *fiber.Ctx) {
	n := QueriesCount(c)
	worlds := AcquireWorlds()[:n]
	for i := 0; i < n; i++ {
		worlds[i] = cachedWorlds[RandomWorld()-1]
	}
	c.JSON(worlds)
	ReleaseWorlds(worlds)
}

// RandomWorld :
func RandomWorld() int {
	return rand.Intn(worldcount) + 1
}

// QueriesCount :
func QueriesCount(c *fiber.Ctx) int {
	n, _ := strconv.Atoi(c.Query(queryparam))
	if n < 1 {
		n = 1
	} else if n > 500 {
		n = 500
	}
	return n
}
<|endoftext|>


<commit_before>/* Key-value data structure with non-blocking resize */
package godict

import (
	"fmt"
	mmh "murmur3"
	"sync"
)

const hash_seed uint32 = 6012
const perturb_shift = 5
const resize_ratio = 1.5

func GenHash(key string) uint32 {
	return mmh.MurMur3_32([]byte(key), hash_seed)
}

func New() *Dict {
	d := new(Dict)
	d.dict = make([]entry, 8, 8)
	d.mask = 7
	return d
}

type hashTable []entry

type Dict struct {
	sync.RWMutex
	active    uint32
	dict      hashTable
	sparedict hashTable
	mask      uint32 // mask = size - 1
	sparemask uint32
	rehashing bool
}

func (d *Dict) Active() uint32 {
	return d.active
}

//Set sets string value to key, spawn rehashing if needed
func (d *Dict) Set(key, value string) error {

	hash := GenHash(key)

	d.Lock()
	slot, err := d.lookUpEntry(key, hash)

	if err != nil {
		return err
	}

	slot.Init(key, value, hash)
	d.active++
	d.Unlock()

	d.resizeIfNeeded()

	return nil
}

//Get retrieve slot from dict, spawn error if no key in dict
func (d *Dict) Get(key string) (slot *entry, err error) {
	hash := GenHash(key)

	d.RLock()
	defer d.RUnlock()
	slot, err = d.lookUpEntry(key, hash)

	if err == nil && slot.data == nil {
		err = fmt.Errorf("Key %v missing in the dictionary", key)
	}

	return
}

//Delete mark slot as deleted and wipe it`s data, spawn error if no key in dict
func (d *Dict) Delete(key string) error {
	hash := GenHash(key)

	d.Lock()
	defer d.Unlock()
	slot, err := d.lookUpEntry(key, hash)

	if err != nil {
		return err
	}

	if slot.data == nil {
		return fmt.Errorf("Key %v missing in the dictionary", key)
	}

	slot.delete()
	d.active--

	return nil
}

// Look for entry by key and hash in hashtable, returns pointer to entry
func (ht hashTable) findSlot(key string, hash, mask uint32) *entry {

	var freeSlot *entry

	index := hash & mask
	slot := &ht[index]

	if slot.deleted {
		freeSlot = slot
	} else {
		if slot.data == nil || slot.key == key {
			return slot
		}
	}

	for perturb := hash; ; perturb >>= perturb_shift {
		index = ((index << 2) + index + perturb + 1) & mask
		slot = &ht[index]

		if slot.deleted {
			if freeSlot == nil {
				freeSlot = slot
			}
			continue
		}

		if slot.data == nil {
			if freeSlot != nil {
				slot = freeSlot
			}
			return slot
		}

		if slot.key == key {
			return slot
		}
	}
}

func (d *Dict) lookUpEntry(key string, hash uint32) (*entry, error) {
	slot := d.dict.findSlot(key, hash, d.mask)

	if slot == nil {
		return nil, fmt.Errorf("Not slot found for key %v, hash %v", key, hash)
	}

	if slot.rehashed {
		slot = d.sparedict.findSlot(key, hash, d.sparemask)
	}

	return slot, nil
}

// rehash make incremental rehashing to sparedict
func (d *Dict) rehash(newsize uint32) {

	d.sparedict = make([]entry, newsize, newsize)
	d.sparemask = newsize - 1

	for _, e := range d.dict {
		d.Lock()
		if e.data != nil {
			slot := d.sparedict.findSlot(e.key, e.hash, d.sparemask)
			slot.Init(e.key, e.value, e.hash)
		}
		e.rehashed = true
		d.Unlock()
	}
	d.Lock()
	defer d.Unlock()
	d.mask = d.sparemask
	d.dict = d.sparedict
	d.rehashing = false
	d.sparedict = nil
	d.sparemask = 0
}

// isReadyForResize atomically check if we can resize and set rehashing true
// in this case
//
// returns true if we must begin resize or false if we must not
func (d *Dict) isReadyForResize() bool {
	d.Lock()
	defer d.Unlock()
	if float64(d.mask+1)/float64(d.active) >= resize_ratio || d.rehashing {
		return false
	}
	d.rehashing = true
	return true
}

func (d *Dict) resizeIfNeeded() {

	if !d.isReadyForResize() {
		return
	}

	newsize := d.mask + 1
	active := d.active

	var mul uint32

	switch {
	case newsize < 50000:
		mul = 2
	default:
		mul = 4
	}

	for ; newsize <= mul*active; newsize <<= 1 {
	}
	d.rehash(newsize)
}
<commit_msg>Remove overhead of copy data on rehashing<commit_after>/* Key-value data structure with non-blocking resize */
package godict

import (
	"fmt"
	mmh "murmur3"
	"sync"
)

const hash_seed uint32 = 6012
const perturb_shift = 5
const resize_ratio = 1.5

func GenHash(key string) uint32 {
	return mmh.MurMur3_32([]byte(key), hash_seed)
}

func New() *Dict {
	d := new(Dict)
	d.dict = make([]entry, 8, 8)
	d.mask = 7
	return d
}

type hashTable []entry

type Dict struct {
	sync.RWMutex
	active    uint32
	dict      hashTable
	sparedict hashTable
	mask      uint32 // mask = size - 1
	sparemask uint32
	rehashing bool
}

func (d *Dict) Active() uint32 {
	return d.active
}

//Set sets string value to key, spawn rehashing if needed
func (d *Dict) Set(key, value string) error {

	hash := GenHash(key)

	d.Lock()
	slot, err := d.lookUpEntry(key, hash)

	if err != nil {
		return err
	}

	slot.Init(key, value, hash)
	d.active++
	d.Unlock()

	d.resizeIfNeeded()

	return nil
}

//Get retrieve slot from dict, spawn error if no key in dict
func (d *Dict) Get(key string) (slot *entry, err error) {
	hash := GenHash(key)

	d.RLock()
	defer d.RUnlock()
	slot, err = d.lookUpEntry(key, hash)

	if err == nil && slot.data == nil {
		err = fmt.Errorf("Key %v missing in the dictionary", key)
	}

	return
}

//Delete mark slot as deleted and wipe it`s data, spawn error if no key in dict
func (d *Dict) Delete(key string) error {
	hash := GenHash(key)

	d.Lock()
	defer d.Unlock()
	slot, err := d.lookUpEntry(key, hash)

	if err != nil {
		return err
	}

	if slot.data == nil {
		return fmt.Errorf("Key %v missing in the dictionary", key)
	}

	slot.delete()
	d.active--

	return nil
}

// Look for entry by key and hash in hashtable, returns pointer to entry
func (ht hashTable) findSlot(key string, hash, mask uint32) *entry {

	var freeSlot *entry

	index := hash & mask
	slot := &ht[index]

	if slot.deleted {
		freeSlot = slot
	} else {
		if slot.data == nil || slot.key == key {
			return slot
		}
	}

	for perturb := hash; ; perturb >>= perturb_shift {
		index = ((index << 2) + index + perturb + 1) & mask
		slot = &ht[index]

		if slot.deleted {
			if freeSlot == nil {
				freeSlot = slot
			}
			continue
		}

		if slot.data == nil {
			if freeSlot != nil {
				slot = freeSlot
			}
			return slot
		}

		if slot.key == key {
			return slot
		}
	}
}

func (d *Dict) lookUpEntry(key string, hash uint32) (*entry, error) {
	slot := d.dict.findSlot(key, hash, d.mask)

	if slot == nil {
		return nil, fmt.Errorf("Not slot found for key %v, hash %v", key, hash)
	}

	if slot.rehashed {
		slot = d.sparedict.findSlot(key, hash, d.sparemask)
	}

	return slot, nil
}

// rehash make incremental rehashing to sparedict
func (d *Dict) rehash(newsize uint32) {

	d.sparedict = make([]entry, newsize, newsize)
	d.sparemask = newsize - 1

	for _, e := range d.dict {
		d.Lock()
		if e.data != nil {
			slot := d.sparedict.findSlot(e.key, e.hash, d.sparemask)
			slot.data = e.data
		}
		e.rehashed = true
		d.Unlock()
	}
	d.Lock()
	defer d.Unlock()
	d.mask = d.sparemask
	d.dict = d.sparedict
	d.rehashing = false
	d.sparedict = nil
	d.sparemask = 0
}

// isReadyForResize atomically check if we can resize and set rehashing true
// in this case
//
// returns true if we must begin resize or false if we must not
func (d *Dict) isReadyForResize() bool {
	d.Lock()
	defer d.Unlock()
	if float64(d.mask+1)/float64(d.active) >= resize_ratio || d.rehashing {
		return false
	}
	d.rehashing = true
	return true
}

func (d *Dict) resizeIfNeeded() {

	if !d.isReadyForResize() {
		return
	}

	newsize := d.mask + 1
	active := d.active

	var mul uint32

	switch {
	case newsize < 50000:
		mul = 2
	default:
		mul = 4
	}

	for ; newsize <= mul*active; newsize <<= 1 {
	}
	d.rehash(newsize)
}
<|endoftext|>


<commit_before>// Copyright 2018 The OPA Authors.  All rights reserved.
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.

// Package presentation prints results of an expression evaluation in
// json and tabular formats.
package presentation

import (
	"encoding/json"
	"fmt"
	"io"
	"os"
	"sort"
	"strconv"
	"time"

	"github.com/olekukonko/tablewriter"
	"github.com/open-policy-agent/opa/metrics"
	"github.com/open-policy-agent/opa/profiler"
	"github.com/open-policy-agent/opa/rego"
	"github.com/open-policy-agent/opa/topdown"
)

// Output contains the result of evaluation to be presented.
type Output struct {
	Error       error                `json:"error,omitempty"`
	Result      rego.ResultSet       `json:"result,omitempty"`
	Metrics     metrics.Metrics      `json:"metrics,omitempty"`
	Explanation []*topdown.Event     `json:"explanation,omitempty"`
	Profile     []profiler.ExprStats `json:"profile,omitempty"`
	limit       int
}

// WithLimit sets the output limit to set on stringified values.
func (e Output) WithLimit(n int) Output {
	e.limit = n
	return e
}

// JSON writes x to w with indentation.
func JSON(w io.Writer, x interface{}) error {
	encoder := json.NewEncoder(w)
	encoder.SetIndent("", "  ")
	return encoder.Encode(x)
}

// Bindings prints the bindings from r to w.
func Bindings(w io.Writer, r Output) error {
	if r.Error != nil {
		return prettyError(w, r.Error)
	}
	for _, rs := range r.Result {
		if err := JSON(w, rs.Bindings); err != nil {
			return err
		}
	}
	return nil
}

// Values prints the values from r to w.
func Values(w io.Writer, r Output) error {
	if r.Error != nil {
		return prettyError(w, r.Error)
	}
	for _, rs := range r.Result {
		line := make([]interface{}, len(rs.Expressions))
		for i := range line {
			line[i] = rs.Expressions[i].Value
		}
		if err := JSON(os.Stdout, line); err != nil {
			return err
		}
	}
	return nil
}

// Pretty prints all of r to w in a human-readable format.
func Pretty(w io.Writer, r Output) error {
	if len(r.Explanation) > 0 {
		if err := prettyExplanation(w, r.Explanation); err != nil {
			return err
		}
	}
	if r.Error != nil {
		if err := prettyError(w, r.Error); err != nil {
			return err
		}
	} else {
		if err := prettyResult(w, r.Result, r.limit); err != nil {
			return err
		}
	}
	if r.Metrics != nil {
		if err := prettyMetrics(w, r.Metrics, r.limit); err != nil {
			return err
		}
	}
	if len(r.Profile) > 0 {
		if err := prettyProfile(w, r.Profile); err != nil {
			return err
		}
	}
	return nil
}

func prettyError(w io.Writer, err error) error {
	_, err = fmt.Fprintln(w, err)
	return err
}

func prettyResult(w io.Writer, rs rego.ResultSet, limit int) error {

	if len(rs) == 0 {
		fmt.Fprintln(w, "undefined")
		return nil
	}

	if len(rs) == 1 {
		if len(rs[0].Bindings) == 0 && len(rs[0].Expressions) == 1 {
			return JSON(w, rs[0].Expressions[0].Value)
		}
	}

	keys := generateResultKeys(rs)
	tableBindings := generateTableBindings(w, keys, rs, limit)
	if tableBindings.NumLines() > 0 {
		tableBindings.Render()
	}

	return nil
}

func prettyMetrics(w io.Writer, m metrics.Metrics, limit int) error {
	tableMetrics := generateTableMetrics(w)
	populateTableMetrics(m, tableMetrics, limit)
	if tableMetrics.NumLines() > 0 {
		tableMetrics.Render()
	}
	return nil
}

func prettyProfile(w io.Writer, profile []profiler.ExprStats) error {
	tableProfile := generateTableProfile(w)
	for _, rs := range profile {
		line := []string{}
		timeNs := time.Duration(rs.ExprTimeNs) * time.Nanosecond
		timeNsStr := timeNs.String()
		numEval := strconv.FormatInt(int64(rs.NumEval), 10)
		numRedo := strconv.FormatInt(int64(rs.NumRedo), 10)
		loc := rs.Location.String()
		line = append(line, timeNsStr, numEval, numRedo, loc)
		tableProfile.Append(line)
	}
	if tableProfile.NumLines() > 0 {
		tableProfile.Render()
	}
	return nil
}

func prettyExplanation(w io.Writer, explanation []*topdown.Event) error {
	topdown.PrettyTrace(w, explanation)
	return nil
}

func checkStrLimit(input string, limit int) string {
	if limit > 0 && len(input) > limit {
		input = input[:limit] + "..."
		return input
	}
	return input
}

func generateTableBindings(writer io.Writer, keys []resultKey, rs rego.ResultSet, prettyLimit int) *tablewriter.Table {
	table := tablewriter.NewWriter(writer)
	table.SetAlignment(tablewriter.ALIGN_CENTER)
	table.SetAutoFormatHeaders(false)
	header := make([]string, len(keys))
	for i := range header {
		header[i] = keys[i].string()
	}
	table.SetHeader(header)
	alignment := make([]int, len(keys))
	for i := range header {
		alignment[i] = tablewriter.ALIGN_LEFT
	}
	table.SetColumnAlignment(alignment)

	for _, row := range rs {
		printPrettyRow(table, keys, row, prettyLimit)
	}
	return table
}

func printPrettyRow(table *tablewriter.Table, keys []resultKey, result rego.Result, prettyLimit int) {
	buf := []string{}
	for _, k := range keys {
		v, ok := k.selectVarValue(result)
		if ok {
			js, err := json.Marshal(v)
			if err != nil {
				buf = append(buf, err.Error())
			} else {
				s := checkStrLimit(string(js), prettyLimit)
				buf = append(buf, s)
			}
		}
	}
	table.Append(buf)
}

func generateTableMetrics(writer io.Writer) *tablewriter.Table {
	table := tablewriter.NewWriter(writer)
	table.SetHeader([]string{"Metric", "Value"})
	table.SetAlignment(tablewriter.ALIGN_CENTER)
	table.SetColumnAlignment([]int{tablewriter.ALIGN_LEFT, tablewriter.ALIGN_LEFT})
	return table
}

func generateTableProfile(writer io.Writer) *tablewriter.Table {
	table := tablewriter.NewWriter(writer)
	table.SetHeader([]string{"Time", "Num Eval", "Num Redo", "Location"})
	table.SetAlignment(tablewriter.ALIGN_CENTER)
	table.SetColumnAlignment([]int{tablewriter.ALIGN_LEFT, tablewriter.ALIGN_LEFT,
		tablewriter.ALIGN_LEFT, tablewriter.ALIGN_LEFT})
	return table
}

func populateTableMetrics(m metrics.Metrics, table *tablewriter.Table, prettyLimit int) {
	lines := [][]string{}
	for varName, varValueInterface := range m.All() {
		val, ok := varValueInterface.(map[string]interface{})
		if !ok {
			line := []string{}
			varValue := checkStrLimit(fmt.Sprintf("%v", varValueInterface), prettyLimit)
			line = append(line, varName, varValue)
			lines = append(lines, line)
		} else {
			for k, v := range val {
				line := []string{}
				newVarName := fmt.Sprintf("%v_%v", varName, k)
				value := checkStrLimit(fmt.Sprintf("%v", v), prettyLimit)
				line = append(line, newVarName, value)
				lines = append(lines, line)
			}
		}
	}
	sortMetricRows(lines)
	table.AppendBulk(lines)
}

func sortMetricRows(data [][]string) {
	sort.Slice(data, func(i, j int) bool {
		return data[i][0] < data[j][0]
	})
}

type resultKey struct {
	varName   string
	exprIndex int
	exprText  string
}

func resultKeyLess(a, b resultKey) bool {
	if a.varName != "" {
		if b.varName == "" {
			return true
		}
		return a.varName < b.varName
	}
	return a.exprIndex < b.exprIndex
}

func (rk resultKey) string() string {
	if rk.varName != "" {
		return rk.varName
	}
	return rk.exprText
}

func (rk resultKey) selectVarValue(result rego.Result) (interface{}, bool) {
	if rk.varName != "" {
		return result.Bindings[rk.varName], true
	}
	val := result.Expressions[rk.exprIndex].Value
	if _, ok := val.(bool); ok {
		return nil, false
	}
	return val, true
}

func generateResultKeys(rs rego.ResultSet) []resultKey {
	keys := []resultKey{}
	if len(rs) != 0 {
		for k := range rs[0].Bindings {
			keys = append(keys, resultKey{
				varName: k,
			})
		}

		for i, expr := range rs[0].Expressions {
			if _, ok := expr.Value.(bool); !ok {
				keys = append(keys, resultKey{
					exprIndex: i,
					exprText:  expr.Text,
				})
			}
		}

		sort.Slice(keys, func(i, j int) bool {
			return resultKeyLess(keys[i], keys[j])
		})
	}
	return keys
}
<commit_msg>Fix REPL output for multiple bool exprs<commit_after>// Copyright 2018 The OPA Authors.  All rights reserved.
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.

// Package presentation prints results of an expression evaluation in
// json and tabular formats.
package presentation

import (
	"encoding/json"
	"fmt"
	"io"
	"os"
	"sort"
	"strconv"
	"time"

	"github.com/olekukonko/tablewriter"
	"github.com/open-policy-agent/opa/metrics"
	"github.com/open-policy-agent/opa/profiler"
	"github.com/open-policy-agent/opa/rego"
	"github.com/open-policy-agent/opa/topdown"
)

// Output contains the result of evaluation to be presented.
type Output struct {
	Error       error                `json:"error,omitempty"`
	Result      rego.ResultSet       `json:"result,omitempty"`
	Metrics     metrics.Metrics      `json:"metrics,omitempty"`
	Explanation []*topdown.Event     `json:"explanation,omitempty"`
	Profile     []profiler.ExprStats `json:"profile,omitempty"`
	limit       int
}

// WithLimit sets the output limit to set on stringified values.
func (e Output) WithLimit(n int) Output {
	e.limit = n
	return e
}

// JSON writes x to w with indentation.
func JSON(w io.Writer, x interface{}) error {
	encoder := json.NewEncoder(w)
	encoder.SetIndent("", "  ")
	return encoder.Encode(x)
}

// Bindings prints the bindings from r to w.
func Bindings(w io.Writer, r Output) error {
	if r.Error != nil {
		return prettyError(w, r.Error)
	}
	for _, rs := range r.Result {
		if err := JSON(w, rs.Bindings); err != nil {
			return err
		}
	}
	return nil
}

// Values prints the values from r to w.
func Values(w io.Writer, r Output) error {
	if r.Error != nil {
		return prettyError(w, r.Error)
	}
	for _, rs := range r.Result {
		line := make([]interface{}, len(rs.Expressions))
		for i := range line {
			line[i] = rs.Expressions[i].Value
		}
		if err := JSON(os.Stdout, line); err != nil {
			return err
		}
	}
	return nil
}

// Pretty prints all of r to w in a human-readable format.
func Pretty(w io.Writer, r Output) error {
	if len(r.Explanation) > 0 {
		if err := prettyExplanation(w, r.Explanation); err != nil {
			return err
		}
	}
	if r.Error != nil {
		if err := prettyError(w, r.Error); err != nil {
			return err
		}
	} else {
		if err := prettyResult(w, r.Result, r.limit); err != nil {
			return err
		}
	}
	if r.Metrics != nil {
		if err := prettyMetrics(w, r.Metrics, r.limit); err != nil {
			return err
		}
	}
	if len(r.Profile) > 0 {
		if err := prettyProfile(w, r.Profile); err != nil {
			return err
		}
	}
	return nil
}

func prettyError(w io.Writer, err error) error {
	_, err = fmt.Fprintln(w, err)
	return err
}

func prettyResult(w io.Writer, rs rego.ResultSet, limit int) error {

	if len(rs) == 0 {
		fmt.Fprintln(w, "undefined")
		return nil
	}

	if len(rs) == 1 && len(rs[0].Bindings) == 0 {
		if len(rs[0].Expressions) == 1 || allBoolean(rs[0].Expressions) {
			return JSON(w, rs[0].Expressions[0].Value)
		}
	}

	keys := generateResultKeys(rs)
	tableBindings := generateTableBindings(w, keys, rs, limit)
	if tableBindings.NumLines() > 0 {
		tableBindings.Render()
	}

	return nil
}

func prettyMetrics(w io.Writer, m metrics.Metrics, limit int) error {
	tableMetrics := generateTableMetrics(w)
	populateTableMetrics(m, tableMetrics, limit)
	if tableMetrics.NumLines() > 0 {
		tableMetrics.Render()
	}
	return nil
}

func prettyProfile(w io.Writer, profile []profiler.ExprStats) error {
	tableProfile := generateTableProfile(w)
	for _, rs := range profile {
		line := []string{}
		timeNs := time.Duration(rs.ExprTimeNs) * time.Nanosecond
		timeNsStr := timeNs.String()
		numEval := strconv.FormatInt(int64(rs.NumEval), 10)
		numRedo := strconv.FormatInt(int64(rs.NumRedo), 10)
		loc := rs.Location.String()
		line = append(line, timeNsStr, numEval, numRedo, loc)
		tableProfile.Append(line)
	}
	if tableProfile.NumLines() > 0 {
		tableProfile.Render()
	}
	return nil
}

func prettyExplanation(w io.Writer, explanation []*topdown.Event) error {
	topdown.PrettyTrace(w, explanation)
	return nil
}

func checkStrLimit(input string, limit int) string {
	if limit > 0 && len(input) > limit {
		input = input[:limit] + "..."
		return input
	}
	return input
}

func generateTableBindings(writer io.Writer, keys []resultKey, rs rego.ResultSet, prettyLimit int) *tablewriter.Table {
	table := tablewriter.NewWriter(writer)
	table.SetAlignment(tablewriter.ALIGN_CENTER)
	table.SetAutoFormatHeaders(false)
	header := make([]string, len(keys))
	for i := range header {
		header[i] = keys[i].string()
	}
	table.SetHeader(header)
	alignment := make([]int, len(keys))
	for i := range header {
		alignment[i] = tablewriter.ALIGN_LEFT
	}
	table.SetColumnAlignment(alignment)

	for _, row := range rs {
		printPrettyRow(table, keys, row, prettyLimit)
	}
	return table
}

func printPrettyRow(table *tablewriter.Table, keys []resultKey, result rego.Result, prettyLimit int) {
	buf := []string{}
	for _, k := range keys {
		v, ok := k.selectVarValue(result)
		if ok {
			js, err := json.Marshal(v)
			if err != nil {
				buf = append(buf, err.Error())
			} else {
				s := checkStrLimit(string(js), prettyLimit)
				buf = append(buf, s)
			}
		}
	}
	table.Append(buf)
}

func generateTableMetrics(writer io.Writer) *tablewriter.Table {
	table := tablewriter.NewWriter(writer)
	table.SetHeader([]string{"Metric", "Value"})
	table.SetAlignment(tablewriter.ALIGN_CENTER)
	table.SetColumnAlignment([]int{tablewriter.ALIGN_LEFT, tablewriter.ALIGN_LEFT})
	return table
}

func generateTableProfile(writer io.Writer) *tablewriter.Table {
	table := tablewriter.NewWriter(writer)
	table.SetHeader([]string{"Time", "Num Eval", "Num Redo", "Location"})
	table.SetAlignment(tablewriter.ALIGN_CENTER)
	table.SetColumnAlignment([]int{tablewriter.ALIGN_LEFT, tablewriter.ALIGN_LEFT,
		tablewriter.ALIGN_LEFT, tablewriter.ALIGN_LEFT})
	return table
}

func populateTableMetrics(m metrics.Metrics, table *tablewriter.Table, prettyLimit int) {
	lines := [][]string{}
	for varName, varValueInterface := range m.All() {
		val, ok := varValueInterface.(map[string]interface{})
		if !ok {
			line := []string{}
			varValue := checkStrLimit(fmt.Sprintf("%v", varValueInterface), prettyLimit)
			line = append(line, varName, varValue)
			lines = append(lines, line)
		} else {
			for k, v := range val {
				line := []string{}
				newVarName := fmt.Sprintf("%v_%v", varName, k)
				value := checkStrLimit(fmt.Sprintf("%v", v), prettyLimit)
				line = append(line, newVarName, value)
				lines = append(lines, line)
			}
		}
	}
	sortMetricRows(lines)
	table.AppendBulk(lines)
}

func sortMetricRows(data [][]string) {
	sort.Slice(data, func(i, j int) bool {
		return data[i][0] < data[j][0]
	})
}

type resultKey struct {
	varName   string
	exprIndex int
	exprText  string
}

func resultKeyLess(a, b resultKey) bool {
	if a.varName != "" {
		if b.varName == "" {
			return true
		}
		return a.varName < b.varName
	}
	return a.exprIndex < b.exprIndex
}

func (rk resultKey) string() string {
	if rk.varName != "" {
		return rk.varName
	}
	return rk.exprText
}

func (rk resultKey) selectVarValue(result rego.Result) (interface{}, bool) {
	if rk.varName != "" {
		return result.Bindings[rk.varName], true
	}
	val := result.Expressions[rk.exprIndex].Value
	if _, ok := val.(bool); ok {
		return nil, false
	}
	return val, true
}

func generateResultKeys(rs rego.ResultSet) []resultKey {
	keys := []resultKey{}
	if len(rs) != 0 {
		for k := range rs[0].Bindings {
			keys = append(keys, resultKey{
				varName: k,
			})
		}

		for i, expr := range rs[0].Expressions {
			if _, ok := expr.Value.(bool); !ok {
				keys = append(keys, resultKey{
					exprIndex: i,
					exprText:  expr.Text,
				})
			}
		}

		sort.Slice(keys, func(i, j int) bool {
			return resultKeyLess(keys[i], keys[j])
		})
	}
	return keys
}

func allBoolean(ev []*rego.ExpressionValue) bool {
	for i := range ev {
		if _, ok := ev[i].Value.(bool); !ok {
			return false
		}
	}
	return true
}
<|endoftext|>


<commit_before>package main_test

import (
	"os"
	"os/exec"

	linkpkg "github.com/cloudfoundry-incubator/garden-linux/iodaemon/link"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/gexec"
)

var _ = Describe("Iodaemon integration tests", func() {
	It("can read stdin", func() {
		spawnS, err := gexec.Start(exec.Command(
			iodaemon,
			"spawn",
			socketPath,
			"bash", "-c", "cat <&0; exit 42",
		), GinkgoWriter, GinkgoWriter)
		Expect(err).ToNot(HaveOccurred())

		defer spawnS.Kill()

		Eventually(spawnS).Should(gbytes.Say("ready\n"))
		Consistently(spawnS).ShouldNot(gbytes.Say("active\n"))

		linkStdout := gbytes.NewBuffer()
		link, err := linkpkg.Create(socketPath, linkStdout, os.Stderr)
		Expect(err).ToNot(HaveOccurred())

		link.Write([]byte("hello\ngoodbye"))
		link.Close()

		Eventually(spawnS).Should(gbytes.Say("active\n"))
		Eventually(linkStdout).Should(gbytes.Say("hello\ngoodbye"))

		Expect(link.Wait()).To(Equal(42))
	})

	It("can read stdin in tty mode", func() {
		spawnS, err := gexec.Start(exec.Command(
			iodaemon,
			"-tty",
			"spawn",
			socketPath,
			"bash", "-c", "cat <&0; exit 42",
		), GinkgoWriter, GinkgoWriter)
		Expect(err).ToNot(HaveOccurred())

		defer spawnS.Kill()

		Eventually(spawnS).Should(gbytes.Say("ready\n"))
		Consistently(spawnS).ShouldNot(gbytes.Say("active\n"))

		linkStdout := gbytes.NewBuffer()
		link, err := linkpkg.Create(socketPath, linkStdout, os.Stderr)
		Expect(err).ToNot(HaveOccurred())

		link.Write([]byte("hello\ngoodbye"))
		link.Close()

		Eventually(spawnS).Should(gbytes.Say("active\n"))
		Eventually(linkStdout).Should(gbytes.Say("hello\r\ngoodbye"))

		Expect(link.Wait()).To(Equal(-1)) // -1 indicates unhandled SIGHUP
	})

	It("consistently executes a quickly-printing-and-exiting command", func() {
		for i := 0; i < 100; i++ {
			spawnS, err := gexec.Start(exec.Command(
				iodaemon,
				"spawn",
				socketPath,
				"echo", "hi",
			), GinkgoWriter, GinkgoWriter)
			Expect(err).ToNot(HaveOccurred())

			Eventually(spawnS).Should(gbytes.Say("ready\n"))

			lk, err := linkpkg.Create(socketPath, GinkgoWriter, GinkgoWriter)
			Expect(err).ToNot(HaveOccurred())
			lk.Close()

			Eventually(spawnS).Should(gbytes.Say("active\n"))
			Eventually(spawnS).Should(gexec.Exit(0))
		}
	})

	It("times out while spawning when no listeners connect", func() {
		process, err := gexec.Start(exec.Command(
			iodaemon,
			"-timeout 5s",
			"spawn",
			socketPath,
			"bash", "-c", "cat <&0",
		), GinkgoWriter, GinkgoWriter)
		Expect(err).ToNot(HaveOccurred())

		Eventually(process, "6s").Should(gexec.Exit(2))
	})
})
<commit_msg>Increase timeout to avoid flake.<commit_after>package main_test

import (
	"os"
	"os/exec"

	linkpkg "github.com/cloudfoundry-incubator/garden-linux/iodaemon/link"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/gexec"
)

var _ = Describe("Iodaemon integration tests", func() {
	It("can read stdin", func() {
		spawnS, err := gexec.Start(exec.Command(
			iodaemon,
			"spawn",
			socketPath,
			"bash", "-c", "cat <&0; exit 42",
		), GinkgoWriter, GinkgoWriter)
		Expect(err).ToNot(HaveOccurred())

		defer spawnS.Kill()

		Eventually(spawnS).Should(gbytes.Say("ready\n"))
		Consistently(spawnS).ShouldNot(gbytes.Say("active\n"))

		linkStdout := gbytes.NewBuffer()
		link, err := linkpkg.Create(socketPath, linkStdout, os.Stderr)
		Expect(err).ToNot(HaveOccurred())

		link.Write([]byte("hello\ngoodbye"))
		link.Close()

		Eventually(spawnS).Should(gbytes.Say("active\n"))
		Eventually(linkStdout).Should(gbytes.Say("hello\ngoodbye"))

		Expect(link.Wait()).To(Equal(42))
	})

	It("can read stdin in tty mode", func() {
		spawnS, err := gexec.Start(exec.Command(
			iodaemon,
			"-tty",
			"spawn",
			socketPath,
			"bash", "-c", "cat <&0; exit 42",
		), GinkgoWriter, GinkgoWriter)
		Expect(err).ToNot(HaveOccurred())

		defer spawnS.Kill()

		Eventually(spawnS).Should(gbytes.Say("ready\n"))
		Consistently(spawnS).ShouldNot(gbytes.Say("active\n"))

		linkStdout := gbytes.NewBuffer()
		link, err := linkpkg.Create(socketPath, linkStdout, os.Stderr)
		Expect(err).ToNot(HaveOccurred())

		link.Write([]byte("hello\ngoodbye"))
		link.Close()

		Eventually(spawnS).Should(gbytes.Say("active\n"))
		Eventually(linkStdout).Should(gbytes.Say("hello\r\ngoodbye"))

		Expect(link.Wait()).To(Equal(-1)) // -1 indicates unhandled SIGHUP
	})

	It("consistently executes a quickly-printing-and-exiting command", func() {
		for i := 0; i < 100; i++ {
			spawnS, err := gexec.Start(exec.Command(
				iodaemon,
				"spawn",
				socketPath,
				"echo", "hi",
			), GinkgoWriter, GinkgoWriter)
			Expect(err).ToNot(HaveOccurred())

			Eventually(spawnS).Should(gbytes.Say("ready\n"))

			lk, err := linkpkg.Create(socketPath, GinkgoWriter, GinkgoWriter)
			Expect(err).ToNot(HaveOccurred())
			lk.Close()

			Eventually(spawnS).Should(gbytes.Say("active\n"))
			Eventually(spawnS, 2).Should(gexec.Exit(0))
		}
	})

	It("times out while spawning when no listeners connect", func() {
		process, err := gexec.Start(exec.Command(
			iodaemon,
			"-timeout 5s",
			"spawn",
			socketPath,
			"bash", "-c", "cat <&0",
		), GinkgoWriter, GinkgoWriter)
		Expect(err).ToNot(HaveOccurred())

		Eventually(process, "6s").Should(gexec.Exit(2))
	})
})
<|endoftext|>


<commit_before>package simpleamqp_test

// +build integration

import (
	"log"
	"os"
	"time"

	"testing"

	. "github.com/aleasoluciones/simpleamqp"
	"github.com/stretchr/testify/assert"
)

func amqpUrlFromEnv() string {
	url := os.Getenv("AMQP_URL")
	if url == "" {
		url = "amqp://"
	}
	return url
}

func TestPublishAndReceiveTwoMessages(t *testing.T) {
	t.Parallel()
	amqpUrl := amqpUrlFromEnv()
	amqpPublisher := NewAmqpPublisher(amqpUrl, "events")
	amqpConsumer := NewAmqpConsumer(amqpUrl)
	messages := amqpConsumer.Receive(
		"events", []string{"routingkey1"},
		"", QueueOptions{Durable: false, Delete: true, Exclusive: true},
		30*time.Second)

	// We should wait until the real async queue creation
	time.Sleep(2 * time.Second)

	amqpPublisher.Publish("routingkey1", []byte("irrelevantBody1"))
	amqpPublisher.Publish("routingkey1", []byte("irrelevantBody2"))

	message1 := <-messages
	assert.Equal(t, message1.Body, "irrelevantBody1")
	assert.Equal(t, message1.Exchange, "events")
	assert.Equal(t, message1.RoutingKey, "routingkey1")
	message2 := <-messages
	assert.Equal(t, message2.Body, "irrelevantBody2")
	assert.Equal(t, message2.Exchange, "events")
	assert.Equal(t, message2.RoutingKey, "routingkey1")

}

func TestAmqpManagementInitialQueueInfo(t *testing.T) {
	t.Parallel()
	amqpUrl := amqpUrlFromEnv()

	management := NewAmqpManagement(amqpUrl)
	management.QueueDelete("q_initial_queueinfo")
	management.QueueDeclare("q_initial_queueinfo", QueueOptions{Durable: false, Delete: true, Exclusive: false})

	result, _ := management.QueueInfo("q_initial_queueinfo")

	assert.Equal(t, "q_initial_queueinfo", result.Name)
	assert.Equal(t, 0, result.Messages)
	assert.Equal(t, 0, result.Consumers)
}

func TestAmqpManagementCountPendingMessages(t *testing.T) {
	t.Parallel()
	amqpUrl := amqpUrlFromEnv()

	management := NewAmqpManagement(amqpUrl)
	management.QueueDelete("q_count_pending_messages")
	management.QueueDeclare("q_count_pending_messages", QueueOptions{Durable: false, Delete: true, Exclusive: false})

	amqpPublisher := NewAmqpPublisher(amqpUrl, "e1")
	// We should wait until the real async queue creation
	time.Sleep(2 * time.Second)

	management.QueueBind("q_count_pending_messages", "e1", "#")
	amqpPublisher.Publish("routingkey1", []byte("irrelevantBody1"))
	amqpPublisher.Publish("routingkey1", []byte("irrelevantBody2"))

	result, _ := management.QueueInfo("q_count_pending_messages")

	assert.Equal(t, "q_count_pending_messages", result.Name)
	assert.Equal(t, 2, result.Messages)
	assert.Equal(t, 0, result.Consumers)

}

func TestAmqpManagementCountConsumers(t *testing.T) {
	t.Parallel()
	amqpUrl := amqpUrlFromEnv()

	management := NewAmqpManagement(amqpUrl)
	management.QueueDelete("q_count_consumers")

	NewAmqpConsumer(amqpUrl).Receive("ex", []string{"#"}, "q_count_consumers",
		QueueOptions{Durable: true, Delete: false, Exclusive: false},
		30*time.Second)

	// We should wait until the real async queue creation
	time.Sleep(2 * time.Second)
	result, _ := management.QueueInfo("q_count_consumers")

	assert.Equal(t, "q_count_consumers", result.Name)
	assert.Equal(t, 0, result.Messages)
	assert.Equal(t, 1, result.Consumers)

}
<commit_msg>Bugfix<commit_after>package simpleamqp_test

// +build integration

import (
	"os"
	"time"

	"testing"

	. "github.com/aleasoluciones/simpleamqp"
	"github.com/stretchr/testify/assert"
)

func amqpUrlFromEnv() string {
	url := os.Getenv("AMQP_URL")
	if url == "" {
		url = "amqp://"
	}
	return url
}

func TestPublishAndReceiveTwoMessages(t *testing.T) {
	t.Parallel()
	amqpUrl := amqpUrlFromEnv()
	amqpPublisher := NewAmqpPublisher(amqpUrl, "events")
	amqpConsumer := NewAmqpConsumer(amqpUrl)
	messages := amqpConsumer.Receive(
		"events", []string{"routingkey1"},
		"", QueueOptions{Durable: false, Delete: true, Exclusive: true},
		30*time.Second)

	// We should wait until the real async queue creation
	time.Sleep(2 * time.Second)

	amqpPublisher.Publish("routingkey1", []byte("irrelevantBody1"))
	amqpPublisher.Publish("routingkey1", []byte("irrelevantBody2"))

	message1 := <-messages
	assert.Equal(t, message1.Body, "irrelevantBody1")
	assert.Equal(t, message1.Exchange, "events")
	assert.Equal(t, message1.RoutingKey, "routingkey1")
	message2 := <-messages
	assert.Equal(t, message2.Body, "irrelevantBody2")
	assert.Equal(t, message2.Exchange, "events")
	assert.Equal(t, message2.RoutingKey, "routingkey1")

}

func TestAmqpManagementInitialQueueInfo(t *testing.T) {
	t.Parallel()
	amqpUrl := amqpUrlFromEnv()

	management := NewAmqpManagement(amqpUrl)
	management.QueueDelete("q_initial_queueinfo")
	management.QueueDeclare("q_initial_queueinfo", QueueOptions{Durable: false, Delete: true, Exclusive: false})

	result, _ := management.QueueInfo("q_initial_queueinfo")

	assert.Equal(t, "q_initial_queueinfo", result.Name)
	assert.Equal(t, 0, result.Messages)
	assert.Equal(t, 0, result.Consumers)
}

func TestAmqpManagementCountPendingMessages(t *testing.T) {
	t.Parallel()
	amqpUrl := amqpUrlFromEnv()

	management := NewAmqpManagement(amqpUrl)
	management.QueueDelete("q_count_pending_messages")
	management.QueueDeclare("q_count_pending_messages", QueueOptions{Durable: false, Delete: true, Exclusive: false})

	amqpPublisher := NewAmqpPublisher(amqpUrl, "e1")
	// We should wait until the real async queue creation
	time.Sleep(2 * time.Second)

	management.QueueBind("q_count_pending_messages", "e1", "#")
	amqpPublisher.Publish("routingkey1", []byte("irrelevantBody1"))
	amqpPublisher.Publish("routingkey1", []byte("irrelevantBody2"))

	result, _ := management.QueueInfo("q_count_pending_messages")

	assert.Equal(t, "q_count_pending_messages", result.Name)
	assert.Equal(t, 2, result.Messages)
	assert.Equal(t, 0, result.Consumers)

}

func TestAmqpManagementCountConsumers(t *testing.T) {
	t.Parallel()
	amqpUrl := amqpUrlFromEnv()

	management := NewAmqpManagement(amqpUrl)
	management.QueueDelete("q_count_consumers")

	NewAmqpConsumer(amqpUrl).Receive("ex", []string{"#"}, "q_count_consumers",
		QueueOptions{Durable: true, Delete: false, Exclusive: false},
		30*time.Second)

	// We should wait until the real async queue creation
	time.Sleep(2 * time.Second)
	result, _ := management.QueueInfo("q_count_consumers")

	assert.Equal(t, "q_count_consumers", result.Name)
	assert.Equal(t, 0, result.Messages)
	assert.Equal(t, 1, result.Consumers)

}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package v1alpha1

import (
	"fmt"
	"k8s.io/kops/pkg/apis/kops"
	"k8s.io/kubernetes/pkg/conversion"
	"reflect"
	"sort"
	"strings"
)

func Convert_v1alpha1_BastionSpec_To_kops_BastionSpec(in *BastionSpec, out *kops.BastionSpec, s conversion.Scope) error {
	out.BastionPublicName = in.PublicName
	out.IdleTimeoutSeconds = in.IdleTimeout

	if !in.Enable {
		out.BastionPublicName = ""
		out.IdleTimeoutSeconds = nil
	}

	return nil
}

func Convert_kops_BastionSpec_To_v1alpha1_BastionSpec(in *kops.BastionSpec, out *BastionSpec, s conversion.Scope) error {
	out.PublicName = in.BastionPublicName
	out.IdleTimeout = in.IdleTimeoutSeconds

	out.Enable = true
	out.MachineType = ""

	return nil
}

func Convert_v1alpha1_ClusterSpec_To_kops_ClusterSpec(in *ClusterSpec, out *kops.ClusterSpec, s conversion.Scope) error {
	topologyPrivate := false
	if in.Topology != nil && in.Topology.Masters == TopologyPrivate {
		topologyPrivate = true
	}

	if in.Zones != nil {
		for _, z := range in.Zones {
			if topologyPrivate {
				// A private zone is mapped to a private- and a utility- subnet
				if z.PrivateCIDR != "" {
					out.Subnets = append(out.Subnets, kops.ClusterSubnetSpec{
						Name:       z.Name,
						CIDR:       z.PrivateCIDR,
						ProviderID: z.ProviderID,
						Zone:       z.Name,
						Type:       kops.SubnetTypePrivate,
					})
				}

				if z.CIDR != "" {
					out.Subnets = append(out.Subnets, kops.ClusterSubnetSpec{
						Name: "utility-" + z.Name,
						CIDR: z.CIDR,
						Zone: z.Name,
						Type: kops.SubnetTypeUtility,
					})
				}
			} else {
				out.Subnets = append(out.Subnets, kops.ClusterSubnetSpec{
					Name:       z.Name,
					CIDR:       z.CIDR,
					ProviderID: z.ProviderID,
					Zone:       z.Name,
					Type:       kops.SubnetTypePublic,
				})
			}
		}
	} else {
		out.Subnets = nil
	}

	out.SSHAccess = in.AdminAccess
	out.KubernetesAPIAccess = in.AdminAccess

	return autoConvert_v1alpha1_ClusterSpec_To_kops_ClusterSpec(in, out, s)
}

// ByName implements sort.Interface for []*ClusterZoneSpec on the Name field.
type ByName []*ClusterZoneSpec

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

func Convert_kops_ClusterSpec_To_v1alpha1_ClusterSpec(in *kops.ClusterSpec, out *ClusterSpec, s conversion.Scope) error {
	topologyPrivate := false
	if in.Topology != nil && in.Topology.Masters == TopologyPrivate {
		topologyPrivate = true
	}

	if in.Subnets != nil {
		zoneMap := make(map[string]*ClusterZoneSpec)

		for _, s := range in.Subnets {
			zoneName := s.Name
			if s.Type == kops.SubnetTypeUtility {
				if !strings.HasPrefix(zoneName, "utility-") {
					return fmt.Errorf("cannot convert subnet to v1alpha1 when subnet with Type=utility does not have name starting with utility-: %q", zoneName)
				}
				zoneName = strings.TrimPrefix(zoneName, "utility-")
			}
			if s.Zone != zoneName {
				return fmt.Errorf("cannot convert to v1alpha1 when subnet Zone != Name: %q != %q", s.Zone, s.Name)
			}

			zone := zoneMap[zoneName]
			if zone == nil {
				zone = &ClusterZoneSpec{
					Name: s.Zone,
				}
				zoneMap[zoneName] = zone
			}

			if topologyPrivate {
				subnetType := s.Type
				if subnetType == "" {
					subnetType = kops.SubnetTypePrivate
				}
				switch subnetType {
				case kops.SubnetTypePrivate:
					if zone.PrivateCIDR != "" || zone.ProviderID != "" {
						return fmt.Errorf("cannot convert to v1alpha1: duplicate zone: %v", zone)
					}
					zone.PrivateCIDR = s.CIDR
					zone.ProviderID = s.ProviderID

				case kops.SubnetTypeUtility:
					if zone.CIDR != "" {
						return fmt.Errorf("cannot convert to v1alpha1: duplicate zone: %v", zone)
					}
					zone.CIDR = s.CIDR

				case kops.SubnetTypePublic:
					return fmt.Errorf("cannot convert to v1alpha1 when subnet type is public")

				default:
					return fmt.Errorf("unknown SubnetType: %v", subnetType)
				}
			} else {
				if zone.CIDR != "" || zone.ProviderID != "" {
					return fmt.Errorf("cannot convert to v1alpha1: duplicate zone: %v", zone)
				}
				zone.CIDR = s.CIDR
				zone.ProviderID = s.ProviderID
			}
		}

		for _, z := range zoneMap {
			out.Zones = append(out.Zones, z)
		}

		sort.Sort(ByName(out.Zones))
	} else {
		out.Zones = nil
	}

	if !reflect.DeepEqual(in.SSHAccess, in.KubernetesAPIAccess) {
		return fmt.Errorf("cannot convert to v1alpha1: SSHAccess != KubernetesAPIAccess")
	}
	out.AdminAccess = in.SSHAccess

	return autoConvert_kops_ClusterSpec_To_v1alpha1_ClusterSpec(in, out, s)
}

func Convert_v1alpha1_EtcdMemberSpec_To_kops_EtcdMemberSpec(in *EtcdMemberSpec, out *kops.EtcdMemberSpec, s conversion.Scope) error {
	if in.Zone != nil {
		instanceGroup := "master-" + *in.Zone
		out.InstanceGroup = &instanceGroup
	} else {
		out.InstanceGroup = nil
	}

	return autoConvert_v1alpha1_EtcdMemberSpec_To_kops_EtcdMemberSpec(in, out, s)
}

func Convert_kops_EtcdMemberSpec_To_v1alpha1_EtcdMemberSpec(in *kops.EtcdMemberSpec, out *EtcdMemberSpec, s conversion.Scope) error {
	err := autoConvert_kops_EtcdMemberSpec_To_v1alpha1_EtcdMemberSpec(in, out, s)
	if err != nil {
		return err
	}

	if in.InstanceGroup != nil {
		zone := *in.InstanceGroup
		if !strings.HasPrefix(zone, "master-") {
			return fmt.Errorf("cannot convert etc instance group name %q to v1alpha1: need master- prefix", zone)
		}
		zone = strings.TrimPrefix(zone, "master-")
		out.Zone = &zone
		out.Name = zone
	} else {
		out.Zone = nil
	}

	return nil
}

func Convert_v1alpha1_InstanceGroupSpec_To_kops_InstanceGroupSpec(in *InstanceGroupSpec, out *kops.InstanceGroupSpec, s conversion.Scope) error {
	out.Subnets = in.Zones

	return autoConvert_v1alpha1_InstanceGroupSpec_To_kops_InstanceGroupSpec(in, out, s)
}

func Convert_kops_InstanceGroupSpec_To_v1alpha1_InstanceGroupSpec(in *kops.InstanceGroupSpec, out *InstanceGroupSpec, s conversion.Scope) error {
	out.Zones = in.Subnets

	return autoConvert_kops_InstanceGroupSpec_To_v1alpha1_InstanceGroupSpec(in, out, s)
}

func Convert_v1alpha1_TopologySpec_To_kops_TopologySpec(in *TopologySpec, out *kops.TopologySpec, s conversion.Scope) error {
	out.Masters = in.Masters
	out.Nodes = in.Nodes
	if in.Bastion != nil && in.Bastion.Enable {
		out.Bastion = new(kops.BastionSpec)
		if err := Convert_v1alpha1_BastionSpec_To_kops_BastionSpec(in.Bastion, out.Bastion, s); err != nil {
			return err
		}
	} else {
		out.Bastion = nil
	}
	return nil
}

func Convert_kops_TopologySpec_To_v1alpha1_TopologySpec(in *kops.TopologySpec, out *TopologySpec, s conversion.Scope) error {
	out.Masters = in.Masters
	out.Nodes = in.Nodes
	if in.Bastion != nil {
		out.Bastion = new(BastionSpec)
		if err := Convert_kops_BastionSpec_To_v1alpha1_BastionSpec(in.Bastion, out.Bastion, s); err != nil {
			return err
		}
	} else {
		out.Bastion = nil
	}
	return nil
}
<commit_msg>If the user tries to save a SubnetID into v1alpha1, fail<commit_after>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package v1alpha1

import (
	"fmt"
	"k8s.io/kops/pkg/apis/kops"
	"k8s.io/kubernetes/pkg/conversion"
	"reflect"
	"sort"
	"strings"
)

func Convert_v1alpha1_BastionSpec_To_kops_BastionSpec(in *BastionSpec, out *kops.BastionSpec, s conversion.Scope) error {
	out.BastionPublicName = in.PublicName
	out.IdleTimeoutSeconds = in.IdleTimeout

	if !in.Enable {
		out.BastionPublicName = ""
		out.IdleTimeoutSeconds = nil
	}

	return nil
}

func Convert_kops_BastionSpec_To_v1alpha1_BastionSpec(in *kops.BastionSpec, out *BastionSpec, s conversion.Scope) error {
	out.PublicName = in.BastionPublicName
	out.IdleTimeout = in.IdleTimeoutSeconds

	out.Enable = true
	out.MachineType = ""

	return nil
}

func Convert_v1alpha1_ClusterSpec_To_kops_ClusterSpec(in *ClusterSpec, out *kops.ClusterSpec, s conversion.Scope) error {
	topologyPrivate := false
	if in.Topology != nil && in.Topology.Masters == TopologyPrivate {
		topologyPrivate = true
	}

	if in.Zones != nil {
		for _, z := range in.Zones {
			if topologyPrivate {
				// A private zone is mapped to a private- and a utility- subnet
				if z.PrivateCIDR != "" {
					out.Subnets = append(out.Subnets, kops.ClusterSubnetSpec{
						Name:       z.Name,
						CIDR:       z.PrivateCIDR,
						ProviderID: z.ProviderID,
						Zone:       z.Name,
						Type:       kops.SubnetTypePrivate,
					})
				}

				if z.CIDR != "" {
					out.Subnets = append(out.Subnets, kops.ClusterSubnetSpec{
						Name: "utility-" + z.Name,
						CIDR: z.CIDR,
						Zone: z.Name,
						Type: kops.SubnetTypeUtility,
					})
				}
			} else {
				out.Subnets = append(out.Subnets, kops.ClusterSubnetSpec{
					Name:       z.Name,
					CIDR:       z.CIDR,
					ProviderID: z.ProviderID,
					Zone:       z.Name,
					Type:       kops.SubnetTypePublic,
				})
			}
		}
	} else {
		out.Subnets = nil
	}

	out.SSHAccess = in.AdminAccess
	out.KubernetesAPIAccess = in.AdminAccess

	return autoConvert_v1alpha1_ClusterSpec_To_kops_ClusterSpec(in, out, s)
}

// ByName implements sort.Interface for []*ClusterZoneSpec on the Name field.
type ByName []*ClusterZoneSpec

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

func Convert_kops_ClusterSpec_To_v1alpha1_ClusterSpec(in *kops.ClusterSpec, out *ClusterSpec, s conversion.Scope) error {
	topologyPrivate := false
	if in.Topology != nil && in.Topology.Masters == TopologyPrivate {
		topologyPrivate = true
	}

	if in.Subnets != nil {
		zoneMap := make(map[string]*ClusterZoneSpec)

		for _, s := range in.Subnets {
			zoneName := s.Name
			if s.Type == kops.SubnetTypeUtility {
				if !strings.HasPrefix(zoneName, "utility-") {
					return fmt.Errorf("cannot convert subnet to v1alpha1 when subnet with Type=utility does not have name starting with utility-: %q", zoneName)
				}
				zoneName = strings.TrimPrefix(zoneName, "utility-")
			}
			if s.Zone != zoneName {
				return fmt.Errorf("cannot convert to v1alpha1 when subnet Zone != Name: %q != %q", s.Zone, s.Name)
			}

			zone := zoneMap[zoneName]
			if zone == nil {
				zone = &ClusterZoneSpec{
					Name: s.Zone,
				}
				zoneMap[zoneName] = zone
			}

			if topologyPrivate {
				subnetType := s.Type
				if subnetType == "" {
					subnetType = kops.SubnetTypePrivate
				}
				switch subnetType {
				case kops.SubnetTypePrivate:
					if zone.PrivateCIDR != "" || zone.ProviderID != "" {
						return fmt.Errorf("cannot convert to v1alpha1: duplicate zone: %v", zone)
					}
					zone.PrivateCIDR = s.CIDR
					zone.ProviderID = s.ProviderID

				case kops.SubnetTypeUtility:
					if zone.CIDR != "" {
						return fmt.Errorf("cannot convert to v1alpha1: duplicate zone: %v", zone)
					}
					zone.CIDR = s.CIDR

					// We simple can't express this in v1alpha1
					if s.ProviderID != "" {
						return fmt.Errorf("cannot convert to v1alpha1: utility subnet had ProviderID %v", s.Name)
					}

				case kops.SubnetTypePublic:
					return fmt.Errorf("cannot convert to v1alpha1 when subnet type is public")

				default:
					return fmt.Errorf("unknown SubnetType: %v", subnetType)
				}
			} else {
				if zone.CIDR != "" || zone.ProviderID != "" {
					return fmt.Errorf("cannot convert to v1alpha1: duplicate zone: %v", zone)
				}
				zone.CIDR = s.CIDR
				zone.ProviderID = s.ProviderID
			}
		}

		for _, z := range zoneMap {
			out.Zones = append(out.Zones, z)
		}

		sort.Sort(ByName(out.Zones))
	} else {
		out.Zones = nil
	}

	if !reflect.DeepEqual(in.SSHAccess, in.KubernetesAPIAccess) {
		return fmt.Errorf("cannot convert to v1alpha1: SSHAccess != KubernetesAPIAccess")
	}
	out.AdminAccess = in.SSHAccess

	return autoConvert_kops_ClusterSpec_To_v1alpha1_ClusterSpec(in, out, s)
}

func Convert_v1alpha1_EtcdMemberSpec_To_kops_EtcdMemberSpec(in *EtcdMemberSpec, out *kops.EtcdMemberSpec, s conversion.Scope) error {
	if in.Zone != nil {
		instanceGroup := "master-" + *in.Zone
		out.InstanceGroup = &instanceGroup
	} else {
		out.InstanceGroup = nil
	}

	return autoConvert_v1alpha1_EtcdMemberSpec_To_kops_EtcdMemberSpec(in, out, s)
}

func Convert_kops_EtcdMemberSpec_To_v1alpha1_EtcdMemberSpec(in *kops.EtcdMemberSpec, out *EtcdMemberSpec, s conversion.Scope) error {
	err := autoConvert_kops_EtcdMemberSpec_To_v1alpha1_EtcdMemberSpec(in, out, s)
	if err != nil {
		return err
	}

	if in.InstanceGroup != nil {
		zone := *in.InstanceGroup
		if !strings.HasPrefix(zone, "master-") {
			return fmt.Errorf("cannot convert etc instance group name %q to v1alpha1: need master- prefix", zone)
		}
		zone = strings.TrimPrefix(zone, "master-")
		out.Zone = &zone
		out.Name = zone
	} else {
		out.Zone = nil
	}

	return nil
}

func Convert_v1alpha1_InstanceGroupSpec_To_kops_InstanceGroupSpec(in *InstanceGroupSpec, out *kops.InstanceGroupSpec, s conversion.Scope) error {
	out.Subnets = in.Zones

	return autoConvert_v1alpha1_InstanceGroupSpec_To_kops_InstanceGroupSpec(in, out, s)
}

func Convert_kops_InstanceGroupSpec_To_v1alpha1_InstanceGroupSpec(in *kops.InstanceGroupSpec, out *InstanceGroupSpec, s conversion.Scope) error {
	out.Zones = in.Subnets

	return autoConvert_kops_InstanceGroupSpec_To_v1alpha1_InstanceGroupSpec(in, out, s)
}

func Convert_v1alpha1_TopologySpec_To_kops_TopologySpec(in *TopologySpec, out *kops.TopologySpec, s conversion.Scope) error {
	out.Masters = in.Masters
	out.Nodes = in.Nodes
	if in.Bastion != nil && in.Bastion.Enable {
		out.Bastion = new(kops.BastionSpec)
		if err := Convert_v1alpha1_BastionSpec_To_kops_BastionSpec(in.Bastion, out.Bastion, s); err != nil {
			return err
		}
	} else {
		out.Bastion = nil
	}
	return nil
}

func Convert_kops_TopologySpec_To_v1alpha1_TopologySpec(in *kops.TopologySpec, out *TopologySpec, s conversion.Scope) error {
	out.Masters = in.Masters
	out.Nodes = in.Nodes
	if in.Bastion != nil {
		out.Bastion = new(BastionSpec)
		if err := Convert_kops_BastionSpec_To_v1alpha1_BastionSpec(in.Bastion, out.Bastion, s); err != nil {
			return err
		}
	} else {
		out.Bastion = nil
	}
	return nil
}
<|endoftext|>