<commit_before>//
// Copyright 2021, Sander van Harmelen
//
// 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 gitlab

import (
	"fmt"
	"net/http"
	"reflect"
	"testing"
	"time"
)

func TestListBillableGroupMembers(t *testing.T) {
	mux, server, client := setup(t)
	defer teardown(server)

	mux.HandleFunc("/api/v4/groups/1/billable_members",
		func(w http.ResponseWriter, r *http.Request) {
			testMethod(t, r, http.MethodGet)
			fmt.Fprint(w, `[{"id":1,"username":"ray","name":"Raymond","state":"active","avatar_url":"https://foo.bar/mypic","web_url":"http://192.168.1.8:3000/root","last_activity_on":"2021-01-27"}]`)
		})

	billableMembers, _, err := client.Groups.ListBillableGroupMembers(1, &ListBillableGroupMembersOptions{})
	if err != nil {
		t.Errorf("Groups.ListBillableGroupMembers returned error: %v", err)
	}

	testTime := ISOTime{}
	err = testTime.UnmarshalJSON([]byte(`"2021-01-27"`))
	if err != nil {
		t.Errorf("Could not unmarshal date string to ISOTime: %v", err)
	}
	want := []*BillableGroupMember{{ID: 1, Username: "ray", Name: "Raymond", State: "active", AvatarURL: "https://foo.bar/mypic", WebURL: "http://192.168.1.8:3000/root", LastActivityOn: testTime}}
	if !reflect.DeepEqual(want, billableMembers) {
		t.Errorf("Groups.ListBillableGroupMembers returned %+v, want %+v", billableMembers, want)
	}
}

func TestListGroupMembersWithoutSAML(t *testing.T) {
	mux, server, client := setup(t)
	defer teardown(server)

	mux.HandleFunc("/api/v4/groups/1/members",
		func(w http.ResponseWriter, r *http.Request) {
			testMethod(t, r, http.MethodGet)
			fmt.Fprint(w, `[{"id": 1,"username": "raymond_smith","name": "Raymond Smith","state": "active","avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon","web_url": "http://192.168.1.8:3000/root","created_at": "2012-10-21T14:13:35Z","expires_at": "2012-10-22T14:13:35Z","access_level": 30,"group_saml_identity": null}]`)
		})

	members, _, err := client.Groups.ListGroupMembers(1, &ListGroupMembersOptions{})
	if err != nil {
		t.Errorf("Groups.ListGroupMembers returned error: %v", err)
	}

	create_at, _ := time.Parse(time.RFC3339, "2012-10-21T14:13:35Z")
	expires_at, _ := time.Parse(time.RFC3339, "2012-10-22T14:13:35Z")
	want := []*GroupMember{{ID: 1, Username: "raymond_smith", Name: "Raymond Smith", State: "active", AvatarURL: "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon", WebURL: "http://192.168.1.8:3000/root", CreatedAt: &create_at, ExpiresAt: &expires_at, AccessLevel: 30, GroupSAMLIdentity: nil}}
	if !reflect.DeepEqual(want, members) {
		t.Errorf("Groups.ListBillableGroupMembers returned %+v, want %+v", members[0], want[0])
	}
}

func TestListGroupMembersWithSAML(t *testing.T) {
	mux, server, client := setup(t)
	defer teardown(server)

	mux.HandleFunc("/api/v4/groups/1/members",
		func(w http.ResponseWriter, r *http.Request) {
			testMethod(t, r, http.MethodGet)
			fmt.Fprint(w, `[{"id": 2,"username": "john_doe","name": "John Doe","state": "active","avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon","web_url": "http://192.168.1.8:3000/root","created_at": "2012-10-21T14:13:35Z","expires_at": "2012-10-22T14:13:35Z","access_level": 30,"group_saml_identity": {"extern_uid":"ABC-1234567890","provider": "group_saml","saml_provider_id": 10}}]`)
		})

	members, _, err := client.Groups.ListGroupMembers(1, &ListGroupMembersOptions{})
	if err != nil {
		t.Errorf("Groups.ListGroupMembers returned error: %v", err)
	}

	create_at, _ := time.Parse(time.RFC3339, "2012-10-21T14:13:35Z")
	expires_at, _ := time.Parse(time.RFC3339, "2012-10-22T14:13:35Z")
	want := []*GroupMember{{ID: 2, Username: "john_doe", Name: "John Doe", State: "active", AvatarURL: "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon", WebURL: "http://192.168.1.8:3000/root", CreatedAt: &create_at, ExpiresAt: &expires_at, AccessLevel: 30, GroupSAMLIdentity: &GroupMemberSAMLIdentity{ExternUID: "ABC-1234567890", Provider: "group_saml", SAMLProviderID: 10}}}
	if !reflect.DeepEqual(want, members) {
		t.Errorf("Groups.ListBillableGroupMembers returned %+v, want %+v", members[0], want[0])
	}
}
<commit_msg>Change var names in tests to fix lint error<commit_after>//
// Copyright 2021, Sander van Harmelen
//
// 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 gitlab

import (
	"fmt"
	"net/http"
	"reflect"
	"testing"
	"time"
)

func TestListBillableGroupMembers(t *testing.T) {
	mux, server, client := setup(t)
	defer teardown(server)

	mux.HandleFunc("/api/v4/groups/1/billable_members",
		func(w http.ResponseWriter, r *http.Request) {
			testMethod(t, r, http.MethodGet)
			fmt.Fprint(w, `[{"id":1,"username":"ray","name":"Raymond","state":"active","avatar_url":"https://foo.bar/mypic","web_url":"http://192.168.1.8:3000/root","last_activity_on":"2021-01-27"}]`)
		})

	billableMembers, _, err := client.Groups.ListBillableGroupMembers(1, &ListBillableGroupMembersOptions{})
	if err != nil {
		t.Errorf("Groups.ListBillableGroupMembers returned error: %v", err)
	}

	testTime := ISOTime{}
	err = testTime.UnmarshalJSON([]byte(`"2021-01-27"`))
	if err != nil {
		t.Errorf("Could not unmarshal date string to ISOTime: %v", err)
	}
	want := []*BillableGroupMember{{ID: 1, Username: "ray", Name: "Raymond", State: "active", AvatarURL: "https://foo.bar/mypic", WebURL: "http://192.168.1.8:3000/root", LastActivityOn: testTime}}
	if !reflect.DeepEqual(want, billableMembers) {
		t.Errorf("Groups.ListBillableGroupMembers returned %+v, want %+v", billableMembers, want)
	}
}

func TestListGroupMembersWithoutSAML(t *testing.T) {
	mux, server, client := setup(t)
	defer teardown(server)

	mux.HandleFunc("/api/v4/groups/1/members",
		func(w http.ResponseWriter, r *http.Request) {
			testMethod(t, r, http.MethodGet)
			fmt.Fprint(w, `[{"id": 1,"username": "raymond_smith","name": "Raymond Smith","state": "active","avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon","web_url": "http://192.168.1.8:3000/root","created_at": "2012-10-21T14:13:35Z","expires_at": "2012-10-22T14:13:35Z","access_level": 30,"group_saml_identity": null}]`)
		})

	members, _, err := client.Groups.ListGroupMembers(1, &ListGroupMembersOptions{})
	if err != nil {
		t.Errorf("Groups.ListGroupMembers returned error: %v", err)
	}

	createdAt, _ := time.Parse(time.RFC3339, "2012-10-21T14:13:35Z")
	expiresAt, _ := time.Parse(time.RFC3339, "2012-10-22T14:13:35Z")
	want := []*GroupMember{{ID: 1, Username: "raymond_smith", Name: "Raymond Smith", State: "active", AvatarURL: "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon", WebURL: "http://192.168.1.8:3000/root", CreatedAt: &createdAt, ExpiresAt: &expiresAt, AccessLevel: 30, GroupSAMLIdentity: nil}}
	if !reflect.DeepEqual(want, members) {
		t.Errorf("Groups.ListBillableGroupMembers returned %+v, want %+v", members[0], want[0])
	}
}

func TestListGroupMembersWithSAML(t *testing.T) {
	mux, server, client := setup(t)
	defer teardown(server)

	mux.HandleFunc("/api/v4/groups/1/members",
		func(w http.ResponseWriter, r *http.Request) {
			testMethod(t, r, http.MethodGet)
			fmt.Fprint(w, `[{"id": 2,"username": "john_doe","name": "John Doe","state": "active","avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon","web_url": "http://192.168.1.8:3000/root","created_at": "2012-10-21T14:13:35Z","expires_at": "2012-10-22T14:13:35Z","access_level": 30,"group_saml_identity": {"extern_uid":"ABC-1234567890","provider": "group_saml","saml_provider_id": 10}}]`)
		})

	members, _, err := client.Groups.ListGroupMembers(1, &ListGroupMembersOptions{})
	if err != nil {
		t.Errorf("Groups.ListGroupMembers returned error: %v", err)
	}

	createdAt, _ := time.Parse(time.RFC3339, "2012-10-21T14:13:35Z")
	expiresAt, _ := time.Parse(time.RFC3339, "2012-10-22T14:13:35Z")
	want := []*GroupMember{{ID: 2, Username: "john_doe", Name: "John Doe", State: "active", AvatarURL: "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon", WebURL: "http://192.168.1.8:3000/root", CreatedAt: &createdAt, ExpiresAt: &expiresAt, AccessLevel: 30, GroupSAMLIdentity: &GroupMemberSAMLIdentity{ExternUID: "ABC-1234567890", Provider: "group_saml", SAMLProviderID: 10}}}
	if !reflect.DeepEqual(want, members) {
		t.Errorf("Groups.ListBillableGroupMembers returned %+v, want %+v", members[0], want[0])
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"

	"github.com/citadel/citadel"
	"github.com/samalba/dockerclient"
)

var (
	configPath     string
	config         *Config
	clusterManager *citadel.ClusterManager

	logger = log.New(os.Stderr, "[bastion] ", log.LstdFlags)
)

func init() {
	flag.StringVar(&configPath, "conf", "", "config file")
	flag.Parse()
}

func receive(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "POST":
		var container citadel.Container
		if err := json.NewDecoder(r.Body).Decode(&container); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		if err := runContainer(&container); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		w.WriteHeader(http.StatusCreated)
	default:
		w.WriteHeader(http.StatusNotFound)
	}
}

func runContainer(container *citadel.Container) error {
	docker, err := clusterManager.ScheduleContainer(container)
	if err != nil {
		return err
	}

	logger.Printf("using host %s (%s)\n", docker.ID, docker.Addr)

	// TODO: error check on run instead of pulling every time?
	if err := docker.Client.PullImage(container.Image, ""); err != nil {
		return err
	}

	// format env
	env := []string{}
	for k, v := range container.Environment {
		env = append(env, fmt.Sprintf("%s=%s", k, v))
	}

	containerConfig := &dockerclient.ContainerConfig{
		Hostname:   container.Hostname,
		Domainname: container.Domainname,
		Image:      container.Image,
		Memory:     int(container.Memory) * 1048576,
		Env:        env,
	}

	// TODO: allow to be customized?
	hostConfig := &dockerclient.HostConfig{
		PublishAllPorts: true,
	}

	containerId, err := docker.Client.CreateContainer(containerConfig, container.Name)
	if err != nil {
		return err
	}

	if err := docker.Client.StartContainer(containerId, hostConfig); err != nil {
		return err
	}

	logger.Printf("launched %s (%s) on %s\n", container.Name, containerId[:5], docker.ID)

	return nil
}

func main() {
	if err := loadConfig(); err != nil {
		logger.Fatal(err)
	}

	tlsConfig, err := getTLSConfig()
	if err != nil {
		logger.Fatal(err)
	}

	for _, d := range config.Dockers {
		if err := setDockerClient(d, tlsConfig); err != nil {
			logger.Fatal(err)
		}
	}

	clusterManager = citadel.NewClusterManager(config.Dockers, logger)
	clusterManager.RegisterScheduler("service", &citadel.LabelScheduler{})

	http.HandleFunc("/", receive)

	logger.Printf("bastion listening on %s\n", config.ListenAddr)
	if err := http.ListenAndServe(config.ListenAddr, nil); err != nil {
		logger.Fatal(err)
	}
}
<commit_msg>Use gorilla mux instead of switch<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"

	"github.com/citadel/citadel"
	"github.com/gorilla/mux"
	"github.com/samalba/dockerclient"
)

var (
	configPath     string
	config         *Config
	clusterManager *citadel.ClusterManager

	logger = log.New(os.Stderr, "[bastion] ", log.LstdFlags)
)

func init() {
	flag.StringVar(&configPath, "conf", "", "config file")
	flag.Parse()
}

func receive(w http.ResponseWriter, r *http.Request) {
	var container *citadel.Container
	if err := json.NewDecoder(r.Body).Decode(&container); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if err := runContainer(container); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.WriteHeader(http.StatusCreated)
}

