<commit_before>package gorma

import "github.com/raphael/goa/design"

// Validate tests whether the StorageGroup definition is consistent
func (a *StorageGroupDefinition) Validate() *design.ValidationErrors {
	verr := new(goa.ValidationErrors)

	a.IterateStores(func(store *RelationalStoreDefinition) error {
		verr.Merge(store.Validate())
	})

	return verr.AsError()
}

// Validate tests whether the RelationalStore definition is consistent
func (a *RelationalStoreDefinition) Validate() *design.ValidationErrors {
	verr := new(goa.ValidationErrors)

	a.IterateModels(func(model *RelationalModelDefinition) error {
		verr.Merge(model.Validate())
	})

	return verr.AsError()
}

// Validate tests whether the RelationalModel definition is consistent
func (a *RelationalModelDefinition) Validate() *design.ValidationErrors {

	verr := new(goa.ValidationErrors)

	a.IterateFields(func(field *RelationalFieldDefinition) error {
		verr.Merge(field.Validate())
	})

	return verr.AsError()
}

// Validate tests whether the RelationalField definition is consistent
func (a *RelationalFieldDefinition) Validate() *design.ValidationErrors {
	verr := new(goa.ValidationErrors)
	if field.Name == "" {
		verr.Add(a, "field name not defined")
	}
	return verr.AsError()
}
<commit_msg>WIP Standalone DSL<commit_after>package gorma

import "github.com/raphael/goa/design"

// Validate tests whether the StorageGroup definition is consistent
func (a *StorageGroupDefinition) Validate() *design.ValidationErrors {
	verr := new(goa.ValidationErrors)

	a.IterateStores(func(store *RelationalStoreDefinition) error {
		verr.Merge(store.Validate())
	})

	return verr.AsError()
}

// Validate tests whether the RelationalStore definition is consistent
func (a *RelationalStoreDefinition) Validate() *design.ValidationErrors {
	verr := new(goa.ValidationErrors)

	a.IterateModels(func(model *RelationalModelDefinition) error {
		verr.Merge(model.Validate())
	})

	return verr.AsError()
}

// Validate tests whether the RelationalModel definition is consistent
func (a *RelationalModelDefinition) Validate() *design.ValidationErrors {

	verr := new(goa.ValidationErrors)
	if a.Name == "" {
		verr.Add(a, "model name not defined")
	}
	a.IterateFields(func(field *RelationalFieldDefinition) error {
		verr.Merge(field.Validate())
	})

	return verr.AsError()
}

// Validate tests whether the RelationalField definition is consistent
func (a *RelationalFieldDefinition) Validate() *design.ValidationErrors {
	verr := new(goa.ValidationErrors)
	if field.Name == "" {
		verr.Add(a, "field name not defined")
	}
	return verr.AsError()
}
<|endoftext|>


<commit_before>package weed_server

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"path/filepath"
	"strconv"
	"strings"
	"time"

	"github.com/chrislusf/seaweedfs/weed/storage/needle"
	"google.golang.org/grpc"

	"github.com/chrislusf/seaweedfs/weed/glog"
	"github.com/chrislusf/seaweedfs/weed/operation"
	"github.com/chrislusf/seaweedfs/weed/stats"
	"github.com/chrislusf/seaweedfs/weed/util"

	_ "github.com/chrislusf/seaweedfs/weed/statik"
	"github.com/gorilla/mux"
	statik "github.com/rakyll/statik/fs"
)

var serverStats *stats.ServerStats
var startTime = time.Now()
var statikFS http.FileSystem

func init() {
	serverStats = stats.NewServerStats()
	go serverStats.Start()
	statikFS, _ = statik.New()
}

func writeJson(w http.ResponseWriter, r *http.Request, httpStatus int, obj interface{}) (err error) {
	var bytes []byte
	if r.FormValue("pretty") != "" {
		bytes, err = json.MarshalIndent(obj, "", "  ")
	} else {
		bytes, err = json.Marshal(obj)
	}
	if err != nil {
		return
	}
	callback := r.FormValue("callback")
	if callback == "" {
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(httpStatus)
		_, err = w.Write(bytes)
	} else {
		w.Header().Set("Content-Type", "application/javascript")
		w.WriteHeader(httpStatus)
		if _, err = w.Write([]uint8(callback)); err != nil {
			return
		}
		if _, err = w.Write([]uint8("(")); err != nil {
			return
		}
		fmt.Fprint(w, string(bytes))
		if _, err = w.Write([]uint8(")")); err != nil {
			return
		}
	}

	return
}

// wrapper for writeJson - just logs errors
func writeJsonQuiet(w http.ResponseWriter, r *http.Request, httpStatus int, obj interface{}) {
	if err := writeJson(w, r, httpStatus, obj); err != nil {
		glog.V(0).Infof("error writing JSON %+v status %d: %v", obj, httpStatus, err)
	}
}
func writeJsonError(w http.ResponseWriter, r *http.Request, httpStatus int, err error) {
	m := make(map[string]interface{})
	m["error"] = err.Error()
	writeJsonQuiet(w, r, httpStatus, m)
}

func debug(params ...interface{}) {
	glog.V(4).Infoln(params...)
}

func submitForClientHandler(w http.ResponseWriter, r *http.Request, masterUrl string, grpcDialOption grpc.DialOption) {
	m := make(map[string]interface{})
	if r.Method != "POST" {
		writeJsonError(w, r, http.StatusMethodNotAllowed, errors.New("Only submit via POST!"))
		return
	}

	debug("parsing upload file...")
	fname, data, mimeType, pairMap, isGzipped, originalDataSize, lastModified, _, _, pe := needle.ParseUpload(r)
	if pe != nil {
		writeJsonError(w, r, http.StatusBadRequest, pe)
		return
	}

	debug("assigning file id for", fname)
	r.ParseForm()
	count := uint64(1)
	if r.FormValue("count") != "" {
		count, pe = strconv.ParseUint(r.FormValue("count"), 10, 32)
		if pe != nil {
			writeJsonError(w, r, http.StatusBadRequest, pe)
			return
		}
	}
	ar := &operation.VolumeAssignRequest{
		Count:       count,
		Replication: r.FormValue("replication"),
		Collection:  r.FormValue("collection"),
		Ttl:         r.FormValue("ttl"),
	}
	assignResult, ae := operation.Assign(masterUrl, grpcDialOption, ar)
	if ae != nil {
		writeJsonError(w, r, http.StatusInternalServerError, ae)
		return
	}

	url := "http://" + assignResult.Url + "/" + assignResult.Fid
	if lastModified != 0 {
		url = url + "?ts=" + strconv.FormatUint(lastModified, 10)
	}

	debug("upload file to store", url)
	uploadResult, err := operation.Upload(url, fname, bytes.NewReader(data), isGzipped, mimeType, pairMap, assignResult.Auth)
	if err != nil {
		writeJsonError(w, r, http.StatusInternalServerError, err)
		return
	}

	m["fileName"] = fname
	m["fid"] = assignResult.Fid
	m["fileUrl"] = assignResult.PublicUrl + "/" + assignResult.Fid
	m["size"] = originalDataSize
	m["eTag"] = uploadResult.ETag
	writeJsonQuiet(w, r, http.StatusCreated, m)
	return
}

func parseURLPath(path string) (vid, fid, filename, ext string, isVolumeIdOnly bool) {
	switch strings.Count(path, "/") {
	case 3:
		parts := strings.Split(path, "/")
		vid, fid, filename = parts[1], parts[2], parts[3]
		ext = filepath.Ext(filename)
	case 2:
		parts := strings.Split(path, "/")
		vid, fid = parts[1], parts[2]
		dotIndex := strings.LastIndex(fid, ".")
		if dotIndex > 0 {
			ext = fid[dotIndex:]
			fid = fid[0:dotIndex]
		}
	default:
		sepIndex := strings.LastIndex(path, "/")
		commaIndex := strings.LastIndex(path[sepIndex:], ",")
		if commaIndex <= 0 {
			vid, isVolumeIdOnly = path[sepIndex+1:], true
			return
		}
		dotIndex := strings.LastIndex(path[sepIndex:], ".")
		vid = path[sepIndex+1 : commaIndex]
		fid = path[commaIndex+1:]
		ext = ""
		if dotIndex > 0 {
			fid = path[commaIndex+1 : dotIndex]
			ext = path[dotIndex:]
		}
	}
	return
}

func statsHealthHandler(w http.ResponseWriter, r *http.Request) {
	m := make(map[string]interface{})
	m["Version"] = util.VERSION
	writeJsonQuiet(w, r, http.StatusOK, m)
}
func statsCounterHandler(w http.ResponseWriter, r *http.Request) {
	m := make(map[string]interface{})
	m["Version"] = util.VERSION
	m["Counters"] = serverStats
	writeJsonQuiet(w, r, http.StatusOK, m)
}

func statsMemoryHandler(w http.ResponseWriter, r *http.Request) {
	m := make(map[string]interface{})
	m["Version"] = util.VERSION
	m["Memory"] = stats.MemStat()
	writeJsonQuiet(w, r, http.StatusOK, m)
}

func handleStaticResources(defaultMux *http.ServeMux) {
	defaultMux.Handle("/favicon.ico", http.FileServer(statikFS))
	defaultMux.Handle("/seaweedfsstatic/", http.StripPrefix("/seaweedfsstatic", http.FileServer(statikFS)))
}

func handleStaticResources2(r *mux.Router) {
	r.Handle("/favicon.ico", http.FileServer(statikFS))
	r.PathPrefix("/seaweedfsstatic/").Handler(http.StripPrefix("/seaweedfsstatic", http.FileServer(statikFS)))
}
<commit_msg>skip writing content if not modified<commit_after>package weed_server

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"path/filepath"
	"strconv"
	"strings"
	"time"

	"github.com/chrislusf/seaweedfs/weed/storage/needle"
	"google.golang.org/grpc"

	"github.com/chrislusf/seaweedfs/weed/glog"
	"github.com/chrislusf/seaweedfs/weed/operation"
	"github.com/chrislusf/seaweedfs/weed/stats"
	"github.com/chrislusf/seaweedfs/weed/util"

	_ "github.com/chrislusf/seaweedfs/weed/statik"
	"github.com/gorilla/mux"
	statik "github.com/rakyll/statik/fs"
)

var serverStats *stats.ServerStats
var startTime = time.Now()
var statikFS http.FileSystem

func init() {
	serverStats = stats.NewServerStats()
	go serverStats.Start()
	statikFS, _ = statik.New()
}

func writeJson(w http.ResponseWriter, r *http.Request, httpStatus int, obj interface{}) (err error) {
	var bytes []byte
	if r.FormValue("pretty") != "" {
		bytes, err = json.MarshalIndent(obj, "", "  ")
	} else {
		bytes, err = json.Marshal(obj)
	}
	if err != nil {
		return
	}
	callback := r.FormValue("callback")
	if callback == "" {
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(httpStatus)
		if httpStatus == http.StatusNotModified {
			return
		}
		_, err = w.Write(bytes)
	} else {
		w.Header().Set("Content-Type", "application/javascript")
		w.WriteHeader(httpStatus)
		if httpStatus == http.StatusNotModified {
			return
		}
		if _, err = w.Write([]uint8(callback)); err != nil {
			return
		}
		if _, err = w.Write([]uint8("(")); err != nil {
			return
		}
		fmt.Fprint(w, string(bytes))
		if _, err = w.Write([]uint8(")")); err != nil {
			return
		}
	}

	return
}

// wrapper for writeJson - just logs errors
func writeJsonQuiet(w http.ResponseWriter, r *http.Request, httpStatus int, obj interface{}) {
	if err := writeJson(w, r, httpStatus, obj); err != nil {
		glog.V(0).Infof("error writing JSON %+v status %d: %v", obj, httpStatus, err)
	}
}
func writeJsonError(w http.ResponseWriter, r *http.Request, httpStatus int, err error) {
	m := make(map[string]interface{})
	m["error"] = err.Error()
	writeJsonQuiet(w, r, httpStatus, m)
}

func debug(params ...interface{}) {
	glog.V(4).Infoln(params...)
}

func submitForClientHandler(w http.ResponseWriter, r *http.Request, masterUrl string, grpcDialOption grpc.DialOption) {
	m := make(map[string]interface{})
	if r.Method != "POST" {
		writeJsonError(w, r, http.StatusMethodNotAllowed, errors.New("Only submit via POST!"))
		return
	}

	debug("parsing upload file...")
	fname, data, mimeType, pairMap, isGzipped, originalDataSize, lastModified, _, _, pe := needle.ParseUpload(r)
	if pe != nil {
		writeJsonError(w, r, http.StatusBadRequest, pe)
		return
	}

	debug("assigning file id for", fname)
	r.ParseForm()
	count := uint64(1)
	if r.FormValue("count") != "" {
		count, pe = strconv.ParseUint(r.FormValue("count"), 10, 32)
		if pe != nil {
			writeJsonError(w, r, http.StatusBadRequest, pe)
			return
		}
	}
	ar := &operation.VolumeAssignRequest{
		Count:       count,
		Replication: r.FormValue("replication"),
		Collection:  r.FormValue("collection"),
		Ttl:         r.FormValue("ttl"),
	}
	assignResult, ae := operation.Assign(masterUrl, grpcDialOption, ar)
	if ae != nil {
		writeJsonError(w, r, http.StatusInternalServerError, ae)
		return
	}

	url := "http://" + assignResult.Url + "/" + assignResult.Fid
	if lastModified != 0 {
		url = url + "?ts=" + strconv.FormatUint(lastModified, 10)
	}

	debug("upload file to store", url)
	uploadResult, err := operation.Upload(url, fname, bytes.NewReader(data), isGzipped, mimeType, pairMap, assignResult.Auth)
	if err != nil {
		writeJsonError(w, r, http.StatusInternalServerError, err)
		return
	}

	m["fileName"] = fname
	m["fid"] = assignResult.Fid
	m["fileUrl"] = assignResult.PublicUrl + "/" + assignResult.Fid
	m["size"] = originalDataSize
	m["eTag"] = uploadResult.ETag
	writeJsonQuiet(w, r, http.StatusCreated, m)
	return
}

