<commit_before>package convox

import (
	"fmt"

	"github.com/hashicorp/terraform/helper/schema"
)

// ResourceConvoxSyslog describes the schema for a Convox Syslog Resource resource
func ResourceConvoxSyslog(clientUnpacker ClientUnpacker) *schema.Resource {
	return &schema.Resource{
		Schema: map[string]*schema.Schema{
			"name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"hostname": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},
			"port": &schema.Schema{
				Type:     schema.TypeInt,
				Required: true,
			},
			"scheme": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},
			"private": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},
			"url": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
		},
		Create: ResourceConvoxSyslogCreateFactory(clientUnpacker),
		Read:   ResourceConvoxSyslogReadFactory(clientUnpacker),
		Update: ResourceConvoxSyslogUpdateFactory(clientUnpacker),
		Delete: ResourceConvoxSyslogDeleteFactory(clientUnpacker),
	}
}

func formURLString(d *schema.ResourceData) string {
	return fmt.Sprintf("%s://%s:%d", d.Get("scheme"), d.Get("hostname"), d.Get("port"))
}

// ResourceConvoxSyslogCreateFactory builds the Convox Syslog CreateFunc
func ResourceConvoxSyslogCreateFactory(clientUnpacker ClientUnpacker) schema.CreateFunc {
	if clientUnpacker == nil {
		panic("clientUnpacker is required")
	}

	return func(d *schema.ResourceData, meta interface{}) error {
		c, err := clientUnpacker(d, meta)
		if err != nil {
			return fmt.Errorf("Error unpacking client in CreateFunc: %s", err.Error())
		}

		options := map[string]string{
			"name":    d.Get("name").(string),
			"Url":     formURLString(d),
			"Private": fmt.Sprintf("%v", d.Get("private")),
		}

		_, err = c.CreateResource("syslog", options)
		if err != nil {
			return fmt.Errorf("Error calling CreateResource: %s -- %v", err.Error(), options)
		}

		// TODO: probably need to wait here for the status to stabilize. (and in update)

		d.Set("url", options["Url"])

		return nil
	}
}

// ResourceConvoxSyslogReadFactory builds the ReadFunc for the Convox Syslog Resource
func ResourceConvoxSyslogReadFactory(clientUnpacker ClientUnpacker) schema.ReadFunc {
	if clientUnpacker == nil {
		panic("clientUnpacker is required")
	}

	return func(d *schema.ResourceData, meta interface{}) error {
		if d == nil {
			panic("d is required")
		}

		if meta == nil {
			panic("meta is required")
		}

		c, err := clientUnpacker(d, meta)
		if err != nil {
			return fmt.Errorf("Error getting client in ReadFunc: %s", err.Error())
		}

		name := d.Get("name").(string)
		convoxResource, err := c.GetResource(name)
		if err != nil {
			return fmt.Errorf("Error calling GetResource: %s", err.Error())
		}

		d.Set("url", convoxResource.Exports["URL"])

		return nil
	}
}

// ResourceConvoxSyslogUpdateFactory creates the UpdateFunc for the Convox Syslog Resource
func ResourceConvoxSyslogUpdateFactory(clientUnpacker ClientUnpacker) schema.UpdateFunc {
	if clientUnpacker == nil {
		panic("clientUnpacker is required")
	}

	return func(d *schema.ResourceData, meta interface{}) error {
		if d == nil {
			panic("d is required")
		}

		if meta == nil {
			panic("meta is required")
		}

		c, err := clientUnpacker(d, meta)
		if err != nil {
			return err
		}

		options := map[string]string{
			"Url":     formURLString(d),
			"Private": fmt.Sprintf("%v", d.Get("private")),
		}

		_, err = c.UpdateResource(d.Get("name").(string), options)
		if err != nil {
			return fmt.Errorf("Error calling UpdateResource: %s -- %v", err.Error(), options)
		}

		d.Set("url", options["Url"])

		return nil
	}
}

// ResourceConvoxSyslogDeleteFactory builds the DeleteFunc for thw Convox Syslog Resource
func ResourceConvoxSyslogDeleteFactory(clientUnpacker ClientUnpacker) schema.DeleteFunc {
	if clientUnpacker == nil {
		panic("clientUnpacker is required")
	}

	return func(d *schema.ResourceData, meta interface{}) error {
		if d == nil {
			panic("d is required")
		}

		if meta == nil {
			panic("meta is required")
		}

		c, err := clientUnpacker(d, meta)
		if err != nil {
			return err
		}

		_, err = c.DeleteResource(d.Get("name").(string))
		if err != nil {
			return fmt.Errorf("Error calling DeleteResource: %s", err.Error())
		}

		return nil
	}
}
<commit_msg>_no_ err without context?<commit_after>package convox

import (
	"fmt"

	"github.com/hashicorp/terraform/helper/schema"
)

// ResourceConvoxSyslog describes the schema for a Convox Syslog Resource resource
func ResourceConvoxSyslog(clientUnpacker ClientUnpacker) *schema.Resource {
	return &schema.Resource{
		Schema: map[string]*schema.Schema{
			"name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"hostname": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},
			"port": &schema.Schema{
				Type:     schema.TypeInt,
				Required: true,
			},
			"scheme": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},
			"private": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},
			"url": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
		},
		Create: ResourceConvoxSyslogCreateFactory(clientUnpacker),
		Read:   ResourceConvoxSyslogReadFactory(clientUnpacker),
		Update: ResourceConvoxSyslogUpdateFactory(clientUnpacker),
		Delete: ResourceConvoxSyslogDeleteFactory(clientUnpacker),
	}
}

func formURLString(d *schema.ResourceData) string {
	return fmt.Sprintf("%s://%s:%d", d.Get("scheme"), d.Get("hostname"), d.Get("port"))
}

// ResourceConvoxSyslogCreateFactory builds the Convox Syslog CreateFunc
func ResourceConvoxSyslogCreateFactory(clientUnpacker ClientUnpacker) schema.CreateFunc {
	if clientUnpacker == nil {
		panic("clientUnpacker is required")
	}

	return func(d *schema.ResourceData, meta interface{}) error {
		c, err := clientUnpacker(d, meta)
		if err != nil {
			return fmt.Errorf("Error unpacking client in CreateFunc: %s", err.Error())
		}

		options := map[string]string{
			"name":    d.Get("name").(string),
			"Url":     formURLString(d),
			"Private": fmt.Sprintf("%v", d.Get("private")),
		}

		_, err = c.CreateResource("syslog", options)
		if err != nil {
			return fmt.Errorf("Error calling CreateResource: %s -- %v", err.Error(), options)
		}

		// TODO: probably need to wait here for the status to stabilize. (and in update)

		d.Set("url", options["Url"])

		return nil
	}
}

// ResourceConvoxSyslogReadFactory builds the ReadFunc for the Convox Syslog Resource
func ResourceConvoxSyslogReadFactory(clientUnpacker ClientUnpacker) schema.ReadFunc {
	if clientUnpacker == nil {
		panic("clientUnpacker is required")
	}

	return func(d *schema.ResourceData, meta interface{}) error {
		if d == nil {
			panic("d is required")
		}

		if meta == nil {
			panic("meta is required")
		}

		c, err := clientUnpacker(d, meta)
		if err != nil {
			return fmt.Errorf("Error getting client in ReadFunc: %s", err.Error())
		}

		name := d.Get("name").(string)
		convoxResource, err := c.GetResource(name)
		if err != nil {
			return fmt.Errorf("Error calling GetResource: %s", err.Error())
		}

		d.Set("url", convoxResource.Exports["URL"])

		return nil
	}
}

// ResourceConvoxSyslogUpdateFactory creates the UpdateFunc for the Convox Syslog Resource
func ResourceConvoxSyslogUpdateFactory(clientUnpacker ClientUnpacker) schema.UpdateFunc {
	if clientUnpacker == nil {
		panic("clientUnpacker is required")
	}

	return func(d *schema.ResourceData, meta interface{}) error {
		if d == nil {
			panic("d is required")
		}

		if meta == nil {
			panic("meta is required")
		}

		c, err := clientUnpacker(d, meta)
		if err != nil {
			return fmt.Errorf("Error getting client in UpdateFunc: %s", err.Error())
		}

		options := map[string]string{
			"Url":     formURLString(d),
			"Private": fmt.Sprintf("%v", d.Get("private")),
		}

		_, err = c.UpdateResource(d.Get("name").(string), options)
		if err != nil {
			return fmt.Errorf("Error calling UpdateResource: %s -- %v", err.Error(), options)
		}

		d.Set("url", options["Url"])

		return nil
	}
}

// ResourceConvoxSyslogDeleteFactory builds the DeleteFunc for thw Convox Syslog Resource
func ResourceConvoxSyslogDeleteFactory(clientUnpacker ClientUnpacker) schema.DeleteFunc {
	if clientUnpacker == nil {
		panic("clientUnpacker is required")
	}

	return func(d *schema.ResourceData, meta interface{}) error {
		if d == nil {
			panic("d is required")
		}

		if meta == nil {
			panic("meta is required")
		}

		c, err := clientUnpacker(d, meta)
		if err != nil {
			return fmt.Errorf("Error getting client in DeleteFunc: %s", err.Error())
		}

		_, err = c.DeleteResource(d.Get("name").(string))
		if err != nil {
			return fmt.Errorf("Error calling DeleteResource: %s", err.Error())
		}

		return nil
	}
}
<|endoftext|>


<commit_before>package components

import (
	"testing"

	"github.com/scipipe/scipipe"
)

func TestCommandToParams(tt *testing.T) {
	// Run test workflow and make sure that the parameter read from the file is
	// always "abc"
	wf := scipipe.NewWorkflow("wf", 4)

	cmdToParams := NewCommandToParams(wf, "cmdtoparams", "echo foo; echo bar; echo baz;")

	checker := wf.NewProc("checker", "# {p:param}")
	checker.CustomExecute = func(t *scipipe.Task) {
		expected := []string{"foo", "bar", "baz"}
		actual := t.Param("param")
		if actual != expected[0] && actual != expected[1] && actual != expected[2] {
			tt.Errorf("Actual string (%s) was not one of the expected ones (%s, %s, %s)", actual, expected[0], expected[1], expected[2])
		}
	}
	checker.InParam("param").From(cmdToParams.OutParam())

	wf.Run()
}
<commit_msg>Improve shell command in test<commit_after>package components

import (
	"testing"

	"github.com/scipipe/scipipe"
)