func runContainer(container *citadel.Container) error {
	docker, err := clusterManager.ScheduleContainer(container)
	if err != nil {
		return err
	}

	logger.Printf("using host %s (%s)\n", docker.ID, docker.Addr)

	// TODO: error check on run instead of pulling every time?
	if err := docker.Client.PullImage(container.Image, ""); err != nil {
		return err
	}

	// format env
	env := []string{}
	for k, v := range container.Environment {
		env = append(env, fmt.Sprintf("%s=%s", k, v))
	}

	containerConfig := &dockerclient.ContainerConfig{
		Hostname:   container.Hostname,
		Domainname: container.Domainname,
		Image:      container.Image,
		Memory:     int(container.Memory) * 1048576,
		Env:        env,
	}

	// TODO: allow to be customized?
	hostConfig := &dockerclient.HostConfig{
		PublishAllPorts: true,
	}

	containerId, err := docker.Client.CreateContainer(containerConfig, container.Name)
	if err != nil {
		return err
	}

	if err := docker.Client.StartContainer(containerId, hostConfig); err != nil {
		return err
	}

	logger.Printf("launched %s (%s) on %s\n", container.Name, containerId[:5], docker.ID)

	return nil
}

func main() {
	if err := loadConfig(); err != nil {
		logger.Fatal(err)
	}

	tlsConfig, err := getTLSConfig()
	if err != nil {
		logger.Fatal(err)
	}

	for _, d := range config.Dockers {
		if err := setDockerClient(d, tlsConfig); err != nil {
			logger.Fatal(err)
		}
	}

	clusterManager = citadel.NewClusterManager(config.Dockers, logger)
	clusterManager.RegisterScheduler("service", &citadel.LabelScheduler{})

	r := mux.NewRouter()
	r.HandleFunc("/", receive).Methods("POST")

	logger.Printf("bastion listening on %s\n", config.ListenAddr)
	if err := http.ListenAndServe(config.ListenAddr, r); err != nil {
		logger.Fatal(err)
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 PingCAP, Inc.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

package types

import (
	"github.com/pingcap/check"
	"github.com/pingcap/tidb/mysql"
)

var _ = check.Suite(&testFieldTypeSuite{})

type testFieldTypeSuite struct {
}

func (s *testFieldTypeSuite) TestFieldType(c *check.C) {
	ft := NewFieldType(mysql.TypeDuration)
	c.Assert(ft.Flen, check.Equals, UnspecifiedLength)
	c.Assert(ft.Decimal, check.Equals, UnspecifiedLength)
	ft.Decimal = 5
	c.Assert(ft.String(), check.Equals, "time(5)")

	ft.Tp = mysql.TypeLong
	ft.Flag |= mysql.UnsignedFlag | mysql.ZerofillFlag
	c.Assert(ft.String(), check.Equals, "int(5) UNSIGNED ZEROFILL")

	ft = NewFieldType(mysql.TypeFloat)
	ft.Flen = 10
	ft.Decimal = 3
	c.Assert(ft.String(), check.Equals, "float(10,3)")
	ft = NewFieldType(mysql.TypeFloat)
	ft.Flen = 10
	ft.Decimal = -1
	c.Assert(ft.String(), check.Equals, "float")

	ft = NewFieldType(mysql.TypeDouble)
	ft.Flen = 10
	ft.Decimal = 3
	c.Assert(ft.String(), check.Equals, "double(10,3)")
	ft = NewFieldType(mysql.TypeDouble)
	ft.Flen = 10
	ft.Decimal = -1
	c.Assert(ft.String(), check.Equals, "double")

	ft = NewFieldType(mysql.TypeBlob)
	ft.Flen = 10
	ft.Charset = "UTF8"
	ft.Collate = "UTF8_UNICODE_GI"
	c.Assert(ft.String(), check.Equals, "text(10) CHARACTER SET UTF8 COLLATE UTF8_UNICODE_GI")

	ft = NewFieldType(mysql.TypeVarchar)
	ft.Flen = 10
	ft.Flag |= mysql.BinaryFlag
	c.Assert(ft.String(), check.Equals, "varchar(10) BINARY")

	ft = NewFieldType(mysql.TypeEnum)
	ft.Elems = []string{"a", "b"}
	c.Assert(ft.String(), check.Equals, "enum('a','b')")

	ft = NewFieldType(mysql.TypeEnum)
	ft.Elems = []string{"'a'", "'b'"}
	c.Assert(ft.String(), check.Equals, "enum('''a''','''b''')")

	ft = NewFieldType(mysql.TypeSet)
	ft.Elems = []string{"a", "b"}
	c.Assert(ft.String(), check.Equals, "set('a','b')")

	ft = NewFieldType(mysql.TypeSet)
	ft.Elems = []string{"'a'", "'b'"}
	c.Assert(ft.String(), check.Equals, "set('''a''','''b''')")

	ft = NewFieldType(mysql.TypeTimestamp)
	ft.Flen = 8
	ft.Decimal = 2
	c.Assert(ft.String(), check.Equals, "timestamp(2)")
	ft = NewFieldType(mysql.TypeTimestamp)
	ft.Flen = 8
	ft.Decimal = 0
	c.Assert(ft.String(), check.Equals, "timestamp")

	ft = NewFieldType(mysql.TypeDatetime)
	ft.Flen = 8
	ft.Decimal = 2
	c.Assert(ft.String(), check.Equals, "datetime(2)")
	ft = NewFieldType(mysql.TypeDatetime)
	ft.Flen = 8
	ft.Decimal = 0
	c.Assert(ft.String(), check.Equals, "datetime")
	ft = NewFieldType(mysql.TypeDate)
	ft.Flen = 8
	ft.Decimal = 2
	c.Assert(ft.String(), check.Equals, "date(2)")
	ft = NewFieldType(mysql.TypeDate)
	ft.Flen = 8
	ft.Decimal = 0
	c.Assert(ft.String(), check.Equals, "date")
}
<commit_msg>types: Add unit tests<commit_after>// Copyright 2015 PingCAP, Inc.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

package types

import (
	"github.com/pingcap/check"
	"github.com/pingcap/tidb/mysql"
)

var _ = check.Suite(&testFieldTypeSuite{})

type testFieldTypeSuite struct {
}

func (s *testFieldTypeSuite) TestFieldType(c *check.C) {
	ft := NewFieldType(mysql.TypeDuration)
	c.Assert(ft.Flen, check.Equals, UnspecifiedLength)
	c.Assert(ft.Decimal, check.Equals, UnspecifiedLength)
	ft.Decimal = 5
	c.Assert(ft.String(), check.Equals, "time(5)")

	ft.Tp = mysql.TypeLong
	ft.Flag |= mysql.UnsignedFlag | mysql.ZerofillFlag
	c.Assert(ft.String(), check.Equals, "int(5) UNSIGNED ZEROFILL")

	ft = NewFieldType(mysql.TypeFloat)
	ft.Flen = 10
	ft.Decimal = 3
	c.Assert(ft.String(), check.Equals, "float(10,3)")
	ft = NewFieldType(mysql.TypeFloat)
	ft.Flen = 10
	ft.Decimal = -1
	c.Assert(ft.String(), check.Equals, "float")

	ft = NewFieldType(mysql.TypeDouble)
	ft.Flen = 10
	ft.Decimal = 3
	c.Assert(ft.String(), check.Equals, "double(10,3)")
	ft = NewFieldType(mysql.TypeDouble)
	ft.Flen = 10
	ft.Decimal = -1
	c.Assert(ft.String(), check.Equals, "double")

	ft = NewFieldType(mysql.TypeBlob)
	ft.Flen = 10
	ft.Charset = "UTF8"
	ft.Collate = "UTF8_UNICODE_GI"
	c.Assert(ft.String(), check.Equals, "text(10) CHARACTER SET UTF8 COLLATE UTF8_UNICODE_GI")

	ft = NewFieldType(mysql.TypeVarchar)
	ft.Flen = 10
	ft.Flag |= mysql.BinaryFlag
	c.Assert(ft.String(), check.Equals, "varchar(10) BINARY")

	ft = NewFieldType(mysql.TypeEnum)
	ft.Elems = []string{"a", "b"}
	c.Assert(ft.String(), check.Equals, "enum('a','b')")

	ft = NewFieldType(mysql.TypeEnum)
	ft.Elems = []string{"'a'", "'b'"}
	c.Assert(ft.String(), check.Equals, "enum('''a''','''b''')")

	ft = NewFieldType(mysql.TypeSet)
	ft.Elems = []string{"a", "b"}
	c.Assert(ft.String(), check.Equals, "set('a','b')")

	ft = NewFieldType(mysql.TypeSet)
	ft.Elems = []string{"'a'", "'b'"}
	c.Assert(ft.String(), check.Equals, "set('''a''','''b''')")

	ft = NewFieldType(mysql.TypeTimestamp)
	ft.Flen = 8
	ft.Decimal = 2
	c.Assert(ft.String(), check.Equals, "timestamp(2)")
	ft = NewFieldType(mysql.TypeTimestamp)
	ft.Flen = 8
	ft.Decimal = 0
	c.Assert(ft.String(), check.Equals, "timestamp")

	ft = NewFieldType(mysql.TypeDatetime)
	ft.Flen = 8
	ft.Decimal = 2
	c.Assert(ft.String(), check.Equals, "datetime(2)")
	ft = NewFieldType(mysql.TypeDatetime)
	ft.Flen = 8
	ft.Decimal = 0
	c.Assert(ft.String(), check.Equals, "datetime")
	ft = NewFieldType(mysql.TypeDate)
	ft.Flen = 8
	ft.Decimal = 2
	c.Assert(ft.String(), check.Equals, "date(2)")
	ft = NewFieldType(mysql.TypeDate)
	ft.Flen = 8
	ft.Decimal = 0
	c.Assert(ft.String(), check.Equals, "date")
}

func (s *testFieldTypeSuite) TestDataItem(c *check.C) {
	ft := NewFieldType(mysql.TypeBlob)
	d := &DataItem{
		Type: ft,
	}
	c.Assert(RawData(d), check.IsNil)
	c.Assert(IsNil(d), check.IsTrue)

	d.Data = "string"
	c.Assert(RawData(d), check.Equals, "string")
	c.Assert(IsNil(d), check.IsFalse)
}
<|endoftext|>


<commit_before>package schema

import (
	"strings"

	"github.com/acsellers/inflections"
	"github.com/drone/sqlgen/parse"
)

func Load(tree *parse.Node) *Table {
	table := new(Table)

	// local map of indexes, used for quick
	// lookups and de-duping.
	indexs := map[string]*Index{}

	// pluralizes the table name and then
	// formats in snake case.
	table.Name = inflections.Underscore(tree.Type)
	table.Name = inflections.Pluralize(table.Name)

	// each edge node in the tree is a column
	// in the table. Convert each edge node to
	// a Field structure.
	for _, node := range tree.Edges() {

		field := new(Field)

		// Lookup the SQL column type
		// TODO: move this to a function
		t, ok := parse.Types[node.Type]
		if ok {
			tt, ok := types[t]
			if !ok {
				tt = BLOB
			}
			field.Type = tt
		} else {
			field.Type = BLOB
		}

		// substitute tag variables
		if node.Tags != nil {

			if node.Tags.Skip {
				continue
			}

			field.Auto = node.Tags.Auto
			field.Primary = node.Tags.Primary
			field.Size = node.Tags.Size

			if node.Tags.Primary {
				table.Primary = append(table.Primary, field)
			}

			if node.Tags.Index != "" {
				index, ok := indexs[node.Tags.Index]
				if !ok {
					index = new(Index)
					index.Name = node.Tags.Index
					indexs[index.Name] = index
				}
				index.Fields = append(index.Fields, field)
			}

			if node.Tags.Unique != "" {
				index, ok := indexs[node.Tags.Index]
				if !ok {
					index = new(Index)
					index.Name = node.Tags.Unique
					index.Unique = true
					indexs[index.Name] = index
					table.Index = append(table.Index, index)
				}
				index.Fields = append(index.Fields, field)
			}
		}

		// get the full path name
		path := node.Path()
		var parts []string
		for _, part := range path {
			parts = append(parts, part.Name)
		}
		field.Name = strings.Join(parts, "_")
		field.Name = inflections.Underscore(field.Name)

		table.Fields = append(table.Fields, field)
	}

	return table
}

// convert Go types to SQL types.
var types = map[uint8]int{
	parse.Bool:       BOOLEAN,
	parse.Int:        INTEGER,
	parse.Int8:       INTEGER,
	parse.Int16:      INTEGER,
	parse.Int32:      INTEGER,
	parse.Int64:      INTEGER,
	parse.Uint:       INTEGER,
	parse.Uint8:      INTEGER,
	parse.Uint16:     INTEGER,
	parse.Uint32:     INTEGER,
	parse.Uint64:     INTEGER,
	parse.Float32:    INTEGER,
	parse.Float64:    INTEGER,
	parse.Complex64:  INTEGER,
	parse.Complex128: INTEGER,
	parse.Interface:  BLOB,
	parse.Bytes:      BLOB,
	parse.String:     VARCHAR,
	parse.Map:        BLOB,
	parse.Slice:      BLOB,
}
<commit_msg>Respect the name: tag value.<commit_after>package schema

import (
	"strings"

	"github.com/acsellers/inflections"
	"github.com/drone/sqlgen/parse"
)

func Load(tree *parse.Node) *Table {
	table := new(Table)

	// local map of indexes, used for quick
	// lookups and de-duping.
	indexs := map[string]*Index{}

	// pluralizes the table name and then
	// formats in snake case.
	table.Name = inflections.Underscore(tree.Type)
	table.Name = inflections.Pluralize(table.Name)

	// each edge node in the tree is a column
	// in the table. Convert each edge node to
	// a Field structure.
	for _, node := range tree.Edges() {

		field := new(Field)

		// Lookup the SQL column type
		// TODO: move this to a function
		t, ok := parse.Types[node.Type]
		if ok {
			tt, ok := types[t]
			if !ok {
				tt = BLOB
			}
			field.Type = tt
		} else {
			field.Type = BLOB
		}

		// substitute tag variables
		if node.Tags != nil {

			if node.Tags.Skip {
				continue
			}

			field.Auto = node.Tags.Auto
			field.Primary = node.Tags.Primary
			field.Size = node.Tags.Size

			if node.Tags.Primary {
				table.Primary = append(table.Primary, field)
			}

			if node.Tags.Index != "" {
				index, ok := indexs[node.Tags.Index]
				if !ok {
					index = new(Index)
					index.Name = node.Tags.Index
					indexs[index.Name] = index
				}
				index.Fields = append(index.Fields, field)
			}

			if node.Tags.Unique != "" {
				index, ok := indexs[node.Tags.Index]
				if !ok {
					index = new(Index)
					index.Name = node.Tags.Unique
					index.Unique = true
					indexs[index.Name] = index
					table.Index = append(table.Index, index)
				}
				index.Fields = append(index.Fields, field)
			}
		}

		// get the full path name
		if node.Tags.Name == "" {
			path := node.Path()
			var parts []string
			for _, part := range path {
				parts = append(parts, part.Name)
			}
			field.Name = strings.Join(parts, "_")
			field.Name = inflections.Underscore(field.Name)
		} else {
			field.Name = node.Tags.Name
		}

		table.Fields = append(table.Fields, field)
	}

	return table
}

// convert Go types to SQL types.
var types = map[uint8]int{
	parse.Bool:       BOOLEAN,
	parse.Int:        INTEGER,
	parse.Int8:       INTEGER,
	parse.Int16:      INTEGER,
	parse.Int32:      INTEGER,
	parse.Int64:      INTEGER,
	parse.Uint:       INTEGER,
	parse.Uint8:      INTEGER,
	parse.Uint16:     INTEGER,
	parse.Uint32:     INTEGER,
	parse.Uint64:     INTEGER,
	parse.Float32:    INTEGER,
	parse.Float64:    INTEGER,
	parse.Complex64:  INTEGER,
	parse.Complex128: INTEGER,
	parse.Interface:  BLOB,
	parse.Bytes:      BLOB,
	parse.String:     VARCHAR,
	parse.Map:        BLOB,
	parse.Slice:      BLOB,
}
<|endoftext|>


<commit_before>package formatter

import (
	"github.com/BluePecker/JwtAuth/dialog/client/formatter/context"
	"github.com/BluePecker/JwtAuth/dialog/server/parameter/jwt/response"
	"bytes"
)

const (
	AddrHeader   = "ADDR"
	TLLHeader    = "TLL"
	DeviceHeader = "DEVICE"
	SingedHeader = "SINGED"

	QuietFormat    = "{{.Singed}}"
	JwtTableFormat = "table {{.Addr}}\t{{.TTL}}\t{{.Device}}\t{{.Singed}}"
)

type (
	JsonWebToken struct {
		context.BaseSubjectContext
		truncate bool
		jwt      response.JsonWebToken
	}

	JsonWebTokenContext struct {
		context.Context
		JsonWebTokens []response.JsonWebToken
	}
)

func (ctx JsonWebTokenContext) Write() {
	switch ctx.Template {
	case context.RawKey:
		if ctx.Quiet {
			ctx.Template = `Singed: {{.Singed}}`
		} else {
			//ctx.Template = `Addr: {{.Addr}}\nTTL: {{.TTL}}\nDevice: {{.Device}}\nSinged: {{.Singed}}\n`
			ctx.Template = `Addr: {{.Addr}}\nDevice: {{.Device}}\nSinged: {{.Singed}}\n`
		}
	case context.TableKey:
		if ctx.Quiet {
			ctx.Template = QuietFormat
		} else {
			ctx.Template = JwtTableFormat
		}
	}

	ctx.Buffer = bytes.NewBufferString("")
	ctx.PreFormat()

	tpl, err := ctx.Parser()
	if err != nil {
		return
	}

	for _, jwt := range ctx.JsonWebTokens {
		jwtCtx := &JsonWebToken{
			truncate: ctx.Truncate,
			jwt:      jwt,
		}
		err = ctx.ContextFormat(tpl, jwtCtx)
		if err != nil {
			return
		}
	}

	ctx.FormFormat(tpl, &JsonWebToken{})
}

func (j *JsonWebToken) Addr() string {
	j.AddHeader(AddrHeader)
	return j.jwt.Addr
}

//func (j *JsonWebToken) TLL() string {
//	j.AddHeader(TLLHeader)
//	return strconv.FormatFloat(j.jwt.TTL, 'f', -1, 64)
//}

func (j *JsonWebToken) Device() string {
	j.AddHeader(DeviceHeader)
	return j.jwt.Device
}

func (j *JsonWebToken) Singed() string {
	j.AddHeader(SingedHeader)
	return j.jwt.Singed
}
<commit_msg>debug<commit_after>package formatter

import (
	"github.com/BluePecker/JwtAuth/dialog/client/formatter/context"
	"github.com/BluePecker/JwtAuth/dialog/server/parameter/jwt/response"
	"bytes"
)

const (
	AddrHeader   = "ADDR"
	TLLHeader    = "TLL"
	DeviceHeader = "DEVICE"
	SingedHeader = "SINGED"

	QuietFormat    = "{{.Singed}}"
	//JwtTableFormat = "table {{.Addr}}\t{{.TTL}}\t{{.Device}}\t{{.Singed}}"
	JwtTableFormat = "table {{.Addr}}\t{{.Device}}\t{{.Singed}}"
)

type (
	JsonWebToken struct {
		context.BaseSubjectContext
		truncate bool
		jwt      response.JsonWebToken
	}

	JsonWebTokenContext struct {
		context.Context
		JsonWebTokens []response.JsonWebToken
	}
)

func (ctx JsonWebTokenContext) Write() {
	switch ctx.Template {
	case context.RawKey:
		if ctx.Quiet {
			ctx.Template = `Singed: {{.Singed}}`
		} else {
			//ctx.Template = `Addr: {{.Addr}}\nTTL: {{.TTL}}\nDevice: {{.Device}}\nSinged: {{.Singed}}\n`
			ctx.Template = `Addr: {{.Addr}}\nDevice: {{.Device}}\nSinged: {{.Singed}}\n`
		}
	case context.TableKey:
		if ctx.Quiet {
			ctx.Template = QuietFormat
		} else {
			ctx.Template = JwtTableFormat
		}
	}

	ctx.Buffer = bytes.NewBufferString("")
	ctx.PreFormat()

	tpl, err := ctx.Parser()
	if err != nil {
		return
	}

	for _, jwt := range ctx.JsonWebTokens {
		jwtCtx := &JsonWebToken{
			truncate: ctx.Truncate,
			jwt:      jwt,
		}
		err = ctx.ContextFormat(tpl, jwtCtx)
		if err != nil {
			return
		}
	}

	ctx.FormFormat(tpl, &JsonWebToken{})
}

func (j *JsonWebToken) Addr() string {
	j.AddHeader(AddrHeader)
	return j.jwt.Addr
}

//func (j *JsonWebToken) TLL() string {
//	j.AddHeader(TLLHeader)
//	return strconv.FormatFloat(j.jwt.TTL, 'f', -1, 64)
//}

func (j *JsonWebToken) Device() string {
	j.AddHeader(DeviceHeader)
	return j.jwt.Device
}

func (j *JsonWebToken) Singed() string {
	j.AddHeader(SingedHeader)
	return j.jwt.Singed
}
<|endoftext|>


<commit_before>package acceptance_test

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net"
	"net/http"
	"os"
	"os/exec"

	"github.com/appc/cni/pkg/types"
	"github.com/cloudfoundry-incubator/ducati-daemon/client"
	"github.com/cloudfoundry-incubator/ducati-daemon/lib/namespace"
	"github.com/cloudfoundry-incubator/ducati-daemon/models"
	"github.com/nu7hatch/gouuid"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gexec"
	"github.com/vishvananda/netlink"    //only linux
	"github.com/vishvananda/netlink/nl" //only linux
)

var _ = Describe("Networks", func() {
	var (
		session     *gexec.Session
		address     string
		networkID   string
		containerID string
		vni         int
		sandboxName string

		sandboxRepo        namespace.Repository
		containerNamespace namespace.Namespace
	)

	BeforeEach(func() {
		address = fmt.Sprintf("127.0.0.1:%d", 4001+GinkgoParallelNode())
		sandboxRepoDir, err := ioutil.TempDir("", "sandbox")
		Expect(err).NotTo(HaveOccurred())

		sandboxRepo, err = namespace.NewRepository(sandboxRepoDir)
		Expect(err).NotTo(HaveOccurred())

		containerRepoDir, err := ioutil.TempDir("", "containers")
		Expect(err).NotTo(HaveOccurred())

		containerRepo, err := namespace.NewRepository(containerRepoDir)
		Expect(err).NotTo(HaveOccurred())

		guid, err := uuid.NewV4()
		Expect(err).NotTo(HaveOccurred())

		containerNamespace, err = containerRepo.Create(guid.String())
		Expect(err).NotTo(HaveOccurred())

		Expect(err).NotTo(HaveOccurred())

		ducatiCmd := exec.Command(
			ducatidPath,
			"-listenAddr", address,
			"-overlayNetwork", "192.168.0.0/16",
			"-localSubnet", "192.168.99.0/24",
			"-databaseURL", testDatabase.URL(),
			"-sandboxRepoDir", sandboxRepoDir,
		)
		session, err = gexec.Start(ducatiCmd, GinkgoWriter, GinkgoWriter)
		Expect(err).NotTo(HaveOccurred())

		networkID = fmt.Sprintf("some-network-id-%x", rand.Int())
		containerID = fmt.Sprintf("some-container-id-%x", rand.Int())
		vni = GinkgoParallelNode() // necessary to avoid test pollution in parallel
		sandboxName = fmt.Sprintf("vni-%d", vni)
	})

	AfterEach(func() {
		session.Interrupt()
		Eventually(session, DEFAULT_TIMEOUT).Should(gexec.Exit(0))
		containerNamespace.Destroy()
	})

	var serverIsAvailable = func() error {
		return VerifyTCPConnection(address)
	}

	It("should boot and gracefully terminate", func() {
		Eventually(serverIsAvailable, DEFAULT_TIMEOUT).Should(Succeed())

		Consistently(session).ShouldNot(gexec.Exit())

		session.Interrupt()
		Eventually(session, DEFAULT_TIMEOUT).Should(gexec.Exit(0))
	})

	Describe("POST and DELETE /networks/:network_id/:container_id", func() {
		var (
			upSpec       models.NetworksSetupContainerPayload
			downSpec     models.NetworksDeleteContainerPayload
			daemonClient *client.DaemonClient
			ipamResult   types.Result
		)

		BeforeEach(func() {
			Eventually(serverIsAvailable).Should(Succeed())

			daemonClient = client.New("http://"+address, http.DefaultClient)

			By("generating config and creating the request")
			ipamResult = types.Result{
				IP4: &types.IPConfig{
					IP: net.IPNet{
						IP:   net.ParseIP("192.168.1.2"),
						Mask: net.CIDRMask(24, 32),
					},
					Gateway: net.ParseIP("192.168.1.1"),
					Routes: []types.Route{{
						Dst: net.IPNet{
							IP:   net.ParseIP("192.168.0.0"),
							Mask: net.CIDRMask(16, 32),
						},
						GW: net.ParseIP("192.168.1.1"),
					}},
				},
			}

			_, destination, err := net.ParseCIDR("10.10.10.0/24")
			Expect(err).NotTo(HaveOccurred())

			ipamResult.IP4.Routes = append(ipamResult.IP4.Routes, types.Route{Dst: *destination})

			upSpec = models.NetworksSetupContainerPayload{
				Args:               "FOO=BAR;ABC=123",
				ContainerNamespace: containerNamespace.Path(),
				InterfaceName:      "vx-eth0",
				VNI:                vni,
				IPAM:               ipamResult,
			}

			downSpec = models.NetworksDeleteContainerPayload{
				InterfaceName:      "vx-eth0",
				ContainerNamespace: containerNamespace.Path(),
				VNI:                vni,
			}

			By("adding the container to a network")
			Expect(daemonClient.ContainerUp(networkID, containerID, upSpec)).To(Succeed())
		})

		AfterEach(func() {
			By("adding the container to a network")
			Expect(daemonClient.ContainerDown(networkID, containerID, downSpec)).To(Succeed())

			By("checking that the sandbox has been cleaned up")
			_, err := sandboxRepo.Get(sandboxName)
			Expect(err).To(MatchError(ContainSubstring("no such file or directory")))

			By("checking that the veth device is no longer in the container")
			err = containerNamespace.Execute(func(_ *os.File) error {
				_, err := netlink.LinkByName("vx-eth0")
				Expect(err).To(MatchError(ContainSubstring("Link not found")))
				return nil
			})
			Expect(err).NotTo(HaveOccurred())
		})

		It("should respond to POST and DELETE /networks/:network_id/:container_id", func() {
			listURL := fmt.Sprintf("http://%s/networks/%s", address, networkID)
			resp, err := http.Get(listURL)
			Expect(err).NotTo(HaveOccurred())
			defer resp.Body.Close()

			Expect(resp.StatusCode).To(Equal(http.StatusOK))

			jsonBytes, err := ioutil.ReadAll(resp.Body)
			Expect(err).NotTo(HaveOccurred())

			var containers []models.Container
			err = json.Unmarshal(jsonBytes, &containers)
			Expect(err).NotTo(HaveOccurred())
			Expect(containers).To(HaveLen(1))
		})

		It("moves a vxlan adapter into the sandbox", func() {
			sandboxNS, err := sandboxRepo.Get(sandboxName)
			Expect(err).NotTo(HaveOccurred())

			sandboxNS.Execute(func(_ *os.File) error {
				link, err := netlink.LinkByName(fmt.Sprintf("vxlan%d", vni))
				Expect(err).NotTo(HaveOccurred())
				vxlan, ok := link.(*netlink.Vxlan)
				Expect(ok).To(BeTrue())

				Expect(vxlan.VxlanId).To(Equal(vni))
				Expect(vxlan.Learning).To(BeTrue())
				Expect(vxlan.Port).To(BeEquivalentTo(nl.Swap16(4789)))
				Expect(vxlan.Proxy).To(BeTrue())
				Expect(vxlan.L2miss).To(BeTrue())
				Expect(vxlan.L3miss).To(BeTrue())
				Expect(vxlan.LinkAttrs.Flags & net.FlagUp).To(Equal(net.FlagUp))

				return nil
			})
		})

		It("creates a vxlan bridge in the sandbox", func() {
			var bridge *netlink.Bridge
			var addrs []netlink.Addr

			sandboxNS, err := sandboxRepo.Get(sandboxName)
			Expect(err).NotTo(HaveOccurred())

			err = sandboxNS.Execute(func(_ *os.File) error {
				link, err := netlink.LinkByName(fmt.Sprintf("vxlanbr%d", vni))
				if err != nil {
					return fmt.Errorf("finding link by name: %s", err)
				}

				var ok bool
				bridge, ok = link.(*netlink.Bridge)
				if !ok {
					return fmt.Errorf("unable to cast link to bridge")
				}

				addrs, err = netlink.AddrList(link, netlink.FAMILY_V4)
				if err != nil {
					return fmt.Errorf("unable to list addrs: %s", err)
				}

				return nil
			})
			Expect(err).NotTo(HaveOccurred())

			Expect(bridge.LinkAttrs.MTU).To(Equal(1450))
			Expect(bridge.LinkAttrs.Flags & net.FlagUp).To(Equal(net.FlagUp))

			Expect(addrs).To(HaveLen(1))
			Expect(addrs[0].IPNet.IP.String()).To(Equal(ipamResult.IP4.Gateway.String()))
		})

		It("creates a veth pair in the container and sandbox namespaces", func() {
			sandboxNS, err := sandboxRepo.Get(sandboxName)
			Expect(err).NotTo(HaveOccurred())

			By("checking that the container has a veth device")
			err = containerNamespace.Execute(func(_ *os.File) error {
				link, err := netlink.LinkByName("vx-eth0")
				Expect(err).NotTo(HaveOccurred())

				bridge, ok := link.(*netlink.Veth)
				Expect(ok).To(BeTrue())
				Expect(bridge.LinkAttrs.MTU).To(Equal(1450))
				Expect(bridge.LinkAttrs.Flags & net.FlagUp).To(Equal(net.FlagUp))

				return nil
			})
			Expect(err).NotTo(HaveOccurred())

			By("checking that the sandbox has a veth device")
			err = sandboxNS.Execute(func(_ *os.File) error {
				link, err := netlink.LinkByName("some-container-")
				Expect(err).NotTo(HaveOccurred())

				bridge, ok := link.(*netlink.Veth)
				Expect(ok).To(BeTrue())
				Expect(bridge.LinkAttrs.MTU).To(Equal(1450))
				Expect(bridge.LinkAttrs.Flags & net.FlagUp).To(Equal(net.FlagUp))

				return nil
			})
			Expect(err).NotTo(HaveOccurred())

		})

		It("should contain the routes", func() {
			err := containerNamespace.Execute(func(_ *os.File) error {
				l, err := netlink.LinkByName("vx-eth0")
				Expect(err).NotTo(HaveOccurred())

				routes, err := netlink.RouteList(l, netlink.FAMILY_V4)
				Expect(err).NotTo(HaveOccurred())
				Expect(routes).To(HaveLen(3))

				var sanitizedRoutes []netlink.Route
				for _, route := range routes {
					sanitizedRoutes = append(sanitizedRoutes, netlink.Route{
						Gw:  route.Gw,
						Dst: route.Dst,
						Src: route.Src,
					})
				}

				_, vxlanNet, err := net.ParseCIDR("192.168.0.0/16")
				Expect(sanitizedRoutes).To(ContainElement(netlink.Route{
					Dst: vxlanNet,
					Gw:  ipamResult.IP4.Gateway.To4(),
				}))

				_, linkLocal, err := net.ParseCIDR("192.168.1.0/24")
				Expect(err).NotTo(HaveOccurred())
				Expect(sanitizedRoutes).To(ContainElement(netlink.Route{
					Dst: linkLocal,
					Src: ipamResult.IP4.IP.IP.To4(),
				}))

				_, dest, err := net.ParseCIDR("10.10.10.0/24")
				Expect(sanitizedRoutes).To(ContainElement(netlink.Route{
					Dst: dest,
					Gw:  ipamResult.IP4.Gateway.To4(),
				}))

				return nil
			})
			Expect(err).NotTo(HaveOccurred())
		})
	})
})
<commit_msg>networks acceptance test uses daemon client for list endpoint<commit_after>package acceptance_test

import (
	"fmt"
	"io/ioutil"
	"math/rand"
	"net"
	"net/http"
	"os"
	"os/exec"

	"github.com/appc/cni/pkg/types"
	"github.com/cloudfoundry-incubator/ducati-daemon/client"
	"github.com/cloudfoundry-incubator/ducati-daemon/lib/namespace"
	"github.com/cloudfoundry-incubator/ducati-daemon/models"
	"github.com/nu7hatch/gouuid"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gexec"
	"github.com/vishvananda/netlink"    //only linux
	"github.com/vishvananda/netlink/nl" //only linux
)

var _ = Describe("Networks", func() {
	var (
		session     *gexec.Session
		address     string
		networkID   string
		containerID string
		vni         int
		sandboxName string

		sandboxRepo        namespace.Repository
		containerNamespace namespace.Namespace
	)

	BeforeEach(func() {
		address = fmt.Sprintf("127.0.0.1:%d", 4001+GinkgoParallelNode())
		sandboxRepoDir, err := ioutil.TempDir("", "sandbox")
		Expect(err).NotTo(HaveOccurred())

		sandboxRepo, err = namespace.NewRepository(sandboxRepoDir)
		Expect(err).NotTo(HaveOccurred())

		containerRepoDir, err := ioutil.TempDir("", "containers")
		Expect(err).NotTo(HaveOccurred())

		containerRepo, err := namespace.NewRepository(containerRepoDir)
		Expect(err).NotTo(HaveOccurred())

		guid, err := uuid.NewV4()
		Expect(err).NotTo(HaveOccurred())

		containerNamespace, err = containerRepo.Create(guid.String())
		Expect(err).NotTo(HaveOccurred())

		Expect(err).NotTo(HaveOccurred())

		ducatiCmd := exec.Command(
			ducatidPath,
			"-listenAddr", address,
			"-overlayNetwork", "192.168.0.0/16",
			"-localSubnet", "192.168.99.0/24",
			"-databaseURL", testDatabase.URL(),
			"-sandboxRepoDir", sandboxRepoDir,
		)
		session, err = gexec.Start(ducatiCmd, GinkgoWriter, GinkgoWriter)
		Expect(err).NotTo(HaveOccurred())

		networkID = fmt.Sprintf("some-network-id-%x", rand.Int())
		containerID = fmt.Sprintf("some-container-id-%x", rand.Int())
		vni = GinkgoParallelNode() // necessary to avoid test pollution in parallel
		sandboxName = fmt.Sprintf("vni-%d", vni)
	})

	AfterEach(func() {
		session.Interrupt()
		Eventually(session, DEFAULT_TIMEOUT).Should(gexec.Exit(0))
		containerNamespace.Destroy()
	})

	var serverIsAvailable = func() error {
		return VerifyTCPConnection(address)
	}

	It("should boot and gracefully terminate", func() {
		Eventually(serverIsAvailable, DEFAULT_TIMEOUT).Should(Succeed())

		Consistently(session).ShouldNot(gexec.Exit())

		session.Interrupt()
		Eventually(session, DEFAULT_TIMEOUT).Should(gexec.Exit(0))
	})

	Describe("POST and DELETE /networks/:network_id/:container_id", func() {
		var (
			upSpec       models.NetworksSetupContainerPayload
			downSpec     models.NetworksDeleteContainerPayload
			daemonClient *client.DaemonClient
			ipamResult   types.Result
		)

		BeforeEach(func() {
			Eventually(serverIsAvailable).Should(Succeed())

			daemonClient = client.New("http://"+address, http.DefaultClient)

			By("generating config and creating the request")
			ipamResult = types.Result{
				IP4: &types.IPConfig{
					IP: net.IPNet{
						IP:   net.ParseIP("192.168.1.2"),
						Mask: net.CIDRMask(24, 32),
					},
					Gateway: net.ParseIP("192.168.1.1"),
					Routes: []types.Route{{
						Dst: net.IPNet{
							IP:   net.ParseIP("192.168.0.0"),
							Mask: net.CIDRMask(16, 32),
						},
						GW: net.ParseIP("192.168.1.1"),
					}},
				},
			}

			_, destination, err := net.ParseCIDR("10.10.10.0/24")
			Expect(err).NotTo(HaveOccurred())

			ipamResult.IP4.Routes = append(ipamResult.IP4.Routes, types.Route{Dst: *destination})

			upSpec = models.NetworksSetupContainerPayload{
				Args:               "FOO=BAR;ABC=123",
				ContainerNamespace: containerNamespace.Path(),
				InterfaceName:      "vx-eth0",
				VNI:                vni,
				IPAM:               ipamResult,
			}

			downSpec = models.NetworksDeleteContainerPayload{
				InterfaceName:      "vx-eth0",
				ContainerNamespace: containerNamespace.Path(),
				VNI:                vni,
			}

			By("adding the container to a network")
			Expect(daemonClient.ContainerUp(networkID, containerID, upSpec)).To(Succeed())
		})

		AfterEach(func() {
			By("adding the container to a network")
			Expect(daemonClient.ContainerDown(networkID, containerID, downSpec)).To(Succeed())

			By("checking that the sandbox has been cleaned up")
			_, err := sandboxRepo.Get(sandboxName)
			Expect(err).To(MatchError(ContainSubstring("no such file or directory")))

			By("checking that the veth device is no longer in the container")
			err = containerNamespace.Execute(func(_ *os.File) error {
				_, err := netlink.LinkByName("vx-eth0")
				Expect(err).To(MatchError(ContainSubstring("Link not found")))
				return nil
			})
			Expect(err).NotTo(HaveOccurred())
		})

		It("should respond to POST and DELETE /networks/:network_id/:container_id", func() {
			containers, err := daemonClient.ListNetworkContainers(networkID)
			Expect(err).NotTo(HaveOccurred())

			Expect(containers).To(HaveLen(1))
		})

		It("moves a vxlan adapter into the sandbox", func() {
			sandboxNS, err := sandboxRepo.Get(sandboxName)
			Expect(err).NotTo(HaveOccurred())

			sandboxNS.Execute(func(_ *os.File) error {
				link, err := netlink.LinkByName(fmt.Sprintf("vxlan%d", vni))
				Expect(err).NotTo(HaveOccurred())
				vxlan, ok := link.(*netlink.Vxlan)
				Expect(ok).To(BeTrue())

				Expect(vxlan.VxlanId).To(Equal(vni))
				Expect(vxlan.Learning).To(BeTrue())
				Expect(vxlan.Port).To(BeEquivalentTo(nl.Swap16(4789)))
				Expect(vxlan.Proxy).To(BeTrue())
				Expect(vxlan.L2miss).To(BeTrue())
				Expect(vxlan.L3miss).To(BeTrue())
				Expect(vxlan.LinkAttrs.Flags & net.FlagUp).To(Equal(net.FlagUp))

				return nil
			})
		})

		It("creates a vxlan bridge in the sandbox", func() {
			var bridge *netlink.Bridge
			var addrs []netlink.Addr

			sandboxNS, err := sandboxRepo.Get(sandboxName)
			Expect(err).NotTo(HaveOccurred())

			err = sandboxNS.Execute(func(_ *os.File) error {
				link, err := netlink.LinkByName(fmt.Sprintf("vxlanbr%d", vni))
				if err != nil {
					return fmt.Errorf("finding link by name: %s", err)
				}

				var ok bool
				bridge, ok = link.(*netlink.Bridge)
				if !ok {
					return fmt.Errorf("unable to cast link to bridge")
				}

				addrs, err = netlink.AddrList(link, netlink.FAMILY_V4)
				if err != nil {
					return fmt.Errorf("unable to list addrs: %s", err)
				}

				return nil
			})
			Expect(err).NotTo(HaveOccurred())

			Expect(bridge.LinkAttrs.MTU).To(Equal(1450))
			Expect(bridge.LinkAttrs.Flags & net.FlagUp).To(Equal(net.FlagUp))

			Expect(addrs).To(HaveLen(1))
			Expect(addrs[0].IPNet.IP.String()).To(Equal(ipamResult.IP4.Gateway.String()))
		})

		It("creates a veth pair in the container and sandbox namespaces", func() {
			sandboxNS, err := sandboxRepo.Get(sandboxName)
			Expect(err).NotTo(HaveOccurred())

			By("checking that the container has a veth device")
			err = containerNamespace.Execute(func(_ *os.File) error {
				link, err := netlink.LinkByName("vx-eth0")
				Expect(err).NotTo(HaveOccurred())

				bridge, ok := link.(*netlink.Veth)
				Expect(ok).To(BeTrue())
				Expect(bridge.LinkAttrs.MTU).To(Equal(1450))
				Expect(bridge.LinkAttrs.Flags & net.FlagUp).To(Equal(net.FlagUp))

				return nil
			})
			Expect(err).NotTo(HaveOccurred())

			By("checking that the sandbox has a veth device")
			err = sandboxNS.Execute(func(_ *os.File) error {
				link, err := netlink.LinkByName("some-container-")
				Expect(err).NotTo(HaveOccurred())

				bridge, ok := link.(*netlink.Veth)
				Expect(ok).To(BeTrue())
				Expect(bridge.LinkAttrs.MTU).To(Equal(1450))
				Expect(bridge.LinkAttrs.Flags & net.FlagUp).To(Equal(net.FlagUp))

				return nil
			})
			Expect(err).NotTo(HaveOccurred())

		})

		It("should contain the routes", func() {
			err := containerNamespace.Execute(func(_ *os.File) error {
				l, err := netlink.LinkByName("vx-eth0")
				Expect(err).NotTo(HaveOccurred())

				routes, err := netlink.RouteList(l, netlink.FAMILY_V4)
				Expect(err).NotTo(HaveOccurred())
				Expect(routes).To(HaveLen(3))

				var sanitizedRoutes []netlink.Route
				for _, route := range routes {
					sanitizedRoutes = append(sanitizedRoutes, netlink.Route{
						Gw:  route.Gw,
						Dst: route.Dst,
						Src: route.Src,
					})
				}

				_, vxlanNet, err := net.ParseCIDR("192.168.0.0/16")
				Expect(sanitizedRoutes).To(ContainElement(netlink.Route{
					Dst: vxlanNet,
					Gw:  ipamResult.IP4.Gateway.To4(),
				}))

				_, linkLocal, err := net.ParseCIDR("192.168.1.0/24")
				Expect(err).NotTo(HaveOccurred())
				Expect(sanitizedRoutes).To(ContainElement(netlink.Route{
					Dst: linkLocal,
					Src: ipamResult.IP4.IP.IP.To4(),
				}))

				_, dest, err := net.ParseCIDR("10.10.10.0/24")
				Expect(sanitizedRoutes).To(ContainElement(netlink.Route{
					Dst: dest,
					Gw:  ipamResult.IP4.Gateway.To4(),
				}))

				return nil
			})
			Expect(err).NotTo(HaveOccurred())
		})
	})
})
<|endoftext|>


<commit_before>package main

// index template
const index = `[[define "index"]]<!doctype html>

[[template "head" . ]]

<ng-include src="'pages/global.html'"></ng-include>

[[template "header" . ]]

[[end]]`

// head items
const head = `[[define "head"]]
<base href="/[[ .base ]]">
<title data-ng-bind="page.title">[[ .title ]]</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="[[ .desc ]]" />
[[if .nsfw -]]
<meta name="rating" content="adult" />
<meta name="rating" content="RTA-5042-1996-1400-1577-RTA" />
[[- end]]
<link rel="stylesheet" href="/assets/prim/[[ .primcss ]]" />
<link rel="stylesheet" href="/assets/styles/[[ .style ]]" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">

[[template "angular" . ]]
[[template "headinclude" . ]]
[[end]]`

// angular config
const angular = `[[define "angular"]][[end]]`

// site header
const header = `[[define "header"]]

                        [[template "navmenuinclude" . ]]
                        [[template "navmenu" . ]]

                <ng-include src="'pages/menus/nav.html'"></ng-include>

                Sign in

                            <ng-include src="'pages/menus/user.html'"></ng-include>

[[end]]`

const navmenu = `[[define "navmenu"]][[ range $ib := .imageboards -]]

[[ $ib.Title ]]

[[- end]][[end]]`
<commit_msg>move stylesheets above js<commit_after>package main

// index template
const index = `[[define "index"]]<!doctype html>

[[template "head" . ]]

<ng-include src="'pages/global.html'"></ng-include>

[[template "header" . ]]

[[end]]`

// head items
const head = `[[define "head"]]
<base href="/[[ .base ]]">
<title data-ng-bind="page.title">[[ .title ]]</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="[[ .desc ]]" />
[[if .nsfw -]]<meta name="rating" content="adult" />
<meta name="rating" content="RTA-5042-1996-1400-1577-RTA" />[[- end]]
<link rel="stylesheet" href="/assets/prim/[[ .primcss ]]" />
<link rel="stylesheet" href="/assets/styles/[[ .style ]]" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">

[[template "angular" . ]]
[[template "headinclude" . ]]
[[end]]`

// angular config
const angular = `[[define "angular"]][[end]]`

// site header
const header = `[[define "header"]]

[[template "navmenuinclude" . ]]
[[template "navmenu" . ]]

<ng-include src="'pages/menus/nav.html'"></ng-include>

Sign in

<ng-include src="'pages/menus/user.html'"></ng-include>

[[end]]`

const navmenu = `[[define "navmenu"]][[ range $ib := .imageboards -]]<li><a target="_self" href="//[[ $ib.Address ]]/">[[ $ib.Title ]]</a></li>[[- end]][[end]]`
<|endoftext|>


<commit_before>package rabbithole

import (
	"encoding/json"
	"net/http"
	"net/url"
)

// Information about backing queue (queue storage engine).
type BackingQueueStatus struct {
	Q1 int `json:"q1"`
	Q2 int `json:"q2"`
	Q3 int `json:"q3"`
	Q4 int `json:"q4"`
	// Total queue length
	Length int64 `json:"len"`
	// Number of pending acks from consumers
	PendingAcks int64 `json:"pending_acks"`
	// Number of messages held in RAM
	RAMMessageCount int64 `json:"ram_msg_count"`
	// Number of outstanding acks held in RAM
	RAMAckCount int64 `json:"ram_ack_count"`
	// Number of persistent messages in the store
	PersistentCount int64 `json:"persistent_count"`
	// Average ingress (inbound) rate, not including messages
	// that straight through to auto-acking consumers.
	AverageIngressRate float64 `json:"avg_ingress_rate"`
	// Average egress (outbound) rate, not including messages
	// that straight through to auto-acking consumers.
	AverageEgressRate float64 `json:"avg_egress_rate"`
	// rate at which unacknowledged message records enter RAM,
	// e.g. because messages are delivered requiring acknowledgement
	AverageAckIngressRate float32 `json:"avg_ack_ingress_rate"`
	// rate at which unacknowledged message records leave RAM,
	// e.g. because acks arrive or unacked messages are paged out
	AverageAckEgressRate float32 `json:"avg_ack_egress_rate"`
}

type OwnerPidDetails struct {
	Name     string `json:"name"`
	PeerPort Port   `json:"peer_port"`
	PeerHost string `json:"peer_host"`
}

type QueueInfo struct {
	// Queue name
	Name string `json:"name"`
	// Virtual host this queue belongs to
	Vhost string `json:"vhost"`
	// Is this queue durable?
	Durable bool `json:"durable"`
	// Is this queue auto-delted?
	AutoDelete bool `json:"auto_delete"`
	// Extra queue arguments
	Arguments map[string]interface{} `json:"arguments"`

	// RabbitMQ node that hosts master for this queue
	Node string `json:"node"`
	// Queue status
	Status string `json:"status"`

	// Total amount of RAM used by this queue
	Memory int64 `json:"memory"`
	// How many consumers this queue has
	Consumers int `json:"consumers"`
	// Utilisation of all the consumers
	ConsumerUtilisation float64 `json:"consumer_utilisation"`
	// If there is an exclusive consumer, its consumer tag
	ExclusiveConsumerTag string `json:"exclusive_consumer_tag"`

	// Policy applied to this queue, if any
	Policy string `json:"policy"`

	// Total bytes of messages in this queues
	MessagesBytes           int64 `json:"message_bytes"`
	MessagesBytesPersistent int64 `json:"message_bytes_persistent"`
	MessagesBytesRAM        int64 `json:"message_bytes_ram"`

	// Total number of messages in this queue
	Messages           int         `json:"messages"`
	MessagesDetails    RateDetails `json:"messages_details"`
	MessagesPersistent int         `json:"messages_persistent"`
	MessagesRAM        int         `json:"messages_ram"`

	// Number of messages ready to be delivered
	MessagesReady        int         `json:"messages_ready"`
	MessagesReadyDetails RateDetails `json:"messages_ready_details"`

	// Number of messages delivered and pending acknowledgements from consumers
	MessagesUnacknowledged        int         `json:"messages_unacknowledged"`
	MessagesUnacknowledgedDetails RateDetails `json:"messages_unacknowledged_details"`

	MessageStats MessageStats `json:"message_stats"`

	OwnerPidDetails OwnerPidDetails `json:"owner_pid_details"`

	BackingQueueStatus BackingQueueStatus `json:"backing_queue_status"`
}

type DetailedQueueInfo QueueInfo

//
// GET /api/queues
//

// [
//   {
//     "owner_pid_details": {
//       "name": "127.0.0.1:46928 -> 127.0.0.1:5672",
//       "peer_port": 46928,
//       "peer_host": "127.0.0.1"
//     },
//     "message_stats": {
//       "publish": 19830,
//       "publish_details": {
//         "rate": 5
//       }
//     },
//     "messages": 15,
//     "messages_details": {
//       "rate": 0
//     },
//     "messages_ready": 15,
//     "messages_ready_details": {
//       "rate": 0
//     },
//     "messages_unacknowledged": 0,
//     "messages_unacknowledged_details": {
//       "rate": 0
//     },
//     "policy": "",
//     "exclusive_consumer_tag": "",
//     "consumers": 0,
//     "memory": 143112,
//     "backing_queue_status": {
//       "q1": 0,
//       "q2": 0,
//       "delta": [
//         "delta",
//         "undefined",
//         0,
//         "undefined"
//       ],
//       "q3": 0,
//       "q4": 15,
//       "len": 15,
//       "pending_acks": 0,
//       "target_ram_count": "infinity",
//       "ram_msg_count": 15,
//       "ram_ack_count": 0,
//       "next_seq_id": 19830,
//       "persistent_count": 0,
//       "avg_ingress_rate": 4.9920127795527,
//       "avg_egress_rate": 4.9920127795527,
//       "avg_ack_ingress_rate": 0,
//       "avg_ack_egress_rate": 0
//     },
//     "status": "running",
//     "name": "amq.gen-QLEaT5Rn_ogbN3O8ZOQt3Q",
//     "vhost": "rabbit\/hole",
//     "durable": false,
//     "auto_delete": false,
//     "arguments": {
//       "x-message-ttl": 5000
//     },
//     "node": "rabbit@marzo"
//   }
// ]

func (c *Client) ListQueues() (rec []QueueInfo, err error) {
	req, err := newGETRequest(c, "queues")
	if err != nil {
		return []QueueInfo{}, err
	}

	if err = executeAndParseRequest(c, req, &rec); err != nil {
		return []QueueInfo{}, err
	}

	return rec, nil
}

//
// GET /api/queues/{vhost}
//

func (c *Client) ListQueuesIn(vhost string) (rec []QueueInfo, err error) {
	req, err := newGETRequest(c, "queues/"+url.QueryEscape(vhost))
	if err != nil {
		return []QueueInfo{}, err
	}

	if err = executeAndParseRequest(c, req, &rec); err != nil {
		return []QueueInfo{}, err
	}

	return rec, nil
}

//
// GET /api/queues/{vhost}/{name}
//

func (c *Client) GetQueue(vhost, queue string) (rec *DetailedQueueInfo, err error) {
	req, err := newGETRequest(c, "queues/"+url.QueryEscape(vhost)+"/"+queue)
	if err != nil {
		return nil, err
	}

	if err = executeAndParseRequest(c, req, &rec); err != nil {
		return nil, err
	}

	return rec, nil
}

//
// PUT /api/exchanges/{vhost}/{exchange}
//

type QueueSettings struct {
	Durable    bool                   `json:"durable"`
	AutoDelete bool                   `json:"auto_delete"`
	Arguments  map[string]interface{} `json:"arguments"`
}

func (c *Client) DeclareQueue(vhost, queue string, info QueueSettings) (res *http.Response, err error) {
	if info.Arguments == nil {
		info.Arguments = make(map[string]interface{})
	}
	body, err := json.Marshal(info)
	if err != nil {
		return nil, err
	}

	req, err := newRequestWithBody(c, "PUT", "queues/"+url.QueryEscape(vhost)+"/"+url.QueryEscape(queue), body)
	if err != nil {
		return nil, err
	}

	res, err = executeRequest(c, req)
	if err != nil {
		return nil, err
	}

	return res, nil
}

//
// DELETE /api/queues/{vhost}/{name}
//

func (c *Client) DeleteQueue(vhost, queue string) (res *http.Response, err error) {
	req, err := newRequestWithBody(c, "DELETE", "queues/"+url.QueryEscape(vhost)+"/"+url.QueryEscape(queue), nil)
	if err != nil {
		return nil, err
	}

	res, err = executeRequest(c, req)
	if err != nil {
		return nil, err
	}

	return res, nil
}

//
// DELETE /api/queues/{vhost}/{name}/contents
//

func (c *Client) PurgeQueue(vhost, queue string) (res *http.Response, err error) {
	req, err := newRequestWithBody(c, "DELETE", "queues/"+url.QueryEscape(vhost)+"/"+url.QueryEscape(queue)+"/contents", nil)
	if err != nil {
		return nil, err
	}

	res, err = executeRequest(c, req)
	if err != nil {
		return nil, err
	}

	return res, nil
}
<commit_msg>Revert "Add ConsumerUtilisation to QueueInfo"<commit_after>package rabbithole

import (
	"encoding/json"
	"net/http"
	"net/url"
)

// Information about backing queue (queue storage engine).
type BackingQueueStatus struct {
	Q1 int `json:"q1"`
	Q2 int `json:"q2"`
	Q3 int `json:"q3"`
	Q4 int `json:"q4"`
	// Total queue length
	Length int64 `json:"len"`
	// Number of pending acks from consumers
	PendingAcks int64 `json:"pending_acks"`
	// Number of messages held in RAM
	RAMMessageCount int64 `json:"ram_msg_count"`
	// Number of outstanding acks held in RAM
	RAMAckCount int64 `json:"ram_ack_count"`
	// Number of persistent messages in the store
	PersistentCount int64 `json:"persistent_count"`
	// Average ingress (inbound) rate, not including messages
	// that straight through to auto-acking consumers.
	AverageIngressRate float64 `json:"avg_ingress_rate"`
	// Average egress (outbound) rate, not including messages
	// that straight through to auto-acking consumers.
	AverageEgressRate float64 `json:"avg_egress_rate"`
	// rate at which unacknowledged message records enter RAM,
	// e.g. because messages are delivered requiring acknowledgement
	AverageAckIngressRate float32 `json:"avg_ack_ingress_rate"`
	// rate at which unacknowledged message records leave RAM,
	// e.g. because acks arrive or unacked messages are paged out
	AverageAckEgressRate float32 `json:"avg_ack_egress_rate"`
}

type OwnerPidDetails struct {
	Name     string `json:"name"`
	PeerPort Port   `json:"peer_port"`
	PeerHost string `json:"peer_host"`
}

type QueueInfo struct {
	// Queue name
	Name string `json:"name"`
	// Virtual host this queue belongs to
	Vhost string `json:"vhost"`
	// Is this queue durable?
	Durable bool `json:"durable"`
	// Is this queue auto-delted?
	AutoDelete bool `json:"auto_delete"`
	// Extra queue arguments
	Arguments map[string]interface{} `json:"arguments"`

	// RabbitMQ node that hosts master for this queue
	Node string `json:"node"`
	// Queue status
	Status string `json:"status"`

	// Total amount of RAM used by this queue
	Memory int64 `json:"memory"`
	// How many consumers this queue has
	Consumers int `json:"consumers"`
	// If there is an exclusive consumer, its consumer tag
	ExclusiveConsumerTag string `json:"exclusive_consumer_tag"`

	// Policy applied to this queue, if any
	Policy string `json:"policy"`

	// Total bytes of messages in this queues
	MessagesBytes           int64 `json:"message_bytes"`
	MessagesBytesPersistent int64 `json:"message_bytes_persistent"`
	MessagesBytesRAM        int64 `json:"message_bytes_ram"`

	// Total number of messages in this queue
	Messages           int         `json:"messages"`
	MessagesDetails    RateDetails `json:"messages_details"`
	MessagesPersistent int         `json:"messages_persistent"`
	MessagesRAM        int         `json:"messages_ram"`

	// Number of messages ready to be delivered
	MessagesReady        int         `json:"messages_ready"`
	MessagesReadyDetails RateDetails `json:"messages_ready_details"`

	// Number of messages delivered and pending acknowledgements from consumers
	MessagesUnacknowledged        int         `json:"messages_unacknowledged"`
	MessagesUnacknowledgedDetails RateDetails `json:"messages_unacknowledged_details"`

	MessageStats MessageStats `json:"message_stats"`

	OwnerPidDetails OwnerPidDetails `json:"owner_pid_details"`

	BackingQueueStatus BackingQueueStatus `json:"backing_queue_status"`
}

type DetailedQueueInfo QueueInfo

//
// GET /api/queues
//

// [
//   {
//     "owner_pid_details": {
//       "name": "127.0.0.1:46928 -> 127.0.0.1:5672",
//       "peer_port": 46928,
//       "peer_host": "127.0.0.1"
//     },
//     "message_stats": {
//       "publish": 19830,
//       "publish_details": {
//         "rate": 5
//       }
//     },
//     "messages": 15,
//     "messages_details": {
//       "rate": 0
//     },
//     "messages_ready": 15,
//     "messages_ready_details": {
//       "rate": 0
//     },
//     "messages_unacknowledged": 0,
//     "messages_unacknowledged_details": {
//       "rate": 0
//     },
//     "policy": "",
//     "exclusive_consumer_tag": "",
//     "consumers": 0,
//     "memory": 143112,
//     "backing_queue_status": {
//       "q1": 0,
//       "q2": 0,
//       "delta": [
//         "delta",
//         "undefined",
//         0,
//         "undefined"
//       ],
//       "q3": 0,
//       "q4": 15,
//       "len": 15,
//       "pending_acks": 0,
//       "target_ram_count": "infinity",
//       "ram_msg_count": 15,
//       "ram_ack_count": 0,
//       "next_seq_id": 19830,
//       "persistent_count": 0,
//       "avg_ingress_rate": 4.9920127795527,
//       "avg_egress_rate": 4.9920127795527,
//       "avg_ack_ingress_rate": 0,
//       "avg_ack_egress_rate": 0
//     },
//     "status": "running",
//     "name": "amq.gen-QLEaT5Rn_ogbN3O8ZOQt3Q",
//     "vhost": "rabbit\/hole",
//     "durable": false,
//     "auto_delete": false,
//     "arguments": {
//       "x-message-ttl": 5000
//     },
//     "node": "rabbit@marzo"
//   }
// ]

func (c *Client) ListQueues() (rec []QueueInfo, err error) {
	req, err := newGETRequest(c, "queues")
	if err != nil {
		return []QueueInfo{}, err
	}

	if err = executeAndParseRequest(c, req, &rec); err != nil {
		return []QueueInfo{}, err
	}

	return rec, nil
}

//
// GET /api/queues/{vhost}
//

func (c *Client) ListQueuesIn(vhost string) (rec []QueueInfo, err error) {
	req, err := newGETRequest(c, "queues/"+url.QueryEscape(vhost))
	if err != nil {
		return []QueueInfo{}, err
	}

	if err = executeAndParseRequest(c, req, &rec); err != nil {
		return []QueueInfo{}, err
	}

	return rec, nil
}

//
// GET /api/queues/{vhost}/{name}
//

func (c *Client) GetQueue(vhost, queue string) (rec *DetailedQueueInfo, err error) {
	req, err := newGETRequest(c, "queues/"+url.QueryEscape(vhost)+"/"+queue)
	if err != nil {
		return nil, err
	}

	if err = executeAndParseRequest(c, req, &rec); err != nil {
		return nil, err
	}

	return rec, nil
}

//
// PUT /api/exchanges/{vhost}/{exchange}
//

type QueueSettings struct {
	Durable    bool                   `json:"durable"`
	AutoDelete bool                   `json:"auto_delete"`
	Arguments  map[string]interface{} `json:"arguments"`
}

func (c *Client) DeclareQueue(vhost, queue string, info QueueSettings) (res *http.Response, err error) {
	if info.Arguments == nil {
		info.Arguments = make(map[string]interface{})
	}
	body, err := json.Marshal(info)
	if err != nil {
		return nil, err
	}

	req, err := newRequestWithBody(c, "PUT", "queues/"+url.QueryEscape(vhost)+"/"+url.QueryEscape(queue), body)
	if err != nil {
		return nil, err
	}

	res, err = executeRequest(c, req)
	if err != nil {
		return nil, err
	}

	return res, nil
}

//
// DELETE /api/queues/{vhost}/{name}
//

func (c *Client) DeleteQueue(vhost, queue string) (res *http.Response, err error) {
	req, err := newRequestWithBody(c, "DELETE", "queues/"+url.QueryEscape(vhost)+"/"+url.QueryEscape(queue), nil)
	if err != nil {
		return nil, err
	}

	res, err = executeRequest(c, req)
	if err != nil {
		return nil, err
	}

	return res, nil
}

//
// DELETE /api/queues/{vhost}/{name}/contents
//

func (c *Client) PurgeQueue(vhost, queue string) (res *http.Response, err error) {
	req, err := newRequestWithBody(c, "DELETE", "queues/"+url.QueryEscape(vhost)+"/"+url.QueryEscape(queue)+"/contents", nil)
	if err != nil {
		return nil, err
	}

	res, err = executeRequest(c, req)
	if err != nil {
		return nil, err
	}

	return res, nil
}
<|endoftext|>


<commit_before>/*
  Package multirender is a middleware for Martini that provides HTML
  templates through multitemplate, it like to imitate and build on the
  render package from martini-contrib.

  package main

  import (
    "github.com/codegangsta/martini"
    "github.com/cooldude/cache"

    // contians the multirender package.
    "github.com/acsellers/multitemplate/martini"
    // import any languages you want to use
    _ "github.com/acsellers/multitemplate/terse"
  )

  func main() {
    app := martini.Classic()
    app.Use(multirender.Renderer())

    app.Get("/", func (mr multirender.Render) {
      mr.HTML(200, "app/index.html", nil)
    })

    app.Get("/admins", func(mr multirender.Render) {
      ctx := mr.NewContext()
      ctx.RenderArgs["Users"] = AdminUsers
      mr.HTML(200, "app/user_list.html", ctx)
    })

    app.Run()
  }

*/
package multirender

import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"html/template"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"github.com/acsellers/multitemplate"
	"github.com/acsellers/multitemplate/helpers"
	"github.com/codegangsta/martini"
)