func parseURLPath(path string) (vid, fid, filename, ext string, isVolumeIdOnly bool) {
	switch strings.Count(path, "/") {
	case 3:
		parts := strings.Split(path, "/")
		vid, fid, filename = parts[1], parts[2], parts[3]
		ext = filepath.Ext(filename)
	case 2:
		parts := strings.Split(path, "/")
		vid, fid = parts[1], parts[2]
		dotIndex := strings.LastIndex(fid, ".")
		if dotIndex > 0 {
			ext = fid[dotIndex:]
			fid = fid[0:dotIndex]
		}
	default:
		sepIndex := strings.LastIndex(path, "/")
		commaIndex := strings.LastIndex(path[sepIndex:], ",")
		if commaIndex <= 0 {
			vid, isVolumeIdOnly = path[sepIndex+1:], true
			return
		}
		dotIndex := strings.LastIndex(path[sepIndex:], ".")
		vid = path[sepIndex+1 : commaIndex]
		fid = path[commaIndex+1:]
		ext = ""
		if dotIndex > 0 {
			fid = path[commaIndex+1 : dotIndex]
			ext = path[dotIndex:]
		}
	}
	return
}

func statsHealthHandler(w http.ResponseWriter, r *http.Request) {
	m := make(map[string]interface{})
	m["Version"] = util.VERSION
	writeJsonQuiet(w, r, http.StatusOK, m)
}
func statsCounterHandler(w http.ResponseWriter, r *http.Request) {
	m := make(map[string]interface{})
	m["Version"] = util.VERSION
	m["Counters"] = serverStats
	writeJsonQuiet(w, r, http.StatusOK, m)
}

func statsMemoryHandler(w http.ResponseWriter, r *http.Request) {
	m := make(map[string]interface{})
	m["Version"] = util.VERSION
	m["Memory"] = stats.MemStat()
	writeJsonQuiet(w, r, http.StatusOK, m)
}

func handleStaticResources(defaultMux *http.ServeMux) {
	defaultMux.Handle("/favicon.ico", http.FileServer(statikFS))
	defaultMux.Handle("/seaweedfsstatic/", http.StripPrefix("/seaweedfsstatic", http.FileServer(statikFS)))
}

func handleStaticResources2(r *mux.Router) {
	r.Handle("/favicon.ico", http.FileServer(statikFS))
	r.PathPrefix("/seaweedfsstatic/").Handler(http.StripPrefix("/seaweedfsstatic", http.FileServer(statikFS)))
}
<|endoftext|>


<commit_before>package model_test

<commit_msg>Start of test framework<commit_after>package model_test

import (
	"encoding/json"
	"github.com/crezam/actions-on-google-golang/model"
	"os"
	"testing"
)

func TestRequestParsing(t *testing.T) {

	var req model.ApiAiRequest

	file, _ := os.Open("./data/sample_request1.json")
	dec := json.NewDecoder(file)

	if err := dec.Decode(&req); err != nil {
		t.Fatal(err)
	}

	if resolvedQuery := req.Result.ResolvedQuery; resolvedQuery != "Hi, my name is Sam!" {
		t.Fatal("Failed parsing resolved query")
	}

}
<|endoftext|>


<commit_before>package wikifier

type tocBlock struct {
	*parserBlock
}

func newTocBlock(name string, b *parserBlock) block {
	return &tocBlock{b}
}

func (toc *tocBlock) html(page *Page, el element) {
	el.setTag("ul")
	el.addHTML(HTML("Contents"))
	// add each top-level section
	for _, child := range page.main.blockContent() {
		if sec, ok := child.(*secBlock); ok {
			tocAdd(sec, el)
		}
	}
}

func tocAdd(sec *secBlock, addTo element) {

	// create an item for this section
	var subList element
	if !sec.isIntro {
		li := addTo.createChild("li", "")
		a := li.createChild("a", "link-internal")
		a.setAttr("href", "#"+sec.headingID)
		a.addHTML(sec.fmtTitle)
		addTo = li
	} else {
		subList = addTo
	}

	// create a sub-list for each section underneath
	for _, child := range sec.blockContent() {
		if secChild, ok := child.(*secBlock); ok {
			if subList == nil {
				subList = addTo.createChild("ul", "")
			}
			tocAdd(secChild, subList)
		}
	}
}
<commit_msg>seems fmtTitle isn't yet defined so format it now<commit_after>package wikifier

type tocBlock struct {
	*parserBlock
}

func newTocBlock(name string, b *parserBlock) block {
	return &tocBlock{b}
}

func (toc *tocBlock) html(page *Page, el element) {
	el.setTag("ul")
	el.addHTML(HTML("Contents"))
	// add each top-level section
	for _, child := range page.main.blockContent() {
		if sec, ok := child.(*secBlock); ok {
			tocAdd(sec, el, page)
		}
	}
}

func tocAdd(sec *secBlock, addTo element, page *Page) {

	// create an item for this section
	var subList element
	if !sec.isIntro {
		li := addTo.createChild("li", "")
		a := li.createChild("a", "link-internal")
		a.setAttr("href", "#"+sec.headingID)
		a.addHTML(page.formatTextOpts(sec.title, fmtOpt{pos: sec.openPos}))
		addTo = li
	} else {
		subList = addTo
	}

	// create a sub-list for each section underneath
	for _, child := range sec.blockContent() {
		if secChild, ok := child.(*secBlock); ok {
			if subList == nil {
				subList = addTo.createChild("ul", "")
			}
			tocAdd(secChild, subList, page)
		}
	}
}
<|endoftext|>


<commit_before>package worker

import (
	"context"
	"encoding/json"
	"fmt"
	"testing"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/sqs"
	"github.com/aws/aws-sdk-go/service/sqs/sqsiface"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/mock"
)

type mockedSqsClient struct {
	Config   *aws.Config
	Response sqs.ReceiveMessageOutput
	sqsiface.SQSAPI
	mock.Mock
}

func (c *mockedSqsClient) GetQueueUrl(urlInput *sqs.GetQueueUrlInput) (*sqs.GetQueueUrlOutput, error) {
	url := fmt.Sprintf("https://sqs.%v.amazonaws.com/123456789/%v", *c.Config.Region, *urlInput.QueueName)

	return &sqs.GetQueueUrlOutput{QueueUrl: &url}, nil
}

func (c *mockedSqsClient) ReceiveMessage(input *sqs.ReceiveMessageInput) (*sqs.ReceiveMessageOutput, error) {
	c.Called(input)

	return &c.Response, nil
}

func (c *mockedSqsClient) DeleteMessage(input *sqs.DeleteMessageInput) (*sqs.DeleteMessageOutput, error) {
	c.Called(input)
	c.Response = sqs.ReceiveMessageOutput{}

	return &sqs.DeleteMessageOutput{}, nil
}

type mockedHandler struct {
	mock.Mock
}

func (mh *mockedHandler) HandleMessage(foo string, qux string) {
	mh.Called(foo, qux)
}

type sqsEvent struct {
	Foo string `json:"foo"`
	Qux string `json:"qux"`
}

func TestStart(t *testing.T) {
	region := "eu-west-1"
	awsConfig := &aws.Config{Region: &region}
	workerConfig := &Config{QueueName: "my-sqs-queue"}
	client := setupMockedSqsClient(awsConfig)
	worker := New(client, workerConfig)

	ctx, cancel := contextAndCancel()
	defer cancel()

	handler := new(mockedHandler)
	handlerFunc := HandlerFunc(func(msg *sqs.Message) (err error) {
		event := &sqsEvent{}

		json.Unmarshal([]byte(aws.StringValue(msg.Body)), event)

		handler.HandleMessage(event.Foo, event.Qux)

		return
	})

	t.Run("the worker has correct configuration", func(t *testing.T) {
		assert.Equal(t, worker.Config.QueueName, "my-sqs-queue", "QueueName has been set properly")
		assert.Equal(t, worker.Config.QueueURL, "https://sqs.eu-west-1.amazonaws.com/123456789/my-sqs-queue", "QueueURL has been set properly")
		assert.Equal(t, worker.Config.MaxNumberOfMessage, int64(10), "MaxNumberOfMessage has been set properly")
		assert.Equal(t, worker.Config.WaitTimeSecond, int64(20), "WaitTimeSecond has been set properly")
	})

	t.Run("the worker successfully processes a message", func(t *testing.T) {
		setupClientSpies(client)
		handler.On("HandleMessage", "bar", "baz").Return().Once()
		worker.Start(ctx, handlerFunc)

		client.AssertExpectations(t)
		handler.AssertExpectations(t)
	})
}

func contextAndCancel() (context.Context, context.CancelFunc) {
	delay := time.Now().Add(1 * time.Millisecond)

	return context.WithDeadline(context.Background(), delay)
}

func setupMockedSqsClient(awsConfig *aws.Config) *mockedSqsClient {
	sqsMessage := &sqs.Message{Body: aws.String(`{ "foo": "bar", "qux": "baz" }`)}
	sqsResponse := sqs.ReceiveMessageOutput{
		Messages: []*sqs.Message{sqsMessage},
	}

	return &mockedSqsClient{Response: sqsResponse, Config: awsConfig}
}

