<commit_before>package memcached

import (
	"bufio"
	"bytes"
	"io/ioutil"
	"reflect"
	"testing"

	"github.com/dustin/gomemcached"
)

func TestTransmitRes(t *testing.T) {
	b := bytes.NewBuffer([]byte{})
	buf := bufio.NewWriter(b)

	res := gomemcached.MCResponse{
		Opcode: gomemcached.SET,
		Cas:    938424885,
		Opaque: 7242,
		Status: 0x338,
		Key:    []byte("somekey"),
		Body:   []byte("somevalue"),
	}

	err := transmitResponse(buf, &res)
	if err != nil {
		t.Fatalf("Error transmitting request: %v", err)
	}

	buf.Flush()

	expected := []byte{
		gomemcached.RES_MAGIC, byte(gomemcached.SET),
		0x0, 0x7, // length of key
		0x0,       // extra length
		0x0,       // reserved
		0x3, 0x38, // Status
		0x0, 0x0, 0x0, 0x10, // Length of value
		0x0, 0x0, 0x1c, 0x4a, // opaque
		0x0, 0x0, 0x0, 0x0, 0x37, 0xef, 0x3a, 0x35, // CAS
		's', 'o', 'm', 'e', 'k', 'e', 'y',
		's', 'o', 'm', 'e', 'v', 'a', 'l', 'u', 'e'}

	if len(b.Bytes()) != res.Size() {
		t.Fatalf("Expected %v bytes, got %v", res.Size(),
			len(b.Bytes()))
	}

	if !reflect.DeepEqual(b.Bytes(), expected) {
		t.Fatalf("Expected:\n%#v\n  -- got -- \n%#v",
			expected, b.Bytes())
	}
}

func BenchmarkTransmitRes(b *testing.B) {
	bout := bytes.NewBuffer([]byte{})

	res := gomemcached.MCResponse{
		Opcode: gomemcached.SET,
		Cas:    938424885,
		Opaque: 7242,
		Status: 824,
		Key:    []byte("somekey"),
		Body:   []byte("somevalue"),
	}

	b.SetBytes(int64(res.Size()))

	for i := 0; i < b.N; i++ {
		bout.Reset()
		buf := bufio.NewWriterSize(bout, res.Size()*2)
		err := transmitResponse(buf, &res)
		if err != nil {
			b.Fatalf("Error transmitting request: %v", err)
		}
	}
}

func BenchmarkTransmitResLarge(b *testing.B) {
	bout := bytes.NewBuffer([]byte{})

	res := gomemcached.MCResponse{
		Opcode: gomemcached.SET,
		Cas:    938424885,
		Opaque: 7242,
		Status: 824,
		Key:    []byte("somekey"),
		Body:   make([]byte, 24*1024),
	}

	b.SetBytes(int64(res.Size()))

	for i := 0; i < b.N; i++ {
		bout.Reset()
		buf := bufio.NewWriterSize(bout, res.Size()*2)
		err := transmitResponse(buf, &res)
		if err != nil {
			b.Fatalf("Error transmitting request: %v", err)
		}
	}
}

func BenchmarkTransmitResNull(b *testing.B) {
	res := gomemcached.MCResponse{
		Opcode: gomemcached.SET,
		Cas:    938424885,
		Opaque: 7242,
		Status: 824,
		Key:    []byte("somekey"),
		Body:   []byte("somevalue"),
	}

	b.SetBytes(int64(res.Size()))

	for i := 0; i < b.N; i++ {
		err := transmitResponse(ioutil.Discard, &res)
		if err != nil {
			b.Fatalf("Error transmitting request: %v", err)
		}
	}
}
<commit_msg>Use &bytes.Buffer{} instead of bytes.NewBuffer([]byte{})<commit_after>package memcached

import (
	"bufio"
	"bytes"
	"io/ioutil"
	"reflect"
	"testing"

	"github.com/dustin/gomemcached"
)

func TestTransmitRes(t *testing.T) {
	b := &bytes.Buffer{}
	buf := bufio.NewWriter(b)

	res := gomemcached.MCResponse{
		Opcode: gomemcached.SET,
		Cas:    938424885,
		Opaque: 7242,
		Status: 0x338,
		Key:    []byte("somekey"),
		Body:   []byte("somevalue"),
	}

	err := transmitResponse(buf, &res)
	if err != nil {
		t.Fatalf("Error transmitting request: %v", err)
	}

	buf.Flush()

	expected := []byte{
		gomemcached.RES_MAGIC, byte(gomemcached.SET),
		0x0, 0x7, // length of key
		0x0,       // extra length
		0x0,       // reserved
		0x3, 0x38, // Status
		0x0, 0x0, 0x0, 0x10, // Length of value
		0x0, 0x0, 0x1c, 0x4a, // opaque
		0x0, 0x0, 0x0, 0x0, 0x37, 0xef, 0x3a, 0x35, // CAS
		's', 'o', 'm', 'e', 'k', 'e', 'y',
		's', 'o', 'm', 'e', 'v', 'a', 'l', 'u', 'e'}

	if len(b.Bytes()) != res.Size() {
		t.Fatalf("Expected %v bytes, got %v", res.Size(),
			len(b.Bytes()))
	}

	if !reflect.DeepEqual(b.Bytes(), expected) {
		t.Fatalf("Expected:\n%#v\n  -- got -- \n%#v",
			expected, b.Bytes())
	}
}

func BenchmarkTransmitRes(b *testing.B) {
	bout := &bytes.Buffer{}

	res := gomemcached.MCResponse{
		Opcode: gomemcached.SET,
		Cas:    938424885,
		Opaque: 7242,
		Status: 824,
		Key:    []byte("somekey"),
		Body:   []byte("somevalue"),
	}

	b.SetBytes(int64(res.Size()))

	for i := 0; i < b.N; i++ {
		bout.Reset()
		buf := bufio.NewWriterSize(bout, res.Size()*2)
		err := transmitResponse(buf, &res)
		if err != nil {
			b.Fatalf("Error transmitting request: %v", err)
		}
	}
}

func BenchmarkTransmitResLarge(b *testing.B) {
	bout := &bytes.Buffer{}

	res := gomemcached.MCResponse{
		Opcode: gomemcached.SET,
		Cas:    938424885,
		Opaque: 7242,
		Status: 824,
		Key:    []byte("somekey"),
		Body:   make([]byte, 24*1024),
	}

	b.SetBytes(int64(res.Size()))

	for i := 0; i < b.N; i++ {
		bout.Reset()
		buf := bufio.NewWriterSize(bout, res.Size()*2)
		err := transmitResponse(buf, &res)
		if err != nil {
			b.Fatalf("Error transmitting request: %v", err)
		}
	}
}

func BenchmarkTransmitResNull(b *testing.B) {
	res := gomemcached.MCResponse{
		Opcode: gomemcached.SET,
		Cas:    938424885,
		Opaque: 7242,
		Status: 824,
		Key:    []byte("somekey"),
		Body:   []byte("somevalue"),
	}

	b.SetBytes(int64(res.Size()))

	for i := 0; i < b.N; i++ {
		err := transmitResponse(ioutil.Discard, &res)
		if err != nil {
			b.Fatalf("Error transmitting request: %v", err)
		}
	}
}
<|endoftext|>


<commit_before>package httpteleport

import (
	"github.com/valyala/fasthttp"
	"runtime"
	"sync/atomic"
	"testing"
	"time"
)

func BenchmarkEndToEndGetNoDelay1(b *testing.B) {
	benchmarkEndToEndGet(b, 1, 0)
}

func BenchmarkEndToEndGetNoDelay10(b *testing.B) {
	benchmarkEndToEndGet(b, 10, 0)
}

func BenchmarkEndToEndGetNoDelay100(b *testing.B) {
	benchmarkEndToEndGet(b, 100, 0)
}

func BenchmarkEndToEndGetNoDelay1000(b *testing.B) {
	benchmarkEndToEndGet(b, 1000, 0)
}

func BenchmarkEndToEndGetNoDelay10K(b *testing.B) {
	benchmarkEndToEndGet(b, 10000, 0)
}

func BenchmarkEndToEndGetDelay1ms(b *testing.B) {
	benchmarkEndToEndGet(b, 1000, time.Millisecond)
}

func BenchmarkEndToEndGetDelay2ms(b *testing.B) {
	benchmarkEndToEndGet(b, 1000, 2*time.Millisecond)
}

func BenchmarkEndToEndGetDelay4ms(b *testing.B) {
	benchmarkEndToEndGet(b, 1000, 4*time.Millisecond)
}

func BenchmarkEndToEndGetDelay8ms(b *testing.B) {
	benchmarkEndToEndGet(b, 1000, 8*time.Millisecond)
}

func BenchmarkEndToEndGetDelay16ms(b *testing.B) {
	benchmarkEndToEndGet(b, 1000, 16*time.Millisecond)
}

func benchmarkEndToEndGet(b *testing.B, parallelism int, batchDelay time.Duration) {
	expectedBody := "Hello world"
	s := &Server{
		Handler: func(ctx *fasthttp.RequestCtx) {
			ctx.SetBodyString(expectedBody)
		},
		Concurrency:   parallelism * runtime.NumCPU(),
		MaxBatchDelay: batchDelay,
	}
	serverStop, ln := newTestServerExt(s)

	var cc []*Client
	for i := 0; i < runtime.NumCPU(); i++ {
		c := newTestClient(ln)
		c.MaxPendingRequests = s.Concurrency
		c.MaxBatchDelay = batchDelay
		cc = append(cc, c)
	}
	var clientIdx uint32

	deadline := time.Now().Add(time.Hour)
	b.SetParallelism(parallelism)
	b.RunParallel(func(pb *testing.PB) {
		n := atomic.AddUint32(&clientIdx, 1)
		c := cc[int(n)%len(cc)]
		req := fasthttp.AcquireRequest()
		resp := fasthttp.AcquireResponse()
		for pb.Next() {
			req.Header.SetHost("foobar")
			req.SetRequestURI("/foo/bar")
			if err := c.DoDeadline(req, resp, deadline); err != nil {
				b.Fatalf("unexpected error: %s", err)
			}
			statusCode := resp.StatusCode()
			if statusCode != fasthttp.StatusOK {
				b.Fatalf("unexpected status code: %d. Expecting %d", statusCode, fasthttp.StatusOK)
			}
			body := resp.Body()
			if string(body) != expectedBody {
				b.Fatalf("unexpected body: %q. Expecting %q", body, expectedBody)
			}
		}
		fasthttp.ReleaseResponse(resp)
		fasthttp.ReleaseRequest(req)
	})

	if err := serverStop(); err != nil {
		b.Fatalf("cannot shutdown server: %s", err)
	}
}
<commit_msg>Use fixed small batch delay on the server, since requests are already sent to the server and processed in batches thanks to client batch delay<commit_after>package httpteleport

import (
	"github.com/valyala/fasthttp"
	"runtime"
	"sync/atomic"
	"testing"
	"time"
)

func BenchmarkEndToEndGetNoDelay1(b *testing.B) {
	benchmarkEndToEndGet(b, 1, 0)
}

func BenchmarkEndToEndGetNoDelay10(b *testing.B) {
	benchmarkEndToEndGet(b, 10, 0)
}

func BenchmarkEndToEndGetNoDelay100(b *testing.B) {
	benchmarkEndToEndGet(b, 100, 0)
}

func BenchmarkEndToEndGetNoDelay1000(b *testing.B) {
	benchmarkEndToEndGet(b, 1000, 0)
}

func BenchmarkEndToEndGetNoDelay10K(b *testing.B) {
	benchmarkEndToEndGet(b, 10000, 0)
}

func BenchmarkEndToEndGetDelay1ms(b *testing.B) {
	benchmarkEndToEndGet(b, 1000, time.Millisecond)
}

func BenchmarkEndToEndGetDelay2ms(b *testing.B) {
	benchmarkEndToEndGet(b, 1000, 2*time.Millisecond)
}

func BenchmarkEndToEndGetDelay4ms(b *testing.B) {
	benchmarkEndToEndGet(b, 1000, 4*time.Millisecond)
}

func BenchmarkEndToEndGetDelay8ms(b *testing.B) {
	benchmarkEndToEndGet(b, 1000, 8*time.Millisecond)
}

func BenchmarkEndToEndGetDelay16ms(b *testing.B) {
	benchmarkEndToEndGet(b, 1000, 16*time.Millisecond)
}

