<commit_before>/*
 * Copyright (c) 2014 Michael Wendland
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 *
 * 	Authors:
 * 		Michael Wendland <michael@michiwend.com>
 */

/*
Package gomusicbrainz implements a MusicBrainz WS2 client library.

MusicBrainz WS2 (Version 2 of the XML Web Service) supports three different requests:

Search requests

With search requests you can search MusicBrainz´ database for all entities.
GoMusicBrainz implements one search method for every search request in the form:

	func (*WS2Client) Search<TYPE>(searchTerm, limit, offset) (Response<TYPE>, error)

searchTerm follows the Apache Lucene syntax and can either contain multiple
fields with logical operators or just a simple search string. Please refer to
https://lucene.apache.org/core/4_3_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#package_description
for more details on the lucene syntax. limit defines how many entries should be
returned (1-100, default 25). offset is used for paging through more than one
page of results. To ignore limit and/or offset, set it to -1.

Lookup requests

TODO

Browse requets

TODO

*/
package gomusicbrainz

import (
	"encoding/xml"
	"log"
	"net/http"
	"net/url"
	"strconv"
)

// NewWS2Client returns a new instance of WS2Client with default values.
func NewWS2Client() *WS2Client {
	c := WS2Client{}

	c.WS2RootURL, _ = url.Parse("https://musicbrainz.org/ws/2")

	// Provide meaningful User-Agent informations.
	c.SetClientInfo(
		"GoMusicBrainz - a Golang WS2 client",
		"0.0.1-beta",
		"michael@michiwend.com",
	)

	return &c
}

// WS2Client defines a Go client for the MusicBrainz Web Service 2.
type WS2Client struct {
	WS2RootURL *url.URL // The API root URL

	userAgentHeader string
}

func (c *WS2Client) getReqeust(data interface{}, params url.Values, endpoint string) error {

	client := &http.Client{}

	req, err := http.NewRequest("GET", c.WS2RootURL.String()+endpoint+"?"+params.Encode(), nil)
	if err != nil {
		log.Fatalln(err)
	}

	req.Header.Set("User-Agent", c.userAgentHeader)

	resp, err := client.Do(req)
	if err != nil {
		log.Fatalln(err)
	}
	defer resp.Body.Close()

	decoder := xml.NewDecoder(resp.Body)

	if err = decoder.Decode(data); err != nil {
		return err
	}
	return nil
}

// intParamToString returns an empty string for -1.
func intParamToString(i int) string {
	if i == -1 {
		return ""
	}
	return strconv.Itoa(i)
}

func (c *WS2Client) searchRequest(endpoint string, result interface{}, searchTerm string, limit int, offset int) error {

	params := url.Values{
		"query":  {searchTerm},
		"limit":  {intParamToString(limit)},
		"offset": {intParamToString(offset)},
	}

	if err := c.getReqeust(result, params, endpoint); err != nil {
		return err
	}

	return nil
}

// SetRootURL sets the root URL for WS2.
func (c *WS2Client) SetRootURL(rooturl string) error {
	var err error
	c.WS2RootURL, err = url.Parse(rooturl)
	return err
}

// SetClientInfo sets the HTTP user-agent header of the WS2Client. Please
// provide meaningful information about your application as described at
// https://musicbrainz.org/doc/XML_Web_Service/Rate_Limiting#Provide_meaningful_User-Agent_strings
func (c *WS2Client) SetClientInfo(application string, version string, contact string) {
	c.userAgentHeader = application + "/" + version + " ( " + contact + " ) "
}

// SearchAnnotation queries MusicBrainz´ Search Server for Annotations.
// With no fields specified searchTerm searches TODO. For a list of all valid
// search fields visit
// http://musicbrainz.org/doc/Development/XML_Web_Service/Version_2/Search#Annotation
func (c *WS2Client) SearchAnnotation(searchTerm string, limit int, offset int) (*AnnotationResponse, error) {

	var result struct {
		Response AnnotationResponse `xml:"annotation-list"`
	}

	err := c.searchRequest("/annotation", &result, searchTerm, limit, offset)

	return &result.Response, err
}

// SearchArea queries MusicBrainz´ Search Server for Areas.
// With no fields specified searchTerm searches the area and sortname fields.
// For a list of all valid search fields visit
// http://musicbrainz.org/doc/Development/XML_Web_Service/Version_2/Search#Area
func (c *WS2Client) SearchArea(searchTerm string, limit int, offset int) (*AreaResponse, error) {

	var result struct {
		Response AreaResponse `xml:"area-list"`
	}

	err := c.searchRequest("/area", &result, searchTerm, limit, offset)

	return &result.Response, err
}

// SearchArtist queries MusicBrainz´ Search Server for Artists.
// With no fields specified searchTerm searches the artist, sortname and alias
// fields. For a list of all valid fields visit
// http://musicbrainz.org/doc/Development/XML_Web_Service/Version_2/Search#Artist
func (c *WS2Client) SearchArtist(searchTerm string, limit int, offset int) (*ArtistResponse, error) {

	var result struct {
		Response ArtistResponse `xml:"artist-list"`
	}

	err := c.searchRequest("/artist", &result, searchTerm, limit, offset)

	return &result.Response, err
}

// SearchRelease queries MusicBrainz´ Search Server for Releases.
// With no fields specified searchTerm searches the release field only. For a
// list of all valid fields visit
// https://musicbrainz.org/doc/Development/XML_Web_Service/Version_2/Search#Release
func (c *WS2Client) SearchRelease(searchTerm string, limit int, offset int) (*ReleaseResponse, error) {

	var result struct {
		Response ReleaseResponse `xml:"release-list"`
	}

	err := c.searchRequest("/release", &result, searchTerm, limit, offset)

	return &result.Response, err
}

// SearchReleaseGroup queries MusicBrainz´ Search Server for ReleaseGroups.
// With no fields specified searchTerm searches the releasgroup field only. For
// a list of all valid fields visit
// https://musicbrainz.org/doc/Development/XML_Web_Service/Version_2/Search#Release_Group
func (c *WS2Client) SearchReleaseGroup(searchTerm string, limit int, offset int) (*ReleaseGroupResponse, error) {

	var result struct {
		Response ReleaseGroupResponse `xml:"release-group-list"`
	}

	err := c.searchRequest("/release-group", &result, searchTerm, limit, offset)

	return &result.Response, err
}

// SearchTag queries MusicBrainz' Search Server for Tags.
// searchTerm only contains the tag field. For more information visit
// https://musicbrainz.org/doc/Development/XML_Web_Service/Version_2/Search#Tag
func (c *WS2Client) SearchTag(searchTerm string, limit int, offset int) (*TagResponse, error) {

	var result struct {
		Response TagResponse `xml:"tag-list"`
	}

	err := c.searchRequest("/tag", &result, searchTerm, limit, offset)

	return &result.Response, err
}

func (c *WS2Client) SearchCDStubs(searchTerm string, limit int, offset int) (*CDStubsResponse, error) {
	//TODO implement
	return nil, nil
}
func (c *WS2Client) SearchFreedb(searchTerm string, limit int, offset int) (*FreedbResponse, error) {
	//TODO implement
	return nil, nil
}
func (c *WS2Client) SearchLabel(searchTerm string, limit int, offset int) (*LabelResponse, error) {
	//TODO implement
	return nil, nil
}
func (c *WS2Client) SearchPlace(searchTerm string, limit int, offset int) (*PlaceResponse, error) {
	//TODO implement
	return nil, nil
}
func (c *WS2Client) SearchRecording(searchTerm string, limit int, offset int) (*RecordingResponse, error) {
	//TODO implement
	return nil, nil
}
func (c *WS2Client) SearchWork(searchTerm string, limit int, offset int) (*WorkResponse, error) {
	//TODO implement
	return nil, nil
}
<commit_msg>more compact method stubs<commit_after>/*
 * Copyright (c) 2014 Michael Wendland
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 *
 * 	Authors:
 * 		Michael Wendland <michael@michiwend.com>
 */

/*
Package gomusicbrainz implements a MusicBrainz WS2 client library.

MusicBrainz WS2 (Version 2 of the XML Web Service) supports three different requests:

Search requests

With search requests you can search MusicBrainz´ database for all entities.
GoMusicBrainz implements one search method for every search request in the form:

	func (*WS2Client) Search<TYPE>(searchTerm, limit, offset) (Response<TYPE>, error)

searchTerm follows the Apache Lucene syntax and can either contain multiple
fields with logical operators or just a simple search string. Please refer to
https://lucene.apache.org/core/4_3_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#package_description
for more details on the lucene syntax. limit defines how many entries should be
returned (1-100, default 25). offset is used for paging through more than one
page of results. To ignore limit and/or offset, set it to -1.

Lookup requests

TODO

Browse requets

TODO

*/
package gomusicbrainz

import (
	"encoding/xml"
	"log"
	"net/http"
	"net/url"
	"strconv"
)

// NewWS2Client returns a new instance of WS2Client with default values.
func NewWS2Client() *WS2Client {
	c := WS2Client{}

	c.WS2RootURL, _ = url.Parse("https://musicbrainz.org/ws/2")

	// Provide meaningful User-Agent informations.
	c.SetClientInfo(
		"GoMusicBrainz - a Golang WS2 client",
		"0.0.1-beta",
		"michael@michiwend.com",
	)

	return &c
}

// WS2Client defines a Go client for the MusicBrainz Web Service 2.
type WS2Client struct {
	WS2RootURL *url.URL // The API root URL

	userAgentHeader string
}

func (c *WS2Client) getReqeust(data interface{}, params url.Values, endpoint string) error {

	client := &http.Client{}

	req, err := http.NewRequest("GET", c.WS2RootURL.String()+endpoint+"?"+params.Encode(), nil)
	if err != nil {
		log.Fatalln(err)
	}

	req.Header.Set("User-Agent", c.userAgentHeader)

	resp, err := client.Do(req)
	if err != nil {
		log.Fatalln(err)
	}
	defer resp.Body.Close()

	decoder := xml.NewDecoder(resp.Body)

	if err = decoder.Decode(data); err != nil {
		return err
	}
	return nil
}

// intParamToString returns an empty string for -1.
func intParamToString(i int) string {
	if i == -1 {
		return ""
	}
	return strconv.Itoa(i)
}

func (c *WS2Client) searchRequest(endpoint string, result interface{}, searchTerm string, limit, offset int) error {

	params := url.Values{
		"query":  {searchTerm},
		"limit":  {intParamToString(limit)},
		"offset": {intParamToString(offset)},
	}

	if err := c.getReqeust(result, params, endpoint); err != nil {
		return err
	}

	return nil
}

// SetRootURL sets the root URL for WS2.
func (c *WS2Client) SetRootURL(rooturl string) error {
	var err error
	c.WS2RootURL, err = url.Parse(rooturl)
	return err
}

// SetClientInfo sets the HTTP user-agent header of the WS2Client. Please
// provide meaningful information about your application as described at
// https://musicbrainz.org/doc/XML_Web_Service/Rate_Limiting#Provide_meaningful_User-Agent_strings
func (c *WS2Client) SetClientInfo(application string, version string, contact string) {
	c.userAgentHeader = application + "/" + version + " ( " + contact + " ) "
}

// SearchAnnotation queries MusicBrainz´ Search Server for Annotations.
// With no fields specified searchTerm searches TODO. For a list of all valid
// search fields visit
// http://musicbrainz.org/doc/Development/XML_Web_Service/Version_2/Search#Annotation
func (c *WS2Client) SearchAnnotation(searchTerm string, limit, offset int) (*AnnotationResponse, error) {

	var result struct {
		Response AnnotationResponse `xml:"annotation-list"`
	}

	err := c.searchRequest("/annotation", &result, searchTerm, limit, offset)

	return &result.Response, err
}

// SearchArea queries MusicBrainz´ Search Server for Areas.
// With no fields specified searchTerm searches the area and sortname fields.
// For a list of all valid search fields visit
// http://musicbrainz.org/doc/Development/XML_Web_Service/Version_2/Search#Area
func (c *WS2Client) SearchArea(searchTerm string, limit, offset int) (*AreaResponse, error) {

	var result struct {
		Response AreaResponse `xml:"area-list"`
	}

	err := c.searchRequest("/area", &result, searchTerm, limit, offset)

	return &result.Response, err
}

// SearchArtist queries MusicBrainz´ Search Server for Artists.
// With no fields specified searchTerm searches the artist, sortname and alias
// fields. For a list of all valid fields visit
// http://musicbrainz.org/doc/Development/XML_Web_Service/Version_2/Search#Artist
func (c *WS2Client) SearchArtist(searchTerm string, limit, offset int) (*ArtistResponse, error) {

	var result struct {
		Response ArtistResponse `xml:"artist-list"`
	}

	err := c.searchRequest("/artist", &result, searchTerm, limit, offset)

	return &result.Response, err
}

// SearchRelease queries MusicBrainz´ Search Server for Releases.
// With no fields specified searchTerm searches the release field only. For a
// list of all valid fields visit
// https://musicbrainz.org/doc/Development/XML_Web_Service/Version_2/Search#Release
func (c *WS2Client) SearchRelease(searchTerm string, limit, offset int) (*ReleaseResponse, error) {

	var result struct {
		Response ReleaseResponse `xml:"release-list"`
	}

	err := c.searchRequest("/release", &result, searchTerm, limit, offset)

	return &result.Response, err
}