func setupClientSpies(client *mockedSqsClient) {
	url := aws.String("https://sqs.eu-west-1.amazonaws.com/123456789/my-sqs-queue")
	receiveInput := &sqs.ReceiveMessageInput{
		QueueUrl:            url,
		MaxNumberOfMessages: aws.Int64(10),
		AttributeNames: []*string{
			aws.String("All"),
		},
		WaitTimeSeconds: aws.Int64(20),
	}
	client.On("ReceiveMessage", receiveInput).Return()

	deleteInput := &sqs.DeleteMessageInput{
		QueueUrl: url,
	}
	client.On("DeleteMessage", deleteInput).Return()
}
<commit_msg>Add tests for different configuration settings (#10)<commit_after>package worker

import (
	"context"
	"encoding/json"
	"fmt"
	"testing"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/sqs"
	"github.com/aws/aws-sdk-go/service/sqs/sqsiface"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/mock"
)

type mockedSqsClient struct {
	Config   *aws.Config
	Response sqs.ReceiveMessageOutput
	sqsiface.SQSAPI
	mock.Mock
}

func (c *mockedSqsClient) GetQueueUrl(urlInput *sqs.GetQueueUrlInput) (*sqs.GetQueueUrlOutput, error) {
	url := fmt.Sprintf("https://sqs.%v.amazonaws.com/123456789/%v", *c.Config.Region, *urlInput.QueueName)

	return &sqs.GetQueueUrlOutput{QueueUrl: &url}, nil
}

func (c *mockedSqsClient) ReceiveMessage(input *sqs.ReceiveMessageInput) (*sqs.ReceiveMessageOutput, error) {
	c.Called(input)

	return &c.Response, nil
}

func (c *mockedSqsClient) DeleteMessage(input *sqs.DeleteMessageInput) (*sqs.DeleteMessageOutput, error) {
	c.Called(input)
	c.Response = sqs.ReceiveMessageOutput{}

	return &sqs.DeleteMessageOutput{}, nil
}

type mockedHandler struct {
	mock.Mock
}

func (mh *mockedHandler) HandleMessage(foo string, qux string) {
	mh.Called(foo, qux)
}

type sqsEvent struct {
	Foo string `json:"foo"`
	Qux string `json:"qux"`
}

const maxNumberOfMessages = 1984
const waitTimeSecond = 1337

func TestStart(t *testing.T) {
	region := "eu-west-1"
	awsConfig := &aws.Config{Region: &region}
	workerConfig := &Config{
		MaxNumberOfMessage: maxNumberOfMessages,
		QueueName:          "my-sqs-queue",
		WaitTimeSecond:     waitTimeSecond,
	}

	clientParams := buildClientParams()
	sqsMessage := &sqs.Message{Body: aws.String(`{ "foo": "bar", "qux": "baz" }`)}
	sqsResponse := sqs.ReceiveMessageOutput{Messages: []*sqs.Message{sqsMessage}}
	client := &mockedSqsClient{Response: sqsResponse, Config: awsConfig}
	deleteInput := &sqs.DeleteMessageInput{QueueUrl: clientParams.QueueUrl}

	worker := New(client, workerConfig)

	ctx, cancel := contextAndCancel()
	defer cancel()

	handler := new(mockedHandler)
	handlerFunc := HandlerFunc(func(msg *sqs.Message) (err error) {
		event := &sqsEvent{}

		json.Unmarshal([]byte(aws.StringValue(msg.Body)), event)

		handler.HandleMessage(event.Foo, event.Qux)

		return
	})

	t.Run("the worker has correct configuration", func(t *testing.T) {
		assert.Equal(t, worker.Config.QueueName, "my-sqs-queue", "QueueName has been set properly")
		assert.Equal(t, worker.Config.QueueURL, "https://sqs.eu-west-1.amazonaws.com/123456789/my-sqs-queue", "QueueURL has been set properly")
		assert.Equal(t, worker.Config.MaxNumberOfMessage, int64(maxNumberOfMessages), "MaxNumberOfMessage has been set properly")
		assert.Equal(t, worker.Config.WaitTimeSecond, int64(waitTimeSecond), "WaitTimeSecond has been set properly")
	})

	t.Run("the worker has correct default configuration", func(t *testing.T) {
		minimumConfig := &Config{
			QueueName: "my-sqs-queue",
		}
		worker := New(client, minimumConfig)

		assert.Equal(t, worker.Config.QueueName, "my-sqs-queue", "QueueName has been set properly")
		assert.Equal(t, worker.Config.QueueURL, "https://sqs.eu-west-1.amazonaws.com/123456789/my-sqs-queue", "QueueURL has been set properly")
		assert.Equal(t, worker.Config.MaxNumberOfMessage, int64(10), "MaxNumberOfMessage has been set by default")
		assert.Equal(t, worker.Config.WaitTimeSecond, int64(20), "WaitTimeSecond has been set by default")
	})

	t.Run("the worker successfully processes a message", func(t *testing.T) {
		client.On("ReceiveMessage", clientParams).Return()
		client.On("DeleteMessage", deleteInput).Return()
		handler.On("HandleMessage", "bar", "baz").Return().Once()

		worker.Start(ctx, handlerFunc)

		client.AssertExpectations(t)
		handler.AssertExpectations(t)
	})
}

func contextAndCancel() (context.Context, context.CancelFunc) {
	delay := time.Now().Add(1 * time.Millisecond)

	return context.WithDeadline(context.Background(), delay)
}

func buildClientParams() *sqs.ReceiveMessageInput {
	url := aws.String("https://sqs.eu-west-1.amazonaws.com/123456789/my-sqs-queue")

	return &sqs.ReceiveMessageInput{
		QueueUrl:            url,
		MaxNumberOfMessages: aws.Int64(maxNumberOfMessages),
		AttributeNames:      []*string{aws.String("All")},
		WaitTimeSeconds:     aws.Int64(waitTimeSecond),
	}
}
<|endoftext|>


<commit_before>package simulator

// Simulator is the object that coordanates workers for the game computations
type Simulator struct {
	killChan    chan struct{}
	workerQueue chan *Worker
	numWorkers,
	maxWorkers int
	JobChan chan *Job
}

// ListenAndServer listen for new requrests and serve the responses
func (s *Simulator) ListenAndServer() {
	for {

		select {

		case tmp := <-s.JobChan:
			// see if there is an open worker
			select {
			// if there is an open worker, assign the job to that worker and run the job
			case w := <-s.workerQueue:
				w.job = tmp
				go w.job.run()
			// if there is no open worker, but the max number of workers has not been reaches, create a new worker and assign it the job
			default:
				if s.numWorkers < s.maxWorkers {
					w := NewWorker(s)
					w.job = tmp
					go w.job.run()
					s.numWorkers += 1
				} else {
					// if a new worker cannot be created, block until worker is ready
					w := <-s.workerQueue
					w.job = tmp
					go w.job.run()
				}
			}
		// If signal on killChan is recieved, close all channels and return the function.
		case <-s.killChan:
			close(s.JobChan)
			close(s.killChan)
			return
		}
	}
}
<commit_msg>the worker now calles the run function<commit_after>package simulator

// Simulator is the object that coordanates workers for the game computations
type Simulator struct {
	killChan    chan struct{}
	workerQueue chan *Worker
	numWorkers,
	maxWorkers int
	JobChan chan *Job
}

// ListenAndServer listen for new requrests and serve the responses
func (s *Simulator) ListenAndServer() {
	for {

		select {

		case tmp := <-s.JobChan:
			// see if there is an open worker
			select {
			// if there is an open worker, assign the job to that worker and run the job
			case w := <-s.workerQueue:
				w.job = tmp
				go w.job.run()
			// if there is no open worker, but the max number of workers has not been reaches, create a new worker and assign it the job
			default:
				if s.numWorkers < s.maxWorkers {
					w := NewWorker(s)
					w.job = tmp
					go w.Run()
					s.numWorkers += 1
				} else {
					// if a new worker cannot be created, block until a worker is ready
					w := <-s.workerQueue
					w.job = tmp
					go w.Run()
				}
			}
		// If signal on killChan is recieved, close all channels and return the function.
		case <-s.killChan:
			close(s.JobChan)
			close(s.killChan)
			return
		}
	}
}
<|endoftext|>


<commit_before>// Package ws provides components for building web services and automating the processing of web service requests.
package handler

import (
	"github.com/graniticio/granitic/logging"
	"github.com/graniticio/granitic/ws"
	"net/http"
	"regexp"
)

//Implements HttpEndpointProvider
type WsHandler struct {
	AccessChecker         ws.WsAccessChecker //
	AllowDirectHTTPAccess bool // Whether or not the underlying HTTP request and response writer should be made available to request Logic.
	AutoBindQuery         bool // Whether or not query parameters should be automatically injected into the request body.
	BindPathParams        []string // A list of fields on the request body that should be populated using elements of the request path.
	CheckAccessAfterParse bool // Check caller's permissions after request has been parsed (true) or before parsing (false).
	DeferFrameworkErrors  bool // If true, do not automatically return an error response if errors are found during the automated phases of request processing.
	DisableQueryParsing   bool // If true, discard the request's query parameters.
	DisablePathParsing    bool // If true, discard any path parameters found by match the request URI against the PathMatchPattern regex.
	ErrorFinder           ws.ServiceErrorFinder // An object that provides access to application defined error messages for use during validation.
	FieldQueryParam       map[string]string // A map of fields on the request body object and the names of query parameters that should be used to populate them
	FrameworkErrors       *ws.FrameworkErrorGenerator // An object that provides access to built-in error messages to use when an error is found during the automated phases of request processing.
	HttpMethod            string // The HTTP method (GET, POST etc) that this handler supports.
	Log                   logging.Logger //
	Logic                 ws.WsRequestProcessor // The object representing the 'logic' behind this handler.
	ParamBinder           *ws.ParamBinder //
	PathMatchPattern      string // A regex that will be matched against inbound request paths to check if this handler should be used to service the request.
	ResponseWriter        ws.WsResponseWriter //
	RequireAuthentication bool // Whether on not the caller needs to be authenticated (using a ws.WsIdentifier) in order to access the logic behind this handler.
	Unmarshaller          ws.WsUnmarshaller //
	UserIdentifier        ws.WsIdentifier //
	bindPathParams        bool
	bindQuery             bool
	httpMethods           []string
	componentName         string
	pathRegex             *regexp.Regexp
	validate              bool
	validator             ws.WsRequestValidator
}

func (wh *WsHandler) ProvideErrorFinder(finder ws.ServiceErrorFinder) {
	wh.ErrorFinder = finder
}

//HttpEndpointProvider
func (wh *WsHandler) ServeHTTP(w *ws.WsHTTPResponseWriter, req *http.Request) ws.WsIdentity {

	defer func() {
		if r := recover(); r != nil {
			wh.Log.LogErrorfWithTrace("Panic recovered while trying process a request or write its response %s", r)
			wh.writePanicResponse(r, w)
		}
	}()

	wsReq := new(ws.WsRequest)
	wsReq.HttpMethod = req.Method

	if wh.AllowDirectHTTPAccess {
		da := new(ws.DirectHTTPAccess)
		da.Request = req
		da.ResponseWriter = w

		wsReq.UnderlyingHTTP = da
	}

	//Try to identify and/or authenticate the caller
	if !wh.identifyAndAuthenticate(w, req, wsReq) {
		return wsReq.UserIdentity
	}

	//Check caller has permission to use this resource
	if !wh.CheckAccessAfterParse && !wh.checkAccess(w, wsReq) {
		return wsReq.UserIdentity
	}

	//Unmarshall body, query parameters and path parameters
	wh.unmarshall(req, wsReq)
	wh.processQueryParams(req, wsReq)
	wh.processPathParams(req, wsReq)

	if wsReq.HasFrameworkErrors() && !wh.DeferFrameworkErrors {
		wh.handleFrameworkErrors(w, wsReq)
		return wsReq.UserIdentity
	}

	//Check caller has permission to use this resource
	if wh.CheckAccessAfterParse && !wh.checkAccess(w, wsReq) {
		return wsReq.UserIdentity
	}

	//Validate request
	var errors ws.ServiceErrors
	errors.ErrorFinder = wh.ErrorFinder

	if wh.validate {
		wh.validator.Validate(&errors, wsReq)
	}

	if errors.HasErrors() {
		wh.writeErrorResponse(&errors, w)

		return wsReq.UserIdentity
	}

	//Execute logic
	wh.process(wsReq, w)

	return wsReq.UserIdentity
}

func (wh *WsHandler) unmarshall(req *http.Request, wsReq *ws.WsRequest) {

	targetSource, found := wh.Logic.(ws.WsUnmarshallTarget)

	if found {
		target := targetSource.UnmarshallTarget()
		wsReq.RequestBody = target

		if req.ContentLength == 0 {
			return
		}

		err := wh.Unmarshaller.Unmarshall(req, wsReq)

		if err != nil {

			wh.Log.LogDebugf("Error unmarshalling request body for %s %s %s", req.URL.Path, req.Method, err)

			m, c := wh.FrameworkErrors.MessageCode(ws.UnableToParseRequest)

			f := ws.NewUnmarshallWsFrameworkError(m, c)
			wsReq.AddFrameworkError(f)
		}

	}
}

func (wh *WsHandler) processPathParams(req *http.Request, wsReq *ws.WsRequest) {

	if wh.DisablePathParsing {
		return
	}

	re := wh.pathRegex
	params := re.FindStringSubmatch(req.URL.Path)
	wsReq.PathParams = params[1:]

	if wh.bindPathParams && len(wsReq.PathParams) > 0 {
		pp := ws.NewWsParamsForPath(wh.BindPathParams, wsReq.PathParams)
		wh.ParamBinder.AutoBindPathParameters(wsReq, pp)
	}

}

func (wh *WsHandler) processQueryParams(req *http.Request, wsReq *ws.WsRequest) {

	if wh.DisableQueryParsing {
		return
	}

	values := req.URL.Query()
	wsReq.QueryParams = ws.NewWsParamsForQuery(values)

	if wh.bindQuery {
		if wsReq.RequestBody == nil {
			wh.Log.LogErrorf("Query parameter binding is enabled, but no target available to bind into. Does your Logic component implement the WsUnmarshallTarget interface?")
			return
		}

		if wh.AutoBindQuery {
			wh.ParamBinder.AutoBindQueryParameters(wsReq)
		} else {
			wh.ParamBinder.BindQueryParameters(wsReq, wh.FieldQueryParam)
		}

	}

}

func (wh *WsHandler) checkAccess(w *ws.WsHTTPResponseWriter, wsReq *ws.WsRequest) bool {

	ac := wh.AccessChecker

	if ac == nil {
		return true
	}

	allowed := ac.Allowed(wsReq)

	if allowed {
		return true
	} else {
		wh.ResponseWriter.WriteAbnormalStatus(http.StatusForbidden, w)
		return false
	}
}

func (wh *WsHandler) identifyAndAuthenticate(w *ws.WsHTTPResponseWriter, req *http.Request, wsReq *ws.WsRequest) bool {

	if wh.UserIdentifier != nil {
		i := wh.UserIdentifier.Identify(req)
		wsReq.UserIdentity = i

		if wh.RequireAuthentication && !i.Authenticated() {
			wh.ResponseWriter.WriteAbnormalStatus(http.StatusUnauthorized, w)
			return false
		}

	}

	if wsReq.UserIdentity == nil {
		wsReq.UserIdentity = ws.NewAnonymousIdentity()
	}

	return true

}

//HttpEndpointProvider
func (wh *WsHandler) SupportedHttpMethods() []string {
	if len(wh.httpMethods) > 0 {
		return wh.httpMethods
	} else {
		return []string{wh.HttpMethod}
	}
}

//HttpEndpointProvider
func (wh *WsHandler) RegexPattern() string {
	return wh.PathMatchPattern
}

func (wh *WsHandler) handleFrameworkErrors(w *ws.WsHTTPResponseWriter, wsReq *ws.WsRequest) {

	var se ws.ServiceErrors
	se.HttpStatus = http.StatusBadRequest

	for _, fe := range wsReq.FrameworkErrors {
		se.AddNewError(ws.Client, fe.Code, fe.Message)
	}

	wh.writeErrorResponse(&se, w)

}

func (wh *WsHandler) process(jsonReq *ws.WsRequest, w *ws.WsHTTPResponseWriter) {

	defer func() {
		if r := recover(); r != nil {
			wh.Log.LogErrorfWithTrace("Panic recovered while trying process a request or write its response %s", r)
			wh.writePanicResponse(r, w)
		}
	}()

	wsRes := ws.NewWsResponse(wh.ErrorFinder)
	wh.Logic.Process(jsonReq, wsRes)

	wh.ResponseWriter.Write(wsRes, w)

}

func (wh *WsHandler) writeErrorResponse(errors *ws.ServiceErrors, w *ws.WsHTTPResponseWriter) {

	l := wh.Log

	defer func() {
		if r := recover(); r != nil {
			l.LogErrorfWithTrace("Panic recovered while trying to write a response that was already in error %s", r)
		}
	}()

	err := wh.ResponseWriter.WriteErrors(errors, w)

	if err != nil {
		l.LogErrorf("Problem writing an HTTP response that was already in error", err)
	}

}

func (wh *WsHandler) writePanicResponse(r interface{}, w *ws.WsHTTPResponseWriter) {

	wh.ResponseWriter.WriteAbnormalStatus(http.StatusInternalServerError, w)

	wh.Log.LogErrorf("Panic recovered but error response served. %s", r)

}

func (wh *WsHandler) StartComponent() error {

	validator, found := wh.Logic.(ws.WsRequestValidator)

	wh.validate = found

	if found {
		wh.validator = validator
	}

	wh.bindQuery = wh.AutoBindQuery || (wh.FieldQueryParam != nil && len(wh.FieldQueryParam) > 0)

	if !wh.DisablePathParsing {

		wh.bindPathParams = len(wh.BindPathParams) > 0

		r, err := regexp.Compile(wh.PathMatchPattern)

		if err != nil {
			return err
		} else {
			wh.pathRegex = r
		}

	}

	return nil

}

func (wh *WsHandler) ComponentName() string {
	return wh.componentName
}

func (wh *WsHandler) SetComponentName(name string) {
	wh.componentName = name
}

<commit_msg>Refactoring packaging of WsHandler<commit_after>package handler

import (
	"github.com/graniticio/granitic/logging"
	"github.com/graniticio/granitic/ws"
	"net/http"
	"regexp"
)

//Implements HttpEndpointProvider
type WsHandler struct {
	AccessChecker         ws.WsAccessChecker //
	AllowDirectHTTPAccess bool // Whether or not the underlying HTTP request and response writer should be made available to request Logic.
	AutoBindQuery         bool // Whether or not query parameters should be automatically injected into the request body.
	BindPathParams        []string // A list of fields on the request body that should be populated using elements of the request path.
	CheckAccessAfterParse bool // Check caller's permissions after request has been parsed (true) or before parsing (false).
	DeferFrameworkErrors  bool // If true, do not automatically return an error response if errors are found during the automated phases of request processing.
	DisableQueryParsing   bool // If true, discard the request's query parameters.
	DisablePathParsing    bool // If true, discard any path parameters found by match the request URI against the PathMatchPattern regex.
	ErrorFinder           ws.ServiceErrorFinder // An object that provides access to application defined error messages for use during validation.
	FieldQueryParam       map[string]string // A map of fields on the request body object and the names of query parameters that should be used to populate them
	FrameworkErrors       *ws.FrameworkErrorGenerator // An object that provides access to built-in error messages to use when an error is found during the automated phases of request processing.
	HttpMethod            string // The HTTP method (GET, POST etc) that this handler supports.
	Log                   logging.Logger //
	Logic                 ws.WsRequestProcessor // The object representing the 'logic' behind this handler.
	ParamBinder           *ws.ParamBinder //
	PathMatchPattern      string // A regex that will be matched against inbound request paths to check if this handler should be used to service the request.
	ResponseWriter        ws.WsResponseWriter //
	RequireAuthentication bool // Whether on not the caller needs to be authenticated (using a ws.WsIdentifier) in order to access the logic behind this handler.
	Unmarshaller          ws.WsUnmarshaller //
	UserIdentifier        ws.WsIdentifier //
	bindPathParams        bool
	bindQuery             bool
	httpMethods           []string
	componentName         string
	pathRegex             *regexp.Regexp
	validate              bool
	validator             ws.WsRequestValidator
}

func (wh *WsHandler) ProvideErrorFinder(finder ws.ServiceErrorFinder) {
	wh.ErrorFinder = finder
}

//HttpEndpointProvider
func (wh *WsHandler) ServeHTTP(w *ws.WsHTTPResponseWriter, req *http.Request) ws.WsIdentity {

	defer func() {
		if r := recover(); r != nil {
			wh.Log.LogErrorfWithTrace("Panic recovered while trying process a request or write its response %s", r)
			wh.writePanicResponse(r, w)
		}
	}()

	wsReq := new(ws.WsRequest)
	wsReq.HttpMethod = req.Method

	if wh.AllowDirectHTTPAccess {
		da := new(ws.DirectHTTPAccess)
		da.Request = req
		da.ResponseWriter = w

		wsReq.UnderlyingHTTP = da
	}

	//Try to identify and/or authenticate the caller
	if !wh.identifyAndAuthenticate(w, req, wsReq) {
		return wsReq.UserIdentity
	}

	//Check caller has permission to use this resource
	if !wh.CheckAccessAfterParse && !wh.checkAccess(w, wsReq) {
		return wsReq.UserIdentity
	}

	//Unmarshall body, query parameters and path parameters
	wh.unmarshall(req, wsReq)
	wh.processQueryParams(req, wsReq)
	wh.processPathParams(req, wsReq)

	if wsReq.HasFrameworkErrors() && !wh.DeferFrameworkErrors {
		wh.handleFrameworkErrors(w, wsReq)
		return wsReq.UserIdentity
	}

	//Check caller has permission to use this resource
	if wh.CheckAccessAfterParse && !wh.checkAccess(w, wsReq) {
		return wsReq.UserIdentity
	}

	//Validate request
	var errors ws.ServiceErrors
	errors.ErrorFinder = wh.ErrorFinder

	if wh.validate {
		wh.validator.Validate(&errors, wsReq)
	}

	if errors.HasErrors() {
		wh.writeErrorResponse(&errors, w)

		return wsReq.UserIdentity
	}

	//Execute logic
	wh.process(wsReq, w)

	return wsReq.UserIdentity
}

func (wh *WsHandler) unmarshall(req *http.Request, wsReq *ws.WsRequest) {

	targetSource, found := wh.Logic.(ws.WsUnmarshallTarget)

	if found {
		target := targetSource.UnmarshallTarget()
		wsReq.RequestBody = target

		if req.ContentLength == 0 {
			return
		}

		err := wh.Unmarshaller.Unmarshall(req, wsReq)

		if err != nil {

			wh.Log.LogDebugf("Error unmarshalling request body for %s %s %s", req.URL.Path, req.Method, err)

			m, c := wh.FrameworkErrors.MessageCode(ws.UnableToParseRequest)

			f := ws.NewUnmarshallWsFrameworkError(m, c)
			wsReq.AddFrameworkError(f)
		}

	}
}

func (wh *WsHandler) processPathParams(req *http.Request, wsReq *ws.WsRequest) {

	if wh.DisablePathParsing {
		return
	}

	re := wh.pathRegex
	params := re.FindStringSubmatch(req.URL.Path)
	wsReq.PathParams = params[1:]

	if wh.bindPathParams && len(wsReq.PathParams) > 0 {
		pp := ws.NewWsParamsForPath(wh.BindPathParams, wsReq.PathParams)
		wh.ParamBinder.AutoBindPathParameters(wsReq, pp)
	}

}

func (wh *WsHandler) processQueryParams(req *http.Request, wsReq *ws.WsRequest) {

	if wh.DisableQueryParsing {
		return
	}

	values := req.URL.Query()
	wsReq.QueryParams = ws.NewWsParamsForQuery(values)

	if wh.bindQuery {
		if wsReq.RequestBody == nil {
			wh.Log.LogErrorf("Query parameter binding is enabled, but no target available to bind into. Does your Logic component implement the WsUnmarshallTarget interface?")
			return
		}

		if wh.AutoBindQuery {
			wh.ParamBinder.AutoBindQueryParameters(wsReq)
		} else {
			wh.ParamBinder.BindQueryParameters(wsReq, wh.FieldQueryParam)
		}

	}

}

func (wh *WsHandler) checkAccess(w *ws.WsHTTPResponseWriter, wsReq *ws.WsRequest) bool {

	ac := wh.AccessChecker

	if ac == nil {
		return true
	}

	allowed := ac.Allowed(wsReq)

	if allowed {
		return true
	} else {
		wh.ResponseWriter.WriteAbnormalStatus(http.StatusForbidden, w)
		return false
	}
}

func (wh *WsHandler) identifyAndAuthenticate(w *ws.WsHTTPResponseWriter, req *http.Request, wsReq *ws.WsRequest) bool {

	if wh.UserIdentifier != nil {
		i := wh.UserIdentifier.Identify(req)
		wsReq.UserIdentity = i

		if wh.RequireAuthentication && !i.Authenticated() {
			wh.ResponseWriter.WriteAbnormalStatus(http.StatusUnauthorized, w)
			return false
		}

	}

	if wsReq.UserIdentity == nil {
		wsReq.UserIdentity = ws.NewAnonymousIdentity()
	}

	return true

}

//HttpEndpointProvider
func (wh *WsHandler) SupportedHttpMethods() []string {
	if len(wh.httpMethods) > 0 {
		return wh.httpMethods
	} else {
		return []string{wh.HttpMethod}
	}
}

//HttpEndpointProvider
func (wh *WsHandler) RegexPattern() string {
	return wh.PathMatchPattern
}

func (wh *WsHandler) handleFrameworkErrors(w *ws.WsHTTPResponseWriter, wsReq *ws.WsRequest) {

	var se ws.ServiceErrors
	se.HttpStatus = http.StatusBadRequest

	for _, fe := range wsReq.FrameworkErrors {
		se.AddNewError(ws.Client, fe.Code, fe.Message)
	}

	wh.writeErrorResponse(&se, w)

}

func (wh *WsHandler) process(jsonReq *ws.WsRequest, w *ws.WsHTTPResponseWriter) {

	defer func() {
		if r := recover(); r != nil {
			wh.Log.LogErrorfWithTrace("Panic recovered while trying process a request or write its response %s", r)
			wh.writePanicResponse(r, w)
		}
	}()

	wsRes := ws.NewWsResponse(wh.ErrorFinder)
	wh.Logic.Process(jsonReq, wsRes)

	wh.ResponseWriter.Write(wsRes, w)

}

func (wh *WsHandler) writeErrorResponse(errors *ws.ServiceErrors, w *ws.WsHTTPResponseWriter) {

	l := wh.Log

	defer func() {
		if r := recover(); r != nil {
			l.LogErrorfWithTrace("Panic recovered while trying to write a response that was already in error %s", r)
		}
	}()

	err := wh.ResponseWriter.WriteErrors(errors, w)

	if err != nil {
		l.LogErrorf("Problem writing an HTTP response that was already in error", err)
	}

}

func (wh *WsHandler) writePanicResponse(r interface{}, w *ws.WsHTTPResponseWriter) {

	wh.ResponseWriter.WriteAbnormalStatus(http.StatusInternalServerError, w)

	wh.Log.LogErrorf("Panic recovered but error response served. %s", r)

}

func (wh *WsHandler) StartComponent() error {

	validator, found := wh.Logic.(ws.WsRequestValidator)

	wh.validate = found

	if found {
		wh.validator = validator
	}

	wh.bindQuery = wh.AutoBindQuery || (wh.FieldQueryParam != nil && len(wh.FieldQueryParam) > 0)

	if !wh.DisablePathParsing {

		wh.bindPathParams = len(wh.BindPathParams) > 0

		r, err := regexp.Compile(wh.PathMatchPattern)

		if err != nil {
			return err
		} else {
			wh.pathRegex = r
		}

	}

	return nil

}

func (wh *WsHandler) ComponentName() string {
	return wh.componentName
}

func (wh *WsHandler) SetComponentName(name string) {
	wh.componentName = name
}

<|endoftext|>


<commit_before>package ari

// Bridge represents a communication path to an
// Asterisk server for working with bridge resources
type Bridge interface {

	// Create creates a bridge
	Create(id string, btype string, name string) (*BridgeHandle, error)

	// Get gets the BridgeHandle
	Get(id string) *BridgeHandle

	// Lists returns the lists of bridges in asterisk
	List() ([]*BridgeHandle, error)

	// Data gets the bridge data
	Data(id string) (BridgeData, error)

	// AddChannel adds a channel to the bridge
	AddChannel(bridgeID string, channelID string) error

	// RemoveChannel removes a channel from the bridge
	RemoveChannel(bridgeID string, channelID string) error

	// Delete deletes the bridge
	Delete(id string) error

	// Play plays the media URI to the bridge
	Play(id string, playbackID string, mediaURI string) (*PlaybackHandle, error)

	// Record records the bridge
	Record(id string, name string, opts *RecordingOptions) (*LiveRecordingHandle, error)

	// Subscribe subscribes the given bridge events events
	Subscribe(id string, n ...string) Subscription
}

// BridgeData describes an Asterisk Bridge, the entity which merges media from
// one or more channels into a common audio output
type BridgeData struct {
	ID         string   `json:"id"`           // Unique Id for this bridge
	Class      string   `json:"bridge_class"` // Class of the bridge
	Type       string   `json:"bridge_type"`  // Type of bridge (mixing, holding, dtmf_events, proxy_media)
	ChannelIDs []string `json:"channels"`     // List of pariticipating channel ids
	Creator    string   `json:"creator"`      // Creating entity of the bridge
	Name       string   `json:"name"`         // The name of the bridge
	Technology string   `json:"technology"`   // Name of the bridging technology
}

// NewBridgeHandle creates a new bridge handle
func NewBridgeHandle(id string, b Bridge) *BridgeHandle {
	return &BridgeHandle{
		id: id,
		b:  b,
	}
}

// BridgeHandle is the handle to a bridge for performing operations
type BridgeHandle struct {
	id string
	b  Bridge
}

// ID returns the identifier for the bridge
func (bh *BridgeHandle) ID() string {
	return bh.id
}

// AddChannel adds a channel to the bridge
func (bh *BridgeHandle) AddChannel(channelID string) (err error) {
	err = bh.b.AddChannel(bh.id, channelID)
	return
}

// RemoveChannel removes a channel from the bridge
func (bh *BridgeHandle) RemoveChannel(channelID string) (err error) {
	err = bh.b.RemoveChannel(bh.id, channelID)
	return
}

// Delete deletes the bridge
func (bh *BridgeHandle) Delete(channelID string) (err error) {
	err = bh.b.Delete(bh.id)
	return
}

// Data gets the bridge data
func (bh *BridgeHandle) Data() (bd BridgeData, err error) {
	bd, err = bh.b.Data(bh.id)
	return
}

// Play initiates playback of the specified media uri
// to the bridge, returning the Playback handle
func (bh *BridgeHandle) Play(id string, mediaURI string) (ph *PlaybackHandle, err error) {
	ph, err = bh.b.Play(bh.id, id, mediaURI)
	return
}

// Record records the bridge to the given filename
func (bh *BridgeHandle) Record(name string, opts *RecordingOptions) (rh *LiveRecordingHandle, err error) {
	rh, err = bh.b.Record(bh.id, name, opts)
	return
}

// Playback returns the playback transport
func (bh *BridgeHandle) Playback() Playback {
	if pb, ok := bh.b.(Playbacker); ok {
		return pb.Playback()
	}
	return nil
}

// Subscribe creates a subscription to the list of events
func (bh *BridgeHandle) Subscribe(n ...string) Subscription {
	if bh == nil {
		return nil
	}
	return bh.b.Subscribe(bh.id, n...)
}

// Match returns true if the event matches the bridge
func (bh *BridgeHandle) Match(e Event) bool {
	bridgeEvent, ok := e.(BridgeEvent)
	if !ok {
		return false
	}
	bridgeIDs := bridgeEvent.GetBridgeIDs()
	for _, i := range bridgeIDs {
		if i == bh.id {
			return true
		}
	}
	return false
}
<commit_msg>bh.Delete should not take an argument<commit_after>package ari

// Bridge represents a communication path to an
// Asterisk server for working with bridge resources
type Bridge interface {

	// Create creates a bridge
	Create(id string, btype string, name string) (*BridgeHandle, error)

	// Get gets the BridgeHandle
	Get(id string) *BridgeHandle

	// Lists returns the lists of bridges in asterisk
	List() ([]*BridgeHandle, error)

	// Data gets the bridge data
	Data(id string) (BridgeData, error)

	// AddChannel adds a channel to the bridge
	AddChannel(bridgeID string, channelID string) error

	// RemoveChannel removes a channel from the bridge
	RemoveChannel(bridgeID string, channelID string) error

	// Delete deletes the bridge
	Delete(id string) error

	// Play plays the media URI to the bridge
	Play(id string, playbackID string, mediaURI string) (*PlaybackHandle, error)

	// Record records the bridge
	Record(id string, name string, opts *RecordingOptions) (*LiveRecordingHandle, error)

	// Subscribe subscribes the given bridge events events
	Subscribe(id string, n ...string) Subscription
}

// BridgeData describes an Asterisk Bridge, the entity which merges media from
// one or more channels into a common audio output
type BridgeData struct {
	ID         string   `json:"id"`           // Unique Id for this bridge
	Class      string   `json:"bridge_class"` // Class of the bridge
	Type       string   `json:"bridge_type"`  // Type of bridge (mixing, holding, dtmf_events, proxy_media)
	ChannelIDs []string `json:"channels"`     // List of pariticipating channel ids
	Creator    string   `json:"creator"`      // Creating entity of the bridge
	Name       string   `json:"name"`         // The name of the bridge
	Technology string   `json:"technology"`   // Name of the bridging technology
}

// NewBridgeHandle creates a new bridge handle
func NewBridgeHandle(id string, b Bridge) *BridgeHandle {
	return &BridgeHandle{
		id: id,
		b:  b,
	}
}

// BridgeHandle is the handle to a bridge for performing operations
type BridgeHandle struct {
	id string
	b  Bridge
}

// ID returns the identifier for the bridge
func (bh *BridgeHandle) ID() string {
	return bh.id
}

// AddChannel adds a channel to the bridge
func (bh *BridgeHandle) AddChannel(channelID string) (err error) {
	err = bh.b.AddChannel(bh.id, channelID)
	return
}

// RemoveChannel removes a channel from the bridge
func (bh *BridgeHandle) RemoveChannel(channelID string) (err error) {
	err = bh.b.RemoveChannel(bh.id, channelID)
	return
}

// Delete deletes the bridge
func (bh *BridgeHandle) Delete() (err error) {
	err = bh.b.Delete(bh.id)
	return
}

// Data gets the bridge data
func (bh *BridgeHandle) Data() (bd BridgeData, err error) {
	bd, err = bh.b.Data(bh.id)
	return
}

// Play initiates playback of the specified media uri
// to the bridge, returning the Playback handle
func (bh *BridgeHandle) Play(id string, mediaURI string) (ph *PlaybackHandle, err error) {
	ph, err = bh.b.Play(bh.id, id, mediaURI)
	return
}

// Record records the bridge to the given filename
func (bh *BridgeHandle) Record(name string, opts *RecordingOptions) (rh *LiveRecordingHandle, err error) {
	rh, err = bh.b.Record(bh.id, name, opts)
	return
}

// Playback returns the playback transport
func (bh *BridgeHandle) Playback() Playback {
	if pb, ok := bh.b.(Playbacker); ok {
		return pb.Playback()
	}
	return nil
}

// Subscribe creates a subscription to the list of events
func (bh *BridgeHandle) Subscribe(n ...string) Subscription {
	if bh == nil {
		return nil
	}
	return bh.b.Subscribe(bh.id, n...)
}

// Match returns true if the event matches the bridge
func (bh *BridgeHandle) Match(e Event) bool {
	bridgeEvent, ok := e.(BridgeEvent)
	if !ok {
		return false
	}
	bridgeIDs := bridgeEvent.GetBridgeIDs()
	for _, i := range bridgeIDs {
		if i == bh.id {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>package golis

import (
	"bytes"
	"encoding/binary"
	"errors"
)

//自定义缓存
type Buffer struct {
	b    []byte
	rOff int //读取位置
	wOff int //写入位置
}

//创建Buffer
func NewBuffer() *Buffer {
	return new(Buffer)
}

//获取缓存当前容量
func (b *Buffer) Cap() int {
	return cap(b.b)
}

//当前可读长度
func (b *Buffer) Length() int {
	return b.wOff
}

//重置读取位 置
func (b *Buffer) ResetRead() {
	b.rOff = 0
}

//重置写入位置
func (b *Buffer) ResetWrite() {
	b.wOff = 0
}

//写入bytes数据
func (b *Buffer) PutBytes(buffer []byte) {
	b.b = append(b.b, buffer...)
	b.wOff = len(buffer) + b.wOff
}

//指定位置写入,如果指定写入位置超出了wOff位置,则抛出异常
//如果指定位置已经存在数据并写入数据超出wOff位置则覆盖之前数据，wOff变更最新
//如果指定位置已经存在数据并写入数据没有超出wOff位置则覆盖之前数据，wOff不变
func (b *Buffer) PutBytesAt(pos int, buffer []byte) error {
	willPos := pos + len(buffer)
	if pos > b.wOff {
		return errors.New("pos is out of wOff")
	}
	if willPos > b.wOff {
		copy(b.b[b.wOff:], buffer)
		b.wOff = willPos
	} else {
		copy(b.b[b.wOff:], buffer)
	}
	return nil
}

//将int数据存入缓存
func (b *Buffer) PutInt(i int) {
	x := int32(i)
	bytesBuffer := bytes.NewBuffer([]byte{})
	binary.Write(bytesBuffer, binary.BigEndian, x)
	b.PutBytes(bytesBuffer.Bytes())
}

//将uint32数据放入内存
func (b *Buffer) PutUint32(i uint32) {
	bytesBuffer := bytes.NewBuffer([]byte{})
	binary.Write(bytesBuffer, binary.BigEndian, i)
	b.PutBytes(bytesBuffer.Bytes())
}

//将字符串存入buffer
func (b *Buffer) PutString(s string) {
	b.PutBytes([]byte(s))
}

//读取指定位置开始，指定长度的bytes数据
//如果读取数据位置超出了写入数据的位置，则返回错误
func (b *Buffer) ReadBytesAt(pos, length int) ([]byte, error) {
	if pos > b.wOff {
		return nil, errors.New("pos is out of wOff")
	}
	buffer := make([]byte, length)
	if pos+length > b.wOff {
		copy(buffer, b.b[pos:b.wOff])
		b.rOff = b.wOff
	} else {
		p := pos + length
		copy(buffer, b.b[pos:p])
		b.rOff = p
	}

	return buffer, nil
}

func (b *Buffer) ReadBytes(length int) ([]byte, error) {
	rpos := b.rOff + length
	if rpos > b.wOff {
		return nil, errors.New("ReadBytes out off wOff")
	}
	buf := make([]byte, length)
	copy(buf, b.b[b.rOff:rpos])
	b.rOff = rpos
	return buf, nil
}

//读取int
func (b *Buffer) ReadInt() (int, error) {
	rpos := b.rOff + 4
	if rpos > b.wOff {
		return 0, errors.New("ReadInt out off wOff")
	}
	bytesBuffer := bytes.NewBuffer(b.b[b.rOff:rpos])
	var x int32
	binary.Read(bytesBuffer, binary.BigEndian, &x)
	b.rOff = rpos
	return int(x), nil
}

//读取uint32数据
func (b *Buffer) ReadUint32() (uint32, error) {
	rpos := b.rOff + 4
	if rpos > b.wOff {
		return 0, errors.New("ReadUint32 out off wOff")
	}
	bytesBuffer := bytes.NewBuffer(b.b[b.rOff:rpos])
	var x uint32
	binary.Read(bytesBuffer, binary.BigEndian, &x)
	b.rOff = rpos
	return x, nil
}

//读取字符串
func (b *Buffer) ReadString(length int) (string, error) {
	rpos := b.rOff + length
	if rpos > b.wOff {
		return "", errors.New("ReadString out of wOff")
	}
	s := string(b.b[b.rOff:rpos])
	b.rOff = rpos
	return s, nil
}
<commit_msg>修改buffer调用<commit_after>package golis

import (
	"bytes"
	"encoding/binary"
	"errors"
)

//自定义缓存
type Buffer struct {
	b    []byte
	rOff int //读取位置
	wOff int //写入位置
}

//创建Buffer
func NewBuffer() *Buffer {
	return new(Buffer)
}

//获取缓存当前容量
func (b *Buffer) Cap() int {
	return cap(b.b)
}

//当前可读长度
func (b *Buffer) ReadLength() int {
	return b.wOff - b.rOff
}

//重置读取位置
func (b *Buffer) ResetRead() {
	b.rOff = 0
}

//获取读取位置
func (b *Buffer) GetReadPos() int {
	return b.rOff
}

func (b *Buffer) SetReadPos(pos int) error {
	if pos > b.wOff {
		return errors.New("ResetReadAt is out of error")
	}
	b.rOff = pos
	return nil
}

//重置写入位置
func (b *Buffer) ResetWrite() {
	b.wOff = 0
}

//写入bytes数据
func (b *Buffer) PutBytes(buffer []byte) {
	b.b = append(b.b, buffer...)
	b.wOff = len(buffer) + b.wOff
}

//指定位置写入,如果指定写入位置超出了wOff位置,则抛出异常
//如果指定位置已经存在数据并写入数据超出wOff位置则覆盖之前数据，wOff变更最新
//如果指定位置已经存在数据并写入数据没有超出wOff位置则覆盖之前数据，wOff不变
func (b *Buffer) PutBytesAt(pos int, buffer []byte) error {
	willPos := pos + len(buffer)
	if pos > b.wOff {
		return errors.New("pos is out of wOff")
	}
	if willPos > b.wOff {
		copy(b.b[b.wOff:], buffer)
		b.wOff = willPos
	} else {
		copy(b.b[b.wOff:], buffer)
	}
	return nil
}

//将int数据存入缓存
func (b *Buffer) PutInt(i int) {
	x := int32(i)
	bytesBuffer := bytes.NewBuffer([]byte{})
	binary.Write(bytesBuffer, binary.BigEndian, x)
	b.PutBytes(bytesBuffer.Bytes())
}

//将uint32数据放入内存
func (b *Buffer) PutUint32(i uint32) {
	bytesBuffer := bytes.NewBuffer([]byte{})
	binary.Write(bytesBuffer, binary.BigEndian, i)
	b.PutBytes(bytesBuffer.Bytes())
}

//将字符串存入buffer
func (b *Buffer) PutString(s string) {
	b.PutBytes([]byte(s))
}

//读取指定位置开始，指定长度的bytes数据
//如果读取数据位置超出了写入数据的位置，则返回错误
func (b *Buffer) ReadBytesAt(pos, length int) ([]byte, error) {
	if pos > b.wOff {
		return nil, errors.New("pos is out of wOff")
	}
	buffer := make([]byte, length)
	if pos+length > b.wOff {
		copy(buffer, b.b[pos:b.wOff])
		b.rOff = b.wOff
	} else {
		p := pos + length
		copy(buffer, b.b[pos:p])
		b.rOff = p
	}

	return buffer, nil
}

func (b *Buffer) ReadBytes(length int) ([]byte, error) {
	rpos := b.rOff + length
	if rpos > b.wOff {
		return nil, errors.New("ReadBytes out off wOff")
	}
	buf := make([]byte, length)
	copy(buf, b.b[b.rOff:rpos])
	b.rOff = rpos
	return buf, nil
}

//读取int
func (b *Buffer) ReadInt() (int, error) {
	rpos := b.rOff + 4
	if rpos > b.wOff {
		return 0, errors.New("ReadInt out off wOff")
	}
	bytesBuffer := bytes.NewBuffer(b.b[b.rOff:rpos])
	var x int32
	binary.Read(bytesBuffer, binary.BigEndian, &x)
	b.rOff = rpos
	return int(x), nil
}

//读取uint32数据
func (b *Buffer) ReadUint32() (uint32, error) {
	rpos := b.rOff + 4
	if rpos > b.wOff {
		return 0, errors.New("ReadUint32 out off wOff")
	}
	bytesBuffer := bytes.NewBuffer(b.b[b.rOff:rpos])
	var x uint32
	binary.Read(bytesBuffer, binary.BigEndian, &x)
	b.rOff = rpos
	return x, nil
}

//读取字符串
func (b *Buffer) ReadString(length int) (string, error) {
	rpos := b.rOff + length
	if rpos > b.wOff {
		return "", errors.New("ReadString out of wOff")
	}
	s := string(b.b[b.rOff:rpos])
	b.rOff = rpos
	return s, nil
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2015 The heketi 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 glusterfs

import (
	"bytes"
	"encoding/gob"
	"github.com/boltdb/bolt"
	"github.com/gorilla/mux"
	"github.com/heketi/heketi/tests"
	"github.com/heketi/heketi/utils"
	"net/http"
	"net/http/httptest"
	"os"
	"testing"
)

func init() {
	// turn off logging
	logger.SetLevel(utils.LEVEL_NOLOG)
}

func TestClusterCreateBadJsonRequest(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Patch dbfilename so that it is restored at the end of the tests
	defer tests.Patch(&dbfilename, tmpfile).Restore()

	// Create the app
	app := NewApp()
	defer app.Close()
	router := mux.NewRouter()
	app.SetRoutes(router)

	// Setup the server
	ts := httptest.NewServer(router)
	defer ts.Close()

	// ClusterCreate JSON Request
	request := []byte(`{
		some really bad json code
    }`)

	// Post nothing
	r, err := http.Post(ts.URL+"/clusters", "application/json", bytes.NewBuffer(request))
	tests.Assert(t, err == nil)
	tests.Assert(t, r.StatusCode == 422)

}

func TestClusterCreateEmptyRequest(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Patch dbfilename so that it is restored at the end of the tests
	defer tests.Patch(&dbfilename, tmpfile).Restore()

	// Create the app
	app := NewApp()
	defer app.Close()
	router := mux.NewRouter()
	app.SetRoutes(router)

	// Setup the server
	ts := httptest.NewServer(router)
	defer ts.Close()

	// ClusterCreate JSON Request
	request := []byte(`{
    }`)

	// Post nothing
	r, err := http.Post(ts.URL+"/clusters", "application/json", bytes.NewBuffer(request))
	tests.Assert(t, err == nil)
	tests.Assert(t, r.StatusCode == http.StatusCreated)

	// Read JSON
	var msg ClusterInfoResponse
	err = utils.GetJsonFromResponse(r, &msg)
	tests.Assert(t, err == nil)

	// Test JSON
	tests.Assert(t, msg.Id == msg.Name)
	tests.Assert(t, len(msg.Nodes) == 0)
	tests.Assert(t, len(msg.Volumes) == 0)

	// Check that the data on the database is recorded correctly
	var entrybytes []byte
	err = app.db.View(func(tx *bolt.Tx) error {
		entrybytes = tx.Bucket([]byte(BOLTDB_BUCKET_CLUSTER)).Get([]byte(msg.Id))
		return nil
	})
	tests.Assert(t, err == nil)

	// Unmarshal
	var entry ClusterEntry
	dec := gob.NewDecoder(bytes.NewReader(entrybytes))
	err = dec.Decode(&entry)
	tests.Assert(t, err == nil)

	// Make sure they entries are euqal
	tests.Assert(t, entry.Info.Id == msg.Id)
	tests.Assert(t, entry.Info.Name == msg.Name)
	tests.Assert(t, len(entry.Info.Volumes) == 0)
	tests.Assert(t, len(entry.Info.Nodes) == 0)
}

func TestClusterCreateWithName(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Patch dbfilename so that it is restored at the end of the tests
	defer tests.Patch(&dbfilename, tmpfile).Restore()

	// Create the app
	app := NewApp()
	defer app.Close()
	router := mux.NewRouter()
	app.SetRoutes(router)

	// Setup the server
	ts := httptest.NewServer(router)
	defer ts.Close()

	// ClusterCreate JSON Request
	request := []byte(`{
        "name" : "test_name"
    }`)

	// Request
	r, err := http.Post(ts.URL+"/clusters", "application/json", bytes.NewBuffer(request))
	tests.Assert(t, r.StatusCode == http.StatusCreated)
	tests.Assert(t, err == nil)

	// Read JSON
	var msg ClusterInfoResponse
	err = utils.GetJsonFromResponse(r, &msg)
	tests.Assert(t, err == nil)

	// Test JSON
	tests.Assert(t, msg.Id != msg.Name)
	tests.Assert(t, "test_name" == msg.Name)
	tests.Assert(t, len(msg.Nodes) == 0)
	tests.Assert(t, len(msg.Volumes) == 0)

	// Check that the data on the database is recorded correctly
	var entrybytes []byte
	err = app.db.View(func(tx *bolt.Tx) error {
		entrybytes = tx.Bucket([]byte(BOLTDB_BUCKET_CLUSTER)).Get([]byte(msg.Id))
		return nil
	})
	tests.Assert(t, err == nil)

	// Unmarshal
	var entry ClusterEntry
	dec := gob.NewDecoder(bytes.NewReader(entrybytes))
	err = dec.Decode(&entry)
	tests.Assert(t, err == nil)

	// Make sure they entries are euqal
	tests.Assert(t, entry.Info.Id == msg.Id)
	tests.Assert(t, entry.Info.Name == msg.Name)
	tests.Assert(t, len(entry.Info.Volumes) == 0)
	tests.Assert(t, len(entry.Info.Nodes) == 0)
}
<commit_msg>ClusterList unittest<commit_after>//
// Copyright (c) 2015 The heketi 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 glusterfs

import (
	"bytes"
	"encoding/gob"
	"errors"
	"fmt"
	"github.com/boltdb/bolt"
	"github.com/gorilla/mux"
	"github.com/heketi/heketi/tests"
	"github.com/heketi/heketi/utils"
	"net/http"
	"net/http/httptest"
	"os"
	"testing"
)

func init() {
	// turn off logging
	logger.SetLevel(utils.LEVEL_NOLOG)
}

func TestClusterCreateBadJsonRequest(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Patch dbfilename so that it is restored at the end of the tests
	defer tests.Patch(&dbfilename, tmpfile).Restore()

	// Create the app
	app := NewApp()
	defer app.Close()
	router := mux.NewRouter()
	app.SetRoutes(router)

	// Setup the server
	ts := httptest.NewServer(router)
	defer ts.Close()

	// ClusterCreate JSON Request
	request := []byte(`{
		some really bad json code
    }`)

	// Post nothing
	r, err := http.Post(ts.URL+"/clusters", "application/json", bytes.NewBuffer(request))
	tests.Assert(t, err == nil)
	tests.Assert(t, r.StatusCode == 422)

}

func TestClusterCreateEmptyRequest(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Patch dbfilename so that it is restored at the end of the tests
	defer tests.Patch(&dbfilename, tmpfile).Restore()

	// Create the app
	app := NewApp()
	defer app.Close()
	router := mux.NewRouter()
	app.SetRoutes(router)

	// Setup the server
	ts := httptest.NewServer(router)
	defer ts.Close()

	// ClusterCreate JSON Request
	request := []byte(`{
    }`)

	// Post nothing
	r, err := http.Post(ts.URL+"/clusters", "application/json", bytes.NewBuffer(request))
	tests.Assert(t, err == nil)
	tests.Assert(t, r.StatusCode == http.StatusCreated)

	// Read JSON
	var msg ClusterInfoResponse
	err = utils.GetJsonFromResponse(r, &msg)
	tests.Assert(t, err == nil)

	// Test JSON
	tests.Assert(t, msg.Id == msg.Name)
	tests.Assert(t, len(msg.Nodes) == 0)
	tests.Assert(t, len(msg.Volumes) == 0)

	// Check that the data on the database is recorded correctly
	var entrybytes []byte
	err = app.db.View(func(tx *bolt.Tx) error {
		entrybytes = tx.Bucket([]byte(BOLTDB_BUCKET_CLUSTER)).Get([]byte(msg.Id))
		return nil
	})
	tests.Assert(t, err == nil)

	// Unmarshal
	var entry ClusterEntry
	dec := gob.NewDecoder(bytes.NewReader(entrybytes))
	err = dec.Decode(&entry)
	tests.Assert(t, err == nil)

	// Make sure they entries are euqal
	tests.Assert(t, entry.Info.Id == msg.Id)
	tests.Assert(t, entry.Info.Name == msg.Name)
	tests.Assert(t, len(entry.Info.Volumes) == 0)
	tests.Assert(t, len(entry.Info.Nodes) == 0)
}

func TestClusterCreateWithName(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Patch dbfilename so that it is restored at the end of the tests
	defer tests.Patch(&dbfilename, tmpfile).Restore()

	// Create the app
	app := NewApp()
	defer app.Close()
	router := mux.NewRouter()
	app.SetRoutes(router)

	// Setup the server
	ts := httptest.NewServer(router)
	defer ts.Close()

	// ClusterCreate JSON Request
	request := []byte(`{
        "name" : "test_name"
    }`)

	// Request
	r, err := http.Post(ts.URL+"/clusters", "application/json", bytes.NewBuffer(request))
	tests.Assert(t, r.StatusCode == http.StatusCreated)
	tests.Assert(t, err == nil)

	// Read JSON
	var msg ClusterInfoResponse
	err = utils.GetJsonFromResponse(r, &msg)
	tests.Assert(t, err == nil)

	// Test JSON
	tests.Assert(t, msg.Id != msg.Name)
	tests.Assert(t, "test_name" == msg.Name)
	tests.Assert(t, len(msg.Nodes) == 0)
	tests.Assert(t, len(msg.Volumes) == 0)

	// Check that the data on the database is recorded correctly
	var entrybytes []byte
	err = app.db.View(func(tx *bolt.Tx) error {
		entrybytes = tx.Bucket([]byte(BOLTDB_BUCKET_CLUSTER)).Get([]byte(msg.Id))
		return nil
	})
	tests.Assert(t, err == nil)

	// Unmarshal
	var entry ClusterEntry
	dec := gob.NewDecoder(bytes.NewReader(entrybytes))
	err = dec.Decode(&entry)
	tests.Assert(t, err == nil)

	// Make sure they entries are euqal
	tests.Assert(t, entry.Info.Id == msg.Id)
	tests.Assert(t, entry.Info.Name == msg.Name)
	tests.Assert(t, len(entry.Info.Volumes) == 0)
	tests.Assert(t, len(entry.Info.Nodes) == 0)
}

func TestClusterList(t *testing.T) {
	tmpfile := tests.Tempfile()
	defer os.Remove(tmpfile)

	// Patch dbfilename so that it is restored at the end of the tests
	defer tests.Patch(&dbfilename, tmpfile).Restore()

	// Create the app
	app := NewApp()
	defer app.Close()
	router := mux.NewRouter()
	app.SetRoutes(router)

	// Setup the server
	ts := httptest.NewServer(router)
	defer ts.Close()

	// Save some objects in the database
	numclusters := 5
	err := app.db.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(BOLTDB_BUCKET_CLUSTER))
		if b == nil {
			return errors.New("Unable to open bucket")
		}

		for i := 0; i < numclusters; i++ {
			var buffer bytes.Buffer
			var entry ClusterEntry

			entry.Info.Id = fmt.Sprintf("%v", 5000+i)
			entry.Info.Name = entry.Info.Id

			enc := gob.NewEncoder(&buffer)
			err := enc.Encode(entry)
			if err != nil {
				return err
			}

			err = b.Put([]byte(entry.Info.Id), buffer.Bytes())
			if err != nil {
				return err
			}
		}

		return nil

	})
	tests.Assert(t, err == nil)

	// Now that we have some data in the database, we can
	// make a request for the clutser list
	r, err := http.Get(ts.URL + "/clusters")
	tests.Assert(t, r.StatusCode == http.StatusOK)
	tests.Assert(t, err == nil)
	tests.Assert(t, r.Header.Get("Content-Type") == "application/json; charset=UTF-8")

	// Read response
	var msg ClusterListResponse
	err = utils.GetJsonFromResponse(r, &msg)
	tests.Assert(t, err == nil)

	// Thanks to BoltDB they come back in order
	mockid := 5000 // This is the mock id value we set above
	for _, id := range msg.Clusters {
		tests.Assert(t, id == fmt.Sprintf("%v", mockid))
		mockid++
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
	"text/template"
	"launchpad.net/goyaml"

	"github.com/shxsun/flags"
	"github.com/shxsun/go-sh"
)

type Option struct {
	Template string `short:"t" long:"template" default:"shxsun/gails-default" description:"use which template(templale should on github)"`
}

var (
	mycnf   = &Option{}
	args    []string
	funcMap template.FuncMap
)

// ORMName, Type, Name
/*
var tmpl = `
		/* XXXX
		{{ range . }}v.{{.Name}} = this.Get{{.Type|title}}("{{.ORMName}}")
		{{ end }}

		type Book struct {
			ID int64 json
			{{ range . }}{{.Name}}  {{.Type}} xorm:"{{.ORMName}}"
			{{ end }}
		}
		XXXX */

type Column struct {
	Name    string
	Type    string
	ORMName string
}

func ignore(info os.FileInfo) bool {
	if info.IsDir() {
		if info.Name() != "." && info.Name() != ".." &&
			strings.HasPrefix(info.Name(), ".") { // ignore hidden dir
			return true
		}
	} else {
		return strings.HasPrefix(info.Name(), ".")
	}
	return false
}

func pathWalk(path string, depth int) (files []string, err error) {
	files = make([]string, 0)
	baseNumSeps := strings.Count(path, string(os.PathSeparator))
	err = filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
		if info.IsDir() {
			pathDepth := strings.Count(path, string(os.PathSeparator)) - baseNumSeps
			if pathDepth > depth {
				return filepath.SkipDir
			}
			if ignore(info) {
				return filepath.SkipDir
			}
		} else if info.Mode().IsRegular() && !ignore(info) {
			files = append(files, path)
			//if matched, _ := regexp.Match(mycnf.Include, []byte(info.Name())); matched { //}
		}
		return nil
	})
	return
}

func init() {
	log.SetFlags(log.Lshortfile | log.LstdFlags)
	var err error
	args, err = flags.Parse(mycnf)
	if len(args) < 2 {
		program := filepath.Base(os.Args[0])
		fmt.Printf(`Usage:
	%s <table> <col:type> [col:type ...]
Example:
	%s book name:string
`, program, program)
		os.Exit(1)
	}
	if err != nil {
		os.Exit(1)
	}
}

func main() {
	// prepare arguments
	patten := regexp.MustCompile(`^(\w+):(string|int)$`)
	vs := make(map[string]interface{}, 0)
	cols := make([]Column, 0)
	vs["Table"] = args[0]
	for _, s := range args[1:] {
		vs := patten.FindStringSubmatch(s)
		if vs == nil {
			log.Fatalf("invalid format: %s", strconv.Quote(s))
		}
		c := Column{}
		c.ORMName, c.Type = vs[1], vs[2]
		c.Name = strings.Title(c.ORMName)
		cols = append(cols, c)
	}
	vs["Cols"] = cols
	pwd, _ := os.Getwd()
	vs["PWD"] = pwd
	vs["PkgPath"] = pwd[len(os.Getenv("GOPATH")+"/src/"):]
	vs["AppName"] = filepath.Base(pwd)

	// render template
	tmpdir, err := ioutil.TempDir("./", "tmp.gails.")
	if err != nil {
		log.Fatal(err)
	}
	defer os.RemoveAll(tmpdir)
	log.Println("use template", mycnf.Template)
	//sh.Command("git", "clone", "https://github.com/"+mycnf.Template, tmpdir).Run()
	sh.Command("git", "clone", "/Users/skyblue/goproj/src/github.com/shxsun/gails-default", tmpdir).Run()

	files, err := pathWalk(tmpdir, 1)
	if err != nil {
		log.Fatal(err)
	}

	// newName func, eg: user.go -- rename -> book.go
	pjoin := func(p string) string { return filepath.Join(tmpdir, p) }
	filemap := readGailsYml(pjoin(".gails.yml"))
	newName := func(file string) string {
		t, ok := filemap[file]
		if !ok {
			return file
		}
		s, err := renderString(t, vs)
		if err != nil {
			log.Fatal(err)
		}
		return s
	}

	// format code
	session := sh.NewSession()
	session.ShowCMD = true
	for _, src := range files {
		//fmt.Println(file)
		orig := src[len(tmpdir)+1:]
		dst := newName(orig)
		if _, exists := fileExists(dst); !exists {
			dstDir := filepath.Dir(dst)
			os.MkdirAll(dstDir, 0755)
			fmt.Println("git://"+orig, "-->", dst)
			if err = renderFile(dst, src, vs); err != nil {
				fmt.Println(err)
				sh.Command("cp", "-v", src, dst).Run()
			}
			// format code
			if strings.HasSuffix(dst, ".go") {
				//session.Command("go", "fmt", file).Run()
			}
		}
	}
}

func init() {
	funcMap = template.FuncMap{
		"title": strings.Title,
	}
}

func fileExists(file string) (os.FileInfo, bool) {
	fi, err := os.Stat(file)
	return fi, err == nil
}
func readGailsYml(file string) (m map[string]string) {
	m = make(map[string]string)
	var err error
	defer func() {
		if err != nil {
			m[".gitignore"] = ".gitignore"
		}
	}()
	data, err := ioutil.ReadFile(file)
	if err != nil {
		return
	}
	err = goyaml.Unmarshal(data, m)
	return
}

func renderString(tmplstr string, v interface{}) (out string, err error) {
	mytmpl := template.New("rdstr").Funcs(funcMap)
	t, err := mytmpl.Parse(tmplstr)
	if err != nil {
		return
	}
	buf := bytes.NewBuffer(nil)
	err = t.Execute(buf, v)
	return string(buf.Bytes()), err
}

func renderFile(dst string, src string, v interface{}) (err error) {
	fmt.Println(src)
	t, err := template.ParseFiles(src)
	if err != nil {
		log.Fatal(err)
	}
	buf := bytes.NewBuffer(nil)
	err = t.Funcs(funcMap).Execute(buf, v)
	if err != nil {
		return
	}
	xxxx := regexp.MustCompile(`.*\s+XXXX.*\n`)
	fi, _ := os.Stat(src)
	out := xxxx.ReplaceAll(buf.Bytes(), []byte(""))
	err = ioutil.WriteFile(dst, out, fi.Mode())
	return
}

func deleteXXXX(filename string) (err error) {
	xxxx := regexp.MustCompile(`.*\s+XXXX.*\n`)
	content, err := ioutil.ReadFile(filename)
	if err != nil {
		return
	}
	fi, _ := os.Stat(filename)
	out := xxxx.ReplaceAll(content, []byte(""))
	err = ioutil.WriteFile(filename, out, fi.Mode())
	return
}
<commit_msg>lunch<commit_after>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
	"text/template"
	"launchpad.net/goyaml"

	"github.com/shxsun/flags"
	"github.com/shxsun/go-sh"
)

