<commit_before>package message

import (
	"encoding/json"
	"fmt"

	"github.com/silenceper/wechat/v2/officialaccount/context"
	"github.com/silenceper/wechat/v2/util"
)

const (
	templateSendURL = "https://api.weixin.qq.com/cgi-bin/message/template/send"
	templateListURL = "https://api.weixin.qq.com/cgi-bin/template/get_all_private_template"
)

//Template 模板消息
type Template struct {
	*context.Context
}

//NewTemplate 实例化
func NewTemplate(context *context.Context) *Template {
	tpl := new(Template)
	tpl.Context = context
	return tpl
}

//TemplateMessage 发送的模板消息内容
type TemplateMessage struct {
	ToUser     string                       `json:"touser"`          // 必须, 接受者OpenID
	TemplateID string                       `json:"template_id"`     // 必须, 模版ID
	URL        string                       `json:"url,omitempty"`   // 可选, 用户点击后跳转的URL, 该URL必须处于开发者在公众平台网站中设置的域中
	Color      string                       `json:"color,omitempty"` // 可选, 整个消息的颜色, 可以不设置
	Data       map[string]*TemplateDataItem `json:"data"`            // 必须, 模板数据

	MiniProgram struct {
		AppID    string `json:"appid"`    //所需跳转到的小程序appid（该小程序appid必须与发模板消息的公众号是绑定关联关系）
		PagePath string `json:"pagepath"` //所需跳转到小程序的具体页面路径，支持带参数,（示例index?foo=bar）
	} `json:"miniprogram"` //可选,跳转至小程序地址
}

//TemplateDataItem 模版内某个 .DATA 的值
type TemplateDataItem struct {
	Value string `json:"value"`
	Color string `json:"color,omitempty"`
}

type resTemplateSend struct {
	util.CommonError

	MsgID int64 `json:"msgid"`
}

//Send 发送模板消息
func (tpl *Template) Send(msg *TemplateMessage) (msgID int64, err error) {
	var accessToken string
	accessToken, err = tpl.GetAccessToken()
	if err != nil {
		return
	}
	uri := fmt.Sprintf("%s?access_token=%s", templateSendURL, accessToken)
	response, err := util.PostJSON(uri, msg)
	if err != nil {
		return
	}
	var result resTemplateSend
	err = json.Unmarshal(response, &result)
	if err != nil {
		return
	}
	if result.ErrCode != 0 {
		err = fmt.Errorf("template msg send error : errcode=%v , errmsg=%v", result.ErrCode, result.ErrMsg)
		return
	}
	msgID = result.MsgID
	return
}

// TemplateItem 模板消息.
type TemplateItem struct {
	TemplateID      string `json:"template_id"`
	Title           string `json:"title"`
	PrimaryIndustry string `json:"primary_industry"`
	DeputyIndustry  string `json:"deputy_industry"`
	Content         string `json:"content"`
	Example         string `json:"example"`
}

type resTemplateList struct {
	util.CommonError

	TemplateList []*TemplateItem `json:"template_list"`
}

//List 获取模板列表
func (tpl *Template) List() (templateList []*TemplateItem, err error) {
	var accessToken string
	accessToken, err = tpl.GetAccessToken()
	if err != nil {
		return
	}
	uri := fmt.Sprintf("%s?access_token=%s", templateListURL, accessToken)
	var response []byte
	response, err = util.HTTPGet(uri)
	if err != nil {
		return
	}
	var res resTemplateList
	err = util.DecodeWithError(response, res, "ListTemplate")
	if err != nil {
		return
	}
	templateList = res.TemplateList
	return
}
<commit_msg>bugfix officialaccount/message/template json non-pointer error (#318)<commit_after>package message

import (
	"encoding/json"
	"fmt"

	"github.com/silenceper/wechat/v2/officialaccount/context"
	"github.com/silenceper/wechat/v2/util"
)

const (
	templateSendURL = "https://api.weixin.qq.com/cgi-bin/message/template/send"
	templateListURL = "https://api.weixin.qq.com/cgi-bin/template/get_all_private_template"
)

//Template 模板消息
type Template struct {
	*context.Context
}

//NewTemplate 实例化
func NewTemplate(context *context.Context) *Template {
	tpl := new(Template)
	tpl.Context = context
	return tpl
}

//TemplateMessage 发送的模板消息内容
type TemplateMessage struct {
	ToUser     string                       `json:"touser"`          // 必须, 接受者OpenID
	TemplateID string                       `json:"template_id"`     // 必须, 模版ID
	URL        string                       `json:"url,omitempty"`   // 可选, 用户点击后跳转的URL, 该URL必须处于开发者在公众平台网站中设置的域中
	Color      string                       `json:"color,omitempty"` // 可选, 整个消息的颜色, 可以不设置
	Data       map[string]*TemplateDataItem `json:"data"`            // 必须, 模板数据

	MiniProgram struct {
		AppID    string `json:"appid"`    //所需跳转到的小程序appid（该小程序appid必须与发模板消息的公众号是绑定关联关系）
		PagePath string `json:"pagepath"` //所需跳转到小程序的具体页面路径，支持带参数,（示例index?foo=bar）
	} `json:"miniprogram"` //可选,跳转至小程序地址
}

//TemplateDataItem 模版内某个 .DATA 的值
type TemplateDataItem struct {
	Value string `json:"value"`
	Color string `json:"color,omitempty"`
}

type resTemplateSend struct {
	util.CommonError

	MsgID int64 `json:"msgid"`
}

//Send 发送模板消息
func (tpl *Template) Send(msg *TemplateMessage) (msgID int64, err error) {
	var accessToken string
	accessToken, err = tpl.GetAccessToken()
	if err != nil {
		return
	}
	uri := fmt.Sprintf("%s?access_token=%s", templateSendURL, accessToken)
	response, err := util.PostJSON(uri, msg)
	if err != nil {
		return
	}
	var result resTemplateSend
	err = json.Unmarshal(response, &result)
	if err != nil {
		return
	}
	if result.ErrCode != 0 {
		err = fmt.Errorf("template msg send error : errcode=%v , errmsg=%v", result.ErrCode, result.ErrMsg)
		return
	}
	msgID = result.MsgID
	return
}

// TemplateItem 模板消息.
type TemplateItem struct {
	TemplateID      string `json:"template_id"`
	Title           string `json:"title"`
	PrimaryIndustry string `json:"primary_industry"`
	DeputyIndustry  string `json:"deputy_industry"`
	Content         string `json:"content"`
	Example         string `json:"example"`
}

type resTemplateList struct {
	util.CommonError

	TemplateList []*TemplateItem `json:"template_list"`
}

//List 获取模板列表
func (tpl *Template) List() (templateList []*TemplateItem, err error) {
	var accessToken string
	accessToken, err = tpl.GetAccessToken()
	if err != nil {
		return
	}
	uri := fmt.Sprintf("%s?access_token=%s", templateListURL, accessToken)
	var response []byte
	response, err = util.HTTPGet(uri)
	if err != nil {
		return
	}
	var res resTemplateList
	err = util.DecodeWithError(response, &res, "ListTemplate")
	if err != nil {
		return
	}
	templateList = res.TemplateList
	return
}
<|endoftext|>


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

package main_test

import (
	"flag"
	"fmt"
	"io/ioutil"
	"math/rand"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"testing"
	"text/template"

	"v.io/x/lib/textutil"
	"v.io/x/ref/test/testutil"
	"v.io/x/ref/test/v23test"
)

var (
	flagProject        = flag.String("project", "", "The name of the GCE project to use.")
	flagZone           = flag.String("zone", "", "The name of the GCE zone to use.")
	flagCluster        = flag.String("cluster", "", "The name of the kubernetes cluster to use.")
	flagGetCredentials = flag.Bool("get-credentials", true, "This flag is passed to vkube.")
)

// TestV23Vkube is an end-to-end test for the vkube command. It operates on a
// pre-existing kubernetes cluster running on GCE.
// This test can easily exceed the default test timeout of 10m. It is
// recommended to use -test.timeout=20m.
func TestV23Vkube(t *testing.T) {
	if *flagProject == "" || (*flagGetCredentials && (*flagZone == "" || *flagCluster == "")) {
		t.Skip("--project, --zone, or --cluster not specified")
	}
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}

	v23test.SkipUnlessRunningIntegrationTests(t)
	sh := v23test.NewShell(t, nil)
	defer sh.Cleanup()

	workdir := sh.MakeTempDir()

	id := fmt.Sprintf("vkube-test-%08x", rand.Uint32())

	vkubeCfgPath := filepath.Join(workdir, "vkube.cfg")
	if err := createVkubeConfig(vkubeCfgPath, id); err != nil {
		t.Fatal(err)
	}

	creds := sh.ForkCredentials("alice")

	vkubeBin := v23test.BuildGoPkg(sh, "v.io/x/ref/services/cluster/vkube")
	vshBin := v23test.BuildGoPkg(sh, "v.io/x/ref/examples/tunnel/vsh")

	var (
		cmd = func(name string, expectSuccess bool, baseArgs ...string) func(args ...string) string {
			return func(args ...string) string {
				args = append(baseArgs, args...)
				// Note, creds do not affect non-Vanadium commands.
				c := sh.Cmd(name, args...).WithCredentials(creds)
				c.ExitErrorIsOk = true
				plw := textutil.PrefixLineWriter(os.Stdout, filepath.Base(name)+"> ")
				c.AddStdoutWriter(plw)
				c.AddStderrWriter(plw)
				output := c.CombinedOutput()
				plw.Flush()
				if expectSuccess && c.Err != nil {
					t.Error(testutil.FormatLogLine(2, "Unexpected failure: %s %s :%v", name, strings.Join(args, " "), c.Err))
				} else if !expectSuccess && c.Err == nil {
					t.Error(testutil.FormatLogLine(2, "Unexpected success %d: %s %s", name, strings.Join(args, " ")))
				}
				return output
			}
		}
		gsutil      = cmd("gsutil", true)
		gcloud      = cmd("gcloud", true, "--project="+*flagProject)
		docker      = cmd("docker", true)
		getCreds    = fmt.Sprintf("--get-credentials=%v", *flagGetCredentials)
		vkubeOK     = cmd(vkubeBin, true, "--config="+vkubeCfgPath, getCreds)
		vkubeFail   = cmd(vkubeBin, false, "--config="+vkubeCfgPath, getCreds)
		kubectlOK   = cmd(vkubeBin, true, "--config="+vkubeCfgPath, getCreds, "kubectl", "--", "--namespace="+id)
		kubectlFail = cmd(vkubeBin, false, "--config="+vkubeCfgPath, getCreds, "kubectl", "--", "--namespace="+id)
		vshOK       = cmd(vshBin, true)
	)

	if out := kubectlOK("cluster-info"); strings.Contains(out, "ERROR:") {
		// Exit early if we don't have valid credentials.
		t.Fatalf("Failed to get cluster information: %v", out)
	}

	// Create a bucket to store the docker images.
	gsutil("mb", "-p", *flagProject, "gs://"+id)
	defer func() {
		kubectlOK("delete", "namespace", id)
		gsutil("-m", "rm", "-R", "-a", "gs://"+id+"/*")
		gsutil("rb", "gs://"+id)
	}()

	// Create app's docker image and configs.
	dockerDir, err := setupDockerDirectory(workdir)
	if err != nil {
		t.Fatal(err)
	}
	appImage := "b.gcr.io/" + id + "/tunneld:latest"
	docker("build", "-t", appImage, dockerDir)
	gcloud("docker", "push", appImage)
	appConf1 := filepath.Join(workdir, "app1.json")
	if err := createAppConfig(appConf1, id, appImage, "1"); err != nil {
		t.Fatal(err)
	}
	appConf2 := filepath.Join(workdir, "app2.json")
	if err := createAppConfig(appConf2, id, appImage, "2"); err != nil {
		t.Fatal(err)
	}

	vkubeOK("build-docker-images", "-v", "-tag=test")
	// Clean up local docker images.
	docker(
		"rmi",
		"b.gcr.io/"+id+"/cluster-agent",
		"b.gcr.io/"+id+"/cluster-agent:test",
		"b.gcr.io/"+id+"/pod-agent",
		"b.gcr.io/"+id+"/pod-agent:test",
		"b.gcr.io/"+id+"/tunneld",
	)

	// Run the actual tests.
	vkubeOK("start-cluster-agent", "--wait")
	kubectlOK("get", "service", "cluster-agent")
	kubectlOK("get", "rc", "cluster-agentd-latest")
	vkubeOK("claim-cluster-agent")
	vkubeFail("start-cluster-agent") // Already running
	vkubeFail("claim-cluster-agent") // Already claimed

	vkubeOK("start", "-f", appConf1, "--wait", "my-app")
	kubectlOK("get", "rc", "tunneld-1")
	vkubeFail("start", "-f", appConf1, "my-app") // Already running

	vkubeOK("update", "-f", appConf2, "--wait")
	kubectlOK("get", "rc", "tunneld-2")

	// Find the pod running tunneld, get the server's addr from its stdout.
	podName := kubectlOK("get", "pod", "-l", "application=tunneld", "--template={{range .items}}{{.metadata.name}}{{end}}")
	var addr string
	for _, log := range strings.Split(kubectlOK("logs", podName, "-c", "tunneld"), "\n") {
		if strings.HasPrefix(log, "NAME=") {
			addr = strings.TrimPrefix(log, "NAME=")
			break
		}
	}
	if got, expected := vshOK(addr, "echo", "hello", "world"), "hello world\n"; got != expected {
		t.Errorf("Unexpected output. Got %q, expected %q", got, expected)
	}

	vkubeOK("stop", "-f", appConf2)
	kubectlFail("get", "rc", "tunneld-2") // No longer running
	vkubeFail("stop", "-f", appConf2)     // No longer running

	vkubeOK("stop-cluster-agent")
	kubectlFail("get", "service", "cluster-agent")
	kubectlFail("get", "rc", "cluster-agentd-latest")
}

