<commit_before>/*
   Copyright The containerd Authors.

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

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

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

package task

import (
	"context"
	"sync"
	"sync/atomic"
	"time"

	"golang.org/x/sync/semaphore"
)

// NewBackgroundTaskManager provides a task manager. You can specify the
// concurrency of background tasks. When running a background task, this will be
// forced to wait until no prioritized task is running for some period. You can
// specify the period through the argument of this function, too.
func NewBackgroundTaskManager(concurrency int64, period time.Duration) *BackgroundTaskManager {
	return &BackgroundTaskManager{
		backgroundSem:                semaphore.NewWeighted(concurrency),
		prioritizedTaskSilencePeriod: period,
		prioritizedTaskStartNotify:   make(chan struct{}),
		prioritizedTaskDoneCond:      sync.NewCond(&sync.Mutex{}),
	}
}

// BackgroundTaskManager is a task manager which manages prioritized tasks and
// background tasks execution. Background tasks are less important than
// prioritized tasks. You can let these background tasks not to use compute
// resources (CPU, NW, etc...) during more important tasks(=prioritized tasks)
// running.
//
// When you run a prioritised task and don't want background tasks to use
// resources you can tell it this manager by calling DoPrioritizedTask method.
// DonePrioritizedTask method must be called at the end of the prioritised task
// execution.
//
// For running a background task, you can use InvokeBackgroundTask method. The
// background task must be able to be cancelled via context.Context argument.
// The task is forced to wait until no prioritized task is running for some
// period. You can specify the period when making this manager instance. The
// limited number of background tasks run simultaneously and you can specify the
// concurrency when making this manager instance too. If a prioritized task
// starts during the execution of background tasks, all background tasks running
// will be cancelled via context. These cancelled tasks will be executed again
// later, same as other background tasks (when no prioritized task is running
// for some period).
type BackgroundTaskManager struct {
	prioritizedTasks             int64
	backgroundSem                *semaphore.Weighted
	prioritizedTaskSilencePeriod time.Duration
	prioritizedTaskStartNotify   chan struct{}
	prioritizedTaskStartNotifyMu sync.Mutex
	prioritizedTaskDoneCond      *sync.Cond
}

// DoPrioritizedTask tells the manager that we are running a prioritized task
// and don't want background tasks to disturb resources(CPU, NW, etc...)
func (ts *BackgroundTaskManager) DoPrioritizedTask() {
	// Notify the prioritized task execution to background tasks.
	ts.prioritizedTaskStartNotifyMu.Lock()
	atomic.AddInt64(&ts.prioritizedTasks, 1)
	close(ts.prioritizedTaskStartNotify)
	ts.prioritizedTaskStartNotify = make(chan struct{})
	ts.prioritizedTaskStartNotifyMu.Unlock()
}

// DonePrioritizedTask tells the manager that we've done a prioritized task
// and don't want background tasks to disturb resources(CPU, NW, etc...)
func (ts *BackgroundTaskManager) DonePrioritizedTask() {
	go func() {
		// Notify the task completion after `ts.prioritizedTaskSilencePeriod`
		// so that background tasks aren't invoked immediately.
		time.Sleep(ts.prioritizedTaskSilencePeriod)
		atomic.AddInt64(&ts.prioritizedTasks, -1)
		ts.prioritizedTaskDoneCond.Broadcast()
	}()
}

// InvokeBackgroundTask invokes a background task. The task is started only when
// no prioritized tasks are running. Prioritized task's execution stops the
// execution of all background tasks. Background task must be able to be
// cancelled via context.Context argument and be able to be restarted again.
func (ts *BackgroundTaskManager) InvokeBackgroundTask(do func(context.Context), timeout time.Duration) {
	for {
		// Wait until all prioritized tasks are done
		for {
			if atomic.LoadInt64(&ts.prioritizedTasks) <= 0 {
				break
			}

			// waits until a prioritized task is done
			ts.prioritizedTaskDoneCond.L.Lock()
			if atomic.LoadInt64(&ts.prioritizedTasks) > 0 {
				ts.prioritizedTaskDoneCond.Wait()
			}
			ts.prioritizedTaskDoneCond.L.Unlock()
		}

		// limited number of background tasks can run at once.
		// if prioritized tasks are running, cancel this task.
		if func() bool {
			ts.backgroundSem.Acquire(context.Background(), 1)
			defer ts.backgroundSem.Release(1)

			// Get notify the prioritized tasks execution.
			ts.prioritizedTaskStartNotifyMu.Lock()
			ch := ts.prioritizedTaskStartNotify
			tasks := atomic.LoadInt64(&ts.prioritizedTasks)
			ts.prioritizedTaskStartNotifyMu.Unlock()
			if tasks > 0 {
				return false
			}

			// Invoke the background task. if some prioritized tasks added during
			// execution, cancel it and try it later.
			var (
				done        = make(chan struct{})
				ctx, cancel = context.WithTimeout(context.Background(), timeout)
			)
			defer cancel()
			go func() {
				do(ctx)
				close(done)
			}()

			// Wait until the background task is done or canceled.
			select {
			case <-ch: // some prioritized tasks started; retry it later
				cancel()
				return false
			case <-done: // All tasks completed
			}
			return true
		}() {
			break
		}
	}
}
<commit_msg>Fixed a potential bug related to conditional variables and lost wakeup.<commit_after>/*
   Copyright The containerd Authors.

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

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

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

package task

import (
	"context"
	"sync"
	"sync/atomic"
	"time"

	"golang.org/x/sync/semaphore"
)

// NewBackgroundTaskManager provides a task manager. You can specify the
// concurrency of background tasks. When running a background task, this will be
// forced to wait until no prioritized task is running for some period. You can
// specify the period through the argument of this function, too.
func NewBackgroundTaskManager(concurrency int64, period time.Duration) *BackgroundTaskManager {
	return &BackgroundTaskManager{
		backgroundSem:                semaphore.NewWeighted(concurrency),
		prioritizedTaskSilencePeriod: period,
		prioritizedTaskStartNotify:   make(chan struct{}),
		prioritizedTaskDoneCond:      sync.NewCond(&sync.Mutex{}),
	}
}

// BackgroundTaskManager is a task manager which manages prioritized tasks and
// background tasks execution. Background tasks are less important than
// prioritized tasks. You can let these background tasks not to use compute
// resources (CPU, NW, etc...) during more important tasks(=prioritized tasks)
// running.
//
// When you run a prioritised task and don't want background tasks to use
// resources you can tell it this manager by calling DoPrioritizedTask method.
// DonePrioritizedTask method must be called at the end of the prioritised task
// execution.
//
// For running a background task, you can use InvokeBackgroundTask method. The
// background task must be able to be cancelled via context.Context argument.
// The task is forced to wait until no prioritized task is running for some
// period. You can specify the period when making this manager instance. The
// limited number of background tasks run simultaneously and you can specify the
// concurrency when making this manager instance too. If a prioritized task
// starts during the execution of background tasks, all background tasks running
// will be cancelled via context. These cancelled tasks will be executed again
// later, same as other background tasks (when no prioritized task is running
// for some period).
type BackgroundTaskManager struct {
	prioritizedTasks             int64
	backgroundSem                *semaphore.Weighted
	prioritizedTaskSilencePeriod time.Duration
	prioritizedTaskStartNotify   chan struct{}
	prioritizedTaskStartNotifyMu sync.Mutex
	prioritizedTaskDoneCond      *sync.Cond
}

// DoPrioritizedTask tells the manager that we are running a prioritized task
// and don't want background tasks to disturb resources(CPU, NW, etc...)
func (ts *BackgroundTaskManager) DoPrioritizedTask() {
	// Notify the prioritized task execution to background tasks.
	ts.prioritizedTaskStartNotifyMu.Lock()
	atomic.AddInt64(&ts.prioritizedTasks, 1)
	close(ts.prioritizedTaskStartNotify)
	ts.prioritizedTaskStartNotify = make(chan struct{})
	ts.prioritizedTaskStartNotifyMu.Unlock()
}

// DonePrioritizedTask tells the manager that we've done a prioritized task
// and don't want background tasks to disturb resources(CPU, NW, etc...)
func (ts *BackgroundTaskManager) DonePrioritizedTask() {
	go func() {
		// Notify the task completion after `ts.prioritizedTaskSilencePeriod`
		// so that background tasks aren't invoked immediately.
		time.Sleep(ts.prioritizedTaskSilencePeriod)
		atomic.AddInt64(&ts.prioritizedTasks, -1)
		ts.prioritizedTaskDoneCond.L.Lock()
		ts.prioritizedTaskDoneCond.Broadcast()
		ts.prioritizedTaskDoneCond.L.Unlock()
	}()
}

// InvokeBackgroundTask invokes a background task. The task is started only when
// no prioritized tasks are running. Prioritized task's execution stops the
// execution of all background tasks. Background task must be able to be
// cancelled via context.Context argument and be able to be restarted again.
func (ts *BackgroundTaskManager) InvokeBackgroundTask(do func(context.Context), timeout time.Duration) {
	for {
		// Wait until all prioritized tasks are done
		for {
			if atomic.LoadInt64(&ts.prioritizedTasks) <= 0 {
				break
			}

			// waits until a prioritized task is done
			ts.prioritizedTaskDoneCond.L.Lock()
			if atomic.LoadInt64(&ts.prioritizedTasks) > 0 {
				ts.prioritizedTaskDoneCond.Wait()
			}
			ts.prioritizedTaskDoneCond.L.Unlock()
		}

		// limited number of background tasks can run at once.
		// if prioritized tasks are running, cancel this task.
		if func() bool {
			ts.backgroundSem.Acquire(context.Background(), 1)
			defer ts.backgroundSem.Release(1)

			// Get notify the prioritized tasks execution.
			ts.prioritizedTaskStartNotifyMu.Lock()
			ch := ts.prioritizedTaskStartNotify
			tasks := atomic.LoadInt64(&ts.prioritizedTasks)
			ts.prioritizedTaskStartNotifyMu.Unlock()
			if tasks > 0 {
				return false
			}

			// Invoke the background task. if some prioritized tasks added during
			// execution, cancel it and try it later.
			var (
				done        = make(chan struct{})
				ctx, cancel = context.WithTimeout(context.Background(), timeout)
			)
			defer cancel()
			go func() {
				do(ctx)
				close(done)
			}()

			// Wait until the background task is done or canceled.
			select {
			case <-ch: // some prioritized tasks started; retry it later
				cancel()
				return false
			case <-done: // All tasks completed
			}
			return true
		}() {
			break
		}
	}
}
<|endoftext|>


<commit_before>package inigo_test

import (
	"fmt"
	"strings"
	"time"

	"github.com/cloudfoundry-incubator/inigo/helpers"
	"github.com/cloudfoundry-incubator/inigo/inigo_server"
	"github.com/cloudfoundry-incubator/runtime-schema/models"
	"github.com/cloudfoundry-incubator/runtime-schema/models/factories"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/grouper"
)

var _ = Describe("Task", func() {
	var executor ifrit.Process

	AfterEach(func() {
		helpers.StopProcess(executor)
	})

	Context("when an exec and rep are running", func() {
		BeforeEach(func() {
			executor = grouper.EnvokeGroup(grouper.RunGroup{
				"exec": componentMaker.Executor("-memoryMB", "1024"),
				"rep":  componentMaker.Rep(),
			})
		})

		Context("and a Task is desired", func() {
			var task models.Task
			var thingWeRan string

			BeforeEach(func() {
				thingWeRan = "fake-" + factories.GenerateGuid()

				task = factories.BuildTaskWithRunAction(
					"inigo",
					componentMaker.Stack,
					512,
					512,
					"bash",
					[]string{
						"-c",
						// sleep a bit so that we can make assertions around behavior as it's
						// running
						fmt.Sprintf("curl %s; sleep 10", strings.Join(inigo_server.CurlArgs(thingWeRan), " ")),
					},
				)

				err := bbs.DesireTask(task)
				Ω(err).ShouldNot(HaveOccurred())
			})

			It("eventually runs the Task", func() {
				Eventually(inigo_server.ReportingGuids, LONG_TIMEOUT).Should(ContainElement(thingWeRan))
			})

			Context("when a converger is running", func() {
				var converger ifrit.Process

				BeforeEach(func() {
					converger = ifrit.Envoke(componentMaker.Converger(
						"-convergeRepeatInterval", "1s",

						// 1s would be ideal, but this also limits container creation time
						"-kickPendingTaskDuration", "10s",
					))
				})

				AfterEach(func() {
					helpers.StopProcess(converger)
				})

				Context("after the task starts", func() {
					BeforeEach(func() {
						Eventually(inigo_server.ReportingGuids, LONG_TIMEOUT).Should(ContainElement(thingWeRan))
					})

					Context("when the executor disappears", func() {
						BeforeEach(func() {
							helpers.StopProcess(executor)
						})

						It("eventually marks the task as failed", func() {
							// time is primarily influenced by rep's heartbeat interval
							Eventually(bbs.GetAllCompletedTasks, 10*time.Second).Should(HaveLen(1))

							tasks, err := bbs.GetAllCompletedTasks()
							Ω(err).ShouldNot(HaveOccurred())

							completedTask := tasks[0]
							Ω(completedTask.Guid).Should(Equal(task.Guid))
							Ω(completedTask.Failed).To(BeTrue())
						})
					})

					Context("and another task is desired, but cannot fit", func() {
						var secondTask models.Task
						var secondThingWeRan string

						BeforeEach(func() {
							secondThingWeRan = "fake-" + factories.GenerateGuid()

							secondTask = factories.BuildTaskWithRunAction(
								"inigo",
								componentMaker.Stack,
								768, // 768 + 512 is more than 1024, as we configured, so this won't fit
								512,
								"bash",
								[]string{"-c", fmt.Sprintf("curl %s && sleep 2", strings.Join(inigo_server.CurlArgs(secondThingWeRan), " "))},
							)

							err := bbs.DesireTask(secondTask)
							Ω(err).ShouldNot(HaveOccurred())
						})

						It("is executed once the first task completes, as its resources are cleared", func() {
							Eventually(bbs.GetAllCompletedTasks).Should(HaveLen(1)) // Wait for first task to complete
							Eventually(inigo_server.ReportingGuids).Should(ContainElement(secondThingWeRan))
						})
					})
				})
			})
		})
	})

	Context("when only a converger is running", func() {
		var converger ifrit.Process

		BeforeEach(func() {
			converger = ifrit.Envoke(componentMaker.Converger(
				"-convergeRepeatInterval", "1s",

				// 1s would be ideal, but this also limits container creation time
				"-kickPendingTaskDuration", "10s",
			))
		})

		AfterEach(func() {
			helpers.StopProcess(converger)
		})

		Context("and a task is desired", func() {
			var thingWeRan string

			BeforeEach(func() {
				thingWeRan = "fake-" + factories.GenerateGuid()

				task := factories.BuildTaskWithRunAction(
					"inigo",
					componentMaker.Stack,
					512,
					512,
					"bash",
					[]string{"-c", fmt.Sprintf("curl %s && sleep 2", strings.Join(inigo_server.CurlArgs(thingWeRan), " "))},
				)

				err := bbs.DesireTask(task)
				Ω(err).ShouldNot(HaveOccurred())
			})

			Context("and then an exec and rep come up", func() {
				BeforeEach(func() {
					executor = grouper.EnvokeGroup(grouper.RunGroup{
						"exec": componentMaker.Executor(),
						"rep":  componentMaker.Rep(),
					})
				})

				It("eventually runs the Task", func() {
					Eventually(inigo_server.ReportingGuids, LONG_TIMEOUT).Should(ContainElement(thingWeRan))
				})
			})
		})
	})

	Context("when a very impatient converger is running", func() {
		var converger ifrit.Process

		BeforeEach(func() {
			converger = ifrit.Envoke(componentMaker.Converger(
				"-convergeRepeatInterval", "1s",
				"-expireClaimedTaskDuration", "1s",
			))
		})

		AfterEach(func() {
			helpers.StopProcess(converger)
		})

		Context("and a task is desired", func() {
			var guid string

			BeforeEach(func() {
				guid = "fake-" + factories.GenerateGuid()

				task := factories.BuildTaskWithRunAction(
					"inigo",
					componentMaker.Stack,
					100,
					100,
					"curl",
					inigo_server.CurlArgs(guid),
				)

				err := bbs.DesireTask(task)
				Ω(err).ShouldNot(HaveOccurred())
			})

			It("should be marked as failed after the expire duration", func() {
				Eventually(bbs.GetAllCompletedTasks).Should(HaveLen(1))

				tasks, err := bbs.GetAllCompletedTasks()
				Ω(err).ShouldNot(HaveOccurred())
				Ω(tasks[0].Failed).Should(BeTrue(), "Task should have failed")
				Ω(tasks[0].FailureReason).Should(ContainSubstring("not claimed within time limit"))

				Ω(inigo_server.ReportingGuids()).Should(BeEmpty())
			})
		})
	})
})
<commit_msg>fix timeout to account for longer interval<commit_after>package inigo_test

import (
	"fmt"
	"strings"
	"time"

	"github.com/cloudfoundry-incubator/inigo/helpers"
	"github.com/cloudfoundry-incubator/inigo/inigo_server"
	"github.com/cloudfoundry-incubator/runtime-schema/models"
	"github.com/cloudfoundry-incubator/runtime-schema/models/factories"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/grouper"
)

var _ = Describe("Task", func() {
	var executor ifrit.Process

	AfterEach(func() {
		helpers.StopProcess(executor)
	})

	kickPendingDuration := 10 * time.Second

	Context("when an exec and rep are running", func() {
		BeforeEach(func() {
			executor = grouper.EnvokeGroup(grouper.RunGroup{
				"exec": componentMaker.Executor("-memoryMB", "1024"),
				"rep":  componentMaker.Rep(),
			})
		})

		Context("and a Task is desired", func() {
			var task models.Task
			var thingWeRan string

			BeforeEach(func() {
				thingWeRan = "fake-" + factories.GenerateGuid()

				task = factories.BuildTaskWithRunAction(
					"inigo",
					componentMaker.Stack,
					512,
					512,
					"bash",
					[]string{
						"-c",
						// sleep a bit so that we can make assertions around behavior as it's
						// running
						fmt.Sprintf("curl %s; sleep 10", strings.Join(inigo_server.CurlArgs(thingWeRan), " ")),
					},
				)

				err := bbs.DesireTask(task)
				Ω(err).ShouldNot(HaveOccurred())
			})

			It("eventually runs the Task", func() {
				Eventually(inigo_server.ReportingGuids, LONG_TIMEOUT).Should(ContainElement(thingWeRan))
			})

			Context("when a converger is running", func() {
				var converger ifrit.Process

				BeforeEach(func() {
					converger = ifrit.Envoke(componentMaker.Converger(
						"-convergeRepeatInterval", "1s",

						// 1s would be ideal, but this also limits container creation time
						"-kickPendingTaskDuration", kickPendingDuration.String(),
					))
				})

				AfterEach(func() {
					helpers.StopProcess(converger)
				})

				Context("after the task starts", func() {
					BeforeEach(func() {
						Eventually(inigo_server.ReportingGuids, LONG_TIMEOUT).Should(ContainElement(thingWeRan))
					})

					Context("when the executor disappears", func() {
						BeforeEach(func() {
							helpers.StopProcess(executor)
						})

						It("eventually marks the task as failed", func() {
							// time is primarily influenced by rep's heartbeat interval
							Eventually(bbs.GetAllCompletedTasks, 10*time.Second).Should(HaveLen(1))

							tasks, err := bbs.GetAllCompletedTasks()
							Ω(err).ShouldNot(HaveOccurred())

							completedTask := tasks[0]
							Ω(completedTask.Guid).Should(Equal(task.Guid))
							Ω(completedTask.Failed).To(BeTrue())
						})
					})

					Context("and another task is desired, but cannot fit", func() {
						var secondTask models.Task
						var secondThingWeRan string

						BeforeEach(func() {
							secondThingWeRan = "fake-" + factories.GenerateGuid()

							secondTask = factories.BuildTaskWithRunAction(
								"inigo",
								componentMaker.Stack,
								768, // 768 + 512 is more than 1024, as we configured, so this won't fit
								512,
								"bash",
								[]string{"-c", fmt.Sprintf("curl %s && sleep 2", strings.Join(inigo_server.CurlArgs(secondThingWeRan), " "))},
							)

							err := bbs.DesireTask(secondTask)
							Ω(err).ShouldNot(HaveOccurred())
						})

						It("is executed once the first task completes, as its resources are cleared", func() {
							Eventually(bbs.GetAllCompletedTasks).Should(HaveLen(1)) // Wait for first task to complete
							Eventually(inigo_server.ReportingGuids, DEFAULT_EVENTUALLY_TIMEOUT+kickPendingDuration).Should(ContainElement(secondThingWeRan))
						})
					})
				})
			})
		})
	})

	Context("when only a converger is running", func() {
		var converger ifrit.Process

		BeforeEach(func() {
			converger = ifrit.Envoke(componentMaker.Converger(
				"-convergeRepeatInterval", "1s",

				// 1s would be ideal, but this also limits container creation time
				"-kickPendingTaskDuration", kickPendingDuration.String(),
			))
		})

		AfterEach(func() {
			helpers.StopProcess(converger)
		})

		Context("and a task is desired", func() {
			var thingWeRan string

			BeforeEach(func() {
				thingWeRan = "fake-" + factories.GenerateGuid()

				task := factories.BuildTaskWithRunAction(
					"inigo",
					componentMaker.Stack,
					512,
					512,
					"bash",
					[]string{"-c", fmt.Sprintf("curl %s && sleep 2", strings.Join(inigo_server.CurlArgs(thingWeRan), " "))},
				)

				err := bbs.DesireTask(task)
				Ω(err).ShouldNot(HaveOccurred())
			})

			Context("and then an exec and rep come up", func() {
				BeforeEach(func() {
					executor = grouper.EnvokeGroup(grouper.RunGroup{
						"exec": componentMaker.Executor(),
						"rep":  componentMaker.Rep(),
					})
				})

				It("eventually runs the Task", func() {
					Eventually(inigo_server.ReportingGuids, DEFAULT_EVENTUALLY_TIMEOUT+kickPendingDuration).Should(ContainElement(thingWeRan))
				})
			})
		})
	})

	Context("when a very impatient converger is running", func() {
		var converger ifrit.Process

		BeforeEach(func() {
			converger = ifrit.Envoke(componentMaker.Converger(
				"-convergeRepeatInterval", "1s",
				"-expireClaimedTaskDuration", "1s",
			))
		})

		AfterEach(func() {
			helpers.StopProcess(converger)
		})

		Context("and a task is desired", func() {
			var guid string

			BeforeEach(func() {
				guid = "fake-" + factories.GenerateGuid()

				task := factories.BuildTaskWithRunAction(
					"inigo",
					componentMaker.Stack,
					100,
					100,
					"curl",
					inigo_server.CurlArgs(guid),
				)

				err := bbs.DesireTask(task)
				Ω(err).ShouldNot(HaveOccurred())
			})

			It("should be marked as failed after the expire duration", func() {
				Eventually(bbs.GetAllCompletedTasks).Should(HaveLen(1))

				tasks, err := bbs.GetAllCompletedTasks()
				Ω(err).ShouldNot(HaveOccurred())
				Ω(tasks[0].Failed).Should(BeTrue(), "Task should have failed")
				Ω(tasks[0].FailureReason).Should(ContainSubstring("not claimed within time limit"))

				Ω(inigo_server.ReportingGuids()).Should(BeEmpty())
			})
		})
	})
})
<|endoftext|>


<commit_before>package main_test

import (
	"crypto/tls"
	"io/ioutil"
	"net/http"
	"net/http/cookiejar"
	"strings"

	"v.io/core/veyron/lib/testutil/v23tests"
)

//go:generate v23 test generate .

var (
	urlRE = "^(https://.*)$"
)

func seekBlessings(i *v23tests.T, principal *v23tests.Binary) {
	args := []string{
		"seekblessings",
		"--browser=false",
		"--from=https://localhost:8125/google",
		"-v=3",
	}
	line := principal.Start(args...).ExpectSetEventuallyRE(urlRE)[0][1]
	// Scan the output of "principal seekblessings", looking for the
	// URL that can be used to retrieve the blessings.
	transport := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	jar, err := cookiejar.New(&cookiejar.Options{})
	if err != nil {
		i.Fatalf("failed to create a cookie jar: %v", err)
	}
	client := &http.Client{
		Jar:       jar,
		Transport: transport,
	}
	resp, err := client.Get(line)
	if err != nil {
		i.Fatalf("Get(%q) failed: %v", line, err)
	}
	output, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()
	if err != nil {
		i.Fatalf("ReadAll() failed: %v", err)
	}
	if want := "Received blessings"; !strings.Contains(string(output), want) {
		i.Fatalf("failed to seek blessings: %v", string(output))
	}
}

func V23TestIdentityServer(i *v23tests.T) {
	v23tests.RunRootMT(i, "--veyron.tcp.address=127.0.0.1:0")

	// Start the identity server.
	args := []string{
		"-host=localhost",
		"-veyron.tcp.address=127.0.0.1:0",
	}
	i.BuildGoPkg("v.io/core/veyron/services/identity/identityd_test").Start(args...)

	// Use the principal tool to seekblessings.
	principal := i.BuildGoPkg("v.io/core/veyron/tools/principal")
	// Test an initial seekblessings call.
	seekBlessings(i, principal)
	// Test that a subsequent call succeeds with the same
	// credentials. This means that the blessings and principal from the
	// first call works correctly.
	seekBlessings(i, principal)
}
<commit_msg>TBR veyron/services/identity/identityd: reproduce sleep present in shell tests<commit_after>package main_test

import (
	"crypto/tls"
	"io/ioutil"
	"net/http"
	"net/http/cookiejar"
	"strings"
	"time"

	"v.io/core/veyron/lib/testutil/v23tests"
)

//go:generate v23 test generate .

var (
	urlRE = "^(https://.*)$"
)

func seekBlessings(i *v23tests.T, principal *v23tests.Binary) {
	args := []string{
		"seekblessings",
		"--browser=false",
		"--from=https://localhost:8125/google",
		"-v=3",
	}
	inv := principal.Start(args...)
	// Reproduce the sleep that was present in the shell test to see if
	// this allows the test to pass on macjenkins.
	time.Sleep(2 * time.Second)
	line := inv.ExpectSetEventuallyRE(urlRE)[0][1]
	// Scan the output of "principal seekblessings", looking for the
	// URL that can be used to retrieve the blessings.
	transport := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	jar, err := cookiejar.New(&cookiejar.Options{})
	if err != nil {
		i.Fatalf("failed to create a cookie jar: %v", err)
	}
	client := &http.Client{
		Jar:       jar,
		Transport: transport,
	}
	resp, err := client.Get(line)
	if err != nil {
		i.Fatalf("Get(%q) failed: %v", line, err)
	}
	output, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()
	if err != nil {
		i.Fatalf("ReadAll() failed: %v", err)
	}
	if want := "Received blessings"; !strings.Contains(string(output), want) {
		i.Fatalf("failed to seek blessings: %v", string(output))
	}
}

func V23TestIdentityServer(i *v23tests.T) {
	v23tests.RunRootMT(i, "--veyron.tcp.address=127.0.0.1:0")

	// Start the identity server.
	args := []string{
		"-host=localhost",
		"-veyron.tcp.address=127.0.0.1:0",
	}
	i.BuildGoPkg("v.io/core/veyron/services/identity/identityd_test").Start(args...)

	// Use the principal tool to seekblessings.
	principal := i.BuildGoPkg("v.io/core/veyron/tools/principal")
	// Test an initial seekblessings call.
	seekBlessings(i, principal)
	// Test that a subsequent call succeeds with the same
	// credentials. This means that the blessings and principal from the
	// first call works correctly.
	seekBlessings(i, principal)
}
<|endoftext|>


<commit_before>package device

import (
	"fmt"
	"github.com/hemtjanst/hemtjanst/messaging"
	"github.com/satori/go.uuid"
)

type Device struct {
	Topic        string
	Name         string              `json:"name"`
	Manufacturer string              `json:"manufacturer"`
	Model        string              `json:"model"`
	SerialNumber string              `json:"serialNumber"`
	Type         string              `json:"device"`
	LastWillID   uuid.UUID           `json:"lastWillID,omitempty"`
	Features     map[string]*Feature `json:"feature"`
	transport    messaging.PublishSubscriber
}

type Feature struct {
	Min      int    `json:"min,omitempty"`
	Max      int    `json:"max,omitempty"`
	Step     int    `json:"step,omitempty"`
	GetTopic string `json:"getTopic,omitempty"`
	SetTopic string `json:"setTopic,omitempty"`
}

func NewDevice(topic string, client messaging.PublishSubscriber) *Device {
	return &Device{Topic: topic, transport: client}
}

func (d *Device) HasFeature(feature string) bool {
	if _, ok := d.Features[feature]; ok {
		return true
	}
	return false
}

func (d *Device) Set(feature string, value string) error {
	if !d.HasFeature(feature) {
		return fmt.Errorf("Feature %s not found on device %s", feature, d.Topic)
	}
	ft := d.Features[feature]
	d.transport.Publish(ft.SetTopic,
		[]byte(value), 1, true)
	return nil
}

func (d *Device) Watch(feature string, callback func(msg messaging.Message)) error {
	if !d.HasFeature(feature) {
		return fmt.Errorf("Feature %s not found on device %s", feature, d.Topic)
	}
	ft := d.Features[feature]
	d.transport.Subscribe(ft.GetTopic,
		1, callback)
	return nil
}
<commit_msg>:sparkles: Make device.Device usable for client implementations<commit_after>package device

import (
	"encoding/json"
	"fmt"
	"github.com/hemtjanst/hemtjanst/messaging"
	"github.com/satori/go.uuid"
)

type Device struct {
	Topic        string
	Name         string              `json:"name"`
	Manufacturer string              `json:"manufacturer"`
	Model        string              `json:"model"`
	SerialNumber string              `json:"serialNumber"`
	Type         string              `json:"device"`
	LastWillID   uuid.UUID           `json:"lastWillID,omitempty"`
	Features     map[string]*Feature `json:"feature"`
	transport    messaging.PublishSubscriber
}

type Feature struct {
	Min      int    `json:"min,omitempty"`
	Max      int    `json:"max,omitempty"`
	Step     int    `json:"step,omitempty"`
	GetTopic string `json:"getTopic,omitempty"`
	SetTopic string `json:"setTopic,omitempty"`
}

func NewDevice(topic string, client messaging.PublishSubscriber) *Device {
	return &Device{Topic: topic, transport: client}
}

func (d *Device) HasFeature(feature string) bool {
	if _, ok := d.Features[feature]; ok {
		return true
	}
	return false
}

func (d *Device) Set(feature, value string) error {
	if !d.HasFeature(feature) {
		return fmt.Errorf("Feature %s not found on device %s", feature, d.Topic)
	}
	ft := d.Features[feature]
	d.transport.Publish(ft.SetTopic,
		[]byte(value), 1, false)
	return nil
}

func (d *Device) Watch(feature string, callback func(msg messaging.Message)) error {
	if !d.HasFeature(feature) {
		return fmt.Errorf("Feature %s not found on device %s", feature, d.Topic)
	}
	ft := d.Features[feature]
	d.transport.Subscribe(ft.GetTopic,
		1, callback)
	return nil
}

func (d *Device) Update(feature, value string) error {
	if !d.HasFeature(feature) {
		return fmt.Errorf("Feature %s not found on device %s", feature, d.Topic)
	}
	ft := d.Features[feature]
	d.transport.Publish(ft.GetTopic,
		[]byte(value), 1, true)
	return nil
}

func (d *Device) OnSet(feature string, callback func(msg messaging.Message)) error {
	if !d.HasFeature(feature) {
		return fmt.Errorf("Feature %s not found on device %s", feature, d.Topic)
	}
	ft := d.Features[feature]
	d.transport.Subscribe(ft.SetTopic,
		1, callback)
	return nil
}

func (d *Device) PublishMeta() error {
	js, err := json.Marshal(d)
	if err != nil {
		return err
	}
	d.transport.Publish(d.Topic+"/meta", js, 1, true)
	return nil
}
<|endoftext|>


<commit_before>package dht

import (
	"context"
	"time"

	process "github.com/jbenet/goprocess"
	processctx "github.com/jbenet/goprocess/context"
	"github.com/libp2p/go-libp2p-core/routing"
	"github.com/multiformats/go-multiaddr"
	_ "github.com/multiformats/go-multiaddr-dns"
)

var DefaultBootstrapPeers []multiaddr.Multiaddr

var minRTBootstrapThreshold = 4

func init() {
	for _, s := range []string{
		"/dnsaddr/bootstrap.libp2p.io/ipfs/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",
		"/dnsaddr/bootstrap.libp2p.io/ipfs/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa",
		"/dnsaddr/bootstrap.libp2p.io/ipfs/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb",
		"/dnsaddr/bootstrap.libp2p.io/ipfs/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt",
		"/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",            // mars.i.ipfs.io
		"/ip4/104.236.179.241/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM",           // pluto.i.ipfs.io
		"/ip4/128.199.219.111/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu",           // saturn.i.ipfs.io
		"/ip4/104.236.76.40/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64",             // venus.i.ipfs.io
		"/ip4/178.62.158.247/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd",            // earth.i.ipfs.io
		"/ip6/2604:a880:1:20::203:d001/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM",  // pluto.i.ipfs.io
		"/ip6/2400:6180:0:d0::151:6001/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu",  // saturn.i.ipfs.io
		"/ip6/2604:a880:800:10::4a:5001/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64", // venus.i.ipfs.io
		"/ip6/2a03:b0c0:0:1010::23:1001/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd", // earth.i.ipfs.io
	} {
		ma, err := multiaddr.NewMultiaddr(s)
		if err != nil {
			panic(err)
		}
		DefaultBootstrapPeers = append(DefaultBootstrapPeers, ma)
	}
}

// Start the bootstrap worker.
func (dht *IpfsDHT) startBootstrapping() error {
	// scan the RT table periodically & do a random walk on k-buckets that haven't been queried since the given bucket period
	dht.proc.Go(func(proc process.Process) {
		ctx := processctx.OnClosingContext(proc)

		scanInterval := time.NewTicker(dht.bootstrapPeriod)
		defer scanInterval.Stop()

		// run bootstrap if option is set
		if dht.autoBootstrap {
			dht.doBootstrap(ctx)
		} else {
			// disable the "auto-bootstrap" ticker so that no more ticks are sent to this channel
			scanInterval.Stop()
		}

		for {
			select {
			case <-scanInterval.C:
			case <-dht.triggerBootstrap:
				logger.Infof("triggering a bootstrap: RT has %d peers", dht.routingTable.Size())
			case <-ctx.Done():
				return
			}
			dht.doBootstrap(ctx)
		}
	})

	return nil
}

func (dht *IpfsDHT) doBootstrap(ctx context.Context) {
	dht.selfWalk(ctx)
	dht.bootstrapBuckets(ctx)
}

// bootstrapBuckets scans the routing table, and does a random walk on k-buckets that haven't been queried since the given bucket period
func (dht *IpfsDHT) bootstrapBuckets(ctx context.Context) {
	doQuery := func(bucketId int, target string, f func(context.Context) error) error {
		logger.Infof("starting bootstrap query for bucket %d to %s (routing table size was %d)",
			bucketId, target, dht.routingTable.Size())
		defer func() {
			logger.Infof("finished bootstrap query for bucket %d to %s (routing table size is now %d)",
				bucketId, target, dht.routingTable.Size())
		}()
		queryCtx, cancel := context.WithTimeout(ctx, dht.bootstrapTimeout)
		defer cancel()
		err := f(queryCtx)
		if err == context.DeadlineExceeded && queryCtx.Err() == context.DeadlineExceeded && ctx.Err() == nil {
			return nil
		}
		return err
	}

	buckets := dht.routingTable.GetAllBuckets()
	for bucketID, bucket := range buckets {
		if time.Since(bucket.RefreshedAt()) > dht.bootstrapPeriod {
			// gen rand peer in the bucket
			randPeerInBucket := dht.routingTable.GenRandPeerID(bucketID)

			// walk to the generated peer
			walkFnc := func(c context.Context) error {
				_, err := dht.FindPeer(ctx, randPeerInBucket)
				if err == routing.ErrNotFound {
					return nil
				}
				return err
			}

			if err := doQuery(bucketID, randPeerInBucket.String(), walkFnc); err != nil {
				logger.Warningf("failed to do a random walk on bucket %d", bucketID)
			}
		}
	}
}

// Traverse the DHT toward the self ID
func (dht *IpfsDHT) selfWalk(ctx context.Context) {
	queryCtx, cancel := context.WithTimeout(ctx, dht.bootstrapTimeout)
	defer cancel()
	_, err := dht.FindPeer(queryCtx, dht.self)
	if err == routing.ErrNotFound {
		return
	}
	logger.Warningf("failed to bootstrap self: %s", err)
}

// Bootstrap tells the DHT to get into a bootstrapped state.
//
// Note: the context is ignored.
func (dht *IpfsDHT) Bootstrap(_ context.Context) error {
	select {
	case dht.triggerBootstrap <- struct{}{}:
	default:
	}
	return nil
}
<commit_msg>fix(bootstrap): don't bootstrap more than 16 buckets<commit_after>package dht

import (
	"context"
	"time"

	process "github.com/jbenet/goprocess"
	processctx "github.com/jbenet/goprocess/context"
	"github.com/libp2p/go-libp2p-core/routing"
	"github.com/multiformats/go-multiaddr"
	_ "github.com/multiformats/go-multiaddr-dns"
)

var DefaultBootstrapPeers []multiaddr.Multiaddr

var minRTBootstrapThreshold = 4

func init() {
	for _, s := range []string{
		"/dnsaddr/bootstrap.libp2p.io/ipfs/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",
		"/dnsaddr/bootstrap.libp2p.io/ipfs/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa",
		"/dnsaddr/bootstrap.libp2p.io/ipfs/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb",
		"/dnsaddr/bootstrap.libp2p.io/ipfs/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt",
		"/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",            // mars.i.ipfs.io
		"/ip4/104.236.179.241/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM",           // pluto.i.ipfs.io
		"/ip4/128.199.219.111/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu",           // saturn.i.ipfs.io
		"/ip4/104.236.76.40/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64",             // venus.i.ipfs.io
		"/ip4/178.62.158.247/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd",            // earth.i.ipfs.io
		"/ip6/2604:a880:1:20::203:d001/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM",  // pluto.i.ipfs.io
		"/ip6/2400:6180:0:d0::151:6001/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu",  // saturn.i.ipfs.io
		"/ip6/2604:a880:800:10::4a:5001/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64", // venus.i.ipfs.io
		"/ip6/2a03:b0c0:0:1010::23:1001/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd", // earth.i.ipfs.io
	} {
		ma, err := multiaddr.NewMultiaddr(s)
		if err != nil {
			panic(err)
		}
		DefaultBootstrapPeers = append(DefaultBootstrapPeers, ma)
	}
}

// Start the bootstrap worker.
func (dht *IpfsDHT) startBootstrapping() error {
	// scan the RT table periodically & do a random walk on k-buckets that haven't been queried since the given bucket period
	dht.proc.Go(func(proc process.Process) {
		ctx := processctx.OnClosingContext(proc)

		scanInterval := time.NewTicker(dht.bootstrapPeriod)
		defer scanInterval.Stop()

		// run bootstrap if option is set
		if dht.autoBootstrap {
			dht.doBootstrap(ctx)
		} else {
			// disable the "auto-bootstrap" ticker so that no more ticks are sent to this channel
			scanInterval.Stop()
		}

		for {
			select {
			case <-scanInterval.C:
			case <-dht.triggerBootstrap:
				logger.Infof("triggering a bootstrap: RT has %d peers", dht.routingTable.Size())
			case <-ctx.Done():
				return
			}
			dht.doBootstrap(ctx)
		}
	})

	return nil
}

func (dht *IpfsDHT) doBootstrap(ctx context.Context) {
	dht.selfWalk(ctx)
	dht.bootstrapBuckets(ctx)
}

// bootstrapBuckets scans the routing table, and does a random walk on k-buckets that haven't been queried since the given bucket period
func (dht *IpfsDHT) bootstrapBuckets(ctx context.Context) {
	doQuery := func(bucketId int, target string, f func(context.Context) error) error {
		logger.Infof("starting bootstrap query for bucket %d to %s (routing table size was %d)",
			bucketId, target, dht.routingTable.Size())
		defer func() {
			logger.Infof("finished bootstrap query for bucket %d to %s (routing table size is now %d)",
				bucketId, target, dht.routingTable.Size())
		}()
		queryCtx, cancel := context.WithTimeout(ctx, dht.bootstrapTimeout)
		defer cancel()
		err := f(queryCtx)
		if err == context.DeadlineExceeded && queryCtx.Err() == context.DeadlineExceeded && ctx.Err() == nil {
			return nil
		}
		return err
	}

	buckets := dht.routingTable.GetAllBuckets()
	if len(buckets) > 16 {
		// Don't bother bootstrapping more than 16 buckets.
		// GenRandPeerID can't generate target peer IDs with more than
		// 16 bits specified anyways.
		buckets = buckets[:16]
	}
	for bucketID, bucket := range buckets {
		if time.Since(bucket.RefreshedAt()) > dht.bootstrapPeriod {
			// gen rand peer in the bucket
			randPeerInBucket := dht.routingTable.GenRandPeerID(bucketID)

			// walk to the generated peer
			walkFnc := func(c context.Context) error {
				_, err := dht.FindPeer(ctx, randPeerInBucket)
				if err == routing.ErrNotFound {
					return nil
				}
				return err
			}

			if err := doQuery(bucketID, randPeerInBucket.String(), walkFnc); err != nil {
				logger.Warningf("failed to do a random walk on bucket %d", bucketID)
			}
		}
	}
}

// Traverse the DHT toward the self ID
func (dht *IpfsDHT) selfWalk(ctx context.Context) {
	queryCtx, cancel := context.WithTimeout(ctx, dht.bootstrapTimeout)
	defer cancel()
	_, err := dht.FindPeer(queryCtx, dht.self)
	if err == routing.ErrNotFound {
		return
	}
	logger.Warningf("failed to bootstrap self: %s", err)
}

// Bootstrap tells the DHT to get into a bootstrapped state.
//
// Note: the context is ignored.
func (dht *IpfsDHT) Bootstrap(_ context.Context) error {
	select {
	case dht.triggerBootstrap <- struct{}{}:
	default:
	}
	return nil
}
<|endoftext|>


<commit_before>package safe

import (
	"github.com/bndw/pick/errors"
)

func (s *Safe) Add(name, username, password string) (*Account, error) {
	if _, exists := s.Accounts[name]; exists {
		account := s.Accounts[name]
		return &account, &errors.AccountExists{}
	}

	account := NewAccount(name, username, password)
	s.Accounts[name] = account

	if err := s.save(); err != nil {
		return nil, err
	}

	return &account, nil
}
<commit_msg>Use the safe.Get when checking for an existing account<commit_after>package safe

import (
	"github.com/bndw/pick/errors"
)

func (s *Safe) Add(name, username, password string) (*Account, error) {
	if existingAccount, _ := s.Get(name); existingAccount != nil {
		return existingAccount, &errors.AccountExists{}
	}

	account := NewAccount(name, username, password)
	s.Accounts[name] = *account

	if err := s.save(); err != nil {
		return nil, err
	}

	return account, nil
}
<|endoftext|>


<commit_before>package test

import (
	"bytes"
	"os"
	"path"
	"path/filepath"

	"gopkg.in/src-d/go-billy.v3"
)

type BasicMock struct {
	CreateArgs   []string
	OpenArgs     []string
	OpenFileArgs [][3]interface{}
	StatArgs     []string
	RenameArgs   [][2]string
	RemoveArgs   []string
	JoinArgs     [][]string
}

func (fs *BasicMock) Create(filename string) (billy.File, error) {
	fs.CreateArgs = append(fs.CreateArgs, filename)
	return &FileMock{name: filename}, nil
}

func (fs *BasicMock) Open(filename string) (billy.File, error) {
	fs.OpenArgs = append(fs.OpenArgs, filename)
	return &FileMock{name: filename}, nil
}

func (fs *BasicMock) OpenFile(filename string, flag int, mode os.FileMode) (billy.File, error) {
	fs.OpenFileArgs = append(fs.OpenFileArgs, [3]interface{}{filename, flag, mode})
	return &FileMock{name: filename}, nil
}

func (fs *BasicMock) Stat(filename string) (os.FileInfo, error) {
	fs.StatArgs = append(fs.StatArgs, filename)
	return nil, nil
}

func (fs *BasicMock) Rename(target, link string) error {
	fs.RenameArgs = append(fs.RenameArgs, [2]string{target, link})
	return nil
}

func (fs *BasicMock) Remove(filename string) error {
	fs.RemoveArgs = append(fs.RemoveArgs, filename)
	return nil
}

func (fs *BasicMock) Join(elem ...string) string {
	fs.JoinArgs = append(fs.JoinArgs, elem)
	return path.Join(elem...)
}

type TempFileMock struct {
	BasicMock
	TempFileArgs [][2]string
}

func (fs *TempFileMock) TempFile(dir, prefix string) (billy.File, error) {
	fs.TempFileArgs = append(fs.TempFileArgs, [2]string{dir, prefix})
	return &FileMock{name: "/tmp/hardcoded/mock/temp"}, nil
}

type DirMock struct {
	BasicMock
	ReadDirArgs  []string
	MkdirAllArgs [][2]interface{}
}

func (fs *DirMock) ReadDir(path string) ([]os.FileInfo, error) {
	fs.ReadDirArgs = append(fs.ReadDirArgs, path)
	return nil, nil
}

func (fs *DirMock) MkdirAll(filename string, perm os.FileMode) error {
	fs.MkdirAllArgs = append(fs.MkdirAllArgs, [2]interface{}{filename, perm})
	return nil
}

type SymlinkMock struct {
	BasicMock
	LstatArgs    []string
	SymlinkArgs  [][2]string
	ReadlinkArgs []string
}

func (fs *SymlinkMock) Lstat(filename string) (os.FileInfo, error) {
	fs.LstatArgs = append(fs.LstatArgs, filename)
	return nil, nil
}

func (fs *SymlinkMock) Symlink(target, link string) error {
	fs.SymlinkArgs = append(fs.SymlinkArgs, [2]string{target, link})
	return nil
}

func (fs *SymlinkMock) Readlink(link string) (string, error) {
	fs.ReadlinkArgs = append(fs.ReadlinkArgs, link)
	return filepath.FromSlash(link), nil
}

type FileMock struct {
	name string
	bytes.Buffer
}

func (f *FileMock) Name() string {
	return f.name
}

func (*FileMock) ReadAt(b []byte, off int64) (int, error) {
	return 0, nil
}

func (*FileMock) Seek(offset int64, whence int) (int64, error) {
	return 0, nil
}

func (*FileMock) Close() error {
	return nil
}
<commit_msg>Mock Lock+Unlock<commit_after>package test

import (
	"bytes"
	"os"
	"path"
	"path/filepath"

	"gopkg.in/src-d/go-billy.v3"
)

type BasicMock struct {
	CreateArgs   []string
	OpenArgs     []string
	OpenFileArgs [][3]interface{}
	StatArgs     []string
	RenameArgs   [][2]string
	RemoveArgs   []string
	JoinArgs     [][]string
}

func (fs *BasicMock) Create(filename string) (billy.File, error) {
	fs.CreateArgs = append(fs.CreateArgs, filename)
	return &FileMock{name: filename}, nil
}

func (fs *BasicMock) Open(filename string) (billy.File, error) {
	fs.OpenArgs = append(fs.OpenArgs, filename)
	return &FileMock{name: filename}, nil
}

func (fs *BasicMock) OpenFile(filename string, flag int, mode os.FileMode) (billy.File, error) {
	fs.OpenFileArgs = append(fs.OpenFileArgs, [3]interface{}{filename, flag, mode})
	return &FileMock{name: filename}, nil
}

func (fs *BasicMock) Stat(filename string) (os.FileInfo, error) {
	fs.StatArgs = append(fs.StatArgs, filename)
	return nil, nil
}

func (fs *BasicMock) Rename(target, link string) error {
	fs.RenameArgs = append(fs.RenameArgs, [2]string{target, link})
	return nil
}

func (fs *BasicMock) Remove(filename string) error {
	fs.RemoveArgs = append(fs.RemoveArgs, filename)
	return nil
}

func (fs *BasicMock) Join(elem ...string) string {
	fs.JoinArgs = append(fs.JoinArgs, elem)
	return path.Join(elem...)
}

type TempFileMock struct {
	BasicMock
	TempFileArgs [][2]string
}

func (fs *TempFileMock) TempFile(dir, prefix string) (billy.File, error) {
	fs.TempFileArgs = append(fs.TempFileArgs, [2]string{dir, prefix})
	return &FileMock{name: "/tmp/hardcoded/mock/temp"}, nil
}

type DirMock struct {
	BasicMock
	ReadDirArgs  []string
	MkdirAllArgs [][2]interface{}
}

func (fs *DirMock) ReadDir(path string) ([]os.FileInfo, error) {
	fs.ReadDirArgs = append(fs.ReadDirArgs, path)
	return nil, nil
}

func (fs *DirMock) MkdirAll(filename string, perm os.FileMode) error {
	fs.MkdirAllArgs = append(fs.MkdirAllArgs, [2]interface{}{filename, perm})
	return nil
}

type SymlinkMock struct {
	BasicMock
	LstatArgs    []string
	SymlinkArgs  [][2]string
	ReadlinkArgs []string
}

func (fs *SymlinkMock) Lstat(filename string) (os.FileInfo, error) {
	fs.LstatArgs = append(fs.LstatArgs, filename)
	return nil, nil
}

func (fs *SymlinkMock) Symlink(target, link string) error {
	fs.SymlinkArgs = append(fs.SymlinkArgs, [2]string{target, link})
	return nil
}

func (fs *SymlinkMock) Readlink(link string) (string, error) {
	fs.ReadlinkArgs = append(fs.ReadlinkArgs, link)
	return filepath.FromSlash(link), nil
}

type FileMock struct {
	name string
	bytes.Buffer
}

func (f *FileMock) Name() string {
	return f.name
}

func (*FileMock) ReadAt(b []byte, off int64) (int, error) {
	return 0, nil
}

func (*FileMock) Seek(offset int64, whence int) (int64, error) {
	return 0, nil
}

func (*FileMock) Close() error {
	return nil
}

func (*FileMock) Lock() error {
	return nil
}

func (*FileMock) Unlock() error {
	return nil
}
<|endoftext|>


<commit_before>package main

type Body struct {
	Xs, Vs []Vector
	M      float64
}

// Shifts all the values in xs by one and puts x at the beginning.
func Shift(xs []Vector, x Vector) {

	for i := len(xs) - 1; i > 0; i-- {

		xs[i] = xs[i-1]
	}

	xs[0] = x
}

type Integrator func(xs, vs []Vector, a Vector, dt float64)

// Performs a step of an Euler integration
func Euler(xs, vs []Vector, a Vector, dt float64) {

	v := vs[0].Plus(a.Scale(dt))
	x := xs[0].Plus(v.Scale(dt))

	Shift(vs, v)
	Shift(xs, x)
}

// Performs a step of a Verlet integrator
//
// Note that v[0] will not be calculated until the next step
func Verlet(xs, vs []Vector, a Vector, dt float64) {

	xNext := xs[0].Scale(2).Minus(xs[1]).Plus(a.Scale(dt * dt))
	vs[0] = xNext.Minus(xs[1]).Scale(1 / (2 * dt))

	Shift(vs, NewZeroVector())
	Shift(xs, xNext)
}

type Spring struct {
	K, L0 float64
}

type Hooke struct {
	Springs [][]Spring
}

func (h Hooke) Accel(bs []Body, i int) (a Vector) {

	f := NewZeroVector()

	b := bs[i]

	for j, b2 := range bs {

		spring := h.Springs[i][j]

		dir, l := b2.Xs[0].Minus(b.Xs[0]).UnitAndNorm()

		f = f.Plus(dir.Scale(spring.K * (l - spring.L0)))
	}

	return f.Scale(1 / b.M)
}

type SingleHooke struct {
	K float64
}

func (sh SingleHooke) Accel(bs []Body, i int) (a Vector) {

	b := bs[i]

	return b.Xs[0].Scale(-sh.K / b.M)
}

type Force interface {
	Accel(bs []Body, i int) (a Vector)
}

func main() {
}
<commit_msg>Add AnalyticSHM<commit_after>package main

import (
	"math"
)

type Body struct {
	Xs, Vs []Vector
	M      float64
}

// Shifts all the values in xs by one and puts x at the beginning.
func Shift(xs []Vector, x Vector) {

	for i := len(xs) - 1; i > 0; i-- {

		xs[i] = xs[i-1]
	}

	xs[0] = x
}

type Integrator func(xs, vs []Vector, a Vector, dt float64)

// Performs a step of an Euler integration
func Euler(xs, vs []Vector, a Vector, dt float64) {

	v := vs[0].Plus(a.Scale(dt))
	x := xs[0].Plus(v.Scale(dt))

	Shift(vs, v)
	Shift(xs, x)
}

// Performs a step of a Verlet integrator
//
// Note that v[0] will not be calculated until the next step
func Verlet(xs, vs []Vector, a Vector, dt float64) {

	xNext := xs[0].Scale(2).Minus(xs[1]).Plus(a.Scale(dt * dt))
	vs[0] = xNext.Minus(xs[1]).Scale(1 / (2 * dt))

	Shift(vs, NewZeroVector())
	Shift(xs, xNext)
}

type Spring struct {
	K, L0 float64
}

type Hooke struct {
	Springs [][]Spring
}

func (h Hooke) Accel(bs []Body, i int) (a Vector) {

	f := NewZeroVector()

	b := bs[i]

	for j, b2 := range bs {

		spring := h.Springs[i][j]

		dir, l := b2.Xs[0].Minus(b.Xs[0]).UnitAndNorm()

		f = f.Plus(dir.Scale(spring.K * (l - spring.L0)))
	}

	return f.Scale(1 / b.M)
}

type SingleHooke struct {
	K float64
}

func (sh SingleHooke) Accel(bs []Body, i int) (a Vector) {

	b := bs[i]

	return b.Xs[0].Scale(-sh.K / b.M)
}

type Force interface {
	Accel(bs []Body, i int) (a Vector)
}

type AnalyticSHM struct {
	K, M float64
	A    Vector
}

func (ashm AnalyticSHM) XVAt(t float64) (x, v Vector) {

	omega := math.Sqrt(ashm.K / ashm.M)

	x = ashm.A.Scale(math.Cos(omega * t))
	v = ashm.A.Negate().Scale(omega * math.Sin(omega*t))

	return
}

func main() {
}
<|endoftext|>


<commit_before>package sshd

import (
	"fmt"
	"io"
	"net"
	"os/exec"
	"sync"

	"github.com/efarrer/gmash/payload"

	"github.com/kr/pty"

	"golang.org/x/crypto/ssh"
)

// Using local function vars to facilitate mocks for tests
var handlePtyRequest func(string, ssh.Channel, *ssh.Request) error
var handleSSHRequests func(channel ssh.Channel, reqsCh <-chan *ssh.Request, shellConf ShellConf)
var processSSHChannels func(sshChan <-chan ssh.NewChannel, shellConf ShellConf)
var newServerConn func(net.Conn, *ssh.ServerConfig) (*ssh.ServerConn, <-chan ssh.NewChannel, <-chan *ssh.Request, error)
var discardRequests func(in <-chan *ssh.Request)
var processSSHConnection func(conn net.Conn, sshConf *ssh.ServerConfig, shellConf ShellConf)

func init() {
	setupFunctionPointers()
}

func setupFunctionPointers() {
	handlePtyRequest = _handlePtyRequest
	handleSSHRequests = _handleSSHRequests
	processSSHChannels = _processSSHChannels
	newServerConn = _newServerConn
	discardRequests = _discardRequests
	processSSHConnection = _processSSHConnection
}

// A ShellConf has common configuration for a ssh shell
type ShellConf interface {
	Shell() string
	ErrorHandler(error)
}

type shellConf struct {
	shell        string
	errorHandler func(error)
}

// DefaultShellConf creates the standard ShellConf
func DefaultShellConf(shell string, errorHandler func(error)) ShellConf {
	return &shellConf{
		shell:        shell,
		errorHandler: errorHandler,
	}
}

func (sc *shellConf) Shell() string {
	return sc.shell
}

func (sc *shellConf) ErrorHandler(err error) {
	sc.errorHandler(err)
}

type exitStatusMsg struct {
	Status uint32
}

func _handlePtyRequest(shell string, channel ssh.Channel, req *ssh.Request) error {
	ptyReq, err := payload.ParsePtyReq(req.Payload)
	if err != nil {
		return fmt.Errorf("Unable to parse pty request (%s)", err)
	}
	_ = ptyReq
	// TODO set the PTY size from ptyReq
	ptyFile, err := pty.Start(exec.Command(shell))
	if err != nil {
		return fmt.Errorf("Unable to create pty request (%s)", err)
	}
	var wg sync.WaitGroup
	wg.Add(2)
	// Note that channel is a ReadWriter to handling the requests stdin and
	// stdout. Stderr is with channel.Stderr()
	go func() {
		_, _ = io.Copy(channel, ptyFile)
		wg.Done()
	}()
	go func() {
		_, _ = io.Copy(ptyFile, channel)
		wg.Done()
	}()

	go func() {
		wg.Wait()
		// TODO get the actual exit status instead of just using 0
		channel.SendRequest("exit-status", false, ssh.Marshal(&struct{ ExitStatus uint32 }{0}))
		channel.Close()
		ptyFile.Close()
	}()

	return nil
}

func _handleSSHRequests(channel ssh.Channel, reqsCh <-chan *ssh.Request, shellConf ShellConf) {
	for req := range reqsCh {
		var err error
		switch req.Type {
		case "pty-req":
			err = handlePtyRequest(shellConf.Shell(), channel, req)
			if err != nil {
				shellConf.ErrorHandler(err)
				continue
			}
		}
		if req.WantReply {
			err = req.Reply(err == nil, nil)
			if err != nil {
				shellConf.ErrorHandler(err)
			}
		}
	}
}

func _processSSHChannels(sshChan <-chan ssh.NewChannel, shellConf ShellConf) {
	for newChannel := range sshChan {
		if newChannel.ChannelType() != "session" {
			shellConf.ErrorHandler(fmt.Errorf("unsupported channel type : %v", newChannel.ChannelType()))
			err := newChannel.Reject(ssh.UnknownChannelType, "unknown channel type")
			if err != nil {
				shellConf.ErrorHandler(err)
			}
			continue
		}

		channel, requests, err := newChannel.Accept()
		if err != nil {
			shellConf.ErrorHandler(fmt.Errorf("could not accept channel: %v", err))
			continue
		}

		go handleSSHRequests(channel, requests, shellConf)
	}
}

func _newServerConn(c net.Conn, config *ssh.ServerConfig) (*ssh.ServerConn, <-chan ssh.NewChannel, <-chan *ssh.Request, error) {
	return ssh.NewServerConn(c, config)
}

func _discardRequests(in <-chan *ssh.Request) {
	ssh.DiscardRequests(in)
}

func _processSSHConnection(conn net.Conn, sshConf *ssh.ServerConfig, shellConf ShellConf) {
	defer func() { _ = conn.Close() }()

	// Establish the ssh connection
	_, sshChan, sshRequest, err := newServerConn(conn, sshConf)
	if err != nil {
		shellConf.ErrorHandler(fmt.Errorf("failed to establish ssh connection (%s)", err))
		return
	}

	// Yea were not going to handle any requests (port/X11 forwarding etc. at this time)
	go discardRequests(sshRequest)

	processSSHChannels(sshChan, shellConf)
}

// SSHServer starts an ssh server on the given address
func SSHServer(addr string, sshConf *ssh.ServerConfig, shellConf ShellConf) (net.Listener, error) {
	listener, err := net.Listen("tcp", addr)
	if err != nil {
		return nil, fmt.Errorf("failed to listen on %s (%s)", addr, err)
	}

	go func() {
		for {
			conn, err := listener.Accept()
			if err != nil {
				shellConf.ErrorHandler(fmt.Errorf("failed to accept TCP connection (%v)", err))
				return
			}

			go processSSHConnection(conn, sshConf, shellConf)
		}
	}()
	return listener, nil
}
<commit_msg>Remove unused structure<commit_after>package sshd

import (
	"fmt"
	"io"
	"net"
	"os/exec"
	"sync"

	"github.com/efarrer/gmash/payload"

	"github.com/kr/pty"

	"golang.org/x/crypto/ssh"
)

// Using local function vars to facilitate mocks for tests
var handlePtyRequest func(string, ssh.Channel, *ssh.Request) error
var handleSSHRequests func(channel ssh.Channel, reqsCh <-chan *ssh.Request, shellConf ShellConf)
var processSSHChannels func(sshChan <-chan ssh.NewChannel, shellConf ShellConf)
var newServerConn func(net.Conn, *ssh.ServerConfig) (*ssh.ServerConn, <-chan ssh.NewChannel, <-chan *ssh.Request, error)
var discardRequests func(in <-chan *ssh.Request)
var processSSHConnection func(conn net.Conn, sshConf *ssh.ServerConfig, shellConf ShellConf)

func init() {
	setupFunctionPointers()
}

func setupFunctionPointers() {
	handlePtyRequest = _handlePtyRequest
	handleSSHRequests = _handleSSHRequests
	processSSHChannels = _processSSHChannels
	newServerConn = _newServerConn
	discardRequests = _discardRequests
	processSSHConnection = _processSSHConnection
}

// A ShellConf has common configuration for a ssh shell
type ShellConf interface {
	Shell() string
	ErrorHandler(error)
}

type shellConf struct {
	shell        string
	errorHandler func(error)
}

// DefaultShellConf creates the standard ShellConf
func DefaultShellConf(shell string, errorHandler func(error)) ShellConf {
	return &shellConf{
		shell:        shell,
		errorHandler: errorHandler,
	}
}

func (sc *shellConf) Shell() string {
	return sc.shell
}

func (sc *shellConf) ErrorHandler(err error) {
	sc.errorHandler(err)
}

func _handlePtyRequest(shell string, channel ssh.Channel, req *ssh.Request) error {
	ptyReq, err := payload.ParsePtyReq(req.Payload)
	if err != nil {
		return fmt.Errorf("Unable to parse pty request (%s)", err)
	}
	_ = ptyReq
	// TODO set the PTY size from ptyReq
	ptyFile, err := pty.Start(exec.Command(shell))
	if err != nil {
		return fmt.Errorf("Unable to create pty request (%s)", err)
	}
	var wg sync.WaitGroup
	wg.Add(2)
	// Note that channel is a ReadWriter to handling the requests stdin and
	// stdout. Stderr is with channel.Stderr()
	go func() {
		_, _ = io.Copy(channel, ptyFile)
		wg.Done()
	}()
	go func() {
		_, _ = io.Copy(ptyFile, channel)
		wg.Done()
	}()

	go func() {
		wg.Wait()
		// TODO get the actual exit status instead of just using 0
		channel.SendRequest("exit-status", false, ssh.Marshal(&struct{ ExitStatus uint32 }{0}))
		channel.Close()
		ptyFile.Close()
	}()

	return nil
}

func _handleSSHRequests(channel ssh.Channel, reqsCh <-chan *ssh.Request, shellConf ShellConf) {
	for req := range reqsCh {
		var err error
		switch req.Type {
		case "pty-req":
			err = handlePtyRequest(shellConf.Shell(), channel, req)
			if err != nil {
				shellConf.ErrorHandler(err)
				continue
			}
		}
		if req.WantReply {
			err = req.Reply(err == nil, nil)
			if err != nil {
				shellConf.ErrorHandler(err)
			}
		}
	}
}

func _processSSHChannels(sshChan <-chan ssh.NewChannel, shellConf ShellConf) {
	for newChannel := range sshChan {
		if newChannel.ChannelType() != "session" {
			shellConf.ErrorHandler(fmt.Errorf("unsupported channel type : %v", newChannel.ChannelType()))
			err := newChannel.Reject(ssh.UnknownChannelType, "unknown channel type")
			if err != nil {
				shellConf.ErrorHandler(err)
			}
			continue
		}

		channel, requests, err := newChannel.Accept()
		if err != nil {
			shellConf.ErrorHandler(fmt.Errorf("could not accept channel: %v", err))
			continue
		}

		go handleSSHRequests(channel, requests, shellConf)
	}
}

func _newServerConn(c net.Conn, config *ssh.ServerConfig) (*ssh.ServerConn, <-chan ssh.NewChannel, <-chan *ssh.Request, error) {
	return ssh.NewServerConn(c, config)
}

func _discardRequests(in <-chan *ssh.Request) {
	ssh.DiscardRequests(in)
}

func _processSSHConnection(conn net.Conn, sshConf *ssh.ServerConfig, shellConf ShellConf) {
	defer func() { _ = conn.Close() }()

	// Establish the ssh connection
	_, sshChan, sshRequest, err := newServerConn(conn, sshConf)
	if err != nil {
		shellConf.ErrorHandler(fmt.Errorf("failed to establish ssh connection (%s)", err))
		return
	}

	// Yea were not going to handle any requests (port/X11 forwarding etc. at this time)
	go discardRequests(sshRequest)

	processSSHChannels(sshChan, shellConf)
}

// SSHServer starts an ssh server on the given address
func SSHServer(addr string, sshConf *ssh.ServerConfig, shellConf ShellConf) (net.Listener, error) {
	listener, err := net.Listen("tcp", addr)
	if err != nil {
		return nil, fmt.Errorf("failed to listen on %s (%s)", addr, err)
	}

	go func() {
		for {
			conn, err := listener.Accept()
			if err != nil {
				shellConf.ErrorHandler(fmt.Errorf("failed to accept TCP connection (%v)", err))
				return
			}

			go processSSHConnection(conn, sshConf, shellConf)
		}
	}()
	return listener, nil
}
<|endoftext|>


<commit_before>// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package maps

import (
	"context"
	"errors"
	"fmt"
	"image"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
	"strings"

	_ "image/jpeg" // Loaded for image decoder
	_ "image/png"  // Loaded for image decoder
)

var staticMapAPI = &apiConfig{
	host:            "https://maps.googleapis.com",
	path:            "/maps/api/staticmap",
	acceptsClientID: true,
}

// MapType (optional) defines the type of map to construct. There are several possible
// maptype values, including roadmap, satellite, hybrid, and terrain
type MapType string

// Format defines the format of the resulting image
type Format string

// MarkerSize specifies the size of marker from the set {tiny, mid, small}
type MarkerSize string

// Anchor sets how the icon is placed in relation to the specified markers locations
type Anchor string

const (
	// RoadMap (default) specifies a standard roadmap image, as is normally shown on the
	// Google Maps website. If no maptype value is specified, the Google Static Maps API
	// serves roadmap tiles by default.
	RoadMap MapType = "roadmap"
	//Satellite specifies a satellite image.
	Satellite MapType = "satellite"
	//Terrain specifies a physical relief map image, showing terrain and vegetation.
	Terrain MapType = "terrain"
	// Hybrid specifies a hybrid of the satellite and roadmap image, showing a
	// transparent layer of major streets and place names on the satellite image.
	Hybrid MapType = "hybrid"
	//PNG8 or png (default) specifies the 8-bit PNG format.
	PNG8 Format = "png8"
	// PNG32 specifies the 32-bit PNG format.
	PNG32 Format = "png32"
	// GIF specifies the GIF format.
	GIF Format = "gif"
	// JPG specifies the JPEG compression format.
	JPG Format = "jpg"
	// JPGBaseline specifies a non-progressive JPEG compression format.
	JPGBaseline Format = "jpg-baseline"

	// Tiny Marker size
	Tiny MarkerSize = "tiny"
	// Mid Marker size
	Mid MarkerSize = "mid"
	// Small Marker size
	Small MarkerSize = "small"

	// Top Marker anchor position
	Top Anchor = "top"
	// Bottom Marker anchor position
	Bottom Anchor = "Bottom"
	// Left Marker anchor position
	Left Anchor = "left"
	// Right Marker anchor position
	Right Anchor = "right"
	// Center Marker anchor position
	Center Anchor = "center"
	// Topleft Marker anchor position
	Topleft Anchor = "topleft"
	// Topright Marker anchor position
	Topright Anchor = "topright"
	// Bottomleft Marker anchor position
	Bottomleft Anchor = "bottomleft"
	// Bottomright Marker anchor position
	Bottomright Anchor = "bottomright"
)

// CustomIcon replace the default Map Pin
type CustomIcon struct {
	// IconURL is th icon URL
	IconURL string
	// Anchor sets how the icon is placed in relation to the specified markers locations
	Anchor Anchor
	// Scale is the custom icon scale
	Scale int
}

func (c CustomIcon) String() string {
	var r []string

	if c.IconURL != "" {
		r = append(r, fmt.Sprintf("icon:%s", c.IconURL))
	}

	if c.Anchor != "" {
		r = append(r, fmt.Sprintf("anchor:%s", c.Anchor))
	}

	if c.Scale != 0 {
		r = append(r, fmt.Sprintf("scale:%d", c.Scale))
	}

	return strings.Join(r, "|")
}

// Marker is a Map pin
type Marker struct {
	// Color specifies a 24-bit color (example: color=0xFFFFCC) or a predefined color
	// from the set {black, brown, green, purple, yellow, blue, gray, orange, red,
	// white}.
	Color string
	// Label specifies a single uppercase alphanumeric character from the set {A-Z, 0-9}
	Label string
	// MarkerSize specifies the size of marker from the set {tiny, mid, small}
	Size string
	// CustomIcon replace the default Map Pin
	CustomIcon CustomIcon
	// Location is the Marker position
	Location []LatLng
}

func (m Marker) String() string {
	var r []string

	if m.CustomIcon != (CustomIcon{}) {
		r = append(r, m.CustomIcon.String())
	} else {
		if m.Color != "" {
			r = append(r, fmt.Sprintf("color:%s", m.Color))
		}

		if m.Label != "" {
			r = append(r, fmt.Sprintf("label:%s", m.Label))
		}

		if m.Size != "" {
			r = append(r, fmt.Sprintf("size:%s", m.Size))
		}
	}

	for _, l := range m.Location {
		r = append(r, l.String())
	}
	return strings.Join(r, "|")
}

// Path defines a single path of two or more connected points to overlay on the image
// at specified locations
type Path struct {
	// Weight (optional) specifies the thickness of the path in pixels.
	Weight int
	// Color (optional) specifies a color in HEX
	Color string
	// Fillcolor (optional) indicates both that the path marks off a polygonal area and
	// specifies the fill color to use as an overlay within that area.
	FillColor string
	// Geodesic (optional) indicates that the requested path should be interpreted as a
	// geodesic line that follows the curvature of the earth.
	Geodesic bool
	// Location two or more connected points to overlay on the image at specified
	// locations
	Location []LatLng
}

func (p Path) String() string {
	var r []string

	if p.Color != "" {
		r = append(r, fmt.Sprintf("color:%s", p.Color))
	}

	if p.FillColor != "" {
		r = append(r, fmt.Sprintf("fillcolor:%s", p.FillColor))
	}

	if p.Weight != 0 {
		r = append(r, fmt.Sprintf("weight:%d", p.Weight))
	}

	if p.Geodesic {
		r = append(r, "geodesic:true")
	}

	for _, l := range p.Location {
		r = append(r, l.String())
	}
	return strings.Join(r, "|")
}

// StaticMapRequest is the functional options struct for staticMap.Get
type StaticMapRequest struct {
	// Center focus the map at the correct location
	Center string
	// Zoom (required if markers not present) defines the zoom level of the map
	Zoom int
	// Size (required) defines the rectangular dimensions of the map image. This
	// parameter takes a string of the form {horizontal_value}x{vertical_value}
	Size string
	// Scale (optional) affects the number of pixels that are returned. Accepted values
	// are 2 and 4
	Scale int
	// Format format (optional) defines the format of the resulting image. Default: PNG.
	// Accepted Values: There are several possible formats including GIF, JPEG and PNG
	// types.
	Format Format
	// Language (optional) defines the language to use for display of labels on map
	// tiles
	Language string
	// Region (optional) defines the appropriate borders to display, based on
	// geo-political sensitivities.
	Region string
	// MapType (optional) defines the type of map to construct.
	MapType MapType
	// Markers (optional) define one or more markers to attach to the image at specified
	// locations.
	Markers []Marker
	// Paths (optional) defines multiple paths of two or more connected points to
	// overlay on the image at specified locations
	Paths []Path
	// Visible specifies one or more locations that should remain visible on the map,
	// though no markers or other indicators will be displayed.
	Visible []LatLng
	// MapStyles (optional) contains map styles.
	MapStyles []string
}

func (r *StaticMapRequest) params() url.Values {
	q := make(url.Values)

	if r.Center != "" {
		q.Set("center", r.Center)
	}

	if r.Zoom > 0 {
		q.Set("zoom", strconv.Itoa(r.Zoom))
	}
	if r.Size != "" {
		q.Set("size", r.Size)
	}
	if r.Scale > 0 {
		q.Set("scale", strconv.Itoa(r.Scale))
	}
	if r.Format != "" {
		q.Set("format", string(r.Format))
	}

	if r.Language != "" {
		q.Set("language", r.Language)
	}

	if r.Region != "" {
		q.Set("region", r.Region)
	}
	if r.MapType != "" {
		q.Set("maptype", string(r.MapType))
	}

	for _, m := range r.Markers {
		q.Add("markers", m.String())
	}

	for _, ps := range r.Paths {
		q.Add("path", ps.String())
	}

	if len(r.Visible) > 0 {
		t := make([]string, len(r.Visible))
		for i, l := range r.Visible {
			t[i] = l.String()
		}
		q.Set("visible", strings.Join(t, "|"))
	}

	for _, style := range r.MapStyles {
		q.Add("style", style)
	}

	return q
}

// StaticMap makes a StaticMap API request.
func (c *Client) StaticMap(ctx context.Context, r *StaticMapRequest) (image.Image, error) {
	if len(r.Markers) == 0 && r.Center == "" && r.Zoom == 0 {
		return nil, errors.New("maps: Center & Zoom required if Markers empty")
	}
	if r.Size == "" {
		return nil, errors.New("maps: Size empty")
	}

	resp, err := c.getBinary(ctx, staticMapAPI, r)
	if err != nil {
		return nil, err
	}
	defer resp.data.Close()

	if resp.statusCode != http.StatusOK {
		b, err := ioutil.ReadAll(resp.data)
		if err != nil {
			return nil, err
		}
		return nil, fmt.Errorf("Maps Static API: %d - %s", resp.statusCode, b)
	}

	img, _, err := image.Decode(resp.data)
	return img, err
}
<commit_msg>Convert Path.Location to an encoded polyline string<commit_after>// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package maps

import (
	"context"
	"errors"
	"fmt"
	"image"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
	"strings"

	_ "image/jpeg" // Loaded for image decoder
	_ "image/png"  // Loaded for image decoder
)

var staticMapAPI = &apiConfig{
	host:            "https://maps.googleapis.com",
	path:            "/maps/api/staticmap",
	acceptsClientID: true,
}

// MapType (optional) defines the type of map to construct. There are several possible
// maptype values, including roadmap, satellite, hybrid, and terrain
type MapType string

// Format defines the format of the resulting image
type Format string

// MarkerSize specifies the size of marker from the set {tiny, mid, small}
type MarkerSize string

// Anchor sets how the icon is placed in relation to the specified markers locations
type Anchor string

const (
	// RoadMap (default) specifies a standard roadmap image, as is normally shown on the
	// Google Maps website. If no maptype value is specified, the Google Static Maps API
	// serves roadmap tiles by default.
	RoadMap MapType = "roadmap"
	//Satellite specifies a satellite image.
	Satellite MapType = "satellite"
	//Terrain specifies a physical relief map image, showing terrain and vegetation.
	Terrain MapType = "terrain"
	// Hybrid specifies a hybrid of the satellite and roadmap image, showing a
	// transparent layer of major streets and place names on the satellite image.
	Hybrid MapType = "hybrid"
	//PNG8 or png (default) specifies the 8-bit PNG format.
	PNG8 Format = "png8"
	// PNG32 specifies the 32-bit PNG format.
	PNG32 Format = "png32"
	// GIF specifies the GIF format.
	GIF Format = "gif"
	// JPG specifies the JPEG compression format.
	JPG Format = "jpg"
	// JPGBaseline specifies a non-progressive JPEG compression format.
	JPGBaseline Format = "jpg-baseline"

	// Tiny Marker size
	Tiny MarkerSize = "tiny"
	// Mid Marker size
	Mid MarkerSize = "mid"
	// Small Marker size
	Small MarkerSize = "small"

	// Top Marker anchor position
	Top Anchor = "top"
	// Bottom Marker anchor position
	Bottom Anchor = "Bottom"
	// Left Marker anchor position
	Left Anchor = "left"
	// Right Marker anchor position
	Right Anchor = "right"
	// Center Marker anchor position
	Center Anchor = "center"
	// Topleft Marker anchor position
	Topleft Anchor = "topleft"
	// Topright Marker anchor position
	Topright Anchor = "topright"
	// Bottomleft Marker anchor position
	Bottomleft Anchor = "bottomleft"
	// Bottomright Marker anchor position
	Bottomright Anchor = "bottomright"
)

// CustomIcon replace the default Map Pin
type CustomIcon struct {
	// IconURL is th icon URL
	IconURL string
	// Anchor sets how the icon is placed in relation to the specified markers locations
	Anchor Anchor
	// Scale is the custom icon scale
	Scale int
}

func (c CustomIcon) String() string {
	var r []string

	if c.IconURL != "" {
		r = append(r, fmt.Sprintf("icon:%s", c.IconURL))
	}

	if c.Anchor != "" {
		r = append(r, fmt.Sprintf("anchor:%s", c.Anchor))
	}

	if c.Scale != 0 {
		r = append(r, fmt.Sprintf("scale:%d", c.Scale))
	}

	return strings.Join(r, "|")
}

// Marker is a Map pin
type Marker struct {
	// Color specifies a 24-bit color (example: color=0xFFFFCC) or a predefined color
	// from the set {black, brown, green, purple, yellow, blue, gray, orange, red,
	// white}.
	Color string
	// Label specifies a single uppercase alphanumeric character from the set {A-Z, 0-9}
	Label string
	// MarkerSize specifies the size of marker from the set {tiny, mid, small}
	Size string
	// CustomIcon replace the default Map Pin
	CustomIcon CustomIcon
	// Location is the Marker position
	Location []LatLng
}

func (m Marker) String() string {
	var r []string

	if m.CustomIcon != (CustomIcon{}) {
		r = append(r, m.CustomIcon.String())
	} else {
		if m.Color != "" {
			r = append(r, fmt.Sprintf("color:%s", m.Color))
		}

		if m.Label != "" {
			r = append(r, fmt.Sprintf("label:%s", m.Label))
		}

		if m.Size != "" {
			r = append(r, fmt.Sprintf("size:%s", m.Size))
		}
	}

	for _, l := range m.Location {
		r = append(r, l.String())
	}
	return strings.Join(r, "|")
}

// Path defines a single path of two or more connected points to overlay on the image
// at specified locations
type Path struct {
	// Weight (optional) specifies the thickness of the path in pixels.
	Weight int
	// Color (optional) specifies a color in HEX
	Color string
	// Fillcolor (optional) indicates both that the path marks off a polygonal area and
	// specifies the fill color to use as an overlay within that area.
	FillColor string
	// Geodesic (optional) indicates that the requested path should be interpreted as a
	// geodesic line that follows the curvature of the earth.
	Geodesic bool
	// Location two or more connected points to overlay on the image at specified
	// locations
	Location []LatLng
}

func (p Path) String() string {
	var r []string

	if p.Color != "" {
		r = append(r, fmt.Sprintf("color:%s", p.Color))
	}

	if p.FillColor != "" {
		r = append(r, fmt.Sprintf("fillcolor:%s", p.FillColor))
	}

	if p.Weight != 0 {
		r = append(r, fmt.Sprintf("weight:%d", p.Weight))
	}

	if p.Geodesic {
		r = append(r, "geodesic:true")
	}

	if len(p.Location) == 0 {
		return strings.Join(r, "|")
	}

	encodedLocationString := fmt.Sprintf("enc:%s", Encode(p.Location))
	latLngsToString := make([]string, len(p.Location))
	for i, l := range p.Location {
		latLngsToString[i] = l.String()
	}
	locationString := strings.Join(latLngsToString, "|")
	if len(locationString) > len(encodedLocationString) {
		r = append(r, encodedLocationString)
	} else {
		r = append(r, latLngsToString...)
	}
	return strings.Join(r, "|")
}

// StaticMapRequest is the functional options struct for staticMap.Get
type StaticMapRequest struct {
	// Center focus the map at the correct location
	Center string
	// Zoom (required if markers not present) defines the zoom level of the map
	Zoom int
	// Size (required) defines the rectangular dimensions of the map image. This
	// parameter takes a string of the form {horizontal_value}x{vertical_value}
	Size string
	// Scale (optional) affects the number of pixels that are returned. Accepted values
	// are 2 and 4
	Scale int
	// Format format (optional) defines the format of the resulting image. Default: PNG.
	// Accepted Values: There are several possible formats including GIF, JPEG and PNG
	// types.
	Format Format
	// Language (optional) defines the language to use for display of labels on map
	// tiles
	Language string
	// Region (optional) defines the appropriate borders to display, based on
	// geo-political sensitivities.
	Region string
	// MapType (optional) defines the type of map to construct.
	MapType MapType
	// Markers (optional) define one or more markers to attach to the image at specified
	// locations.
	Markers []Marker
	// Paths (optional) defines multiple paths of two or more connected points to
	// overlay on the image at specified locations
	Paths []Path
	// Visible specifies one or more locations that should remain visible on the map,
	// though no markers or other indicators will be displayed.
	Visible []LatLng
	// MapStyles (optional) contains map styles.
	MapStyles []string
}

func (r *StaticMapRequest) params() url.Values {
	q := make(url.Values)

	if r.Center != "" {
		q.Set("center", r.Center)
	}

	if r.Zoom > 0 {
		q.Set("zoom", strconv.Itoa(r.Zoom))
	}
	if r.Size != "" {
		q.Set("size", r.Size)
	}
	if r.Scale > 0 {
		q.Set("scale", strconv.Itoa(r.Scale))
	}
	if r.Format != "" {
		q.Set("format", string(r.Format))
	}

	if r.Language != "" {
		q.Set("language", r.Language)
	}

	if r.Region != "" {
		q.Set("region", r.Region)
	}
	if r.MapType != "" {
		q.Set("maptype", string(r.MapType))
	}

	for _, m := range r.Markers {
		q.Add("markers", m.String())
	}

	for _, ps := range r.Paths {
		q.Add("path", ps.String())
	}

	if len(r.Visible) > 0 {
		t := make([]string, len(r.Visible))
		for i, l := range r.Visible {
			t[i] = l.String()
		}
		q.Set("visible", strings.Join(t, "|"))
	}

	for _, style := range r.MapStyles {
		q.Add("style", style)
	}

	return q
}

// StaticMap makes a StaticMap API request.
func (c *Client) StaticMap(ctx context.Context, r *StaticMapRequest) (image.Image, error) {
	if len(r.Markers) == 0 && r.Center == "" && r.Zoom == 0 {
		return nil, errors.New("maps: Center & Zoom required if Markers empty")
	}
	if r.Size == "" {
		return nil, errors.New("maps: Size empty")
	}

	resp, err := c.getBinary(ctx, staticMapAPI, r)
	if err != nil {
		return nil, err
	}
	defer resp.data.Close()

	if resp.statusCode != http.StatusOK {
		b, err := ioutil.ReadAll(resp.data)
		if err != nil {
			return nil, err
		}
		return nil, fmt.Errorf("Maps Static API: %d - %s", resp.statusCode, b)
	}

	img, _, err := image.Decode(resp.data)
	return img, err
}
<|endoftext|>


<commit_before>package stone

import (
	"fmt"
	"strings"
	"time"

	jwt "github.com/dgrijalva/jwt-go"
	"github.com/google/uuid"
	"github.com/mundipagg/boleto-api/certificate"
	"github.com/mundipagg/boleto-api/config"
)

const (
	StoneRealm = "stone"
)

func generateJWT() (string, error) {
	sk, err := certificate.GetCertificateFromStore(config.Get().AzureStorageOpenBankSkName)
	if err != nil {
		return "", err
	}

	signKey, err := jwt.ParseRSAPrivateKeyFromPEM(sk.([]byte))
	if err != nil {
		return "", err
	}

	now := time.Now()

	atClaims := jwt.MapClaims{}
	atClaims["exp"] = now.Add(time.Duration(config.Get().StoneTokenDurationInMinutes) * time.Minute).Unix()
	atClaims["nbf"] = now.Unix()
	atClaims["aud"] = config.Get().StoneAudience
	atClaims["realm"] = StoneRealm
	atClaims["sub"] = config.Get().StoneClientID
	atClaims["clientId"] = config.Get().StoneClientID
	atClaims["iat"] = now.Unix()
	atClaims["jti"] = generateJTIFromTime(now)

	at := jwt.NewWithClaims(jwt.SigningMethodRS256, atClaims)

	token, err := at.SignedString(signKey)
	if err != nil {
		return "", err
	}
	return token, nil
}

func generateJTIFromTime(t time.Time) string {
	id, _ := uuid.NewUUID()
	nowStr := t.Format("2006-01-02T15:04:05.000Z")

	removable := []string{"-", "T", ":", "."}
	for _, ch := range removable {
		nowStr = strings.ReplaceAll(nowStr, ch, "")
	}

	return fmt.Sprintf("%s.%s", nowStr[:17], id.String()[:7])
}
<commit_msg>feat:adiciona issue na geracao de jwt da stone<commit_after>package stone

import (
	"fmt"
	"strings"
	"time"

	jwt "github.com/dgrijalva/jwt-go"
	"github.com/google/uuid"
	"github.com/mundipagg/boleto-api/certificate"
	"github.com/mundipagg/boleto-api/config"
)

const (
	StoneRealm = "stone"
)

func generateJWT() (string, error) {
	sk, err := certificate.GetCertificateFromStore(config.Get().AzureStorageOpenBankSkName)
	if err != nil {
		return "", err
	}

	signKey, err := jwt.ParseRSAPrivateKeyFromPEM(sk.([]byte))
	if err != nil {
		return "", err
	}

	now := time.Now()

	atClaims := jwt.MapClaims{}
	atClaims["exp"] = now.Add(time.Duration(config.Get().StoneTokenDurationInMinutes) * time.Minute).Unix()
	atClaims["nbf"] = now.Unix()
	atClaims["aud"] = config.Get().StoneAudience
	atClaims["realm"] = StoneRealm
	atClaims["sub"] = config.Get().StoneClientID
	atClaims["clientId"] = config.Get().StoneClientID
	atClaims["iat"] = now.Unix()
	atClaims["jti"] = generateJTIFromTime(now)
	atClaims["iss"] = config.Get().StoneClientID

	at := jwt.NewWithClaims(jwt.SigningMethodRS256, atClaims)

	token, err := at.SignedString(signKey)
	if err != nil {
		return "", err
	}
	return token, nil
}

func generateJTIFromTime(t time.Time) string {
	id, _ := uuid.NewUUID()
	nowStr := t.Format("2006-01-02T15:04:05.000Z")

	removable := []string{"-", "T", ":", "."}
	for _, ch := range removable {
		nowStr = strings.ReplaceAll(nowStr, ch, "")
	}

	return fmt.Sprintf("%s.%s", nowStr[:17], id.String()[:7])
}
<|endoftext|>


<commit_before>package stow

import (
	"fmt"
	"os"
	"testing"

	"github.com/boltdb/bolt"
)

type MyType struct {
	FirstName string `json:"first"`
	LastName  string `json:"last"`
}

func (t *MyType) String() string {
	return fmt.Sprintf("%s %s", t.FirstName, t.LastName)
}

func init() {
	Register(&MyType{})
	RegisterName("stow.YourType", &YourType{})
}

type YourType struct {
	FirstName string `json:"first"`
}

func TestChangeType(t *testing.T) {
	db, err := bolt.Open("my4.db", 0600, nil)
	if err != nil {
		t.Error(err.Error())
	}
	defer os.Remove("my4.db")
	defer db.Close()

	s := NewStore(db, []byte("interface"))

	s.Put([]byte("test"), &YourType{"DJ"})

	var v MyType
	s.Get([]byte("test"), &v)

	if v.String() != "DJ " {
		t.Errorf("unexpected response name", v.String())
	}
}

func TestInterfaces(t *testing.T) {
	db, err := bolt.Open("my4.db", 0600, nil)
	if err != nil {
		t.Error(err.Error())
	}
	defer os.Remove("my4.db")
	defer db.Close()

	s := NewStore(db, []byte("interface"))

	var j fmt.Stringer = &MyType{"First", "Last"}
	s.Put([]byte("test"), &j)

	err = s.ForEach(func(str fmt.Stringer) {
		if str.String() != "First Last" {
			t.Errorf("unexpected string %s", str)
		}
	})
	if err != nil {
		t.Error(err.Error())
	}

	var i fmt.Stringer
	err = s.Get([]byte("test"), &i)
	if err != nil {
		t.Error(err.Error())
	} else {
		if i.String() != "First Last" {
			t.Errorf("unexpected string %s", i)
		}
	}
}

func testStore(t *testing.T, store *Store) {
	store.Put([]byte("hello"), &MyType{"Derek", "Kered"})

	var found bool
	err := store.ForEach(func(name MyType) {
		found = true
		if name.FirstName != "Derek" || name.LastName != "Kered" {
			t.Errorf("mismatching name %s", name)
		}
	})

	if !found {
		t.Errorf("ForEach failed!")
	}

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

	var name MyType
	store.Get([]byte("hello"), &name)

	if name.FirstName != "Derek" || name.LastName != "Kered" {
		t.Errorf("Unexpected name: %v", name)
	}

	var name2 MyType
	store.Pull([]byte("hello"), &name2)

	if name2.FirstName != "Derek" || name2.LastName != "Kered" {
		t.Errorf("Unexpected name2: %v", name2)
	}

	var name3 MyType
	err = store.Pull([]byte("hello"), &name3)
	if err != ErrNotFound {
		t.Errorf("pull failed to remove the name!")
	}

	store.Put([]byte("hello"), &MyType{"Friend", "person"})
	store.DeleteAll()

	var name4 MyType
	err = store.Pull([]byte("hello"), &name4)
	if err != ErrNotFound {
		t.Errorf("DeleteAll failed!")
	}
}

func TestJSON(t *testing.T) {
	db, err := bolt.Open("my1.db", 0600, nil)
	if err != nil {
		t.Error(err.Error())
	}
	defer os.Remove("my1.db")
	defer db.Close()

	testStore(t, NewJSONStore(db, []byte("json")))
}

func TestXML(t *testing.T) {
	db, err := bolt.Open("my2.db", 0600, nil)
	if err != nil {
		t.Error(err.Error())
	}
	defer os.Remove("my2.db")
	defer db.Close()

	testStore(t, NewXMLStore(db, []byte("xml")))
}

func TestGob(t *testing.T) {
	db, err := bolt.Open("my3.db", 0600, nil)
	if err != nil {
		t.Error(err.Error())
	}
	defer os.Remove("my3.db")
	defer db.Close()

	testStore(t, NewStore(db, []byte("gob")))
}
<commit_msg>fixed error fmt<commit_after>package stow

import (
	"fmt"
	"os"
	"testing"

	"github.com/boltdb/bolt"
)

type MyType struct {
	FirstName string `json:"first"`
	LastName  string `json:"last"`
}

func (t *MyType) String() string {
	return fmt.Sprintf("%s %s", t.FirstName, t.LastName)
}

func init() {
	Register(&MyType{})
	RegisterName("stow.YourType", &YourType{})
}

type YourType struct {
	FirstName string `json:"first"`
}

func TestChangeType(t *testing.T) {
	db, err := bolt.Open("my4.db", 0600, nil)
	if err != nil {
		t.Error(err.Error())
	}
	defer os.Remove("my4.db")
	defer db.Close()

	s := NewStore(db, []byte("interface"))

	s.Put([]byte("test"), &YourType{"DJ"})

	var v MyType
	s.Get([]byte("test"), &v)

	if v.String() != "DJ " {
		t.Errorf("unexpected response name %s", v.String())
	}
}

func TestInterfaces(t *testing.T) {
	db, err := bolt.Open("my4.db", 0600, nil)
	if err != nil {
		t.Error(err.Error())
	}
	defer os.Remove("my4.db")
	defer db.Close()

	s := NewStore(db, []byte("interface"))

	var j fmt.Stringer = &MyType{"First", "Last"}
	s.Put([]byte("test"), &j)

	err = s.ForEach(func(str fmt.Stringer) {
		if str.String() != "First Last" {
			t.Errorf("unexpected string %s", str)
		}
	})
	if err != nil {
		t.Error(err.Error())
	}

	var i fmt.Stringer
	err = s.Get([]byte("test"), &i)
	if err != nil {
		t.Error(err.Error())
	} else {
		if i.String() != "First Last" {
			t.Errorf("unexpected string %s", i)
		}
	}
}

func testStore(t *testing.T, store *Store) {
	store.Put([]byte("hello"), &MyType{"Derek", "Kered"})

	var found bool
	err := store.ForEach(func(name MyType) {
		found = true
		if name.FirstName != "Derek" || name.LastName != "Kered" {
			t.Errorf("mismatching name %s", name)
		}
	})

	if !found {
		t.Errorf("ForEach failed!")
	}

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

	var name MyType
	store.Get([]byte("hello"), &name)

	if name.FirstName != "Derek" || name.LastName != "Kered" {
		t.Errorf("Unexpected name: %v", name)
	}

	var name2 MyType
	store.Pull([]byte("hello"), &name2)

	if name2.FirstName != "Derek" || name2.LastName != "Kered" {
		t.Errorf("Unexpected name2: %v", name2)
	}

	var name3 MyType
	err = store.Pull([]byte("hello"), &name3)
	if err != ErrNotFound {
		t.Errorf("pull failed to remove the name!")
	}

	store.Put([]byte("hello"), &MyType{"Friend", "person"})
	store.DeleteAll()

	var name4 MyType
	err = store.Pull([]byte("hello"), &name4)
	if err != ErrNotFound {
		t.Errorf("DeleteAll failed!")
	}
}

func TestJSON(t *testing.T) {
	db, err := bolt.Open("my1.db", 0600, nil)
	if err != nil {
		t.Error(err.Error())
	}
	defer os.Remove("my1.db")
	defer db.Close()

	testStore(t, NewJSONStore(db, []byte("json")))
}

func TestXML(t *testing.T) {
	db, err := bolt.Open("my2.db", 0600, nil)
	if err != nil {
		t.Error(err.Error())
	}
	defer os.Remove("my2.db")
	defer db.Close()

	testStore(t, NewXMLStore(db, []byte("xml")))
}

func TestGob(t *testing.T) {
	db, err := bolt.Open("my3.db", 0600, nil)
	if err != nil {
		t.Error(err.Error())
	}
	defer os.Remove("my3.db")
	defer db.Close()

	testStore(t, NewStore(db, []byte("gob")))
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"go/build"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"github.com/PuerkitoBio/goquery"
)

func getVendorSubmodules() (map[string]string, error) {
	output, err := execute(
		exec.Command("git", "submodule", "status"),
	)
	if err != nil {
		return nil, err
	}

	vendors := map[string]string{}

	lines := strings.Split(output, "\n")
	for _, line := range lines {
		if line == "" {
			continue
		}

		parts := strings.Split(strings.TrimLeft(line, " -"), " ")
		if len(parts) >= 2 {
			path := parts[1]
			commit := parts[0]
			if strings.HasPrefix(path, "vendor/") {
				path = strings.TrimPrefix(path, "vendor/")
				vendors[path] = commit
			}
		}
	}

	return vendors, nil
}

func addVendorSubmodule(importpath string) error {
	var (
		target   = "vendor/" + importpath
		prefixes = []string{
			"https://",
			"git+ssh://",
			"git://",
		}

		errs []string
	)

	for _, prefix := range prefixes {
		var url string
		if prefix == "https://" {
			var err error
			url, err = getHttpsURLForImportPath(importpath)
			if err != nil {
				errs = append(errs, err.Error())
				continue
			}
		} else {
			url = prefix + importpath
		}

		_, err := execute(
			exec.Command("git", "submodule", "add", "-f", url, target),
		)
		if err == nil {
			return nil
		}

		errs = append(errs, err.Error())
	}

	return errors.New(strings.Join(errs, "\n"))
}

// NOTE: This list is copied from
// https://github.com/golang/go/blob/10538a8f9e2e718a47633ac5a6e90415a2c3f5f1/src/cmd/go/vcs.go#L821-L861
var wellKnownSites = []string{
	"github.com/",
	"bitbucket.org/",
	"hub.jazz.net/git/",
	"git.apache.org/",
	"git.openstack.org/",
}

func getHttpsURLForImportPath(importpath string) (url string, err error) {
	url = "https://" + importpath
	for _, site := range wellKnownSites {
		if strings.HasPrefix(importpath, site) {
			return url, nil
		}
	}

	// NOTE: Parse <meta name="go-import" content="import-prefix vcs repo-root">
	// For detail, see the output of "go help importpath"
	var doc *goquery.Document
	doc, err = goquery.NewDocument(url)
	if err != nil {
		return
	}
	doc.Find("meta[name=go-import]").Each(func(i int, s *goquery.Selection) {
		if err != nil {
			return
		}
		content, exists := s.Attr("content")
		if !exists {
			err = fmt.Errorf(`"content" attribute not found in meta name="go-import" at %s`, url)
			return
		}
		terms := strings.Fields(content)
		if len(terms) != 3 {
			err = fmt.Errorf(`invalid formatted "content" attribute in meta name="go-import" at %s`, url)
			return
		}
		prefix := terms[0]
		vcs := terms[1]
		repoRoot := terms[2]
		if strings.HasPrefix(importpath, prefix) && vcs == "git" {
			url = repoRoot
		}
	})
	if err != nil {
		return "", err
	}
	return url, nil
}

func removeVendorSubmodule(importpath string) error {
	vendor := "vendor/" + importpath

	_, err := execute(
		exec.Command("git", "submodule", "deinit", "-f", vendor),
	)
	if err != nil {
		return fmt.Errorf(
			"can't deinit submodule: %s", err,
		)
	}

	_, err = execute(
		exec.Command("git", "rm", "--force", vendor),
	)
	if err != nil {
		return fmt.Errorf(
			"can't remove submodule directory: %s", err,
		)
	}

	_, err = execute(
		exec.Command("rm", "-r", filepath.Join(".git", "modules", vendor)),
	)
	if err != nil {
		return fmt.Errorf(
			"can't remove submodule directory in .git/modules: %s", err,
		)
	}

	return nil
}

func updateVendorSubmodule(importpath string) error {
	cwd, err := os.Getwd()
	if err != nil {
		return err
	}

	cmd := exec.Command("git", "pull", "origin", "master")
	cmd.Dir = filepath.Join(cwd, "vendor", importpath)

	_, err = execute(cmd)

	return err
}

func getRootImportpath(importpath string) (string, error) {
	pkg, err := build.Import(importpath, "", build.IgnoreVendor)
	if err != nil {
		return "", err
	}

	cmd := exec.Command("git", "rev-parse", "--show-toplevel")
	cmd.Dir = filepath.Join(pkg.SrcRoot, importpath)

	rootdir, err := execute(cmd)
	if err != nil {
		return "", err
	}

	return strings.Trim(
		strings.TrimSpace(strings.TrimPrefix(rootdir, pkg.SrcRoot)),
		"/",
	), nil
}
<commit_msg>Rename s to selection<commit_after>package main

import (
	"errors"
	"fmt"
	"go/build"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"github.com/PuerkitoBio/goquery"
)

func getVendorSubmodules() (map[string]string, error) {
	output, err := execute(
		exec.Command("git", "submodule", "status"),
	)
	if err != nil {
		return nil, err
	}

	vendors := map[string]string{}

	lines := strings.Split(output, "\n")
	for _, line := range lines {
		if line == "" {
			continue
		}

		parts := strings.Split(strings.TrimLeft(line, " -"), " ")
		if len(parts) >= 2 {
			path := parts[1]
			commit := parts[0]
			if strings.HasPrefix(path, "vendor/") {
				path = strings.TrimPrefix(path, "vendor/")
				vendors[path] = commit
			}
		}
	}

	return vendors, nil
}

func addVendorSubmodule(importpath string) error {
	var (
		target   = "vendor/" + importpath
		prefixes = []string{
			"https://",
			"git+ssh://",
			"git://",
		}

		errs []string
	)

	for _, prefix := range prefixes {
		var url string
		if prefix == "https://" {
			var err error
			url, err = getHttpsURLForImportPath(importpath)
			if err != nil {
				errs = append(errs, err.Error())
				continue
			}
		} else {
			url = prefix + importpath
		}

		_, err := execute(
			exec.Command("git", "submodule", "add", "-f", url, target),
		)
		if err == nil {
			return nil
		}

		errs = append(errs, err.Error())
	}

	return errors.New(strings.Join(errs, "\n"))
}

// NOTE: This list is copied from
// https://github.com/golang/go/blob/10538a8f9e2e718a47633ac5a6e90415a2c3f5f1/src/cmd/go/vcs.go#L821-L861
var wellKnownSites = []string{
	"github.com/",
	"bitbucket.org/",
	"hub.jazz.net/git/",
	"git.apache.org/",
	"git.openstack.org/",
}

func getHttpsURLForImportPath(importpath string) (url string, err error) {
	url = "https://" + importpath
	for _, site := range wellKnownSites {
		if strings.HasPrefix(importpath, site) {
			return url, nil
		}
	}

	// NOTE: Parse <meta name="go-import" content="import-prefix vcs repo-root">
	// For detail, see the output of "go help importpath"
	var doc *goquery.Document
	doc, err = goquery.NewDocument(url)
	if err != nil {
		return
	}
	doc.Find("meta[name=go-import]").Each(func(_ int, selection *goquery.Selection) {
		if err != nil {
			return
		}
		content, exists := selection.Attr("content")
		if !exists {
			err = fmt.Errorf(`"content" attribute not found in meta name="go-import" at %s`, url)
			return
		}
		terms := strings.Fields(content)
		if len(terms) != 3 {
			err = fmt.Errorf(`invalid formatted "content" attribute in meta name="go-import" at %s`, url)
			return
		}
		prefix := terms[0]
		vcs := terms[1]
		repoRoot := terms[2]
		if strings.HasPrefix(importpath, prefix) && vcs == "git" {
			url = repoRoot
		}
	})
	if err != nil {
		return "", err
	}
	return url, nil
}

func removeVendorSubmodule(importpath string) error {
	vendor := "vendor/" + importpath

	_, err := execute(
		exec.Command("git", "submodule", "deinit", "-f", vendor),
	)
	if err != nil {
		return fmt.Errorf(
			"can't deinit submodule: %s", err,
		)
	}

	_, err = execute(
		exec.Command("git", "rm", "--force", vendor),
	)
	if err != nil {
		return fmt.Errorf(
			"can't remove submodule directory: %s", err,
		)
	}

	_, err = execute(
		exec.Command("rm", "-r", filepath.Join(".git", "modules", vendor)),
	)
	if err != nil {
		return fmt.Errorf(
			"can't remove submodule directory in .git/modules: %s", err,
		)
	}

	return nil
}

func updateVendorSubmodule(importpath string) error {
	cwd, err := os.Getwd()
	if err != nil {
		return err
	}

	cmd := exec.Command("git", "pull", "origin", "master")
	cmd.Dir = filepath.Join(cwd, "vendor", importpath)

	_, err = execute(cmd)

	return err
}

func getRootImportpath(importpath string) (string, error) {
	pkg, err := build.Import(importpath, "", build.IgnoreVendor)
	if err != nil {
		return "", err
	}

	cmd := exec.Command("git", "rev-parse", "--show-toplevel")
	cmd.Dir = filepath.Join(pkg.SrcRoot, importpath)

	rootdir, err := execute(cmd)
	if err != nil {
		return "", err
	}

	return strings.Trim(
		strings.TrimSpace(strings.TrimPrefix(rootdir, pkg.SrcRoot)),
		"/",
	), nil
}
<|endoftext|>