func TestCommandToParams(tt *testing.T) {
	// Run test workflow and make sure that the parameter read from the file is
	// always "abc"
	wf := scipipe.NewWorkflow("wf", 4)

	cmdToParams := NewCommandToParams(wf, "cmdtoparams", "{ echo foo; echo bar; echo baz; }")

	checker := wf.NewProc("checker", "# {p:param}")
	checker.CustomExecute = func(t *scipipe.Task) {
		expected := []string{"foo", "bar", "baz"}
		actual := t.Param("param")
		if actual != expected[0] && actual != expected[1] && actual != expected[2] {
			tt.Errorf("Actual string (%s) was not one of the expected ones (%s, %s, %s)", actual, expected[0], expected[1], expected[2])
		}
	}
	checker.InParam("param").From(cmdToParams.OutParam())

	wf.Run()
}
<|endoftext|>


<commit_before>// This file is part of Monsti, a web content management system.
// Copyright 2012-2013 Christian Neumann
//
// Monsti is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option) any
// later version.
//
// Monsti is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with Monsti.  If not, see <http://www.gnu.org/licenses/>.

package service

import (
	"fmt"
	"html/template"
	"path"
	"strings"
	"time"

	"github.com/chrneumann/htmlwidgets"
	"pkg.monsti.org/gettext"
	"pkg.monsti.org/monsti/api/util"
)

type Field interface {
	// RenderHTML returns a string or template.HTML to be used in a html
	// template.
	RenderHTML() interface{}
	// String returns a raw string representation of the field.
	String() string
	// Load loads the field data (also see Dump).
	Load(interface{}) error
	// Dump dumps the field data.
	//
	// The dumped value must be something that can be marshalled into
	// JSON by encoding/json.
	Dump() interface{}
	// Adds a form field to the node edit form.
	ToFormField(*htmlwidgets.Form, util.NestedMap, *NodeField, string)
	// Load values from the form submission
	FromFormField(util.NestedMap, *NodeField)
}

// TextField is a basic unicode text field
type TextField string

func (t TextField) String() string {
	return string(t)
}

func (t TextField) RenderHTML() interface{} {
	return t
}

func (t *TextField) Load(in interface{}) error {
	*t = TextField(in.(string))
	return nil
}

func (t TextField) Dump() interface{} {
	return string(t)
}

func (t TextField) ToFormField(form *htmlwidgets.Form, data util.NestedMap,
	field *NodeField, locale string) {
	data.Set(field.Id, string(t))
	G, _, _, _ := gettext.DefaultLocales.Use("", locale)
	form.AddWidget(&htmlwidgets.TextWidget{
		MinLength: 1, ValidationError: G("Required.")}, "Fields."+field.Id,
		field.Name[locale], "")
}

func (t *TextField) FromFormField(data util.NestedMap, field *NodeField) {
	*t = TextField(data.Get(field.Id).(string))
}

// HTMLField is a text area containing HTML code
type HTMLField string

func (t HTMLField) String() string {
	return string(t)
}

func (t HTMLField) RenderHTML() interface{} {
	return template.HTML(t)
}

func (t *HTMLField) Load(in interface{}) error {
	*t = HTMLField(in.(string))
	return nil
}

func (t HTMLField) Dump() interface{} {
	return string(t)
}

func (t HTMLField) ToFormField(form *htmlwidgets.Form, data util.NestedMap,
	field *NodeField, locale string) {
	//G, _, _, _ := gettext.DefaultLocales.Use("", locale)
	data.Set(field.Id, string(t))
	widget := form.AddWidget(new(htmlwidgets.TextAreaWidget), "Fields."+field.Id,
		field.Name[locale], "")
	widget.Base().Classes = []string{"html-field"}
}

func (t *HTMLField) FromFormField(data util.NestedMap, field *NodeField) {
	*t = HTMLField(data.Get(field.Id).(string))
}

type FileField string

func (t FileField) String() string {
	return string(t)
}

func (t FileField) RenderHTML() interface{} {
	return template.HTML(t)
}

func (t *FileField) Load(in interface{}) error {
	*t = FileField(in.(string))
	return nil
}

func (t FileField) Dump() interface{} {
	return ""
}

func (t FileField) ToFormField(form *htmlwidgets.Form, data util.NestedMap,
	field *NodeField, locale string) {
	data.Set(field.Id, "")
	form.AddWidget(new(htmlwidgets.FileWidget), "Fields."+field.Id,
		field.Name[locale], "")
}

func (t *FileField) FromFormField(data util.NestedMap, field *NodeField) {
	*t = FileField(data.Get(field.Id).(string))
}

type DateTimeField time.Time

func (t DateTimeField) String() string {
	return time.Time(t).String()
}

func (t DateTimeField) RenderHTML() interface{} {
	return t.String()
}

func (t *DateTimeField) Load(in interface{}) error {
	date, ok := in.(string)
	if !ok {
		return fmt.Errorf("Data is not string")
	}
	val, err := time.Parse(time.RFC3339, date)
	if err != nil {
		return fmt.Errorf("Could not parse the date value: %v", err)
	}
	*t = DateTimeField(val)
	return nil
}

func (t DateTimeField) Dump() interface{} {
	return time.Time(t).Format(time.RFC3339)
}

func (t DateTimeField) ToFormField(form *htmlwidgets.Form, data util.NestedMap,
	field *NodeField, locale string) {
	data.Set(field.Id, time.Time(t))
	form.AddWidget(&htmlwidgets.TimeWidget{}, "Fields."+field.Id,
		field.Name[locale], "")
}

func (t *DateTimeField) FromFormField(data util.NestedMap, field *NodeField) {
	*t = DateTimeField(data.Get(field.Id).(time.Time))
}

type Node struct {
	Path string `json:",omitempty"`
	// Content type of the node.
	Type  *NodeType `json:"-"`
	Order int
	// Don't show the node in navigations if Hide is true.
	Hide   bool
	Fields map[string]Field `json:"-"`
}

func (n *Node) InitFields() {
	n.Fields = make(map[string]Field)
	for _, field := range n.Type.Fields {
		var val Field
		switch field.Type {
		case "DateTime":
			val = new(DateTimeField)
		case "File":
			val = new(FileField)
		case "Text":
			val = new(TextField)
		case "HTMLArea":
			val = new(HTMLField)
		default:
			panic(fmt.Sprintf("Unknown field type %v", field.Type))
		}
		n.Fields[field.Id] = val
	}
}

func (n Node) GetField(id string) Field {
	return n.Fields[id]
}

func (n Node) GetValue(id string) interface{} {
	return n.Fields[id]
}

// PathToID returns an ID for the given node based on it's path.
//
// The ID is simply the path of the node with all slashes replaced by two
// underscores and the result prefixed with "node-".
//
// PathToID will panic if the path is not set.
//
// For example, a node with path "/foo/bar" will get the ID "node-__foo__bar".
func (n Node) PathToID() string {
	if len(n.Path) == 0 {
		panic("Can't calculate ID of node with unset path.")
	}
	return "node-" + strings.Replace(n.Path, "/", "__", -1)
}

// Name returns the name of the node.
func (n Node) Name() string {
	base := path.Base(n.Path)
	if base == "." || base == "/" {
		return ""
	}
	return base
}

/*

// RequestFile stores the path or content of a multipart request's file.
type RequestFile struct {
	// TmpFile stores the path to a temporary file with the contents.
	TmpFile string
	// Content stores the file content if TmpFile is not set.
	Content []byte
}

// ReadFile returns the file's content. Uses io/ioutil ReadFile if the request
// file's content is in a temporary file.
func (r RequestFile) ReadFile() ([]byte, error) {
	if len(r.TmpFile) > 0 {
		return ioutil.ReadFile(r.TmpFile)
	}
	return r.Content, nil
}

type RequestMethod uint

const (
	GetRequest = iota
	PostRequest
)
*/

type Action uint

const (
	ViewAction = iota
	EditAction
	LoginAction
	LogoutAction
	AddAction
	RemoveAction
)

/*
// A request to be processed by a nodes service.
type Request struct {
	// Site name
	Site string
	// The requested node.
	Node Node
	// The query values of the request URL.
	Query url.Values
	// Method of the request (GET,POST,...).
	Method RequestMethod
	// User session
	Session UserSession
	// Action to perform (e.g. "edit").
	Action Action
	// FormData stores the requests form data.
	FormData url.Values
	// Files stores files of multipart requests.
	Files map[string][]RequestFile
}
*/

/*
// Response to a node request.
type Response struct {
	// The html content to be embedded in the root template.
	Body []byte
	// Raw must be set to true if Body should not be embedded in the root
	// template. The content type will be automatically detected.
	Raw bool
	// If set, redirect to this target using error 303 'see other'.
	Redirect string
	// The node as received by GetRequest, possibly with some fields
	// updated (e.g. modified title).
	//
	// If nil, the original node data is used.
	Node *Node
}
*/

/*
// Write appends the given bytes to the body of the response.
func (r *Response) Write(p []byte) (n int, err error) {
	r.Body = append(r.Body, p...)
	return len(p), nil
}
*/

/*
// Request performs the given request.
func (s *MonstiClient) Request(req *Request) (*Response, error) {
	var res Response
	err := s.RPCClient.Call("Monsti.Request", req, &res)
	if err != nil {
		return nil, fmt.Errorf("service: RPC error for Request: %v", err)
	}
	return &res, nil
}
*/

// GetNodeType returns all supported node types.
func (s *MonstiClient) GetNodeTypes() ([]string, error) {
	var res []string
	err := s.RPCClient.Call("Monsti.GetNodeTypes", 0, &res)
	if err != nil {
		return nil, fmt.Errorf("service: RPC error for GetNodeTypes: %v", err)
	}
	return res, nil
}
<commit_msg>Refactor DateTimeField.<commit_after>// This file is part of Monsti, a web content management system.
// Copyright 2012-2013 Christian Neumann
//
// Monsti is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option) any
// later version.
//
// Monsti is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with Monsti.  If not, see <http://www.gnu.org/licenses/>.

package service

import (
	"fmt"
	"html/template"
	"path"
	"strings"
	"time"

	"github.com/chrneumann/htmlwidgets"
	"pkg.monsti.org/gettext"
	"pkg.monsti.org/monsti/api/util"
)

type Field interface {
	// RenderHTML returns a string or template.HTML to be used in a html
	// template.
	RenderHTML() interface{}
	// String returns a raw string representation of the field.
	String() string
	// Load loads the field data (also see Dump).
	Load(interface{}) error
	// Dump dumps the field data.
	//
	// The dumped value must be something that can be marshalled into
	// JSON by encoding/json.
	Dump() interface{}
	// Adds a form field to the node edit form.
	ToFormField(*htmlwidgets.Form, util.NestedMap, *NodeField, string)
	// Load values from the form submission
	FromFormField(util.NestedMap, *NodeField)
}

// TextField is a basic unicode text field
type TextField string

func (t TextField) String() string {
	return string(t)
}

func (t TextField) RenderHTML() interface{} {
	return t
}

func (t *TextField) Load(in interface{}) error {
	*t = TextField(in.(string))
	return nil
}

func (t TextField) Dump() interface{} {
	return string(t)
}