func createVkubeConfig(path, id string) error {
	f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0644)
	if err != nil {
		return err
	}
	defer f.Close()

	params := struct{ Project, Zone, Cluster, ID string }{*flagProject, *flagZone, *flagCluster, id}
	return template.Must(template.New("cfg").Parse(`{
  "project": "{{.Project}}",
  "zone": "{{.Zone}}",
  "cluster": "{{.Cluster}}",
  "clusterAgent": {
    "namespace": "{{.ID}}",
    "image": "b.gcr.io/{{.ID}}/cluster-agent:latest",
    "blessing": "root:alice:cluster-agent",
    "admin": "root:alice",
    "cpu": "0.1",
    "memory": "100M"
  },
  "podAgent": {
    "image": "b.gcr.io/{{.ID}}/pod-agent:latest"
  }
}`)).Execute(f, params)
}

func setupDockerDirectory(workdir string) (string, error) {
	dockerDir := filepath.Join(workdir, "docker")
	if err := os.Mkdir(dockerDir, 0755); err != nil {
		return "", err
	}
	if err := ioutil.WriteFile(
		filepath.Join(dockerDir, "Dockerfile"),
		[]byte("FROM busybox\nCOPY tunneld /usr/local/bin/\n"),
		0644,
	); err != nil {
		return "", err
	}
	if out, err := exec.Command("jiri", "go", "build",
		"-o", filepath.Join(dockerDir, "tunneld"),
		// TODO(rthellend): Remove -tags noopenssl after we move to Go 1.6.
		"-tags", "noopenssl",
		"-ldflags", "-extldflags \"-static\"",
		"v.io/x/ref/examples/tunnel/tunneld").CombinedOutput(); err != nil {
		return "", fmt.Errorf("build failed: %v: %s", err, string(out))
	}
	return dockerDir, nil
}

func createAppConfig(path, id, image, version string) error {
	f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0644)
	if err != nil {
		return err
	}
	defer f.Close()

	params := struct{ ID, Image, Version string }{id, image, version}
	return template.Must(template.New("appcfg").Parse(`{
  "apiVersion": "v1",
  "kind": "ReplicationController",
  "metadata": {
    "name": "tunneld-{{.Version}}",
    "namespace": "{{.ID}}",
    "labels": {
      "application": "tunneld"
    }
  },
  "spec": {
    "replicas": 1,
    "template": {
      "metadata": {
        "labels": {
          "application": "tunneld",
          "version": "{{.Version}}"
        }
      },
      "spec": {
        "containers": [
          {
            "name": "tunneld",
            "image": "{{.Image}}",
            "command": [
              "tunneld",
              "--v23.tcp.address=:8193",
              "--v23.permissions.literal={\"Admin\":{\"In\":[\"root:alice\"]}}",
	      "--alsologtostderr=false"
            ],
            "ports": [
              { "containerPort": 8193, "hostPort": 8193 }
            ],
            "resources": {
              "limits": { "cpu": "0.1", "memory": "100M" }
            }
          }
        ]
      }
    }
  }
}`)).Execute(f, params)
}

func TestMain(m *testing.M) {
	v23test.TestMain(m)
}
<commit_msg>TBR: services/cluster/vkube: Print the commands<commit_after>// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main_test

import (
	"flag"
	"fmt"
	"io/ioutil"
	"math/rand"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"testing"
	"text/template"

	"v.io/x/lib/textutil"
	"v.io/x/ref/test/testutil"
	"v.io/x/ref/test/v23test"
)

var (
	flagProject        = flag.String("project", "", "The name of the GCE project to use.")
	flagZone           = flag.String("zone", "", "The name of the GCE zone to use.")
	flagCluster        = flag.String("cluster", "", "The name of the kubernetes cluster to use.")
	flagGetCredentials = flag.Bool("get-credentials", true, "This flag is passed to vkube.")
)

// TestV23Vkube is an end-to-end test for the vkube command. It operates on a
// pre-existing kubernetes cluster running on GCE.
// This test can easily exceed the default test timeout of 10m. It is
// recommended to use -test.timeout=20m.
func TestV23Vkube(t *testing.T) {
	if *flagProject == "" || (*flagGetCredentials && (*flagZone == "" || *flagCluster == "")) {
		t.Skip("--project, --zone, or --cluster not specified")
	}
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}

	v23test.SkipUnlessRunningIntegrationTests(t)
	sh := v23test.NewShell(t, nil)
	defer sh.Cleanup()

	workdir := sh.MakeTempDir()

	id := fmt.Sprintf("vkube-test-%08x", rand.Uint32())

	vkubeCfgPath := filepath.Join(workdir, "vkube.cfg")
	if err := createVkubeConfig(vkubeCfgPath, id); err != nil {
		t.Fatal(err)
	}

	creds := sh.ForkCredentials("alice")

	vkubeBin := v23test.BuildGoPkg(sh, "v.io/x/ref/services/cluster/vkube")
	vshBin := v23test.BuildGoPkg(sh, "v.io/x/ref/examples/tunnel/vsh")

	var (
		cmd = func(name string, expectSuccess bool, baseArgs ...string) func(args ...string) string {
			return func(args ...string) string {
				args = append(baseArgs, args...)
				fmt.Printf("Running: %s %s\nExpect success: %v\n", name, strings.Join(args, " "), expectSuccess)
				// Note, creds do not affect non-Vanadium commands.
				c := sh.Cmd(name, args...).WithCredentials(creds)
				c.ExitErrorIsOk = true
				plw := textutil.PrefixLineWriter(os.Stdout, filepath.Base(name)+"> ")
				c.AddStdoutWriter(plw)
				c.AddStderrWriter(plw)
				output := c.CombinedOutput()
				plw.Flush()
				if expectSuccess && c.Err != nil {
					t.Error(testutil.FormatLogLine(2, "Unexpected failure: %s %s :%v", name, strings.Join(args, " "), c.Err))
				} else if !expectSuccess && c.Err == nil {
					t.Error(testutil.FormatLogLine(2, "Unexpected success %d: %s %s", name, strings.Join(args, " ")))
				}
				return output
			}
		}
		gsutil      = cmd("gsutil", true)
		gcloud      = cmd("gcloud", true, "--project="+*flagProject)
		docker      = cmd("docker", true)
		getCreds    = fmt.Sprintf("--get-credentials=%v", *flagGetCredentials)
		vkubeOK     = cmd(vkubeBin, true, "--config="+vkubeCfgPath, getCreds)
		vkubeFail   = cmd(vkubeBin, false, "--config="+vkubeCfgPath, getCreds)
		kubectlOK   = cmd(vkubeBin, true, "--config="+vkubeCfgPath, getCreds, "kubectl", "--", "--namespace="+id)
		kubectlFail = cmd(vkubeBin, false, "--config="+vkubeCfgPath, getCreds, "kubectl", "--", "--namespace="+id)
		vshOK       = cmd(vshBin, true)
	)

	if out := kubectlOK("cluster-info"); strings.Contains(out, "ERROR:") {
		// Exit early if we don't have valid credentials.
		t.Fatalf("Failed to get cluster information: %v", out)
	}

	// Create a bucket to store the docker images.
	gsutil("mb", "-p", *flagProject, "gs://"+id)
	defer func() {
		kubectlOK("delete", "namespace", id)
		gsutil("-m", "rm", "-R", "-a", "gs://"+id+"/*")
		gsutil("rb", "gs://"+id)
	}()

	// Create app's docker image and configs.
	dockerDir, err := setupDockerDirectory(workdir)
	if err != nil {
		t.Fatal(err)
	}
	appImage := "b.gcr.io/" + id + "/tunneld:latest"
	docker("build", "-t", appImage, dockerDir)
	gcloud("docker", "push", appImage)
	appConf1 := filepath.Join(workdir, "app1.json")
	if err := createAppConfig(appConf1, id, appImage, "1"); err != nil {
		t.Fatal(err)
	}
	appConf2 := filepath.Join(workdir, "app2.json")
	if err := createAppConfig(appConf2, id, appImage, "2"); err != nil {
		t.Fatal(err)
	}

	vkubeOK("build-docker-images", "-v", "-tag=test")
	// Clean up local docker images.
	docker(
		"rmi",
		"b.gcr.io/"+id+"/cluster-agent",
		"b.gcr.io/"+id+"/cluster-agent:test",
		"b.gcr.io/"+id+"/pod-agent",
		"b.gcr.io/"+id+"/pod-agent:test",
		"b.gcr.io/"+id+"/tunneld",
	)

	// Run the actual tests.
	vkubeOK("start-cluster-agent", "--wait")
	kubectlOK("get", "service", "cluster-agent")
	kubectlOK("get", "rc", "cluster-agentd-latest")
	vkubeOK("claim-cluster-agent")
	vkubeFail("start-cluster-agent") // Already running
	vkubeFail("claim-cluster-agent") // Already claimed

	vkubeOK("start", "-f", appConf1, "--wait", "my-app")
	kubectlOK("get", "rc", "tunneld-1")
	vkubeFail("start", "-f", appConf1, "my-app") // Already running

	vkubeOK("update", "-f", appConf2, "--wait")
	kubectlOK("get", "rc", "tunneld-2")

	// Find the pod running tunneld, get the server's addr from its stdout.
	podName := kubectlOK("get", "pod", "-l", "application=tunneld", "--template={{range .items}}{{.metadata.name}}{{end}}")
	var addr string
	for _, log := range strings.Split(kubectlOK("logs", podName, "-c", "tunneld"), "\n") {
		if strings.HasPrefix(log, "NAME=") {
			addr = strings.TrimPrefix(log, "NAME=")
			break
		}
	}
	if got, expected := vshOK(addr, "echo", "hello", "world"), "hello world\n"; got != expected {
		t.Errorf("Unexpected output. Got %q, expected %q", got, expected)
	}

	vkubeOK("stop", "-f", appConf2)
	kubectlFail("get", "rc", "tunneld-2") // No longer running
	vkubeFail("stop", "-f", appConf2)     // No longer running

	vkubeOK("stop-cluster-agent")
	kubectlFail("get", "service", "cluster-agent")
	kubectlFail("get", "rc", "cluster-agentd-latest")
}

func createVkubeConfig(path, id string) error {
	f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0644)
	if err != nil {
		return err
	}
	defer f.Close()

	params := struct{ Project, Zone, Cluster, ID string }{*flagProject, *flagZone, *flagCluster, id}
	return template.Must(template.New("cfg").Parse(`{
  "project": "{{.Project}}",
  "zone": "{{.Zone}}",
  "cluster": "{{.Cluster}}",
  "clusterAgent": {
    "namespace": "{{.ID}}",
    "image": "b.gcr.io/{{.ID}}/cluster-agent:latest",
    "blessing": "root:alice:cluster-agent",
    "admin": "root:alice",
    "cpu": "0.1",
    "memory": "100M"
  },
  "podAgent": {
    "image": "b.gcr.io/{{.ID}}/pod-agent:latest"
  }
}`)).Execute(f, params)
}

func setupDockerDirectory(workdir string) (string, error) {
	dockerDir := filepath.Join(workdir, "docker")
	if err := os.Mkdir(dockerDir, 0755); err != nil {
		return "", err
	}
	if err := ioutil.WriteFile(
		filepath.Join(dockerDir, "Dockerfile"),
		[]byte("FROM busybox\nCOPY tunneld /usr/local/bin/\n"),
		0644,
	); err != nil {
		return "", err
	}
	if out, err := exec.Command("jiri", "go", "build",
		"-o", filepath.Join(dockerDir, "tunneld"),
		// TODO(rthellend): Remove -tags noopenssl after we move to Go 1.6.
		"-tags", "noopenssl",
		"-ldflags", "-extldflags \"-static\"",
		"v.io/x/ref/examples/tunnel/tunneld").CombinedOutput(); err != nil {
		return "", fmt.Errorf("build failed: %v: %s", err, string(out))
	}
	return dockerDir, nil
}

func createAppConfig(path, id, image, version string) error {
	f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0644)
	if err != nil {
		return err
	}
	defer f.Close()

	params := struct{ ID, Image, Version string }{id, image, version}
	return template.Must(template.New("appcfg").Parse(`{
  "apiVersion": "v1",
  "kind": "ReplicationController",
  "metadata": {
    "name": "tunneld-{{.Version}}",
    "namespace": "{{.ID}}",
    "labels": {
      "application": "tunneld"
    }
  },
  "spec": {
    "replicas": 1,
    "template": {
      "metadata": {
        "labels": {
          "application": "tunneld",
          "version": "{{.Version}}"
        }
      },
      "spec": {
        "containers": [
          {
            "name": "tunneld",
            "image": "{{.Image}}",
            "command": [
              "tunneld",
              "--v23.tcp.address=:8193",
              "--v23.permissions.literal={\"Admin\":{\"In\":[\"root:alice\"]}}",
	      "--alsologtostderr=false"
            ],
            "ports": [
              { "containerPort": 8193, "hostPort": 8193 }
            ],
            "resources": {
              "limits": { "cpu": "0.1", "memory": "100M" }
            }
          }
        ]
      }
    }
  }
}`)).Execute(f, params)
}

