<commit_before>package collector

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"testing"
	"time"

	"fullerite/metric"
	"fullerite/util"

	l "github.com/Sirupsen/logrus"
	"github.com/stretchr/testify/assert"
)

// MockMLE Mock for MesosLeaderElectInterface that encapsulate functionality to check if the interface methods have been called/not. We embed the interface for the case of the test because this interface has unexported methods (set()). And since the interface comes from a different package, we cannot provide a concrete implementation for it.
type MockMLE struct {
	util.MesosLeaderElectInterface
	ConfigureCalled bool
}

func (m *MockMLE) Configure(nodes string, ttl time.Duration) {
	m.ConfigureCalled = true
}

func (m *MockMLE) Get() string {
	return httptest.DefaultRemoteAddr
}

// mockExternalIP Injectable mock for externalIP, for test assertions.
func mockExternalIP() (string, error) {
	return httptest.DefaultRemoteAddr, nil
}

func TestMesosStatsNewMesosStats(t *testing.T) {
	oldExternalIP := externalIP
	defer func() { externalIP = oldExternalIP }()

	externalIP = mockExternalIP

	c := make(chan metric.Metric)
	i := 10
	l := defaultLog.WithFields(l.Fields{"collector": "Mesos"})

	sut := NewMesosStats(c, i, l)

	assert.Equal(t, c, sut.channel)
	assert.Equal(t, i, sut.interval)
	assert.Equal(t, l, sut.log)
	assert.Equal(t, httptest.DefaultRemoteAddr, sut.IP)
	assert.Equal(t, http.Client{Timeout: getTimeout}, sut.client)
}

func TestMesosStatsConfigure(t *testing.T) {
	oldNewMLE := newMLE
	defer func() { newMLE = oldNewMLE }()

	newMLE = func() util.MesosLeaderElectInterface { return &MockMLE{} }

	tests := []struct {
		config map[string]interface{}
		isNil  bool
		msg    string
	}{
		{map[string]interface{}{}, true, "Config does not contain mesosNodes, so Configure should fail."},
		{map[string]interface{}{"mesosNodes": ""}, true, "Config contains empty mesosNodes, so Configure should fail."},
		{map[string]interface{}{"mesosNodes": "ip1,ip2"}, false, "Config contains mesosNodes, so Configure should work."},
	}

	for _, test := range tests {
		config := test.config
		sut := NewMesosStats(nil, 0, defaultLog)

		assert.Nil(t, sut.mesosCache, "Before *baseCollector.Configure() is called, MesosStats.mesosCache should not be created.")

		sut.Configure(config)

		switch test.isNil {
		case true:
			assert.Nil(t, sut.mesosCache, test.msg)
		case false:
			assert.NotNil(t, sut.mesosCache, test.msg)
			mock, _ := sut.mesosCache.(*MockMLE)
			assert.True(t, mock.ConfigureCalled, "*MesosLeaderElect.Configure() should be called.")
		}

	}
}

func TestMesosStatsCollect(t *testing.T) {
	oldExternalIP := externalIP
	oldNewMLE := newMLE
	oldSendMetrics := sendMetrics
	defer func() {
		externalIP = oldExternalIP
		newMLE = oldNewMLE
		sendMetrics = oldSendMetrics
	}()

	newMLE = func() util.MesosLeaderElectInterface { return &MockMLE{} }

	sendMetricsCalled := false
	c := make(chan bool)
	sendMetrics = func(m *MesosStats) {
		sendMetricsCalled = true
		c <- true
	}

	tests := []struct {
		configMap           map[string]interface{}
		externalIP          string
		isSendMetricsCalled bool
		msg                 string
	}{
		{map[string]interface{}{"mesosNodes": ""}, httptest.DefaultRemoteAddr, false, "Invalid collector config, therefore no mesosCache is initialised."},
		{map[string]interface{}{"mesosNodes": "ip1,ip2"}, "5.6.7.8", false, "Machine IP is not equal to leader IP, therefore we should skip collection."},
		{map[string]interface{}{"mesosNodes": "ip1,ip2"}, httptest.DefaultRemoteAddr, true, "Current box is leader; therefore, we should be called sendMetrics."},
	}

	for _, test := range tests {
		sendMetricsCalled = false
		configMap := test.configMap
		externalIP = func() (string, error) { return test.externalIP, nil }

		sut := NewMesosStats(nil, 0, defaultLog)
		sut.Configure(configMap)
		sut.Collect()

		switch test.isSendMetricsCalled {
		case false:
			assert.False(t, sendMetricsCalled, test.msg)
		case true:
			<-c
			assert.True(t, sendMetricsCalled, test.msg)
		}
	}
}

func TestMesosStatsSendMetrics(t *testing.T) {
	oldGetMetrics := getMetrics
	defer func() { getMetrics = oldGetMetrics }()

	expected := metric.Metric{"test", "gauge", 0.1, map[string]string{}}
	getMetrics = func(m *MesosStats, ip string) map[string]float64 {
		return map[string]float64{
			"test": 0.1,
		}
	}

	c := make(chan metric.Metric)
	sut := NewMesosStats(c, 10, defaultLog)

	go sut.sendMetrics()
	actual := <-c

	assert.Equal(t, expected, actual)
}

func TestMesosStatsGetMetrics(t *testing.T) {
	oldGetMetricsURL := getMetricsURL
	defer func() {
		getMetricsURL = oldGetMetricsURL
	}()

	tests := []struct {
		rawResponse string
		expected    map[string]float64
		msg         string
	}{
		{"{\"frameworks\\/chronos\\/messages_processed\":6784068}", map[string]float64{"frameworks.chronos.messages_processed": 6784068}, "Valid JSON should return valid metrics."},
		{"{\"frameworks\\/chronos\\/messages_processed6784068}", nil, "Invalid JSON should return nil."},
	}

	for _, test := range tests {
		expected := test.expected
		ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			w.Header().Set("Content-Type", "application/json")
			fmt.Fprintln(w, test.rawResponse)
		}))
		defer ts.Close()

		getMetricsURL = func(ip string) string { return ts.URL }

		sut := NewMesosStats(nil, 10, defaultLog)
		actual := getMetrics(sut, httptest.DefaultRemoteAddr)

		assert.Equal(t, expected, actual)
	}
}

func TestMesosStatsGetMetricsHandleErrors(t *testing.T) {
	oldGetMetricsURL := getMetricsURL
	defer func() {
		getMetricsURL = oldGetMetricsURL
	}()

	getMetricsURL = func(ip string) string { return "" }

	sut := NewMesosStats(nil, 10, defaultLog)
	actual := getMetrics(sut, httptest.DefaultRemoteAddr)

	assert.Nil(t, actual, "Empty (invalid) URL, which means http client should throw an error; therefore, we expect a nil from getMetrics")
}

func TestMesosStatsGetMetricsHandleNon200s(t *testing.T) {
	oldGetMetricsURL := getMetricsURL
	defer func() {
		getMetricsURL = oldGetMetricsURL
	}()

	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(500)
		fmt.Fprintln(w, `Custom error`)
	}))
	defer ts.Close()

	getMetricsURL = func(ip string) string { return ts.URL }

	sut := NewMesosStats(nil, 10, defaultLog)
	actual := getMetrics(sut, httptest.DefaultRemoteAddr)

	assert.Nil(t, actual, "Server threw a 500, so we should expect nil from getMetrics")
}

func TestMesosStatsBuildMetric(t *testing.T) {
	expected := metric.Metric{"test", "gauge", 0.1, map[string]string{}}

	actual := buildMetric("test", 0.1)

	assert.Equal(t, expected, actual)
}
<commit_msg>Added test for mesos cumulative cunter metrics<commit_after>package collector

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"testing"
	"time"

	"fullerite/metric"
	"fullerite/util"

	l "github.com/Sirupsen/logrus"
	"github.com/stretchr/testify/assert"
)

// MockMLE Mock for MesosLeaderElectInterface that encapsulate functionality to check if the interface methods have been called/not. We embed the interface for the case of the test because this interface has unexported methods (set()). And since the interface comes from a different package, we cannot provide a concrete implementation for it.
type MockMLE struct {
	util.MesosLeaderElectInterface
	ConfigureCalled bool
}

func (m *MockMLE) Configure(nodes string, ttl time.Duration) {
	m.ConfigureCalled = true
}

func (m *MockMLE) Get() string {
	return httptest.DefaultRemoteAddr
}

// mockExternalIP Injectable mock for externalIP, for test assertions.
func mockExternalIP() (string, error) {
	return httptest.DefaultRemoteAddr, nil
}

func TestMesosStatsNewMesosStats(t *testing.T) {
	oldExternalIP := externalIP
	defer func() { externalIP = oldExternalIP }()

	externalIP = mockExternalIP

	c := make(chan metric.Metric)
	i := 10
	l := defaultLog.WithFields(l.Fields{"collector": "Mesos"})

	sut := NewMesosStats(c, i, l)

	assert.Equal(t, c, sut.channel)
	assert.Equal(t, i, sut.interval)
	assert.Equal(t, l, sut.log)
	assert.Equal(t, httptest.DefaultRemoteAddr, sut.IP)
	assert.Equal(t, http.Client{Timeout: getTimeout}, sut.client)
}

func TestMesosStatsConfigure(t *testing.T) {
	oldNewMLE := newMLE
	defer func() { newMLE = oldNewMLE }()

	newMLE = func() util.MesosLeaderElectInterface { return &MockMLE{} }

	tests := []struct {
		config map[string]interface{}
		isNil  bool
		msg    string
	}{
		{map[string]interface{}{}, true, "Config does not contain mesosNodes, so Configure should fail."},
		{map[string]interface{}{"mesosNodes": ""}, true, "Config contains empty mesosNodes, so Configure should fail."},
		{map[string]interface{}{"mesosNodes": "ip1,ip2"}, false, "Config contains mesosNodes, so Configure should work."},
	}

	for _, test := range tests {
		config := test.config
		sut := NewMesosStats(nil, 0, defaultLog)

		assert.Nil(t, sut.mesosCache, "Before *baseCollector.Configure() is called, MesosStats.mesosCache should not be created.")

		sut.Configure(config)

		switch test.isNil {
		case true:
			assert.Nil(t, sut.mesosCache, test.msg)
		case false:
			assert.NotNil(t, sut.mesosCache, test.msg)
			mock, _ := sut.mesosCache.(*MockMLE)
			assert.True(t, mock.ConfigureCalled, "*MesosLeaderElect.Configure() should be called.")
		}

	}
}

func TestMesosStatsCollect(t *testing.T) {
	oldExternalIP := externalIP
	oldNewMLE := newMLE
	oldSendMetrics := sendMetrics
	defer func() {
		externalIP = oldExternalIP
		newMLE = oldNewMLE
		sendMetrics = oldSendMetrics
	}()

	newMLE = func() util.MesosLeaderElectInterface { return &MockMLE{} }

	sendMetricsCalled := false
	c := make(chan bool)
	sendMetrics = func(m *MesosStats) {
		sendMetricsCalled = true
		c <- true
	}

	tests := []struct {
		configMap           map[string]interface{}
		externalIP          string
		isSendMetricsCalled bool
		msg                 string
	}{
		{map[string]interface{}{"mesosNodes": ""}, httptest.DefaultRemoteAddr, false, "Invalid collector config, therefore no mesosCache is initialised."},
		{map[string]interface{}{"mesosNodes": "ip1,ip2"}, "5.6.7.8", false, "Machine IP is not equal to leader IP, therefore we should skip collection."},
		{map[string]interface{}{"mesosNodes": "ip1,ip2"}, httptest.DefaultRemoteAddr, true, "Current box is leader; therefore, we should be called sendMetrics."},
	}

	for _, test := range tests {
		sendMetricsCalled = false
		configMap := test.configMap
		externalIP = func() (string, error) { return test.externalIP, nil }

		sut := NewMesosStats(nil, 0, defaultLog)
		sut.Configure(configMap)
		sut.Collect()

		switch test.isSendMetricsCalled {
		case false:
			assert.False(t, sendMetricsCalled, test.msg)
		case true:
			<-c
			assert.True(t, sendMetricsCalled, test.msg)
		}
	}
}