// SearchReleaseGroup queries MusicBrainz´ Search Server for ReleaseGroups.
// With no fields specified searchTerm searches the releasgroup field only. For
// a list of all valid fields visit
// https://musicbrainz.org/doc/Development/XML_Web_Service/Version_2/Search#Release_Group
func (c *WS2Client) SearchReleaseGroup(searchTerm string, limit, offset int) (*ReleaseGroupResponse, error) {

	var result struct {
		Response ReleaseGroupResponse `xml:"release-group-list"`
	}

	err := c.searchRequest("/release-group", &result, searchTerm, limit, offset)

	return &result.Response, err
}

// SearchTag queries MusicBrainz' Search Server for Tags.
// searchTerm only contains the tag field. For more information visit
// https://musicbrainz.org/doc/Development/XML_Web_Service/Version_2/Search#Tag
func (c *WS2Client) SearchTag(searchTerm string, limit, offset int) (*TagResponse, error) {

	var result struct {
		Response TagResponse `xml:"tag-list"`
	}

	err := c.searchRequest("/tag", &result, searchTerm, limit, offset)

	return &result.Response, err
}

func (c *WS2Client) SearchCDStubs(searchTerm string, limit, offset int) (*CDStubsResponse, error) {
	//TODO implement
	return nil, nil
}
func (c *WS2Client) SearchFreedb(searchTerm string, limit, offset int) (*FreedbResponse, error) {
	//TODO implement
	return nil, nil
}
func (c *WS2Client) SearchLabel(searchTerm string, limit, offset int) (*LabelResponse, error) {
	//TODO implement
	return nil, nil
}
func (c *WS2Client) SearchPlace(searchTerm string, limit, offset int) (*PlaceResponse, error) {
	//TODO implement
	return nil, nil
}
func (c *WS2Client) SearchRecording(searchTerm string, limit, offset int) (*RecordingResponse, error) {
	//TODO implement
	return nil, nil
}
func (c *WS2Client) SearchWork(searchTerm string, limit, offset int) (*WorkResponse, error) {
	//TODO implement
	return nil, nil
}
<|endoftext|>


<commit_before>package main

import (
	c "github.com/dlapiduz/govcode.org/common"
	"github.com/go-martini/martini"
	"github.com/martini-contrib/cors"
	"github.com/martini-contrib/render"
)

func main() {
	m := App()
	m.Run()
}

func App() *martini.ClassicMartini {
	m := martini.Classic()

	m.Use(render.Renderer(render.Options{
		Directory: "templates",
	}))

	m.Use(cors.Allow(&cors.Options{
		AllowOrigins: []string{"*"},
	}))

	m.Group("/repos", func(r martini.Router) {
		r.Get("", ReposIndex)
		r.Get("/:name", ReposShow)
	})

	m.Group("/orgs", func(r martini.Router) {
		r.Get("", OrgsIndex)
		r.Get("/:id", OrgsShow)
	})

	m.Group("/users", func(r martini.Router) {
		r.Get("", UserIndex)
		r.Get("/:id", UserShow)
	})

	return m
}

func ReposIndex(r render.Render) {
	var results []c.Repository
	rows := c.DB.Table("repositories")
	rows = rows.Select(`repositories.*, organizations.login as organization_login,
		date_part('day', now() - last_pull) as days_since_pull,
		date_part('day', now() - last_commit) as days_since_commit
		`)
	rows = rows.Joins("inner join organizations on organizations.id = repositories.organization_id")
	rows.Scan(&results)

	r.JSON(200, results)
}

func ReposShow(r render.Render, params martini.Params) {

	var repo c.Repository
	c.DB.Where("name = ?", params["name"]).First(&repo)
	c.DB.Model(&repo).Related(&repo.Organization)
	c.DB.Model(&repo).Related(&repo.RepoStat)

	r.JSON(200, repo)
}

func OrgsIndex(r render.Render) {
	var results []c.Organization
	c.DB.Find(&results)

	r.JSON(200, results)
}

func OrgsShow(r render.Render, params martini.Params) {
	var result c.Organization
	c.DB.Where("id = ?", params["id"]).First(&result)

	r.JSON(200, result)
}

func UserIndex(r render.Render) {
	var results []c.User
	c.DB.Find(&results)

	r.JSON(200, results)
}

func UserShow(r render.Render, params martini.Params) {
	var result c.User
	c.DB.Where("id = ?", params["id"]).First(&result)

	r.JSON(200, result)
}
<commit_msg>Add stats endpoint and use gzip<commit_after>package main

import (
	c "github.com/dlapiduz/govcode.org/common"
	"github.com/go-martini/martini"
	"github.com/martini-contrib/cors"
	"github.com/martini-contrib/gzip"
	"github.com/martini-contrib/render"
	"time"
)

func main() {
	m := App()
	m.Run()
}

func App() *martini.ClassicMartini {
	m := martini.Classic()

	m.Use(gzip.All())

	m.Use(render.Renderer(render.Options{
		Directory: "templates",
	}))

	m.Use(cors.Allow(&cors.Options{
		AllowAllOrigins: true,
	}))

	m.Group("/repos", func(r martini.Router) {
		r.Get("", ReposIndex)
		r.Get("/:name", ReposShow)
	})

	m.Group("/orgs", func(r martini.Router) {
		r.Get("", OrgsIndex)
		r.Get("/:id", OrgsShow)
	})

	m.Group("/users", func(r martini.Router) {
		r.Get("", UserIndex)
		r.Get("/:id", UserShow)
	})

	m.Get("/stats", StatsIndex)

	return m
}

func ReposIndex(r render.Render) {
	var results []c.Repository
	rows := c.DB.Table("repositories")
	rows = rows.Select(`repositories.*, organizations.login as organization_login,
		date_part('day', now() - last_pull) as days_since_pull,
		date_part('day', now() - last_commit) as days_since_commit
		`)
	rows = rows.Joins("inner join organizations on organizations.id = repositories.organization_id")
	rows.Scan(&results)

	r.JSON(200, results)
}

func ReposShow(r render.Render, params martini.Params) {

	var repo c.Repository
	c.DB.Where("name = ?", params["name"]).First(&repo)
	c.DB.Model(&repo).Related(&repo.Organization)
	c.DB.Model(&repo).Related(&repo.RepoStat)

	r.JSON(200, repo)
}

func OrgsIndex(r render.Render) {
	var results []c.Organization
	c.DB.Find(&results)

	r.JSON(200, results)
}

func OrgsShow(r render.Render, params martini.Params) {
	var result c.Organization
	c.DB.Where("id = ?", params["id"]).First(&result)

	r.JSON(200, result)
}

func UserIndex(r render.Render) {
	var results []c.User
	c.DB.Find(&results)

	r.JSON(200, results)
}

func UserShow(r render.Render, params martini.Params) {
	var result c.User
	c.DB.Where("id = ?", params["id"]).First(&result)

	r.JSON(200, result)
}

func StatsIndex(r render.Render) {
	// Get the repo counts per org
	type repoCount struct {
		OrganizationLogin string
		RepoCount         int64
	}
	var repo_counts []repoCount
	rows := c.DB.Table("repositories")
	rows = rows.Select(`organizations.login as organization_login,
		count(repositories.name) as repo_count
		`)
	rows = rows.Joins("inner join organizations on organizations.id = repositories.organization_id")
	rows = rows.Group("organizations.login")
	rows = rows.Order("repo_count desc")
	rows.Scan(&repo_counts)

	// Get commit stats per org per month for the past year
	type orgStat struct {
		OrganizationLogin string
		Week              time.Time
		Month             string
		Add               int64
		Del               int64
		Commits           int64
	}
	var org_stats []orgStat
	rows = c.DB.Debug().Table("repo_stats")
	rows = rows.Select(`organizations.login as organization_login,
		min(repo_stats.week) as week,
		TO_CHAR(repo_stats.week, 'Mon YYYY') as month,
		sum(repo_stats.add) as add,
		sum(repo_stats.del) as del,
		sum(repo_stats.commits) as commits
	`)
	rows = rows.Joins(`inner join repositories on repositories.id = repo_stats.repository_id
		inner join organizations on organizations.id = repositories.organization_id
	`)
	rows = rows.Where("repo_stats.week > now()::date - 365")
	rows = rows.Group("organizations.login, month")
	rows = rows.Order("week")
	rows.Scan(&org_stats)

	var result map[string]interface{}
	result = make(map[string]interface{})

	result["repo_counts"] = repo_counts
	result["org_stats"] = org_stats

	r.JSON(200, result)
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The xridge kubestone 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 e2e

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/xridge/kubestone/api/v1alpha1"
	appsv1 "k8s.io/api/apps/v1"
	batchv1 "k8s.io/api/batch/v1"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/types"
)

const (
	iperf3SampleCR     = samplesDir + "/perf_v1alpha1_iperf3.yaml"
	e2eNamespaceIperf3 = "kubestone-e2e-iperf3"
)