func TestMain(m *testing.M) {
	v23test.TestMain(m)
}
<|endoftext|>


<commit_before>//
// DISCLAIMER
//
// Copyright 2017 ArangoDB GmbH, Cologne, Germany
//
// 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.
//
// Copyright holder is ArangoDB GmbH, Cologne, Germany
//
// Author Ewout Prangsma
//

package test

import (
	"context"
	"testing"
	"time"

	driver "github.com/arangodb/go-driver"
)

// TestClusterHealth tests the Cluster.Health method.
func TestClusterHealth(t *testing.T) {
	ctx := context.Background()
	c := createClientFromEnv(t, true)
	cl, err := c.Cluster(ctx)
	if driver.IsPreconditionFailed(err) {
		t.Skip("Not a cluster")
	} else {
		h, err := cl.Health(ctx)
		if err != nil {
			t.Fatalf("Health failed: %s", describe(err))
		}
		if h.ID == "" {
			t.Error("Expected cluster ID to be non-empty")
		}
		agents := 0
		dbservers := 0
		coordinators := 0
		for _, sh := range h.Health {
			switch sh.Role {
			case driver.ServerRoleAgent:
				agents++
			case driver.ServerRoleDBServer:
				dbservers++
			case driver.ServerRoleCoordinator:
				coordinators++
			}
		}
		if agents == 0 {
			t.Error("Expected at least 1 agent")
		}
		if dbservers == 0 {
			t.Error("Expected at least 1 dbserver")
		}
		if coordinators == 0 {
			t.Error("Expected at least 1 coordinator")
		}
	}
}

// TestClusterDatabaseInventory tests the Cluster.DatabaseInventory method.
func TestClusterDatabaseInventory(t *testing.T) {
	ctx := context.Background()
	c := createClientFromEnv(t, true)
	cl, err := c.Cluster(ctx)
	if driver.IsPreconditionFailed(err) {
		t.Skip("Not a cluster")
	} else {
		db, err := c.Database(ctx, "_system")
		if err != nil {
			t.Fatalf("Failed to open _system database: %s", describe(err))
		}
		h, err := cl.Health(ctx)
		if err != nil {
			t.Fatalf("Health failed: %s", describe(err))
		}
		inv, err := cl.DatabaseInventory(ctx, db)
		if err != nil {
			t.Fatalf("DatabaseInventory failed: %s", describe(err))
		}
		if len(inv.Collections) == 0 {
			t.Error("Expected multiple collections, got 0")
		}
		for _, col := range inv.Collections {
			if len(col.Parameters.Shards) == 0 {
				t.Errorf("Expected 1 or more shards in collection %s, got 0", col.Parameters.Name)
			}
			for shardID, dbServers := range col.Parameters.Shards {
				for _, serverID := range dbServers {
					if _, found := h.Health[serverID]; !found {
						t.Errorf("Unexpected dbserver ID for shard '%s': %s", shardID, serverID)
					}
				}
			}
		}
	}
}

// TestClusterMoveShard tests the Cluster.MoveShard method.
func TestClusterMoveShard(t *testing.T) {
	ctx := context.Background()
	c := createClientFromEnv(t, true)
	cl, err := c.Cluster(ctx)
	if driver.IsPreconditionFailed(err) {
		t.Skip("Not a cluster")
	} else {
		db, err := c.Database(ctx, "_system")
		if err != nil {
			t.Fatalf("Failed to open _system database: %s", describe(err))
		}
		col, err := db.CreateCollection(ctx, "test_move_shard", &driver.CreateCollectionOptions{
			NumberOfShards: 12,
		})
		if err != nil {
			t.Fatalf("CreateCollection failed: %s", describe(err))
		}
		h, err := cl.Health(ctx)
		if err != nil {
			t.Fatalf("Health failed: %s", describe(err))
		}
		inv, err := cl.DatabaseInventory(ctx, db)
		if err != nil {
			t.Fatalf("DatabaseInventory failed: %s", describe(err))
		}
		if len(inv.Collections) == 0 {
			t.Error("Expected multiple collections, got 0")
		}
		var targetServerID driver.ServerID
		for id, s := range h.Health {
			if s.Role == driver.ServerRoleDBServer {
				targetServerID = id
				break
			}
		}
		if len(targetServerID) == 0 {
			t.Fatalf("Failed to find any dbserver")
		}
		movedShards := 0
		for _, colInv := range inv.Collections {
			if colInv.Parameters.Name == col.Name() {
				for shardID, dbServers := range colInv.Parameters.Shards {
					if dbServers[0] != targetServerID {
						movedShards++
						var rawResponse []byte
						if err := cl.MoveShard(driver.WithRawResponse(ctx, &rawResponse), col, shardID, dbServers[0], targetServerID); err != nil {
							t.Errorf("MoveShard for shard %s in collection %s failed: %s (raw response '%s')", shardID, col.Name(), describe(err), string(rawResponse))
						}
					}
				}
			}
		}
		if movedShards == 0 {
			t.Fatal("Expected to have moved at least 1 shard, all seem to be on target server already")
		}
		// Wait until all shards are on the targetServerID
		start := time.Now()
		maxTestTime := time.Minute
		lastShardsNotOnTargetServerID := movedShards
		for {
			shardsNotOnTargetServerID := 0
			inv, err := cl.DatabaseInventory(ctx, db)
			if err != nil {
				t.Errorf("DatabaseInventory failed: %s", describe(err))
			} else {
				for _, colInv := range inv.Collections {
					if colInv.Parameters.Name == col.Name() {
						for shardID, dbServers := range colInv.Parameters.Shards {
							if dbServers[0] != targetServerID {
								shardsNotOnTargetServerID++
								t.Logf("Shard %s in on %s, wanted %s", shardID, dbServers[0], targetServerID)
							}
						}
					}
				}
			}
			if shardsNotOnTargetServerID == 0 {
				// We're done
				break
			}
			if shardsNotOnTargetServerID != lastShardsNotOnTargetServerID {
				// Something changed, we give a bit more time
				maxTestTime = maxTestTime + time.Second*15
				lastShardsNotOnTargetServerID = shardsNotOnTargetServerID
			}
			if time.Since(start) > maxTestTime {
				t.Errorf("%d shards did not move within %s", shardsNotOnTargetServerID, maxTestTime)
				break
			}
			t.Log("Waiting a bit")
			time.Sleep(time.Second * 5)
		}
	}
}
<commit_msg>Include raw hex response<commit_after>//
// DISCLAIMER
//
// Copyright 2017 ArangoDB GmbH, Cologne, Germany
//
// 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.
//
// Copyright holder is ArangoDB GmbH, Cologne, Germany
//
// Author Ewout Prangsma
//

package test

import (
	"context"
	"testing"
	"time"

	driver "github.com/arangodb/go-driver"
)

// TestClusterHealth tests the Cluster.Health method.
func TestClusterHealth(t *testing.T) {
	ctx := context.Background()
	c := createClientFromEnv(t, true)
	cl, err := c.Cluster(ctx)
	if driver.IsPreconditionFailed(err) {
		t.Skip("Not a cluster")
	} else {
		h, err := cl.Health(ctx)
		if err != nil {
			t.Fatalf("Health failed: %s", describe(err))
		}
		if h.ID == "" {
			t.Error("Expected cluster ID to be non-empty")
		}
		agents := 0
		dbservers := 0
		coordinators := 0
		for _, sh := range h.Health {
			switch sh.Role {
			case driver.ServerRoleAgent:
				agents++
			case driver.ServerRoleDBServer:
				dbservers++
			case driver.ServerRoleCoordinator:
				coordinators++
			}
		}
		if agents == 0 {
			t.Error("Expected at least 1 agent")
		}
		if dbservers == 0 {
			t.Error("Expected at least 1 dbserver")
		}
		if coordinators == 0 {
			t.Error("Expected at least 1 coordinator")
		}
	}
}

// TestClusterDatabaseInventory tests the Cluster.DatabaseInventory method.
func TestClusterDatabaseInventory(t *testing.T) {
	ctx := context.Background()
	c := createClientFromEnv(t, true)
	cl, err := c.Cluster(ctx)
	if driver.IsPreconditionFailed(err) {
		t.Skip("Not a cluster")
	} else {
		db, err := c.Database(ctx, "_system")
		if err != nil {
			t.Fatalf("Failed to open _system database: %s", describe(err))
		}
		h, err := cl.Health(ctx)
		if err != nil {
			t.Fatalf("Health failed: %s", describe(err))
		}
		inv, err := cl.DatabaseInventory(ctx, db)
		if err != nil {
			t.Fatalf("DatabaseInventory failed: %s", describe(err))
		}
		if len(inv.Collections) == 0 {
			t.Error("Expected multiple collections, got 0")
		}
		for _, col := range inv.Collections {
			if len(col.Parameters.Shards) == 0 {
				t.Errorf("Expected 1 or more shards in collection %s, got 0", col.Parameters.Name)
			}
			for shardID, dbServers := range col.Parameters.Shards {
				for _, serverID := range dbServers {
					if _, found := h.Health[serverID]; !found {
						t.Errorf("Unexpected dbserver ID for shard '%s': %s", shardID, serverID)
					}
				}
			}
		}
	}
}

// TestClusterMoveShard tests the Cluster.MoveShard method.
func TestClusterMoveShard(t *testing.T) {
	ctx := context.Background()
	c := createClientFromEnv(t, true)
	cl, err := c.Cluster(ctx)
	if driver.IsPreconditionFailed(err) {
		t.Skip("Not a cluster")
	} else {
		db, err := c.Database(ctx, "_system")
		if err != nil {
			t.Fatalf("Failed to open _system database: %s", describe(err))
		}
		col, err := db.CreateCollection(ctx, "test_move_shard", &driver.CreateCollectionOptions{
			NumberOfShards: 12,
		})
		if err != nil {
			t.Fatalf("CreateCollection failed: %s", describe(err))
		}
		h, err := cl.Health(ctx)
		if err != nil {
			t.Fatalf("Health failed: %s", describe(err))
		}
		inv, err := cl.DatabaseInventory(ctx, db)
		if err != nil {
			t.Fatalf("DatabaseInventory failed: %s", describe(err))
		}
		if len(inv.Collections) == 0 {
			t.Error("Expected multiple collections, got 0")
		}
		var targetServerID driver.ServerID
		for id, s := range h.Health {
			if s.Role == driver.ServerRoleDBServer {
				targetServerID = id
				break
			}
		}
		if len(targetServerID) == 0 {
			t.Fatalf("Failed to find any dbserver")
		}
		movedShards := 0
		for _, colInv := range inv.Collections {
			if colInv.Parameters.Name == col.Name() {
				for shardID, dbServers := range colInv.Parameters.Shards {
					if dbServers[0] != targetServerID {
						movedShards++
						var rawResponse []byte
						if err := cl.MoveShard(driver.WithRawResponse(ctx, &rawResponse), col, shardID, dbServers[0], targetServerID); err != nil {
							t.Errorf("MoveShard for shard %s in collection %s failed: %s (raw response '%s' %x)", shardID, col.Name(), describe(err), string(rawResponse), rawResponse)
						}
					}
				}
			}
		}
		if movedShards == 0 {
			t.Fatal("Expected to have moved at least 1 shard, all seem to be on target server already")
		}
		// Wait until all shards are on the targetServerID
		start := time.Now()
		maxTestTime := time.Minute
		lastShardsNotOnTargetServerID := movedShards
		for {
			shardsNotOnTargetServerID := 0
			inv, err := cl.DatabaseInventory(ctx, db)
			if err != nil {
				t.Errorf("DatabaseInventory failed: %s", describe(err))
			} else {
				for _, colInv := range inv.Collections {
					if colInv.Parameters.Name == col.Name() {
						for shardID, dbServers := range colInv.Parameters.Shards {
							if dbServers[0] != targetServerID {
								shardsNotOnTargetServerID++
								t.Logf("Shard %s in on %s, wanted %s", shardID, dbServers[0], targetServerID)
							}
						}
					}
				}
			}
			if shardsNotOnTargetServerID == 0 {
				// We're done
				break
			}
			if shardsNotOnTargetServerID != lastShardsNotOnTargetServerID {
				// Something changed, we give a bit more time
				maxTestTime = maxTestTime + time.Second*15
				lastShardsNotOnTargetServerID = shardsNotOnTargetServerID
			}
			if time.Since(start) > maxTestTime {
				t.Errorf("%d shards did not move within %s", shardsNotOnTargetServerID, maxTestTime)
				break
			}
			t.Log("Waiting a bit")
			time.Sleep(time.Second * 5)
		}
	}
}
<|endoftext|>


<commit_before>package tap_test

import (
	"errors"
	"os/exec"
	"syscall"
	"testing"

	"github.com/bobuhiro11/gokvm/tap"
)

func TestNew(t *testing.T) { // nolint:paralleltest
	tap, err := tap.New("test_tap")
	if err != nil {
		t.Fatal(err)
	}

	err = tap.Close()
	if err != nil {
		t.Fatal(err)
	}
}

func TestWrite(t *testing.T) { // nolint:paralleltest
	tap, err := tap.New("test_write")
	if err != nil {
		t.Fatal(err)
	}

	if err := exec.Command("ip", "link", "set", "test_write", "up").Run(); err != nil {
		t.Fatal(err)
	}

	if _, err := tap.Write(make([]byte, 20)); err != nil {
		t.Fatal(err)
	}

	_ = tap.Close()
}

