<commit_before>// Copyright © 2015 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package http

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"sync"

	"github.com/TheThingsNetwork/ttn/core"
	"github.com/TheThingsNetwork/ttn/core/adapters/http/parser"
	. "github.com/TheThingsNetwork/ttn/core/errors"
	"github.com/TheThingsNetwork/ttn/utils/errors"
	"github.com/TheThingsNetwork/ttn/utils/stats"
	"github.com/apex/log"
)

// Adapter type materializes an http adapter which implements the basic http protocol
type Adapter struct {
	parser.PacketParser                // The adapter's parser contract
	http.Client                        // Adapter is also an http client
	serveMux            *http.ServeMux // Holds a references to the adapter servemux in order to dynamically define endpoints
	packets             chan pktReq    // Channel used to "transforms" incoming request to something we can handle concurrently
	ctx                 log.Interface  // Just a logger, no one really cares about him.
}

// Message sent through the packets channel when an incoming request arrives
type pktReq struct {
	core.Packet             // The actual packet that has been parsed
	response    chan pktRes // A response channel waiting for an success or reject confirmation
}

// Message sent through the response channel of a pktReq
type pktRes struct {
	statusCode int    // The http status code to set as an answer
	content    []byte // The response content.
}

// NewAdapter constructs and allocates a new http adapter
func NewAdapter(port uint, parser parser.PacketParser, ctx log.Interface) (*Adapter, error) {
	a := Adapter{
		PacketParser: parser,
		serveMux:     http.NewServeMux(),
		packets:      make(chan pktReq),
		ctx:          ctx,
		Client:       http.Client{},
	}

	a.RegisterEndpoint("/healthz", func(w http.ResponseWriter, req *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Write([]byte("ok"))
	})

	a.RegisterEndpoint("/packets", a.handlePostPacket)
	go a.listenRequests(port)

	return &a, nil
}

// Send implements the core.Adapter interface
func (a *Adapter) Send(p core.Packet, r ...core.Recipient) (core.Packet, error) {
	stats.MarkMeter("http_adapter.send")
	stats.UpdateHistogram("http_adapter.send.recipients", int64(len(r)))

	// Generate payload from core packet
	m, err := json.Marshal(p.Metadata)
	if err != nil {
		a.ctx.WithError(err).Warn("Invalid Packet")
		return core.Packet{}, errors.New(ErrInvalidStructure, err)
	}
	pl, err := p.Payload.MarshalBinary()
	if err != nil {
		a.ctx.WithError(err).Warn("Invalid Packet")
		return core.Packet{}, errors.New(ErrInvalidStructure, err)
	}
	payload := fmt.Sprintf(`{"payload":"%s","metadata":%s}`, base64.StdEncoding.EncodeToString(pl), m)

	devAddr, _ := p.DevAddr()
	ctx := a.ctx.WithField("devAddr", devAddr)
	ctx.Debug("Sending Packet")

	// Prepare ground for parrallel http request
	nb := len(r)
	cherr := make(chan error, nb)
	chresp := make(chan core.Packet, nb)
	wg := sync.WaitGroup{}
	wg.Add(nb)

	// Run each request
	for _, recipient := range r {
		go func(recipient core.Recipient) {
			defer wg.Done()

			ctx := ctx.WithField("recipient", recipient.Address)
			ctx.Debug("POST Request")

			buf := new(bytes.Buffer)
			buf.Write([]byte(payload))

			// Send request
			resp, err := a.Post(fmt.Sprintf("http://%s", recipient.Address.(string)), "application/json", buf)
			if err != nil {
				cherr <- err
				return
			}

			defer func() {
				// This is needed because the default HTTP client's Transport does not
				// attempt to reuse HTTP/1.0 or HTTP/1.1 TCP connections unless the Body
				// is read to completion and is closed.
				io.Copy(ioutil.Discard, resp.Body)
				resp.Body.Close()
			}()

			// Check response code
			if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusAccepted && resp.StatusCode != http.StatusCreated {
				ctx.WithField("response", resp.StatusCode).Warn("Unexpected response")
				cherr <- fmt.Errorf("Unexpected response from server: %s (%d)", resp.Status, resp.StatusCode)
				return
			}

			// Process response body
			raw, err := ioutil.ReadAll(resp.Body)
			if err != nil && err != io.EOF {
				cherr <- err
				return
			}

			// Process packet
			var packet core.Packet
			if err := json.Unmarshal(raw, &packet); err != nil {
				cherr <- err
				return
			}

			chresp <- packet
		}(recipient)
	}

	// Wait for each request to be done, and return
	stats.IncCounter("http_adapter.send.waiting")
	wg.Wait()
	stats.DecCounter("http_adapter.send.waiting")

	// Collect errors
	var errs []error
	for i := 0; i < len(cherr); i += 1 {
		err := <-cherr
		ctx.WithError(err).Error("POST Failed")
		errs = append(errs, err)
	}

	// Check responses
	if len(chresp) > 1 {
		ctx.WithField("response_count", len(chresp)).Error("Received too many positive answers")
		return core.Packet{}, errors.New(ErrWrongBehavior, "Received too many positive answers")
	}

	// Get packet
	select {
	case packet := <-chresp:
		return packet, nil
	default:
		if errs != nil {
			return core.Packet{}, errors.New(ErrFailedOperation, fmt.Sprintf("%+v", errs))
		}
		ctx.Error("No response packet available")
		return core.Packet{}, errors.New(ErrWrongBehavior, "No response packet available")
	}
}

// RegisterEndpoint can be used by an external agent to register a handler to the adapter servemux
func (a *Adapter) RegisterEndpoint(url string, handler func(w http.ResponseWriter, req *http.Request)) {
	a.ctx.WithField("url", url).Info("Register new endpoint")
	a.serveMux.HandleFunc(url, handler)
}

// Next implements the core.Adapter interface
func (a *Adapter) Next() (core.Packet, core.AckNacker, error) {
	pktReq := <-a.packets
	return pktReq.Packet, packetAckNacker{response: pktReq.response}, nil
}

// NextRegistration implements the core.Adapter interface. Not implemented for this adapter.
//
// See broadcast and pubsub adapters for mechanisms to handle registrations.
func (a *Adapter) NextRegistration() (core.Packet, core.AckNacker, error) {
	return core.Packet{}, nil, errors.New(ErrNotSupported, "NextRegistration not supported for http adapter")
}

// listenRequests handles incoming registration request sent through http to the adapter
func (a *Adapter) listenRequests(port uint) {
	server := http.Server{
		Addr:    fmt.Sprintf("0.0.0.0:%d", port),
		Handler: a.serveMux,
	}
	a.ctx.WithField("port", port).Info("Starting Server")
	err := server.ListenAndServe()
	a.ctx.WithError(err).Warn("HTTP connection lost")
}
<commit_msg>[refactor] Set timeout of HTTP adapter to 6 seconds<commit_after>// Copyright © 2015 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package http

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"sync"
	"time"

	"github.com/TheThingsNetwork/ttn/core"
	"github.com/TheThingsNetwork/ttn/core/adapters/http/parser"
	. "github.com/TheThingsNetwork/ttn/core/errors"
	"github.com/TheThingsNetwork/ttn/utils/errors"
	"github.com/TheThingsNetwork/ttn/utils/stats"
	"github.com/apex/log"
)

// Adapter type materializes an http adapter which implements the basic http protocol
type Adapter struct {
	parser.PacketParser                // The adapter's parser contract
	http.Client                        // Adapter is also an http client
	serveMux            *http.ServeMux // Holds a references to the adapter servemux in order to dynamically define endpoints
	packets             chan pktReq    // Channel used to "transforms" incoming request to something we can handle concurrently
	ctx                 log.Interface  // Just a logger, no one really cares about him.
}

// Message sent through the packets channel when an incoming request arrives
type pktReq struct {
	core.Packet             // The actual packet that has been parsed
	response    chan pktRes // A response channel waiting for an success or reject confirmation
}

// Message sent through the response channel of a pktReq
type pktRes struct {
	statusCode int    // The http status code to set as an answer
	content    []byte // The response content.
}

// NewAdapter constructs and allocates a new http adapter
func NewAdapter(port uint, parser parser.PacketParser, ctx log.Interface) (*Adapter, error) {
	a := Adapter{
		PacketParser: parser,
		serveMux:     http.NewServeMux(),
		packets:      make(chan pktReq),
		ctx:          ctx,
		Client: http.Client{
			Timeout: 6 * time.Second,
		},
	}

	a.RegisterEndpoint("/healthz", func(w http.ResponseWriter, req *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Write([]byte("ok"))
	})

	a.RegisterEndpoint("/packets", a.handlePostPacket)
	go a.listenRequests(port)

	return &a, nil
}

// Send implements the core.Adapter interface
func (a *Adapter) Send(p core.Packet, r ...core.Recipient) (core.Packet, error) {
	stats.MarkMeter("http_adapter.send")
	stats.UpdateHistogram("http_adapter.send.recipients", int64(len(r)))

	// Generate payload from core packet
	m, err := json.Marshal(p.Metadata)
	if err != nil {
		a.ctx.WithError(err).Warn("Invalid Packet")
		return core.Packet{}, errors.New(ErrInvalidStructure, err)
	}
	pl, err := p.Payload.MarshalBinary()
	if err != nil {
		a.ctx.WithError(err).Warn("Invalid Packet")
		return core.Packet{}, errors.New(ErrInvalidStructure, err)
	}
	payload := fmt.Sprintf(`{"payload":"%s","metadata":%s}`, base64.StdEncoding.EncodeToString(pl), m)

	devAddr, _ := p.DevAddr()
	ctx := a.ctx.WithField("devAddr", devAddr)
	ctx.Debug("Sending Packet")

	// Prepare ground for parrallel http request
	nb := len(r)
	cherr := make(chan error, nb)
	chresp := make(chan core.Packet, nb)
	wg := sync.WaitGroup{}
	wg.Add(nb)

	// Run each request
	for _, recipient := range r {
		go func(recipient core.Recipient) {
			defer wg.Done()

			ctx := ctx.WithField("recipient", recipient.Address)
			ctx.Debug("POST Request")

			buf := new(bytes.Buffer)
			buf.Write([]byte(payload))

			// Send request
			resp, err := a.Post(fmt.Sprintf("http://%s", recipient.Address.(string)), "application/json", buf)
			if err != nil {
				cherr <- err
				return
			}

			defer func() {
				// This is needed because the default HTTP client's Transport does not
				// attempt to reuse HTTP/1.0 or HTTP/1.1 TCP connections unless the Body
				// is read to completion and is closed.
				io.Copy(ioutil.Discard, resp.Body)
				resp.Body.Close()
			}()

			// Check response code
			if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusAccepted && resp.StatusCode != http.StatusCreated {
				ctx.WithField("response", resp.StatusCode).Warn("Unexpected response")
				cherr <- fmt.Errorf("Unexpected response from server: %s (%d)", resp.Status, resp.StatusCode)
				return
			}

			// Process response body
			raw, err := ioutil.ReadAll(resp.Body)
			if err != nil && err != io.EOF {
				cherr <- err
				return
			}

			// Process packet
			var packet core.Packet
			if err := json.Unmarshal(raw, &packet); err != nil {
				cherr <- err
				return
			}

			chresp <- packet
		}(recipient)
	}

	// Wait for each request to be done, and return
	stats.IncCounter("http_adapter.send.waiting")
	wg.Wait()
	stats.DecCounter("http_adapter.send.waiting")

	// Collect errors
	var errs []error
	for i := 0; i < len(cherr); i += 1 {
		err := <-cherr
		ctx.WithError(err).Error("POST Failed")
		errs = append(errs, err)
	}

	// Check responses
	if len(chresp) > 1 {
		ctx.WithField("response_count", len(chresp)).Error("Received too many positive answers")
		return core.Packet{}, errors.New(ErrWrongBehavior, "Received too many positive answers")
	}

	// Get packet
	select {
	case packet := <-chresp:
		return packet, nil
	default:
		if errs != nil {
			return core.Packet{}, errors.New(ErrFailedOperation, fmt.Sprintf("%+v", errs))
		}
		ctx.Error("No response packet available")
		return core.Packet{}, errors.New(ErrWrongBehavior, "No response packet available")
	}
}

// RegisterEndpoint can be used by an external agent to register a handler to the adapter servemux
func (a *Adapter) RegisterEndpoint(url string, handler func(w http.ResponseWriter, req *http.Request)) {
	a.ctx.WithField("url", url).Info("Register new endpoint")
	a.serveMux.HandleFunc(url, handler)
}

// Next implements the core.Adapter interface
func (a *Adapter) Next() (core.Packet, core.AckNacker, error) {
	pktReq := <-a.packets
	return pktReq.Packet, packetAckNacker{response: pktReq.response}, nil
}

// NextRegistration implements the core.Adapter interface. Not implemented for this adapter.
//
// See broadcast and pubsub adapters for mechanisms to handle registrations.
func (a *Adapter) NextRegistration() (core.Packet, core.AckNacker, error) {
	return core.Packet{}, nil, errors.New(ErrNotSupported, "NextRegistration not supported for http adapter")
}

