<commit_before>// TODO: For structs that define a ResourceURI, add a method to fetch those
//       contents and parse them into the correct response struct.
//       e.g., Series(123).Data.Results[0].Characters.Items[0].Get()...
// TODO: Add a test to fetch a resource, serialize it into JSON and compare
//       it against the response JSON to catch missing fields
// TODO: Figure out the correct incantation to let Series not have to take an
//       empty struct and instead take nil
// TODO: Find/write Swagger Go client generator?

package marvel

import (
	"crypto/md5"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"time"

	"github.com/google/go-querystring/query"
)

type Client struct {
	public, private string
}

func NewClient(public, private string) Client {
	return Client{public, private}
}

// See http://developer.marvel.com/documentation/authorization
func (c Client) hash() (int64, string) {
	ts := time.Now().Unix()
	hash := md5.New()
	io.WriteString(hash, fmt.Sprintf("%d%s%s", ts, c.private, c.public))
	return ts, fmt.Sprintf("%x", hash.Sum(nil))
}

func (c Client) baseURL(path string, params interface{}) url.URL {
	u := url.URL{
		Scheme: "https",
		Host:   "gateway.marvel.com",
		Path:   "/v1/public/" + path,
	}
	if params != nil {
		q, _ := query.Values(params)
		u.RawQuery += "&" + q.Encode()
	}
	return u
}

// Fields common to all response entities
type commonResponse struct {
	Code            int
	ETag            string
	Status          string
	Copyright       string
	AttributionText string
	AttributionHTML string
}

type CommonParams struct {
	Offset int `url:"offset,omitempty"`
	Limit  int `url:"limit,omitempty"`
}

// Fields common to data that lists entities, with pagination
type commonList struct {
	Offset int
	Limit  int
	Total  int
	Count  int
}

type Image struct {
	Path      string
	Extension string
}

type Variant string

var (
	PortraitSmall       = Variant("portrait_small")
	PortraitMedium      = Variant("portrait_medium")
	PortraitXLarge      = Variant("portrait_xlarge")
	PortraitFantastic   = Variant("portrait_fantastic")
	PortraitUncanny     = Variant("portrait_uncanny")
	PortraitIncredible  = Variant("portrait_incredible")
	StandardSmall       = Variant("standard_small")
	StandardMedium      = Variant("standard_medium")
	StandardXLarge      = Variant("standard_xlarge")
	StandardFantastic   = Variant("standard_fantastic")
	StandardUncanny     = Variant("standard_uncanny")
	StandardIncredible  = Variant("standard_incredible")
	LandscapeSmall      = Variant("landscape_small")
	LandscapeMedium     = Variant("landscape_medium")
	LandscapeXLarge     = Variant("landscape_xlarge")
	LandscapeFantastic  = Variant("landscape_fantastic")
	LandscapeUncanny    = Variant("landscape_uncanny")
	LandscapeIncredible = Variant("landscape_incredible")
)

func (i Image) URL(v Variant) string {
	return fmt.Sprintf("%s/%s.%s", i.Path, string(v), i.Extension)
}

type Date string

const dateLayout = "2006-01-02T15:04:05-0700"

func (d Date) Parse() time.Time {
	t, err := time.Parse(dateLayout, string(d))
	if err != nil {
		panic(err)
	}
	return t
}

func (c Client) Series(id int) Series {
	return Series{id, c}
}

type Series struct {
	seriesID int
	client Client
}

func (s Series) Comics(params CommonParams) (resp struct{
	commonResponse
	Data struct {
		commonList
		Results []Comic
	}
}, err error) {
	u := s.client.baseURL(fmt.Sprintf("series/%d/comics", id), params)
	r, err := c.fetch(u)
	if err != nil {
		return
	}
	defer r.Close()
	err = json.NewDecoder(r).Decode(&resp)
	return
}

func (c Client) fetch(u url.URL) (io.ReadCloser, error) {
	if u.RawQuery != "" {
		u.RawQuery += "&"
	}
	ts, hash := c.hash()
	u.RawQuery += url.Values(map[string][]string{
		"ts":     []string{fmt.Sprintf("%d", ts)},
		"apikey": []string{c.public},
		"hash":   []string{hash},
	}).Encode()

	resp, err := http.Get(u.String())
	if err != nil {
		return nil, err
	}
	if resp.StatusCode >= http.StatusBadRequest {
		slurp, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return nil, err
		}
		return nil, fmt.Errorf("error response from API: %d\n%s", resp.StatusCode, slurp)
	}
	return resp.Body, nil
}

type resourceList struct {
	Available     int
	Returned      int
	CollectionURI string
}

type Character struct {
	ResourceURI string
	ID          *int         `json:"id,omitempty"`
	Name        *string      `json:"name,omitempty"`
	Description *string      `json:"description,omitempty"`
	Modified    *Date        `json:"modified,omitempty"`
	URLs        []URL        `json:"urls,omitempty"`
	Thumbnail   *Image       `json:"thumbnail,omitempty"`
	Comics      *ComicsList  `json:"comics,omitempty"`
	Stories     *StoriesList `json:"stories,omitempty"`
	Events      *EventsList  `json:"events,omitempty"`
	Series      *SeriesList  `json:"series,omitempty"`
}

type CharactersList struct {
	resourceList
	Items []Character
}

type Comic struct {
	ResourceURI        string
	ID                 *int            `json:"id,omitempty"`
	Name               *string         `json:"id,omitempty"`
	DigitalID          *int            `json:"digitalId,omitempty"`
	Title              *string         `json:"title,omitempty"`
	IssueNumber        *float64        `json:"issueNumber,omitempty"`
	VariantDescription *string         `json:"variantDescription,omitEmpty"`
	Description        *string         `json:"description,omitempty"`
	Modified           *Date           `json:"modified,omitempty"`
	ISBN               *string         `json:"isbn,omitempty"`
	UPC                *string         `json:"upc,omitempty"`
	DiamondCode        *string         `json:"diamondCode,omitempty"`
	EAN                *string         `json:"ean,omitempty"`
	ISSN               *string         `json:"issn,omitempty"`
	Format             *string         `json:"format,omitempty"`
	PageCount          *int            `json:"pageCount,omitEmpty"`
	TextObjects        []TextObject    `json:"textObjects,omitempty"`
	URLs               []URL           `json:"urls,omitempty"`
	Series             *Series         `json:"series,omitempty"`
	Variants           []Comic         `json:"variants,omitempty"`
	Collections        []Comic         `json:"collections,omitempty"`
	CollectedIssues    []Comic         `json:"collectedIssues,omitempty"`
	Dates              []ComicDate     `json:"dates,omitempty"`
	Prices             []ComicPrice    `json:"prices,omitempty"`
	Thumbnail          *Image          `json:"thumbnail,omitempty"`
	Images             []Image         `json:"images,omitempty"`
	Creators           *CreatorsList   `json:"creators,omitempty"`
	Characters         *CharactersList `json:"characters,omitempty"`
	Stories            *StoriesList    `json:"stories,omitempty"`
	Events             *EventsList     `json:"events,omitempty"`
}

type TextObject struct {
	Type     string
	Language string
	Text     string
}

type ComicDate struct {
	Type string
	Date Date
}

type ComicPrice struct {
	Type  string
	Price float64
}

type ComicsList struct {
	resourceList
	Items []Comic
}

type Story struct {
	ResourceURI   string
	ID            *int            `json:"id,omitempty"`
	Name          *string         `json:"name,omitempty"`
	Title         *string         `json:"title,omitempty"`
	Description   *string         `json:"description,omitempty"`
	Type          *string         `json:"type,omitempty"`
	Modified      *Date           `json:"date,omitempty"`
	Thumbnail     *Image          `json:"image,omitempty"`
	Comics        *ComicsList     `json:"comics,omitempty"`
	Series        *SeriesList     `json:"series,omitempty"`
	Events        *EventsList     `json:"events,omitempty"`
	Characters    *CharactersList `json:"characters,omitempty"`
	Creators      *CreatorsList   `json:"creators,omitempty"`
	OriginalIssue Comic
}

type StoriesList struct {
	resourceList
	Items []Story
}

type Event struct {
	ResourceURI string
	ID          *int            `json:"id,omitempty"`
	Title       *string         `json:"title,omitempty"`
	Description *string         `json:"description,omitempty"`
	URLs        []URL           `json:"urls,omitempty"`
	Modified    *Date           `json:"modified,omitempty"`
	Start       *Date           `json:"start,omitempty"`
	End         *Date           `json:"end,omitempty"`
	Thumbnail   *Image          `json:"thumbnail,omitempty"`
	Comics      *ComicsList     `json:"comics,omitempty"`
	Stories     *StoriesList    `json:"stories,omitempty"`
	Series      *SeriesList     `json:"series,omitempty"`
	Characters  *CharactersList `json:"characters,omitempty"`
	Creators    *CreatorsList   `json:"creators,omitempty"`
	Next        *Event          `json:"next,omitempty"`
	Previous    *Event          `json:"next,omitempty"`
}

type EventsList struct {
	resourceList
	Items []Event
}

type Series struct {
	ResourceURI string
	ID          *int            `json:"id,omitempty"`
	Name        *string         `json:"name,omitempty"`
	Title       *string         `json:"title,omitempty"`
	Description *string         `json:"description,omitempty"`
	URLs        []URL           `json:"urls,omitempty"`
	StartYear   *int            `json:"startYear,omitempty"`
	EndYear     *int            `json:"endYear,omitempty"`
	Rating      *string         `json:"rating,omitempty"`
	Modified    *Date           `json:"modified,omitempty"`
	Thumbnail   *Image          `json:"thumbnail,omitempty"`
	Comics      *ComicsList     `json:"comics,omitempty"`
	Stories     *StoriesList    `json:"stories,omitempty"`
	Events      *EventsList     `json:"events,omitempty"`
	Characters  *CharactersList `json:"characters,omitempty"`
	Creators    *CreatorsList   `json:"creators,omitempty"`
	Next        *Series         `json:"next,omitempty"`
	Previous    *Series         `json:"next,omitempty"`
}

type SeriesList struct {
	resourceList
	Items []Series
}

type Creator struct {
	ResourceURI string
	ID          *int         `json:"id,omitempty"`
	Name        *string      `json:"name,omitempty"`
	FirstName   *string      `json:"firstName,omitempty"`
	MiddleName  *string      `json:"middleName,omitempty"`
	LastName    *string      `json:"lastName,omitempty"`
	Suffix      *string      `json:"suffix,omitempty"`
	FullName    *string      `json:"fullName,omitempty"`
	Modified    *Date        `json:"modified,omitempty"`
	URLs        []URL        `json:"urls,omitempty"`
	Thumbnail   *Image       `json:"thumbnail,omitempty"`
	Series      *SeriesList  `json:"series,omitempty"`
	Stories     *StoriesList `json:"stories,omitempty"`
	Comics      *ComicsList  `json:"comics,omitempty"`
	Events      *EventsList  `json:"events,omitempty"`
}

type CreatorsList struct {
	resourceList
	Items []Creator
}

// TODO: Replace with subtypes that know what their response will be, with a Fetch() method to pull down and deserialize correctly.
type URL struct {
	Type, URL string
}
<commit_msg>blergh<commit_after>// TODO: For structs that define a ResourceURI, add a method to fetch those
//       contents and parse them into the correct response struct.
//       e.g., Series(123).Data.Results[0].Characters.Items[0].Get()...
// TODO: Add a test to fetch a resource, serialize it into JSON and compare
//       it against the response JSON to catch missing fields
// TODO: Figure out the correct incantation to let Series not have to take an
//       empty struct and instead take nil
// TODO: Find/write Swagger Go client generator?

package marvel

import (
	"crypto/md5"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"time"

	"github.com/google/go-querystring/query"
)

type Client struct {
	public, private string
}

func NewClient(public, private string) Client {
	return Client{public, private}
}

// See http://developer.marvel.com/documentation/authorization
func (c Client) hash() (int64, string) {
	ts := time.Now().Unix()
	hash := md5.New()
	io.WriteString(hash, fmt.Sprintf("%d%s%s", ts, c.private, c.public))
	return ts, fmt.Sprintf("%x", hash.Sum(nil))
}

func (c Client) baseURL(path string, params interface{}) url.URL {
	u := url.URL{
		Scheme: "https",
		Host:   "gateway.marvel.com",
		Path:   "/v1/public/" + path,
	}
	if params != nil {
		q, _ := query.Values(params)
		u.RawQuery += "&" + q.Encode()
	}
	return u
}