func TestRead(t *testing.T) { // nolint:paralleltest
	tap, err := tap.New("test_read")
	if err != nil {
		t.Fatal(err)
	}

	if err := exec.Command("ip", "link", "set", "test_read", "up").Run(); err != nil {
		t.Fatal(err)
	}

	buf := make([]byte, 20)
	if _, err := tap.Read(buf); !errors.Is(err, syscall.EAGAIN) {
		t.Fatal(err)
	}

	_ = tap.Close()
}
<commit_msg>tap_test: do not do the tests if we are not root<commit_after>package tap_test

import (
	"errors"
	"os"
	"os/exec"
	"syscall"
	"testing"

	"github.com/bobuhiro11/gokvm/tap"
)

func TestNew(t *testing.T) { // nolint:paralleltest
	if os.Getuid() != 0 {
		t.Skipf("Skipping test since we are not root")
	}

	tap, err := tap.New("test_tap")
	if err != nil {
		t.Fatal(err)
	}

	err = tap.Close()
	if err != nil {
		t.Fatal(err)
	}
}

func TestWrite(t *testing.T) { // nolint:paralleltest
	if os.Getuid() != 0 {
		t.Skipf("Skipping test since we are not root")
	}

	tap, err := tap.New("test_write")
	if err != nil {
		t.Fatal(err)
	}

	if err := exec.Command("ip", "link", "set", "test_write", "up").Run(); err != nil {
		t.Fatal(err)
	}

	if _, err := tap.Write(make([]byte, 20)); err != nil {
		t.Fatal(err)
	}

	if err := tap.Close(); err != nil {
		t.Fatal(err)
	}
}

func TestRead(t *testing.T) { // nolint:paralleltest
	if os.Getuid() != 0 {
		t.Skipf("Skipping test since we are not root")
	}

	tap, err := tap.New("test_read")
	if err != nil {
		t.Fatal(err)
	}

	if err := exec.Command("ip", "link", "set", "test_read", "up").Run(); err != nil {
		t.Fatal(err)
	}

	buf := make([]byte, 20)
	if _, err := tap.Read(buf); !errors.Is(err, syscall.EAGAIN) {
		t.Fatal(err)
	}

	if err := tap.Close(); err != nil {
		t.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package client

import (
	"encoding/base64"
	"encoding/json"
	"io"
	"net/http"
	"net/url"
	"regexp"
	"strconv"
	"strings"

	"golang.org/x/net/context"

	"github.com/docker/engine-api/types"
	"github.com/docker/engine-api/types/container"
)

var headerRegexp = regexp.MustCompile(`\ADocker/.+\s\((.+)\)\z`)

// ImageBuild sends request to the daemon to build images.
// The Body in the response implement an io.ReadCloser and it's up to the caller to
// close it.
func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) {
	query, err := imageBuildOptionsToQuery(options)
	if err != nil {
		return types.ImageBuildResponse{}, err
	}

	headers := http.Header(make(map[string][]string))
	buf, err := json.Marshal(options.AuthConfigs)
	if err != nil {
		return types.ImageBuildResponse{}, err
	}
	headers.Add("X-Registry-Config", base64.URLEncoding.EncodeToString(buf))
	headers.Set("Content-Type", "application/tar")

	serverResp, err := cli.postRaw(ctx, "/build", query, buildContext, headers)
	if err != nil {
		return types.ImageBuildResponse{}, err
	}

	osType := getDockerOS(serverResp.header.Get("Server"))

	return types.ImageBuildResponse{
		Body:   serverResp.body,
		OSType: osType,
	}, nil
}

func imageBuildOptionsToQuery(options types.ImageBuildOptions) (url.Values, error) {
	query := url.Values{
		"t": options.Tags,
	}
	if options.SuppressOutput {
		query.Set("q", "1")
	}
	if options.RemoteContext != "" {
		query.Set("remote", options.RemoteContext)
	}
	if options.NoCache {
		query.Set("nocache", "1")
	}
	if options.Remove {
		query.Set("rm", "1")
	} else {
		query.Set("rm", "0")
	}

	if options.ForceRemove {
		query.Set("forcerm", "1")
	}

	if options.PullParent {
		query.Set("pull", "1")
	}

	if !container.Isolation.IsDefault(options.Isolation) {
		query.Set("isolation", string(options.Isolation))
	}

	query.Set("cpusetcpus", options.CPUSetCPUs)
	query.Set("cpusetmems", options.CPUSetMems)
	query.Set("cpushares", strconv.FormatInt(options.CPUShares, 10))
	query.Set("cpuquota", strconv.FormatInt(options.CPUQuota, 10))
	query.Set("cpuperiod", strconv.FormatInt(options.CPUPeriod, 10))
	query.Set("memory", strconv.FormatInt(options.Memory, 10))
	query.Set("memswap", strconv.FormatInt(options.MemorySwap, 10))
	query.Set("cgroupparent", options.CgroupParent)
	query.Set("shmsize", strconv.FormatInt(options.ShmSize, 10))
	query.Set("dockerfile", options.Dockerfile)

	ulimitsJSON, err := json.Marshal(options.Ulimits)
	if err != nil {
		return query, err
	}
	query.Set("ulimits", string(ulimitsJSON))

	buildArgsJSON, err := json.Marshal(options.BuildArgs)
	if err != nil {
		return query, err
	}
	query.Set("buildargs", string(buildArgsJSON))

	labelsJSON, err := json.Marshal(options.Labels)
	if err != nil {
		return query, err
	}
	query.Set("labels", string(labelsJSON))
	return query, nil
}

func getDockerOS(serverHeader string) string {
	var osType string
	matches := headerRegexp.FindStringSubmatch(serverHeader)
	if len(matches) > 0 {
		osType = matches[1]
	}
	return osType
}

// convertKVStringsToMap converts ["key=value"] to {"key":"value"}
func convertKVStringsToMap(values []string) map[string]string {
	result := make(map[string]string, len(values))
	for _, value := range values {
		kv := strings.SplitN(value, "=", 2)
		if len(kv) == 1 {
			result[kv[0]] = ""
		} else {
			result[kv[0]] = kv[1]
		}
	}

	return result
}
<commit_msg>Remove some dead code.<commit_after>package client

import (
	"encoding/base64"
	"encoding/json"
	"io"
	"net/http"
	"net/url"
	"regexp"
	"strconv"

	"golang.org/x/net/context"

	"github.com/docker/engine-api/types"
	"github.com/docker/engine-api/types/container"
)

var headerRegexp = regexp.MustCompile(`\ADocker/.+\s\((.+)\)\z`)

// ImageBuild sends request to the daemon to build images.
// The Body in the response implement an io.ReadCloser and it's up to the caller to
// close it.
func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) {
	query, err := imageBuildOptionsToQuery(options)
	if err != nil {
		return types.ImageBuildResponse{}, err
	}

	headers := http.Header(make(map[string][]string))
	buf, err := json.Marshal(options.AuthConfigs)
	if err != nil {
		return types.ImageBuildResponse{}, err
	}
	headers.Add("X-Registry-Config", base64.URLEncoding.EncodeToString(buf))
	headers.Set("Content-Type", "application/tar")

	serverResp, err := cli.postRaw(ctx, "/build", query, buildContext, headers)
	if err != nil {
		return types.ImageBuildResponse{}, err
	}

	osType := getDockerOS(serverResp.header.Get("Server"))

	return types.ImageBuildResponse{
		Body:   serverResp.body,
		OSType: osType,
	}, nil
}

func imageBuildOptionsToQuery(options types.ImageBuildOptions) (url.Values, error) {
	query := url.Values{
		"t": options.Tags,
	}
	if options.SuppressOutput {
		query.Set("q", "1")
	}
	if options.RemoteContext != "" {
		query.Set("remote", options.RemoteContext)
	}
	if options.NoCache {
		query.Set("nocache", "1")
	}
	if options.Remove {
		query.Set("rm", "1")
	} else {
		query.Set("rm", "0")
	}

	if options.ForceRemove {
		query.Set("forcerm", "1")
	}

	if options.PullParent {
		query.Set("pull", "1")
	}

	if !container.Isolation.IsDefault(options.Isolation) {
		query.Set("isolation", string(options.Isolation))
	}

	query.Set("cpusetcpus", options.CPUSetCPUs)
	query.Set("cpusetmems", options.CPUSetMems)
	query.Set("cpushares", strconv.FormatInt(options.CPUShares, 10))
	query.Set("cpuquota", strconv.FormatInt(options.CPUQuota, 10))
	query.Set("cpuperiod", strconv.FormatInt(options.CPUPeriod, 10))
	query.Set("memory", strconv.FormatInt(options.Memory, 10))
	query.Set("memswap", strconv.FormatInt(options.MemorySwap, 10))
	query.Set("cgroupparent", options.CgroupParent)
	query.Set("shmsize", strconv.FormatInt(options.ShmSize, 10))
	query.Set("dockerfile", options.Dockerfile)

	ulimitsJSON, err := json.Marshal(options.Ulimits)
	if err != nil {
		return query, err
	}
	query.Set("ulimits", string(ulimitsJSON))

	buildArgsJSON, err := json.Marshal(options.BuildArgs)
	if err != nil {
		return query, err
	}
	query.Set("buildargs", string(buildArgsJSON))

	labelsJSON, err := json.Marshal(options.Labels)
	if err != nil {
		return query, err
	}
	query.Set("labels", string(labelsJSON))
	return query, nil
}

func getDockerOS(serverHeader string) string {
	var osType string
	matches := headerRegexp.FindStringSubmatch(serverHeader)
	if len(matches) > 0 {
		osType = matches[1]
	}
	return osType
}
<|endoftext|>


<commit_before>package kiwi

// Convert incoming values to string representation. For keys and values.

/* Copyright (c) 2016, Alexander I.Grafov aka Axel
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

* Neither the name of kvlog nor the names of its
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

ॐ तारे तुत्तारे तुरे स्व */

import (
	"encoding"
	"fmt"
	"strconv"
	"time"
)

const (
	deleted = iota - 1
	BooleanVal
	IntegerVal
	FloatVal
	ComplexVal
	CustomUnquoted
	VoidVal
	StringVal
	TimeVal
	CustomQuoted
)

// FloatFormat used in Float to String conversion.
// It is second parameter passed to strconv.FormatFloat()
var FloatFormat byte = 'e'

// TimeLayout used in time.Time to String conversion.
var TimeLayout = time.RFC3339

// it applicable for all scalar types and for strings
func toKey(val interface{}) string {
	switch val.(type) {
	case string:
		return val.(string)
	case []byte:
		return string(val.([]byte))
	case fmt.Stringer:
		return val.(fmt.Stringer).String()
	case encoding.TextMarshaler:
		data, err := val.(encoding.TextMarshaler).MarshalText()
		if err != nil {
			return fmt.Sprintf("%s", err)
		}
		return string(data)
	case bool:
		if val.(bool) {
			return "true"
		}
		return "false"
	case int:
		return strconv.Itoa(val.(int))
	case int8:
		return strconv.FormatInt(int64(val.(int8)), 10)
	case int16:
		return strconv.FormatInt(int64(val.(int16)), 10)
	case int32:
		return strconv.FormatInt(int64(val.(int32)), 10)
	case int64:
		return strconv.FormatInt(val.(int64), 10)
	case uint:
		return strconv.FormatUint(uint64(val.(uint)), 10)
	case uint8:
		return strconv.FormatUint(uint64(val.(uint8)), 10)
	case uint16:
		return strconv.FormatUint(uint64(val.(uint16)), 10)
	case uint32:
		return strconv.FormatUint(uint64(val.(uint32)), 10)
	case uint64:
		return strconv.FormatUint(val.(uint64), 10)
	case float32:
		return strconv.FormatFloat(float64(val.(float32)), FloatFormat, -1, 32)
	case float64:
		return strconv.FormatFloat(val.(float64), FloatFormat, -1, 64)
	case complex64:
		return fmt.Sprintf("%f", val.(complex64))
	case complex128:
		return fmt.Sprintf("%f", val.(complex128))
	case time.Time:
		return val.(time.Time).Format(TimeLayout)
	case nil:
		return ""
	default:
		return fmt.Sprintf("%v", val)
	}
}