func TestMesosStatsSendMetrics(t *testing.T) {
	oldGetMetrics := getMetrics
	defer func() { getMetrics = oldGetMetrics }()

	expected := metric.Metric{"test", "gauge", 0.1, map[string]string{}}
	getMetrics = func(m *MesosStats, ip string) map[string]float64 {
		return map[string]float64{
			"test": 0.1,
		}
	}

	c := make(chan metric.Metric)
	sut := NewMesosStats(c, 10, defaultLog)

	go sut.sendMetrics()
	actual := <-c

	assert.Equal(t, expected, actual)
}

func TestMesosStatsGetMetrics(t *testing.T) {
	oldGetMetricsURL := getMetricsURL
	defer func() {
		getMetricsURL = oldGetMetricsURL
	}()

	tests := []struct {
		rawResponse string
		expected    map[string]float64
		msg         string
	}{
		{"{\"frameworks\\/chronos\\/messages_processed\":6784068}", map[string]float64{"frameworks.chronos.messages_processed": 6784068}, "Valid JSON should return valid metrics."},
		{"{\"frameworks\\/chronos\\/messages_processed6784068}", nil, "Invalid JSON should return nil."},
	}

	for _, test := range tests {
		expected := test.expected
		ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			w.Header().Set("Content-Type", "application/json")
			fmt.Fprintln(w, test.rawResponse)
		}))
		defer ts.Close()

		getMetricsURL = func(ip string) string { return ts.URL }

		sut := NewMesosStats(nil, 10, defaultLog)
		actual := getMetrics(sut, httptest.DefaultRemoteAddr)

		assert.Equal(t, expected, actual)
	}
}

func TestMesosStatsGetMetricsHandleErrors(t *testing.T) {
	oldGetMetricsURL := getMetricsURL
	defer func() {
		getMetricsURL = oldGetMetricsURL
	}()

	getMetricsURL = func(ip string) string { return "" }

	sut := NewMesosStats(nil, 10, defaultLog)
	actual := getMetrics(sut, httptest.DefaultRemoteAddr)

	assert.Nil(t, actual, "Empty (invalid) URL, which means http client should throw an error; therefore, we expect a nil from getMetrics")
}

func TestMesosStatsGetMetricsHandleNon200s(t *testing.T) {
	oldGetMetricsURL := getMetricsURL
	defer func() {
		getMetricsURL = oldGetMetricsURL
	}()

	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(500)
		fmt.Fprintln(w, `Custom error`)
	}))
	defer ts.Close()

	getMetricsURL = func(ip string) string { return ts.URL }

	sut := NewMesosStats(nil, 10, defaultLog)
	actual := getMetrics(sut, httptest.DefaultRemoteAddr)

	assert.Nil(t, actual, "Server threw a 500, so we should expect nil from getMetrics")
}

func TestMesosStatsBuildMetric(t *testing.T) {
	expected := metric.Metric{"test", "gauge", 0.1, map[string]string{}}

	actual := buildMetric("test", 0.1)

	assert.Equal(t, expected, actual)
}

func TestMesosStatsBuildMetricCumCounter(t *testing.T) {
	expected := metric.Metric{"master.slave_reregistrations", metric.CumulativeCounter, 0.1, map[string]string{}}

	actual := buildMetric("master.slave_reregistrations", 0.1)

	assert.Equal(t, expected, actual)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/gonuts/commander"
	"github.com/gonuts/flag"
	"github.com/smira/aptly/debian"
	"strings"
)

func aptlySnapshotCreate(cmd *commander.Command, args []string) error {
	var err error

	if len(args) < 4 || args[1] != "from" || args[2] != "mirror" {
		cmd.Usage()
		return err
	}

	repoName, mirrorName := args[3], args[0]

	repoCollection := debian.NewRemoteRepoCollection(context.database)
	repo, err := repoCollection.ByName(repoName)
	if err != nil {
		return fmt.Errorf("unable to create snapshot: %s", err)
	}

	err = repoCollection.LoadComplete(repo)
	if err != nil {
		return fmt.Errorf("unable to create snapshot: %s", err)
	}

	snapshot, err := debian.NewSnapshotFromRepository(mirrorName, repo)
	if err != nil {
		return fmt.Errorf("unable to create snapshot: %s", err)
	}

	snapshotCollection := debian.NewSnapshotCollection(context.database)

	err = snapshotCollection.Add(snapshot)
	if err != nil {
		return fmt.Errorf("unable to add snapshot: %s", err)
	}

	fmt.Printf("\nSnapshot %s successfully created.\nYou can run 'aptly publish snapshot %s' to publish snapshot as Debian repository.\n", snapshot.Name, snapshot.Name)

	return err
}

func aptlySnapshotList(cmd *commander.Command, args []string) error {
	var err error
	if len(args) != 0 {
		cmd.Usage()
		return err
	}

	snapshotCollection := debian.NewSnapshotCollection(context.database)

	if snapshotCollection.Len() > 0 {
		fmt.Printf("List of snapshots:\n")
		snapshotCollection.ForEach(func(snapshot *debian.Snapshot) error {
			fmt.Printf(" * %s\n", snapshot)
			return nil
		})

		fmt.Printf("\nTo get more information about snapshot, run `aptly snapshot show <name>`.\n")
	} else {
		fmt.Printf("\nNo snapshots found, create one with `aptly snapshot create...`.\n")
	}
	return err

}

func aptlySnapshotShow(cmd *commander.Command, args []string) error {
	var err error
	if len(args) != 1 {
		cmd.Usage()
		return err
	}

	name := args[0]

	snapshotCollection := debian.NewSnapshotCollection(context.database)
	snapshot, err := snapshotCollection.ByName(name)
	if err != nil {
		return fmt.Errorf("unable to show: %s", err)
	}

	err = snapshotCollection.LoadComplete(snapshot)
	if err != nil {
		return fmt.Errorf("unable to show: %s", err)
	}

	fmt.Printf("Name: %s\n", snapshot.Name)
	fmt.Printf("Created At: %s\n", snapshot.CreatedAt.Format("2006-01-02 15:04:05 MST"))
	fmt.Printf("Description: %s\n", snapshot.Description)
	fmt.Printf("Number of packages: %d\n", snapshot.NumPackages())
	fmt.Printf("Packages:\n")

	packageCollection := debian.NewPackageCollection(context.database)

	err = snapshot.RefList().ForEach(func(key []byte) error {
		p, err := packageCollection.ByKey(key)
		if err != nil {
			return err
		}
		fmt.Printf("  %s\n", p)
		return nil
	})
	if err != nil {
		return fmt.Errorf("unable to load packages: %s", err)
	}

	return err
}

func aptlySnapshotVerify(cmd *commander.Command, args []string) error {
	var err error
	if len(args) < 1 {
		cmd.Usage()
		return err
	}

	snapshotCollection := debian.NewSnapshotCollection(context.database)
	packageCollection := debian.NewPackageCollection(context.database)

	snapshots := make([]*debian.Snapshot, len(args))
	for i := range snapshots {
		snapshots[i], err = snapshotCollection.ByName(args[i])
		if err != nil {
			return fmt.Errorf("unable to verify: %s", err)
		}

		err = snapshotCollection.LoadComplete(snapshots[i])
		if err != nil {
			return fmt.Errorf("unable to verify: %s", err)
		}
	}

	packageList, err := debian.NewPackageListFromRefList(snapshots[0].RefList(), packageCollection)
	if err != nil {
		fmt.Errorf("unable to load packages: %s", err)
	}

	packageIndexedList := debian.NewPackageIndexedList()
	packageIndexedList.Append(packageList)

	for i := 1; i < len(snapshots); i++ {
		pL, err := debian.NewPackageListFromRefList(snapshots[i].RefList(), packageCollection)
		if err != nil {
			fmt.Errorf("unable to load packages: %s", err)
		}

		packageIndexedList.Append(pL)
	}

	packageIndexedList.PrepareIndex()

	var architecturesList []string

	architectures := cmd.Flag.Lookup("architectures").Value.String()
	if architectures != "" {
		architecturesList = strings.Split(architectures, ",")
	} else {
		architecturesList = packageList.Architectures()
	}

	if len(architecturesList) == 0 {
		return fmt.Errorf("unable to determine list of architectures, please specify explicitly")
	}

	missing, err := packageList.VerifyDependencies(0, architecturesList, packageIndexedList)
	if err != nil {
		return fmt.Errorf("unable to verify dependencies: %s", err)
	}

	if len(missing) == 0 {
		fmt.Printf("All dependencies are satisfied.\n")
	} else {
		fmt.Printf("Missing dependencies (%d):\n", len(missing))
		for _, dep := range missing {
			fmt.Printf("  %s\n", dep.String())
		}
	}

	return err
}

func makeCmdSnapshotCreate() *commander.Command {
	cmd := &commander.Command{
		Run:       aptlySnapshotCreate,
		UsageLine: "create",
		Short:     "creates snapshot out of any mirror",
		Long: `
Create makes persistent immutable snapshot of repository mirror state in givent moment of time.

ex:
  $ aptly snapshot create <name> from mirror <mirror-name>
`,
		Flag: *flag.NewFlagSet("aptly-snapshot-create", flag.ExitOnError),
	}

	return cmd

}

func makeCmdSnapshotList() *commander.Command {
	cmd := &commander.Command{
		Run:       aptlySnapshotList,
		UsageLine: "list",
		Short:     "lists snapshots",
		Long: `
list shows full list of snapshots created.

ex:
  $ aptly snapshot list
`,
		Flag: *flag.NewFlagSet("aptly-snapshot-list", flag.ExitOnError),
	}

	return cmd
}

func makeCmdSnapshotShow() *commander.Command {
	cmd := &commander.Command{
		Run:       aptlySnapshotShow,
		UsageLine: "show",
		Short:     "shows details about snapshot",
		Long: `
shows shows full information about snapshot.

ex:
  $ aptly snapshot show <name>
`,
		Flag: *flag.NewFlagSet("aptly-snapshot-show", flag.ExitOnError),
	}

	return cmd
}

func makeCmdSnapshotVerify() *commander.Command {
	cmd := &commander.Command{
		Run:       aptlySnapshotVerify,
		UsageLine: "verify",
		Short:     "verifies that dependencies are satisfied in snapshot",
		Long: `
Verify does depenency resolution in snapshot, possibly using additional snapshots as dependency sources.
All unsatisfied dependencies are returned.

ex:
  $ aptly snapshot verify <name> [<source> ...]
`,
		Flag: *flag.NewFlagSet("aptly-snapshot-verify", flag.ExitOnError),
	}

	cmd.Flag.String("architectures", "", "list of architectures to publish (comma-separated)")

	return cmd
}

func makeCmdSnapshot() *commander.Command {
	return &commander.Command{
		UsageLine: "snapshot",
		Short:     "manage snapshots of repositories",
		Subcommands: []*commander.Command{
			makeCmdSnapshotCreate(),
			makeCmdSnapshotList(),
			makeCmdSnapshotShow(),
			makeCmdSnapshotVerify(),
			//makeCmdSnapshotDestroy(),
		},
		Flag: *flag.NewFlagSet("aptly-snapshot", flag.ExitOnError),
	}
}
<commit_msg>Snapshot pull command.<commit_after>package main

