<commit_before>package app_runner_test

import (
	"errors"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"github.com/cloudfoundry-incubator/receptor"
	"github.com/cloudfoundry-incubator/receptor/fake_receptor"
	"github.com/cloudfoundry-incubator/runtime-schema/models"
	"github.com/pivotal-cf-experimental/diego-edge-cli/app_runner"
)

var _ = Describe("AppRunner", func() {

	var (
		fakeReceptorClient *fake_receptor.FakeClient
		appRunner          *app_runner.DiegoAppRunner
	)

	BeforeEach(func() {
		fakeReceptorClient = &fake_receptor.FakeClient{}
		appRunner = app_runner.NewDiegoAppRunner(fakeReceptorClient, "myDiegoInstall.com")

	})

	Describe("StartDockerApp", func() {
		It("Starts a Docker App", func() {
			fakeReceptorClient.DesiredLRPsReturns([]receptor.DesiredLRPResponse{}, nil)

			args := []string{"app", "arg1", "--app", "arg 2"}
			envs := map[string]string{"APPROOT": "/root/env/path"}
			err := appRunner.StartDockerApp("americano-app", "docker://runtest/runner", "/app-run-statement", args, envs, true, 128, 1024, 2000)
			Expect(err).To(BeNil())

			Expect(fakeReceptorClient.CreateDesiredLRPCallCount()).To(Equal(1))
			Expect(fakeReceptorClient.CreateDesiredLRPArgsForCall(0)).To(Equal(receptor.DesiredLRPCreateRequest{
				ProcessGuid:          "americano-app",
				Domain:               "diego-edge",
				RootFSPath:           "docker://runtest/runner",
				Instances:            1,
				Stack:                "lucid64",
				EnvironmentVariables: []receptor.EnvironmentVariable{receptor.EnvironmentVariable{Name: "APPROOT", Value: "/root/env/path"}},
				Routes:               []string{"americano-app.myDiegoInstall.com"},
				MemoryMB:             128,
				DiskMB:               1024,
				Ports:                []uint32{2000},
				LogGuid:              "americano-app",
				LogSource:            "APP",
				Setup: &models.DownloadAction{
					From: "http://file_server.service.dc1.consul:8080/v1/static/docker-circus/docker-circus.tgz",
					To:   "/tmp",
				},
				Action: &models.RunAction{
					Path:       "/app-run-statement",
					Args:       []string{"app", "arg1", "--app", "arg 2"},
					Privileged: true,
				},
				Monitor: &models.RunAction{
					Path: "/tmp/spy",
					Args: []string{"-addr", ":2000"},
				},
			}))
		})

		It("returns errors if the app is already desired", func() {
			desiredLRPs := []receptor.DesiredLRPResponse{receptor.DesiredLRPResponse{ProcessGuid: "app-already-desired", Instances: 1}}
			fakeReceptorClient.DesiredLRPsReturns(desiredLRPs, nil)

			err := appRunner.StartDockerApp("app-already-desired", "docker://faily/boom", "/app-bork-statement", []string{}, map[string]string{}, false, 128, 1024, 8080)

			Expect(err).ToNot(BeNil())
			Expect(err.Error()).To(Equal("App app-already-desired, is already running"))
			Expect(fakeReceptorClient.DesiredLRPsCallCount()).To(Equal(1))
		})

		Describe("returning errors from the receptor", func() {
			It("returns desiring lrp errors", func() {
				receptorError := errors.New("error - Desiring an LRP")
				fakeReceptorClient.CreateDesiredLRPReturns(receptorError)

				err := appRunner.StartDockerApp("nescafe-app", "docker://faily/boom", "/app-bork-statement", []string{}, map[string]string{}, false, 128, 1024, 8080)
				Expect(err).To(Equal(receptorError))
			})

			It("returns existing count errors", func() {
				receptorError := errors.New("error - Existing Count")
				fakeReceptorClient.DesiredLRPsReturns([]receptor.DesiredLRPResponse{}, receptorError)

				err := appRunner.StartDockerApp("nescafe-app", "docker://faily/boom", "/app-bork-statement", []string{}, map[string]string{}, false, 128, 1024, 8080)
				Expect(err).To(Equal(receptorError))
			})
		})

	})

	Describe("ScaleDockerApp", func() {

		It("Scales a Docker App", func() {
			desiredLRPs := []receptor.DesiredLRPResponse{receptor.DesiredLRPResponse{ProcessGuid: "americano-app", Instances: 1}}
			fakeReceptorClient.DesiredLRPsReturns(desiredLRPs, nil)
			instanceCount := 25

			err := appRunner.ScaleDockerApp("americano-app", instanceCount)
			Expect(err).To(BeNil())

			Expect(fakeReceptorClient.UpdateDesiredLRPCallCount()).To(Equal(1))
			processGuid, updateRequest := fakeReceptorClient.UpdateDesiredLRPArgsForCall(0)
			Expect(processGuid).To(Equal("americano-app"))

			Expect(updateRequest).To(Equal(receptor.DesiredLRPUpdateRequest{Instances: &instanceCount}))
		})

		It("returns errors if the app is NOT already started", func() {
			desiredLRPs := []receptor.DesiredLRPResponse{receptor.DesiredLRPResponse{ProcessGuid: "americano-app", Instances: 1}}
			fakeReceptorClient.DesiredLRPsReturns(desiredLRPs, nil)

			err := appRunner.ScaleDockerApp("app-not-running", 15)

			Expect(err).ToNot(BeNil())
			Expect(err.Error()).To(Equal("app-not-running, is not started. Please start an app first"))
			Expect(fakeReceptorClient.DesiredLRPsCallCount()).To(Equal(1))
		})

		Describe("returning errors from the receptor", func() {
			It("returns desiring lrp errors", func() {
				desiredLRPs := []receptor.DesiredLRPResponse{receptor.DesiredLRPResponse{ProcessGuid: "americano-app", Instances: 1}}
				fakeReceptorClient.DesiredLRPsReturns(desiredLRPs, nil)

				receptorError := errors.New("error - Updating an LRP")
				fakeReceptorClient.UpdateDesiredLRPReturns(receptorError)

				err := appRunner.ScaleDockerApp("americano-app", 17)
				Expect(err).To(Equal(receptorError))
			})

			It("returns errors fetching the existing lrp count", func() {
				receptorError := errors.New("error - Existing Count")
				fakeReceptorClient.DesiredLRPsReturns([]receptor.DesiredLRPResponse{}, receptorError)

				err := appRunner.ScaleDockerApp("nescafe-app", 2)
				Expect(err).To(Equal(receptorError))
			})
		})

	})

	Describe("StopDockerApp", func() {
		It("Stops a Docker App", func() {
			desiredLRPs := []receptor.DesiredLRPResponse{receptor.DesiredLRPResponse{ProcessGuid: "americano-app", Instances: 1}}
			fakeReceptorClient.DesiredLRPsReturns(desiredLRPs, nil)
			fakeReceptorClient.DeleteDesiredLRPReturns(nil)

			err := appRunner.StopDockerApp("americano-app")
			Expect(err).To(BeNil())

			Expect(fakeReceptorClient.DeleteDesiredLRPCallCount()).To(Equal(1))
			Expect(fakeReceptorClient.DeleteDesiredLRPArgsForCall(0)).To(Equal("americano-app"))
		})

		It("returns errors if the app is NOT already started", func() {
			desiredLRPs := []receptor.DesiredLRPResponse{receptor.DesiredLRPResponse{ProcessGuid: "americano-app", Instances: 1}}
			fakeReceptorClient.DesiredLRPsReturns(desiredLRPs, nil)

			err := appRunner.StopDockerApp("app-not-running")

			Expect(err).ToNot(BeNil())
			Expect(err.Error()).To(Equal("app-not-running, is not started. Please start an app first"))
			Expect(fakeReceptorClient.DesiredLRPsCallCount()).To(Equal(1))

		})

		Describe("returning errors from the receptor", func() {
			It("returns deleting lrp errors", func() {
				desiredLRPs := []receptor.DesiredLRPResponse{receptor.DesiredLRPResponse{ProcessGuid: "americano-app", Instances: 1}}
				fakeReceptorClient.DesiredLRPsReturns(desiredLRPs, nil)

				deletingError := errors.New("deleting failed")
				fakeReceptorClient.DeleteDesiredLRPReturns(deletingError)

				err := appRunner.StopDockerApp("americano-app")

				Expect(err).To(Equal(deletingError))
			})

			It("returns errors fetching the existing count", func() {
				receptorError := errors.New("error - Existing Count")
				fakeReceptorClient.DesiredLRPsReturns([]receptor.DesiredLRPResponse{}, receptorError)

				err := appRunner.StopDockerApp("nescafe-app")
				Expect(err).To(Equal(receptorError))
			})
		})

	})

	Describe("IsDockerAppUp", func() {
		It("returns true if the docker app is running with a status of ActualLRPStateRunning", func() {
			actualLrpsResponse := []receptor.ActualLRPResponse{receptor.ActualLRPResponse{ProcessGuid: "americano-app", State: receptor.ActualLRPStateRunning}}
			fakeReceptorClient.ActualLRPsByProcessGuidReturns(actualLrpsResponse, nil)

			status, err := appRunner.IsDockerAppUp("americano-app")
			Expect(err).To(BeNil())
			Expect(status).To(BeTrue())

			Expect(fakeReceptorClient.ActualLRPsByProcessGuidCallCount()).To(Equal(1))

			Expect(fakeReceptorClient.ActualLRPsByProcessGuidArgsForCall(0)).To(Equal("americano-app"))
		})

		It("returns false if the docker app is running without a status of ActualLRPStateRunning", func() {
			actualLrpsResponse := []receptor.ActualLRPResponse{receptor.ActualLRPResponse{ProcessGuid: "americano-app", State: receptor.ActualLRPStateStarting}}
			fakeReceptorClient.ActualLRPsByProcessGuidReturns(actualLrpsResponse, nil)

			status, _ := appRunner.IsDockerAppUp("americano-app")
			Expect(status).To(BeFalse())

		})

		It("returns false if the docker app is not running", func() {
			actualLrpsResponse := []receptor.ActualLRPResponse{}
			fakeReceptorClient.ActualLRPsByProcessGuidReturns(actualLrpsResponse, nil)

			status, _ := appRunner.IsDockerAppUp("americano-app")
			Expect(status).To(BeFalse())

		})

		Describe("returning errors from the receptor", func() {
			It("returns errors fetching the existing count", func() {
				receptorError := errors.New("error - Existing Count")
				fakeReceptorClient.ActualLRPsByProcessGuidReturns([]receptor.ActualLRPResponse{}, receptorError)
				_, err := appRunner.IsDockerAppUp("nescafe-app")
				Expect(err).To(Equal(receptorError))
			})
		})
	})
})
<commit_msg>No longer use const receptor.ActualLRPStateStarting in tests as it is no longer defined<commit_after>package app_runner_test

import (
	"errors"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"github.com/cloudfoundry-incubator/receptor"
	"github.com/cloudfoundry-incubator/receptor/fake_receptor"
	"github.com/cloudfoundry-incubator/runtime-schema/models"
	"github.com/pivotal-cf-experimental/diego-edge-cli/app_runner"
)