// listenRequests handles incoming registration request sent through http to the adapter
func (a *Adapter) listenRequests(port uint) {
	server := http.Server{
		Addr:    fmt.Sprintf("0.0.0.0:%d", port),
		Handler: a.serveMux,
	}
	a.ctx.WithField("port", port).Info("Starting Server")
	err := server.ListenAndServe()
	a.ctx.WithError(err).Warn("HTTP connection lost")
}
<|endoftext|>


<commit_before>package model

// swagger:model build
type Build struct {
	ID        int64  `json:"id"            meddler:"build_id,pk"`
	RepoID    int64  `json:"-"             meddler:"build_repo_id"`
	Number    int    `json:"number"        meddler:"build_number"`
	Parent    int    `json:"parent"        meddler:"build_parent"`
	Event     string `json:"event"         meddler:"build_event"`
	Status    string `json:"status"        meddler:"build_status"`
	Enqueued  int64  `json:"enqueued_at"   meddler:"build_enqueued"`
	Created   int64  `json:"created_at"    meddler:"build_created"`
	Started   int64  `json:"started_at"    meddler:"build_started"`
	Finished  int64  `json:"finished_at"   meddler:"build_finished"`
	Deploy    string `json:"deploy_to"     meddler:"build_deploy"`
	Commit    string `json:"commit"        meddler:"build_commit"`
	Branch    string `json:"branch"        meddler:"build_branch"`
	Ref       string `json:"ref"           meddler:"build_ref"`
	Refspec   string `json:"refspec"       meddler:"build_refspec"`
	Remote    string `json:"remote"        meddler:"build_remote"`
	Title     string `json:"title"         meddler:"build_title"`
	Message   string `json:"message"       meddler:"build_message"`
	Timestamp int64  `json:"timestamp"     meddler:"build_timestamp"`
	Author    string `json:"author"        meddler:"build_author"`
	Avatar    string `json:"author_avatar" meddler:"build_avatar"`
	Email     string `json:"author_email"  meddler:"build_email"`
	Link      string `json:"link_url"      meddler:"build_link"`
	Signed    bool   `json:"signed"        meddler:"build_signed"`
	Verified  bool   `json:"verified"      meddler:"build_verified"`
}

type BuildGroup struct {
	Date   string
	Builds []*Build
}
<commit_msg>Add jobs property to build model<commit_after>package model

// swagger:model build
type Build struct {
	ID        int64  `json:"id"            meddler:"build_id,pk"`
	RepoID    int64  `json:"-"             meddler:"build_repo_id"`
	Number    int    `json:"number"        meddler:"build_number"`
	Parent    int    `json:"parent"        meddler:"build_parent"`
	Event     string `json:"event"         meddler:"build_event"`
	Status    string `json:"status"        meddler:"build_status"`
	Enqueued  int64  `json:"enqueued_at"   meddler:"build_enqueued"`
	Created   int64  `json:"created_at"    meddler:"build_created"`
	Started   int64  `json:"started_at"    meddler:"build_started"`
	Finished  int64  `json:"finished_at"   meddler:"build_finished"`
	Deploy    string `json:"deploy_to"     meddler:"build_deploy"`
	Commit    string `json:"commit"        meddler:"build_commit"`
	Branch    string `json:"branch"        meddler:"build_branch"`
	Ref       string `json:"ref"           meddler:"build_ref"`
	Refspec   string `json:"refspec"       meddler:"build_refspec"`
	Remote    string `json:"remote"        meddler:"build_remote"`
	Title     string `json:"title"         meddler:"build_title"`
	Message   string `json:"message"       meddler:"build_message"`
	Timestamp int64  `json:"timestamp"     meddler:"build_timestamp"`
	Author    string `json:"author"        meddler:"build_author"`
	Avatar    string `json:"author_avatar" meddler:"build_avatar"`
	Email     string `json:"author_email"  meddler:"build_email"`
	Link      string `json:"link_url"      meddler:"build_link"`
	Signed    bool   `json:"signed"        meddler:"build_signed"`
	Verified  bool   `json:"verified"      meddler:"build_verified"`
	Jobs      []*Job `json:"jobs,omitempty" meddler:"-"`
}

type BuildGroup struct {
	Date   string
	Builds []*Build
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

var cmdImport = &Command{
	Run:   runImport,
	Usage: "import [dir]",
	Short: "Import metadata from a local directory",
	Long: `
Import metadata from a local directory

Examples:

  force import

  force import org/schema
`,
}

func runImport(cmd *Command, args []string) {
	wd, _ := os.Getwd()
	root := filepath.Join(wd, "metadata")
	if len(args) == 1 {
		root, _ = filepath.Abs(args[0])
	}
	force, _ := ActiveForce()
	files := make(ForceMetadataFiles)
	if _, err := os.Stat(filepath.Join(root, "package.xml")); os.IsNotExist(err) {
		ErrorAndExit("Must specify a directory that contains metadata files")
	}
	err := filepath.Walk(root, func(path string, f os.FileInfo, err error) error {
		if f.Mode().IsRegular() {
			data, err := ioutil.ReadFile(path)
			if err != nil {
				ErrorAndExit(err.Error())
			}
			files[strings.Replace(path, fmt.Sprintf("%s/", root), "", -1)] = data
		}
		return nil
	})
	if err != nil {
		ErrorAndExit(err.Error())
	}
	problems, err := force.Metadata.Deploy(files)
	if err != nil {
		ErrorAndExit(err.Error())
	}
	for _, problem := range problems {
		fmt.Printf("%s: %s: %s\n", problem.Name, problem.Filename, problem.Problem)
	}
	fmt.Printf("Imported from %s\n", root)
}
<commit_msg>fix error output<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

var cmdImport = &Command{
	Run:   runImport,
	Usage: "import [dir]",
	Short: "Import metadata from a local directory",
	Long: `
Import metadata from a local directory

Examples:

  force import

  force import org/schema
`,
}

func runImport(cmd *Command, args []string) {
	wd, _ := os.Getwd()
	root := filepath.Join(wd, "metadata")
	if len(args) == 1 {
		root, _ = filepath.Abs(args[0])
	}
	force, _ := ActiveForce()
	files := make(ForceMetadataFiles)
	if _, err := os.Stat(filepath.Join(root, "package.xml")); os.IsNotExist(err) {
		ErrorAndExit("Must specify a directory that contains metadata files")
	}
	err := filepath.Walk(root, func(path string, f os.FileInfo, err error) error {
		if f.Mode().IsRegular() {
			data, err := ioutil.ReadFile(path)
			if err != nil {
				ErrorAndExit(err.Error())
			}
			files[strings.Replace(path, fmt.Sprintf("%s/", root), "", -1)] = data
		}
		return nil
	})
	if err != nil {
		ErrorAndExit(err.Error())
	}
	problems, err := force.Metadata.Deploy(files)
	if err != nil {
		ErrorAndExit(err.Error())
	}
	for _, problem := range problems {
		if problem.Name == "" {
			fmt.Println(problem.Problem)
		} else {
			fmt.Printf("%s: %s\n", problem.Name, problem.Problem)
		}
	}
	fmt.Printf("Imported from %s\n", root)
}
<|endoftext|>


<commit_before>package file

import (
	"fmt"
	"regexp"
	"strconv"
)

var appVersion = "2.0.0"

// GetAppVersion return app version
func GetAppVersion() string {
	return appVersion
}

// getAppDbVersion return app version recorded in database
func getAppDbVersion() (string, error) {
	var version string

	res, err := db.Query("select id from version")

	if err != nil {
		return "", fmt.Errorf("Can't retrieve database app version")
	}

	res.Next()

	err = res.Scan(&version)

	return version, err
}

// HasMajorVersionEqualFrom check if major version in given version is equal to app version
func HasMajorVersionEqualFrom() (bool, error) {
	re := regexp.MustCompile(`^(\d)\.(\d)\.(\d)(?:(?:\-|\+).*)?`)

	dbVer, err := getAppDbVersion()

	if err != nil {
		return false, err
	}

	dbVerComp := re.FindStringSubmatch(dbVer)
	appVerComp := re.FindStringSubmatch(appVersion)

	if len(dbVerComp) != 4 {
		return false, fmt.Errorf("Wrong version format : %s, must follows semver", dbVer)
	}

	appVerMajor, err := strconv.Atoi(appVerComp[1])

	if err != nil {
		return false, err
	}

	verMajor, err := strconv.Atoi(dbVerComp[1])

	if err != nil {
		return false, err
	}

	if verMajor == appVerMajor {
		return true, nil
	}

	return false, fmt.Errorf("Database version : %s and app version : %s don't have same major version", dbVer, appVersion)
}
<commit_msg>feat(version) : 2.1.0<commit_after>package file

import (
	"fmt"
	"regexp"
	"strconv"
)

var appVersion = "2.1.0"

// GetAppVersion return app version
func GetAppVersion() string {
	return appVersion
}

// getAppDbVersion return app version recorded in database
func getAppDbVersion() (string, error) {
	var version string

	res, err := db.Query("select id from version")

	if err != nil {
		return "", fmt.Errorf("Can't retrieve database app version")
	}

	res.Next()

	err = res.Scan(&version)

	return version, err
}

// HasMajorVersionEqualFrom check if major version in given version is equal to app version
func HasMajorVersionEqualFrom() (bool, error) {
	re := regexp.MustCompile(`^(\d)\.(\d)\.(\d)(?:(?:\-|\+).*)?`)

	dbVer, err := getAppDbVersion()

	if err != nil {
		return false, err
	}

	dbVerComp := re.FindStringSubmatch(dbVer)
	appVerComp := re.FindStringSubmatch(appVersion)

	if len(dbVerComp) != 4 {
		return false, fmt.Errorf("Wrong version format : %s, must follows semver", dbVer)
	}

	appVerMajor, err := strconv.Atoi(appVerComp[1])

	if err != nil {
		return false, err
	}

	verMajor, err := strconv.Atoi(dbVerComp[1])

	if err != nil {
		return false, err
	}

	if verMajor == appVerMajor {
		return true, nil
	}

	return false, fmt.Errorf("Database version : %s and app version : %s don't have same major version", dbVer, appVersion)
}
<|endoftext|>


<commit_before>package models

import (
	"regexp"

	"github.com/alxeg/flibooks/utils"
)

var re = regexp.MustCompile(`^[\s\P{L}]*(.*?)[\P{L}\s]*$`)

type Book struct {
	ID          uint      `gorm:"primary_key"`
	Container   Container `json:"container"`
	ContainerID uint      `json:"-"`
	Authors     []Author  `json:"authors" gorm:"many2many:book_authors;"`
	Genres      []Genre   `json:"genres"  gorm:"many2many:book_genres;"`
	Title       string    `json:"title" gorm:"index"`
	Series      string    `json:"series,omitempty"`
	SerNo       string    `json:"ser_no,omitempty"`
	File        string    `json:"file"`
	FileSize    string    `json:"file_size"`
	LibId       string    `json:"lib_id" gorm:"index"`
	Del         string    `json:"del"`
	Ext         string    `json:"ext"`
	Date        string    `json:"date"`
	Lang        string    `json:"lang"`
	Extra1      string    `json:"extra_1,omitempty"`
	Extra2      string    `json:"extra_2,omitempty"`
	Extra3      string    `json:"extra_3,omitempty"`
	Update      bool      `json:"-" gorm:"-"`
}

func (book *Book) AfterFind() {
	book.Title = utils.UpperInitialAll(book.Title)
}

func (book *Book) GetFullFilename() string {
	authors := ""
	for _, a := range book.Authors {
		authors = authors + a.Name
	}
	authors = re.ReplaceAllString(authors, "$1")
	outName := authors + " - "
	if book.SerNo != "" && book.SerNo != "0" {
		if len(book.SerNo) == 1 {
			book.SerNo = "0" + book.SerNo
		}
		outName = outName + "[" + book.SerNo + "] "
	}

	return outName + book.Title + "." + book.Ext
}
<commit_msg>Limit authors.<commit_after>package models

import (
	"regexp"

	"github.com/alxeg/flibooks/utils"
)

var re = regexp.MustCompile(`^[\s\P{L}]*(.*?)[\P{L}\s]*$`)

type Book struct {
	ID          uint      `gorm:"primary_key"`
	Container   Container `json:"container"`
	ContainerID uint      `json:"-"`
	Authors     []Author  `json:"authors" gorm:"many2many:book_authors;"`
	Genres      []Genre   `json:"genres"  gorm:"many2many:book_genres;"`
	Title       string    `json:"title" gorm:"index"`
	Series      string    `json:"series,omitempty"`
	SerNo       string    `json:"ser_no,omitempty"`
	File        string    `json:"file"`
	FileSize    string    `json:"file_size"`
	LibId       string    `json:"lib_id" gorm:"index"`
	Del         string    `json:"del"`
	Ext         string    `json:"ext"`
	Date        string    `json:"date"`
	Lang        string    `json:"lang"`
	Extra1      string    `json:"extra_1,omitempty"`
	Extra2      string    `json:"extra_2,omitempty"`
	Extra3      string    `json:"extra_3,omitempty"`
	Update      bool      `json:"-" gorm:"-"`
}

func (book *Book) AfterFind() {
	book.Title = utils.UpperInitialAll(book.Title)
}

func (book *Book) GetFullFilename() string {
	authors := ""
	for _, a := range book.Authors {
		authors = authors + a.Name
	}
	authors = re.ReplaceAllString(authors, "$1")
	if len(authors) > 100 {
		authors = string([]rune(authors)[0:100]) + `…`
	}
	outName := authors + " - "
	if book.SerNo != "" && book.SerNo != "0" {
		if len(book.SerNo) == 1 {
			book.SerNo = "0" + book.SerNo
		}
		outName = outName + "[" + book.SerNo + "] "
	}

	return outName + book.Title + "." + book.Ext
}
<|endoftext|>


<commit_before>package gosnmp

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"strconv"
	"strings"

	l "github.com/alouca/gologger"
)