type Render interface {
	// JSON writes the status code and JSON version of the value to the
	// http.ResponseWriter
	JSON(status int, v interface{})
	// XML writes the status code and XML version of the value to the
	// http.ResponseWriter
	XML(status int, v interface{})
	// HTML render the template given by name, with the status and options
	// given.
	HTML(status int, name string, htmlOpt *Context)
	// Create a Context with default options set
	NewContext() *Context
	// Render the text to the output
	Text(status int, text string)
	// Write the given status to the Response
	Error(status int)
	// Redirect to the location with an optional status, default status is
	// 302.
	Redirect(location string, status ...int)
	// Return the Template by name
	Template() *multitemplate.Template
	// Sets the content type, will also append charset from Options
	SetContentType(string)
}

func (r *renderer) NewContext() *Context {
	return &Context{
		Layout:     r.opt.DefaultLayout,
		Yields:     make(map[string]string),
		blocks:     make(map[string]multitemplate.RenderedBlock),
		RenderArgs: make(map[string]interface{}),
	}
}

type Context struct {
	Status     int
	Layout     string
	NoLayout   bool
	Yields     map[string]string
	blocks     map[string]multitemplate.RenderedBlock
	RenderArgs map[string]interface{}
}

func (c *Context) SetContent(name, content string) {
	if c.blocks == nil {
		c.blocks = make(map[string]multitemplate.RenderedBlock)
	}
	c.blocks[name] = multitemplate.RenderedBlock{
		Content: template.HTML(content),
	}
}