import (
	"fmt"
	"github.com/gonuts/commander"
	"github.com/gonuts/flag"
	"github.com/smira/aptly/debian"
	"github.com/wsxiaoys/terminal/color"
	"strings"
)

func aptlySnapshotCreate(cmd *commander.Command, args []string) error {
	var err error

	if len(args) < 4 || args[1] != "from" || args[2] != "mirror" {
		cmd.Usage()
		return err
	}

	repoName, mirrorName := args[3], args[0]

	repoCollection := debian.NewRemoteRepoCollection(context.database)
	repo, err := repoCollection.ByName(repoName)
	if err != nil {
		return fmt.Errorf("unable to create snapshot: %s", err)
	}

	err = repoCollection.LoadComplete(repo)
	if err != nil {
		return fmt.Errorf("unable to create snapshot: %s", err)
	}

	snapshot, err := debian.NewSnapshotFromRepository(mirrorName, repo)
	if err != nil {
		return fmt.Errorf("unable to create snapshot: %s", err)
	}

	snapshotCollection := debian.NewSnapshotCollection(context.database)

	err = snapshotCollection.Add(snapshot)
	if err != nil {
		return fmt.Errorf("unable to add snapshot: %s", err)
	}

	fmt.Printf("\nSnapshot %s successfully created.\nYou can run 'aptly publish snapshot %s' to publish snapshot as Debian repository.\n", snapshot.Name, snapshot.Name)

	return err
}

func aptlySnapshotList(cmd *commander.Command, args []string) error {
	var err error
	if len(args) != 0 {
		cmd.Usage()
		return err
	}

	snapshotCollection := debian.NewSnapshotCollection(context.database)

	if snapshotCollection.Len() > 0 {
		fmt.Printf("List of snapshots:\n")
		snapshotCollection.ForEach(func(snapshot *debian.Snapshot) error {
			fmt.Printf(" * %s\n", snapshot)
			return nil
		})

		fmt.Printf("\nTo get more information about snapshot, run `aptly snapshot show <name>`.\n")
	} else {
		fmt.Printf("\nNo snapshots found, create one with `aptly snapshot create...`.\n")
	}
	return err

}

func aptlySnapshotShow(cmd *commander.Command, args []string) error {
	var err error
	if len(args) != 1 {
		cmd.Usage()
		return err
	}

	name := args[0]

	snapshotCollection := debian.NewSnapshotCollection(context.database)
	snapshot, err := snapshotCollection.ByName(name)
	if err != nil {
		return fmt.Errorf("unable to show: %s", err)
	}

	err = snapshotCollection.LoadComplete(snapshot)
	if err != nil {
		return fmt.Errorf("unable to show: %s", err)
	}

	fmt.Printf("Name: %s\n", snapshot.Name)
	fmt.Printf("Created At: %s\n", snapshot.CreatedAt.Format("2006-01-02 15:04:05 MST"))
	fmt.Printf("Description: %s\n", snapshot.Description)
	fmt.Printf("Number of packages: %d\n", snapshot.NumPackages())
	fmt.Printf("Packages:\n")

	packageCollection := debian.NewPackageCollection(context.database)

	err = snapshot.RefList().ForEach(func(key []byte) error {
		p, err := packageCollection.ByKey(key)
		if err != nil {
			return err
		}
		fmt.Printf("  %s\n", p)
		return nil
	})
	if err != nil {
		return fmt.Errorf("unable to load packages: %s", err)
	}

	return err
}

func aptlySnapshotVerify(cmd *commander.Command, args []string) error {
	var err error
	if len(args) < 1 {
		cmd.Usage()
		return err
	}

	snapshotCollection := debian.NewSnapshotCollection(context.database)
	packageCollection := debian.NewPackageCollection(context.database)

	snapshots := make([]*debian.Snapshot, len(args))
	for i := range snapshots {
		snapshots[i], err = snapshotCollection.ByName(args[i])
		if err != nil {
			return fmt.Errorf("unable to verify: %s", err)
		}

		err = snapshotCollection.LoadComplete(snapshots[i])
		if err != nil {
			return fmt.Errorf("unable to verify: %s", err)
		}
	}

	packageList, err := debian.NewPackageListFromRefList(snapshots[0].RefList(), packageCollection)
	if err != nil {
		fmt.Errorf("unable to load packages: %s", err)
	}

	sourcePackageList := debian.NewPackageList()
	err = sourcePackageList.Append(packageList)
	if err != nil {
		fmt.Errorf("unable to merge sources: %s", err)
	}

	for i := 1; i < len(snapshots); i++ {
		pL, err := debian.NewPackageListFromRefList(snapshots[i].RefList(), packageCollection)
		if err != nil {
			fmt.Errorf("unable to load packages: %s", err)
		}

		err = sourcePackageList.Append(pL)
		if err != nil {
			fmt.Errorf("unable to merge sources: %s", err)
		}
	}

	sourcePackageList.PrepareIndex()

	var architecturesList []string

	architectures := cmd.Flag.Lookup("architectures").Value.String()
	if architectures != "" {
		architecturesList = strings.Split(architectures, ",")
	} else {
		architecturesList = packageList.Architectures()
	}

	if len(architecturesList) == 0 {
		return fmt.Errorf("unable to determine list of architectures, please specify explicitly")
	}

	missing, err := packageList.VerifyDependencies(0, architecturesList, sourcePackageList)
	if err != nil {
		return fmt.Errorf("unable to verify dependencies: %s", err)
	}

	if len(missing) == 0 {
		fmt.Printf("All dependencies are satisfied.\n")
	} else {
		fmt.Printf("Missing dependencies (%d):\n", len(missing))
		for _, dep := range missing {
			fmt.Printf("  %s\n", dep.String())
		}
	}

	return err
}

func aptlySnapshotPull(cmd *commander.Command, args []string) error {
	var err error
	if len(args) < 4 {
		cmd.Usage()
		return err
	}

	snapshotCollection := debian.NewSnapshotCollection(context.database)
	packageCollection := debian.NewPackageCollection(context.database)

	// Load <name> snapshot
	snapshot, err := snapshotCollection.ByName(args[0])
	if err != nil {
		return fmt.Errorf("unable to pull: %s", err)
	}

	err = snapshotCollection.LoadComplete(snapshot)
	if err != nil {
		return fmt.Errorf("unable to pull: %s", err)
	}

	// Load <source> snapshot
	source, err := snapshotCollection.ByName(args[1])
	if err != nil {
		return fmt.Errorf("unable to pull: %s", err)
	}

	err = snapshotCollection.LoadComplete(source)
	if err != nil {
		return fmt.Errorf("unable to pull: %s", err)
	}

	fmt.Printf("Dependencies would be pulled into snapshot:\n    %s\nfrom snapshot:\n    %s\nand result would be saved as new snapshot %s.\n",
		snapshot, source, args[2])

	// Convert snapshot to package list
	fmt.Printf("Loading packages (%d)...\n", snapshot.RefList().Len()+source.RefList().Len())
	packageList, err := debian.NewPackageListFromRefList(snapshot.RefList(), packageCollection)
	if err != nil {
		return fmt.Errorf("unable to load packages: %s", err)
	}

	sourcePackageList, err := debian.NewPackageListFromRefList(source.RefList(), packageCollection)
	if err != nil {
		return fmt.Errorf("unable to load packages: %s", err)
	}

	fmt.Printf("Building indexes...\n")
	packageList.PrepareIndex()
	sourcePackageList.PrepareIndex()

	// Calculate architectures
	var architecturesList []string

	architectures := cmd.Flag.Lookup("architectures").Value.String()
	if architectures != "" {
		architecturesList = strings.Split(architectures, ",")
	} else {
		architecturesList = packageList.Architectures()
	}

	if len(architecturesList) == 0 {
		return fmt.Errorf("unable to determine list of architectures, please specify explicitly")
	}

	// Initial dependencies out of arguments
	initialDependencies := make([]debian.Dependency, len(args)-3)
	for i, arg := range args[3:] {
		initialDependencies[i], err = debian.ParseDependency(arg)
		if err != nil {
			return fmt.Errorf("unable to parse argument: %s", err)
		}
	}

	// Perform pull
	for _, arch := range architecturesList {
		dependencies := make([]debian.Dependency, len(initialDependencies), 128)
		for i := range dependencies {
			dependencies[i] = initialDependencies[i]
			dependencies[i].Architecture = arch
		}

		// Go over list of initial dependencies + list of dependencies found
		for i := 0; i < len(dependencies); i++ {
			dep := dependencies[i]

			// Search for package that can satisfy dependencies
			pkg := sourcePackageList.Search(dep)
			if pkg == nil {
				color.Printf("@y[!]@| @!Dependency %s can't be satisfied with source %s@|\n", &dep, source)
				continue
			}

			// Remove all packages with the same name and architecture
			for p := packageList.Search(debian.Dependency{Architecture: arch, Pkg: pkg.Name}); p != nil; {
				packageList.Remove(p)
				color.Printf("@r[-]@| %s removed\n", p)
				p = packageList.Search(debian.Dependency{Architecture: arch, Pkg: pkg.Name})
			}

			// Add new discovered package
			packageList.Add(pkg)
			color.Printf("@g[+]@| %s added\n", pkg)

			// Find missing dependencies for single added package
			pL := debian.NewPackageList()
			pL.Add(pkg)

			missing, err := pL.VerifyDependencies(0, []string{arch}, packageList)
			if err != nil {
				color.Printf("@y[!]@| @!Error while verifying dependencies for pkg %s: %s@|\n", pkg, err)
			}

			// Append missing dependencies to the list of dependencies to satisfy
			for _, misDep := range missing {
				found := false
				for _, d := range dependencies {
					if d == misDep {
						found = true
						break
					}
				}

				if !found {
					dependencies = append(dependencies, misDep)
				}
			}
		}
	}

	// Create <destination> snapshot
	destination := debian.NewSnapshotFromPackageList(args[2], []*debian.Snapshot{snapshot, source}, packageList,
		fmt.Sprintf("Pulled into '%s' with '%s' as source, pull request was: '%s'", snapshot.Name, source.Name, strings.Join(args[3:], " ")))

	err = snapshotCollection.Add(destination)
	if err != nil {
		return fmt.Errorf("unable to create snapshot: %s", err)
	}

	fmt.Printf("\nSnapshot %s successfully created.\nYou can run 'aptly publish snapshot %s' to publish snapshot as Debian repository.\n", destination.Name, destination.Name)

	return err
}

func makeCmdSnapshotCreate() *commander.Command {
	cmd := &commander.Command{
		Run:       aptlySnapshotCreate,
		UsageLine: "create <name> from mirror <mirror-name>",
		Short:     "creates snapshot out of any mirror",
		Long: `
Create makes persistent immutable snapshot of repository mirror state in givent moment of time.
`,
		Flag: *flag.NewFlagSet("aptly-snapshot-create", flag.ExitOnError),
	}

	return cmd

}

func makeCmdSnapshotList() *commander.Command {
	cmd := &commander.Command{
		Run:       aptlySnapshotList,
		UsageLine: "list",
		Short:     "lists snapshots",
		Long: `
list shows full list of snapshots created.

ex:
  $ aptly snapshot list
`,
		Flag: *flag.NewFlagSet("aptly-snapshot-list", flag.ExitOnError),
	}

	return cmd
}

func makeCmdSnapshotShow() *commander.Command {
	cmd := &commander.Command{
		Run:       aptlySnapshotShow,
		UsageLine: "show <name>",
		Short:     "shows details about snapshot",
		Long: `
Show shows full information about snapshot.
`,
		Flag: *flag.NewFlagSet("aptly-snapshot-show", flag.ExitOnError),
	}

	return cmd
}

