<commit_before>/*
Copyright 2014 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package authorizer

import (
	"net/http"

	"k8s.io/apiserver/pkg/authentication/user"
)

// Attributes is an interface used by an Authorizer to get information about a request
// that is used to make an authorization decision.
type Attributes interface {
	// GetUser returns the user.Info object to authorize
	GetUser() user.Info

	// GetVerb returns the kube verb associated with API requests (this includes get, list, watch, create, update, patch, delete, deletecollection, and proxy),
	// or the lowercased HTTP verb associated with non-API requests (this includes get, put, post, patch, and delete)
	GetVerb() string

	// When IsReadOnly() == true, the request has no side effects, other than
	// caching, logging, and other incidentals.
	IsReadOnly() bool

	// The namespace of the object, if a request is for a REST object.
	GetNamespace() string

	// The kind of object, if a request is for a REST object.
	GetResource() string

	// GetSubresource returns the subresource being requested, if present
	GetSubresource() string

	// GetName returns the name of the object as parsed off the request.  This will not be present for all request types, but
	// will be present for: get, update, delete
	GetName() string

	// The group of the resource, if a request is for a REST object.
	GetAPIGroup() string

	// GetAPIVersion returns the version of the group requested, if a request is for a REST object.
	GetAPIVersion() string

	// IsResourceRequest returns true for requests to API resources, like /api/v1/nodes,
	// and false for non-resource endpoints like /api, /healthz, and /swaggerapi
	IsResourceRequest() bool

	// GetPath returns the path of the request
	GetPath() string
}

// Authorizer makes an authorization decision based on information gained by making
// zero or more calls to methods of the Attributes interface.  It returns nil when an action is
// authorized, otherwise it returns an error.
type Authorizer interface {
	Authorize(a Attributes) (authorized bool, reason string, err error)
}

type AuthorizerFunc func(a Attributes) (bool, string, error)

func (f AuthorizerFunc) Authorize(a Attributes) (bool, string, error) {
	return f(a)
}

// RuleResolver provides a mechanism for resolving the list of rules that apply to a given user within a namespace.
type RuleResolver interface {
	// RulesFor get the list of cluster wide rules, the list of rules in the specific namespace, incomplete status and errors.
	RulesFor(user user.Info, namespace string) ([]ResourceRuleInfo, []NonResourceRuleInfo, bool, error)
}

// RequestAttributesGetter provides a function that extracts Attributes from an http.Request
type RequestAttributesGetter interface {
	GetRequestAttributes(user.Info, *http.Request) Attributes
}

// AttributesRecord implements Attributes interface.
type AttributesRecord struct {
	User            user.Info
	Verb            string
	Namespace       string
	APIGroup        string
	APIVersion      string
	Resource        string
	Subresource     string
	Name            string
	ResourceRequest bool
	Path            string
}

func (a AttributesRecord) GetUser() user.Info {
	return a.User
}

func (a AttributesRecord) GetVerb() string {
	return a.Verb
}

func (a AttributesRecord) IsReadOnly() bool {
	return a.Verb == "get" || a.Verb == "list" || a.Verb == "watch"
}

func (a AttributesRecord) GetNamespace() string {
	return a.Namespace
}

func (a AttributesRecord) GetResource() string {
	return a.Resource
}

func (a AttributesRecord) GetSubresource() string {
	return a.Subresource
}

func (a AttributesRecord) GetName() string {
	return a.Name
}

func (a AttributesRecord) GetAPIGroup() string {
	return a.APIGroup
}

func (a AttributesRecord) GetAPIVersion() string {
	return a.APIVersion
}

func (a AttributesRecord) IsResourceRequest() bool {
	return a.ResourceRequest
}

func (a AttributesRecord) GetPath() string {
	return a.Path
}
<commit_msg>refactor authorizer to return a tristate decision<commit_after>/*
Copyright 2014 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package authorizer

import (
	"net/http"

	"k8s.io/apiserver/pkg/authentication/user"
)

// Attributes is an interface used by an Authorizer to get information about a request
// that is used to make an authorization decision.
type Attributes interface {
	// GetUser returns the user.Info object to authorize
	GetUser() user.Info

	// GetVerb returns the kube verb associated with API requests (this includes get, list, watch, create, update, patch, delete, deletecollection, and proxy),
	// or the lowercased HTTP verb associated with non-API requests (this includes get, put, post, patch, and delete)
	GetVerb() string

	// When IsReadOnly() == true, the request has no side effects, other than
	// caching, logging, and other incidentals.
	IsReadOnly() bool

	// The namespace of the object, if a request is for a REST object.
	GetNamespace() string

	// The kind of object, if a request is for a REST object.
	GetResource() string

	// GetSubresource returns the subresource being requested, if present
	GetSubresource() string

	// GetName returns the name of the object as parsed off the request.  This will not be present for all request types, but
	// will be present for: get, update, delete
	GetName() string

	// The group of the resource, if a request is for a REST object.
	GetAPIGroup() string

	// GetAPIVersion returns the version of the group requested, if a request is for a REST object.
	GetAPIVersion() string

	// IsResourceRequest returns true for requests to API resources, like /api/v1/nodes,
	// and false for non-resource endpoints like /api, /healthz, and /swaggerapi
	IsResourceRequest() bool

	// GetPath returns the path of the request
	GetPath() string
}

// Authorizer makes an authorization decision based on information gained by making
// zero or more calls to methods of the Attributes interface.  It returns nil when an action is
// authorized, otherwise it returns an error.
type Authorizer interface {
	Authorize(a Attributes) (authorized Decision, reason string, err error)
}

type AuthorizerFunc func(a Attributes) (Decision, string, error)

func (f AuthorizerFunc) Authorize(a Attributes) (Decision, string, error) {
	return f(a)
}

// RuleResolver provides a mechanism for resolving the list of rules that apply to a given user within a namespace.
type RuleResolver interface {
	// RulesFor get the list of cluster wide rules, the list of rules in the specific namespace, incomplete status and errors.
	RulesFor(user user.Info, namespace string) ([]ResourceRuleInfo, []NonResourceRuleInfo, bool, error)
}

// RequestAttributesGetter provides a function that extracts Attributes from an http.Request
type RequestAttributesGetter interface {
	GetRequestAttributes(user.Info, *http.Request) Attributes
}

// AttributesRecord implements Attributes interface.
type AttributesRecord struct {
	User            user.Info
	Verb            string
	Namespace       string
	APIGroup        string
	APIVersion      string
	Resource        string
	Subresource     string
	Name            string
	ResourceRequest bool
	Path            string
}

func (a AttributesRecord) GetUser() user.Info {
	return a.User
}

func (a AttributesRecord) GetVerb() string {
	return a.Verb
}

func (a AttributesRecord) IsReadOnly() bool {
	return a.Verb == "get" || a.Verb == "list" || a.Verb == "watch"
}

func (a AttributesRecord) GetNamespace() string {
	return a.Namespace
}

func (a AttributesRecord) GetResource() string {
	return a.Resource
}

func (a AttributesRecord) GetSubresource() string {
	return a.Subresource
}

func (a AttributesRecord) GetName() string {
	return a.Name
}

func (a AttributesRecord) GetAPIGroup() string {
	return a.APIGroup
}

func (a AttributesRecord) GetAPIVersion() string {
	return a.APIVersion
}

func (a AttributesRecord) IsResourceRequest() bool {
	return a.ResourceRequest
}

func (a AttributesRecord) GetPath() string {
	return a.Path
}

type Decision int

const (
	// DecisionDeny means that an authorizer decided to deny the action.
	DecisionDeny Decision = iota
	// DecisionAllow means that an authorizer decided to allow the action.
	DecisionAllow
	// DecisionNoOpionion means that an authorizer has no opinion on wether
	// to allow or deny an action.
	DecisionNoOpinion
)
<|endoftext|>


<commit_before>// Package mixmux wraps HTTPRouter and HTTPTreeMux to provide more consistent
// and more idiomatic APIs.
package mixmux

import (
	"net/http"

	"github.com/dimfeld/httptreemux"
	"github.com/julienschmidt/httprouter"
)

// MixMuxer defines available methods for wrapped multiplexers.
type MixMuxer interface {
	Options(path string, h http.Handler)
	Get(path string, h http.Handler)
	Post(path string, h http.Handler)
	Put(path string, h http.Handler)
	Patch(path string, h http.Handler)
	Delete(path string, h http.Handler)
	Head(path string, h http.Handler)
}

// Router wraps HTTPRouter.
type Router struct {
	*httprouter.Router
	path string
}

// NewHTTPRouter returns a wrapped HTTPRouter.
func NewHTTPRouter() *Router {
	return &Router{httprouter.New(), ""}
}

// Group takes a path and returns a new Router around the original HTTPRouter.
func (r *Router) Group(path string) *Router {
	return &Router{r.Router, r.path + path}
}

// Options takes a path and http.Handler and adds them to the mux.
func (r *Router) Options(path string, h http.Handler) {
	r.Handle("OPTIONS", r.path+path, httpRouterWrapHandler(h))
}

// Get takes a path and http.Handler and adds them to the mux.
func (r *Router) Get(path string, h http.Handler) {
	r.Handle("GET", r.path+path, httpRouterWrapHandler(h))
}

// Post takes a path and http.Handler and adds them to the mux.
func (r *Router) Post(path string, h http.Handler) {
	r.Handle("POST", r.path+path, httpRouterWrapHandler(h))
}

// Put takes a path and http.Handler and adds them to the mux.
func (r *Router) Put(path string, h http.Handler) {
	r.Handle("PUT", r.path+path, httpRouterWrapHandler(h))
}

// Patch takes a path and http.Handler and adds them to the mux.
func (r *Router) Patch(path string, h http.Handler) {
	r.Handle("PATCH", r.path+path, httpRouterWrapHandler(h))
}

// Delete takes a path and http.Handler and adds them to the mux.
func (r *Router) Delete(path string, h http.Handler) {
	r.Handle("DELETE", r.path+path, httpRouterWrapHandler(h))
}

// Head takes a path and http.Handler and adds them to the mux.
func (r *Router) Head(path string, h http.Handler) {
	r.Handle("HEAD", r.path+path, httpRouterWrapHandler(h))
}

func httpRouterWrapHandler(next http.Handler) httprouter.Handle {
	return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
		next.ServeHTTP(w, r)
	}
}

// TreeMux wraps HTTPTreeMux.
type TreeMux struct {
	*httptreemux.TreeMux
	path string
}

// NewTreeMux returns a wrapped HTTPTreeMux.
func NewTreeMux() *TreeMux {
	return &TreeMux{httptreemux.New()}
}

// Group takes a path and returns a new TreeMux around the original HTTPTreeMux.
func (tm *TreeMux) Group(path string) *TreeMux {
	return &Router{tm.TreeMux, tm.path + path}
}

// Options takes a path and http.Handler and adds them to the mux.
func (tm *TreeMux) Options(path string, h http.Handler) {
	tm.Handle("OPTIONS", tm.path+path, treeMuxWrapHandler(h))
}

// Get takes a path and http.Handler and adds them to the mux.
func (tm *TreeMux) Get(path string, h http.Handler) {
	tm.Handle("GET", tm.path+path, treeMuxWrapHandler(h))
}

// Post takes a path and http.Handler and adds them to the mux.
func (tm *TreeMux) Post(path string, h http.Handler) {
	tm.Handle("POST", tm.path+path, treeMuxWrapHandler(h))
}

// Put takes a path and http.Handler and adds them to the mux.
func (tm *TreeMux) Put(path string, h http.Handler) {
	tm.Handle("PUT", tm.path+path, treeMuxWrapHandler(h))
}

// Patch takes a path and http.Handler and adds them to the mux.
func (tm *TreeMux) Patch(path string, h http.Handler) {
	tm.Handle("PATCH", tm.path+path, treeMuxWrapHandler(h))
}

// Delete takes a path and http.Handler and adds them to the mux.
func (tm *TreeMux) Delete(path string, h http.Handler) {
	tm.Handle("DELETE", tm.path+path, treeMuxWrapHandler(h))
}

// Head takes a path and http.Handler and adds them to the mux.
func (tm *TreeMux) Head(path string, h http.Handler) {
	tm.Handle("HEAD", tm.path+path, treeMuxWrapHandler(h))
}

func treeMuxWrapHandler(next http.Handler) httptreemux.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request, _ map[string]string) {
		next.ServeHTTP(w, r)
	}
}
<commit_msg>Fixed mistakes in TreeMux funcs.<commit_after>// Package mixmux wraps HTTPRouter and HTTPTreeMux to provide more consistent
// and more idiomatic APIs.
package mixmux

import (
	"net/http"

	"github.com/dimfeld/httptreemux"
	"github.com/julienschmidt/httprouter"
)

// MixMuxer defines available methods for wrapped multiplexers.
type MixMuxer interface {
	Options(path string, h http.Handler)
	Get(path string, h http.Handler)
	Post(path string, h http.Handler)
	Put(path string, h http.Handler)
	Patch(path string, h http.Handler)
	Delete(path string, h http.Handler)
	Head(path string, h http.Handler)
}

// Router wraps HTTPRouter.
type Router struct {
	*httprouter.Router
	path string
}

// NewHTTPRouter returns a wrapped HTTPRouter.
func NewHTTPRouter() *Router {
	return &Router{httprouter.New(), ""}
}

// Group takes a path and returns a new Router around the original HTTPRouter.
func (r *Router) Group(path string) *Router {
	return &Router{r.Router, r.path + path}
}

// Options takes a path and http.Handler and adds them to the mux.
func (r *Router) Options(path string, h http.Handler) {
	r.Handle("OPTIONS", r.path+path, httpRouterWrapHandler(h))
}

// Get takes a path and http.Handler and adds them to the mux.
func (r *Router) Get(path string, h http.Handler) {
	r.Handle("GET", r.path+path, httpRouterWrapHandler(h))
}

// Post takes a path and http.Handler and adds them to the mux.
func (r *Router) Post(path string, h http.Handler) {
	r.Handle("POST", r.path+path, httpRouterWrapHandler(h))
}

// Put takes a path and http.Handler and adds them to the mux.
func (r *Router) Put(path string, h http.Handler) {
	r.Handle("PUT", r.path+path, httpRouterWrapHandler(h))
}

// Patch takes a path and http.Handler and adds them to the mux.
func (r *Router) Patch(path string, h http.Handler) {
	r.Handle("PATCH", r.path+path, httpRouterWrapHandler(h))
}

// Delete takes a path and http.Handler and adds them to the mux.
func (r *Router) Delete(path string, h http.Handler) {
	r.Handle("DELETE", r.path+path, httpRouterWrapHandler(h))
}

// Head takes a path and http.Handler and adds them to the mux.
func (r *Router) Head(path string, h http.Handler) {
	r.Handle("HEAD", r.path+path, httpRouterWrapHandler(h))
}

func httpRouterWrapHandler(next http.Handler) httprouter.Handle {
	return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
		next.ServeHTTP(w, r)
	}
}

// TreeMux wraps HTTPTreeMux.
type TreeMux struct {
	*httptreemux.TreeMux
	path string
}

// NewTreeMux returns a wrapped HTTPTreeMux.
func NewTreeMux() *TreeMux {
	return &TreeMux{httptreemux.New(), ""}
}

// Group takes a path and returns a new TreeMux around the original HTTPTreeMux.
func (tm *TreeMux) Group(path string) *TreeMux {
	return &TreeMux{tm.TreeMux, tm.path + path}
}

// Options takes a path and http.Handler and adds them to the mux.
func (tm *TreeMux) Options(path string, h http.Handler) {
	tm.Handle("OPTIONS", tm.path+path, treeMuxWrapHandler(h))
}

// Get takes a path and http.Handler and adds them to the mux.
func (tm *TreeMux) Get(path string, h http.Handler) {
	tm.Handle("GET", tm.path+path, treeMuxWrapHandler(h))
}

// Post takes a path and http.Handler and adds them to the mux.
func (tm *TreeMux) Post(path string, h http.Handler) {
	tm.Handle("POST", tm.path+path, treeMuxWrapHandler(h))
}

// Put takes a path and http.Handler and adds them to the mux.
func (tm *TreeMux) Put(path string, h http.Handler) {
	tm.Handle("PUT", tm.path+path, treeMuxWrapHandler(h))
}

// Patch takes a path and http.Handler and adds them to the mux.
func (tm *TreeMux) Patch(path string, h http.Handler) {
	tm.Handle("PATCH", tm.path+path, treeMuxWrapHandler(h))
}

// Delete takes a path and http.Handler and adds them to the mux.
func (tm *TreeMux) Delete(path string, h http.Handler) {
	tm.Handle("DELETE", tm.path+path, treeMuxWrapHandler(h))
}

// Head takes a path and http.Handler and adds them to the mux.
func (tm *TreeMux) Head(path string, h http.Handler) {
	tm.Handle("HEAD", tm.path+path, treeMuxWrapHandler(h))
}

func treeMuxWrapHandler(next http.Handler) httptreemux.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request, _ map[string]string) {
		next.ServeHTTP(w, r)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"testing"
)

func TestChangeBodyMiddleware(t *testing.T) {
	command := "./examples/middleware/modify_response/modify_response.py"

	resp := response{Status: 201, Body: "original body"}
	req := requestDetails{Path: "/", Method: "GET", Destination: "hostname-x", Query: ""}

	payload := Payload{Response: resp, Request: req}

	newPayload, err := ExecuteMiddleware(command, payload)

	expect(t, err, nil)
	expect(t, newPayload.Response.Body, "body was replaced by middleware")
}

func TestMalformedPayloadMiddleware(t *testing.T) {
	command := "./examples/middleware/ruby_echo/echo.rb"

	resp := response{Status: 201, Body: "original body"}
	req := requestDetails{Path: "/", Method: "GET", Destination: "hostname-x", Query: ""}

	payload := Payload{Response: resp, Request: req}

	newPayload, err := ExecuteMiddleware(command, payload)

	expect(t, err, nil)
	expect(t, newPayload.Response.Body, "original body")
}

<commit_msg>test for go example<commit_after>package main

import (
	"testing"
)

func TestChangeBodyMiddleware(t *testing.T) {
	command := "./examples/middleware/modify_response/modify_response.py"

	resp := response{Status: 201, Body: "original body"}
	req := requestDetails{Path: "/", Method: "GET", Destination: "hostname-x", Query: ""}

	payload := Payload{Response: resp, Request: req}

	newPayload, err := ExecuteMiddleware(command, payload)

	expect(t, err, nil)
	expect(t, newPayload.Response.Body, "body was replaced by middleware")
}

func TestMalformedPayloadMiddleware(t *testing.T) {
	command := "./examples/middleware/ruby_echo/echo.rb"

	resp := response{Status: 201, Body: "original body"}
	req := requestDetails{Path: "/", Method: "GET", Destination: "hostname-x", Query: ""}

	payload := Payload{Response: resp, Request: req}

	newPayload, err := ExecuteMiddleware(command, payload)

	expect(t, err, nil)
	expect(t, newPayload.Response.Body, "original body")
}

func TestMakeCustom404(t *testing.T) {
	command := "go run ./examples/middleware/go_example/change_to_custom_404.go"

	resp := response{Status: 201, Body: "original body"}
	req := requestDetails{Path: "/", Method: "GET", Destination: "hostname-x", Query: ""}

	payload := Payload{Response: resp, Request: req}

	newPayload, err := ExecuteMiddleware(command, payload)

	expect(t, err, nil)
	expect(t, newPayload.Response.Body, "Custom body here")
	expect(t, newPayload.Response.Status, 404)
	expect(t, newPayload.Response.Headers["middleware"][0], "changed response")
}
<|endoftext|>


<commit_before>package xsdgen_test

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"

	"aqwari.net/xml/xsdgen"
)

func tmpfile() *os.File {
	f, err := ioutil.TempFile("", "xsdgen_test")
	if err != nil {
		panic(err)
	}
	return f
}

func xsdfile(s string) (filename string) {
	file := tmpfile()
	defer file.Close()
	fmt.Fprintf(file, `
		<schema xmlns="http://www.w3.org/2001/XMLSchema"
		        xmlns:tns="http://www.example.com/"
		        xmlns:xs="http://www.w3.org/2001/XMLSchema"
		        xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
		        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
		        targetNamespace="http://www.example.com/">
		  %s
		</schema>
	`, s)
	return file.Name()
}

func ExampleConfig_GenCLI() {
	var cfg xsdgen.Config
	cfg.Option(
		xsdgen.IgnoreAttributes("id", "href", "offset"),
		xsdgen.IgnoreElements("comment"),
		xsdgen.PackageName("webapi"),
		xsdgen.Replace("_", ""),
		xsdgen.HandleSOAPArrayType(),
		xsdgen.SOAPArrayAsSlice(),
	)
	if err := cfg.GenCLI("webapi.xsd", "deps/soap11.xsd"); err != nil {
		log.Fatal(err)
	}
}

func ExampleLogOutput() {
	var cfg xsdgen.Config
	cfg.Option(
		xsdgen.LogOutput(log.New(os.Stderr, "", 0)),
		xsdgen.LogLevel(2))
	if err := cfg.GenCLI("file.wsdl"); err != nil {
		log.Fatal(err)
	}
}

func ExampleIgnoreAttributes() {
	doc := xsdfile(`
	  <complexType name="ArrayOfString">
	    <any maxOccurs="unbounded" />
	    <attribute name="soapenc:arrayType" type="xs:string" />
	  </complexType>
	`)
	var cfg xsdgen.Config
	cfg.Option(xsdgen.IgnoreAttributes("arrayType"))

	out, err := cfg.GenSource(doc)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", out)

	// Output: package ws
	//
	// type ArrayOfString struct {
	// 	Items []string `xml:",any"`
	// }
}

func ExampleIgnoreElements() {
	doc := xsdfile(`
	  <complexType name="Person">
	    <sequence>
	      <element name="name" type="xs:string" />
	      <element name="deceased" type="soapenc:boolean" />
	      <element name="private" type="xs:int" />
	    </sequence>
	  </complexType>
	`)
	var cfg xsdgen.Config
	cfg.Option(
		xsdgen.IgnoreElements("private"),
		xsdgen.IgnoreAttributes("id", "href"))

	out, err := cfg.GenSource(doc)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", out)

	// Output: package ws
	//
	// type Person struct {
	// 	Name     string `xml:"http://www.example.com/ name"`
	// 	Deceased bool   `xml:"http://www.example.com/ deceased"`
	// }
}

func ExamplePackageName() {
	doc := xsdfile(`
	  <simpleType name="zipcode">
	    <restriction base="xs:string">
	      <length value="10" />
	    </restriction>
	  </simpleType>
	`)
	var cfg xsdgen.Config
	cfg.Option(xsdgen.PackageName("postal"))

	out, err := cfg.GenSource(doc)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", out)

	// Output: package postal
	//
	// // May be no more than 10 items long
	// type Zipcode string
}

func ExampleReplace() {
	doc := xsdfile(`
	  <complexType name="ArrayOfString">
	    <any maxOccurs="unbounded" />
	    <attribute name="soapenc:arrayType" type="xs:string" />
	  </complexType>
	`)
	var cfg xsdgen.Config
	cfg.Option(xsdgen.Replace("ArrayOf(.*)", "${1}Array"))

	out, err := cfg.GenSource(doc)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", out)

	// Output: package ws
	//
	// type StringArray struct {
	// 	ArrayType string   `xml:"arrayType,attr"`
	// 	Items     []string `xml:",any"`
	// }
}

func ExampleHandleSOAPArrayType() {
	doc := xsdfile(`
	  <complexType name="BoolArray">
	    <complexContent>
	      <restriction base="soapenc:Array">
	        <attribute ref="soapenc:arrayType" wsdl:arrayType="xs:boolean[]"/>
	      </restriction>
	    </complexContent>
	  </complexType>`)

	var cfg xsdgen.Config
	cfg.Option(xsdgen.HandleSOAPArrayType())

	out, err := cfg.GenSource(doc)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", out)

	// Output: package ws
	//
	// type BoolArray struct {
	// 	Offset ArrayCoordinate `xml:"offset,attr"`
	// 	Id     string          `xml:"id,attr"`
	// 	Href   string          `xml:"href,attr"`
	// 	Items  []bool          `xml:",any"`
	// }
}

func ExampleSOAPArrayAsSlice() {
	doc := xsdfile(`
	  <complexType name="BoolArray">
	    <complexContent>
	      <restriction base="soapenc:Array">
	        <attribute ref="soapenc:arrayType" wsdl:arrayType="xs:boolean[]"/>
	      </restriction>
	    </complexContent>
	  </complexType>`)

	var cfg xsdgen.Config
	cfg.Option(
		xsdgen.HandleSOAPArrayType(),
		xsdgen.SOAPArrayAsSlice(),
		xsdgen.LogOutput(log.New(os.Stderr, "", 0)),
		xsdgen.LogLevel(3),
		xsdgen.IgnoreAttributes("offset", "id", "href"))

	out, err := cfg.GenSource(doc)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", out)

	// Output: package ws
	//
	// import "encoding/xml"
	//
	// type BoolArray []bool
	//
	// func (a BoolArray) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	// 	var output struct {
	// 		ArrayType string `xml:"http://schemas.xmlsoap.org/wsdl/ arrayType,attr"`
	// 		Items     []bool `xml:" item"`
	// 	}
	// 	output.Items = []bool(a)
	// 	start.Attr = append(start.Attr, xml.Attr{Name: xml.Name{"", "xmlns:ns1"}, Value: "http://www.w3.org/2001/XMLSchema"})
	// 	output.ArrayType = "ns1:boolean[]"
	// 	return e.EncodeElement(&output, start)
	// }
	// func (a *BoolArray) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error) {
	// 	var tok xml.Token
	// 	for tok, err = d.Token(); err == nil; tok, err = d.Token() {
	// 		if tok, ok := tok.(xml.StartElement); ok {
	// 			var item bool
	// 			if err = d.DecodeElement(&item, &tok); err == nil {
	// 				*a = append(*a, item)
	// 			}
	// 		}
	// 		if _, ok := tok.(xml.EndElement); ok {
	// 			break
	// 		}
	// 	}
	// 	return err
	// }
}

func ExampleUseFieldNames() {
	doc := xsdfile(`
	  <complexType name="library">
	    <sequence>
	      <element name="book" maxOccurs="unbounded">
	        <complexType>
	          <all>
	            <element name="title" type="xs:string" />
	            <element name="published" type="xs:date" />
	            <element name="author" type="xs:string" />
	          </all>
	        </complexType>
	      </element>
	    </sequence>
	  </complexType>`)

	var cfg xsdgen.Config
	cfg.Option(xsdgen.UseFieldNames())

	out, err := cfg.GenSource(doc)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", out)

	// Output: package ws
	//
	// import (
	// 	"bytes"
	// 	"encoding/xml"
	// 	"time"
	// )
	//
	// type Book struct {
	// 	Title     string    `xml:"http://www.example.com/ title"`
	// 	Published time.Time `xml:"http://www.example.com/ published"`
	// 	Author    string    `xml:"http://www.example.com/ author"`
	// }
	//
	// func (t *Book) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	// 	type T Book
	// 	var layout struct {
	// 		*T
	// 		Published xsdDate `xml:"http://www.example.com/ published"`
	// 	}
	// 	layout.T = (*T)(t)
	// 	layout.Published = xsdDate(layout.T.Published)
	// 	return e.EncodeElement(layout, start)
	// }
	// func (t *Book) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	// 	type T Book
	// 	var overlay struct {
	// 		*T
	// 		Published xsdDate `xml:"http://www.example.com/ published"`
	// 	}
	// 	overlay.T = (*T)(t)
	// 	if err := d.Decode(&overlay, &start); err != nil {
	// 		return err
	// 	}
	// 	overlay.T.Published = overlay.Published
	// 	return nil
	// }
	//
	// type Library struct {
	// 	Book      []Book    `xml:"http://www.example.com/ book"`
	// 	Title     string    `xml:"http://www.example.com/ title"`
	// 	Published time.Time `xml:"http://www.example.com/ published"`
	// 	Author    string    `xml:"http://www.example.com/ author"`
	// }
	//
	// func (t *Library) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	// 	type T Library
	// 	var layout struct {
	// 		*T
	// 		Published xsdDate `xml:"http://www.example.com/ published"`
	// 	}
	// 	layout.T = (*T)(t)
	// 	layout.Published = xsdDate(layout.T.Published)
	// 	return e.EncodeElement(layout, start)
	// }
	// func (t *Library) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	// 	type T Library
	// 	var overlay struct {
	// 		*T
	// 		Published xsdDate `xml:"http://www.example.com/ published"`
	// 	}
	// 	overlay.T = (*T)(t)
	// 	if err := d.Decode(&overlay, &start); err != nil {
	// 		return err
	// 	}
	// 	overlay.T.Published = overlay.Published
	// 	return nil
	// }
	//
	// type xsdDate time.Time
	//
	// func (t *xsdDate) UnmarshalText(text []byte) error {
	// 	return _unmarshalTime(text, (*time.Time)(t), "2006-01-02")
	// }
	// func (t xsdDate) UnmarshalText() ([]byte, error) {
	// 	return []byte((time.Time)(t).Format("2006-01-02")), nil
	// }
	// func _unmarshalTime(text []byte, t *time.Time, format string) (err error) {
	// 	s := string(bytes.TrimSpace(text))
	// 	*t, err = time.Parse(format, s)
	// 	if _, ok := err.(*time.ParseError); ok {
	// 		*t, err = time.Parse(format+"Z07:00", s)
	// 	}
	// 	return err
	// }

}
<commit_msg>Fix example output<commit_after>package xsdgen_test

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"

	"aqwari.net/xml/xsdgen"
)

func tmpfile() *os.File {
	f, err := ioutil.TempFile("", "xsdgen_test")
	if err != nil {
		panic(err)
	}
	return f
}

func xsdfile(s string) (filename string) {
	file := tmpfile()
	defer file.Close()
	fmt.Fprintf(file, `
		<schema xmlns="http://www.w3.org/2001/XMLSchema"
		        xmlns:tns="http://www.example.com/"
		        xmlns:xs="http://www.w3.org/2001/XMLSchema"
		        xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
		        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
		        targetNamespace="http://www.example.com/">
		  %s
		</schema>
	`, s)
	return file.Name()
}

func ExampleConfig_GenCLI() {
	var cfg xsdgen.Config
	cfg.Option(
		xsdgen.IgnoreAttributes("id", "href", "offset"),
		xsdgen.IgnoreElements("comment"),
		xsdgen.PackageName("webapi"),
		xsdgen.Replace("_", ""),
		xsdgen.HandleSOAPArrayType(),
		xsdgen.SOAPArrayAsSlice(),
	)
	if err := cfg.GenCLI("webapi.xsd", "deps/soap11.xsd"); err != nil {
		log.Fatal(err)
	}
}

func ExampleLogOutput() {
	var cfg xsdgen.Config
	cfg.Option(
		xsdgen.LogOutput(log.New(os.Stderr, "", 0)),
		xsdgen.LogLevel(2))
	if err := cfg.GenCLI("file.wsdl"); err != nil {
		log.Fatal(err)
	}
}

func ExampleIgnoreAttributes() {
	doc := xsdfile(`
	  <complexType name="ArrayOfString">
	    <any maxOccurs="unbounded" />
	    <attribute name="soapenc:arrayType" type="xs:string" />
	  </complexType>
	`)
	var cfg xsdgen.Config
	cfg.Option(xsdgen.IgnoreAttributes("arrayType"))

	out, err := cfg.GenSource(doc)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", out)

	// Output: package ws
	//
	// type ArrayOfString struct {
	// 	Items []string `xml:",any"`
	// }
}

func ExampleIgnoreElements() {
	doc := xsdfile(`
	  <complexType name="Person">
	    <sequence>
	      <element name="name" type="xs:string" />
	      <element name="deceased" type="soapenc:boolean" />
	      <element name="private" type="xs:int" />
	    </sequence>
	  </complexType>
	`)
	var cfg xsdgen.Config
	cfg.Option(
		xsdgen.IgnoreElements("private"),
		xsdgen.IgnoreAttributes("id", "href"))

	out, err := cfg.GenSource(doc)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", out)

	// Output: package ws
	//
	// type Person struct {
	// 	Name     string `xml:"http://www.example.com/ name"`
	// 	Deceased bool   `xml:"http://www.example.com/ deceased"`
	// }
}

func ExamplePackageName() {
	doc := xsdfile(`
	  <simpleType name="zipcode">
	    <restriction base="xs:string">
	      <length value="10" />
	    </restriction>
	  </simpleType>
	`)
	var cfg xsdgen.Config
	cfg.Option(xsdgen.PackageName("postal"))

	out, err := cfg.GenSource(doc)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", out)

	// Output: package postal
	//
	// // May be no more than 10 items long
	// type Zipcode string
}

func ExampleReplace() {
	doc := xsdfile(`
	  <complexType name="ArrayOfString">
	    <any maxOccurs="unbounded" />
	    <attribute name="soapenc:arrayType" type="xs:string" />
	  </complexType>
	`)
	var cfg xsdgen.Config
	cfg.Option(xsdgen.Replace("ArrayOf(.*)", "${1}Array"))

	out, err := cfg.GenSource(doc)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", out)

	// Output: package ws
	//
	// type StringArray struct {
	// 	ArrayType string   `xml:"arrayType,attr"`
	// 	Items     []string `xml:",any"`
	// }
}

func ExampleHandleSOAPArrayType() {
	doc := xsdfile(`
	  <complexType name="BoolArray">
	    <complexContent>
	      <restriction base="soapenc:Array">
	        <attribute ref="soapenc:arrayType" wsdl:arrayType="xs:boolean[]"/>
	      </restriction>
	    </complexContent>
	  </complexType>`)

	var cfg xsdgen.Config
	cfg.Option(xsdgen.HandleSOAPArrayType())

	out, err := cfg.GenSource(doc)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", out)

	// Output: package ws
	//
	// type BoolArray struct {
	// 	Offset ArrayCoordinate `xml:"offset,attr"`
	// 	Id     string          `xml:"id,attr"`
	// 	Href   string          `xml:"href,attr"`
	// 	Items  []bool          `xml:",any"`
	// }
}

func ExampleSOAPArrayAsSlice() {
	doc := xsdfile(`
	  <complexType name="BoolArray">
	    <complexContent>
	      <restriction base="soapenc:Array">
	        <attribute ref="soapenc:arrayType" wsdl:arrayType="xs:boolean[]"/>
	      </restriction>
	    </complexContent>
	  </complexType>`)

	var cfg xsdgen.Config
	cfg.Option(
		xsdgen.HandleSOAPArrayType(),
		xsdgen.SOAPArrayAsSlice(),
		xsdgen.LogOutput(log.New(os.Stderr, "", 0)),
		xsdgen.LogLevel(3),
		xsdgen.IgnoreAttributes("offset", "id", "href"))

	out, err := cfg.GenSource(doc)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", out)

	// Output: package ws
	//
	// import "encoding/xml"
	//
	// type BoolArray []bool
	//
	// func (a BoolArray) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	// 	var output struct {
	// 		ArrayType string `xml:"http://schemas.xmlsoap.org/wsdl/ arrayType,attr"`
	// 		Items     []bool `xml:" item"`
	// 	}
	// 	output.Items = []bool(a)
	// 	start.Attr = append(start.Attr, xml.Attr{Name: xml.Name{"", "xmlns:ns1"}, Value: "http://www.w3.org/2001/XMLSchema"})
	// 	output.ArrayType = "ns1:boolean[]"
	// 	return e.EncodeElement(&output, start)
	// }
	// func (a *BoolArray) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error) {
	// 	var tok xml.Token
	// 	for tok, err = d.Token(); err == nil; tok, err = d.Token() {
	// 		if tok, ok := tok.(xml.StartElement); ok {
	// 			var item bool
	// 			if err = d.DecodeElement(&item, &tok); err == nil {
	// 				*a = append(*a, item)
	// 			}
	// 		}
	// 		if _, ok := tok.(xml.EndElement); ok {
	// 			break
	// 		}
	// 	}
	// 	return err
	// }
}

func ExampleUseFieldNames() {
	doc := xsdfile(`
	  <complexType name="library">
	    <sequence>
	      <element name="book" maxOccurs="unbounded">
	        <complexType>
	          <all>
	            <element name="title" type="xs:string" />
	            <element name="published" type="xs:date" />
	            <element name="author" type="xs:string" />
	          </all>
	        </complexType>
	      </element>
	    </sequence>
	  </complexType>`)

	var cfg xsdgen.Config
	cfg.Option(xsdgen.UseFieldNames())

	out, err := cfg.GenSource(doc)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", out)

	// Output: package ws
	//
	// import (
	// 	"bytes"
	// 	"encoding/xml"
	// 	"time"
	// )
	//
	// type Book struct {
	// 	Title     string    `xml:"http://www.example.com/ title"`
	// 	Published time.Time `xml:"http://www.example.com/ published"`
	// 	Author    string    `xml:"http://www.example.com/ author"`
	// }
	//
	// func (t *Book) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	// 	type T Book
	// 	var layout struct {
	// 		*T
	// 		Published xsdDate `xml:"http://www.example.com/ published"`
	// 	}
	// 	layout.T = (*T)(t)
	// 	layout.Published = xsdDate(layout.T.Published)
	// 	return e.EncodeElement(layout, start)
	// }
	// func (t *Book) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	// 	type T Book
	// 	var overlay struct {
	// 		*T
	// 		Published xsdDate `xml:"http://www.example.com/ published"`
	// 	}
	// 	overlay.T = (*T)(t)
	// 	if err := d.DecodeElement(&overlay, &start); err != nil {
	// 		return err
	// 	}
	// 	overlay.T.Published = time.Time(overlay.Published)
	// 	return nil
	// }
	//
	// type Library struct {
	// 	Book      []Book    `xml:"http://www.example.com/ book"`
	// 	Title     string    `xml:"http://www.example.com/ title"`
	// 	Published time.Time `xml:"http://www.example.com/ published"`
	// 	Author    string    `xml:"http://www.example.com/ author"`
	// }
	//
	// func (t *Library) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	// 	type T Library
	// 	var layout struct {
	// 		*T
	// 		Published xsdDate `xml:"http://www.example.com/ published"`
	// 	}
	// 	layout.T = (*T)(t)
	// 	layout.Published = xsdDate(layout.T.Published)
	// 	return e.EncodeElement(layout, start)
	// }
	// func (t *Library) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	// 	type T Library
	// 	var overlay struct {
	// 		*T
	// 		Published xsdDate `xml:"http://www.example.com/ published"`
	// 	}
	// 	overlay.T = (*T)(t)
	// 	if err := d.DecodeElement(&overlay, &start); err != nil {
	// 		return err
	// 	}
	// 	overlay.T.Published = time.Time(overlay.Published)
	// 	return nil
	// }
	//
	// type xsdDate time.Time
	//
	// func (t *xsdDate) UnmarshalText(text []byte) error {
	// 	return _unmarshalTime(text, (*time.Time)(t), "2006-01-02")
	// }
	// func (t xsdDate) MarshalText() ([]byte, error) {
	// 	return []byte((time.Time)(t).Format("2006-01-02")), nil
	// }
	// func _unmarshalTime(text []byte, t *time.Time, format string) (err error) {
	// 	s := string(bytes.TrimSpace(text))
	// 	*t, err = time.Parse(format, s)
	// 	if _, ok := err.(*time.ParseError); ok {
	// 		*t, err = time.Parse(format+"Z07:00", s)
	// 	}
	// 	return err
	// }

}
<|endoftext|>


<commit_before>// Copyright 2012 commandmocker authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package commandmocker

import (
	"bufio"
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"strings"
	"sync"
	"syscall"
	"text/template"
	"time"
)

var source = `#!/bin/bash -e

output="{{.output}}"
dirname=$(dirname ${0})
echo -n "${output}"{{if .status}} >&2{{end}} | tee -a ${dirname}/.out
for i in "$@"
do
	echo $i >> ${dirname}/.params
done
touch ${dirname}/.ran
exit {{.status}}
`

var pathMutex sync.Mutex

func add(name, output string, status int) (tempdir string, err error) {
	pathMutex.Lock()
	tempdir = path.Join(os.TempDir(), "commandmocker+"+time.Now().Format("20060102150405999999999"))
	_, err = os.Stat(tempdir)
	for !os.IsNotExist(err) {
		tempdir = path.Join(os.TempDir(), "commandmocker+"+time.Now().Format("20060102150405999999999"))
		_, err = os.Stat(tempdir)
	}
	err = os.MkdirAll(tempdir, 0777)
	if err != nil {
		return
	}
	f, err := os.OpenFile(path.Join(tempdir, name), syscall.O_WRONLY|syscall.O_CREAT|syscall.O_TRUNC, 0755)
	if err != nil {
		return
	}
	defer f.Close()
	t, err := template.New(name).Parse(source)
	if err != nil {
		return
	}
	param := map[string]interface{}{
		"output": output,
		"status": status,
	}
	err = t.Execute(f, param)
	if err != nil {
		return
	}
	path := os.Getenv("PATH")
	path = tempdir + ":" + path
	err = os.Setenv("PATH", path)
	return
}

// Add creates a temporary directory containing an executable file named "name"
// that prints "output" when executed. It also adds the temporary directory to
// the first position of $PATH.
//
// It returns the temporary directory path (for future removing, using the
// Remove function) and an error if any happen.
func Add(name, output string) (tempdir string, err error) {
	return add(name, output, 0)
}

// Error works like Add, but the created executable returns a non-zero status
// code (an error). The returned status code will be the value provided by
// status.
func Error(name, output string, status int) (tempdir string, err error) {
	return add(name, output, status)
}

// Ran indicates whether the mocked executable was called or not.
//
// It just checks if the given tempdir contains a .ran file.
func Ran(tempdir string) bool {
	p := path.Join(tempdir, ".ran")
	_, err := os.Stat(p)
	return err == nil || !os.IsNotExist(err)
}

// Output returns the output generated by the previously added command
// execution.
func Output(tempdir string) string {
	p := path.Join(tempdir, ".out")
	f, err := os.OpenFile(p, os.O_RDONLY, 0755)
	if err != nil {
		return ""
	}
	defer f.Close()
	b, err := ioutil.ReadAll(f)
	if err != nil {
		return ""
	}
	return string(b)
}

// Parameters returns a slice containing all positional parameters given to the
// command mocked in tempdir in its last execution.
func Parameters(tempdir string) []string {
	p := path.Join(tempdir, ".params")
	f, err := os.Open(p)
	if err != nil {
		return nil
	}
	defer f.Close()
	var params []string
	reader := bufio.NewReader(f)
	line, err := reader.ReadString('\n')
	for err == nil {
		params = append(params, strings.TrimSpace(line))
		line, err = reader.ReadString('\n')
	}
	return params
}

// Remove removes the tempdir from $PATH and from file system.
//
// This function is intended only to undo what Add does. It returns error if
// the given tempdir is not a temporary directory.
func Remove(tempdir string) error {
	if !strings.HasPrefix(tempdir, os.TempDir()) {
		return errors.New("Remove can only remove temporary directories, tryied to remove " + tempdir)
	}
	path := os.Getenv("PATH")
	index := strings.Index(path, tempdir)
	if index < 0 {
		pathMutex.Unlock()
		return errors.New(fmt.Sprintf("%s is not in $PATH", tempdir))
	}
	path = path[:index] + path[index+len(tempdir)+1:]
	err := os.Setenv("PATH", path)
	pathMutex.Unlock()
	if err != nil {
		return err
	}
	return os.RemoveAll(tempdir)
}
<commit_msg>mocker: use random bytes instead of time.Now()<commit_after>// Copyright 2013 commandmocker authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package commandmocker

import (
	"bufio"
	"crypto/rand"
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"strings"
	"sync"
	"syscall"
	"text/template"
)

var source = `#!/bin/bash -e

output="{{.output}}"
dirname=$(dirname ${0})
echo -n "${output}"{{if .status}} >&2{{end}} | tee -a ${dirname}/.out
for i in "$@"
do
	echo $i >> ${dirname}/.params
done
touch ${dirname}/.ran
exit {{.status}}
`

var pathMutex sync.Mutex

func add(name, output string, status int) (tempdir string, err error) {
	pathMutex.Lock()
	var buf [8]byte
	rand.Read(buf[:])
	tempdir = path.Join(os.TempDir(), fmt.Sprintf("commandmocker-%x", buf))
	_, err = os.Stat(tempdir)
	for !os.IsNotExist(err) {
		rand.Read(buf[:])
		tempdir = path.Join(os.TempDir(), fmt.Sprintf("commandmocker-%x", buf))
		_, err = os.Stat(tempdir)
	}
	err = os.MkdirAll(tempdir, 0777)
	if err != nil {
		return
	}
	f, err := os.OpenFile(path.Join(tempdir, name), syscall.O_WRONLY|syscall.O_CREAT|syscall.O_TRUNC, 0755)
	if err != nil {
		return
	}
	defer f.Close()
	t, err := template.New(name).Parse(source)
	if err != nil {
		return
	}
	param := map[string]interface{}{
		"output": output,
		"status": status,
	}
	err = t.Execute(f, param)
	if err != nil {
		return
	}
	path := os.Getenv("PATH")
	path = tempdir + ":" + path
	err = os.Setenv("PATH", path)
	return
}

// Add creates a temporary directory containing an executable file named "name"
// that prints "output" when executed. It also adds the temporary directory to
// the first position of $PATH.
//
// It returns the temporary directory path (for future removing, using the
// Remove function) and an error if any happen.
func Add(name, output string) (tempdir string, err error) {
	return add(name, output, 0)
}

// Error works like Add, but the created executable returns a non-zero status
// code (an error). The returned status code will be the value provided by
// status.
func Error(name, output string, status int) (tempdir string, err error) {
	return add(name, output, status)
}

// Ran indicates whether the mocked executable was called or not.
//
// It just checks if the given tempdir contains a .ran file.
func Ran(tempdir string) bool {
	p := path.Join(tempdir, ".ran")
	_, err := os.Stat(p)
	return err == nil || !os.IsNotExist(err)
}

// Output returns the output generated by the previously added command
// execution.
func Output(tempdir string) string {
	p := path.Join(tempdir, ".out")
	f, err := os.OpenFile(p, os.O_RDONLY, 0755)
	if err != nil {
		return ""
	}
	defer f.Close()
	b, err := ioutil.ReadAll(f)
	if err != nil {
		return ""
	}
	return string(b)
}

// Parameters returns a slice containing all positional parameters given to the
// command mocked in tempdir in its last execution.
func Parameters(tempdir string) []string {
	p := path.Join(tempdir, ".params")
	f, err := os.Open(p)
	if err != nil {
		return nil
	}
	defer f.Close()
	var params []string
	reader := bufio.NewReader(f)
	line, err := reader.ReadString('\n')
	for err == nil {
		params = append(params, strings.TrimSpace(line))
		line, err = reader.ReadString('\n')
	}
	return params
}

// Remove removes the tempdir from $PATH and from file system.
//
// This function is intended only to undo what Add does. It returns error if
// the given tempdir is not a temporary directory.
func Remove(tempdir string) error {
	if !strings.HasPrefix(tempdir, os.TempDir()) {
		return errors.New("Remove can only remove temporary directories, tryied to remove " + tempdir)
	}
	path := os.Getenv("PATH")
	index := strings.Index(path, tempdir)
	if index < 0 {
		pathMutex.Unlock()
		return errors.New(fmt.Sprintf("%s is not in $PATH", tempdir))
	}
	path = path[:index] + path[index+len(tempdir)+1:]
	err := os.Setenv("PATH", path)
	pathMutex.Unlock()
	if err != nil {
		return err
	}
	return os.RemoveAll(tempdir)
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/pachyderm/pachyderm/src/cmd/pachctl/cmd"
	"go.pedge.io/env"
)

type appEnv struct {
	Address string `env:"PACH_ADDRESS,default=0.0.0.0:650"`
}

func main() {
	env.Main(do, &appEnv{})
}

func do(appEnvObj interface{}) error {
	appEnv := appEnvObj.(*appEnv)
	rootCmd, err := cmd.PachctlCmd(appEnv.Address)
	if err != nil {
		return err
	}
	return rootCmd.Execute()
}
<commit_msg>Change port to 30650.<commit_after>package main

import (
	"github.com/pachyderm/pachyderm/src/cmd/pachctl/cmd"
	"go.pedge.io/env"
)

type appEnv struct {
	Address string `env:"PACH_ADDRESS,default=0.0.0.0:30650"`
}

func main() {
	env.Main(do, &appEnv{})
}

func do(appEnvObj interface{}) error {
	appEnv := appEnvObj.(*appEnv)
	rootCmd, err := cmd.PachctlCmd(appEnv.Address)
	if err != nil {
		return err
	}
	return rootCmd.Execute()
}
<|endoftext|>


<commit_before>package vaultutil

import (
	vaultapi "github.com/hashicorp/vault/api"
)

func CreateMount(c *vaultapi.Client, mount_path, mount_type string) error {
	data := map[string]interface{}{"type": mount_type}

	_, err := c.Logical().Write("sys/mounts/"+mount_path, data)
	if err != nil {
		return err
	}
	return nil
}

func DoRemount(c *vaultapi.Client, mount_path, new_mount_path string) error {
	data := map[string]interface{}{"from": mount_path, "to": new_mount_path}

	_, err := c.Logical().Write("sys/remount", data)
	if err != nil {
		return err
	}
	return nil
}

func DeleteMount(c *vaultapi.Client, mount_path string) error {
	_, err := c.Logical().Delete("sys/mounts/" + mount_path)
	if err != nil {
		return err
	}
	return nil
}

func ListMounts(c *vaultapi.Client) error {
	_, err := c.Logical().Read("sys/mounts")
	if err != nil {
		return err
	}
	return nil
}
<commit_msg>Adding return data for ListMounts<commit_after>package vaultutil

import (
	vaultapi "github.com/hashicorp/vault/api"
)

func CreateMount(c *vaultapi.Client, mount_path, mount_type string) error {
	data := map[string]interface{}{"type": mount_type}

	_, err := c.Logical().Write("sys/mounts/"+mount_path, data)
	if err != nil {
		return err
	}
	return nil
}

func DoRemount(c *vaultapi.Client, mount_path, new_mount_path string) error {
	data := map[string]interface{}{"from": mount_path, "to": new_mount_path}

	_, err := c.Logical().Write("sys/remount", data)
	if err != nil {
		return err
	}
	return nil
}

func DeleteMount(c *vaultapi.Client, mount_path string) error {
	_, err := c.Logical().Delete("sys/mounts/" + mount_path)
	if err != nil {
		return err
	}
	return nil
}

func ListMounts(c *vaultapi.Client) (map[string]*api.MountOutput, error) {
	data, err := c.Sys().ListMounts()
	if err != nil {
		return data, err
	}
	return data, err
}
<|endoftext|>


<commit_before>package cloudflare

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"time"

	"github.com/pkg/errors"
)

type ZoneCacheVariantsValues struct {
	Avif []string `json:"avif,omitempty"`
	Bmp  []string `json:"bmp,omitempty"`
	Gif  []string `json:"gif,omitempty"`
	Jpeg []string `json:"jpeg,omitempty"`
	Jpg  []string `json:"jpg,omitempty"`
	Jpg2 []string `json:"jpg2,omitempty"`
	Jp2  []string `json:"jp2,omitempty"`
	Png  []string `json:"png,omitempty"`
	Tiff []string `json:"tiff,omitempty"`
	Tif  []string `json:"tif,omitempty"`
	Webp []string `json:"webp,omitempty"`
}

type ZoneCacheVariants struct {
	ModifiedOn time.Time               `json:"modified_on"`
	Value      ZoneCacheVariantsValues `json:"value"`
}

type updateZoneCacheVariantsRequest struct {
	Value ZoneCacheVariantsValues `json:"value"`
}

type zoneCacheVariantsSingleResponse struct {
	Response
	Result ZoneCacheVariants `json:"result"`
}

// ZoneCacheVariants returns information about the current cache variants
//
// API reference: https://api.cloudflare.com/#zone-cache-settings-get-variants-setting
func (api *API) ZoneCacheVariants(ctx context.Context, zoneID string) (ZoneCacheVariants, error) {
	uri := fmt.Sprintf("/zones/%s/cache/variants", zoneID)
	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
	if err != nil {
		return ZoneCacheVariants{}, err
	}
	var r zoneCacheVariantsSingleResponse
	err = json.Unmarshal(res, &r)
	if err != nil {
		return ZoneCacheVariants{}, errors.Wrap(err, errUnmarshalError)
	}
	return r.Result, nil
}

// ZoneCacheVariants updates the cache variants for a given zone.
//
// API reference: https://api.cloudflare.com/#zone-cache-settings-change-variants-setting
func (api *API) UpdateZoneCacheVariants(ctx context.Context, zoneID string, variants ZoneCacheVariantsValues) (ZoneCacheVariants, error) {
	uri := fmt.Sprintf("/zones/%s/cache/variants", zoneID)

	updateReq := updateZoneCacheVariantsRequest{Value: variants}
	res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, updateReq)
	if err != nil {
		return ZoneCacheVariants{}, err
	}

	response := &zoneCacheVariantsSingleResponse{}
	err = json.Unmarshal(res, &response)
	if err != nil {
		return ZoneCacheVariants{}, errors.Wrap(err, errUnmarshalError)
	}

	return response.Result, nil
}

// DeleteZoneCacheVariants deletes cache variants for a given zone.
//
// API reference: https://api.cloudflare.com/#zone-cache-settings-delete-variants-setting
func (api *API) DeleteZoneCacheVariants(ctx context.Context, zoneID string) error {
	uri := fmt.Sprintf("/zones/%s/cache/variants", zoneID)
	_, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil)
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>Fix documentation mistake<commit_after>package cloudflare

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"time"

	"github.com/pkg/errors"
)

type ZoneCacheVariantsValues struct {
	Avif []string `json:"avif,omitempty"`
	Bmp  []string `json:"bmp,omitempty"`
	Gif  []string `json:"gif,omitempty"`
	Jpeg []string `json:"jpeg,omitempty"`
	Jpg  []string `json:"jpg,omitempty"`
	Jpg2 []string `json:"jpg2,omitempty"`
	Jp2  []string `json:"jp2,omitempty"`
	Png  []string `json:"png,omitempty"`
	Tiff []string `json:"tiff,omitempty"`
	Tif  []string `json:"tif,omitempty"`
	Webp []string `json:"webp,omitempty"`
}

type ZoneCacheVariants struct {
	ModifiedOn time.Time               `json:"modified_on"`
	Value      ZoneCacheVariantsValues `json:"value"`
}

type updateZoneCacheVariantsRequest struct {
	Value ZoneCacheVariantsValues `json:"value"`
}

type zoneCacheVariantsSingleResponse struct {
	Response
	Result ZoneCacheVariants `json:"result"`
}

// ZoneCacheVariants returns information about the current cache variants
//
// API reference: https://api.cloudflare.com/#zone-cache-settings-get-variants-setting
func (api *API) ZoneCacheVariants(ctx context.Context, zoneID string) (ZoneCacheVariants, error) {
	uri := fmt.Sprintf("/zones/%s/cache/variants", zoneID)
	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
	if err != nil {
		return ZoneCacheVariants{}, err
	}
	var r zoneCacheVariantsSingleResponse
	err = json.Unmarshal(res, &r)
	if err != nil {
		return ZoneCacheVariants{}, errors.Wrap(err, errUnmarshalError)
	}
	return r.Result, nil
}

// UpdateZoneCacheVariants updates the cache variants for a given zone.
//
// API reference: https://api.cloudflare.com/#zone-cache-settings-change-variants-setting
func (api *API) UpdateZoneCacheVariants(ctx context.Context, zoneID string, variants ZoneCacheVariantsValues) (ZoneCacheVariants, error) {
	uri := fmt.Sprintf("/zones/%s/cache/variants", zoneID)

	updateReq := updateZoneCacheVariantsRequest{Value: variants}
	res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, updateReq)
	if err != nil {
		return ZoneCacheVariants{}, err
	}

	response := &zoneCacheVariantsSingleResponse{}
	err = json.Unmarshal(res, &response)
	if err != nil {
		return ZoneCacheVariants{}, errors.Wrap(err, errUnmarshalError)
	}

	return response.Result, nil
}

// DeleteZoneCacheVariants deletes cache variants for a given zone.
//
// API reference: https://api.cloudflare.com/#zone-cache-settings-delete-variants-setting
func (api *API) DeleteZoneCacheVariants(ctx context.Context, zoneID string) error {
	uri := fmt.Sprintf("/zones/%s/cache/variants", zoneID)
	_, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil)
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package json

import (
	"encoding/json"
	//"errors"
	"fmt"
	"io"
	"strings"

	messages "github.com/cucumber/cucumber-messages-go/v6"
	gio "github.com/gogo/protobuf/io"
)

type jsonFeature struct {
	Description string                `json:"description"`
	Elements    []*jsonFeatureElement `json:"elements"`
	ID          string                `json:"id"`
	Keyword     string                `json:"keyword"`
	Line        uint32                `json:"line"`
	Name        string                `json:"name"`
	URI         string                `json:"uri"`
	Tags        []*jsonTag            `json:"tags,omitempty"`
}

type jsonFeatureElement struct {
	Description string      `json:"description"`
	ID          string      `json:"id,omitempty"`
	Keyword     string      `json:"keyword"`
	Line        uint32      `json:"line"`
	Name        string      `json:"name"`
	Steps       []*jsonStep `json:"steps"`
	Type        string      `json:"type"`
	Tags        []*jsonTag  `json:"tags,omitempty"`
}

type jsonStep struct {
	Keyword   string              `json:"keyword"`
	Line      uint32              `json:"line"`
	Name      string              `json:"name"`
	Result    *jsonStepResult     `json:"result"`
	Match     *jsonStepMatch      `json:"match,omitempty"`
	DocString *jsonDocString      `json:"doc_string,omitempty"`
	Rows      []*jsonDatatableRow `json:"rows,omitempty"`
}

type jsonDocString struct {
	ContentType string `json:"content_type"`
	Line        uint32 `json:"line"`
	Value       string `json:"value"`
}

type jsonDatatableRow struct {
	Cells []string `json:"cells"`
}

type jsonStepResult struct {
	Duration     uint64 `json:"duration,omitempty"`
	Status       string `json:"status"`
	ErrorMessage string `json:"error_message,omitempty"`
}

type jsonStepMatch struct {
	Location string `json:"location"`
}

type jsonTag struct {
	Line uint32 `json:"line"`
	Name string `json:"name"`
}

type Formatter struct {
	lookup *MessageLookup

	jsonFeatures            []*jsonFeature
	jsonFeaturesByURI       map[string]*jsonFeature
	jsonStepsByPickleStepId map[string]*jsonStep
	exampleRowIndexById     map[string]int
}

// ProcessMessages writes a JSON report to STDOUT
func (self *Formatter) ProcessMessages(stdin io.Reader, stdout io.Writer) (err error) {
	self.lookup = &MessageLookup{}
	self.lookup.Initialize()

	self.jsonFeatures = make([]*jsonFeature, 0)
	self.jsonFeaturesByURI = make(map[string]*jsonFeature)
	self.jsonStepsByPickleStepId = make(map[string]*jsonStep)
	self.exampleRowIndexById = make(map[string]int)

	reader := gio.NewDelimitedReader(stdin, 4096)

	for {
		envelope := &messages.Envelope{}
		err := reader.ReadMsg(envelope)
		if err == io.EOF {
			break
		}
		if err != nil {
			return err
		}

		self.lookup.ProcessMessage(envelope)

		switch m := envelope.Message.(type) {
		case *messages.Envelope_GherkinDocument:
			for _, child := range m.GherkinDocument.Feature.Children {
				scenario := child.GetScenario()
				if scenario != nil {
					for _, example := range scenario.Examples {
						for index, row := range example.TableBody {
							// index + 2: it's a 1 based index and the header is counted too.
							self.exampleRowIndexById[row.Id] = index + 2
						}
					}
				}
			}

		case *messages.Envelope_Pickle:
			pickle := m.Pickle
			jsonFeature := self.findOrCreateJsonFeature(pickle)
			scenario := self.lookup.LookupScenario(pickle.SourceIds[0])
			// TODO: find a better way to get backgrounds
			background := &messages.GherkinDocument_Feature_Background{}
			scenarioJsonSteps := make([]*jsonStep, 0)
			backgroundJsonSteps := make([]*jsonStep, 0)

			for _, pickleStep := range pickle.Steps {
				step := self.lookup.LookupStep(pickleStep.StepId)
				jsonStep := &jsonStep{
					Keyword: step.Keyword,
					Line:    step.Location.Line,
					Name:    pickleStep.Text,
					// The match field defaults to the Gherkin step itself for some curious reason
					Match: &jsonStepMatch{
						Location: fmt.Sprintf("%s", pickle.Uri),
					},
				}

				docString := step.GetDocString()
				if docString != nil {
					jsonStep.DocString = &jsonDocString{
						Line:        docString.Location.Line,
						ContentType: docString.ContentType,
						Value:       docString.Content,
					}
				}

				datatable := step.GetDataTable()
				if datatable != nil {
					jsonStep.Rows = make([]*jsonDatatableRow, len(datatable.GetRows()))
					for rowIndex, row := range datatable.GetRows() {
						cells := make([]string, len(row.Cells))
						for cellIndex, cell := range row.Cells {
							cells[cellIndex] = cell.Value
						}

						jsonStep.Rows[rowIndex] = &jsonDatatableRow{
							Cells: cells,
						}
					}
				}
				if self.lookup.IsBackgroundStep(step.Id) {
					backgroundJsonSteps = append(backgroundJsonSteps, jsonStep)
					background = self.lookup.LookupBrackgroundByStepId(step.Id)
				} else {
					scenarioJsonSteps = append(scenarioJsonSteps, jsonStep)
				}

				self.jsonStepsByPickleStepId[pickleStep.Id] = jsonStep
			}

			if len(backgroundJsonSteps) > 0 {
				jsonFeature.Elements = append(jsonFeature.Elements, &jsonFeatureElement{
					Description: background.Description,
					Keyword:     background.Keyword,
					Line:        background.Location.Line,
					Steps:       backgroundJsonSteps,
					Type:        "background",
				})
			}

			scenarioID := fmt.Sprintf("%s;%s", jsonFeature.ID, makeId(scenario.Name))

			if len(pickle.SourceIds) > 1 {
				exampleRow := self.lookup.LookupExampleRow(pickle.SourceIds[1])
				example := self.lookup.LookupExample(pickle.SourceIds[1])
				scenarioID = fmt.Sprintf(
					"%s;%s;%s;%d",
					jsonFeature.ID,
					makeId(scenario.Name),
					makeId(example.Name),
					self.exampleRowIndexById[exampleRow.Id])
			}

			scenarioTags := make([]*jsonTag, len(pickle.Tags))
			for tagIndex, pickleTag := range pickle.Tags {
				tag := self.lookup.LookupTagByURIAndName(pickle.Uri, pickleTag.Name)

				scenarioTags[tagIndex] = &jsonTag{
					Line: tag.Location.Line,
					Name: tag.Name,
				}
			}

			jsonFeature.Elements = append(jsonFeature.Elements, &jsonFeatureElement{
				Description: scenario.Description,
				ID:          scenarioID,
				Keyword:     scenario.Keyword,
				Line:        scenario.Location.Line,
				Name:        scenario.Name,
				Steps:       scenarioJsonSteps,
				Type:        "scenario",
				Tags:        scenarioTags,
			})

		case *messages.Envelope_TestStepFinished:
			testStep := self.lookup.LookupTestStepByID(m.TestStepFinished.TestStepId)
			pickleStep := self.lookup.LookupPickleStepByID(testStep.PickleStepId)
			jsonStep := self.jsonStepsByPickleStepId[pickleStep.Id]

			status := strings.ToLower(m.TestStepFinished.TestResult.Status.String())
			jsonStep.Result = &jsonStepResult{
				Duration:     durationToNanos(m.TestStepFinished.TestResult.Duration),
				Status:       status,
				ErrorMessage: m.TestStepFinished.TestResult.Message,
			}

			stepDefinitions := self.lookup.LookupStepDefinitionConfigsByIDs(testStep.StepDefinitionId)
			if len(stepDefinitions) > 0 {
				jsonStep.Match = &jsonStepMatch{
					Location: fmt.Sprintf(
						"%s:%d",
						stepDefinitions[0].Location.Uri,
						stepDefinitions[0].Location.Location.Line,
					),
				}
			}
		}
	}

	output, _ := json.MarshalIndent(self.jsonFeatures, "", "  ")
	_, err = fmt.Fprintln(stdout, string(output))
	return err
}

func (self *Formatter) findOrCreateJsonFeature(pickle *messages.Pickle) *jsonFeature {
	jFeature, ok := self.jsonFeaturesByURI[pickle.Uri]
	if !ok {
		gherkinDocumentFeature := self.lookup.LookupGherkinDocument(pickle.Uri).Feature

		jFeature = &jsonFeature{
			Description: gherkinDocumentFeature.Description,
			Elements:    make([]*jsonFeatureElement, 0),
			ID:          makeId(gherkinDocumentFeature.Name),
			Keyword:     gherkinDocumentFeature.Keyword,
			Line:        gherkinDocumentFeature.Location.Line,
			Name:        gherkinDocumentFeature.Name,
			URI:         pickle.Uri,
			Tags:        make([]*jsonTag, len(gherkinDocumentFeature.Tags)),
		}

		for tagIndex, tag := range gherkinDocumentFeature.Tags {
			jFeature.Tags[tagIndex] = &jsonTag{
				Line: tag.Location.Line,
				Name: tag.Name,
			}
		}

		self.jsonFeaturesByURI[pickle.Uri] = jFeature
		self.jsonFeatures = append(self.jsonFeatures, jFeature)
	}
	return jFeature
}

func key(uri string) string {
	return fmt.Sprintf("%s", uri)
}

func makeId(s string) string {
	return strings.ToLower(strings.Replace(s, " ", "-", -1))
}

func durationToNanos(d *messages.Duration) uint64 {
	return uint64(d.Seconds*1000000000 + int64(d.Nanos))
}
<commit_msg>Use correct line when using examples<commit_after>package json

import (
	"encoding/json"
	//"errors"
	"fmt"
	"io"
	"strings"

	messages "github.com/cucumber/cucumber-messages-go/v6"
	gio "github.com/gogo/protobuf/io"
)

type jsonFeature struct {
	Description string                `json:"description"`
	Elements    []*jsonFeatureElement `json:"elements"`
	ID          string                `json:"id"`
	Keyword     string                `json:"keyword"`
	Line        uint32                `json:"line"`
	Name        string                `json:"name"`
	URI         string                `json:"uri"`
	Tags        []*jsonTag            `json:"tags,omitempty"`
}

type jsonFeatureElement struct {
	Description string      `json:"description"`
	ID          string      `json:"id,omitempty"`
	Keyword     string      `json:"keyword"`
	Line        uint32      `json:"line"`
	Name        string      `json:"name"`
	Steps       []*jsonStep `json:"steps"`
	Type        string      `json:"type"`
	Tags        []*jsonTag  `json:"tags,omitempty"`
}

type jsonStep struct {
	Keyword   string              `json:"keyword"`
	Line      uint32              `json:"line"`
	Name      string              `json:"name"`
	Result    *jsonStepResult     `json:"result"`
	Match     *jsonStepMatch      `json:"match,omitempty"`
	DocString *jsonDocString      `json:"doc_string,omitempty"`
	Rows      []*jsonDatatableRow `json:"rows,omitempty"`
}

type jsonDocString struct {
	ContentType string `json:"content_type"`
	Line        uint32 `json:"line"`
	Value       string `json:"value"`
}

type jsonDatatableRow struct {
	Cells []string `json:"cells"`
}

type jsonStepResult struct {
	Duration     uint64 `json:"duration,omitempty"`
	Status       string `json:"status"`
	ErrorMessage string `json:"error_message,omitempty"`
}

type jsonStepMatch struct {
	Location string `json:"location"`
}

type jsonTag struct {
	Line uint32 `json:"line"`
	Name string `json:"name"`
}

type Formatter struct {
	lookup *MessageLookup

	jsonFeatures            []*jsonFeature
	jsonFeaturesByURI       map[string]*jsonFeature
	jsonStepsByPickleStepId map[string]*jsonStep
	exampleRowIndexById     map[string]int
}

// ProcessMessages writes a JSON report to STDOUT
func (self *Formatter) ProcessMessages(stdin io.Reader, stdout io.Writer) (err error) {
	self.lookup = &MessageLookup{}
	self.lookup.Initialize()

	self.jsonFeatures = make([]*jsonFeature, 0)
	self.jsonFeaturesByURI = make(map[string]*jsonFeature)
	self.jsonStepsByPickleStepId = make(map[string]*jsonStep)
	self.exampleRowIndexById = make(map[string]int)

	reader := gio.NewDelimitedReader(stdin, 4096)

	for {
		envelope := &messages.Envelope{}
		err := reader.ReadMsg(envelope)
		if err == io.EOF {
			break
		}
		if err != nil {
			return err
		}

		self.lookup.ProcessMessage(envelope)

		switch m := envelope.Message.(type) {
		case *messages.Envelope_GherkinDocument:
			for _, child := range m.GherkinDocument.Feature.Children {
				scenario := child.GetScenario()
				if scenario != nil {
					for _, example := range scenario.Examples {
						for index, row := range example.TableBody {
							// index + 2: it's a 1 based index and the header is counted too.
							self.exampleRowIndexById[row.Id] = index + 2
						}
					}
				}
			}

		case *messages.Envelope_Pickle:
			pickle := m.Pickle
			jsonFeature := self.findOrCreateJsonFeature(pickle)
			scenario := self.lookup.LookupScenario(pickle.SourceIds[0])
			elementLine := scenario.Location.Line

			// TODO: find a better way to get backgrounds
			background := &messages.GherkinDocument_Feature_Background{}
			scenarioJsonSteps := make([]*jsonStep, 0)
			backgroundJsonSteps := make([]*jsonStep, 0)

			for _, pickleStep := range pickle.Steps {
				step := self.lookup.LookupStep(pickleStep.StepId)
				jsonStep := &jsonStep{
					Keyword: step.Keyword,
					Line:    step.Location.Line,
					Name:    pickleStep.Text,
					// The match field defaults to the Gherkin step itself for some curious reason
					Match: &jsonStepMatch{
						Location: fmt.Sprintf("%s", pickle.Uri),
					},
				}

				docString := step.GetDocString()
				if docString != nil {
					jsonStep.DocString = &jsonDocString{
						Line:        docString.Location.Line,
						ContentType: docString.ContentType,
						Value:       docString.Content,
					}
				}

				datatable := step.GetDataTable()
				if datatable != nil {
					jsonStep.Rows = make([]*jsonDatatableRow, len(datatable.GetRows()))
					for rowIndex, row := range datatable.GetRows() {
						cells := make([]string, len(row.Cells))
						for cellIndex, cell := range row.Cells {
							cells[cellIndex] = cell.Value
						}

						jsonStep.Rows[rowIndex] = &jsonDatatableRow{
							Cells: cells,
						}
					}
				}
				if self.lookup.IsBackgroundStep(step.Id) {
					backgroundJsonSteps = append(backgroundJsonSteps, jsonStep)
					background = self.lookup.LookupBrackgroundByStepId(step.Id)
				} else {
					scenarioJsonSteps = append(scenarioJsonSteps, jsonStep)
				}

				self.jsonStepsByPickleStepId[pickleStep.Id] = jsonStep
			}

			if len(backgroundJsonSteps) > 0 {
				jsonFeature.Elements = append(jsonFeature.Elements, &jsonFeatureElement{
					Description: background.Description,
					Keyword:     background.Keyword,
					Line:        background.Location.Line,
					Steps:       backgroundJsonSteps,
					Type:        "background",
				})
			}

			scenarioID := fmt.Sprintf("%s;%s", jsonFeature.ID, makeId(scenario.Name))

			if len(pickle.SourceIds) > 1 {
				exampleRow := self.lookup.LookupExampleRow(pickle.SourceIds[1])
				example := self.lookup.LookupExample(pickle.SourceIds[1])
				scenarioID = fmt.Sprintf(
					"%s;%s;%s;%d",
					jsonFeature.ID,
					makeId(scenario.Name),
					makeId(example.Name),
					self.exampleRowIndexById[exampleRow.Id])

				elementLine = exampleRow.Location.Line
			}

			scenarioTags := make([]*jsonTag, len(pickle.Tags))
			for tagIndex, pickleTag := range pickle.Tags {
				tag := self.lookup.LookupTagByURIAndName(pickle.Uri, pickleTag.Name)

				scenarioTags[tagIndex] = &jsonTag{
					Line: tag.Location.Line,
					Name: tag.Name,
				}
			}

			jsonFeature.Elements = append(jsonFeature.Elements, &jsonFeatureElement{
				Description: scenario.Description,
				ID:          scenarioID,
				Keyword:     scenario.Keyword,
				Line:        elementLine,
				Name:        scenario.Name,
				Steps:       scenarioJsonSteps,
				Type:        "scenario",
				Tags:        scenarioTags,
			})

		case *messages.Envelope_TestStepFinished:
			testStep := self.lookup.LookupTestStepByID(m.TestStepFinished.TestStepId)
			pickleStep := self.lookup.LookupPickleStepByID(testStep.PickleStepId)
			jsonStep := self.jsonStepsByPickleStepId[pickleStep.Id]

			status := strings.ToLower(m.TestStepFinished.TestResult.Status.String())
			jsonStep.Result = &jsonStepResult{
				Duration:     durationToNanos(m.TestStepFinished.TestResult.Duration),
				Status:       status,
				ErrorMessage: m.TestStepFinished.TestResult.Message,
			}

			stepDefinitions := self.lookup.LookupStepDefinitionConfigsByIDs(testStep.StepDefinitionId)
			if len(stepDefinitions) > 0 {
				jsonStep.Match = &jsonStepMatch{
					Location: fmt.Sprintf(
						"%s:%d",
						stepDefinitions[0].Location.Uri,
						stepDefinitions[0].Location.Location.Line,
					),
				}
			}
		}
	}

	output, _ := json.MarshalIndent(self.jsonFeatures, "", "  ")
	_, err = fmt.Fprintln(stdout, string(output))
	return err
}

func (self *Formatter) findOrCreateJsonFeature(pickle *messages.Pickle) *jsonFeature {
	jFeature, ok := self.jsonFeaturesByURI[pickle.Uri]
	if !ok {
		gherkinDocumentFeature := self.lookup.LookupGherkinDocument(pickle.Uri).Feature

		jFeature = &jsonFeature{
			Description: gherkinDocumentFeature.Description,
			Elements:    make([]*jsonFeatureElement, 0),
			ID:          makeId(gherkinDocumentFeature.Name),
			Keyword:     gherkinDocumentFeature.Keyword,
			Line:        gherkinDocumentFeature.Location.Line,
			Name:        gherkinDocumentFeature.Name,
			URI:         pickle.Uri,
			Tags:        make([]*jsonTag, len(gherkinDocumentFeature.Tags)),
		}

		for tagIndex, tag := range gherkinDocumentFeature.Tags {
			jFeature.Tags[tagIndex] = &jsonTag{
				Line: tag.Location.Line,
				Name: tag.Name,
			}
		}

		self.jsonFeaturesByURI[pickle.Uri] = jFeature
		self.jsonFeatures = append(self.jsonFeatures, jFeature)
	}
	return jFeature
}

func key(uri string) string {
	return fmt.Sprintf("%s", uri)
}

func makeId(s string) string {
	return strings.ToLower(strings.Replace(s, " ", "-", -1))
}

func durationToNanos(d *messages.Duration) uint64 {
	return uint64(d.Seconds*1000000000 + int64(d.Nanos))
}
<|endoftext|>


<commit_before>package lumberjack

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/tls"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"errors"
	"io"
	"math/big"
	"net"
	"os"
	"sync"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"

	"github.com/elastic/libbeat/common"
	"github.com/elastic/libbeat/common/streambuf"
	"github.com/elastic/libbeat/outputs"
)

func newTestLumberjackOutput(
	t *testing.T,
	config outputs.MothershipConfig,
) outputs.Outputer {
	plugin := outputs.FindOutputPlugin("lumberjack")
	if plugin == nil {
		t.Fatalf("No lumberjack output plugin found")
	}

	output, err := plugin.NewOutput("test", &config, 0)
	if err != nil {
		t.Fatalf("init lumberjack output plugin failed: %v", err)
	}

	return output
}

func sockReadMessage(buf *streambuf.Buffer, in io.Reader) (*message, error) {
	for {
		// try parse message from buffered data
		msg, err := readMessage(buf)
		if msg != nil || (err != nil && err != streambuf.ErrNoMoreBytes) {
			return msg, err
		}

		// read next bytes from socket if incomplete message in buffer
		buffer := make([]byte, 1024)
		n, err := in.Read(buffer)
		if err != nil {
			return nil, err
		}

		buf.Write(buffer[:n])
	}
}

func sockSendACK(out io.Writer, seq uint32) error {
	buf := streambuf.New(nil)
	buf.WriteByte('1')
	buf.WriteByte('A')
	buf.WriteNetUint32(seq)
	_, err := out.Write(buf.Bytes())
	return err
}

// genCertsIfMIssing generates a testing certificate for ip 127.0.0.1 for
// testing if certificate or key is missing. Generated is used for CA,
// client-auth and server-auth. Use only for testing.
func genCertsIfMIssing(
	t *testing.T,
	capem string,
	cakey string,
) error {
	_, err := os.Stat(capem)
	if err == nil {
		_, err = os.Stat(cakey)
		if err == nil {
			return nil
		}
	}

	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
	if err != nil {
		t.Fatalf("failed to generate serial number: %s", err)
	}

	caTemplate := x509.Certificate{
		SerialNumber: serialNumber,
		Subject: pkix.Name{
			Country:            []string{"US"},
			Organization:       []string{"elastic"},
			OrganizationalUnit: []string{"beats"},
		},
		Issuer: pkix.Name{
			Country:            []string{"US"},
			Organization:       []string{"elastic"},
			OrganizationalUnit: []string{"beats"},
			Locality:           []string{"locality"},
			Province:           []string{"province"},
			StreetAddress:      []string{"Mainstreet"},
			PostalCode:         []string{"12345"},
			SerialNumber:       "23",
			CommonName:         "*",
		},
		IPAddresses: []net.IP{
			net.IP{127, 0, 0, 1},
		},

		SignatureAlgorithm:    x509.SHA512WithRSA,
		PublicKeyAlgorithm:    x509.ECDSA,
		NotBefore:             time.Now(),
		NotAfter:              time.Now().AddDate(10, 0, 0),
		SubjectKeyId:          []byte("12345"),
		BasicConstraintsValid: true,
		IsCA: true,
		ExtKeyUsage: []x509.ExtKeyUsage{
			x509.ExtKeyUsageClientAuth,
			x509.ExtKeyUsageServerAuth},
		KeyUsage: x509.KeyUsageKeyEncipherment |
			x509.KeyUsageDigitalSignature |
			x509.KeyUsageCertSign,
	}

	// generate keys
	priv, err := rsa.GenerateKey(rand.Reader, 4096)
	if err != nil {
		t.Fatalf("failed to generate ca private key: %v", err)
	}
	pub := &priv.PublicKey

	// generate certificate
	caBytes, err := x509.CreateCertificate(
		rand.Reader,
		&caTemplate,
		&caTemplate,
		pub, priv)
	if err != nil {
		t.Fatalf("failed to generate ca certificate: %v", err)
	}

	// write key file
	keyOut, err := os.OpenFile(cakey, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		t.Fatalf("failed to open key file for writing: %v", err)
	}
	pem.Encode(keyOut, &pem.Block{
		Type:  "RSA PRIVATE KEY",
		Bytes: x509.MarshalPKCS1PrivateKey(priv)})
	keyOut.Close()

	// write certificate
	certOut, err := os.Create(capem)
	if err != nil {
		t.Fatalf("failed to open cert.pem for writing: %s", err)
	}
	pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: caBytes})
	certOut.Close()

	return nil
}

func TestLumberjackTCP(t *testing.T) {
	var serverErr error
	var win, data *message

	// create server with randomized port
	listener, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		t.Fatalf("Failed to create test server")
	}

	// start server
	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		defer wg.Done()

		// server read timeout
		timeout := 5 * time.Second
		buf := streambuf.New(nil)

		client, err := listener.Accept()
		if err != nil {
			t.Logf("failed on accept: %v", err)
			serverErr = err
			return
		}

		if err := client.SetDeadline(time.Now().Add(timeout)); err != nil {
			serverErr = err
			return
		}
		win, err = sockReadMessage(buf, client)
		if err != nil {
			t.Logf("failed on read window size: %v", err)
			serverErr = err
			return
		}

		if err := client.SetDeadline(time.Now().Add(timeout)); err != nil {
			serverErr = err
			return
		}
		data, err = sockReadMessage(buf, client)
		if err != nil {
			t.Logf("failed on read data frame: %v", err)
			serverErr = err
			return
		}

		if err := client.SetDeadline(time.Now().Add(timeout)); err != nil {
			serverErr = err
			return
		}
		err = sockSendACK(client, 1)
		if err != nil {
			t.Logf("failed on read data frame: %v", err)
			serverErr = err
		}
	}()

	// create lumberjack output client
	config := outputs.MothershipConfig{
		TLS:     nil,
		Timeout: 2,
		Hosts:   []string{listener.Addr().String()},
	}
	output := newTestLumberjackOutput(t, config)

	// send event to server
	event := common.MapStr{"name": "me", "line": 10}
	output.PublishEvent(nil, time.Now(), event)

	wg.Wait()
	listener.Close()

	// validate output
	assert.Nil(t, serverErr)
	assert.NotNil(t, win)
	if data == nil {
		t.Fatalf("No data received")
	}
	assert.Equal(t, 1, len(data.events))
	data = data.events[0]
	assert.Equal(t, "me", data.doc["name"])
	assert.Equal(t, 10.0, data.doc["line"])
}

func TestLumberjackTLS(t *testing.T) {
	pem := "ca_test.pem"
	key := "ca_test.key"

	var serverErr error
	var win, data *message

	genCertsIfMIssing(t, pem, key)

	tcpListener, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		t.Fatalf("failed to generate TCP listener")
	}

	// create lumberjack output client
	config := outputs.MothershipConfig{
		TLS: &outputs.TLSConfig{
			Certificate:    pem,
			CertificateKey: key,
			CAs:            []string{pem},
		},
		Timeout: 5,
		Hosts:   []string{tcpListener.Addr().String()},
	}

	tlsConfig, err := outputs.LoadTLSConfig(config.TLS)
	if err != nil {
		tcpListener.Close()
		t.Fatalf("failed to load certificates")
	}

	listener := tls.NewListener(tcpListener, tlsConfig)

	// start server
	var wg sync.WaitGroup
	var wgReady sync.WaitGroup
	wg.Add(1)
	wgReady.Add(1)
	go func() {
		defer wg.Done()

		for i := 0; i < 3; i++ { // try up to 3 failed connection attempts
			buf := streambuf.New(nil)
			wgReady.Done()
			client, err := listener.Accept()
			if err != nil {
				continue
			}

			tlsConn, ok := client.(*tls.Conn)
			if !ok {
				serverErr = errors.New("no tls connection")
				return
			}

			err = tlsConn.Handshake()
			if err != nil {
				serverErr = err
				return
			}

			win, err = sockReadMessage(buf, client)
			if err != nil {
				serverErr = err
				return
			}

			data, err = sockReadMessage(buf, client)
			if err != nil {
				serverErr = err
				return
			}
			serverErr = sockSendACK(client, 1)

			return
		}
	}()

	// send event to server
	go func() {
		wgReady.Wait()
		output := newTestLumberjackOutput(t, config)

		event := common.MapStr{"name": "me", "line": 10}
		output.PublishEvent(nil, time.Now(), event)
	}()

	wg.Wait()
	listener.Close()

	// validate output
	assert.Nil(t, serverErr)
	assert.NotNil(t, win)
	assert.NotNil(t, data)
	if data != nil {
		assert.Equal(t, 1, len(data.events))
		data = data.events[0]
		assert.Equal(t, "me", data.doc["name"])
		assert.Equal(t, 10.0, data.doc["line"])
	}
}
<commit_msg>stabilize lumberjack TLS unit test<commit_after>package lumberjack

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/tls"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"errors"
	"io"
	"math/big"
	"net"
	"os"
	"sync"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"

	"github.com/elastic/libbeat/common"
	"github.com/elastic/libbeat/common/streambuf"
	"github.com/elastic/libbeat/outputs"
)

func newTestLumberjackOutput(
	t *testing.T,
	config outputs.MothershipConfig,
) outputs.Outputer {
	plugin := outputs.FindOutputPlugin("lumberjack")
	if plugin == nil {
		t.Fatalf("No lumberjack output plugin found")
	}

	output, err := plugin.NewOutput("test", &config, 0)
	if err != nil {
		t.Fatalf("init lumberjack output plugin failed: %v", err)
	}

	return output
}

func sockReadMessage(buf *streambuf.Buffer, in io.Reader) (*message, error) {
	for {
		// try parse message from buffered data
		msg, err := readMessage(buf)
		if msg != nil || (err != nil && err != streambuf.ErrNoMoreBytes) {
			return msg, err
		}

		// read next bytes from socket if incomplete message in buffer
		buffer := make([]byte, 1024)
		n, err := in.Read(buffer)
		if err != nil {
			return nil, err
		}

		buf.Write(buffer[:n])
	}
}

func sockSendACK(out io.Writer, seq uint32) error {
	buf := streambuf.New(nil)
	buf.WriteByte('1')
	buf.WriteByte('A')
	buf.WriteNetUint32(seq)
	_, err := out.Write(buf.Bytes())
	return err
}

// genCertsIfMIssing generates a testing certificate for ip 127.0.0.1 for
// testing if certificate or key is missing. Generated is used for CA,
// client-auth and server-auth. Use only for testing.
func genCertsIfMIssing(
	t *testing.T,
	capem string,
	cakey string,
) error {
	_, err := os.Stat(capem)
	if err == nil {
		_, err = os.Stat(cakey)
		if err == nil {
			return nil
		}
	}

	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
	if err != nil {
		t.Fatalf("failed to generate serial number: %s", err)
	}

	caTemplate := x509.Certificate{
		SerialNumber: serialNumber,
		Subject: pkix.Name{
			Country:            []string{"US"},
			Organization:       []string{"elastic"},
			OrganizationalUnit: []string{"beats"},
		},
		Issuer: pkix.Name{
			Country:            []string{"US"},
			Organization:       []string{"elastic"},
			OrganizationalUnit: []string{"beats"},
			Locality:           []string{"locality"},
			Province:           []string{"province"},
			StreetAddress:      []string{"Mainstreet"},
			PostalCode:         []string{"12345"},
			SerialNumber:       "23",
			CommonName:         "*",
		},
		IPAddresses: []net.IP{
			net.IP{127, 0, 0, 1},
		},

		SignatureAlgorithm:    x509.SHA512WithRSA,
		PublicKeyAlgorithm:    x509.ECDSA,
		NotBefore:             time.Now(),
		NotAfter:              time.Now().AddDate(10, 0, 0),
		SubjectKeyId:          []byte("12345"),
		BasicConstraintsValid: true,
		IsCA: true,
		ExtKeyUsage: []x509.ExtKeyUsage{
			x509.ExtKeyUsageClientAuth,
			x509.ExtKeyUsageServerAuth},
		KeyUsage: x509.KeyUsageKeyEncipherment |
			x509.KeyUsageDigitalSignature |
			x509.KeyUsageCertSign,
	}

	// generate keys
	priv, err := rsa.GenerateKey(rand.Reader, 4096)
	if err != nil {
		t.Fatalf("failed to generate ca private key: %v", err)
	}
	pub := &priv.PublicKey

	// generate certificate
	caBytes, err := x509.CreateCertificate(
		rand.Reader,
		&caTemplate,
		&caTemplate,
		pub, priv)
	if err != nil {
		t.Fatalf("failed to generate ca certificate: %v", err)
	}

	// write key file
	keyOut, err := os.OpenFile(cakey, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		t.Fatalf("failed to open key file for writing: %v", err)
	}
	pem.Encode(keyOut, &pem.Block{
		Type:  "RSA PRIVATE KEY",
		Bytes: x509.MarshalPKCS1PrivateKey(priv)})
	keyOut.Close()

	// write certificate
	certOut, err := os.Create(capem)
	if err != nil {
		t.Fatalf("failed to open cert.pem for writing: %s", err)
	}
	pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: caBytes})
	certOut.Close()

	return nil
}

func TestLumberjackTCP(t *testing.T) {
	var serverErr error
	var win, data *message

	// create server with randomized port
	listener, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		t.Fatalf("Failed to create test server")
	}

	// start server
	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		defer wg.Done()

		// server read timeout
		timeout := 5 * time.Second
		buf := streambuf.New(nil)

		client, err := listener.Accept()
		if err != nil {
			t.Logf("failed on accept: %v", err)
			serverErr = err
			return
		}

		if err := client.SetDeadline(time.Now().Add(timeout)); err != nil {
			serverErr = err
			return
		}
		win, err = sockReadMessage(buf, client)
		if err != nil {
			t.Logf("failed on read window size: %v", err)
			serverErr = err
			return
		}

		if err := client.SetDeadline(time.Now().Add(timeout)); err != nil {
			serverErr = err
			return
		}
		data, err = sockReadMessage(buf, client)
		if err != nil {
			t.Logf("failed on read data frame: %v", err)
			serverErr = err
			return
		}

		if err := client.SetDeadline(time.Now().Add(timeout)); err != nil {
			serverErr = err
			return
		}
		err = sockSendACK(client, 1)
		if err != nil {
			t.Logf("failed on read data frame: %v", err)
			serverErr = err
		}
	}()

	// create lumberjack output client
	config := outputs.MothershipConfig{
		TLS:     nil,
		Timeout: 2,
		Hosts:   []string{listener.Addr().String()},
	}
	output := newTestLumberjackOutput(t, config)

	// send event to server
	event := common.MapStr{"name": "me", "line": 10}
	output.PublishEvent(nil, time.Now(), event)

	wg.Wait()
	listener.Close()

	// validate output
	assert.Nil(t, serverErr)
	assert.NotNil(t, win)
	if data == nil {
		t.Fatalf("No data received")
	}
	assert.Equal(t, 1, len(data.events))
	data = data.events[0]
	assert.Equal(t, "me", data.doc["name"])
	assert.Equal(t, 10.0, data.doc["line"])
}

func TestLumberjackTLS(t *testing.T) {
	pem := "ca_test.pem"
	key := "ca_test.key"

	var serverErr error
	var win, data *message

	genCertsIfMIssing(t, pem, key)

	tcpListener, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		t.Fatalf("failed to generate TCP listener")
	}

	// create lumberjack output client
	config := outputs.MothershipConfig{
		TLS: &outputs.TLSConfig{
			Certificate:    pem,
			CertificateKey: key,
			CAs:            []string{pem},
		},
		Timeout: 5,
		Hosts:   []string{tcpListener.Addr().String()},
	}

	tlsConfig, err := outputs.LoadTLSConfig(config.TLS)
	if err != nil {
		tcpListener.Close()
		t.Fatalf("failed to load certificates")
	}

	listener := tls.NewListener(tcpListener, tlsConfig)

	// start server
	var wg sync.WaitGroup
	var wgReady sync.WaitGroup
	wg.Add(1)
	wgReady.Add(1)
	go func() {
		defer wg.Done()

		for i := 0; i < 3; i++ { // try up to 3 failed connection attempts
			// server read timeout
			timeout := 5 * time.Second
			buf := streambuf.New(nil)
			wgReady.Done()
			client, err := listener.Accept()
			if err != nil {
				continue
			}

			tlsConn, ok := client.(*tls.Conn)
			if !ok {
				serverErr = errors.New("no tls connection")
				return
			}

			if err := client.SetDeadline(time.Now().Add(timeout)); err != nil {
				serverErr = err
				return
			}

			err = tlsConn.Handshake()
			if err != nil {
				serverErr = err
				return
			}

			if err := client.SetDeadline(time.Now().Add(timeout)); err != nil {
				serverErr = err
				return
			}
			win, err = sockReadMessage(buf, client)
			if err != nil {
				serverErr = err
				return
			}

			if err := client.SetDeadline(time.Now().Add(timeout)); err != nil {
				serverErr = err
				return
			}
			data, err = sockReadMessage(buf, client)
			if err != nil {
				serverErr = err
				return
			}
			serverErr = sockSendACK(client, 1)

			return
		}
	}()

	// send event to server
	go func() {
		wgReady.Wait()
		output := newTestLumberjackOutput(t, config)

		event := common.MapStr{"name": "me", "line": 10}
		output.PublishEvent(nil, time.Now(), event)
	}()

	wg.Wait()
	listener.Close()

	// validate output
	assert.Nil(t, serverErr)
	assert.NotNil(t, win)
	assert.NotNil(t, data)
	if data != nil {
		assert.Equal(t, 1, len(data.events))
		data = data.events[0]
		assert.Equal(t, "me", data.doc["name"])
		assert.Equal(t, 10.0, data.doc["line"])
	}
}
<|endoftext|>


<commit_before>package peerstore

import (
	"fmt"
	"math"
	"math/rand"
	"testing"
	"time"

	"github.com/libp2p/go-libp2p-core/test"
)

func TestLatencyEWMAFun(t *testing.T) {
	t.Skip("run it for fun")

	m := NewMetrics()
	id, err := test.RandPeerID()
	if err != nil {
		t.Fatal(err)
	}

	mu := 100.0
	sig := 10.0
	next := func() time.Duration {
		mu = (rand.NormFloat64() * sig) + mu
		return time.Duration(mu)
	}

	print := func() {
		fmt.Printf("%3.f %3.f --> %d\n", sig, mu, m.LatencyEWMA(id))
	}

	for {
		time.Sleep(200 * time.Millisecond)
		m.RecordLatency(id, next())
		print()
	}
}

func TestLatencyEWMA(t *testing.T) {
	m := NewMetrics()
	id, err := test.RandPeerID()
	if err != nil {
		t.Fatal(err)
	}

	exp := 100.0
	mu := exp
	sig := 10.0
	next := func() time.Duration {
		mu := (rand.NormFloat64() * sig) + mu
		return time.Duration(mu)
	}

	for i := 0; i < 10; i++ {
		time.Sleep(200 * time.Millisecond)
		m.RecordLatency(id, next())
	}

	lat := m.LatencyEWMA(id)
	if math.Abs(exp-float64(lat)) > sig {
		t.Fatal("latency outside of expected range: ", exp, lat, sig)
	}
}
<commit_msg>fix flaky EWMA test (#205)<commit_after>package peerstore

import (
	"fmt"
	"math/rand"
	"testing"
	"time"

	"github.com/libp2p/go-libp2p-core/test"
)

func TestLatencyEWMAFun(t *testing.T) {
	t.Skip("run it for fun")

	m := NewMetrics()
	id, err := test.RandPeerID()
	if err != nil {
		t.Fatal(err)
	}

	mu := 100.0
	sig := 10.0
	next := func() time.Duration {
		mu = (rand.NormFloat64() * sig) + mu
		return time.Duration(mu)
	}

	print := func() {
		fmt.Printf("%3.f %3.f --> %d\n", sig, mu, m.LatencyEWMA(id))
	}

	for {
		time.Sleep(200 * time.Millisecond)
		m.RecordLatency(id, next())
		print()
	}
}

func TestLatencyEWMA(t *testing.T) {
	m := NewMetrics()
	id, err := test.RandPeerID()
	if err != nil {
		t.Fatal(err)
	}

	const exp = 100
	const mu = exp
	const sig = 10
	next := func() time.Duration { return time.Duration(rand.Intn(20) - 10 + mu) }

	for i := 0; i < 10; i++ {
		m.RecordLatency(id, next())
	}

	lat := m.LatencyEWMA(id)
	diff := exp - lat
	if diff < 0 {
		diff = -diff
	}
	if diff > sig {
		t.Fatalf("latency outside of expected range. expected %d ± %d, got %d", exp, sig, lat)
	}
}
<|endoftext|>


<commit_before>package labeler

import (
	"fmt"
	"log"
	"time"

	"github.com/google/go-github/github"
	"github.com/parkr/auto-reply/common"
	"github.com/parkr/auto-reply/ctx"
)

const repoMergeabilityCheckWaitSec = 2

var PendingRebaseNeedsWorkPRUnlabeler = func(context *ctx.Context, payload interface{}) error {
	event, ok := payload.(*github.PullRequestEvent)
	if !ok {
		return context.NewError("PendingRebaseUnlabeler: not a pull request event")
	}

	if *event.Action != "synchronize" {
		return nil
	}

	owner, repo, num := *event.Repo.Owner.Login, *event.Repo.Name, *event.Number

	// Allow the job to run which determines mergeability.
	log.Printf("checking the mergeability of %s/%s#%d in %d sec...", owner, repo, num, repoMergeabilityCheckWaitSec)
	time.Sleep(repoMergeabilityCheckWaitSec * time.Second)

	var err error
	if isMergeable(context, owner, repo, num) {
		err = RemoveLabelIfExists(context, owner, repo, num, "pending-rebase")
		if err != nil {
			log.Printf("error removing the pending-rebase label: %v", err)
		}
		err = RemoveLabelIfExists(context, owner, repo, num, "needs-work")
	} else {
		err = fmt.Errorf("%s/%s#%d is not mergeable", owner, repo, num)
	}

	if err != nil {
		log.Printf("error removing the pending-rebase & needs-work labels: %v", err)
	}
	return err
}

func isMergeable(context *ctx.Context, owner, repo string, number int) bool {
	pr, res, err := context.GitHub.PullRequests.Get(context.Context(), owner, repo, number)
	err = common.ErrorFromResponse(res, err)
	if err != nil {
		log.Printf("couldn't determine mergeability of %s/%s#%d: %v", owner, repo, number, err)
		return false
	}
	return *pr.Mergeable
}
<commit_msg>labeler: isMergeable needs some nil checks<commit_after>package labeler

import (
	"fmt"
	"log"
	"time"

	"github.com/google/go-github/github"
	"github.com/parkr/auto-reply/common"
	"github.com/parkr/auto-reply/ctx"
)

const repoMergeabilityCheckWaitSec = 2

var PendingRebaseNeedsWorkPRUnlabeler = func(context *ctx.Context, payload interface{}) error {
	event, ok := payload.(*github.PullRequestEvent)
	if !ok {
		return context.NewError("PendingRebaseUnlabeler: not a pull request event")
	}

	if *event.Action != "synchronize" {
		return nil
	}

	owner, repo, num := *event.Repo.Owner.Login, *event.Repo.Name, *event.Number

	// Allow the job to run which determines mergeability.
	log.Printf("checking the mergeability of %s/%s#%d in %d sec...", owner, repo, num, repoMergeabilityCheckWaitSec)
	time.Sleep(repoMergeabilityCheckWaitSec * time.Second)

	var err error
	if isMergeable(context, owner, repo, num) {
		err = RemoveLabelIfExists(context, owner, repo, num, "pending-rebase")
		if err != nil {
			log.Printf("error removing the pending-rebase label: %v", err)
		}
		err = RemoveLabelIfExists(context, owner, repo, num, "needs-work")
	} else {
		err = fmt.Errorf("%s/%s#%d is not mergeable", owner, repo, num)
	}

	if err != nil {
		log.Printf("error removing the pending-rebase & needs-work labels: %v", err)
	}
	return err
}

func isMergeable(context *ctx.Context, owner, repo string, number int) bool {
	if context == nil {
		panic("context cannot be nil!")
	}

	pr, res, err := context.GitHub.PullRequests.Get(context.Context(), owner, repo, number)
	err = common.ErrorFromResponse(res, err)
	if err != nil {
		log.Printf("couldn't determine mergeability of %s/%s#%d: %v", owner, repo, number, err)
		return false
	}

	if pr == nil {
		log.Printf("isMergeable: %s/%s#%d appears not to exist", owner, repo, number)
		return false
	}

	if pr.Mergeable == nil {
		log.Printf("isMergeable: %s/%s#%d mergability is not populated in the API response", owner, repo, number)
		return false
	}

	return *pr.Mergeable
}
<|endoftext|>