func benchmarkEndToEndGet(b *testing.B, parallelism int, batchDelay time.Duration) {
	var serverBatchDelay time.Duration
	if batchDelay > 0 {
		serverBatchDelay = 100 * time.Microsecond
	}
	expectedBody := "Hello world"
	s := &Server{
		Handler: func(ctx *fasthttp.RequestCtx) {
			ctx.SetBodyString(expectedBody)
		},
		Concurrency:   parallelism * runtime.NumCPU(),
		MaxBatchDelay: serverBatchDelay,
	}
	serverStop, ln := newTestServerExt(s)

	var cc []*Client
	for i := 0; i < runtime.NumCPU(); i++ {
		c := newTestClient(ln)
		c.MaxPendingRequests = s.Concurrency
		c.MaxBatchDelay = batchDelay
		cc = append(cc, c)
	}
	var clientIdx uint32

	deadline := time.Now().Add(time.Hour)
	b.SetParallelism(parallelism)
	b.RunParallel(func(pb *testing.PB) {
		n := atomic.AddUint32(&clientIdx, 1)
		c := cc[int(n)%len(cc)]
		req := fasthttp.AcquireRequest()
		resp := fasthttp.AcquireResponse()
		for pb.Next() {
			req.Header.SetHost("foobar")
			req.SetRequestURI("/foo/bar")
			if err := c.DoDeadline(req, resp, deadline); err != nil {
				b.Fatalf("unexpected error: %s", err)
			}
			statusCode := resp.StatusCode()
			if statusCode != fasthttp.StatusOK {
				b.Fatalf("unexpected status code: %d. Expecting %d", statusCode, fasthttp.StatusOK)
			}
			body := resp.Body()
			if string(body) != expectedBody {
				b.Fatalf("unexpected body: %q. Expecting %q", body, expectedBody)
			}
		}
		fasthttp.ReleaseResponse(resp)
		fasthttp.ReleaseRequest(req)
	})

	if err := serverStop(); err != nil {
		b.Fatalf("cannot shutdown server: %s", err)
	}
}
<|endoftext|>


<commit_before>package fasthttp

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"runtime"
	"sync/atomic"
	"testing"
	"time"
)

var defaultClientsCount = runtime.NumCPU()

func BenchmarkServerGet1ReqPerConn(b *testing.B) {
	benchmarkServerGet(b, defaultClientsCount, 1)
}

func BenchmarkServerGet2ReqPerConn(b *testing.B) {
	benchmarkServerGet(b, defaultClientsCount, 2)
}

func BenchmarkServerGet10ReqPerConn(b *testing.B) {
	benchmarkServerGet(b, defaultClientsCount, 10)
}

func BenchmarkServerGet10KReqPerConn(b *testing.B) {
	benchmarkServerGet(b, defaultClientsCount, 10000)
}

func BenchmarkNetHTTPServerGet1ReqPerConn(b *testing.B) {
	benchmarkNetHTTPServerGet(b, defaultClientsCount, 1)
}

func BenchmarkNetHTTPServerGet2ReqPerConn(b *testing.B) {
	benchmarkNetHTTPServerGet(b, defaultClientsCount, 2)
}

func BenchmarkNetHTTPServerGet10ReqPerConn(b *testing.B) {
	benchmarkNetHTTPServerGet(b, defaultClientsCount, 10)
}

func BenchmarkNetHTTPServerGet10000ReqPerConn(b *testing.B) {
	benchmarkNetHTTPServerGet(b, defaultClientsCount, 10000)
}

func BenchmarkServerPost1ReqPerConn(b *testing.B) {
	benchmarkServerPost(b, defaultClientsCount, 1)
}

func BenchmarkServerPost2ReqPerConn(b *testing.B) {
	benchmarkServerPost(b, defaultClientsCount, 2)
}

func BenchmarkServerPost10ReqPerConn(b *testing.B) {
	benchmarkServerPost(b, defaultClientsCount, 10)
}

func BenchmarkServerPost10KReqPerConn(b *testing.B) {
	benchmarkServerPost(b, defaultClientsCount, 10000)
}

func BenchmarkNetHTTPServerPost1ReqPerConn(b *testing.B) {
	benchmarkNetHTTPServerPost(b, defaultClientsCount, 1)
}

func BenchmarkNetHTTPServerPost2ReqPerConn(b *testing.B) {
	benchmarkNetHTTPServerPost(b, defaultClientsCount, 2)
}

func BenchmarkNetHTTPServerPost10ReqPerConn(b *testing.B) {
	benchmarkNetHTTPServerPost(b, defaultClientsCount, 10)
}

func BenchmarkNetHTTPServerPost10KReqPerConn(b *testing.B) {
	benchmarkNetHTTPServerPost(b, defaultClientsCount, 10000)
}

func BenchmarkServerGet1ReqPerConn1KClients(b *testing.B) {
	benchmarkServerGet(b, 1000, 1)
}

func BenchmarkServerGet2ReqPerConn1KClients(b *testing.B) {
	benchmarkServerGet(b, 1000, 2)
}

func BenchmarkServerGet10ReqPerConn1KClients(b *testing.B) {
	benchmarkServerGet(b, 1000, 10)
}

func BenchmarkServerGet10KReqPerConn1KClients(b *testing.B) {
	benchmarkServerGet(b, 1000, 10000)
}

func BenchmarkNetHTTPServerGet1ReqPerConn1KClients(b *testing.B) {
	benchmarkNetHTTPServerGet(b, 1000, 1)
}

func BenchmarkNetHTTPServerGet2ReqPerConn1KClients(b *testing.B) {
	benchmarkNetHTTPServerGet(b, 1000, 2)
}

func BenchmarkNetHTTPServerGet10ReqPerConn1KClients(b *testing.B) {
	benchmarkNetHTTPServerGet(b, 1000, 10)
}

func BenchmarkNetHTTPServerGet10KReqPerConn1KClients(b *testing.B) {
	benchmarkNetHTTPServerGet(b, 1000, 10000)
}

func BenchmarkServerMaxConnsPerIP(b *testing.B) {
	clientsCount := 1000
	requestsPerConn := 10
	ch := make(chan struct{}, b.N)
	responseBody := []byte("123")
	s := &Server{
		Handler: func(ctx *RequestCtx) {
			ctx.Success("foobar", responseBody)
			registerServedRequest(b, ch)
		},
		MaxConnsPerIP: clientsCount * 2,
		Concurrency:   16 * clientsCount,
	}
	req := "GET /foo HTTP/1.1\r\nHost: google.com\r\n\r\n"
	benchmarkServer(b, s, clientsCount, requestsPerConn, req)
	verifyRequestsServed(b, ch)
}

func BenchmarkServerTimeoutError(b *testing.B) {
	clientsCount := 1
	requestsPerConn := 10
	ch := make(chan struct{}, b.N)
	n := uint32(0)
	responseBody := []byte("123")
	s := &Server{
		Handler: func(ctx *RequestCtx) {
			if atomic.AddUint32(&n, 1)&7 == 0 {
				ctx.TimeoutError("xxx")
				go func() {
					ctx.Success("foobar", responseBody)
				}()
			} else {
				ctx.Success("foobar", responseBody)
			}
			registerServedRequest(b, ch)
		},
		Concurrency: 16 * clientsCount,
	}
	req := "GET /foo HTTP/1.1\r\nHost: google.com\r\n\r\n"
	benchmarkServer(b, s, clientsCount, requestsPerConn, req)
	verifyRequestsServed(b, ch)
}

type fakeServerConn struct {
	net.TCPConn
	ln            *fakeListener
	requestsCount int
	pos           int
	closed        uint32
}

func (c *fakeServerConn) Read(b []byte) (int, error) {
	nn := 0
	reqLen := len(c.ln.request)
	for len(b) > 0 {
		if c.requestsCount == 0 {
			if nn == 0 {
				return 0, io.EOF
			}
			return nn, nil
		}
		pos := c.pos % reqLen
		n := copy(b, c.ln.request[pos:])
		b = b[n:]
		nn += n
		c.pos += n
		if n+pos == reqLen {
			c.requestsCount--
		}
	}
	return nn, nil
}

func (c *fakeServerConn) Write(b []byte) (int, error) {
	return len(b), nil
}

var fakeAddr = net.TCPAddr{
	IP:   []byte{1, 2, 3, 4},
	Port: 12345,
}

func (c *fakeServerConn) RemoteAddr() net.Addr {
	return &fakeAddr
}

func (c *fakeServerConn) Close() error {
	if atomic.AddUint32(&c.closed, 1) == 1 {
		c.ln.ch <- c
	}
	return nil
}

func (c *fakeServerConn) SetReadDeadline(t time.Time) error {
	return nil
}

func (c *fakeServerConn) SetWriteDeadline(t time.Time) error {
	return nil
}

type fakeListener struct {
	requestsCount   int
	requestsPerConn int
	request         []byte
	ch              chan *fakeServerConn
	done            chan struct{}
}

func (ln *fakeListener) Accept() (net.Conn, error) {
	if ln.requestsCount == 0 {
		for len(ln.ch) < cap(ln.ch) {
			time.Sleep(10 * time.Millisecond)
		}
		close(ln.done)
		return nil, io.EOF
	}
	requestsCount := ln.requestsPerConn
	if requestsCount > ln.requestsCount {
		requestsCount = ln.requestsCount
	}
	ln.requestsCount -= requestsCount

	c := <-ln.ch
	c.requestsCount = requestsCount
	c.closed = 0
	c.pos = 0

	return c, nil
}

func (ln *fakeListener) Close() error {
	return nil
}

func (ln *fakeListener) Addr() net.Addr {
	return &fakeAddr
}

func newFakeListener(requestsCount, clientsCount, requestsPerConn int, request string) *fakeListener {
	ln := &fakeListener{
		requestsCount:   requestsCount,
		requestsPerConn: requestsPerConn,
		request:         []byte(request),
		ch:              make(chan *fakeServerConn, clientsCount),
		done:            make(chan struct{}),
	}
	for i := 0; i < clientsCount; i++ {
		ln.ch <- &fakeServerConn{
			ln: ln,
		}
	}
	return ln
}

var (
	fakeResponse = []byte("Hello, world!")
	getRequest   = "GET /foobar?baz HTTP/1.1\r\nHost: google.com\r\nUser-Agent: aaa/bbb/ccc/ddd/eee Firefox Chrome MSIE Opera\r\n" +
		"Referer: http://xxx.com/aaa?bbb=ccc\r\nCookie: foo=bar; baz=baraz; aa=aakslsdweriwereowriewroire\r\n\r\n"
	postRequest = fmt.Sprintf("POST /foobar?baz HTTP/1.1\r\nHost: google.com\r\nContent-Type: foo/bar\r\nContent-Length: %d\r\n"+
		"User-Agent: Opera Chrome MSIE Firefox and other/1.2.34\r\nReferer: http://google.com/aaaa/bbb/ccc\r\n"+
		"Cookie: foo=bar; baz=baraz; aa=aakslsdweriwereowriewroire\r\n\r\n%s",
		len(fakeResponse), fakeResponse)
)

func benchmarkServerGet(b *testing.B, clientsCount, requestsPerConn int) {
	ch := make(chan struct{}, b.N)
	s := &Server{
		Handler: func(ctx *RequestCtx) {
			if !ctx.IsGet() {
				b.Fatalf("Unexpected request method: %s", ctx.Method())
			}
			ctx.Success("text/plain", fakeResponse)
			if requestsPerConn == 1 {
				ctx.SetConnectionClose()
			}
			registerServedRequest(b, ch)
		},
		Concurrency: 16 * clientsCount,
	}
	benchmarkServer(b, s, clientsCount, requestsPerConn, getRequest)
	verifyRequestsServed(b, ch)
}

func benchmarkNetHTTPServerGet(b *testing.B, clientsCount, requestsPerConn int) {
	ch := make(chan struct{}, b.N)
	s := &http.Server{
		Handler: http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
			if req.Method != "GET" {
				b.Fatalf("Unexpected request method: %s", req.Method)
			}
			h := w.Header()
			h.Set("Content-Type", "text/plain")
			if requestsPerConn == 1 {
				h.Set("Connection", "close")
			}
			w.Write(fakeResponse)
			registerServedRequest(b, ch)
		}),
	}
	benchmarkServer(b, s, clientsCount, requestsPerConn, getRequest)
	verifyRequestsServed(b, ch)
}

func benchmarkServerPost(b *testing.B, clientsCount, requestsPerConn int) {
	ch := make(chan struct{}, b.N)
	s := &Server{
		Handler: func(ctx *RequestCtx) {
			if !ctx.IsPost() {
				b.Fatalf("Unexpected request method: %s", ctx.Method())
			}
			body := ctx.Request.Body()
			if !bytes.Equal(body, fakeResponse) {
				b.Fatalf("Unexpected body %q. Expected %q", body, fakeResponse)
			}
			ctx.Success("text/plain", body)
			if requestsPerConn == 1 {
				ctx.SetConnectionClose()
			}
			registerServedRequest(b, ch)
		},
		Concurrency: 16 * clientsCount,
	}
	benchmarkServer(b, s, clientsCount, requestsPerConn, postRequest)
	verifyRequestsServed(b, ch)
}

func benchmarkNetHTTPServerPost(b *testing.B, clientsCount, requestsPerConn int) {
	ch := make(chan struct{}, b.N)
	s := &http.Server{
		Handler: http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
			if req.Method != "POST" {
				b.Fatalf("Unexpected request method: %s", req.Method)
			}
			body, err := ioutil.ReadAll(req.Body)
			if err != nil {
				b.Fatalf("Unexpected error: %s", err)
			}
			req.Body.Close()
			if !bytes.Equal(body, fakeResponse) {
				b.Fatalf("Unexpected body %q. Expected %q", body, fakeResponse)
			}
			h := w.Header()
			h.Set("Content-Type", "text/plain")
			if requestsPerConn == 1 {
				h.Set("Connection", "close")
			}
			w.Write(body)
			registerServedRequest(b, ch)
		}),
	}
	benchmarkServer(b, s, clientsCount, requestsPerConn, postRequest)
	verifyRequestsServed(b, ch)
}