var _ = Describe("end to end test", func() {
	Context("preparing namespace", func() {
		_, _, err := run("kubectl create namespace " + e2eNamespaceIperf3)
		It("should succeed", func() {
			Expect(err).To(BeNil())
		})
	})

	Describe("for iperf3", func() {
		Context("creation from samples", func() {
			_, _, err := run("kubectl create -n " + e2eNamespaceIperf3 + " -f " + iperf3SampleCR)
			It("should create iperf3-sample cr", func() {
				Expect(err).To(BeNil())
			})
		})

		Context("created job", func() {
			It("Should finish in a pre-defined time", func() {
				timeout := 60
				cr := &v1alpha1.Iperf3{}
				// TODO: find the respective objects via the CR owner reference
				namespacedName := types.NamespacedName{
					Namespace: e2eNamespaceIperf3,
					Name:      "iperf3-sample",
				}
				Eventually(func() bool {
					if err := client.Get(ctx, namespacedName, cr); err != nil {
						Fail("Unable to get iperf3 CR")
					}
					return (cr.Status.Running == false) && (cr.Status.Completed)
				}, timeout).Should(BeTrue())
			})
			It("Should leave a successful job", func() {
				pod := &batchv1.Job{}
				namespacedName := types.NamespacedName{
					Namespace: e2eNamespaceSysbench,
					Name:      "iperf3-sample-client",
				}
				Expect(client.Get(ctx, namespacedName, pod)).To(Succeed())
				Expect(pod.Status.Succeeded).To(Equal(int32(1)))
			})
			It("Should not leave deployment", func() {
				deployment := &appsv1.Deployment{}
				namespacedName := types.NamespacedName{
					Namespace: e2eNamespaceIperf3,
					Name:      "iperf3-sample",
				}
				Expect(client.Get(ctx, namespacedName, deployment)).NotTo(Succeed())
			})
			It("Should not leave service", func() {
				service := &corev1.Service{}
				namespacedName := types.NamespacedName{
					Namespace: e2eNamespaceIperf3,
					Name:      "iperf3-sample",
				}
				Expect(client.Get(ctx, namespacedName, service)).NotTo(Succeed())
			})
		})
	})
})
<commit_msg>TST: Fix e2e testcase for iperf3 (2)<commit_after>/*
Copyright 2019 The xridge kubestone 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 e2e

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/xridge/kubestone/api/v1alpha1"
	appsv1 "k8s.io/api/apps/v1"
	batchv1 "k8s.io/api/batch/v1"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/types"
)

const (
	iperf3SampleCR     = samplesDir + "/perf_v1alpha1_iperf3.yaml"
	e2eNamespaceIperf3 = "kubestone-e2e-iperf3"
)

var _ = Describe("end to end test", func() {
	Context("preparing namespace", func() {
		_, _, err := run("kubectl create namespace " + e2eNamespaceIperf3)
		It("should succeed", func() {
			Expect(err).To(BeNil())
		})
	})

	Describe("for iperf3", func() {
		Context("creation from samples", func() {
			_, _, err := run("kubectl create -n " + e2eNamespaceIperf3 + " -f " + iperf3SampleCR)
			It("should create iperf3-sample cr", func() {
				Expect(err).To(BeNil())
			})
		})

		Context("created job", func() {
			It("Should finish in a pre-defined time", func() {
				timeout := 60
				cr := &v1alpha1.Iperf3{}
				// TODO: find the respective objects via the CR owner reference
				namespacedName := types.NamespacedName{
					Namespace: e2eNamespaceIperf3,
					Name:      "iperf3-sample",
				}
				Eventually(func() bool {
					if err := client.Get(ctx, namespacedName, cr); err != nil {
						Fail("Unable to get iperf3 CR")
					}
					return (cr.Status.Running == false) && (cr.Status.Completed)
				}, timeout).Should(BeTrue())
			})
			It("Should leave a successful job", func() {
				pod := &batchv1.Job{}
				namespacedName := types.NamespacedName{
					Namespace: e2eNamespaceIperf3,
					Name:      "iperf3-sample-client",
				}
				Expect(client.Get(ctx, namespacedName, pod)).To(Succeed())
				Expect(pod.Status.Succeeded).To(Equal(int32(1)))
			})
			It("Should not leave deployment", func() {
				deployment := &appsv1.Deployment{}
				namespacedName := types.NamespacedName{
					Namespace: e2eNamespaceIperf3,
					Name:      "iperf3-sample",
				}
				Expect(client.Get(ctx, namespacedName, deployment)).NotTo(Succeed())
			})
			It("Should not leave service", func() {
				service := &corev1.Service{}
				namespacedName := types.NamespacedName{
					Namespace: e2eNamespaceIperf3,
					Name:      "iperf3-sample",
				}
				Expect(client.Get(ctx, namespacedName, service)).NotTo(Succeed())
			})
		})
	})
})
<|endoftext|>


<commit_before>package util

import (
	"fmt"
	"os"
)

func (u *SomaUtil) AbortOnError(err error, txt ...string) {
	if err != nil {
		for _, s := range txt {
			fmt.Fprintf(os.Stderr, "%s\n", s)
			u.Log.Print(s)
		}
		fmt.Fprintf(os.Stderr, "%s\n", err.Error())
		u.Log.Fatal(err)
	}
}

func (u *SomaUtil) Abort(txt ...string) {
	for _, s := range txt {
		fmt.Fprintf(os.Stderr, "%s\n", s)
		u.Log.Print(s)
	}

	// ensure there is _something_
	if len(txt) == 0 {
		e := `abort called without error message. Sorry!`
		fmt.Fprintf(os.Stderr, "%s\n", e)
		u.Log.Print(e)
	}
	os.Exit(1)
}

// vim: ts=4 sw=4 sts=4 noet fenc=utf-8 ffs=unix
<commit_msg>Add NotImplemented() utility function<commit_after>package util

import (
	"fmt"
	"os"
)

func (u *SomaUtil) AbortOnError(err error, txt ...string) {
	if err != nil {
		for _, s := range txt {
			fmt.Fprintf(os.Stderr, "%s\n", s)
			u.Log.Print(s)
		}
		fmt.Fprintf(os.Stderr, "%s\n", err.Error())
		u.Log.Fatal(err)
	}
}

func (u *SomaUtil) Abort(txt ...string) {
	for _, s := range txt {
		fmt.Fprintf(os.Stderr, "%s\n", s)
		u.Log.Print(s)
	}

	// ensure there is _something_
	if len(txt) == 0 {
		e := `Abort() called without error message. Sorry!`
		fmt.Fprintf(os.Stderr, "%s\n", e)
		u.Log.Print(e)
	}
	os.Exit(1)
}

func (u *SomaUtil) NotImplemented(txt ...string) {
	for _, s := range txt {
		fmt.Fprintf(os.Stderr, "%s\n", s)
		u.Log.Print(s)
	}

	// ensure there is _something_ in the log
	if len(txt) == 0 {
		e := `This command is currently not implemented.`
		fmt.Fprintf(os.Stderr, "%s\n", e)
		u.Log.Print(e)
	}
	os.Exit(1)
}

// vim: ts=4 sw=4 sts=4 noet fenc=utf-8 ffs=unix
<|endoftext|>


<commit_before>package utils

import (
	"bytes"
	"crypto/md5"
	"encoding/hex"
	"errors"
	"fmt"
	"image"
	_ "image/gif"
	_ "image/jpeg"
	_ "image/png"
	"io"
	"math/rand"
	"mime/multipart"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/eirka/eirka-libs/amazon"
	"github.com/eirka/eirka-libs/config"

	local "github.com/eirka/eirka-post/config"
)

// valid file extensions
var validExt = map[string]bool{
	".jpg":  true,
	".jpeg": true,
	".png":  true,
	".gif":  true,
	".webm": true,
}

type ImageType struct {
	File        multipart.File
	Header      *multipart.FileHeader
	Filename    string
	Thumbnail   string
	Ext         string
	MD5         string
	OrigWidth   int
	OrigHeight  int
	ThumbWidth  int
	ThumbHeight int
	image       *bytes.Buffer
	mime        string
	duration    int
}

func (i *ImageType) IsValid() bool {

	if i.Filename == "" {
		return false
	}

	if i.Thumbnail == "" {
		return false
	}

	if i.Ext == "" {
		return false
	}

	if i.MD5 == "" {
		return false
	}

	if i.mime == "" {
		return false
	}

	return true
}

func (i *ImageType) IsValidPost() bool {
	if i.OrigWidth == 0 {
		return false
	}

	if i.OrigHeight == 0 {
		return false
	}

	if i.ThumbWidth == 0 {
		return false
	}

	if i.ThumbHeight == 0 {
		return false
	}

	return true
}

// ProcessFile will check file integrity, get an md5, and make filenames
func (i *ImageType) ProcessFile() (err error) {

	// check given file ext
	err = i.checkReqExt()
	if err != nil {
		return
	}

	// get file md5
	err = i.getMD5()
	if err != nil {
		return
	}

	// check file magic sig
	err = i.checkMagic()
	if err != nil {
		return
	}

	// check final state
	if !i.IsValidPost() {
		return errors.New("ImageType is not valid")
	}

	return

}

// save an image file
func (i *ImageType) SaveImage() (err error) {

	// check image stats
	err = i.getStats()
	if err != nil {
		return
	}

	// save the file to disk
	err = i.saveFile()
	if err != nil {
		return
	}

	// create a thumbnail
	err = i.createThumbnail()
	if err != nil {
		return
	}

	return

}

// Get file extension from request header
func (i *ImageType) checkReqExt() (err error) {
	// Get ext from request header
	name := i.Header.Filename
	ext := filepath.Ext(name)

	if ext == "" {
		return errors.New("no file extension")
	}

	// Check to see if extension is allowed
	ext_check := isAllowedExt(ext)
	if !ext_check {
		return errors.New("format not supported")
	}

	return

}

// Check if file ext allowed
func isAllowedExt(ext string) bool {

	if validExt[strings.ToLower(ext)] {
		return true
	}

	return false

}

// Get image MD5 and write file into buffer
func (i *ImageType) getMD5() (err error) {

	defer i.File.Close()

	hasher := md5.New()

	i.image = new(bytes.Buffer)

	// Save file and also read into hasher for md5
	_, err = io.Copy(i.image, io.TeeReader(i.File, hasher))
	if err != nil {
		return errors.New("problem copying file")
	}

	// Set md5sum from hasher
	i.MD5 = hex.EncodeToString(hasher.Sum(nil))

	return

}

func (i *ImageType) checkMagic() (err error) {

	// detect the mime type
	i.mime = http.DetectContentType(i.image.Bytes())

	switch i.mime {
	case "image/png":
		i.Ext = ".png"
	case "image/jpeg":
		i.Ext = ".jpg"
	case "image/gif":
		i.Ext = ".gif"
	case "video/webm":
		i.Ext = ".webm"
	default:
		return errors.New("unknown file type")
	}

	// Check to see if extension is allowed
	ext_check := isAllowedExt(i.Ext)
	if !ext_check {
		return errors.New("format not supported")
	}

	return

}

func (i *ImageType) getStats() (err error) {

	// decode image config
	img, _, err := image.DecodeConfig(bytes.NewReader(i.image.Bytes()))
	if err != nil {
		return errors.New("problem decoding image")
	}

	// set original width
	i.OrigWidth = img.Width
	// set original height
	i.OrigHeight = img.Height

	// Check against maximum sizes
	switch {
	case i.OrigWidth > config.Settings.Limits.ImageMaxWidth:
		return errors.New("image width too large")
	case img.Width < config.Settings.Limits.ImageMinWidth:
		return errors.New("image width too small")
	case i.OrigHeight > config.Settings.Limits.ImageMaxHeight:
		return errors.New("image height too large")
	case img.Height < config.Settings.Limits.ImageMinHeight:
		return errors.New("image height too small")
	case i.image.Len() > config.Settings.Limits.ImageMaxSize:
		return errors.New("image size too large")
	}

	return

}

func (i *ImageType) saveFile() (err error) {

	defer i.image.Reset()

	// generate filenames
	i.makeFilenames()

	if !i.IsValid() {
		return errors.New("ImageType is not valid")
	}

	imagefile := filepath.Join(local.Settings.Directories.ImageDir, i.Filename)

	image, err := os.Create(imagefile)
	if err != nil {
		return errors.New("problem saving file")
	}
	defer image.Close()

	_, err = io.Copy(image, bytes.NewReader(i.image.Bytes()))
	if err != nil {
		return errors.New("problem saving file")
	}

	s3 := amazon.New()

	err = s3.Save(imagefile, fmt.Sprintf("src/%s", i.Filename), i.mime)
	if err != nil {
		return
	}

	return

}

// Make a random unix time filename
func (i *ImageType) makeFilenames() {

	// Create seed for random
	rand.Seed(time.Now().UnixNano())

	// Get random 3 digit int to append to unix time
	rand_t := rand.Intn(899) + 100

	// Get current unix time
	time_t := time.Now().Unix()

	// Append random int to unix time
	file_t := fmt.Sprintf("%d%d", time_t, rand_t)

	// Append ext to filename
	i.Filename = fmt.Sprintf("%s%s", file_t, i.Ext)

	// Append jpg to thumbnail name because it is always a jpg
	i.Thumbnail = fmt.Sprintf("%ss.jpg", file_t)

	return

}

func (i *ImageType) createThumbnail() (err error) {

	if !i.IsValid() {
		return errors.New("ImageType is not valid")
	}

	object := amazon.LambdaThumbnail{
		Bucket:    config.Settings.Amazon.Bucket,
		Filename:  i.Filename,
		Thumbnail: i.Thumbnail,
		MaxWidth:  config.Settings.Limits.ThumbnailMaxWidth,
		MaxHeight: config.Settings.Limits.ThumbnailMaxHeight,
	}

	lambda := amazon.New()

	// run our lambda job and get the dimensions
	i.ThumbWidth, i.ThumbHeight, err = lambda.Execute(object)
	if err != nil {
		return
	}

	return

}
<commit_msg>add tests and change image functions a bit<commit_after>package utils

import (
	"bytes"
	"crypto/md5"
	"encoding/hex"
	"errors"
	"fmt"
	"image"
	_ "image/gif"
	_ "image/jpeg"
	_ "image/png"
	"io"
	"math/rand"
	"mime/multipart"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/eirka/eirka-libs/amazon"
	"github.com/eirka/eirka-libs/config"

	local "github.com/eirka/eirka-post/config"
)

// valid file extensions
var validExt = map[string]bool{
	".jpg":  true,
	".jpeg": true,
	".png":  true,
	".gif":  true,
	".webm": true,
}

type ImageType struct {
	File        multipart.File
	Header      *multipart.FileHeader
	Filename    string
	Thumbnail   string
	Ext         string
	MD5         string
	OrigWidth   int
	OrigHeight  int
	ThumbWidth  int
	ThumbHeight int
	image       *bytes.Buffer
	mime        string
	duration    int
}

func (i *ImageType) IsValid() bool {

	if i.Filename == "" {
		return false
	}

	if i.Thumbnail == "" {
		return false
	}

	if i.Ext == "" {
		return false
	}

	if i.MD5 == "" {
		return false
	}

	if i.mime == "" {
		return false
	}

	return true
}

func (i *ImageType) IsValidPost() bool {
	if i.OrigWidth == 0 {
		return false
	}

	if i.OrigHeight == 0 {
		return false
	}

	if i.ThumbWidth == 0 {
		return false
	}

	if i.ThumbHeight == 0 {
		return false
	}

	return true
}

// ProcessFile will check file integrity, get an md5, and make filenames
func (i *ImageType) ProcessFile() (err error) {

	// check given file ext
	err = i.checkReqExt()
	if err != nil {
		return
	}

	// get file md5
	err = i.getMD5()
	if err != nil {
		return
	}

	// check file magic sig
	err = i.checkMagic()
	if err != nil {
		return
	}

	return

}

// save an image file
func (i *ImageType) SaveImage() (err error) {

	// check image stats
	err = i.getStats()
	if err != nil {
		return
	}

	// save the file to disk
	err = i.saveFile()
	if err != nil {
		return
	}

	// create a thumbnail
	err = i.createThumbnail()
	if err != nil {
		return
	}

	// check final state
	if !i.IsValidPost() {
		return errors.New("ImageType is not valid")
	}

	return

}

// Get file extension from request header
func (i *ImageType) checkReqExt() (err error) {
	// Get ext from request header
	name := i.Header.Filename
	ext := filepath.Ext(name)

	if ext == "" {
		return errors.New("no file extension")
	}

	// Check to see if extension is allowed
	ext_check := isAllowedExt(ext)
	if !ext_check {
		return errors.New("format not supported")
	}

	return

}

// Check if file ext allowed
func isAllowedExt(ext string) bool {

	if validExt[strings.ToLower(ext)] {
		return true
	}

	return false

}

// Get image MD5 and write file into buffer
func (i *ImageType) getMD5() (err error) {

	defer i.File.Close()

	hasher := md5.New()

	i.image = new(bytes.Buffer)

	// Save file and also read into hasher for md5
	_, err = io.Copy(i.image, io.TeeReader(i.File, hasher))
	if err != nil {
		return errors.New("problem copying file")
	}

	// Set md5sum from hasher
	i.MD5 = hex.EncodeToString(hasher.Sum(nil))

	return

}

func (i *ImageType) checkMagic() (err error) {

	// detect the mime type
	i.mime = http.DetectContentType(i.image.Bytes())

	switch i.mime {
	case "image/png":
		i.Ext = ".png"
	case "image/jpeg":
		i.Ext = ".jpg"
	case "image/gif":
		i.Ext = ".gif"
	case "video/webm":
		i.Ext = ".webm"
	default:
		return errors.New("unknown file type")
	}

	// Check to see if extension is allowed
	ext_check := isAllowedExt(i.Ext)
	if !ext_check {
		return errors.New("format not supported")
	}

	return

}

func (i *ImageType) getStats() (err error) {

	// decode image config
	img, _, err := image.DecodeConfig(bytes.NewReader(i.image.Bytes()))
	if err != nil {
		return errors.New("problem decoding image")
	}

	// set original width
	i.OrigWidth = img.Width
	// set original height
	i.OrigHeight = img.Height

	// Check against maximum sizes
	switch {
	case i.OrigWidth > config.Settings.Limits.ImageMaxWidth:
		return errors.New("image width too large")
	case img.Width < config.Settings.Limits.ImageMinWidth:
		return errors.New("image width too small")
	case i.OrigHeight > config.Settings.Limits.ImageMaxHeight:
		return errors.New("image height too large")
	case img.Height < config.Settings.Limits.ImageMinHeight:
		return errors.New("image height too small")
	case i.image.Len() > config.Settings.Limits.ImageMaxSize:
		return errors.New("image size too large")
	}

	return

}

func (i *ImageType) saveFile() (err error) {

	defer i.image.Reset()

	// generate filenames
	i.makeFilenames()

	if !i.IsValid() {
		return errors.New("ImageType is not valid")
	}

	imagefile := filepath.Join(local.Settings.Directories.ImageDir, i.Filename)

	image, err := os.Create(imagefile)
	if err != nil {
		return errors.New("problem saving file")
	}
	defer image.Close()

	_, err = io.Copy(image, bytes.NewReader(i.image.Bytes()))
	if err != nil {
		return errors.New("problem saving file")
	}

	s3 := amazon.New()

	err = s3.Save(imagefile, fmt.Sprintf("src/%s", i.Filename), i.mime)
	if err != nil {
		return
	}

	return

}

// Make a random unix time filename
func (i *ImageType) makeFilenames() {

	// Create seed for random
	rand.Seed(time.Now().UnixNano())

	// Get random 3 digit int to append to unix time
	rand_t := rand.Intn(899) + 100

	// Get current unix time
	time_t := time.Now().Unix()

	// Append random int to unix time
	file_t := fmt.Sprintf("%d%d", time_t, rand_t)

	// Append ext to filename
	i.Filename = fmt.Sprintf("%s%s", file_t, i.Ext)

	// Append jpg to thumbnail name because it is always a jpg
	i.Thumbnail = fmt.Sprintf("%ss.jpg", file_t)

	return

}

func (i *ImageType) createThumbnail() (err error) {

	if !i.IsValid() {
		return errors.New("ImageType is not valid")
	}

	object := amazon.LambdaThumbnail{
		Bucket:    config.Settings.Amazon.Bucket,
		Filename:  i.Filename,
		Thumbnail: i.Thumbnail,
		MaxWidth:  config.Settings.Limits.ThumbnailMaxWidth,
		MaxHeight: config.Settings.Limits.ThumbnailMaxHeight,
	}

	lambda := amazon.New()

	// run our lambda job and get the dimensions
	i.ThumbWidth, i.ThumbHeight, err = lambda.Execute(object)
	if err != nil {
		return
	}

	return

}
<|endoftext|>


<commit_before>package utils

import (
	"bytes"
	"fmt"
	"io"
	"os/exec"
	"runtime"
	"strings"

	systemdDbus "github.com/coreos/go-systemd/dbus"
	"github.com/godbus/dbus"
)

// ExecCmd executes a command with args and returns its output as a string along
// with an error, if any
func ExecCmd(name string, args ...string) (string, error) {
	cmd := exec.Command(name, args...)
	var stdout bytes.Buffer
	var stderr bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr

	err := cmd.Run()
	if err != nil {
		return "", fmt.Errorf("`%v %v` failed: %v %v (%v)", name, strings.Join(args, " "), stderr.String(), stdout.String(), err)
	}

	return stdout.String(), nil
}

// ExecCmdWithStdStreams execute a command with the specified standard streams.
func ExecCmdWithStdStreams(stdin io.Reader, stdout, stderr io.Writer, name string, args ...string) error {
	cmd := exec.Command(name, args...)
	cmd.Stdin = stdin
	cmd.Stdout = stdout
	cmd.Stderr = stderr

	err := cmd.Run()
	if err != nil {
		return fmt.Errorf("`%v %v` failed: %v", name, strings.Join(args, " "), err)
	}

	return nil
}

// StatusToExitCode converts wait status code to an exit code
func StatusToExitCode(status int) int {
	return ((status) & 0xff00) >> 8
}

// RunUnderSystemdScope adds the specified pid to a systemd scope
func RunUnderSystemdScope(pid int, slice string, unitName string) error {
	var properties []systemdDbus.Property
	conn, err := systemdDbus.New()
	if err != nil {
		return err
	}
	properties = append(properties, systemdDbus.PropSlice(slice))
	properties = append(properties, newProp("PIDs", []uint32{uint32(pid)}))
	properties = append(properties, newProp("Delegate", true))
	properties = append(properties, newProp("DefaultDependencies", false))
	ch := make(chan string)
	_, err = conn.StartTransientUnit(unitName, "replace", properties, ch)
	if err != nil {
		return err
	}
	defer conn.Close()

	// Block until job is started
	<-ch

	return nil
}

func newProp(name string, units interface{}) systemdDbus.Property {
	return systemdDbus.Property{
		Name:  name,
		Value: dbus.MakeVariant(units),
	}
}

// DetachError is special error which returned in case of container detach.
type DetachError struct{}

func (DetachError) Error() string {
	return "detached from container"
}

// CopyDetachable is similar to io.Copy but support a detach key sequence to break out.
func CopyDetachable(dst io.Writer, src io.Reader, keys []byte) (written int64, err error) {
	if len(keys) == 0 {
		// Default keys : ctrl-p ctrl-q
		keys = []byte{16, 17}
	}

	buf := make([]byte, 32*1024)
	for {
		nr, er := src.Read(buf)
		if nr > 0 {
			preservBuf := []byte{}
			for i, key := range keys {
				preservBuf = append(preservBuf, buf[0:nr]...)
				if nr != 1 || buf[0] != key {
					break
				}
				if i == len(keys)-1 {
					// src.Close()
					return 0, DetachError{}
				}
				nr, er = src.Read(buf)
			}
			var nw int
			var ew error
			if len(preservBuf) > 0 {
				nw, ew = dst.Write(preservBuf)
				nr = len(preservBuf)
			} else {
				nw, ew = dst.Write(buf[0:nr])
			}
			if nw > 0 {
				written += int64(nw)
			}
			if ew != nil {
				err = ew
				break
			}
			if nr != nw {
				err = io.ErrShortWrite
				break
			}
		}
		if er != nil {
			if er != io.EOF {
				err = er
			}
			break
		}
	}
	return written, err
}

// WriteGoroutineStacks writes out the goroutine stacks
// of the caller. Up to 32 MB is allocated to print the
// stack.
func WriteGoroutineStacks(w io.Writer) error {
	buf := make([]byte, 1<<20)
	for i := 0; ; i++ {
		n := runtime.Stack(buf, true)
		if n < len(buf) {
			buf = buf[:n]
			break
		}
		if len(buf) >= 32<<20 {
			break
		}
		buf = make([]byte, 2*len(buf))
	}
	_, err := w.Write(buf)
	return err
}
<commit_msg>utils: Add function to write goroutine stacks to a file<commit_after>package utils

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"os/exec"
	"runtime"
	"strings"

	systemdDbus "github.com/coreos/go-systemd/dbus"
	"github.com/godbus/dbus"
)

// ExecCmd executes a command with args and returns its output as a string along
// with an error, if any
func ExecCmd(name string, args ...string) (string, error) {
	cmd := exec.Command(name, args...)
	var stdout bytes.Buffer
	var stderr bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr

	err := cmd.Run()
	if err != nil {
		return "", fmt.Errorf("`%v %v` failed: %v %v (%v)", name, strings.Join(args, " "), stderr.String(), stdout.String(), err)
	}

	return stdout.String(), nil
}

// ExecCmdWithStdStreams execute a command with the specified standard streams.
func ExecCmdWithStdStreams(stdin io.Reader, stdout, stderr io.Writer, name string, args ...string) error {
	cmd := exec.Command(name, args...)
	cmd.Stdin = stdin
	cmd.Stdout = stdout
	cmd.Stderr = stderr

	err := cmd.Run()
	if err != nil {
		return fmt.Errorf("`%v %v` failed: %v", name, strings.Join(args, " "), err)
	}

	return nil
}

// StatusToExitCode converts wait status code to an exit code
func StatusToExitCode(status int) int {
	return ((status) & 0xff00) >> 8
}

// RunUnderSystemdScope adds the specified pid to a systemd scope
func RunUnderSystemdScope(pid int, slice string, unitName string) error {
	var properties []systemdDbus.Property
	conn, err := systemdDbus.New()
	if err != nil {
		return err
	}
	properties = append(properties, systemdDbus.PropSlice(slice))
	properties = append(properties, newProp("PIDs", []uint32{uint32(pid)}))
	properties = append(properties, newProp("Delegate", true))
	properties = append(properties, newProp("DefaultDependencies", false))
	ch := make(chan string)
	_, err = conn.StartTransientUnit(unitName, "replace", properties, ch)
	if err != nil {
		return err
	}
	defer conn.Close()

	// Block until job is started
	<-ch

	return nil
}

func newProp(name string, units interface{}) systemdDbus.Property {
	return systemdDbus.Property{
		Name:  name,
		Value: dbus.MakeVariant(units),
	}
}

// DetachError is special error which returned in case of container detach.
type DetachError struct{}

func (DetachError) Error() string {
	return "detached from container"
}

// CopyDetachable is similar to io.Copy but support a detach key sequence to break out.
func CopyDetachable(dst io.Writer, src io.Reader, keys []byte) (written int64, err error) {
	if len(keys) == 0 {
		// Default keys : ctrl-p ctrl-q
		keys = []byte{16, 17}
	}

	buf := make([]byte, 32*1024)
	for {
		nr, er := src.Read(buf)
		if nr > 0 {
			preservBuf := []byte{}
			for i, key := range keys {
				preservBuf = append(preservBuf, buf[0:nr]...)
				if nr != 1 || buf[0] != key {
					break
				}
				if i == len(keys)-1 {
					// src.Close()
					return 0, DetachError{}
				}
				nr, er = src.Read(buf)
			}
			var nw int
			var ew error
			if len(preservBuf) > 0 {
				nw, ew = dst.Write(preservBuf)
				nr = len(preservBuf)
			} else {
				nw, ew = dst.Write(buf[0:nr])
			}
			if nw > 0 {
				written += int64(nw)
			}
			if ew != nil {
				err = ew
				break
			}
			if nr != nw {
				err = io.ErrShortWrite
				break
			}
		}
		if er != nil {
			if er != io.EOF {
				err = er
			}
			break
		}
	}
	return written, err
}

// WriteGoroutineStacks writes out the goroutine stacks
// of the caller. Up to 32 MB is allocated to print the
// stack.
func WriteGoroutineStacks(w io.Writer) error {
	buf := make([]byte, 1<<20)
	for i := 0; ; i++ {
		n := runtime.Stack(buf, true)
		if n < len(buf) {
			buf = buf[:n]
			break
		}
		if len(buf) >= 32<<20 {
			break
		}
		buf = make([]byte, 2*len(buf))
	}
	_, err := w.Write(buf)
	return err
}

// WriteGoroutineStacksToFile write goroutine stacks
// to the specified file.
func WriteGoroutineStacksToFile(path string) error {
	f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0666)
	if err != nil {
		return err
	}
	defer f.Close()
	defer f.Sync()

	return WriteGoroutineStacks(f)
}
<|endoftext|>


<commit_before>package utils

import (
	"encoding/csv"
	"fmt"
	"io"
	"math"
	"math/big"
	"os"
)

//WriteMsg - Just a wrapper of fmt.Print()
func WriteMsg(s string) {
	fmt.Println(s)
}

// DecodeDecimal - What the Hell
func DecodeDecimal(b []byte, m *big.Int) (bool, int) {

	//bigint word size (*--> src/pkg/math/big/arith.go)
	const (
		dec128Bias = 6176
		// Compute the size _S of a Word in bytes.
		_m    = ^big.Word(0)
		_logS = _m>>8&1 + _m>>16&1 + _m>>32&1
		_S    = 1 << _logS
	)

	neg := (b[15] & 0x80) != 0
	exp := int((((uint16(b[15])<<8)|uint16(b[14]))<<1)>>2) - dec128Bias

	b14 := b[14]  // save b[14]
	b[14] &= 0x01 // keep the mantissa bit (rest: sign and exp)

	//most significand byte
	msb := 14
	for msb > 0 {
		if b[msb] != 0 {
			break
		}
		msb--
	}

	//calc number of words
	numWords := (msb / _S) + 1
	w := make([]big.Word, numWords)

	k := numWords - 1
	d := big.Word(0)
	for i := msb; i >= 0; i-- {
		d |= big.Word(b[i])
		if k*_S == i {
			w[k] = d
			k--
			d = 0
		}
		d <<= 8
	}
	b[14] = b14 // restore b[14]
	m.SetBits(w)
	return neg, exp
}

// BigIntToFloat - Convert to float
func BigIntToFloat(sign bool, m *big.Int, exp int) float64 {
	var neg int64
	if sign {
		neg = -1
	} else {
		neg = 1
	}

	return float64(neg*m.Int64()) * math.Pow10(exp)
}

// ReadCsv - Read CSV file and return as string slice
func ReadCsv(f string, comma rune) (rec [][]string, count int) {
	file, err := os.Open(f)
	if err != nil {
		fmt.Println("Error: ", err)
		return
	}
	defer file.Close()

	reader := csv.NewReader(file)
	reader.Comma = comma

	lineCount := 0

	var WholeRecord [][]string

	for {
		record, err := reader.Read()
		if err == io.EOF {
			break
		} else if err != nil {
			fmt.Println("Error: ", err)
			return
		}
		lineCount++
		WholeRecord = append(WholeRecord, record)
	}
	return WholeRecord, lineCount
}
<commit_msg>- add convert byte to str function<commit_after>package utils

import (
	"encoding/csv"
	"fmt"
	"io"
	"math"
	"math/big"
	"os"
)

//WriteMsg - Just a wrapper of fmt.Print()
func WriteMsg(s string) {
	fmt.Println(s)
}

// DecodeDecimal - What the Hell
func DecodeDecimal(b []byte, m *big.Int) (bool, int) {

	//bigint word size (*--> src/pkg/math/big/arith.go)
	const (
		dec128Bias = 6176
		// Compute the size _S of a Word in bytes.
		_m    = ^big.Word(0)
		_logS = _m>>8&1 + _m>>16&1 + _m>>32&1
		_S    = 1 << _logS
	)

	neg := (b[15] & 0x80) != 0
	exp := int((((uint16(b[15])<<8)|uint16(b[14]))<<1)>>2) - dec128Bias

	b14 := b[14]  // save b[14]
	b[14] &= 0x01 // keep the mantissa bit (rest: sign and exp)

	//most significand byte
	msb := 14
	for msb > 0 {
		if b[msb] != 0 {
			break
		}
		msb--
	}

	//calc number of words
	numWords := (msb / _S) + 1
	w := make([]big.Word, numWords)

	k := numWords - 1
	d := big.Word(0)
	for i := msb; i >= 0; i-- {
		d |= big.Word(b[i])
		if k*_S == i {
			w[k] = d
			k--
			d = 0
		}
		d <<= 8
	}
	b[14] = b14 // restore b[14]
	m.SetBits(w)
	return neg, exp
}

// BigIntToFloat - Convert to float
func BigIntToFloat(sign bool, m *big.Int, exp int) float64 {
	var neg int64
	if sign {
		neg = -1
	} else {
		neg = 1
	}

	return float64(neg*m.Int64()) * math.Pow10(exp)
}

// ReadCsv - Read CSV file and return as string slice
func ReadCsv(f string, comma rune) (rec [][]string, count int) {
	file, err := os.Open(f)
	if err != nil {
		fmt.Println("Error: ", err)
		return
	}
	defer file.Close()

	reader := csv.NewReader(file)
	reader.Comma = comma

	lineCount := 0

	var WholeRecord [][]string

	for {
		record, err := reader.Read()
		if err == io.EOF {
			break
		} else if err != nil {
			fmt.Println("Error: ", err)
			return
		}
		lineCount++
		WholeRecord = append(WholeRecord, record)
	}
	return WholeRecord, lineCount
}

// ConvertByteToStr = ConvertByteToStr
func ConvertByteToStr(b []byte, bi big.Int) string {
	//var bi big.Int
	var z float64
	var neg bool
	var i int

	neg, i = DecodeDecimal(b, &bi)
	z = BigIntToFloat(neg, &bi, i)
	//record = append(record, fmt.Sprintf("%.4f", z))
	return fmt.Sprintf("%.4f", z)
}
<|endoftext|>


<commit_before>package utils

import (
	"errors"
	"fmt"
	"math"
	"sort"
	"strconv"
	"strings"

	"github.com/vmware/govmomi/vim25/types"
)

// Min : get the minimum of values
func Min(n ...int64) int64 {
	var min int64 = -1
	for _, i := range n {
		if i >= 0 {
			if min == -1 {
				min = i
			} else {
				if i < min {
					min = i
				}
			}
		}
	}
	return min
}

// Max : get the maximum of the values
func Max(n ...int64) int64 {
	var max int64 = -1
	for _, i := range n {
		if i >= 0 {
			if max == -1 {
				max = i
			} else {
				if i > max {
					max = i
				}
			}
		}
	}
	return max
}

// Sum : Sum the values
func Sum(n ...int64) int64 {
	var total int64
	for _, i := range n {
		if i > 0 {
			total += i
		}
	}
	return total
}

// Average : average the values
func Average(n ...int64) int64 {
	var total int64
	var count int64
	for _, i := range n {
		if i >= 0 {
			count++
			total += i
		}
	}
	favg := float64(total) / float64(count)
	return int64(math.Floor(favg + .5))
}

// MapObjRefs fills in object references into a map to another object reference
func MapObjRefs(sourceVal types.AnyType, dest map[types.ManagedObjectReference][]types.ManagedObjectReference, index types.ManagedObjectReference) error {
	mors, ok := sourceVal.(types.ArrayOfManagedObjectReference)
	if ok {
		if len(mors.ManagedObjectReference) > 0 {
			dest[index] = mors.ManagedObjectReference
			return nil
		} else {
			return errors.New("Property didn't contain any object references")
		}
	} else {
		return errors.New("Property " + index.String() + " was not a ManagedObjectReferences, it was " + fmt.Sprintf("%T", sourceVal))
	}
}

// MapObjRef fills in object reference into a map to another object reference
func MapObjRef(sourceVal types.AnyType, dest map[types.ManagedObjectReference]types.ManagedObjectReference, index types.ManagedObjectReference) error {
	mor, ok := sourceVal.(types.ManagedObjectReference)
	if ok {
		dest[index] = mor
		return nil
	} else {
		return errors.New("Property of " + index.String() + " was not a ManagedObjectReference, it was " + fmt.Sprintf("%T", sourceVal))
	}
}

// MapObjInt32 fills in an int32 into a map to another object reference
func MapObjInt32(sourceVal types.AnyType, dest map[types.ManagedObjectReference]int32, index types.ManagedObjectReference) error {
	val, ok := sourceVal.(int32)
	if ok {
		dest[index] = val
		return nil
	} else {
		return errors.New("Property of " + index.String() + " was not an int32, it was " + fmt.Sprintf("%T", sourceVal))
	}
}

// StringMaptoString converts a string map to csv or get the first value
func StringMaptoString(value []string, separator string, noarray bool) string {
	if len(value) == 0 {
		return ""
	}
	if noarray {
		return value[0]
	}
	return strings.Join(value, separator)
}

// IntMaptoString converts a int map to csv or get the first value
func IntMaptoString(value []int, separator string, noarray bool) string {
	if len(value) == 0 {
		return ""
	}
	if noarray {
		return strconv.Itoa(value[0])
	}
	var strval []string
	for _, i := range value {
		strval = append(strval, strconv.Itoa(i))
	}
	return strings.Join(strval, separator)
}

// Int32MaptoString converts a int32 map to csv or get the first value
func Int32MaptoString(value []int32, separator string, noarray bool) string {
	if len(value) == 0 {
		return ""
	}
	if noarray {
		return strconv.FormatInt(int64(value[0]), 10)
	}
	var strval []string
	for _, i := range value {
		strval = append(strval, strconv.FormatInt(int64(i), 10))
	}
	return strings.Join(strval, separator)
}

// Int64MaptoString converts a int64 map to csv or get the first value
func Int64MaptoString(value []int64, separator string, noarray bool) string {
	if len(value) == 0 {
		return ""
	}
	if noarray {
		return strconv.FormatInt(value[0], 10)
	}
	var strval []string
	for _, i := range value {
		strval = append(strval, strconv.FormatInt(i, 10))
	}
	return strings.Join(strval, separator)
}

// ValToString : try to convert interface to string. Separated by separator if slice
func ValToString(value interface{}, separator string, noarray bool) string {
	switch v := value.(type) {
	case string:
		return v
	case []string:
		return StringMaptoString(v, separator, noarray)
	case int:
		return strconv.Itoa(v)
	case []int:
		return IntMaptoString(v, separator, noarray)
	case int32:
		return strconv.FormatInt(int64(v), 10)
	case []int32:
		return Int32MaptoString(v, separator, noarray)
	case int64:
		return strconv.FormatInt(v, 10)
	case []int64:
		return Int64MaptoString(v, separator, noarray)
	default:
		return ""
	}
}

// Join map[int]string into a string
func Join(values map[int]string, separator string) string {
	var keys []int
	for k := range values {
		keys = append(keys, k)
	}
	sort.Ints(keys)
	// create a map with the key parts in order
	var tmp []string
	for _, k := range keys {
		tmp = append(tmp, values[k])
	}
	return strings.Join(tmp, separator)
}

// MustAtoi converts a string to integer and return 0 i case of error
func MustAtoi(value string) int {
	i, err := strconv.Atoi(value)
	if err != nil {
		i = 0
	}
	return i
}
<commit_msg>Update utils.go<commit_after>package utils

import (
	"errors"
	"fmt"
	"math"
	"sort"
	"strconv"
	"strings"

	"github.com/vmware/govmomi/vim25/types"
)

// Min : get the minimum of values
func Min(n ...int64) int64 {
	var min int64 = -1
	for _, i := range n {
		if i >= 0 {
			if min == -1 {
				min = i
			} else {
				if i < min {
					min = i
				}
			}
		}
	}
	return min
}

// Max : get the maximum of the values
func Max(n ...int64) int64 {
	var max int64 = -1
	for _, i := range n {
		if i >= 0 {
			if max == -1 {
				max = i
			} else {
				if i > max {
					max = i
				}
			}
		}
	}
	return max
}

// Sum : Sum the values
func Sum(n ...int64) int64 {
	var total int64
	for _, i := range n {
		if i > 0 {
			total += i
		}
	}
	return total
}

// Average : average the values
func Average(n ...int64) int64 {
	var total int64
	var count int64
	for _, i := range n {
		if i >= 0 {
			count++
			total += i
		}
	}
	favg := float64(total) / float64(count)
	return int64(math.Floor(favg + .5))
}

// MapObjRefs fills in object references into a map to another object reference
func MapObjRefs(sourceVal types.AnyType, dest map[types.ManagedObjectReference][]types.ManagedObjectReference, index types.ManagedObjectReference) error {
	mors, ok := sourceVal.(types.ArrayOfManagedObjectReference)
	if ok {
		if len(mors.ManagedObjectReference) > 0 {
			dest[index] = mors.ManagedObjectReference
			return nil
		} else {
			return errors.New("Property " + index.String() + "didn't contain any object references")
		}
	} else {
		return errors.New("Property " + index.String() + " was not a ManagedObjectReferences, it was " + fmt.Sprintf("%T", sourceVal))
	}
}

// MapObjRef fills in object reference into a map to another object reference
func MapObjRef(sourceVal types.AnyType, dest map[types.ManagedObjectReference]types.ManagedObjectReference, index types.ManagedObjectReference) error {
	mor, ok := sourceVal.(types.ManagedObjectReference)
	if ok {
		dest[index] = mor
		return nil
	} else {
		return errors.New("Property of " + index.String() + " was not a ManagedObjectReference, it was " + fmt.Sprintf("%T", sourceVal))
	}
}

// MapObjInt32 fills in an int32 into a map to another object reference
func MapObjInt32(sourceVal types.AnyType, dest map[types.ManagedObjectReference]int32, index types.ManagedObjectReference) error {
	val, ok := sourceVal.(int32)
	if ok {
		dest[index] = val
		return nil
	} else {
		return errors.New("Property of " + index.String() + " was not an int32, it was " + fmt.Sprintf("%T", sourceVal))
	}
}

// StringMaptoString converts a string map to csv or get the first value
func StringMaptoString(value []string, separator string, noarray bool) string {
	if len(value) == 0 {
		return ""
	}
	if noarray {
		return value[0]
	}
	return strings.Join(value, separator)
}

// IntMaptoString converts a int map to csv or get the first value
func IntMaptoString(value []int, separator string, noarray bool) string {
	if len(value) == 0 {
		return ""
	}
	if noarray {
		return strconv.Itoa(value[0])
	}
	var strval []string
	for _, i := range value {
		strval = append(strval, strconv.Itoa(i))
	}
	return strings.Join(strval, separator)
}

// Int32MaptoString converts a int32 map to csv or get the first value
func Int32MaptoString(value []int32, separator string, noarray bool) string {
	if len(value) == 0 {
		return ""
	}
	if noarray {
		return strconv.FormatInt(int64(value[0]), 10)
	}
	var strval []string
	for _, i := range value {
		strval = append(strval, strconv.FormatInt(int64(i), 10))
	}
	return strings.Join(strval, separator)
}

// Int64MaptoString converts a int64 map to csv or get the first value
func Int64MaptoString(value []int64, separator string, noarray bool) string {
	if len(value) == 0 {
		return ""
	}
	if noarray {
		return strconv.FormatInt(value[0], 10)
	}
	var strval []string
	for _, i := range value {
		strval = append(strval, strconv.FormatInt(i, 10))
	}
	return strings.Join(strval, separator)
}

// ValToString : try to convert interface to string. Separated by separator if slice
func ValToString(value interface{}, separator string, noarray bool) string {
	switch v := value.(type) {
	case string:
		return v
	case []string:
		return StringMaptoString(v, separator, noarray)
	case int:
		return strconv.Itoa(v)
	case []int:
		return IntMaptoString(v, separator, noarray)
	case int32:
		return strconv.FormatInt(int64(v), 10)
	case []int32:
		return Int32MaptoString(v, separator, noarray)
	case int64:
		return strconv.FormatInt(v, 10)
	case []int64:
		return Int64MaptoString(v, separator, noarray)
	default:
		return ""
	}
}

// Join map[int]string into a string
func Join(values map[int]string, separator string) string {
	var keys []int
	for k := range values {
		keys = append(keys, k)
	}
	sort.Ints(keys)
	// create a map with the key parts in order
	var tmp []string
	for _, k := range keys {
		tmp = append(tmp, values[k])
	}
	return strings.Join(tmp, separator)
}

// MustAtoi converts a string to integer and return 0 i case of error
func MustAtoi(value string) int {
	i, err := strconv.Atoi(value)
	if err != nil {
		i = 0
	}
	return i
}
<|endoftext|>


<commit_before>package utils

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"syscall"
)

const PR_SET_CHILD_SUBREAPER = 36

func ExecCmd(name string, args ...string) (string, error) {
	cmd := exec.Command(name, args...)
	var stdout bytes.Buffer
	var stderr bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr

	err := cmd.Run()
	if err != nil {
		return "", fmt.Errorf("`%v %v` failed: %v (%v)", name, strings.Join(args, " "), stderr.String(), err)
	}

	return stdout.String(), nil
}

// ExecCmdWithStdStreams execute a command with the specified standard streams.
func ExecCmdWithStdStreams(stdin, stdout, stderr *os.File, name string, args ...string) error {
	cmd := exec.Command(name, args...)
	cmd.Stdin = stdin
	cmd.Stdout = stdout
	cmd.Stderr = stderr

	err := cmd.Run()
	if err != nil {
		return fmt.Errorf("`%v %v` failed: %v", name, strings.Join(args, " "), err)
	}

	return nil
}

// SetSubreaper sets the value i as the subreaper setting for the calling process
func SetSubreaper(i int) error {
	return Prctl(PR_SET_CHILD_SUBREAPER, uintptr(i), 0, 0, 0)
}

// Prctl is a way to make the prctl linux syscall
func Prctl(option int, arg2, arg3, arg4, arg5 uintptr) (err error) {
	_, _, e1 := syscall.Syscall6(syscall.SYS_PRCTL, uintptr(option), arg2, arg3, arg4, arg5, 0)
	if e1 != 0 {
		err = e1
	}
	return
}

// CreateFakeRootfs creates a fake rootfs for test.
func CreateFakeRootfs(dir string, image string) error {
	if len(image) <= 9 || image[:9] != "docker://" {
		return fmt.Errorf("CreateFakeRootfs only support docker images currently")
	}

	rootfs := filepath.Join(dir, "rootfs")
	if err := os.MkdirAll(rootfs, 0755); err != nil {
		return err
	}

	// docker export $(docker create image[9:]) | tar -C rootfs -xf -
	return dockerExport(image[9:], rootfs)
}

func dockerExport(image string, rootfs string) error {
	out, err := ExecCmd("docker", "create", image)
	if err != nil {
		return err
	}

	container := out[:strings.Index(out, "\n")]

	cmd := fmt.Sprintf("docker export %s | tar -C %s -xf -", container, rootfs)
	if _, err := ExecCmd("/bin/bash", "-c", cmd); err != nil {
		err1 := dockerRemove(container)
		if err1 == nil {
			return err
		}
		return fmt.Errorf("%v; %v", err, err1)
	}

	return dockerRemove(container)
}

func dockerRemove(container string) error {
	if _, err := ExecCmd("docker", "rm", container); err != nil {
		return err
	}
	return nil
}
<commit_msg>Add utility to start a child process reaper<commit_after>package utils

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"os/signal"
	"path/filepath"
	"strings"
	"syscall"

	"github.com/Sirupsen/logrus"
)

const PR_SET_CHILD_SUBREAPER = 36

func ExecCmd(name string, args ...string) (string, error) {
	cmd := exec.Command(name, args...)
	var stdout bytes.Buffer
	var stderr bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr

	err := cmd.Run()
	if err != nil {
		return "", fmt.Errorf("`%v %v` failed: %v (%v)", name, strings.Join(args, " "), stderr.String(), err)
	}

	return stdout.String(), nil
}

// ExecCmdWithStdStreams execute a command with the specified standard streams.
func ExecCmdWithStdStreams(stdin, stdout, stderr *os.File, name string, args ...string) error {
	cmd := exec.Command(name, args...)
	cmd.Stdin = stdin
	cmd.Stdout = stdout
	cmd.Stderr = stderr

	err := cmd.Run()
	if err != nil {
		return fmt.Errorf("`%v %v` failed: %v", name, strings.Join(args, " "), err)
	}

	return nil
}

// SetSubreaper sets the value i as the subreaper setting for the calling process
func SetSubreaper(i int) error {
	return Prctl(PR_SET_CHILD_SUBREAPER, uintptr(i), 0, 0, 0)
}

// Prctl is a way to make the prctl linux syscall
func Prctl(option int, arg2, arg3, arg4, arg5 uintptr) (err error) {
	_, _, e1 := syscall.Syscall6(syscall.SYS_PRCTL, uintptr(option), arg2, arg3, arg4, arg5, 0)
	if e1 != 0 {
		err = e1
	}
	return
}

// CreateFakeRootfs creates a fake rootfs for test.
func CreateFakeRootfs(dir string, image string) error {
	if len(image) <= 9 || image[:9] != "docker://" {
		return fmt.Errorf("CreateFakeRootfs only support docker images currently")
	}

	rootfs := filepath.Join(dir, "rootfs")
	if err := os.MkdirAll(rootfs, 0755); err != nil {
		return err
	}

	// docker export $(docker create image[9:]) | tar -C rootfs -xf -
	return dockerExport(image[9:], rootfs)
}

func dockerExport(image string, rootfs string) error {
	out, err := ExecCmd("docker", "create", image)
	if err != nil {
		return err
	}

	container := out[:strings.Index(out, "\n")]

	cmd := fmt.Sprintf("docker export %s | tar -C %s -xf -", container, rootfs)
	if _, err := ExecCmd("/bin/bash", "-c", cmd); err != nil {
		err1 := dockerRemove(container)
		if err1 == nil {
			return err
		}
		return fmt.Errorf("%v; %v", err, err1)
	}

	return dockerRemove(container)
}

func dockerRemove(container string) error {
	if _, err := ExecCmd("docker", "rm", container); err != nil {
		return err
	}
	return nil
}

// StartReaper starts a goroutine to reap processes
func StartReaper() {
	logrus.Infof("Starting reaper")
	go func() {
		sigs := make(chan os.Signal, 10)
		signal.Notify(sigs, syscall.SIGCHLD)
		for {
			// Wait for a child to terminate
			sig := <-sigs
			logrus.Infof("Signal received: %v", sig)
			for {
				// Reap processes
				cpid, _ := syscall.Wait4(-1, nil, syscall.WNOHANG, nil)
				if cpid < 1 {
					break
				}

				logrus.Infof("Reaped process with pid %d", cpid)
			}
		}
	}()
}
<|endoftext|>


<commit_before>package govector

import (
	"fmt"
	"testing"

	"github.com/bmizerany/assert"
)

func TestVectors(t *testing.T) {
	x, err := AsVector([]int{2, 2, 2, 4, 2, 5})
	assert.Equal(t, nil, err, "Error casting integer array to vector")

	w, err := AsVector([]float64{1.0, 1.0, 1.0, 1.0, 1.0, 4.0})
	assert.Equal(t, nil, err, "Error casting float64 array to vector")

	q, err := AsVector([]float64{0.05, 0.95})
	assert.Equal(t, nil, err, "Error casing float64 array to vector")

	d_x := x.Diff()
	d_w := w.Diff()

	max := x.Max()
	assert.Equal(t, 5.0, max, "Error calculating max")

	min := x.Min()
	assert.Equal(t, 2.0, min, "Error calculating min")

	empirical := x.Ecdf()

	percentile := empirical(2.4)
	assert.Equal(t, 2.0/3.0, percentile, "Error in CDF calculation")

	_, err = d_x.WeightedMean(d_w)
	assert.Equal(t, nil, err, "Error calculating weighted mean")

	_ = x.Quantiles(q)

	cumsum := x.Cumsum()
	assert.Equal(t, Vector{2, 4, 6, 10, 12, 17}, cumsum, "Error calculating cumulative sum")

	ranks := x.Rank()
	assert.Equal(t, Vector{3, 0, 0, 4, 0, 5}, ranks, "Error calculating ranks")

	shuffled := x.Shuffle()
	assert.Equal(t, x.Len(), shuffled.Len(), "Error shuffling vector")

	y, err := AsVector([]int{-2, 2, -1, 4, 2, 5})
	assert.Equal(t, nil, err, "Error casting negative integer array to vector")

	abs := y.Abs()
	assert.Equal(t, Vector{2, 2, 1, 4, 2, 5}, abs, "Error finding absolute values")

	_ = x.Apply(empirical)

	n := x.Len()
	x.Push(50)
	assert.Equal(t, n+1, x.Len(), "Error appending value to vector")

	xw := Join(x, w)
	assert.Equal(t, x.Len()+w.Len(), xw.Len(), "Error joining vectors")

	filtered := xw.Filter(func(x float64) bool {
		if x < 10 {
			return false
		}
		return true
	})
	assert.Equal(t, 12, len(filtered), "Error filtering vector")

	z, err := AsVector([]int{0, 2, 4, 6, 8, 10, 12, 14, 16, 18})
	assert.Equal(t, nil, err)

	smoothed, err := z.Smooth(0, 0)
	assert.Equal(t, nil, err)
	assert.Equal(t, z, smoothed)

	smoothed, err = z.Smooth(1, 1)
	expected := Vector{1, 2, 4, 6, 8, 10, 12, 14, 16, 17}
	assert.Equal(t, nil, err, "Error smoothing vector")
	assert.Equal(t, expected, smoothed, "Error smoothing vector")

	smoothed, err = z.Smooth(-1, -1)
	assert.NotEqual(t, nil, err, "Negative input indices should return an error")
	assert.Equal(t, z, smoothed, "Negative input indices should return the original vector")

	fmt.Println(x)
	x.Sort()
	fmt.Println(x)
}
<commit_msg>fix sort test<commit_after>package govector

import (
	"testing"

	"github.com/bmizerany/assert"
)

func TestVectors(t *testing.T) {
	x, err := AsVector([]int{2, 2, 2, 4, 2, 5})
	assert.Equal(t, nil, err, "Error casting integer array to vector")

	w, err := AsVector([]float64{1.0, 1.0, 1.0, 1.0, 1.0, 4.0})
	assert.Equal(t, nil, err, "Error casting float64 array to vector")

	q, err := AsVector([]float64{0.05, 0.95})
	assert.Equal(t, nil, err, "Error casing float64 array to vector")

	d_x := x.Diff()
	d_w := w.Diff()

	max := x.Max()
	assert.Equal(t, 5.0, max, "Error calculating max")

	min := x.Min()
	assert.Equal(t, 2.0, min, "Error calculating min")

	empirical := x.Ecdf()

	percentile := empirical(2.4)
	assert.Equal(t, 2.0/3.0, percentile, "Error in CDF calculation")

	_, err = d_x.WeightedMean(d_w)
	assert.Equal(t, nil, err, "Error calculating weighted mean")

	_ = x.Quantiles(q)

	cumsum := x.Cumsum()
	assert.Equal(t, Vector{2, 4, 6, 10, 12, 17}, cumsum, "Error calculating cumulative sum")

	ranks := x.Rank()
	assert.Equal(t, Vector{3, 0, 0, 4, 0, 5}, ranks, "Error calculating ranks")

	shuffled := x.Shuffle()
	assert.Equal(t, x.Len(), shuffled.Len(), "Error shuffling vector")

	y, err := AsVector([]int{-2, 2, -1, 4, 2, 5})
	assert.Equal(t, nil, err, "Error casting negative integer array to vector")

	abs := y.Abs()
	assert.Equal(t, Vector{2, 2, 1, 4, 2, 5}, abs, "Error finding absolute values")

	_ = x.Apply(empirical)

	n := x.Len()
	x.Push(50)
	assert.Equal(t, n+1, x.Len(), "Error appending value to vector")

	xw := Join(x, w)
	assert.Equal(t, x.Len()+w.Len(), xw.Len(), "Error joining vectors")

	filtered := xw.Filter(func(x float64) bool {
		if x < 10 {
			return false
		}
		return true
	})
	assert.Equal(t, 12, len(filtered), "Error filtering vector")

	z, err := AsVector([]int{0, 2, 4, 6, 8, 10, 12, 14, 16, 18})
	assert.Equal(t, nil, err)

	smoothed, err := z.Smooth(0, 0)
	assert.Equal(t, nil, err)
	assert.Equal(t, z, smoothed)

	smoothed, err = z.Smooth(1, 1)
	expected := Vector{1, 2, 4, 6, 8, 10, 12, 14, 16, 17}
	assert.Equal(t, nil, err, "Error smoothing vector")
	assert.Equal(t, expected, smoothed, "Error smoothing vector")

	smoothed, err = z.Smooth(-1, -1)
	assert.NotEqual(t, nil, err, "Negative input indices should return an error")
	assert.Equal(t, z, smoothed, "Negative input indices should return the original vector")

	x.Sort()
	assert.Equal(t, Vector{2, 2, 2, 2, 4, 5, 50}, x)
}
<|endoftext|>


<commit_before>package mesos_test

import (
	"reflect"
	"testing"

	"github.com/gogo/protobuf/proto"
	"github.com/mesos/mesos-go"
)

func scalar(f float64) *mesos.Value_Scalar {
	return &mesos.Value_Scalar{
		Value: f,
	}
}

func r(b, e uint64) mesos.Value_Range {
	return mesos.Value_Range{
		Begin: b,
		End:   e,
	}
}

func ranges(x ...mesos.Value_Range) *mesos.Value_Ranges {
	if x == nil {
		return nil
	}
	return &mesos.Value_Ranges{Range: x}
}

func TestValue_Ranges_Add(t *testing.T) {
	for i, tc := range []struct {
		left, right, want *mesos.Value_Ranges
	}{
		{nil, nil, ranges()},
		{nil, ranges(r(0, 0)), ranges(r(0, 0))},
		{ranges(r(0, 0)), nil, ranges(r(0, 0))},
		{ranges(r(0, 0)), ranges(r(0, 0)), ranges(r(0, 0))},
		{ranges(r(0, 1)), ranges(r(0, 0)), ranges(r(0, 1))},
		{ranges(r(0, 0)), ranges(r(0, 1)), ranges(r(0, 1))},
		{ranges(r(0, 1)), ranges(r(1, 1)), ranges(r(0, 1))},
		{ranges(r(0, 1)), ranges(r(1, 2)), ranges(r(0, 2))},
		{ranges(r(3, 4), r(0, 1)), ranges(r(1, 2)), ranges(r(0, 4))},
		{ranges(r(2, 6), r(3, 4), r(0, 1)), ranges(r(1, 2)), ranges(r(0, 6))},
	} {
		preleft := proto.Clone(tc.left).(*mesos.Value_Ranges)
		preright := proto.Clone(tc.right).(*mesos.Value_Ranges)
		x := tc.left.Add(tc.right)
		if !reflect.DeepEqual(x, tc.want) {
			t.Errorf("test case %d failed: expected %#+v instead of %#+v", i, tc.want, x)
		}
		if !preleft.Equal(tc.left) {
			t.Errorf("test case %d failed: before(left) != after(left): %#+v != %#+v", i, preleft, tc.left)
		}
		if !preright.Equal(tc.right) {
			t.Errorf("test case %d failed: before(right) != after(right): %#+v != %#+v", i, preright, tc.right)
		}
	}
}

func TestValue_Ranges_Subtract(t *testing.T) {
	for i, tc := range []struct {
		left, right, want *mesos.Value_Ranges
	}{
		{nil, nil, ranges()},
		{nil, ranges(r(0, 0)), ranges()},
		{ranges(r(0, 0)), nil, ranges(r(0, 0))},
		{ranges(r(0, 0)), ranges(r(0, 0)), ranges()},
		{ranges(r(0, 1)), ranges(r(0, 0)), ranges(r(1, 1))},
		{ranges(r(0, 0)), ranges(r(0, 1)), ranges()},
		{ranges(r(0, 1)), ranges(r(1, 1)), ranges(r(0, 0))},
		{ranges(r(0, 1)), ranges(r(1, 2)), ranges(r(0, 0))},
		{ranges(r(3, 4), r(0, 1)), ranges(r(1, 2)), ranges(r(0, 0), r(3, 4))},
		{ranges(r(2, 6), r(3, 4), r(0, 1)), ranges(r(2, 4)), ranges(r(0, 1), r(5, 6))},
	} {
		preleft := proto.Clone(tc.left).(*mesos.Value_Ranges)
		preright := proto.Clone(tc.right).(*mesos.Value_Ranges)
		x := tc.left.Subtract(tc.right)
		if !reflect.DeepEqual(x, tc.want) {
			t.Errorf("test case %d failed: expected %#+v instead of %#+v", i, tc.want, x)
		}
		if !preleft.Equal(tc.left) {
			t.Errorf("test case %d failed: before(left) != after(left): %#+v != %#+v", i, preleft, tc.left)
		}
		if !preright.Equal(tc.right) {
			t.Errorf("test case %d failed: before(right) != after(right): %#+v != %#+v", i, preright, tc.right)
		}
	}
}

func TestValue_Scalar_Add(t *testing.T) {
	for i, tc := range []struct {
		left, right, want *mesos.Value_Scalar
	}{
		{nil, nil, scalar(0)},
		{nil, scalar(0), scalar(0)},
		{scalar(0), nil, scalar(0)},
		{scalar(0), scalar(0), scalar(0)},
		{scalar(1), scalar(0), scalar(1)},
		{scalar(0), scalar(1), scalar(1)},
		{scalar(-1), scalar(0), scalar(-1)},
		{scalar(1), scalar(-1), scalar(0)},
		{scalar(1), scalar(1), scalar(2)},
		{scalar(-1), scalar(-1), scalar(-2)},
	} {
		preleft := proto.Clone(tc.left).(*mesos.Value_Scalar)
		preright := proto.Clone(tc.right).(*mesos.Value_Scalar)
		x := tc.left.Add(tc.right)
		if !x.Equal(tc.want) {
			t.Errorf("expected %v instead of %v", tc.want, x)
		}
		if !preleft.Equal(tc.left) {
			t.Errorf("test case %d failed: before(left) != after(left): %#+v != %#+v", i, preleft, tc.left)
		}
		if !preright.Equal(tc.right) {
			t.Errorf("test case %d failed: before(right) != after(right): %#+v != %#+v", i, preright, tc.right)
		}
	}
}

func TestValue_Scalar_Subtract(t *testing.T) {
	for i, tc := range []struct {
		left, right, want *mesos.Value_Scalar
	}{
		{nil, nil, scalar(0)},
		{nil, scalar(0), scalar(0)},
		{scalar(0), nil, scalar(0)},
		{scalar(0), scalar(0), scalar(0)},
		{scalar(1), scalar(0), scalar(1)},
		{scalar(0), scalar(1), scalar(-1)},
		{scalar(-1), scalar(0), scalar(-1)},
		{scalar(1), scalar(-1), scalar(2)},
		{scalar(1), scalar(1), scalar(0)},
		{scalar(-1), scalar(-1), scalar(0)},
	} {
		preleft := proto.Clone(tc.left).(*mesos.Value_Scalar)
		preright := proto.Clone(tc.right).(*mesos.Value_Scalar)
		x := tc.left.Subtract(tc.right)
		if !x.Equal(tc.want) {
			t.Errorf("expected %v instead of %v", tc.want, x)
		}
		if !preleft.Equal(tc.left) {
			t.Errorf("test case %d failed: before(left) != after(left): %#+v != %#+v", i, preleft, tc.left)
		}
		if !preright.Equal(tc.right) {
			t.Errorf("test case %d failed: before(right) != after(right): %#+v != %#+v", i, preright, tc.right)
		}
	}
}

func TestValue_Scalar_Compare(t *testing.T) {
	for i, tc := range []struct {
		left, right *mesos.Value_Scalar
		want        int
	}{
		{nil, nil, 0},
		{nil, scalar(0), 0},
		{scalar(0), nil, 0},
		{scalar(0), scalar(0), 0},
		{scalar(1), scalar(0), 1},
		{scalar(0), scalar(1), -1},
		{scalar(-1), scalar(0), -1},
		{scalar(1), scalar(-1), 1},
		{scalar(1), scalar(1), 0},
		{scalar(-1), scalar(-1), 0},
	} {
		preleft := proto.Clone(tc.left).(*mesos.Value_Scalar)
		preright := proto.Clone(tc.right).(*mesos.Value_Scalar)
		x := tc.left.Compare(tc.right)
		if x != tc.want {
			t.Errorf("test case %d failed: expected %v instead of %v", i, tc.want, x)
		}
		if !preleft.Equal(tc.left) {
			t.Errorf("test case %d failed: before(left) != after(left): %#+v != %#+v", i, preleft, tc.left)
		}
		if !preright.Equal(tc.right) {
			t.Errorf("test case %d failed: before(right) != after(right): %#+v != %#+v", i, preright, tc.right)
		}
	}
}
<commit_msg>unit test for Value_Ranges.Compare<commit_after>package mesos_test

import (
	"reflect"
	"testing"

	"github.com/gogo/protobuf/proto"
	"github.com/mesos/mesos-go"
)

func scalar(f float64) *mesos.Value_Scalar {
	return &mesos.Value_Scalar{
		Value: f,
	}
}

func r(b, e uint64) mesos.Value_Range {
	return mesos.Value_Range{
		Begin: b,
		End:   e,
	}
}

func ranges(x ...mesos.Value_Range) *mesos.Value_Ranges {
	if x == nil {
		return nil
	}
	return &mesos.Value_Ranges{Range: x}
}

func TestValue_Ranges_Compare(t *testing.T) {
	for i, tc := range []struct {
		left, right *mesos.Value_Ranges
		want        int
	}{
		{nil, nil, 0},
		{nil, ranges(r(0, 0)), -1},
		{ranges(r(0, 0)), nil, 1},
		{ranges(r(0, 0)), ranges(r(0, 0)), 0},
		{ranges(r(0, 1)), ranges(r(0, 0)), 1},
		{ranges(r(0, 0)), ranges(r(0, 1)), -1},
		{ranges(r(0, 1)), ranges(r(1, 1)), 1},
		{ranges(r(0, 1)), ranges(r(1, 2)), 1},
		{ranges(r(3, 4), r(0, 1)), ranges(r(1, 2)), 1},
		{ranges(r(1, 2)), ranges(r(2, 6), r(3, 4), r(0, 1)), -1},
	} {
		preleft := proto.Clone(tc.left).(*mesos.Value_Ranges)
		preright := proto.Clone(tc.right).(*mesos.Value_Ranges)
		x := tc.left.Compare(tc.right)
		if !reflect.DeepEqual(x, tc.want) {
			t.Errorf("test case %d failed: expected %#+v instead of %#+v", i, tc.want, x)
		}
		if !preleft.Equal(tc.left) {
			t.Errorf("test case %d failed: before(left) != after(left): %#+v != %#+v", i, preleft, tc.left)
		}
		if !preright.Equal(tc.right) {
			t.Errorf("test case %d failed: before(right) != after(right): %#+v != %#+v", i, preright, tc.right)
		}
	}
}

func TestValue_Ranges_Add(t *testing.T) {
	for i, tc := range []struct {
		left, right, want *mesos.Value_Ranges
	}{
		{nil, nil, ranges()},
		{nil, ranges(r(0, 0)), ranges(r(0, 0))},
		{ranges(r(0, 0)), nil, ranges(r(0, 0))},
		{ranges(r(0, 0)), ranges(r(0, 0)), ranges(r(0, 0))},
		{ranges(r(0, 1)), ranges(r(0, 0)), ranges(r(0, 1))},
		{ranges(r(0, 0)), ranges(r(0, 1)), ranges(r(0, 1))},
		{ranges(r(0, 1)), ranges(r(1, 1)), ranges(r(0, 1))},
		{ranges(r(0, 1)), ranges(r(1, 2)), ranges(r(0, 2))},
		{ranges(r(3, 4), r(0, 1)), ranges(r(1, 2)), ranges(r(0, 4))},
		{ranges(r(2, 6), r(3, 4), r(0, 1)), ranges(r(1, 2)), ranges(r(0, 6))},
	} {
		preleft := proto.Clone(tc.left).(*mesos.Value_Ranges)
		preright := proto.Clone(tc.right).(*mesos.Value_Ranges)
		x := tc.left.Add(tc.right)
		if !reflect.DeepEqual(x, tc.want) {
			t.Errorf("test case %d failed: expected %#+v instead of %#+v", i, tc.want, x)
		}
		if !preleft.Equal(tc.left) {
			t.Errorf("test case %d failed: before(left) != after(left): %#+v != %#+v", i, preleft, tc.left)
		}
		if !preright.Equal(tc.right) {
			t.Errorf("test case %d failed: before(right) != after(right): %#+v != %#+v", i, preright, tc.right)
		}
	}
}

func TestValue_Ranges_Subtract(t *testing.T) {
	for i, tc := range []struct {
		left, right, want *mesos.Value_Ranges
	}{
		{nil, nil, ranges()},
		{nil, ranges(r(0, 0)), ranges()},
		{ranges(r(0, 0)), nil, ranges(r(0, 0))},
		{ranges(r(0, 0)), ranges(r(0, 0)), ranges()},
		{ranges(r(0, 1)), ranges(r(0, 0)), ranges(r(1, 1))},
		{ranges(r(0, 0)), ranges(r(0, 1)), ranges()},
		{ranges(r(0, 1)), ranges(r(1, 1)), ranges(r(0, 0))},
		{ranges(r(0, 1)), ranges(r(1, 2)), ranges(r(0, 0))},
		{ranges(r(3, 4), r(0, 1)), ranges(r(1, 2)), ranges(r(0, 0), r(3, 4))},
		{ranges(r(2, 6), r(3, 4), r(0, 1)), ranges(r(2, 4)), ranges(r(0, 1), r(5, 6))},
	} {
		preleft := proto.Clone(tc.left).(*mesos.Value_Ranges)
		preright := proto.Clone(tc.right).(*mesos.Value_Ranges)
		x := tc.left.Subtract(tc.right)
		if !reflect.DeepEqual(x, tc.want) {
			t.Errorf("test case %d failed: expected %#+v instead of %#+v", i, tc.want, x)
		}
		if !preleft.Equal(tc.left) {
			t.Errorf("test case %d failed: before(left) != after(left): %#+v != %#+v", i, preleft, tc.left)
		}
		if !preright.Equal(tc.right) {
			t.Errorf("test case %d failed: before(right) != after(right): %#+v != %#+v", i, preright, tc.right)
		}
	}
}

func TestValue_Scalar_Add(t *testing.T) {
	for i, tc := range []struct {
		left, right, want *mesos.Value_Scalar
	}{
		{nil, nil, scalar(0)},
		{nil, scalar(0), scalar(0)},
		{scalar(0), nil, scalar(0)},
		{scalar(0), scalar(0), scalar(0)},
		{scalar(1), scalar(0), scalar(1)},
		{scalar(0), scalar(1), scalar(1)},
		{scalar(-1), scalar(0), scalar(-1)},
		{scalar(1), scalar(-1), scalar(0)},
		{scalar(1), scalar(1), scalar(2)},
		{scalar(-1), scalar(-1), scalar(-2)},
	} {
		preleft := proto.Clone(tc.left).(*mesos.Value_Scalar)
		preright := proto.Clone(tc.right).(*mesos.Value_Scalar)
		x := tc.left.Add(tc.right)
		if !x.Equal(tc.want) {
			t.Errorf("expected %v instead of %v", tc.want, x)
		}
		if !preleft.Equal(tc.left) {
			t.Errorf("test case %d failed: before(left) != after(left): %#+v != %#+v", i, preleft, tc.left)
		}
		if !preright.Equal(tc.right) {
			t.Errorf("test case %d failed: before(right) != after(right): %#+v != %#+v", i, preright, tc.right)
		}
	}
}

func TestValue_Scalar_Subtract(t *testing.T) {
	for i, tc := range []struct {
		left, right, want *mesos.Value_Scalar
	}{
		{nil, nil, scalar(0)},
		{nil, scalar(0), scalar(0)},
		{scalar(0), nil, scalar(0)},
		{scalar(0), scalar(0), scalar(0)},
		{scalar(1), scalar(0), scalar(1)},
		{scalar(0), scalar(1), scalar(-1)},
		{scalar(-1), scalar(0), scalar(-1)},
		{scalar(1), scalar(-1), scalar(2)},
		{scalar(1), scalar(1), scalar(0)},
		{scalar(-1), scalar(-1), scalar(0)},
	} {
		preleft := proto.Clone(tc.left).(*mesos.Value_Scalar)
		preright := proto.Clone(tc.right).(*mesos.Value_Scalar)
		x := tc.left.Subtract(tc.right)
		if !x.Equal(tc.want) {
			t.Errorf("expected %v instead of %v", tc.want, x)
		}
		if !preleft.Equal(tc.left) {
			t.Errorf("test case %d failed: before(left) != after(left): %#+v != %#+v", i, preleft, tc.left)
		}
		if !preright.Equal(tc.right) {
			t.Errorf("test case %d failed: before(right) != after(right): %#+v != %#+v", i, preright, tc.right)
		}
	}
}

func TestValue_Scalar_Compare(t *testing.T) {
	for i, tc := range []struct {
		left, right *mesos.Value_Scalar
		want        int
	}{
		{nil, nil, 0},
		{nil, scalar(0), 0},
		{scalar(0), nil, 0},
		{scalar(0), scalar(0), 0},
		{scalar(1), scalar(0), 1},
		{scalar(0), scalar(1), -1},
		{scalar(-1), scalar(0), -1},
		{scalar(1), scalar(-1), 1},
		{scalar(1), scalar(1), 0},
		{scalar(-1), scalar(-1), 0},
	} {
		preleft := proto.Clone(tc.left).(*mesos.Value_Scalar)
		preright := proto.Clone(tc.right).(*mesos.Value_Scalar)
		x := tc.left.Compare(tc.right)
		if x != tc.want {
			t.Errorf("test case %d failed: expected %v instead of %v", i, tc.want, x)
		}
		if !preleft.Equal(tc.left) {
			t.Errorf("test case %d failed: before(left) != after(left): %#+v != %#+v", i, preleft, tc.left)
		}
		if !preright.Equal(tc.right) {
			t.Errorf("test case %d failed: before(right) != after(right): %#+v != %#+v", i, preright, tc.right)
		}
	}
}
<|endoftext|>


<commit_before>// Same copyright and license as the rest of the files in this project

package gtk

// #include <gtk/gtk.h>
// #include "gtk.go.h"
import "C"

import "unsafe"

/*
 * GtkTextMark
 */