type SnmpVersion uint8

const (
	Version1  SnmpVersion = 0x0
	Version2c SnmpVersion = 0x1
)

func (s SnmpVersion) String() string {
	if s == Version1 {
		return "1"
	} else if s == Version2c {
		return "2c"
	}
	return "U"
}

type SnmpPacket struct {
	Version        SnmpVersion
	Community      string
	RequestType    Asn1BER
	RequestID      uint32
	Error          uint8
	ErrorIndex     uint8
	NonRepeaters   uint8
	MaxRepetitions uint8
	Variables      []SnmpPDU
}

type SnmpPDU struct {
	Name  string
	Type  Asn1BER
	Value interface{}
}

func Unmarshal(packet []byte) (*SnmpPacket, error) {
	log := l.GetDefaultLogger()

	log.Debug("Begin SNMP Packet unmarshal\n")

	//var err error
	response := new(SnmpPacket)
	response.Variables = make([]SnmpPDU, 0, 5)

	// Start parsing the packet
	var cursor uint64 = 0

	// First bytes should be 0x30
	if Asn1BER(packet[0]) == Sequence {
		// Parse packet length
		ber, err := parseField(packet)

		if err != nil {
			log.Error("Unable to parse packet header: %s\n", err.Error())
			return nil, err
		}

		log.Debug("Packet sanity verified, we got all the bytes (%d)\n", ber.DataLength)

		cursor += ber.HeaderLength
		// Parse SNMP Version
		rawVersion, err := parseField(packet[cursor:])

		if err != nil {
			return nil, fmt.Errorf("Error parsing SNMP packet version: %s", err.Error())
		}

		cursor += rawVersion.DataLength + rawVersion.HeaderLength
		if version, ok := rawVersion.BERVariable.Value.(int); ok {
			response.Version = SnmpVersion(version)
			log.Debug("Parsed Version %d\n", version)
		}

		// Parse community
		rawCommunity, err := parseField(packet[cursor:])
		if err != nil {
			log.Debug("Unable to parse Community Field: %s\n", err)
		}
		cursor += rawCommunity.DataLength + rawCommunity.HeaderLength

		if community, ok := rawCommunity.BERVariable.Value.(string); ok {
			response.Community = community
			log.Debug("Parsed community %s\n", community)
		}

		rawPDU, err := parseField(packet[cursor:])

		if err != nil {
			log.Debug("Unable to parse SNMP PDU: %s\n", err.Error())
		}
		response.RequestType = rawPDU.Type

		switch rawPDU.Type {
		default:
			log.Debug("Unsupported SNMP Packet Type %s\n", rawPDU.Type.String())
			log.Debug("PDU Size is %d\n", rawPDU.DataLength)
		case GetRequest, GetResponse, GetBulkRequest:
			log.Debug("SNMP Packet is %s\n", rawPDU.Type.String())
			log.Debug("PDU Size is %d\n", rawPDU.DataLength)
			cursor += rawPDU.HeaderLength

			// Parse Request ID
			rawRequestId, err := parseField(packet[cursor:])

			if err != nil {
				return nil, err
			}

			cursor += rawRequestId.DataLength + rawRequestId.HeaderLength
			if requestid, ok := rawRequestId.BERVariable.Value.(int); ok {
				response.RequestID = uint32(requestid)
				log.Debug("Parsed Request ID: %d\n", requestid)
			}

			// Parse Error
			rawError, err := parseField(packet[cursor:])

			if err != nil {
				return nil, err
			}

			cursor += rawError.DataLength + rawError.HeaderLength
			if errorNo, ok := rawError.BERVariable.Value.(int); ok {
				response.Error = uint8(errorNo)
			}

			// Parse Error Index
			rawErrorIndex, err := parseField(packet[cursor:])

			if err != nil {
				return nil, err
			}

			cursor += rawErrorIndex.DataLength + rawErrorIndex.HeaderLength

			if errorindex, ok := rawErrorIndex.BERVariable.Value.(int); ok {
				response.ErrorIndex = uint8(errorindex)
			}

			log.Debug("Request ID: %d Error: %d Error Index: %d\n", response.RequestID, response.Error, response.ErrorIndex)
			rawResp, err := parseField(packet[cursor:])

			if err != nil {
				return nil, err
			}

			cursor += rawResp.HeaderLength
			// Loop & parse Varbinds
			for cursor < uint64(len(packet)) {
				log.Debug("Parsing var bind response (Cursor at %d/%d)", cursor, len(packet))

				rawVarbind, err := parseField(packet[cursor:])

				if err != nil {
					return nil, err
				}

				cursor += rawVarbind.HeaderLength
				log.Debug("Varbind length: %d/%d\n", rawVarbind.HeaderLength, rawVarbind.DataLength)

				log.Debug("Parsing OID (Cursor at %d)\n", cursor)
				// Parse OID
				rawOid, err := parseField(packet[cursor:])

				if err != nil {
					return nil, err
				}

				cursor += rawOid.HeaderLength + rawOid.DataLength

				log.Debug("OID (%v) Field was %d bytes\n", rawOid, rawOid.DataLength)

				rawValue, err := parseField(packet[cursor:])

				if err != nil {
					return nil, err
				}
				cursor += rawValue.HeaderLength + rawValue.DataLength

				log.Debug("Value field was %d bytes\n", rawValue.DataLength)

				if oid, ok := rawOid.BERVariable.Value.([]int); ok {
					log.Debug("Varbind decoding success\n")
					response.Variables = append(response.Variables, SnmpPDU{oidToString(oid), rawValue.Type, rawValue.BERVariable.Value})
				}
			}

		}
	} else {
		return nil, fmt.Errorf("Invalid packet header\n")
	}

	return response, nil
}

type RawBER struct {
	Type         Asn1BER
	HeaderLength uint64
	DataLength   uint64
	Data         []byte
	BERVariable  *Variable
}

// Parses a given field, return the ASN.1 BER Type, its header length and the data
func parseField(data []byte) (*RawBER, error) {
	log := l.GetDefaultLogger()
	var err error

	if len(data) == 0 {
		return nil, fmt.Errorf("Unable to parse BER: Data length 0")
	}

	ber := new(RawBER)

	ber.Type = Asn1BER(data[0])

	// Parse Length
	length := data[1]

	// Check if this is padded or not
	if length > 0x80 {
		length = length - 0x80
		log.Debug("Field length is padded to %d bytes\n", length)
		ber.DataLength = Uvarint(data[2 : 2+length])
		log.Debug("Decoded final length: %d\n", ber.DataLength)

		ber.HeaderLength = 2 + uint64(length)

	} else {
		ber.HeaderLength = 2
		ber.DataLength = uint64(length)
	}

	// Do sanity checks
	if ber.DataLength > uint64(len(data)) {
		return nil, fmt.Errorf("Unable to parse BER: provided data length is longer than actual data (%d vs %d)", ber.DataLength, len(data))
	}

	ber.Data = data[ber.HeaderLength : ber.HeaderLength+ber.DataLength]

	ber.BERVariable, err = decodeValue(ber.Type, ber.Data)

	if err != nil {
		return nil, fmt.Errorf("Unable to decode value: %s\n", err.Error())
	}

	return ber, nil
}

func (packet *SnmpPacket) marshal() ([]byte, error) {
	// Prepare the buffer to send
	buffer := make([]byte, 0, 1024)
	buf := bytes.NewBuffer(buffer)

	// Write the packet header (Message type 0x30) & Version = 2
	buf.Write([]byte{byte(Sequence), 0, 2, 1, byte(packet.Version)})

	// Write Community
	buf.Write([]byte{4, uint8(len(packet.Community))})
	buf.WriteString(packet.Community)

	// Marshal the SNMP PDU
	snmpPduBuffer := make([]byte, 0, 1024)
	snmpPduBuf := bytes.NewBuffer(snmpPduBuffer)

	requestIDBytes := make([]byte, 4)
	binary.BigEndian.PutUint32(requestIDBytes, packet.RequestID)
	snmpPduBuf.Write(append([]byte{byte(packet.RequestType), 0, 2, 4}, requestIDBytes...))

	switch packet.RequestType {
	case GetBulkRequest:
		snmpPduBuf.Write([]byte{
			2, 1, packet.NonRepeaters,
			2, 1, packet.MaxRepetitions,
		})
	default:
		snmpPduBuf.Write([]byte{
			2, 1, packet.Error,
			2, 1, packet.ErrorIndex,
		})
	}

	snmpPduBuf.Write([]byte{byte(Sequence), 0})

	pduLength := 0
	for _, varlist := range packet.Variables {
		pdu, err := marshalPDU(&varlist)

		if err != nil {
			return nil, err
		}
		pduLength += len(pdu)
		snmpPduBuf.Write(pdu)
	}

	pduBytes := snmpPduBuf.Bytes()
	// Varbind list length
	pduBytes[15] = byte(pduLength)
	// SNMP PDU length (PDU header + varbind list length)
	pduBytes[1] = byte(pduLength + 14)

	buf.Write(pduBytes)

	// Write the
	//buf.Write([]byte{packet.RequestType, uint8(17 + len(mOid)), 2, 1, 1, 2, 1, 0, 2, 1, 0, 0x30, uint8(6 + len(mOid)), 0x30, uint8(4 + len(mOid)), 6, uint8(len(mOid))})
	//buf.Write(mOid)
	//buf.Write([]byte{5, 0})

	ret := buf.Bytes()

	// Set the packet size
	ret[1] = uint8(len(ret) - 2)

	return ret, nil
}

func marshalPDU(pdu *SnmpPDU) ([]byte, error) {
	oid, err := marshalOID(pdu.Name)
	if err != nil {
		return nil, err
	}

	pduBuffer := make([]byte, 0, 1024)
	pduBuf := bytes.NewBuffer(pduBuffer)

	// Mashal the PDU type into the appropriate BER
	switch pdu.Type {
	case Null:
		pduBuf.Write([]byte{byte(Sequence), byte(len(oid) + 4)})
		pduBuf.Write([]byte{byte(ObjectIdentifier), byte(len(oid))})
		pduBuf.Write(oid)
		pduBuf.Write([]byte{Null, 0x00})
	default:
		return nil, fmt.Errorf("Unable to marshal PDU: unknown BER type %d", pdu.Type)
	}

	return pduBuf.Bytes(), nil
}

func oidToString(oid []int) (ret string) {
	values := make([]interface{}, len(oid))
	for i, v := range oid {
		values[i] = v
	}
	return fmt.Sprintf(strings.Repeat(".%d", len(oid)), values...)
}

func marshalOID(oid string) ([]byte, error) {
	var err error

	// Encode the oid
	oid = strings.Trim(oid, ".")
	oidParts := strings.Split(oid, ".")
	oidBytes := make([]int, len(oidParts))

	// Convert the string OID to an array of integers
	for i := 0; i < len(oidParts); i++ {
		oidBytes[i], err = strconv.Atoi(oidParts[i])
		if err != nil {
			return nil, fmt.Errorf("Unable to parse OID: %s\n", err.Error())
		}
	}

	mOid, err := marshalObjectIdentifier(oidBytes)

	if err != nil {
		return nil, fmt.Errorf("Unable to marshal OID: %s\n", err.Error())
	}

	return mOid, err
}
<commit_msg>Set the correct length for length >= 128<commit_after>package gosnmp

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"math"
	"strconv"
	"strings"

	l "github.com/alouca/gologger"
)

type SnmpVersion uint8

const (
	Version1  SnmpVersion = 0x0
	Version2c SnmpVersion = 0x1
)

func (s SnmpVersion) String() string {
	if s == Version1 {
		return "1"
	} else if s == Version2c {
		return "2c"
	}
	return "U"
}

type SnmpPacket struct {
	Version        SnmpVersion
	Community      string
	RequestType    Asn1BER
	RequestID      uint32
	Error          uint8
	ErrorIndex     uint8
	NonRepeaters   uint8
	MaxRepetitions uint8
	Variables      []SnmpPDU
}

type SnmpPDU struct {
	Name  string
	Type  Asn1BER
	Value interface{}
}