func registerServedRequest(b *testing.B, ch chan<- struct{}) {
	select {
	case ch <- struct{}{}:
	default:
		b.Fatalf("More than %d requests served", cap(ch))
	}
}

func verifyRequestsServed(b *testing.B, ch <-chan struct{}) {
	requestsServed := 0
	for len(ch) > 0 {
		<-ch
		requestsServed++
	}
	requestsSent := b.N
	for requestsServed < requestsSent {
		select {
		case <-ch:
			requestsServed++
		case <-time.After(100 * time.Millisecond):
			b.Fatalf("Unexpected number of requests served %d. Expected %d", requestsServed, requestsSent)
		}
	}
}

type realServer interface {
	Serve(ln net.Listener) error
}

func benchmarkServer(b *testing.B, s realServer, clientsCount, requestsPerConn int, request string) {
	ln := newFakeListener(b.N, clientsCount, requestsPerConn, request)
	ch := make(chan struct{})
	go func() {
		s.Serve(ln)
		ch <- struct{}{}
	}()

	<-ln.done

	select {
	case <-ch:
	case <-time.After(10 * time.Second):
		b.Fatalf("Server.Serve() didn't stop")
	}
}
<commit_msg>Consistency fix: BenchmarkNetHTTPServerGet10000ReqPerConn -> BenchmarkNetHTTPServerGet10KReqPerConn<commit_after>package fasthttp

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"runtime"
	"sync/atomic"
	"testing"
	"time"
)

var defaultClientsCount = runtime.NumCPU()

func BenchmarkServerGet1ReqPerConn(b *testing.B) {
	benchmarkServerGet(b, defaultClientsCount, 1)
}

func BenchmarkServerGet2ReqPerConn(b *testing.B) {
	benchmarkServerGet(b, defaultClientsCount, 2)
}

func BenchmarkServerGet10ReqPerConn(b *testing.B) {
	benchmarkServerGet(b, defaultClientsCount, 10)
}

func BenchmarkServerGet10KReqPerConn(b *testing.B) {
	benchmarkServerGet(b, defaultClientsCount, 10000)
}

func BenchmarkNetHTTPServerGet1ReqPerConn(b *testing.B) {
	benchmarkNetHTTPServerGet(b, defaultClientsCount, 1)
}

func BenchmarkNetHTTPServerGet2ReqPerConn(b *testing.B) {
	benchmarkNetHTTPServerGet(b, defaultClientsCount, 2)
}

func BenchmarkNetHTTPServerGet10ReqPerConn(b *testing.B) {
	benchmarkNetHTTPServerGet(b, defaultClientsCount, 10)
}

func BenchmarkNetHTTPServerGet10KReqPerConn(b *testing.B) {
	benchmarkNetHTTPServerGet(b, defaultClientsCount, 10000)
}

func BenchmarkServerPost1ReqPerConn(b *testing.B) {
	benchmarkServerPost(b, defaultClientsCount, 1)
}

func BenchmarkServerPost2ReqPerConn(b *testing.B) {
	benchmarkServerPost(b, defaultClientsCount, 2)
}

func BenchmarkServerPost10ReqPerConn(b *testing.B) {
	benchmarkServerPost(b, defaultClientsCount, 10)
}

func BenchmarkServerPost10KReqPerConn(b *testing.B) {
	benchmarkServerPost(b, defaultClientsCount, 10000)
}

func BenchmarkNetHTTPServerPost1ReqPerConn(b *testing.B) {
	benchmarkNetHTTPServerPost(b, defaultClientsCount, 1)
}

func BenchmarkNetHTTPServerPost2ReqPerConn(b *testing.B) {
	benchmarkNetHTTPServerPost(b, defaultClientsCount, 2)
}

func BenchmarkNetHTTPServerPost10ReqPerConn(b *testing.B) {
	benchmarkNetHTTPServerPost(b, defaultClientsCount, 10)
}

func BenchmarkNetHTTPServerPost10KReqPerConn(b *testing.B) {
	benchmarkNetHTTPServerPost(b, defaultClientsCount, 10000)
}

func BenchmarkServerGet1ReqPerConn1KClients(b *testing.B) {
	benchmarkServerGet(b, 1000, 1)
}

func BenchmarkServerGet2ReqPerConn1KClients(b *testing.B) {
	benchmarkServerGet(b, 1000, 2)
}

func BenchmarkServerGet10ReqPerConn1KClients(b *testing.B) {
	benchmarkServerGet(b, 1000, 10)
}

func BenchmarkServerGet10KReqPerConn1KClients(b *testing.B) {
	benchmarkServerGet(b, 1000, 10000)
}

func BenchmarkNetHTTPServerGet1ReqPerConn1KClients(b *testing.B) {
	benchmarkNetHTTPServerGet(b, 1000, 1)
}

func BenchmarkNetHTTPServerGet2ReqPerConn1KClients(b *testing.B) {
	benchmarkNetHTTPServerGet(b, 1000, 2)
}

func BenchmarkNetHTTPServerGet10ReqPerConn1KClients(b *testing.B) {
	benchmarkNetHTTPServerGet(b, 1000, 10)
}

func BenchmarkNetHTTPServerGet10KReqPerConn1KClients(b *testing.B) {
	benchmarkNetHTTPServerGet(b, 1000, 10000)
}

func BenchmarkServerMaxConnsPerIP(b *testing.B) {
	clientsCount := 1000
	requestsPerConn := 10
	ch := make(chan struct{}, b.N)
	responseBody := []byte("123")
	s := &Server{
		Handler: func(ctx *RequestCtx) {
			ctx.Success("foobar", responseBody)
			registerServedRequest(b, ch)
		},
		MaxConnsPerIP: clientsCount * 2,
		Concurrency:   16 * clientsCount,
	}
	req := "GET /foo HTTP/1.1\r\nHost: google.com\r\n\r\n"
	benchmarkServer(b, s, clientsCount, requestsPerConn, req)
	verifyRequestsServed(b, ch)
}

func BenchmarkServerTimeoutError(b *testing.B) {
	clientsCount := 1
	requestsPerConn := 10
	ch := make(chan struct{}, b.N)
	n := uint32(0)
	responseBody := []byte("123")
	s := &Server{
		Handler: func(ctx *RequestCtx) {
			if atomic.AddUint32(&n, 1)&7 == 0 {
				ctx.TimeoutError("xxx")
				go func() {
					ctx.Success("foobar", responseBody)
				}()
			} else {
				ctx.Success("foobar", responseBody)
			}
			registerServedRequest(b, ch)
		},
		Concurrency: 16 * clientsCount,
	}
	req := "GET /foo HTTP/1.1\r\nHost: google.com\r\n\r\n"
	benchmarkServer(b, s, clientsCount, requestsPerConn, req)
	verifyRequestsServed(b, ch)
}

type fakeServerConn struct {
	net.TCPConn
	ln            *fakeListener
	requestsCount int
	pos           int
	closed        uint32
}

func (c *fakeServerConn) Read(b []byte) (int, error) {
	nn := 0
	reqLen := len(c.ln.request)
	for len(b) > 0 {
		if c.requestsCount == 0 {
			if nn == 0 {
				return 0, io.EOF
			}
			return nn, nil
		}
		pos := c.pos % reqLen
		n := copy(b, c.ln.request[pos:])
		b = b[n:]
		nn += n
		c.pos += n
		if n+pos == reqLen {
			c.requestsCount--
		}
	}
	return nn, nil
}

func (c *fakeServerConn) Write(b []byte) (int, error) {
	return len(b), nil
}

var fakeAddr = net.TCPAddr{
	IP:   []byte{1, 2, 3, 4},
	Port: 12345,
}

func (c *fakeServerConn) RemoteAddr() net.Addr {
	return &fakeAddr
}

func (c *fakeServerConn) Close() error {
	if atomic.AddUint32(&c.closed, 1) == 1 {
		c.ln.ch <- c
	}
	return nil
}

func (c *fakeServerConn) SetReadDeadline(t time.Time) error {
	return nil
}

func (c *fakeServerConn) SetWriteDeadline(t time.Time) error {
	return nil
}

type fakeListener struct {
	requestsCount   int
	requestsPerConn int
	request         []byte
	ch              chan *fakeServerConn
	done            chan struct{}
}

func (ln *fakeListener) Accept() (net.Conn, error) {
	if ln.requestsCount == 0 {
		for len(ln.ch) < cap(ln.ch) {
			time.Sleep(10 * time.Millisecond)
		}
		close(ln.done)
		return nil, io.EOF
	}
	requestsCount := ln.requestsPerConn
	if requestsCount > ln.requestsCount {
		requestsCount = ln.requestsCount
	}
	ln.requestsCount -= requestsCount

	c := <-ln.ch
	c.requestsCount = requestsCount
	c.closed = 0
	c.pos = 0

	return c, nil
}

func (ln *fakeListener) Close() error {
	return nil
}

func (ln *fakeListener) Addr() net.Addr {
	return &fakeAddr
}

func newFakeListener(requestsCount, clientsCount, requestsPerConn int, request string) *fakeListener {
	ln := &fakeListener{
		requestsCount:   requestsCount,
		requestsPerConn: requestsPerConn,
		request:         []byte(request),
		ch:              make(chan *fakeServerConn, clientsCount),
		done:            make(chan struct{}),
	}
	for i := 0; i < clientsCount; i++ {
		ln.ch <- &fakeServerConn{
			ln: ln,
		}
	}
	return ln
}

var (
	fakeResponse = []byte("Hello, world!")
	getRequest   = "GET /foobar?baz HTTP/1.1\r\nHost: google.com\r\nUser-Agent: aaa/bbb/ccc/ddd/eee Firefox Chrome MSIE Opera\r\n" +
		"Referer: http://xxx.com/aaa?bbb=ccc\r\nCookie: foo=bar; baz=baraz; aa=aakslsdweriwereowriewroire\r\n\r\n"
	postRequest = fmt.Sprintf("POST /foobar?baz HTTP/1.1\r\nHost: google.com\r\nContent-Type: foo/bar\r\nContent-Length: %d\r\n"+
		"User-Agent: Opera Chrome MSIE Firefox and other/1.2.34\r\nReferer: http://google.com/aaaa/bbb/ccc\r\n"+
		"Cookie: foo=bar; baz=baraz; aa=aakslsdweriwereowriewroire\r\n\r\n%s",
		len(fakeResponse), fakeResponse)
)

func benchmarkServerGet(b *testing.B, clientsCount, requestsPerConn int) {
	ch := make(chan struct{}, b.N)
	s := &Server{
		Handler: func(ctx *RequestCtx) {
			if !ctx.IsGet() {
				b.Fatalf("Unexpected request method: %s", ctx.Method())
			}
			ctx.Success("text/plain", fakeResponse)
			if requestsPerConn == 1 {
				ctx.SetConnectionClose()
			}
			registerServedRequest(b, ch)
		},
		Concurrency: 16 * clientsCount,
	}
	benchmarkServer(b, s, clientsCount, requestsPerConn, getRequest)
	verifyRequestsServed(b, ch)
}

func benchmarkNetHTTPServerGet(b *testing.B, clientsCount, requestsPerConn int) {
	ch := make(chan struct{}, b.N)
	s := &http.Server{
		Handler: http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
			if req.Method != "GET" {
				b.Fatalf("Unexpected request method: %s", req.Method)
			}
			h := w.Header()
			h.Set("Content-Type", "text/plain")
			if requestsPerConn == 1 {
				h.Set("Connection", "close")
			}
			w.Write(fakeResponse)
			registerServedRequest(b, ch)
		}),
	}
	benchmarkServer(b, s, clientsCount, requestsPerConn, getRequest)
	verifyRequestsServed(b, ch)
}

func benchmarkServerPost(b *testing.B, clientsCount, requestsPerConn int) {
	ch := make(chan struct{}, b.N)
	s := &Server{
		Handler: func(ctx *RequestCtx) {
			if !ctx.IsPost() {
				b.Fatalf("Unexpected request method: %s", ctx.Method())
			}
			body := ctx.Request.Body()
			if !bytes.Equal(body, fakeResponse) {
				b.Fatalf("Unexpected body %q. Expected %q", body, fakeResponse)
			}
			ctx.Success("text/plain", body)
			if requestsPerConn == 1 {
				ctx.SetConnectionClose()
			}
			registerServedRequest(b, ch)
		},
		Concurrency: 16 * clientsCount,
	}
	benchmarkServer(b, s, clientsCount, requestsPerConn, postRequest)
	verifyRequestsServed(b, ch)
}

func benchmarkNetHTTPServerPost(b *testing.B, clientsCount, requestsPerConn int) {
	ch := make(chan struct{}, b.N)
	s := &http.Server{
		Handler: http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
			if req.Method != "POST" {
				b.Fatalf("Unexpected request method: %s", req.Method)
			}
			body, err := ioutil.ReadAll(req.Body)
			if err != nil {
				b.Fatalf("Unexpected error: %s", err)
			}
			req.Body.Close()
			if !bytes.Equal(body, fakeResponse) {
				b.Fatalf("Unexpected body %q. Expected %q", body, fakeResponse)
			}
			h := w.Header()
			h.Set("Content-Type", "text/plain")
			if requestsPerConn == 1 {
				h.Set("Connection", "close")
			}
			w.Write(body)
			registerServedRequest(b, ch)
		}),
	}
	benchmarkServer(b, s, clientsCount, requestsPerConn, postRequest)
	verifyRequestsServed(b, ch)
}

