<commit_before>/*
Copyright 2018 The Skaffold Authors

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

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

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

package deploy

import (
	"bytes"
	"context"
	"fmt"
	"os/exec"
	"testing"

	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/build"
	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/v1alpha2"
	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/util"
	"github.com/GoogleContainerTools/skaffold/testutil"
)

var testBuilds = []build.Build{
	{
		ImageName: "skaffold-helm",
		Tag:       "skaffold-helm:3605e7bc17cf46e53f4d81c4cbc24e5b4c495184",
	},
}

var testDeployConfig = &v1alpha2.DeployConfig{
	DeployType: v1alpha2.DeployType{
		HelmDeploy: &v1alpha2.HelmDeploy{
			Releases: []v1alpha2.HelmRelease{
				{
					Name:      "skaffold-helm",
					ChartPath: "examples/test",
					Values: map[string]string{
						"image.tag": "skaffold-helm",
					},
					SetValues: map[string]string{
						"some.key": "somevalue",
					},
				},
			},
		},
	},
}

var testDeployConfigParameterUnmatched = &v1alpha2.DeployConfig{
	DeployType: v1alpha2.DeployType{
		HelmDeploy: &v1alpha2.HelmDeploy{
			Releases: []v1alpha2.HelmRelease{
				{
					Name:      "skaffold-helm",
					ChartPath: "examples/test",
					Values: map[string]string{
						"image.tag": "skaffold-helm-unmatched",
					},
				},
			},
		},
	},
}

func TestHelmDeploy(t *testing.T) {
	var tests = []struct {
		description string
		cmd         util.Command
		deployer    *HelmDeployer
		builds      []build.Build
		shouldErr   bool
	}{
		{
			description: "deploy success",
			cmd:         &MockHelm{t: t},
			deployer:    NewHelmDeployer(testDeployConfig, testKubeContext),
			builds:      testBuilds,
		},
		{
			description: "deploy error unmatched parameter",
			cmd:         &MockHelm{t: t},
			deployer:    NewHelmDeployer(testDeployConfigParameterUnmatched, testKubeContext),
			builds:      testBuilds,
			shouldErr:   true,
		},
		{
			description: "get failure should install not upgrade",
			cmd: &MockHelm{
				t:             t,
				getResult:     fmt.Errorf("not found"),
				upgradeResult: fmt.Errorf("should not have called upgrade"),
			},
			deployer: NewHelmDeployer(testDeployConfig, testKubeContext),
			builds:   testBuilds,
		},
		{
			description: "get success should upgrade not install",
			cmd: &MockHelm{
				t:             t,
				installResult: fmt.Errorf("should not have called install"),
			},
			deployer: NewHelmDeployer(testDeployConfig, testKubeContext),
			builds:   testBuilds,
		},
		{
			description: "deploy error",
			cmd: &MockHelm{
				t:             t,
				upgradeResult: fmt.Errorf("unexpected error"),
			},
			shouldErr: true,
			deployer:  NewHelmDeployer(testDeployConfig, testKubeContext),
			builds:    testBuilds,
		},
		{
			description: "dep build error",
			cmd: &MockHelm{
				t:         t,
				depResult: fmt.Errorf("unexpected error"),
			},
			shouldErr: true,
			deployer:  NewHelmDeployer(testDeployConfig, testKubeContext),
			builds:    testBuilds,
		},
	}

	for _, tt := range tests {
		t.Run(tt.description, func(t *testing.T) {
			defer func(c util.Command) { util.DefaultExecCommand = c }(util.DefaultExecCommand)
			util.DefaultExecCommand = tt.cmd

			err := tt.deployer.Deploy(context.Background(), &bytes.Buffer{}, tt.builds)
			testutil.CheckError(t, tt.shouldErr, err)
		})
	}
}

type MockHelm struct {
	t *testing.T

	getResult     error
	installResult error
	upgradeResult error
	depResult     error
}

func (m *MockHelm) RunCmdOut(c *exec.Cmd) ([]byte, error) {
	m.t.Error("Shouldn't be used")
	return nil, nil
}

func (m *MockHelm) RunCmd(c *exec.Cmd) error {
	if len(c.Args) < 3 {
		m.t.Errorf("Not enough args in command %v", c)
	}

	if c.Args[1] != "--kube-context" || c.Args[2] != testKubeContext {
		m.t.Errorf("Invalid kubernetes context %v", c)
	}

	switch c.Args[3] {
	case "get":
		return m.getResult
	case "install":
		return m.installResult
	case "upgrade":
		return m.upgradeResult
	case "dep":
		return m.depResult
	default:
		m.t.Errorf("Unknown helm command: %+v", c)
		return nil
	}
}
<commit_msg>updated test for overrides<commit_after>/*
Copyright 2018 The Skaffold Authors

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

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

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

package deploy

import (
	"bytes"
	"context"
	"fmt"
	"os/exec"
	"testing"

	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/build"
	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/v1alpha2"
	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/util"
	"github.com/GoogleContainerTools/skaffold/testutil"
)

var testBuilds = []build.Build{
	{
		ImageName: "skaffold-helm",
		Tag:       "skaffold-helm:3605e7bc17cf46e53f4d81c4cbc24e5b4c495184",
	},
}

var testDeployConfig = &v1alpha2.DeployConfig{
	DeployType: v1alpha2.DeployType{
		HelmDeploy: &v1alpha2.HelmDeploy{
			Releases: []v1alpha2.HelmRelease{
				{
					Name:      "skaffold-helm",
					ChartPath: "examples/test",
					Values: map[string]string{
						"image.tag": "skaffold-helm",
					},
					Overrides: map[string]interface{}{
						"foo": "bar",
					},
					SetValues: map[string]string{
						"some.key": "somevalue",
					},
				},
			},
		},
	},
}

var testDeployConfigParameterUnmatched = &v1alpha2.DeployConfig{
	DeployType: v1alpha2.DeployType{
		HelmDeploy: &v1alpha2.HelmDeploy{
			Releases: []v1alpha2.HelmRelease{
				{
					Name:      "skaffold-helm",
					ChartPath: "examples/test",
					Values: map[string]string{
						"image.tag": "skaffold-helm-unmatched",
					},
				},
			},
		},
	},
}

func TestHelmDeploy(t *testing.T) {
	var tests = []struct {
		description string
		cmd         util.Command
		deployer    *HelmDeployer
		builds      []build.Build
		shouldErr   bool
	}{
		{
			description: "deploy success",
			cmd:         &MockHelm{t: t},
			deployer:    NewHelmDeployer(testDeployConfig, testKubeContext),
			builds:      testBuilds,
		},
		{
			description: "deploy error unmatched parameter",
			cmd:         &MockHelm{t: t},
			deployer:    NewHelmDeployer(testDeployConfigParameterUnmatched, testKubeContext),
			builds:      testBuilds,
			shouldErr:   true,
		},
		{
			description: "get failure should install not upgrade",
			cmd: &MockHelm{
				t:             t,
				getResult:     fmt.Errorf("not found"),
				upgradeResult: fmt.Errorf("should not have called upgrade"),
			},
			deployer: NewHelmDeployer(testDeployConfig, testKubeContext),
			builds:   testBuilds,
		},
		{
			description: "get success should upgrade not install",
			cmd: &MockHelm{
				t:             t,
				installResult: fmt.Errorf("should not have called install"),
			},
			deployer: NewHelmDeployer(testDeployConfig, testKubeContext),
			builds:   testBuilds,
		},
		{
			description: "deploy error",
			cmd: &MockHelm{
				t:             t,
				upgradeResult: fmt.Errorf("unexpected error"),
			},
			shouldErr: true,
			deployer:  NewHelmDeployer(testDeployConfig, testKubeContext),
			builds:    testBuilds,
		},
		{
			description: "dep build error",
			cmd: &MockHelm{
				t:         t,
				depResult: fmt.Errorf("unexpected error"),
			},
			shouldErr: true,
			deployer:  NewHelmDeployer(testDeployConfig, testKubeContext),
			builds:    testBuilds,
		},
	}

	for _, tt := range tests {
		t.Run(tt.description, func(t *testing.T) {
			defer func(c util.Command) { util.DefaultExecCommand = c }(util.DefaultExecCommand)
			util.DefaultExecCommand = tt.cmd

			err := tt.deployer.Deploy(context.Background(), &bytes.Buffer{}, tt.builds)
			testutil.CheckError(t, tt.shouldErr, err)
		})
	}
}

type MockHelm struct {
	t *testing.T

	getResult     error
	installResult error
	upgradeResult error
	depResult     error
}

func (m *MockHelm) RunCmdOut(c *exec.Cmd) ([]byte, error) {
	m.t.Error("Shouldn't be used")
	return nil, nil
}

func (m *MockHelm) RunCmd(c *exec.Cmd) error {
	if len(c.Args) < 3 {
		m.t.Errorf("Not enough args in command %v", c)
	}

	if c.Args[1] != "--kube-context" || c.Args[2] != testKubeContext {
		m.t.Errorf("Invalid kubernetes context %v", c)
	}

	switch c.Args[3] {
	case "get":
		return m.getResult
	case "install":
		return m.installResult
	case "upgrade":
		return m.upgradeResult
	case "dep":
		return m.depResult
	default:
		m.t.Errorf("Unknown helm command: %+v", c)
		return nil
	}
}
<|endoftext|>


<commit_before>// Package pbf decodes OpenStreetMap pbf files.
// Use this package by creating a NewDecoder and passing it a PBF file. Use
// Decode to return Node, Way and Relation structs.
package pbf

import (
	"bytes"
	"code.google.com/p/goprotobuf/proto"
	"compress/zlib"
	"encoding/binary"
	"errors"
	"fmt"
	"github.com/qedus/pbf/OSMPBF"
	"io"
	"io/ioutil"
)

const (
	maxBlobHeaderSize = 64 * 1024
	maxBlobSize       = 32 * 1024 * 1024
)

const (
	NodeType MemberType = iota
	WayType
	RelationType
)

var (
	parseCapabilities = map[string]bool{
		"OsmSchema-V0.6": true,
		"DenseNodes":     true}
)

type Node struct {
	Id   int64
	Lat  float64
	Lon  float64
	Tags map[string]string

	// TODO: Add DenseInfo
}

type Way struct {
	ID      int64
	Tags    map[string]string
	NodeIDs []int64

	// TODO: Add Info
}

type Relation struct {
	ID      int64
	Tags    map[string]string
	Members []*Member

	// TODO: Add Info
	// TODO: Add roles_sid
}

type MemberType int

type Member struct {
	ID   int64
	Type MemberType
}

// A Decoder reads and decodes OpenStreetMap PBF data from an input stream.
type Decoder struct {
	r io.Reader

	objectQueue []interface{}
	objectIndex int
}

// NewDecoder returns a new decoder that reads from r.
func NewDecoder(r io.Reader) *Decoder {
	return &Decoder{r, make([]interface{}, 0), 0}
}

// Decode reads the next object from the input stream and returns either a
// Node, Way or Relation struct representing the underlying OpenStreetMap PBF
// data.
//
// The end of the input stream is reported by an io.EOF error.
func (dec *Decoder) Decode() (interface{}, error) {
	if dec.objectIndex >= len(dec.objectQueue) {
		dec.objectQueue = dec.objectQueue[:0]
		dec.objectIndex = 0
		if err := dec.readNextPrimitiveBlock(); err != nil {
			return nil, err
		}
	}

	dec.objectIndex++
	return dec.objectQueue[dec.objectIndex-1], nil
}

func (dec *Decoder) readNextPrimitiveBlock() error {
	for {
		blobHeaderSize, err := dec.readBlobHeaderSize()
		if err != nil {
			return err
		}

		blobHeader, err := dec.readBlobHeader(blobHeaderSize)
		if err != nil {
			return err
		}

		blob, err := dec.readBlob(blobHeader)
		if err != nil {
			return err
		}
		switch blobHeader.GetType() {
		case "OSMHeader":
			if err := dec.readOSMHeader(blob); err != nil {
				return err
			}
		case "OSMData":
			return dec.readOSMData(blob)
		default:
			// Skip over unknown type
		}
	}
}

func (dec *Decoder) readBlobHeaderSize() (uint32, error) {
	buf := make([]byte, 4)
	if _, err := io.ReadFull(dec.r, buf); err != nil {
		return 0, err
	}
	size := binary.BigEndian.Uint32(buf)

	if size >= maxBlobHeaderSize {
		return 0, errors.New("BlobHeader size >= 64Kb")
	}
	return size, nil
}

func (dec *Decoder) readBlobHeader(size uint32) (*OSMPBF.BlobHeader, error) {
	buf := make([]byte, size)
	if _, err := io.ReadFull(dec.r, buf); err != nil {
		return nil, err
	}

	blobHeader := &OSMPBF.BlobHeader{}
	if err := proto.Unmarshal(buf, blobHeader); err != nil {
		return nil, err
	}

	if blobHeader.GetDatasize() >= maxBlobSize {
		return nil, errors.New("Blob size >= 32Mb")
	}
	return blobHeader, nil
}

func (dec *Decoder) readBlob(blobHeader *OSMPBF.BlobHeader) (*OSMPBF.Blob, error) {
	buf := make([]byte, blobHeader.GetDatasize())
	if _, err := io.ReadFull(dec.r, buf); err != nil {
		return nil, err
	}

	blob := &OSMPBF.Blob{}
	if err := proto.Unmarshal(buf, blob); err != nil {
		return nil, err
	}
	return blob, nil
}

func (dec *Decoder) readOSMHeader(blob *OSMPBF.Blob) error {
	data, err := getData(blob)
	if err != nil {
		return err
	}
	headerBlock := &OSMPBF.HeaderBlock{}
	if err := proto.Unmarshal(data, headerBlock); err != nil {
		return err
	}

	// Check we have the parse capabilities
	requiredFeatures := headerBlock.GetRequiredFeatures()
	for _, feature := range requiredFeatures {
		if !parseCapabilities[feature] {
			return fmt.Errorf("parser does not have %s capability",
				feature)
		}
	}
	return nil
}

func (dec *Decoder) readOSMData(blob *OSMPBF.Blob) error {
	data, err := getData(blob)
	if err != nil {
		return err
	}

	primitiveBlock := &OSMPBF.PrimitiveBlock{}
	if err := proto.Unmarshal(data, primitiveBlock); err != nil {
		return err
	}
	dec.parsePrimitiveBlock(primitiveBlock)
	return nil
}

func getData(blob *OSMPBF.Blob) ([]byte, error) {
	switch {
	case blob.Raw != nil:
		return blob.GetRaw(), nil
	case blob.ZlibData != nil:
		compressedData := bytes.NewBuffer(blob.GetZlibData())
		r, err := zlib.NewReader(compressedData)
		if err != nil {
			return nil, err
		}
		data, err := ioutil.ReadAll(r)
		if err != nil {
			return nil, err
		}
		if len(data) != int(blob.GetRawSize()) {
			return nil, fmt.Errorf(
				"raw blob data size %d but expected %d",
				len(data), blob.GetRawSize())
		}
		return data, nil
	}
	return nil, errors.New("unknown blob data")
}

func (dec *Decoder) parsePrimitiveBlock(pb *OSMPBF.PrimitiveBlock) {
	primitiveGroups := pb.GetPrimitivegroup()
	for _, pg := range primitiveGroups {
		dec.parsePrimitiveGroup(pb, pg)
	}
}

func (dec *Decoder) parsePrimitiveGroup(pb *OSMPBF.PrimitiveBlock, pg *OSMPBF.PrimitiveGroup) {
	dec.parseNodes(pb, pg.GetNodes())
	dec.parseDenseNodes(pb, pg.GetDense())
	dec.parseWays(pb, pg.GetWays())
	dec.parseRelations(pb, pg.GetRelations())
}

func (dec *Decoder) parseNodes(pb *OSMPBF.PrimitiveBlock, nodes []*OSMPBF.Node) {
	st := pb.GetStringtable().GetS()
	granularity := int64(pb.GetGranularity())
	latOffset := pb.GetLatOffset()
	lonOffset := pb.GetLonOffset()

	for _, node := range nodes {
		id := node.GetId()
		lat := node.GetLat()
		lon := node.GetLon()

		latitude := 1e-9 * float64((latOffset + (granularity * lat)))
		longitude := 1e-9 * float64((lonOffset + (granularity * lon)))

		tags := extractTags(st, node.GetKeys(), node.GetVals())
		dec.objectQueue = append(dec.objectQueue,
			&Node{id, latitude, longitude, tags})
		panic("Please test this first")
	}
}

func (dec *Decoder) parseDenseNodes(pb *OSMPBF.PrimitiveBlock, dn *OSMPBF.DenseNodes) {
	st := pb.GetStringtable().GetS()
	granularity := int64(pb.GetGranularity())
	latOffset := pb.GetLatOffset()
	lonOffset := pb.GetLonOffset()
	ids := dn.GetId()
	lats := dn.GetLat()
	lons := dn.GetLon()
	tu := &tagUnpacker{st, dn.GetKeysVals(), 0}
	id, lat, lon := int64(0), int64(0), int64(0)
	for index := range ids {
		id = ids[index] + id
		lat = lats[index] + lat
		lon = lons[index] + lon
		latitude := 1e-9 * float64((latOffset + (granularity * lat)))
		longitude := 1e-9 * float64((lonOffset + (granularity * lon)))
		tags := tu.next()
		dec.objectQueue = append(dec.objectQueue,
			&Node{id, latitude, longitude, tags})
	}
}

type tagUnpacker struct {
	stringTable [][]byte
	keysVals    []int32
	index       int
}

func (tu *tagUnpacker) next() map[string]string {
	tags := make(map[string]string)
	for ; tu.index < len(tu.keysVals); tu.index++ {

		keyID := tu.keysVals[tu.index]
		tu.index++
		if keyID == 0 {
			break
		}
		valID := tu.keysVals[tu.index]
		key := string(tu.stringTable[keyID])
		val := string(tu.stringTable[valID])
		tags[key] = val
	}
	return tags
}

func extractTags(stringTable [][]byte, keyIDs, valueIDs []uint32) map[string]string {
	tags := make(map[string]string)
	for index := range keyIDs {
		key := string(stringTable[keyIDs[index]])
		val := string(stringTable[valueIDs[index]])
		tags[key] = val
	}
	return tags
}

func (dec *Decoder) parseWays(pb *OSMPBF.PrimitiveBlock, ways []*OSMPBF.Way) {
	st := pb.GetStringtable().GetS()
	for _, way := range ways {
		id := way.GetId()
		tags := extractTags(st, way.GetKeys(), way.GetVals())

		// NodeIDs
		refs := way.GetRefs()
		nodeID := int64(0)
		nodeIDs := make([]int64, 0, len(refs))
		for index := range refs {
			nodeID = refs[index] + nodeID
			nodeIDs = append(nodeIDs, nodeID)
		}
		dec.objectQueue = append(dec.objectQueue,
			&Way{id, tags, nodeIDs})
	}
}

func extractMembers(rel *OSMPBF.Relation) []*Member {
	memIDs := rel.GetMemids()
	types := rel.GetTypes()
	members := make([]*Member, 0, len(memIDs))
	memID := int64(0)
	for index := range memIDs {
		memID = memIDs[index] + memID
		memType := types[index]
		t := NodeType
		switch memType {
		case OSMPBF.Relation_WAY:
			t = WayType
		case OSMPBF.Relation_RELATION:
			t = RelationType
		}
		members = append(members, &Member{memID, t})
	}
	return members
}

func (dec *Decoder) parseRelations(pb *OSMPBF.PrimitiveBlock, relations []*OSMPBF.Relation) {
	st := pb.GetStringtable().GetS()
	for _, rel := range relations {
		id := rel.GetId()
		tags := extractTags(st, rel.GetKeys(), rel.GetVals())

		members := extractMembers(rel)

		dec.objectQueue = append(dec.objectQueue,
			&Relation{id, tags, members})
	}
}
<commit_msg>Removed unnecessary deference.<commit_after>// Package pbf decodes OpenStreetMap pbf files.
// Use this package by creating a NewDecoder and passing it a PBF file. Use
// Decode to return Node, Way and Relation structs.
package pbf

import (
	"bytes"
	"code.google.com/p/goprotobuf/proto"
	"compress/zlib"
	"encoding/binary"
	"errors"
	"fmt"
	"github.com/qedus/pbf/OSMPBF"
	"io"
	"io/ioutil"
)

const (
	maxBlobHeaderSize = 64 * 1024
	maxBlobSize       = 32 * 1024 * 1024
)

const (
	NodeType MemberType = iota
	WayType
	RelationType
)

var (
	parseCapabilities = map[string]bool{
		"OsmSchema-V0.6": true,
		"DenseNodes":     true}
)

type Node struct {
	Id   int64
	Lat  float64
	Lon  float64
	Tags map[string]string

	// TODO: Add DenseInfo
}

type Way struct {
	ID      int64
	Tags    map[string]string
	NodeIDs []int64

	// TODO: Add Info
}

type Relation struct {
	ID      int64
	Tags    map[string]string
	Members []*Member

	// TODO: Add Info
	// TODO: Add roles_sid
}

type MemberType int

type Member struct {
	ID   int64
	Type MemberType
}

// A Decoder reads and decodes OpenStreetMap PBF data from an input stream.
type Decoder struct {
	r io.Reader

	objectQueue []interface{}
	objectIndex int
}

// NewDecoder returns a new decoder that reads from r.
func NewDecoder(r io.Reader) *Decoder {
	return &Decoder{r, make([]interface{}, 0), 0}
}

// Decode reads the next object from the input stream and returns either a
// Node, Way or Relation struct representing the underlying OpenStreetMap PBF
// data.
//
// The end of the input stream is reported by an io.EOF error.
func (dec *Decoder) Decode() (interface{}, error) {
	if dec.objectIndex >= len(dec.objectQueue) {
		dec.objectQueue = dec.objectQueue[:0]
		dec.objectIndex = 0
		if err := dec.readNextPrimitiveBlock(); err != nil {
			return nil, err
		}
	}

	dec.objectIndex++
	return dec.objectQueue[dec.objectIndex-1], nil
}

func (dec *Decoder) readNextPrimitiveBlock() error {
	for {
		blobHeaderSize, err := dec.readBlobHeaderSize()
		if err != nil {
			return err
		}

		blobHeader, err := dec.readBlobHeader(blobHeaderSize)
		if err != nil {
			return err
		}

		blob, err := dec.readBlob(blobHeader)
		if err != nil {
			return err
		}
		switch blobHeader.GetType() {
		case "OSMHeader":
			if err := dec.readOSMHeader(blob); err != nil {
				return err
			}
		case "OSMData":
			return dec.readOSMData(blob)
		default:
			// Skip over unknown type
		}
	}
}

func (dec *Decoder) readBlobHeaderSize() (uint32, error) {
	buf := make([]byte, 4)
	if _, err := io.ReadFull(dec.r, buf); err != nil {
		return 0, err
	}
	size := binary.BigEndian.Uint32(buf)

	if size >= maxBlobHeaderSize {
		return 0, errors.New("BlobHeader size >= 64Kb")
	}
	return size, nil
}

func (dec *Decoder) readBlobHeader(size uint32) (*OSMPBF.BlobHeader, error) {
	buf := make([]byte, size)
	if _, err := io.ReadFull(dec.r, buf); err != nil {
		return nil, err
	}

	blobHeader := &OSMPBF.BlobHeader{}
	if err := proto.Unmarshal(buf, blobHeader); err != nil {
		return nil, err
	}

	if blobHeader.GetDatasize() >= maxBlobSize {
		return nil, errors.New("Blob size >= 32Mb")
	}
	return blobHeader, nil
}

func (dec *Decoder) readBlob(blobHeader *OSMPBF.BlobHeader) (*OSMPBF.Blob, error) {
	buf := make([]byte, blobHeader.GetDatasize())
	if _, err := io.ReadFull(dec.r, buf); err != nil {
		return nil, err
	}

	blob := &OSMPBF.Blob{}
	if err := proto.Unmarshal(buf, blob); err != nil {
		return nil, err
	}
	return blob, nil
}

func (dec *Decoder) readOSMHeader(blob *OSMPBF.Blob) error {
	data, err := getData(blob)
	if err != nil {
		return err
	}
	headerBlock := &OSMPBF.HeaderBlock{}
	if err := proto.Unmarshal(data, headerBlock); err != nil {
		return err
	}

	// Check we have the parse capabilities
	requiredFeatures := headerBlock.GetRequiredFeatures()
	for _, feature := range requiredFeatures {
		if !parseCapabilities[feature] {
			return fmt.Errorf("parser does not have %s capability",
				feature)
		}
	}
	return nil
}

func (dec *Decoder) readOSMData(blob *OSMPBF.Blob) error {
	data, err := getData(blob)
	if err != nil {
		return err
	}

	primitiveBlock := &OSMPBF.PrimitiveBlock{}
	if err := proto.Unmarshal(data, primitiveBlock); err != nil {
		return err
	}
	dec.parsePrimitiveBlock(primitiveBlock)
	return nil
}

func getData(blob *OSMPBF.Blob) ([]byte, error) {
	switch {
	case blob.Raw != nil:
		return blob.GetRaw(), nil
	case blob.ZlibData != nil:
		compressedData := bytes.NewBuffer(blob.GetZlibData())
		r, err := zlib.NewReader(compressedData)
		if err != nil {
			return nil, err
		}
		data, err := ioutil.ReadAll(r)
		if err != nil {
			return nil, err
		}
		if len(data) != int(blob.GetRawSize()) {
			return nil, fmt.Errorf(
				"raw blob data size %d but expected %d",
				len(data), blob.GetRawSize())
		}
		return data, nil
	}
	return nil, errors.New("unknown blob data")
}

func (dec *Decoder) parsePrimitiveBlock(pb *OSMPBF.PrimitiveBlock) {
	primitiveGroups := pb.GetPrimitivegroup()
	for _, pg := range primitiveGroups {
		dec.parsePrimitiveGroup(pb, pg)
	}
}

func (dec *Decoder) parsePrimitiveGroup(pb *OSMPBF.PrimitiveBlock, pg *OSMPBF.PrimitiveGroup) {
	dec.parseNodes(pb, pg.GetNodes())
	dec.parseDenseNodes(pb, pg.GetDense())
	dec.parseWays(pb, pg.GetWays())
	dec.parseRelations(pb, pg.GetRelations())
}

func (dec *Decoder) parseNodes(pb *OSMPBF.PrimitiveBlock, nodes []*OSMPBF.Node) {
	st := pb.GetStringtable().GetS()
	granularity := int64(pb.GetGranularity())
	latOffset := pb.GetLatOffset()
	lonOffset := pb.GetLonOffset()

	for _, node := range nodes {
		id := node.GetId()
		lat := node.GetLat()
		lon := node.GetLon()

		latitude := 1e-9 * float64((latOffset + (granularity * lat)))
		longitude := 1e-9 * float64((lonOffset + (granularity * lon)))

		tags := extractTags(st, node.GetKeys(), node.GetVals())
		dec.objectQueue = append(dec.objectQueue,
			&Node{id, latitude, longitude, tags})
		panic("Please test this first")
	}
}

func (dec *Decoder) parseDenseNodes(pb *OSMPBF.PrimitiveBlock, dn *OSMPBF.DenseNodes) {
	st := pb.GetStringtable().GetS()
	granularity := int64(pb.GetGranularity())
	latOffset := pb.GetLatOffset()
	lonOffset := pb.GetLonOffset()
	ids := dn.GetId()
	lats := dn.GetLat()
	lons := dn.GetLon()
	tu := tagUnpacker{st, dn.GetKeysVals(), 0}
	id, lat, lon := int64(0), int64(0), int64(0)
	for index := range ids {
		id = ids[index] + id
		lat = lats[index] + lat
		lon = lons[index] + lon
		latitude := 1e-9 * float64((latOffset + (granularity * lat)))
		longitude := 1e-9 * float64((lonOffset + (granularity * lon)))
		tags := tu.next()
		dec.objectQueue = append(dec.objectQueue,
			&Node{id, latitude, longitude, tags})
	}
}

type tagUnpacker struct {
	stringTable [][]byte
	keysVals    []int32
	index       int
}

func (tu *tagUnpacker) next() map[string]string {
	tags := make(map[string]string)
	for ; tu.index < len(tu.keysVals); tu.index++ {

		keyID := tu.keysVals[tu.index]
		tu.index++
		if keyID == 0 {
			break
		}
		valID := tu.keysVals[tu.index]
		key := string(tu.stringTable[keyID])
		val := string(tu.stringTable[valID])
		tags[key] = val
	}
	return tags
}

func extractTags(stringTable [][]byte, keyIDs, valueIDs []uint32) map[string]string {
	tags := make(map[string]string)
	for index := range keyIDs {
		key := string(stringTable[keyIDs[index]])
		val := string(stringTable[valueIDs[index]])
		tags[key] = val
	}
	return tags
}

func (dec *Decoder) parseWays(pb *OSMPBF.PrimitiveBlock, ways []*OSMPBF.Way) {
	st := pb.GetStringtable().GetS()
	for _, way := range ways {
		id := way.GetId()
		tags := extractTags(st, way.GetKeys(), way.GetVals())

		// NodeIDs
		refs := way.GetRefs()
		nodeID := int64(0)
		nodeIDs := make([]int64, 0, len(refs))
		for index := range refs {
			nodeID = refs[index] + nodeID
			nodeIDs = append(nodeIDs, nodeID)
		}
		dec.objectQueue = append(dec.objectQueue,
			&Way{id, tags, nodeIDs})
	}
}

func extractMembers(rel *OSMPBF.Relation) []*Member {
	memIDs := rel.GetMemids()
	types := rel.GetTypes()
	members := make([]*Member, 0, len(memIDs))
	memID := int64(0)
	for index := range memIDs {
		memID = memIDs[index] + memID
		memType := types[index]
		t := NodeType
		switch memType {
		case OSMPBF.Relation_WAY:
			t = WayType
		case OSMPBF.Relation_RELATION:
			t = RelationType
		}
		members = append(members, &Member{memID, t})
	}
	return members
}

func (dec *Decoder) parseRelations(pb *OSMPBF.PrimitiveBlock, relations []*OSMPBF.Relation) {
	st := pb.GetStringtable().GetS()
	for _, rel := range relations {
		id := rel.GetId()
		tags := extractTags(st, rel.GetKeys(), rel.GetVals())

		members := extractMembers(rel)

		dec.objectQueue = append(dec.objectQueue,
			&Relation{id, tags, members})
	}
}
<|endoftext|>


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

// Package filter contains utility functions for filtering slices through the
// distributed application of a filter function
package filter

import (
	"reflect"
)

// Apply takes a slice of type []T and a function of type func(T) T. (If the
// input conditions are not satisfied, Apply panics.) It returns a newly
// allocated slice where each element is the result of calling the function on
// successive elements of the slice.
func Apply(slice, function interface{}) interface{} {
	return apply(slice, function, false)
}

// ApplyInPlace is like Apply, but overwrites the slice rather than returning a
// newly allocated slice.
func ApplyInPlace(slice, function interface{}) {
	apply(slice, function, true)
}

// Choose takes a slice of type []T and a function of type func(T) bool. (If
// the input conditions are not satisfied, Choose panics.) It returns a newly
// allocated slice containing only those elements of the input slice that
// satisfy the function.
func Choose(slice, function interface{}) interface{} {
	out, _ := chooseOrDrop(slice, function, false, true)
	return out
}

// Drop takes a slice of type []T and a function of type func(T) bool. (If the
// input conditions are not satisfied, Drop panics.) It returns a newly
// allocated slice containing only those elements of the input slice that do
// not satisfy the function, that is, it removes elements that satisfy the
// function.
func Drop(slice, function interface{}) interface{} {
	out, _ := chooseOrDrop(slice, function, false, false)
	return out
}

// ChooseInPlace is like Choose, but overwrites the slice rather than returning
// a newly allocated slice. Since ChooseInPlace must modify the header of the
// slice to set the new length, it takes as argument a pointer to a slice
// rather than a slice.
func ChooseInPlace(pointerToSlice, function interface{}) {
	chooseOrDropInPlace(pointerToSlice, function, true)
}

// DropInPlace is like Drop, but overwrites the slice rather than returning a
// newly allocated slice. Since DropInPlace must modify the header of the slice
// to set the new length, it takes as argument a pointer to a slice rather than
// a slice.
func DropInPlace(pointerToSlice, function interface{}) {
	chooseOrDropInPlace(pointerToSlice, function, false)
}

func apply(slice, function interface{}, inPlace bool) interface{} {
	// Special case for strings, very common.
	if strSlice, ok := slice.([]string); ok {
		if strFn, ok := function.(func(string) string); ok {
			r := strSlice
			if !inPlace {
				r = make([]string, len(strSlice))
			}
			for i, s := range strSlice {
				r[i] = strFn(s)
			}
			return r
		}
	}
	in := reflect.ValueOf(slice)
	if in.Kind() != reflect.Slice {
		panic("apply: not slice")
	}
	fn := reflect.ValueOf(function)
	elemType := in.Type().Elem()
	if !goodFunc(fn, elemType, nil) {
		panic("apply: function must be of type func(" + in.Type().Elem().String() + ")  outputElemType")
	}
	out := in
	if !inPlace {
		out = reflect.MakeSlice(reflect.SliceOf(fn.Type().Out(0)), in.Len(), in.Len())
	}
	var ins [1]reflect.Value // Outside the loop to avoid one allocation.
	for i := 0; i < in.Len(); i++ {
		ins[0] = in.Index(i)
		out.Index(i).Set(fn.Call(ins[:])[0])
	}
	return out.Interface()
}

func chooseOrDropInPlace(slice, function interface{}, truth bool) {
	inp := reflect.ValueOf(slice)
	if inp.Kind() != reflect.Ptr {
		panic("choose/drop: not pointer to slice")
	}
	_, n := chooseOrDrop(inp.Elem().Interface(), function, true, truth)
	inp.Elem().SetLen(n)
}

var boolType = reflect.ValueOf(true).Type()

func chooseOrDrop(slice, function interface{}, inPlace, truth bool) (interface{}, int) {
	// Special case for strings, very common.
	if strSlice, ok := slice.([]string); ok {
		if strFn, ok := function.(func(string) bool); ok {
			var r []string
			if inPlace {
				r = strSlice[:0]
			}
			for _, s := range strSlice {
				if strFn(s) == truth {
					r = append(r, s)
				}
			}
			return r, len(r)
		}
	}
	in := reflect.ValueOf(slice)
	if in.Kind() != reflect.Slice {
		panic("choose/drop: not slice")
	}
	fn := reflect.ValueOf(function)
	elemType := in.Type().Elem()
	if !goodFunc(fn, elemType, boolType) {
		panic("choose/drop: function must be of type func(" + elemType.String() + ") bool")
	}
	var which []int
	var ins [1]reflect.Value // Outside the loop to avoid one allocation.
	for i := 0; i < in.Len(); i++ {
		ins[0] = in.Index(i)
		if fn.Call(ins[:])[0].Bool() == truth {
			which = append(which, i)
		}
	}
	out := in
	if !inPlace {
		out = reflect.MakeSlice(in.Type(), len(which), len(which))
	}
	for i := range which {
		out.Index(i).Set(in.Index(which[i]))
	}
	return out.Interface(), len(which)
}

// goodFunc verifies that the function satisfies the signature, represented as a slice of types.
// The last type is the single result type; the others are the input types.
// A final type of nil means any result type is accepted.
func goodFunc(fn reflect.Value, types ...reflect.Type) bool {
	if fn.Kind() != reflect.Func {
		return false
	}
	// Last type is return, the rest are ins.
	if fn.Type().NumIn() != len(types)-1 || fn.Type().NumOut() != 1 {
		return false
	}
	for i := 0; i < len(types)-1; i++ {
		if fn.Type().In(i) != types[i] {
			return false
		}
	}
	outType := types[len(types)-1]
	if outType != nil && fn.Type().Out(0) != outType {
		return false
	}
	return true
}
<commit_msg>filter: add vanity import comment<commit_after>// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package filter contains utility functions for filtering slices through the
// distributed application of a filter function
package filter // import "robpike.io/filter"

import (
	"reflect"
)

// Apply takes a slice of type []T and a function of type func(T) T. (If the
// input conditions are not satisfied, Apply panics.) It returns a newly
// allocated slice where each element is the result of calling the function on
// successive elements of the slice.
func Apply(slice, function interface{}) interface{} {
	return apply(slice, function, false)
}

// ApplyInPlace is like Apply, but overwrites the slice rather than returning a
// newly allocated slice.
func ApplyInPlace(slice, function interface{}) {
	apply(slice, function, true)
}

// Choose takes a slice of type []T and a function of type func(T) bool. (If
// the input conditions are not satisfied, Choose panics.) It returns a newly
// allocated slice containing only those elements of the input slice that
// satisfy the function.
func Choose(slice, function interface{}) interface{} {
	out, _ := chooseOrDrop(slice, function, false, true)
	return out
}

// Drop takes a slice of type []T and a function of type func(T) bool. (If the
// input conditions are not satisfied, Drop panics.) It returns a newly
// allocated slice containing only those elements of the input slice that do
// not satisfy the function, that is, it removes elements that satisfy the
// function.
func Drop(slice, function interface{}) interface{} {
	out, _ := chooseOrDrop(slice, function, false, false)
	return out
}

// ChooseInPlace is like Choose, but overwrites the slice rather than returning
// a newly allocated slice. Since ChooseInPlace must modify the header of the
// slice to set the new length, it takes as argument a pointer to a slice
// rather than a slice.
func ChooseInPlace(pointerToSlice, function interface{}) {
	chooseOrDropInPlace(pointerToSlice, function, true)
}

// DropInPlace is like Drop, but overwrites the slice rather than returning a
// newly allocated slice. Since DropInPlace must modify the header of the slice
// to set the new length, it takes as argument a pointer to a slice rather than
// a slice.
func DropInPlace(pointerToSlice, function interface{}) {
	chooseOrDropInPlace(pointerToSlice, function, false)
}

func apply(slice, function interface{}, inPlace bool) interface{} {
	// Special case for strings, very common.
	if strSlice, ok := slice.([]string); ok {
		if strFn, ok := function.(func(string) string); ok {
			r := strSlice
			if !inPlace {
				r = make([]string, len(strSlice))
			}
			for i, s := range strSlice {
				r[i] = strFn(s)
			}
			return r
		}
	}
	in := reflect.ValueOf(slice)
	if in.Kind() != reflect.Slice {
		panic("apply: not slice")
	}
	fn := reflect.ValueOf(function)
	elemType := in.Type().Elem()
	if !goodFunc(fn, elemType, nil) {
		panic("apply: function must be of type func(" + in.Type().Elem().String() + ")  outputElemType")
	}
	out := in
	if !inPlace {
		out = reflect.MakeSlice(reflect.SliceOf(fn.Type().Out(0)), in.Len(), in.Len())
	}
	var ins [1]reflect.Value // Outside the loop to avoid one allocation.
	for i := 0; i < in.Len(); i++ {
		ins[0] = in.Index(i)
		out.Index(i).Set(fn.Call(ins[:])[0])
	}
	return out.Interface()
}

func chooseOrDropInPlace(slice, function interface{}, truth bool) {
	inp := reflect.ValueOf(slice)
	if inp.Kind() != reflect.Ptr {
		panic("choose/drop: not pointer to slice")
	}
	_, n := chooseOrDrop(inp.Elem().Interface(), function, true, truth)
	inp.Elem().SetLen(n)
}

var boolType = reflect.ValueOf(true).Type()

func chooseOrDrop(slice, function interface{}, inPlace, truth bool) (interface{}, int) {
	// Special case for strings, very common.
	if strSlice, ok := slice.([]string); ok {
		if strFn, ok := function.(func(string) bool); ok {
			var r []string
			if inPlace {
				r = strSlice[:0]
			}
			for _, s := range strSlice {
				if strFn(s) == truth {
					r = append(r, s)
				}
			}
			return r, len(r)
		}
	}
	in := reflect.ValueOf(slice)
	if in.Kind() != reflect.Slice {
		panic("choose/drop: not slice")
	}
	fn := reflect.ValueOf(function)
	elemType := in.Type().Elem()
	if !goodFunc(fn, elemType, boolType) {
		panic("choose/drop: function must be of type func(" + elemType.String() + ") bool")
	}
	var which []int
	var ins [1]reflect.Value // Outside the loop to avoid one allocation.
	for i := 0; i < in.Len(); i++ {
		ins[0] = in.Index(i)
		if fn.Call(ins[:])[0].Bool() == truth {
			which = append(which, i)
		}
	}
	out := in
	if !inPlace {
		out = reflect.MakeSlice(in.Type(), len(which), len(which))
	}
	for i := range which {
		out.Index(i).Set(in.Index(which[i]))
	}
	return out.Interface(), len(which)
}

// goodFunc verifies that the function satisfies the signature, represented as a slice of types.
// The last type is the single result type; the others are the input types.
// A final type of nil means any result type is accepted.
func goodFunc(fn reflect.Value, types ...reflect.Type) bool {
	if fn.Kind() != reflect.Func {
		return false
	}
	// Last type is return, the rest are ins.
	if fn.Type().NumIn() != len(types)-1 || fn.Type().NumOut() != 1 {
		return false
	}
	for i := 0; i < len(types)-1; i++ {
		if fn.Type().In(i) != types[i] {
			return false
		}
	}
	outType := types[len(types)-1]
	if outType != nil && fn.Type().Out(0) != outType {
		return false
	}
	return true
}
<|endoftext|>


<commit_before>package redis

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

	redigo "github.com/garyburd/redigo/redis"
	"github.com/zenazn/goji/web"
)

func TestSessionCreate(t *testing.T) {
	conn, err := redigo.Dial("tcp", ":6379")
	if err != nil {
		t.Skipf("Cannot connect to redis. %v", err)
	}
	c := web.C{
		Env: map[string]interface{}{"redis": conn},
	}
	sh := NewSessionHolder()

	// Create the session
	s := sh.Create(c)

	s.Put("cheese", "cheddar")
	err = sh.Save(c, s)
	if err != nil {
		t.Fatalf("failed to save session - %v", err)
	}

	// Check we can write the session Id to the response
	w := httptest.NewRecorder()
	sh.AddToResponse(c, s, w)

	ch := w.HeaderMap.Get("Set-Cookie")
	if ch != fmt.Sprintf("sessionid=%s; Path=/", s.Id()) {
		t.Fatalf("cookie header is %v", ch)
	}

	// Can we extract the session from a request carrying a cookie?
	r, _ := http.NewRequest("GET", "/", nil)
	r.AddCookie(&http.Cookie{
		Name:  "sessionid",
		Value: s.Id(),
	})

	s1, err := sh.Get(c, r)
	if err != nil {
		t.Fatalf("got error reading session from request, %v", err)
	}

	val, ok := s1.Get("cheese")
	cheese := val.(string)
	if !ok || cheese != "cheddar" {
		t.Fatalf("could not get right cheese %v %v", ok, cheese)
	}

	sh.Destroy(c, s1)

	s1, err = sh.Get(c, r)
	if err == nil {
		t.Fatalf("session should be destroyed")
	}

}
<commit_msg>fixed redis session test<commit_after>package redis

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

	redigo "github.com/garyburd/redigo/redis"
	"github.com/zenazn/goji/web"
)

func TestSessionCreate(t *testing.T) {
	conn, err := redigo.Dial("tcp", ":6379")
	if err != nil {
		t.Skipf("Cannot connect to redis. %v", err)
	}
	c := web.C{
		Env: map[string]interface{}{"redis": conn},
	}
	sh := NewSessionHolder()

	// Create the session
	s := sh.Create(c)

	s.Put("cheese", "cheddar")
	err = sh.Save(c, s)
	if err != nil {
		t.Fatalf("failed to save session - %v", err)
	}

	// Check we can write the session Id to the response
	w := httptest.NewRecorder()
	sh.AddToResponse(c, s, w)

	ch := w.HeaderMap.Get("Set-Cookie")
	if ch != fmt.Sprintf("sessionid=%s; Path=/; Max-Age=%d", s.Id(), sh.GetTimeout()) {
		t.Fatalf("cookie header is %v", ch)
	}

	// Can we extract the session from a request carrying a cookie?
	r, _ := http.NewRequest("GET", "/", nil)
	r.AddCookie(&http.Cookie{
		Name:  "sessionid",
		Value: s.Id(),
	})

	s1, err := sh.Get(c, r)
	if err != nil {
		t.Fatalf("got error reading session from request, %v", err)
	}

	val, ok := s1.Get("cheese")
	cheese := val.(string)
	if !ok || cheese != "cheddar" {
		t.Fatalf("could not get right cheese %v %v", ok, cheese)
	}

	sh.Destroy(c, s1)

	s1, err = sh.Get(c, r)
	if err == nil {
		t.Fatalf("session should be destroyed")
	}

}
<|endoftext|>


<commit_before>package controllers

import (
	"github.com/Tsuguya/revmgo/app"
	"yarukoto/app/models/project"
	"github.com/revel/revel"
)

type Todo struct {
	*revel.Controller
	mgo.MongoController
}

func (c Todo) List() revel.Result {
    c.Response.ContentType = "application/json; charset=utf8"

    if c.Request.Method == "POST" {
        //b := models.FindTodoListByProjectId(c.Database, "5467157be4b0c9468004aef6")
        b := models.FindTodoListByProjectId(c.Database, c.Request.PostForm.Get("project_id"))
        Max := len(b) - 1
        return c.Render(b, Max)
    }

    return c.Render()
}

<commit_msg>Remove unnecessary comment out<commit_after>package controllers

import (
	"github.com/Tsuguya/revmgo/app"
	"yarukoto/app/models/project"
	"github.com/revel/revel"
)

type Todo struct {
	*revel.Controller
	mgo.MongoController
}

func (c Todo) List() revel.Result {
    c.Response.ContentType = "application/json; charset=utf8"

    if c.Request.Method == "POST" {
        b := models.FindTodoListByProjectId(c.Database, c.Request.PostForm.Get("project_id"))
        Max := len(b) - 1
        return c.Render(b, Max)
    }

    return c.Render()
}

<|endoftext|>


<commit_before>package relay

import (
	"bytes"
	"fmt"
	"testing"
	"time"

	net "github.com/nikkolasg/mulsigo/network"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

var chanId1 = "MyCustomChanId1"
var chanId2 = "MyCustomChanId2"
var msg = []byte("Hello World")

func TestMultiplex(t *testing.T) {
	relay := newRelay(t)
	go relay.Start()
	defer relay.Stop()

	cl1 := newClient(t, cAddr1)
	cl2 := newClient(t, cAddr2)
	defer cl1.Close()
	defer cl2.Close()

	m1 := NewMultiplexer(cl1)
	m2 := NewMultiplexer(cl2)

	c11, err := m1.Channel(chanId1)
	assert.Nil(t, err)
	assert.NotNil(t, getChannel(m1, chanId1))
	c21, err := m2.Channel(chanId1)
	assert.Nil(t, err)
	assert.NotNil(t, getChannel(m2, chanId1))

	assert.Nil(t, c11.Send(msg))

	_, eg, err := c21.Receive()
	require.Nil(t, err)
	assert.Equal(t, msg, eg)
}

func TestChannelProcess(t *testing.T) {
	//log.TestOutput(true, 3)
	router, err := net.NewLocalRouter(rAddr, enc)
	//rAddr = net.NewTCPAddress("127.0.0.1:2000")
	//router, err := net.NewTCPRouter(rAddr, enc)
	require.Nil(t, err)
	go router.Start()
	defer router.Stop()
	r := NewRelay(router)
	defer r.Stop()
	//ch := newChannel(r, chanId1)
	cl1, err := net.NewLocalConn(cAddr1, rAddr)
	//cl1, err := net.NewTCPConn(rAddr, enc)
	require.Nil(t, err)
	cl2, err := net.NewLocalConn(cAddr2, rAddr)
	//cl2, err := net.NewTCPConn(rAddr, enc)
	require.Nil(t, err)
	defer cl1.Close()
	defer cl2.Close()
	fmt.Println("cl1.Local()", cl1.Local().String())
	fmt.Println("cl2.Local()", cl2.Local().String())

	// should be no op
	fmt.Println("\n -- MSG FROM ", cl1.Local(), " --\n")
	require.Nil(t, cl1.Send(relayMessage([]byte("whoup whoup"))))

	// add cl1
	fmt.Println("\n -- JOIN FROM ", cl1.Local(), " --\n")
	require.Nil(t, cl1.Send(joinMessage(cl1.Local())))
	//require.Nil(t, waitNClients(ch, 1))
	nm, err := cl1.Receive()
	require.Nil(t, err)
	rm, ok := nm.(*RelayMessage)
	require.True(t, ok)
	require.NotNil(t, rm.GetJoinResponse())
	require.Equal(t, JoinResponse_OK, rm.GetJoinResponse().Status)
	// should just continue as there's no other destination
	fmt.Println("\n -- MSG FROM ", cl1.Local(), " --\n")
	require.Nil(t, cl1.Send(relayMessage([]byte("still wrong"))))
	// let the time to the goroutine
	time.Sleep(5 * time.Millisecond)
	// add cl2
	fmt.Println("\n -- JOIN FROM ", cl2.Local(), " --\n")
	require.Nil(t, cl2.Send(joinMessage(cl2.Local())))
	// join response ack
	_, err = cl2.Receive()
	require.Nil(t, err)

	//require.Nil(t, waitNClients(ch, 2))
	fmt.Println("\n -- MSG FROM ", cl1.Local(), " --\n")
	require.Nil(t, cl1.Send(relayMessage([]byte("good one"))))

	good := make(chan net.Message)
	bad := make(chan error)
	go func() {
		// message broadcasted
		m, err := cl2.Receive()
		if err != nil {
			bad <- err
		} else {
			good <- m
		}
	}()

	select {
	case m := <-good:
		rm, ok := m.(*RelayMessage)
		if !ok {
			t.Fatal("wrong message type")
		}
		egress := rm.GetEgress()
		if egress == nil {
			//fmt.Printf("%+v\n", rm)
			t.Fatal("no outgoing message")
		}
		if !bytes.Contains(egress.GetBlob(), []byte("good")) {
			t.Fatal("wrong message" + string(egress.Blob))
		}
		if egress.GetAddress() != cl1.Local().String() {
			t.Fatalf("wrong sender %s vs %s %s", egress.GetAddress(), cl1.Local().String())
		}
		if rm.GetChannel() != chanId1 {
			t.Fatal("wrong channel")
		}
	case e := <-bad:
		t.Error(e)
	case <-time.After(100 * time.Millisecond):
		t.Fatal("no message broadcasted")
	}

}

func TestChannelConnectionDown(t *testing.T) {
	router, err := net.NewLocalRouter(rAddr, enc)
	require.Nil(t, err)

	r := NewRelay(router)
	go r.Start()
	defer r.Stop()

	cl1, err := net.NewLocalConn(cAddr1, rAddr)
	require.Nil(t, err)
	cl2, err := net.NewLocalConn(cAddr2, rAddr)
	require.Nil(t, err)

	addClient := func(c net.Conn) bool {
		require.Nil(t, c.Send(&RelayMessage{
			Channel: chanId1,
			Type:    RelayMessage_JOIN,
		}))
		m, err := c.Receive()
		require.Nil(t, err)
		rm, ok := m.(*RelayMessage)
		require.True(t, ok)
		require.Equal(t, RelayMessage_JOIN_RESPONSE, rm.GetType())
		return JoinResponse_OK == rm.JoinResponse.Status
	}

	send := func(c1 net.Conn) {
		require.Nil(t, c1.Send(&RelayMessage{
			Channel: chanId1,
			Type:    RelayMessage_INGRESS,
			Ingress: &Ingress{
				Blob: []byte("hello world"),
			},
		}))
	}

	require.True(t, addClient(cl1))
	require.True(t, addClient(cl2))
	send(cl1)
	_, err = cl2.Receive()
	require.Nil(t, err)
	// close the connection
	require.Nil(t, cl2.Close())
	// make sure the router drops the connection
	require.Error(t, router.Send(cl2.Local(), &RelayMessage{}))
	send(cl1)
	r.channelsMut.Lock()
	require.Len(t, r.channels[chanId1].clients, 1)
	r.channelsMut.Unlock()
}

func TestChannelAddRemove(t *testing.T) {
	//log.TestOutput(true, 3)
	router, err := net.NewLocalRouter(rAddr, enc)
	require.Nil(t, err)

	r := NewRelay(router)
	go r.Start()
	defer r.Stop()

	cl1, err := net.NewLocalConn(cAddr1, rAddr)
	require.Nil(t, err)

	addClient := func(c net.Conn) bool {
		require.Nil(t, c.Send(&RelayMessage{
			Channel: chanId1,
			Type:    RelayMessage_JOIN,
		}))
		m, err := c.Receive()
		require.Nil(t, err)
		rm, ok := m.(*RelayMessage)
		require.True(t, ok)
		require.Equal(t, RelayMessage_JOIN_RESPONSE, rm.GetType())
		return JoinResponse_OK == rm.JoinResponse.Status
	}
	getList := func() map[net.Address]bool {
		r.channelsMut.Lock()
		defer r.channelsMut.Unlock()
		ch, ok := r.channels[chanId1]
		require.True(t, ok)
		return ch.clients
	}

	addClient(cl1)
	assert.Contains(t, getList(), cAddr1)
	assert.Len(t, getList(), 1)
	// registering twice
	addClient(cl1)
	assert.Len(t, getList(), 1)

	// too many clients
	conns := make([]net.Conn, ChannelSize+1)
	for i := 0; i < ChannelSize+1; i++ {
		addr := net.NewLocalAddress(fmt.Sprintf("channel-%d", i))
		conns[i], err = net.NewLocalConn(addr, rAddr)
		require.Nil(t, err)
		defer conns[i].Close()
		addClient(conns[i])
		//if i == ChannelSize {
		//	require.False(t, addClient(conns[i]))
		//}
	}
	time.Sleep(10 * time.Millisecond)
	assert.Len(t, getList(), ChannelSize)

	// remove our client
	require.Nil(t, cl1.Send(&RelayMessage{
		Channel: chanId1,
		Type:    RelayMessage_LEAVE,
	}))
	time.Sleep(10 * time.Millisecond)
	_, ok := getList()[cAddr1]
	assert.False(t, ok)
}

func getChannel(m *Multiplexer, id string) *clientChannel {
	m.chanMut.Lock()
	defer m.chanMut.Unlock()
	return m.channels[id]
}

func newRelay(t *testing.T) *Relay {
	router, err := net.NewLocalRouter(rAddr, enc)
	require.Nil(t, err)

	return NewRelay(router)
}

func newClient(t *testing.T, addr net.Address) net.Conn {
	cl1, err := net.NewLocalConn(addr, rAddr)
	require.Nil(t, err)
	return cl1
}
<commit_msg>fixing relay test<commit_after>package relay

import (
	"bytes"
	"fmt"
	"testing"
	"time"

	net "github.com/nikkolasg/mulsigo/network"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

var chanId1 = "MyCustomChanId1"
var chanId2 = "MyCustomChanId2"
var msg = []byte("Hello World")

func TestMultiplex(t *testing.T) {
	relay := newRelay(t)
	go relay.Start()
	defer relay.Stop()

	cl1 := newClient(t, cAddr1)
	cl2 := newClient(t, cAddr2)
	defer cl1.Close()
	defer cl2.Close()

	m1 := NewMultiplexer(cl1)
	m2 := NewMultiplexer(cl2)

	c11, err := m1.Channel(chanId1)
	assert.Nil(t, err)
	assert.NotNil(t, getChannel(m1, chanId1))
	c21, err := m2.Channel(chanId1)
	assert.Nil(t, err)
	assert.NotNil(t, getChannel(m2, chanId1))

	assert.Nil(t, c11.Send(msg))

	_, eg, err := c21.Receive()
	require.Nil(t, err)
	assert.Equal(t, msg, eg)
}

func TestChannelProcess(t *testing.T) {
	//log.TestOutput(true, 3)
	router, err := net.NewLocalRouter(rAddr, enc)
	//rAddr = net.NewTCPAddress("127.0.0.1:2000")
	//router, err := net.NewTCPRouter(rAddr, enc)
	require.Nil(t, err)
	go router.Start()
	defer router.Stop()
	r := NewRelay(router)
	defer r.Stop()
	//ch := newChannel(r, chanId1)
	cl1, err := net.NewLocalConn(cAddr1, rAddr)
	//cl1, err := net.NewTCPConn(rAddr, enc)
	require.Nil(t, err)
	cl2, err := net.NewLocalConn(cAddr2, rAddr)
	//cl2, err := net.NewTCPConn(rAddr, enc)
	require.Nil(t, err)
	defer cl1.Close()
	defer cl2.Close()
	fmt.Println("cl1.Local()", cl1.Local().String())
	fmt.Println("cl2.Local()", cl2.Local().String())

	// should be no op
	fmt.Println("\n -- MSG FROM ", cl1.Local(), " --\n")
	require.Nil(t, cl1.Send(relayMessage([]byte("whoup whoup"))))

	// add cl1
	fmt.Println("\n -- JOIN FROM ", cl1.Local(), " --\n")
	require.Nil(t, cl1.Send(joinMessage(cl1.Local())))
	//require.Nil(t, waitNClients(ch, 1))
	nm, err := cl1.Receive()
	require.Nil(t, err)
	rm, ok := nm.(*RelayMessage)
	require.True(t, ok)
	require.NotNil(t, rm.GetJoinResponse())
	require.Equal(t, JoinResponse_OK, rm.GetJoinResponse().Status)
	// should just continue as there's no other destination
	fmt.Println("\n -- MSG FROM ", cl1.Local(), " --\n")
	require.Nil(t, cl1.Send(relayMessage([]byte("still wrong"))))
	// let the time to the goroutine
	time.Sleep(5 * time.Millisecond)
	// add cl2
	fmt.Println("\n -- JOIN FROM ", cl2.Local(), " --\n")
	require.Nil(t, cl2.Send(joinMessage(cl2.Local())))
	// join response ack
	_, err = cl2.Receive()
	require.Nil(t, err)

	//require.Nil(t, waitNClients(ch, 2))
	fmt.Println("\n -- MSG FROM ", cl1.Local(), " --\n")
	require.Nil(t, cl1.Send(relayMessage([]byte("good one"))))

	good := make(chan net.Message)
	bad := make(chan error)
	go func() {
		// message broadcasted
		m, err := cl2.Receive()
		if err != nil {
			bad <- err
		} else {
			good <- m
		}
	}()

	select {
	case m := <-good:
		rm, ok := m.(*RelayMessage)
		if !ok {
			t.Fatal("wrong message type")
		}
		egress := rm.GetEgress()
		if egress == nil {
			//fmt.Printf("%+v\n", rm)
			t.Fatal("no outgoing message")
		}
		if !bytes.Contains(egress.GetBlob(), []byte("good")) {
			t.Fatal("wrong message" + string(egress.Blob))
		}
		// address not a field set anymore
		// TODO remove from RelayMessage
		/*if egress.GetAddress() != cl1.Local().String() {*/
		//t.Fatalf("wrong sender %s vs %s", egress.GetAddress(), cl1.Local().String())
		/*}*/
		if rm.GetChannel() != chanId1 {
			t.Fatal("wrong channel")
		}
	case e := <-bad:
		t.Error(e)
	case <-time.After(100 * time.Millisecond):
		t.Fatal("no message broadcasted")
	}

}