// TextMark is a representation of GTK's GtkTextMark
type TextMark C.GtkTextMark

// native returns a pointer to the underlying GtkTextMark.
func (v *TextMark) native() *C.GtkTextMark {
	if v == nil {
		return nil
	}
	return (*C.GtkTextMark)(v)
}

func marshalTextMark(p uintptr) (interface{}, error) {
	c := C.g_value_get_boxed((*C.GValue)(unsafe.Pointer(p)))
	return (*TextMark)(unsafe.Pointer(c)), nil
}
<commit_msg>Rewrote GtkTextMark implementation and adding full methods<commit_after>// Same copyright and license as the rest of the files in this project

package gtk

// #include <gtk/gtk.h>
// #include "gtk.go.h"
import "C"

import (
	"unsafe"

	"github.com/gotk3/gotk3/glib"
)

func init() {

	WrapMap["GtkTextMark"] = wrapTextMark
}

/*
 * GtkTextMark
 */

// TextMark is a representation of GTK's GtkTextMark.
// A position in the buffer preserved across buffer modifications
type TextMark struct {
	*glib.Object
}

// native returns a pointer to the underlying GtkSourceStyleSchemeManager.
func (v *TextMark) native() *C.GtkTextMark {
	if v == nil || v.GObject == nil {
		return nil
	}
	p := unsafe.Pointer(v.GObject)
	return C.toGtkTextMark(p)
}