func makeCmdSnapshotVerify() *commander.Command {
	cmd := &commander.Command{
		Run:       aptlySnapshotVerify,
		UsageLine: "verify <name> [<source> ...]",
		Short:     "verifies that dependencies are satisfied in snapshot",
		Long: `
Verify does depenency resolution in snapshot, possibly using additional snapshots as dependency sources.
All unsatisfied dependencies are returned.
`,
		Flag: *flag.NewFlagSet("aptly-snapshot-verify", flag.ExitOnError),
	}

	cmd.Flag.String("architectures", "", "list of architectures to verify (comma-separated)")

	return cmd
}

func makeCmdSnapshotPull() *commander.Command {
	cmd := &commander.Command{
		Run:       aptlySnapshotPull,
		UsageLine: "pull <name> <source> <destination> <package-name> ...",
		Short:     "performs partial upgrades (pulls new packages) from another snapshot",
		Long: `
Pulls (upgrades) new packages (upgrades version) along with its dependencies in <name> snapshot
from <source> snapshot. New snapshot <destination> is created.
`,
		Flag: *flag.NewFlagSet("aptly-snapshot-pull", flag.ExitOnError),
	}

	cmd.Flag.String("architectures", "", "list of architectures to consider during pull (comma-separated)")

	return cmd
}

func makeCmdSnapshot() *commander.Command {
	return &commander.Command{
		UsageLine: "snapshot",
		Short:     "manage snapshots of repositories",
		Subcommands: []*commander.Command{
			makeCmdSnapshotCreate(),
			makeCmdSnapshotList(),
			makeCmdSnapshotShow(),
			makeCmdSnapshotVerify(),
			makeCmdSnapshotPull(),
			//makeCmdSnapshotDestroy(),
		},
		Flag: *flag.NewFlagSet("aptly-snapshot", flag.ExitOnError),
	}
}
<|endoftext|>


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

package http_test

import (
	"context"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/signal"
)

func ExampleHijacker() {
	http.HandleFunc("/hijack", func(w http.ResponseWriter, r *http.Request) {
		hj, ok := w.(http.Hijacker)
		if !ok {
			http.Error(w, "webserver doesn't support hijacking", http.StatusInternalServerError)
			return
		}
		conn, bufrw, err := hj.Hijack()
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		// Don't forget to close the connection:
		defer conn.Close()
		bufrw.WriteString("Now we're speaking raw TCP. Say hi: ")
		bufrw.Flush()
		s, err := bufrw.ReadString('\n')
		if err != nil {
			log.Printf("error reading string: %v", err)
			return
		}
		fmt.Fprintf(bufrw, "You said: %q\nBye.\n", s)
		bufrw.Flush()
	})
}

func ExampleGet() {
	res, err := http.Get("http://www.google.com/robots.txt")
	if err != nil {
		log.Fatal(err)
	}
	robots, err := io.ReadAll(res.Body)
	res.Body.Close()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s", robots)
}

func ExampleFileServer() {
	// Simple static webserver:
	log.Fatal(http.ListenAndServe(":8080", http.FileServer(http.Dir("/usr/share/doc"))))
}

func ExampleFileServer_stripPrefix() {
	// To serve a directory on disk (/tmp) under an alternate URL
	// path (/tmpfiles/), use StripPrefix to modify the request
	// URL's path before the FileServer sees it:
	http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp"))))
}

func ExampleStripPrefix() {
	// To serve a directory on disk (/tmp) under an alternate URL
	// path (/tmpfiles/), use StripPrefix to modify the request
	// URL's path before the FileServer sees it:
	http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp"))))
}

type apiHandler struct{}

func (apiHandler) ServeHTTP(http.ResponseWriter, *http.Request) {}

func ExampleServeMux_Handle() {
	mux := http.NewServeMux()
	mux.Handle("/api/", apiHandler{})
	mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
		// The "/" pattern matches everything, so we need to check
		// that we're at the root here.
		if req.URL.Path != "/" {
			http.NotFound(w, req)
			return
		}
		fmt.Fprintf(w, "Welcome to the home page!")
	})
}

// HTTP Trailers are a set of key/value pairs like headers that come
// after the HTTP response, instead of before.
func ExampleResponseWriter_trailers() {
	mux := http.NewServeMux()
	mux.HandleFunc("/sendstrailers", func(w http.ResponseWriter, req *http.Request) {
		// Before any call to WriteHeader or Write, declare
		// the trailers you will set during the HTTP
		// response. These three headers are actually sent in
		// the trailer.
		w.Header().Set("Trailer", "AtEnd1, AtEnd2")
		w.Header().Add("Trailer", "AtEnd3")

		w.Header().Set("Content-Type", "text/plain; charset=utf-8") // normal header
		w.WriteHeader(http.StatusOK)

		w.Header().Set("AtEnd1", "value 1")
		io.WriteString(w, "This HTTP response has both headers before this text and trailers at the end.\n")
		w.Header().Set("AtEnd2", "value 2")
		w.Header().Set("AtEnd3", "value 3") // These will appear as trailers.
	})
}

func ExampleServer_Shutdown() {
	var srv http.Server

	idleConnsClosed := make(chan struct{})
	go func() {
		sigint := make(chan os.Signal, 1)
		signal.Notify(sigint, os.Interrupt)
		<-sigint

		// We received an interrupt signal, shut down.
		if err := srv.Shutdown(context.Background()); err != nil {
			// Error from closing listeners, or context timeout:
			log.Printf("HTTP server Shutdown: %v", err)
		}
		close(idleConnsClosed)
	}()

	if err := srv.ListenAndServe(); err != http.ErrServerClosed {
		// Error starting or closing listener:
		log.Fatalf("HTTP server ListenAndServe: %v", err)
	}

	<-idleConnsClosed
}

func ExampleListenAndServeTLS() {
	http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
		io.WriteString(w, "Hello, TLS!\n")
	})

	// One can use generate_cert.go in crypto/tls to generate cert.pem and key.pem.
	log.Printf("About to listen on 8443. Go to https://127.0.0.1:8443/")
	err := http.ListenAndServeTLS(":8443", "cert.pem", "key.pem", nil)
	log.Fatal(err)
}

func ExampleListenAndServe() {
	// Hello world, the web server

	helloHandler := func(w http.ResponseWriter, req *http.Request) {
		io.WriteString(w, "Hello, world!\n")
	}

	http.HandleFunc("/hello", helloHandler)
	log.Fatal(http.ListenAndServe(":8080", nil))
}

func ExampleHandleFunc() {
	h1 := func(w http.ResponseWriter, _ *http.Request) {
		io.WriteString(w, "Hello from a HandleFunc #1!\n")
	}
	h2 := func(w http.ResponseWriter, _ *http.Request) {
		io.WriteString(w, "Hello from a HandleFunc #2!\n")
	}

	http.HandleFunc("/", h1)
	http.HandleFunc("/endpoint", h2)

	log.Fatal(http.ListenAndServe(":8080", nil))
}

func newPeopleHandler() http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintln(w, "This is the people handler.")
	})
}

func ExampleNotFoundHandler() {
	mux := http.NewServeMux()

	// Create sample handler to returns 404
	mux.Handle("/resources", http.NotFoundHandler())

	// Create sample handler that returns 200
	mux.Handle("/resources/people/", newPeopleHandler())

	log.Fatal(http.ListenAndServe(":8080", mux))
}
<commit_msg>net/http: make ExampleGet show StatusCode checks for non-1XX,2XX responses<commit_after>// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package http_test

import (
	"context"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/signal"
)

func ExampleHijacker() {
	http.HandleFunc("/hijack", func(w http.ResponseWriter, r *http.Request) {
		hj, ok := w.(http.Hijacker)
		if !ok {
			http.Error(w, "webserver doesn't support hijacking", http.StatusInternalServerError)
			return
		}
		conn, bufrw, err := hj.Hijack()
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		// Don't forget to close the connection:
		defer conn.Close()
		bufrw.WriteString("Now we're speaking raw TCP. Say hi: ")
		bufrw.Flush()
		s, err := bufrw.ReadString('\n')
		if err != nil {
			log.Printf("error reading string: %v", err)
			return
		}
		fmt.Fprintf(bufrw, "You said: %q\nBye.\n", s)
		bufrw.Flush()
	})
}

func ExampleGet() {
	res, err := http.Get("http://www.google.com/robots.txt")
	if err != nil {
		log.Fatal(err)
	}
	body, err := io.ReadAll(res.Body)
	res.Body.Close()
	if res.StatusCode > 299 {
		log.Fatalf("Response failed with status code: %d and\nbody: %s\n", res.StatusCode, body)
	}
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s", body)
}

func ExampleFileServer() {
	// Simple static webserver:
	log.Fatal(http.ListenAndServe(":8080", http.FileServer(http.Dir("/usr/share/doc"))))
}

func ExampleFileServer_stripPrefix() {
	// To serve a directory on disk (/tmp) under an alternate URL
	// path (/tmpfiles/), use StripPrefix to modify the request
	// URL's path before the FileServer sees it:
	http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp"))))
}

func ExampleStripPrefix() {
	// To serve a directory on disk (/tmp) under an alternate URL
	// path (/tmpfiles/), use StripPrefix to modify the request
	// URL's path before the FileServer sees it:
	http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp"))))
}

type apiHandler struct{}

func (apiHandler) ServeHTTP(http.ResponseWriter, *http.Request) {}

func ExampleServeMux_Handle() {
	mux := http.NewServeMux()
	mux.Handle("/api/", apiHandler{})
	mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
		// The "/" pattern matches everything, so we need to check
		// that we're at the root here.
		if req.URL.Path != "/" {
			http.NotFound(w, req)
			return
		}
		fmt.Fprintf(w, "Welcome to the home page!")
	})
}

// HTTP Trailers are a set of key/value pairs like headers that come
// after the HTTP response, instead of before.
func ExampleResponseWriter_trailers() {
	mux := http.NewServeMux()
	mux.HandleFunc("/sendstrailers", func(w http.ResponseWriter, req *http.Request) {
		// Before any call to WriteHeader or Write, declare
		// the trailers you will set during the HTTP
		// response. These three headers are actually sent in
		// the trailer.
		w.Header().Set("Trailer", "AtEnd1, AtEnd2")
		w.Header().Add("Trailer", "AtEnd3")

		w.Header().Set("Content-Type", "text/plain; charset=utf-8") // normal header
		w.WriteHeader(http.StatusOK)

		w.Header().Set("AtEnd1", "value 1")
		io.WriteString(w, "This HTTP response has both headers before this text and trailers at the end.\n")
		w.Header().Set("AtEnd2", "value 2")
		w.Header().Set("AtEnd3", "value 3") // These will appear as trailers.
	})
}

func ExampleServer_Shutdown() {
	var srv http.Server

	idleConnsClosed := make(chan struct{})
	go func() {
		sigint := make(chan os.Signal, 1)
		signal.Notify(sigint, os.Interrupt)
		<-sigint

		// We received an interrupt signal, shut down.
		if err := srv.Shutdown(context.Background()); err != nil {
			// Error from closing listeners, or context timeout:
			log.Printf("HTTP server Shutdown: %v", err)
		}
		close(idleConnsClosed)
	}()

	if err := srv.ListenAndServe(); err != http.ErrServerClosed {
		// Error starting or closing listener:
		log.Fatalf("HTTP server ListenAndServe: %v", err)
	}

	<-idleConnsClosed
}

func ExampleListenAndServeTLS() {
	http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
		io.WriteString(w, "Hello, TLS!\n")
	})

	// One can use generate_cert.go in crypto/tls to generate cert.pem and key.pem.
	log.Printf("About to listen on 8443. Go to https://127.0.0.1:8443/")
	err := http.ListenAndServeTLS(":8443", "cert.pem", "key.pem", nil)
	log.Fatal(err)
}