func TestChannelConnectionDown(t *testing.T) {
	router, err := net.NewLocalRouter(rAddr, enc)
	require.Nil(t, err)

	r := NewRelay(router)
	go r.Start()
	defer r.Stop()

	cl1, err := net.NewLocalConn(cAddr1, rAddr)
	require.Nil(t, err)
	cl2, err := net.NewLocalConn(cAddr2, rAddr)
	require.Nil(t, err)

	addClient := func(c net.Conn) bool {
		require.Nil(t, c.Send(&RelayMessage{
			Channel: chanId1,
			Type:    RelayMessage_JOIN,
		}))
		m, err := c.Receive()
		require.Nil(t, err)
		rm, ok := m.(*RelayMessage)
		require.True(t, ok)
		require.Equal(t, RelayMessage_JOIN_RESPONSE, rm.GetType())
		return JoinResponse_OK == rm.JoinResponse.Status
	}

	send := func(c1 net.Conn) {
		require.Nil(t, c1.Send(&RelayMessage{
			Channel: chanId1,
			Type:    RelayMessage_INGRESS,
			Ingress: &Ingress{
				Blob: []byte("hello world"),
			},
		}))
	}

	require.True(t, addClient(cl1))
	require.True(t, addClient(cl2))
	send(cl1)
	_, err = cl2.Receive()
	require.Nil(t, err)
	// close the connection
	require.Nil(t, cl2.Close())
	// make sure the router drops the connection
	require.Error(t, router.Send(cl2.Local(), &RelayMessage{}))
	send(cl1)
	r.channelsMut.Lock()
	require.Len(t, r.channels[chanId1].clients, 1)
	r.channelsMut.Unlock()
}