// it applicable for all scalar types and for strings
func toPair(key string, val interface{}) *pair {
	switch val.(type) {
	case string:
		return &pair{key, val.(string), nil, StringVal}
	case []byte:
		return &pair{key, string(val.([]byte)), nil, StringVal}
	case bool:
		if val.(bool) {
			return &pair{key, "true", nil, BooleanVal}
		}
		return &pair{key, "false", nil, BooleanVal}
	case int:
		return &pair{key, strconv.Itoa(val.(int)), nil, IntegerVal}
	case int8:
		return &pair{key, strconv.FormatInt(int64(val.(int8)), 10), nil, IntegerVal}
	case int16:
		return &pair{key, strconv.FormatInt(int64(val.(int16)), 10), nil, IntegerVal}
	case int32:
		return &pair{key, strconv.FormatInt(int64(val.(int32)), 10), nil, IntegerVal}
	case int64:
		return &pair{key, strconv.FormatInt(val.(int64), 10), nil, IntegerVal}
	case uint:
		return &pair{key, strconv.FormatUint(uint64(val.(uint)), 10), nil, IntegerVal}
	case uint8:
		return &pair{key, strconv.FormatUint(uint64(val.(uint8)), 10), nil, IntegerVal}
	case uint16:
		return &pair{key, strconv.FormatUint(uint64(val.(uint16)), 10), nil, IntegerVal}
	case uint32:
		return &pair{key, strconv.FormatUint(uint64(val.(uint32)), 10), nil, IntegerVal}
	case uint64:
		return &pair{key, strconv.FormatUint(val.(uint64), 10), nil, IntegerVal}
	case float32:
		return &pair{key, strconv.FormatFloat(float64(val.(float32)), FloatFormat, -1, 32), nil, FloatVal}
	case float64:
		return &pair{key, strconv.FormatFloat(val.(float64), FloatFormat, -1, 64), nil, FloatVal}
	case complex64:
		return &pair{key, fmt.Sprintf("%f", val.(complex64)), nil, ComplexVal}
	case complex128:
		return &pair{key, fmt.Sprintf("%f", val.(complex128)), nil, ComplexVal}
	case time.Time:
		return &pair{key, val.(time.Time).Format(TimeLayout), nil, TimeVal}
	case Valuer:
		var pairType = CustomUnquoted
		if val.(Valuer).IsQuoted() {
			pairType = CustomQuoted
		}
		return &pair{key, val.(Valuer).String(), nil, pairType}
	case Stringer:
		return &pair{key, val.(Stringer).String(), nil, StringVal}
	case encoding.TextMarshaler:
		data, err := val.(encoding.TextMarshaler).MarshalText()
		if err != nil {
			return &pair{key, fmt.Sprintf("%s", err), nil, StringVal}
		}
		return &pair{key, string(data), nil, StringVal}
	case func() string:
		return &pair{key, "", val.(func() string), StringVal}
	case nil:
		return &pair{key, "", nil, VoidVal}
	default:
		// Worst case conversion that depends on reflection.
		return &pair{key, fmt.Sprintf("%v", val), nil, StringVal}
	}
}
<commit_msg>Add comments for exported consts for kinds of types.<commit_after>package kiwi

// Convert incoming values to string representation. For keys and values.

/* Copyright (c) 2016, Alexander I.Grafov aka Axel
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

* Neither the name of kvlog nor the names of its
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

ॐ तारे तुत्तारे तुरे स्व */

import (
	"encoding"
	"fmt"
	"strconv"
	"time"
)

// Possible kinds of logged values.
const (
	deleted = iota - 1
	// BooleanVal and other types below commonly formatted unquoted.
	// But it depends on the formatter.
	BooleanVal
	IntegerVal
	FloatVal
	ComplexVal
	CustomUnquoted
	// VoidVal and other types below commonly formatted unquoted.
	// But it depends on the formatter.
	VoidVal
	StringVal
	TimeVal
	CustomQuoted
)

// FloatFormat used in Float to String conversion.
// It is second parameter passed to strconv.FormatFloat()
var FloatFormat byte = 'e'

// TimeLayout used in time.Time to String conversion.
var TimeLayout = time.RFC3339

// it applicable for all scalar types and for strings
func toKey(val interface{}) string {
	switch val.(type) {
	case string:
		return val.(string)
	case []byte:
		return string(val.([]byte))
	case fmt.Stringer:
		return val.(fmt.Stringer).String()
	case encoding.TextMarshaler:
		data, err := val.(encoding.TextMarshaler).MarshalText()
		if err != nil {
			return fmt.Sprintf("%s", err)
		}
		return string(data)
	case bool:
		if val.(bool) {
			return "true"
		}
		return "false"
	case int:
		return strconv.Itoa(val.(int))
	case int8:
		return strconv.FormatInt(int64(val.(int8)), 10)
	case int16:
		return strconv.FormatInt(int64(val.(int16)), 10)
	case int32:
		return strconv.FormatInt(int64(val.(int32)), 10)
	case int64:
		return strconv.FormatInt(val.(int64), 10)
	case uint:
		return strconv.FormatUint(uint64(val.(uint)), 10)
	case uint8:
		return strconv.FormatUint(uint64(val.(uint8)), 10)
	case uint16:
		return strconv.FormatUint(uint64(val.(uint16)), 10)
	case uint32:
		return strconv.FormatUint(uint64(val.(uint32)), 10)
	case uint64:
		return strconv.FormatUint(val.(uint64), 10)
	case float32:
		return strconv.FormatFloat(float64(val.(float32)), FloatFormat, -1, 32)
	case float64:
		return strconv.FormatFloat(val.(float64), FloatFormat, -1, 64)
	case complex64:
		return fmt.Sprintf("%f", val.(complex64))
	case complex128:
		return fmt.Sprintf("%f", val.(complex128))
	case time.Time:
		return val.(time.Time).Format(TimeLayout)
	case nil:
		return ""
	default:
		return fmt.Sprintf("%v", val)
	}
}

// it applicable for all scalar types and for strings
func toPair(key string, val interface{}) *pair {
	switch val.(type) {
	case string:
		return &pair{key, val.(string), nil, StringVal}
	case []byte:
		return &pair{key, string(val.([]byte)), nil, StringVal}
	case bool:
		if val.(bool) {
			return &pair{key, "true", nil, BooleanVal}
		}
		return &pair{key, "false", nil, BooleanVal}
	case int:
		return &pair{key, strconv.Itoa(val.(int)), nil, IntegerVal}
	case int8:
		return &pair{key, strconv.FormatInt(int64(val.(int8)), 10), nil, IntegerVal}
	case int16:
		return &pair{key, strconv.FormatInt(int64(val.(int16)), 10), nil, IntegerVal}
	case int32:
		return &pair{key, strconv.FormatInt(int64(val.(int32)), 10), nil, IntegerVal}
	case int64:
		return &pair{key, strconv.FormatInt(val.(int64), 10), nil, IntegerVal}
	case uint:
		return &pair{key, strconv.FormatUint(uint64(val.(uint)), 10), nil, IntegerVal}
	case uint8:
		return &pair{key, strconv.FormatUint(uint64(val.(uint8)), 10), nil, IntegerVal}
	case uint16:
		return &pair{key, strconv.FormatUint(uint64(val.(uint16)), 10), nil, IntegerVal}
	case uint32:
		return &pair{key, strconv.FormatUint(uint64(val.(uint32)), 10), nil, IntegerVal}
	case uint64:
		return &pair{key, strconv.FormatUint(val.(uint64), 10), nil, IntegerVal}
	case float32:
		return &pair{key, strconv.FormatFloat(float64(val.(float32)), FloatFormat, -1, 32), nil, FloatVal}
	case float64:
		return &pair{key, strconv.FormatFloat(val.(float64), FloatFormat, -1, 64), nil, FloatVal}
	case complex64:
		return &pair{key, fmt.Sprintf("%f", val.(complex64)), nil, ComplexVal}
	case complex128:
		return &pair{key, fmt.Sprintf("%f", val.(complex128)), nil, ComplexVal}
	case time.Time:
		return &pair{key, val.(time.Time).Format(TimeLayout), nil, TimeVal}
	case Valuer:
		var pairType = CustomUnquoted
		if val.(Valuer).IsQuoted() {
			pairType = CustomQuoted
		}
		return &pair{key, val.(Valuer).String(), nil, pairType}
	case Stringer:
		return &pair{key, val.(Stringer).String(), nil, StringVal}
	case encoding.TextMarshaler:
		data, err := val.(encoding.TextMarshaler).MarshalText()
		if err != nil {
			return &pair{key, fmt.Sprintf("%s", err), nil, StringVal}
		}
		return &pair{key, string(data), nil, StringVal}
	case func() string:
		return &pair{key, "", val.(func() string), StringVal}
	case nil:
		return &pair{key, "", nil, VoidVal}
	default:
		// Worst case conversion that depends on reflection.
		return &pair{key, fmt.Sprintf("%v", val), nil, StringVal}
	}
}
<|endoftext|>


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

package ipv6_test

import (
	"code.google.com/p/go.net/ipv6"
	"fmt"
	"net"
	"os"
	"runtime"
	"testing"
)

var udpMultipleGroupListenerTests = []net.Addr{
	&net.UDPAddr{IP: net.ParseIP("ff02::114")}, // see RFC 4727
	&net.UDPAddr{IP: net.ParseIP("ff02::1:114")},
	&net.UDPAddr{IP: net.ParseIP("ff02::2:114")},
}

func TestUDPSinglePacketConnWithMultipleGroupListeners(t *testing.T) {
	switch runtime.GOOS {
	case "plan9", "windows":
		t.Skipf("not supported on %q", runtime.GOOS)
	}
	if !supportsIPv6 {
		t.Skip("ipv6 is not supported")
	}

	for _, gaddr := range udpMultipleGroupListenerTests {
		c, err := net.ListenPacket("udp6", "[::]:0") // wildcard address with non-reusable port
		if err != nil {
			t.Fatalf("net.ListenPacket failed: %v", err)
		}
		defer c.Close()

		p := ipv6.NewPacketConn(c)
		var mift []*net.Interface

		ift, err := net.Interfaces()
		if err != nil {
			t.Fatalf("net.Interfaces failed: %v", err)
		}
		for i, ifi := range ift {
			if _, ok := isMulticastAvailable(&ifi); !ok {
				continue
			}
			if err := p.JoinGroup(&ifi, gaddr); err != nil {
				t.Fatalf("ipv6.PacketConn.JoinGroup %v on %v failed: %v", gaddr, ifi, err)
			}
			mift = append(mift, &ift[i])
		}
		for _, ifi := range mift {
			if err := p.LeaveGroup(ifi, gaddr); err != nil {
				t.Fatalf("ipv6.PacketConn.LeaveGroup %v on %v failed: %v", gaddr, ifi, err)
			}
		}
	}
}

func TestUDPMultipleConnWithMultipleGroupListeners(t *testing.T) {
	switch runtime.GOOS {
	case "plan9", "windows":
		t.Skipf("not supported on %q", runtime.GOOS)
	}
	if !supportsIPv6 {
		t.Skip("ipv6 is not supported")
	}

	for _, gaddr := range udpMultipleGroupListenerTests {
		c1, err := net.ListenPacket("udp6", "[ff02::]:1024") // wildcard address with reusable port
		if err != nil {
			t.Fatalf("net.ListenPacket failed: %v", err)
		}
		defer c1.Close()

		c2, err := net.ListenPacket("udp6", "[ff02::]:1024") // wildcard address with reusable port
		if err != nil {
			t.Fatalf("net.ListenPacket failed: %v", err)
		}
		defer c2.Close()

		var ps [2]*ipv6.PacketConn
		ps[0] = ipv6.NewPacketConn(c1)
		ps[1] = ipv6.NewPacketConn(c2)
		var mift []*net.Interface

		ift, err := net.Interfaces()
		if err != nil {
			t.Fatalf("net.Interfaces failed: %v", err)
		}
		for i, ifi := range ift {
			if _, ok := isMulticastAvailable(&ifi); !ok {
				continue
			}
			for _, p := range ps {
				if err := p.JoinGroup(&ifi, gaddr); err != nil {
					t.Fatalf("ipv6.PacketConn.JoinGroup %v on %v failed: %v", gaddr, ifi, err)
				}
			}
			mift = append(mift, &ift[i])
		}
		for _, ifi := range mift {
			for _, p := range ps {
				if err := p.LeaveGroup(ifi, gaddr); err != nil {
					t.Fatalf("ipv6.PacketConn.LeaveGroup %v on %v failed: %v", gaddr, ifi, err)
				}
			}
		}
	}
}

func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) {
	switch runtime.GOOS {
	case "plan9", "windows":
		t.Skipf("not supported on %q", runtime.GOOS)
	}
	if !supportsIPv6 {
		t.Skip("ipv6 is not supported")
	}

	gaddr := &net.IPAddr{IP: net.ParseIP("ff02::114")} // see RFC 4727
	type ml struct {
		c   *ipv6.PacketConn
		ifi *net.Interface
	}
	var mlt []*ml

	ift, err := net.Interfaces()
	if err != nil {
		t.Fatalf("net.Interfaces failed: %v", err)
	}
	for i, ifi := range ift {
		ip, ok := isMulticastAvailable(&ifi)
		if !ok {
			continue
		}
		c, err := net.ListenPacket("udp6", fmt.Sprintf("[%s%%%s]:1024", ip.String(), ifi.Name)) // unicast address with non-reusable port
		if err != nil {
			t.Fatalf("net.ListenPacket with %v failed: %v", ip, err)
		}
		defer c.Close()
		p := ipv6.NewPacketConn(c)
		if err := p.JoinGroup(&ifi, gaddr); err != nil {
			t.Fatalf("ipv6.PacketConn.JoinGroup on %v failed: %v", ifi, err)
		}
		mlt = append(mlt, &ml{p, &ift[i]})
	}
	for _, m := range mlt {
		if err := m.c.LeaveGroup(m.ifi, gaddr); err != nil {
			t.Fatalf("ipv6.PacketConn.LeaveGroup on %v failed: %v", m.ifi, err)
		}
	}
}

