<commit_before>// Copyright 2016 The Serviced 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.

// +build unit

package web

import (
	"net/http"

	"github.com/control-center/serviced/domain"
	"github.com/control-center/serviced/domain/service"
	"github.com/control-center/serviced/utils"
	. "gopkg.in/check.v1"
)

var serviceDetailsTestData = struct {
	tenant        service.ServiceDetails
	firstService  service.ServiceDetails
	secondService service.ServiceDetails
}{
	tenant: service.ServiceDetails{
		ID:              "tenant",
		Name:            "Tenant Name",
		Description:     "Tenant Description",
		PoolID:          "pool",
		ParentServiceID: "",
		Instances:       1,
		InstanceLimits: domain.MinMax{
			Min:     0,
			Max:     2,
			Default: 1,
		},
		RAMCommitment: utils.EngNotation{
			Value: uint64(2147483648),
		},
		Startup: "firstservice -start",
	},
	firstService: service.ServiceDetails{
		ID:              "firstService",
		Name:            "First Service Name",
		Description:     "The first child service",
		PoolID:          "pool",
		ParentServiceID: "tenant",
		Instances:       1,
		InstanceLimits: domain.MinMax{
			Min:     0,
			Max:     2,
			Default: 1,
		},
		RAMCommitment: utils.EngNotation{
			Value: uint64(2147483648),
		},
		Startup: "firstservice -start",
	},
	secondService: service.ServiceDetails{
		ID:              "secondService",
		Name:            "Second Service Name",
		Description:     "The second child service",
		PoolID:          "pool",
		ParentServiceID: "tenant",
		Instances:       1,
		InstanceLimits: domain.MinMax{
			Min:     0,
			Max:     10,
			Default: 1,
		},
		RAMCommitment: utils.EngNotation{
			Value: uint64(1073741824),
		},
		Startup: "secondservice -start",
	},
}

func (s *TestWebSuite) TestRestGetChildServiceDetailsShouldReturnStatusOK(c *C) {
	request := s.buildRequest("GET", "http://www.example.com/services/tenant/services", "")
	request.PathParams["serviceId"] = "tenant"

	s.mockFacade.
		On("GetServiceDetailsByParentID", s.ctx.getDatastoreContext(), "tenant").
		Return([]service.ServiceDetails{serviceDetailsTestData.firstService}, nil)

	getChildServiceDetails(&(s.writer), &request, s.ctx)

	c.Assert(s.recorder.Code, Equals, http.StatusOK)
}

func (s *TestWebSuite) TestRestGetChildServiceDetailsShouldReturnCorrectValueForTotal(c *C) {
	request := s.buildRequest("GET", "http://www.example.com/services/tenant/services", "")
	request.PathParams["serviceId"] = "tenant"

	s.mockFacade.
		On("GetServiceDetailsByParentID", s.ctx.getDatastoreContext(), "tenant").
		Return([]service.ServiceDetails{serviceDetailsTestData.firstService, serviceDetailsTestData.secondService}, nil)

	getChildServiceDetails(&(s.writer), &request, s.ctx)

	response := serviceDetailsListResponse{}
	s.getResult(c, &response)

	c.Assert(response.Total, Equals, 2)
}

func (s *TestWebSuite) TestRestGetChildServiceDetailsShouldReturnCorrectLinkValues(c *C) {
	request := s.buildRequest("GET", "http://www.example.com/services/tenant/services", "")
	request.PathParams["serviceId"] = "tenant"

	s.mockFacade.
		On("GetServiceDetailsByParentID", s.ctx.getDatastoreContext(), "tenant").
		Return([]service.ServiceDetails{serviceDetailsTestData.firstService, serviceDetailsTestData.secondService}, nil)

	getChildServiceDetails(&(s.writer), &request, s.ctx)

	response := serviceDetailsListResponse{}
	s.getResult(c, &response)

	c.Assert(response.Links[0].HRef, Equals, "/services/tenant/services")
	c.Assert(response.Links[0].Rel, Equals, "self")
	c.Assert(response.Links[0].Method, Equals, "GET")
}

func (s *TestWebSuite) TestRestGetServiceDetailsShouldReturnStatusOK(c *C) {
	request := s.buildRequest("GET", "http://www.example.com/services/firstservice/services", "")
	request.PathParams["serviceId"] = "firstservice"

	s.mockFacade.
		On("GetServiceDetails", s.ctx.getDatastoreContext(), "firstservice").
		Return(&serviceDetailsTestData.firstService, nil)

	getServiceDetails(&(s.writer), &request, s.ctx)

	c.Assert(s.recorder.Code, Equals, http.StatusOK)
}

func (s *TestWebSuite) TestRestGetServiceDetailsShouldReturnCorrectLinkValues(c *C) {
	request := s.buildRequest("GET", "http://www.example.com/services/firstservice/services", "")
	request.PathParams["serviceId"] = "firstservice"

	s.mockFacade.
		On("GetServiceDetails", s.ctx.getDatastoreContext(), "firstservice").
		Return(&serviceDetailsTestData.firstService, nil)

	getServiceDetails(&(s.writer), &request, s.ctx)

	response := serviceDetailsResponse{}
	s.getResult(c, &response)

	c.Assert(response.Links[0].HRef, Equals, "/services/firstservice/services")
	c.Assert(response.Links[0].Rel, Equals, "self")
	c.Assert(response.Links[0].Method, Equals, "GET")
}

func (s *TestWebSuite) TestRestGetServiceDetailsShouldReturnStatusNotFoundIfNoService(c *C) {
	request := s.buildRequest("GET", "http://www.example.com/services/firstservice/services", "")
	request.PathParams["serviceId"] = "firstservice"

	s.mockFacade.
		On("GetServiceDetails", s.ctx.getDatastoreContext(), "firstservice").
		Return(nil, nil)

	getServiceDetails(&(s.writer), &request, s.ctx)

	c.Assert(s.recorder.Code, Equals, http.StatusNotFound)
}

func (s *TestWebSuite) TestRestGetAllServiceDetailsShouldReturnStatusOK(c *C) {
	request := s.buildRequest("GET", "http://www.example.com/services", "")

	s.mockFacade.
		On("GetAllServiceDetails", s.ctx.getDatastoreContext()).
		Return([]service.ServiceDetails{
			serviceDetailsTestData.firstService,
			serviceDetailsTestData.secondService,
			serviceDetailsTestData.tenant,
		}, nil)

	getAllServiceDetails(&(s.writer), &request, s.ctx)

	c.Assert(s.recorder.Code, Equals, http.StatusOK)
}

func (s *TestWebSuite) TestRestGetAllServiceDetailsShouldReturnCorrectValueForTotal(c *C) {
	request := s.buildRequest("GET", "http://www.example.com/services", "")

	s.mockFacade.
		On("GetAllServiceDetails", s.ctx.getDatastoreContext()).
		Return([]service.ServiceDetails{
			serviceDetailsTestData.firstService,
			serviceDetailsTestData.secondService,
			serviceDetailsTestData.tenant,
		}, nil)

	getAllServiceDetails(&(s.writer), &request, s.ctx)

	response := serviceDetailsListResponse{}
	s.getResult(c, &response)

	c.Assert(response.Total, Equals, 3)
}

func (s *TestWebSuite) TestRestGetAllServiceDetailsShouldReturnCorrectLinkValues(c *C) {
	request := s.buildRequest("GET", "http://www.example.com/services", "")

	s.mockFacade.
		On("GetAllServiceDetails", s.ctx.getDatastoreContext()).
		Return([]service.ServiceDetails{
			serviceDetailsTestData.firstService,
			serviceDetailsTestData.secondService,
			serviceDetailsTestData.tenant,
		}, nil)

	getAllServiceDetails(&(s.writer), &request, s.ctx)

	response := serviceDetailsListResponse{}
	s.getResult(c, &response)

	c.Assert(response.Links[0].HRef, Equals, "/services")
	c.Assert(response.Links[0].Rel, Equals, "self")
	c.Assert(response.Links[0].Method, Equals, "GET")
}

func (s *TestWebSuite) TestRestGetAllServiceDetailsShouldOnlyReturnTenants(c *C) {
	request := s.buildRequest("GET", "http://www.example.com/services?tenants", "")

	s.mockFacade.
		On("GetServiceDetailsByParentID", s.ctx.getDatastoreContext(), "").
		Return([]service.ServiceDetails{
			serviceDetailsTestData.tenant,
		}, nil)

	getAllServiceDetails(&(s.writer), &request, s.ctx)

	response := serviceDetailsListResponse{}
	s.getResult(c, &response)

	c.Assert(len(response.Results), Equals, 1)
	c.Assert(response.Results[0].ID, Equals, "tenant")
}
<commit_msg>updated test to exclude RAMCommitment and Instances from the ServiceDetails object<commit_after>// Copyright 2016 The Serviced 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.

// +build unit

package web

import (
	"net/http"

	"github.com/control-center/serviced/domain"
	"github.com/control-center/serviced/domain/service"
	. "gopkg.in/check.v1"
)

var serviceDetailsTestData = struct {
	tenant        service.ServiceDetails
	firstService  service.ServiceDetails
	secondService service.ServiceDetails
}{
	tenant: service.ServiceDetails{
		ID:              "tenant",
		Name:            "Tenant Name",
		Description:     "Tenant Description",
		PoolID:          "pool",
		ParentServiceID: "",
		InstanceLimits: domain.MinMax{
			Min:     0,
			Max:     2,
			Default: 1,
		},
		Startup: "firstservice -start",
	},
	firstService: service.ServiceDetails{
		ID:              "firstService",
		Name:            "First Service Name",
		Description:     "The first child service",
		PoolID:          "pool",
		ParentServiceID: "tenant",
		InstanceLimits: domain.MinMax{
			Min:     0,
			Max:     2,
			Default: 1,
		},
		Startup: "firstservice -start",
	},
	secondService: service.ServiceDetails{
		ID:              "secondService",
		Name:            "Second Service Name",
		Description:     "The second child service",
		PoolID:          "pool",
		ParentServiceID: "tenant",
		InstanceLimits: domain.MinMax{
			Min:     0,
			Max:     10,
			Default: 1,
		},
		Startup: "secondservice -start",
	},
}

func (s *TestWebSuite) TestRestGetChildServiceDetailsShouldReturnStatusOK(c *C) {
	request := s.buildRequest("GET", "http://www.example.com/services/tenant/services", "")
	request.PathParams["serviceId"] = "tenant"

	s.mockFacade.
		On("GetServiceDetailsByParentID", s.ctx.getDatastoreContext(), "tenant").
		Return([]service.ServiceDetails{serviceDetailsTestData.firstService}, nil)

	getChildServiceDetails(&(s.writer), &request, s.ctx)

	c.Assert(s.recorder.Code, Equals, http.StatusOK)
}

func (s *TestWebSuite) TestRestGetChildServiceDetailsShouldReturnCorrectValueForTotal(c *C) {
	request := s.buildRequest("GET", "http://www.example.com/services/tenant/services", "")
	request.PathParams["serviceId"] = "tenant"

	s.mockFacade.
		On("GetServiceDetailsByParentID", s.ctx.getDatastoreContext(), "tenant").
		Return([]service.ServiceDetails{serviceDetailsTestData.firstService, serviceDetailsTestData.secondService}, nil)

	getChildServiceDetails(&(s.writer), &request, s.ctx)

	response := serviceDetailsListResponse{}
	s.getResult(c, &response)

	c.Assert(response.Total, Equals, 2)
}

func (s *TestWebSuite) TestRestGetChildServiceDetailsShouldReturnCorrectLinkValues(c *C) {
	request := s.buildRequest("GET", "http://www.example.com/services/tenant/services", "")
	request.PathParams["serviceId"] = "tenant"

	s.mockFacade.
		On("GetServiceDetailsByParentID", s.ctx.getDatastoreContext(), "tenant").
		Return([]service.ServiceDetails{serviceDetailsTestData.firstService, serviceDetailsTestData.secondService}, nil)

	getChildServiceDetails(&(s.writer), &request, s.ctx)

	response := serviceDetailsListResponse{}
	s.getResult(c, &response)

	c.Assert(response.Links[0].HRef, Equals, "/services/tenant/services")
	c.Assert(response.Links[0].Rel, Equals, "self")
	c.Assert(response.Links[0].Method, Equals, "GET")
}

func (s *TestWebSuite) TestRestGetServiceDetailsShouldReturnStatusOK(c *C) {
	request := s.buildRequest("GET", "http://www.example.com/services/firstservice/services", "")
	request.PathParams["serviceId"] = "firstservice"

	s.mockFacade.
		On("GetServiceDetails", s.ctx.getDatastoreContext(), "firstservice").
		Return(&serviceDetailsTestData.firstService, nil)

	getServiceDetails(&(s.writer), &request, s.ctx)

	c.Assert(s.recorder.Code, Equals, http.StatusOK)
}