var _ = Describe("AppRunner", func() {

	var (
		fakeReceptorClient *fake_receptor.FakeClient
		appRunner          *app_runner.DiegoAppRunner
	)

	BeforeEach(func() {
		fakeReceptorClient = &fake_receptor.FakeClient{}
		appRunner = app_runner.NewDiegoAppRunner(fakeReceptorClient, "myDiegoInstall.com")

	})

	Describe("StartDockerApp", func() {
		It("Starts a Docker App", func() {
			fakeReceptorClient.DesiredLRPsReturns([]receptor.DesiredLRPResponse{}, nil)

			args := []string{"app", "arg1", "--app", "arg 2"}
			envs := map[string]string{"APPROOT": "/root/env/path"}
			err := appRunner.StartDockerApp("americano-app", "docker://runtest/runner", "/app-run-statement", args, envs, true, 128, 1024, 2000)
			Expect(err).To(BeNil())

			Expect(fakeReceptorClient.CreateDesiredLRPCallCount()).To(Equal(1))
			Expect(fakeReceptorClient.CreateDesiredLRPArgsForCall(0)).To(Equal(receptor.DesiredLRPCreateRequest{
				ProcessGuid:          "americano-app",
				Domain:               "diego-edge",
				RootFSPath:           "docker://runtest/runner",
				Instances:            1,
				Stack:                "lucid64",
				EnvironmentVariables: []receptor.EnvironmentVariable{receptor.EnvironmentVariable{Name: "APPROOT", Value: "/root/env/path"}},
				Routes:               []string{"americano-app.myDiegoInstall.com"},
				MemoryMB:             128,
				DiskMB:               1024,
				Ports:                []uint32{2000},
				LogGuid:              "americano-app",
				LogSource:            "APP",
				Setup: &models.DownloadAction{
					From: "http://file_server.service.dc1.consul:8080/v1/static/docker-circus/docker-circus.tgz",
					To:   "/tmp",
				},
				Action: &models.RunAction{
					Path:       "/app-run-statement",
					Args:       []string{"app", "arg1", "--app", "arg 2"},
					Privileged: true,
				},
				Monitor: &models.RunAction{
					Path: "/tmp/spy",
					Args: []string{"-addr", ":2000"},
				},
			}))
		})

		It("returns errors if the app is already desired", func() {
			desiredLRPs := []receptor.DesiredLRPResponse{receptor.DesiredLRPResponse{ProcessGuid: "app-already-desired", Instances: 1}}
			fakeReceptorClient.DesiredLRPsReturns(desiredLRPs, nil)

			err := appRunner.StartDockerApp("app-already-desired", "docker://faily/boom", "/app-bork-statement", []string{}, map[string]string{}, false, 128, 1024, 8080)

			Expect(err).ToNot(BeNil())
			Expect(err.Error()).To(Equal("App app-already-desired, is already running"))
			Expect(fakeReceptorClient.DesiredLRPsCallCount()).To(Equal(1))
		})

		Describe("returning errors from the receptor", func() {
			It("returns desiring lrp errors", func() {
				receptorError := errors.New("error - Desiring an LRP")
				fakeReceptorClient.CreateDesiredLRPReturns(receptorError)

				err := appRunner.StartDockerApp("nescafe-app", "docker://faily/boom", "/app-bork-statement", []string{}, map[string]string{}, false, 128, 1024, 8080)
				Expect(err).To(Equal(receptorError))
			})

			It("returns existing count errors", func() {
				receptorError := errors.New("error - Existing Count")
				fakeReceptorClient.DesiredLRPsReturns([]receptor.DesiredLRPResponse{}, receptorError)

				err := appRunner.StartDockerApp("nescafe-app", "docker://faily/boom", "/app-bork-statement", []string{}, map[string]string{}, false, 128, 1024, 8080)
				Expect(err).To(Equal(receptorError))
			})
		})

	})

	Describe("ScaleDockerApp", func() {

		It("Scales a Docker App", func() {
			desiredLRPs := []receptor.DesiredLRPResponse{receptor.DesiredLRPResponse{ProcessGuid: "americano-app", Instances: 1}}
			fakeReceptorClient.DesiredLRPsReturns(desiredLRPs, nil)
			instanceCount := 25

			err := appRunner.ScaleDockerApp("americano-app", instanceCount)
			Expect(err).To(BeNil())

			Expect(fakeReceptorClient.UpdateDesiredLRPCallCount()).To(Equal(1))
			processGuid, updateRequest := fakeReceptorClient.UpdateDesiredLRPArgsForCall(0)
			Expect(processGuid).To(Equal("americano-app"))

			Expect(updateRequest).To(Equal(receptor.DesiredLRPUpdateRequest{Instances: &instanceCount}))
		})

		It("returns errors if the app is NOT already started", func() {
			desiredLRPs := []receptor.DesiredLRPResponse{receptor.DesiredLRPResponse{ProcessGuid: "americano-app", Instances: 1}}
			fakeReceptorClient.DesiredLRPsReturns(desiredLRPs, nil)

			err := appRunner.ScaleDockerApp("app-not-running", 15)

			Expect(err).ToNot(BeNil())
			Expect(err.Error()).To(Equal("app-not-running, is not started. Please start an app first"))
			Expect(fakeReceptorClient.DesiredLRPsCallCount()).To(Equal(1))
		})

		Describe("returning errors from the receptor", func() {
			It("returns desiring lrp errors", func() {
				desiredLRPs := []receptor.DesiredLRPResponse{receptor.DesiredLRPResponse{ProcessGuid: "americano-app", Instances: 1}}
				fakeReceptorClient.DesiredLRPsReturns(desiredLRPs, nil)

				receptorError := errors.New("error - Updating an LRP")
				fakeReceptorClient.UpdateDesiredLRPReturns(receptorError)

				err := appRunner.ScaleDockerApp("americano-app", 17)
				Expect(err).To(Equal(receptorError))
			})

			It("returns errors fetching the existing lrp count", func() {
				receptorError := errors.New("error - Existing Count")
				fakeReceptorClient.DesiredLRPsReturns([]receptor.DesiredLRPResponse{}, receptorError)

				err := appRunner.ScaleDockerApp("nescafe-app", 2)
				Expect(err).To(Equal(receptorError))
			})
		})

	})

	Describe("StopDockerApp", func() {
		It("Stops a Docker App", func() {
			desiredLRPs := []receptor.DesiredLRPResponse{receptor.DesiredLRPResponse{ProcessGuid: "americano-app", Instances: 1}}
			fakeReceptorClient.DesiredLRPsReturns(desiredLRPs, nil)
			fakeReceptorClient.DeleteDesiredLRPReturns(nil)

			err := appRunner.StopDockerApp("americano-app")
			Expect(err).To(BeNil())

			Expect(fakeReceptorClient.DeleteDesiredLRPCallCount()).To(Equal(1))
			Expect(fakeReceptorClient.DeleteDesiredLRPArgsForCall(0)).To(Equal("americano-app"))
		})

		It("returns errors if the app is NOT already started", func() {
			desiredLRPs := []receptor.DesiredLRPResponse{receptor.DesiredLRPResponse{ProcessGuid: "americano-app", Instances: 1}}
			fakeReceptorClient.DesiredLRPsReturns(desiredLRPs, nil)

			err := appRunner.StopDockerApp("app-not-running")

			Expect(err).ToNot(BeNil())
			Expect(err.Error()).To(Equal("app-not-running, is not started. Please start an app first"))
			Expect(fakeReceptorClient.DesiredLRPsCallCount()).To(Equal(1))

		})

		Describe("returning errors from the receptor", func() {
			It("returns deleting lrp errors", func() {
				desiredLRPs := []receptor.DesiredLRPResponse{receptor.DesiredLRPResponse{ProcessGuid: "americano-app", Instances: 1}}
				fakeReceptorClient.DesiredLRPsReturns(desiredLRPs, nil)

				deletingError := errors.New("deleting failed")
				fakeReceptorClient.DeleteDesiredLRPReturns(deletingError)

				err := appRunner.StopDockerApp("americano-app")

				Expect(err).To(Equal(deletingError))
			})

			It("returns errors fetching the existing count", func() {
				receptorError := errors.New("error - Existing Count")
				fakeReceptorClient.DesiredLRPsReturns([]receptor.DesiredLRPResponse{}, receptorError)

				err := appRunner.StopDockerApp("nescafe-app")
				Expect(err).To(Equal(receptorError))
			})
		})

	})

	Describe("IsDockerAppUp", func() {
		It("returns true if the docker app is running with a status of ActualLRPStateRunning", func() {
			actualLrpsResponse := []receptor.ActualLRPResponse{receptor.ActualLRPResponse{ProcessGuid: "americano-app", State: receptor.ActualLRPStateRunning}}
			fakeReceptorClient.ActualLRPsByProcessGuidReturns(actualLrpsResponse, nil)

			status, err := appRunner.IsDockerAppUp("americano-app")
			Expect(err).To(BeNil())
			Expect(status).To(BeTrue())

			Expect(fakeReceptorClient.ActualLRPsByProcessGuidCallCount()).To(Equal(1))

			Expect(fakeReceptorClient.ActualLRPsByProcessGuidArgsForCall(0)).To(Equal("americano-app"))
		})

		It("returns false if the docker app is running without a status of ActualLRPStateRunning", func() {
			actualLrpsResponse := []receptor.ActualLRPResponse{receptor.ActualLRPResponse{ProcessGuid: "americano-app", State: receptor.ActualLRPStateClaimed}}
			fakeReceptorClient.ActualLRPsByProcessGuidReturns(actualLrpsResponse, nil)

			status, _ := appRunner.IsDockerAppUp("americano-app")
			Expect(status).To(BeFalse())

		})

		It("returns false if the docker app is not running", func() {
			actualLrpsResponse := []receptor.ActualLRPResponse{}
			fakeReceptorClient.ActualLRPsByProcessGuidReturns(actualLrpsResponse, nil)

			status, _ := appRunner.IsDockerAppUp("americano-app")
			Expect(status).To(BeFalse())

		})

		Describe("returning errors from the receptor", func() {
			It("returns errors fetching the existing count", func() {
				receptorError := errors.New("error - Existing Count")
				fakeReceptorClient.ActualLRPsByProcessGuidReturns([]receptor.ActualLRPResponse{}, receptorError)
				_, err := appRunner.IsDockerAppUp("nescafe-app")
				Expect(err).To(Equal(receptorError))
			})
		})
	})
})
<|endoftext|>


<commit_before>package cemi

import (
	"io"

	"github.com/vapourismo/knx-go/knx/encoding"
	"github.com/vapourismo/knx-go/knx/util"
)

// A LData is a link-layer data frame. L_Data.req, L_Data.con and L_Data.ind share this structure.
type LData struct {
	Info        Info
	Control1    ControlField1
	Control2    ControlField2
	Source      uint16
	Destination uint16
	Data        TransportUnit
}

// Unpack initializes the structure by parsing the given data.
func (ldata *LData) Unpack(data []byte) (n uint, err error) {
	if n, err = util.UnpackSome(
		data,
		&ldata.Info,
		(*uint8)(&ldata.Control1),
		(*uint8)(&ldata.Control2),
		(*uint16)(&ldata.Source),
		(*uint16)(&ldata.Destination),
	); err != nil {
		return
	}

	m, err := UnpackTransportUnit(data[n:], &ldata.Data)
	n += m

	return
}

// WriteTo serializes the LData structure and writes it to the given Writer.
func (ldata *LData) WriteTo(w io.Writer) (int64, error) {
	return encoding.WriteSome(
		w,
		ldata.Info,
		ldata.Control1,
		ldata.Control2,
		ldata.Source,
		ldata.Destination,
		ldata.Data.Pack(),
	)
}

// A LDataReq represents a L_Data.req message body.
type LDataReq struct {
	LData
}

// MessageCode returns the message code for L_Data.req.
func (LDataReq) MessageCode() MessageCode {
	return LDataReqCode
}

// A LDataCon represents a L_Data.con message body.
type LDataCon struct {
	LData
}

// MessageCode returns the message code for L_Data.con.
func (LDataCon) MessageCode() MessageCode {
	return LDataConCode
}

// A LDataInd represents a L_Data.ind message body.
type LDataInd struct {
	LData
}

// MessageCode returns the message code for L_Data.ind.
func (LDataInd) MessageCode() MessageCode {
	return LDataConCode
}
<commit_msg>Remove unused conversions<commit_after>package cemi

import (
	"io"

	"github.com/vapourismo/knx-go/knx/encoding"
	"github.com/vapourismo/knx-go/knx/util"
)

// A LData is a link-layer data frame. L_Data.req, L_Data.con and L_Data.ind share this structure.
type LData struct {
	Info        Info
	Control1    ControlField1
	Control2    ControlField2
	Source      uint16
	Destination uint16
	Data        TransportUnit
}

// Unpack initializes the structure by parsing the given data.
func (ldata *LData) Unpack(data []byte) (n uint, err error) {
	if n, err = util.UnpackSome(
		data,
		&ldata.Info,
		(*uint8)(&ldata.Control1),
		(*uint8)(&ldata.Control2),
		&ldata.Source,
		&ldata.Destination,
	); err != nil {
		return
	}

	m, err := UnpackTransportUnit(data[n:], &ldata.Data)
	n += m

	return
}

// WriteTo serializes the LData structure and writes it to the given Writer.
func (ldata *LData) WriteTo(w io.Writer) (int64, error) {
	return encoding.WriteSome(
		w,
		ldata.Info,
		ldata.Control1,
		ldata.Control2,
		ldata.Source,
		ldata.Destination,
		ldata.Data.Pack(),
	)
}

// A LDataReq represents a L_Data.req message body.
type LDataReq struct {
	LData
}

// MessageCode returns the message code for L_Data.req.
func (LDataReq) MessageCode() MessageCode {
	return LDataReqCode
}

// A LDataCon represents a L_Data.con message body.
type LDataCon struct {
	LData
}

// MessageCode returns the message code for L_Data.con.
func (LDataCon) MessageCode() MessageCode {
	return LDataConCode
}

// A LDataInd represents a L_Data.ind message body.
type LDataInd struct {
	LData
}

// MessageCode returns the message code for L_Data.ind.
func (LDataInd) MessageCode() MessageCode {
	return LDataConCode
}
<|endoftext|>


<commit_before>package proto

import (
	"io"
	"errors"
)

// A TPCI is the transport-layer protocol control information (TPCI).
type TPCI uint8

const (
	UnnumberedDataPacket    TPCI = 0
	NumberedDataPacket      TPCI = 1
	UnnumberedControlPacket TPCI = 2
	NumberedControlPacket   TPCI = 3
)

// An APCI is the application-layer protocol control information (APCI).
type APCI uint8

const (
	GroupValueRead         APCI = 0
	GroupValueResponse     APCI = 1
	GroupValueWrite        APCI = 2
	IndividualAddrWrite    APCI = 3
	IndividualAddrRequest  APCI = 4
	IndividualAddrResponse APCI = 5
	AdcRead                APCI = 6
	AdcResponse            APCI = 7
	MemoryRead             APCI = 8
	MemoryResponse         APCI = 9
	MemoryWrite            APCI = 10
	UserMessage            APCI = 11
	MaskVersionRead        APCI = 12
	MaskVersionResponse    APCI = 13
	Restart                APCI = 14
	Escape                 APCI = 15
)

// A TPDU is the transport-layer protocol data unit within a L_Data frame.
type TPDU struct {
	PacketType TPCI
	SeqNumber  uint8
	Control    uint8
	Info       APCI
	Data       []byte
}

var (
	ErrTransportUnitTooShort = errors.New("Given TPDU is too short")
)