func registerServedRequest(b *testing.B, ch chan<- struct{}) {
	select {
	case ch <- struct{}{}:
	default:
		b.Fatalf("More than %d requests served", cap(ch))
	}
}

func verifyRequestsServed(b *testing.B, ch <-chan struct{}) {
	requestsServed := 0
	for len(ch) > 0 {
		<-ch
		requestsServed++
	}
	requestsSent := b.N
	for requestsServed < requestsSent {
		select {
		case <-ch:
			requestsServed++
		case <-time.After(100 * time.Millisecond):
			b.Fatalf("Unexpected number of requests served %d. Expected %d", requestsServed, requestsSent)
		}
	}
}

type realServer interface {
	Serve(ln net.Listener) error
}

func benchmarkServer(b *testing.B, s realServer, clientsCount, requestsPerConn int, request string) {
	ln := newFakeListener(b.N, clientsCount, requestsPerConn, request)
	ch := make(chan struct{})
	go func() {
		s.Serve(ln)
		ch <- struct{}{}
	}()

	<-ln.done

	select {
	case <-ch:
	case <-time.After(10 * time.Second):
		b.Fatalf("Server.Serve() didn't stop")
	}
}
<|endoftext|>


<commit_before>package services

import (
    "encoding/json"
    "strconv"
    "strings"
)

// Bitbucket

type BBActor struct {
    Username     string
    Display_name string
    Uuid         string
    Links        string
}

type BBRepository struct {
    Name       string
    Full_name  string
    Uuid       string
    Links      BBLinks
    Scm        string
    Is_private bool
}

type BBAuthor struct {
    User User
    Raw  string
}

type BBLink struct {
    Href string
}

type BBLinks struct {
    Html BBLink
    Diff BBLink
    Self BBLink
}

type BBCommits struct {
    Message string
    Hash    string
    Type    string
    Date    string
    Author  BBAuthor
}

type BBNew struct {
    Type    string
    Name    string
    Target  BBCommits
    Parents BBCommits
}

type BBChanges struct {
    Commits []BBCommits
    New     BBNew
    Old     BBNew
    Created bool
    Forced  bool
    Closed  bool
}

type BBPush struct {
    Changes []BBChanges
}

type BBContent struct {
    Raw    string
    Markup string
    Html   string
}

type BBInline struct {
    To   int
    From int
    Path string
}

type BBParent struct {
    Id int
}

type BBComment struct {
    Id         int
    Parent     BBParent
    Content    BBContent
    Inline     BBInline
    Created_on string
    Updated_on string
    Links      BBLinks
}

type BBBranch struct {
    Name string
}

type BBSource struct {
    Branch     BBBranch
    Commit     BBCommits
    Repository BBRepository
}

type BBPullrequest struct {
    Id                  int
    Title               string
    Description         string
    State               string
    Author              string
    Source              BBSource
    Destination         BBSource
    Merge_commit        BBCommits
    Participants        []BBActor
    Reviewers           []BBActor
    Close_source_branch bool
    Closed_by           BBActor
    Reason              string
    Created_on          string
    Updated_on          string
    Links               BBLinks
}

type BBApproval struct {
    Date string
    User BBActor
}

type BBPayload struct {
    Repository  BBRepository
    Push        BBPush
    Actor       BBActor
    Fork        BBRepository
    Comment     BBComment
    Commit      BBCommits
    Pullrequest BBPullrequest
    Approval    BBApproval
}

// Return bitbucket data.
func getBitbucketData(decoder *json.Decoder, eType string) (string, string) {
    var bEvent BBPayload
    decoder.Decode(&bEvent)
    action := strings.Split(eType, ":")
    event, desc := "", ""
    who := bEvent.Actor.Username + " (" + bEvent.Actor.Display_name + ")"
    if action[0] == "repo" {
        switch action[1] {
        case "push":
            event = bEvent.Repository.Name + ": Push Event"
            if len(bEvent.Push.Changes) > 0 {
                change := bEvent.Push.Changes[0]
                desc = "Who: " + who + "\nCommits:\n"
                for i := 0; i < len(change.Commits); i++ {
                    desc += "\n- " + change.Commits[i].Message +
                        " (" + change.Commits[i].Hash + ")" +
                        "\n * " + change.Commits[i].Author.Raw
                }
            }
        case "fork":
            event = bEvent.Repository.Name + ": Fork Event"
            desc = "\n" + who + " Forked."
        case "commit_comment_created":
            event = bEvent.Repository.Name + ": Commit Comment Created"
            desc = who + " commented on " + bEvent.Commit.Hash
            desc += "\n Comment: " + bEvent.Comment.Content.Markup
            desc += "\n File: " + bEvent.Comment.Inline.Path
        }
    } else if action[0] == "pullrequest" {
        desc = "Description: " + bEvent.Pullrequest.Description
        desc += "\n From Repository: " +
            bEvent.Pullrequest.Source.Repository.Name
        switch action[1] {
        case "created":
            desc += "\n Created by: " + who
        case "updated":
            desc += "\n Updated by: " + who
        case "approved":
            desc += "\n Approved by: " + bEvent.Approval.User.Username
        case "unapproved":
            desc += "\n Unapproved by: " + bEvent.Approval.User.Username
        case "fulfilled":
            desc += "\n Merged by: " + who
            desc += "\n **Merged**"
        case "rejected":
            desc += "\n Rejected by: " + who
            desc += "\n **Rejected** because " + bEvent.Pullrequest.Reason
        case "comment_created":
            desc += "\n Commented by: " + who
            desc += "\n Comment: " + bEvent.Comment.Content.Markup
            desc += "\n File: " + bEvent.Comment.Inline.Path + " at line " +
                strconv.Itoa(bEvent.Comment.Inline.To)
        case "comment_updated":
            desc += "\n Comment updated by: " + who
            desc += "\n File: " + bEvent.Comment.Inline.Path + " at line " +
                strconv.Itoa(bEvent.Comment.Inline.To)
        case "comment_deleted":
            desc += "\n Comment deleted by: " + who
            desc += "\n File: " + bEvent.Comment.Inline.Path + " at line " +
                strconv.Itoa(bEvent.Comment.Inline.To)
        }
        event = bEvent.Repository.Name + ": Pull request " + action[1] + ": " +
            bEvent.Pullrequest.Title + "(" + bEvent.Pullrequest.State + ")"
    }
    return event, desc
}
<commit_msg>comment fix<commit_after>package services

import (
    "encoding/json"
    "strconv"
    "strings"
)

// Bitbucket

type BBActor struct {
    Username     string
    Display_name string
    Uuid         string
    Links        string
}

type BBRepository struct {
    Name       string
    Full_name  string
    Uuid       string
    Links      BBLinks
    Scm        string
    Is_private bool
}

type BBAuthor struct {
    User User
    Raw  string
}

type BBLink struct {
    Href string
}

type BBLinks struct {
    Html BBLink
    Diff BBLink
    Self BBLink
}

type BBCommits struct {
    Message string
    Hash    string
    Type    string
    Date    string
    Author  BBAuthor
}

type BBNew struct {
    Type    string
    Name    string
    Target  BBCommits
    Parents BBCommits
}

type BBChanges struct {
    Commits []BBCommits
    New     BBNew
    Old     BBNew
    Created bool
    Forced  bool
    Closed  bool
}

type BBPush struct {
    Changes []BBChanges
}

type BBContent struct {
    Raw    string
    Markup string
    Html   string
}

type BBInline struct {
    To   int
    From int
    Path string
}

type BBParent struct {
    Id int
}

type BBComment struct {
    Id         int
    Parent     BBParent
    Content    BBContent
    Inline     BBInline
    Created_on string
    Updated_on string
    Links      BBLinks
}

type BBBranch struct {
    Name string
}

type BBSource struct {
    Branch     BBBranch
    Commit     BBCommits
    Repository BBRepository
}

type BBPullrequest struct {
    Id                  int
    Title               string
    Description         string
    State               string
    Author              string
    Source              BBSource
    Destination         BBSource
    Merge_commit        BBCommits
    Participants        []BBActor
    Reviewers           []BBActor
    Close_source_branch bool
    Closed_by           BBActor
    Reason              string
    Created_on          string
    Updated_on          string
    Links               BBLinks
}

type BBApproval struct {
    Date string
    User BBActor
}

type BBPayload struct {
    Repository  BBRepository
    Push        BBPush
    Actor       BBActor
    Fork        BBRepository
    Comment     BBComment
    Commit      BBCommits
    Pullrequest BBPullrequest
    Approval    BBApproval
}

// Return bitbucket data.
func getBitbucketData(decoder *json.Decoder, eType string) (string, string) {
    var bEvent BBPayload
    decoder.Decode(&bEvent)
    action := strings.Split(eType, ":")
    event, desc := "", ""
    who := bEvent.Actor.Username + " (" + bEvent.Actor.Display_name + ")"
    if action[0] == "repo" {
        switch action[1] {
        case "push":
            event = bEvent.Repository.Name + ": Push Event"
            if len(bEvent.Push.Changes) > 0 {
                change := bEvent.Push.Changes[0]
                desc = "Who: " + who + "\nCommits:\n"
                for i := 0; i < len(change.Commits); i++ {
                    desc += "\n- " + change.Commits[i].Message +
                        " (" + change.Commits[i].Hash + ")" +
                        "\n * " + change.Commits[i].Author.Raw
                }
            }
        case "fork":
            event = bEvent.Repository.Name + ": Fork Event"
            desc = "\n" + who + " Forked."
        case "commit_comment_created":
            event = bEvent.Repository.Name + ": Commit Comment Created"
            desc = who + " commented on " + bEvent.Commit.Hash
            desc += "\n Comment: " + bEvent.Comment.Content.Raw
            desc += "\n File: " + bEvent.Comment.Inline.Path
        }
    } else if action[0] == "pullrequest" {
        desc = "Description: " + bEvent.Pullrequest.Description
        desc += "\n From Repository: " +
            bEvent.Pullrequest.Source.Repository.Name
        switch action[1] {
        case "created":
            desc += "\n Created by: " + who
        case "updated":
            desc += "\n Updated by: " + who
        case "approved":
            desc += "\n Approved by: " + bEvent.Approval.User.Username
        case "unapproved":
            desc += "\n Unapproved by: " + bEvent.Approval.User.Username
        case "fulfilled":
            desc += "\n Merged by: " + who
            desc += "\n **Merged**"
        case "rejected":
            desc += "\n Rejected by: " + who
            desc += "\n **Rejected** because " + bEvent.Pullrequest.Reason
        case "comment_created":
            desc += "\n Commented by: " + who
            desc += "\n Comment: " + bEvent.Comment.Content.Raw
            desc += "\n File: " + bEvent.Comment.Inline.Path + " at line " +
                strconv.Itoa(bEvent.Comment.Inline.To)
        case "comment_updated":
            desc += "\n Comment updated by: " + who
            desc += "\n File: " + bEvent.Comment.Inline.Path + " at line " +
                strconv.Itoa(bEvent.Comment.Inline.To)
        case "comment_deleted":
            desc += "\n Comment deleted by: " + who
            desc += "\n File: " + bEvent.Comment.Inline.Path + " at line " +
                strconv.Itoa(bEvent.Comment.Inline.To)
        }
        event = bEvent.Repository.Name + ": Pull request " + action[1] + ": " +
            bEvent.Pullrequest.Title + "(" + bEvent.Pullrequest.State + ")"
    }
    return event, desc
}
<|endoftext|>


<commit_before>package session

import (
	"github.com/gorilla/sessions"
)

type FilesystemStore interface {
	Store
}

// Keys are defined in pairs to allow key rotation, but the common case is to set a single
// authentication key and optionally an encryption key.
//
// The first key in a pair is used for authentication and the second for encryption. The
// encryption key can be set to nil or omitted in the last pair, but the authentication key
// is required in all pairs.
//
// It is recommended to use an authentication key with 32 or 64 bytes. The encryption key,
// if set, must be either 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256 modes.
func NewFilesystemStore(keyPairs ...[]byte) CookieStore {
	return &filesystemStore{sessions.NewCookieStore(keyPairs...)}
}

type filesystemStore struct {
	*sessions.CookieStore
}

func (c *filesystemStore) Options(options Options) {
	c.FilesystemStore.Options = &sessions.Options{
		Path:     options.Path,
		Domain:   options.Domain,
		MaxAge:   options.MaxAge,
		Secure:   options.Secure,
		HttpOnly: options.HttpOnly,
	}
}
<commit_msg>fixing the filesystem store to actually work<commit_after>package session

import (
	"github.com/gorilla/sessions"
)

type FilesystemStore interface {
	Store
}

// NewFilesystemStore returns a new FilesystemStore.
//
// The path argument is the directory where sessions will be saved. If empty
// it will use os.TempDir().
//
// See NewCookieStore() for a description of the other parameters.
func NewFilesystemStore(path string, keyPairs ...[]byte) FilesystemStore {
	return &filesystemStore{sessions.NewFilesystemStore(path, keyPairs...)}
}