func ExampleListenAndServe() {
	// Hello world, the web server

	helloHandler := func(w http.ResponseWriter, req *http.Request) {
		io.WriteString(w, "Hello, world!\n")
	}

	http.HandleFunc("/hello", helloHandler)
	log.Fatal(http.ListenAndServe(":8080", nil))
}

func ExampleHandleFunc() {
	h1 := func(w http.ResponseWriter, _ *http.Request) {
		io.WriteString(w, "Hello from a HandleFunc #1!\n")
	}
	h2 := func(w http.ResponseWriter, _ *http.Request) {
		io.WriteString(w, "Hello from a HandleFunc #2!\n")
	}

	http.HandleFunc("/", h1)
	http.HandleFunc("/endpoint", h2)

	log.Fatal(http.ListenAndServe(":8080", nil))
}

func newPeopleHandler() http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintln(w, "This is the people handler.")
	})
}

func ExampleNotFoundHandler() {
	mux := http.NewServeMux()

	// Create sample handler to returns 404
	mux.Handle("/resources", http.NotFoundHandler())

	// Create sample handler that returns 200
	mux.Handle("/resources/people/", newPeopleHandler())

	log.Fatal(http.ListenAndServe(":8080", mux))
}
<|endoftext|>


<commit_before>/*
 *
 * 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 cmds

import (
	"fmt"

	"github.com/fabric8io/gofabric8/util"
	"github.com/spf13/cobra"
	yaml "gopkg.in/yaml.v2"
	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/unversioned"
	k8client "k8s.io/kubernetes/pkg/client/unversioned"
	cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
)

type EnvironmentData struct {
	Name      string `yaml:"name"`
	Namespace string `yaml:"namespace"`
	Order     int    `yaml:"order"`
}

func NewCmdGetEnviron(f *cmdutil.Factory) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "environ",
		Short: "Get environment from fabric8-environments configmap",
		Run: func(cmd *cobra.Command, args []string) {
			c, ns := getKubeClient(cmd, f)
			selector, err := unversioned.LabelSelectorAsSelector(
				&unversioned.LabelSelector{MatchLabels: map[string]string{"kind": "environments"}})
			cmdutil.CheckErr(err)

			cfgmap, err := c.ConfigMaps(ns).List(api.ListOptions{LabelSelector: selector})
			cmdutil.CheckErr(err)

			fmt.Printf("%-10s DATA\n", "ENV")
			for _, item := range cfgmap.Items {
				for key, data := range item.Data {
					var ed EnvironmentData
					err := yaml.Unmarshal([]byte(data), &ed)
					cmdutil.CheckErr(err)
					fmt.Printf("%-10s name=%s namespace=%s order=%d\n",
						key, ed.Name, ed.Namespace, ed.Order)
				}
			}
		},
	}
	// NB(chmou): we may try to do the whole shenanigans like kubectl/oc does for
	// outputting stuff but currently this is like swatting flies with a
	// sledgehammer.
	// cmdutil.AddPrinterFlags(cmd)
	return cmd
}

func getKubeClient(cmd *cobra.Command, f *cmdutil.Factory) (c *k8client.Client, ns string) {
	c, _, err := keepTryingToGetClient(f)
	cmdutil.CheckErr(err)
	ns, _, err = f.DefaultNamespace()
	cmdutil.CheckErr(err)

	return c, ns
}

func NewCmdDeleteEnviron(f *cmdutil.Factory) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "environ",
		Short: "Delete environment from fabric8-environments configmap",
		Run: func(cmd *cobra.Command, args []string) {
			c, ns := getKubeClient(cmd, f)
			selector, err := unversioned.LabelSelectorAsSelector(
				&unversioned.LabelSelector{MatchLabels: map[string]string{"kind": "environments"}})
			cmdutil.CheckErr(err)

			if len(args) == 0 {
				util.Errorf("Delete command requires the name of the environment as a parameter\n.")
				return
			}

			cfgmap, err := c.ConfigMaps(ns).List(api.ListOptions{LabelSelector: selector})
			cmdutil.CheckErr(err)

			//  get all environ names
			var environNames []string

			//fmt.Printf("%-10s DATA\n", "ENV")
			for _, item := range cfgmap.Items {
				for _, data := range item.Data {
					var ed EnvironmentData
					err := yaml.Unmarshal([]byte(data), &ed)
					cmdutil.CheckErr(err)
					//fmt.Printf("%-10s name=%s namespace=%s order=%d\n", key, ed.Name, ed.Namespace, ed.Order)
					environNames = append(environNames, ed.Name)
				}
			}

			for _, arg := range args {
				found := false
				for _, env := range environNames {
					if arg == env {
						found = true
						break
					}
				}
				if !found {
					util.Errorf("Could not find environment named %s.\n", arg)
					return
				}
			}
		},
	}
	// NB(chmou): we may try to do the whole shenanigans like kubectl/oc does for
	// outputting stuff but currently this is like swatting flies with a
	// sledgehammer.
	// cmdutil.AddPrinterFlags(cmd)
	return cmd
}
<commit_msg>removing in memory entry for delte environ some-name<commit_after>/*
 *
 * 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 cmds

import (
	"fmt"

	"github.com/fabric8io/gofabric8/util"
	"github.com/spf13/cobra"
	yaml "gopkg.in/yaml.v2"
	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/unversioned"
	k8client "k8s.io/kubernetes/pkg/client/unversioned"
	cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
)

type EnvironmentData struct {
	Name      string `yaml:"name"`
	Namespace string `yaml:"namespace"`
	Order     int    `yaml:"order"`
}

func NewCmdGetEnviron(f *cmdutil.Factory) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "environ",
		Short: "Get environment from fabric8-environments configmap",
		Run: func(cmd *cobra.Command, args []string) {
			c, ns := getKubeClient(cmd, f)
			selector, err := unversioned.LabelSelectorAsSelector(
				&unversioned.LabelSelector{MatchLabels: map[string]string{"kind": "environments"}})
			cmdutil.CheckErr(err)

			cfgmap, err := c.ConfigMaps(ns).List(api.ListOptions{LabelSelector: selector})
			cmdutil.CheckErr(err)

			fmt.Printf("%-10s DATA\n", "ENV")
			for _, item := range cfgmap.Items {
				for key, data := range item.Data {
					var ed EnvironmentData
					err := yaml.Unmarshal([]byte(data), &ed)
					cmdutil.CheckErr(err)
					fmt.Printf("%-10s name=%s namespace=%s order=%d\n",
						key, ed.Name, ed.Namespace, ed.Order)
				}
			}
		},
	}
	// NB(chmou): we may try to do the whole shenanigans like kubectl/oc does for
	// outputting stuff but currently this is like swatting flies with a
	// sledgehammer.
	// cmdutil.AddPrinterFlags(cmd)
	return cmd
}

func getKubeClient(cmd *cobra.Command, f *cmdutil.Factory) (c *k8client.Client, ns string) {
	c, _, err := keepTryingToGetClient(f)
	cmdutil.CheckErr(err)
	ns, _, err = f.DefaultNamespace()
	cmdutil.CheckErr(err)

	return c, ns
}

// NewCmdDeleteEnviron is a command to delete an environ using: gofabric8 delete environ abcd
func NewCmdDeleteEnviron(f *cmdutil.Factory) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "environ",
		Short: "Delete environment from fabric8-environments configmap",
		Run: func(cmd *cobra.Command, args []string) {
			c, ns := getKubeClient(cmd, f)
			selector, err := unversioned.LabelSelectorAsSelector(
				&unversioned.LabelSelector{MatchLabels: map[string]string{"kind": "environments"}})
			cmdutil.CheckErr(err)

			if len(args) == 0 {
				util.Errorf("Delete command requires the name of the environment as a parameter\n.")
				return
			}

			cfgmap, err := c.ConfigMaps(ns).List(api.ListOptions{LabelSelector: selector})
			cmdutil.CheckErr(err)

			/*
				fmt.Printf("Config map: %#v\n", cfgmap)
				for _, item := range cfgmap.Items {
					fmt.Printf("Config map items: %#v\n", item)
					for _, data := range item.Data {
						fmt.Printf("Config map items data : %#v\n", data)
					}
				}
			*/

			//  get all environ names
			var environNames []string

			//fmt.Printf("%-10s DATA\n", "ENV")
			for _, item := range cfgmap.Items {
				for _, data := range item.Data {
					var ed EnvironmentData
					err := yaml.Unmarshal([]byte(data), &ed)
					cmdutil.CheckErr(err)
					//fmt.Printf("%-10s name=%s namespace=%s order=%d\n", key, ed.Name, ed.Namespace, ed.Order)
					environNames = append(environNames, ed.Name)
				}
			}

			fmt.Println("environNames")
			for _, v := range environNames {
				fmt.Println(v)
			}

			// args is a list of config map names
			for _, arg := range args {
				found := false
				for _, env := range environNames {
					if arg == env {
						found = true
						break
					}
				}
				if !found {
					util.Errorf("Could not find environment named %s.\n", arg)
					return
				}
			}

			// remove the entry from the config map
			for _, arg := range args {
				for _, item := range cfgmap.Items {
					for k, data := range item.Data {
						var ed EnvironmentData
						err := yaml.Unmarshal([]byte(data), &ed)
						cmdutil.CheckErr(err)

						if arg == ed.Name {
							delete(item.Data, k)
						}

					}
				}
			}

			/*
				fmt.Printf("Config map: %#v\n", cfgmap)
				for _, item := range cfgmap.Items {
					fmt.Printf("Config map items: %#v\n", item)
					for _, data := range item.Data {
						fmt.Printf("Config map items data : %#v\n", data)
					}
				}
			*/
			// I can see that the entry is removed here if I run: ./gofabric8 delete environ Production
			// Was:
			// Config map items data : "name: Staging\nnamespace: default-staging\norder: 0"
			// Config map items data : "name: Production\nnamespace: default-production\norder: 1"

			// Is:
			// Config map items data : "name: Production\nnamespace: default-production\norder: 1"

		},
	}
	return cmd
}
<|endoftext|>


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

package trace_test

import (
	"bytes"
	"internal/trace"
	"net"
	"os"
	"runtime"
	. "runtime/trace"
	"sync"
	"testing"
	"time"
)