func TestIPSinglePacketConnWithSingleGroupListener(t *testing.T) {
	switch runtime.GOOS {
	case "plan9", "windows":
		t.Skipf("not supported on %q", runtime.GOOS)
	}
	if !supportsIPv6 {
		t.Skip("ipv6 is not supported")
	}
	if os.Getuid() != 0 {
		t.Skip("must be root")
	}

	c, err := net.ListenPacket("ip6:ipv6-icmp", "::")
	if err != nil {
		t.Fatalf("net.ListenPacket failed: %v", err)
	}
	defer c.Close()

	p := ipv6.NewPacketConn(c)
	gaddr := &net.IPAddr{IP: net.ParseIP("ff02::114")} // see RFC 4727
	var mift []*net.Interface

	ift, err := net.Interfaces()
	if err != nil {
		t.Fatalf("net.Interfaces failed: %v", err)
	}
	for i, ifi := range ift {
		if _, ok := isMulticastAvailable(&ifi); !ok {
			continue
		}
		if err := p.JoinGroup(&ifi, gaddr); err != nil {
			t.Fatalf("ipv6.PacketConn.JoinGroup on %v failed: %v", ifi, err)
		}
		mift = append(mift, &ift[i])
	}
	for _, ifi := range mift {
		if err := p.LeaveGroup(ifi, gaddr); err != nil {
			t.Fatalf("ipv6.PacketConn.LeaveGroup on %v failed: %v", ifi, err)
		}
	}
}
<commit_msg>go.net/ipv6: add missing per interface multicast listener test<commit_after>// Copyright 2013 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package ipv6_test

import (
	"code.google.com/p/go.net/ipv6"
	"fmt"
	"net"
	"os"
	"runtime"
	"testing"
)

var udpMultipleGroupListenerTests = []net.Addr{
	&net.UDPAddr{IP: net.ParseIP("ff02::114")}, // see RFC 4727
	&net.UDPAddr{IP: net.ParseIP("ff02::1:114")},
	&net.UDPAddr{IP: net.ParseIP("ff02::2:114")},
}

func TestUDPSinglePacketConnWithMultipleGroupListeners(t *testing.T) {
	switch runtime.GOOS {
	case "plan9", "windows":
		t.Skipf("not supported on %q", runtime.GOOS)
	}
	if !supportsIPv6 {
		t.Skip("ipv6 is not supported")
	}

	for _, gaddr := range udpMultipleGroupListenerTests {
		c, err := net.ListenPacket("udp6", "[::]:0") // wildcard address with non-reusable port
		if err != nil {
			t.Fatalf("net.ListenPacket failed: %v", err)
		}
		defer c.Close()

		p := ipv6.NewPacketConn(c)
		var mift []*net.Interface

		ift, err := net.Interfaces()
		if err != nil {
			t.Fatalf("net.Interfaces failed: %v", err)
		}
		for i, ifi := range ift {
			if _, ok := isMulticastAvailable(&ifi); !ok {
				continue
			}
			if err := p.JoinGroup(&ifi, gaddr); err != nil {
				t.Fatalf("ipv6.PacketConn.JoinGroup %v on %v failed: %v", gaddr, ifi, err)
			}
			mift = append(mift, &ift[i])
		}
		for _, ifi := range mift {
			if err := p.LeaveGroup(ifi, gaddr); err != nil {
				t.Fatalf("ipv6.PacketConn.LeaveGroup %v on %v failed: %v", gaddr, ifi, err)
			}
		}
	}
}

func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) {
	switch runtime.GOOS {
	case "plan9", "windows":
		t.Skipf("not supported on %q", runtime.GOOS)
	}
	if !supportsIPv6 {
		t.Skip("ipv6 is not supported")
	}

	for _, gaddr := range udpMultipleGroupListenerTests {
		c1, err := net.ListenPacket("udp6", "[ff02::]:1024") // wildcard address with reusable port
		if err != nil {
			t.Fatalf("net.ListenPacket failed: %v", err)
		}
		defer c1.Close()

		c2, err := net.ListenPacket("udp6", "[ff02::]:1024") // wildcard address with reusable port
		if err != nil {
			t.Fatalf("net.ListenPacket failed: %v", err)
		}
		defer c2.Close()

		var ps [2]*ipv6.PacketConn
		ps[0] = ipv6.NewPacketConn(c1)
		ps[1] = ipv6.NewPacketConn(c2)
		var mift []*net.Interface

		ift, err := net.Interfaces()
		if err != nil {
			t.Fatalf("net.Interfaces failed: %v", err)
		}
		for i, ifi := range ift {
			if _, ok := isMulticastAvailable(&ifi); !ok {
				continue
			}
			for _, p := range ps {
				if err := p.JoinGroup(&ifi, gaddr); err != nil {
					t.Fatalf("ipv6.PacketConn.JoinGroup %v on %v failed: %v", gaddr, ifi, err)
				}
			}
			mift = append(mift, &ift[i])
		}
		for _, ifi := range mift {
			for _, p := range ps {
				if err := p.LeaveGroup(ifi, gaddr); err != nil {
					t.Fatalf("ipv6.PacketConn.LeaveGroup %v on %v failed: %v", gaddr, ifi, err)
				}
			}
		}
	}
}

func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) {
	switch runtime.GOOS {
	case "plan9", "windows":
		t.Skipf("not supported on %q", runtime.GOOS)
	}
	if !supportsIPv6 {
		t.Skip("ipv6 is not supported")
	}

	gaddr := net.IPAddr{IP: net.ParseIP("ff02::114")} // see RFC 4727
	type ml struct {
		c   *ipv6.PacketConn
		ifi *net.Interface
	}
	var mlt []*ml

	ift, err := net.Interfaces()
	if err != nil {
		t.Fatalf("net.Interfaces failed: %v", err)
	}
	for i, ifi := range ift {
		ip, ok := isMulticastAvailable(&ifi)
		if !ok {
			continue
		}
		c, err := net.ListenPacket("udp6", fmt.Sprintf("[%s%%%s]:1024", ip.String(), ifi.Name)) // unicast address with non-reusable port
		if err != nil {
			t.Fatalf("net.ListenPacket with %v failed: %v", ip, err)
		}
		defer c.Close()
		p := ipv6.NewPacketConn(c)
		if err := p.JoinGroup(&ifi, &gaddr); err != nil {
			t.Fatalf("ipv6.PacketConn.JoinGroup on %v failed: %v", ifi, err)
		}
		mlt = append(mlt, &ml{p, &ift[i]})
	}
	for _, m := range mlt {
		if err := m.c.LeaveGroup(m.ifi, &gaddr); err != nil {
			t.Fatalf("ipv6.PacketConn.LeaveGroup on %v failed: %v", m.ifi, err)
		}
	}
}

func TestIPSinglePacketConnWithSingleGroupListener(t *testing.T) {
	switch runtime.GOOS {
	case "plan9", "windows":
		t.Skipf("not supported on %q", runtime.GOOS)
	}
	if !supportsIPv6 {
		t.Skip("ipv6 is not supported")
	}
	if os.Getuid() != 0 {
		t.Skip("must be root")
	}

	c, err := net.ListenPacket("ip6:ipv6-icmp", "::") // wildcard address
	if err != nil {
		t.Fatalf("net.ListenPacket failed: %v", err)
	}
	defer c.Close()

	p := ipv6.NewPacketConn(c)
	gaddr := net.IPAddr{IP: net.ParseIP("ff02::114")} // see RFC 4727
	var mift []*net.Interface

	ift, err := net.Interfaces()
	if err != nil {
		t.Fatalf("net.Interfaces failed: %v", err)
	}
	for i, ifi := range ift {
		if _, ok := isMulticastAvailable(&ifi); !ok {
			continue
		}
		if err := p.JoinGroup(&ifi, &gaddr); err != nil {
			t.Fatalf("ipv6.PacketConn.JoinGroup on %v failed: %v", ifi, err)
		}
		mift = append(mift, &ift[i])
	}
	for _, ifi := range mift {
		if err := p.LeaveGroup(ifi, &gaddr); err != nil {
			t.Fatalf("ipv6.PacketConn.LeaveGroup on %v failed: %v", ifi, err)
		}
	}
}

func TestIPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) {
	switch runtime.GOOS {
	case "darwin", "plan9", "windows":
		t.Skipf("not supported on %q", runtime.GOOS)
	}
	if !supportsIPv6 {
		t.Skip("ipv6 is not supported")
	}
	if os.Getuid() != 0 {
		t.Skip("must be root")
	}

	gaddr := net.IPAddr{IP: net.ParseIP("ff02::114")} // see RFC 4727
	type ml struct {
		c   *ipv6.PacketConn
		ifi *net.Interface
	}
	var mlt []*ml

	ift, err := net.Interfaces()
	if err != nil {
		t.Fatalf("net.Interfaces failed: %v", err)
	}
	for i, ifi := range ift {
		ip, ok := isMulticastAvailable(&ifi)
		if !ok {
			continue
		}
		c, err := net.ListenPacket("ip6:ipv6-icmp", fmt.Sprintf("%s%%%s", ip.String(), ifi.Name)) // unicast address
		if err != nil {
			t.Fatalf("net.ListenPacket failed: %v", err)
		}
		defer c.Close()
		p := ipv6.NewPacketConn(c)
		if err := p.JoinGroup(&ifi, &gaddr); err != nil {
			t.Fatalf("ipv6.PacketConn.JoinGroup on %v failed: %v", ifi, err)
		}
		mlt = append(mlt, &ml{p, &ift[i]})
	}
	for _, m := range mlt {
		if err := m.c.LeaveGroup(m.ifi, &gaddr); err != nil {
			t.Fatalf("ipv6.PacketConn.LeaveGroup on %v failed: %v", m.ifi, err)
		}
	}
}
<|endoftext|>


<commit_before>package tcpreuse

import (
	"net"
	"testing"

	ma "github.com/multiformats/go-multiaddr"
)

func TestSingle(t *testing.T) {
	var trA Transport
	var trB Transport
	laddr, _ := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/0")
	listenerA, err := trA.Listen(laddr)
	if err != nil {
		t.Fatal(err)
	}
	defer listenerA.Close()
	listenerB, err := trB.Listen(laddr)
	if err != nil {
		t.Fatal(err)
	}
	defer listenerB.Close()

	done := make(chan struct{})
	go func() {
		defer close(done)
		c, err := listenerA.Accept()
		if err != nil {
			t.Fatal(err)
		}
		c.Close()
	}()

	c, err := trB.Dial(listenerA.Multiaddr())
	if err != nil {
		t.Fatal(err)
	}
	<-done
	c.Close()
}

func TestTwoLocal(t *testing.T) {
	var trA Transport
	var trB Transport
	laddr, _ := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/0")
	listenerA, err := trA.Listen(laddr)
	if err != nil {
		t.Fatal(err)
	}
	defer listenerA.Close()

	listenerB1, err := trB.Listen(laddr)
	if err != nil {
		t.Fatal(err)
	}
	defer listenerB1.Close()

	listenerB2, err := trB.Listen(laddr)
	if err != nil {
		t.Fatal(err)
	}
	defer listenerB2.Close()

	done := make(chan struct{})
	go func() {
		defer close(done)
		c, err := listenerA.Accept()
		if err != nil {
			t.Fatal(err)
		}
		c.Close()
	}()

	c, err := trB.Dial(listenerA.Multiaddr())
	if err != nil {
		t.Fatal(err)
	}
	localPort := c.LocalAddr().(*net.TCPAddr).Port
	if localPort != listenerB1.Addr().(*net.TCPAddr).Port &&
		localPort != listenerB2.Addr().(*net.TCPAddr).Port {
		t.Fatal("didn't dial from one of our listener ports")
	}
	<-done
	c.Close()
}
<commit_msg>add a test for dialing with a local and an unspecified listener<commit_after>package tcpreuse

import (
	"net"
	"testing"

	ma "github.com/multiformats/go-multiaddr"
)

func TestSingle(t *testing.T) {
	var trA Transport
	var trB Transport
	laddr, _ := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/0")
	listenerA, err := trA.Listen(laddr)
	if err != nil {
		t.Fatal(err)
	}
	defer listenerA.Close()
	listenerB, err := trB.Listen(laddr)
	if err != nil {
		t.Fatal(err)
	}
	defer listenerB.Close()

	done := make(chan struct{})
	go func() {
		defer close(done)
		c, err := listenerA.Accept()
		if err != nil {
			t.Fatal(err)
		}
		c.Close()
	}()

	c, err := trB.Dial(listenerA.Multiaddr())
	if err != nil {
		t.Fatal(err)
	}
	<-done
	c.Close()
}

func TestTwoLocal(t *testing.T) {
	var trA Transport
	var trB Transport
	laddr, _ := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/0")
	listenerA, err := trA.Listen(laddr)
	if err != nil {
		t.Fatal(err)
	}
	defer listenerA.Close()

	listenerB1, err := trB.Listen(laddr)
	if err != nil {
		t.Fatal(err)
	}
	defer listenerB1.Close()

	listenerB2, err := trB.Listen(laddr)
	if err != nil {
		t.Fatal(err)
	}
	defer listenerB2.Close()

	done := make(chan struct{})
	go func() {
		defer close(done)
		c, err := listenerA.Accept()
		if err != nil {
			t.Fatal(err)
		}
		c.Close()
	}()

	c, err := trB.Dial(listenerA.Multiaddr())
	if err != nil {
		t.Fatal(err)
	}
	localPort := c.LocalAddr().(*net.TCPAddr).Port
	if localPort != listenerB1.Addr().(*net.TCPAddr).Port &&
		localPort != listenerB2.Addr().(*net.TCPAddr).Port {
		t.Fatal("didn't dial from one of our listener ports")
	}
	<-done
	c.Close()
}