// Fields common to all response entities
type commonResponse struct {
	Code            int
	ETag            string
	Status          string
	Copyright       string
	AttributionText string
	AttributionHTML string
}

type CommonParams struct {
	Offset int `url:"offset,omitempty"`
	Limit  int `url:"limit,omitempty"`
}

// Fields common to data that lists entities, with pagination
type commonList struct {
	Offset int
	Limit  int
	Total  int
	Count  int
}

type Image struct {
	Path      string
	Extension string
}

type Variant string

var (
	PortraitSmall       = Variant("portrait_small")
	PortraitMedium      = Variant("portrait_medium")
	PortraitXLarge      = Variant("portrait_xlarge")
	PortraitFantastic   = Variant("portrait_fantastic")
	PortraitUncanny     = Variant("portrait_uncanny")
	PortraitIncredible  = Variant("portrait_incredible")
	StandardSmall       = Variant("standard_small")
	StandardMedium      = Variant("standard_medium")
	StandardXLarge      = Variant("standard_xlarge")
	StandardFantastic   = Variant("standard_fantastic")
	StandardUncanny     = Variant("standard_uncanny")
	StandardIncredible  = Variant("standard_incredible")
	LandscapeSmall      = Variant("landscape_small")
	LandscapeMedium     = Variant("landscape_medium")
	LandscapeXLarge     = Variant("landscape_xlarge")
	LandscapeFantastic  = Variant("landscape_fantastic")
	LandscapeUncanny    = Variant("landscape_uncanny")
	LandscapeIncredible = Variant("landscape_incredible")
)

func (i Image) URL(v Variant) string {
	return fmt.Sprintf("%s/%s.%s", i.Path, string(v), i.Extension)
}

type Date string

const dateLayout = "2006-01-02T15:04:05-0700"

func (d Date) Parse() time.Time {
	t, err := time.Parse(dateLayout, string(d))
	if err != nil {
		panic(err)
	}
	return t
}

func (c Client) Series(id int) SeriesRequest {
	return SeriesRequest{seriesID: id, client: c}
}

type SeriesRequest struct {
	seriesID int
	client Client
}

func (s SeriesRequest) Comics(params CommonParams) (resp struct{
	commonResponse
	Data struct {
		commonList
		Results []Comic
	}
}, err error) {
	u := s.client.baseURL(fmt.Sprintf("series/%d/comics", s.seriesID), params)
	r, err := s.client.fetch(u)
	if err != nil {
		return
	}
	defer r.Close()
	err = json.NewDecoder(r).Decode(&resp)
	return
}

func (c Client) fetch(u url.URL) (io.ReadCloser, error) {
	if u.RawQuery != "" {
		u.RawQuery += "&"
	}
	ts, hash := c.hash()
	u.RawQuery += url.Values(map[string][]string{
		"ts":     []string{fmt.Sprintf("%d", ts)},
		"apikey": []string{c.public},
		"hash":   []string{hash},
	}).Encode()

	resp, err := http.Get(u.String())
	if err != nil {
		return nil, err
	}
	if resp.StatusCode >= http.StatusBadRequest {
		slurp, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return nil, err
		}
		return nil, fmt.Errorf("error response from API: %d\n%s", resp.StatusCode, slurp)
	}
	return resp.Body, nil
}

type resourceList struct {
	Available     int
	Returned      int
	CollectionURI string
}

type Character struct {
	ResourceURI string
	ID          *int         `json:"id,omitempty"`
	Name        *string      `json:"name,omitempty"`
	Description *string      `json:"description,omitempty"`
	Modified    *Date        `json:"modified,omitempty"`
	URLs        []URL        `json:"urls,omitempty"`
	Thumbnail   *Image       `json:"thumbnail,omitempty"`
	Comics      *ComicsList  `json:"comics,omitempty"`
	Stories     *StoriesList `json:"stories,omitempty"`
	Events      *EventsList  `json:"events,omitempty"`
	Series      *SeriesList  `json:"series,omitempty"`
}

type CharactersList struct {
	resourceList
	Items []Character
}

type Comic struct {
	ResourceURI        string
	ID                 *int            `json:"id,omitempty"`
	Name               *string         `json:"id,omitempty"`
	DigitalID          *int            `json:"digitalId,omitempty"`
	Title              *string         `json:"title,omitempty"`
	IssueNumber        *float64        `json:"issueNumber,omitempty"`
	VariantDescription *string         `json:"variantDescription,omitEmpty"`
	Description        *string         `json:"description,omitempty"`
	Modified           *Date           `json:"modified,omitempty"`
	ISBN               *string         `json:"isbn,omitempty"`
	UPC                *string         `json:"upc,omitempty"`
	DiamondCode        *string         `json:"diamondCode,omitempty"`
	EAN                *string         `json:"ean,omitempty"`
	ISSN               *string         `json:"issn,omitempty"`
	Format             *string         `json:"format,omitempty"`
	PageCount          *int            `json:"pageCount,omitEmpty"`
	TextObjects        []TextObject    `json:"textObjects,omitempty"`
	URLs               []URL           `json:"urls,omitempty"`
	Series             *Series         `json:"series,omitempty"`
	Variants           []Comic         `json:"variants,omitempty"`
	Collections        []Comic         `json:"collections,omitempty"`
	CollectedIssues    []Comic         `json:"collectedIssues,omitempty"`
	Dates              []ComicDate     `json:"dates,omitempty"`
	Prices             []ComicPrice    `json:"prices,omitempty"`
	Thumbnail          *Image          `json:"thumbnail,omitempty"`
	Images             []Image         `json:"images,omitempty"`
	Creators           *CreatorsList   `json:"creators,omitempty"`
	Characters         *CharactersList `json:"characters,omitempty"`
	Stories            *StoriesList    `json:"stories,omitempty"`
	Events             *EventsList     `json:"events,omitempty"`
}

type TextObject struct {
	Type     string
	Language string
	Text     string
}

type ComicDate struct {
	Type string
	Date Date
}

type ComicPrice struct {
	Type  string
	Price float64
}

type ComicsList struct {
	resourceList
	Items []Comic
}

type Story struct {
	ResourceURI   string
	ID            *int            `json:"id,omitempty"`
	Name          *string         `json:"name,omitempty"`
	Title         *string         `json:"title,omitempty"`
	Description   *string         `json:"description,omitempty"`
	Type          *string         `json:"type,omitempty"`
	Modified      *Date           `json:"date,omitempty"`
	Thumbnail     *Image          `json:"image,omitempty"`
	Comics        *ComicsList     `json:"comics,omitempty"`
	Series        *SeriesList     `json:"series,omitempty"`
	Events        *EventsList     `json:"events,omitempty"`
	Characters    *CharactersList `json:"characters,omitempty"`
	Creators      *CreatorsList   `json:"creators,omitempty"`
	OriginalIssue Comic
}

type StoriesList struct {
	resourceList
	Items []Story
}

type Event struct {
	ResourceURI string
	ID          *int            `json:"id,omitempty"`
	Title       *string         `json:"title,omitempty"`
	Description *string         `json:"description,omitempty"`
	URLs        []URL           `json:"urls,omitempty"`
	Modified    *Date           `json:"modified,omitempty"`
	Start       *Date           `json:"start,omitempty"`
	End         *Date           `json:"end,omitempty"`
	Thumbnail   *Image          `json:"thumbnail,omitempty"`
	Comics      *ComicsList     `json:"comics,omitempty"`
	Stories     *StoriesList    `json:"stories,omitempty"`
	Series      *SeriesList     `json:"series,omitempty"`
	Characters  *CharactersList `json:"characters,omitempty"`
	Creators    *CreatorsList   `json:"creators,omitempty"`
	Next        *Event          `json:"next,omitempty"`
	Previous    *Event          `json:"next,omitempty"`
}

type EventsList struct {
	resourceList
	Items []Event
}

type Series struct {
	ResourceURI string
	ID          *int            `json:"id,omitempty"`
	Name        *string         `json:"name,omitempty"`
	Title       *string         `json:"title,omitempty"`
	Description *string         `json:"description,omitempty"`
	URLs        []URL           `json:"urls,omitempty"`
	StartYear   *int            `json:"startYear,omitempty"`
	EndYear     *int            `json:"endYear,omitempty"`
	Rating      *string         `json:"rating,omitempty"`
	Modified    *Date           `json:"modified,omitempty"`
	Thumbnail   *Image          `json:"thumbnail,omitempty"`
	Comics      *ComicsList     `json:"comics,omitempty"`
	Stories     *StoriesList    `json:"stories,omitempty"`
	Events      *EventsList     `json:"events,omitempty"`
	Characters  *CharactersList `json:"characters,omitempty"`
	Creators    *CreatorsList   `json:"creators,omitempty"`
	Next        *Series         `json:"next,omitempty"`
	Previous    *Series         `json:"next,omitempty"`
}

type SeriesList struct {
	resourceList
	Items []Series
}

type Creator struct {
	ResourceURI string
	ID          *int         `json:"id,omitempty"`
	Name        *string      `json:"name,omitempty"`
	FirstName   *string      `json:"firstName,omitempty"`
	MiddleName  *string      `json:"middleName,omitempty"`
	LastName    *string      `json:"lastName,omitempty"`
	Suffix      *string      `json:"suffix,omitempty"`
	FullName    *string      `json:"fullName,omitempty"`
	Modified    *Date        `json:"modified,omitempty"`
	URLs        []URL        `json:"urls,omitempty"`
	Thumbnail   *Image       `json:"thumbnail,omitempty"`
	Series      *SeriesList  `json:"series,omitempty"`
	Stories     *StoriesList `json:"stories,omitempty"`
	Comics      *ComicsList  `json:"comics,omitempty"`
	Events      *EventsList  `json:"events,omitempty"`
}

type CreatorsList struct {
	resourceList
	Items []Creator
}

// TODO: Replace with subtypes that know what their response will be, with a Fetch() method to pull down and deserialize correctly.
type URL struct {
	Type, URL string
}
<|endoftext|>


<commit_before>// Package matrix provides functions for simple linear algebra
package matrix

import (
	"bytes"
	"fmt"
	"math"
	"math/rand"
	"strconv"
	"strings"
)

var (
	ErrIncompatibleSizes    = &MatrixError{"Incompatible sizes of matricies"}
	ErrInsertionOutOfBounds = &MatrixError{"The matrix you are trying to insert to hasn't got that row or column."}
	ErrOutOfBounds          = &MatrixError{"The element you are trying to access is out of bounds."}
)

// Describes error during calculations
type MatrixError struct {
	ErrorString string
}

// Return the Error's string
func (err *MatrixError) Error() string { return err.ErrorString }

// Matrix construct that holds all the information about a matrix
type Matrix struct {
	rows, cols int
	values     []float64
}

// A function that will apply an abitary transformation to an element in the matrix
type ApplyFunc func(index int, value float64) float64

// Creates a new Matrix and initializes all values to 0
func Zeros(rows, cols int) *Matrix {
	A := new(Matrix)

	A.rows = rows
	A.cols = cols
	A.values = make([]float64, rows*cols)

	return A
}

// Creates a new Matrix and initializes all values to 1
func Ones(rows, cols int) *Matrix {
	A := Zeros(rows, cols)
	A.AddNum(1)

	return A
}

// Creates a new identity matrix
func Eye(size int) *Matrix {
	A := Zeros(size, size)

	for i := 1; i <= size; i++ {
		A.Set(i, i, 1)
	}

	return A
}

// Constructs a new matrix with random values in range [0;1)
func Rand(rows, cols int) *Matrix {
	A := Zeros(rows, cols)

	for i := range A.values {
		A.values[i] = rand.Float64()
	}

	return A
}

// Constructs a new Matrix from a Matlab style representation
//
//	A := matrix.FromMatlab("[1 2 3; 4 5 6]")
func FromMatlab(str string) *Matrix {
	rows := strings.Split(str, ";")

	for i, row := range rows {
		rows[i] = strings.Replace(row, ",", " ", -1)
	}

	nRows := len(rows)
	nColumns := len(strings.Fields(rows[0]))

	A := Zeros(nRows, nColumns)

	for i, row := range rows {
		row = strings.Trim(row, "[] ")
		strNums := strings.Fields(row)

		for j, num := range strNums {
			n, _ := strconv.ParseFloat(num, 64)
			A.Set(i+1, j+1, n)
		}
	}

	return A
}

// Return a Matlab representation of the matrix
func (A *Matrix) ToMatlab() string {
	buffer := new(bytes.Buffer)
	buffer.WriteString("[")

	for i, v := range A.values {
		buffer.WriteString(fmt.Sprintf("%f ", v))

		if (i+1)%A.cols == 0 {
			buffer.WriteString("; ")
		}
	}

	buffer.WriteString("]")

	return buffer.String()
}