type Option struct {
	Template string `short:"t" long:"template" default:"shxsun/gails-default" description:"use which template(templale should on github)"`
}

var (
	mycnf   = &Option{}
	args    []string
	funcMap template.FuncMap
)

// ORMName, Type, Name
/*
var tmpl = `
		/* XXXX
		{{ range . }}v.{{.Name}} = this.Get{{.Type|title}}("{{.ORMName}}")
		{{ end }}

		type Book struct {
			ID int64 json
			{{ range . }}{{.Name}}  {{.Type}} xorm:"{{.ORMName}}"
			{{ end }}
		}
		XXXX */

type Column struct {
	Name    string
	Type    string
	ORMName string
}

func ignore(info os.FileInfo) bool {
	if info.IsDir() {
		if info.Name() != "." && info.Name() != ".." &&
			strings.HasPrefix(info.Name(), ".") { // ignore hidden dir
			return true
		}
	} else {
		return strings.HasPrefix(info.Name(), ".")
	}
	return false
}

func pathWalk(path string, depth int) (files []string, err error) {
	files = make([]string, 0)
	baseNumSeps := strings.Count(path, string(os.PathSeparator))
	err = filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
		if info.IsDir() {
			pathDepth := strings.Count(path, string(os.PathSeparator)) - baseNumSeps
			if pathDepth > depth {
				return filepath.SkipDir
			}
			if ignore(info) {
				return filepath.SkipDir
			}
		} else if info.Mode().IsRegular() && !ignore(info) {
			files = append(files, path)
			//if matched, _ := regexp.Match(mycnf.Include, []byte(info.Name())); matched { //}
		}
		return nil
	})
	return
}