func (s *TestWebSuite) TestRestGetServiceDetailsShouldReturnCorrectLinkValues(c *C) {
	request := s.buildRequest("GET", "http://www.example.com/services/firstservice/services", "")
	request.PathParams["serviceId"] = "firstservice"

	s.mockFacade.
		On("GetServiceDetails", s.ctx.getDatastoreContext(), "firstservice").
		Return(&serviceDetailsTestData.firstService, nil)

	getServiceDetails(&(s.writer), &request, s.ctx)

	response := serviceDetailsResponse{}
	s.getResult(c, &response)

	c.Assert(response.Links[0].HRef, Equals, "/services/firstservice/services")
	c.Assert(response.Links[0].Rel, Equals, "self")
	c.Assert(response.Links[0].Method, Equals, "GET")
}

func (s *TestWebSuite) TestRestGetServiceDetailsShouldReturnStatusNotFoundIfNoService(c *C) {
	request := s.buildRequest("GET", "http://www.example.com/services/firstservice/services", "")
	request.PathParams["serviceId"] = "firstservice"

	s.mockFacade.
		On("GetServiceDetails", s.ctx.getDatastoreContext(), "firstservice").
		Return(nil, nil)

	getServiceDetails(&(s.writer), &request, s.ctx)

	c.Assert(s.recorder.Code, Equals, http.StatusNotFound)
}

func (s *TestWebSuite) TestRestGetAllServiceDetailsShouldReturnStatusOK(c *C) {
	request := s.buildRequest("GET", "http://www.example.com/services", "")

	s.mockFacade.
		On("GetAllServiceDetails", s.ctx.getDatastoreContext()).
		Return([]service.ServiceDetails{
			serviceDetailsTestData.firstService,
			serviceDetailsTestData.secondService,
			serviceDetailsTestData.tenant,
		}, nil)

	getAllServiceDetails(&(s.writer), &request, s.ctx)

	c.Assert(s.recorder.Code, Equals, http.StatusOK)
}

func (s *TestWebSuite) TestRestGetAllServiceDetailsShouldReturnCorrectValueForTotal(c *C) {
	request := s.buildRequest("GET", "http://www.example.com/services", "")

	s.mockFacade.
		On("GetAllServiceDetails", s.ctx.getDatastoreContext()).
		Return([]service.ServiceDetails{
			serviceDetailsTestData.firstService,
			serviceDetailsTestData.secondService,
			serviceDetailsTestData.tenant,
		}, nil)

	getAllServiceDetails(&(s.writer), &request, s.ctx)

	response := serviceDetailsListResponse{}
	s.getResult(c, &response)

	c.Assert(response.Total, Equals, 3)
}

func (s *TestWebSuite) TestRestGetAllServiceDetailsShouldReturnCorrectLinkValues(c *C) {
	request := s.buildRequest("GET", "http://www.example.com/services", "")

	s.mockFacade.
		On("GetAllServiceDetails", s.ctx.getDatastoreContext()).
		Return([]service.ServiceDetails{
			serviceDetailsTestData.firstService,
			serviceDetailsTestData.secondService,
			serviceDetailsTestData.tenant,
		}, nil)

	getAllServiceDetails(&(s.writer), &request, s.ctx)

	response := serviceDetailsListResponse{}
	s.getResult(c, &response)

	c.Assert(response.Links[0].HRef, Equals, "/services")
	c.Assert(response.Links[0].Rel, Equals, "self")
	c.Assert(response.Links[0].Method, Equals, "GET")
}

func (s *TestWebSuite) TestRestGetAllServiceDetailsShouldOnlyReturnTenants(c *C) {
	request := s.buildRequest("GET", "http://www.example.com/services?tenants", "")

	s.mockFacade.
		On("GetServiceDetailsByParentID", s.ctx.getDatastoreContext(), "").
		Return([]service.ServiceDetails{
			serviceDetailsTestData.tenant,
		}, nil)

	getAllServiceDetails(&(s.writer), &request, s.ctx)

	response := serviceDetailsListResponse{}
	s.getResult(c, &response)

	c.Assert(len(response.Results), Equals, 1)
	c.Assert(response.Results[0].ID, Equals, "tenant")
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
)

func main() {
	fmt.Println("程序开始")

}
	<commit_msg>提供了1.3.26的答案<commit_after>package main

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

func main() {
	fmt.Println("程序开始")
	rand.Seed(time.Now().UnixNano())
	randKey := 4
	n := 30
	fmt.Println("n=", n)
	key := rand.Intn(randKey)
	fmt.Println("key=", key)

	first := newNode(0)
	last := first

	for i := 1; i < n; i++ {
		newND := newNode(rand.Intn(randKey))
		last.next = newND
		last = newND
	}

	temp := first
	for temp != nil {
		fmt.Printf("%v ", temp.item)
		temp = temp.next
	}
	fmt.Println()

	first = remove(first, key)

	temp = first
	for temp != nil {
		fmt.Printf("%v ", temp.item)
		temp = temp.next
	}
	fmt.Println()
}

func remove(first *node, key interface{}) *node {
	for first.item == key { //处理链表一开头就出现key的情况。
		first = first.next
	}

	move := first

	for move.next != nil { //处理链表中间出现key的情况。
		if move.next.item == key {
			move.next = move.next.next
			continue
		}
		move = move.next
	}

	return first
}

type node struct {
	item interface{}
	next *node
}

func newNode(item interface{}) *node {
	return &node{
		item: item,
	}
}
<|endoftext|>


<commit_before>// Original Work
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/

// gopl.io Exercise 7.8
// Modifications Copyright © 2017 Douglas Will
// License: https://creativecommons.org/licenses/by-sa/4.0/

// ***********  This Exersize is not finished   ********/
// at this point,

package main

import (
	"bufio"
	"fmt"
	"os"
	"sort"
	"strconv"
	"text/tabwriter"
	"time"
)

//!+main
type Track struct {
	Title  string
	Artist string
	Album  string
	Year   int
	Length time.Duration
}

var tracks = []*Track{
	{"Go", "Delilah", "From the Roots Up", 2012, length("3m38s")},
	{"Go", "Moby", "Moby", 1992, length("3m37s")},
	{"Go Ahead", "Alicia Keys", "As I Am", 2007, length("4m36s")},
	{"Ready 2 Go", "Martin Solveig", "Smash", 2020, length("4m24s")},
	{"Don't go", "Alicia Keys", "Bobby", 2006, length("8m36s")},
	{"Not Ready 2 Go", "Martin Solveig", "Smash", 2011, length("4m24s")},
}

var headings = []string{
	"Title",
	"Artist",
	"Album",
	"Year",
	"Length",
}

//length converts a string with time indicators to a duration
func length(s string) time.Duration {
	d, err := time.ParseDuration(s)
	if err != nil {
		panic(s)
	}
	return d
}

func main() {

	scanner := bufio.NewScanner(os.Stdin)

	// Enter input loop, q is the esc char
	for scanner.Text() != "q" {
		list(headings)
		printTracks(tracks)
		fmt.Print("Select a Heading:")

		//Get input from user
		scanner.Scan()

		// check for esc char q
		if scanner.Text() != "q" {
			// convert the input string to a int
			if i, err := strconv.Atoi(scanner.Text()); err == nil {
				//normalize the input to 0 base counting
				i -= 1

				//Check for valid choice and call the sort func
				if i < len(headings) && i >= 0 {

					// Sort headings
					headings = sortHeadings(headings, i)

					// sort table based on headings order
					// how to suppy the sort order??
					// Modified the customSort struct to include the sorted headings
					// Modified the Anonymous Func in customSort to iterate through
					// headings in their sort order
					sort.Sort(customSort{tracks, headings, func(x, y *Track) bool {
						// counter to iterate through the heading in sorted order
						for i := 0; i < 5; i++ {

							// for each sort layer, this Switch/Case selectis and
							// returns the correct bool answer for the layer
							switch headings[i] {
							case "Title":
								{
									if x.Title != y.Title {
										return x.Title < y.Title
									}
								}
							case "Artist":
								{
									if x.Artist != y.Artist {
										return x.Artist < y.Artist
									}
								}
							case "Album":
								{
									if x.Album != y.Album {
										return x.Album < y.Album
									}
								}
							case "Year":
								{
									if x.Year != y.Year {
										return x.Year < y.Year
									}
								}
							case "Length":
								{
									if x.Length != y.Length {
										return x.Length < y.Length
									} //if --- I needed to add comments to track the closing brackets
								} // case Length
							} // switch
						} // for
						return false
					}}) // anonymous func, customSort, sort
				} else {
					fmt.Println("Invalid Choice\n")
				}
			} //ifAtoi
		} //if scanner
	} //for scanner
} //main
//!-main

//!+sortHeading
// sortHeading takes a slice of strings and one element from that slice
// It re-orders the slice, placing the selection in the first position
func sortHeadings(headings []string, i int) []string {

	fmt.Println("Selection:", headings[i])

	// Check to see if the selection the first in the list
	if headings[i] == headings[0] {
		fmt.Println("Order is correct")
		return headings
	}

	// tmp holds the selection as the items are reordered
	tmp := headings[i]

	// Reorder slice. Iterate through the slic, moving items
	// before the selection to the right
	for index := i; index > 0; index-- {
		headings[index] = headings[index-1]
	}

	//Place the selection at the front of the slice
	headings[0] = tmp
	// return the reordered slice
	return headings
}

//!-sortHeading

//!+ list
// list prints the headings list to Stdout along with the escape char q
func list(headings []string) {
	fmt.Printf("Sort order\n")
	for index := 0; index < len(headings); index++ {
		fmt.Printf("%d. %s\n", index+1, headings[index])
	}
	fmt.Println("q to quit\n")
}

//!- list

//!+printTracks
func printTracks(tracks []*Track) {
	const format = "%v\t%v\t%v\t%v\t%v\t\n"
	tw := new(tabwriter.Writer).Init(os.Stdout, 0, 8, 2, ' ', 0)
	fmt.Fprintf(tw, format, "Title", "Artist", "Album", "Year", "Length")
	fmt.Fprintf(tw, format, "-----", "------", "-----", "----", "------")
	for _, t := range tracks {
		fmt.Fprintf(tw, format, t.Title, t.Artist, t.Album, t.Year, t.Length)
	}
	tw.Flush() // calculate column widths and print table
	fmt.Println()
}

//!-printTracks

//!+customcode
// Modified customSort struct to inlcude headings
type customSort struct {
	t        []*Track
	headings []string
	less     func(x, y *Track) bool
}

func (x customSort) Len() int           { return len(x.t) }
func (x customSort) Less(i, j int) bool { return x.less(x.t[i], x.t[j]) }
func (x customSort) Swap(i, j int)      { x.t[i], x.t[j] = x.t[j], x.t[i] }

//!-customcode
<commit_msg>Removed 'not finished' comment from ex7.8 now that it is done<commit_after>// Original Work
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/

// gopl.io Exercise 7.8
// Modifications Copyright © 2017 Douglas Will
// License: https://creativecommons.org/licenses/by-sa/4.0/

package main

import (
	"bufio"
	"fmt"
	"os"
	"sort"
	"strconv"
	"text/tabwriter"
	"time"
)

//!+main
type Track struct {
	Title  string
	Artist string
	Album  string
	Year   int
	Length time.Duration
}

var tracks = []*Track{
	{"Go", "Delilah", "From the Roots Up", 2012, length("3m38s")},
	{"Go", "Moby", "Moby", 1992, length("3m37s")},
	{"Go Ahead", "Alicia Keys", "As I Am", 2007, length("4m36s")},
	{"Ready 2 Go", "Martin Solveig", "Smash", 2020, length("4m24s")},
	{"Don't go", "Alicia Keys", "Bobby", 2006, length("8m36s")},
	{"Not Ready 2 Go", "Martin Solveig", "Smash", 2011, length("4m24s")},
}

var headings = []string{
	"Title",
	"Artist",
	"Album",
	"Year",
	"Length",
}

//length converts a string with time indicators to a duration
func length(s string) time.Duration {
	d, err := time.ParseDuration(s)
	if err != nil {
		panic(s)
	}
	return d
}

func main() {

	scanner := bufio.NewScanner(os.Stdin)

	// Enter input loop, q is the esc char
	for scanner.Text() != "q" {
		list(headings)
		printTracks(tracks)
		fmt.Print("Select a Heading:")

		//Get input from user
		scanner.Scan()

		// check for esc char q
		if scanner.Text() != "q" {
			// convert the input string to a int
			if i, err := strconv.Atoi(scanner.Text()); err == nil {
				//normalize the input to 0 base counting
				i -= 1

				//Check for valid choice and call the sort func
				if i < len(headings) && i >= 0 {

					// Sort headings
					headings = sortHeadings(headings, i)

					// sort table based on headings order
					// how to suppy the sort order??
					// Modified the customSort struct to include the sorted headings
					// Modified the Anonymous Func in customSort to iterate through
					// headings in their sort order
					sort.Sort(customSort{tracks, headings, func(x, y *Track) bool {
						// counter to iterate through the heading in sorted order
						for i := 0; i < 5; i++ {

							// for each sort layer, this Switch/Case selectis and
							// returns the correct bool answer for the layer
							switch headings[i] {
							case "Title":
								{
									if x.Title != y.Title {
										return x.Title < y.Title
									}
								}
							case "Artist":
								{
									if x.Artist != y.Artist {
										return x.Artist < y.Artist
									}
								}
							case "Album":
								{
									if x.Album != y.Album {
										return x.Album < y.Album
									}
								}
							case "Year":
								{
									if x.Year != y.Year {
										return x.Year < y.Year
									}
								}
							case "Length":
								{
									if x.Length != y.Length {
										return x.Length < y.Length
									} //if --- I needed to add comments to track the closing brackets
								} // case Length
							} // switch
						} // for
						return false
					}}) // anonymous func, customSort, sort
				} else {
					fmt.Println("Invalid Choice\n")
				}
			} //ifAtoi
		} //if scanner
	} //for scanner
} //main
//!-main