// ReadTPDU parses the given data in order to produce a TPDU struct.
func ReadTPDU(data []byte) (*TPDU, error) {
	if len(data) < 1 {
		return nil, ErrTransportUnitTooShort
	}

	packetType := TPCI((data[0] >> 6) & 3)
	seqNumber := (data[0] >> 2) & 15

	switch packetType {
	case UnnumberedControlPacket, NumberedControlPacket:
		return &TPDU{packetType, seqNumber, data[0] & 3, 0, nil}, nil

	case UnnumberedDataPacket, NumberedDataPacket:
		if len(data) < 2 {
			return nil, ErrTransportUnitTooShort
		}

		info := APCI((data[0] & 3) << 2 | (data[1] >> 6) & 3)

		var appData []byte
		if len(data) > 2 {
			appData = make([]byte, len(data) - 2)
			copy(appData, data[2:])
		} else {
			appData = []byte{data[1] & 63}
		}

		return &TPDU{packetType, seqNumber, 0, info, appData}, nil
	}

	return nil, errors.New("Unreachable")
}

// WriteTo writes the TPDU structure to the given Writer.
func (tpdu TPDU) WriteTo(w io.Writer) (err error) {

	buffer := []byte{
		byte(tpdu.PacketType & 3) << 6 | byte(tpdu.SeqNumber & 15) << 2,
	}

	switch tpdu.PacketType {
	case UnnumberedControlPacket, NumberedControlPacket:
		buffer[0] |= byte(tpdu.Control & 3)

	case UnnumberedDataPacket, NumberedDataPacket:
		buffer[0] |= byte(tpdu.Info >> 2) & 3

		if len(tpdu.Data) > 0 {
			buffer = append(buffer, tpdu.Data...)
			buffer[1] &= 63
			buffer[1] |= byte(tpdu.Info & 3) << 6
		} else {
			buffer = []byte{buffer[0], byte(tpdu.Info & 3) << 6}
		}
	}

	_, err = w.Write(buffer)
	return
}
<commit_msg>Clean up TPDU file<commit_after>package proto

import (
	"io"
	"errors"
)

// A TPCI is the transport-layer protocol control information (TPCI).
type TPCI uint8

//
const (
	UnnumberedDataPacket    TPCI = 0
	NumberedDataPacket      TPCI = 1
	UnnumberedControlPacket TPCI = 2
	NumberedControlPacket   TPCI = 3
)

// An APCI is the application-layer protocol control information (APCI).
type APCI uint8

//
const (
	GroupValueRead         APCI = 0
	GroupValueResponse     APCI = 1
	GroupValueWrite        APCI = 2
	IndividualAddrWrite    APCI = 3
	IndividualAddrRequest  APCI = 4
	IndividualAddrResponse APCI = 5
	AdcRead                APCI = 6
	AdcResponse            APCI = 7
	MemoryRead             APCI = 8
	MemoryResponse         APCI = 9
	MemoryWrite            APCI = 10
	UserMessage            APCI = 11
	MaskVersionRead        APCI = 12
	MaskVersionResponse    APCI = 13
	Restart                APCI = 14
	Escape                 APCI = 15
)

// A TPDU is the transport-layer protocol data unit within a L_Data frame.
type TPDU struct {
	PacketType TPCI
	SeqNumber  uint8
	Control    uint8
	Info       APCI
	Data       []byte
}

//
var (
	ErrTransportUnitTooShort = errors.New("Given TPDU is too short")
)

// ReadTPDU parses the given data in order to produce a TPDU struct.
func ReadTPDU(data []byte) (*TPDU, error) {
	if len(data) < 1 {
		return nil, ErrTransportUnitTooShort
	}

	packetType := TPCI((data[0] >> 6) & 3)
	seqNumber := (data[0] >> 2) & 15

	switch packetType {
	case UnnumberedControlPacket, NumberedControlPacket:
		return &TPDU{packetType, seqNumber, data[0] & 3, 0, nil}, nil

	case UnnumberedDataPacket, NumberedDataPacket:
		if len(data) < 2 {
			return nil, ErrTransportUnitTooShort
		}

		info := APCI((data[0] & 3) << 2 | (data[1] >> 6) & 3)

		var appData []byte
		if len(data) > 2 {
			appData = make([]byte, len(data) - 2)
			copy(appData, data[2:])
		} else {
			appData = []byte{data[1] & 63}
		}

		return &TPDU{packetType, seqNumber, 0, info, appData}, nil
	}

	return nil, errors.New("Unreachable")
}

// WriteTo writes the TPDU structure to the given Writer.
func (tpdu TPDU) WriteTo(w io.Writer) (err error) {
	buffer := []byte{
		byte(tpdu.PacketType & 3) << 6 | byte(tpdu.SeqNumber & 15) << 2,
	}

	switch tpdu.PacketType {
	case UnnumberedControlPacket, NumberedControlPacket:
		buffer[0] |= byte(tpdu.Control & 3)

	case UnnumberedDataPacket, NumberedDataPacket:
		buffer[0] |= byte(tpdu.Info >> 2) & 3

		if len(tpdu.Data) > 0 {
			buffer = append(buffer, tpdu.Data...)
			buffer[1] &= 63
			buffer[1] |= byte(tpdu.Info & 3) << 6
		} else {
			buffer = []byte{buffer[0], byte(tpdu.Info & 3) << 6}
		}
	}

	_, err = w.Write(buffer)
	return
}
<|endoftext|>


<commit_before>package ingester

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

	"golang.org/x/net/html"

	"github.com/jaytaylor/html2text"
	"github.com/mmcdole/gofeed"
	"mozilla.org/crec/content"
	"mozilla.org/crec/provider"

	"log"

	"net/http"
	"time"

	"encoding/json"

	"mozilla.org/crec/config"
	"mozilla.org/crec/processor"
)

// Ingest content from configured providers
func Ingest(config *config.Config, providers provider.Providers, curIndex *Index) *Index {
	CleanUp(config, curIndex)

	index := CreateIndex(config.GetIndexDir(), config.GetIndexFile())
	for _, provider := range providers {
		var err error

		if provider.ContentURL != "" {
			lastUpdated := curIndex.GetProviderLastUpdated(provider.ID)
			nextRefresh := config.GetIndexRefreshInterval()

			if int(time.Now().Add(nextRefresh).Sub(lastUpdated).Minutes()) > provider.MaxContentAge {
				log.Println("Refreshing content from provider " + provider.ID)
				err = ingestFromProvider(provider, index)
				if err == nil {
					index.SetProviderLastUpdated(provider.ID)
				}
			} else {
				log.Println("Reusing content from provider " + provider.ID)
				index.AddAll(curIndex.GetProviderContent(provider.ID))
			}
		} else {
			err = ingestFromQueue(config, provider, index)
		}

		if err != nil {
			index.AddAll(curIndex.GetProviderContent(provider.ID))
			log.Printf("Failed to ingest content from provider %v: %v", provider.ID, err)
		}
	}
	return index
}

// Queue content to be ingested in the next iteration
func Queue(config *config.Config, content []byte, provider string) error {
	path := filepath.Join(config.GetImportQueueDir(), provider)
	err := os.MkdirAll(path, os.ModePerm)
	if err != nil {
		return err
	}
	f, err := ioutil.TempFile(path, "import")
	if err != nil {
		return err
	}
	_, err = f.Write(content)
	return err
}

// CleanUp deletes all but the current active index
func CleanUp(config *config.Config, curIndex *Index) {
	indexDirs, _ := ioutil.ReadDir(config.GetIndexDir())
	for _, indexDir := range indexDirs {
		if indexDir.Name() != curIndex.GetID() {
			err := os.RemoveAll(filepath.FromSlash(config.GetIndexDir() + "/" + indexDir.Name()))
			if err != nil {
				log.Println("Failed to clean up old indexes: ", err)
			}
		}
	}
}

func ingestFromProvider(provider *provider.Provider, index *Index) error {
	client := &http.Client{Timeout: time.Duration(time.Second * 5)}
	var err error
	if provider.Native {
		err = ingestNative(provider, client, index)
	} else {
		err = ingestSyndicationFeed(provider, client, index)
	}
	return err
}

func ingestFromQueue(config *config.Config, provider *provider.Provider, index *Index) error {
	path := filepath.Join(config.GetImportQueueDir(), provider.ID)
	err := filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
		if info != nil && !info.IsDir() {
			bytes, err := ioutil.ReadFile(path)
			if err != nil {
				return err
			}

			err = ingestJSON(bytes, provider, index)
			if err != nil {
				return err
			}
		}
		return nil
	})
	return err
}

func ingestNative(provider *provider.Provider, client *http.Client, index *Index) error {
	resp, err := client.Get(provider.ContentURL)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

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

	return ingestJSON(body, provider, index)
}

func ingestJSON(bytes []byte, provider *provider.Provider, index *Index) error {
	var content []content.Content
	err := json.Unmarshal(bytes, &content)
	if err != nil {
		return err
	}

	for _, item := range content {
		if len(item.Domains) == 0 {
			item.Domains = provider.Domains
		}
		index.Add(&item)
	}

	return nil
}

func ingestSyndicationFeed(provider *provider.Provider, client *http.Client, index *Index) error {
	fp := gofeed.NewParser()
	fp.Client = client
	feed, err := fp.ParseURL(provider.ContentURL)
	if err != nil {
		return err
	}

	for _, item := range feed.Items {
		newc, err := createContentFromFeedItem(provider, item)
		if err != nil {
			return err
		}
		index.Add(newc)
	}

	return nil
}

func createContentFromFeedItem(provider *provider.Provider, item *gofeed.Item) (*content.Content, error) {
	r := strings.NewReader(item.Description)
	doc, err := html.Parse(r)
	if err != nil {
		return nil, err
	}

	var context = processor.NewHTMLContext(doc)
	for _, processor := range provider.GetProcessors() {
		context, err = processor.Process(context)
		if err != nil {
			return nil, err
		}
	}

	summary, err := html2text.FromHtmlNode(context.Content.(*html.Node))
	if err != nil {
		return nil, err
	}

	newc := &content.Content{
		ID:        findID(item),
		Source:    provider.ID,
		Title:     item.Title,
		Link:      item.Link,
		Image:     findImage(item, context),
		Summary:   summary,
		HTML:      item.Description,
		Tags:      append(item.Categories, provider.Categories...),
		Author:    processAuthor(item),
		Published: item.Published,
		Regions:   provider.Regions,
		Language:  provider.Language,
		Script:    provider.Script,
		Domains:   provider.Domains}
	return newc, nil
}

func findImage(item *gofeed.Item, context *processor.Context) string {
	if item.Image != nil && item.Image.URL != "" {
		return item.Image.URL
	}

	contentExt := item.Extensions["media"]["content"]
	for _, cExt := range contentExt {
		url := cExt.Attrs["url"]
		if url != "" {
			return url
		}
	}

	return context.Result["image"]
}

func processAuthor(item *gofeed.Item) string {
	if item.Author != nil {
		return item.Author.Name
	}
	return ""
}

func findID(item *gofeed.Item) string {
	if item.GUID != "" {
		return item.GUID
	}
	return item.Link
}
<commit_msg>Parallelize content ingestion<commit_after>package ingester

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"sync"

	"golang.org/x/net/html"

	"github.com/jaytaylor/html2text"
	"github.com/mmcdole/gofeed"
	"mozilla.org/crec/content"
	"mozilla.org/crec/provider"

	"log"

	"net/http"
	"time"

	"encoding/json"

	"mozilla.org/crec/config"
	"mozilla.org/crec/processor"
)

// Ingest content from configured providers
func Ingest(config *config.Config, providers provider.Providers, curIndex *Index) *Index {
	CleanUp(config, curIndex)

	index := CreateIndex(config.GetIndexDir(), config.GetIndexFile())

	var wg sync.WaitGroup
	wg.Add(len(providers))
	for _, p := range providers {
		go func(provider *provider.Provider) {
			defer wg.Done()
			var err error

			if provider.ContentURL != "" {
				lastUpdated := curIndex.GetProviderLastUpdated(provider.ID)
				nextRefresh := config.GetIndexRefreshInterval()

				if int(time.Now().Add(nextRefresh).Sub(lastUpdated).Minutes()) > provider.MaxContentAge {
					log.Println("Refreshing content from provider " + provider.ID)
					err = ingestFromProvider(provider, index)
					if err == nil {
						index.SetProviderLastUpdated(provider.ID)
					}
				} else {
					log.Println("Reusing content from provider " + provider.ID)
					index.AddAll(curIndex.GetProviderContent(provider.ID))
				}
			} else {
				err = ingestFromQueue(config, provider, index)
			}

			if err != nil {
				index.AddAll(curIndex.GetProviderContent(provider.ID))
				log.Printf("Failed to refresh content from provider %v: %v", provider.ID, err)
			}
		}(p)
	}
	wg.Wait()
	log.Println("Indexing complete")

	return index
}

// Queue content to be ingested in the next iteration
func Queue(config *config.Config, content []byte, provider string) error {
	path := filepath.Join(config.GetImportQueueDir(), provider)
	err := os.MkdirAll(path, os.ModePerm)
	if err != nil {
		return err
	}
	f, err := ioutil.TempFile(path, "import")
	if err != nil {
		return err
	}
	_, err = f.Write(content)
	return err
}

// CleanUp deletes all but the current active index
func CleanUp(config *config.Config, curIndex *Index) {
	indexDirs, _ := ioutil.ReadDir(config.GetIndexDir())
	for _, indexDir := range indexDirs {
		if indexDir.Name() != curIndex.GetID() {
			err := os.RemoveAll(filepath.FromSlash(config.GetIndexDir() + "/" + indexDir.Name()))
			if err != nil {
				log.Println("Failed to clean up old indexes: ", err)
			}
		}
	}
}

func ingestFromProvider(provider *provider.Provider, index *Index) error {
	client := &http.Client{Timeout: time.Duration(time.Second * 5)}
	var err error
	if provider.Native {
		err = ingestNative(provider, client, index)
	} else {
		err = ingestSyndicationFeed(provider, client, index)
	}
	return err
}