func Unmarshal(packet []byte) (*SnmpPacket, error) {
	log := l.GetDefaultLogger()

	log.Debug("Begin SNMP Packet unmarshal\n")

	//var err error
	response := new(SnmpPacket)
	response.Variables = make([]SnmpPDU, 0, 5)

	// Start parsing the packet
	var cursor uint64 = 0

	// First bytes should be 0x30
	if Asn1BER(packet[0]) == Sequence {
		// Parse packet length
		ber, err := parseField(packet)

		if err != nil {
			log.Error("Unable to parse packet header: %s\n", err.Error())
			return nil, err
		}

		log.Debug("Packet sanity verified, we got all the bytes (%d)\n", ber.DataLength)

		cursor += ber.HeaderLength
		// Parse SNMP Version
		rawVersion, err := parseField(packet[cursor:])

		if err != nil {
			return nil, fmt.Errorf("Error parsing SNMP packet version: %s", err.Error())
		}

		cursor += rawVersion.DataLength + rawVersion.HeaderLength
		if version, ok := rawVersion.BERVariable.Value.(int); ok {
			response.Version = SnmpVersion(version)
			log.Debug("Parsed Version %d\n", version)
		}

		// Parse community
		rawCommunity, err := parseField(packet[cursor:])
		if err != nil {
			log.Debug("Unable to parse Community Field: %s\n", err)
		}
		cursor += rawCommunity.DataLength + rawCommunity.HeaderLength

		if community, ok := rawCommunity.BERVariable.Value.(string); ok {
			response.Community = community
			log.Debug("Parsed community %s\n", community)
		}

		rawPDU, err := parseField(packet[cursor:])

		if err != nil {
			log.Debug("Unable to parse SNMP PDU: %s\n", err.Error())
		}
		response.RequestType = rawPDU.Type

		switch rawPDU.Type {
		default:
			log.Debug("Unsupported SNMP Packet Type %s\n", rawPDU.Type.String())
			log.Debug("PDU Size is %d\n", rawPDU.DataLength)
		case GetRequest, GetResponse, GetBulkRequest:
			log.Debug("SNMP Packet is %s\n", rawPDU.Type.String())
			log.Debug("PDU Size is %d\n", rawPDU.DataLength)
			cursor += rawPDU.HeaderLength

			// Parse Request ID
			rawRequestId, err := parseField(packet[cursor:])

			if err != nil {
				return nil, err
			}

			cursor += rawRequestId.DataLength + rawRequestId.HeaderLength
			if requestid, ok := rawRequestId.BERVariable.Value.(int); ok {
				response.RequestID = uint32(requestid)
				log.Debug("Parsed Request ID: %d\n", requestid)
			}

			// Parse Error
			rawError, err := parseField(packet[cursor:])

			if err != nil {
				return nil, err
			}

			cursor += rawError.DataLength + rawError.HeaderLength
			if errorNo, ok := rawError.BERVariable.Value.(int); ok {
				response.Error = uint8(errorNo)
			}

			// Parse Error Index
			rawErrorIndex, err := parseField(packet[cursor:])

			if err != nil {
				return nil, err
			}

			cursor += rawErrorIndex.DataLength + rawErrorIndex.HeaderLength

			if errorindex, ok := rawErrorIndex.BERVariable.Value.(int); ok {
				response.ErrorIndex = uint8(errorindex)
			}

			log.Debug("Request ID: %d Error: %d Error Index: %d\n", response.RequestID, response.Error, response.ErrorIndex)
			rawResp, err := parseField(packet[cursor:])

			if err != nil {
				return nil, err
			}

			cursor += rawResp.HeaderLength
			// Loop & parse Varbinds
			for cursor < uint64(len(packet)) {
				log.Debug("Parsing var bind response (Cursor at %d/%d)", cursor, len(packet))

				rawVarbind, err := parseField(packet[cursor:])

				if err != nil {
					return nil, err
				}

				cursor += rawVarbind.HeaderLength
				log.Debug("Varbind length: %d/%d\n", rawVarbind.HeaderLength, rawVarbind.DataLength)

				log.Debug("Parsing OID (Cursor at %d)\n", cursor)
				// Parse OID
				rawOid, err := parseField(packet[cursor:])

				if err != nil {
					return nil, err
				}

				cursor += rawOid.HeaderLength + rawOid.DataLength

				log.Debug("OID (%v) Field was %d bytes\n", rawOid, rawOid.DataLength)

				rawValue, err := parseField(packet[cursor:])

				if err != nil {
					return nil, err
				}
				cursor += rawValue.HeaderLength + rawValue.DataLength

				log.Debug("Value field was %d bytes\n", rawValue.DataLength)

				if oid, ok := rawOid.BERVariable.Value.([]int); ok {
					log.Debug("Varbind decoding success\n")
					response.Variables = append(response.Variables, SnmpPDU{oidToString(oid), rawValue.Type, rawValue.BERVariable.Value})
				}
			}

		}
	} else {
		return nil, fmt.Errorf("Invalid packet header\n")
	}

	return response, nil
}

type RawBER struct {
	Type         Asn1BER
	HeaderLength uint64
	DataLength   uint64
	Data         []byte
	BERVariable  *Variable
}

// Parses a given field, return the ASN.1 BER Type, its header length and the data
func parseField(data []byte) (*RawBER, error) {
	log := l.GetDefaultLogger()
	var err error

	if len(data) == 0 {
		return nil, fmt.Errorf("Unable to parse BER: Data length 0")
	}

	ber := new(RawBER)

	ber.Type = Asn1BER(data[0])

	// Parse Length
	length := data[1]

	// Check if this is padded or not
	if length > 0x80 {
		length = length - 0x80
		log.Debug("Field length is padded to %d bytes\n", length)
		ber.DataLength = Uvarint(data[2 : 2+length])
		log.Debug("Decoded final length: %d\n", ber.DataLength)

		ber.HeaderLength = 2 + uint64(length)

	} else {
		ber.HeaderLength = 2
		ber.DataLength = uint64(length)
	}

	// Do sanity checks
	if ber.DataLength > uint64(len(data)) {
		return nil, fmt.Errorf("Unable to parse BER: provided data length is longer than actual data (%d vs %d)", ber.DataLength, len(data))
	}

	ber.Data = data[ber.HeaderLength : ber.HeaderLength+ber.DataLength]

	ber.BERVariable, err = decodeValue(ber.Type, ber.Data)

	if err != nil {
		return nil, fmt.Errorf("Unable to decode value: %s\n", err.Error())
	}

	return ber, nil
}

func (packet *SnmpPacket) marshal() ([]byte, error) {
	// Marshal the SNMP PDU
	snmpPduBuffer := make([]byte, 0, 1024)
	snmpPduBuf := bytes.NewBuffer(snmpPduBuffer)

	requestIDBytes := make([]byte, 4)
	binary.BigEndian.PutUint32(requestIDBytes, packet.RequestID)
	snmpPduBuf.Write(append([]byte{byte(packet.RequestType), 0, 2, 4}, requestIDBytes...))

	switch packet.RequestType {
	case GetBulkRequest:
		snmpPduBuf.Write([]byte{
			2, 1, packet.NonRepeaters,
			2, 1, packet.MaxRepetitions,
		})
	default:
		snmpPduBuf.Write([]byte{
			2, 1, packet.Error,
			2, 1, packet.ErrorIndex,
		})
	}

	snmpPduBuf.Write([]byte{byte(Sequence), 0})

	pduLength := 0
	for _, varlist := range packet.Variables {
		pdu, err := marshalPDU(&varlist)

		if err != nil {
			return nil, err
		}
		pduLength += len(pdu)
		snmpPduBuf.Write(pdu)
	}

	pduBytes := snmpPduBuf.Bytes()
	// Varbind list length
	pduBytes[15] = byte(pduLength)
	// SNMP PDU length (PDU header + varbind list length)
	pduBytes[1] = byte(pduLength + 14)

	// Prepare the buffer to send
	buffer := make([]byte, 0, 1024)
	buf := bytes.NewBuffer(buffer)

	// Write the message type 0x30
	buf.Write([]byte{byte(Sequence)})

	// Find the size of the whole data
	// The extra 5 bytes are snmp verion (3 bytes) + community string type and
	// community string length
	dataLength := len(pduBytes) + len(packet.Community) + 5

	// If the data is 128 bytes or larger then we need to use 2 or more bytes
	// to represent the length
	if dataLength >= 128 {
		// Work out how many bytes we require
		bytesNeeded := int(math.Ceil(math.Log2(float64(dataLength)) / 8))
		// Set the most significant bit to 1 to show we are using the long for,
		// then the 7 least significant bits to show how many bytes will be used
		// to represent the length
		lengthIdentifier := 128 + bytesNeeded
		buf.Write([]byte{uint8(lengthIdentifier)})
		lengthBytes := make([]byte, bytesNeeded)
		for i := bytesNeeded; i >= 1; i-- {
			lengthBytes[i-1] = uint8(dataLength % 256)
			dataLength = dataLength >> 8
		}
		buf.Write(lengthBytes)
	} else {
		buf.Write([]byte{uint8(dataLength)})
	}

	// Write the Version
	buf.Write([]byte{2, 1, byte(packet.Version)})

	// Write Community
	buf.Write([]byte{4, uint8(len(packet.Community))})
	buf.WriteString(packet.Community)

	// Write the PDU
	buf.Write(pduBytes)

	// Write the
	//buf.Write([]byte{packet.RequestType, uint8(17 + len(mOid)), 2, 1, 1, 2, 1, 0, 2, 1, 0, 0x30, uint8(6 + len(mOid)), 0x30, uint8(4 + len(mOid)), 6, uint8(len(mOid))})
	//buf.Write(mOid)
	//buf.Write([]byte{5, 0})

	return buf.Bytes(), nil
}

func marshalPDU(pdu *SnmpPDU) ([]byte, error) {
	oid, err := marshalOID(pdu.Name)
	if err != nil {
		return nil, err
	}

	pduBuffer := make([]byte, 0, 1024)
	pduBuf := bytes.NewBuffer(pduBuffer)

	// Mashal the PDU type into the appropriate BER
	switch pdu.Type {
	case Null:
		pduBuf.Write([]byte{byte(Sequence), byte(len(oid) + 4)})
		pduBuf.Write([]byte{byte(ObjectIdentifier), byte(len(oid))})
		pduBuf.Write(oid)
		pduBuf.Write([]byte{Null, 0x00})
	default:
		return nil, fmt.Errorf("Unable to marshal PDU: unknown BER type %d", pdu.Type)
	}

	return pduBuf.Bytes(), nil
}

func oidToString(oid []int) (ret string) {
	values := make([]interface{}, len(oid))
	for i, v := range oid {
		values[i] = v
	}
	return fmt.Sprintf(strings.Repeat(".%d", len(oid)), values...)
}

func marshalOID(oid string) ([]byte, error) {
	var err error

	// Encode the oid
	oid = strings.Trim(oid, ".")
	oidParts := strings.Split(oid, ".")
	oidBytes := make([]int, len(oidParts))

	// Convert the string OID to an array of integers
	for i := 0; i < len(oidParts); i++ {
		oidBytes[i], err = strconv.Atoi(oidParts[i])
		if err != nil {
			return nil, fmt.Errorf("Unable to parse OID: %s\n", err.Error())
		}
	}

	mOid, err := marshalObjectIdentifier(oidBytes)

	if err != nil {
		return nil, fmt.Errorf("Unable to marshal OID: %s\n", err.Error())
	}

	return mOid, err
}
<|endoftext|>


<commit_before>package benchmark

import (
	"testing"
)

func BenchmarkSlice(b *testing.B) {
	const n = 100000

	b.Run("None", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			b.StopTimer()
			var dst []int
			b.StartTimer()
			for i := 0; i < n; i++ {
				dst = append(dst, i)
			}
		}
	})

	b.Run("Len", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			b.StopTimer()
			dst := make([]int, n)
			b.StartTimer()
			for i := 0; i < n; i++ {
				dst[i] = i
			}
		}
	})

	b.Run("Cap", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			b.StopTimer()
			dst := make([]int, 0, n)
			b.StartTimer()
			for i := 0; i < n; i++ {
				dst = append(dst, i)
			}
		}
	})

	b.Run("Len-Cap", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			b.StopTimer()
			dst := make([]int, n, n)
			b.StartTimer()
			for i := 0; i < n; i++ {
				dst[i] = i
			}
		}
	})
}
<commit_msg>Add merge<commit_after>package benchmark

import (
	"testing"
)

func BenchmarkSlice(b *testing.B) {
	const n = 100000

	b.Run("None", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			b.StopTimer()
			var dst []int
			b.StartTimer()
			for i := 0; i < n; i++ {
				dst = append(dst, i)
			}
		}
	})

	b.Run("Len", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			b.StopTimer()
			dst := make([]int, n)
			b.StartTimer()
			for i := 0; i < n; i++ {
				dst[i] = i
			}
		}
	})

	b.Run("Cap", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			b.StopTimer()
			dst := make([]int, 0, n)
			b.StartTimer()
			for i := 0; i < n; i++ {
				dst = append(dst, i)
			}
		}
	})

	b.Run("Len-Cap", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			b.StopTimer()
			dst := make([]int, n, n)
			b.StartTimer()
			for i := 0; i < n; i++ {
				dst[i] = i
			}
		}
	})
}

func mergeAAndB(a, b []int) []int {
	ret := make([]int, 0, len(a)+len(b))
	const step = 2

	i := 0
	for _, b := range b {
		left := i * step
		right := (i + 1) * step
		ret = append(ret, a[left:right]...)
		ret = append(ret, b)
		_ = b
		i++
	}

	return append(ret, a[i*step:]...)
}