//!+sortHeading
// sortHeading takes a slice of strings and one element from that slice
// It re-orders the slice, placing the selection in the first position
func sortHeadings(headings []string, i int) []string {

	fmt.Println("Selection:", headings[i])

	// Check to see if the selection the first in the list
	if headings[i] == headings[0] {
		fmt.Println("Order is correct")
		return headings
	}

	// tmp holds the selection as the items are reordered
	tmp := headings[i]

	// Reorder slice. Iterate through the slic, moving items
	// before the selection to the right
	for index := i; index > 0; index-- {
		headings[index] = headings[index-1]
	}

	//Place the selection at the front of the slice
	headings[0] = tmp
	// return the reordered slice
	return headings
}

//!-sortHeading

//!+ list
// list prints the headings list to Stdout along with the escape char q
func list(headings []string) {
	fmt.Printf("Sort order\n")
	for index := 0; index < len(headings); index++ {
		fmt.Printf("%d. %s\n", index+1, headings[index])
	}
	fmt.Println("q to quit\n")
}

//!- list

//!+printTracks
func printTracks(tracks []*Track) {
	const format = "%v\t%v\t%v\t%v\t%v\t\n"
	tw := new(tabwriter.Writer).Init(os.Stdout, 0, 8, 2, ' ', 0)
	fmt.Fprintf(tw, format, "Title", "Artist", "Album", "Year", "Length")
	fmt.Fprintf(tw, format, "-----", "------", "-----", "----", "------")
	for _, t := range tracks {
		fmt.Fprintf(tw, format, t.Title, t.Artist, t.Album, t.Year, t.Length)
	}
	tw.Flush() // calculate column widths and print table
	fmt.Println()
}

//!-printTracks

//!+customcode
// Modified customSort struct to inlcude headings
type customSort struct {
	t        []*Track
	headings []string
	less     func(x, y *Track) bool
}

func (x customSort) Len() int           { return len(x.t) }
func (x customSort) Less(i, j int) bool { return x.less(x.t[i], x.t[j]) }
func (x customSort) Swap(i, j int)      { x.t[i], x.t[j] = x.t[j], x.t[i] }

//!-customcode
<|endoftext|>


<commit_before>// Copyright 2016 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

package libfuse

import (
	"errors"
	"fmt"
	"os"
	"os/exec"
	"path"
	"runtime"

	"bazil.org/fuse"
)

type mounter struct {
	options StartOptions
	c       *fuse.Conn
}

// fuseMount tries to mount the mountpoint.
// On a force mount then unmount, re-mount if unsuccessful
func (m *mounter) Mount() (err error) {
	m.c, err = fuseMountDir(m.options.MountPoint, m.options.PlatformParams)
	// Exit if we were succesful or we are not a force mounting on error.
	if err == nil || !m.options.ForceMount {
		return err
	}

	// Mount failed, let's try to unmount and then try mounting again, even
	// if unmounting errors here.
	m.Unmount()

	m.c, err = fuseMountDir(m.options.MountPoint, m.options.PlatformParams)
	return err
}

func fuseMountDir(dir string, platformParams PlatformParams) (*fuse.Conn, error) {
	fi, err := os.Stat(dir)
	if err != nil {
		return nil, err
	}
	if !fi.IsDir() {
		return nil, errors.New("mount point is not a directory")
	}
	options, err := getPlatformSpecificMountOptions(dir, platformParams)
	if err != nil {
		return nil, err
	}
	c, err := fuse.Mount(dir, options...)
	if err != nil {
		err = translatePlatformSpecificError(err, platformParams)
		return nil, err
	}
	return c, nil
}

func (m *mounter) Unmount() (err error) {
	dir := m.options.MountPoint
	// Try normal unmount
	switch runtime.GOOS {
	case "darwin":
		_, err = exec.Command("/sbin/umount", dir).Output()
	case "linux":
		_, err = exec.Command("fusermount", "-u", dir).Output()
	default:
		err = fuse.Unmount(dir)
	}
	if err != nil && m.options.ForceMount {
		// Unmount failed, so let's try and force it.
		switch runtime.GOOS {
		case "darwin":
			_, err = exec.Command(
				"/usr/sbin/diskutil", "unmountDisk", "force", dir).Output()
		case "linux":
			_, err = exec.Command("fusermount", "-ul", dir).Output()
		default:
			err = errors.New("Forced unmount is not supported on this platform yet")
		}
	}
	if execErr, ok := err.(*exec.ExitError); ok && execErr.Stderr != nil {
		err = fmt.Errorf("%s (%s)", execErr, execErr.Stderr)
	}
	return
}

// volumeName returns the directory (base) name
func volumeName(dir string) (string, error) {
	volName := path.Base(dir)
	if volName == "." || volName == "/" {
		err := fmt.Errorf("Bad volume name: %v", volName)
		return "", err
	}
	return volName, nil
}
<commit_msg>unmount and mount again even if not in force mode<commit_after>// Copyright 2016 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

package libfuse

import (
	"errors"
	"fmt"
	"os"
	"os/exec"
	"path"
	"runtime"

	"bazil.org/fuse"
)

type mounter struct {
	options StartOptions
	c       *fuse.Conn
}

// fuseMount tries to mount the mountpoint.
// On a force mount then unmount, re-mount if unsuccessful
func (m *mounter) Mount() (err error) {
	m.c, err = fuseMountDir(m.options.MountPoint, m.options.PlatformParams)
	// Exit if we were succesful. Otherwise, try unmounting and mounting again.
	if err == nil {
		return err
	}

	// Mount failed, let's try to unmount and then try mounting again, even
	// if unmounting errors here.
	m.Unmount()

	m.c, err = fuseMountDir(m.options.MountPoint, m.options.PlatformParams)
	return err
}

func fuseMountDir(dir string, platformParams PlatformParams) (*fuse.Conn, error) {
	fi, err := os.Stat(dir)
	if err != nil {
		return nil, err
	}
	if !fi.IsDir() {
		return nil, errors.New("mount point is not a directory")
	}
	options, err := getPlatformSpecificMountOptions(dir, platformParams)
	if err != nil {
		return nil, err
	}
	c, err := fuse.Mount(dir, options...)
	if err != nil {
		err = translatePlatformSpecificError(err, platformParams)
		return nil, err
	}
	return c, nil
}

func (m *mounter) Unmount() (err error) {
	dir := m.options.MountPoint
	// Try normal unmount
	switch runtime.GOOS {
	case "darwin":
		_, err = exec.Command("/sbin/umount", dir).Output()
	case "linux":
		_, err = exec.Command("fusermount", "-u", dir).Output()
	default:
		err = fuse.Unmount(dir)
	}
	if err != nil && m.options.ForceMount {
		// Unmount failed, so let's try and force it.
		switch runtime.GOOS {
		case "darwin":
			_, err = exec.Command(
				"/usr/sbin/diskutil", "unmountDisk", "force", dir).Output()
		case "linux":
			_, err = exec.Command("fusermount", "-ul", dir).Output()
		default:
			err = errors.New("Forced unmount is not supported on this platform yet")
		}
	}
	if execErr, ok := err.(*exec.ExitError); ok && execErr.Stderr != nil {
		err = fmt.Errorf("%s (%s)", execErr, execErr.Stderr)
	}
	return
}

// volumeName returns the directory (base) name
func volumeName(dir string) (string, error) {
	volName := path.Base(dir)
	if volName == "." || volName == "/" {
		err := fmt.Errorf("Bad volume name: %v", volName)
		return "", err
	}
	return volName, nil
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"flag"
	"fmt"
	"os"
	"path"
	"strings"
	"text/template"
	"time"
)

var templateContent = `
-- +migrate Up

-- +migrate Down
`
var tpl *template.Template

func init() {
	tpl = template.Must(template.New("new_migration").Parse(templateContent))
}

type NewCommand struct {
}

func (c *NewCommand) Help() string {
	helpText := `
Usage: sql-migrate new [options] name

  Create a new a database migration.

Options:

  -config=dbconfig.yml   Configuration file to use.
  -env="development"     Environment.
  name                   The name of the migration
`
	return strings.TrimSpace(helpText)
}

func (c *NewCommand) Synopsis() string {
	return "Create a new migration"
}

func (c *NewCommand) Run(args []string) int {
	cmdFlags := flag.NewFlagSet("redo", flag.ContinueOnError)
	cmdFlags.Usage = func() { ui.Output(c.Help()) }
	ConfigFlags(cmdFlags)

	if len(args) < 1 {
		err := errors.New("A name for the migration is needed")
		ui.Error(err.Error())
		return 1
	}

	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	if err := CreateMigration(args[0]); err != nil {
		ui.Error(err.Error())
		return 1
	}
	return 0
}

func CreateMigration(name string) error {
	env, err := GetEnvironment()
	if err != nil {
		return err
	}

	if _, err := os.Stat(env.Dir); os.IsNotExist(err) {
		return err
	}

	fileName := fmt.Sprintf("%s-%s.sql", time.Now().Format("20060201150405"), strings.TrimSpace(name))
	f, err := os.Create(path.Join(env.Dir, fileName))

	if err != nil {
		return err
	}
	defer f.Close()
	return tpl.Execute(f, nil)
}
<commit_msg>Create a migration from the first non-flag arg<commit_after>package main

import (
	"errors"
	"flag"
	"fmt"
	"os"
	"path"
	"strings"
	"text/template"
	"time"
)

var templateContent = `
-- +migrate Up

-- +migrate Down
`
var tpl *template.Template

func init() {
	tpl = template.Must(template.New("new_migration").Parse(templateContent))
}

type NewCommand struct {
}

func (c *NewCommand) Help() string {
	helpText := `
Usage: sql-migrate new [options] name

  Create a new a database migration.

Options:

  -config=dbconfig.yml   Configuration file to use.
  -env="development"     Environment.
  name                   The name of the migration
`
	return strings.TrimSpace(helpText)
}

func (c *NewCommand) Synopsis() string {
	return "Create a new migration"
}

func (c *NewCommand) Run(args []string) int {
	cmdFlags := flag.NewFlagSet("redo", flag.ContinueOnError)
	cmdFlags.Usage = func() { ui.Output(c.Help()) }
	ConfigFlags(cmdFlags)

	if len(args) < 1 {
		err := errors.New("A name for the migration is needed")
		ui.Error(err.Error())
		return 1
	}

	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	if err := CreateMigration(cmdFlags.Arg(0)); err != nil {
		ui.Error(err.Error())
		return 1
	}
	return 0
}

func CreateMigration(name string) error {
	env, err := GetEnvironment()
	if err != nil {
		return err
	}

	if _, err := os.Stat(env.Dir); os.IsNotExist(err) {
		return err
	}

	fileName := fmt.Sprintf("%s-%s.sql", time.Now().Format("20060201150405"), strings.TrimSpace(name))
	f, err := os.Create(path.Join(env.Dir, fileName))

	if err != nil {
		return err
	}
	defer f.Close()
	return tpl.Execute(f, nil)
}
<|endoftext|>


<commit_before>package resource

import (
	"errors"
	"fmt"
	"log"
	"math"
	"time"
)

// StateRefreshFunc is a function type used for StateChangeConf that is
// responsible for refreshing the item being watched for a state change.
//
// It returns three results. `result` is any object that will be returned
// as the final object after waiting for state change. This allows you to
// return the final updated object, for example an EC2 instance after refreshing
// it.
//
// `state` is the latest state of that object. And `err` is any error that
// may have happened while refreshing the state.
type StateRefreshFunc func() (result interface{}, state string, err error)

// StateChangeConf is the configuration struct used for `WaitForState`.
type StateChangeConf struct {
	Delay          time.Duration    // Wait this time before starting checks
	Pending        []string         // States that are "allowed" and will continue trying
	Refresh        StateRefreshFunc // Refreshes the current state
	Target         string           // Target state
	Timeout        time.Duration    // The amount of time to wait before timeout
	MinTimeout     time.Duration    // Smallest time to wait before refreshes
	NotFoundChecks int              // Number of times to allow not found
}