func TestChannelAddRemove(t *testing.T) {
	//log.TestOutput(true, 3)
	router, err := net.NewLocalRouter(rAddr, enc)
	require.Nil(t, err)

	r := NewRelay(router)
	go r.Start()
	defer r.Stop()

	cl1, err := net.NewLocalConn(cAddr1, rAddr)
	require.Nil(t, err)

	addClient := func(c net.Conn) bool {
		require.Nil(t, c.Send(&RelayMessage{
			Channel: chanId1,
			Type:    RelayMessage_JOIN,
		}))
		m, err := c.Receive()
		require.Nil(t, err)
		rm, ok := m.(*RelayMessage)
		require.True(t, ok)
		require.Equal(t, RelayMessage_JOIN_RESPONSE, rm.GetType())
		return JoinResponse_OK == rm.JoinResponse.Status
	}
	getList := func() map[net.Address]bool {
		r.channelsMut.Lock()
		defer r.channelsMut.Unlock()
		ch, ok := r.channels[chanId1]
		require.True(t, ok)
		return ch.clients
	}

	addClient(cl1)
	assert.Contains(t, getList(), cAddr1)
	assert.Len(t, getList(), 1)
	// registering twice
	addClient(cl1)
	assert.Len(t, getList(), 1)

	// too many clients
	conns := make([]net.Conn, ChannelSize+1)
	for i := 0; i < ChannelSize+1; i++ {
		addr := net.NewLocalAddress(fmt.Sprintf("channel-%d", i))
		conns[i], err = net.NewLocalConn(addr, rAddr)
		require.Nil(t, err)
		defer conns[i].Close()
		addClient(conns[i])
		//if i == ChannelSize {
		//	require.False(t, addClient(conns[i]))
		//}
	}
	time.Sleep(10 * time.Millisecond)
	assert.Len(t, getList(), ChannelSize)

	// remove our client
	require.Nil(t, cl1.Send(&RelayMessage{
		Channel: chanId1,
		Type:    RelayMessage_LEAVE,
	}))
	time.Sleep(10 * time.Millisecond)
	_, ok := getList()[cAddr1]
	assert.False(t, ok)
}