func init() {
	log.SetFlags(log.Lshortfile | log.LstdFlags)
	var err error
	args, err = flags.Parse(mycnf)
	if len(args) < 2 {
		program := filepath.Base(os.Args[0])
		fmt.Printf(`Usage:
	%s <table> <col:type> [col:type ...]
Example:
	%s book name:string
`, program, program)
		os.Exit(1)
	}
	if err != nil {
		os.Exit(1)
	}
}

func main() {
	// prepare arguments
	patten := regexp.MustCompile(`^(\w+):(string|int)$`)
	vs := make(map[string]interface{}, 0)
	cols := make([]Column, 0)
	vs["Table"] = args[0]
	for _, s := range args[1:] {
		vs := patten.FindStringSubmatch(s)
		if vs == nil {
			log.Fatalf("invalid format: %s", strconv.Quote(s))
		}
		c := Column{}
		c.ORMName, c.Type = vs[1], vs[2]
		c.Name = strings.Title(c.ORMName)
		cols = append(cols, c)
	}
	vs["Cols"] = cols
	pwd, _ := os.Getwd()
	vs["PWD"] = pwd
	vs["PkgPath"] = pwd[len(os.Getenv("GOPATH")+"/src/"):]
	vs["AppName"] = filepath.Base(pwd)

	// render template
	tmpdir, err := ioutil.TempDir("./", "tmp.gails.")
	if err != nil {
		log.Fatal(err)
	}
	defer os.RemoveAll(tmpdir)
	log.Println("use template", mycnf.Template)
	//sh.Command("git", "clone", "https://github.com/"+mycnf.Template, tmpdir).Run()
	sh.Command("git", "clone", "/Users/skyblue/goproj/src/github.com/shxsun/gails-default", tmpdir).Run()

	files, err := pathWalk(tmpdir, 1)
	if err != nil {
		log.Fatal(err)
	}

	// newName func, eg: user.go -- rename -> book.go
	pjoin := func(p string) string { return filepath.Join(tmpdir, p) }
	filemap := readGailsYml(pjoin(".gails.yml"))
	newName := func(file string) string {
		t, ok := filemap[file]
		if !ok {
			return file
		}
		s, err := renderString(t, vs)
		if err != nil {
			log.Fatal(err)
		}
		return s
	}

	// format code
	session := sh.NewSession()
	session.ShowCMD = true
	for _, src := range files {
		//fmt.Println(file)
		orig := src[len(tmpdir)+1:]
		dst := newName(orig)
		if _, exists := fileExists(dst); !exists {
			dstDir := filepath.Dir(dst)
			os.MkdirAll(dstDir, 0755)
			fmt.Println("git://"+orig, "-->", dst)
			if err = renderFile(dst, src, vs); err != nil {
				sh.Command("cp", "-v", src, dst).Run()
			}
			// format code
			if strings.HasSuffix(dst, ".go") {
				session.Command("go", "fmt", dst).Run()
			}
		}
	}
}