// WaitForState watches an object and waits for it to achieve the state
// specified in the configuration using the specified Refresh() func,
// waiting the number of seconds specified in the timeout configuration.
func (conf *StateChangeConf) WaitForState() (interface{}, error) {
	log.Printf("[DEBUG] Waiting for state to become: %s", conf.Target)

	notfoundTick := 0

	// Set a default for times to check for not found
	if conf.NotFoundChecks == 0 {
		conf.NotFoundChecks = 20
	}

	var result interface{}
	var resulterr error

	doneCh := make(chan struct{})
	go func() {
		defer close(doneCh)

		// Wait for the delay
		time.Sleep(conf.Delay)

		var err error
		for tries := 0; ; tries++ {
			// Wait between refreshes using an exponential backoff
			wait := time.Duration(math.Pow(2, float64(tries))) *
				100 * time.Millisecond
			if wait < conf.MinTimeout {
				wait = conf.MinTimeout
			} else if wait > 10*time.Second {
				wait = 10 * time.Second
			}

			log.Printf("[TRACE] Waiting %s before next try", wait)
			time.Sleep(wait)

			var currentState string
			result, currentState, err = conf.Refresh()
			if err != nil {
				resulterr = err
				return
			}

			// If we're waiting for the absence of a thing, then return
			if result == nil && conf.Target == "" {
				return
			}

			if result == nil {
				// If we didn't find the resource, check if we have been
				// not finding it for awhile, and if so, report an error.
				notfoundTick += 1
				if notfoundTick > conf.NotFoundChecks {
					resulterr = errors.New("couldn't find resource")
					return
				}
			} else {
				// Reset the counter for when a resource isn't found
				notfoundTick = 0

				if currentState == conf.Target {
					return
				}

				found := false
				for _, allowed := range conf.Pending {
					if currentState == allowed {
						found = true
						break
					}
				}

				if !found {
					resulterr = fmt.Errorf(
						"unexpected state '%s', wanted target '%s'",
						currentState,
						conf.Target)
					return
				}
			}
		}
	}()

	select {
	case <-doneCh:
		return result, resulterr
	case <-time.After(conf.Timeout):
		return nil, fmt.Errorf(
			"timeout while waiting for state to become '%s'",
			conf.Target)
	}
}
<commit_msg>Better document StateChangeConf.WaitForState<commit_after>package resource

import (
	"errors"
	"fmt"
	"log"
	"math"
	"time"
)

// StateRefreshFunc is a function type used for StateChangeConf that is
// responsible for refreshing the item being watched for a state change.
//
// It returns three results. `result` is any object that will be returned
// as the final object after waiting for state change. This allows you to
// return the final updated object, for example an EC2 instance after refreshing
// it.
//
// `state` is the latest state of that object. And `err` is any error that
// may have happened while refreshing the state.
type StateRefreshFunc func() (result interface{}, state string, err error)

// StateChangeConf is the configuration struct used for `WaitForState`.
type StateChangeConf struct {
	Delay          time.Duration    // Wait this time before starting checks
	Pending        []string         // States that are "allowed" and will continue trying
	Refresh        StateRefreshFunc // Refreshes the current state
	Target         string           // Target state
	Timeout        time.Duration    // The amount of time to wait before timeout
	MinTimeout     time.Duration    // Smallest time to wait before refreshes
	NotFoundChecks int              // Number of times to allow not found
}

// WaitForState watches an object and waits for it to achieve the state
// specified in the configuration using the specified Refresh() func,
// waiting the number of seconds specified in the timeout configuration.
//
// If the Refresh function returns a error, exit immediately with that error.
//
// If the Refresh function returns a state other than the Target state or one
// listed in Pending, return immediately with an error.
//
// If the Timeout is exceeded before reaching the Target state, return an
// error.
//
// Otherwise, result the result of the first call to the Refresh function to
// reach the target state.
func (conf *StateChangeConf) WaitForState() (interface{}, error) {
	log.Printf("[DEBUG] Waiting for state to become: %s", conf.Target)

	notfoundTick := 0

	// Set a default for times to check for not found
	if conf.NotFoundChecks == 0 {
		conf.NotFoundChecks = 20
	}

	var result interface{}
	var resulterr error

	doneCh := make(chan struct{})
	go func() {
		defer close(doneCh)

		// Wait for the delay
		time.Sleep(conf.Delay)

		var err error
		for tries := 0; ; tries++ {
			// Wait between refreshes using an exponential backoff
			wait := time.Duration(math.Pow(2, float64(tries))) *
				100 * time.Millisecond
			if wait < conf.MinTimeout {
				wait = conf.MinTimeout
			} else if wait > 10*time.Second {
				wait = 10 * time.Second
			}

			log.Printf("[TRACE] Waiting %s before next try", wait)
			time.Sleep(wait)

			var currentState string
			result, currentState, err = conf.Refresh()
			if err != nil {
				resulterr = err
				return
			}

			// If we're waiting for the absence of a thing, then return
			if result == nil && conf.Target == "" {
				return
			}

			if result == nil {
				// If we didn't find the resource, check if we have been
				// not finding it for awhile, and if so, report an error.
				notfoundTick += 1
				if notfoundTick > conf.NotFoundChecks {
					resulterr = errors.New("couldn't find resource")
					return
				}
			} else {
				// Reset the counter for when a resource isn't found
				notfoundTick = 0

				if currentState == conf.Target {
					return
				}

				found := false
				for _, allowed := range conf.Pending {
					if currentState == allowed {
						found = true
						break
					}
				}

				if !found {
					resulterr = fmt.Errorf(
						"unexpected state '%s', wanted target '%s'",
						currentState,
						conf.Target)
					return
				}
			}
		}
	}()

	select {
	case <-doneCh:
		return result, resulterr
	case <-time.After(conf.Timeout):
		return nil, fmt.Errorf(
			"timeout while waiting for state to become '%s'",
			conf.Target)
	}
}
<|endoftext|>


<commit_before>package v3_helpers

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

	"github.com/cloudfoundry-incubator/cf-test-helpers/cf"
	"github.com/cloudfoundry-incubator/cf-test-helpers/config"
	"github.com/cloudfoundry-incubator/cf-test-helpers/helpers"

	. "github.com/cloudfoundry/cf-acceptance-tests/cats_suite_helpers"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"
)

func StartApp(appGuid string) {
	startURL := fmt.Sprintf("/v3/apps/%s/start", appGuid)
	Expect(cf.Cf("curl", startURL, "-X", "PUT").Wait(Config.DefaultTimeoutDuration())).To(Exit(0))
}

func StopApp(appGuid string) {
	stopURL := fmt.Sprintf("/v3/apps/%s/stop", appGuid)
	Expect(cf.Cf("curl", stopURL, "-X", "PUT").Wait(Config.DefaultTimeoutDuration())).To(Exit(0))
}

func CreateApp(appName, spaceGuid, environmentVariables string) string {
	session := cf.Cf("curl", "/v3/apps", "-X", "POST", "-d", fmt.Sprintf(`{"name":"%s", "relationships": {"space": {"guid": "%s"}}, "environment_variables":%s}`, appName, spaceGuid, environmentVariables))
	bytes := session.Wait(Config.DefaultTimeoutDuration()).Out.Contents()
	var app struct {
		Guid string `json:"guid"`
	}
	json.Unmarshal(bytes, &app)
	return app.Guid
}

func CreateDockerApp(appName, spaceGuid, environmentVariables string) string {
	session := cf.Cf("curl", "/v3/apps", "-X", "POST", "-d", fmt.Sprintf(`{"name":"%s", "relationships": {"space": {"guid": "%s"}}, "environment_variables":%s, "lifecycle": {"type": "docker", "data": {} } }`, appName, spaceGuid, environmentVariables))
	bytes := session.Wait(Config.DefaultTimeoutDuration()).Out.Contents()
	var app struct {
		Guid string `json:"guid"`
	}
	json.Unmarshal(bytes, &app)
	return app.Guid
}

func DeleteApp(appGuid string) {
	session := cf.Cf("curl", fmt.Sprintf("/v3/apps/%s", appGuid), "-X", "DELETE", "-v")
	bytes := session.Wait(Config.DefaultTimeoutDuration()).Out.Contents()
	Expect(bytes).To(ContainSubstring("204 No Content"))
}

func WaitForPackageToBeReady(packageGuid string) {
	pkgUrl := fmt.Sprintf("/v3/packages/%s", packageGuid)
	Eventually(func() *Session {
		session := cf.Cf("curl", pkgUrl)
		Expect(session.Wait(Config.DefaultTimeoutDuration())).To(Exit(0))
		return session
	}, Config.LongCurlTimeoutDuration()).Should(Say("READY"))
}

func WaitForDropletToStage(dropletGuid string) {
	dropletPath := fmt.Sprintf("/v3/droplets/%s", dropletGuid)
	Eventually(func() *Session {
		session := cf.Cf("curl", dropletPath).Wait(Config.DefaultTimeoutDuration())
		Expect(session).NotTo(Say("FAILED"))
		return session
	}, Config.CfPushTimeoutDuration()).Should(Say("STAGED"))
}

func CreatePackage(appGuid string) string {
	packageCreateUrl := fmt.Sprintf("/v3/apps/%s/packages", appGuid)
	session := cf.Cf("curl", packageCreateUrl, "-X", "POST", "-d", fmt.Sprintf(`{"type":"bits"}`))
	bytes := session.Wait(Config.DefaultTimeoutDuration()).Out.Contents()
	var pac struct {
		Guid string `json:"guid"`
	}
	json.Unmarshal(bytes, &pac)
	return pac.Guid
}

func CreateDockerPackage(appGuid, imagePath string) string {
	packageCreateUrl := fmt.Sprintf("/v3/apps/%s/packages", appGuid)
	session := cf.Cf("curl", packageCreateUrl, "-X", "POST", "-d", fmt.Sprintf(`{"type":"docker", "data": {"image": "%s"}}`, imagePath))
	bytes := session.Wait(Config.DefaultTimeoutDuration()).Out.Contents()
	var pac struct {
		Guid string `json:"guid"`
	}
	json.Unmarshal(bytes, &pac)
	return pac.Guid
}

func GetSpaceGuidFromName(spaceName string) string {
	session := cf.Cf("space", spaceName, "--guid")
	bytes := session.Wait(Config.DefaultTimeoutDuration()).Out.Contents()
	return strings.TrimSpace(string(bytes))
}

func GetAuthToken() string {
	bytes := helpers.Run("bash", "-c", "cf oauth-token | grep bearer").Wait(Config.DefaultTimeoutDuration()).Out.Contents()
	return strings.TrimSpace(string(bytes))
}

func UploadPackage(uploadUrl, packageZipPath, token string) {
	bits := fmt.Sprintf(`bits=@%s`, packageZipPath)
	curl := helpers.Curl("-v", "-s", uploadUrl, "-F", bits, "-H", fmt.Sprintf("Authorization: %s", token)).Wait(Config.DefaultTimeoutDuration())
	Expect(curl).To(Exit(0))
}

func StageBuildpackPackage(packageGuid, buildpack string) string {
	stageBody := fmt.Sprintf(`{"lifecycle":{ "type": "buildpack", "data": { "buildpack": "%s" } }}`, buildpack)
	stageUrl := fmt.Sprintf("/v3/packages/%s/droplets", packageGuid)
	session := cf.Cf("curl", stageUrl, "-X", "POST", "-d", stageBody)
	bytes := session.Wait(Config.DefaultTimeoutDuration()).Out.Contents()
	var droplet struct {
		Guid string `json:"guid"`
	}
	json.Unmarshal(bytes, &droplet)
	return droplet.Guid
}

func StageDockerPackage(packageGuid string) string {
	stageUrl := fmt.Sprintf("/v3/packages/%s/droplets", packageGuid)
	session := cf.Cf("curl", stageUrl, "-X", "POST", "-d", "")
	bytes := session.Wait(Config.DefaultTimeoutDuration()).Out.Contents()
	var droplet struct {
		Guid string `json:"guid"`
	}
	json.Unmarshal(bytes, &droplet)
	return droplet.Guid
}

func CreateAndMapRoute(appGuid, space, domain, host string) {
	CreateRoute(space, domain, host)
	getRoutePath := fmt.Sprintf("/v2/routes?q=host:%s", host)
	routeBody := cf.Cf("curl", getRoutePath).Wait(Config.DefaultTimeoutDuration()).Out.Contents()
	routeJSON := struct {
		Resources []struct {
			Metadata struct {
				Guid string `json:"guid"`
			} `json:"metadata"`
		} `json:"resources"`
	}{}
	json.Unmarshal([]byte(routeBody), &routeJSON)
	routeGuid := routeJSON.Resources[0].Metadata.Guid
	addRouteBody := fmt.Sprintf(`
	{
		"relationships": {
			"app":   {"guid": "%s"},
			"route": {"guid": "%s"}
		}
	}`, appGuid, routeGuid)
	Expect(cf.Cf("curl", "/v3/route_mappings", "-X", "POST", "-d", addRouteBody).Wait(Config.DefaultTimeoutDuration())).To(Exit(0))
}

func AssignDropletToApp(appGuid, dropletGuid string) {
	appUpdatePath := fmt.Sprintf("/v3/apps/%s/droplets/current", appGuid)
	appUpdateBody := fmt.Sprintf(`{"droplet_guid":"%s"}`, dropletGuid)
	Expect(cf.Cf("curl", appUpdatePath, "-X", "PUT", "-d", appUpdateBody).Wait(Config.DefaultTimeoutDuration())).To(Exit(0))

	for _, process := range GetProcesses(appGuid, "") {
		ScaleProcess(appGuid, process.Type, DEFAULT_MEMORY_LIMIT)
	}
}