func ingestFromQueue(config *config.Config, provider *provider.Provider, index *Index) error {
	path := filepath.Join(config.GetImportQueueDir(), provider.ID)
	err := filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
		if info != nil && !info.IsDir() {
			bytes, err := ioutil.ReadFile(path)
			if err != nil {
				return err
			}

			err = ingestJSON(bytes, provider, index)
			if err != nil {
				return err
			}
		}
		return nil
	})
	return err
}

func ingestNative(provider *provider.Provider, client *http.Client, index *Index) error {
	resp, err := client.Get(provider.ContentURL)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

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

	return ingestJSON(body, provider, index)
}

func ingestJSON(bytes []byte, provider *provider.Provider, index *Index) error {
	var content []content.Content
	err := json.Unmarshal(bytes, &content)
	if err != nil {
		return err
	}

	for _, item := range content {
		if len(item.Domains) == 0 {
			item.Domains = provider.Domains
		}
		index.Add(&item)
	}

	return nil
}

func ingestSyndicationFeed(provider *provider.Provider, client *http.Client, index *Index) error {
	fp := gofeed.NewParser()
	fp.Client = client
	feed, err := fp.ParseURL(provider.ContentURL)
	if err != nil {
		return err
	}

	for _, item := range feed.Items {
		newc, err := createContentFromFeedItem(provider, item)
		if err != nil {
			return err
		}
		index.Add(newc)
	}

	return nil
}

func createContentFromFeedItem(provider *provider.Provider, item *gofeed.Item) (*content.Content, error) {
	r := strings.NewReader(item.Description)
	doc, err := html.Parse(r)
	if err != nil {
		return nil, err
	}

	var context = processor.NewHTMLContext(doc)
	for _, processor := range provider.GetProcessors() {
		context, err = processor.Process(context)
		if err != nil {
			return nil, err
		}
	}

	summary, err := html2text.FromHtmlNode(context.Content.(*html.Node))
	if err != nil {
		return nil, err
	}

	newc := &content.Content{
		ID:        findID(item),
		Source:    provider.ID,
		Title:     item.Title,
		Link:      item.Link,
		Image:     findImage(item, context),
		Summary:   summary,
		HTML:      item.Description,
		Tags:      append(item.Categories, provider.Categories...),
		Author:    processAuthor(item),
		Published: item.Published,
		Regions:   provider.Regions,
		Language:  provider.Language,
		Script:    provider.Script,
		Domains:   provider.Domains}
	return newc, nil
}

func findImage(item *gofeed.Item, context *processor.Context) string {
	if item.Image != nil && item.Image.URL != "" {
		return item.Image.URL
	}

	contentExt := item.Extensions["media"]["content"]
	for _, cExt := range contentExt {
		url := cExt.Attrs["url"]
		if url != "" {
			return url
		}
	}

	return context.Result["image"]
}

func processAuthor(item *gofeed.Item) string {
	if item.Author != nil {
		return item.Author.Name
	}
	return ""
}

func findID(item *gofeed.Item) string {
	if item.GUID != "" {
		return item.GUID
	}
	return item.Link
}
<|endoftext|>


<commit_before>package main

import (
	"poliskarta/helperfunctions"
	"strings"
)

var europeRoads = []string{"E4", "E6", "E10", "E12", "E14", "E16", "E18", "E22", "E45", "E65", "E", "Lv"}
var validWordsForPlaces = []string{
	"väg", "gränd", "plats", "gata", "led", "torg", "park", "trappa",
	"trappor", "bro", "gångbro", "allé", "alle", "aveny", "plan", "kaj",
	"hamn", "strand", "stig", "backe", "kajen", "hamnen", "holme", "holmar",
	"dockan", "parkväg", "byväg", "byaväg", "gård", "stråket", "tvärgata",
	"gårdar", "parkgata", "idrottsväg", "broväg", "vägen", "stationsgata",
	"hamngata", "bangårdsgata", "fätåg", "kyrkogata", "hage", "stråket", "ö",
	"träsk", "flygplats", "industriväg", "trappgata", "kärr", "ringvägen"}
var invalidWordsForRoads = []string{"väg", "Lv", "Länsväg", "länsväg"}

//Rule 1:
func Rule1(description string) []string {
	prevWordAdded := false

	//Split string on spaces - descWords = array
	descWords := strings.Split(description, " ")

	//Remove spaces from words
	helperfunctions.TrimSpacesFromArray(&descWords)

	//The resulting array of location words after filtering
	locationWords := []string{}

	//Loop through the array of words
	for i := 1; i < len(descWords); i++ {
		currentWord := descWords[i]
		prevWord := descWords[i-1]

		//Skip iteration if the previous word had a "." in the end
		if strings.HasSuffix(prevWord, ".") {
			prevWordAdded = false
			continue
		}

		//Check if previous word was added and current word is in valid road list
		if prevWordAdded {
			helperfunctions.TrimSuffixesFromWord(&currentWord, ".", ",")

			if helperfunctions.StringInSlice(currentWord, validWordsForPlaces) {
				locationWords = append(locationWords, currentWord)
				prevWordAdded = true
				continue
			}
		}

		/*
			Här har jag en tanke om att fixa en bakåt-koll när man stöter på en siffra, istället
			för en framåtkoll. Nu kollas ifall VARJE ord finns med i invalid road-listan!
			Då följer man samma struktur som för övriga checkar vi gör. Men det kan också bli kass, har
			inte tänkt igenom det helt.

			Dessutom: kanske kan fixa en punkt-koll så att man bara behöver göra trim på . och , en gång i början,
			alltså först kolla om ordet har punkt eller komma, och isf sätta en bool till true, sen trimma oavsett.
			Nu trimmas det tre gånger, och fler lär det bli.
		*/

		//Check if current word is part of the invalid road-words
		if helperfunctions.StringInSlice(currentWord, invalidWordsForRoads) && currentIndexNotLast(i, descWords) {
			nextWordInArray := descWords[i+1]
			helperfunctions.TrimSuffixesFromWord(&nextWordInArray, ".", ",")

			//Check if next word is number, if so: add it
			if helperfunctions.WordIsNumber(nextWordInArray) {
				locationWords = append(locationWords, nextWordInArray)
				prevWordAdded = true
				i++
				continue
			}
		}

		//Check if current word starts with uppercase and is NOT europe road
		if helperfunctions.StartsWithUppercase(currentWord) {
			helperfunctions.TrimSuffixesFromWord(&currentWord, ".", ",")

			if !helperfunctions.StringInSliceIgnoreCase(currentWord, europeRoads) {
				locationWords = append(locationWords, currentWord)
				prevWordAdded = true
			}

		} else {
			prevWordAdded = false
		}
	}

	return locationWords
}

func currentIndexNotLast(index int, strings []string) bool {
	return index < len(strings)-1
}
<commit_msg>Removed word from europe road list and changed a method call<commit_after>package main

import (
	"poliskarta/helperfunctions"
	"strings"
)

var europeRoads = []string{"E4", "E6", "E10", "E12", "E14", "E16", "E18", "E22", "E45", "E65", "E"}
var invalidWordsForRoads = []string{"väg", "Lv", "Länsväg", "länsväg"}
var validWordsForPlaces = []string{
	"väg", "gränd", "plats", "gata", "led", "torg", "park", "trappa",
	"trappor", "bro", "gångbro", "allé", "alle", "aveny", "plan", "kaj",
	"hamn", "strand", "stig", "backe", "kajen", "hamnen", "holme", "holmar",
	"dockan", "parkväg", "byväg", "byaväg", "gård", "stråket", "tvärgata",
	"gårdar", "parkgata", "idrottsväg", "broväg", "vägen", "stationsgata",
	"hamngata", "bangårdsgata", "fätåg", "kyrkogata", "hage", "stråket", "ö",
	"träsk", "flygplats", "industriväg", "trappgata", "kärr", "ringvägen"}

//Rule 1:
func Rule1(description string) []string {
	prevWordAdded := false

	//Split string on spaces - descWords = array
	descWords := strings.Split(description, " ")

	//Remove spaces from words
	helperfunctions.TrimSpacesFromArray(&descWords)

	//The resulting array of location words after filtering
	locationWords := []string{}

	//Loop through the array of words
	for i := 1; i < len(descWords); i++ {
		currentWord := descWords[i]
		prevWord := descWords[i-1]

		//Skip iteration if the previous word had a "." in the end
		if strings.HasSuffix(prevWord, ".") {
			prevWordAdded = false
			continue
		}

		//Check if previous word was added and current word is in valid road list
		if prevWordAdded {
			helperfunctions.TrimSuffixesFromWord(&currentWord, ".", ",")

			if helperfunctions.StringInSlice(currentWord, validWordsForPlaces) {
				locationWords = append(locationWords, currentWord)
				prevWordAdded = true
				continue
			}
		}

		/*
			Här har jag en tanke om att fixa en bakåt-koll när man stöter på en siffra, istället
			för en framåtkoll. Nu kollas ifall VARJE ord finns med i invalid road-listan!
			Då följer man samma struktur som för övriga checkar vi gör. Men det kan också bli kass, har
			inte tänkt igenom det helt.

			Dessutom: kanske kan fixa en punkt-koll så att man bara behöver göra trim på . och , en gång i början,
			alltså först kolla om ordet har punkt eller komma, och isf sätta en bool till true, sen trimma oavsett.
			Nu trimmas det tre gånger, och fler lär det bli.
		*/

		//Check if current word is part of the invalid road-words
		if helperfunctions.StringInSlice(currentWord, invalidWordsForRoads) && currentIndexNotLast(i, descWords) {
			nextWordInArray := descWords[i+1]
			helperfunctions.TrimSuffixesFromWord(&nextWordInArray, ".", ",")

			//Check if next word is number, if so: add it
			if helperfunctions.WordIsNumber(nextWordInArray) {
				locationWords = append(locationWords, nextWordInArray)
				prevWordAdded = true
				i++
				continue
			}
		}

		//Check if current word starts with uppercase and is NOT europe road
		if helperfunctions.StartsWithUppercase(currentWord) {
			helperfunctions.TrimSuffixesFromWord(&currentWord, ".", ",")

			if !helperfunctions.StringInSlice(currentWord, europeRoads) {
				locationWords = append(locationWords, currentWord)
				prevWordAdded = true
			}

		} else {
			prevWordAdded = false
		}
	}

	return locationWords
}

func currentIndexNotLast(index int, strings []string) bool {
	return index < len(strings)-1
}
<|endoftext|>


<commit_before>package command

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"sort"
	"sync"
	"testing"
	"time"

	"github.com/mackerelio/golib/logging"
	"github.com/mackerelio/mackerel-agent/agent"
	"github.com/mackerelio/mackerel-agent/checks"
	"github.com/mackerelio/mackerel-agent/config"
	"github.com/mackerelio/mackerel-agent/mackerel"
	"github.com/mackerelio/mackerel-agent/metrics"
	mkr "github.com/mackerelio/mackerel-client-go"
)

func TestDelayByHost(t *testing.T) {
	delay1 := time.Duration(delayByHost(&mkr.Host{
		ID:     "246PUVUngPo",
		Name:   "hogehoge2.host.h",
		Type:   "unknown",
		Status: "working",
	})) * time.Second

	delay2 := time.Duration(delayByHost(&mkr.Host{
		ID:     "21GZjCE5Etb",
		Name:   "hogehoge2.host.h",
		Type:   "unknown",
		Status: "working",
	})) * time.Second

	if !(0 <= delay1.Seconds() && delay1.Seconds() < 60) {
		t.Errorf("delay shoud be between 0 and 60 but %v", delay1)
	}

	if delay1 == delay2 {
		t.Error("delays shoud be different")
	}
}

type jsonObject map[string]interface{}

// newMockAPIServer makes a dummy root directry, a mock API server, a conf.Config to using them
// and returns the Config, mock handlers map and the server.
// The mock handlers map is "<method> <path>"-to-jsonObject-generator map.
func newMockAPIServer(t *testing.T) (config.Config, map[string]func(*http.Request) (int, jsonObject), *httptest.Server) {
	mockHandlers := map[string]func(*http.Request) (int, jsonObject){}

	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		key := req.Method + " " + req.URL.Path
		handler, ok := mockHandlers[key]
		if !ok {
			t.Fatal("Unexpected request: " + key)
		}

		statusCode, data := handler(req)

		respJSON, err := json.Marshal(data)
		if err != nil {
			t.Fatal("marshalling JSON failed: ", err)
		}

		if statusCode != 0 {
			w.WriteHeader(statusCode)
		}

		w.Header().Set("Content-Type", "application/json")
		fmt.Fprint(w, string(respJSON))
	}))

	root, err := ioutil.TempDir("", "mackerel-agent-test")
	if err != nil {
		t.Fatal(err)
	}

	conf := config.Config{
		Apibase: ts.URL,
		Root:    root,
	}

	return conf, mockHandlers, ts
}

func TestPrepareWithCreate(t *testing.T) {
	conf, mockHandlers, ts := newMockAPIServer(t)
	defer ts.Close()

	mockHandlers["POST /api/v0/hosts"] = func(req *http.Request) (int, jsonObject) {
		return 200, jsonObject{
			"id": "xxx1234567890",
		}
	}

	mockHandlers["GET /api/v0/hosts/xxx1234567890"] = func(req *http.Request) (int, jsonObject) {
		return 200, jsonObject{
			"host": mkr.Host{
				ID:     "xxx1234567890",
				Name:   "host.example.com",
				Type:   "unknown",
				Status: "standby",
			},
		}
	}

	c, _ := Prepare(&conf, &AgentMeta{})
	api := c.API
	host := c.Host

	if api.BaseURL.String() != ts.URL {
		t.Errorf("Apibase mismatch: %s != %s", api.BaseURL, ts.URL)
	}

	if host.ID != "xxx1234567890" {
		t.Error("Host ID mismatch", host)
	}

	if host.Name != "host.example.com" {
		t.Error("Host name mismatch", host)
	}
}