func init() {
	funcMap = template.FuncMap{
		"title": strings.Title,
	}
}

func fileExists(file string) (os.FileInfo, bool) {
	fi, err := os.Stat(file)
	return fi, err == nil
}
func readGailsYml(file string) (m map[string]string) {
	m = make(map[string]string)
	var err error
	defer func() {
		if err != nil {
			m[".gitignore"] = ".gitignore"
		}
	}()
	data, err := ioutil.ReadFile(file)
	if err != nil {
		return
	}
	err = goyaml.Unmarshal(data, m)
	return
}

func renderString(tmplstr string, v interface{}) (out string, err error) {
	mytmpl := template.New("rdstr").Funcs(funcMap)
	t, err := mytmpl.Parse(tmplstr)
	if err != nil {
		return
	}
	buf := bytes.NewBuffer(nil)
	err = t.Execute(buf, v)
	return string(buf.Bytes()), err
}

func renderFile(dst string, src string, v interface{}) (err error) {
	fmt.Println(src)
	xxxx := regexp.MustCompile(`[^\n]*XXXX[^\n]*\n`)
	nnnn := regexp.MustCompile(`.*NNNN`)
	s, err := ioutil.ReadFile(src)
	if err != nil {
		return
	}
	out := xxxx.ReplaceAll(s, []byte(""))
	out = nnnn.ReplaceAll(out, []byte(""))

	t, err := template.New("rdfile").Funcs(funcMap).Parse(string(out))
	if err != nil {
		log.Fatal(err)
	}
	buf := bytes.NewBuffer(nil)
	err = t.Execute(buf, v)
	if err != nil {
		return
	}
	fi, _ := os.Stat(src)
	err = ioutil.WriteFile(dst, buf.Bytes(), fi.Mode())
	return
}
<|endoftext|>