func FetchRecentLogs(appGuid, oauthToken string, config config.Config) *Session {
	loggregatorEndpoint := strings.Replace(config.ApiEndpoint, "api", "doppler", -1)
	logUrl := fmt.Sprintf("%s/recent?app=%s", loggregatorEndpoint, appGuid)
	session := helpers.Curl(logUrl, "-H", fmt.Sprintf("Authorization: %s", oauthToken))
	Expect(session.Wait(Config.DefaultTimeoutDuration())).To(Exit(0))
	return session
}

func ScaleProcess(appGuid, processType, memoryInMb string) {
	scalePath := fmt.Sprintf("/v3/apps/%s/processes/%s/scale", appGuid, processType)
	scaleBody := fmt.Sprintf(`{"memory_in_mb":"%s"}`, memoryInMb)
	Expect(cf.Cf("curl", scalePath, "-X", "PUT", "-d", scaleBody).Wait(Config.DefaultTimeoutDuration())).To(Exit(0))
}

func CreateRoute(space, domain, host string) {
	Expect(cf.Cf("create-route", space, domain, "-n", host).Wait(Config.DefaultTimeoutDuration())).To(Exit(0))
}
<commit_msg>Update doppler endpoint for v3 tests<commit_after>package v3_helpers

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

	"github.com/cloudfoundry-incubator/cf-test-helpers/cf"
	"github.com/cloudfoundry-incubator/cf-test-helpers/config"
	"github.com/cloudfoundry-incubator/cf-test-helpers/helpers"

	. "github.com/cloudfoundry/cf-acceptance-tests/cats_suite_helpers"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"
)

func StartApp(appGuid string) {
	startURL := fmt.Sprintf("/v3/apps/%s/start", appGuid)
	Expect(cf.Cf("curl", startURL, "-X", "PUT").Wait(Config.DefaultTimeoutDuration())).To(Exit(0))
}

func StopApp(appGuid string) {
	stopURL := fmt.Sprintf("/v3/apps/%s/stop", appGuid)
	Expect(cf.Cf("curl", stopURL, "-X", "PUT").Wait(Config.DefaultTimeoutDuration())).To(Exit(0))
}

func CreateApp(appName, spaceGuid, environmentVariables string) string {
	session := cf.Cf("curl", "/v3/apps", "-X", "POST", "-d", fmt.Sprintf(`{"name":"%s", "relationships": {"space": {"guid": "%s"}}, "environment_variables":%s}`, appName, spaceGuid, environmentVariables))
	bytes := session.Wait(Config.DefaultTimeoutDuration()).Out.Contents()
	var app struct {
		Guid string `json:"guid"`
	}
	json.Unmarshal(bytes, &app)
	return app.Guid
}

func CreateDockerApp(appName, spaceGuid, environmentVariables string) string {
	session := cf.Cf("curl", "/v3/apps", "-X", "POST", "-d", fmt.Sprintf(`{"name":"%s", "relationships": {"space": {"guid": "%s"}}, "environment_variables":%s, "lifecycle": {"type": "docker", "data": {} } }`, appName, spaceGuid, environmentVariables))
	bytes := session.Wait(Config.DefaultTimeoutDuration()).Out.Contents()
	var app struct {
		Guid string `json:"guid"`
	}
	json.Unmarshal(bytes, &app)
	return app.Guid
}

func DeleteApp(appGuid string) {
	session := cf.Cf("curl", fmt.Sprintf("/v3/apps/%s", appGuid), "-X", "DELETE", "-v")
	bytes := session.Wait(Config.DefaultTimeoutDuration()).Out.Contents()
	Expect(bytes).To(ContainSubstring("204 No Content"))
}

func WaitForPackageToBeReady(packageGuid string) {
	pkgUrl := fmt.Sprintf("/v3/packages/%s", packageGuid)
	Eventually(func() *Session {
		session := cf.Cf("curl", pkgUrl)
		Expect(session.Wait(Config.DefaultTimeoutDuration())).To(Exit(0))
		return session
	}, Config.LongCurlTimeoutDuration()).Should(Say("READY"))
}

func WaitForDropletToStage(dropletGuid string) {
	dropletPath := fmt.Sprintf("/v3/droplets/%s", dropletGuid)
	Eventually(func() *Session {
		session := cf.Cf("curl", dropletPath).Wait(Config.DefaultTimeoutDuration())
		Expect(session).NotTo(Say("FAILED"))
		return session
	}, Config.CfPushTimeoutDuration()).Should(Say("STAGED"))
}

func CreatePackage(appGuid string) string {
	packageCreateUrl := fmt.Sprintf("/v3/apps/%s/packages", appGuid)
	session := cf.Cf("curl", packageCreateUrl, "-X", "POST", "-d", fmt.Sprintf(`{"type":"bits"}`))
	bytes := session.Wait(Config.DefaultTimeoutDuration()).Out.Contents()
	var pac struct {
		Guid string `json:"guid"`
	}
	json.Unmarshal(bytes, &pac)
	return pac.Guid
}

func CreateDockerPackage(appGuid, imagePath string) string {
	packageCreateUrl := fmt.Sprintf("/v3/apps/%s/packages", appGuid)
	session := cf.Cf("curl", packageCreateUrl, "-X", "POST", "-d", fmt.Sprintf(`{"type":"docker", "data": {"image": "%s"}}`, imagePath))
	bytes := session.Wait(Config.DefaultTimeoutDuration()).Out.Contents()
	var pac struct {
		Guid string `json:"guid"`
	}
	json.Unmarshal(bytes, &pac)
	return pac.Guid
}

func GetSpaceGuidFromName(spaceName string) string {
	session := cf.Cf("space", spaceName, "--guid")
	bytes := session.Wait(Config.DefaultTimeoutDuration()).Out.Contents()
	return strings.TrimSpace(string(bytes))
}

func GetAuthToken() string {
	bytes := helpers.Run("bash", "-c", "cf oauth-token | grep bearer").Wait(Config.DefaultTimeoutDuration()).Out.Contents()
	return strings.TrimSpace(string(bytes))
}

func UploadPackage(uploadUrl, packageZipPath, token string) {
	bits := fmt.Sprintf(`bits=@%s`, packageZipPath)
	curl := helpers.Curl("-v", "-s", uploadUrl, "-F", bits, "-H", fmt.Sprintf("Authorization: %s", token)).Wait(Config.DefaultTimeoutDuration())
	Expect(curl).To(Exit(0))
}

func StageBuildpackPackage(packageGuid, buildpack string) string {
	stageBody := fmt.Sprintf(`{"lifecycle":{ "type": "buildpack", "data": { "buildpack": "%s" } }}`, buildpack)
	stageUrl := fmt.Sprintf("/v3/packages/%s/droplets", packageGuid)
	session := cf.Cf("curl", stageUrl, "-X", "POST", "-d", stageBody)
	bytes := session.Wait(Config.DefaultTimeoutDuration()).Out.Contents()
	var droplet struct {
		Guid string `json:"guid"`
	}
	json.Unmarshal(bytes, &droplet)
	return droplet.Guid
}

func StageDockerPackage(packageGuid string) string {
	stageUrl := fmt.Sprintf("/v3/packages/%s/droplets", packageGuid)
	session := cf.Cf("curl", stageUrl, "-X", "POST", "-d", "")
	bytes := session.Wait(Config.DefaultTimeoutDuration()).Out.Contents()
	var droplet struct {
		Guid string `json:"guid"`
	}
	json.Unmarshal(bytes, &droplet)
	return droplet.Guid
}

func CreateAndMapRoute(appGuid, space, domain, host string) {
	CreateRoute(space, domain, host)
	getRoutePath := fmt.Sprintf("/v2/routes?q=host:%s", host)
	routeBody := cf.Cf("curl", getRoutePath).Wait(Config.DefaultTimeoutDuration()).Out.Contents()
	routeJSON := struct {
		Resources []struct {
			Metadata struct {
				Guid string `json:"guid"`
			} `json:"metadata"`
		} `json:"resources"`
	}{}
	json.Unmarshal([]byte(routeBody), &routeJSON)
	routeGuid := routeJSON.Resources[0].Metadata.Guid
	addRouteBody := fmt.Sprintf(`
	{
		"relationships": {
			"app":   {"guid": "%s"},
			"route": {"guid": "%s"}
		}
	}`, appGuid, routeGuid)
	Expect(cf.Cf("curl", "/v3/route_mappings", "-X", "POST", "-d", addRouteBody).Wait(Config.DefaultTimeoutDuration())).To(Exit(0))
}

func AssignDropletToApp(appGuid, dropletGuid string) {
	appUpdatePath := fmt.Sprintf("/v3/apps/%s/droplets/current", appGuid)
	appUpdateBody := fmt.Sprintf(`{"droplet_guid":"%s"}`, dropletGuid)
	Expect(cf.Cf("curl", appUpdatePath, "-X", "PUT", "-d", appUpdateBody).Wait(Config.DefaultTimeoutDuration())).To(Exit(0))

	for _, process := range GetProcesses(appGuid, "") {
		ScaleProcess(appGuid, process.Type, DEFAULT_MEMORY_LIMIT)
	}
}

func FetchRecentLogs(appGuid, oauthToken string, config config.Config) *Session {
	loggregatorEndpoint := strings.Replace(config.ApiEndpoint, "api", "doppler", -1)
	logUrl := fmt.Sprintf("%s/apps/%s/recentlogs", loggregatorEndpoint, appGuid)
	session := helpers.Curl(logUrl, "-H", fmt.Sprintf("Authorization: %s", oauthToken))
	Expect(session.Wait(Config.DefaultTimeoutDuration())).To(Exit(0))
	return session
}

func ScaleProcess(appGuid, processType, memoryInMb string) {
	scalePath := fmt.Sprintf("/v3/apps/%s/processes/%s/scale", appGuid, processType)
	scaleBody := fmt.Sprintf(`{"memory_in_mb":"%s"}`, memoryInMb)
	Expect(cf.Cf("curl", scalePath, "-X", "PUT", "-d", scaleBody).Wait(Config.DefaultTimeoutDuration())).To(Exit(0))
}

func CreateRoute(space, domain, host string) {
	Expect(cf.Cf("create-route", space, domain, "-n", host).Wait(Config.DefaultTimeoutDuration())).To(Exit(0))
}
<|endoftext|>


<commit_before>package easygen

import (
	"fmt"
	"testing"

	"github.com/suntong/easygen"
)

////////////////////////////////////////////////////////////////////////////
// Lists

//==========================================================================
// list0

func TestList0(t *testing.T) {
	t.Log("First and plainest list test")
	const await = "The colors are: red, blue, white, .\n"
	if got := easygen.Generate(false, "test/list0"); got != await {
		t.Errorf("Mismatch:, got '%s' instead", got)
	}
}

//==========================================================================
// list1

func TestList1Text(t *testing.T) {
	t.Log("Second test, with text template")
	const await = "The quoted colors are: \"red\", \"blue\", \"white\", .\n"
	if got := easygen.Generate(false, "test/list1"); got != await {
		t.Errorf("Mismatch:, got '%s' instead", got)
	}
}

func TestList1HTML(t *testing.T) {
	t.Log("Second test, with html template")
	const await = "The quoted colors are: "red", "blue", "white", .\n"
	if got := easygen.Generate(true, "test/list1"); got != await {
		t.Errorf("Mismatch:, got '%s' instead", got)
	}
}

//==========================================================================
// listfunc1

func TestListFunc1(t *testing.T) {
	t.Log("Test custom template function - minus1")
	const await = "red, blue, white.\n"
	if got := easygen.Generate(false, "test/listfunc1"); got != await {
		t.Errorf("Mismatch:, got '%s' instead", got)
	}
}

func ExampleFunc1() {
	fmt.Print(easygen.Generate(false, "test/listfunc1"))
	// Output:
	// red, blue, white.
}

//==========================================================================
// list0 data + listfunc1 template
// I.e.: EasyGen -tf test/listfunc1 test/list0
func ExampleList0Func1() {
	fmt.Print(easygen.Generate2(false, "test/listfunc1", "test/list0"))
	// Output:
	// red, blue, white.
}

//==========================================================================
// list0 data + string template
// I.e.: EasyGen -ts "{{range .Colors}}{{.}}, {{end}}" test/list0
func ExampleList0StrTemplate() {
	fmt.Print(easygen.Generate0(false, "{{range .Colors}}{{.}}, {{end}}", "test/list0"))
	// Output:
	// red, blue, white,
}

//==========================================================================
// listfunc2

func ExampleFunc2() {
	fmt.Print(easygen.Generate(false, "test/listfunc2"))
	// Output:
	// some-init-method 5 5 someInitMethod SomeInitMethod
}

////////////////////////////////////////////////////////////////////////////
// Commandline definitions

func ExampleTestExample() {
	// Ref https://groups.google.com/d/msg/golang-nuts/9jKexxD19Js/xrNAQA1ACnMJ
	fmt.Println(`  flags.Bool("Debug", false, "Turn on debugging.")`)
	fmt.Println(`  viper.BindPFlag("Debug", flags.Lookup("Debug"))`)
	// Output:
	//   flags.Bool("Debug", false, "Turn on debugging.")
	//   viper.BindPFlag("Debug", flags.Lookup("Debug"))
}