// TestTraceSymbolize tests symbolization and that events has proper stacks.
// In particular that we strip bottom uninteresting frames like goexit,
// top uninteresting frames (runtime guts).
func TestTraceSymbolize(t *testing.T) {
	skipTraceTestsIfNeeded(t)
	if runtime.GOOS == "nacl" {
		t.Skip("skipping: nacl tests fail with 'failed to symbolize trace: failed to start addr2line'")
	}
	buf := new(bytes.Buffer)
	if err := Start(buf); err != nil {
		t.Fatalf("failed to start tracing: %v", err)
	}

	// Now we will do a bunch of things for which we verify stacks later.
	// It is impossible to ensure that a goroutine has actually blocked
	// on a channel, in a select or otherwise. So we kick off goroutines
	// that need to block first in the hope that while we are executing
	// the rest of the test, they will block.
	go func() {
		select {}
	}()
	go func() {
		var c chan int
		c <- 0
	}()
	go func() {
		var c chan int
		<-c
	}()
	done1 := make(chan bool)
	go func() {
		<-done1
	}()
	done2 := make(chan bool)
	go func() {
		done2 <- true
	}()
	c1 := make(chan int)
	c2 := make(chan int)
	go func() {
		select {
		case <-c1:
		case <-c2:
		}
	}()
	var mu sync.Mutex
	mu.Lock()
	go func() {
		mu.Lock()
		mu.Unlock()
	}()
	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		wg.Wait()
	}()
	cv := sync.NewCond(&sync.Mutex{})
	go func() {
		cv.L.Lock()
		cv.Wait()
		cv.L.Unlock()
	}()
	ln, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		t.Fatalf("failed to listen: %v", err)
	}
	go func() {
		c, err := ln.Accept()
		if err != nil {
			t.Fatalf("failed to accept: %v", err)
		}
		c.Close()
	}()
	rp, wp, err := os.Pipe()
	if err != nil {
		t.Fatalf("failed to create a pipe: %v", err)
	}
	defer rp.Close()
	defer wp.Close()
	pipeReadDone := make(chan bool)
	go func() {
		var data [1]byte
		rp.Read(data[:])
		pipeReadDone <- true
	}()

	time.Sleep(time.Millisecond)
	runtime.GC()
	runtime.Gosched()
	time.Sleep(time.Millisecond) // the last chance for the goroutines above to block
	done1 <- true
	<-done2
	select {
	case c1 <- 0:
	case c2 <- 0:
	}
	mu.Unlock()
	wg.Done()
	cv.Signal()
	c, err := net.Dial("tcp", ln.Addr().String())
	if err != nil {
		t.Fatalf("failed to dial: %v", err)
	}
	c.Close()
	var data [1]byte
	wp.Write(data[:])
	<-pipeReadDone

	Stop()
	events, _, err := parseTrace(buf)
	if err != nil {
		t.Fatalf("failed to parse trace: %v", err)
	}
	err = trace.Symbolize(events, os.Args[0])
	if err != nil {
		t.Fatalf("failed to symbolize trace: %v", err)
	}

	// Now check that the stacks are correct.
	type frame struct {
		Fn   string
		Line int
	}
	type eventDesc struct {
		Type byte
		Stk  []frame
	}
	want := []eventDesc{
		eventDesc{trace.EvGCStart, []frame{
			frame{"runtime.GC", 0},
			frame{"runtime/trace_test.TestTraceSymbolize", 106},
			frame{"testing.tRunner", 0},
		}},
		eventDesc{trace.EvGoSched, []frame{
			frame{"runtime/trace_test.TestTraceSymbolize", 107},
			frame{"testing.tRunner", 0},
		}},
		eventDesc{trace.EvGoCreate, []frame{
			frame{"runtime/trace_test.TestTraceSymbolize", 39},
			frame{"testing.tRunner", 0},
		}},
		eventDesc{trace.EvGoStop, []frame{
			frame{"runtime.block", 0},
			frame{"runtime/trace_test.TestTraceSymbolize.func1", 38},
		}},
		eventDesc{trace.EvGoStop, []frame{
			frame{"runtime.chansend1", 0},
			frame{"runtime/trace_test.TestTraceSymbolize.func2", 42},
		}},
		eventDesc{trace.EvGoStop, []frame{
			frame{"runtime.chanrecv1", 0},
			frame{"runtime/trace_test.TestTraceSymbolize.func3", 46},
		}},
		eventDesc{trace.EvGoBlockRecv, []frame{
			frame{"runtime.chanrecv1", 0},
			frame{"runtime/trace_test.TestTraceSymbolize.func4", 50},
		}},
		eventDesc{trace.EvGoUnblock, []frame{
			frame{"runtime.chansend1", 0},
			frame{"runtime/trace_test.TestTraceSymbolize", 109},
			frame{"testing.tRunner", 0},
		}},
		eventDesc{trace.EvGoBlockSend, []frame{
			frame{"runtime.chansend1", 0},
			frame{"runtime/trace_test.TestTraceSymbolize.func5", 54},
		}},
		eventDesc{trace.EvGoUnblock, []frame{
			frame{"runtime.chanrecv1", 0},
			frame{"runtime/trace_test.TestTraceSymbolize", 110},
			frame{"testing.tRunner", 0},
		}},
		eventDesc{trace.EvGoBlockSelect, []frame{
			frame{"runtime.selectgo", 0},
			frame{"runtime/trace_test.TestTraceSymbolize.func6", 59},
		}},
		eventDesc{trace.EvGoUnblock, []frame{
			frame{"runtime.selectgo", 0},
			frame{"runtime/trace_test.TestTraceSymbolize", 111},
			frame{"testing.tRunner", 0},
		}},
		eventDesc{trace.EvGoBlockSync, []frame{
			frame{"sync.(*Mutex).Lock", 0},
			frame{"runtime/trace_test.TestTraceSymbolize.func7", 67},
		}},
		eventDesc{trace.EvGoUnblock, []frame{
			frame{"sync.(*Mutex).Unlock", 0},
			frame{"runtime/trace_test.TestTraceSymbolize", 115},
			frame{"testing.tRunner", 0},
		}},
		eventDesc{trace.EvGoBlockSync, []frame{
			frame{"sync.(*WaitGroup).Wait", 0},
			frame{"runtime/trace_test.TestTraceSymbolize.func8", 73},
		}},
		eventDesc{trace.EvGoUnblock, []frame{
			frame{"sync.(*WaitGroup).Add", 0},
			frame{"sync.(*WaitGroup).Done", 0},
			frame{"runtime/trace_test.TestTraceSymbolize", 116},
			frame{"testing.tRunner", 0},
		}},
		eventDesc{trace.EvGoBlockCond, []frame{
			frame{"sync.(*Cond).Wait", 0},
			frame{"runtime/trace_test.TestTraceSymbolize.func9", 78},
		}},
		eventDesc{trace.EvGoUnblock, []frame{
			frame{"sync.(*Cond).Signal", 0},
			frame{"runtime/trace_test.TestTraceSymbolize", 117},
			frame{"testing.tRunner", 0},
		}},
		eventDesc{trace.EvGoSleep, []frame{
			frame{"time.Sleep", 0},
			frame{"runtime/trace_test.TestTraceSymbolize", 108},
			frame{"testing.tRunner", 0},
		}},
	}
	// Stacks for the following events are OS-dependent due to OS-specific code in net package.
	if runtime.GOOS != "windows" && runtime.GOOS != "plan9" {
		want = append(want, []eventDesc{
			eventDesc{trace.EvGoBlockNet, []frame{
				frame{"net.(*netFD).accept", 0},
				frame{"net.(*TCPListener).AcceptTCP", 0},
				frame{"net.(*TCPListener).Accept", 0},
				frame{"runtime/trace_test.TestTraceSymbolize.func10", 86},
			}},
			eventDesc{trace.EvGoSysCall, []frame{
				frame{"syscall.read", 0},
				frame{"syscall.Read", 0},
				frame{"os.(*File).read", 0},
				frame{"os.(*File).Read", 0},
				frame{"runtime/trace_test.TestTraceSymbolize.func11", 101},
			}},
		}...)
	}
	matched := make([]bool, len(want))
	for _, ev := range events {
	wantLoop:
		for i, w := range want {
			if matched[i] || w.Type != ev.Type || len(w.Stk) != len(ev.Stk) {
				continue
			}

			for fi, f := range ev.Stk {
				wf := w.Stk[fi]
				if wf.Fn != f.Fn || wf.Line != 0 && wf.Line != f.Line {
					continue wantLoop
				}
			}
			matched[i] = true
		}
	}
	for i, m := range matched {
		if m {
			continue
		}
		w := want[i]
		t.Errorf("did not match event %v at %v:%v", trace.EventDescriptions[w.Type].Name, w.Stk[0].Fn, w.Stk[0].Line)
		t.Errorf("seen the following events of this type:")
		for _, ev := range events {
			if ev.Type != w.Type {
				continue
			}
			for _, f := range ev.Stk {
				t.Logf("  %v:%v", f.Fn, f.Line)
			}
			t.Logf("---")
		}
	}
}
<commit_msg>runtime/trace: fix TestTraceSymbolize networking<commit_after>// Copyright 2014 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package trace_test

import (
	"bytes"
	"internal/testenv"
	"internal/trace"
	"net"
	"os"
	"runtime"
	. "runtime/trace"
	"sync"
	"testing"
	"time"
)