func (t TextField) ToFormField(form *htmlwidgets.Form, data util.NestedMap,
	field *NodeField, locale string) {
	data.Set(field.Id, string(t))
	G, _, _, _ := gettext.DefaultLocales.Use("", locale)
	form.AddWidget(&htmlwidgets.TextWidget{
		MinLength: 1, ValidationError: G("Required.")}, "Fields."+field.Id,
		field.Name[locale], "")
}

func (t *TextField) FromFormField(data util.NestedMap, field *NodeField) {
	*t = TextField(data.Get(field.Id).(string))
}

// HTMLField is a text area containing HTML code
type HTMLField string

func (t HTMLField) String() string {
	return string(t)
}

func (t HTMLField) RenderHTML() interface{} {
	return template.HTML(t)
}

func (t *HTMLField) Load(in interface{}) error {
	*t = HTMLField(in.(string))
	return nil
}

func (t HTMLField) Dump() interface{} {
	return string(t)
}

func (t HTMLField) ToFormField(form *htmlwidgets.Form, data util.NestedMap,
	field *NodeField, locale string) {
	//G, _, _, _ := gettext.DefaultLocales.Use("", locale)
	data.Set(field.Id, string(t))
	widget := form.AddWidget(new(htmlwidgets.TextAreaWidget), "Fields."+field.Id,
		field.Name[locale], "")
	widget.Base().Classes = []string{"html-field"}
}

func (t *HTMLField) FromFormField(data util.NestedMap, field *NodeField) {
	*t = HTMLField(data.Get(field.Id).(string))
}

type FileField string

func (t FileField) String() string {
	return string(t)
}

func (t FileField) RenderHTML() interface{} {
	return template.HTML(t)
}

func (t *FileField) Load(in interface{}) error {
	*t = FileField(in.(string))
	return nil
}

func (t FileField) Dump() interface{} {
	return ""
}

func (t FileField) ToFormField(form *htmlwidgets.Form, data util.NestedMap,
	field *NodeField, locale string) {
	data.Set(field.Id, "")
	form.AddWidget(new(htmlwidgets.FileWidget), "Fields."+field.Id,
		field.Name[locale], "")
}

func (t *FileField) FromFormField(data util.NestedMap, field *NodeField) {
	*t = FileField(data.Get(field.Id).(string))
}

type DateTimeField struct {
	time.Time
}

func (t DateTimeField) RenderHTML() interface{} {
	return t.String()
}

func (t *DateTimeField) Load(in interface{}) error {
	date, ok := in.(string)
	if !ok {
		return fmt.Errorf("Data is not string")
	}
	val, err := time.Parse(time.RFC3339, date)
	if err != nil {
		return fmt.Errorf("Could not parse the date value: %v", err)
	}
	*t = DateTimeField{Time: val}
	return nil
}

func (t DateTimeField) Dump() interface{} {
	return t.Format(time.RFC3339)
}

func (t DateTimeField) ToFormField(form *htmlwidgets.Form, data util.NestedMap,
	field *NodeField, locale string) {
	data.Set(field.Id, t.Time)
	form.AddWidget(&htmlwidgets.TimeWidget{}, "Fields."+field.Id,
		field.Name[locale], "")
}

func (t *DateTimeField) FromFormField(data util.NestedMap, field *NodeField) {
	*t = DateTimeField{Time: data.Get(field.Id).(time.Time)}
}

type Node struct {
	Path string `json:",omitempty"`
	// Content type of the node.
	Type  *NodeType `json:"-"`
	Order int
	// Don't show the node in navigations if Hide is true.
	Hide   bool
	Fields map[string]Field `json:"-"`
}

func (n *Node) InitFields() {
	n.Fields = make(map[string]Field)
	for _, field := range n.Type.Fields {
		var val Field
		switch field.Type {
		case "DateTime":
			val = new(DateTimeField)
		case "File":
			val = new(FileField)
		case "Text":
			val = new(TextField)
		case "HTMLArea":
			val = new(HTMLField)
		default:
			panic(fmt.Sprintf("Unknown field type %v", field.Type))
		}
		n.Fields[field.Id] = val
	}
}

func (n Node) GetField(id string) Field {
	return n.Fields[id]
}

func (n Node) GetValue(id string) interface{} {
	return n.Fields[id]
}

// PathToID returns an ID for the given node based on it's path.
//
// The ID is simply the path of the node with all slashes replaced by two
// underscores and the result prefixed with "node-".
//
// PathToID will panic if the path is not set.
//
// For example, a node with path "/foo/bar" will get the ID "node-__foo__bar".
func (n Node) PathToID() string {
	if len(n.Path) == 0 {
		panic("Can't calculate ID of node with unset path.")
	}
	return "node-" + strings.Replace(n.Path, "/", "__", -1)
}

// Name returns the name of the node.
func (n Node) Name() string {
	base := path.Base(n.Path)
	if base == "." || base == "/" {
		return ""
	}
	return base
}

/*

// RequestFile stores the path or content of a multipart request's file.
type RequestFile struct {
	// TmpFile stores the path to a temporary file with the contents.
	TmpFile string
	// Content stores the file content if TmpFile is not set.
	Content []byte
}

// ReadFile returns the file's content. Uses io/ioutil ReadFile if the request
// file's content is in a temporary file.
func (r RequestFile) ReadFile() ([]byte, error) {
	if len(r.TmpFile) > 0 {
		return ioutil.ReadFile(r.TmpFile)
	}
	return r.Content, nil
}

type RequestMethod uint

const (
	GetRequest = iota
	PostRequest
)
*/

type Action uint

const (
	ViewAction = iota
	EditAction
	LoginAction
	LogoutAction
	AddAction
	RemoveAction
)

/*
// A request to be processed by a nodes service.
type Request struct {
	// Site name
	Site string
	// The requested node.
	Node Node
	// The query values of the request URL.
	Query url.Values
	// Method of the request (GET,POST,...).
	Method RequestMethod
	// User session
	Session UserSession
	// Action to perform (e.g. "edit").
	Action Action
	// FormData stores the requests form data.
	FormData url.Values
	// Files stores files of multipart requests.
	Files map[string][]RequestFile
}
*/

/*
// Response to a node request.
type Response struct {
	// The html content to be embedded in the root template.
	Body []byte
	// Raw must be set to true if Body should not be embedded in the root
	// template. The content type will be automatically detected.
	Raw bool
	// If set, redirect to this target using error 303 'see other'.
	Redirect string
	// The node as received by GetRequest, possibly with some fields
	// updated (e.g. modified title).
	//
	// If nil, the original node data is used.
	Node *Node
}
*/

/*
// Write appends the given bytes to the body of the response.
func (r *Response) Write(p []byte) (n int, err error) {
	r.Body = append(r.Body, p...)
	return len(p), nil
}
*/

/*
// Request performs the given request.
func (s *MonstiClient) Request(req *Request) (*Response, error) {
	var res Response
	err := s.RPCClient.Call("Monsti.Request", req, &res)
	if err != nil {
		return nil, fmt.Errorf("service: RPC error for Request: %v", err)
	}
	return &res, nil
}
*/

// GetNodeType returns all supported node types.
func (s *MonstiClient) GetNodeTypes() ([]string, error) {
	var res []string
	err := s.RPCClient.Call("Monsti.GetNodeTypes", 0, &res)
	if err != nil {
		return nil, fmt.Errorf("service: RPC error for GetNodeTypes: %v", err)
	}
	return res, nil
}
<|endoftext|>


<commit_before>package legacy_test

import (
	"testing"

	"github.com/m-lab/annotation-service/legacy"
)

func TestOpenAndFree(t *testing.T) {
	file := "./testdata/GeoLiteCity.dat"

	gi, err := legacy.Open(file, "GeoLiteCity.dat")

	if err != nil {
		t.Error(err)
	}

	if gi == nil {
		t.Fatal("legacy file not loaded")
	}
	gi.Free()

	if gi.Check() {
		t.Error("Not correctly freed")
	}
}
<commit_msg>Update geoip_test.go<commit_after>package legacy_test

import (
	"testing"

	"github.com/m-lab/annotation-service/legacy"
)

func TestOpenAndFree(t *testing.T) {
	file := "./testdata/GeoLiteCity.dat"

	gi, err := legacy.Open(file, "GeoLiteCity.dat")

	if err != nil {
		t.Error(err)
	}

	if gi == nil {
		t.Fatal("legacy file not loaded")
	}
	gi.Free()
}
<|endoftext|>


<commit_before>package symlink

import (
	"fmt"
	"io"
	"os"
	"os/exec"
	"strings"
	"testing"
)

// Making a symlink means:
// - making sure the destination exists
// - making sure the source don't exist and the parent folder is created
// - if the source does exist and
//   - is a symlink pointing to a different destination: rmdir
//   - is a symlink pointing to the same
//   - is a folder x, rename it to x.1 (if x.1 exists, x.2, ...)

type test struct {
	src string
	dst string
	err string
	sl  *SL
}

func TestDestination(t *testing.T) {
	t.Skip("Skip TestDestination")
	// only a nil bit will make filepath.Abs() fail:
	// https://github.com/golang/go/blob/d16c7f8004bd1c9f896367af7ea86f5530596b39/src/syscall/syscall_windows.go#L41
	// from UTF16FromString (https://github.com/golang/go/blob/d16c7f8004bd1c9f896367af7ea86f5530596b39/src/syscall/syscall_windows.go#L71)
	// from FullPath (https://github.com/golang/go/blob/d16c7f8004bd1c9f896367af7ea86f5530596b39/src/syscall/exec_windows.go#L134)
	// from abs (https://github.com/golang/go/blob/d16c7f8004bd1c9f896367af7ea86f5530596b39/src/path/filepath/path_windows.go#L109)
	// from Abs (https://github.com/golang/go/blob/d16c7f8004bd1c9f896367af7ea86f5530596b39/src/path/filepath/path.go#L235)

	osStat = testOsStat
	execRun = testExecRun
	tests := []*test{
		&test{dst: "unknown/dst", err: "The system cannot find the path specified"},
		&test{dst: string([]byte{0}), err: "invalid argument"},
		&test{dst: "err", err: "Test error on os.Stat with non-nil fi"},
		&test{dst: "badsymlink/dir", err: "unreadable dir on symlink"},
		&test{dst: "nojunction/dir", err: "Unable to find junction symlink in parent dir"},
		&test{dst: "cmdRun/dir", err: "The system cannot find the file specified"},
		&test{dst: "WarningOnDir/dir", err: "Warning on run"},
	}
	var sl *SL
	var err error
	for _, test := range tests {
		sl, err = New(".", test.dst)
		if err == nil || strings.Contains(err.Error(), test.err) == false {
			t.Errorf("Err '%v', expected '%s'", err, test.err)
		}
		if sl != nil {
			t.Errorf("SL '%v', expected <nil>", sl)
		}
	}
	// destination is a symlink
	_, err = New(`.`, `symlink`)
	// destination exists
	_, err = New(`x`, `.`)
	// fmt.Printf("%+v\n", err)
}