func ExampleCommandLineCobraViper() {
	// EasyGen commandlineCV | sed 's|^\t|&//&|; s|^$|\t//|'
	fmt.Print(easygen.Generate(false, "test/commandlineCV"))
	// Output:
	//
	//	flags.Bool("debug", false, "Turn on debugging.")
	//	viper.BindPFlag("debug", flags.Lookup("debug"))
	//
	//	flags.String("addr", "localhost:5002", "Address of the service.")
	//	viper.BindPFlag("addr", flags.Lookup("addr"))
	//
	//	flags.String("smtp-addr", "localhost:25", "Address of the SMTP server.")
	//	viper.BindPFlag("smtp-addr", flags.Lookup("smtp-addr"))
	//
	//	flags.String("smtp-user", "", "User for the SMTP server.")
	//	viper.BindPFlag("smtp-user", flags.Lookup("smtp-user"))
	//
	//	flags.String("smtp-password", "", "Password for the SMTP server.")
	//	viper.BindPFlag("smtp-password", flags.Lookup("smtp-password"))
	//
	//	flags.String("email-from", "noreply@abc.com", "The from email address.")
	//	viper.BindPFlag("email-from", flags.Lookup("email-from"))
	//
}

func ExampleCommandLineOptInitFull() {
	// EasyGen commandlineCVFull | sed 's|^|\t// |;'
	fmt.Print(easygen.Generate(false, "test/commandlineCVFull"))
	// Output:
	// func init() {
	//
	//   viper.SetEnvPrefix("DISPATCH")
	//   viper.AutomaticEnv()
	//
	//   /*
	//
	//     When AutomaticEnv called, Viper will check for an environment variable any
	//     time a viper.Get request is made. It will apply the following rules. It
	//     will check for a environment variable with a name matching the key
	//     uppercased and prefixed with the EnvPrefix if set.
	//
	//   */
	//
	//   flags := mainCmd.Flags()
	//
	//   flags.Bool("Debug", false, "Turn on debugging.")
	//   viper.BindPFlag("Debug", flags.Lookup("Debug"))
	//
	//   flags.String("addr", "localhost:5002", "Address of the service.")
	//   viper.BindPFlag("addr", flags.Lookup("addr"))
	//
	//   flags.String("smtp-addr", "localhost:25", "Address of the SMTP server.")
	//   viper.BindPFlag("smtp-addr", flags.Lookup("smtp-addr"))
	//
	//   flags.String("smtp-user", "", "User for the SMTP server.")
	//   viper.BindPFlag("smtp-user", flags.Lookup("smtp-user"))
	//
	//   flags.String("smtp-password", "", "Password for the SMTP server.")
	//   viper.BindPFlag("smtp-password", flags.Lookup("smtp-password"))
	//
	//   flags.String("email-from", "noreply@abc.com", "The from email address.")
	//   viper.BindPFlag("email-from", flags.Lookup("email-from"))
	//
	//   // Viper supports reading from yaml, toml and/or json files. Viper can
	//   // search multiple paths. Paths will be searched in the order they are
	//   // provided. Searches stopped once Config File found.
	//
	//   viper.SetConfigName("CommandLineCV") // name of config file (without extension)
	//
	//   viper.AddConfigPath("/tmp")
	//   viper.AddConfigPath(".")
	//
	//   err := viper.ReadInConfig()
	//   if err != nil {
	//     println("No config file found. Using built-in defaults.")
	//   }
	//
	// }
}

////////////////////////////////////////////////////////////////////////////
// Varible Names

func ExampleVaribleNames() {
}

////////////////////////////////////////////////////////////////////////////
// Strings Test

func ExampleTestStringsCmp() {
	fmt.Print(easygen.Generate0(false, `The {{if eq .StrTest "-AB-axxb- HTML Html html"}}eq says Yea{{else}}eq says Nay{{end}} but {{if eqf .StrTest "-AB-axxb- HTML Html html"}}eqf says Yea{{else}}eqf says Nay{{end}}.`, "test/strings0"))
	// Output:
	// The eq says Nay but eqf says Yea.
}

func ExampleTestStringSplit0() {
	fmt.Print(easygen.Generate0(false, `{{split .Colorlist}}`, "test/list0"))
	// Output:
	// [red blue white]
}

func ExampleTestStringSplit1() {
	fmt.Print(easygen.Generate0(false, `{{range (split .Colorlist)}}{{.}} {{end}}`, "test/list0"))
	// Output:
	// red blue white
}

/*

// Ref https://golang.org/pkg/regexp/#Regexp.ReplaceAllString
$ easygen -rf="a(x*)b" -rt='${1}W' -ts="{{.StrTest}}, {{replace .StrTest}}, {{.StrTest | replace}}" test/strings0
-ab-axxb- HTML Html html, -W-xxW- HTML Html html, -W-xxW- HTML Html html

$ easygen -rf="HTML" -rt='XML' -ts="{{.StrTest}}, {{replacec .StrTest}}, {{replace .StrTest}}" test/strings0
-ab-axxb- HTML Html html, -ab-axxb- XML Html html, -ab-axxb- XML XML XML

$ EASYGEN_RF="HTML" EASYGEN_RT='XML' easygen -ts="{{.StrTest}}, {{replacec .StrTest}}, {{replace .StrTest}}" test/strings0
-ab-axxb- HTML Html html, -ab-axxb- XML Html html, -ab-axxb- XML XML XML

*/

/*
func ExampleTestStrings() {
	// panic: runtime error: invalid memory address or nil pointer dereference [recovered]
	easygen.Opts.StrFrom = "a(x*)b"
	easygen.Opts.StrTo = "${1}W"
	//fmt.Print(easygen.Generate0(false, "{{.StrTest}} {{replace .StrTest}} {{.StrTest | replace}}", "test/strings0"))
	easygen.Opts.TemplateStr = `{{.StrTest}} {{replace .StrTest}} {{.StrTest | replace}}`
	fmt.Print(easygen.Generate(false, "test/strings0"))
	// Output:
	// -ab-axxb- HTML Html html -W-xxW- HTML Html html -W-xxW- HTML Html html
}
*/
<commit_msg>- [*] convert test cases into (testable) examples so as for easy following<commit_after>package easygen_test

import (
	"fmt"
	"testing"

	"github.com/suntong/easygen"
)

////////////////////////////////////////////////////////////////////////////
// Lists

//==========================================================================
// list0

func TestList0(t *testing.T) {
	t.Log("First and plainest list test")
	const await = "The colors are: red, blue, white, .\n"
	if got := easygen.Generate(false, "test/list0"); got != await {
		t.Errorf("Mismatch:, got '%s' instead", got)
	}
}

//==========================================================================
// list1

func TestList1Text(t *testing.T) {
	t.Log("Second test, with text template")
	const await = "The quoted colors are: \"red\", \"blue\", \"white\", .\n"
	if got := easygen.Generate(false, "test/list1"); got != await {
		t.Errorf("Mismatch:, got '%s' instead", got)
	}
}

func TestList1HTML(t *testing.T) {
	t.Log("Second test, with html template")
	const await = "The quoted colors are: "red", "blue", "white", .\n"
	if got := easygen.Generate(true, "test/list1"); got != await {
		t.Errorf("Mismatch:, got '%s' instead", got)
	}
}

//==========================================================================
// listfunc1

func TestListFunc1(t *testing.T) {
	t.Log("Test custom template function - minus1")
	const await = "red, blue, white.\n"
	if got := easygen.Generate(false, "test/listfunc1"); got != await {
		t.Errorf("Mismatch:, got '%s' instead", got)
	}
}

// Test the provided listfunc1, template and data
func ExampleGenerate_listfunc1() {
	// Equivalent testing on commandline:
	//   easygen test/listfunc1
	fmt.Print(easygen.Generate(false, "test/listfunc1"))
	// Output:
	// red, blue, white.
}

//==========================================================================
// list0 data + listfunc1 template
// I.e.: EasyGen -tf test/listfunc1 test/list0

// Test the provided listfunc1 template with list0 data
func ExampleGenerate2_listfunc1List0() {
	// Equivalent testing on commandline:
	//   easygen -tf test/listfunc1 test/list0
	fmt.Print(easygen.Generate2(false, "test/listfunc1", "test/list0"))
	// Output:
	// red, blue, white.
}

//==========================================================================
// list0 data + string template
// I.e.: EasyGen -ts "{{range .Colors}}{{.}}, {{end}}" test/list0

// Test string template with list0 data
func ExampleGenerate0_list0StrTemplate() {
	// Equivalent testing on commandline:
	//   easygen -ts '{{range .Colors}}{{.}}, {{end}}' test/list0
	fmt.Print(easygen.Generate0(false, "{{range .Colors}}{{.}}, {{end}}", "test/list0"))
	// Output:
	// red, blue, white,
}

//==========================================================================
// listfunc2

// Test the provided listfunc2, template and data
func ExampleGenerate_listfunc2() {
	// Equivalent testing on commandline:
	//   easygen test/listfunc2
	fmt.Print(easygen.Generate(false, "test/listfunc2"))
	// Output:
	// some-init-method 5 5 someInitMethod SomeInitMethod
}

////////////////////////////////////////////////////////////////////////////
// Commandline definitions

func ExampleTestExample() {
	// Ref https://groups.google.com/d/msg/golang-nuts/9jKexxD19Js/xrNAQA1ACnMJ
	fmt.Println(`  flags.Bool("Debug", false, "Turn on debugging.")`)
	fmt.Println(`  viper.BindPFlag("Debug", flags.Lookup("Debug"))`)
	// Output:
	//   flags.Bool("Debug", false, "Turn on debugging.")
	//   viper.BindPFlag("Debug", flags.Lookup("Debug"))
}

//   easygen test/commandlineCV | sed 's|^\t|&//&|; s|^$|\t//|'

// Test the provided Cobra/Viper command line flag auto generation
func ExampleGenerate_commandLineCobraViper() {
	// Equivalent testing on commandline:
	//   easygen test/commandlineCV
	fmt.Print(easygen.Generate(false, "test/commandlineCV"))
	// Output:
	//
	//	flags.Bool("debug", false, "Turn on debugging.")
	//	viper.BindPFlag("debug", flags.Lookup("debug"))
	//
	//	flags.String("addr", "localhost:5002", "Address of the service.")
	//	viper.BindPFlag("addr", flags.Lookup("addr"))
	//
	//	flags.String("smtp-addr", "localhost:25", "Address of the SMTP server.")
	//	viper.BindPFlag("smtp-addr", flags.Lookup("smtp-addr"))
	//
	//	flags.String("smtp-user", "", "User for the SMTP server.")
	//	viper.BindPFlag("smtp-user", flags.Lookup("smtp-user"))
	//
	//	flags.String("smtp-password", "", "Password for the SMTP server.")
	//	viper.BindPFlag("smtp-password", flags.Lookup("smtp-password"))
	//
	//	flags.String("email-from", "noreply@abc.com", "The from email address.")
	//	viper.BindPFlag("email-from", flags.Lookup("email-from"))
	//
}

//   easygen test/commandlineCVFull | sed 's|^|\t// |;'

// Test the provided Cobra/Viper command line flag init() function auto generation
func ExampleGenerate_commandLineCobraViperInit() {
	// Equivalent testing on commandline:
	//   easygen test/commandlineCVFull
	fmt.Print(easygen.Generate(false, "test/commandlineCVFull"))
	// Output:
	// func init() {
	//
	//   viper.SetEnvPrefix("DISPATCH")
	//   viper.AutomaticEnv()
	//
	//   /*
	//
	//     When AutomaticEnv called, Viper will check for an environment variable any
	//     time a viper.Get request is made. It will apply the following rules. It
	//     will check for a environment variable with a name matching the key
	//     uppercased and prefixed with the EnvPrefix if set.
	//
	//   */
	//
	//   flags := mainCmd.Flags()
	//
	//   flags.Bool("Debug", false, "Turn on debugging.")
	//   viper.BindPFlag("Debug", flags.Lookup("Debug"))
	//
	//   flags.String("addr", "localhost:5002", "Address of the service.")
	//   viper.BindPFlag("addr", flags.Lookup("addr"))
	//
	//   flags.String("smtp-addr", "localhost:25", "Address of the SMTP server.")
	//   viper.BindPFlag("smtp-addr", flags.Lookup("smtp-addr"))
	//
	//   flags.String("smtp-user", "", "User for the SMTP server.")
	//   viper.BindPFlag("smtp-user", flags.Lookup("smtp-user"))
	//
	//   flags.String("smtp-password", "", "Password for the SMTP server.")
	//   viper.BindPFlag("smtp-password", flags.Lookup("smtp-password"))
	//
	//   flags.String("email-from", "noreply@abc.com", "The from email address.")
	//   viper.BindPFlag("email-from", flags.Lookup("email-from"))
	//
	//   // Viper supports reading from yaml, toml and/or json files. Viper can
	//   // search multiple paths. Paths will be searched in the order they are
	//   // provided. Searches stopped once Config File found.
	//
	//   viper.SetConfigName("CommandLineCV") // name of config file (without extension)
	//
	//   viper.AddConfigPath("/tmp")
	//   viper.AddConfigPath(".")
	//
	//   err := viper.ReadInConfig()
	//   if err != nil {
	//     println("No config file found. Using built-in defaults.")
	//   }
	//
	// }
}

////////////////////////////////////////////////////////////////////////////
// Varible Names