func (c *Context) SetTemplate(blockName, templateName string) {
	if c.Yields == nil {
		c.Yields = make(map[string]string)
	}
	c.Yields[blockName] = templateName
}

func Renderer(opt Options) martini.Handler {
	if opt.Charset == "" {
		opt.Charset = "utf-8"
	}
	mt := multitemplate.New("martini").Funcs(opt.Funcs)
	var err error
	mt = mt.Funcs(helpers.GetHelpers(opt.Helpers...))
	mt, _ = compile(opt, mt)
	return func(w http.ResponseWriter, r *http.Request, c martini.Context) {
		if martini.Env == martini.Dev {
			mt := multitemplate.New("martini").Funcs(opt.Funcs)
			mt = mt.Funcs(helpers.GetHelpers(opt.Helpers...))
			mt, err = compile(opt, mt)
		}
		c.MapTo(&renderer{w, r, mt, opt, err}, (*Render)(nil))
	}
}

type Options struct {
	// Directories to search for template files
	Directories []string
	// Layout to render by default
	DefaultLayout string
	// Helper modules to load from multitemplate helpers
	Helpers []string
	// Additional functions to add
	Funcs template.FuncMap
	// JSON & XML indentation, an empty string disables indentation
	IndentEncoding string
	// Default is set to utf-8
	Charset string
	// Note that you will need to set the delims for each multitemplate
	// language you are using, you cannot set it in this Options struct.
}