func TestPrepareWithCreateWithFail(t *testing.T) {
	conf, mockHandlers, ts := newMockAPIServer(t)
	defer ts.Close()

	mockHandlers["POST /api/v0/hosts"] = func(req *http.Request) (int, jsonObject) {
		return 403, jsonObject{
			"result": "error",
		}
	}

	origRetryNum := retryNum
	retryNum = 1
	defer func() {
		retryNum = origRetryNum
	}()

	_, err := Prepare(&conf, &AgentMeta{})

	if err == nil {
		t.Errorf("error should be occurred")
	}
}

func TestPrepareWithUpdate(t *testing.T) {
	conf, mockHandlers, ts := newMockAPIServer(t)
	defer ts.Close()
	tempDir, _ := ioutil.TempDir("", "")
	conf.Root = tempDir
	conf.SaveHostID("xxx12345678901")

	mockHandlers["PUT /api/v0/hosts/xxx12345678901"] = func(req *http.Request) (int, jsonObject) {
		return 200, jsonObject{
			"result": "OK",
		}
	}

	mockHandlers["GET /api/v0/hosts/xxx12345678901"] = func(req *http.Request) (int, jsonObject) {
		return 200, jsonObject{
			"host": mkr.Host{
				ID:     "xxx12345678901",
				Name:   "host.example.com",
				Type:   "unknown",
				Status: "standby",
			},
		}
	}

	c, _ := Prepare(&conf, &AgentMeta{})
	api := c.API
	host := c.Host

	if api.BaseURL.String() != ts.URL {
		t.Errorf("Apibase mismatch: %s != %s", api.BaseURL, ts.URL)
	}

	if host.ID != "xxx12345678901" {
		t.Error("Host ID mismatch", host)
	}

	if host.Name != "host.example.com" {
		t.Error("Host name mismatch", host)
	}
}

func TestCollectHostSpecs(t *testing.T) {
	conf := config.Config{}
	hostParam, err := collectHostParam(&conf, &AgentMeta{})

	if err != nil {
		t.Errorf("collectHostParam should not fail: %s", err)
	}

	if hostParam.Name == "" {
		t.Error("hostname should not be empty")
	}

	if len(hostParam.Meta.CPU) == 0 {
		t.Error("meta.cpu should exist")
	}

	if len(hostParam.Meta.Memory) == 0 {
		t.Error("meta.memory should exist")
	}

	if len(hostParam.Meta.Filesystem) == 0 {
		t.Error("meta.filesystem should exist")
	}

	if len(hostParam.Meta.Kernel) == 0 {
		t.Error("meta.kernel should exist")
	}
}

type counterGenerator struct {
	counter int
	sync.Mutex
}

func (g *counterGenerator) Generate() (metrics.Values, error) {
	g.Lock()
	defer g.Unlock()
	g.counter = g.counter + 1
	return map[string]float64{"dummy.a": float64(g.counter)}, nil
}

type byTime []mkr.HostMetricValue

func (b byTime) Len() int           { return len(b) }
func (b byTime) Swap(i, j int)      { b[i], b[j] = b[j], b[i] }
func (b byTime) Less(i, j int) bool { return b[i].Time < b[j].Time }

func TestLoop(t *testing.T) {
	if testing.Verbose() {
		logging.SetLogLevel(logging.DEBUG)
	}

	conf, mockHandlers, ts := newMockAPIServer(t)
	defer ts.Close()

	if testing.Short() {
		// Shrink time scale
		originalPostMetricsInterval := config.PostMetricsInterval

		config.PostMetricsInterval = 10 * time.Second
		ratio := config.PostMetricsInterval.Seconds() / originalPostMetricsInterval.Seconds()

		postMetricsDequeueDelaySeconds =
			int(float64(postMetricsDequeueDelaySeconds) * ratio)
		postMetricsRetryDelaySeconds =
			int(float64(postMetricsRetryDelaySeconds) * ratio)

		defer func() {
			config.PostMetricsInterval = originalPostMetricsInterval
		}()
	}

	/// Simulate the situation that mackerel.io is down for 3 min
	// Strategy:
	// counterGenerator generates values 1,2,3,4,...
	// when we got value 3, the server will start responding 503 for three times (inclusive)
	// so the agent should queue the generated values and retry sending.
	//
	//  status: o . o . x . x . x . o o o o o
	//    send: 1 . 2 . 3 . 3 . 3 . 3 4 5 6 7
	// collect: 1 . 2 . 3 . 4 . 5 . 6 . 7 . 8
	//           ^
	//           30s
	const (
		totalFailures = 3
		totalPosts    = 7
	)
	failureCount := 0
	receivedDataPoints := []mkr.HostMetricValue{}
	done := make(chan struct{})

	mockHandlers["POST /api/v0/tsdb"] = func(req *http.Request) (int, jsonObject) {
		payload := []mkr.HostMetricValue{}
		json.NewDecoder(req.Body).Decode(&payload)

		for _, p := range payload {
			value := p.Value.(float64)
			if value == 3 {
				failureCount++
				if failureCount <= totalFailures {
					return 503, jsonObject{
						"failure": failureCount, // just for DEBUG logging
					}
				}
			}

			if value == totalPosts {
				defer func() { done <- struct{}{} }()
			}
		}

		receivedDataPoints = append(receivedDataPoints, payload...)

		return 200, jsonObject{
			"success": true,
		}
	}
	mockHandlers["PUT /api/v0/hosts/xyzabc12345"] = func(req *http.Request) (int, jsonObject) {
		return 200, jsonObject{
			"result": "OK",
		}
	}

	// Prepare required objects...
	ag := &agent.Agent{
		MetricsGenerators: []metrics.Generator{
			&counterGenerator{},
		},
	}

	api, err := mackerel.NewAPI(conf.Apibase, conf.Apikey, true)
	if err != nil {
		t.Fatal(err)
	}

	host := &mkr.Host{ID: "xyzabc12345"}

	termCh := make(chan struct{})
	exitCh := make(chan error)
	app := &App{
		Agent:     ag,
		Config:    &conf,
		API:       api,
		Host:      host,
		AgentMeta: &AgentMeta{},
	}
	// Start looping!
	go func() {
		exitCh <- loop(app, termCh)
	}()

	<-done

	// Verify results
	if len(receivedDataPoints) != totalPosts {
		t.Errorf("the agent should have sent %d datapoints, got: %+v", totalPosts, receivedDataPoints)
	}

	sort.Sort(byTime(receivedDataPoints))

	for i := 0; i < totalPosts; i++ {
		value := receivedDataPoints[i].Value.(float64)
		if value != float64(i+1) {
			t.Errorf("the %dth datapoint should have value %d, got: %+v", i, i+1, receivedDataPoints)
		}
	}

	termCh <- struct{}{}
	exitErr := <-exitCh
	if exitErr != nil {
		t.Errorf("exitErr should be nil, got: %s", exitErr)
	}
}

func TestReportCheckMonitors(t *testing.T) {
	if testing.Verbose() {
		logging.SetLogLevel(logging.DEBUG)
	}

	cases := []struct {
		Status      int
		expectRetry bool
	}{
		{http.StatusOK, false},
		{http.StatusBadRequest, false},
		{http.StatusInternalServerError, true},
	}

	for _, tc := range cases {
		conf, mockHandlers, ts := newMockAPIServer(t)
		defer ts.Close()

		if testing.Short() {
			reportCheckRetryDelaySeconds = 1
		}

		postCount := 0
		retried := false
		mu := &sync.Mutex{}

		mockHandlers["POST /api/v0/monitoring/checks/report"] = func(req *http.Request) (int, jsonObject) {
			mu.Lock()
			defer mu.Unlock()
			postCount++
			if postCount > 1 {
				retried = true
			}
			return tc.Status, jsonObject{}
		}

		api, err := mackerel.NewAPI(conf.Apibase, conf.Apikey, true)
		if err != nil {
			t.Fatal(err)
		}

		host := &mkr.Host{ID: "xyzabc12345"}

		app := &App{
			Agent:     &agent.Agent{},
			Config:    &conf,
			API:       api,
			Host:      host,
			AgentMeta: &AgentMeta{},
		}

		go func() {
			reportCheckMonitors(app, app.Host, []*checks.Report{})
		}()

		time.Sleep(time.Duration(reportCheckRetryDelaySeconds) * 3 * time.Second)

		mu.Lock()
		defer mu.Unlock()

		if retried != tc.expectRetry {
			text := http.StatusText(tc.Status)
			if tc.expectRetry {
				t.Errorf("the agent should have resend reports when got %d %q", tc.Status, text)
			} else {
				t.Errorf("the agent should not have resend reports when got %d %q", tc.Status, text)
			}
		}
	}
}
<commit_msg>rename<commit_after>package command

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"sort"
	"sync"
	"testing"
	"time"

	"github.com/mackerelio/golib/logging"
	"github.com/mackerelio/mackerel-agent/agent"
	"github.com/mackerelio/mackerel-agent/checks"
	"github.com/mackerelio/mackerel-agent/config"
	"github.com/mackerelio/mackerel-agent/mackerel"
	"github.com/mackerelio/mackerel-agent/metrics"
	mkr "github.com/mackerelio/mackerel-client-go"
)

func TestDelayByHost(t *testing.T) {
	delay1 := time.Duration(delayByHost(&mkr.Host{
		ID:     "246PUVUngPo",
		Name:   "hogehoge2.host.h",
		Type:   "unknown",
		Status: "working",
	})) * time.Second

	delay2 := time.Duration(delayByHost(&mkr.Host{
		ID:     "21GZjCE5Etb",
		Name:   "hogehoge2.host.h",
		Type:   "unknown",
		Status: "working",
	})) * time.Second

	if !(0 <= delay1.Seconds() && delay1.Seconds() < 60) {
		t.Errorf("delay shoud be between 0 and 60 but %v", delay1)
	}

	if delay1 == delay2 {
		t.Error("delays shoud be different")
	}
}

type jsonObject map[string]interface{}

// newMockAPIServer makes a dummy root directry, a mock API server, a conf.Config to using them
// and returns the Config, mock handlers map and the server.
// The mock handlers map is "<method> <path>"-to-jsonObject-generator map.
func newMockAPIServer(t *testing.T) (config.Config, map[string]func(*http.Request) (int, jsonObject), *httptest.Server) {
	mockHandlers := map[string]func(*http.Request) (int, jsonObject){}

	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		key := req.Method + " " + req.URL.Path
		handler, ok := mockHandlers[key]
		if !ok {
			t.Fatal("Unexpected request: " + key)
		}

		statusCode, data := handler(req)

		respJSON, err := json.Marshal(data)
		if err != nil {
			t.Fatal("marshalling JSON failed: ", err)
		}

		if statusCode != 0 {
			w.WriteHeader(statusCode)
		}

		w.Header().Set("Content-Type", "application/json")
		fmt.Fprint(w, string(respJSON))
	}))

	root, err := ioutil.TempDir("", "mackerel-agent-test")
	if err != nil {
		t.Fatal(err)
	}

	conf := config.Config{
		Apibase: ts.URL,
		Root:    root,
	}

	return conf, mockHandlers, ts
}

func TestPrepareWithCreate(t *testing.T) {
	conf, mockHandlers, ts := newMockAPIServer(t)
	defer ts.Close()

	mockHandlers["POST /api/v0/hosts"] = func(req *http.Request) (int, jsonObject) {
		return 200, jsonObject{
			"id": "xxx1234567890",
		}
	}

	mockHandlers["GET /api/v0/hosts/xxx1234567890"] = func(req *http.Request) (int, jsonObject) {
		return 200, jsonObject{
			"host": mkr.Host{
				ID:     "xxx1234567890",
				Name:   "host.example.com",
				Type:   "unknown",
				Status: "standby",
			},
		}
	}

	c, _ := Prepare(&conf, &AgentMeta{})
	api := c.API
	host := c.Host

	if api.BaseURL.String() != ts.URL {
		t.Errorf("Apibase mismatch: %s != %s", api.BaseURL, ts.URL)
	}

	if host.ID != "xxx1234567890" {
		t.Error("Host ID mismatch", host)
	}

	if host.Name != "host.example.com" {
		t.Error("Host name mismatch", host)
	}
}

func TestPrepareWithCreateWithFail(t *testing.T) {
	conf, mockHandlers, ts := newMockAPIServer(t)
	defer ts.Close()

	mockHandlers["POST /api/v0/hosts"] = func(req *http.Request) (int, jsonObject) {
		return 403, jsonObject{
			"result": "error",
		}
	}

	origRetryNum := retryNum
	retryNum = 1
	defer func() {
		retryNum = origRetryNum
	}()

	_, err := Prepare(&conf, &AgentMeta{})

	if err == nil {
		t.Errorf("error should be occurred")
	}
}