func ExampleVaribleNames() {
}

////////////////////////////////////////////////////////////////////////////
// Strings Test

// Test string comparison in template
func ExampleGenerate0_stringsCmp() {
	// Equivalent testing on commandline:
	//   easygen -ts '{{The {{if ... {{end}}.' test/strings0
	fmt.Print(easygen.Generate0(false, `The {{if eq .StrTest "-AB-axxb- HTML Html html"}}eq says Yea{{else}}eq says Nay{{end}} but {{if eqf .StrTest "-AB-axxb- HTML Html html"}}eqf says Yea{{else}}eqf says Nay{{end}}.`, "test/strings0"))
	// Output:
	// The eq says Nay but eqf says Yea.
}

// Test the string split function in template
func ExampleGenerate0_split0() {
	// Equivalent testing on commandline:
	//   easygen -ts '{{split .Colorlist}}' test/list0
	fmt.Print(easygen.Generate0(false, `{{split .Colorlist}}`, "test/list0"))
	// Output:
	// [red blue white]
}

// Test the string split function in template again
func ExampleGenerate0_split1() {
	// Equivalent testing on commandline:
	//   easygen -ts '{{range ... {{end}}' test/list0
	fmt.Print(easygen.Generate0(false, `{{range (split .Colorlist)}}{{.}} {{end}}`, "test/list0"))
	// Output:
	// red blue white
}

/*

// Ref https://golang.org/pkg/regexp/#Regexp.ReplaceAllString
$ easygen -rf="a(x*)b" -rt='${1}W' -ts="{{.StrTest}}, {{replace .StrTest}}, {{.StrTest | replace}}" test/strings0
-ab-axxb- HTML Html html, -W-xxW- HTML Html html, -W-xxW- HTML Html html

$ easygen -rf="HTML" -rt='XML' -ts="{{.StrTest}}, {{replacec .StrTest}}, {{replace .StrTest}}" test/strings0
-ab-axxb- HTML Html html, -ab-axxb- XML Html html, -ab-axxb- XML XML XML

$ EASYGEN_RF="HTML" EASYGEN_RT='XML' easygen -ts="{{.StrTest}}, {{replacec .StrTest}}, {{replace .StrTest}}" test/strings0
-ab-axxb- HTML Html html, -ab-axxb- XML Html html, -ab-axxb- XML XML XML

*/

/*
func ExampleTestStrings() {
	// panic: runtime error: invalid memory address or nil pointer dereference [recovered]
	easygen.Opts.StrFrom = "a(x*)b"
	easygen.Opts.StrTo = "${1}W"
	//fmt.Print(easygen.Generate0(false, "{{.StrTest}} {{replace .StrTest}} {{.StrTest | replace}}", "test/strings0"))
	easygen.Opts.TemplateStr = `{{.StrTest}} {{replace .StrTest}} {{.StrTest | replace}}`
	fmt.Print(easygen.Generate(false, "test/strings0"))
	// Output:
	// -ab-axxb- HTML Html html -W-xxW- HTML Html html -W-xxW- HTML Html html
}
*/
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"strconv"
	"strings"

	. "github.com/spf13/cast"

	"github.com/yutaro/slack-cmd-go"
)

func main() {
	conf := scmd.LoadToml("config.toml")
	bot := scmd.New(conf.TOKEN)

	// two phrase command
	calc := bot.NewCmdGroup("calc")

	// calc sum 2 3 => The result is : 5
	calc.Cmd("sum", "Add two numbers.",
		func(c *scmd.Context) {
			args := c.GetArgs()
			x := ToInt(args[0])
			y := ToInt(args[1])
			c.SendMessage(fmt.Sprintf("The result is : %d", x+y))
		})

	// calc sub 5 10 => The result is : -5
	calc.Cmd("sub", "Sub two numbers.",
		func(c *scmd.Context) {
			args := c.GetArgs()
			x := ToInt(args[0])
			y := ToInt(args[1])
			c.SendMessage(fmt.Sprintf("The result is : %d", x-y))
		})

	// calc fib 5 => The result is : 1 1 2 3 5
	calc.Cmd("fib", "Show fibonacci numbers.",
		func(c *scmd.Context) {
			args := c.GetArgs()
			x := ToInt(args[0])

			nums := make([]string, x)
			f := fibonacci()
			for i := 0; i < x; i++ {
				nums[i] = strconv.Itoa(f())
			}

			c.SendMessage(fmt.Sprintf("The result is : %s", strings.Join(nums, " ")))
		})

	bot.Start()
}

func fibonacci() func() int {
	fib1 := 0
	fib2 := 1
	return func() int {
		fib := fib1 + fib2
		fib1 = fib2
		fib2 = fib
		return fib1
	}
}
<commit_msg>revert<commit_after>package main

import (
	"fmt"
	"strconv"
	"strings"

	"github.com/yutaro/slack-cmd-go"
)

func main() {
	conf := scmd.LoadToml("config.toml")
	bot := scmd.New(conf.TOKEN)

	// two phrase command
	calc := bot.NewCmdGroup("calc")

	// calc sum 2 3 => The result is : 5
	calc.Cmd("sum", "Add two numbers.",
		func(c *scmd.Context) {
			args := c.GetArgs()
			x, _ := strconv.Atoi(args[0])
			y, _ := strconv.Atoi(args[1])
			c.SendMessage(fmt.Sprintf("The result is : %d", x+y))
		})

	// calc sub 5 10 => The result is : -5
	calc.Cmd("sub", "Sub two numbers.",
		func(c *scmd.Context) {
			args := c.GetArgs()
			x, _ := strconv.Atoi(args[0])
			y, _ := strconv.Atoi(args[1])
			c.SendMessage(fmt.Sprintf("The result is : %d", x-y))
		})

	// calc fib 5 => The result is : 1 1 2 3 5
	calc.Cmd("fib", "Show fibonacci numbers.",
		func(c *scmd.Context) {
			args := c.GetArgs()
			x, _ := strconv.Atoi(args[0])

			nums := make([]string, x)
			f := fibonacci()
			for i := 0; i < x; i++ {
				nums[i] = strconv.Itoa(f())
			}

			c.SendMessage(fmt.Sprintf("The result is : %s", strings.Join(nums, " ")))
		})

	bot.Start()
}

func fibonacci() func() int {
	fib1 := 0
	fib2 := 1
	return func() int {
		fib := fib1 + fib2
		fib1 = fib2
		fib2 = fib
		return fib1
	}
}
<|endoftext|>


<commit_before>package tfexec

import (
	"encoding/json"
)

// AllowMissingConfigOption represents the -allow-missing-config flag.
type AllowMissingConfigOption struct {
	allowMissingConfig bool
}

// AllowMissingConfig represents the -allow-missing-config flag.
func AllowMissingConfig(allowMissingConfig bool) *AllowMissingConfigOption {
	return &AllowMissingConfigOption{allowMissingConfig}
}

// BackendOption represents the -backend flag.
type BackendOption struct {
	backend bool
}

// Backend represents the -backend flag.
func Backend(backend bool) *BackendOption {
	return &BackendOption{backend}
}

// BackendConfigOption represents the -backend-config flag.
type BackendConfigOption struct {
	path string
}

// BackendConfig represents the -backend-config flag.
func BackendConfig(backendConfig string) *BackendConfigOption {
	return &BackendConfigOption{backendConfig}
}

type BackupOutOption struct {
	path string
}

// BackupOutOption represents the -backup-out flag.
func BackupOut(path string) *BackupOutOption {
	return &BackupOutOption{path}
}

// BackupOption represents the -backup flag.
type BackupOption struct {
	path string
}

// Backup represents the -backup flag.
func Backup(path string) *BackupOption {
	return &BackupOption{path}
}

// DisableBackup is a convenience method for Backup("-"), indicating backup state should be disabled.
func DisableBackup() *BackupOption {
	return &BackupOption{"-"}
}

// ConfigOption represents the -config flag.
type ConfigOption struct {
	path string
}

// Config represents the -config flag.
func Config(path string) *ConfigOption {
	return &ConfigOption{path}
}

// CopyStateOption represents the -state flag for terraform workspace new. This flag is used
// to copy an existing state file in to the new workspace.
type CopyStateOption struct {
	path string
}

// CopyState represents the -state flag for terraform workspace new. This flag is used
// to copy an existing state file in to the new workspace.
func CopyState(path string) *CopyStateOption {
	return &CopyStateOption{path}
}

type DirOption struct {
	path string
}

func Dir(path string) *DirOption {
	return &DirOption{path}
}

type DirOrPlanOption struct {
	path string
}

func DirOrPlan(path string) *DirOrPlanOption {
	return &DirOrPlanOption{path}
}

// DestroyFlagOption represents the -destroy flag.
type DestroyFlagOption struct {
	// named to prevent conflict with DestroyOption interface

	destroy bool
}

// Destroy represents the -destroy flag.
func Destroy(destroy bool) *DestroyFlagOption {
	return &DestroyFlagOption{destroy}
}

type DryRunOption struct {
	dryRun bool
}

// DryRun represents the -dry-run flag.
func DryRun(dryRun bool) *DryRunOption {
	return &DryRunOption{dryRun}
}

type ForceOption struct {
	force bool
}

func Force(force bool) *ForceOption {
	return &ForceOption{force}
}

type ForceCopyOption struct {
	forceCopy bool
}

func ForceCopy(forceCopy bool) *ForceCopyOption {
	return &ForceCopyOption{forceCopy}
}

type FromModuleOption struct {
	source string
}

func FromModule(source string) *FromModuleOption {
	return &FromModuleOption{source}
}

type GetOption struct {
	get bool
}

func Get(get bool) *GetOption {
	return &GetOption{get}
}

type GetPluginsOption struct {
	getPlugins bool
}

func GetPlugins(getPlugins bool) *GetPluginsOption {
	return &GetPluginsOption{getPlugins}
}

// LockOption represents the -lock flag.
type LockOption struct {
	lock bool
}

// Lock represents the -lock flag.
func Lock(lock bool) *LockOption {
	return &LockOption{lock}
}

// LockTimeoutOption represents the -lock-timeout flag.
type LockTimeoutOption struct {
	timeout string
}

// LockTimeout represents the -lock-timeout flag.
func LockTimeout(lockTimeout string) *LockTimeoutOption {
	// TODO: should this just use a duration instead?
	return &LockTimeoutOption{lockTimeout}
}

type OutOption struct {
	path string
}

func Out(path string) *OutOption {
	return &OutOption{path}
}

type ParallelismOption struct {
	parallelism int
}

func Parallelism(n int) *ParallelismOption {
	return &ParallelismOption{n}
}

type PluginDirOption struct {
	pluginDir string
}

func PluginDir(pluginDir string) *PluginDirOption {
	return &PluginDirOption{pluginDir}
}

type ReattachInfo map[string]ReattachConfig

// ReattachConfig holds the information Terraform needs to be able to attach
// itself to a provider process, so it can drive the process.
type ReattachConfig struct {
	Protocol string
	Pid      int
	Test     bool
	Addr     ReattachConfigAddr
}

// ReattachConfigAddr is a JSON-encoding friendly version of net.Addr.
type ReattachConfigAddr struct {
	Network string
	String  string
}

type ReattachOption struct {
	info ReattachInfo
}

func (info ReattachInfo) marshalString() (string, error) {
	reattachStr, err := json.Marshal(info)
	if err != nil {
		return "", err
	}
	return string(reattachStr), nil
}

func Reattach(info ReattachInfo) *ReattachOption {
	return &ReattachOption{info}
}

type ReconfigureOption struct {
	reconfigure bool
}

func Reconfigure(reconfigure bool) *ReconfigureOption {
	return &ReconfigureOption{reconfigure}
}

type RecursiveOption struct {
	recursive bool
}

func Recursive(r bool) *RecursiveOption {
	return &RecursiveOption{r}
}

type RefreshOption struct {
	refresh bool
}

func Refresh(refresh bool) *RefreshOption {
	return &RefreshOption{refresh}
}

type StateOption struct {
	path string
}

// State represents the -state flag.
//
// Deprecated: The -state CLI flag is a legacy flag and should not be used.
// If you need a different state file for every run, you can instead use the
// local backend.
// See https://github.com/hashicorp/terraform/issues/25920#issuecomment-676560799
func State(path string) *StateOption {
	return &StateOption{path}
}

type StateOutOption struct {
	path string
}

func StateOut(path string) *StateOutOption {
	return &StateOutOption{path}
}

type TargetOption struct {
	target string
}

func Target(resource string) *TargetOption {
	return &TargetOption{resource}
}

type UpgradeOption struct {
	upgrade bool
}

func Upgrade(upgrade bool) *UpgradeOption {
	return &UpgradeOption{upgrade}
}

type VarOption struct {
	assignment string
}

func Var(assignment string) *VarOption {
	return &VarOption{assignment}
}

type VarFileOption struct {
	path string
}

func VarFile(path string) *VarFileOption {
	return &VarFileOption{path}
}

type VerifyPluginsOption struct {
	verifyPlugins bool
}

func VerifyPlugins(verifyPlugins bool) *VerifyPluginsOption {
	return &VerifyPluginsOption{verifyPlugins}
}
<commit_msg>add ProtocolVersion to ReattachConfig<commit_after>package tfexec