func getChannel(m *Multiplexer, id string) *clientChannel {
	m.chanMut.Lock()
	defer m.chanMut.Unlock()
	return m.channels[id]
}

func newRelay(t *testing.T) *Relay {
	router, err := net.NewLocalRouter(rAddr, enc)
	require.Nil(t, err)

	return NewRelay(router)
}

func newClient(t *testing.T, addr net.Address) net.Conn {
	cl1, err := net.NewLocalConn(addr, rAddr)
	require.Nil(t, err)
	return cl1
}
<|endoftext|>


<commit_before>package argot

import (
	"bytes"
	"errors"
	"fmt"
	"github.com/xeipuuv/gojsonschema"
	"io"
	"io/ioutil"
	"net/http"
	"strings"
	"testing"
)

type Step interface {
	Go() error
}

type Steps []Step

// t can be nil. If t is not nil and an error occurs, then t.Fatal
// will be called. The steps returned represent the steps that were
// executed, including the step that errored, if an error occurred.
func (ss Steps) Go(t *testing.T) (results Steps, err error) {
	if t != nil {
		defer func() {
			if err != nil {
				t.Fatalf("Achieved Steps: %v; Error: %v", results, err)
			}
		}()
	}
	results = make([]Step, 0, len(ss))
	for _, step := range ss {
		results = append(results, step)
		err = step.Go()
		if err != nil {
			return results, err
		}
	}
	return results, nil
}