func compile(opt Options, mt *multitemplate.Template) (*multitemplate.Template, error) {
	var err error
	for _, dir := range opt.Directories {
		mt.Base = dir
		e := filepath.Walk(dir, func(path string, i os.FileInfo, e error) error {
			if !i.IsDir() && strings.Contains(path, "html") {
				fmt.Println("Compiling file:", path)
				_, err := mt.ParseFiles(path)
				if err == nil {
					fmt.Println("Successfully compiled file")
				}
				return err
			}
			return nil
		})
		if e != nil && err == nil {
			err = e
		}
	}

	return mt, err
}

type renderer struct {
	http.ResponseWriter
	r   *http.Request
	mt  *multitemplate.Template
	opt Options
	err error
}

func (r *renderer) SetContentType(ct string) {
	r.Header().Set("Content-Type", ct+";charset="+r.opt.Charset)
}

// this is pretty much the same as the render packages
func (r *renderer) JSON(status int, v interface{}) {
	var result []byte
	var err error
	if r.opt.IndentEncoding != "" {
		result, err = json.MarshalIndent(v, "", r.opt.IndentEncoding)
	} else {
		result, err = json.Marshal(v)
	}
	if err != nil {
		http.Error(r, err.Error(), 500)
	}
	r.SetContentType("application/json")
	r.WriteHeader(status)
	r.Write(result)
}
func (r *renderer) XML(status int, v interface{}) {
	var result []byte
	var err error
	if r.opt.IndentEncoding != "" {
		result, err = xml.MarshalIndent(v, "", r.opt.IndentEncoding)
	} else {
		result, err = xml.Marshal(v)
	}
	if err != nil {
		http.Error(r, err.Error(), 500)
	}
	r.SetContentType("application/xml")
	r.WriteHeader(status)
	r.Write(result)
}
func (r *renderer) HTML(status int, name string, htmlOpt *Context) {
	var ctx *multitemplate.Context
	if htmlOpt != nil {
		ctx = multitemplate.NewContext(htmlOpt.RenderArgs)
		if !htmlOpt.NoLayout {
			ctx.Layout = htmlOpt.Layout
		}
		if len(htmlOpt.Yields) > 0 {
			ctx.Yields = htmlOpt.Yields
		}
		if len(htmlOpt.blocks) > 0 {
			ctx.Blocks = htmlOpt.blocks
		}
	} else {
		ctx = multitemplate.NewContext(nil)
		ctx.Layout = r.opt.DefaultLayout
	}
	ctx.Main = name
	fmt.Println(r.mt.Lookup("layout.html").Tmpl.Tree.Root.String())
	b := &bytes.Buffer{}
	if r.mt == nil || r.mt.Tmpl == nil {
		panic("here")
	}
	e := r.mt.ExecuteContext(b, ctx)
	if e != nil {
		http.Error(r, e.Error(), 500)
	}
	io.Copy(r, b)
}