func TestPrepareWithUpdate(t *testing.T) {
	conf, mockHandlers, ts := newMockAPIServer(t)
	defer ts.Close()
	tempDir, _ := ioutil.TempDir("", "")
	conf.Root = tempDir
	conf.SaveHostID("xxx12345678901")

	mockHandlers["PUT /api/v0/hosts/xxx12345678901"] = func(req *http.Request) (int, jsonObject) {
		return 200, jsonObject{
			"result": "OK",
		}
	}

	mockHandlers["GET /api/v0/hosts/xxx12345678901"] = func(req *http.Request) (int, jsonObject) {
		return 200, jsonObject{
			"host": mkr.Host{
				ID:     "xxx12345678901",
				Name:   "host.example.com",
				Type:   "unknown",
				Status: "standby",
			},
		}
	}

	c, _ := Prepare(&conf, &AgentMeta{})
	api := c.API
	host := c.Host

	if api.BaseURL.String() != ts.URL {
		t.Errorf("Apibase mismatch: %s != %s", api.BaseURL, ts.URL)
	}

	if host.ID != "xxx12345678901" {
		t.Error("Host ID mismatch", host)
	}

	if host.Name != "host.example.com" {
		t.Error("Host name mismatch", host)
	}
}

func TestCollectHostParam(t *testing.T) {
	conf := config.Config{}
	hostParam, err := collectHostParam(&conf, &AgentMeta{})

	if err != nil {
		t.Errorf("collectHostParam should not fail: %s", err)
	}

	if hostParam.Name == "" {
		t.Error("hostname should not be empty")
	}

	if len(hostParam.Meta.CPU) == 0 {
		t.Error("meta.cpu should exist")
	}

	if len(hostParam.Meta.Memory) == 0 {
		t.Error("meta.memory should exist")
	}

	if len(hostParam.Meta.Filesystem) == 0 {
		t.Error("meta.filesystem should exist")
	}

	if len(hostParam.Meta.Kernel) == 0 {
		t.Error("meta.kernel should exist")
	}
}

type counterGenerator struct {
	counter int
	sync.Mutex
}

func (g *counterGenerator) Generate() (metrics.Values, error) {
	g.Lock()
	defer g.Unlock()
	g.counter = g.counter + 1
	return map[string]float64{"dummy.a": float64(g.counter)}, nil
}

type byTime []mkr.HostMetricValue

func (b byTime) Len() int           { return len(b) }
func (b byTime) Swap(i, j int)      { b[i], b[j] = b[j], b[i] }
func (b byTime) Less(i, j int) bool { return b[i].Time < b[j].Time }

func TestLoop(t *testing.T) {
	if testing.Verbose() {
		logging.SetLogLevel(logging.DEBUG)
	}

	conf, mockHandlers, ts := newMockAPIServer(t)
	defer ts.Close()

	if testing.Short() {
		// Shrink time scale
		originalPostMetricsInterval := config.PostMetricsInterval

		config.PostMetricsInterval = 10 * time.Second
		ratio := config.PostMetricsInterval.Seconds() / originalPostMetricsInterval.Seconds()

		postMetricsDequeueDelaySeconds =
			int(float64(postMetricsDequeueDelaySeconds) * ratio)
		postMetricsRetryDelaySeconds =
			int(float64(postMetricsRetryDelaySeconds) * ratio)

		defer func() {
			config.PostMetricsInterval = originalPostMetricsInterval
		}()
	}

	/// Simulate the situation that mackerel.io is down for 3 min
	// Strategy:
	// counterGenerator generates values 1,2,3,4,...
	// when we got value 3, the server will start responding 503 for three times (inclusive)
	// so the agent should queue the generated values and retry sending.
	//
	//  status: o . o . x . x . x . o o o o o
	//    send: 1 . 2 . 3 . 3 . 3 . 3 4 5 6 7
	// collect: 1 . 2 . 3 . 4 . 5 . 6 . 7 . 8
	//           ^
	//           30s
	const (
		totalFailures = 3
		totalPosts    = 7
	)
	failureCount := 0
	receivedDataPoints := []mkr.HostMetricValue{}
	done := make(chan struct{})

	mockHandlers["POST /api/v0/tsdb"] = func(req *http.Request) (int, jsonObject) {
		payload := []mkr.HostMetricValue{}
		json.NewDecoder(req.Body).Decode(&payload)

		for _, p := range payload {
			value := p.Value.(float64)
			if value == 3 {
				failureCount++
				if failureCount <= totalFailures {
					return 503, jsonObject{
						"failure": failureCount, // just for DEBUG logging
					}
				}
			}

			if value == totalPosts {
				defer func() { done <- struct{}{} }()
			}
		}

		receivedDataPoints = append(receivedDataPoints, payload...)

		return 200, jsonObject{
			"success": true,
		}
	}
	mockHandlers["PUT /api/v0/hosts/xyzabc12345"] = func(req *http.Request) (int, jsonObject) {
		return 200, jsonObject{
			"result": "OK",
		}
	}

	// Prepare required objects...
	ag := &agent.Agent{
		MetricsGenerators: []metrics.Generator{
			&counterGenerator{},
		},
	}

	api, err := mackerel.NewAPI(conf.Apibase, conf.Apikey, true)
	if err != nil {
		t.Fatal(err)
	}

	host := &mkr.Host{ID: "xyzabc12345"}

	termCh := make(chan struct{})
	exitCh := make(chan error)
	app := &App{
		Agent:     ag,
		Config:    &conf,
		API:       api,
		Host:      host,
		AgentMeta: &AgentMeta{},
	}
	// Start looping!
	go func() {
		exitCh <- loop(app, termCh)
	}()

	<-done

	// Verify results
	if len(receivedDataPoints) != totalPosts {
		t.Errorf("the agent should have sent %d datapoints, got: %+v", totalPosts, receivedDataPoints)
	}

	sort.Sort(byTime(receivedDataPoints))

	for i := 0; i < totalPosts; i++ {
		value := receivedDataPoints[i].Value.(float64)
		if value != float64(i+1) {
			t.Errorf("the %dth datapoint should have value %d, got: %+v", i, i+1, receivedDataPoints)
		}
	}

	termCh <- struct{}{}
	exitErr := <-exitCh
	if exitErr != nil {
		t.Errorf("exitErr should be nil, got: %s", exitErr)
	}
}

func TestReportCheckMonitors(t *testing.T) {
	if testing.Verbose() {
		logging.SetLogLevel(logging.DEBUG)
	}

	cases := []struct {
		Status      int
		expectRetry bool
	}{
		{http.StatusOK, false},
		{http.StatusBadRequest, false},
		{http.StatusInternalServerError, true},
	}

	for _, tc := range cases {
		conf, mockHandlers, ts := newMockAPIServer(t)
		defer ts.Close()

		if testing.Short() {
			reportCheckRetryDelaySeconds = 1
		}

		postCount := 0
		retried := false
		mu := &sync.Mutex{}

		mockHandlers["POST /api/v0/monitoring/checks/report"] = func(req *http.Request) (int, jsonObject) {
			mu.Lock()
			defer mu.Unlock()
			postCount++
			if postCount > 1 {
				retried = true
			}
			return tc.Status, jsonObject{}
		}

		api, err := mackerel.NewAPI(conf.Apibase, conf.Apikey, true)
		if err != nil {
			t.Fatal(err)
		}

		host := &mkr.Host{ID: "xyzabc12345"}

		app := &App{
			Agent:     &agent.Agent{},
			Config:    &conf,
			API:       api,
			Host:      host,
			AgentMeta: &AgentMeta{},
		}

		go func() {
			reportCheckMonitors(app, app.Host, []*checks.Report{})
		}()

		time.Sleep(time.Duration(reportCheckRetryDelaySeconds) * 3 * time.Second)

		mu.Lock()
		defer mu.Unlock()

		if retried != tc.expectRetry {
			text := http.StatusText(tc.Status)
			if tc.expectRetry {
				t.Errorf("the agent should have resend reports when got %d %q", tc.Status, text)
			} else {
				t.Errorf("the agent should not have resend reports when got %d %q", tc.Status, text)
			}
		}
	}
}
<|endoftext|>


<commit_before>package service

import (
	"fmt"
	"io"
	"strings"
	"text/tabwriter"

	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/filters"
	"github.com/docker/docker/api/types/swarm"
	"github.com/docker/docker/cli"
	"github.com/docker/docker/cli/command"
	"github.com/docker/docker/opts"
	"github.com/docker/docker/pkg/stringid"
	"github.com/spf13/cobra"
	"golang.org/x/net/context"
)

const (
	listItemFmt = "%s\t%s\t%s\t%s\t%s\n"
)

type listOptions struct {
	quiet  bool
	filter opts.FilterOpt
}

func newListCommand(dockerCli *command.DockerCli) *cobra.Command {
	opts := listOptions{filter: opts.NewFilterOpt()}

	cmd := &cobra.Command{
		Use:     "ls [OPTIONS]",
		Aliases: []string{"list"},
		Short:   "List services",
		Args:    cli.NoArgs,
		RunE: func(cmd *cobra.Command, args []string) error {
			return runList(dockerCli, opts)
		},
	}

	flags := cmd.Flags()
	flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Only display IDs")
	flags.VarP(&opts.filter, "filter", "f", "Filter output based on conditions provided")

	return cmd
}

func runList(dockerCli *command.DockerCli, opts listOptions) error {
	ctx := context.Background()
	client := dockerCli.Client()
	out := dockerCli.Out()

	services, err := client.ServiceList(ctx, types.ServiceListOptions{Filters: opts.filter.Value()})
	if err != nil {
		return err
	}

	if len(services) > 0 && !opts.quiet {
		// only non-empty services and not quiet, should we call TaskList and NodeList api
		taskFilter := filters.NewArgs()
		for _, service := range services {
			taskFilter.Add("service", service.ID)
		}

		tasks, err := client.TaskList(ctx, types.TaskListOptions{Filters: taskFilter})
		if err != nil {
			return err
		}

		nodes, err := client.NodeList(ctx, types.NodeListOptions{})
		if err != nil {
			return err
		}

		PrintNotQuiet(out, services, nodes, tasks)
	} else if !opts.quiet {
		// no services and not quiet, print only one line with columns ID, NAME, REPLICAS...
		PrintNotQuiet(out, services, []swarm.Node{}, []swarm.Task{})
	} else {
		PrintQuiet(out, services)
	}

	return nil
}

// PrintNotQuiet shows service list in a non-quiet way.
// Besides this, command `docker stack services xxx` will call this, too.
func PrintNotQuiet(out io.Writer, services []swarm.Service, nodes []swarm.Node, tasks []swarm.Task) {
	activeNodes := make(map[string]struct{})
	for _, n := range nodes {
		if n.Status.State != swarm.NodeStateDown {
			activeNodes[n.ID] = struct{}{}
		}
	}

	running := map[string]int{}
	for _, task := range tasks {
		if _, nodeActive := activeNodes[task.NodeID]; nodeActive && task.Status.State == "running" {
			running[task.ServiceID]++
		}
	}

	printTable(out, services, running)
}

func printTable(out io.Writer, services []swarm.Service, running map[string]int) {
	writer := tabwriter.NewWriter(out, 0, 4, 2, ' ', 0)

	// Ignore flushing errors
	defer writer.Flush()

	fmt.Fprintf(writer, listItemFmt, "ID", "NAME", "REPLICAS", "IMAGE", "COMMAND")
	for _, service := range services {
		replicas := ""
		if service.Spec.Mode.Replicated != nil && service.Spec.Mode.Replicated.Replicas != nil {
			replicas = fmt.Sprintf("%d/%d", running[service.ID], *service.Spec.Mode.Replicated.Replicas)
		} else if service.Spec.Mode.Global != nil {
			replicas = "global"
		}
		fmt.Fprintf(
			writer,
			listItemFmt,
			stringid.TruncateID(service.ID),
			service.Spec.Name,
			replicas,
			service.Spec.TaskTemplate.ContainerSpec.Image,
			strings.Join(service.Spec.TaskTemplate.ContainerSpec.Args, " "))
	}
}

// PrintQuiet shows service list in a quiet way.
// Besides this, command `docker stack services xxx` will call this, too.
func PrintQuiet(out io.Writer, services []swarm.Service) {
	for _, service := range services {
		fmt.Fprintln(out, service.ID)
	}
}
<commit_msg>remove COMMAND column from service ls output. closes #27994<commit_after>package service

import (
	"fmt"
	"io"
	"text/tabwriter"

	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/filters"
	"github.com/docker/docker/api/types/swarm"
	"github.com/docker/docker/cli"
	"github.com/docker/docker/cli/command"
	"github.com/docker/docker/opts"
	"github.com/docker/docker/pkg/stringid"
	"github.com/spf13/cobra"
	"golang.org/x/net/context"
)

const (
	listItemFmt = "%s\t%s\t%s\t%s\n"
)

type listOptions struct {
	quiet  bool
	filter opts.FilterOpt
}

func newListCommand(dockerCli *command.DockerCli) *cobra.Command {
	opts := listOptions{filter: opts.NewFilterOpt()}

	cmd := &cobra.Command{
		Use:     "ls [OPTIONS]",
		Aliases: []string{"list"},
		Short:   "List services",
		Args:    cli.NoArgs,
		RunE: func(cmd *cobra.Command, args []string) error {
			return runList(dockerCli, opts)
		},
	}

	flags := cmd.Flags()
	flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Only display IDs")
	flags.VarP(&opts.filter, "filter", "f", "Filter output based on conditions provided")

	return cmd
}

func runList(dockerCli *command.DockerCli, opts listOptions) error {
	ctx := context.Background()
	client := dockerCli.Client()
	out := dockerCli.Out()

	services, err := client.ServiceList(ctx, types.ServiceListOptions{Filters: opts.filter.Value()})
	if err != nil {
		return err
	}

	if len(services) > 0 && !opts.quiet {
		// only non-empty services and not quiet, should we call TaskList and NodeList api
		taskFilter := filters.NewArgs()
		for _, service := range services {
			taskFilter.Add("service", service.ID)
		}

		tasks, err := client.TaskList(ctx, types.TaskListOptions{Filters: taskFilter})
		if err != nil {
			return err
		}

		nodes, err := client.NodeList(ctx, types.NodeListOptions{})
		if err != nil {
			return err
		}

		PrintNotQuiet(out, services, nodes, tasks)
	} else if !opts.quiet {
		// no services and not quiet, print only one line with columns ID, NAME, REPLICAS...
		PrintNotQuiet(out, services, []swarm.Node{}, []swarm.Task{})
	} else {
		PrintQuiet(out, services)
	}

	return nil
}