// Use a chan to indicate the steps to carry out rather than a
// slice. The advantage of a chan is that it allows more laziness:
// steps can even be responsible for issuing their own subsequent
// steps.
type StepsChan <-chan Step

// t can be nil. If t is not nil and an error occurs, then t.Fatal
// will be called. The steps returned represent the steps that were
// executed, including the step that errored, if an error occurred.
func (sc StepsChan) Go(t *testing.T) (results Steps, err error) {
	if t != nil {
		defer func() {
			if err != nil {
				t.Fatalf("Achieved Steps: %v; Error: %v", results, err)
			}
		}()
	}
	results = make([]Step, 0, 16)
	for step := range sc {
		results = append(results, step)
		err = step.Go()
		if err != nil {
			return results, err
		}
	}
	return results, nil
}

type StepFunc func() error

func (sf StepFunc) Go() error {
	return sf()
}

type NamedStep struct {
	StepFunc
	name string
}

func (ns NamedStep) String() string {
	return ns.name
}

func NewNamedStep(name string, step StepFunc) *NamedStep {
	return &NamedStep{
		StepFunc: step,
		name:     name,
	}
}

type HttpCall struct {
	Client       *http.Client
	Request      *http.Request
	Response     *http.Response
	ResponseBody []byte
}

// client can be nil. If it is nil, a new http.Client is used.
func NewHttpCall(client *http.Client) *HttpCall {
	if client == nil {
		client = new(http.Client)
	}
	return &HttpCall{
		Client: client,
	}
}

func (hc *HttpCall) AssertNoRequest() error {
	if hc.Request == nil {
		return nil
	} else {
		return errors.New("Request already set")
	}
}

func (hc *HttpCall) AssertRequest() error {
	if hc.Request == nil {
		return errors.New("No Request set")
	} else {
		return nil
	}
}

func (hc *HttpCall) AssertNoRespose() error {
	if hc.Response == nil {
		return nil
	} else {
		return errors.New("Response already set")
	}
}

func (hc *HttpCall) EnsureResponse() error {
	if hc.Response != nil {
		return nil
	} else if hc.Request == nil {
		return errors.New("Cannot ensure response: no request.")
	} else if response, err := hc.Client.Do(hc.Request); err != nil {
		return fmt.Errorf("Error when making call of %v: %v", hc.Request, err)
	} else {
		hc.Response = response
		return nil
	}
}

// Idempotent.
func (hc *HttpCall) ReceiveBody() error {
	if err := hc.EnsureResponse(); err != nil {
		return err
	} else if hc.ResponseBody != nil {
		return nil
	} else {
		defer hc.Response.Body.Close()
		bites := new(bytes.Buffer)
		if _, err = io.Copy(bites, hc.Response.Body); err != nil {
			return err
		} else {
			hc.ResponseBody = bites.Bytes()
			return nil
		}
	}
}

// Idempotent. You should ensure this is called at the end of life for
// each HttpCall. It drains bodies and generally sweeps up the mess.
func (hc *HttpCall) Reset() error {
	hc.Request = nil
	if hc.Response != nil && hc.ResponseBody == nil {
		io.Copy(ioutil.Discard, hc.Response.Body)
		hc.Response.Body.Close()
	}
	hc.Response = nil
	hc.ResponseBody = nil
	return nil
}

// This will automatically call HttpCall.Reset to ensure it's safe to
// create a new request.
func (hc *HttpCall) NewRequest(method, urlStr string, body io.Reader) Step {
	return NewNamedStep("NewRequest", func() error {
		if err := hc.Reset(); err != nil {
			return err
		} else if req, err := http.NewRequest(method, urlStr, body); err != nil {
			return err
		} else {
			hc.Request = req
			return nil
		}
	})
}

func (hc *HttpCall) RequestHeader(key, value string) Step {
	return NewNamedStep("RequestHeader", func() error {
		if err := AnyError(hc.AssertRequest(), hc.AssertNoRespose()); err != nil {
			return err
		} else {
			hc.Request.Header.Set(key, value)
			return nil
		}
	})
}

func (hc *HttpCall) Call() Step {
	return NewNamedStep("Call", hc.EnsureResponse)
}