// TestTraceSymbolize tests symbolization and that events has proper stacks.
// In particular that we strip bottom uninteresting frames like goexit,
// top uninteresting frames (runtime guts).
func TestTraceSymbolize(t *testing.T) {
	skipTraceTestsIfNeeded(t)
	testenv.MustHaveExec(t)
	buf := new(bytes.Buffer)
	if err := Start(buf); err != nil {
		t.Fatalf("failed to start tracing: %v", err)
	}
	defer Stop() // in case of early return

	// Now we will do a bunch of things for which we verify stacks later.
	// It is impossible to ensure that a goroutine has actually blocked
	// on a channel, in a select or otherwise. So we kick off goroutines
	// that need to block first in the hope that while we are executing
	// the rest of the test, they will block.
	go func() {
		select {}
	}()
	go func() {
		var c chan int
		c <- 0
	}()
	go func() {
		var c chan int
		<-c
	}()
	done1 := make(chan bool)
	go func() {
		<-done1
	}()
	done2 := make(chan bool)
	go func() {
		done2 <- true
	}()
	c1 := make(chan int)
	c2 := make(chan int)
	go func() {
		select {
		case <-c1:
		case <-c2:
		}
	}()
	var mu sync.Mutex
	mu.Lock()
	go func() {
		mu.Lock()
		mu.Unlock()
	}()
	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		wg.Wait()
	}()
	cv := sync.NewCond(&sync.Mutex{})
	go func() {
		cv.L.Lock()
		cv.Wait()
		cv.L.Unlock()
	}()
	ln, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatalf("failed to listen: %v", err)
	}
	go func() {
		c, err := ln.Accept()
		if err != nil {
			t.Fatalf("failed to accept: %v", err)
		}
		c.Close()
	}()
	rp, wp, err := os.Pipe()
	if err != nil {
		t.Fatalf("failed to create a pipe: %v", err)
	}
	defer rp.Close()
	defer wp.Close()
	pipeReadDone := make(chan bool)
	go func() {
		var data [1]byte
		rp.Read(data[:])
		pipeReadDone <- true
	}()

	time.Sleep(time.Millisecond)
	runtime.GC()
	runtime.Gosched()
	time.Sleep(time.Millisecond) // the last chance for the goroutines above to block
	done1 <- true
	<-done2
	select {
	case c1 <- 0:
	case c2 <- 0:
	}
	mu.Unlock()
	wg.Done()
	cv.Signal()
	c, err := net.Dial("tcp", ln.Addr().String())
	if err != nil {
		t.Fatalf("failed to dial: %v", err)
	}
	c.Close()
	var data [1]byte
	wp.Write(data[:])
	<-pipeReadDone

	Stop()
	events, _, err := parseTrace(buf)
	if err != nil {
		t.Fatalf("failed to parse trace: %v", err)
	}
	err = trace.Symbolize(events, os.Args[0])
	if err != nil {
		t.Fatalf("failed to symbolize trace: %v", err)
	}

	// Now check that the stacks are correct.
	type frame struct {
		Fn   string
		Line int
	}
	type eventDesc struct {
		Type byte
		Stk  []frame
	}
	want := []eventDesc{
		eventDesc{trace.EvGCStart, []frame{
			frame{"runtime.GC", 0},
			frame{"runtime/trace_test.TestTraceSymbolize", 106},
			frame{"testing.tRunner", 0},
		}},
		eventDesc{trace.EvGoSched, []frame{
			frame{"runtime/trace_test.TestTraceSymbolize", 107},
			frame{"testing.tRunner", 0},
		}},
		eventDesc{trace.EvGoCreate, []frame{
			frame{"runtime/trace_test.TestTraceSymbolize", 39},
			frame{"testing.tRunner", 0},
		}},
		eventDesc{trace.EvGoStop, []frame{
			frame{"runtime.block", 0},
			frame{"runtime/trace_test.TestTraceSymbolize.func1", 38},
		}},
		eventDesc{trace.EvGoStop, []frame{
			frame{"runtime.chansend1", 0},
			frame{"runtime/trace_test.TestTraceSymbolize.func2", 42},
		}},
		eventDesc{trace.EvGoStop, []frame{
			frame{"runtime.chanrecv1", 0},
			frame{"runtime/trace_test.TestTraceSymbolize.func3", 46},
		}},
		eventDesc{trace.EvGoBlockRecv, []frame{
			frame{"runtime.chanrecv1", 0},
			frame{"runtime/trace_test.TestTraceSymbolize.func4", 50},
		}},
		eventDesc{trace.EvGoUnblock, []frame{
			frame{"runtime.chansend1", 0},
			frame{"runtime/trace_test.TestTraceSymbolize", 109},
			frame{"testing.tRunner", 0},
		}},
		eventDesc{trace.EvGoBlockSend, []frame{
			frame{"runtime.chansend1", 0},
			frame{"runtime/trace_test.TestTraceSymbolize.func5", 54},
		}},
		eventDesc{trace.EvGoUnblock, []frame{
			frame{"runtime.chanrecv1", 0},
			frame{"runtime/trace_test.TestTraceSymbolize", 110},
			frame{"testing.tRunner", 0},
		}},
		eventDesc{trace.EvGoBlockSelect, []frame{
			frame{"runtime.selectgo", 0},
			frame{"runtime/trace_test.TestTraceSymbolize.func6", 59},
		}},
		eventDesc{trace.EvGoUnblock, []frame{
			frame{"runtime.selectgo", 0},
			frame{"runtime/trace_test.TestTraceSymbolize", 111},
			frame{"testing.tRunner", 0},
		}},
		eventDesc{trace.EvGoBlockSync, []frame{
			frame{"sync.(*Mutex).Lock", 0},
			frame{"runtime/trace_test.TestTraceSymbolize.func7", 67},
		}},
		eventDesc{trace.EvGoUnblock, []frame{
			frame{"sync.(*Mutex).Unlock", 0},
			frame{"runtime/trace_test.TestTraceSymbolize", 115},
			frame{"testing.tRunner", 0},
		}},
		eventDesc{trace.EvGoBlockSync, []frame{
			frame{"sync.(*WaitGroup).Wait", 0},
			frame{"runtime/trace_test.TestTraceSymbolize.func8", 73},
		}},
		eventDesc{trace.EvGoUnblock, []frame{
			frame{"sync.(*WaitGroup).Add", 0},
			frame{"sync.(*WaitGroup).Done", 0},
			frame{"runtime/trace_test.TestTraceSymbolize", 116},
			frame{"testing.tRunner", 0},
		}},
		eventDesc{trace.EvGoBlockCond, []frame{
			frame{"sync.(*Cond).Wait", 0},
			frame{"runtime/trace_test.TestTraceSymbolize.func9", 78},
		}},
		eventDesc{trace.EvGoUnblock, []frame{
			frame{"sync.(*Cond).Signal", 0},
			frame{"runtime/trace_test.TestTraceSymbolize", 117},
			frame{"testing.tRunner", 0},
		}},
		eventDesc{trace.EvGoSleep, []frame{
			frame{"time.Sleep", 0},
			frame{"runtime/trace_test.TestTraceSymbolize", 108},
			frame{"testing.tRunner", 0},
		}},
	}
	// Stacks for the following events are OS-dependent due to OS-specific code in net package.
	if runtime.GOOS != "windows" && runtime.GOOS != "plan9" {
		want = append(want, []eventDesc{
			eventDesc{trace.EvGoBlockNet, []frame{
				frame{"net.(*netFD).accept", 0},
				frame{"net.(*TCPListener).AcceptTCP", 0},
				frame{"net.(*TCPListener).Accept", 0},
				frame{"runtime/trace_test.TestTraceSymbolize.func10", 86},
			}},
			eventDesc{trace.EvGoSysCall, []frame{
				frame{"syscall.read", 0},
				frame{"syscall.Read", 0},
				frame{"os.(*File).read", 0},
				frame{"os.(*File).Read", 0},
				frame{"runtime/trace_test.TestTraceSymbolize.func11", 101},
			}},
		}...)
	}
	matched := make([]bool, len(want))
	for _, ev := range events {
	wantLoop:
		for i, w := range want {
			if matched[i] || w.Type != ev.Type || len(w.Stk) != len(ev.Stk) {
				continue
			}

			for fi, f := range ev.Stk {
				wf := w.Stk[fi]
				if wf.Fn != f.Fn || wf.Line != 0 && wf.Line != f.Line {
					continue wantLoop
				}
			}
			matched[i] = true
		}
	}
	for i, m := range matched {
		if m {
			continue
		}
		w := want[i]
		t.Errorf("did not match event %v at %v:%v", trace.EventDescriptions[w.Type].Name, w.Stk[0].Fn, w.Stk[0].Line)
		t.Errorf("seen the following events of this type:")
		for _, ev := range events {
			if ev.Type != w.Type {
				continue
			}
			for _, f := range ev.Stk {
				t.Logf("  %v:%v", f.Fn, f.Line)
			}
			t.Logf("---")
		}
	}
}
<|endoftext|>


<commit_before>package evaluator

import (
	"fmt"
	"monkey/object"
)

var builtins = map[string]*object.Builtin{
	"len": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			if len(args) != 1 {
				return newError("wrong number of arguments. got=%d, want=1", len(args))
			}

			switch arg := args[0].(type) {
			case *object.String:
				return &object.Integer{Value: int64(len(arg.Value))}
			case *object.Array:
				return &object.Integer{Value: int64(len(arg.Elements))}
			default:
				return newError("argument to 'len' not supported, got %s", args[0].Type())
			}
		},
	},
	"first": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			if len(args) != 1 {
				return newError("wrong number of arguments. got=%d, want=1", len(args))
			}

			if args[0].Type() != object.ARRAY_OBJ {
				return newError("argument to 'first' must be ARRAY, got %s", args[0].Type())
			}

			arr := args[0].(*object.Array)
			if len(arr.Elements) > 0 {
				return arr.Elements[0]
			}

			return NULL
		},
	},
	"last": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			if len(args) != 1 {
				return newError("wrong number of arguments. got=%d, want=1", len(args))
			}

			if args[0].Type() != object.ARRAY_OBJ {
				return newError("argument to 'last' must be ARRAY, got %s", args[0].Type())
			}

			arr := args[0].(*object.Array)
			length := len(arr.Elements)
			if length > 0 {
				return arr.Elements[length-1]
			}

			return NULL
		},
	},
	"tail": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			if len(args) != 1 {
				return newError("wrong number of arguments. got=%d, want=1", len(args))
			}

			if args[0].Type() != object.ARRAY_OBJ {
				return newError("argument to 'tail' must be ARRAY, got %s", args[0].Type())
			}

			arr := args[0].(*object.Array)
			length := len(arr.Elements)
			if length > 0 {
				newElements := make([]object.Object, length-1, length-1)
				copy(newElements, arr.Elements[1:length])
				return &object.Array{Elements: newElements}
			}

			return NULL
		},
	},
	"push": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			if len(args) != 2 {
				return newError("wrong number of arguments. got=%d, want=2", len(args))
			}

			if args[0].Type() != object.ARRAY_OBJ {
				return newError("argument to 'push' must be ARRAY, got %s", args[0].Type())
			}

			arr := args[0].(*object.Array)
			length := len(arr.Elements)
			newElements := make([]object.Object, length+1, length+1)
			copy(newElements, arr.Elements)

			newElements[length] = args[1]
			return &object.Array{Elements: newElements}
		},
	},
	"put": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			for _, arg := range args {
				fmt.Print(arg.Inspect())
			}

			return NULL
		},
	},
	"putln": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			if len(args) == 0 {
				fmt.Println()
			}
			for _, arg := range args {
				fmt.Println(arg.Inspect())
			}

			return NULL
		},
	},
	"type": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			if len(args) != 1 {
				return newError("wrong number of arguments. got=%d, want=1", len(args))
			}

			return &object.String{Value: string(args[0].Type())}
		},
	},
}
<commit_msg>added substring builtin<commit_after>package evaluator

import (
	"fmt"
	"monkey/object"
)

var builtins = map[string]*object.Builtin{
	"len": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			if len(args) != 1 {
				return newError("wrong number of arguments. got=%d, want=1", len(args))
			}

			switch arg := args[0].(type) {
			case *object.String:
				return &object.Integer{Value: int64(len(arg.Value))}
			case *object.Array:
				return &object.Integer{Value: int64(len(arg.Elements))}
			default:
				return newError("argument to 'len' not supported, got %s", args[0].Type())
			}
		},
	},
	"first": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			if len(args) != 1 {
				return newError("wrong number of arguments. got=%d, want=1", len(args))
			}

			if args[0].Type() != object.ARRAY_OBJ {
				return newError("argument to 'first' must be ARRAY, got %s", args[0].Type())
			}

			arr := args[0].(*object.Array)
			if len(arr.Elements) > 0 {
				return arr.Elements[0]
			}

			return NULL
		},
	},
	"last": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			if len(args) != 1 {
				return newError("wrong number of arguments. got=%d, want=1", len(args))
			}

			if args[0].Type() != object.ARRAY_OBJ {
				return newError("argument to 'last' must be ARRAY, got %s", args[0].Type())
			}

			arr := args[0].(*object.Array)
			length := len(arr.Elements)
			if length > 0 {
				return arr.Elements[length-1]
			}

			return NULL
		},
	},
	"tail": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			if len(args) != 1 {
				return newError("wrong number of arguments. got=%d, want=1", len(args))
			}

			if args[0].Type() != object.ARRAY_OBJ {
				return newError("argument to 'tail' must be ARRAY, got %s", args[0].Type())
			}

			arr := args[0].(*object.Array)
			length := len(arr.Elements)
			if length > 0 {
				newElements := make([]object.Object, length-1, length-1)
				copy(newElements, arr.Elements[1:length])
				return &object.Array{Elements: newElements}
			}

			return NULL
		},
	},
	"push": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			if len(args) != 2 {
				return newError("wrong number of arguments. got=%d, want=2", len(args))
			}

			if args[0].Type() != object.ARRAY_OBJ {
				return newError("argument to 'push' must be ARRAY, got %s", args[0].Type())
			}

			arr := args[0].(*object.Array)
			length := len(arr.Elements)
			newElements := make([]object.Object, length+1, length+1)
			copy(newElements, arr.Elements)

			newElements[length] = args[1]
			return &object.Array{Elements: newElements}
		},
	},
	"put": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			for _, arg := range args {
				fmt.Print(arg.Inspect())
			}

			return NULL
		},
	},
	"putln": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			if len(args) == 0 {
				fmt.Println()
			}
			for _, arg := range args {
				fmt.Println(arg.Inspect())
			}

			return NULL
		},
	},
	"type": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			if len(args) != 1 {
				return newError("wrong number of arguments. got=%d, want=1", len(args))
			}

			return &object.String{Value: string(args[0].Type())}
		},
	},
	"substr": &object.Builtin{
		Fn: func(args ...object.Object) object.Object {
			if len(args) != 3 {
				return newError("wrong number of arguments. got=%d, want=1", len(args))
			}

			if args[0].Type() != object.STRING_OBJ {
				return newError("first argument to 'substr' must be STRING, got %s", args[0].Type())
			}

			if args[1].Type() != object.INTEGER_OBJ && args[2].Type() != object.INTEGER_OBJ {
				return newError("last arguments to 'substr' must be INT, got %s and %s", args[1].Type(), args[2].Type())
			}

			str := args[0].(*object.String)
			start := args[1].(*object.Integer)
			end := args[2].(*object.Integer)

			if start.Value > end.Value {
				return newError("start index cannot be larger than end index")
			}

			if start.Value > int64(len(str.Value)) || end.Value > int64(len(str.Value)) {
				return newError("substring indices must be at most the string length")
			}

			return &object.String{Value: str.Value[start.Value:end.Value]}
		},
	},
}
<|endoftext|>


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