func marshalTextMark(p uintptr) (interface{}, error) {
	c := C.g_value_get_object((*C.GValue)(unsafe.Pointer(p)))
	obj := glib.Take(unsafe.Pointer(c))
	return wrapTextMark(obj), nil
}

func wrapTextMark(obj *glib.Object) *TextMark {
	return &TextMark{obj}
}

// TextMarkNew is a wrapper around gtk_text_mark_new().
func TextMarkNew(name string, leftGravity bool) (*TextMark, error) {
	cstr := C.CString(name)
	defer C.free(unsafe.Pointer(cstr))

	c := C.gtk_text_mark_new((*C.gchar)(cstr), gbool(leftGravity))
	if c == nil {
		return nil, nilPtrErr
	}
	return wrapTextMark(glib.Take(unsafe.Pointer(c))), nil
}

// SetVisible is a wrapper around gtk_text_mark_set_visible().
func (v *TextMark) SetVisible(setting bool) {
	C.gtk_text_mark_set_visible(v.native(), gbool(setting))
}

// GetVisible is a wrapper around gtk_text_mark_get_visible().
func (v *TextMark) GetVisible() bool {
	return gobool(C.gtk_text_mark_get_visible(v.native()))
}

// GetDeleted is a wrapper around gtk_text_mark_get_deleted().
func (v *TextMark) GetDeleted() bool {
	return gobool(C.gtk_text_mark_get_deleted(v.native()))
}