func TestLocalAndUnspecified(t *testing.T) {
	var trA Transport
	var trB Transport
	laddr, _ := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/0")
	unspec, _ := ma.NewMultiaddr("/ip4/0.0.0.0/tcp/0")
	listenerA, err := trA.Listen(laddr)
	if err != nil {
		t.Fatal(err)
	}
	defer listenerA.Close()

	listenerB1, err := trB.Listen(laddr)
	if err != nil {
		t.Fatal(err)
	}
	defer listenerB1.Close()

	listenerB2, err := trB.Listen(unspec)
	if err != nil {
		t.Fatal(err)
	}
	defer listenerB2.Close()

	done := make(chan struct{})
	go func() {
		defer close(done)
		c, err := listenerA.Accept()
		if err != nil {
			t.Fatal(err)
		}
		c.Close()
	}()

	c, err := trB.Dial(listenerA.Multiaddr())
	if err != nil {
		t.Fatal(err)
	}
	actual := c.LocalAddr().(*net.TCPAddr).Port
	expected := listenerB1.Addr().(*net.TCPAddr).Port
	if actual != expected {
		t.Errorf("expected to use port %d, used port %d", expected, actual)
	}
	<-done
	c.Close()

	// Closing the listener should reset the dialer.
	listenerB1.Close()

	done = make(chan struct{})
	go func() {
		defer close(done)
		c, err := listenerA.Accept()
		if err != nil {
			t.Fatal(err)
		}
		c.Close()
	}()

	c, err = trB.Dial(listenerA.Multiaddr())
	if err != nil {
		t.Fatal(err)
	}
	actual = c.LocalAddr().(*net.TCPAddr).Port
	expected = listenerB2.Addr().(*net.TCPAddr).Port
	if actual != expected {
		t.Errorf("expected to use port %d, used port %d", expected, actual)
	}
	<-done
	c.Close()
}
<|endoftext|>


<commit_before>// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package ifuzz

import (
	"fmt"
)

// Decode decodes instruction length for the given mode.
// It can have falsely decode incorrect instructions,
// but should not fail to decode correct instructions.
func Decode(mode int, text []byte) (int, error) {
	if len(text) == 0 {
		return 0, fmt.Errorf("zero-length instruction")
	}
	prefixes := prefixes32
	var operSize, immSize, dispSize, addrSize int
	switch mode {
	case ModeLong64:
		operSize, immSize, dispSize, addrSize = 4, 4, 4, 8
		prefixes = prefixes64
	case ModeProt32:
		operSize, immSize, dispSize, addrSize = 4, 4, 4, 4
	case ModeProt16, ModeReal16:
		operSize, immSize, dispSize, addrSize = 2, 2, 2, 2
	default:
		panic("bad mode")
	}
	prefixLen := 0
	var decodedPrefixes []byte
	vex := false
	if len(text) > 1 {
		// There are only 2 32-bit instructions that look like VEX-prefixed but are actually not: LDS, LES.
		// They always reference memory (mod!=3), but all VEX instructions have "mod=3" where LDS/LES would have mod.
		if (text[0] == 0xc4 || text[0] == 0xc5) && (mode == ModeLong64 || text[1]&0xc0 == 0xc0) {
			vex = true
		}
		// There is only one instruction that looks like XOP-prefixed but is actually not: POP.
		// It always has reg=0, but all XOP instructions have "reg!=0" where POP would have reg.
		if text[0] == 0x8f && text[1]&0x38 != 0 {
			vex = true
		}
	}
	var vexMap byte
	if vex {
		prefixLen = 3
		if text[0] == 0xc5 {
			prefixLen = 2
		}
		if len(text) < prefixLen {
			return 0, fmt.Errorf("bad VEX/XOP prefix")
		}
		if prefixLen == 3 {
			vexMap = text[1] & 0x1f
		}
		text = text[prefixLen:]
	} else {
		decodedPrefixes = text
		operSize1, immSize1, dispSize1, addrSize1 := operSize, immSize, dispSize, addrSize
		for len(text) != 0 && prefixes[text[0]] {
			switch text[0] {
			case 0x66:
				if immSize == 4 {
					immSize1 = 2
					operSize1 = 2
				} else if immSize == 2 {
					immSize1 = 4
					operSize1 = 4
				}
			case 0x67:
				if addrSize == 8 {
					addrSize1 = 4
				} else if addrSize == 4 {
					dispSize1 = 2
					addrSize1 = 2
				} else if addrSize == 2 {
					dispSize1 = 4
					addrSize1 = 4
				}
			}
			if text[0] & ^byte(7) == 0x48 {
				operSize1 = 8
				immSize1 = 4
			}
			text = text[1:]
			prefixLen++
		}
		operSize, immSize, dispSize, addrSize = operSize1, immSize1, dispSize1, addrSize1
		decodedPrefixes = decodedPrefixes[:prefixLen]
		if len(text) == 0 {
			return 0, fmt.Errorf("no opcode, only prefixes")
		}
	}
nextInsn:
	for _, insn := range modeInsns[mode][typeAll] {
		if vex != (insn.Vex != 0) {
			continue nextInsn
		}
		if vex && insn.VexMap != vexMap {
			continue nextInsn
		}
		if insn.NoRepPrefix || insn.No66Prefix {
			for _, p := range decodedPrefixes {
				if len(insn.Prefix) != 0 && insn.Prefix[0] == p {
					continue
				}
				switch p {
				case 0xf2, 0xf3:
					if insn.NoRepPrefix {
						continue nextInsn
					}
				case 0x66:
					if insn.No66Prefix {
						continue nextInsn
					}
				}
			}
		}
		text1 := text
		for i, v := range insn.Opcode {
			if len(text1) == 0 {
				continue nextInsn
			}
			b := text1[0]
			if insn.Srm && i == len(insn.Opcode)-1 {
				b &^= 7
			}
			if b != v {
				continue nextInsn
			}
			text1 = text1[1:]
		}
		if insn.Modrm {
			if len(text1) == 0 {
				continue nextInsn
			}
			modrm := text1[0]
			text1 = text1[1:]
			mod := modrm >> 6
			rm := modrm & 7
			if !insn.NoSibDisp {
				disp := 0
				if addrSize == 2 {
					if mod == 1 {
						disp = 1
					} else if mod == 2 || mod == 0 && rm == 6 {
						disp = 2
					}
				} else {
					var sibbase byte
					if mod != 3 && rm == 4 {
						if len(text1) == 0 {
							continue nextInsn
						}
						sib := text1[0]
						text1 = text1[1:]
						sibbase = sib & 7
					}
					if mod == 1 {
						disp = 1
					} else if mod == 2 || mod == 0 && rm == 5 || mod == 0 && sibbase == 5 {
						disp = dispSize
					}
				}
				if disp != 0 {
					if len(text1) < disp {
						continue nextInsn
					}
					text1 = text1[disp:]
				}
			}
		}
		immLen := 0
		for _, imm := range []int8{insn.Imm, insn.Imm2} {
			switch imm {
			case -1:
				immLen += immSize
			case -2:
				immLen += addrSize
			case -3:
				immLen += operSize
			default:
				immLen += int(imm)
			}
		}
		if immLen != 0 {
			if len(text1) < immLen {
				continue nextInsn
			}
			text1 = text1[immLen:]
		}
		for _, v := range insn.Suffix {
			if len(text1) == 0 || text1[0] != v {
				continue nextInsn
			}
			text1 = text1[1:]
		}
		return prefixLen + len(text) - len(text1), nil
	}
	return 0, fmt.Errorf("unknown instruction")
}

var XedDecode func(mode int, text []byte) (int, error)

var (
	prefixes32 = map[byte]bool{0x2E: true, 0x3E: true, 0x26: true, 0x64: true, 0x65: true, 0x36: true, 0x66: true, 0x67: true, 0xF3: true, 0xF2: true, 0xF0: true}
	prefixes64 = map[byte]bool{0x2E: true, 0x3E: true, 0x26: true, 0x64: true, 0x65: true, 0x36: true, 0x66: true, 0x67: true, 0xF3: true, 0xF2: true, 0xF0: true,
		0x40: true, 0x41: true, 0x42: true, 0x43: true, 0x44: true, 0x45: true, 0x46: true, 0x47: true,
		0x48: true, 0x49: true, 0x4a: true, 0x4b: true, 0x4c: true, 0x4d: true, 0x4e: true, 0x4f: true}
)
<commit_msg>ifuzz: fix 2-byte vex decoding<commit_after>// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package ifuzz

import (
	"fmt"
)

// Decode decodes instruction length for the given mode.
// It can have falsely decode incorrect instructions,
// but should not fail to decode correct instructions.
func Decode(mode int, text []byte) (int, error) {
	if len(text) == 0 {
		return 0, fmt.Errorf("zero-length instruction")
	}
	prefixes := prefixes32
	var operSize, immSize, dispSize, addrSize int
	switch mode {
	case ModeLong64:
		operSize, immSize, dispSize, addrSize = 4, 4, 4, 8
		prefixes = prefixes64
	case ModeProt32:
		operSize, immSize, dispSize, addrSize = 4, 4, 4, 4
	case ModeProt16, ModeReal16:
		operSize, immSize, dispSize, addrSize = 2, 2, 2, 2
	default:
		panic("bad mode")
	}
	prefixLen := 0
	var decodedPrefixes []byte
	vex := false
	if len(text) > 1 {
		// There are only 2 32-bit instructions that look like VEX-prefixed but are actually not: LDS, LES.
		// They always reference memory (mod!=3), but all VEX instructions have "mod=3" where LDS/LES would have mod.
		if (text[0] == 0xc4 || text[0] == 0xc5) && (mode == ModeLong64 || text[1]&0xc0 == 0xc0) {
			vex = true
		}
		// There is only one instruction that looks like XOP-prefixed but is actually not: POP.
		// It always has reg=0, but all XOP instructions have "reg!=0" where POP would have reg.
		if text[0] == 0x8f && text[1]&0x38 != 0 {
			vex = true
		}
	}
	var vexMap byte
	if vex {
		prefixLen = 3
		if text[0] == 0xc5 {
			prefixLen = 2
			vexMap = 1 // V0F
		}
		if len(text) < prefixLen {
			return 0, fmt.Errorf("bad VEX/XOP prefix")
		}
		if prefixLen == 3 {
			vexMap = text[1] & 0x1f
		}
		text = text[prefixLen:]
	} else {
		decodedPrefixes = text
		operSize1, immSize1, dispSize1, addrSize1 := operSize, immSize, dispSize, addrSize
		for len(text) != 0 && prefixes[text[0]] {
			switch text[0] {
			case 0x66:
				if immSize == 4 {
					immSize1 = 2
					operSize1 = 2
				} else if immSize == 2 {
					immSize1 = 4
					operSize1 = 4
				}
			case 0x67:
				if addrSize == 8 {
					addrSize1 = 4
				} else if addrSize == 4 {
					dispSize1 = 2
					addrSize1 = 2
				} else if addrSize == 2 {
					dispSize1 = 4
					addrSize1 = 4
				}
			}
			if text[0] & ^byte(7) == 0x48 {
				operSize1 = 8
				immSize1 = 4
			}
			text = text[1:]
			prefixLen++
		}
		operSize, immSize, dispSize, addrSize = operSize1, immSize1, dispSize1, addrSize1
		decodedPrefixes = decodedPrefixes[:prefixLen]
		if len(text) == 0 {
			return 0, fmt.Errorf("no opcode, only prefixes")
		}
	}
nextInsn:
	for _, insn := range modeInsns[mode][typeAll] {
		if vex != (insn.Vex != 0) {
			continue nextInsn
		}
		if vex && insn.VexMap != vexMap {
			continue nextInsn
		}
		if insn.NoRepPrefix || insn.No66Prefix {
			for _, p := range decodedPrefixes {
				if len(insn.Prefix) != 0 && insn.Prefix[0] == p {
					continue
				}
				switch p {
				case 0xf2, 0xf3:
					if insn.NoRepPrefix {
						continue nextInsn
					}
				case 0x66:
					if insn.No66Prefix {
						continue nextInsn
					}
				}
			}
		}
		text1 := text
		for i, v := range insn.Opcode {
			if len(text1) == 0 {
				continue nextInsn
			}
			b := text1[0]
			if insn.Srm && i == len(insn.Opcode)-1 {
				b &^= 7
			}
			if b != v {
				continue nextInsn
			}
			text1 = text1[1:]
		}
		if insn.Modrm {
			if len(text1) == 0 {
				continue nextInsn
			}
			modrm := text1[0]
			text1 = text1[1:]
			mod := modrm >> 6
			rm := modrm & 7
			if !insn.NoSibDisp {
				disp := 0
				if addrSize == 2 {
					if mod == 1 {
						disp = 1
					} else if mod == 2 || mod == 0 && rm == 6 {
						disp = 2
					}
				} else {
					var sibbase byte
					if mod != 3 && rm == 4 {
						if len(text1) == 0 {
							continue nextInsn
						}
						sib := text1[0]
						text1 = text1[1:]
						sibbase = sib & 7
					}
					if mod == 1 {
						disp = 1
					} else if mod == 2 || mod == 0 && rm == 5 || mod == 0 && sibbase == 5 {
						disp = dispSize
					}
				}
				if disp != 0 {
					if len(text1) < disp {
						continue nextInsn
					}
					text1 = text1[disp:]
				}
			}
		}
		immLen := 0
		for _, imm := range []int8{insn.Imm, insn.Imm2} {
			switch imm {
			case -1:
				immLen += immSize
			case -2:
				immLen += addrSize
			case -3:
				immLen += operSize
			default:
				immLen += int(imm)
			}
		}
		if immLen != 0 {
			if len(text1) < immLen {
				continue nextInsn
			}
			text1 = text1[immLen:]
		}
		for _, v := range insn.Suffix {
			if len(text1) == 0 || text1[0] != v {
				continue nextInsn
			}
			text1 = text1[1:]
		}
		return prefixLen + len(text) - len(text1), nil
	}
	return 0, fmt.Errorf("unknown instruction")
}