func (hc *HttpCall) ResponseStatusEquals(status int) Step {
	return NewNamedStep("ResponseStatusEquals", func() error {
		if err := hc.EnsureResponse(); err != nil {
			return err
		} else if hc.Response.StatusCode != status {
			return fmt.Errorf("Status: Expected %d; found %d.", status, hc.Response.StatusCode)
		} else {
			return nil
		}
	})
}

func (hc *HttpCall) ResponseHeaderEquals(key, value string) Step {
	return NewNamedStep("ResponseHeaderEquals", func() error {
		if err := hc.EnsureResponse(); err != nil {
			return err
		} else if header := hc.Response.Header.Get(key); header != value {
			return fmt.Errorf("Header '%s': Expected '%s'; found '%s'.", key, value, header)
		} else {
			return nil
		}
	})
}

func (hc *HttpCall) ResponseHeaderContains(key, value string) Step {
	return NewNamedStep("ResponseHeaderContains", func() error {
		if err := hc.EnsureResponse(); err != nil {
			return err
		} else if header := hc.Response.Header.Get(key); !strings.Contains(header, value) {
			return fmt.Errorf("Header '%s': Expected '%s'; found '%s'.", key, value, header)
		} else {
			return nil
		}
	})
}

func (hc *HttpCall) ResponseBodyEquals(value string) Step {
	return NewNamedStep("ResponseBodyEquals", func() error {
		if err := hc.ReceiveBody(); err != nil {
			return err
		} else if string(hc.ResponseBody) != value {
			return fmt.Errorf("Body: Expected '%s'; found '%s'.", value, string(hc.ResponseBody))
		} else {
			return nil
		}
	})
}

func (hc *HttpCall) ResponseBodyContains(value string) Step {
	return NewNamedStep("ResponseBodyContains", func() error {
		if err := hc.ReceiveBody(); err != nil {
			return err
		} else if !strings.Contains(string(hc.ResponseBody), value) {
			return fmt.Errorf("Body: Expected '%s'; found '%s'.", value, string(hc.ResponseBody))
		} else {
			return nil
		}
	})
}

func (hc *HttpCall) ResponseBodyJSONSchema(schema string) Step {
	return NewNamedStep("ResponseBodyJSONSchema", func() error {
		if err := hc.ReceiveBody(); err != nil {
			return err
		} else {
			schemaLoader := gojsonschema.NewStringLoader(schema)
			bodyLoader := gojsonschema.NewStringLoader(string(hc.ResponseBody))
			if result, err := gojsonschema.Validate(schemaLoader, bodyLoader); err != nil {
				return err
			} else if !result.Valid() {
				msg := "Validation failure:\n"
				for _, err := range result.Errors() {
					msg += fmt.Sprintf("\t%v\n", err)
				}
				return errors.New(msg[:len(msg)-1])
			} else {
				return nil
			}
		}
	})
}

func AnyError(errs ...error) error {
	for _, err := range errs {
		if err != nil {
			return err
		}
	}
	return nil
}
<commit_msg>Make strings super.<commit_after>package argot

import (
	"bytes"
	"errors"
	"fmt"
	"github.com/xeipuuv/gojsonschema"
	"io"
	"io/ioutil"
	"net/http"
	"strings"
	"testing"
)

type Step interface {
	Go() error
}

type Steps []Step

// t can be nil. If t is not nil and an error occurs, then t.Fatal
// will be called. The steps returned represent the steps that were
// executed, including the step that errored, if an error occurred.
func (ss Steps) Go(t *testing.T) (results Steps, err error) {
	if t != nil {
		defer func() {
			if err != nil {
				t.Fatalf("Achieved Steps: %v; Error: %v", results, err)
			}
		}()
	}
	results = make([]Step, 0, len(ss))
	for _, step := range ss {
		results = append(results, step)
		err = step.Go()
		if err != nil {
			return results, err
		}
	}
	return results, nil
}

// Use a chan to indicate the steps to carry out rather than a
// slice. The advantage of a chan is that it allows more laziness:
// steps can even be responsible for issuing their own subsequent
// steps.
type StepsChan <-chan Step

// t can be nil. If t is not nil and an error occurs, then t.Fatal
// will be called. The steps returned represent the steps that were
// executed, including the step that errored, if an error occurred.
func (sc StepsChan) Go(t *testing.T) (results Steps, err error) {
	if t != nil {
		defer func() {
			if err != nil {
				t.Fatalf("Achieved Steps: %v; Error: %v", results, err)
			}
		}()
	}
	results = make([]Step, 0, 16)
	for step := range sc {
		results = append(results, step)
		err = step.Go()
		if err != nil {
			return results, err
		}
	}
	return results, nil
}

type StepFunc func() error

func (sf StepFunc) Go() error {
	return sf()
}

type NamedStep struct {
	StepFunc
	name string
}

func (ns NamedStep) String() string {
	return ns.name
}

func NewNamedStep(name string, step StepFunc) *NamedStep {
	return &NamedStep{
		StepFunc: step,
		name:     name,
	}
}

type HttpCall struct {
	Client       *http.Client
	Request      *http.Request
	Response     *http.Response
	ResponseBody []byte
}

// client can be nil. If it is nil, a new http.Client is used.
func NewHttpCall(client *http.Client) *HttpCall {
	if client == nil {
		client = new(http.Client)
	}
	return &HttpCall{
		Client: client,
	}
}

func (hc *HttpCall) AssertNoRequest() error {
	if hc.Request == nil {
		return nil
	} else {
		return errors.New("Request already set")
	}
}

func (hc *HttpCall) AssertRequest() error {
	if hc.Request == nil {
		return errors.New("No Request set")
	} else {
		return nil
	}
}

func (hc *HttpCall) AssertNoRespose() error {
	if hc.Response == nil {
		return nil
	} else {
		return errors.New("Response already set")
	}
}

func (hc *HttpCall) EnsureResponse() error {
	if hc.Response != nil {
		return nil
	} else if hc.Request == nil {
		return errors.New("Cannot ensure response: no request.")
	} else if response, err := hc.Client.Do(hc.Request); err != nil {
		return fmt.Errorf("Error when making call of %v: %v", hc.Request, err)
	} else {
		hc.Response = response
		return nil
	}
}

// Idempotent.
func (hc *HttpCall) ReceiveBody() error {
	if err := hc.EnsureResponse(); err != nil {
		return err
	} else if hc.ResponseBody != nil {
		return nil
	} else {
		defer hc.Response.Body.Close()
		bites := new(bytes.Buffer)
		if _, err = io.Copy(bites, hc.Response.Body); err != nil {
			return err
		} else {
			hc.ResponseBody = bites.Bytes()
			return nil
		}
	}
}

// Idempotent. You should ensure this is called at the end of life for
// each HttpCall. It drains bodies and generally sweeps up the mess.
func (hc *HttpCall) Reset() error {
	hc.Request = nil
	if hc.Response != nil && hc.ResponseBody == nil {
		io.Copy(ioutil.Discard, hc.Response.Body)
		hc.Response.Body.Close()
	}
	hc.Response = nil
	hc.ResponseBody = nil
	return nil
}

// This will automatically call HttpCall.Reset to ensure it's safe to
// create a new request.
func (hc *HttpCall) NewRequest(method, urlStr string, body io.Reader) Step {
	return NewNamedStep(fmt.Sprintf("NewRequest(%s: %s)", method, urlStr), func() error {
		if err := hc.Reset(); err != nil {
			return err
		} else if req, err := http.NewRequest(method, urlStr, body); err != nil {
			return err
		} else {
			hc.Request = req
			return nil
		}
	})
}

func (hc *HttpCall) RequestHeader(key, value string) Step {
	return NewNamedStep(fmt.Sprintf("RequestHeader(%s: %s)", key, value), func() error {
		if err := AnyError(hc.AssertRequest(), hc.AssertNoRespose()); err != nil {
			return err
		} else {
			hc.Request.Header.Set(key, value)
			return nil
		}
	})
}

func (hc *HttpCall) Call() Step {
	return NewNamedStep("Call", hc.EnsureResponse)
}

func (hc *HttpCall) ResponseStatusEquals(status int) Step {
	return NewNamedStep(fmt.Sprintf("ResponseStatusEquals(%d)", status), func() error {
		if err := hc.EnsureResponse(); err != nil {
			return err
		} else if hc.Response.StatusCode != status {
			return fmt.Errorf("Status: Expected %d; found %d.", status, hc.Response.StatusCode)
		} else {
			return nil
		}
	})
}

func (hc *HttpCall) ResponseHeaderEquals(key, value string) Step {
	return NewNamedStep(fmt.Sprintf("ResponseHeaderEquals(%s: %s)", key, value), func() error {
		if err := hc.EnsureResponse(); err != nil {
			return err
		} else if header := hc.Response.Header.Get(key); header != value {
			return fmt.Errorf("Header '%s': Expected '%s'; found '%s'.", key, value, header)
		} else {
			return nil
		}
	})
}

func (hc *HttpCall) ResponseHeaderContains(key, value string) Step {
	return NewNamedStep(fmt.Sprintf("ResponseHeaderContains(%s: %s)", key, value), func() error {
		if err := hc.EnsureResponse(); err != nil {
			return err
		} else if header := hc.Response.Header.Get(key); !strings.Contains(header, value) {
			return fmt.Errorf("Header '%s': Expected '%s'; found '%s'.", key, value, header)
		} else {
			return nil
		}
	})
}

func (hc *HttpCall) ResponseBodyEquals(value string) Step {
	return NewNamedStep("ResponseBodyEquals", func() error {
		if err := hc.ReceiveBody(); err != nil {
			return err
		} else if string(hc.ResponseBody) != value {
			return fmt.Errorf("Body: Expected '%s'; found '%s'.", value, string(hc.ResponseBody))
		} else {
			return nil
		}
	})
}

func (hc *HttpCall) ResponseBodyContains(value string) Step {
	return NewNamedStep("ResponseBodyContains", func() error {
		if err := hc.ReceiveBody(); err != nil {
			return err
		} else if !strings.Contains(string(hc.ResponseBody), value) {
			return fmt.Errorf("Body: Expected '%s'; found '%s'.", value, string(hc.ResponseBody))
		} else {
			return nil
		}
	})
}

func (hc *HttpCall) ResponseBodyJSONSchema(schema string) Step {
	return NewNamedStep("ResponseBodyJSONSchema", func() error {
		if err := hc.ReceiveBody(); err != nil {
			return err
		} else {
			schemaLoader := gojsonschema.NewStringLoader(schema)
			bodyLoader := gojsonschema.NewStringLoader(string(hc.ResponseBody))
			if result, err := gojsonschema.Validate(schemaLoader, bodyLoader); err != nil {
				return err
			} else if !result.Valid() {
				msg := "Validation failure:\n"
				for _, err := range result.Errors() {
					msg += fmt.Sprintf("\t%v\n", err)
				}
				return errors.New(msg[:len(msg)-1])
			} else {
				return nil
			}
		}
	})
}