func (r *renderer) Error(status int) {
	r.WriteHeader(status)
}

func (r *renderer) Redirect(location string, status ...int) {
	code := http.StatusFound
	if len(status) > 0 {
		code = status[0]
	}
	http.Redirect(r, r.r, location, code)
}

func (r *renderer) Template() *multitemplate.Template {
	return r.mt
}

func (r *renderer) Text(status int, text string) {
	r.WriteHeader(status)
	io.WriteString(r, text)
}
<commit_msg>Fix and improve martini integration<commit_after>/*
  Package multirender is a middleware for Martini that provides HTML
  templates through multitemplate, it like to imitate and build on the
  render package from martini-contrib.

  package main

  import (
    "github.com/codegangsta/martini"
    "github.com/cooldude/cache"

    // contians the multirender package.
    "github.com/acsellers/multitemplate/martini"
    // import any languages you want to use
    _ "github.com/acsellers/multitemplate/terse"
  )

  func main() {
    app := martini.Classic()
    app.Use(multirender.Renderer())

    app.Get("/", func (mr multirender.Render) {
      mr.HTML(200, "app/index.html", nil)
    })

    app.Get("/admins", func(mr multirender.Render) {
      ctx := mr.NewContext()
      ctx.RenderArgs["Users"] = AdminUsers
      mr.HTML(200, "app/user_list.html", ctx)
    })

    app.Run()
  }

*/
package multirender