<commit_before>// Copyright The OpenTelemetry 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 consumererror

import (
	"errors"

	"go.opentelemetry.io/collector/consumer/pdata"
)

// Traces is an error that may carry associated Trace data for a subset of received data
// that faiiled to be processed or sent.
type Traces struct {
	error
	failed pdata.Traces
}

// NewTraces creates a Traces that can encapsulate received data that failed to be processed or sent.
func NewTraces(err error, failed pdata.Traces) error {
	return Traces{
		error:  err,
		failed: failed,
	}
}

// AsTraces finds the first error in err's chain that can be assigned to target. If such an error is found
// it is assigned to target and true is returned, otherwise false is returned.
func AsTraces(err error, target *Traces) bool {
	if err == nil {
		return false
	}
	return errors.As(err, target)
}

// GetTraces returns failed traces from the associated error.
func (err Traces) GetTraces() pdata.Traces {
	return err.failed
}

// Logs is an error that may carry associated Log data for a subset of received data
// that faiiled to be processed or sent.
type Logs struct {
	error
	failed pdata.Logs
}

// NewLogs creates a Logs that can encapsulate received data that failed to be processed or sent.
func NewLogs(err error, failed pdata.Logs) error {
	return Logs{
		error:  err,
		failed: failed,
	}
}

// AsLogs finds the first error in err's chain that can be assigned to target. If such an error is found
// it is assigned to target and true is returned, otherwise false is returned.
func AsLogs(err error, target *Logs) bool {
	if err == nil {
		return false
	}
	return errors.As(err, target)
}

// GetLogs returns failed logs from the associated error.
func (err Logs) GetLogs() pdata.Logs {
	return err.failed
}

// Metrics is an error that may carry associated Metrics data for a subset of received data
// that faiiled to be processed or sent.
type Metrics struct {
	error
	failed pdata.Metrics
}

// NewMetrics creates a Metrics that can encapsulate received data that failed to be processed or sent.
func NewMetrics(err error, failed pdata.Metrics) error {
	return Metrics{
		error:  err,
		failed: failed,
	}
}

// AsMetrics finds the first error in err's chain that can be assigned to target. If such an error is found
// it is assigned to target and true is returned, otherwise false is returned.
func AsMetrics(err error, target *Metrics) bool {
	if err == nil {
		return false
	}
	return errors.As(err, target)
}