// PrintNotQuiet shows service list in a non-quiet way.
// Besides this, command `docker stack services xxx` will call this, too.
func PrintNotQuiet(out io.Writer, services []swarm.Service, nodes []swarm.Node, tasks []swarm.Task) {
	activeNodes := make(map[string]struct{})
	for _, n := range nodes {
		if n.Status.State != swarm.NodeStateDown {
			activeNodes[n.ID] = struct{}{}
		}
	}

	running := map[string]int{}
	for _, task := range tasks {
		if _, nodeActive := activeNodes[task.NodeID]; nodeActive && task.Status.State == "running" {
			running[task.ServiceID]++
		}
	}

	printTable(out, services, running)
}

func printTable(out io.Writer, services []swarm.Service, running map[string]int) {
	writer := tabwriter.NewWriter(out, 0, 4, 2, ' ', 0)

	// Ignore flushing errors
	defer writer.Flush()

	fmt.Fprintf(writer, listItemFmt, "ID", "NAME", "REPLICAS", "IMAGE")
	for _, service := range services {
		replicas := ""
		if service.Spec.Mode.Replicated != nil && service.Spec.Mode.Replicated.Replicas != nil {
			replicas = fmt.Sprintf("%d/%d", running[service.ID], *service.Spec.Mode.Replicated.Replicas)
		} else if service.Spec.Mode.Global != nil {
			replicas = "global"
		}
		fmt.Fprintf(
			writer,
			listItemFmt,
			stringid.TruncateID(service.ID),
			service.Spec.Name,
			replicas,
			service.Spec.TaskTemplate.ContainerSpec.Image)
	}
}

// PrintQuiet shows service list in a quiet way.
// Besides this, command `docker stack services xxx` will call this, too.
func PrintQuiet(out io.Writer, services []swarm.Service) {
	for _, service := range services {
		fmt.Fprintln(out, service.ID)
	}
}
<|endoftext|>


<commit_before>package instructions

var (
    _aload_0 = &aload_0{}
    _aload_1 = &aload_1{}
    _aload_2 = &aload_2{}
    _aload_3 = &aload_3{}
    _arraylength = &arraylength{}
    _astore_0 = &astore_0{}
    _astore_1 = &astore_1{}
    _astore_2 = &astore_2{}
    _astore_3 = &astore_3{}
    _athrow = &athrow{}
    _d2f = &d2f{}
    _d2i = &d2i{}
    _d2l = &d2l{}
    _dcmpg = &dcmpg{}
    _dcmpl = &dcmpl{}
    _dload_0 = &dload_0{}
    _dload_1 = &dload_1{}
    _dload_2 = &dload_2{}
    _dload_3 = &dload_3{}
    _dstore_0 = &dstore_0{}
    _dstore_1 = &dstore_1{}
    _dstore_2 = &dstore_2{}
    _dstore_3 = &dstore_3{}
    _dup = &dup{}
    _dup_x1 = &dup_x1{}
    _dup_x2 = &dup_x2{}
    _dup2 = &dup2{}
    _dup2_x1 = &dup2_x1{}
    _dup2_x2 = &dup2_x2{}
    _f2d = &f2d{}
    _f2i = &f2i{}
    _f2l = &f2l{}
    _fcmpg = &fcmpg{}
    _fcmpl = &fcmpl{}
    _fload_0 = &fload_0{}
    _fload_1 = &fload_1{}
    _fload_2 = &fload_2{}
    _fload_3 = &fload_3{}
    _fstore_0 = &fstore_0{}
    _fstore_1 = &fstore_1{}
    _fstore_2 = &fstore_2{}
    _fstore_3 = &fstore_3{}
    _i2b = &i2b{}
    _i2c = &i2c{}
    _i2d = &i2d{}
    _i2f = &i2f{}
    _i2l = &i2l{}
    _i2s = &i2s{}
    _iload_0 = &iload_0{}
    _iload_1 = &iload_1{}
    _iload_2 = &iload_2{}
    _iload_3 = &iload_3{}
    _istore_0 = &istore_0{}
    _istore_1 = &istore_1{}
    _istore_2 = &istore_2{}
    _istore_3 = &istore_3{}
    _l2d = &l2d{}
    _l2f = &l2f{}
    _l2i = &l2i{}
    _lcmp = &lcmp{}
    _lload_0 = &lload_0{}
    _lload_1 = &lload_1{}
    _lload_2 = &lload_2{}
    _lload_3 = &lload_3{}
    _lstore_0 = &lstore_0{}
    _lstore_1 = &lstore_1{}
    _lstore_2 = &lstore_2{}
    _lstore_3 = &lstore_3{}
    _monitorenter = &monitorenter{}
    _monitorexit = &monitorexit{}
    _nop = &nop{}
    _pop = &pop{}
    _pop2 = &pop2{}
    _swap = &swap{}
    _dadd = &dadd{}
    _fadd = &fadd{}
    _iadd = &iadd{}
    _ladd = &ladd{}
    _aaload = &aaload{}
    _baload = &baload{}
    _caload = &caload{}
    _daload = &daload{}
    _faload = &faload{}
    _iaload = &iaload{}
    _laload = &laload{}
    _saload = &saload{}
    _iand = &iand{}
    _land = &land{}
    _aastore = &aastore{}
    _bastore = &bastore{}
    _castore = &castore{}
    _dastore = &dastore{}
    _fastore = &fastore{}
    _iastore = &iastore{}
    _lastore = &lastore{}
    _sastore = &sastore{}
    _aconst_null = &aconst_null{}
    _dconst_0 = &dconst_0{}
    _dconst_1 = &dconst_1{}
    _fconst_0 = &fconst_0{}
    _fconst_1 = &fconst_1{}
    _fconst_2 = &fconst_2{}
    _iconst_m1 = &iconst_m1{}
    _iconst_0 = &iconst_0{}
    _iconst_1 = &iconst_1{}
    _iconst_2 = &iconst_2{}
    _iconst_3 = &iconst_3{}
    _iconst_4 = &iconst_4{}
    _iconst_5 = &iconst_5{}
    _lconst_0 = &lconst_0{}
    _lconst_1 = &lconst_1{}
    _ddiv = &ddiv{}
    _fdiv = &fdiv{}
    _idiv = &idiv{}
    _ldiv = &ldiv{}
    _dmul = &dmul{}
    _fmul = &fmul{}
    _imul = &imul{}
    _lmul = &lmul{}
)

func Decode(bcr *BytecodeReader) (Instruction) {
    opcode := bcr.readUint8()
    instruction := newInstruction(opcode)
    instruction.fetchOperands(bcr)
    return instruction
}

func newInstruction(opcode byte) (Instruction) {
    switch opcode {
    case 0x00: return _nop
    case 0x01: return _aconst_null
    case 0x02: return _iconst_m1
    case 0x03: return _iconst_0
    case 0x04: return _iconst_1
    case 0x05: return _iconst_2
    case 0x06: return _iconst_3
    case 0x07: return _iconst_4
    case 0x08: return _iconst_5
    case 0x09: return _lconst_0
    case 0x0a: return _lconst_1
    case 0x0b: return _fconst_0
    case 0x0c: return _fconst_1
    case 0x0d: return _fconst_2
    case 0x0e: return _dconst_0
    case 0x0f: return _dconst_1
    case 0x10: return &bipush{}
    case 0x11: return &sipush{}
    case 0x12: return &ldc{}
    case 0x13: return &ldc_w{}
    case 0x14: return &ldc2_w{}
    case 0x15: return &iload{}
    case 0x16: return &lload{}
    case 0x17: return &fload{}
    case 0x18: return &dload{}
    case 0x19: return &aload{}
    case 0x1a: return _iload_0
    case 0x1b: return _iload_1
    case 0x1c: return _iload_2
    case 0x1d: return _iload_3
    case 0x1e: return _lload_0
    case 0x1f: return _lload_1
    case 0x20: return _lload_2
    case 0x21: return _lload_3
    case 0x22: return _fload_0
    case 0x23: return _fload_1
    case 0x24: return _fload_2
    case 0x25: return _fload_3
    case 0x26: return _dload_0
    case 0x27: return _dload_1
    case 0x28: return _dload_2
    case 0x29: return _dload_3
    case 0x2a: return _aload_0
    case 0x2b: return _aload_1
    case 0x2c: return _aload_2
    case 0x2d: return _aload_3
    case 0x2e: return _iaload
    case 0x2f: return _laload
    case 0x30: return _faload
    case 0x31: return _daload
    case 0x32: return _aaload
    case 0x33: return _baload
    case 0x34: return _caload
    case 0x35: return _saload
    case 0x36: return &istore{}
    case 0x37: return &lstore{}
    case 0x38: return &fstore{}
    case 0x39: return &dstore{}
    case 0x3a: return &astore{}
    case 0x3b: return _istore_0
    case 0x3c: return _istore_1
    case 0x3d: return _istore_2
    case 0x3e: return _istore_3
    case 0x3f: return _lstore_0
    case 0x40: return _lstore_1
    case 0x41: return _lstore_2
    case 0x42: return _lstore_3
    case 0x43: return _fstore_0
    case 0x44: return _fstore_1
    case 0x45: return _fstore_2
    case 0x46: return _fstore_3
    case 0x47: return _dstore_0
    case 0x48: return _dstore_1
    case 0x49: return _dstore_2
    case 0x4a: return _dstore_3
    case 0x4b: return _astore_0
    case 0x4c: return _astore_1
    case 0x4d: return _astore_2
    case 0x4e: return _astore_3
    case 0x4f: return _iastore
    case 0x50: return _lastore
    case 0x51: return _fastore
    case 0x52: return _dastore
    case 0x53: return _aastore
    case 0x54: return _bastore
    case 0x55: return _castore
    case 0x56: return _sastore
    case 0x57: return _pop
    case 0x58: return _pop2
    case 0x59: return _dup
    case 0x5a: return _dup_x1
    case 0x5b: return _dup_x2
    case 0x5c: return _dup2
    case 0x5d: return _dup2_x1
    case 0x5e: return _dup2_x2
    case 0x5f: return _swap
    case 0x60: return _iadd
    case 0x61: return _ladd
    case 0x62: return _fadd
    case 0x63: return _dadd
    case 0x64: return &isub{}
    case 0x65: return &lsub{}
    case 0x66: return &fsub{}
    case 0x67: return &dsub{}
    case 0x68: return _imul
    case 0x69: return _lmul
    case 0x6a: return _fmul
    case 0x6b: return _dmul
    case 0x6c: return _idiv
    case 0x6d: return _ldiv
    case 0x6e: return _fdiv
    case 0x6f: return _ddiv
    case 0x70: return &irem{}
    case 0x71: return &lrem{}
    case 0x72: return &frem{}
    case 0x73: return &drem{}
    case 0x74: return &ineg{}
    case 0x75: return &lneg{}
    case 0x76: return &fneg{}
    case 0x77: return &dneg{}
    case 0x78: return &ishl{}
    case 0x79: return &lshl{}
    case 0x7a: return &ishr{}
    case 0x7b: return &lshr{}
    case 0x7c: return &iushr{}
    case 0x7d: return &lushr{}
    case 0x7e: return _iand
    case 0x7f: return _land
    case 0x80: return &ior{}
    case 0x81: return &lor{}
    case 0x82: return &ixor{}
    case 0x83: return &lxor{}
    case 0x84: return &iinc{}
    case 0x85: return _i2l
    case 0x86: return _i2f
    case 0x87: return _i2d
    case 0x88: return _l2i
    case 0x89: return _l2f
    case 0x8a: return _l2d
    case 0x8b: return _f2i
    case 0x8c: return _f2l
    case 0x8d: return _f2d
    case 0x8e: return _d2i
    case 0x8f: return _d2l
    case 0x90: return _d2f
    case 0x91: return _i2b
    case 0x92: return _i2c
    case 0x93: return _i2s
    case 0x94: return _lcmp
    case 0x95: return _fcmpl
    case 0x96: return _fcmpg
    case 0x97: return _dcmpl
    case 0x98: return _dcmpg
    case 0x99: return &ifeq{}
    case 0x9a: return &ifne{}
    case 0x9b: return &iflt{}
    case 0x9c: return &ifge{}
    case 0x9d: return &ifgt{}
    case 0x9e: return &ifle{}
    case 0x9f: return &if_icmpeq{}
    case 0xa0: return &if_icmpne{}
    case 0xa1: return &if_icmplt{}
    case 0xa2: return &if_icmpge{}
    case 0xa3: return &if_icmpgt{}
    case 0xa4: return &if_icmple{}
    case 0xa5: return &if_acmpeq{}
    case 0xa6: return &if_acmpne{}
    case 0xa7: return &_goto{}
  //case 0xa8: return &jsr{}
  //case 0xa9: return &ret{}
    case 0xaa: return &tableswitch{}
    case 0xab: return &lookupswitch{}
    case 0xac: return &ireturn{}
    case 0xad: return &lreturn{}
    case 0xae: return &freturn{}
    case 0xaf: return &dreturn{}
    case 0xb0: return &areturn{}
    case 0xb1: return &_return{}
    case 0xb2: return &getstatic{}
    case 0xb3: return &putstatic{}
    case 0xb4: return &getfield{}
    case 0xb5: return &putfield{}
    case 0xb6: return &invokevirtual{}
    case 0xb7: return &invokespecial{}
    case 0xb8: return &invokestatic{}
    case 0xb9: return &invokeinterface{}
    case 0xba: return &invokedynamic{}
    case 0xbb: return &_new{}
    case 0xbc: return &newarray{}
    case 0xbd: return &anewarray{}
    case 0xbe: return _arraylength
    case 0xbf: return _athrow
    case 0xc0: return &checkcast{}
    case 0xc1: return &instanceof{}
    case 0xc2: return _monitorenter
    case 0xc3: return _monitorexit
    case 0xc5: return &multianewarray{}
    case 0xc6: return &ifnull{}
    case 0xc7: return &ifnonnull{}
    case 0xc8: return &goto_w{}
  //case 0xc9: return &jsr_w{}
  //case 0xca: return &breakpoint{}
  //case 0xfe: return &impdep1{}
  //case 0xff: return &impdep2{}
    // todo
    default: panic("BAD opcode!")
    }
}
<commit_msg>optmize<commit_after>package instructions