type filesystemStore struct {
	*sessions.FilesystemStore
}

func (c *filesystemStore) Options(options Options) {
	c.FilesystemStore.Options = &sessions.Options{
		Path:     options.Path,
		Domain:   options.Domain,
		MaxAge:   options.MaxAge,
		Secure:   options.Secure,
		HttpOnly: options.HttpOnly,
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"

	"github.com/flant/dapp/pkg/deploy/secret"

	"k8s.io/kubernetes/pkg/util/file"
)

func SecretsRegenerate(newManager, oldManager secret.Manager, projectPath string, secretValuesPaths ...string) error {
	var secretFilesPaths []string
	regeneratedFilesData := map[string][]byte{}
	secretFilesData := map[string][]byte{}
	secretValuesFilesData := map[string][]byte{}

	helmChartPath := filepath.Join(projectPath, ".helm")
	exist, err := file.FileExists(helmChartPath)
	if err != nil {
		return err
	}

	if exist {
		defaultSecretValuesPath := filepath.Join(helmChartPath, "secret-values.yaml")
		exist, err := file.FileExists(defaultSecretValuesPath)
		if err != nil {
			return err
		}

		if exist {
			secretValuesPaths = append(secretValuesPaths, defaultSecretValuesPath)
		}

		secretDirectory := filepath.Join(helmChartPath, "secret")
		err = filepath.Walk(secretDirectory,
			func(path string, info os.FileInfo, err error) error {
				if err != nil {
					return err
				}

				fileInfo, err := os.Stat(path)
				if err != nil {
					return err
				}

				if !fileInfo.IsDir() {
					secretFilesPaths = append(secretFilesPaths, path)
				}

				return nil
			})
		if err != nil {
			return err
		}
	}

	pwd, err := os.Getwd()
	if err != nil {
		return err
	}

	secretFilesData, err = readFilesToDecode(secretFilesPaths, pwd)
	if err != nil {
		return err
	}

	secretValuesFilesData, err = readFilesToDecode(secretValuesPaths, pwd)
	if err != nil {
		return err
	}

	if err := regenerateSecrets(secretFilesData, regeneratedFilesData, oldManager.Extract, newManager.Generate); err != nil {
		return err
	}

	if err := regenerateSecrets(secretValuesFilesData, regeneratedFilesData, oldManager.ExtractYamlData, newManager.GenerateYamlData); err != nil {
		return err
	}

	for filePath, fileData := range regeneratedFilesData {
		fmt.Printf("save file '%s'\n", filePath)

		fileData = append(bytes.TrimSpace(fileData), []byte("\n")...)
		if err := ioutil.WriteFile(filePath, fileData, 0644); err != nil {
			return err
		}
	}

	return nil
}

func regenerateSecrets(filesData, regeneratedFilesData map[string][]byte, decodeFunc, encodeFunc func([]byte) ([]byte, error)) error {
	for filePath, fileData := range filesData {
		fmt.Printf("regenerate file '%s' data\n", filePath)

		data, err := decodeFunc(fileData)
		if err != nil {
			return fmt.Errorf("check old encryption key and file data: %s", err)
		}

		resultData, err := encodeFunc(data)
		if err != nil {
			return err
		}

		regeneratedFilesData[filePath] = resultData
	}

	return nil
}

func readFilesToDecode(filePaths []string, pwd string) (map[string][]byte, error) {
	filesData := map[string][]byte{}
	for _, filePath := range filePaths {
		fileData, err := ioutil.ReadFile(filePath)
		if err != nil {
			return nil, err
		}

		if filepath.IsAbs(filePath) {
			filePath, err = filepath.Rel(pwd, filePath)
			if err != nil {
				return nil, err
			}
		}

		filesData[filePath] = bytes.TrimSpace(fileData)
	}

	return filesData, nil
}
<commit_msg>Fix command `secret_regenerate` ... .helm/secret: no such file or directory`<commit_after>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"

	"github.com/flant/dapp/pkg/deploy/secret"

	"k8s.io/kubernetes/pkg/util/file"
)

func SecretsRegenerate(newManager, oldManager secret.Manager, projectPath string, secretValuesPaths ...string) error {
	var secretFilesPaths []string
	regeneratedFilesData := map[string][]byte{}
	secretFilesData := map[string][]byte{}
	secretValuesFilesData := map[string][]byte{}

	helmChartPath := filepath.Join(projectPath, ".helm")
	isHelmChartDirExist, err := file.FileExists(helmChartPath)
	if err != nil {
		return err
	}

	if isHelmChartDirExist {
		defaultSecretValuesPath := filepath.Join(helmChartPath, "secret-values.yaml")
		isDefaultSecretValuesExist, err := file.FileExists(defaultSecretValuesPath)
		if err != nil {
			return err
		}

		if isDefaultSecretValuesExist {
			secretValuesPaths = append(secretValuesPaths, defaultSecretValuesPath)
		}

		secretDirectory := filepath.Join(helmChartPath, "secret")
		isSecretDirectoryExist, err := file.FileExists(defaultSecretValuesPath)
		if err != nil {
			return err
		}

		if isSecretDirectoryExist {
			err = filepath.Walk(secretDirectory,
				func(path string, info os.FileInfo, err error) error {
					if err != nil {
						return err
					}

					fileInfo, err := os.Stat(path)
					if err != nil {
						return err
					}

					if !fileInfo.IsDir() {
						secretFilesPaths = append(secretFilesPaths, path)
					}

					return nil
				})
			if err != nil {
				return err
			}
		}
	}

	pwd, err := os.Getwd()
	if err != nil {
		return err
	}

	secretFilesData, err = readFilesToDecode(secretFilesPaths, pwd)
	if err != nil {
		return err
	}

	secretValuesFilesData, err = readFilesToDecode(secretValuesPaths, pwd)
	if err != nil {
		return err
	}

	if err := regenerateSecrets(secretFilesData, regeneratedFilesData, oldManager.Extract, newManager.Generate); err != nil {
		return err
	}

	if err := regenerateSecrets(secretValuesFilesData, regeneratedFilesData, oldManager.ExtractYamlData, newManager.GenerateYamlData); err != nil {
		return err
	}

	for filePath, fileData := range regeneratedFilesData {
		fmt.Printf("save file '%s'\n", filePath)

		fileData = append(bytes.TrimSpace(fileData), []byte("\n")...)
		if err := ioutil.WriteFile(filePath, fileData, 0644); err != nil {
			return err
		}
	}

	return nil
}

func regenerateSecrets(filesData, regeneratedFilesData map[string][]byte, decodeFunc, encodeFunc func([]byte) ([]byte, error)) error {
	for filePath, fileData := range filesData {
		fmt.Printf("regenerate file '%s' data\n", filePath)

		data, err := decodeFunc(fileData)
		if err != nil {
			return fmt.Errorf("check old encryption key and file data: %s", err)
		}

		resultData, err := encodeFunc(data)
		if err != nil {
			return err
		}

		regeneratedFilesData[filePath] = resultData
	}

	return nil
}

func readFilesToDecode(filePaths []string, pwd string) (map[string][]byte, error) {
	filesData := map[string][]byte{}
	for _, filePath := range filePaths {
		fileData, err := ioutil.ReadFile(filePath)
		if err != nil {
			return nil, err
		}

		if filepath.IsAbs(filePath) {
			filePath, err = filepath.Rel(pwd, filePath)
			if err != nil {
				return nil, err
			}
		}

		filesData[filePath] = bytes.TrimSpace(fileData)
	}

	return filesData, nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"strings"
	"text/template"

	"github.com/sbinet/go-clang"
)

type Struct struct {
	Name           string
	CName          string
	CNameIsTypeDef bool
	Receiver       string
	Comment        string
	ImportUnsafe   bool

	Methods []string
}

type FuncDef struct {
	Comment    string
	Name       string
	GType      string
	FuncName   string
	ReturnType string

	ReturnString string
}

var returnPrimitive = "return %s(%s)"
var returnComplex = "return %s{%s}"

var templateGenerateReturnSlice = template.Must(template.New("go-clang-generate-slice").Parse(`
	{{$.Comment}}
	func ({{$.Name}} {{$.GType}}) {{$.FuncName}}() {{$.ReturnType}} {
 		s := {{$.ReturnType}}{}
 		length := C.sizeof(%s[0]) / C.sizeof(%s[0][0])
		for is:=0;is < length; is++ {
     		s = append(s, %s{%s[is]})
		}
		return s
	}
`))

var templateGenerateGetter = template.Must(template.New("go-clang-generate-getter").Parse(`
	{{$.Comment}}
	func ({{$.Name}} {{$.GType}}) {{$.FuncName}}() {{$.ReturnType}} {
		{{$.ReturnString}}
	}
`))

func handleStructCursor(cursor clang.Cursor, cname string, cnameIsTypeDef bool) *Struct {
	s := handleVoidStructCursor(cursor, cname, cnameIsTypeDef)
	gType := trimClangPrefix(cname)

	cursor.Visit(func(cursor, parent clang.Cursor) clang.ChildVisitResult {

		switch cursor.Kind() {
		case clang.CK_FieldDecl:
			conv := getTypeConversion(cursor.Type())

			if conv.FunctionPointer {
				return clang.CVR_Continue
			}

			receiver := strings.ToLower(string(gType[0]))

			f := FuncDef{
				Comment:    cleanDoxygenComment(cursor.RawCommentText()),
				Name:       receiver,
				GType:      gType,
				FuncName:   upperFirstCharacter(cursor.DisplayName()),
				ReturnType: conv.GType,
			}

			callToC := receiver + ".c." + cursor.DisplayName()

			var method string

			if conv.Pointer == 2 {
				elemType := "&" + f.ReturnType
				f.ReturnType = "[]*" + f.ReturnType

				var b bytes.Buffer
				if err := templateGenerateReturnSlice.Execute(&b, f); err != nil {
					fmt.Println(err.Error())
				}

				method = fmt.Sprintf(b.String(), callToC, callToC, elemType, callToC)
			} else if conv.Pointer < 2 {
				if conv.Pointer == 1 {
					f.ReturnType = "*" + f.ReturnType
				}

				if f.ReturnType == "*void" {
					f.ReturnType = GoPointer
					s.ImportUnsafe = true
				}

				if conv.IsArray {
					f.ReturnType = "[]" + f.ReturnType
				}

				if conv.Primitive {
					f.ReturnString = fmt.Sprintf(returnPrimitive, strings.Replace(f.ReturnType, "*", "&", -1), callToC)
				} else {
					f.ReturnString = fmt.Sprintf(returnComplex, strings.Replace(f.ReturnType, "*", "&", -1), callToC)
				}

				var b bytes.Buffer
				if err := templateGenerateGetter.Execute(&b, f); err != nil {
					fmt.Println(err.Error())
				}

				method = b.String()
			} // fuck you, three levels of pointers or more

			s.Methods = append(s.Methods, method)
		}

		return clang.CVR_Continue
	})

	return s
}

const (
	GoInt8      = "int8"
	GoUInt8     = "uint8"
	GoInt16     = "int16"
	GoUInt16    = "uint16"
	GoInt32     = "int32"
	GoUInt32    = "uint32"
	GoInt64     = "int64"
	GoUInt64    = "uint64"
	GoFloat32   = "float32"
	GoFloat64   = "float64"
	GoBool      = "bool"
	GoInterface = "interface"
	GoPointer   = "unsafe.Pointer"
)

type Conversion struct {
	GType           string
	Pointer         int
	Primitive       bool
	IsArray         bool
	FunctionPointer bool
}

func getTypeConversion(cType clang.Type) Conversion {
	conv := Conversion{
		Pointer:   0,
		Primitive: true,
		IsArray:   false,
	}

	switch cType.Kind() {
	case clang.TK_Char_S:
		conv.GType = string(GoInt8)
	case clang.TK_Char_U:
		conv.GType = GoUInt8
	case clang.TK_Int, clang.TK_Short:
		conv.GType = GoInt16
	case clang.TK_UInt, clang.TK_UShort:
		conv.GType = GoUInt16
	case clang.TK_Long:
		conv.GType = GoInt32
	case clang.TK_ULong:
		conv.GType = GoUInt32
	case clang.TK_LongLong:
		conv.GType = GoInt64
	case clang.TK_ULongLong:
		conv.GType = GoUInt64
	case clang.TK_Float:
		conv.GType = GoFloat32
	case clang.TK_Double:
		conv.GType = GoFloat64
	case clang.TK_Bool:
		conv.GType = GoBool
	case clang.TK_Void:
		conv.GType = "void"
	case clang.TK_ConstantArray:
		subConv := getTypeConversion(cType.ArrayElementType())
		conv.GType = subConv.GType
		conv.Pointer += subConv.Pointer
		conv.IsArray = true
	case clang.TK_Typedef:
		typeStr := cType.TypeSpelling()
		if typeStr == "CXString" {
			typeStr = "cxstring"
		} else {
			typeStr = trimClangPrefix(cType.TypeSpelling())
		}
		conv.GType = typeStr
		conv.Primitive = false
	case clang.TK_Pointer:
		conv.Pointer++

		if cType.PointeeType().CanonicalType().Kind() == clang.TK_FunctionProto {
			conv.FunctionPointer = true
		}

		subConv := getTypeConversion(cType.PointeeType().Declaration().Type()) // ComplexTypes
		if subConv.GType == "" {                                               // datatypes
			subConv = getTypeConversion(cType.PointeeType())
		} else {
			conv.Primitive = false
		}
		conv.GType = subConv.GType
		conv.Pointer += subConv.Pointer
	case clang.TK_Unexposed: // there is a bug in clang for enums the kind is set to unexposed dunno why, bug persists since 2013
		enumStr := cType.CanonicalType().TypeSpelling()
		if strings.Contains(enumStr, "enum") {
			enumStr = trimClangPrefix(cType.CanonicalType().Declaration().DisplayName())
		} else {
			enumStr = ""
		}
		conv.GType = enumStr
	}

	return conv
}

func handleVoidStructCursor(cursor clang.Cursor, cname string, cnameIsTypeDef bool) *Struct {
	s := Struct{
		CName:          cname,
		CNameIsTypeDef: cnameIsTypeDef,
		Comment:        cleanDoxygenComment(cursor.RawCommentText()),
	}

	s.Name = trimClangPrefix(s.CName)
	s.Receiver = receiverName(s.Name)

	return &s
}

var templateGenerateStruct = template.Must(template.New("go-clang-generate-struct").Parse(`package phoenix
// #include "go-clang.h"
import "C"
%s

{{$.Comment}}
type {{$.Name}} struct {
	c C.{{if not $.CNameIsTypeDef}}struct_{{end}}{{$.CName}}
}
{{range $i, $m := .Methods}}
{{$m}}
{{end}}
`))

func generateStruct(s *Struct) error {
	var b bytes.Buffer
	if err := templateGenerateStruct.Execute(&b, s); err != nil {
		return err
	}

	file := b.String()

	if s.ImportUnsafe {
		file = fmt.Sprintf(file, "import \"unsafe\"")
	} else {
		file = fmt.Sprintf(file, "")
	}
	// TODO remove "_" from names for files here?

	return ioutil.WriteFile(strings.ToLower(s.Name)+"_gen.go", []byte(file), 0600)
}
<commit_msg>Disable member getter generation since it does not produce compileable code just yet<commit_after>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"strings"
	"text/template"

	"github.com/sbinet/go-clang"
)

type Struct struct {
	Name           string
	CName          string
	CNameIsTypeDef bool
	Receiver       string
	Comment        string
	ImportUnsafe   bool

	Methods []string
}

type FuncDef struct {
	Comment    string
	Name       string
	GType      string
	FuncName   string
	ReturnType string

	ReturnString string
}

var returnPrimitive = "return %s(%s)"
var returnComplex = "return %s{%s}"

var templateGenerateReturnSlice = template.Must(template.New("go-clang-generate-slice").Parse(`
	{{$.Comment}}
	func ({{$.Name}} {{$.GType}}) {{$.FuncName}}() {{$.ReturnType}} {
 		s := {{$.ReturnType}}{}
 		length := C.sizeof(%s[0]) / C.sizeof(%s[0][0])
		for is:=0;is < length; is++ {
     		s = append(s, %s{%s[is]})
		}
		return s
	}
`))

var templateGenerateGetter = template.Must(template.New("go-clang-generate-getter").Parse(`
	{{$.Comment}}
	func ({{$.Name}} {{$.GType}}) {{$.FuncName}}() {{$.ReturnType}} {
		{{$.ReturnString}}
	}
`))

func handleStructCursor(cursor clang.Cursor, cname string, cnameIsTypeDef bool) *Struct {
	s := handleVoidStructCursor(cursor, cname, cnameIsTypeDef)

	if true == false {
		gType := trimClangPrefix(cname)

		cursor.Visit(func(cursor, parent clang.Cursor) clang.ChildVisitResult {

			switch cursor.Kind() {
			case clang.CK_FieldDecl:
				conv := getTypeConversion(cursor.Type())

				if conv.FunctionPointer {
					return clang.CVR_Continue
				}

				receiver := strings.ToLower(string(gType[0]))

				f := FuncDef{
					Comment:    cleanDoxygenComment(cursor.RawCommentText()),
					Name:       receiver,
					GType:      gType,
					FuncName:   upperFirstCharacter(cursor.DisplayName()),
					ReturnType: conv.GType,
				}

				callToC := receiver + ".c." + cursor.DisplayName()

				var method string

				if conv.Pointer == 2 {
					elemType := "&" + f.ReturnType
					f.ReturnType = "[]*" + f.ReturnType

					var b bytes.Buffer
					if err := templateGenerateReturnSlice.Execute(&b, f); err != nil {
						fmt.Println(err.Error())
					}

					method = fmt.Sprintf(b.String(), callToC, callToC, elemType, callToC)
				} else if conv.Pointer < 2 {
					if conv.Pointer == 1 {
						f.ReturnType = "*" + f.ReturnType
					}

					if f.ReturnType == "*void" {
						f.ReturnType = GoPointer
						s.ImportUnsafe = true
					}

					if conv.IsArray {
						f.ReturnType = "[]" + f.ReturnType
					}

					if conv.Primitive {
						f.ReturnString = fmt.Sprintf(returnPrimitive, strings.Replace(f.ReturnType, "*", "&", -1), callToC)
					} else {
						f.ReturnString = fmt.Sprintf(returnComplex, strings.Replace(f.ReturnType, "*", "&", -1), callToC)
					}

					var b bytes.Buffer
					if err := templateGenerateGetter.Execute(&b, f); err != nil {
						fmt.Println(err.Error())
					}

					method = b.String()
				} // fuck you, three levels of pointers or more

				s.Methods = append(s.Methods, method)
			}

			return clang.CVR_Continue
		})
	}

	return s
}

const (
	GoInt8      = "int8"
	GoUInt8     = "uint8"
	GoInt16     = "int16"
	GoUInt16    = "uint16"
	GoInt32     = "int32"
	GoUInt32    = "uint32"
	GoInt64     = "int64"
	GoUInt64    = "uint64"
	GoFloat32   = "float32"
	GoFloat64   = "float64"
	GoBool      = "bool"
	GoInterface = "interface"
	GoPointer   = "unsafe.Pointer"
)

type Conversion struct {
	GType           string
	Pointer         int
	Primitive       bool
	IsArray         bool
	FunctionPointer bool
}

func getTypeConversion(cType clang.Type) Conversion {
	conv := Conversion{
		Pointer:   0,
		Primitive: true,
		IsArray:   false,
	}

	switch cType.Kind() {
	case clang.TK_Char_S:
		conv.GType = string(GoInt8)
	case clang.TK_Char_U:
		conv.GType = GoUInt8
	case clang.TK_Int, clang.TK_Short:
		conv.GType = GoInt16
	case clang.TK_UInt, clang.TK_UShort:
		conv.GType = GoUInt16
	case clang.TK_Long:
		conv.GType = GoInt32
	case clang.TK_ULong:
		conv.GType = GoUInt32
	case clang.TK_LongLong:
		conv.GType = GoInt64
	case clang.TK_ULongLong:
		conv.GType = GoUInt64
	case clang.TK_Float:
		conv.GType = GoFloat32
	case clang.TK_Double:
		conv.GType = GoFloat64
	case clang.TK_Bool:
		conv.GType = GoBool
	case clang.TK_Void:
		conv.GType = "void"
	case clang.TK_ConstantArray:
		subConv := getTypeConversion(cType.ArrayElementType())
		conv.GType = subConv.GType
		conv.Pointer += subConv.Pointer
		conv.IsArray = true
	case clang.TK_Typedef:
		typeStr := cType.TypeSpelling()
		if typeStr == "CXString" {
			typeStr = "cxstring"
		} else {
			typeStr = trimClangPrefix(cType.TypeSpelling())
		}
		conv.GType = typeStr
		conv.Primitive = false
	case clang.TK_Pointer:
		conv.Pointer++

		if cType.PointeeType().CanonicalType().Kind() == clang.TK_FunctionProto {
			conv.FunctionPointer = true
		}

		subConv := getTypeConversion(cType.PointeeType().Declaration().Type()) // ComplexTypes
		if subConv.GType == "" {                                               // datatypes
			subConv = getTypeConversion(cType.PointeeType())
		} else {
			conv.Primitive = false
		}
		conv.GType = subConv.GType
		conv.Pointer += subConv.Pointer
	case clang.TK_Unexposed: // there is a bug in clang for enums the kind is set to unexposed dunno why, bug persists since 2013
		enumStr := cType.CanonicalType().TypeSpelling()
		if strings.Contains(enumStr, "enum") {
			enumStr = trimClangPrefix(cType.CanonicalType().Declaration().DisplayName())
		} else {
			enumStr = ""
		}
		conv.GType = enumStr
	}

	return conv
}

func handleVoidStructCursor(cursor clang.Cursor, cname string, cnameIsTypeDef bool) *Struct {
	s := Struct{
		CName:          cname,
		CNameIsTypeDef: cnameIsTypeDef,
		Comment:        cleanDoxygenComment(cursor.RawCommentText()),
	}

	s.Name = trimClangPrefix(s.CName)
	s.Receiver = receiverName(s.Name)

	return &s
}

var templateGenerateStruct = template.Must(template.New("go-clang-generate-struct").Parse(`package phoenix
// #include "go-clang.h"
import "C"
%s

{{$.Comment}}
type {{$.Name}} struct {
	c C.{{if not $.CNameIsTypeDef}}struct_{{end}}{{$.CName}}
}
{{range $i, $m := .Methods}}
{{$m}}
{{end}}
`))

func generateStruct(s *Struct) error {
	var b bytes.Buffer
	if err := templateGenerateStruct.Execute(&b, s); err != nil {
		return err
	}

	file := b.String()

	if s.ImportUnsafe {
		file = fmt.Sprintf(file, "import \"unsafe\"")
	} else {
		file = fmt.Sprintf(file, "")
	}
	// TODO remove "_" from names for files here?

	return ioutil.WriteFile(strings.ToLower(s.Name)+"_gen.go", []byte(file), 0600)
}
<|endoftext|>


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

package agent_test

import (
	stdtesting "testing"

	"github.com/juju/testing"

	coretesting "github.com/juju/juju/testing"
)

func TestPackage(t *stdtesting.T) {
	if testing.RaceEnabled {
		t.Skip("skipping package under -race, see LP 1519133, 1519097")
	}
	// TODO(waigani) 2014-03-19 bug 1294458
	// Refactor to use base suites
	coretesting.MgoTestPackage(t)
}
<commit_msg>cmd/jujud/agent: fix test snafu<commit_after>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package agent // not agent_test for no good reason

import (
	stdtesting "testing"

	"github.com/juju/testing"

	coretesting "github.com/juju/juju/testing"
)

func TestPackage(t *stdtesting.T) {
	if testing.RaceEnabled {
		t.Skip("skipping package under -race, see LP 1519133, 1519097")
	}
	// TODO(waigani) 2014-03-19 bug 1294458
	// Refactor to use base suites
	coretesting.MgoTestPackage(t)
}
<|endoftext|>


<commit_before>package qemu

import (
	"fmt"
	"log"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/mitchellh/multistep"
	"github.com/mitchellh/packer/packer"
	"github.com/mitchellh/packer/template/interpolate"
)

// stepRun runs the virtual machine
type stepRun struct {
	BootDrive string
	Message   string
}

type qemuArgsTemplateData struct {
	HTTPIP      string
	HTTPPort    uint
	HTTPDir     string
	OutputDir   string
	Name        string
	SSHHostPort uint
}

func (s *stepRun) Run(state multistep.StateBag) multistep.StepAction {
	driver := state.Get("driver").(Driver)
	ui := state.Get("ui").(packer.Ui)

	ui.Say(s.Message)

	command, err := getCommandArgs(s.BootDrive, state)
	if err != nil {
		err := fmt.Errorf("Error processing QemuArggs: %s", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	if err := driver.Qemu(command...); err != nil {
		err := fmt.Errorf("Error launching VM: %s", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	return multistep.ActionContinue
}

func (s *stepRun) Cleanup(state multistep.StateBag) {
	driver := state.Get("driver").(Driver)
	ui := state.Get("ui").(packer.Ui)

	if err := driver.Stop(); err != nil {
		ui.Error(fmt.Sprintf("Error shutting down VM: %s", err))
	}
}

func getCommandArgs(bootDrive string, state multistep.StateBag) ([]string, error) {
	config := state.Get("config").(*Config)
	isoPath := state.Get("iso_path").(string)
	vncPort := state.Get("vnc_port").(uint)
	sshHostPort := state.Get("sshHostPort").(uint)
	ui := state.Get("ui").(packer.Ui)
	driver := state.Get("driver").(Driver)

	vnc := fmt.Sprintf("0.0.0.0:%d", vncPort-5900)
	vmName := config.VMName
	imgPath := filepath.Join(config.OutputDir, vmName)

	defaultArgs := make(map[string]interface{})
	var deviceArgs []string
	var driveArgs []string

	defaultArgs["-name"] = vmName
	defaultArgs["-machine"] = fmt.Sprintf("type=%s", config.MachineType)
	defaultArgs["-netdev"] = fmt.Sprintf("user,id=user.0,hostfwd=tcp::%v-:%d", sshHostPort, config.Comm.Port())

	qemuVersion, err := driver.Version()
	if err != nil {
		return nil, err
	}
	parts := strings.Split(qemuVersion, ".")
	qemuMajor, err := strconv.Atoi(parts[0])
	if err != nil {
		return nil, err
	}
	if qemuMajor >= 2 {
		if config.DiskInterface == "virtio-scsi" {
			deviceArgs = append(deviceArgs, "virtio-scsi-pci,id=scsi0", "scsi-hd,bus=scsi0.0,drive=drive0")
			driveArgs = append(driveArgs, fmt.Sprintf("if=none,file=%s,id=drive0,cache=%s,discard=%s", imgPath, config.DiskCache, config.DiskDiscard))
		} else {
			driveArgs = append(driveArgs, fmt.Sprintf("file=%s,if=%s,cache=%s,discard=%s", imgPath, config.DiskInterface, config.DiskCache, config.DiskDiscard))
		}
	} else {
		defaultArgs["-drive"] = fmt.Sprintf("file=%s,if=%s,cache=%s", imgPath, config.DiskInterface, config.DiskCache)
	}
	deviceArgs = append(deviceArgs, fmt.Sprintf("%s,netdev=user.0", config.NetDevice))

	if config.Headless == true {
		ui.Message("WARNING: The VM will be started in headless mode, as configured.\n" +
			"In headless mode, errors during the boot sequence or OS setup\n" +
			"won't be easily visible. Use at your own discretion.")
	} else {
		if qemuMajor >= 2 {
			defaultArgs["-display"] = "sdl"
		} else {
			ui.Message("WARNING: The version of qemu  on your host doesn't support display mode.\n" +
				"The display parameter will be ignored.")
		}
	}

	defaultArgs["-device"] = deviceArgs
	defaultArgs["-drive"] = driveArgs

	if !config.DiskImage {
		defaultArgs["-cdrom"] = isoPath
	}
	defaultArgs["-boot"] = bootDrive
	defaultArgs["-m"] = "512M"
	defaultArgs["-vnc"] = vnc

	// Append the accelerator to the machine type if it is specified
	if config.Accelerator != "none" {
		defaultArgs["-machine"] = fmt.Sprintf("%s,accel=%s", defaultArgs["-machine"], config.Accelerator)
	} else {
		ui.Message("WARNING: The VM will be started with no hardware acceleration.\n" +
			"The installation may take considerably longer to finish.\n")
	}

	// Determine if we have a floppy disk to attach
	if floppyPathRaw, ok := state.GetOk("floppy_path"); ok {
		defaultArgs["-fda"] = floppyPathRaw.(string)
	} else {
		log.Println("Qemu Builder has no floppy files, not attaching a floppy.")
	}

	inArgs := make(map[string][]string)
	if len(config.QemuArgs) > 0 {
		ui.Say("Overriding defaults Qemu arguments with QemuArgs...")

		httpPort := state.Get("http_port").(uint)
		ctx := config.ctx
		ctx.Data = qemuArgsTemplateData{
			"10.0.2.2",
			httpPort,
			config.HTTPDir,
			config.OutputDir,
			config.VMName,
			sshHostPort,
		}
		newQemuArgs, err := processArgs(config.QemuArgs, &ctx)
		if err != nil {
			return nil, err
		}

		// because qemu supports multiple appearances of the same
		// switch, just different values, each key in the args hash
		// will have an array of string values
		for _, qemuArgs := range newQemuArgs {
			key := qemuArgs[0]
			val := strings.Join(qemuArgs[1:], "")
			if _, ok := inArgs[key]; !ok {
				inArgs[key] = make([]string, 0)
			}
			if len(val) > 0 {
				inArgs[key] = append(inArgs[key], val)
			}
		}
	}

	// get any remaining missing default args from the default settings
	for key := range defaultArgs {
		if _, ok := inArgs[key]; !ok {
			arg := make([]string, 1)
			switch defaultArgs[key].(type) {
			case string:
				arg[0] = defaultArgs[key].(string)
			case []string:
				arg = defaultArgs[key].([]string)
			}
			inArgs[key] = arg
		}
	}

	// Flatten to array of strings
	outArgs := make([]string, 0)
	for key, values := range inArgs {
		if len(values) > 0 {
			for idx := range values {
				outArgs = append(outArgs, key, values[idx])
			}
		} else {
			outArgs = append(outArgs, key)
		}
	}

	return outArgs, nil
}

func processArgs(args [][]string, ctx *interpolate.Context) ([][]string, error) {
	var err error

	if args == nil {
		return make([][]string, 0), err
	}

	newArgs := make([][]string, len(args))
	for argsIdx, rowArgs := range args {
		parms := make([]string, len(rowArgs))
		newArgs[argsIdx] = parms
		for i, parm := range rowArgs {
			parms[i], err = interpolate.Render(parm, ctx)
			if err != nil {
				return nil, err
			}
		}
	}

	return newArgs, err
}
<commit_msg>fix assign to driveArgs<commit_after>package qemu

import (
	"fmt"
	"log"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/mitchellh/multistep"
	"github.com/mitchellh/packer/packer"
	"github.com/mitchellh/packer/template/interpolate"
)

// stepRun runs the virtual machine
type stepRun struct {
	BootDrive string
	Message   string
}

type qemuArgsTemplateData struct {
	HTTPIP      string
	HTTPPort    uint
	HTTPDir     string
	OutputDir   string
	Name        string
	SSHHostPort uint
}

func (s *stepRun) Run(state multistep.StateBag) multistep.StepAction {
	driver := state.Get("driver").(Driver)
	ui := state.Get("ui").(packer.Ui)

	ui.Say(s.Message)

	command, err := getCommandArgs(s.BootDrive, state)
	if err != nil {
		err := fmt.Errorf("Error processing QemuArggs: %s", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	if err := driver.Qemu(command...); err != nil {
		err := fmt.Errorf("Error launching VM: %s", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	return multistep.ActionContinue
}

func (s *stepRun) Cleanup(state multistep.StateBag) {
	driver := state.Get("driver").(Driver)
	ui := state.Get("ui").(packer.Ui)

	if err := driver.Stop(); err != nil {
		ui.Error(fmt.Sprintf("Error shutting down VM: %s", err))
	}
}

func getCommandArgs(bootDrive string, state multistep.StateBag) ([]string, error) {
	config := state.Get("config").(*Config)
	isoPath := state.Get("iso_path").(string)
	vncPort := state.Get("vnc_port").(uint)
	sshHostPort := state.Get("sshHostPort").(uint)
	ui := state.Get("ui").(packer.Ui)
	driver := state.Get("driver").(Driver)

	vnc := fmt.Sprintf("0.0.0.0:%d", vncPort-5900)
	vmName := config.VMName
	imgPath := filepath.Join(config.OutputDir, vmName)

	defaultArgs := make(map[string]interface{})
	var deviceArgs []string
	var driveArgs []string

	defaultArgs["-name"] = vmName
	defaultArgs["-machine"] = fmt.Sprintf("type=%s", config.MachineType)
	defaultArgs["-netdev"] = fmt.Sprintf("user,id=user.0,hostfwd=tcp::%v-:%d", sshHostPort, config.Comm.Port())

	qemuVersion, err := driver.Version()
	if err != nil {
		return nil, err
	}
	parts := strings.Split(qemuVersion, ".")
	qemuMajor, err := strconv.Atoi(parts[0])
	if err != nil {
		return nil, err
	}
	if qemuMajor >= 2 {
		if config.DiskInterface == "virtio-scsi" {
			deviceArgs = append(deviceArgs, "virtio-scsi-pci,id=scsi0", "scsi-hd,bus=scsi0.0,drive=drive0")
			driveArgs = append(driveArgs, fmt.Sprintf("if=none,file=%s,id=drive0,cache=%s,discard=%s", imgPath, config.DiskCache, config.DiskDiscard))
		} else {
			driveArgs = append(driveArgs, fmt.Sprintf("file=%s,if=%s,cache=%s,discard=%s", imgPath, config.DiskInterface, config.DiskCache, config.DiskDiscard))
		}
	} else {
		driveArgs = append(driveArgs, fmt.Sprintf("file=%s,if=%s,cache=%s", imgPath, config.DiskInterface, config.DiskCache))
	}
	deviceArgs = append(deviceArgs, fmt.Sprintf("%s,netdev=user.0", config.NetDevice))

	if config.Headless == true {
		ui.Message("WARNING: The VM will be started in headless mode, as configured.\n" +
			"In headless mode, errors during the boot sequence or OS setup\n" +
			"won't be easily visible. Use at your own discretion.")
	} else {
		if qemuMajor >= 2 {
			defaultArgs["-display"] = "sdl"
		} else {
			ui.Message("WARNING: The version of qemu  on your host doesn't support display mode.\n" +
				"The display parameter will be ignored.")
		}
	}

	defaultArgs["-device"] = deviceArgs
	defaultArgs["-drive"] = driveArgs

	if !config.DiskImage {
		defaultArgs["-cdrom"] = isoPath
	}
	defaultArgs["-boot"] = bootDrive
	defaultArgs["-m"] = "512M"
	defaultArgs["-vnc"] = vnc

	// Append the accelerator to the machine type if it is specified
	if config.Accelerator != "none" {
		defaultArgs["-machine"] = fmt.Sprintf("%s,accel=%s", defaultArgs["-machine"], config.Accelerator)
	} else {
		ui.Message("WARNING: The VM will be started with no hardware acceleration.\n" +
			"The installation may take considerably longer to finish.\n")
	}

	// Determine if we have a floppy disk to attach
	if floppyPathRaw, ok := state.GetOk("floppy_path"); ok {
		defaultArgs["-fda"] = floppyPathRaw.(string)
	} else {
		log.Println("Qemu Builder has no floppy files, not attaching a floppy.")
	}

	inArgs := make(map[string][]string)
	if len(config.QemuArgs) > 0 {
		ui.Say("Overriding defaults Qemu arguments with QemuArgs...")

		httpPort := state.Get("http_port").(uint)
		ctx := config.ctx
		ctx.Data = qemuArgsTemplateData{
			"10.0.2.2",
			httpPort,
			config.HTTPDir,
			config.OutputDir,
			config.VMName,
			sshHostPort,
		}
		newQemuArgs, err := processArgs(config.QemuArgs, &ctx)
		if err != nil {
			return nil, err
		}

		// because qemu supports multiple appearances of the same
		// switch, just different values, each key in the args hash
		// will have an array of string values
		for _, qemuArgs := range newQemuArgs {
			key := qemuArgs[0]
			val := strings.Join(qemuArgs[1:], "")
			if _, ok := inArgs[key]; !ok {
				inArgs[key] = make([]string, 0)
			}
			if len(val) > 0 {
				inArgs[key] = append(inArgs[key], val)
			}
		}
	}

	// get any remaining missing default args from the default settings
	for key := range defaultArgs {
		if _, ok := inArgs[key]; !ok {
			arg := make([]string, 1)
			switch defaultArgs[key].(type) {
			case string:
				arg[0] = defaultArgs[key].(string)
			case []string:
				arg = defaultArgs[key].([]string)
			}
			inArgs[key] = arg
		}
	}

	// Flatten to array of strings
	outArgs := make([]string, 0)
	for key, values := range inArgs {
		if len(values) > 0 {
			for idx := range values {
				outArgs = append(outArgs, key, values[idx])
			}
		} else {
			outArgs = append(outArgs, key)
		}
	}

	return outArgs, nil
}

func processArgs(args [][]string, ctx *interpolate.Context) ([][]string, error) {
	var err error

	if args == nil {
		return make([][]string, 0), err
	}

	newArgs := make([][]string, len(args))
	for argsIdx, rowArgs := range args {
		parms := make([]string, len(rowArgs))
		newArgs[argsIdx] = parms
		for i, parm := range rowArgs {
			parms[i], err = interpolate.Render(parm, ctx)
			if err != nil {
				return nil, err
			}
		}
	}

	return newArgs, err
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors All rights reserved.

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 cmd

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"

	"github.com/google/go-cmp/cmp"
	"github.com/otiai10/copy"
	"github.com/spf13/viper"

	"k8s.io/minikube/pkg/minikube/config"
	"k8s.io/minikube/pkg/minikube/localpath"
)

// except returns a list of strings, minus the excluded ones
func exclude(vals []string, exclude []string) []string {
	result := []string{}
	for _, v := range vals {
		excluded := false
		for _, e := range exclude {
			if e == v {
				excluded = true
				continue
			}
		}
		if !excluded {
			result = append(result, v)
		}
	}
	return result
}

func fileNames(path string) ([]string, error) {
	result := []string{}
	fis, err := ioutil.ReadDir(path)
	if err != nil {
		return result, err
	}
	for _, fi := range fis {
		result = append(result, fi.Name())
	}
	return result, nil
}

func TestDeleteProfile(t *testing.T) {
	td, err := ioutil.TempDir("", "single")
	if err != nil {
		t.Fatalf("tempdir: %v", err)
	}

	defer func() { //clean up tempdir
		err := os.RemoveAll(td)
		if err != nil {
			t.Errorf("failed to clean up temp folder  %q", td)
		}
	}()

	err = copy.Copy("../../../pkg/minikube/config/testdata/delete-single", td)
	if err != nil {
		t.Fatalf("copy: %v", err)
	}

	tests := []struct {
		name     string
		profile  string
		expected []string
	}{
		{"normal", "p1", []string{"p1"}},
		{"empty-profile", "p2_empty_profile_config", []string{"p2_empty_profile_config"}},
		{"invalid-profile", "p3_invalid_profile_config", []string{"p3_invalid_profile_config"}},
		{"partial-profile", "p4_partial_profile_config", []string{"p4_partial_profile_config"}},
		{"missing-mach", "p5_missing_machine_config", []string{"p5_missing_machine_config"}},
		{"empty-mach", "p6_empty_machine_config", []string{"p6_empty_machine_config"}},
		{"invalid-mach", "p7_invalid_machine_config", []string{"p7_invalid_machine_config"}},
		{"partial-mach", "p8_partial_machine_config", []string{"p8_partial_machine_config"}},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err = os.Setenv(localpath.MinikubeHome, td)
			if err != nil {
				t.Errorf("setenv: %v", err)
			}

			beforeProfiles, err := fileNames(filepath.Join(localpath.MiniPath(), "profiles"))
			if err != nil {
				t.Errorf("readdir: %v", err)
			}
			beforeMachines, err := fileNames(filepath.Join(localpath.MiniPath(), "machines"))
			if err != nil {
				t.Errorf("readdir: %v", err)
			}

			profile, err := config.LoadProfile(tt.profile)
			if err != nil {
				t.Logf("load failure: %v", err)
			}

			errs := DeleteProfiles([]*config.Profile{profile})
			if len(errs) > 0 {
				HandleDeletionErrors(errs)
				t.Errorf("Errors while deleting profiles: %v", errs)
			}
			pathToProfile := config.ProfileFolderPath(profile.Name, localpath.MiniPath())
			if _, err := os.Stat(pathToProfile); !os.IsNotExist(err) {
				t.Errorf("Profile folder of profile \"%s\" was not deleted", profile.Name)
			}

			pathToMachine := localpath.MachinePath(profile.Name, localpath.MiniPath())
			if _, err := os.Stat(pathToMachine); !os.IsNotExist(err) {
				t.Errorf("Profile folder of profile \"%s\" was not deleted", profile.Name)
			}

			afterProfiles, err := fileNames(filepath.Join(localpath.MiniPath(), "profiles"))
			if err != nil {
				t.Errorf("readdir profiles: %v", err)
			}

			afterMachines, err := fileNames(filepath.Join(localpath.MiniPath(), "machines"))
			if err != nil {
				t.Errorf("readdir machines: %v", err)
			}

			expectedProfiles := exclude(beforeProfiles, tt.expected)
			if diff := cmp.Diff(expectedProfiles, afterProfiles); diff != "" {
				t.Errorf("profiles mismatch (-want +got):\n%s", diff)
			}

			expectedMachines := exclude(beforeMachines, tt.expected)
			if diff := cmp.Diff(expectedMachines, afterMachines); diff != "" {
				t.Errorf("machines mismatch (-want +got):\n%s", diff)
			}

			viper.Set(config.ProfileName, "")
		})
	}
}

func TestDeleteAllProfiles(t *testing.T) {
	td, err := ioutil.TempDir("", "all")
	if err != nil {
		t.Fatalf("tempdir: %v", err)
	}
	defer func() { //clean up tempdir
		err := os.RemoveAll(td)
		if err != nil {
			t.Errorf("failed to clean up temp folder  %q", td)
		}
	}()

	err = copy.Copy("../../../pkg/minikube/config/testdata/delete-all", td)
	if err != nil {
		t.Fatalf("copy: %v", err)
	}

	err = os.Setenv(localpath.MinikubeHome, td)
	if err != nil {
		t.Errorf("error setting up test environment. could not set %s", localpath.MinikubeHome)
	}

	pFiles, err := fileNames(filepath.Join(localpath.MiniPath(), "profiles"))
	if err != nil {
		t.Errorf("filenames: %v", err)
	}
	mFiles, err := fileNames(filepath.Join(localpath.MiniPath(), "machines"))
	if err != nil {
		t.Errorf("filenames: %v", err)
	}

	const numberOfTotalProfileDirs = 8
	if numberOfTotalProfileDirs != len(pFiles) {
		t.Errorf("got %d test profiles, expected %d: %s", len(pFiles), numberOfTotalProfileDirs, pFiles)
	}
	const numberOfTotalMachineDirs = 7
	if numberOfTotalMachineDirs != len(mFiles) {
		t.Errorf("got %d test machines, expected %d: %s", len(mFiles), numberOfTotalMachineDirs, mFiles)
	}

	validProfiles, inValidProfiles, err := config.ListProfiles()
	if err != nil {
		t.Error(err)
	}

	if numberOfTotalProfileDirs != len(validProfiles)+len(inValidProfiles) {
		t.Errorf("ListProfiles length = %d, expected %d\nvalid: %v\ninvalid: %v\n", len(validProfiles)+len(inValidProfiles), numberOfTotalProfileDirs, validProfiles, inValidProfiles)
	}

	profiles := append(validProfiles, inValidProfiles...)
	errs := DeleteProfiles(profiles)

	if errs != nil {
		t.Errorf("errors while deleting all profiles: %v", errs)
	}

	afterProfiles, err := fileNames(filepath.Join(localpath.MiniPath(), "profiles"))
	if err != nil {
		t.Errorf("profiles: %v", err)
	}
	afterMachines, err := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines"))
	if err != nil {
		t.Errorf("machines: %v", err)
	}
	if len(afterProfiles) != 0 {
		t.Errorf("Did not delete all profiles, remaining: %v", afterProfiles)
	}

	if len(afterMachines) != 0 {
		t.Errorf("Did not delete all machines, remaining: %v", afterMachines)
	}

	viper.Set(config.ProfileName, "")
}
<commit_msg>add cleanup in another test<commit_after>/*
Copyright 2016 The Kubernetes Authors All rights reserved.

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 cmd

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"

	"github.com/google/go-cmp/cmp"
	"github.com/otiai10/copy"
	"github.com/spf13/viper"

	"k8s.io/minikube/pkg/minikube/config"
	"k8s.io/minikube/pkg/minikube/localpath"
)

// except returns a list of strings, minus the excluded ones
func exclude(vals []string, exclude []string) []string {
	result := []string{}
	for _, v := range vals {
		excluded := false
		for _, e := range exclude {
			if e == v {
				excluded = true
				continue
			}
		}
		if !excluded {
			result = append(result, v)
		}
	}
	return result
}

func fileNames(path string) ([]string, error) {
	result := []string{}
	fis, err := ioutil.ReadDir(path)
	if err != nil {
		return result, err
	}
	for _, fi := range fis {
		result = append(result, fi.Name())
	}
	return result, nil
}

func TestDeleteProfile(t *testing.T) {
	td, err := ioutil.TempDir("", "single")
	if err != nil {
		t.Fatalf("tempdir: %v", err)
	}

	t.Cleanup(func() {
		err := os.RemoveAll(td)
		if err != nil {
			t.Errorf("failed to clean up temp folder  %q", td)
		}
	})

	err = copy.Copy("../../../pkg/minikube/config/testdata/delete-single", td)
	if err != nil {
		t.Fatalf("copy: %v", err)
	}

	tests := []struct {
		name     string
		profile  string
		expected []string
	}{
		{"normal", "p1", []string{"p1"}},
		{"empty-profile", "p2_empty_profile_config", []string{"p2_empty_profile_config"}},
		{"invalid-profile", "p3_invalid_profile_config", []string{"p3_invalid_profile_config"}},
		{"partial-profile", "p4_partial_profile_config", []string{"p4_partial_profile_config"}},
		{"missing-mach", "p5_missing_machine_config", []string{"p5_missing_machine_config"}},
		{"empty-mach", "p6_empty_machine_config", []string{"p6_empty_machine_config"}},
		{"invalid-mach", "p7_invalid_machine_config", []string{"p7_invalid_machine_config"}},
		{"partial-mach", "p8_partial_machine_config", []string{"p8_partial_machine_config"}},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err = os.Setenv(localpath.MinikubeHome, td)
			if err != nil {
				t.Errorf("setenv: %v", err)
			}

			beforeProfiles, err := fileNames(filepath.Join(localpath.MiniPath(), "profiles"))
			if err != nil {
				t.Errorf("readdir: %v", err)
			}
			beforeMachines, err := fileNames(filepath.Join(localpath.MiniPath(), "machines"))
			if err != nil {
				t.Errorf("readdir: %v", err)
			}

			profile, err := config.LoadProfile(tt.profile)
			if err != nil {
				t.Logf("load failure: %v", err)
			}

			errs := DeleteProfiles([]*config.Profile{profile})
			if len(errs) > 0 {
				HandleDeletionErrors(errs)
				t.Errorf("Errors while deleting profiles: %v", errs)
			}
			pathToProfile := config.ProfileFolderPath(profile.Name, localpath.MiniPath())
			if _, err := os.Stat(pathToProfile); !os.IsNotExist(err) {
				t.Errorf("Profile folder of profile \"%s\" was not deleted", profile.Name)
			}

			pathToMachine := localpath.MachinePath(profile.Name, localpath.MiniPath())
			if _, err := os.Stat(pathToMachine); !os.IsNotExist(err) {
				t.Errorf("Profile folder of profile \"%s\" was not deleted", profile.Name)
			}

			afterProfiles, err := fileNames(filepath.Join(localpath.MiniPath(), "profiles"))
			if err != nil {
				t.Errorf("readdir profiles: %v", err)
			}

			afterMachines, err := fileNames(filepath.Join(localpath.MiniPath(), "machines"))
			if err != nil {
				t.Errorf("readdir machines: %v", err)
			}

			expectedProfiles := exclude(beforeProfiles, tt.expected)
			if diff := cmp.Diff(expectedProfiles, afterProfiles); diff != "" {
				t.Errorf("profiles mismatch (-want +got):\n%s", diff)
			}

			expectedMachines := exclude(beforeMachines, tt.expected)
			if diff := cmp.Diff(expectedMachines, afterMachines); diff != "" {
				t.Errorf("machines mismatch (-want +got):\n%s", diff)
			}

			viper.Set(config.ProfileName, "")
		})
	}
}

func TestDeleteAllProfiles(t *testing.T) {
	td, err := ioutil.TempDir("", "all")
	if err != nil {
		t.Fatalf("tempdir: %v", err)
	}
	defer func() { //clean up tempdir
		err := os.RemoveAll(td)
		if err != nil {
			t.Errorf("failed to clean up temp folder  %q", td)
		}
	}()

	err = copy.Copy("../../../pkg/minikube/config/testdata/delete-all", td)
	if err != nil {
		t.Fatalf("copy: %v", err)
	}

	err = os.Setenv(localpath.MinikubeHome, td)
	if err != nil {
		t.Errorf("error setting up test environment. could not set %s", localpath.MinikubeHome)
	}

	pFiles, err := fileNames(filepath.Join(localpath.MiniPath(), "profiles"))
	if err != nil {
		t.Errorf("filenames: %v", err)
	}
	mFiles, err := fileNames(filepath.Join(localpath.MiniPath(), "machines"))
	if err != nil {
		t.Errorf("filenames: %v", err)
	}

	const numberOfTotalProfileDirs = 8
	if numberOfTotalProfileDirs != len(pFiles) {
		t.Errorf("got %d test profiles, expected %d: %s", len(pFiles), numberOfTotalProfileDirs, pFiles)
	}
	const numberOfTotalMachineDirs = 7
	if numberOfTotalMachineDirs != len(mFiles) {
		t.Errorf("got %d test machines, expected %d: %s", len(mFiles), numberOfTotalMachineDirs, mFiles)
	}

	validProfiles, inValidProfiles, err := config.ListProfiles()
	if err != nil {
		t.Error(err)
	}

	if numberOfTotalProfileDirs != len(validProfiles)+len(inValidProfiles) {
		t.Errorf("ListProfiles length = %d, expected %d\nvalid: %v\ninvalid: %v\n", len(validProfiles)+len(inValidProfiles), numberOfTotalProfileDirs, validProfiles, inValidProfiles)
	}

	profiles := append(validProfiles, inValidProfiles...)
	errs := DeleteProfiles(profiles)

	if errs != nil {
		t.Errorf("errors while deleting all profiles: %v", errs)
	}

	afterProfiles, err := fileNames(filepath.Join(localpath.MiniPath(), "profiles"))
	if err != nil {
		t.Errorf("profiles: %v", err)
	}
	afterMachines, err := ioutil.ReadDir(filepath.Join(localpath.MiniPath(), "machines"))
	if err != nil {
		t.Errorf("machines: %v", err)
	}
	if len(afterProfiles) != 0 {
		t.Errorf("Did not delete all profiles, remaining: %v", afterProfiles)
	}

	if len(afterMachines) != 0 {
		t.Errorf("Did not delete all machines, remaining: %v", afterMachines)
	}

	viper.Set(config.ProfileName, "")
}
<|endoftext|>