// Gives the dimensions of the matrix
func (A *Matrix) Dim() (int, int) {
	return A.rows, A.cols
}

// Return the number of rows in the matrix
func (A *Matrix) Rows() int {
	return A.rows
}

// Return the number of columns in the matrix
func (A *Matrix) Columns() int {
	return A.cols
}

// Returns an array of all the values
func (A *Matrix) Values() []float64 {
	tmp := make([]float64, len(A.values))
	copy(tmp, A.values)
	return tmp
}

// Returns a string representation of the matrix
func (A *Matrix) String() string {
	buffer := new(bytes.Buffer)

	for i, elem := range A.values {
		buffer.WriteString(fmt.Sprintf("%.3f ", elem))

		if (i+1)%A.cols == 0 {
			buffer.WriteString("\n")
		}
	}

	return buffer.String()
}

// Returns an exact copy of the matrix
func (A *Matrix) Copy() *Matrix {
	B := Zeros(A.rows, A.cols)
	copy(B.values, A.values)

	return B
}

// Insert the given rows into the matrix, returning a new matrix.
// Passing 0 as the second argument is like making the
// passed rows the first few, whereas passing Rows() is like appending
// the additional rows to the matrix.
//
// Warning: This is an unsafe method to use, it does no boundary
// checking what so ever. If you'd like a safe version
// use: SafeInsertRows
func (A *Matrix) InsertRows(rows *Matrix, afterRow int) *Matrix {
	B := Zeros(A.rows+rows.rows, A.cols)

	// copy rows before inserted rows
	copy(B.values[0:afterRow*B.cols], A.values[0:afterRow*B.cols])
	// insert new rows
	copy(B.values[afterRow*B.cols:afterRow*B.cols+rows.rows*B.cols], rows.values)
	// copy rows after inserted rows
	copy(B.values[afterRow*B.cols+rows.rows*B.cols:], A.values[afterRow*B.cols:])

	return B
}

// Remove a single row from the matrix.
// The indexing for the rows start with 1 and go upto A.Rows()
func (A *Matrix) RemoveRow(row int) *Matrix {
	B := Zeros(A.rows-1, A.cols)
	copy(B.values, append(append([]float64{}, A.values[:(row-1)*A.cols]...), A.values[(row-1)*A.cols+A.cols:]...))
	return B
}

// Insert the given columns into the matrix, returning a new matrix.
// Passing 0 as the second argument is like making the
// passed columns the first few (on the left), whereas passing Columns() is like appending
// the additional columns to the matrix (on the right).
//
// Warning: This is an unsafe method to use, it does no boundary
// checking what so ever. If you'd like a safe version
// use: SafeInsertColumns
func (A *Matrix) InsertColumns(cols *Matrix, afterCol int) *Matrix {
	B := Zeros(A.rows, A.cols+cols.cols)

	for i := 0; i < A.rows; i++ {
		copy(B.values[i*B.cols:i*B.cols+afterCol], A.values[i*A.cols:i*A.cols+afterCol])
		copy(B.values[i*B.cols+afterCol:i*B.cols+afterCol+cols.cols], cols.values[i*cols.cols:(i+1)*cols.cols])
		copy(B.values[i*B.cols+afterCol+cols.cols:(i+1)*B.cols], A.values[i*A.cols+afterCol:(i+1)*A.cols])
	}

	return B
}

// Give a function, apply its transformation to every element in the matrix.
//
//	A := matrix.Rand(4, 8)
//	A.Apply(func(index int, value float64) float64 {
//		return sigmoid(value)
//	})
func (A *Matrix) Apply(f ApplyFunc) *Matrix {
	for i, v := range A.values {
		A.values[i] = f(i, v)
	}

	return A
}

// Get the element at [row, col].
//
// Warning: This is an unsafe method to use, it does no boundary
// checking what so ever. If you'd like a safe version
// use: SafeGet
func (A *Matrix) Get(row, col int) float64 {
	return A.values[(row-1)*A.cols+col-1]
}

// Set the element at [row, col] to val.
//
// Warning: This is an unsafe method to use, it does no boundary
// checking what so ever. If you'd like a safe version
// use: SafeSet
func (A *Matrix) Set(row, col int, val float64) {

	A.values[(row-1)*A.cols+col-1] = val

}

// Transpose the matrix
func (A *Matrix) Transpose() *Matrix {
	B := Zeros(A.cols, A.rows)

	for i := 1; i <= A.rows; i++ {
		for j := 1; j <= A.cols; j++ {
			B.values[(j-1)*B.cols+i-1] = A.values[(i-1)*A.cols+j-1]
		}
	}

	return B
}

// Add B to the matrix A, produces new matrix
func (A *Matrix) Add(B *Matrix) (*Matrix, error) {
	if !sameSize(A, B) {
		return nil, ErrIncompatibleSizes
	}

	C := Zeros(A.rows, A.cols)

	for i, val := range A.values {
		C.values[i] = val + B.values[i]
	}

	return C, nil
}

// Subtract B from the matrix A, produces a new matrix
func (A *Matrix) Sub(B *Matrix) (*Matrix, error) {
	if !sameSize(A, B) {
		return nil, ErrIncompatibleSizes
	}

	C := Zeros(A.rows, A.cols)

	for i, val := range A.values {
		C.values[i] = val - B.values[i]
	}

	return C, nil
}

// Multiplies 2 matricies with each other.
// Returns a new matrix.
//
// Warning: This is an unsafe method to use, it does no boundary
// checking what so ever. If you'd like a safe version
// use: SafeMul
func (A *Matrix) Mul(B *Matrix) *Matrix {

	C := Zeros(A.rows, B.cols)

	for i := 0; i < C.rows; i++ {
		for j := 0; j < C.cols; j++ {
			sum := float64(0)

			for k := 0; k < A.cols; k++ {
				sum += A.values[i*A.cols+k] * B.values[k*B.cols+j]
			}

			C.values[i*C.cols+j] = sum
		}
	}

	return C
}

// Standard scalar product of 2 matricies.
// Returns a new matrix.
//
// Warning: This is an unsafe method to use, it does no boundary
// checking what so ever. If you'd like a safe version
// use: SafeDot
func (A *Matrix) Dot(B *Matrix) *Matrix {
	C := Zeros(A.rows, A.cols)

	for i, val := range A.values {
		C.values[i] = val * B.values[i]
	}

	return C
}

// Scale the matrix by the factor f
func (A *Matrix) Scale(f float64) *Matrix {
	B := Zeros(A.rows, A.cols)

	for i, val := range A.values {
		B.values[i] = val * f
	}

	return B
}

// Take every element of the matrix to the power of n
func (A *Matrix) Power(n float64) *Matrix {
	B := Zeros(A.rows, A.cols)

	for i, val := range A.values {
		B.values[i] = math.Pow(val, n)
	}

	return B
}

// Add n to all elements in the matrix (in-place)
func (A *Matrix) AddNum(n float64) *Matrix {
	for i := range A.values {
		A.values[i] += n
	}

	return A
}
<commit_msg>added template for removecols<commit_after>// Package matrix provides functions for simple linear algebra
package matrix

import (
	"bytes"
	"fmt"
	"math"
	"math/rand"
	"strconv"
	"strings"
)

var (
	ErrIncompatibleSizes    = &MatrixError{"Incompatible sizes of matricies"}
	ErrInsertionOutOfBounds = &MatrixError{"The matrix you are trying to insert to hasn't got that row or column."}
	ErrOutOfBounds          = &MatrixError{"The element you are trying to access is out of bounds."}
)

// Describes error during calculations
type MatrixError struct {
	ErrorString string
}

// Return the Error's string
func (err *MatrixError) Error() string { return err.ErrorString }

// Matrix construct that holds all the information about a matrix
type Matrix struct {
	rows, cols int
	values     []float64
}

// A function that will apply an abitary transformation to an element in the matrix
type ApplyFunc func(index int, value float64) float64

// Creates a new Matrix and initializes all values to 0
func Zeros(rows, cols int) *Matrix {
	A := new(Matrix)

	A.rows = rows
	A.cols = cols
	A.values = make([]float64, rows*cols)

	return A
}

// Creates a new Matrix and initializes all values to 1
func Ones(rows, cols int) *Matrix {
	A := Zeros(rows, cols)
	A.AddNum(1)

	return A
}

// Creates a new identity matrix
func Eye(size int) *Matrix {
	A := Zeros(size, size)

	for i := 1; i <= size; i++ {
		A.Set(i, i, 1)
	}

	return A
}

// Constructs a new matrix with random values in range [0;1)
func Rand(rows, cols int) *Matrix {
	A := Zeros(rows, cols)

	for i := range A.values {
		A.values[i] = rand.Float64()
	}

	return A
}

// Constructs a new Matrix from a Matlab style representation
//
//	A := matrix.FromMatlab("[1 2 3; 4 5 6]")
func FromMatlab(str string) *Matrix {
	rows := strings.Split(str, ";")

	for i, row := range rows {
		rows[i] = strings.Replace(row, ",", " ", -1)
	}

	nRows := len(rows)
	nColumns := len(strings.Fields(rows[0]))

	A := Zeros(nRows, nColumns)

	for i, row := range rows {
		row = strings.Trim(row, "[] ")
		strNums := strings.Fields(row)

		for j, num := range strNums {
			n, _ := strconv.ParseFloat(num, 64)
			A.Set(i+1, j+1, n)
		}
	}

	return A
}

// Return a Matlab representation of the matrix
func (A *Matrix) ToMatlab() string {
	buffer := new(bytes.Buffer)
	buffer.WriteString("[")

	for i, v := range A.values {
		buffer.WriteString(fmt.Sprintf("%f ", v))

		if (i+1)%A.cols == 0 {
			buffer.WriteString("; ")
		}
	}

	buffer.WriteString("]")

	return buffer.String()
}

// Gives the dimensions of the matrix
func (A *Matrix) Dim() (int, int) {
	return A.rows, A.cols
}

// Return the number of rows in the matrix
func (A *Matrix) Rows() int {
	return A.rows
}

// Return the number of columns in the matrix
func (A *Matrix) Columns() int {
	return A.cols
}

// Returns an array of all the values
func (A *Matrix) Values() []float64 {
	tmp := make([]float64, len(A.values))
	copy(tmp, A.values)
	return tmp
}

// Returns a string representation of the matrix
func (A *Matrix) String() string {
	buffer := new(bytes.Buffer)

	for i, elem := range A.values {
		buffer.WriteString(fmt.Sprintf("%.3f ", elem))

		if (i+1)%A.cols == 0 {
			buffer.WriteString("\n")
		}
	}

	return buffer.String()
}

// Returns an exact copy of the matrix
func (A *Matrix) Copy() *Matrix {
	B := Zeros(A.rows, A.cols)
	copy(B.values, A.values)

	return B
}

// Insert the given rows into the matrix, returning a new matrix.
// Passing 0 as the second argument is like making the
// passed rows the first few, whereas passing Rows() is like appending
// the additional rows to the matrix.
//
// Warning: This is an unsafe method to use, it does no boundary
// checking what so ever. If you'd like a safe version
// use: SafeInsertRows
func (A *Matrix) InsertRows(rows *Matrix, afterRow int) *Matrix {
	B := Zeros(A.rows+rows.rows, A.cols)

	// copy rows before inserted rows
	copy(B.values[0:afterRow*B.cols], A.values[0:afterRow*B.cols])
	// insert new rows
	copy(B.values[afterRow*B.cols:afterRow*B.cols+rows.rows*B.cols], rows.values)
	// copy rows after inserted rows
	copy(B.values[afterRow*B.cols+rows.rows*B.cols:], A.values[afterRow*B.cols:])

	return B
}

// Remove a single row from the matrix.
// The indexing for the rows start with 1 and go upto A.Rows()
func (A *Matrix) RemoveRow(row int) *Matrix {
	B := Zeros(A.rows-1, A.cols)
	copy(B.values, append(append([]float64{}, A.values[:(row-1)*A.cols]...), A.values[(row-1)*A.cols+A.cols:]...))
	return B
}

func (A *Matrix) RemoveColumn(col int) *Matrix {
	B := Zeros(A.rows, A.cols-1)
	for i := 1; i <= B.rows; i++ {

	}

	return B
}