var (
    _aload_0 = &aload_0{}
    _aload_1 = &aload_1{}
    _aload_2 = &aload_2{}
    _aload_3 = &aload_3{}
    _arraylength = &arraylength{}
    _astore_0 = &astore_0{}
    _astore_1 = &astore_1{}
    _astore_2 = &astore_2{}
    _astore_3 = &astore_3{}
    _athrow = &athrow{}
    _d2f = &d2f{}
    _d2i = &d2i{}
    _d2l = &d2l{}
    _dcmpg = &dcmpg{}
    _dcmpl = &dcmpl{}
    _dload_0 = &dload_0{}
    _dload_1 = &dload_1{}
    _dload_2 = &dload_2{}
    _dload_3 = &dload_3{}
    _dstore_0 = &dstore_0{}
    _dstore_1 = &dstore_1{}
    _dstore_2 = &dstore_2{}
    _dstore_3 = &dstore_3{}
    _dup = &dup{}
    _dup_x1 = &dup_x1{}
    _dup_x2 = &dup_x2{}
    _dup2 = &dup2{}
    _dup2_x1 = &dup2_x1{}
    _dup2_x2 = &dup2_x2{}
    _f2d = &f2d{}
    _f2i = &f2i{}
    _f2l = &f2l{}
    _fcmpg = &fcmpg{}
    _fcmpl = &fcmpl{}
    _fload_0 = &fload_0{}
    _fload_1 = &fload_1{}
    _fload_2 = &fload_2{}
    _fload_3 = &fload_3{}
    _fstore_0 = &fstore_0{}
    _fstore_1 = &fstore_1{}
    _fstore_2 = &fstore_2{}
    _fstore_3 = &fstore_3{}
    _i2b = &i2b{}
    _i2c = &i2c{}
    _i2d = &i2d{}
    _i2f = &i2f{}
    _i2l = &i2l{}
    _i2s = &i2s{}
    _iload_0 = &iload_0{}
    _iload_1 = &iload_1{}
    _iload_2 = &iload_2{}
    _iload_3 = &iload_3{}
    _istore_0 = &istore_0{}
    _istore_1 = &istore_1{}
    _istore_2 = &istore_2{}
    _istore_3 = &istore_3{}
    _l2d = &l2d{}
    _l2f = &l2f{}
    _l2i = &l2i{}
    _lcmp = &lcmp{}
    _lload_0 = &lload_0{}
    _lload_1 = &lload_1{}
    _lload_2 = &lload_2{}
    _lload_3 = &lload_3{}
    _lstore_0 = &lstore_0{}
    _lstore_1 = &lstore_1{}
    _lstore_2 = &lstore_2{}
    _lstore_3 = &lstore_3{}
    _monitorenter = &monitorenter{}
    _monitorexit = &monitorexit{}
    _nop = &nop{}
    _pop = &pop{}
    _pop2 = &pop2{}
    _swap = &swap{}
    _dadd = &dadd{}
    _fadd = &fadd{}
    _iadd = &iadd{}
    _ladd = &ladd{}
    _aaload = &aaload{}
    _baload = &baload{}
    _caload = &caload{}
    _daload = &daload{}
    _faload = &faload{}
    _iaload = &iaload{}
    _laload = &laload{}
    _saload = &saload{}
    _iand = &iand{}
    _land = &land{}
    _aastore = &aastore{}
    _bastore = &bastore{}
    _castore = &castore{}
    _dastore = &dastore{}
    _fastore = &fastore{}
    _iastore = &iastore{}
    _lastore = &lastore{}
    _sastore = &sastore{}
    _aconst_null = &aconst_null{}
    _dconst_0 = &dconst_0{}
    _dconst_1 = &dconst_1{}
    _fconst_0 = &fconst_0{}
    _fconst_1 = &fconst_1{}
    _fconst_2 = &fconst_2{}
    _iconst_m1 = &iconst_m1{}
    _iconst_0 = &iconst_0{}
    _iconst_1 = &iconst_1{}
    _iconst_2 = &iconst_2{}
    _iconst_3 = &iconst_3{}
    _iconst_4 = &iconst_4{}
    _iconst_5 = &iconst_5{}
    _lconst_0 = &lconst_0{}
    _lconst_1 = &lconst_1{}
    _ddiv = &ddiv{}
    _fdiv = &fdiv{}
    _idiv = &idiv{}
    _ldiv = &ldiv{}
    _dmul = &dmul{}
    _fmul = &fmul{}
    _imul = &imul{}
    _lmul = &lmul{}
    _dneg = &dneg{}
    _fneg = &fneg{}
    _ineg = &ineg{}
    _lneg = &lneg{}
)

func Decode(bcr *BytecodeReader) (Instruction) {
    opcode := bcr.readUint8()
    instruction := newInstruction(opcode)
    instruction.fetchOperands(bcr)
    return instruction
}

func newInstruction(opcode byte) (Instruction) {
    switch opcode {
    case 0x00: return _nop
    case 0x01: return _aconst_null
    case 0x02: return _iconst_m1
    case 0x03: return _iconst_0
    case 0x04: return _iconst_1
    case 0x05: return _iconst_2
    case 0x06: return _iconst_3
    case 0x07: return _iconst_4
    case 0x08: return _iconst_5
    case 0x09: return _lconst_0
    case 0x0a: return _lconst_1
    case 0x0b: return _fconst_0
    case 0x0c: return _fconst_1
    case 0x0d: return _fconst_2
    case 0x0e: return _dconst_0
    case 0x0f: return _dconst_1
    case 0x10: return &bipush{}
    case 0x11: return &sipush{}
    case 0x12: return &ldc{}
    case 0x13: return &ldc_w{}
    case 0x14: return &ldc2_w{}
    case 0x15: return &iload{}
    case 0x16: return &lload{}
    case 0x17: return &fload{}
    case 0x18: return &dload{}
    case 0x19: return &aload{}
    case 0x1a: return _iload_0
    case 0x1b: return _iload_1
    case 0x1c: return _iload_2
    case 0x1d: return _iload_3
    case 0x1e: return _lload_0
    case 0x1f: return _lload_1
    case 0x20: return _lload_2
    case 0x21: return _lload_3
    case 0x22: return _fload_0
    case 0x23: return _fload_1
    case 0x24: return _fload_2
    case 0x25: return _fload_3
    case 0x26: return _dload_0
    case 0x27: return _dload_1
    case 0x28: return _dload_2
    case 0x29: return _dload_3
    case 0x2a: return _aload_0
    case 0x2b: return _aload_1
    case 0x2c: return _aload_2
    case 0x2d: return _aload_3
    case 0x2e: return _iaload
    case 0x2f: return _laload
    case 0x30: return _faload
    case 0x31: return _daload
    case 0x32: return _aaload
    case 0x33: return _baload
    case 0x34: return _caload
    case 0x35: return _saload
    case 0x36: return &istore{}
    case 0x37: return &lstore{}
    case 0x38: return &fstore{}
    case 0x39: return &dstore{}
    case 0x3a: return &astore{}
    case 0x3b: return _istore_0
    case 0x3c: return _istore_1
    case 0x3d: return _istore_2
    case 0x3e: return _istore_3
    case 0x3f: return _lstore_0
    case 0x40: return _lstore_1
    case 0x41: return _lstore_2
    case 0x42: return _lstore_3
    case 0x43: return _fstore_0
    case 0x44: return _fstore_1
    case 0x45: return _fstore_2
    case 0x46: return _fstore_3
    case 0x47: return _dstore_0
    case 0x48: return _dstore_1
    case 0x49: return _dstore_2
    case 0x4a: return _dstore_3
    case 0x4b: return _astore_0
    case 0x4c: return _astore_1
    case 0x4d: return _astore_2
    case 0x4e: return _astore_3
    case 0x4f: return _iastore
    case 0x50: return _lastore
    case 0x51: return _fastore
    case 0x52: return _dastore
    case 0x53: return _aastore
    case 0x54: return _bastore
    case 0x55: return _castore
    case 0x56: return _sastore
    case 0x57: return _pop
    case 0x58: return _pop2
    case 0x59: return _dup
    case 0x5a: return _dup_x1
    case 0x5b: return _dup_x2
    case 0x5c: return _dup2
    case 0x5d: return _dup2_x1
    case 0x5e: return _dup2_x2
    case 0x5f: return _swap
    case 0x60: return _iadd
    case 0x61: return _ladd
    case 0x62: return _fadd
    case 0x63: return _dadd
    case 0x64: return &isub{}
    case 0x65: return &lsub{}
    case 0x66: return &fsub{}
    case 0x67: return &dsub{}
    case 0x68: return _imul
    case 0x69: return _lmul
    case 0x6a: return _fmul
    case 0x6b: return _dmul
    case 0x6c: return _idiv
    case 0x6d: return _ldiv
    case 0x6e: return _fdiv
    case 0x6f: return _ddiv
    case 0x70: return &irem{}
    case 0x71: return &lrem{}
    case 0x72: return &frem{}
    case 0x73: return &drem{}
    case 0x74: return _ineg
    case 0x75: return _lneg
    case 0x76: return _fneg
    case 0x77: return _dneg
    case 0x78: return &ishl{}
    case 0x79: return &lshl{}
    case 0x7a: return &ishr{}
    case 0x7b: return &lshr{}
    case 0x7c: return &iushr{}
    case 0x7d: return &lushr{}
    case 0x7e: return _iand
    case 0x7f: return _land
    case 0x80: return &ior{}
    case 0x81: return &lor{}
    case 0x82: return &ixor{}
    case 0x83: return &lxor{}
    case 0x84: return &iinc{}
    case 0x85: return _i2l
    case 0x86: return _i2f
    case 0x87: return _i2d
    case 0x88: return _l2i
    case 0x89: return _l2f
    case 0x8a: return _l2d
    case 0x8b: return _f2i
    case 0x8c: return _f2l
    case 0x8d: return _f2d
    case 0x8e: return _d2i
    case 0x8f: return _d2l
    case 0x90: return _d2f
    case 0x91: return _i2b
    case 0x92: return _i2c
    case 0x93: return _i2s
    case 0x94: return _lcmp
    case 0x95: return _fcmpl
    case 0x96: return _fcmpg
    case 0x97: return _dcmpl
    case 0x98: return _dcmpg
    case 0x99: return &ifeq{}
    case 0x9a: return &ifne{}
    case 0x9b: return &iflt{}
    case 0x9c: return &ifge{}
    case 0x9d: return &ifgt{}
    case 0x9e: return &ifle{}
    case 0x9f: return &if_icmpeq{}
    case 0xa0: return &if_icmpne{}
    case 0xa1: return &if_icmplt{}
    case 0xa2: return &if_icmpge{}
    case 0xa3: return &if_icmpgt{}
    case 0xa4: return &if_icmple{}
    case 0xa5: return &if_acmpeq{}
    case 0xa6: return &if_acmpne{}
    case 0xa7: return &_goto{}
  //case 0xa8: return &jsr{}
  //case 0xa9: return &ret{}
    case 0xaa: return &tableswitch{}
    case 0xab: return &lookupswitch{}
    case 0xac: return &ireturn{}
    case 0xad: return &lreturn{}
    case 0xae: return &freturn{}
    case 0xaf: return &dreturn{}
    case 0xb0: return &areturn{}
    case 0xb1: return &_return{}
    case 0xb2: return &getstatic{}
    case 0xb3: return &putstatic{}
    case 0xb4: return &getfield{}
    case 0xb5: return &putfield{}
    case 0xb6: return &invokevirtual{}
    case 0xb7: return &invokespecial{}
    case 0xb8: return &invokestatic{}
    case 0xb9: return &invokeinterface{}
    case 0xba: return &invokedynamic{}
    case 0xbb: return &_new{}
    case 0xbc: return &newarray{}
    case 0xbd: return &anewarray{}
    case 0xbe: return _arraylength
    case 0xbf: return _athrow
    case 0xc0: return &checkcast{}
    case 0xc1: return &instanceof{}
    case 0xc2: return _monitorenter
    case 0xc3: return _monitorexit
    case 0xc5: return &multianewarray{}
    case 0xc6: return &ifnull{}
    case 0xc7: return &ifnonnull{}
    case 0xc8: return &goto_w{}
  //case 0xc9: return &jsr_w{}
  //case 0xca: return &breakpoint{}
  //case 0xfe: return &impdep1{}
  //case 0xff: return &impdep2{}
    // todo
    default: panic("BAD opcode!")
    }
}
<|endoftext|>