var c []int

func BenchmarkMergeAAndB(b *testing.B) {
	as := []int{
		1, 2, 3, 4, 5, 6, 7, 8, 9,
	}
	bs := []int{
		91, 92, 93,
	}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		c = mergeAAndB(as, bs)
	}
}
<|endoftext|>


<commit_before>package merkletree2

import (
	"crypto/hmac"
	cryptorand "crypto/rand"
	"crypto/sha512"

	"github.com/keybase/go-codec/codec"
)

type EncodingType uint8

const (
	// For KeyValuePairs, the hash of the pair (k, v) is p(p(k, s), v )) where p
	// = HMAC-SHA512-256 and s is a secret unique per Merkle seqno. Note that
	// users learn k, v and p(k,s) but not s itself, so the hash is a commitment
	// to the value only and not the key. However, the key is written and hashed
	// as part of the merkle tree leaf node, so keybase cannot equivocate that.
	// For generic data structures, this encoder uses SHA512-256 to hash the
	// msgpack canonical encoding.
	EncodingTypeBlindedSHA512_256v1 EncodingType = 1

	// Generic testing encoding.
	EncodingTypeForTesting EncodingType = 127
)

func (e EncodingType) GetEncoder() Encoder {
	switch e {
	case EncodingTypeBlindedSHA512_256v1:
		return NewBlindedSHA512_256v1Encoder()
	default:
		panic("Invalid EncodingType")
	}
}

// BlindedSHA512_256v1Encoder is not safe for concurrent use.
type BlindedSHA512_256v1Encoder struct {
	enc *codec.Encoder
	dec *codec.Decoder
}

var _ Encoder = &BlindedSHA512_256v1Encoder{}

func NewBlindedSHA512_256v1Encoder() *BlindedSHA512_256v1Encoder {
	var mh codec.MsgpackHandle
	mh.WriteExt = true
	mh.Canonical = true

	return &BlindedSHA512_256v1Encoder{enc: codec.NewEncoderBytes(nil, &mh), dec: codec.NewDecoderBytes(nil, &mh)}
}

func (e *BlindedSHA512_256v1Encoder) Encode(o interface{}) (out []byte, err error) {
	e.enc.ResetBytes(&out)
	return out, e.enc.Encode(o)
}

func (e *BlindedSHA512_256v1Encoder) Decode(dest interface{}, src []byte) error {
	e.dec.ResetBytes(src)
	return e.dec.Decode(dest)
}

func (e *BlindedSHA512_256v1Encoder) EncodeAndHashGeneric(o interface{}) ([]byte, Hash, error) {
	enc, err := e.Encode(o)
	if err != nil {
		return nil, nil, err
	}
	hasher := sha512.New512_256()
	// hasher.Write never errors.
	_, _ = hasher.Write(enc)
	return enc, hasher.Sum(nil), nil
}

func (e *BlindedSHA512_256v1Encoder) HashKeyValuePairWithKeySpecificSecret(kvp KeyValuePair, kss KeySpecificSecret) (Hash, error) {
	encVal, err := e.Encode(kvp.Value)
	if err != nil {
		return nil, err
	}
	return e.HashKeyEncodedValuePairWithKeySpecificSecret(KeyEncodedValuePair{Key: kvp.Key, Value: encVal}, kss)
}

func (e *BlindedSHA512_256v1Encoder) HashKeyEncodedValuePairWithKeySpecificSecret(kevp KeyEncodedValuePair, kss KeySpecificSecret) (Hash, error) {
	hasher := hmac.New(sha512.New512_256, kss)
	// hasher.Write never errors.
	_, _ = hasher.Write(kevp.Value)
	return hasher.Sum(nil), nil
}

func (e *BlindedSHA512_256v1Encoder) GenerateMasterSecret(Seqno) (MasterSecret, error) {
	secret := make([]byte, 32)
	_, err := cryptorand.Read(secret)
	return MasterSecret(secret), err
}

func (e *BlindedSHA512_256v1Encoder) ComputeKeySpecificSecret(ms MasterSecret, k Key) KeySpecificSecret {
	hasher := hmac.New(sha512.New512_256, ms)
	// hasher.Write never errors.
	_, _ = hasher.Write(k)
	return hasher.Sum(nil)
}