// Package driver defines interfaces to be implemented by database
// drivers as used by package sql.
//
// Code simply using databases should use package sql.
//
// Drivers only need to be aware of a subset of Go's types.  The db package
// will convert all types into one of the following:
//
//   int64
//   float64
//   bool
//   nil
//   []byte
//   string   [*] everywhere except from Rows.Next.
//
package driver

import "errors"

// Driver is the interface that must be implemented by a database
// driver.
type Driver interface {
	// Open returns a new connection to the database.
	// The name is a string in a driver-specific format.
	//
	// Open may return a cached connection (one previously
	// closed), but doing so is unnecessary; the sql package
	// maintains a pool of idle connections for efficient re-use.
	//
	// The returned connection is only used by one goroutine at a
	// time.
	Open(name string) (Conn, error)
}

// ErrSkip may be returned by some optional interfaces' methods to
// indicate at runtime that the fast path is unavailable and the sql
// package should continue as if the optional interface was not
// implemented. ErrSkip is only supported where explicitly
// documented.
var ErrSkip = errors.New("driver: skip fast-path; continue as if unimplemented")

// Execer is an optional interface that may be implemented by a Conn.
//
// If a Conn does not implement Execer, the db package's DB.Exec will
// first prepare a query, execute the statement, and then close the
// statement.
//
// All arguments are of a subset type as defined in the package docs.
//
// Exec may return ErrSkip.
type Execer interface {
	Exec(query string, args []interface{}) (Result, error)
}

// Conn is a connection to a database. It is not used concurrently
// by multiple goroutines.
//
// Conn is assumed to be stateful.
type Conn interface {
	// Prepare returns a prepared statement, bound to this connection.
	Prepare(query string) (Stmt, error)

	// Close invalidates and potentially stops any current
	// prepared statements and transactions, marking this
	// connection as no longer in use.
	//
	// Because the sql package maintains a free pool of
	// connections and only calls Close when there's a surplus of
	// idle connections, it shouldn't be necessary for drivers to
	// do their own connection caching.
	Close() error

	// Begin starts and returns a new transaction.
	Begin() (Tx, error)
}

// Result is the result of a query execution.
type Result interface {
	// LastInsertId returns the database's auto-generated ID
	// after, for example, an INSERT into a table with primary
	// key.
	LastInsertId() (int64, error)

	// RowsAffected returns the number of rows affected by the
	// query.
	RowsAffected() (int64, error)
}

// Stmt is a prepared statement. It is bound to a Conn and not
// used by multiple goroutines concurrently.
type Stmt interface {
	// Close closes the statement.
	Close() error

	// NumInput returns the number of placeholder parameters.
	NumInput() int

	// Exec executes a query that doesn't return rows, such
	// as an INSERT or UPDATE.  The args are all of a subset
	// type as defined above.
	Exec(args []interface{}) (Result, error)

	// Exec executes a query that may return rows, such as a
	// SELECT.  The args of all of a subset type as defined above.
	Query(args []interface{}) (Rows, error)
}

// ColumnConverter may be optionally implemented by Stmt if the
// the statement is aware of its own columns' types and can
// convert from any type to a driver subset type.
type ColumnConverter interface {
	// ColumnConverter returns a ValueConverter for the provided
	// column index.  If the type of a specific column isn't known
	// or shouldn't be handled specially, DefaultValueConverter
	// can be returned.
	ColumnConverter(idx int) ValueConverter
}

// Rows is an iterator over an executed query's results.
type Rows interface {
	// Columns returns the names of the columns. The number of
	// columns of the result is inferred from the length of the
	// slice.  If a particular column name isn't known, an empty
	// string should be returned for that entry.
	Columns() []string

	// Close closes the rows iterator.
	Close() error

	// Next is called to populate the next row of data into
	// the provided slice. The provided slice will be the same
	// size as the Columns() are wide.
	//
	// The dest slice may be populated with only with values
	// of subset types defined above, but excluding string.
	// All string values must be converted to []byte.
	Next(dest []interface{}) error
}

// Tx is a transaction.
type Tx interface {
	Commit() error
	Rollback() error
}

// RowsAffected implements Result for an INSERT or UPDATE operation
// which mutates a number of rows.
type RowsAffected int64

var _ Result = RowsAffected(0)

func (RowsAffected) LastInsertId() (int64, error) {
	return 0, errors.New("no LastInsertId available")
}

func (v RowsAffected) RowsAffected() (int64, error) {
	return int64(v), nil
}

// DDLSuccess is a pre-defined Result for drivers to return when a DDL
// command succeeds.
var DDLSuccess ddlSuccess

type ddlSuccess struct{}

var _ Result = ddlSuccess{}

func (ddlSuccess) LastInsertId() (int64, error) {
	return 0, errors.New("no LastInsertId available after DDL statement")
}

func (ddlSuccess) RowsAffected() (int64, error) {
	return 0, errors.New("no RowsAffected available after DDL statement")
}
<commit_msg>sql: document that for drivers, io.EOF means no more rows<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package driver defines interfaces to be implemented by database
// drivers as used by package sql.
//
// Code simply using databases should use package sql.
//
// Drivers only need to be aware of a subset of Go's types.  The db package
// will convert all types into one of the following:
//
//   int64
//   float64
//   bool
//   nil
//   []byte
//   string   [*] everywhere except from Rows.Next.
//
package driver

import "errors"

// Driver is the interface that must be implemented by a database
// driver.
type Driver interface {
	// Open returns a new connection to the database.
	// The name is a string in a driver-specific format.
	//
	// Open may return a cached connection (one previously
	// closed), but doing so is unnecessary; the sql package
	// maintains a pool of idle connections for efficient re-use.
	//
	// The returned connection is only used by one goroutine at a
	// time.
	Open(name string) (Conn, error)
}

// ErrSkip may be returned by some optional interfaces' methods to
// indicate at runtime that the fast path is unavailable and the sql
// package should continue as if the optional interface was not
// implemented. ErrSkip is only supported where explicitly
// documented.
var ErrSkip = errors.New("driver: skip fast-path; continue as if unimplemented")

// Execer is an optional interface that may be implemented by a Conn.
//
// If a Conn does not implement Execer, the db package's DB.Exec will
// first prepare a query, execute the statement, and then close the
// statement.
//
// All arguments are of a subset type as defined in the package docs.
//
// Exec may return ErrSkip.
type Execer interface {
	Exec(query string, args []interface{}) (Result, error)
}

// Conn is a connection to a database. It is not used concurrently
// by multiple goroutines.
//
// Conn is assumed to be stateful.
type Conn interface {
	// Prepare returns a prepared statement, bound to this connection.
	Prepare(query string) (Stmt, error)

	// Close invalidates and potentially stops any current
	// prepared statements and transactions, marking this
	// connection as no longer in use.
	//
	// Because the sql package maintains a free pool of
	// connections and only calls Close when there's a surplus of
	// idle connections, it shouldn't be necessary for drivers to
	// do their own connection caching.
	Close() error

	// Begin starts and returns a new transaction.
	Begin() (Tx, error)
}

// Result is the result of a query execution.
type Result interface {
	// LastInsertId returns the database's auto-generated ID
	// after, for example, an INSERT into a table with primary
	// key.
	LastInsertId() (int64, error)

	// RowsAffected returns the number of rows affected by the
	// query.
	RowsAffected() (int64, error)
}

// Stmt is a prepared statement. It is bound to a Conn and not
// used by multiple goroutines concurrently.
type Stmt interface {
	// Close closes the statement.
	Close() error

	// NumInput returns the number of placeholder parameters.
	NumInput() int

	// Exec executes a query that doesn't return rows, such
	// as an INSERT or UPDATE.  The args are all of a subset
	// type as defined above.
	Exec(args []interface{}) (Result, error)

	// Exec executes a query that may return rows, such as a
	// SELECT.  The args of all of a subset type as defined above.
	Query(args []interface{}) (Rows, error)
}

// ColumnConverter may be optionally implemented by Stmt if the
// the statement is aware of its own columns' types and can
// convert from any type to a driver subset type.
type ColumnConverter interface {
	// ColumnConverter returns a ValueConverter for the provided
	// column index.  If the type of a specific column isn't known
	// or shouldn't be handled specially, DefaultValueConverter
	// can be returned.
	ColumnConverter(idx int) ValueConverter
}

// Rows is an iterator over an executed query's results.
type Rows interface {
	// Columns returns the names of the columns. The number of
	// columns of the result is inferred from the length of the
	// slice.  If a particular column name isn't known, an empty
	// string should be returned for that entry.
	Columns() []string

	// Close closes the rows iterator.
	Close() error

	// Next is called to populate the next row of data into
	// the provided slice. The provided slice will be the same
	// size as the Columns() are wide.
	//
	// The dest slice may be populated with only with values
	// of subset types defined above, but excluding string.
	// All string values must be converted to []byte.
	//
	// Next should return io.EOF when there are no more rows.
	Next(dest []interface{}) error
}

// Tx is a transaction.
type Tx interface {
	Commit() error
	Rollback() error
}

// RowsAffected implements Result for an INSERT or UPDATE operation
// which mutates a number of rows.
type RowsAffected int64

var _ Result = RowsAffected(0)

func (RowsAffected) LastInsertId() (int64, error) {
	return 0, errors.New("no LastInsertId available")
}

func (v RowsAffected) RowsAffected() (int64, error) {
	return int64(v), nil
}

// DDLSuccess is a pre-defined Result for drivers to return when a DDL
// command succeeds.
var DDLSuccess ddlSuccess

type ddlSuccess struct{}

var _ Result = ddlSuccess{}

func (ddlSuccess) LastInsertId() (int64, error) {
	return 0, errors.New("no LastInsertId available after DDL statement")
}

func (ddlSuccess) RowsAffected() (int64, error) {
	return 0, errors.New("no RowsAffected available after DDL statement")
}
<|endoftext|>


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

/*
A trivial example of wrapping a C library in Go.
For a more complex example and explanation,
see ../gmp/gmp.go.
*/

package stdio

/*
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <errno.h>

char* greeting = "hello, world";
*/
import "C"
import "unsafe"

type File C.FILE

var Stdout = (*File)(C.stdout)
var Stderr = (*File)(C.stderr)

// Test reference to library symbol.
// Stdout and stderr are too special to be a reliable test.
var myerr = C.sys_errlist

func (f *File) WriteString(s string) {
	p := C.CString(s)
	C.fputs(p, (*C.FILE)(f))
	C.free(unsafe.Pointer(p))
	f.Flush()
}

func (f *File) Flush() {
	C.fflush((*C.FILE)(f))
}

var Greeting = C.GoString(C.greeting)
<commit_msg>go/build: fix windows build by commenting out references to stdout and stderr in cgotest<commit_after>// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
A trivial example of wrapping a C library in Go.
For a more complex example and explanation,
see ../gmp/gmp.go.
*/

package stdio

/*
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <errno.h>

char* greeting = "hello, world";
*/
import "C"
import "unsafe"

type File C.FILE

// TODO(brainman): uncomment once stdout and stderr references are working on Windows.
//var Stdout = (*File)(C.stdout)
//var Stderr = (*File)(C.stderr)

// Test reference to library symbol.
// Stdout and stderr are too special to be a reliable test.
var myerr = C.sys_errlist

func (f *File) WriteString(s string) {
	p := C.CString(s)
	C.fputs(p, (*C.FILE)(f))
	C.free(unsafe.Pointer(p))
	f.Flush()
}

func (f *File) Flush() {
	C.fflush((*C.FILE)(f))
}

var Greeting = C.GoString(C.greeting)
<|endoftext|>