func AnyError(errs ...error) error {
	for _, err := range errs {
		if err != nil {
			return err
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package pgtype

import (
	"bytes"
	"encoding/binary"
	"io"
	"reflect"
	"strconv"
	"strings"
	"unicode"

	"github.com/jackc/pgio"
	errors "golang.org/x/xerrors"
)

// Information on the internals of PostgreSQL arrays can be found in
// src/include/utils/array.h and src/backend/utils/adt/arrayfuncs.c. Of
// particular interest is the array_send function.

type ArrayHeader struct {
	ContainsNull bool
	ElementOID   int32
	Dimensions   []ArrayDimension
}

type ArrayDimension struct {
	Length     int32
	LowerBound int32
}

func (dst *ArrayHeader) DecodeBinary(ci *ConnInfo, src []byte) (int, error) {
	if len(src) < 12 {
		return 0, errors.Errorf("array header too short: %d", len(src))
	}

	rp := 0

	numDims := int(binary.BigEndian.Uint32(src[rp:]))
	rp += 4

	dst.ContainsNull = binary.BigEndian.Uint32(src[rp:]) == 1
	rp += 4

	dst.ElementOID = int32(binary.BigEndian.Uint32(src[rp:]))
	rp += 4

	if numDims > 0 {
		dst.Dimensions = make([]ArrayDimension, numDims)
	}
	if len(src) < 12+numDims*8 {
		return 0, errors.Errorf("array header too short for %d dimensions: %d", numDims, len(src))
	}
	for i := range dst.Dimensions {
		dst.Dimensions[i].Length = int32(binary.BigEndian.Uint32(src[rp:]))
		rp += 4

		dst.Dimensions[i].LowerBound = int32(binary.BigEndian.Uint32(src[rp:]))
		rp += 4
	}

	return rp, nil
}

func (src ArrayHeader) EncodeBinary(ci *ConnInfo, buf []byte) []byte {
	buf = pgio.AppendInt32(buf, int32(len(src.Dimensions)))

	var containsNull int32
	if src.ContainsNull {
		containsNull = 1
	}
	buf = pgio.AppendInt32(buf, containsNull)

	buf = pgio.AppendInt32(buf, src.ElementOID)

	for i := range src.Dimensions {
		buf = pgio.AppendInt32(buf, src.Dimensions[i].Length)
		buf = pgio.AppendInt32(buf, src.Dimensions[i].LowerBound)
	}

	return buf
}

type UntypedTextArray struct {
	Elements   []string
	Quoted     []bool
	Dimensions []ArrayDimension
}

func ParseUntypedTextArray(src string) (*UntypedTextArray, error) {
	dst := &UntypedTextArray{}

	buf := bytes.NewBufferString(src)

	skipWhitespace(buf)

	r, _, err := buf.ReadRune()
	if err != nil {
		return nil, errors.Errorf("invalid array: %v", err)
	}

	var explicitDimensions []ArrayDimension

	// Array has explicit dimensions
	if r == '[' {
		buf.UnreadRune()

		for {
			r, _, err = buf.ReadRune()
			if err != nil {
				return nil, errors.Errorf("invalid array: %v", err)
			}

			if r == '=' {
				break
			} else if r != '[' {
				return nil, errors.Errorf("invalid array, expected '[' or '=' got %v", r)
			}

			lower, err := arrayParseInteger(buf)
			if err != nil {
				return nil, errors.Errorf("invalid array: %v", err)
			}

			r, _, err = buf.ReadRune()
			if err != nil {
				return nil, errors.Errorf("invalid array: %v", err)
			}

			if r != ':' {
				return nil, errors.Errorf("invalid array, expected ':' got %v", r)
			}

			upper, err := arrayParseInteger(buf)
			if err != nil {
				return nil, errors.Errorf("invalid array: %v", err)
			}

			r, _, err = buf.ReadRune()
			if err != nil {
				return nil, errors.Errorf("invalid array: %v", err)
			}

			if r != ']' {
				return nil, errors.Errorf("invalid array, expected ']' got %v", r)
			}

			explicitDimensions = append(explicitDimensions, ArrayDimension{LowerBound: lower, Length: upper - lower + 1})
		}

		r, _, err = buf.ReadRune()
		if err != nil {
			return nil, errors.Errorf("invalid array: %v", err)
		}
	}

	if r != '{' {
		return nil, errors.Errorf("invalid array, expected '{': %v", err)
	}

	implicitDimensions := []ArrayDimension{{LowerBound: 1, Length: 0}}

	// Consume all initial opening brackets. This provides number of dimensions.
	for {
		r, _, err = buf.ReadRune()
		if err != nil {
			return nil, errors.Errorf("invalid array: %v", err)
		}

		if r == '{' {
			implicitDimensions[len(implicitDimensions)-1].Length = 1
			implicitDimensions = append(implicitDimensions, ArrayDimension{LowerBound: 1})
		} else {
			buf.UnreadRune()
			break
		}
	}
	currentDim := len(implicitDimensions) - 1
	counterDim := currentDim

	for {
		r, _, err = buf.ReadRune()
		if err != nil {
			return nil, errors.Errorf("invalid array: %v", err)
		}

		switch r {
		case '{':
			if currentDim == counterDim {
				implicitDimensions[currentDim].Length++
			}
			currentDim++
		case ',':
		case '}':
			currentDim--
			if currentDim < counterDim {
				counterDim = currentDim
			}
		default:
			buf.UnreadRune()
			value, quoted, err := arrayParseValue(buf)
			if err != nil {
				return nil, errors.Errorf("invalid array value: %v", err)
			}
			if currentDim == counterDim {
				implicitDimensions[currentDim].Length++
			}
			dst.Quoted = append(dst.Quoted, quoted)
			dst.Elements = append(dst.Elements, value)
		}

		if currentDim < 0 {
			break
		}
	}

	skipWhitespace(buf)

	if buf.Len() > 0 {
		return nil, errors.Errorf("unexpected trailing data: %v", buf.String())
	}

	if len(dst.Elements) == 0 {
		dst.Dimensions = nil
	} else if len(explicitDimensions) > 0 {
		dst.Dimensions = explicitDimensions
	} else {
		dst.Dimensions = implicitDimensions
	}

	return dst, nil
}

func skipWhitespace(buf *bytes.Buffer) {
	var r rune
	var err error
	for r, _, _ = buf.ReadRune(); unicode.IsSpace(r); r, _, _ = buf.ReadRune() {
	}

	if err != io.EOF {
		buf.UnreadRune()
	}
}

func arrayParseValue(buf *bytes.Buffer) (string, bool, error) {
	r, _, err := buf.ReadRune()
	if err != nil {
		return "", false, err
	}
	if r == '"' {
		return arrayParseQuotedValue(buf)
	}
	buf.UnreadRune()

	s := &bytes.Buffer{}

	for {
		r, _, err := buf.ReadRune()
		if err != nil {
			return "", false, err
		}

		switch r {
		case ',', '}':
			buf.UnreadRune()
			return s.String(), false, nil
		}

		s.WriteRune(r)
	}
}

func arrayParseQuotedValue(buf *bytes.Buffer) (string, bool, error) {
	s := &bytes.Buffer{}

	for {
		r, _, err := buf.ReadRune()
		if err != nil {
			return "", false, err
		}

		switch r {
		case '\\':
			r, _, err = buf.ReadRune()
			if err != nil {
				return "", false, err
			}
		case '"':
			r, _, err = buf.ReadRune()
			if err != nil {
				return "", false, err
			}
			buf.UnreadRune()
			return s.String(), true, nil
		}
		s.WriteRune(r)
	}
}

func arrayParseInteger(buf *bytes.Buffer) (int32, error) {
	s := &bytes.Buffer{}

	for {
		r, _, err := buf.ReadRune()
		if err != nil {
			return 0, err
		}

		if '0' <= r && r <= '9' {
			s.WriteRune(r)
		} else {
			buf.UnreadRune()
			n, err := strconv.ParseInt(s.String(), 10, 32)
			if err != nil {
				return 0, err
			}
			return int32(n), nil
		}
	}
}

func EncodeTextArrayDimensions(buf []byte, dimensions []ArrayDimension) []byte {
	var customDimensions bool
	for _, dim := range dimensions {
		if dim.LowerBound != 1 {
			customDimensions = true
		}
	}

	if !customDimensions {
		return buf
	}

	for _, dim := range dimensions {
		buf = append(buf, '[')
		buf = append(buf, strconv.FormatInt(int64(dim.LowerBound), 10)...)
		buf = append(buf, ':')
		buf = append(buf, strconv.FormatInt(int64(dim.LowerBound+dim.Length-1), 10)...)
		buf = append(buf, ']')
	}

	return append(buf, '=')
}

var quoteArrayReplacer = strings.NewReplacer(`\`, `\\`, `"`, `\"`)

func quoteArrayElement(src string) string {
	return `"` + quoteArrayReplacer.Replace(src) + `"`
}

func QuoteArrayElementIfNeeded(src string) string {
	if src == "" || (len(src) == 4 && strings.ToLower(src) == "null") || src[0] == ' ' || src[len(src)-1] == ' ' || strings.ContainsAny(src, `{},"\`) {
		return quoteArrayElement(src)
	}
	return src
}

func findDimensionsFromValue(value reflect.Value, dimensions []ArrayDimension, elementsLength int) ([]ArrayDimension, int, bool) {
	switch value.Kind() {
	case reflect.Array:
		fallthrough
	case reflect.Slice:
		length := value.Len()
		if 0 == elementsLength {
			elementsLength = length
		} else {
			elementsLength *= length
		}
		dimensions = append(dimensions, ArrayDimension{Length: int32(length), LowerBound: 1})
		for i := 0; i < length; i++ {
			if d, l, ok := findDimensionsFromValue(value.Index(i), dimensions, elementsLength); ok {
				return d, l, true
			}
		}
	}
	return dimensions, elementsLength, true
}
<commit_msg>Fix: escaped strings when they start or end with a newline char (jackc/pgtype#86)<commit_after>package pgtype

import (
	"bytes"
	"encoding/binary"
	"io"
	"reflect"
	"strconv"
	"strings"
	"unicode"

	"github.com/jackc/pgio"
	errors "golang.org/x/xerrors"
)

// Information on the internals of PostgreSQL arrays can be found in
// src/include/utils/array.h and src/backend/utils/adt/arrayfuncs.c. Of
// particular interest is the array_send function.

type ArrayHeader struct {
	ContainsNull bool
	ElementOID   int32
	Dimensions   []ArrayDimension
}

type ArrayDimension struct {
	Length     int32
	LowerBound int32
}

func (dst *ArrayHeader) DecodeBinary(ci *ConnInfo, src []byte) (int, error) {
	if len(src) < 12 {
		return 0, errors.Errorf("array header too short: %d", len(src))
	}

	rp := 0

	numDims := int(binary.BigEndian.Uint32(src[rp:]))
	rp += 4

	dst.ContainsNull = binary.BigEndian.Uint32(src[rp:]) == 1
	rp += 4

	dst.ElementOID = int32(binary.BigEndian.Uint32(src[rp:]))
	rp += 4

	if numDims > 0 {
		dst.Dimensions = make([]ArrayDimension, numDims)
	}
	if len(src) < 12+numDims*8 {
		return 0, errors.Errorf("array header too short for %d dimensions: %d", numDims, len(src))
	}
	for i := range dst.Dimensions {
		dst.Dimensions[i].Length = int32(binary.BigEndian.Uint32(src[rp:]))
		rp += 4

		dst.Dimensions[i].LowerBound = int32(binary.BigEndian.Uint32(src[rp:]))
		rp += 4
	}

	return rp, nil
}

func (src ArrayHeader) EncodeBinary(ci *ConnInfo, buf []byte) []byte {
	buf = pgio.AppendInt32(buf, int32(len(src.Dimensions)))

	var containsNull int32
	if src.ContainsNull {
		containsNull = 1
	}
	buf = pgio.AppendInt32(buf, containsNull)

	buf = pgio.AppendInt32(buf, src.ElementOID)

	for i := range src.Dimensions {
		buf = pgio.AppendInt32(buf, src.Dimensions[i].Length)
		buf = pgio.AppendInt32(buf, src.Dimensions[i].LowerBound)
	}

	return buf
}

type UntypedTextArray struct {
	Elements   []string
	Quoted     []bool
	Dimensions []ArrayDimension
}

func ParseUntypedTextArray(src string) (*UntypedTextArray, error) {
	dst := &UntypedTextArray{}

	buf := bytes.NewBufferString(src)

	skipWhitespace(buf)

	r, _, err := buf.ReadRune()
	if err != nil {
		return nil, errors.Errorf("invalid array: %v", err)
	}

	var explicitDimensions []ArrayDimension

	// Array has explicit dimensions
	if r == '[' {
		buf.UnreadRune()

		for {
			r, _, err = buf.ReadRune()
			if err != nil {
				return nil, errors.Errorf("invalid array: %v", err)
			}

			if r == '=' {
				break
			} else if r != '[' {
				return nil, errors.Errorf("invalid array, expected '[' or '=' got %v", r)
			}

			lower, err := arrayParseInteger(buf)
			if err != nil {
				return nil, errors.Errorf("invalid array: %v", err)
			}

			r, _, err = buf.ReadRune()
			if err != nil {
				return nil, errors.Errorf("invalid array: %v", err)
			}

			if r != ':' {
				return nil, errors.Errorf("invalid array, expected ':' got %v", r)
			}

			upper, err := arrayParseInteger(buf)
			if err != nil {
				return nil, errors.Errorf("invalid array: %v", err)
			}

			r, _, err = buf.ReadRune()
			if err != nil {
				return nil, errors.Errorf("invalid array: %v", err)
			}

			if r != ']' {
				return nil, errors.Errorf("invalid array, expected ']' got %v", r)
			}

			explicitDimensions = append(explicitDimensions, ArrayDimension{LowerBound: lower, Length: upper - lower + 1})
		}

		r, _, err = buf.ReadRune()
		if err != nil {
			return nil, errors.Errorf("invalid array: %v", err)
		}
	}

	if r != '{' {
		return nil, errors.Errorf("invalid array, expected '{': %v", err)
	}

	implicitDimensions := []ArrayDimension{{LowerBound: 1, Length: 0}}

	// Consume all initial opening brackets. This provides number of dimensions.
	for {
		r, _, err = buf.ReadRune()
		if err != nil {
			return nil, errors.Errorf("invalid array: %v", err)
		}

		if r == '{' {
			implicitDimensions[len(implicitDimensions)-1].Length = 1
			implicitDimensions = append(implicitDimensions, ArrayDimension{LowerBound: 1})
		} else {
			buf.UnreadRune()
			break
		}
	}
	currentDim := len(implicitDimensions) - 1
	counterDim := currentDim

	for {
		r, _, err = buf.ReadRune()
		if err != nil {
			return nil, errors.Errorf("invalid array: %v", err)
		}

		switch r {
		case '{':
			if currentDim == counterDim {
				implicitDimensions[currentDim].Length++
			}
			currentDim++
		case ',':
		case '}':
			currentDim--
			if currentDim < counterDim {
				counterDim = currentDim
			}
		default:
			buf.UnreadRune()
			value, quoted, err := arrayParseValue(buf)
			if err != nil {
				return nil, errors.Errorf("invalid array value: %v", err)
			}
			if currentDim == counterDim {
				implicitDimensions[currentDim].Length++
			}
			dst.Quoted = append(dst.Quoted, quoted)
			dst.Elements = append(dst.Elements, value)
		}

		if currentDim < 0 {
			break
		}
	}

	skipWhitespace(buf)

	if buf.Len() > 0 {
		return nil, errors.Errorf("unexpected trailing data: %v", buf.String())
	}

	if len(dst.Elements) == 0 {
		dst.Dimensions = nil
	} else if len(explicitDimensions) > 0 {
		dst.Dimensions = explicitDimensions
	} else {
		dst.Dimensions = implicitDimensions
	}

	return dst, nil
}

func skipWhitespace(buf *bytes.Buffer) {
	var r rune
	var err error
	for r, _, _ = buf.ReadRune(); unicode.IsSpace(r); r, _, _ = buf.ReadRune() {
	}

	if err != io.EOF {
		buf.UnreadRune()
	}
}

func arrayParseValue(buf *bytes.Buffer) (string, bool, error) {
	r, _, err := buf.ReadRune()
	if err != nil {
		return "", false, err
	}
	if r == '"' {
		return arrayParseQuotedValue(buf)
	}
	buf.UnreadRune()

	s := &bytes.Buffer{}

	for {
		r, _, err := buf.ReadRune()
		if err != nil {
			return "", false, err
		}

		switch r {
		case ',', '}':
			buf.UnreadRune()
			return s.String(), false, nil
		}

		s.WriteRune(r)
	}
}

func arrayParseQuotedValue(buf *bytes.Buffer) (string, bool, error) {
	s := &bytes.Buffer{}

	for {
		r, _, err := buf.ReadRune()
		if err != nil {
			return "", false, err
		}

		switch r {
		case '\\':
			r, _, err = buf.ReadRune()
			if err != nil {
				return "", false, err
			}
		case '"':
			r, _, err = buf.ReadRune()
			if err != nil {
				return "", false, err
			}
			buf.UnreadRune()
			return s.String(), true, nil
		}
		s.WriteRune(r)
	}
}

func arrayParseInteger(buf *bytes.Buffer) (int32, error) {
	s := &bytes.Buffer{}

	for {
		r, _, err := buf.ReadRune()
		if err != nil {
			return 0, err
		}

		if '0' <= r && r <= '9' {
			s.WriteRune(r)
		} else {
			buf.UnreadRune()
			n, err := strconv.ParseInt(s.String(), 10, 32)
			if err != nil {
				return 0, err
			}
			return int32(n), nil
		}
	}
}

func EncodeTextArrayDimensions(buf []byte, dimensions []ArrayDimension) []byte {
	var customDimensions bool
	for _, dim := range dimensions {
		if dim.LowerBound != 1 {
			customDimensions = true
		}
	}

	if !customDimensions {
		return buf
	}

	for _, dim := range dimensions {
		buf = append(buf, '[')
		buf = append(buf, strconv.FormatInt(int64(dim.LowerBound), 10)...)
		buf = append(buf, ':')
		buf = append(buf, strconv.FormatInt(int64(dim.LowerBound+dim.Length-1), 10)...)
		buf = append(buf, ']')
	}

	return append(buf, '=')
}

var quoteArrayReplacer = strings.NewReplacer(`\`, `\\`, `"`, `\"`)

func quoteArrayElement(src string) string {
	return `"` + quoteArrayReplacer.Replace(src) + `"`
}

func QuoteArrayElementIfNeeded(src string) string {
	if src == "" || (len(src) == 4 && strings.ToLower(src) == "null") || src[0] == ' ' || src[0] == '\n' || src[len(src)-1] == ' ' || src[len(src)-1] == '\n' || strings.ContainsAny(src, `{},"\`) {
		return quoteArrayElement(src)
	}
	return src
}

func findDimensionsFromValue(value reflect.Value, dimensions []ArrayDimension, elementsLength int) ([]ArrayDimension, int, bool) {
	switch value.Kind() {
	case reflect.Array:
		fallthrough
	case reflect.Slice:
		length := value.Len()
		if 0 == elementsLength {
			elementsLength = length
		} else {
			elementsLength *= length
		}
		dimensions = append(dimensions, ArrayDimension{Length: int32(length), LowerBound: 1})
		for i := 0; i < length; i++ {
			if d, l, ok := findDimensionsFromValue(value.Index(i), dimensions, elementsLength); ok {
				return d, l, true
			}
		}
	}
	return dimensions, elementsLength, true
}
<|endoftext|>


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

package main

import (
	"fmt"
	"os"

	vc "github.com/containers/virtcontainers"
	"github.com/containers/virtcontainers/pkg/oci"
	"github.com/urfave/cli"
)

var deleteCommand = cli.Command{
	Name:  "delete",
	Usage: "Delete any resources held by one or more containers",
	ArgsUsage: `<container-id> [container-id...]

   <container-id> is the name for the instance of the container.

EXAMPLE:
   If the container id is "ubuntu01" and ` + name + ` list currently shows the
   status of "ubuntu01" as "stopped" the following will delete resources held
   for "ubuntu01" removing "ubuntu01" from the ` + name + ` list of containers:

       # ` + name + ` delete ubuntu01`,
	Flags: []cli.Flag{
		cli.BoolFlag{
			Name:  "force, f",
			Usage: "Forcibly deletes the container if it is still running (uses SIGKILL)",
		},
	},
	Action: func(context *cli.Context) error {
		args := context.Args()
		if args.Present() == false {
			return fmt.Errorf("Missing container ID, should at least provide one")
		}

		force := context.Bool("force")
		for _, cID := range []string(args) {
			if err := delete(cID, force); err != nil {
				return err
			}
		}

		return nil
	},
}

func delete(containerID string, force bool) error {
	// Checks the MUST and MUST NOT from OCI runtime specification
	status, podID, err := getExistingContainerInfo(containerID)
	if err != nil {
		return err
	}

	if force == false {
		running, err := processRunning(status.PID)
		if err != nil {
			return err
		}

		if running == true {
			return fmt.Errorf("Container still running, should be stopped")
		}
	}

	// Retrieve OCI spec configuration.
	ociSpec, err := oci.GetOCIConfig(status)
	if err != nil {
		return err
	}

	if _, err = vc.StopPod(podID); err != nil {
		return err
	}

	if _, err := vc.DeletePod(podID); err != nil {
		return err
	}

	// In order to prevent any file descriptor leak related to cgroups files
	// that have been previously created, we have to remove them before this
	// function returns.
	cgroupsPathList, err := processCgroupsPath(ociSpec, true)
	if err != nil {
		return err
	}

	if err := removeCgroupsPath(cgroupsPathList); err != nil {
		return err
	}

	return nil
}

func removeCgroupsPath(cgroupsPathList []string) error {
	if len(cgroupsPathList) == 0 {
		ccLog.Info("Cgroups files not removed because cgroupsPath was empty")
		return nil
	}

	for _, cgroupsPath := range cgroupsPathList {
		if err := os.RemoveAll(cgroupsPath); err != nil {
			return err
		}
	}

	return nil
}
<commit_msg>delete: Add support for CRI-O<commit_after>// Copyright (c) 2014,2015,2016 Docker, Inc.
// Copyright (c) 2017 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"fmt"
	"os"

	vc "github.com/containers/virtcontainers"
	"github.com/containers/virtcontainers/pkg/oci"
	"github.com/urfave/cli"
)

var deleteCommand = cli.Command{
	Name:  "delete",
	Usage: "Delete any resources held by one or more containers",
	ArgsUsage: `<container-id> [container-id...]

   <container-id> is the name for the instance of the container.

EXAMPLE:
   If the container id is "ubuntu01" and ` + name + ` list currently shows the
   status of "ubuntu01" as "stopped" the following will delete resources held
   for "ubuntu01" removing "ubuntu01" from the ` + name + ` list of containers:

       # ` + name + ` delete ubuntu01`,
	Flags: []cli.Flag{
		cli.BoolFlag{
			Name:  "force, f",
			Usage: "Forcibly deletes the container if it is still running (uses SIGKILL)",
		},
	},
	Action: func(context *cli.Context) error {
		args := context.Args()
		if args.Present() == false {
			return fmt.Errorf("Missing container ID, should at least provide one")
		}

		force := context.Bool("force")
		for _, cID := range []string(args) {
			if err := delete(cID, force); err != nil {
				return err
			}
		}

		return nil
	},
}

func delete(containerID string, force bool) error {
	// Checks the MUST and MUST NOT from OCI runtime specification
	status, podID, err := getExistingContainerInfo(containerID)
	if err != nil {
		return err
	}

	containerID = status.ID

	containerType, err := oci.GetContainerType(status.Annotations)
	if err != nil {
		return err
	}

	// Retrieve OCI spec configuration.
	ociSpec, err := oci.GetOCIConfig(status)
	if err != nil {
		return err
	}

	running, err := processRunning(status.PID)
	if err != nil {
		return err
	}

	if !force && running {
		return fmt.Errorf("Container still running, should be stopped")
	}

	forceStop := false
	if oci.StateToOCIState(status.State) == oci.StateRunning {
		forceStop = true
		ccLog.Info("Force stopping the pod/container before deleting")
	}

	switch containerType {
	case vc.PodSandbox:
		if err := deletePod(podID, forceStop); err != nil {
			return err
		}
	case vc.PodContainer:
		if err := deleteContainer(podID, containerID, forceStop); err != nil {
			return err
		}
	default:
		return fmt.Errorf("Invalid container type found")
	}

	// In order to prevent any file descriptor leak related to cgroups files
	// that have been previously created, we have to remove them before this
	// function returns.
	cgroupsPathList, err := processCgroupsPath(ociSpec, containerType.IsPod())
	if err != nil {
		return err
	}

	return removeCgroupsPath(cgroupsPathList)
}

func deletePod(podID string, forceStop bool) error {
	if forceStop {
		if _, err := vc.StopPod(podID); err != nil {
			return err
		}
	}

	if _, err := vc.DeletePod(podID); err != nil {
		return err
	}

	return nil
}

func deleteContainer(podID, containerID string, forceStop bool) error {
	if forceStop {
		if _, err := vc.StopContainer(podID, containerID); err != nil {
			return err
		}
	}

	if _, err := vc.DeleteContainer(podID, containerID); err != nil {
		return err
	}

	return nil
}

func removeCgroupsPath(cgroupsPathList []string) error {
	if len(cgroupsPathList) == 0 {
		ccLog.Info("Cgroups files not removed because cgroupsPath was empty")
		return nil
	}

	for _, cgroupsPath := range cgroupsPathList {
		if err := os.RemoveAll(cgroupsPath); err != nil {
			return err
		}
	}

	return nil
}
<|endoftext|>


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

package ggstat

import (
	"github.com/aclements/go-gg/generic"
	"github.com/aclements/go-gg/table"
	"github.com/aclements/go-moremath/fit"
	"github.com/aclements/go-moremath/vec"
)

// LeastSquares constructs a least squares polynomial regression for
// the data (X, Y).
//
// X and Y are required. All other fields have reasonable default zero
// values.
//
// The result of LeastSquares has two columns in addition to constant
// columns from the input:
//
// - Column X is the points at which the fit function is sampled.
//
// - Column Y is the result of the fit function.
//
// TODO: Confidence internals/bootstrap distributions?
type LeastSquares struct {
	// X and Y are the names of the columns to use for X and Y
	// values of data points, respectively.
	X, Y string

	// N is the number of points to sample the regression at. If N
	// is 0, a reasonable default is used.
	N int

	// Widen sets the domain of the returned LOESS sample points
	// to Widen times the span of the data. If Widen is 0, it is
	// treated as 1.1 (that is, widen the domain by 10%, or 5% on
	// the left and 5% on the right).
	//
	// TODO: Have a way to specify a specific range?
	Widen float64

	// SplitGroups indicates that each group in the table should
	// have separate bounds based on the data in that group alone.
	// The default, false, indicates that the bounds should be
	// based on all of the data in the table combined. This makes
	// it possible to stack LOESS fits and easier to compare them
	// across groups.
	SplitGroups bool

	// Degree specifies the degree of the fit polynomial. If it is
	// 0, it is treated as 1.
	Degree int
}

func (s LeastSquares) F(g table.Grouping) table.Grouping {
	if s.Degree <= 0 {
		s.Degree = 1
	}
	if s.Degree == 1 && s.N == 0 {
		// No point in evaluating a line at a ton of points.
		//
		// TODO: If we're on a non-linear scale, we *do* want
		// lots of intermediate points (unless LayerPaths
		// curves its connections).
		s.N = 2
	}

	evals := evalPoints(g, s.X, s.N, s.Widen, s.SplitGroups)

	var xs, ys []float64
	return table.MapTables(func(gid table.GroupID, t *table.Table) *table.Table {
		// TODO: We potentially convert each X column twice,
		// since evalPoints also has to convert them.
		generic.ConvertSlice(&xs, t.MustColumn(s.X))
		generic.ConvertSlice(&ys, t.MustColumn(s.Y))
		eval := evals[gid]

		r := fit.PolynomialRegression(xs, ys, nil, s.Degree)
		nt := new(table.Table).Add(s.X, eval).Add(s.Y, vec.Map(r.F, eval))
		return preserveConsts(nt, t)
	}, g)
}
<commit_msg>ggstat: don't short-circuit linear regressions<commit_after>// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package ggstat

import (
	"github.com/aclements/go-gg/generic"
	"github.com/aclements/go-gg/table"
	"github.com/aclements/go-moremath/fit"
	"github.com/aclements/go-moremath/vec"
)

// LeastSquares constructs a least squares polynomial regression for
// the data (X, Y).
//
// X and Y are required. All other fields have reasonable default zero
// values.
//
// The result of LeastSquares has two columns in addition to constant
// columns from the input:
//
// - Column X is the points at which the fit function is sampled.
//
// - Column Y is the result of the fit function.
//
// TODO: Confidence internals/bootstrap distributions?
type LeastSquares struct {
	// X and Y are the names of the columns to use for X and Y
	// values of data points, respectively.
	X, Y string

	// N is the number of points to sample the regression at. If N
	// is 0, a reasonable default is used.
	N int

	// Widen sets the domain of the returned LOESS sample points
	// to Widen times the span of the data. If Widen is 0, it is
	// treated as 1.1 (that is, widen the domain by 10%, or 5% on
	// the left and 5% on the right).
	//
	// TODO: Have a way to specify a specific range?
	Widen float64

	// SplitGroups indicates that each group in the table should
	// have separate bounds based on the data in that group alone.
	// The default, false, indicates that the bounds should be
	// based on all of the data in the table combined. This makes
	// it possible to stack LOESS fits and easier to compare them
	// across groups.
	SplitGroups bool

	// Degree specifies the degree of the fit polynomial. If it is
	// 0, it is treated as 1.
	Degree int
}

func (s LeastSquares) F(g table.Grouping) table.Grouping {
	if s.Degree <= 0 {
		s.Degree = 1
	}

	evals := evalPoints(g, s.X, s.N, s.Widen, s.SplitGroups)

	var xs, ys []float64
	return table.MapTables(func(gid table.GroupID, t *table.Table) *table.Table {
		// TODO: We potentially convert each X column twice,
		// since evalPoints also has to convert them.
		generic.ConvertSlice(&xs, t.MustColumn(s.X))
		generic.ConvertSlice(&ys, t.MustColumn(s.Y))
		eval := evals[gid]

		r := fit.PolynomialRegression(xs, ys, nil, s.Degree)
		nt := new(table.Table).Add(s.X, eval).Add(s.Y, vec.Map(r.F, eval))
		return preserveConsts(nt, t)
	}, g)
}
<|endoftext|>