import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"html/template"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"github.com/acsellers/multitemplate"
	"github.com/acsellers/multitemplate/helpers"
	"github.com/codegangsta/martini"
)

type Render interface {
	// JSON writes the status code and JSON version of the value to the
	// http.ResponseWriter
	JSON(status int, v interface{})
	// XML writes the status code and XML version of the value to the
	// http.ResponseWriter
	XML(status int, v interface{})
	// HTML render the template given by name, with the status and options
	// given.
	HTML(status int, name string, htmlOpt *Context)
	// Create a Context with default options set
	NewContext() *Context
	// Render the text to the output
	Text(status int, text string)
	// Write the given status to the Response
	Error(status int)
	// Redirect to the location with an optional status, default status is
	// 302.
	Redirect(location string, status ...int)
	// Return the Template by name
	Template() *multitemplate.Template
	// Sets the content type, will also append charset from Options
	SetContentType(string)
}

func (r *renderer) NewContext() *Context {
	return &Context{
		Layout:     r.opt.DefaultLayout,
		Yields:     make(map[string]string),
		blocks:     make(map[string]multitemplate.RenderedBlock),
		RenderArgs: make(map[string]interface{}),
	}
}

type Context struct {
	Status     int
	Layout     string
	NoLayout   bool
	Yields     map[string]string
	blocks     map[string]multitemplate.RenderedBlock
	RenderArgs map[string]interface{}
}

func (c *Context) SetContent(name, content string) {
	if c.blocks == nil {
		c.blocks = make(map[string]multitemplate.RenderedBlock)
	}
	c.blocks[name] = multitemplate.RenderedBlock{
		Content: template.HTML(content),
	}
}

func (c *Context) SetTemplate(blockName, templateName string) {
	if c.Yields == nil {
		c.Yields = make(map[string]string)
	}
	c.Yields[blockName] = templateName
}

func Renderer(opt Options) martini.Handler {
	if opt.Charset == "" {
		opt.Charset = "utf-8"
	}
	mt := multitemplate.New("martini").Funcs(opt.Funcs)
	var err error
	mt = mt.Funcs(helpers.GetHelpers(opt.Helpers...))
	mt, _ = compile(opt, mt)
	return func(w http.ResponseWriter, r *http.Request, c martini.Context) {
		if martini.Env == martini.Dev {
			mt = multitemplate.New("martini").Funcs(opt.Funcs)
			mt = mt.Funcs(helpers.GetHelpers(opt.Helpers...))
			mt, err = compile(opt, mt)
		}
		c.MapTo(&renderer{w, r, mt, opt, err}, (*Render)(nil))
	}
}

type Options struct {
	// Directories to search for template files
	Directories []string
	// Layout to render by default
	DefaultLayout string
	// Helper modules to load from multitemplate helpers
	Helpers []string
	// Additional functions to add
	Funcs template.FuncMap
	// JSON & XML indentation, an empty string disables indentation
	IndentEncoding string
	// Default is set to utf-8
	Charset string
	// Note that you will need to set the delims for each multitemplate
	// language you are using, you cannot set it in this Options struct.
}

func compile(opt Options, mt *multitemplate.Template) (*multitemplate.Template, error) {
	var err error
	fmt.Println("[multitemplate] Start Template Compile")
	for _, dir := range opt.Directories {
		mt.Base = dir
		e := filepath.Walk(dir, func(path string, i os.FileInfo, e error) error {
			if !i.IsDir() && strings.Contains(path, "html") {
				fmt.Println("[multitemplate] Compiling file:", path)
				_, err := mt.ParseFiles(path)
				if err == nil {
					fmt.Println("[multitemplate] Successfully compiled file")
				} else {
					fmt.Printf("[multitemplate] Could not compile file: %s\n", err.Error())
				}
				return err
			}
			return nil
		})
		if e != nil && err == nil {
			err = e
		}
	}
	fmt.Println("[multitemplate] End Template Compile")
	return mt, err
}

type renderer struct {
	http.ResponseWriter
	r   *http.Request
	mt  *multitemplate.Template
	opt Options
	err error
}

func (r *renderer) SetContentType(ct string) {
	r.Header().Set("Content-Type", ct+";charset="+r.opt.Charset)
}

// this is pretty much the same as the render packages
func (r *renderer) JSON(status int, v interface{}) {
	var result []byte
	var err error
	if r.opt.IndentEncoding != "" {
		result, err = json.MarshalIndent(v, "", r.opt.IndentEncoding)
	} else {
		result, err = json.Marshal(v)
	}
	if err != nil {
		http.Error(r, err.Error(), 500)
	}
	r.SetContentType("application/json")
	r.WriteHeader(status)
	r.Write(result)
}
func (r *renderer) XML(status int, v interface{}) {
	var result []byte
	var err error
	if r.opt.IndentEncoding != "" {
		result, err = xml.MarshalIndent(v, "", r.opt.IndentEncoding)
	} else {
		result, err = xml.Marshal(v)
	}
	if err != nil {
		http.Error(r, err.Error(), 500)
	}
	r.SetContentType("application/xml")
	r.WriteHeader(status)
	r.Write(result)
}
func (r *renderer) HTML(status int, name string, htmlOpt *Context) {
	var ctx *multitemplate.Context
	if htmlOpt != nil {
		ctx = multitemplate.NewContext(htmlOpt.RenderArgs)
		if !htmlOpt.NoLayout {
			ctx.Layout = htmlOpt.Layout
		}
		if len(htmlOpt.Yields) > 0 {
			ctx.Yields = htmlOpt.Yields
		}
		if len(htmlOpt.blocks) > 0 {
			ctx.Blocks = htmlOpt.blocks
		}
	} else {
		ctx = multitemplate.NewContext(nil)
		ctx.Layout = r.opt.DefaultLayout
	}
	ctx.Main = name
	b := &bytes.Buffer{}
	if r.mt == nil || r.mt.Tmpl == nil {
		panic("here")
	}
	e := r.mt.ExecuteContext(b, ctx)
	if e != nil {
		http.Error(r, e.Error(), 500)
	}
	io.Copy(r, b)
}

func (r *renderer) Error(status int) {
	r.WriteHeader(status)
}

func (r *renderer) Redirect(location string, status ...int) {
	code := http.StatusFound
	if len(status) > 0 {
		code = status[0]
	}
	http.Redirect(r, r.r, location, code)
}

func (r *renderer) Template() *multitemplate.Template {
	return r.mt
}

func (r *renderer) Text(status int, text string) {
	r.WriteHeader(status)
	io.WriteString(r, text)
}
<|endoftext|>


<commit_before>// etl package provides all interfaces that are used across other packages
// in the project.
package intf

import (
	"cloud.google.com/go/bigquery"
	"time"
)

// An Inserter provides:
//   InsertRows - inserts one or more rows into BQ (or the insert buffer).
//   Flush - flushes any rows in the buffer out to bigquery.
//   InsertCount - returns the total count of rows passed through InsertRow.
//   BufferSize - returns the count of rows currently in the buffer.
type Inserter interface {
	InsertRows(data interface{}) error
	Flush() error
	Count() int
	RowsInBuffer() int
}

// Params for NewInserter
type InserterParams struct {
	// These specify the google cloud project/dataset/table to write to.
	Project    string
	Dataset    string
	Table      string
	Timeout    time.Duration // max duration of backend calls.  (for context)
	BufferSize int           // Number of rows to buffer before writing to backend.
}

type Parser interface {
	// meta - metadata, e.g. from the original tar file name.
	// testName - Name of test file (typically extracted from a tar file)
	// test - binary test data
	ParseAndInsert(meta map[string]bigquery.Value, testName string, test []byte) error

	// The name of the table that this Parser inserts into.
	// Used for metrics and logging.
	TableName() string
}
<commit_msg>Inject Inserter into Parser<commit_after>// etl package provides all interfaces that are used across other packages
// in the project.
package intf

import (
	"cloud.google.com/go/bigquery"
	"time"
)

// An Inserter provides:
//   InsertRows - inserts one or more rows into the insert buffer.
//   Flush - flushes any rows in the buffer out to bigquery.
//   Count - returns the count of rows currently in the buffer.
//   RowsInBuffer - returns the count of rows currently in the buffer.
type Inserter interface {
	InsertRows(data interface{}) error
	Flush() error
	Count() int
	RowsInBuffer() int
}

// Params for NewInserter
type InserterParams struct {
	// These specify the google cloud project/dataset/table to write to.
	Project    string
	Dataset    string
	Table      string
	Timeout    time.Duration // max duration of backend calls.  (for context)
	BufferSize int           // Number of rows to buffer before writing to backend.
}

type Parser interface {
	// meta - metadata, e.g. from the original tar file name.
	// testName - Name of test file (typically extracted from a tar file)
	// test - binary test data
	ParseAndInsert(meta map[string]bigquery.Value, testName string, test []byte) error

	// The name of the table that this Parser inserts into.
	// Used for metrics and logging.
	TableName() string
}
<|endoftext|>


<commit_before>// Package intintmap is a fast int64 key -> int64 value map.
//
// It is copied nearly verbatim from http://java-performance.info/implementing-world-fastest-java-int-to-int-hash-map/
package intintmap