// GetMetrics returns failed metrics from the associated error.
func (err Metrics) GetMetrics() pdata.Metrics {
	return err.failed
}
<commit_msg>Small typos in consumererror (#2933)<commit_after>// Copyright The OpenTelemetry 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 consumererror

import (
	"errors"

	"go.opentelemetry.io/collector/consumer/pdata"
)

// Traces is an error that may carry associated Trace data for a subset of received data
// that failed to be processed or sent.
type Traces struct {
	error
	failed pdata.Traces
}

// NewTraces creates a Traces that can encapsulate received data that failed to be processed or sent.
func NewTraces(err error, failed pdata.Traces) error {
	return Traces{
		error:  err,
		failed: failed,
	}
}

// AsTraces finds the first error in err's chain that can be assigned to target. If such an error is found
// it is assigned to target and true is returned, otherwise false is returned.
func AsTraces(err error, target *Traces) bool {
	if err == nil {
		return false
	}
	return errors.As(err, target)
}

// GetTraces returns failed traces from the associated error.
func (err Traces) GetTraces() pdata.Traces {
	return err.failed
}

// Logs is an error that may carry associated Log data for a subset of received data
// that failed to be processed or sent.
type Logs struct {
	error
	failed pdata.Logs
}

// NewLogs creates a Logs that can encapsulate received data that failed to be processed or sent.
func NewLogs(err error, failed pdata.Logs) error {
	return Logs{
		error:  err,
		failed: failed,
	}
}

// AsLogs finds the first error in err's chain that can be assigned to target. If such an error is found
// it is assigned to target and true is returned, otherwise false is returned.
func AsLogs(err error, target *Logs) bool {
	if err == nil {
		return false
	}
	return errors.As(err, target)
}

// GetLogs returns failed logs from the associated error.
func (err Logs) GetLogs() pdata.Logs {
	return err.failed
}

// Metrics is an error that may carry associated Metrics data for a subset of received data
// that failed to be processed or sent.
type Metrics struct {
	error
	failed pdata.Metrics
}

// NewMetrics creates a Metrics that can encapsulate received data that failed to be processed or sent.
func NewMetrics(err error, failed pdata.Metrics) error {
	return Metrics{
		error:  err,
		failed: failed,
	}
}

// AsMetrics finds the first error in err's chain that can be assigned to target. If such an error is found
// it is assigned to target and true is returned, otherwise false is returned.
func AsMetrics(err error, target *Metrics) bool {
	if err == nil {
		return false
	}
	return errors.As(err, target)
}

// GetMetrics returns failed metrics from the associated error.
func (err Metrics) GetMetrics() pdata.Metrics {
	return err.failed
}
<|endoftext|>


<commit_before>package gring_test

import (
	"container/ring"
	"github.com/gogf/gf/g"
	"github.com/gogf/gf/g/container/gring"
	"github.com/gogf/gf/g/test/gtest"
	"testing"
)
type Student struct {
	position int
	name    string
	upgrade bool
}

func TestRing_Val(t *testing.T) {
	gtest.Case(t, func() {
		//定义cap 为3的ring类型数据
		r := gring.New(3, true)
		//分别给3个元素初始化赋值
		r.Put(&Student{1,"jimmy", true})
		r.Put(&Student{2,"tom", true})
		r.Put(&Student{3,"alon", false})

		//元素取值并判断和预设值是否相等
		gtest.Assert(r.Val().(*Student).name,"jimmy")
		//从当前位置往后移两个元素
		r.Move(2)
		gtest.Assert(r.Val().(*Student).name,"alon")
		//更新元素值
		//测试 value == nil
		r.Set(nil)
		gtest.Assert(r.Val(),nil)
		//测试value != nil
		r.Set(&Student{3, "jack", true})
	})
}
func TestRing_CapLen(t *testing.T) {
	gtest.Case(t, func() {
		r := gring.New(10)
		r.Put("goframe")
		//cap长度 10
		gtest.Assert(r.Cap(), 10)
		//已有数据项 1
		gtest.Assert(r.Len(), 1)
	})
}

func TestRing_Position(t *testing.T) {
	gtest.Case(t, func() {
		r := gring.New(2)
		r.Put(1)
		r.Put(2)
		//往后移动1个元素
		r.Next()
		gtest.Assert(r.Val(),2)
		//往前移动1个元素
		r.Prev()
		gtest.Assert(r.Val(),1)

	})
}

func TestRing_Link(t *testing.T) {
	gtest.Case(t, func() {
		r := gring.New(3)
		r.Put(1)
		r.Put(2)
		r.Put(3)
		s := gring.New(2)
		s.Put("a")
		s.Put("b")

		rs := r.Link(s)
		gtest.Assert(rs.Move(2).Val(), "b")

	})
}

func TestRing_Unlink(t *testing.T) {
	gtest.Case(t, func() {
		r := gring.New(5)
		for i := 0; i< 5; i++  {
			r.Put(i+1)
		}
		// 1 2 3 4 5
		// 删除当前位置往后的2个数据，返回被删除的数据
		// 重新计算s len
		s := r.Unlink(2)		// 2 3
		gtest.Assert(s.Val(), 2)
		gtest.Assert(s.Len(), 1)
	})
}

func TestRing_Slice(t *testing.T) {
	gtest.Case(t, func() {
		ringLen := 5
		r := gring.New(ringLen)
		for i := 0; i< ringLen; i++  {
			r.Put(i+1)
		}
		r.Move(2)	// 3
		array := r.SliceNext()		// [3 4 5 1 2]
		gtest.Assert(array[0], 3)
		gtest.Assert(len(array), 5)

		//判断array是否等于[3 4 5 1 2]
		ra := []int{3,4,5,1,2}
		gtest.Assert(ra, array)

		//第3个元素设为nil
		r.Set(nil)
		array2 := r.SliceNext() 	//[4 5 1 2]
		//返回当前位置往后不为空的元素数组，长度为4
		gtest.Assert(array2, g.Slice{4,5,1,2})

		array3 := r.SlicePrev() 	//[2 1 5 4]
		gtest.Assert(array3, g.Slice{2,1,5,4})

		s := gring.New(ringLen)
		array4 := s.SlicePrev()	// []
		gtest.Assert(array4, g.Slice{})

	})
}

func TestRing_RLockIterator(t *testing.T) {
	gtest.Case(t, func() {
		ringLen := 5
		r := gring.New(ringLen)

		//ring不存在有值元素
		r.RLockIteratorNext(func(value interface{}) bool {
			gtest.Assert(r.Val(), nil)
			return true
		})

		r.RLockIteratorPrev(func(value interface{}) bool {
			gtest.Assert(r.Val(), nil)
			return true
		})

		for i := 0; i< ringLen; i++  {
			r.Put(i+1)
		}

		//回调函数返回true,RLockIteratorNext遍历5次
		r.RLockIteratorNext(func(value interface{}) bool {
			gtest.Assert(r.Val(), 1)
			return true
		})

		//RLockIteratorPrev遍历3次返回 false,退出遍历
		r.RLockIteratorPrev(func(value interface{}) bool {
			gtest.Assert(r.Val(), 1)
			return false
		})

	})
}

func TestRing_LockIterator(t *testing.T) {
	gtest.Case(t, func() {
		ringLen := 5
		r := gring.New(ringLen)

		//不存在有值元素
		r.LockIteratorNext(func(item *ring.Ring) bool {
			gtest.Assert(item.Value, nil)
			return true
		})

		r.LockIteratorPrev(func(item *ring.Ring) bool {
			gtest.Assert(item.Value, nil)
			return true
		})

		//ring初始化元素值
		for i := 0; i< ringLen; i++  {
			r.Put(i+1)
		}

		//往后遍历组成数据 [1,2,3,4,5]
		array1 := g.Slice{1,2,3,4,5}
		ii := 0
		r.LockIteratorNext(func(item *ring.Ring) bool {
			//校验每一次遍历取值是否是期望值
			gtest.Assert(item.Value, array1[ii])
			ii++;
			return true
		})

		//往后取3个元素组成数组
		//获得 [1,5,4]
		i := 0
		a := g.Slice{1,5,4}
		r.LockIteratorPrev(func(item *ring.Ring) bool {
			if i > 2 {
				return false
			}
			gtest.Assert(item.Value, a[i])
			i++;
			return true
		})

	})
}<commit_msg>Update unit test for gring<commit_after>package gring_test

import (
	"container/ring"
	"github.com/gogf/gf/g"
	"github.com/gogf/gf/g/container/gring"
	"github.com/gogf/gf/g/test/gtest"
	"testing"
)
type Student struct {
	position int
	name    string
	upgrade bool
}

func TestRing_Val(t *testing.T) {
	gtest.Case(t, func() {
		//定义cap 为3的ring类型数据
		r := gring.New(3, true)
		//分别给3个元素初始化赋值
		r.Put(&Student{1,"jimmy", true})
		r.Put(&Student{2,"tom", true})
		r.Put(&Student{3,"alon", false})

		//元素取值并判断和预设值是否相等
		gtest.Assert(r.Val().(*Student).name,"jimmy")
		//从当前位置往后移两个元素
		r.Move(2)
		gtest.Assert(r.Val().(*Student).name,"alon")
		//更新元素值
		//测试 value == nil
		r.Set(nil)
		gtest.Assert(r.Val(),nil)
		//测试value != nil
		r.Set(&Student{3, "jack", true})
	})
}
func TestRing_CapLen(t *testing.T) {
	gtest.Case(t, func() {
		r := gring.New(10)
		r.Put("goframe")
		//cap长度 10
		gtest.Assert(r.Cap(), 10)
		//已有数据项 1
		gtest.Assert(r.Len(), 1)
	})
}

func TestRing_Position(t *testing.T) {
	gtest.Case(t, func() {
		r := gring.New(2)
		r.Put(1)
		r.Put(2)
		//往后移动1个元素
		r.Next()
		gtest.Assert(r.Val(),2)
		//往前移动1个元素
		r.Prev()
		gtest.Assert(r.Val(),1)

	})
}

func TestRing_Link(t *testing.T) {
	gtest.Case(t, func() {
		r := gring.New(3)
		r.Put(1)
		r.Put(2)
		r.Put(3)
		s := gring.New(2)
		s.Put("a")
		s.Put("b")

		rs := r.Link(s)
		gtest.Assert(rs.Move(2).Val(), "b")

	})
}

func TestRing_Unlink(t *testing.T) {
	gtest.Case(t, func() {
		r := gring.New(5)
		for i := 0; i< 5; i++  {
			r.Put(i+1)
		}
		// 1 2 3 4
		// 删除当前位置往后的2个数据，返回被删除的数据
		// 重新计算s len
		s := r.Unlink(2)		// 2 3
		gtest.Assert(s.Val(), 2)
		gtest.Assert(s.Len(), 1)
	})
}

func TestRing_Slice(t *testing.T) {
	gtest.Case(t, func() {
		ringLen := 5
		r := gring.New(ringLen)
		for i := 0; i< ringLen; i++  {
			r.Put(i+1)
		}
		r.Move(2)	// 3
		array := r.SliceNext()		// [3 4 5 1 2]
		gtest.Assert(array[0], 3)
		gtest.Assert(len(array), 5)

		//判断array是否等于[3 4 5 1 2]
		ra := []int{3,4,5,1,2}
		gtest.Assert(ra, array)

		//第3个元素设为nil
		r.Set(nil)
		array2 := r.SliceNext() 	//[4 5 1 2]
		//返回当前位置往后不为空的元素数组，长度为4
		gtest.Assert(array2, g.Slice{4,5,1,2})

		array3 := r.SlicePrev() 	//[2 1 5 4]
		gtest.Assert(array3, g.Slice{2,1,5,4})

		s := gring.New(ringLen)
		for i := 0; i< ringLen; i++  {
			s.Put(i+1)
		}
		array4 := s.SlicePrev()	// []
		gtest.Assert(array4, g.Slice{1,5,4,3,2})

	})
}

func TestRing_RLockIterator(t *testing.T) {
	gtest.Case(t, func() {
		ringLen := 5
		r := gring.New(ringLen)

		//ring不存在有值元素
		r.RLockIteratorNext(func(value interface{}) bool {
			gtest.Assert(r.Val(), nil)
			return false
		})
		r.RLockIteratorNext(func(value interface{}) bool {
			gtest.Assert(r.Val(), nil)
			return true
		})

		r.RLockIteratorPrev(func(value interface{}) bool {
			gtest.Assert(r.Val(), nil)
			return true
		})

		for i := 0; i< ringLen; i++  {
			r.Put(i+1)
		}

		//回调函数返回true,RLockIteratorNext遍历5次
		r.RLockIteratorNext(func(value interface{}) bool {
			gtest.Assert(r.Val(), 1)
			return true
		})

		//RLockIteratorPrev遍历3次返回 false,退出遍历
		r.RLockIteratorPrev(func(value interface{}) bool {
			gtest.Assert(r.Val(), 1)
			return false
		})

	})
}

func TestRing_LockIterator(t *testing.T) {
	gtest.Case(t, func() {
		ringLen := 5
		r := gring.New(ringLen)

		//不存在有值元素
		r.LockIteratorNext(func(item *ring.Ring) bool {
			gtest.Assert(item.Value, nil)
			return false
		})
		r.LockIteratorNext(func(item *ring.Ring) bool {
			gtest.Assert(item.Value, nil)
			return false
		})
		r.LockIteratorNext(func(item *ring.Ring) bool {
			gtest.Assert(item.Value, nil)
			return true
		})

		r.LockIteratorPrev(func(item *ring.Ring) bool {
			gtest.Assert(item.Value, nil)
			return false
		})
		r.LockIteratorPrev(func(item *ring.Ring) bool {
			gtest.Assert(item.Value, nil)
			return true
		})

		//ring初始化元素值
		for i := 0; i< ringLen; i++  {
			r.Put(i+1)
		}

		//往后遍历组成数据 [1,2,3,4,5]
		array1 := g.Slice{1,2,3,4,5}
		ii := 0
		r.LockIteratorNext(func(item *ring.Ring) bool {
			//校验每一次遍历取值是否是期望值
			gtest.Assert(item.Value, array1[ii])
			ii++;
			return true
		})

		//往后取3个元素组成数组
		//获得 [1,5,4]
		i := 0
		a := g.Slice{1,5,4}
		r.LockIteratorPrev(func(item *ring.Ring) bool {
			if i > 2 {
				return false
			}
			gtest.Assert(item.Value, a[i])
			i++;
			return true
		})

	})
}<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/ryanuber/go-license"
)

type response struct {
	License string
	File    string
}

func getLicense(input chan string, output chan response) {
	for file := range input {
		l, err := license.NewFromFile(file)
		splitFile := strings.Split(file, "/")
		newFile := splitFile[1 : len(splitFile)-1]
		file = strings.Join(newFile, "/")
		if err != nil {
			output <- response{File: file, License: err.Error()}
		} else {
			output <- response{File: file, License: l.Type}
		}
	}
}

func main() {
	root := "vendor/"
	i := 0
	input := make(chan string)
	output := make(chan response)

	for a := 0; a < 5; a++ {
		go getLicense(input, output)
	}
	var files []string
	filepath.Walk(root, func(path string, f os.FileInfo, err error) error {
		if err != nil {
			fmt.Println("No vendor folder found. Aborting..")
			return err
		}
		if !f.IsDir() {
			splitPath := strings.Split(path, "/")
			rawPath := splitPath[len(splitPath)-1]
			if strings.Contains(strings.ToUpper(rawPath), "LICENSE") {
				files = append(files, path)
			}
		}
		return nil
	})

	if len(files) == 0 {
		return
	}

	go func() {
		for _, v := range files {
			input <- v
		}
	}()
	for out := range output {
		fmt.Printf("%v =======> %v\n", out.File, out.License)
		i++
		if i == len(files)-1 || len(files) == 1 {
			break
		}

	}
}
<commit_msg>Check for COPYING as part of license file<commit_after>package main

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/ryanuber/go-license"
)

type response struct {
	License string
	File    string
}

func getLicense(input chan string, output chan response) {
	for file := range input {
		l, err := license.NewFromFile(file)
		splitFile := strings.Split(file, "/")
		newFile := splitFile[1 : len(splitFile)-1]
		file = strings.Join(newFile, "/")
		if err != nil {
			output <- response{File: file, License: err.Error()}
		} else {
			output <- response{File: file, License: l.Type}
		}
	}
}
func scan(path string) bool {
	path = strings.ToUpper(path)
	return strings.Contains(path, "LICENSE") || strings.Contains(path, "COPYING")
}

func main() {
	root := "vendor/"
	i := 0
	input := make(chan string)
	output := make(chan response)

	for a := 0; a < 5; a++ {
		go getLicense(input, output)
	}
	var files []string
	filepath.Walk(root, func(path string, f os.FileInfo, err error) error {
		if err != nil {
			fmt.Println("No vendor folder found. Aborting..")
			return err
		}
		if !f.IsDir() {
			splitPath := strings.Split(path, "/")
			rawPath := splitPath[len(splitPath)-1]
			if scan(rawPath) {
				files = append(files, path)
			}
		}
		return nil
	})

	if len(files) == 0 {
		return
	}

	go func() {
		for _, v := range files {
			input <- v
		}
	}()
	for out := range output {
		fmt.Printf("%v =======> %v\n", out.File, out.License)
		i++
		if i == len(files)-1 || len(files) == 1 {
			break
		}

	}
}
<|endoftext|>


<commit_before>package gobls

import "bufio"

// const DefaultBufferSize = 16 * 1024
const DefaultBufferSize = bufio.MaxScanTokenSize

// Scanner provides an interface for reading newline-delimited lines
// of text. It is similar to `bufio.Scanner`, but wraps
// `bufio.ReadLine` so lines of arbitrary length can be
// scanned. Successive calls to the Scan method will step through the
// lines of a file, skipping the newline whitespace between lines.
//
// Scanning stops unrecoverably at EOF, or at the first I/O
// error. Unlike `bufio.Scanner`, howver, attempting to scan a line
// longer than `bufio.MaxScanTokenSize` will not result in an error,
// but will return the long line.
//
// It is not necessary to check for errors by calling the Err method
// until after scanning stops, when the Scan method returns false.
type Scanner interface {
	Bytes() []byte
	Err() error
	Scan() bool
	Text() string
}
<commit_msg>uses 16K buffers by default<commit_after>package gobls

const DefaultBufferSize = 16 * 1024

// Scanner provides an interface for reading newline-delimited lines
// of text. It is similar to `bufio.Scanner`, but wraps
// `bufio.ReadLine` so lines of arbitrary length can be
// scanned. Successive calls to the Scan method will step through the
// lines of a file, skipping the newline whitespace between lines.
//
// Scanning stops unrecoverably at EOF, or at the first I/O
// error. Unlike `bufio.Scanner`, howver, attempting to scan a line
// longer than `bufio.MaxScanTokenSize` will not result in an error,
// but will return the long line.
//
// It is not necessary to check for errors by calling the Err method
// until after scanning stops, when the Scan method returns false.
type Scanner interface {
	Bytes() []byte
	Err() error
	Scan() bool
	Text() string
}
<|endoftext|>