// GetName is a wrapper around gtk_text_mark_get_name().
func (v *TextMark) GetName() string {
	return goString(C.gtk_text_mark_get_name(v.native()))
}

// GetBuffer is a wrapper around gtk_text_mark_get_buffer().
func (v *TextMark) GetBuffer() (*TextBuffer, error) {
	c := C.gtk_text_mark_get_buffer(v.native())
	if c == nil {
		return nil, nilPtrErr
	}
	return wrapTextBuffer(glib.Take(unsafe.Pointer(c))), nil
}

// GetLeftGravity is a wrapper around gtk_text_mark_get_left_gravity().
func (v *TextMark) GetLeftGravity() bool {
	return gobool(C.gtk_text_mark_get_left_gravity(v.native()))
}
<|endoftext|>


<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 mqtt

import (
	"fmt"

	. "github.com/TheThingsNetwork/ttn/core/errors"
	"github.com/TheThingsNetwork/ttn/utils/errors"
	db "github.com/TheThingsNetwork/ttn/utils/storage"
)

// !!!!!!!!!!!!!!!!!!!!!!!!
// NOTE THIS IS NOT THE ADAPTER ROLE -> SHOULD BE MOVED TO HANDLER
// !!!!!!!!!!!!!!!!!!!!!!!!

// Storage defines an interface for the mqtt adapter
type Storage interface {
	Push(topic string, data []byte) error
	Pull(topic string) ([]byte, error)
}