// Insert the given columns into the matrix, returning a new matrix.
// Passing 0 as the second argument is like making the
// passed columns the first few (on the left), whereas passing Columns() is like appending
// the additional columns to the matrix (on the right).
//
// Warning: This is an unsafe method to use, it does no boundary
// checking what so ever. If you'd like a safe version
// use: SafeInsertColumns
func (A *Matrix) InsertColumns(cols *Matrix, afterCol int) *Matrix {
	B := Zeros(A.rows, A.cols+cols.cols)

	for i := 0; i < A.rows; i++ {
		copy(B.values[i*B.cols:i*B.cols+afterCol], A.values[i*A.cols:i*A.cols+afterCol])
		copy(B.values[i*B.cols+afterCol:i*B.cols+afterCol+cols.cols], cols.values[i*cols.cols:(i+1)*cols.cols])
		copy(B.values[i*B.cols+afterCol+cols.cols:(i+1)*B.cols], A.values[i*A.cols+afterCol:(i+1)*A.cols])
	}

	return B
}

// Give a function, apply its transformation to every element in the matrix.
//
//	A := matrix.Rand(4, 8)
//	A.Apply(func(index int, value float64) float64 {
//		return sigmoid(value)
//	})
func (A *Matrix) Apply(f ApplyFunc) *Matrix {
	for i, v := range A.values {
		A.values[i] = f(i, v)
	}

	return A
}

// Get the element at [row, col].
//
// Warning: This is an unsafe method to use, it does no boundary
// checking what so ever. If you'd like a safe version
// use: SafeGet
func (A *Matrix) Get(row, col int) float64 {
	return A.values[(row-1)*A.cols+col-1]
}

// Set the element at [row, col] to val.
//
// Warning: This is an unsafe method to use, it does no boundary
// checking what so ever. If you'd like a safe version
// use: SafeSet
func (A *Matrix) Set(row, col int, val float64) {

	A.values[(row-1)*A.cols+col-1] = val

}

// Transpose the matrix
func (A *Matrix) Transpose() *Matrix {
	B := Zeros(A.cols, A.rows)

	for i := 1; i <= A.rows; i++ {
		for j := 1; j <= A.cols; j++ {
			B.values[(j-1)*B.cols+i-1] = A.values[(i-1)*A.cols+j-1]
		}
	}

	return B
}

// Add B to the matrix A, produces new matrix
func (A *Matrix) Add(B *Matrix) (*Matrix, error) {
	if !sameSize(A, B) {
		return nil, ErrIncompatibleSizes
	}

	C := Zeros(A.rows, A.cols)

	for i, val := range A.values {
		C.values[i] = val + B.values[i]
	}

	return C, nil
}

// Subtract B from the matrix A, produces a new matrix
func (A *Matrix) Sub(B *Matrix) (*Matrix, error) {
	if !sameSize(A, B) {
		return nil, ErrIncompatibleSizes
	}

	C := Zeros(A.rows, A.cols)

	for i, val := range A.values {
		C.values[i] = val - B.values[i]
	}

	return C, nil
}

// Multiplies 2 matricies with each other.
// Returns a new matrix.
//
// Warning: This is an unsafe method to use, it does no boundary
// checking what so ever. If you'd like a safe version
// use: SafeMul
func (A *Matrix) Mul(B *Matrix) *Matrix {

	C := Zeros(A.rows, B.cols)

	for i := 0; i < C.rows; i++ {
		for j := 0; j < C.cols; j++ {
			sum := float64(0)

			for k := 0; k < A.cols; k++ {
				sum += A.values[i*A.cols+k] * B.values[k*B.cols+j]
			}

			C.values[i*C.cols+j] = sum
		}
	}

	return C
}

// Standard scalar product of 2 matricies.
// Returns a new matrix.
//
// Warning: This is an unsafe method to use, it does no boundary
// checking what so ever. If you'd like a safe version
// use: SafeDot
func (A *Matrix) Dot(B *Matrix) *Matrix {
	C := Zeros(A.rows, A.cols)

	for i, val := range A.values {
		C.values[i] = val * B.values[i]
	}

	return C
}

// Scale the matrix by the factor f
func (A *Matrix) Scale(f float64) *Matrix {
	B := Zeros(A.rows, A.cols)

	for i, val := range A.values {
		B.values[i] = val * f
	}

	return B
}

// Take every element of the matrix to the power of n
func (A *Matrix) Power(n float64) *Matrix {
	B := Zeros(A.rows, A.cols)

	for i, val := range A.values {
		B.values[i] = math.Pow(val, n)
	}

	return B
}

// Add n to all elements in the matrix (in-place)
func (A *Matrix) AddNum(n float64) *Matrix {
	for i := range A.values {
		A.values[i] += n
	}

	return A
}
<|endoftext|>


<commit_before>// Package jsonconfig is a super tiny (pseudo) JSON configuration parser for Go with support for comments.

// Kailash Nadh, http://nadh.in/code/jsonconfig
// Jan 2015
// MIT License

package jsonconfig

import (
	"regexp"
	"encoding/json"
	"io/ioutil"
	"errors"
)

func Load(filename string, config interface{})  error {
	// read file
	data, err := ioutil.ReadFile(filename)
	if(err != nil) {
		return errors.New("Error reading file")
	}

	// regex monstrosity because of the lack of lookbehinds/aheads
	// stand alone comments
	r1, _ := regexp.Compile(`(?m)^(\s+)?//(.*)$`)

	// numbers and boolean
	r2, _ := regexp.Compile(`(?m)"(.+?)":(\s+)?([0-9\.\-]+|true|false|null)(\s+)?,(\s+)?//(.*)$`)

	// strings
	r3, _ := regexp.Compile(`(?m)"(.+?)":(\s+)?"(.+?)"(\s+)?,(\s+)?//(.*)$`)

	// arrays and objects
	r4, _ := regexp.Compile(`(?m)"(.+?)":(\s+)?([\{\[])(.+?)([\}\]])(\s+)?,(\s+)?//(.*)$`)

	res := r1.ReplaceAllString(string(data), "")
	res = r2.ReplaceAllString(res, `"$1": $3,`)
	res = r3.ReplaceAllString(res, `"$1": "$3",`)
	res = r4.ReplaceAllString(res, `"$1": $3$4$5,`)

	// decode json
	if err := json.Unmarshal([]byte(res), &config); err != nil {
		return err
	}

	return nil
}
<commit_msg>Idiomatic comments<commit_after>// Package jsonconfig is a super tiny (pseudo) JSON configuration parser for Go with support for comments.

// Kailash Nadh, http://nadh.in/code/jsonconfig
// Jan 2015
// MIT License

package jsonconfig

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"regexp"
)

func Load(filename string, config interface{}) error {
	// Read the config file.
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return errors.New("Error reading file")
	}

	// Regex monstrosity because of the lack of lookbehinds/aheads.

	// Standalone comments.
	r1, _ := regexp.Compile(`(?m)^(\s+)?//(.*)$`)

	// Numbers and boolean.
	r2, _ := regexp.Compile(`(?m)"(.+?)":(\s+)?([0-9\.\-]+|true|false|null)(\s+)?,(\s+)?//(.*)$`)

	// Strings.
	r3, _ := regexp.Compile(`(?m)"(.+?)":(\s+)?"(.+?)"(\s+)?,(\s+)?//(.*)$`)

	// Arrays and objects.
	r4, _ := regexp.Compile(`(?m)"(.+?)":(\s+)?([\{\[])(.+?)([\}\]])(\s+)?,(\s+)?//(.*)$`)

	res := r1.ReplaceAllString(string(data), "")
	res = r2.ReplaceAllString(res, `"$1": $3,`)
	res = r3.ReplaceAllString(res, `"$1": "$3",`)
	res = r4.ReplaceAllString(res, `"$1": $3$4$5,`)

	// Decode json.
	if err := json.Unmarshal([]byte(res), &config); err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright (C) 2014 Miquel Sabaté Solà <mikisabate@gmail.com>
// This file is licensed under the MIT license.
// See the LICENSE file.

package app