import (
	"math"
)

// INT_PHI is for scrambling the keys
const INT_PHI = 0x9E3779B9

// FREE_KEY is the 'free' key
const FREE_KEY = 0

func phiMix(x int64) int64 {
	h := x * INT_PHI
	return h ^ (h >> 16)
}

// Map is a map-like data-structure for int64s
type Map struct {
	data       []int64 // interleaved keys and values
	fillFactor float64
	threshold  int // we will resize a map once it reaches this size
	size       int

	mask  int64 // mask to calculate the original position
	mask2 int64

	hasFreeKey bool  // do we have 'free' key in the map?
	freeVal    int64 // value of 'free' key
}

func nextPowerOf2(x uint32) uint32 {
	if x == 0 {
		return 1
	}
	x--
	x |= x >> 1
	x |= x >> 2
	x |= x >> 4
	x |= x >> 8
	x |= x >> 16
	return (x | x>>32) + 1
}

func arraySize(exp int, fill float64) int {
	s := nextPowerOf2(uint32(math.Ceil(float64(exp) / fill)))
	if s < 2 {
		s = 2
	}
	return int(s)
}

// New returns a map initialized with n spaces and uses the stated fillFactor.
// The map will grow as needed.
func New(size int, fillFactor float64) *Map {
	if fillFactor <= 0 || fillFactor >= 1 {
		panic("FillFactor must be in (0, 1)")
	}
	if size <= 0 {
		panic("Size must be positive")
	}

	capacity := arraySize(size, fillFactor)
	return &Map{
		data:       make([]int64, 2*capacity),
		fillFactor: fillFactor,
		threshold:  int(math.Floor(float64(capacity) * fillFactor)),
		mask:       int64(capacity - 1),
		mask2:      int64(2*capacity - 1),
	}
}

// Get returns the value if the key is found.
func (m *Map) Get(key int64) (int64, bool) {
	if key == FREE_KEY {
		if m.hasFreeKey {
			return m.freeVal, true
		}
		return 0, false
	}

	ptr := (phiMix(key) & m.mask) << 1
	k := m.data[ptr]

	if key == FREE_KEY { // end of chain already
		return 0, false
	}
	if k == key { // we check FREE prior to this call
		return m.data[ptr+1], true
	}

	for {
		ptr = (ptr + 2) & m.mask2
		k = m.data[ptr]
		if k == FREE_KEY {
			return 0, false
		}
		if k == key {
			return m.data[ptr+1], true
		}
	}
}

// Put adds or updates key with value val.
func (m *Map) Put(key int64, val int64) {
	if key == FREE_KEY {
		if !m.hasFreeKey {
			m.size++
		}
		m.hasFreeKey = true
		m.freeVal = val
		return
	}

	ptr := (phiMix(key) & m.mask) << 1
	k := m.data[ptr]

	if k == FREE_KEY { // end of chain already
		m.data[ptr] = key
		m.data[ptr+1] = val
		if m.size >= m.threshold {
			m.rehash()
		} else {
			m.size++
		}
		return
	} else if k == key { // overwrite existed value
		m.data[ptr+1] = val
		return
	}

	for {
		ptr = (ptr + 2) & m.mask2
		k = m.data[ptr]

		if k == FREE_KEY {
			m.data[ptr] = key
			m.data[ptr+1] = val
			if m.size >= m.threshold {
				m.rehash()
			} else {
				m.size++
			}
			return
		} else if k == key {
			m.data[ptr+1] = val
			return
		}
	}

}

// Del deletes a key and its value.
func (m *Map) Del(key int64) {
	if key == FREE_KEY {
		m.hasFreeKey = false
		m.size--
		return
	}

	ptr := (phiMix(key) & m.mask) << 1
	k := m.data[ptr]

	if k == key {
		m.shiftKeys(ptr)
		m.size--
		return
	} else if k == FREE_KEY { // end of chain already
		return
	}

	for {
		ptr = (ptr + 2) & m.mask2
		k = m.data[ptr]

		if k == key {
			m.shiftKeys(ptr)
			m.size--
			return
		} else if k == FREE_KEY {
			return
		}

	}
}

func (m *Map) shiftKeys(pos int64) int64 {
	// Shift entries with the same hash.
	var last, slot int64
	var k int64
	var data = m.data
	for {
		last = pos
		pos = (last + 2) & m.mask2
		for {
			k = data[pos]
			if k == FREE_KEY {
				data[last] = FREE_KEY
				return last
			}

			slot = (phiMix(k) & m.mask) << 1
			if last <= pos {
				if last >= slot || slot > pos {
					break
				}
			} else {
				if last >= slot && slot > pos {
					break
				}
			}
			pos = (pos + 2) & m.mask2
		}
		data[last] = k
		data[last+1] = data[pos+1]
	}
}

func (m *Map) rehash() {
	newCapacity := len(m.data) * 2
	m.threshold = int(math.Floor(float64(newCapacity/2) * m.fillFactor))
	m.mask = int64(newCapacity/2 - 1)
	m.mask2 = int64(newCapacity - 1)

	data := make([]int64, len(m.data)) // copy of original data
	copy(data, m.data)

	m.data = make([]int64, newCapacity)
	if m.hasFreeKey { // reset size
		m.size = 1
	} else {
		m.size = 0
	}

	var o int64
	for i := 0; i < len(data); i += 2 {
		o = data[i]
		if o != FREE_KEY {
			m.Put(o, data[i+1])
		}
	}
}

// Size returns size of the map.
func (m *Map) Size() int {
	return m.size
}

// Keys returns a channel for iterating all keys.
func (m *Map) Keys() chan int64 {
	c := make(chan int64, 10)
	go func() {
		data := m.data
		var k int64

		if m.hasFreeKey {
			c <- FREE_KEY // value is m.freeVal
		}

		for i := 0; i < len(data); i += 2 {
			k = data[i]
			if k == FREE_KEY {
				continue
			}
			c <- k // value is data[i+1]
		}
		close(c)
	}()
	return c
}

// Items returns a channel for iterating all key-value pairs.
func (m *Map) Items() chan [2]int64 {
	c := make(chan [2]int64, 10)
	go func() {
		data := m.data
		var k int64

		if m.hasFreeKey {
			c <- [2]int64{FREE_KEY, m.freeVal}
		}

		for i := 0; i < len(data); i += 2 {
			k = data[i]
			if k == FREE_KEY {
				continue
			}
			c <- [2]int64{k, data[i+1]}
		}
		close(c)
	}()
	return c
}
<commit_msg>Extra check to help compiler eliminate a bounds check (#5)<commit_after>// Package intintmap is a fast int64 key -> int64 value map.
//
// It is copied nearly verbatim from http://java-performance.info/implementing-world-fastest-java-int-to-int-hash-map/
package intintmap

import (
	"math"
)

// INT_PHI is for scrambling the keys
const INT_PHI = 0x9E3779B9

// FREE_KEY is the 'free' key
const FREE_KEY = 0

func phiMix(x int64) int64 {
	h := x * INT_PHI
	return h ^ (h >> 16)
}

// Map is a map-like data-structure for int64s
type Map struct {
	data       []int64 // interleaved keys and values
	fillFactor float64
	threshold  int // we will resize a map once it reaches this size
	size       int

	mask  int64 // mask to calculate the original position
	mask2 int64

	hasFreeKey bool  // do we have 'free' key in the map?
	freeVal    int64 // value of 'free' key
}

func nextPowerOf2(x uint32) uint32 {
	if x == 0 {
		return 1
	}
	x--
	x |= x >> 1
	x |= x >> 2
	x |= x >> 4
	x |= x >> 8
	x |= x >> 16
	return (x | x>>32) + 1
}

func arraySize(exp int, fill float64) int {
	s := nextPowerOf2(uint32(math.Ceil(float64(exp) / fill)))
	if s < 2 {
		s = 2
	}
	return int(s)
}

// New returns a map initialized with n spaces and uses the stated fillFactor.
// The map will grow as needed.
func New(size int, fillFactor float64) *Map {
	if fillFactor <= 0 || fillFactor >= 1 {
		panic("FillFactor must be in (0, 1)")
	}
	if size <= 0 {
		panic("Size must be positive")
	}

	capacity := arraySize(size, fillFactor)
	return &Map{
		data:       make([]int64, 2*capacity),
		fillFactor: fillFactor,
		threshold:  int(math.Floor(float64(capacity) * fillFactor)),
		mask:       int64(capacity - 1),
		mask2:      int64(2*capacity - 1),
	}
}

// Get returns the value if the key is found.
func (m *Map) Get(key int64) (int64, bool) {
	if key == FREE_KEY {
		if m.hasFreeKey {
			return m.freeVal, true
		}
		return 0, false
	}

	ptr := (phiMix(key) & m.mask) << 1
	if ptr < 0 || ptr >= int64(len(m.data)) {	// Check to help to compiler to eliminate a bounds check below.
		return 0, false
	}
	k := m.data[ptr]

	if key == FREE_KEY { // end of chain already
		return 0, false
	}
	if k == key { // we check FREE prior to this call
		return m.data[ptr+1], true
	}

	for {
		ptr = (ptr + 2) & m.mask2
		k = m.data[ptr]
		if k == FREE_KEY {
			return 0, false
		}
		if k == key {
			return m.data[ptr+1], true
		}
	}
}

// Put adds or updates key with value val.
func (m *Map) Put(key int64, val int64) {
	if key == FREE_KEY {
		if !m.hasFreeKey {
			m.size++
		}
		m.hasFreeKey = true
		m.freeVal = val
		return
	}

	ptr := (phiMix(key) & m.mask) << 1
	k := m.data[ptr]

	if k == FREE_KEY { // end of chain already
		m.data[ptr] = key
		m.data[ptr+1] = val
		if m.size >= m.threshold {
			m.rehash()
		} else {
			m.size++
		}
		return
	} else if k == key { // overwrite existed value
		m.data[ptr+1] = val
		return
	}

	for {
		ptr = (ptr + 2) & m.mask2
		k = m.data[ptr]

		if k == FREE_KEY {
			m.data[ptr] = key
			m.data[ptr+1] = val
			if m.size >= m.threshold {
				m.rehash()
			} else {
				m.size++
			}
			return
		} else if k == key {
			m.data[ptr+1] = val
			return
		}
	}

}

// Del deletes a key and its value.
func (m *Map) Del(key int64) {
	if key == FREE_KEY {
		m.hasFreeKey = false
		m.size--
		return
	}

	ptr := (phiMix(key) & m.mask) << 1
	k := m.data[ptr]

	if k == key {
		m.shiftKeys(ptr)
		m.size--
		return
	} else if k == FREE_KEY { // end of chain already
		return
	}

	for {
		ptr = (ptr + 2) & m.mask2
		k = m.data[ptr]

		if k == key {
			m.shiftKeys(ptr)
			m.size--
			return
		} else if k == FREE_KEY {
			return
		}

	}
}

func (m *Map) shiftKeys(pos int64) int64 {
	// Shift entries with the same hash.
	var last, slot int64
	var k int64
	var data = m.data
	for {
		last = pos
		pos = (last + 2) & m.mask2
		for {
			k = data[pos]
			if k == FREE_KEY {
				data[last] = FREE_KEY
				return last
			}

			slot = (phiMix(k) & m.mask) << 1
			if last <= pos {
				if last >= slot || slot > pos {
					break
				}
			} else {
				if last >= slot && slot > pos {
					break
				}
			}
			pos = (pos + 2) & m.mask2
		}
		data[last] = k
		data[last+1] = data[pos+1]
	}
}

func (m *Map) rehash() {
	newCapacity := len(m.data) * 2
	m.threshold = int(math.Floor(float64(newCapacity/2) * m.fillFactor))
	m.mask = int64(newCapacity/2 - 1)
	m.mask2 = int64(newCapacity - 1)

	data := make([]int64, len(m.data)) // copy of original data
	copy(data, m.data)

	m.data = make([]int64, newCapacity)
	if m.hasFreeKey { // reset size
		m.size = 1
	} else {
		m.size = 0
	}

	var o int64
	for i := 0; i < len(data); i += 2 {
		o = data[i]
		if o != FREE_KEY {
			m.Put(o, data[i+1])
		}
	}
}

// Size returns size of the map.
func (m *Map) Size() int {
	return m.size
}

// Keys returns a channel for iterating all keys.
func (m *Map) Keys() chan int64 {
	c := make(chan int64, 10)
	go func() {
		data := m.data
		var k int64

		if m.hasFreeKey {
			c <- FREE_KEY // value is m.freeVal
		}

		for i := 0; i < len(data); i += 2 {
			k = data[i]
			if k == FREE_KEY {
				continue
			}
			c <- k // value is data[i+1]
		}
		close(c)
	}()
	return c
}

// Items returns a channel for iterating all key-value pairs.
func (m *Map) Items() chan [2]int64 {
	c := make(chan [2]int64, 10)
	go func() {
		data := m.data
		var k int64

		if m.hasFreeKey {
			c <- [2]int64{FREE_KEY, m.freeVal}
		}

		for i := 0; i < len(data); i += 2 {
			k = data[i]
			if k == FREE_KEY {
				continue
			}
			c <- [2]int64{k, data[i+1]}
		}
		close(c)
	}()
	return c
}
<|endoftext|>