import (
	"encoding/json"
)

// AllowMissingConfigOption represents the -allow-missing-config flag.
type AllowMissingConfigOption struct {
	allowMissingConfig bool
}

// AllowMissingConfig represents the -allow-missing-config flag.
func AllowMissingConfig(allowMissingConfig bool) *AllowMissingConfigOption {
	return &AllowMissingConfigOption{allowMissingConfig}
}

// BackendOption represents the -backend flag.
type BackendOption struct {
	backend bool
}

// Backend represents the -backend flag.
func Backend(backend bool) *BackendOption {
	return &BackendOption{backend}
}

// BackendConfigOption represents the -backend-config flag.
type BackendConfigOption struct {
	path string
}

// BackendConfig represents the -backend-config flag.
func BackendConfig(backendConfig string) *BackendConfigOption {
	return &BackendConfigOption{backendConfig}
}

type BackupOutOption struct {
	path string
}

// BackupOutOption represents the -backup-out flag.
func BackupOut(path string) *BackupOutOption {
	return &BackupOutOption{path}
}

// BackupOption represents the -backup flag.
type BackupOption struct {
	path string
}

// Backup represents the -backup flag.
func Backup(path string) *BackupOption {
	return &BackupOption{path}
}

// DisableBackup is a convenience method for Backup("-"), indicating backup state should be disabled.
func DisableBackup() *BackupOption {
	return &BackupOption{"-"}
}

// ConfigOption represents the -config flag.
type ConfigOption struct {
	path string
}

// Config represents the -config flag.
func Config(path string) *ConfigOption {
	return &ConfigOption{path}
}

// CopyStateOption represents the -state flag for terraform workspace new. This flag is used
// to copy an existing state file in to the new workspace.
type CopyStateOption struct {
	path string
}

// CopyState represents the -state flag for terraform workspace new. This flag is used
// to copy an existing state file in to the new workspace.
func CopyState(path string) *CopyStateOption {
	return &CopyStateOption{path}
}

type DirOption struct {
	path string
}

func Dir(path string) *DirOption {
	return &DirOption{path}
}

type DirOrPlanOption struct {
	path string
}

func DirOrPlan(path string) *DirOrPlanOption {
	return &DirOrPlanOption{path}
}

// DestroyFlagOption represents the -destroy flag.
type DestroyFlagOption struct {
	// named to prevent conflict with DestroyOption interface

	destroy bool
}

// Destroy represents the -destroy flag.
func Destroy(destroy bool) *DestroyFlagOption {
	return &DestroyFlagOption{destroy}
}

type DryRunOption struct {
	dryRun bool
}

// DryRun represents the -dry-run flag.
func DryRun(dryRun bool) *DryRunOption {
	return &DryRunOption{dryRun}
}

type ForceOption struct {
	force bool
}

func Force(force bool) *ForceOption {
	return &ForceOption{force}
}

type ForceCopyOption struct {
	forceCopy bool
}

func ForceCopy(forceCopy bool) *ForceCopyOption {
	return &ForceCopyOption{forceCopy}
}

type FromModuleOption struct {
	source string
}

func FromModule(source string) *FromModuleOption {
	return &FromModuleOption{source}
}

type GetOption struct {
	get bool
}

func Get(get bool) *GetOption {
	return &GetOption{get}
}

type GetPluginsOption struct {
	getPlugins bool
}

func GetPlugins(getPlugins bool) *GetPluginsOption {
	return &GetPluginsOption{getPlugins}
}

// LockOption represents the -lock flag.
type LockOption struct {
	lock bool
}

// Lock represents the -lock flag.
func Lock(lock bool) *LockOption {
	return &LockOption{lock}
}

// LockTimeoutOption represents the -lock-timeout flag.
type LockTimeoutOption struct {
	timeout string
}

// LockTimeout represents the -lock-timeout flag.
func LockTimeout(lockTimeout string) *LockTimeoutOption {
	// TODO: should this just use a duration instead?
	return &LockTimeoutOption{lockTimeout}
}

type OutOption struct {
	path string
}

func Out(path string) *OutOption {
	return &OutOption{path}
}

type ParallelismOption struct {
	parallelism int
}

func Parallelism(n int) *ParallelismOption {
	return &ParallelismOption{n}
}

type PluginDirOption struct {
	pluginDir string
}

func PluginDir(pluginDir string) *PluginDirOption {
	return &PluginDirOption{pluginDir}
}

type ReattachInfo map[string]ReattachConfig

// ReattachConfig holds the information Terraform needs to be able to attach
// itself to a provider process, so it can drive the process.
type ReattachConfig struct {
	Protocol        string
	ProtocolVersion int
	Pid             int
	Test            bool
	Addr            ReattachConfigAddr
}

// ReattachConfigAddr is a JSON-encoding friendly version of net.Addr.
type ReattachConfigAddr struct {
	Network string
	String  string
}

type ReattachOption struct {
	info ReattachInfo
}

func (info ReattachInfo) marshalString() (string, error) {
	reattachStr, err := json.Marshal(info)
	if err != nil {
		return "", err
	}
	return string(reattachStr), nil
}

func Reattach(info ReattachInfo) *ReattachOption {
	return &ReattachOption{info}
}

type ReconfigureOption struct {
	reconfigure bool
}

func Reconfigure(reconfigure bool) *ReconfigureOption {
	return &ReconfigureOption{reconfigure}
}

type RecursiveOption struct {
	recursive bool
}

func Recursive(r bool) *RecursiveOption {
	return &RecursiveOption{r}
}

type RefreshOption struct {
	refresh bool
}

func Refresh(refresh bool) *RefreshOption {
	return &RefreshOption{refresh}
}

type StateOption struct {
	path string
}

// State represents the -state flag.
//
// Deprecated: The -state CLI flag is a legacy flag and should not be used.
// If you need a different state file for every run, you can instead use the
// local backend.
// See https://github.com/hashicorp/terraform/issues/25920#issuecomment-676560799
func State(path string) *StateOption {
	return &StateOption{path}
}

type StateOutOption struct {
	path string
}

func StateOut(path string) *StateOutOption {
	return &StateOutOption{path}
}

type TargetOption struct {
	target string
}

func Target(resource string) *TargetOption {
	return &TargetOption{resource}
}

type UpgradeOption struct {
	upgrade bool
}

func Upgrade(upgrade bool) *UpgradeOption {
	return &UpgradeOption{upgrade}
}

type VarOption struct {
	assignment string
}

func Var(assignment string) *VarOption {
	return &VarOption{assignment}
}

type VarFileOption struct {
	path string
}

func VarFile(path string) *VarFileOption {
	return &VarFileOption{path}
}

type VerifyPluginsOption struct {
	verifyPlugins bool
}

func VerifyPlugins(verifyPlugins bool) *VerifyPluginsOption {
	return &VerifyPluginsOption{verifyPlugins}
}
<|endoftext|>


<commit_before>package mongocaputils

import (
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"sync"
	"time"

	"container/heap"

	"code.google.com/p/gopacket"
	"code.google.com/p/gopacket/tcpassembly"

	"github.com/tmc/mongocaputils/mongoproto"
	"github.com/tmc/mongocaputils/tcpreaderwrapper"
)

// TODO(tmc): reorder ops according to frame timings

type mongoOpStream struct {
	Ops chan mongoproto.Op

	firstSeen    time.Time
	opsWithTimes chan OpWithTime
	opHeap       *orderedOps

	started bool
	mu      sync.Mutex // for debugging
}

func NewMongoOpStream(heapBufSize int) *mongoOpStream {
	h := make(orderedOps, 0, heapBufSize)
	s := &mongoOpStream{
		Ops:          make(chan mongoproto.Op),
		opsWithTimes: make(chan OpWithTime),
		opHeap:       &h,
	}
	heap.Init(s.opHeap)
	go s.handleOps()
	return s
}

func (s *mongoOpStream) New(a, b gopacket.Flow) tcpassembly.Stream {
	r := tcpreaderwrapper.NewReaderStreamWrapper()
	if !s.started {
		s.started = true
	}
	log.Println("starting stream", a, b)
	go s.handleStream(&r)
	return &r
}

func (s *mongoOpStream) Close() error {
	s.opsWithTimes = nil
	return nil
}

func (s *mongoOpStream) SetFirstSeen(t time.Time) {
	s.firstSeen = t
}

func (s *mongoOpStream) handleOps() {
	defer close(s.Ops)
	for op := range s.opsWithTimes {
		heap.Push(s.opHeap, op)
		if len(*s.opHeap) >= cap(*s.opHeap) {
			op := heap.Pop(s.opHeap).(OpWithTime)
			fmt.Printf("%f %v\n\n", float64(op.Seen.Sub(s.firstSeen))/10e8, op.Op)
			s.Ops <- op.Op
			//s.Ops <- s.opHeap.Pop().(OpWithTime).Op
		}
	}
	for len(*s.opHeap) > 0 {
		op := heap.Pop(s.opHeap).(OpWithTime)
		s.Ops <- op.Op
		fmt.Printf("%f %v \n\n", float64(op.Seen.Sub(s.firstSeen))/10e8, op.Op)
		//s.Ops <- s.opHeap.Pop().(OpWithTime).Op
	}
}

func (s *mongoOpStream) readOp(r io.Reader) (mongoproto.Op, error) {
	return mongoproto.OpFromReader(r)
}

func (s *mongoOpStream) handleStream(r *tcpreaderwrapper.ReaderStreamWrapper) {
	for {
		op, err := s.readOp(r)
		if err == io.EOF {
			log.Println("stopping")
			discarded, err := ioutil.ReadAll(r)
			fmt.Println("discarded ", len(discarded), err)
			return
		}
		if err != nil {
			log.Println("Error parsing op:", err)
			return
		}
		seen := r.Reassemblies[0].Seen
		s.opsWithTimes <- OpWithTime{op, seen}
		//r.Reassemblies = r.Reassemblies[:0]
	}
}
<commit_msg>Use first reassembly with content as start time.<commit_after>package mongocaputils

import (
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"sync"
	"time"

	"container/heap"

	"code.google.com/p/gopacket"
	"code.google.com/p/gopacket/tcpassembly"

	"github.com/tmc/mongocaputils/mongoproto"
	"github.com/tmc/mongocaputils/tcpreaderwrapper"
)

// TODO(tmc): reorder ops according to frame timings

type mongoOpStream struct {
	Ops chan mongoproto.Op

	firstSeen    time.Time
	opsWithTimes chan OpWithTime
	opHeap       *orderedOps

	started bool
	mu      sync.Mutex // for debugging
}

func NewMongoOpStream(heapBufSize int) *mongoOpStream {
	h := make(orderedOps, 0, heapBufSize)
	s := &mongoOpStream{
		Ops:          make(chan mongoproto.Op),
		opsWithTimes: make(chan OpWithTime),
		opHeap:       &h,
	}
	heap.Init(s.opHeap)
	go s.handleOps()
	return s
}

func (s *mongoOpStream) New(a, b gopacket.Flow) tcpassembly.Stream {
	r := tcpreaderwrapper.NewReaderStreamWrapper()
	if !s.started {
		s.started = true
	}
	log.Println("starting stream", a, b)
	go s.handleStream(&r)
	return &r
}

func (s *mongoOpStream) Close() error {
	close(s.opsWithTimes)
	s.opsWithTimes = nil
	return nil
}

func (s *mongoOpStream) SetFirstSeen(t time.Time) {
	s.firstSeen = t
}

func (s *mongoOpStream) handleOps() {
	defer close(s.Ops)
	for op := range s.opsWithTimes {
		heap.Push(s.opHeap, op)
		if len(*s.opHeap) >= cap(*s.opHeap) {
			op := heap.Pop(s.opHeap).(OpWithTime)
			fmt.Printf("%f %v\n", float64(op.Seen.Sub(s.firstSeen))/10e8, op.Op)
			s.Ops <- op.Op
			//s.Ops <- s.opHeap.Pop().(OpWithTime).Op
		}
	}
	for len(*s.opHeap) > 0 {
		op := heap.Pop(s.opHeap).(OpWithTime)
		fmt.Printf("%f %v \n", float64(op.Seen.Sub(s.firstSeen))/10e8, op.Op)
		s.Ops <- op.Op
		//s.Ops <- s.opHeap.Pop().(OpWithTime).Op
	}
}

func (s *mongoOpStream) readOp(r io.Reader) (mongoproto.Op, error) {
	return mongoproto.OpFromReader(r)
}

func (s *mongoOpStream) handleStream(r *tcpreaderwrapper.ReaderStreamWrapper) {
	for {
		op, err := s.readOp(r)
		if err == io.EOF {
			log.Println("stopping")
			discarded, err := ioutil.ReadAll(r)
			fmt.Println("discarded ", len(discarded), err)
			return
		}
		if err != nil {
			log.Println("error parsing op:", err)
			return
		}
		seen := time.Now()
		for _, r := range r.Reassemblies {
			if r.NumBytes > 0 {
				seen = r.Seen
			}
		}
		s.opsWithTimes <- OpWithTime{op, seen}
		r.Reassemblies = r.Reassemblies[:0]
	}
}
<|endoftext|>