import (
	"net/http"
	"net/http/httptest"
	"net/url"
	"testing"

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

func TestTopicsCreate(t *testing.T) {
	InitTestDB()
	defer CloseTestDB()

	param := make(url.Values)
	param["name"] = []string{"user"}

	req, err := http.NewRequest("POST", "/", nil)
	assert.Nil(t, err)
	req.PostForm = param
	w := httptest.NewRecorder()
	TopicsCreate(w, req)

	assert.Equal(t, w.Code, 302)
	assert.Equal(t, w.HeaderMap["Location"][0], "/topics")

	var topic Topic
	err = Db.SelectOne(&topic, "select * from topics")
	assert.Nil(t, err)
	assert.NotEmpty(t, topic.Id)
	assert.Equal(t, topic.Name, "user")
	assert.NotEmpty(t, topic.Created_at)
}

func TestTopicsCreateNoName(t *testing.T) {
	InitTestDB()
	defer CloseTestDB()

	param := make(url.Values)

	req, err := http.NewRequest("POST", "/", nil)
	assert.Nil(t, err)
	req.PostForm = param
	w := httptest.NewRecorder()
	TopicsCreate(w, req)

	assert.Equal(t, w.Code, 302)
	assert.Equal(t, w.HeaderMap["Location"][0], "/topics")

	var topic Topic
	err = Db.SelectOne(&topic, "select * from topics")
	assert.Empty(t, topic.Id)
	assert.NotNil(t, err)
	count, err := Db.SelectInt("select count(*) from users")
	assert.Equal(t, count, 0)
}
<commit_msg>app: added some tests to the topics resource.<commit_after>// Copyright (C) 2014 Miquel Sabaté Solà <mikisabate@gmail.com>
// This file is licensed under the MIT license.
// See the LICENSE file.

package app

import (
	"net/http"
	"net/http/httptest"
	"net/url"
	"testing"

	"github.com/gorilla/mux"
	"github.com/stretchr/testify/assert"
)

func TestTopicsCreate(t *testing.T) {
	InitTestDB()
	defer CloseTestDB()

	param := make(url.Values)
	param["name"] = []string{"user"}

	req, err := http.NewRequest("POST", "/", nil)
	assert.Nil(t, err)
	req.PostForm = param
	w := httptest.NewRecorder()
	TopicsCreate(w, req)

	assert.Equal(t, w.Code, 302)
	assert.Equal(t, w.HeaderMap["Location"][0], "/topics")

	var topic Topic
	err = Db.SelectOne(&topic, "select * from topics")
	assert.Nil(t, err)
	assert.NotEmpty(t, topic.Id)
	assert.Equal(t, topic.Name, "user")
	assert.NotEmpty(t, topic.Created_at)
}

func TestTopicsCreateNoName(t *testing.T) {
	InitTestDB()
	defer CloseTestDB()

	param := make(url.Values)

	req, err := http.NewRequest("POST", "/", nil)
	assert.Nil(t, err)
	req.PostForm = param
	w := httptest.NewRecorder()
	TopicsCreate(w, req)

	assert.Equal(t, w.Code, 302)
	assert.Equal(t, w.HeaderMap["Location"][0], "/topics")

	var topic Topic
	err = Db.SelectOne(&topic, "select * from topics")
	assert.Empty(t, topic.Id)
	assert.NotNil(t, err)
	count, err := Db.SelectInt("select count(*) from users")
	assert.Equal(t, count, 0)
}

func TestTopicsRename(t *testing.T) {
	InitTestDB()
	defer CloseTestDB()

	err := createTopic("topic")
	assert.Nil(t, err)

	var t1, t2 Topic
	err = Db.SelectOne(&t1, "select * from topics")
	assert.Nil(t, err)

	param := make(url.Values)

	req, err := http.NewRequest("POST", "/topics/"+t1.Id, nil)
	assert.Nil(t, err)
	param["name"] = []string{"topic1"}
	req.PostForm = param
	w := httptest.NewRecorder()

	m := mux.NewRouter()
	m.HandleFunc("/topics/{id}", TopicsUpdate)
	m.ServeHTTP(w, req)

	// DB
	err = Db.SelectOne(&t2, "select * from topics")
	assert.Nil(t, err)
	assert.Equal(t, t2.Name, "topic1")
	assert.Equal(t, t1.Id, t2.Id)

	// HTTP
	assert.Equal(t, w.Code, 302)
	assert.Equal(t, w.HeaderMap["Location"][0], "/topics")
}

func TestUpdateContents(t *testing.T) {
	InitTestDB()
	defer CloseTestDB()

	err := createTopic("topic")
	assert.Nil(t, err)

	var t1, t2 Topic
	err = Db.SelectOne(&t1, "select * from topics")
	assert.Nil(t, err)

	param := make(url.Values)

	req, err := http.NewRequest("POST", "/topics/"+t1.Id, nil)
	assert.Nil(t, err)
	param["contents"] = []string{"**bold**"}
	req.PostForm = param
	w := httptest.NewRecorder()

	m := mux.NewRouter()
	m.HandleFunc("/topics/{id}", TopicsUpdate)
	m.ServeHTTP(w, req)

	// DB
	err = Db.SelectOne(&t2, "select * from topics")
	assert.Nil(t, err)
	assert.Equal(t, t1.Name, t2.Name)
	assert.Equal(t, t1.Id, t2.Id)
	assert.NotEqual(t, t1.Contents, t2.Contents)
	assert.Equal(t, t2.Contents, "**bold**")

	// HTTP
	assert.Equal(t, w.Code, 302)
	assert.Equal(t, w.HeaderMap["Location"][0], "/topics")
}

func TestDestroy(t *testing.T) {
	InitTestDB()
	defer CloseTestDB()

	err := createTopic("topic")
	assert.Nil(t, err)

	var t1 Topic
	err = Db.SelectOne(&t1, "select * from topics")
	assert.Nil(t, err)

	req, err := http.NewRequest("POST", "/topics/"+t1.Id+"/delete", nil)
	assert.Nil(t, err)
	w := httptest.NewRecorder()

	m := mux.NewRouter()
	m.HandleFunc("/topics/{id}/delete", TopicsDestroy)
	m.ServeHTTP(w, req)

	// DB
	c, err := Db.SelectInt("select count(*) from topics")
	assert.Nil(t, err)
	assert.Equal(t, c, 0)

	// HTTP
	assert.Equal(t, w.Code, 302)
	assert.Equal(t, w.HeaderMap["Location"][0], "/topics")
}
<|endoftext|>


<commit_before>// $G $F.go && $L $F.$A && ./$A.out

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

package main

const (
	Bool = iota;
	Int;
	Float;
	String;
	Struct;
	Chan;
	Array;
	Map;
	Func;
	Last;
)

type S struct { a int }
var s S = S{1234}

var c = make(chan int);

var a	= []int{0,1,2,3}

var m = make(map[string]int)

func assert(b bool, s string) {
	if !b {
		println(s);
		sys.Exit(1);
	}
}

func f(i int) interface{} {
	switch i {
	case Bool:
		return true;
	case Int:
		return 7;
	case Float:
		return 7.4;
	case String:
		return "hello";
	case Struct:
		return s;
	case Chan:
		return c;
	case Array:
		return a;
	case Map:
		return m;
	case Func:
		return f;
	}
	panic("bad type number");
}

func main() {
	// type guard style
	for i := Bool; i < Last; i++ {
		switch v := f(i); true {
		case x := v.(bool):
			assert(x == true && i == Bool, "switch 1 bool");
		case x := v.(int):
			assert(x == 7 && i == Int, "switch 1 int");
		case x := v.(float):
			assert(x == 7.4 && i == Float, "switch 1 float");
		case x := v.(string):
			assert(x == "hello" && i == String, "switch 1 string");
		case x := v.(S):
			assert(x.a == 1234 && i == Struct, "switch 1 struct");
		case x := v.(chan int):
			assert(x == c && i == Chan, "switch 1 chan");
		case x := v.([]int):
			assert(x[3] == 3 && i == Array, "switch 1 array");
		case x := v.(map[string]int):
			assert(x == m && i == Map, "switch 1 map");
		case x := v.(func(i int) interface{}):
			assert(x == f && i == Func, "switch 1 fun");
		default:
			assert(false, "switch 1 unknown");
		}
	}

	// type switch style
	for i := Bool; i < Last; i++ {
		switch x := f(i).(type) {
		case bool:
			assert(x == true, "switch 2 bool");
		case int:
			assert(x == 7, "switch 2 int");
		case float:
			assert(x == 7.4, "switch 2 float");
		case string:
			assert(x == "hello", "switch 2 string");
		case S:
			assert(x.a == 1234, "switch 2 struct");
		case chan int:
			assert(x == c, "switch 2 chan");
		case []int:
			assert(x[3] == 3, "switch 2 array");
		case map[string]int:
			assert(x == m, "switch 2 map");
		case func(i int) interface{}:
			assert(x == f, "switch 2 fun");
		default:
			assert(false, "switch 2 unknown");
		}
	}

	// catch-all style in various forms
	switch {
	case true:
		assert(true, "switch 3 bool");
	default:
		assert(false, "switch 3 unknown");
	}

	switch true {
	case true:
		assert(true, "switch 3 bool");
	default:
		assert(false, "switch 3 unknown");
	}

	switch false {
	case false:
		assert(true, "switch 4 bool");
	default:
		assert(false, "switch 4 unknown");
	}

	switch true {
	case x := f(Int).(float):
		assert(false, "switch 5 type guard wrong type");
	case x := f(Int).(int):
		assert(x == 7, "switch 5 type guard");
	default:
		assert(false, "switch 5 unknown");
	}

	m["7"] = 7;
	switch true {
	case x := m["6"]:
		assert(false, "switch 6 map reference wrong");
	case x := m["7"]:
		assert(x == 7, "switch 6 map reference");
	default:
		assert(false, "switch 6 unknown");
	}

	go func() { <-c; c <- 77; } ();
	// guarantee the channel is ready
	c <- 77;
	for i := 0; i < 5; i++ {
		sys.Gosched();
	}
	dummyc := make(chan int);
	switch true {
	case x := <-dummyc:
		assert(false, "switch 7 chan wrong");
	case x := <-c:
		assert(x == 77, "switch 7 chan");
	default:
		assert(false, "switch 7 unknown");
	}

}
<commit_msg>add value checks to the other switch - should have done this in prior round<commit_after>// $G $F.go && $L $F.$A && ./$A.out

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

package main

const (
	Bool = iota;
	Int;
	Float;
	String;
	Struct;
	Chan;
	Array;
	Map;
	Func;
	Last;
)

type S struct { a int }
var s S = S{1234}

var c = make(chan int);

var a	= []int{0,1,2,3}

var m = make(map[string]int)

func assert(b bool, s string) {
	if !b {
		println(s);
		sys.Exit(1);
	}
}

func f(i int) interface{} {
	switch i {
	case Bool:
		return true;
	case Int:
		return 7;
	case Float:
		return 7.4;
	case String:
		return "hello";
	case Struct:
		return s;
	case Chan:
		return c;
	case Array:
		return a;
	case Map:
		return m;
	case Func:
		return f;
	}
	panic("bad type number");
}

func main() {
	// type guard style
	for i := Bool; i < Last; i++ {
		switch v := f(i); true {
		case x := v.(bool):
			assert(x == true && i == Bool, "switch 1 bool");
		case x := v.(int):
			assert(x == 7 && i == Int, "switch 1 int");
		case x := v.(float):
			assert(x == 7.4 && i == Float, "switch 1 float");
		case x := v.(string):
			assert(x == "hello" && i == String, "switch 1 string");
		case x := v.(S):
			assert(x.a == 1234 && i == Struct, "switch 1 struct");
		case x := v.(chan int):
			assert(x == c && i == Chan, "switch 1 chan");
		case x := v.([]int):
			assert(x[3] == 3 && i == Array, "switch 1 array");
		case x := v.(map[string]int):
			assert(x == m && i == Map, "switch 1 map");
		case x := v.(func(i int) interface{}):
			assert(x == f && i == Func, "switch 1 fun");
		default:
			assert(false, "switch 1 unknown");
		}
	}

	// type switch style
	for i := Bool; i < Last; i++ {
		switch x := f(i).(type) {
		case bool:
			assert(x == true && i == Bool, "switch 2 bool");
		case int:
			assert(x == 7 && i == Int, "switch 2 int");
		case float:
			assert(x == 7.4 && i == Float, "switch 2 float");
		case string:
			assert(x == "hello" && i == String, "switch 2 string");
		case S:
			assert(x.a == 1234 && i == Struct, "switch 2 struct");
		case chan int:
			assert(x == c && i == Chan, "switch 2 chan");
		case []int:
			assert(x[3] == 3 && i == Array, "switch 2 array");
		case map[string]int:
			assert(x == m && i == Map, "switch 2 map");
		case func(i int) interface{}:
			assert(x == f && i == Func, "switch 2 fun");
		default:
			assert(false, "switch 2 unknown");
		}
	}

	// catch-all style in various forms
	switch {
	case true:
		assert(true, "switch 3 bool");
	default:
		assert(false, "switch 3 unknown");
	}

	switch true {
	case true:
		assert(true, "switch 3 bool");
	default:
		assert(false, "switch 3 unknown");
	}

	switch false {
	case false:
		assert(true, "switch 4 bool");
	default:
		assert(false, "switch 4 unknown");
	}

	switch true {
	case x := f(Int).(float):
		assert(false, "switch 5 type guard wrong type");
	case x := f(Int).(int):
		assert(x == 7, "switch 5 type guard");
	default:
		assert(false, "switch 5 unknown");
	}

	m["7"] = 7;
	switch true {
	case x := m["6"]:
		assert(false, "switch 6 map reference wrong");
	case x := m["7"]:
		assert(x == 7, "switch 6 map reference");
	default:
		assert(false, "switch 6 unknown");
	}

	go func() { <-c; c <- 77; } ();
	// guarantee the channel is ready
	c <- 77;
	for i := 0; i < 5; i++ {
		sys.Gosched();
	}
	dummyc := make(chan int);
	switch true {
	case x := <-dummyc:
		assert(false, "switch 7 chan wrong");
	case x := <-c:
		assert(x == 77, "switch 7 chan");
	default:
		assert(false, "switch 7 unknown");
	}

}
<|endoftext|>


<commit_before>package correctable

import (
	"context"
	"testing"
	"time"

	"github.com/relab/gorums"
	"google.golang.org/grpc"
)

// run a test on a correctable call.
// n is the number of replicas, and div is a divider.
// the target level is n, and the level is calculated by the quorum function
// by dividing the sum of levels from the servers with the divider.
func run(t *testing.T, n int, div int, corr func(*Configuration) *gorums.Correctable) {
	addrs, teardown := gorums.TestSetup(t, n, func(i int) gorums.ServerIface {
		gorumsSrv := gorums.NewServer()
		RegisterCorrectableTestServer(gorumsSrv, &testSrv{n})
		return gorumsSrv
	})
	defer teardown()

	mgr := NewManager(gorums.WithDialTimeout(time.Second), gorums.WithGrpcDialOptions(
		grpc.WithInsecure(), grpc.WithBlock(),
	))

	cfg, err := mgr.NewConfiguration(qspec{div, n}, gorums.WithNodeList(addrs))
	if err != nil {
		t.Fatal(err)
	}

	res := corr(cfg)

	for i := 1; i <= n; i++ {
		<-res.Watch(i)
	}

	<-res.Done()
}

func TestCorrectable(t *testing.T) {
	run(t, 4, 1, func(c *Configuration) *gorums.Correctable {
		corr := c.Correctable(context.Background(), &CorrectableRequest{})
		return corr.Correctable
	})
}

func TestCorrectableStream(t *testing.T) {
	run(t, 4, 4, func(c *Configuration) *gorums.Correctable {
		corr := c.CorrectableStream(context.Background(), &CorrectableRequest{})
		return corr.Correctable
	})
}

type qspec struct {
	div       int
	doneLevel int
}

func (q qspec) q(replies map[uint32]*CorrectableResponse) (*CorrectableResponse, int, bool) {
	sum := 0
	for _, reply := range replies {
		sum += int(reply.Level)
	}
	level := sum / q.div
	return &CorrectableResponse{Level: int32(level)}, level, level >= q.doneLevel
}

// CorrectableStreamQF is the quorum function for the CorrectableStream
// correctable stream quorum call method. The in parameter is the request object
// supplied to the CorrectableStream method at call time, and may or may not
// be used by the quorum function. If the in parameter is not needed
// you should implement your quorum function with '_ *CorrectableRequest'.
func (q qspec) CorrectableStreamQF(_ *CorrectableRequest, replies map[uint32]*CorrectableResponse) (*CorrectableResponse, int, bool) {
	return q.q(replies)
}

// CorrectableQF is the quorum function for the Correctable
// correctable quorum call method. The in parameter is the request object
// supplied to the Correctable method at call time, and may or may not
// be used by the quorum function. If the in parameter is not needed
// you should implement your quorum function with '_ *CorrectableRequest'.
func (q qspec) CorrectableQF(_ *CorrectableRequest, replies map[uint32]*CorrectableResponse) (*CorrectableResponse, int, bool) {
	return q.q(replies)
}

type testSrv struct {
	n int
}

func (srv testSrv) CorrectableStream(_ gorums.ServerCtx, request *CorrectableRequest, send func(response *CorrectableResponse) error) error {
	for i := 0; i < srv.n; i++ {
		err := send(&CorrectableResponse{Level: int32(i + 1)})
		if err != nil {
			return err
		}
	}
	return nil
}

func (srv testSrv) Correctable(_ gorums.ServerCtx, request *CorrectableRequest) (response *CorrectableResponse, err error) {
	return &CorrectableResponse{Level: 1}, nil
}
<commit_msg>prevent correctable test from blocking forever<commit_after>package correctable

import (
	"context"
	"testing"
	"time"

	"github.com/relab/gorums"
	"google.golang.org/grpc"
)

// run a test on a correctable call.
// n is the number of replicas, and div is a divider.
// the target level is n, and the level is calculated by the quorum function
// by dividing the sum of levels from the servers with the divider.
func run(t *testing.T, n int, div int, corr func(context.Context, *Configuration) *gorums.Correctable) {
	addrs, teardown := gorums.TestSetup(t, n, func(i int) gorums.ServerIface {
		gorumsSrv := gorums.NewServer()
		RegisterCorrectableTestServer(gorumsSrv, &testSrv{n})
		return gorumsSrv
	})
	defer teardown()

	mgr := NewManager(gorums.WithDialTimeout(time.Second), gorums.WithGrpcDialOptions(
		grpc.WithInsecure(), grpc.WithBlock(),
	))

	cfg, err := mgr.NewConfiguration(qspec{div, n}, gorums.WithNodeList(addrs))
	if err != nil {
		t.Fatal(err)
	}

	ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
	defer cancel()
	res := corr(ctx, cfg)

	donech := res.Done()

	for i := 1; i <= n; i++ {
		select {
		case <-res.Watch(i):
		case <-donech:
		}
	}

	<-donech

	_, _, err = res.Get()
	if err != nil {
		t.Error(err)
	}
}

func TestCorrectable(t *testing.T) {
	run(t, 4, 1, func(ctx context.Context, c *Configuration) *gorums.Correctable {
		corr := c.Correctable(ctx, &CorrectableRequest{})
		return corr.Correctable
	})
}

func TestCorrectableStream(t *testing.T) {
	run(t, 4, 4, func(ctx context.Context, c *Configuration) *gorums.Correctable {
		corr := c.CorrectableStream(ctx, &CorrectableRequest{})
		return corr.Correctable
	})
}

type qspec struct {
	div       int
	doneLevel int
}

func (q qspec) q(replies map[uint32]*CorrectableResponse) (*CorrectableResponse, int, bool) {
	sum := 0
	for _, reply := range replies {
		sum += int(reply.Level)
	}
	level := sum / q.div
	return &CorrectableResponse{Level: int32(level)}, level, level >= q.doneLevel
}

// CorrectableStreamQF is the quorum function for the CorrectableStream
// correctable stream quorum call method. The in parameter is the request object
// supplied to the CorrectableStream method at call time, and may or may not
// be used by the quorum function. If the in parameter is not needed
// you should implement your quorum function with '_ *CorrectableRequest'.
func (q qspec) CorrectableStreamQF(_ *CorrectableRequest, replies map[uint32]*CorrectableResponse) (*CorrectableResponse, int, bool) {
	return q.q(replies)
}

// CorrectableQF is the quorum function for the Correctable
// correctable quorum call method. The in parameter is the request object
// supplied to the Correctable method at call time, and may or may not
// be used by the quorum function. If the in parameter is not needed
// you should implement your quorum function with '_ *CorrectableRequest'.
func (q qspec) CorrectableQF(_ *CorrectableRequest, replies map[uint32]*CorrectableResponse) (*CorrectableResponse, int, bool) {
	return q.q(replies)
}

type testSrv struct {
	n int
}

func (srv testSrv) CorrectableStream(_ gorums.ServerCtx, request *CorrectableRequest, send func(response *CorrectableResponse) error) error {
	for i := 0; i < srv.n; i++ {
		err := send(&CorrectableResponse{Level: int32(i + 1)})
		if err != nil {
			return err
		}
	}
	return nil
}

func (srv testSrv) Correctable(_ gorums.ServerCtx, request *CorrectableRequest) (response *CorrectableResponse, err error) {
	return &CorrectableResponse{Level: 1}, nil
}
<|endoftext|>


<commit_before>package tests

import (
	"testing"
)

// Mimics some of SHRDLU's functions, but in the cli-go way

func TestBlocksWorld(t *testing.T) {

}
<commit_msg>blocks test<commit_after>package tests

import (
	"nli-go/lib/common"
	"nli-go/lib/global"
	"os"
	"testing"
)

// Mimics some of SHRDLU's functions, but in the cli-go way

func TestBlocksWorld(t *testing.T) {
	log := common.NewSystemLog(false)
	system := global.NewSystem(common.Dir() + "/../../resources/shrdlu/config.json", log)
	sessionId := "1"
	actualSessionPath := common.AbsolutePath(common.Dir(), "sessions/" + sessionId + ".json")

	if !log.IsOk() {
		t.Errorf(log.String())
		return
	}

	var tests = [][]struct {
		question      string
		answer        string
		inSessionName string
		outSessionName string
	}{
		{
			{"Pick up a big red block", "OK", "", ""},
		},
	}

	for _, session := range tests {

		os.Remove(actualSessionPath)

		for _, test := range session {

			log.Clear()

			if test.inSessionName == "" {
				system.ClearDialogContext()
			} else {
				inSessionPath := common.AbsolutePath(common.Dir(), "resources/" + test.inSessionName)
				inSession, _ := common.ReadFile(inSessionPath)
				common.WriteFile(actualSessionPath, inSession)
				system.PopulateDialogContext(actualSessionPath)
			}

			answer, options := system.Answer(test.question)

			if options.HasOptions() {
				answer += options.String()
			}

			system.StoreDialogContext(actualSessionPath)

			if answer != test.answer {
				t.Errorf("Test relationships: got %v, want %v", answer, test.answer)
				t.Error(log.String())
			}

			if test.outSessionName != "" {
				outSessionPath := common.AbsolutePath(common.Dir(), "resources/"+test.outSessionName)
				expected, err := common.ReadFile(outSessionPath)

				if err != nil {
					t.Errorf("Test relationships: error reading %v", outSessionPath)
				}

				actual, err := common.ReadFile(actualSessionPath)

				if err != nil {
					t.Errorf("Test relationships: error reading %v", actualSessionPath)
				}

				if expected != actual {
					t.Errorf("Test relationships: got %v, want %v", actual, expected)
				}
			}
		}
	}
}
<|endoftext|>


<commit_before>package horizon

import (
	"encoding/json"
	. "github.com/smartystreets/goconvey/convey"
	"github.com/stellar/horizon/resource"
	"github.com/stellar/horizon/test"
	"github.com/stellar/horizon/txsub"
	"github.com/stellar/horizon/txsub/sequence"
	"net/url"
	"testing"
)

func TestTransactionActions(t *testing.T) {

	Convey("Transactions Actions:", t, func() {
		test.LoadScenario("base")
		app := NewTestApp()
		defer app.Close()
		rh := NewRequestHelper(app)

		Convey("GET /transactions/2374e99349b9ef7dba9a5db3339b78fda8f34777b1af33ba468ad5c0df946d4d", func() {
			w := rh.Get("/transactions/2374e99349b9ef7dba9a5db3339b78fda8f34777b1af33ba468ad5c0df946d4d")
			So(w.Code, ShouldEqual, 200)

			var result resource.Transaction
			err := json.Unmarshal(w.Body.Bytes(), &result)
			So(err, ShouldBeNil)
			So(result.Hash, ShouldEqual, "2374e99349b9ef7dba9a5db3339b78fda8f34777b1af33ba468ad5c0df946d4d")
		})

		Convey("GET /transactions/not_real", func() {
			w := rh.Get("/transactions/not_real")
			So(w.Code, ShouldEqual, 404)
		})

		Convey("GET /ledgers/100/transactions", func() {
			w := rh.Get("/ledgers/100/transactions")
			So(w.Code, ShouldEqual, 404)
		})

		Convey("GET /transactions", func() {
			w := rh.Get("/transactions")
			So(w.Code, ShouldEqual, 200)
			So(w.Body, ShouldBePageOf, 4)
		})

		Convey("GET /ledgers/:ledger_id/transactions", func() {
			w := rh.Get("/ledgers/1/transactions")
			So(w.Code, ShouldEqual, 200)
			So(w.Body, ShouldBePageOf, 0)

			w = rh.Get("/ledgers/2/transactions")
			So(w.Code, ShouldEqual, 200)
			So(w.Body, ShouldBePageOf, 3)

			w = rh.Get("/ledgers/3/transactions")
			So(w.Code, ShouldEqual, 200)
			So(w.Body, ShouldBePageOf, 1)
		})

		Convey("GET /accounts/:account_od/transactions", func() {
			w := rh.Get("/accounts/GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H/transactions")
			So(w.Code, ShouldEqual, 200)
			So(w.Body, ShouldBePageOf, 3)

			w = rh.Get("/accounts/GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2/transactions")
			So(w.Code, ShouldEqual, 200)
			So(w.Body, ShouldBePageOf, 1)

			w = rh.Get("/accounts/GCXKG6RN4ONIEPCMNFB732A436Z5PNDSRLGWK7GBLCMQLIFO4S7EYWVU/transactions")
			So(w.Code, ShouldEqual, 200)
			So(w.Body, ShouldBePageOf, 2)
		})

		Convey("POST /transactions", func() {
			Convey("503 response when Sequence buffer is full", func() {
				app.submitter.Results = &txsub.MockResultProvider{
					Results: []txsub.Result{
						{Err: sequence.ErrNoMoreRoom},
					},
				}

				w := rh.Post(
					"/transactions",
					url.Values{"tx": []string{"AAAAAGL8HQvQkbK2HA3WVjRrKmjX00fG8sLI7m0ERwJW/AX3AAAAZAAAAAAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAArqN6LeOagjxMaUP96Bzfs9e0corNZXzBWJkFoK7kvkwAAAAAO5rKAAAAAAAAAAABVvwF9wAAAECDzqvkQBQoNAJifPRXDoLhvtycT3lFPCQ51gkdsFHaBNWw05S/VhW0Xgkr0CBPE4NaFV2Kmcs3ZwLmib4TRrML"}},
					test.RequestHelperNoop,
				)
				So(w.Code, ShouldEqual, 503)

			})

			Convey("200 response for existing transaction", func() {
				w := rh.Post(
					"/transactions",
					url.Values{"tx": []string{"AAAAAGL8HQvQkbK2HA3WVjRrKmjX00fG8sLI7m0ERwJW/AX3AAAAZAAAAAAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAArqN6LeOagjxMaUP96Bzfs9e0corNZXzBWJkFoK7kvkwAAAAAO5rKAAAAAAAAAAABVvwF9wAAAECDzqvkQBQoNAJifPRXDoLhvtycT3lFPCQ51gkdsFHaBNWw05S/VhW0Xgkr0CBPE4NaFV2Kmcs3ZwLmib4TRrML"}},
					test.RequestHelperNoop,
				)
				So(w.Code, ShouldEqual, 200)

			})
		})

	})
}
<commit_msg>Fix busted tests<commit_after>package horizon

import (
	"encoding/json"
	. "github.com/smartystreets/goconvey/convey"
	"github.com/stellar/horizon/resource"
	"github.com/stellar/horizon/test"
	"github.com/stellar/horizon/txsub"
	"github.com/stellar/horizon/txsub/sequence"
	"net/url"
	"testing"
)

func TestTransactionActions(t *testing.T) {

	Convey("Transactions Actions:", t, func() {
		test.LoadScenario("base")
		app := NewTestApp()
		defer app.Close()
		rh := NewRequestHelper(app)

		Convey("GET /transactions/2374e99349b9ef7dba9a5db3339b78fda8f34777b1af33ba468ad5c0df946d4d", func() {
			w := rh.Get("/transactions/2374e99349b9ef7dba9a5db3339b78fda8f34777b1af33ba468ad5c0df946d4d")
			So(w.Code, ShouldEqual, 200)

			var result resource.Transaction
			err := json.Unmarshal(w.Body.Bytes(), &result)
			So(err, ShouldBeNil)
			So(result.Hash, ShouldEqual, "2374e99349b9ef7dba9a5db3339b78fda8f34777b1af33ba468ad5c0df946d4d")
		})

		Convey("GET /transactions/not_real", func() {
			w := rh.Get("/transactions/not_real")
			So(w.Code, ShouldEqual, 404)
		})

		Convey("GET /ledgers/100/transactions", func() {
			w := rh.Get("/ledgers/100/transactions")
			So(w.Code, ShouldEqual, 404)
		})

		Convey("GET /transactions", func() {
			w := rh.Get("/transactions")
			So(w.Code, ShouldEqual, 200)
			So(w.Body, ShouldBePageOf, 4)
		})

		Convey("GET /ledgers/:ledger_id/transactions", func() {
			w := rh.Get("/ledgers/1/transactions")
			So(w.Code, ShouldEqual, 200)
			So(w.Body, ShouldBePageOf, 0)

			w = rh.Get("/ledgers/2/transactions")
			So(w.Code, ShouldEqual, 200)
			So(w.Body, ShouldBePageOf, 3)

			w = rh.Get("/ledgers/3/transactions")
			So(w.Code, ShouldEqual, 200)
			So(w.Body, ShouldBePageOf, 1)
		})

		Convey("GET /accounts/:account_od/transactions", func() {
			w := rh.Get("/accounts/GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H/transactions")
			So(w.Code, ShouldEqual, 200)
			So(w.Body, ShouldBePageOf, 3)

			w = rh.Get("/accounts/GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2/transactions")
			So(w.Code, ShouldEqual, 200)
			So(w.Body, ShouldBePageOf, 1)

			w = rh.Get("/accounts/GCXKG6RN4ONIEPCMNFB732A436Z5PNDSRLGWK7GBLCMQLIFO4S7EYWVU/transactions")
			So(w.Code, ShouldEqual, 200)
			So(w.Body, ShouldBePageOf, 2)
		})

		Convey("POST /transactions", func() {
			Convey("503 response when Sequence buffer is full", func() {
				app.submitter.Results = &txsub.MockResultProvider{
					Results: []txsub.Result{
						{Err: sequence.ErrNoMoreRoom},
					},
				}

				w := rh.Post(
					"/transactions",
					url.Values{"tx": []string{"AAAAAGL8HQvQkbK2HA3WVjRrKmjX00fG8sLI7m0ERwJW/AX3AAAAZAAAAAAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAArqN6LeOagjxMaUP96Bzfs9e0corNZXzBWJkFoK7kvkwAAAAAO5rKAAAAAAAAAAABVvwF9wAAAECDzqvkQBQoNAJifPRXDoLhvtycT3lFPCQ51gkdsFHaBNWw05S/VhW0Xgkr0CBPE4NaFV2Kmcs3ZwLmib4TRrML"}},
				)
				So(w.Code, ShouldEqual, 503)

			})

			Convey("200 response for existing transaction", func() {
				w := rh.Post(
					"/transactions",
					url.Values{"tx": []string{"AAAAAGL8HQvQkbK2HA3WVjRrKmjX00fG8sLI7m0ERwJW/AX3AAAAZAAAAAAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAArqN6LeOagjxMaUP96Bzfs9e0corNZXzBWJkFoK7kvkwAAAAAO5rKAAAAAAAAAAABVvwF9wAAAECDzqvkQBQoNAJifPRXDoLhvtycT3lFPCQ51gkdsFHaBNWw05S/VhW0Xgkr0CBPE4NaFV2Kmcs3ZwLmib4TRrML"}},
				)
				So(w.Code, ShouldEqual, 200)

			})
		})

	})
}
<|endoftext|>


<commit_before>// Copyright 2014 Brave New Software

//    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 archive

import (
	"log"
	"os"
	"strings"
	"time"

	"github.com/getlantern/statshub/bigquery"
	"github.com/getlantern/statshub/statshub"
)

const (
	ARCHIVE_TO_BIGQUERY = "ARCHIVE_TO_BIGQUERY"
)

var (
	shouldArchive = strings.ToLower(os.Getenv(ARCHIVE_TO_BIGQUERY)) == "true"
)

// StartArchiving starts a goroutine that continuously archives data at regular intervals
// based on the archiveInterval constant.
func StartArchiving() {
	if shouldArchive {
		log.Printf("Archiving to BigQuery at %s", bigquery.ProjectId)
		archivePeriodically("fallback", 10*time.Minute)
		archivePeriodically("country", 1*time.Hour)
		//archivePeriodically("host", 1*time.Hour)
		archivePeriodically("user", 24*time.Hour)
		archivePeriodically("answererCountry", 1*time.Hour)
		archivePeriodically("offererAnswererCountries", 1*time.Hour)
		archivePeriodically("operatingSystem", 1*time.Hour)
	} else {
		log.Printf("%s was not \"true\", not archiving to BigQuery", ARCHIVE_TO_BIGQUERY)
	}
}

func archivePeriodically(dim string, interval time.Duration) {
	go func() {
		for {
			nextInterval := time.Now().Truncate(interval).Add(interval)
			waitTime := nextInterval.Sub(time.Now())
			time.Sleep(waitTime)
			if err := archiveToBigQuery(dim, interval); err != nil {
				log.Printf("Unable to archive dimension %s to BigQuery: %s", dim, err)
			}
		}
	}()
}

func archiveToBigQuery(dim string, interval time.Duration) error {
	log.Printf("Archiving dim %s to BigQuery", dim)
	if statsByDim, err := statshub.QueryDims([]string{dim}); err != nil {
		return err
	} else {
		for dimName, dimStats := range statsByDim {
			if statsTable, err := NewStatsTable(bigquery.ProjectId, bigquery.DATASET_ID, dimName); err != nil {
				return err
			} else {
				return statsTable.WriteStats(dimStats, time.Now().Truncate(interval))
			}
		}
		return nil
	}
}
<commit_msg>Temporarily increased archive frequency for natty stats<commit_after>// Copyright 2014 Brave New Software

//    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 archive

import (
	"log"
	"os"
	"strings"
	"time"

	"github.com/getlantern/statshub/bigquery"
	"github.com/getlantern/statshub/statshub"
)

const (
	ARCHIVE_TO_BIGQUERY = "ARCHIVE_TO_BIGQUERY"
)

var (
	shouldArchive = strings.ToLower(os.Getenv(ARCHIVE_TO_BIGQUERY)) == "true"
)

// StartArchiving starts a goroutine that continuously archives data at regular intervals
// based on the archiveInterval constant.
func StartArchiving() {
	if shouldArchive {
		log.Printf("Archiving to BigQuery at %s", bigquery.ProjectId)
		archivePeriodically("fallback", 10*time.Minute)
		archivePeriodically("country", 1*time.Hour)
		//archivePeriodically("host", 1*time.Hour)
		archivePeriodically("user", 24*time.Hour)
		archivePeriodically("answererCountry", 10*time.Minute)
		archivePeriodically("offererAnswererCountries", 10*time.Minute)
		archivePeriodically("operatingSystem", 10*time.Minute)
	} else {
		log.Printf("%s was not \"true\", not archiving to BigQuery", ARCHIVE_TO_BIGQUERY)
	}
}

func archivePeriodically(dim string, interval time.Duration) {
	go func() {
		for {
			nextInterval := time.Now().Truncate(interval).Add(interval)
			waitTime := nextInterval.Sub(time.Now())
			time.Sleep(waitTime)
			if err := archiveToBigQuery(dim, interval); err != nil {
				log.Printf("Unable to archive dimension %s to BigQuery: %s", dim, err)
			}
		}
	}()
}

func archiveToBigQuery(dim string, interval time.Duration) error {
	log.Printf("Archiving dim %s to BigQuery", dim)
	if statsByDim, err := statshub.QueryDims([]string{dim}); err != nil {
		return err
	} else {
		for dimName, dimStats := range statsByDim {
			if statsTable, err := NewStatsTable(bigquery.ProjectId, bigquery.DATASET_ID, dimName); err != nil {
				return err
			} else {
				return statsTable.WriteStats(dimStats, time.Now().Truncate(interval))
			}
		}
		return nil
	}
}
<|endoftext|>


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

package errors

import (
	"fmt"
	"reflect"
	"time"
)

type Nature string

const (
	Structural     Nature = "Invalid structure"           // Requests, parameters or inputs are wrong. Retry won't work.
	Behavioural    Nature = "Wrong but expected behavior" // No error but the result isn't the one expected
	Operational    Nature = "Invalid operation"           // An operation failed due to external causes, a retry could work
	Implementation Nature = "Illegal call"                // Method not implemented or unsupported for the given structure
)

// Failure states for fault that occurs during a process.
type Failure struct {
	Nature    Nature    // Kind of error, used a comparator
	Timestamp time.Time // The moment the error was created
	Fault     error     // The source of the failure
}

// NewFailure creates a new Failure from a source error
func New(nat Nature, src interface{}) Failure {
	var fault error
	switch src.(type) {
	case string:
		fault = fmt.Errorf("%s", src.(string))
	case error:
		fault = src.(error)
	default:
		panic("Unexpected error source")
	}

	failure := Failure{
		Nature:    nat,
		Timestamp: time.Now(),
		Fault:     fault,
	}

	// Pop one level if we made a failure from a failure
	t := reflect.TypeOf(src)
	tf := reflect.TypeOf(failure)
	if t == tf {
		failure.Fault = src.(Failure).Fault
	}

	return failure
}

// Error implements the error built-in interface
func (err Failure) Error() string {
	if err.Fault == nil {
		return fmt.Sprintf("%s", err.Nature)
	}
	return fmt.Sprintf("%s: %s", err.Nature, err.Fault.Error())
}
<commit_msg>[refactor/errors] Introduce NotFound error Nature<commit_after>// Copyright © 2016 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package errors

import (
	"fmt"
	"reflect"
	"time"
)

type Nature string

const (
	Structural     Nature = "Invalid structure"        // Requests, parameters or inputs are wrong. Retry won't work.
	NotFound       Nature = "Unable to found entity"   // Failed to lookup something, somewhere
	Behavioural    Nature = "Wrong behavior or result" // No error but the result isn't the one expected
	Operational    Nature = "Invalid operation"        // An operation failed due to external causes, a retry could work
	Implementation Nature = "Illegal call"             // Method not implemented or unsupported for the given structure
)

// Failure states for fault that occurs during a process.
type Failure struct {
	Nature    Nature    // Kind of error, used a comparator
	Timestamp time.Time // The moment the error was created
	Fault     error     // The source of the failure
}

// NewFailure creates a new Failure from a source error
func New(nat Nature, src interface{}) Failure {
	var fault error
	switch src.(type) {
	case string:
		fault = fmt.Errorf("%s", src.(string))
	case error:
		fault = src.(error)
	default:
		panic("Unexpected error source")
	}

	failure := Failure{
		Nature:    nat,
		Timestamp: time.Now(),
		Fault:     fault,
	}

	// Pop one level if we made a failure from a failure
	t := reflect.TypeOf(src)
	tf := reflect.TypeOf(failure)
	if t == tf {
		failure.Fault = src.(Failure).Fault
	}

	return failure
}

// Error implements the error built-in interface
func (err Failure) Error() string {
	if err.Fault == nil {
		return fmt.Sprintf("%s", err.Nature)
	}
	return fmt.Sprintf("%s: %s", err.Nature, err.Fault.Error())
}
<|endoftext|>


<commit_before>package configuration

import (
	"testing"

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

func TestEnvironmentVariavels(t *testing.T) {
	// arrange
	conf := Config{}

	// act
	SetEnvironmentVariables(&conf)

	// assert
	assert.NotNil(t, conf, "Configuration should not be nil")
}
<commit_msg>unit testing package configuration 100% coverage<commit_after>package configuration

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"os"
)

func TestEnvironmentVariabels(t *testing.T) {
	// arrange
	conf := Config{}

	// act
	os.Setenv("gost_server_name","server")
	os.Setenv("gost_server_host","host")
	os.Setenv("gost_server_port","8080")
	os.Setenv("gost_server_external_uri","uri")
	os.Setenv("gost_client_content","client_content")
	os.Setenv("gost_server_max_entities","1")
	os.Setenv("gost_server_indent_json","true")
	os.Setenv("gost_server_https","false")
	os.Setenv("gost_server_https_key","key")
	os.Setenv("gost_server_https_cert","cert")
	os.Setenv("gost_mqtt_enabled","true")
	os.Setenv("gost_mqtt_host","mqtt_host")
	os.Setenv("gost_mqtt_port","9001")
	os.Setenv("gost_db_host","db_host")
	os.Setenv("gost_db_port","5432")
	os.Setenv("gost_db_user","db_user")
	os.Setenv("gost_db_password","db_password")
	os.Setenv("gost_db_database","db_database")
	os.Setenv("gost_db_schema","db_schema")
	os.Setenv("gost_mqtt_ssl_enabled","true")
	os.Setenv("gost_db_max_idle_cons","1")
	os.Setenv("gost_db_max_open_cons","1")

	SetEnvironmentVariables(&conf)

	// assert
	assert.NotNil(t, conf, "Configuration should not be nil")
}

<|endoftext|>


<commit_before>/*
 * Copyright 2020 Dgraph Labs, Inc. and Contributors
 *
 * 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 z

import (
	"encoding/binary"
	"fmt"
	"io"
	"os"
	"path"

	"github.com/pkg/errors"
)

// MmapFile represents an mmapd file and includes both the buffer to the data
// and the file descriptor.
type MmapFile struct {
	Data []byte
	Fd   *os.File
}

var NewFile = errors.New("Create a new file")

func OpenMmapFileUsing(fd *os.File, sz int, writable bool) (*MmapFile, error) {
	filename := fd.Name()
	fi, err := fd.Stat()
	if err != nil {
		return nil, errors.Wrapf(err, "cannot stat file: %s", filename)
	}

	var rerr error
	fileSize := fi.Size()
	if sz > 0 && fileSize == 0 {
		// If file is empty, truncate it to sz.
		if err := fd.Truncate(int64(sz)); err != nil {
			return nil, errors.Wrapf(err, "error while truncation")
		}
		fileSize = int64(sz)
		rerr = NewFile
	}

	// fmt.Printf("Mmaping file: %s with writable: %v filesize: %d\n", fd.Name(), writable, fileSize)
	buf, err := Mmap(fd, writable, fileSize) // Mmap up to file size.
	if err != nil {
		return nil, errors.Wrapf(err, "while mmapping %s with size: %d", fd.Name(), fileSize)
	}

	if fileSize == 0 {
		dir, _ := path.Split(filename)
		go SyncDir(dir)
	}
	return &MmapFile{
		Data: buf,
		Fd:   fd,
	}, rerr
}

// OpenMmapFile opens an existing file or creates a new file. If the file is
// created, it would truncate the file to maxSz. In both cases, it would mmap
// the file to maxSz and returned it. In case the file is created, z.NewFile is
// returned.
func OpenMmapFile(filename string, flag int, maxSz int) (*MmapFile, error) {
	// fmt.Printf("opening file %s with flag: %v\n", filename, flag)
	fd, err := os.OpenFile(filename, flag, 0666)
	if err != nil {
		return nil, errors.Wrapf(err, "unable to open: %s", filename)
	}
	writable := true
	if flag == os.O_RDONLY {
		writable = false
	}
	return OpenMmapFileUsing(fd, maxSz, writable)
}

type mmapReader struct {
	Data   []byte
	offset int
}

func (mr *mmapReader) Read(buf []byte) (int, error) {
	if mr.offset > len(mr.Data) {
		return 0, io.EOF
	}
	n := copy(buf, mr.Data[mr.offset:])
	mr.offset += n
	if n < len(buf) {
		return n, io.EOF
	}
	return n, nil
}

func (m *MmapFile) NewReader(offset int) io.Reader {
	return &mmapReader{
		Data:   m.Data,
		offset: offset,
	}
}

// Bytes returns data starting from offset off of size sz. If there's not enough data, it would
// return nil slice and io.EOF.
func (m *MmapFile) Bytes(off, sz int) ([]byte, error) {
	if len(m.Data[off:]) < sz {
		return nil, io.EOF
	}
	return m.Data[off : off+sz], nil
}

// Slice returns the slice at the given offset.
func (m *MmapFile) Slice(offset int) []byte {
	sz := binary.BigEndian.Uint32(m.Data[offset:])
	start := offset + 4
	next := start + int(sz)
	if next > len(m.Data) {
		return []byte{}
	}
	res := m.Data[start:next]
	return res
}

// AllocateSlice allocates a slice of the given size at the given offset.
func (m *MmapFile) AllocateSlice(sz, offset int) ([]byte, int, error) {
	start := offset + 4

	// If the file is too small, double its size or increase it by 1GB, whichever is smaller.
	if start+sz > len(m.Data) {
		const oneGB = 1 << 30
		growBy := len(m.Data)
		if growBy > oneGB {
			growBy = oneGB
		}
		if growBy < sz+4 {
			growBy = sz + 4
		}
		if err := m.Truncate(int64(len(m.Data) + growBy)); err != nil {
			return nil, 0, err
		}
	}

	binary.BigEndian.PutUint32(m.Data[offset:], uint32(sz))
	return m.Data[start : start+sz], start + sz, nil
}

func (m *MmapFile) Sync() error {
	if m == nil {
		return nil
	}
	return Msync(m.Data)
}

func (m *MmapFile) Delete() error {
	// Badger can set the m.Data directly, without setting any Fd. In that case, this should be a
	// NOOP.
	if m.Fd == nil {
		return nil
	}

	if err := Munmap(m.Data); err != nil {
		return fmt.Errorf("while munmap file: %s, error: %v\n", m.Fd.Name(), err)
	}
	m.Data = nil
	if err := m.Fd.Truncate(0); err != nil {
		return fmt.Errorf("while truncate file: %s, error: %v\n", m.Fd.Name(), err)
	}
	return os.Remove(m.Fd.Name())
}

// Close would close the file. It would also truncate the file if maxSz >= 0.
func (m *MmapFile) Close(maxSz int64) error {
	// Badger can set the m.Data directly, without setting any Fd. In that case, this should be a
	// NOOP.
	if m.Fd == nil {
		return nil
	}
	if err := m.Sync(); err != nil {
		return fmt.Errorf("while sync file: %s, error: %v\n", m.Fd.Name(), err)
	}
	if err := Munmap(m.Data); err != nil {
		return fmt.Errorf("while munmap file: %s, error: %v\n", m.Fd.Name(), err)
	}
	if maxSz >= 0 {
		if err := m.Fd.Truncate(maxSz); err != nil {
			return fmt.Errorf("while truncate file: %s, error: %v\n", m.Fd.Name(), err)
		}
	}
	return m.Fd.Close()
}

func SyncDir(dir string) error {
	df, err := os.Open(dir)
	if err != nil {
		return errors.Wrapf(err, "while opening %s", dir)
	}
	if err := df.Sync(); err != nil {
		return errors.Wrapf(err, "while syncing %s", dir)
	}
	if err := df.Close(); err != nil {
		return errors.Wrapf(err, "while closing %s", dir)
	}
	return nil
}
<commit_msg>fix(MmapFile): Close the fd before deleting the file (#242)<commit_after>/*
 * Copyright 2020 Dgraph Labs, Inc. and Contributors
 *
 * 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 z

import (
	"encoding/binary"
	"fmt"
	"io"
	"os"
	"path"

	"github.com/pkg/errors"
)

// MmapFile represents an mmapd file and includes both the buffer to the data
// and the file descriptor.
type MmapFile struct {
	Data []byte
	Fd   *os.File
}

var NewFile = errors.New("Create a new file")

func OpenMmapFileUsing(fd *os.File, sz int, writable bool) (*MmapFile, error) {
	filename := fd.Name()
	fi, err := fd.Stat()
	if err != nil {
		return nil, errors.Wrapf(err, "cannot stat file: %s", filename)
	}

	var rerr error
	fileSize := fi.Size()
	if sz > 0 && fileSize == 0 {
		// If file is empty, truncate it to sz.
		if err := fd.Truncate(int64(sz)); err != nil {
			return nil, errors.Wrapf(err, "error while truncation")
		}
		fileSize = int64(sz)
		rerr = NewFile
	}

	// fmt.Printf("Mmaping file: %s with writable: %v filesize: %d\n", fd.Name(), writable, fileSize)
	buf, err := Mmap(fd, writable, fileSize) // Mmap up to file size.
	if err != nil {
		return nil, errors.Wrapf(err, "while mmapping %s with size: %d", fd.Name(), fileSize)
	}

	if fileSize == 0 {
		dir, _ := path.Split(filename)
		go SyncDir(dir)
	}
	return &MmapFile{
		Data: buf,
		Fd:   fd,
	}, rerr
}

// OpenMmapFile opens an existing file or creates a new file. If the file is
// created, it would truncate the file to maxSz. In both cases, it would mmap
// the file to maxSz and returned it. In case the file is created, z.NewFile is
// returned.
func OpenMmapFile(filename string, flag int, maxSz int) (*MmapFile, error) {
	// fmt.Printf("opening file %s with flag: %v\n", filename, flag)
	fd, err := os.OpenFile(filename, flag, 0666)
	if err != nil {
		return nil, errors.Wrapf(err, "unable to open: %s", filename)
	}
	writable := true
	if flag == os.O_RDONLY {
		writable = false
	}
	return OpenMmapFileUsing(fd, maxSz, writable)
}

type mmapReader struct {
	Data   []byte
	offset int
}

func (mr *mmapReader) Read(buf []byte) (int, error) {
	if mr.offset > len(mr.Data) {
		return 0, io.EOF
	}
	n := copy(buf, mr.Data[mr.offset:])
	mr.offset += n
	if n < len(buf) {
		return n, io.EOF
	}
	return n, nil
}

func (m *MmapFile) NewReader(offset int) io.Reader {
	return &mmapReader{
		Data:   m.Data,
		offset: offset,
	}
}

// Bytes returns data starting from offset off of size sz. If there's not enough data, it would
// return nil slice and io.EOF.
func (m *MmapFile) Bytes(off, sz int) ([]byte, error) {
	if len(m.Data[off:]) < sz {
		return nil, io.EOF
	}
	return m.Data[off : off+sz], nil
}

// Slice returns the slice at the given offset.
func (m *MmapFile) Slice(offset int) []byte {
	sz := binary.BigEndian.Uint32(m.Data[offset:])
	start := offset + 4
	next := start + int(sz)
	if next > len(m.Data) {
		return []byte{}
	}
	res := m.Data[start:next]
	return res
}

// AllocateSlice allocates a slice of the given size at the given offset.
func (m *MmapFile) AllocateSlice(sz, offset int) ([]byte, int, error) {
	start := offset + 4

	// If the file is too small, double its size or increase it by 1GB, whichever is smaller.
	if start+sz > len(m.Data) {
		const oneGB = 1 << 30
		growBy := len(m.Data)
		if growBy > oneGB {
			growBy = oneGB
		}
		if growBy < sz+4 {
			growBy = sz + 4
		}
		if err := m.Truncate(int64(len(m.Data) + growBy)); err != nil {
			return nil, 0, err
		}
	}

	binary.BigEndian.PutUint32(m.Data[offset:], uint32(sz))
	return m.Data[start : start+sz], start + sz, nil
}

func (m *MmapFile) Sync() error {
	if m == nil {
		return nil
	}
	return Msync(m.Data)
}

func (m *MmapFile) Delete() error {
	// Badger can set the m.Data directly, without setting any Fd. In that case, this should be a
	// NOOP.
	if m.Fd == nil {
		return nil
	}

	if err := Munmap(m.Data); err != nil {
		return fmt.Errorf("while munmap file: %s, error: %v\n", m.Fd.Name(), err)
	}
	m.Data = nil
	if err := m.Fd.Truncate(0); err != nil {
		return fmt.Errorf("while truncate file: %s, error: %v\n", m.Fd.Name(), err)
	}
	if err := m.Fd.Close(); err != nil {
		return fmt.Errorf("while close file: %s, error: %v\n", m.Fd.Name(), err)
	}
	return os.Remove(m.Fd.Name())
}

// Close would close the file. It would also truncate the file if maxSz >= 0.
func (m *MmapFile) Close(maxSz int64) error {
	// Badger can set the m.Data directly, without setting any Fd. In that case, this should be a
	// NOOP.
	if m.Fd == nil {
		return nil
	}
	if err := m.Sync(); err != nil {
		return fmt.Errorf("while sync file: %s, error: %v\n", m.Fd.Name(), err)
	}
	if err := Munmap(m.Data); err != nil {
		return fmt.Errorf("while munmap file: %s, error: %v\n", m.Fd.Name(), err)
	}
	if maxSz >= 0 {
		if err := m.Fd.Truncate(maxSz); err != nil {
			return fmt.Errorf("while truncate file: %s, error: %v\n", m.Fd.Name(), err)
		}
	}
	return m.Fd.Close()
}

func SyncDir(dir string) error {
	df, err := os.Open(dir)
	if err != nil {
		return errors.Wrapf(err, "while opening %s", dir)
	}
	if err := df.Sync(); err != nil {
		return errors.Wrapf(err, "while syncing %s", dir)
	}
	if err := df.Close(); err != nil {
		return errors.Wrapf(err, "while closing %s", dir)
	}
	return nil
}
<|endoftext|>