func (e *BlindedSHA512_256v1Encoder) GetEncodingType() EncodingType {
	return EncodingTypeBlindedSHA512_256v1
}
<commit_msg>make blind tree encoder thread safe (needed as the surveyor can serve more than one request at a time using the same encoder) (#20802)<commit_after>package merkletree2

import (
	"crypto/hmac"
	cryptorand "crypto/rand"
	"crypto/sha512"

	"github.com/keybase/go-codec/codec"
)

type EncodingType uint8

const (
	// For KeyValuePairs, the hash of the pair (k, v) is p(p(k, s), v )) where p
	// = HMAC-SHA512-256 and s is a secret unique per Merkle seqno. Note that
	// users learn k, v and p(k,s) but not s itself, so the hash is a commitment
	// to the value only and not the key. However, the key is written and hashed
	// as part of the merkle tree leaf node, so keybase cannot equivocate that.
	// For generic data structures, this encoder uses SHA512-256 to hash the
	// msgpack canonical encoding.
	EncodingTypeBlindedSHA512_256v1 EncodingType = 1

	// Generic testing encoding.
	EncodingTypeForTesting EncodingType = 127
)

func (e EncodingType) GetEncoder() Encoder {
	switch e {
	case EncodingTypeBlindedSHA512_256v1:
		return NewBlindedSHA512_256v1Encoder()
	default:
		panic("Invalid EncodingType")
	}
}

type BlindedSHA512_256v1Encoder struct {
	mh codec.MsgpackHandle
}

var _ Encoder = &BlindedSHA512_256v1Encoder{}

func NewBlindedSHA512_256v1Encoder() *BlindedSHA512_256v1Encoder {
	var mh codec.MsgpackHandle
	mh.WriteExt = true
	mh.Canonical = true

	return &BlindedSHA512_256v1Encoder{mh: mh}
}

func (e *BlindedSHA512_256v1Encoder) Encode(o interface{}) (out []byte, err error) {
	return out, codec.NewEncoderBytes(&out, &e.mh).Encode(o)
}

func (e *BlindedSHA512_256v1Encoder) Decode(dest interface{}, src []byte) error {
	return codec.NewDecoderBytes(src, &e.mh).Decode(dest)
}

func (e *BlindedSHA512_256v1Encoder) EncodeAndHashGeneric(o interface{}) ([]byte, Hash, error) {
	enc, err := e.Encode(o)
	if err != nil {
		return nil, nil, err
	}
	hasher := sha512.New512_256()
	// hasher.Write never errors.
	_, _ = hasher.Write(enc)
	return enc, hasher.Sum(nil), nil
}

func (e *BlindedSHA512_256v1Encoder) HashKeyValuePairWithKeySpecificSecret(kvp KeyValuePair, kss KeySpecificSecret) (Hash, error) {
	encVal, err := e.Encode(kvp.Value)
	if err != nil {
		return nil, err
	}
	return e.HashKeyEncodedValuePairWithKeySpecificSecret(KeyEncodedValuePair{Key: kvp.Key, Value: encVal}, kss)
}

func (e *BlindedSHA512_256v1Encoder) HashKeyEncodedValuePairWithKeySpecificSecret(kevp KeyEncodedValuePair, kss KeySpecificSecret) (Hash, error) {
	hasher := hmac.New(sha512.New512_256, kss)
	// hasher.Write never errors.
	_, _ = hasher.Write(kevp.Value)
	return hasher.Sum(nil), nil
}

func (e *BlindedSHA512_256v1Encoder) GenerateMasterSecret(Seqno) (MasterSecret, error) {
	secret := make([]byte, 32)
	_, err := cryptorand.Read(secret)
	return MasterSecret(secret), err
}

func (e *BlindedSHA512_256v1Encoder) ComputeKeySpecificSecret(ms MasterSecret, k Key) KeySpecificSecret {
	hasher := hmac.New(sha512.New512_256, ms)
	// hasher.Write never errors.
	_, _ = hasher.Write(k)
	return hasher.Sum(nil)
}

func (e *BlindedSHA512_256v1Encoder) GetEncodingType() EncodingType {
	return EncodingTypeBlindedSHA512_256v1
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Vitess 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 main

import (
	"flag"
	"fmt"
	"go/parser"
	"go/token"
	"os"

	"vitess.io/vitess/go/visitorgen"
)

var (
	inputFile  = flag.String("input", "", "input file to use")
	outputFile = flag.String("output", "", "output file")
)

const usage = `Usage of visitorgen:

go run go/visitorgen/main/main.go -input=/path/to/ast.go -output=/path/to/rewriter.go
`

func main() {
	flag.Usage = func() {
		os.Stderr.WriteString(usage)
		os.Stderr.WriteString("\nOptions:\n")
		flag.PrintDefaults()

	}
	flag.Parse()

	if *inputFile == "" || *outputFile == "" {
		fmt.Println("> " + *inputFile)
		fmt.Println("> " + *outputFile)
		panic("need input and output file")
	}

	fs := token.NewFileSet()
	file, err := parser.ParseFile(fs, *inputFile, nil, parser.DeclarationErrors)
	if err != nil {
		panic(err)
	}

	astWalkResult := visitorgen.Walk(file)
	vp := visitorgen.Transform(astWalkResult)
	vd := visitorgen.ToVisitorPlan(vp)

	replacementMethods := visitorgen.EmitReplacementMethods(vd)
	typeSwitch := visitorgen.EmitTypeSwitches(vd)

	fw := newFileWriter(*outputFile)
	defer fw.Close()

	fw.writeln(fileHeader)
	fw.writeln(replacementMethods)
	fw.write(applyHeader)
	fw.writeln(typeSwitch)
	fw.writeln(fileFooter)
}

type fileWriter struct {
	file *os.File
}

func newFileWriter(file string) *fileWriter {
	f, err := os.Create(file)
	if err != nil {
		panic(err)
	}
	return &fileWriter{file: f}
}

func (fw *fileWriter) writeln(s string) {
	fw.write(s)
	fw.write("\n")
}

func (fw *fileWriter) write(s string) {
	_, err := fw.file.WriteString(s)
	if err != nil {
		panic(err)
	}
}

func (fw *fileWriter) Close() {
	fw.file.Close()
}

const fileHeader = `// Code generated by visitorgen/main/main.go. DO NOT EDIT.

package sqlparser

//go:generate make visitor

import (
	"reflect"
)

type replacerFunc func(newNode, parent SQLNode)

// application carries all the shared data so we can pass it around cheaply.
type application struct {
	pre, post ApplyFunc
	cursor    Cursor
}
`

const applyHeader = `
// apply is where the visiting happens. Here is where we keep the big switch-case that will be used
// to do the actual visiting of SQLNodes
func (a *application) apply(parent, node SQLNode, replacer replacerFunc) {
	if node == nil || isNilValue(node) {
		return
	}

	// avoid heap-allocating a new cursor for each apply call; reuse a.cursor instead
	saved := a.cursor
	a.cursor.replacer = replacer
	a.cursor.node = node
	a.cursor.parent = parent

	if a.pre != nil && !a.pre(&a.cursor) {
		a.cursor = saved
		return
	}

	// walk children
	// (the order of the cases is alphabetical)
	switch n := node.(type) {
	case nil:
	`

const fileFooter = `
	default:
		panic("unknown ast type " + reflect.TypeOf(node).String())
	}

	if a.post != nil && !a.post(&a.cursor) {
		panic(abort)
	}

	a.cursor = saved
}

func isNilValue(i interface{}) bool {
	valueOf := reflect.ValueOf(i)
	kind := valueOf.Kind()
	isNullable := kind == reflect.Ptr || kind == reflect.Array || kind == reflect.Slice
	return isNullable && valueOf.IsNil()
}`
<commit_msg>Cleanup of main() code<commit_after>/*
Copyright 2019 The Vitess 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 main

import (
	"bytes"
	"flag"
	"fmt"
	"go/parser"
	"go/token"
	"io/ioutil"
	"os"

	"vitess.io/vitess/go/exit"
	"vitess.io/vitess/go/vt/log"

	"vitess.io/vitess/go/visitorgen"
)

var (
	inputFile  = flag.String("input", "", "input file to use")
	outputFile = flag.String("output", "", "output file")
)

const usage = `Usage of visitorgen:

go run ./go/visitorgen/main -input=/path/to/ast.go -output=/path/to/rewriter.go
`

func main() {
	defer exit.Recover()
	flag.Usage = printUsage
	flag.Parse()

	if *inputFile == "" || *outputFile == "" {
		printUsage()
		exit.Return(1)
	}

	fs := token.NewFileSet()
	file, err := parser.ParseFile(fs, *inputFile, nil, parser.DeclarationErrors)
	if err != nil {
		log.Error(err)
		exit.Return(1)
	}

	astWalkResult := visitorgen.Walk(file)
	vp := visitorgen.Transform(astWalkResult)
	vd := visitorgen.ToVisitorPlan(vp)

	replacementMethods := visitorgen.EmitReplacementMethods(vd)
	typeSwitch := visitorgen.EmitTypeSwitches(vd)

	b := &bytes.Buffer{}
	fmt.Fprint(b, fileHeader)
	fmt.Fprintln(b)
	fmt.Fprintln(b, replacementMethods)
	fmt.Fprint(b, applyHeader)
	fmt.Fprintln(b, typeSwitch)
	fmt.Fprintln(b, fileFooter)

	err = ioutil.WriteFile(*outputFile, b.Bytes(), 0644)
	if err != nil {
		log.Error(err)
		exit.Return(1)
	}
}

func printUsage() {
	os.Stderr.WriteString(usage)
	os.Stderr.WriteString("\nOptions:\n")
	flag.PrintDefaults()
}

const fileHeader = `// Code generated by visitorgen/main/main.go. DO NOT EDIT.

package sqlparser

//go:generate make visitor

import (
	"reflect"
)

type replacerFunc func(newNode, parent SQLNode)

// application carries all the shared data so we can pass it around cheaply.
type application struct {
	pre, post ApplyFunc
	cursor    Cursor
}
`

const applyHeader = `
// apply is where the visiting happens. Here is where we keep the big switch-case that will be used
// to do the actual visiting of SQLNodes
func (a *application) apply(parent, node SQLNode, replacer replacerFunc) {
	if node == nil || isNilValue(node) {
		return
	}

	// avoid heap-allocating a new cursor for each apply call; reuse a.cursor instead
	saved := a.cursor
	a.cursor.replacer = replacer
	a.cursor.node = node
	a.cursor.parent = parent

	if a.pre != nil && !a.pre(&a.cursor) {
		a.cursor = saved
		return
	}

	// walk children
	// (the order of the cases is alphabetical)
	switch n := node.(type) {
	case nil:
	`

const fileFooter = `
	default:
		panic("unknown ast type " + reflect.TypeOf(node).String())
	}

	if a.post != nil && !a.post(&a.cursor) {
		panic(abort)
	}

	a.cursor = saved
}

func isNilValue(i interface{}) bool {
	valueOf := reflect.ValueOf(i)
	kind := valueOf.Kind()
	isNullable := kind == reflect.Ptr || kind == reflect.Array || kind == reflect.Slice
	return isNullable && valueOf.IsNil()
}`
<|endoftext|>


<commit_before>package render

import (
	"encoding/json"
	"encoding/xml"
	"github.com/andviro/noodle"
	"golang.org/x/net/context"
	"html/template"
	"io"
	"net/http"
	"sync"
)

var renderKey int = 0

type renderResult struct {
	mu   sync.RWMutex // guards data
	code int
	data interface{}
}

// htmlJSON is a generic template for outputting JSON data inside a PRE tag
var htmlJSON = template.Must(template.New("htmlJSON").Parse("
{{.}}
"))

// SerializerFunc is modelled after template's Execute method.
// Used by Generic middleware factory to create specific rendering middlewares
type SerializerFunc func(io.Writer, interface{}) error

// Generic factory for a middleware that lifts handler's data object from context
// and serializes it into HTTP ResponseWriter. Receives SerializerFunc and content type
func Generic(s SerializerFunc, contentType string) noodle.Middleware {
	return func(next noodle.Handler) noodle.Handler {
		return func(c context.Context, w http.ResponseWriter, r *http.Request) error {
			var res renderResult

			err := next(context.WithValue(c, renderKey, &res), w, r)
			if err != nil {
				return err
			}
			w.Header().Set("Content-Type", contentType)

			res.mu.RLock()
			defer res.mu.RUnlock()
			if res.code != 0 {
				w.WriteHeader(res.code)
			}
			return s(w, res.data)
		}
	}
}

// JSON serializes result object into JSON format
var JSON = Generic(func(w io.Writer, data interface{}) error {
	return json.NewEncoder(w).Encode(data)
}, "application/json")

// XML serializes result object into "application/xml" content type. Use TextXML for "text/xml" output.
var XML = Generic(func(w io.Writer, data interface{}) error {
	return xml.NewEncoder(w).Encode(data)
}, "application/xml")

// TextXML is the same as XML, but with "text/xml" content type
var TextXML = Generic(func(w io.Writer, data interface{}) error {
	return xml.NewEncoder(w).Encode(data)
}, "text/xml")

// Template creates middleware that applies pre-compiled template to handler's data object
func Template(tpl *template.Template) noodle.Middleware {
	return Generic(tpl.Execute, "text/html")
}

// ContentType creates renderer middleware that renders response to JSON, XML or HTML template
// based on Accept header.  If Accept header is not specified, JSON is used as the output format.
// If nil is passed as template, only XML and JSON are rendered and text/html is output as JSON inside PRE tag.
func ContentType(tpl *template.Template) noodle.Middleware {
	var htmlRender noodle.Middleware
	if tpl == nil {
		htmlRender = Generic(func(w io.Writer, data interface{}) error {
			s, err := json.MarshalIndent(data, "", "  ")
			if err != nil {
				return err
			}
			return htmlJSON.Execute(w, string(s))
		}, "text/html")
	} else {
		htmlRender = Template(tpl)
	}
	return func(next noodle.Handler) noodle.Handler {
		return func(c context.Context, w http.ResponseWriter, r *http.Request) error {
			switch r.Header.Get("Accept") {
			case "text/xml":
				return TextXML(next)(c, w, r)
			case "application/xml":
				return XML(next)(c, w, r)
			case "text/html":
				return htmlRender(next)(c, w, r)
			default:
				return JSON(next)(c, w, r)
			}
		}
	}
}

// Yield puts arbitrary data into context for subsequent rendering into response.
// The first argument of Yield is a HTTP status code.
func Yield(c context.Context, code int, data interface{}) error {
	dest := c.Value(renderKey).(*renderResult)
	dest.mu.Lock() // better safe than sorry
	defer dest.mu.Unlock()
	dest.code = code
	dest.data = data
	return nil
}
<commit_msg>added UTF-8 as the default charset<commit_after>package render

import (
	"encoding/json"
	"encoding/xml"
	"github.com/andviro/noodle"
	"golang.org/x/net/context"
	"html/template"
	"io"
	"net/http"
	"sync"
)

var renderKey int = 0

type renderResult struct {
	mu   sync.RWMutex // guards data
	code int
	data interface{}
}

// htmlJSON is a generic template for outputting JSON data inside a PRE tag
var htmlJSON = template.Must(template.New("htmlJSON").Parse("
{{.}}
"))

// SerializerFunc is modelled after template's Execute method.
// Used by Generic middleware factory to create specific rendering middlewares
type SerializerFunc func(io.Writer, interface{}) error

// Generic factory for a middleware that lifts handler's data object from context
// and serializes it into HTTP ResponseWriter. Receives SerializerFunc and content type
func Generic(s SerializerFunc, contentType string) noodle.Middleware {
	return func(next noodle.Handler) noodle.Handler {
		return func(c context.Context, w http.ResponseWriter, r *http.Request) error {
			var res renderResult

			err := next(context.WithValue(c, renderKey, &res), w, r)
			if err != nil {
				return err
			}
			w.Header().Set("Content-Type", contentType)

			res.mu.RLock()
			defer res.mu.RUnlock()
			if res.code != 0 {
				w.WriteHeader(res.code)
			}
			return s(w, res.data)
		}
	}
}

// JSON serializes result object into JSON format
var JSON = Generic(func(w io.Writer, data interface{}) error {
	return json.NewEncoder(w).Encode(data)
}, "application/json;charset=utf-8")

// XML serializes result object into "application/xml" content type. Use TextXML for "text/xml" output.
var XML = Generic(func(w io.Writer, data interface{}) error {
	return xml.NewEncoder(w).Encode(data)
}, "application/xml;charset=utf-8")

// TextXML is the same as XML, but with "text/xml" content type
var TextXML = Generic(func(w io.Writer, data interface{}) error {
	return xml.NewEncoder(w).Encode(data)
}, "text/xml;charset=utf-8")

// Template creates middleware that applies pre-compiled template to handler's data object
func Template(tpl *template.Template) noodle.Middleware {
	return Generic(tpl.Execute, "text/html;charset=utf-8")
}

// ContentType creates renderer middleware that renders response to JSON, XML or HTML template
// based on Accept header.  If Accept header is not specified, JSON is used as the output format.
// If nil is passed as template, only XML and JSON are rendered and text/html is output as JSON inside PRE tag.
func ContentType(tpl *template.Template) noodle.Middleware {
	var htmlRender noodle.Middleware
	if tpl == nil {
		htmlRender = Generic(func(w io.Writer, data interface{}) error {
			s, err := json.MarshalIndent(data, "", "  ")
			if err != nil {
				return err
			}
			return htmlJSON.Execute(w, string(s))
		}, "text/html;charset=utf-8")
	} else {
		htmlRender = Template(tpl)
	}
	return func(next noodle.Handler) noodle.Handler {
		return func(c context.Context, w http.ResponseWriter, r *http.Request) error {
			switch r.Header.Get("Accept") {
			case "text/xml":
				return TextXML(next)(c, w, r)
			case "application/xml":
				return XML(next)(c, w, r)
			case "text/html":
				return htmlRender(next)(c, w, r)
			default:
				return JSON(next)(c, w, r)
			}
		}
	}
}

// Yield puts arbitrary data into context for subsequent rendering into response.
// The first argument of Yield is a HTTP status code.
func Yield(c context.Context, code int, data interface{}) error {
	dest := c.Value(renderKey).(*renderResult)
	dest.mu.Lock() // better safe than sorry
	defer dest.mu.Unlock()
	dest.code = code
	dest.data = data
	return nil
}
<|endoftext|>


<commit_before>package tuplespace

import (
	"reflect"
	"sync"
	"testing"
	"time"
)

var testTupleSpace *TupleSpace

func init() {
	testTupleSpace = CreateTupleSpace(9080)
}

// TestCreateTupleSpace will test that the tuple space is initialised as
// intended.
func TestCreateTupleSpace(t *testing.T) {
	tuplespaceManual := TupleSpace{muTuples: new(sync.RWMutex), muWaitingClients: new(sync.RWMutex), port: ":8081"}

	// Check equality between the mutex for tuples[].
	if !reflect.DeepEqual(testTupleSpace.muTuples, tuplespaceManual.muTuples) {
		t.Errorf("The mutex of %+v looks like %q and should have looked like the mutex of %+v, which looks like %q.", *testTupleSpace, testTupleSpace.muTuples, tuplespaceManual, tuplespaceManual.muTuples)
	}

	// Check equality between the mutex for waitingClients[].
	if !reflect.DeepEqual(testTupleSpace.muWaitingClients, tuplespaceManual.muWaitingClients) {
		t.Errorf("The mutex of %+v looks like %q and should have looked like the mutex of %+v, which looks like %q.", *testTupleSpace, testTupleSpace.muWaitingClients, tuplespaceManual, tuplespaceManual.muWaitingClients)
	}

	// Check equality between the data structures for storing tuples.
	if !reflect.DeepEqual(testTupleSpace.tuples, tuplespaceManual.tuples) {
		t.Errorf("The data structure to store tuples of %+v looks like %q and should have looked like the data structure of %+v, which looks like %q.", *testTupleSpace, testTupleSpace.tuples, tuplespaceManual, tuplespaceManual.tuples)
	}

	// Check equality between the data structures for storing waiting clients.
	if !reflect.DeepEqual(testTupleSpace.waitingClients, tuplespaceManual.waitingClients) {
		t.Errorf("The data structure to store tuples of %+v looks like %+v and should have looked like the data structure of %+v, which looks like %+v.", *testTupleSpace, testTupleSpace.waitingClients, tuplespaceManual, tuplespaceManual.waitingClients)
	}

	// Check port number is of right format.
	if !reflect.DeepEqual(testTupleSpace.port, ":9080") {
		t.Errorf("The port number of %+v looks like %q and should have looked like the :9080", *testTupleSpace, testTupleSpace.port)
	}
}

// TestTupleSpaceSize will make sure Size() returns the right size of the data
// structure for tuples. The size is defined as the amount of tuples.
func TestTupleSpaceSize(t *testing.T) {
	tuplesSizeExpected := 0
	tuplesSize := testTupleSpace.Size()

	// Check the two sizes are equal.
	if !reflect.DeepEqual(tuplesSize, tuplesSizeExpected) {
		t.Errorf("The size of tuples was %d but was expected to have the size %d", tuplesSize, tuplesSizeExpected)
	}
}

// TestAddNewClient will make sure the right client is added to the data
// structure correctly.
func TestAddNewClient(t *testing.T) {
	// Initially check there are no waiting clients by securing the size of it
	// is 0.
	if len(testTupleSpace.waitingClients) != 0 {
		t.Errorf("The size of %+v was %d but was expected to have the size 0.", testTupleSpace.waitingClients, len(testTupleSpace.waitingClients))
	}

	// Make a client.
	temp := CreateTemplate("test field")
	response := make(chan *Tuple)
	remove := false // QueryRequest
	client := CreateWaitingClient(temp, response, remove)

	// Add client to the data structure with method.
	testTupleSpace.addNewClient(client)

	// Check that the size of the waitingClients is 1.
	if len(testTupleSpace.waitingClients) != 1 {
		t.Errorf("The size of %+v was %d but was expected to have the size 1 after the client %+v was added to an empty data structure", testTupleSpace.waitingClients, len(testTupleSpace.waitingClients), client)
	}
}

func TestRemoveClientAt(t *testing.T) {
	// Initially check there are one waiting client from previous test by
	// securing the size of it is 1.
	if len(testTupleSpace.waitingClients) != 1 {
		t.Errorf("The size of %+v was %d but was expected to have the size 1.", testTupleSpace.waitingClients, len(testTupleSpace.waitingClients))
	}

	// Add two additional clients.
	// Make a client.
	temp2 := CreateTemplate("test field2")
	temp3 := CreateTemplate("test field3")
	response := make(chan *Tuple)
	remove := false // QueryRequest
	client2 := CreateWaitingClient(temp2, response, remove)
	client3 := CreateWaitingClient(temp3, response, remove)
	// NOTE: client is not added, as it was added in the previous test.
	testTupleSpace.addNewClient(client2)
	testTupleSpace.addNewClient(client3)

	// Remove the 2nd client for waitingClients.
	testTupleSpace.removeClientAt(1)
	// The third client is now found at the index where the 2nd client used to
	// be.
	// Check that the 3rd client is at 1
	if !reflect.DeepEqual(testTupleSpace.waitingClients[1], client3) {
		t.Errorf("The client %+v from the waitingClients isn't equal to the client %+v that was added to the waitingClients.", testTupleSpace.waitingClients[1], client3)
	}

	// Remove the 3rd client for waitingClients.
	testTupleSpace.removeClientAt(1)

	// Check that the size is as started, 1
	if len(testTupleSpace.waitingClients) != 1 {
		t.Errorf("The size of %+v was %d but was expected to have the size 1.", testTupleSpace.waitingClients, len(testTupleSpace.waitingClients))
	}

	// Remove the last client to clear the tuple space.
	testTupleSpace.removeClientAt(0)
}

// TestTupleSpacePutP will make sure a tuple is added to the tuple space
// correctly.
func TestTupleSpacePutPNoWaitingClients(t *testing.T) {
	// Initially check the tuple space is empty by securing the size of it is
	// 0.
	if testTupleSpace.Size() != 0 {
		t.Errorf("The size of %q was %d but was expected to have the size 0.", testTupleSpace.tuples, testTupleSpace.Size())
	}

	// Initially check there are no waiting clients by securing the size of it
	// is 0.
	if len(testTupleSpace.waitingClients) != 0 {
		t.Errorf("The size of %+v was %d but was expected to have the size 0.", testTupleSpace.waitingClients, len(testTupleSpace.waitingClients))
	}

	// Add a tuple to the tuple space.
	testTupleSpace.putP(&testTupleFourFields)

	// Check that the size of the tuples is 1.
	if testTupleSpace.Size() != 1 {
		t.Errorf("The size of %q was %d but was expected to have the size 1 after to tuple %q was added to an empty tuple space", testTupleSpace.tuples, testTupleSpace.Size(), testTupleFourFields)
	}

	// Extract the tuple from the data structure for tuples in the tuple space
	// and check it was added without being altered.
	tuple := testTupleSpace.tuples[0]

	if !reflect.DeepEqual(testTupleFourFields, tuple) {
		t.Errorf("The tuple %q from the tuple spaces isn't equal to the tuple %q that was added to the tuple space.", tuple, testTupleFourFields)
	}
}

// TestTupleSpaceClearTupleSpace will make sure that the method will clear the
// data structure tuples[] for tuples.
func TestTupleSpaceClearTupleSpace(t *testing.T) {
	// Initially check that the tuple space contains some number of tuples.
	if testTupleSpace.Size() == 0 {
		t.Errorf("The tuple space is empty, %q, and should contain some amount of tuples to test clearTupleSpace().", testTupleSpace.tuples)
	}

	// Clear the tuple space for exsisting tuples.
	testTupleSpace.clearTupleSpace()

	if testTupleSpace.Size() != 0 {
		t.Errorf("The size of %q was %d but was expected to have the size 0.", testTupleSpace.tuples, testTupleSpace.Size())
	}
}

// TestTupleSpacePut will make sure a tuple is the right response is returned
// when a tuple has been added to the tuple space.
func TestTupleSpacePut(t *testing.T) {
	// Make sure the tuple space is empty.
	testTupleSpace.clearTupleSpace()

	// Create channel to receive the response.
	response := make(chan bool)

	// Add the tuple to the tuple space with the put()
	go func() {
		testTupleSpace.put(&testTupleFourFields, response)
		time.Sleep(time.Second * 1)
	}()

	// Read the response from the channel.
	b := <-response

	// Check the response is as expected.
	if !b {
		t.Errorf("TestTupleSpaceFindTuple(%t) should be true", b)
	}
}

// TestTupleSpaceRemoveTupleAt will make sure the right tuple is removed.
func TestTupleSpaceRemoveTupleAt(t *testing.T) {
	// Initially check that the tuple space contains some number of tuples.
	if testTupleSpace.Size() == 0 {
		t.Errorf("The tuple space is empty, %q, and should contain some amount of tuples to test clearTupleSpace().", testTupleSpace.tuples)
	}

	// Get the first tuple.
	tuple := testTupleSpace.tuples[0]

	// Remove the first tuple from the tuple space.
	testTupleSpace.removeTupleAt(0)

	// Check the tuple isn't in the tuple space anymore.
	for _, tupleFromTS := range testTupleSpace.tuples {
		if reflect.DeepEqual(tuple, tupleFromTS) {
			t.Errorf("The tuple %q is still in the tuples space %q", tuple, testTupleSpace.tuples)
		}
	}
}

// TestTupleSpaceFindTuple will make sure that the right tuple is found of the
// data structure of tuples.
func TestTupleSpaceFindTuple(t *testing.T) {
	// Make sure the tuple space is empty.
	testTupleSpace.clearTupleSpace()

	// Add a tuple to the tuple space.
	testTupleSpace.putP(&testTupleTwoFields)

	// Create a template that matches the tuple just added to the tuple space.
	temp := CreateTemplate("Field 1", true)

	// Find the tuple using the method, without removing the tuple.
	t1 := testTupleSpace.findTuple(temp, false)

	// Check that the tuple found is equal to the tuple that was added.
	if !reflect.DeepEqual(*t1, testTupleTwoFields) {
		t.Errorf("The tuple %q was found by the method by should be %q", *t1, testTupleTwoFields)
	}

	// Check that the tuple wasn't removed from the tuple space
	if testTupleSpace.Size() != 1 {
		t.Errorf("The size of %q was %d but was expected to have the size 1 as the tuple shouldn't have been removed from the tuple space", testTupleSpace.tuples, testTupleSpace.Size())
	}

	// Find the tuple using the method and removing the tuple.
	t2 := testTupleSpace.findTuple(temp, true)

	// Check that the tuple found is equal to the tuple that was added.
	if !reflect.DeepEqual(*t2, testTupleTwoFields) {
		t.Errorf("The tuple %q was found by the method by should be %q", *t1, testTupleTwoFields)
	}

	// Check that the tuple was removed from the tuple space
	if testTupleSpace.Size() != 0 {
		t.Errorf("The size of %q was %d but was expected to have the size 0 as the tuple should have been removed from the tuple space", testTupleSpace.tuples, testTupleSpace.Size())
	}

	// Find a tuple that doesn't exists in the tuple space.
	t3 := testTupleSpace.findTuple(temp, true)

	// Check that the tuple is nil, meaning there was no tuple matching the
	// template.
	if t3 != nil {
		t.Errorf("TestTupleSpaceFindTuple(%q) should be nil", t3)
	}
}

// TestTupleSpacePutPWithOneGetWaitingClient will make sure that is there's a
// client performing a get who matches the tuple, the tuple is sent to it and
// isn't added to the tuple space.
func TestTupleSpacePutPWithOneGetWaitingClient(t *testing.T) {
	// Initially check the tuple space is empty by securing the size of it is
	// 0.
	if testTupleSpace.Size() != 0 {
		t.Errorf("The size of %q was %d but was expected to have the size 0.", testTupleSpace.tuples, testTupleSpace.Size())
	}

	// Initially check there are no waiting clients by securing the size of it
	// is 0.
	if len(testTupleSpace.waitingClients) != 0 {
		t.Errorf("The size of %+v was %d but was expected to have the size 0.", testTupleSpace.waitingClients, len(testTupleSpace.waitingClients))
	}

	temp := CreateTemplate("test field")
	tupleChan := make(chan *Tuple)
	remove := true
	client := CreateWaitingClient(temp, tupleChan, remove)
	tupleResponse := new(Tuple)
	testTupleSpace.addNewClient(client)
	go func() {
		tupleResponse = <-tupleChan
	}()

	// Add a matching tuple to the tuple space.
	tuple := CreateTuple("test field")
	testTupleSpace.putP(&tuple)

	// Check that the size of the tuples is 0.
	if testTupleSpace.Size() != 0 {
		t.Errorf("The size of %q was %d but was expected to have the size 0 as the waiting client was performing a get operation.", testTupleSpace.tuples, testTupleSpace.Size(), tuple)
	}

	if len(testTupleSpace.waitingClients) != 0 {
		t.Errorf("The size of %+v was %d but was expected to have the size 0", testTupleSpace.waitingClients, len(testTupleSpace.waitingClients))
	}

	if !reflect.DeepEqual(tuple, *tupleResponse) {
		t.Errorf("The tuples were not equal, they tuple place by putP looks like %+v and the found tuple looks like %+v", tuple, tupleResponse)
	}
}

// TestTupleSpacePutPWithOneQueryWaitingClient will make sure that is there's a
// client performing a query who matches the tuple, the tuple is sent to it and
// isn't added to the tuple space.
func TestTupleSpacePutPWithOneQueryWaitingClient(t *testing.T) {
	// Initially check the tuple space is empty by securing the size of it is
	// 0.
	if testTupleSpace.Size() != 0 {
		t.Errorf("The size of %q was %d but was expected to have the size 0.", testTupleSpace.tuples, testTupleSpace.Size())
	}

	// Initially check there are no waiting clients by securing the size of it
	// is 0.
	if len(testTupleSpace.waitingClients) != 0 {
		t.Errorf("The size of %+v was %d but was expected to have the size 0.", testTupleSpace.waitingClients, len(testTupleSpace.waitingClients))
	}

	temp := CreateTemplate("test field")
	tupleChan := make(chan *Tuple)
	remove := false
	client := CreateWaitingClient(temp, tupleChan, remove)
	tupleResponse := new(Tuple)
	testTupleSpace.addNewClient(client)
	go func() {
		tupleResponse = <-tupleChan
	}()

	// Add a matching tuple to the tuple space.
	tuple := CreateTuple("test field")
	testTupleSpace.putP(&tuple)

	// Check that the size of the tuples is 1.
	if testTupleSpace.Size() != 1 {
		t.Errorf("The size of %q was %d but was expected to have the size 1 as the waiting client was performing a get operation.", testTupleSpace.tuples, testTupleSpace.Size())
	}

	if len(testTupleSpace.waitingClients) != 0 {
		t.Errorf("The size of %+v was %d but was expected to have the size 0", testTupleSpace.waitingClients, len(testTupleSpace.waitingClients))
	}

	if !reflect.DeepEqual(tuple, *tupleResponse) {
		t.Errorf("The tuples were not equal, they tuple place by putP looks like %+v and the found tuple looks like %+v", tuple, tupleResponse)
	}
}

// TestTupleSpacePutPWithOneQueryWaitingClient will make sure that is there's a
// client performing a query who matches the tuple followed by a client
// performing a get who matches the tuple. The tuple is sent to both client due
// to their order and it isn't added to the tuple space.
func TestTupleSpacePutPWithOneQueryOneGetWaitingClient(t *testing.T) {
	// Make sure tuple space is empty.
	testTupleSpace.clearTupleSpace()

	// Initially check there are no waiting clients by securing the size of it
	// is 0.
	if len(testTupleSpace.waitingClients) != 0 {
		t.Errorf("The size of %+v was %d but was expected to have the size 0.", testTupleSpace.waitingClients, len(testTupleSpace.waitingClients))
	}

	temp := CreateTemplate("test field")
	tupleChanQ := make(chan *Tuple)
	tupleChanG := make(chan *Tuple)
	bQuery := false
	bGet := true
	cQuery := CreateWaitingClient(temp, tupleChanQ, bQuery)
	testTupleSpace.addNewClient(cQuery)
	cGet := CreateWaitingClient(temp, tupleChanG, bGet)
	testTupleSpace.addNewClient(cGet)
	tupleResponseQ := new(Tuple)
	tupleResponseG := new(Tuple)

	go func() {
		tupleResponseQ = <-tupleChanQ
	}()
	go func() {
		tupleResponseG = <-tupleChanG
	}()

	// Add a matching tuple to the tuple space.
	tuple := CreateTuple("test field")
	testTupleSpace.putP(&tuple)

	time.Sleep(1 * time.Second)

	// Check that the size of the tuples is 1.
	if testTupleSpace.Size() != 0 {
		t.Errorf("The size of %q was %d but was expected to have the size 0 as the waiting clients were performing a query followed by a get operation.", testTupleSpace.tuples, testTupleSpace.Size())
	}

	if len(testTupleSpace.waitingClients) != 0 {
		t.Errorf("The size of %+v was %d but was expected to have the size 0", testTupleSpace.waitingClients, len(testTupleSpace.waitingClients))
	}

	// Check that the Query found the correct tuple.
	if !reflect.DeepEqual(tuple, *tupleResponseQ) {
		t.Errorf("The tuples were not equal, they tuple place by putP looks like %+v and the found tuple by Query looks like %+v", tuple, tupleResponseQ)
	}

	// Check that the Get found the correct tuple.
	if !reflect.DeepEqual(tuple, *tupleResponseG) {
		t.Errorf("The tuples were not equal, they tuple place by putP looks like %+v and the found tuple by Get looks like %+v", tuple, tupleResponseG)
	}
}

// TestTupleSpaceFindTupleBlocking will make sure that if a tuple matching the
// template doesn't exsist in the tuple space it will add the client to
// waitingClients.
/*
func TestTupleSpaceFindTupleBlocking(t *testing.T) {
	// Make sure the tuple space is empty.
	testTupleSpace.muTuples.Lock()
	testTupleSpace.clearTupleSpace()
	testTupleSpace.muTuples.Unlock()

	if len(testTupleSpace.waitingClients) != 0 {
		t.Errorf("The size of %+v was %d but was expected to have the size 0.", testTupleSpace.waitingClients, len(testTupleSpace.waitingClients))
	}

	// Create a template that matches the tuple just added to the tuple space.
	temp := CreateTemplate("Field 1")

	// Create a channel to receive the response
	response := make(chan<- *Tuple)

	testTupleSpace.findTupleBlocking(temp, response, true)

	if len(testTupleSpace.waitingClients) != 1 {
		t.Errorf("The size of %+v was %d but was expected to have the size 1.", testTupleSpace.waitingClients, len(testTupleSpace.waitingClients))
	}

	tuple := CreateTuple("Field 1")
	go testTupleSpace.putP(&tuple)

	if len(testTupleSpace.waitingClients) != 0 {
		t.Errorf("The size of %+v was %d but was expected to have the size 0.", testTupleSpace.waitingClients, len(testTupleSpace.waitingClients))
	}
}*/

// TestTupleSpaceQueryAndGet will make sure that query() and get() returns the
// correct tuple.
func TestTupleSpaceQueryAndGet(t *testing.T) {
	// Make sure the tuple space is empty.
	testTupleSpace.clearTupleSpace()

	// Add a tuple to the tuple space.
	testTupleSpace.putP(&testTupleTwoFields)

	// Create a template that matches the tuple just added to the tuple space.
	temp := CreateTemplate("Field 1", true)

	// Create a channel to receive the response
	response := make(chan *Tuple)

	// Find a tuple matching the template with the query method.
	go testTupleSpace.query(temp, response)

	// Read the tuple found.
	tQuery := <-response

	// Check that it's equal to the tuple added.
	if !reflect.DeepEqual(*tQuery, testTupleTwoFields) {
		t.Errorf("The query found %q but should have found %q", tQuery, testTupleTwoFields)
	}

	// Find a tupe matching the template with the get method.
	go testTupleSpace.get(temp, response)

	// Read the tuple found.
	tGet := <-response

	// Check that it's equal to the tuple added.
	if !reflect.DeepEqual(*tGet, testTupleTwoFields) {
		t.Errorf("The get found %q but should have found %q", tGet, testTupleTwoFields)
	}
}

// TestTupleSpaceFindTupleNonlocking will make sure the method isn't blocking
// if there isn't a tuple matching a template in the tuple space.
func TestTupleSpaceFindTupleNonlocking(t *testing.T) {
	// Make sure the tuple space is empty.
	testTupleSpace.clearTupleSpace()

	// Create a template that matches the tuple just added to the tuple space.
	temp := CreateTemplate("Field 1", true)

	// Create a channel to receive the response
	response := make(chan *Tuple)

	// Run the findTupleNonblocking, with no tuples in the tuple space.
	go testTupleSpace.findTupleNonblocking(temp, response, true)

	// Read the tuple found.
	tNonblockingNil := <-response

	// Check the tuple found is nil as no tuple were in the tuple space.
	if tNonblockingNil != nil {
		t.Errorf("tNonblockingNil should have been nil but was %q instead", tNonblockingNil)
	}

	// Add a tuple to the tuple space.
	testTupleSpace.putP(&testTupleTwoFields)

	// Run the findTupleNonblocking, with a macthing tuple in the tuple space.
	go testTupleSpace.findTupleNonblocking(temp, response, true)

	// Read the tuple found.
	tNonblocking := <-response

	// Check that the found tuple is equal to the tuple added to the tuple
	// space.
	if !reflect.DeepEqual(*tNonblocking, testTupleTwoFields) {
		t.Errorf("The findTupleNonblocking found %q but should have found %q", tNonblocking, testTupleTwoFields)
	}
}

// TestTupleSpaceQueryPAndGetP will make sure that queryP() and getP() returns
// the correct tuple.
func TestTupleSpaceQueryPAndGetP(t *testing.T) {
	// Make sure the tuple space is empty.
	testTupleSpace.clearTupleSpace()

	// Add a tuple to the tuple space.
	testTupleSpace.putP(&testTupleTwoFields)

	// Create a template that matches the tuple just added to the tuple space.
	temp := CreateTemplate("Field 1", true)

	// Create a channel to receive the response
	response := make(chan *Tuple)

	// Find a tuple matching the template with the query method.
	go testTupleSpace.queryP(temp, response)

	// Read the tuple found.
	tQueryP := <-response

	// Check that it's equal to the tuple added.
	if !reflect.DeepEqual(*tQueryP, testTupleTwoFields) {
		t.Errorf("The query found %q but should have found %q", tQueryP, testTupleTwoFields)
	}

	// Find a tupe matching the template with the get method.
	go testTupleSpace.getP(temp, response)

	// Read the tuple found.
	tGetP := <-response

	// Check that it's equal to the tuple added.
	if !reflect.DeepEqual(*tGetP, testTupleTwoFields) {
		t.Errorf("The get found %q but should have found %q", tGetP, testTupleTwoFields)
	}
}

// TestTupleSpaceFindAllTuples will make sure all tuples from the tuple space
// are returned.
func TestTupleSpaceFindAllTuples(t *testing.T) {
	// Make sure the tuple space is empty.
	testTupleSpace.clearTupleSpace()

	// Add a tuple twice to the tuple space.
	testTupleSpace.putP(&testTupleTwoFields)
	testTupleSpace.putP(&testTupleTwoFields)

	// Make local list of tuples for comparison.
	tuplesLocal := []Tuple{testTupleTwoFields, testTupleTwoFields}

	// Create a channel to receive the response
	response := make(chan []Tuple)

	// Run the findAllTuples, without removing them.
	go testTupleSpace.findAllTuples(response, false)

	// Read the tuples.
	tuples := <-response

	// Check the list of tuples found is equal to the local list of tuples.
	if !reflect.DeepEqual(tuplesLocal, tuples) {
		t.Errorf("findAllTuples returned %q but was expected to return %q.", tuples, tuplesLocal)
	}

	// Run the findAllTuples and remove them.
	go testTupleSpace.findAllTuples(response, true)

	// Read the tuples.
	tuples = <-response

	// Check the list of tuples found is equal to the local list of tuples.
	if !reflect.DeepEqual(tuplesLocal, tuples) {
		t.Errorf("findAllTuples returned %q but was expected to return %q.", tuples, tuplesLocal)
	}
}

// TestTupleSpaceQueryAllAndGetAll will make sure that queryAll() returns every
// tuple without removing them and that getAll() returns every tuple along with
// removing them from the tuple space.
func TestTupleSpaceQueryAllAndGetAll(t *testing.T) {
	// Make sure the tuple space is empty.
	testTupleSpace.clearTupleSpace()

	// Add a tuple twice to the tuple space.
	testTupleSpace.putP(&testTupleTwoFields)
	testTupleSpace.putP(&testTupleTwoFields)

	// Make local list of tuples for comparison.
	tuplesLocal := []Tuple{testTupleTwoFields, testTupleTwoFields}

	// Create a channel to receive the response
	response := make(chan []Tuple)

	// Find a tuple matching the template with the query method.
	go testTupleSpace.queryAll(response)

	// Read the tuples.
	tuplesQuery := <-response

	// Check the list of tuples found is equal to the local list of tuples.
	if !reflect.DeepEqual(tuplesLocal, tuplesQuery) {
		t.Errorf("findAllTuples returned %q but was expected to return %q.", tuplesQuery, tuplesLocal)
	}

	// Find a tupe matching the template with the get method.
	go testTupleSpace.getAll(response)

	// Read the tuple found.
	tuplesGet := <-response

	// Check the list of tuples found is equal to the local list of tuples.
	if !reflect.DeepEqual(tuplesLocal, tuplesGet) {
		t.Errorf("findAllTuples returned %q but was expected to return %q.", tuplesGet, tuplesLocal)
	}
}
<commit_msg>Delete tupleSpace_test.go<commit_after><|endoftext|>


<commit_before>package repo

type SettingsData struct {
	PaymentDataInQR    *bool              `json:"paymentDataInQR"`
	ShowNotifications  *bool              `json:"showNotificatons"`
	ShowNsfw           *bool              `json:"showNsfw"`
	ShippingAddresses  *[]ShippingAddress `json:"shippingAddresses"`
	LocalCurrency      *string            `json:"localCurrency"`
	Country            *string            `json:"country"`
	Language           *string            `json:"language"`
	TermsAndConditions *string            `json:"termsAndConditions"`
	RefundPolicy       *string            `json:"refundPolicy"`
	BlockedNodes       *[]string          `json:"blockedNodes"`
	StoreModerators    *[]string          `json:"storeModerators"`
	SMTPSettings       *SMTPSettings      `json:"smtpSettings"`
}

type ShippingAddress struct {
	Name           string
	Company        string
	AddressLineOne string
	AddressLineTwo string
	City           string
	State          string
	Country        string
	PostalCode     string
	AddressNotes   string
}

type SMTPSettings struct {
	Notifications  bool
	ServerAddress  string
	Username       string
	Password       string
	SenderEmail    string
	RecipientEmail string
}
<commit_msg>capitalized nested settings attributes<commit_after>package repo

type SettingsData struct {
	PaymentDataInQR    *bool              `json:"paymentDataInQR"`
	ShowNotifications  *bool              `json:"showNotificatons"`
	ShowNsfw           *bool              `json:"showNsfw"`
	ShippingAddresses  *[]ShippingAddress `json:"shippingAddresses"`
	LocalCurrency      *string            `json:"localCurrency"`
	Country            *string            `json:"country"`
	Language           *string            `json:"language"`
	TermsAndConditions *string            `json:"termsAndConditions"`
	RefundPolicy       *string            `json:"refundPolicy"`
	BlockedNodes       *[]string          `json:"blockedNodes"`
	StoreModerators    *[]string          `json:"storeModerators"`
	SMTPSettings       *SMTPSettings      `json:"smtpSettings"`
}

type ShippingAddress struct {
	Name           string                 `json:"name"`
	Company        string                 `json:"company"`
	AddressLineOne string                 `json:"addressLineOne"`
	AddressLineTwo string                 `json:"addressLineTwo"`
	City           string                 `json:"city"`
	State          string                 `json:"state"`
	Country        string                 `json:"country"`
	PostalCode     string                 `json:"postalCode"`
	AddressNotes   string                 `json:"addressNotes"`
}

type SMTPSettings struct {
	Notifications  bool                   `json:"notifications"`
	ServerAddress  string                 `json:"serverAddress"`
	Username       string                 `json:"username"`
	Password       string                 `json:"password"`
	SenderEmail    string                 `json:"senderEmail"`
	RecipientEmail string                 `json:"recipientEmail"`
}
<|endoftext|>


<commit_before>package awsprice

// ParseInput takes a pricer and the input string and returns
// a string representation of the price
func ParseInput(pricedb PriceDB, input string) (string, error) {

	attr := make(map[string]string)
	offer, err := pricedb.Get(input, attr)
	if err != nil {
		prices := pricedb.Search(input, attr)
		if len(prices) == 0 {
			return "", err
		}
		if len(prices) == 1 {
			return prices[0].String(), nil
		}
		return PriceTable(prices), nil

	}
	return offer.String(), nil
}
<commit_msg>switched to work with the interface not implementation<commit_after>package awsprice

// ParseInput takes a pricer and the input string and returns
// a string representation of the price
func ParseInput(pricer Pricer, input string) (string, error) {

	attr := make(map[string]string)
	offer, err := pricer.Get(input, attr)
	if err != nil {
		prices := pricer.Search(input, attr)
		if len(prices) == 0 {
			return "", err
		}
		if len(prices) == 1 {
			return prices[0].String(), nil
		}
		return PriceTable(prices), nil

	}
	return offer.String(), nil
}
<|endoftext|>