func TestSource(t *testing.T) {
	osStat = testOsStat
	execRun = testExecRun
	osMkdirAll = testOsMkdirAll
	osRename = testOsRename

	tests := []*test{
		// &test{src: "parentNotYetCreated/newlink"},
		// &test{src: "badSrcParent/newlink", err: "Test error badSrcParent on os.Stat with non-nil fi"},
		// &test{src: "badSrcParentMdirAll/newlink", err: "Error on mkDirAll for"},
		&test{src: "symlinkdir/newlink", err: ""},
		&test{src: "badsrcparentdir/newlink", err: "Impossible to check/access link parent folder"},
	}
	var sl *SL
	var err error
	for _, test := range tests {
		sl, err = New(test.src, ".")
		if err != nil && strings.Contains(err.Error(), test.err) == false {
			t.Errorf("Err '%v', expected '%s'", err, test.err)
		}
		if err == nil && test.err != "" {
			t.Errorf("Err nil, expected '%s'", test.err)
		}
		if sl == nil && err == nil {
			t.Errorf("SL '%v', expected NOT <nil>", sl)
		}
	}
}

func testOsStat(name string) (os.FileInfo, error) {
	fmt.Printf("testOsStat name='%+v'\n", name)
	if strings.HasSuffix(name, `prj\symlink\err\`) {
		fi, _ := os.Stat(".")
		return fi, fmt.Errorf("Test error on os.Stat with non-nil fi")
	}
	if strings.HasSuffix(name, `prj\symlink\symlink\`) {
		fi, _ := os.Stat(".")
		return fi, fmt.Errorf("readlink for symlink")
	}
	if strings.HasSuffix(name, `prj\symlink\badsymlink\dir\`) {
		fi, _ := os.Stat(".")
		return fi, fmt.Errorf("readlink for bad symlink")
	}
	if strings.HasSuffix(name, `prj\symlink\nojunction\dir\`) {
		fi, _ := os.Stat(".")
		return fi, fmt.Errorf("readlink for no junction")
	}
	if strings.HasSuffix(name, `prj\symlink\cmdRun\dir\`) {
		fi, _ := os.Stat(".")
		return fi, fmt.Errorf("readlink for no junction")
	}
	if strings.HasSuffix(name, `prj\symlink\WarningOnDir\dir\`) {
		fi, _ := os.Stat(".")
		return fi, fmt.Errorf("readlink for warning on dir")
	}
	if strings.HasSuffix(name, `prj\symlink\badSrcParent\`) {
		fi, _ := os.Stat(".")
		return fi, fmt.Errorf("Test error badSrcParent on os.Stat with non-nil fi")
	}
	if strings.HasSuffix(name, `prj\symlink\symlinkdir\`) {
		fi, _ := os.Stat(".")
		return fi, fmt.Errorf("readlink for symlinkdir")
	}
	if strings.HasSuffix(name, `prj\symlink\badsrcparentdir\`) {
		return nil, fmt.Errorf("badsrcparentdir cannot be stat'd")
	}
	if strings.HasSuffix(name, `.1`) {
		fi, _ := os.Stat(".")
		return fi, nil
	}
	return os.Stat(name)
}

func testOsMkdirAll(path string, perm os.FileMode) error {
	fmt.Printf("testOsMkdirAll path='%+v'\n", path)
	if strings.HasSuffix(path, `badSrcParentMdirAll\`) {
		return fmt.Errorf("Error on mkDirAll for '%s'", path)
	}
	return nil
}

var junctionOut = `
 Répertoire de C:\Users\VonC\prog\git\ggb\deps\src\github.com\VonC

22/06/2015  11:03    <REP>          .
22/06/2015  11:03    <REP>          ..
22/06/2015  11:03    <JONCTION>     symlink [C:\Users\VonC\prog\git\ggb\]
22/06/2015  11:03    <JONCTION>     symlinkdir [C:\Users\VonC\prog\git\ggb\]`

func testExecRun(cmd *exec.Cmd) error {
	tmsg := fmt.Sprintf("testExecRun cmd='%v' in '%s'", cmd.Args, cmd.Dir)
	fmt.Println(tmsg)
	if strings.Contains(tmsg, "/J") {
		return nil
	}
	if strings.HasSuffix(cmd.Dir, `\WarningOnDir`) {
		io.WriteString(cmd.Stdout, "dummy content")
		io.WriteString(cmd.Stderr, "Some warning on dir")
		return nil
	}
	if strings.HasSuffix(cmd.Dir, `\nojunction`) {
		io.WriteString(cmd.Stdout, "dummy content without any junction")
		return nil
	}
	if strings.HasSuffix(cmd.Dir, `\badsymlink`) {
		return fmt.Errorf("unreadable dir on symlink")
	}
	if strings.HasSuffix(cmd.Dir, `\symlink`) {
		io.WriteString(cmd.Stdout, junctionOut)
		return nil
	}
	return cmdRun(cmd)
}

func testOsRename(oldpath, newpath string) error {
	fmt.Printf("testOsRename oldpath='%v', newpath '%s'\n", oldpath, newpath)
	return nil
}
<commit_msg>symlink_test.go: test test bad src absolute path<commit_after>package symlink

import (
	"fmt"
	"io"
	"os"
	"os/exec"
	"strings"
	"testing"
)

// Making a symlink means:
// - making sure the destination exists
// - making sure the source don't exist and the parent folder is created
// - if the source does exist and
//   - is a symlink pointing to a different destination: rmdir
//   - is a symlink pointing to the same
//   - is a folder x, rename it to x.1 (if x.1 exists, x.2, ...)

type test struct {
	src string
	dst string
	err string
	sl  *SL
}

func TestDestination(t *testing.T) {
	t.Skip("Skip TestDestination")
	// only a nil bit will make filepath.Abs() fail:
	// https://github.com/golang/go/blob/d16c7f8004bd1c9f896367af7ea86f5530596b39/src/syscall/syscall_windows.go#L41
	// from UTF16FromString (https://github.com/golang/go/blob/d16c7f8004bd1c9f896367af7ea86f5530596b39/src/syscall/syscall_windows.go#L71)
	// from FullPath (https://github.com/golang/go/blob/d16c7f8004bd1c9f896367af7ea86f5530596b39/src/syscall/exec_windows.go#L134)
	// from abs (https://github.com/golang/go/blob/d16c7f8004bd1c9f896367af7ea86f5530596b39/src/path/filepath/path_windows.go#L109)
	// from Abs (https://github.com/golang/go/blob/d16c7f8004bd1c9f896367af7ea86f5530596b39/src/path/filepath/path.go#L235)

	osStat = testOsStat
	execRun = testExecRun
	tests := []*test{
		&test{dst: "unknown/dst", err: "The system cannot find the path specified"},
		&test{dst: string([]byte{0}), err: "invalid argument"},
		&test{dst: "err", err: "Test error on os.Stat with non-nil fi"},
		&test{dst: "badsymlink/dir", err: "unreadable dir on symlink"},
		&test{dst: "nojunction/dir", err: "Unable to find junction symlink in parent dir"},
		&test{dst: "cmdRun/dir", err: "The system cannot find the file specified"},
		&test{dst: "WarningOnDir/dir", err: "Warning on run"},
	}
	var sl *SL
	var err error
	for _, test := range tests {
		sl, err = New(".", test.dst)
		if err == nil || strings.Contains(err.Error(), test.err) == false {
			t.Errorf("Err '%v', expected '%s'", err, test.err)
		}
		if sl != nil {
			t.Errorf("SL '%v', expected <nil>", sl)
		}
	}
	// destination is a symlink
	_, err = New(`.`, `symlink`)
	// destination exists
	_, err = New(`x`, `.`)
	// fmt.Printf("%+v\n", err)
}

func TestSource(t *testing.T) {
	osStat = testOsStat
	execRun = testExecRun
	osMkdirAll = testOsMkdirAll
	osRename = testOsRename

	tests := []*test{
		// &test{src: "parentNotYetCreated/newlink"},
		// &test{src: "badSrcParent/newlink", err: "Test error badSrcParent on os.Stat with non-nil fi"},
		// &test{src: "badSrcParentMdirAll/newlink", err: "Error on mkDirAll for"},
		&test{src: "symlinkdir/newlink", err: ""},
		&test{src: "badsrcparentdir/newlink", err: "Impossible to check/access link parent folder"},
		&test{src: string([]byte{0}), err: "invalid argument"},
	}
	var sl *SL
	var err error
	for _, test := range tests {
		sl, err = New(test.src, ".")
		if err != nil && strings.Contains(err.Error(), test.err) == false {
			t.Errorf("Err '%v', expected '%s'", err, test.err)
		}
		if err == nil && test.err != "" {
			t.Errorf("Err nil, expected '%s'", test.err)
		}
		if sl == nil && err == nil {
			t.Errorf("SL '%v', expected NOT <nil>", sl)
		}
	}
}

func testOsStat(name string) (os.FileInfo, error) {
	fmt.Printf("testOsStat name='%+v'\n", name)
	if strings.HasSuffix(name, `prj\symlink\err\`) {
		fi, _ := os.Stat(".")
		return fi, fmt.Errorf("Test error on os.Stat with non-nil fi")
	}
	if strings.HasSuffix(name, `prj\symlink\symlink\`) {
		fi, _ := os.Stat(".")
		return fi, fmt.Errorf("readlink for symlink")
	}
	if strings.HasSuffix(name, `prj\symlink\badsymlink\dir\`) {
		fi, _ := os.Stat(".")
		return fi, fmt.Errorf("readlink for bad symlink")
	}
	if strings.HasSuffix(name, `prj\symlink\nojunction\dir\`) {
		fi, _ := os.Stat(".")
		return fi, fmt.Errorf("readlink for no junction")
	}
	if strings.HasSuffix(name, `prj\symlink\cmdRun\dir\`) {
		fi, _ := os.Stat(".")
		return fi, fmt.Errorf("readlink for no junction")
	}
	if strings.HasSuffix(name, `prj\symlink\WarningOnDir\dir\`) {
		fi, _ := os.Stat(".")
		return fi, fmt.Errorf("readlink for warning on dir")
	}
	if strings.HasSuffix(name, `prj\symlink\badSrcParent\`) {
		fi, _ := os.Stat(".")
		return fi, fmt.Errorf("Test error badSrcParent on os.Stat with non-nil fi")
	}
	if strings.HasSuffix(name, `prj\symlink\symlinkdir\`) {
		fi, _ := os.Stat(".")
		return fi, fmt.Errorf("readlink for symlinkdir")
	}
	if strings.HasSuffix(name, `prj\symlink\badsrcparentdir\`) {
		return nil, fmt.Errorf("badsrcparentdir cannot be stat'd")
	}
	if strings.HasSuffix(name, `.1`) {
		fi, _ := os.Stat(".")
		return fi, nil
	}
	return os.Stat(name)
}

func testOsMkdirAll(path string, perm os.FileMode) error {
	fmt.Printf("testOsMkdirAll path='%+v'\n", path)
	if strings.HasSuffix(path, `badSrcParentMdirAll\`) {
		return fmt.Errorf("Error on mkDirAll for '%s'", path)
	}
	return nil
}

var junctionOut = `
 Répertoire de C:\Users\VonC\prog\git\ggb\deps\src\github.com\VonC

22/06/2015  11:03    <REP>          .
22/06/2015  11:03    <REP>          ..
22/06/2015  11:03    <JONCTION>     symlink [C:\Users\VonC\prog\git\ggb\]
22/06/2015  11:03    <JONCTION>     symlinkdir [C:\Users\VonC\prog\git\ggb\]`

func testExecRun(cmd *exec.Cmd) error {
	tmsg := fmt.Sprintf("testExecRun cmd='%v' in '%s'", cmd.Args, cmd.Dir)
	fmt.Println(tmsg)
	if strings.Contains(tmsg, "/J") {
		return nil
	}
	if strings.HasSuffix(cmd.Dir, `\WarningOnDir`) {
		io.WriteString(cmd.Stdout, "dummy content")
		io.WriteString(cmd.Stderr, "Some warning on dir")
		return nil
	}
	if strings.HasSuffix(cmd.Dir, `\nojunction`) {
		io.WriteString(cmd.Stdout, "dummy content without any junction")
		return nil
	}
	if strings.HasSuffix(cmd.Dir, `\badsymlink`) {
		return fmt.Errorf("unreadable dir on symlink")
	}
	if strings.HasSuffix(cmd.Dir, `\symlink`) {
		io.WriteString(cmd.Stdout, junctionOut)
		return nil
	}
	return cmdRun(cmd)
}

func testOsRename(oldpath, newpath string) error {
	fmt.Printf("testOsRename oldpath='%v', newpath '%s'\n", oldpath, newpath)
	return nil
}
<|endoftext|>


<commit_before>//+build unit

// Copyright 2016 Mesosphere, Inc.
//
// 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 http

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"strings"
	"testing"
	"time"

	"github.com/dcos/dcos-metrics/producers"
	. "github.com/smartystreets/goconvey/convey"
)

var (
	testTime = time.Now()

	testNodeData = producers.MetricsMessage{
		Name: producers.NodeMetricPrefix,
		Datapoints: []producers.Datapoint{
			producers.Datapoint{
				Name:      "some-node-metric",
				Unit:      "",
				Value:     "1234",
				Timestamp: testTime.Format(time.RFC3339Nano),
			},
		},
		Dimensions: producers.Dimensions{
			MesosID:  "foo",
			Hostname: "some-host",
		},
		Timestamp: testTime.UTC().Unix(),
	}

	testContainerData = producers.MetricsMessage{
		Name: producers.ContainerMetricPrefix,
		Datapoints: []producers.Datapoint{
			producers.Datapoint{
				Name:      "some-container-metric",
				Unit:      "",
				Value:     "1234",
				Timestamp: testTime.Format(time.RFC3339Nano),
			},
		},
		Dimensions: producers.Dimensions{
			MesosID:     "foo",
			Hostname:    "some-host",
			ContainerID: "foo-container",
		},
		Timestamp: testTime.UTC().Unix(),
	}

	testAppData = producers.MetricsMessage{
		Name: producers.AppMetricPrefix,
		Datapoints: []producers.Datapoint{
			producers.Datapoint{
				Name:      "some-app-metric",
				Unit:      "",
				Value:     "1234",
				Timestamp: testTime.Format(time.RFC3339Nano),
			},
		},
		Dimensions: producers.Dimensions{
			MesosID:     "foo",
			Hostname:    "some-host",
			ContainerID: "foo-container",
		},
		Timestamp: testTime.UTC().Unix(),
	}
)

func setup() int {
	port, err := getEphemeralPort()
	if err != nil {
		panic(err)
	}

	pi, pc := New(Config{
		DCOSRole:    "agent",
		IP:          "127.0.0.1",
		Port:        port,
		CacheExpiry: time.Duration(5) * time.Second})
	go pi.Run()
	time.Sleep(1 * time.Second) // give the http server a chance to start before querying it

	pc <- testNodeData
	pc <- testContainerData
	pc <- testAppData

	return port
}

// Functional test for the /system/metrics/api/v0/node endpoint.
func TestHTTPProducer_Node(t *testing.T) {
	Convey("When querying the /system/metrics/api/v0/node endpoint", t, func() {
		Convey("Should return metrics in the expected structure", func() {
			port := setup()
			resp, err := http.Get(fmt.Sprintf("http://127.0.0.1:%d/system/metrics/api/v0/node", port))
			if err != nil {
				panic(err)
			}
			defer resp.Body.Close()

			got, err := ioutil.ReadAll(resp.Body)
			if err != nil {
				panic(err)
			}

			expected, err := json.Marshal(testNodeData)
			if err != nil {
				panic(err)
			}

			So(strings.TrimSpace(string(got)), ShouldEqual, strings.TrimSpace(string(expected)))
		})
	})
}

func TestHTTPProducer_Containers(t *testing.T) {
	Convey("When querying the /system/metrics/api/v0/containers endpoint", t, func() {
		Convey("Should return container IDs in the expected structure", nil)
		port := setup()
		resp, err := http.Get(fmt.Sprintf("http://127.0.0.1:%d/system/metrics/api/v0/containers", port))
		if err != nil {
			panic(err)
		}
		defer resp.Body.Close()

		got, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			panic(err)
		}
		expected, err := json.Marshal([]string{testContainerData.Dimensions.ContainerID})
		if err != nil {
			panic(err)
		}

		So(strings.TrimSpace(string(got)), ShouldEqual, strings.TrimSpace(string(expected)))
	})
}

func TestHTTPProducer_ContainerID(t *testing.T) {
	Convey("When querying the /system/metrics/api/v0/containers/{id} endpoint", t, func() {
		Convey("Should return container metrics for the container ID given", nil)
		port := setup()
		resp, err := http.Get(fmt.Sprintf("http://127.0.0.1:%d/system/metrics/api/v0/containers/foo-container", port))
		if err != nil {
			panic(err)
		}
		defer resp.Body.Close()

		got, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			panic(err)
		}
		expected, err := json.Marshal(testContainerData)
		if err != nil {
			panic(err)
		}

		So(strings.TrimSpace(string(got)), ShouldEqual, strings.TrimSpace(string(expected)))
	})
}

func TestHTTPProducer_ContainerApp(t *testing.T) {
	Convey("When querying the /system/metrics/api/v0/containers/{id}/app endpoint", t, func() {
		Convey("Should return app metrics in the expected structure", nil)
		port := setup()
		resp, err := http.Get(fmt.Sprintf("http://127.0.0.1:%d/system/metrics/api/v0/containers/foo-container/app", port))
		if err != nil {
			panic(err)
		}
		defer resp.Body.Close()

		got, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			panic(err)
		}
		expected, err := json.Marshal(testAppData)
		if err != nil {
			panic(err)
		}

		So(strings.TrimSpace(string(got)), ShouldEqual, strings.TrimSpace(string(expected)))
	})
}

// getEphemeralPort returns an available ephemeral port on the system.
func getEphemeralPort() (int, error) {
	addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
	if err != nil {
		return 0, err
	}

	l, err := net.ListenTCP("tcp", addr)
	if err != nil {
		return 0, err
	}
	defer l.Close()

	return l.Addr().(*net.TCPAddr).Port, nil
}
<commit_msg>Update tests to reflect new base route<commit_after>//+build unit

// Copyright 2016 Mesosphere, Inc.
//
// 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 http

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"strings"
	"testing"
	"time"

	"github.com/dcos/dcos-metrics/producers"
	. "github.com/smartystreets/goconvey/convey"
)

var (
	testTime = time.Now()

	testNodeData = producers.MetricsMessage{
		Name: producers.NodeMetricPrefix,
		Datapoints: []producers.Datapoint{
			producers.Datapoint{
				Name:      "some-node-metric",
				Unit:      "",
				Value:     "1234",
				Timestamp: testTime.Format(time.RFC3339Nano),
			},
		},
		Dimensions: producers.Dimensions{
			MesosID:  "foo",
			Hostname: "some-host",
		},
		Timestamp: testTime.UTC().Unix(),
	}

	testContainerData = producers.MetricsMessage{
		Name: producers.ContainerMetricPrefix,
		Datapoints: []producers.Datapoint{
			producers.Datapoint{
				Name:      "some-container-metric",
				Unit:      "",
				Value:     "1234",
				Timestamp: testTime.Format(time.RFC3339Nano),
			},
		},
		Dimensions: producers.Dimensions{
			MesosID:     "foo",
			Hostname:    "some-host",
			ContainerID: "foo-container",
		},
		Timestamp: testTime.UTC().Unix(),
	}

	testAppData = producers.MetricsMessage{
		Name: producers.AppMetricPrefix,
		Datapoints: []producers.Datapoint{
			producers.Datapoint{
				Name:      "some-app-metric",
				Unit:      "",
				Value:     "1234",
				Timestamp: testTime.Format(time.RFC3339Nano),
			},
		},
		Dimensions: producers.Dimensions{
			MesosID:     "foo",
			Hostname:    "some-host",
			ContainerID: "foo-container",
		},
		Timestamp: testTime.UTC().Unix(),
	}
)

func setup() int {
	port, err := getEphemeralPort()
	if err != nil {
		panic(err)
	}

	pi, pc := New(Config{
		DCOSRole:    "agent",
		IP:          "127.0.0.1",
		Port:        port,
		CacheExpiry: time.Duration(5) * time.Second})
	go pi.Run()
	time.Sleep(1 * time.Second) // give the http server a chance to start before querying it

	pc <- testNodeData
	pc <- testContainerData
	pc <- testAppData

	return port
}

// Functional test for the /system/metrics/api/v0/node endpoint.
func TestHTTPProducer_Node(t *testing.T) {
	Convey("When querying the /v0/node endpoint", t, func() {
		Convey("Should return metrics in the expected structure", func() {
			port := setup()
			resp, err := http.Get(fmt.Sprintf("http://127.0.0.1:%d/v0/node", port))
			if err != nil {
				panic(err)
			}
			defer resp.Body.Close()

			got, err := ioutil.ReadAll(resp.Body)
			if err != nil {
				panic(err)
			}

			expected, err := json.Marshal(testNodeData)
			if err != nil {
				panic(err)
			}

			So(strings.TrimSpace(string(got)), ShouldEqual, strings.TrimSpace(string(expected)))
		})
	})
}

func TestHTTPProducer_Containers(t *testing.T) {
	Convey("When querying the /v0/containers endpoint", t, func() {
		Convey("Should return container IDs in the expected structure", nil)
		port := setup()
		resp, err := http.Get(fmt.Sprintf("http://127.0.0.1:%d/v0/containers", port))
		if err != nil {
			panic(err)
		}
		defer resp.Body.Close()

		got, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			panic(err)
		}
		expected, err := json.Marshal([]string{testContainerData.Dimensions.ContainerID})
		if err != nil {
			panic(err)
		}

		So(strings.TrimSpace(string(got)), ShouldEqual, strings.TrimSpace(string(expected)))
	})
}

func TestHTTPProducer_ContainerID(t *testing.T) {
	Convey("When querying the /v0/containers/{id} endpoint", t, func() {
		Convey("Should return container metrics for the container ID given", nil)
		port := setup()
		resp, err := http.Get(fmt.Sprintf("http://127.0.0.1:%d/v0/containers/foo-container", port))
		if err != nil {
			panic(err)
		}
		defer resp.Body.Close()

		got, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			panic(err)
		}
		expected, err := json.Marshal(testContainerData)
		if err != nil {
			panic(err)
		}

		So(strings.TrimSpace(string(got)), ShouldEqual, strings.TrimSpace(string(expected)))
	})
}

func TestHTTPProducer_ContainerApp(t *testing.T) {
	Convey("When querying the /v0/containers/{id}/app endpoint", t, func() {
		Convey("Should return app metrics in the expected structure", nil)
		port := setup()
		resp, err := http.Get(fmt.Sprintf("http://127.0.0.1:%d/v0/containers/foo-container/app", port))
		if err != nil {
			panic(err)
		}
		defer resp.Body.Close()

		got, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			panic(err)
		}
		expected, err := json.Marshal(testAppData)
		if err != nil {
			panic(err)
		}

		So(strings.TrimSpace(string(got)), ShouldEqual, strings.TrimSpace(string(expected)))
	})
}

// getEphemeralPort returns an available ephemeral port on the system.
func getEphemeralPort() (int, error) {
	addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
	if err != nil {
		return 0, err
	}

	l, err := net.ListenTCP("tcp", addr)
	if err != nil {
		return 0, err
	}
	defer l.Close()

	return l.Addr().(*net.TCPAddr).Port, nil
}
<|endoftext|>


<commit_before>package hal

import (
	"fmt"
	"log"
	"sync"
)

// RouterCTX holds the router's context, including input/output chans.
type RouterCTX struct {
	brokers map[string]*Broker
	in      chan *Evt     // messages from brokers --> plugins
	out     chan *Evt     // messages from plugins --> brokers
	update  chan struct{} // to notify the router that the instance list changed
	mut     sync.Mutex
	init    sync.Once
}

var routerSingleton RouterCTX

// Router returns the singleton router context. The router is initialized
// on the first call to this function.
func Router() *RouterCTX {
	routerSingleton.init.Do(func() {
		routerSingleton.in = make(chan *Evt, 1000)
		routerSingleton.out = make(chan *Evt, 1000)
		routerSingleton.update = make(chan struct{}, 1)
		routerSingleton.brokers = make(map[string]*Broker)
	})

	return &routerSingleton
}

// forward from one (go) channel to another
// TODO: figure out if this needs to check for closed channels, etc.
func forward(from, to chan *Evt) {
	for {
		select {
		case evt := <-from:
			to <- evt
		}
	}
}

// AddBroker adds a broker to the router and starts forwarding
// events between it and the router.
func (r *RouterCTX) AddBroker(b Broker) {
	r.mut.Lock()
	defer r.mut.Unlock()

	if _, exists := r.brokers[b.Name()]; exists {
		panic(fmt.Sprintf("BUG: broker '%s' added > 1 times.", b.Name()))
	}

	b2r := make(chan *Evt, 1000) // messages from the broker to the router

	// start the broker's event stream
	go b.Stream(b2r)

	// forward events from the broker to the router's input channel
	go forward(b2r, r.in)

	r.brokers[b.Name()] = &b
}

func (r *RouterCTX) GetBroker(name string) *Broker {
	if broker, exists := r.brokers[name]; exists {
		return broker
	}

	return nil
}

// Route is the main method for the router. It blocks and should be run in a goroutine
// exactly once.
func (r *RouterCTX) Route() {
	for {
		select {
		case evt := <-r.in:
			if evt.Broker == nil {
				panic("BUG: received event with nil Broker. This breaks all the things!")
			}

			go r.processEvent(evt)
		}
	}
}

// processEvent processes one event and is intended to run in a goroutine.
func (r *RouterCTX) processEvent(evt *Evt) {
	var pname string // must be in the recovery handler's scope

	// get a snapshot of the instance list
	// TODO: keep an eye on the cost of copying this list for every message
	pr := PluginRegistry()
	instances := pr.InstanceList()

	// if a plugin panics, catch it & log it
	// TODO: report errors to a channel?
	defer func() {
		if r := recover(); r != nil {
			log.Printf("recovered panic in plugin %q\n", pname)
			log.Printf("panic: %q", r)
		}
	}()

	for _, inst := range instances {
		ibname := inst.Broker.Name()
		pname = inst.Plugin.Name // recovery handler ^ will pick this up in a panic

		// a plugin instance matches on broker, channel, and regex
		// first, check if the instance is attached to a specific broker or generic
		if ibname != evt.Broker.Name() && ibname != gBroker.Name() {
			continue
		}

		// if this is a generic broker instance and the event is marked as not
		// generic, skip it
		if ibname == gBroker.Name() && !evt.IsGeneric {
			continue
		}

		// check if it's the correct channel
		if evt.Channel != inst.Channel {
			continue
		}

		// finally, check message text against the regex
		if inst.Regex == "" || inst.regex.MatchString(evt.Body) {
			// this will copy the struct twice. It's intentional to avoid
			// mutating the evt between calls. The plugin func signature
			// forces the second copy.
			evtcpy := *evt

			// pass the plugin instance pointer to the plugin function so
			// it can access its fields for settings, etc.
			evtcpy.instance = inst

			// call the plugin function
			// this may block other plugins from processing the same event but
			// since it's already in a goroutine, other events won't be blocked
			inst.Func(evtcpy)
		}
	}
}
<commit_msg>Revert "explicitly use pointers to broker"<commit_after>package hal

import (
	"fmt"
	"log"
	"sync"
)

// RouterCTX holds the router's context, including input/output chans.
type RouterCTX struct {
	brokers map[string]Broker
	in      chan *Evt     // messages from brokers --> plugins
	out     chan *Evt     // messages from plugins --> brokers
	update  chan struct{} // to notify the router that the instance list changed
	mut     sync.Mutex
	init    sync.Once
}

var routerSingleton RouterCTX

// Router returns the singleton router context. The router is initialized
// on the first call to this function.
func Router() *RouterCTX {
	routerSingleton.init.Do(func() {
		routerSingleton.in = make(chan *Evt, 1000)
		routerSingleton.out = make(chan *Evt, 1000)
		routerSingleton.update = make(chan struct{}, 1)
		routerSingleton.brokers = make(map[string]Broker)
	})

	return &routerSingleton
}

// forward from one (go) channel to another
// TODO: figure out if this needs to check for closed channels, etc.
func forward(from, to chan *Evt) {
	for {
		select {
		case evt := <-from:
			to <- evt
		}
	}
}

// AddBroker adds a broker to the router and starts forwarding
// events between it and the router.
func (r *RouterCTX) AddBroker(b Broker) {
	r.mut.Lock()
	defer r.mut.Unlock()

	if _, exists := r.brokers[b.Name()]; exists {
		panic(fmt.Sprintf("BUG: broker '%s' added > 1 times.", b.Name()))
	}

	b2r := make(chan *Evt, 1000) // messages from the broker to the router

	// start the broker's event stream
	go b.Stream(b2r)

	// forward events from the broker to the router's input channel
	go forward(b2r, r.in)

	r.brokers[b.Name()] = b
}

func (r *RouterCTX) GetBroker(name string) Broker {
	if broker, exists := r.brokers[name]; exists {
		return broker
	}

	return nil
}

// Route is the main method for the router. It blocks and should be run in a goroutine
// exactly once.
func (r *RouterCTX) Route() {
	for {
		select {
		case evt := <-r.in:
			if evt.Broker == nil {
				panic("BUG: received event with nil Broker. This breaks all the things!")
			}

			go r.processEvent(evt)
		}
	}
}

// processEvent processes one event and is intended to run in a goroutine.
func (r *RouterCTX) processEvent(evt *Evt) {
	var pname string // must be in the recovery handler's scope

	// get a snapshot of the instance list
	// TODO: keep an eye on the cost of copying this list for every message
	pr := PluginRegistry()
	instances := pr.InstanceList()

	// if a plugin panics, catch it & log it
	// TODO: report errors to a channel?
	defer func() {
		if r := recover(); r != nil {
			log.Printf("recovered panic in plugin %q\n", pname)
			log.Printf("panic: %q", r)
		}
	}()

	for _, inst := range instances {
		ibname := inst.Broker.Name()
		pname = inst.Plugin.Name // recovery handler ^ will pick this up in a panic

		// a plugin instance matches on broker, channel, and regex
		// first, check if the instance is attached to a specific broker or generic
		if ibname != evt.Broker.Name() && ibname != gBroker.Name() {
			continue
		}

		// if this is a generic broker instance and the event is marked as not
		// generic, skip it
		if ibname == gBroker.Name() && !evt.IsGeneric {
			continue
		}

		// check if it's the correct channel
		if evt.Channel != inst.Channel {
			continue
		}

		// finally, check message text against the regex
		if inst.Regex == "" || inst.regex.MatchString(evt.Body) {
			// this will copy the struct twice. It's intentional to avoid
			// mutating the evt between calls. The plugin func signature
			// forces the second copy.
			evtcpy := *evt

			// pass the plugin instance pointer to the plugin function so
			// it can access its fields for settings, etc.
			evtcpy.instance = inst

			// call the plugin function
			// this may block other plugins from processing the same event but
			// since it's already in a goroutine, other events won't be blocked
			inst.Func(evtcpy)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"

	weavenet "github.com/weaveworks/weave/net"
)

func uniqueID(args []string) error {
	if len(args) != 2 {
		cmdUsage("unique-id", "<db-prefix> <host-root>")
	}
	dbPrefix := args[0]
	hostRoot := args[1]
	uid, err := weavenet.GetSystemPeerName(dbPrefix, hostRoot)
	if err != nil {
		return err
	}
	fmt.Printf(uid)
	return nil
}
<commit_msg>Don't use Printf without a format<commit_after>package main

import (
	"fmt"

	weavenet "github.com/weaveworks/weave/net"
)

func uniqueID(args []string) error {
	if len(args) != 2 {
		cmdUsage("unique-id", "<db-prefix> <host-root>")
	}
	dbPrefix := args[0]
	hostRoot := args[1]
	uid, err := weavenet.GetSystemPeerName(dbPrefix, hostRoot)
	if err != nil {
		return err
	}
	fmt.Print(uid)
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"strings"
	"testing"

	"whitehouse.id.au/microlisp/read"
	"whitehouse.id.au/microlisp/run"
	"whitehouse.id.au/microlisp/scan"
	"whitehouse.id.au/microlisp/value"
)

var src = readFile("testdata/eval.lisp")

func BenchmarkParse(b *testing.B) {
	b.SetBytes(int64(len(src)))
	for i := 0; i < b.N; i++ {
		scanner := scan.New(bytes.NewReader(src))
		reader := read.New(scanner)
		v := reader.Read()
		if err, ok := v.(value.Error); ok {
			b.Fatalf("benchmark failed due to parse error: %s", err)
		}
	}
}

func BenchmarkFprint(b *testing.B) {
	scanner := scan.New(bytes.NewReader(src))
	reader := read.New(scanner)
	v := reader.Read()
	if err, ok := v.(value.Error); ok {
		b.Fatalf("benchmark failed due to parse error: %s", err)
	}

	// Initial print to allocate underlying buffer.
	var buf bytes.Buffer
	v.Write(&buf)
	b.SetBytes(int64(buf.Len()))
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		buf.Reset()
		v.Write(&buf)
	}
}

func BenchmarkEval(b *testing.B) {
	scanner := scan.New(bytes.NewReader(src))
	reader := read.New(scanner)
	v := reader.Read()
	if err, ok := v.(value.Error); ok {
		b.Fatalf("benchmark failed due to parse error: %s", err)
	}

	for i := 0; i < b.N; i++ {
		run.Eval(v)
	}
}

func BenchmarkInvoke(b *testing.B) {
	testCases := []struct {
		name string
		args string
	}{
		{"list", "1 2 3"},
		{"car", "(quote (x y z))"},
		{"cdr", "(quote (a b c))"},
		{"cons", "1 2"},
		{"equal", "(quote (a (b c) d (e (f) g))) (quote (a (b c) d (e (f) g)))"},
		{"lambda", "(a) a"},
	}

	for _, tc := range testCases {
		b.Run(tc.name, func(b *testing.B) {
			src := fmt.Sprintf("(%s %s)", tc.name, tc.args)
			scanner := scan.New(strings.NewReader(src))
			reader := read.New(scanner)
			v := reader.Read()
			if err, ok := v.(value.Error); ok {
				b.Fatalf("benchmark failed due to parse error: %s", err)
			}

			for i := 0; i < b.N; i++ {
				if _, err := unwrapEval(v); err != nil {
					b.Fatalf("benchmark failed due to eval error: %s", err)
				}
			}
		})
	}
}

func readFile(name string) []byte {
	b, err := ioutil.ReadFile(name)
	if err != nil {
		log.Fatal(err)
	}
	return b
}

func unwrapEval(expr value.Value) (value.Value, error) {
	v := run.Eval(expr)
	if err, ok := v.(value.Error); ok {
		return nil, err
	}
	return v, nil
}
<commit_msg>Add native cons lookup functions to benchmark<commit_after>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"strings"
	"testing"

	"whitehouse.id.au/microlisp/read"
	"whitehouse.id.au/microlisp/run"
	"whitehouse.id.au/microlisp/scan"
	"whitehouse.id.au/microlisp/value"
)

var src = readFile("testdata/eval.lisp")

func BenchmarkParse(b *testing.B) {
	b.SetBytes(int64(len(src)))
	for i := 0; i < b.N; i++ {
		scanner := scan.New(bytes.NewReader(src))
		reader := read.New(scanner)
		v := reader.Read()
		if err, ok := v.(value.Error); ok {
			b.Fatalf("benchmark failed due to parse error: %s", err)
		}
	}
}

func BenchmarkFprint(b *testing.B) {
	scanner := scan.New(bytes.NewReader(src))
	reader := read.New(scanner)
	v := reader.Read()
	if err, ok := v.(value.Error); ok {
		b.Fatalf("benchmark failed due to parse error: %s", err)
	}

	// Initial print to allocate underlying buffer.
	var buf bytes.Buffer
	v.Write(&buf)
	b.SetBytes(int64(buf.Len()))
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		buf.Reset()
		v.Write(&buf)
	}
}

func BenchmarkEval(b *testing.B) {
	scanner := scan.New(bytes.NewReader(src))
	reader := read.New(scanner)
	v := reader.Read()
	if err, ok := v.(value.Error); ok {
		b.Fatalf("benchmark failed due to parse error: %s", err)
	}

	for i := 0; i < b.N; i++ {
		run.Eval(v)
	}
}

func BenchmarkInvoke(b *testing.B) {
	testCases := []struct {
		name string
		args string
	}{
		{"list", "1 2 3"},
		{"car", "(quote (x y z))"},
		{"cdr", "(quote (a b c))"},
		{"cadr", "(quote (a b c))"},
		{"cddr", "(quote (a b c))"},
		{"caddr", "(quote (a b c))"},
		{"cons", "1 2"},
		{"equal", "(quote (a (b c) d (e (f) g))) (quote (a (b c) d (e (f) g)))"},
		{"lambda", "(a) a"},
	}

	for _, tc := range testCases {
		b.Run(tc.name, func(b *testing.B) {
			src := fmt.Sprintf("(%s %s)", tc.name, tc.args)
			scanner := scan.New(strings.NewReader(src))
			reader := read.New(scanner)
			v := reader.Read()
			if err, ok := v.(value.Error); ok {
				b.Fatalf("benchmark failed due to parse error: %s", err)
			}

			for i := 0; i < b.N; i++ {
				if _, err := unwrapEval(v); err != nil {
					b.Fatalf("benchmark failed due to eval error: %s", err)
				}
			}
		})
	}
}

func readFile(name string) []byte {
	b, err := ioutil.ReadFile(name)
	if err != nil {
		log.Fatal(err)
	}
	return b
}

func unwrapEval(expr value.Value) (value.Value, error) {
	v := run.Eval(expr)
	if err, ok := v.(value.Error); ok {
		return nil, err
	}
	return v, nil
}
<|endoftext|>


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

package testing

import (
	"bytes"
	"encoding/json"
	"io"
	"net"
	"net/http"
	"os"
	"strconv"
	"strings"

	"github.com/loggo/loggo"
	gc "launchpad.net/gocheck"

	"launchpad.net/juju-core/charm"
	"launchpad.net/juju-core/testing"
	"launchpad.net/juju-core/utils"
)

var logger = loggo.GetLogger("juju.charm.testing.mockstore")

// MockStore provides a mock charm store implementation useful when testing.
type MockStore struct {
	mux            *http.ServeMux
	listener       net.Listener
	bundleBytes    []byte
	bundleSha256   string
	Downloads      []*charm.URL
	Authorizations []string
	Metadata       []string

	charms map[string]int
}

// NewMockStore creates a mock charm store containing the specified charms.
func NewMockStore(c *gc.C, charms map[string]int) *MockStore {
	s := &MockStore{charms: charms}
	f, err := os.Open(testing.Charms.BundlePath(c.MkDir(), "dummy"))
	c.Assert(err, gc.IsNil)
	defer f.Close()
	buf := &bytes.Buffer{}
	s.bundleSha256, _, err = utils.ReadSHA256(io.TeeReader(f, buf))
	c.Assert(err, gc.IsNil)
	s.bundleBytes = buf.Bytes()
	c.Assert(err, gc.IsNil)
	s.mux = http.NewServeMux()
	s.mux.HandleFunc("/charm-info", s.serveInfo)
	s.mux.HandleFunc("/charm-event", s.serveEvent)
	s.mux.HandleFunc("/charm/", s.serveCharm)
	lis, err := net.Listen("tcp", "127.0.0.1:0")
	c.Assert(err, gc.IsNil)
	s.listener = lis
	go http.Serve(s.listener, s)
	return s
}

// Close closes the mock store's socket.
func (s *MockStore) Close() {
	s.listener.Close()
}

// Address returns the URL used to make requests to the mock store.
func (s *MockStore) Address() string {
	return "http://" + s.listener.Addr().String()
}

// UpdateStoreRevision sets the revision of the specified charm to rev.
func (s *MockStore) UpdateStoreRevision(ch string, rev int) {
	s.charms[ch] = rev
}

// ServeHTTP implements http.ServeHTTP
func (s *MockStore) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	s.mux.ServeHTTP(w, r)
}

func (s *MockStore) serveInfo(w http.ResponseWriter, r *http.Request) {
	if metadata := r.Header.Get("Juju-Metadata"); metadata != "" {
		s.Metadata = append(s.Metadata, metadata)
		logger.Infof("Juju metadata: " + metadata)
	}

	r.ParseForm()
	response := map[string]*charm.InfoResponse{}
	for _, url := range r.Form["charms"] {
		cr := &charm.InfoResponse{}
		response[url] = cr
		charmURL := charm.MustParseURL(url)
		switch charmURL.Name {
		case "borken":
			cr.Errors = append(cr.Errors, "badness")
		case "terracotta":
			cr.Errors = append(cr.Errors, "cannot get revision")
		case "unwise":
			cr.Warnings = append(cr.Warnings, "foolishness")
			fallthrough
		default:
			if rev, ok := s.charms[charmURL.WithRevision(-1).String()]; ok {
				if charmURL.Revision == -1 {
					cr.Revision = rev
				} else {
					cr.Revision = charmURL.Revision
				}
				cr.Sha256 = s.bundleSha256
			} else {
				cr.Errors = append(cr.Errors, "entry not found")
			}
		}
	}
	data, err := json.Marshal(response)
	if err != nil {
		panic(err)
	}
	w.Header().Set("Content-Type", "application/json")
	_, err = w.Write(data)
	if err != nil {
		panic(err)
	}
}

func (s *MockStore) serveEvent(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	response := map[string]*charm.EventResponse{}
	for _, url := range r.Form["charms"] {
		digest := ""
		if i := strings.Index(url, "@"); i >= 0 {
			digest = url[i+1:]
			url = url[:i]
		}
		er := &charm.EventResponse{}
		response[url] = er
		if digest != "" && digest != "the-digest" {
			er.Kind = "not-found"
			er.Errors = []string{"entry not found"}
			continue
		}
		charmURL := charm.MustParseURL(url)
		switch charmURL.Name {
		case "borken":
			er.Kind = "publish-error"
			er.Errors = append(er.Errors, "badness")
		case "unwise":
			er.Warnings = append(er.Warnings, "foolishness")
			fallthrough
		default:
			if rev, ok := s.charms[charmURL.WithRevision(-1).String()]; ok {
				er.Kind = "published"
				er.Revision = rev
				er.Digest = "the-digest"
			} else {
				er.Kind = "not-found"
				er.Errors = []string{"entry not found"}
			}
		}
	}
	data, err := json.Marshal(response)
	if err != nil {
		panic(err)
	}
	w.Header().Set("Content-Type", "application/json")
	_, err = w.Write(data)
	if err != nil {
		panic(err)
	}
}

func (s *MockStore) serveCharm(w http.ResponseWriter, r *http.Request) {
	charmURL := charm.MustParseURL("cs:" + r.URL.Path[len("/charm/"):])
	s.Downloads = append(s.Downloads, charmURL)

	if auth := r.Header.Get("Authorization"); auth != "" {
		s.Authorizations = append(s.Authorizations, auth)
	}

	w.Header().Set("Connection", "close")
	w.Header().Set("Content-Type", "application/octet-stream")
	w.Header().Set("Content-Length", strconv.Itoa(len(s.bundleBytes)))
	_, err := w.Write(s.bundleBytes)
	if err != nil {
		panic(err)
	}
}
<commit_msg>[r=thumper] Move loggo import to be under github.com/juju<commit_after>// Copyright 2012, 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package testing

import (
	"bytes"
	"encoding/json"
	"io"
	"net"
	"net/http"
	"os"
	"strconv"
	"strings"

	"github.com/juju/loggo"
	gc "launchpad.net/gocheck"

	"launchpad.net/juju-core/charm"
	"launchpad.net/juju-core/testing"
	"launchpad.net/juju-core/utils"
)

var logger = loggo.GetLogger("juju.charm.testing.mockstore")

// MockStore provides a mock charm store implementation useful when testing.
type MockStore struct {
	mux            *http.ServeMux
	listener       net.Listener
	bundleBytes    []byte
	bundleSha256   string
	Downloads      []*charm.URL
	Authorizations []string
	Metadata       []string

	charms map[string]int
}

// NewMockStore creates a mock charm store containing the specified charms.
func NewMockStore(c *gc.C, charms map[string]int) *MockStore {
	s := &MockStore{charms: charms}
	f, err := os.Open(testing.Charms.BundlePath(c.MkDir(), "dummy"))
	c.Assert(err, gc.IsNil)
	defer f.Close()
	buf := &bytes.Buffer{}
	s.bundleSha256, _, err = utils.ReadSHA256(io.TeeReader(f, buf))
	c.Assert(err, gc.IsNil)
	s.bundleBytes = buf.Bytes()
	c.Assert(err, gc.IsNil)
	s.mux = http.NewServeMux()
	s.mux.HandleFunc("/charm-info", s.serveInfo)
	s.mux.HandleFunc("/charm-event", s.serveEvent)
	s.mux.HandleFunc("/charm/", s.serveCharm)
	lis, err := net.Listen("tcp", "127.0.0.1:0")
	c.Assert(err, gc.IsNil)
	s.listener = lis
	go http.Serve(s.listener, s)
	return s
}

// Close closes the mock store's socket.
func (s *MockStore) Close() {
	s.listener.Close()
}

// Address returns the URL used to make requests to the mock store.
func (s *MockStore) Address() string {
	return "http://" + s.listener.Addr().String()
}

// UpdateStoreRevision sets the revision of the specified charm to rev.
func (s *MockStore) UpdateStoreRevision(ch string, rev int) {
	s.charms[ch] = rev
}

// ServeHTTP implements http.ServeHTTP
func (s *MockStore) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	s.mux.ServeHTTP(w, r)
}

func (s *MockStore) serveInfo(w http.ResponseWriter, r *http.Request) {
	if metadata := r.Header.Get("Juju-Metadata"); metadata != "" {
		s.Metadata = append(s.Metadata, metadata)
		logger.Infof("Juju metadata: " + metadata)
	}

	r.ParseForm()
	response := map[string]*charm.InfoResponse{}
	for _, url := range r.Form["charms"] {
		cr := &charm.InfoResponse{}
		response[url] = cr
		charmURL := charm.MustParseURL(url)
		switch charmURL.Name {
		case "borken":
			cr.Errors = append(cr.Errors, "badness")
		case "terracotta":
			cr.Errors = append(cr.Errors, "cannot get revision")
		case "unwise":
			cr.Warnings = append(cr.Warnings, "foolishness")
			fallthrough
		default:
			if rev, ok := s.charms[charmURL.WithRevision(-1).String()]; ok {
				if charmURL.Revision == -1 {
					cr.Revision = rev
				} else {
					cr.Revision = charmURL.Revision
				}
				cr.Sha256 = s.bundleSha256
			} else {
				cr.Errors = append(cr.Errors, "entry not found")
			}
		}
	}
	data, err := json.Marshal(response)
	if err != nil {
		panic(err)
	}
	w.Header().Set("Content-Type", "application/json")
	_, err = w.Write(data)
	if err != nil {
		panic(err)
	}
}

func (s *MockStore) serveEvent(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	response := map[string]*charm.EventResponse{}
	for _, url := range r.Form["charms"] {
		digest := ""
		if i := strings.Index(url, "@"); i >= 0 {
			digest = url[i+1:]
			url = url[:i]
		}
		er := &charm.EventResponse{}
		response[url] = er
		if digest != "" && digest != "the-digest" {
			er.Kind = "not-found"
			er.Errors = []string{"entry not found"}
			continue
		}
		charmURL := charm.MustParseURL(url)
		switch charmURL.Name {
		case "borken":
			er.Kind = "publish-error"
			er.Errors = append(er.Errors, "badness")
		case "unwise":
			er.Warnings = append(er.Warnings, "foolishness")
			fallthrough
		default:
			if rev, ok := s.charms[charmURL.WithRevision(-1).String()]; ok {
				er.Kind = "published"
				er.Revision = rev
				er.Digest = "the-digest"
			} else {
				er.Kind = "not-found"
				er.Errors = []string{"entry not found"}
			}
		}
	}
	data, err := json.Marshal(response)
	if err != nil {
		panic(err)
	}
	w.Header().Set("Content-Type", "application/json")
	_, err = w.Write(data)
	if err != nil {
		panic(err)
	}
}

func (s *MockStore) serveCharm(w http.ResponseWriter, r *http.Request) {
	charmURL := charm.MustParseURL("cs:" + r.URL.Path[len("/charm/"):])
	s.Downloads = append(s.Downloads, charmURL)

	if auth := r.Header.Get("Authorization"); auth != "" {
		s.Authorizations = append(s.Authorizations, auth)
	}

	w.Header().Set("Connection", "close")
	w.Header().Set("Content-Type", "application/octet-stream")
	w.Header().Set("Content-Length", strconv.Itoa(len(s.bundleBytes)))
	_, err := w.Write(s.bundleBytes)
	if err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>package docker

import (
	"bytes"
	"os"
	"os/exec"
	"strings"
	"testing"

	sparta "github.com/mweagle/Sparta"
	"github.com/mweagle/Sparta/system"
)

func TestLogin(t *testing.T) {
	logger, _ := sparta.NewLogger("info")

	// If docker -v doesn't work, then login definitely won't
	dockerVersionCmd := exec.Command("docker", "-v")
	dockerVersionCmdErr := system.RunOSCommand(dockerVersionCmd, logger)
	if dockerVersionCmdErr != nil {
		t.Logf("WARNING: failed to execute `docker -v` as prerequisite for testing STDIN password")
		return
	}
	// Don't supply password on command line

	dockerLoginCmd := exec.Command("docker",
		"login",
		"-u",
		"mweagle",
		"--password-stdin")
	dockerLoginCmd.Stdout = os.Stdout
	dockerLoginCmd.Stdin = bytes.NewReader([]byte("0AA421A3-931B-4985-8E99-9F5432A2BB58\n"))
	dockerLoginCmd.Stderr = os.Stderr
	dockerLoginCmdErr := system.RunOSCommand(dockerLoginCmd, logger)
	if dockerLoginCmdErr != nil {
		if strings.Contains(dockerLoginCmdErr.Error(), "Cannot perform an interactive login") {
			// The stdin write failed...
			t.Fatalf("Failed to write password to STDIN")
		} else if strings.Contains(dockerLoginCmdErr.Error(), "unauthorized: incorrect username or password") {
			t.Logf("Expected authorization rejection detected")
		}
	} else {
		// This should never happen
		t.Fatalf("Docker login with invalid credentials")
	}
}
<commit_msg>Correct test<commit_after>package docker

import (
	"bytes"
	"os"
	"os/exec"
	"strings"
	"testing"

	"github.com/mweagle/Sparta/system"
	"github.com/rs/zerolog"
)

func TestLogin(t *testing.T) {
	logger := zerolog.New(os.Stdout).With().Timestamp().Logger()

	// If docker -v doesn't work, then login definitely won't
	dockerVersionCmd := exec.Command("docker", "-v")
	dockerVersionCmdErr := system.RunOSCommand(dockerVersionCmd, &logger)
	if dockerVersionCmdErr != nil {
		t.Logf("WARNING: failed to execute `docker -v` as prerequisite for testing STDIN password")
		return
	}
	// Don't supply password on command line

	dockerLoginCmd := exec.Command("docker",
		"login",
		"-u",
		"mweagle",
		"--password-stdin")
	dockerLoginCmd.Stdout = os.Stdout
	dockerLoginCmd.Stdin = bytes.NewReader([]byte("0AA421A3-931B-4985-8E99-9F5432A2BB58\n"))
	dockerLoginCmd.Stderr = os.Stderr
	dockerLoginCmdErr := system.RunOSCommand(dockerLoginCmd, &logger)
	if dockerLoginCmdErr != nil {
		if strings.Contains(dockerLoginCmdErr.Error(), "Cannot perform an interactive login") {
			// The stdin write failed...
			t.Fatalf("Failed to write password to STDIN")
		} else if strings.Contains(dockerLoginCmdErr.Error(), "unauthorized: incorrect username or password") {
			t.Logf("Expected authorization rejection detected")
		}
	} else {
		// This should never happen
		t.Fatalf("Docker login with invalid credentials")
	}
}
<|endoftext|>


<commit_before>// +build linux freebsd netbsd

package pidfile

import (
	"fmt"
	"os"
)

func existsPid(pid int) bool {
	_, err := os.Stat(fmt.Sprintf("/proc/%d/", pid))
	return err == nil
}
<commit_msg>check command name of saved pid in existsPid on Linux<commit_after>// +build linux freebsd netbsd

package pidfile

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

func existsPid(pid int) bool {
	cnt, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/cmdline", pid))
	if err != nil {
		return false
	}

	out := string(cnt)
	if i := strings.IndexRune(out, '\x00'); i > 0 {
		out = out[:i]
	}
	return filepath.Base(out) == filepath.Base(os.Args[0])
}
<|endoftext|>