// type storage materializes a concrete mqtt.Storage
type storage struct {
	db.Interface
	Name string
}

// Storage entry implements the storage.StorageEntry interface
type storageEntry struct {
	Data []byte
}

// NewStorage creates a new mqtt.Storage
func NewStorage(name string) (Storage, error) {
	itf, err := db.New(name)
	if err != nil {
		return nil, errors.New(ErrFailedOperation, err)
	}

	tableName := "mqtt_adapter"
	if err := itf.Init(tableName); err != nil {
		return nil, errors.New(ErrFailedOperation, err)
	}
	return storage{Interface: itf, Name: tableName}, nil
}

// Push implements the Storage interface
func (s storage) Push(topic string, data []byte) error {
	err := s.Store(s.Name, []byte(topic), []db.StorageEntry{&storageEntry{data}})
	if err != nil {
		return errors.New(ErrFailedOperation, err)
	}
	return nil
}

// Pull implements the Storage interface
func (s storage) Pull(topic string) ([]byte, error) {
	entries, err := s.Lookup(s.Name, []byte(topic), &storageEntry{})
	if err != nil {
		return nil, errors.New(ErrFailedOperation, err)
	}

	packets, ok := entries.([]*storageEntry)
	if !ok {
		return nil, errors.New(ErrFailedOperation, "Unable to retrieve data from db")
	}

	// NOTE: one day, those entry will be more complicated, with a ttl.
	// Here's the place where we should check for that. Cheers.
	if len(packets) == 0 {
		return nil, errors.New(ErrWrongBehavior, fmt.Sprintf("Entry not found for %s", topic))
	}

	pkt := packets[0]

	var newEntries []db.StorageEntry
	for _, p := range packets[1:] {
		newEntries = append(newEntries, p)
	}

	if err := s.Replace(s.Name, []byte(topic), newEntries); err != nil {
		return nil, errors.New(ErrFailedOperation, "Unable to restore data in db")
	}

	return pkt.Data, nil
}

// MarshalBinary implements the encoding.BinaryMarshaler interface
func (e storageEntry) MarshalBinary() ([]byte, error) {
	return e.Data, nil
}

// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
func (e *storageEntry) UnmarshalBinary(data []byte) error {
	if e == nil {
		return errors.New(ErrInvalidStructure, "Unable to unmarshal nil entry")
	}
	e.Data = data
	return nil
}
<commit_msg>[refactor] Remove old and not accurate mqttStorage<commit_after><|endoftext|>