var XedDecode func(mode int, text []byte) (int, error)

var (
	prefixes32 = map[byte]bool{0x2E: true, 0x3E: true, 0x26: true, 0x64: true, 0x65: true, 0x36: true, 0x66: true, 0x67: true, 0xF3: true, 0xF2: true, 0xF0: true}
	prefixes64 = map[byte]bool{0x2E: true, 0x3E: true, 0x26: true, 0x64: true, 0x65: true, 0x36: true, 0x66: true, 0x67: true, 0xF3: true, 0xF2: true, 0xF0: true,
		0x40: true, 0x41: true, 0x42: true, 0x43: true, 0x44: true, 0x45: true, 0x46: true, 0x47: true,
		0x48: true, 0x49: true, 0x4a: true, 0x4b: true, 0x4c: true, 0x4d: true, 0x4e: true, 0x4f: true}
)
<|endoftext|>


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

package api

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"net/http/httptest"
	"reflect"
	"testing"
)

var (
	testAlert = Alert{
		CID:                "/alert/1234",
		AcknowledgementCID: "/acknowledgement/1234",
		AlertURL:           "https://example.circonus.com/fault-detection?alert_id=1234",
		BrokerCID:          "/broker/1234",
		CheckCID:           "/check/1234",
		CheckName:          "foo bar",
		ClearedOn:          &[]uint{1483033602}[0],
		ClearedValue:       &[]string{"1234"}[0],
		Maintenance:        []string{},
		MetricLinkURL:      &[]string{"http://example.com/docs/what_to_do_when/foo_bar_failure.html"}[0],
		MetricName:         "baz",
		MetricNotes:        &[]string{"blah blah blah"}[0],
		OccurredOn:         1483033102,
		RuleSetCID:         "/rule_set/1234_baz",
		Severity:           2,
		Tags:               []string{"cat:tag"},
		Value:              "5678",
	}
)

func testAlertServer() *httptest.Server {
	f := func(w http.ResponseWriter, r *http.Request) {
		path := r.URL.Path
		if path == "/alert/1234" {
			switch r.Method {
			case "GET":
				ret, err := json.Marshal(testAlert)
				if err != nil {
					panic(err)
				}
				w.WriteHeader(200)
				w.Header().Set("Content-Type", "application/json")
				fmt.Fprintln(w, string(ret))
			default:
				w.WriteHeader(404)
				fmt.Fprintln(w, fmt.Sprintf("not found: %s %s", r.Method, path))
			}
		} else if path == "/alert" {
			switch r.Method {
			case "GET":
				c := []Alert{testAlert}
				ret, err := json.Marshal(c)
				if err != nil {
					panic(err)
				}
				w.WriteHeader(200)
				w.Header().Set("Content-Type", "application/json")
				fmt.Fprintln(w, string(ret))
			default:
				w.WriteHeader(404)
				fmt.Fprintln(w, fmt.Sprintf("not found: %s %s", r.Method, path))
			}
		} else {
			w.WriteHeader(404)
			fmt.Fprintln(w, fmt.Sprintf("not found: %s %s", r.Method, path))
		}
	}

	return httptest.NewServer(http.HandlerFunc(f))
}

func TestFetchAlert(t *testing.T) {
	server := testAlertServer()
	defer server.Close()

	ac := &Config{
		TokenKey: "abc123",
		TokenApp: "test",
		URL:      server.URL,
	}
	apih, err := NewAPI(ac)
	if err != nil {
		t.Errorf("Expected no error, got '%v'", err)
	}

	t.Log("without CID")
	{
		cid := ""
		expectedError := errors.New("Invalid alert CID [none]")
		_, err := apih.FetchAlert(CIDType(&cid))
		if err == nil {
			t.Fatalf("Expected error")
		}
		if err.Error() != expectedError.Error() {
			t.Fatalf("Expected %+v got '%+v'", expectedError, err)
		}
	}

	t.Log("with valid CID")
	{
		cid := "/alert/1234"
		alert, err := apih.FetchAlert(CIDType(&cid))
		if err != nil {
			t.Fatalf("Expected no error, got '%v'", err)
		}

		actualType := reflect.TypeOf(alert)
		expectedType := "*api.Alert"
		if actualType.String() != expectedType {
			t.Fatalf("Expected %s, got %s", expectedType, actualType.String())
		}

		if alert.CID != testAlert.CID {
			t.Fatalf("CIDs do not match: %+v != %+v\n", alert, testAlert)
		}
	}

	t.Log("with invalid CID")
	{
		cid := "/invalid"
		expectedError := errors.New("Invalid alert CID [/invalid]")
		_, err := apih.FetchAlert(CIDType(&cid))
		if err == nil {
			t.Fatalf("Expected error")
		}
		if err.Error() != expectedError.Error() {
			t.Fatalf("Expected %+v got '%+v'", expectedError, err)
		}
	}
}

func TestFetchAlerts(t *testing.T) {
	server := testAlertServer()
	defer server.Close()

	ac := &Config{
		TokenKey: "abc123",
		TokenApp: "test",
		URL:      server.URL,
	}
	apih, err := NewAPI(ac)
	if err != nil {
		t.Errorf("Expected no error, got '%v'", err)
	}

	alerts, err := apih.FetchAlerts()
	if err != nil {
		t.Fatalf("Expected no error, got '%v'", err)
	}

	actualType := reflect.TypeOf(alerts)
	expectedType := "*[]api.Alert"
	if actualType.String() != expectedType {
		t.Fatalf("Expected %s, got %s", expectedType, actualType.String())
	}

}
<commit_msg>add: search test coverage<commit_after>// Copyright 2016 Circonus, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package api

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"net/http/httptest"
	"reflect"
	"testing"
)

var (
	testAlert = Alert{
		CID:                "/alert/1234",
		AcknowledgementCID: "/acknowledgement/1234",
		AlertURL:           "https://example.circonus.com/fault-detection?alert_id=1234",
		BrokerCID:          "/broker/1234",
		CheckCID:           "/check/1234",
		CheckName:          "foo bar",
		ClearedOn:          &[]uint{1483033602}[0],
		ClearedValue:       &[]string{"1234"}[0],
		Maintenance:        []string{},
		MetricLinkURL:      &[]string{"http://example.com/docs/what_to_do_when/foo_bar_failure.html"}[0],
		MetricName:         "baz",
		MetricNotes:        &[]string{"blah blah blah"}[0],
		OccurredOn:         1483033102,
		RuleSetCID:         "/rule_set/1234_baz",
		Severity:           2,
		Tags:               []string{"cat:tag"},
		Value:              "5678",
	}
)

func testAlertServer() *httptest.Server {
	f := func(w http.ResponseWriter, r *http.Request) {
		path := r.URL.Path
		if path == "/alert/1234" {
			switch r.Method {
			case "GET":
				ret, err := json.Marshal(testAlert)
				if err != nil {
					panic(err)
				}
				w.WriteHeader(200)
				w.Header().Set("Content-Type", "application/json")
				fmt.Fprintln(w, string(ret))
			default:
				w.WriteHeader(404)
				fmt.Fprintln(w, fmt.Sprintf("not found: %s %s", r.Method, path))
			}
		} else if path == "/alert" {
			switch r.Method {
			case "GET":
				reqURL := r.URL.String()
				var c []Alert
				if reqURL == "/alert?search=%28host%3D%22somehost.example.com%22%29" {
					c = []Alert{testAlert}
				} else if reqURL == "/alert?f__cleared_on=null" {
					c = []Alert{testAlert}
				} else if reqURL == "/alert?f__cleared_on=null&search=%28host%3D%22somehost.example.com%22%29" {
					c = []Alert{testAlert}
				} else if reqURL == "/alert" {
					c = []Alert{testAlert}
				} else {
					c = []Alert{}
				}
				if len(c) > 0 {
					ret, err := json.Marshal(c)
					if err != nil {
						panic(err)
					}
					w.WriteHeader(200)
					w.Header().Set("Content-Type", "application/json")
					fmt.Fprintln(w, string(ret))
				} else {
					w.WriteHeader(404)
					fmt.Fprintln(w, fmt.Sprintf("not found: %s %s", r.Method, reqURL))
				}
			default:
				w.WriteHeader(404)
				fmt.Fprintln(w, fmt.Sprintf("not found: %s %s", r.Method, path))
			}
		} else {
			w.WriteHeader(404)
			fmt.Fprintln(w, fmt.Sprintf("not found: %s %s", r.Method, path))
		}
	}

	return httptest.NewServer(http.HandlerFunc(f))
}

func TestFetchAlert(t *testing.T) {
	server := testAlertServer()
	defer server.Close()

	ac := &Config{
		TokenKey: "abc123",
		TokenApp: "test",
		URL:      server.URL,
	}
	apih, err := NewAPI(ac)
	if err != nil {
		t.Errorf("Expected no error, got '%v'", err)
	}

	t.Log("without CID")
	{
		cid := ""
		expectedError := errors.New("Invalid alert CID [none]")
		_, err := apih.FetchAlert(CIDType(&cid))
		if err == nil {
			t.Fatalf("Expected error")
		}
		if err.Error() != expectedError.Error() {
			t.Fatalf("Expected %+v got '%+v'", expectedError, err)
		}
	}

	t.Log("with valid CID")
	{
		cid := "/alert/1234"
		alert, err := apih.FetchAlert(CIDType(&cid))
		if err != nil {
			t.Fatalf("Expected no error, got '%v'", err)
		}

		actualType := reflect.TypeOf(alert)
		expectedType := "*api.Alert"
		if actualType.String() != expectedType {
			t.Fatalf("Expected %s, got %s", expectedType, actualType.String())
		}

		if alert.CID != testAlert.CID {
			t.Fatalf("CIDs do not match: %+v != %+v\n", alert, testAlert)
		}
	}

	t.Log("with invalid CID")
	{
		cid := "/invalid"
		expectedError := errors.New("Invalid alert CID [/invalid]")
		_, err := apih.FetchAlert(CIDType(&cid))
		if err == nil {
			t.Fatalf("Expected error")
		}
		if err.Error() != expectedError.Error() {
			t.Fatalf("Expected %+v got '%+v'", expectedError, err)
		}
	}
}

func TestFetchAlerts(t *testing.T) {
	server := testAlertServer()
	defer server.Close()

	ac := &Config{
		TokenKey: "abc123",
		TokenApp: "test",
		URL:      server.URL,
	}
	apih, err := NewAPI(ac)
	if err != nil {
		t.Errorf("Expected no error, got '%v'", err)
	}

	alerts, err := apih.FetchAlerts()
	if err != nil {
		t.Fatalf("Expected no error, got '%v'", err)
	}

	actualType := reflect.TypeOf(alerts)
	expectedType := "*[]api.Alert"
	if actualType.String() != expectedType {
		t.Fatalf("Expected %s, got %s", expectedType, actualType.String())
	}

}

func TestSearchAlerts(t *testing.T) {
	server := testAlertServer()
	defer server.Close()

	var apih *API

	ac := &Config{
		TokenKey: "abc123",
		TokenApp: "test",
		URL:      server.URL,
	}
	apih, err := NewAPI(ac)
	if err != nil {
		t.Errorf("Expected no error, got '%v'", err)
	}

	t.Log("no search, no filter")
	{
		acknowledgements, err := apih.SearchAlerts(nil, nil)
		if err != nil {
			t.Fatalf("Expected no error, got '%v'", err)
		}

		actualType := reflect.TypeOf(acknowledgements)
		expectedType := "*[]api.Alert"
		if actualType.String() != expectedType {
			t.Fatalf("Expected %s, got %s", expectedType, actualType.String())
		}
	}

	t.Log("search, no filter")
	{
		search := SearchQueryType(`(host="somehost.example.com")`)
		acknowledgements, err := apih.SearchAlerts(&search, nil)
		if err != nil {
			t.Fatalf("Expected no error, got '%v'", err)
		}

		actualType := reflect.TypeOf(acknowledgements)
		expectedType := "*[]api.Alert"
		if actualType.String() != expectedType {
			t.Fatalf("Expected %s, got %s", expectedType, actualType.String())
		}
	}

	t.Log("no search, filter")
	{
		filter := SearchFilterType(map[string][]string{"f__cleared_on": []string{"null"}})
		acknowledgements, err := apih.SearchAlerts(nil, &filter)
		if err != nil {
			t.Fatalf("Expected no error, got '%v'", err)
		}

		actualType := reflect.TypeOf(acknowledgements)
		expectedType := "*[]api.Alert"
		if actualType.String() != expectedType {
			t.Fatalf("Expected %s, got %s", expectedType, actualType.String())
		}
	}

	t.Log("search, filter")
	{
		search := SearchQueryType(`(host="somehost.example.com")`)
		filter := SearchFilterType(map[string][]string{"f__cleared_on": []string{"null"}})
		acknowledgements, err := apih.SearchAlerts(&search, &filter)
		if err != nil {
			t.Fatalf("Expected no error, got '%v'", err)
		}

		actualType := reflect.TypeOf(acknowledgements)
		expectedType := "*[]api.Alert"
		if actualType.String() != expectedType {
			t.Fatalf("Expected %s, got %s", expectedType, actualType.String())
		}
	}
}
<|endoftext|>