<commit_before>/*
Copyright 2015 The Kubernetes Authors.

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

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

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

package e2e

import (
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"syscall"
	"time"

	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/v1"
	"k8s.io/kubernetes/pkg/util/wait"
	"k8s.io/kubernetes/pkg/version"
	"k8s.io/kubernetes/test/e2e/framework"

	. "github.com/onsi/ginkgo"
)

const (
	podName = "pfpod"
)

// TODO support other ports besides 80
var (
	portForwardRegexp        = regexp.MustCompile("Forwarding from 127.0.0.1:([0-9]+) -> 80")
	portForwardPortToStdOutV = version.MustParse("v1.3.0-alpha.4")
)

func pfPod(expectedClientData, chunks, chunkSize, chunkIntervalMillis string) *api.Pod {
	return &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:   podName,
			Labels: map[string]string{"name": podName},
		},
		Spec: api.PodSpec{
			Containers: []api.Container{
				{
					Name:  "portforwardtester",
					Image: "gcr.io/google_containers/portforwardtester:1.2",
					Env: []v1.EnvVar{
						{
							Name:  "BIND_PORT",
							Value: "80",
						},
						{
							Name:  "EXPECTED_CLIENT_DATA",
							Value: expectedClientData,
						},
						{
							Name:  "CHUNKS",
							Value: chunks,
						},
						{
							Name:  "CHUNK_SIZE",
							Value: chunkSize,
						},
						{
							Name:  "CHUNK_INTERVAL",
							Value: chunkIntervalMillis,
						},
					},
				},
			},
			RestartPolicy: api.RestartPolicyNever,
		},
	}
}

type portForwardCommand struct {
	cmd  *exec.Cmd
	port int
}

// Stop attempts to gracefully stop `kubectl port-forward`, only killing it if necessary.
// This helps avoid spdy goroutine leaks in the Kubelet.
func (c *portForwardCommand) Stop() {
	// SIGINT signals that kubectl port-forward should gracefully terminate
	if err := c.cmd.Process.Signal(syscall.SIGINT); err != nil {
		framework.Logf("error sending SIGINT to kubectl port-forward: %v", err)
	}

	// try to wait for a clean exit
	done := make(chan error)
	go func() {
		done <- c.cmd.Wait()
	}()

	expired := time.NewTimer(wait.ForeverTestTimeout)
	defer expired.Stop()

	select {
	case err := <-done:
		if err == nil {
			// success
			return
		}
		framework.Logf("error waiting for kubectl port-forward to exit: %v", err)
	case <-expired.C:
		framework.Logf("timed out waiting for kubectl port-forward to exit")
	}

	framework.Logf("trying to forcibly kill kubectl port-forward")
	framework.TryKill(c.cmd)
}

func runPortForward(ns, podName string, port int) *portForwardCommand {
	cmd := framework.KubectlCmd("port-forward", fmt.Sprintf("--namespace=%v", ns), podName, fmt.Sprintf(":%d", port))
	// This is somewhat ugly but is the only way to retrieve the port that was picked
	// by the port-forward command. We don't want to hard code the port as we have no
	// way of guaranteeing we can pick one that isn't in use, particularly on Jenkins.
	framework.Logf("starting port-forward command and streaming output")
	stdout, stderr, err := framework.StartCmdAndStreamOutput(cmd)
	if err != nil {
		framework.Failf("Failed to start port-forward command: %v", err)
	}

	buf := make([]byte, 128)

	// After v1.3.0-alpha.4 (#17030), kubectl port-forward outputs port
	// info to stdout, not stderr, so for version-skewed tests, look there
	// instead.
	var portOutput io.ReadCloser
	if useStdOut, err := framework.KubectlVersionGTE(portForwardPortToStdOutV); err != nil {
		framework.Failf("Failed to get kubectl version: %v", err)
	} else if useStdOut {
		portOutput = stdout
	} else {
		portOutput = stderr
	}

	var n int
	framework.Logf("reading from `kubectl port-forward` command's stdout")
	if n, err = portOutput.Read(buf); err != nil {
		framework.Failf("Failed to read from kubectl port-forward stdout: %v", err)
	}
	portForwardOutput := string(buf[:n])
	match := portForwardRegexp.FindStringSubmatch(portForwardOutput)
	if len(match) != 2 {
		framework.Failf("Failed to parse kubectl port-forward output: %s", portForwardOutput)
	}

	listenPort, err := strconv.Atoi(match[1])
	if err != nil {
		framework.Failf("Error converting %s to an int: %v", match[1], err)
	}

	return &portForwardCommand{
		cmd:  cmd,
		port: listenPort,
	}
}

var _ = framework.KubeDescribe("Port forwarding", func() {
	f := framework.NewDefaultFramework("port-forwarding")

	framework.KubeDescribe("With a server that expects a client request", func() {
		It("should support a client that connects, sends no data, and disconnects [Conformance]", func() {
			By("creating the target pod")
			pod := pfPod("abc", "1", "1", "1")
			if _, err := f.Client.Pods(f.Namespace.Name).Create(pod); err != nil {
				framework.Failf("Couldn't create pod: %v", err)
			}
			if err := f.WaitForPodRunning(pod.Name); err != nil {
				framework.Failf("Pod did not start running: %v", err)
			}
			defer func() {
				logs, err := framework.GetPodLogs(f.Client, f.Namespace.Name, pod.Name, "portforwardtester")
				if err != nil {
					framework.Logf("Error getting pod log: %v", err)
				} else {
					framework.Logf("Pod log:\n%s", logs)
				}
			}()

			By("Running 'kubectl port-forward'")
			cmd := runPortForward(f.Namespace.Name, pod.Name, 80)
			defer cmd.Stop()

			By("Dialing the local port")
			conn, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", cmd.port))
			if err != nil {
				framework.Failf("Couldn't connect to port %d: %v", cmd.port, err)
			}

			By("Closing the connection to the local port")
			conn.Close()

			By("Waiting for the target pod to stop running")
			if err := f.WaitForPodNoLongerRunning(pod.Name); err != nil {
				framework.Failf("Pod did not stop running: %v", err)
			}

			By("Verifying logs")
			logOutput, err := framework.GetPodLogs(f.Client, f.Namespace.Name, pod.Name, "portforwardtester")
			if err != nil {
				framework.Failf("Error retrieving pod logs: %v", err)
			}
			verifyLogMessage(logOutput, "Accepted client connection")
			verifyLogMessage(logOutput, "Expected to read 3 bytes from client, but got 0 instead")
		})

		It("should support a client that connects, sends data, and disconnects [Conformance]", func() {
			By("creating the target pod")
			pod := pfPod("abc", "10", "10", "100")
			if _, err := f.Client.Pods(f.Namespace.Name).Create(pod); err != nil {
				framework.Failf("Couldn't create pod: %v", err)
			}
			if err := f.WaitForPodRunning(pod.Name); err != nil {
				framework.Failf("Pod did not start running: %v", err)
			}
			defer func() {
				logs, err := framework.GetPodLogs(f.Client, f.Namespace.Name, pod.Name, "portforwardtester")
				if err != nil {
					framework.Logf("Error getting pod log: %v", err)
				} else {
					framework.Logf("Pod log:\n%s", logs)
				}
			}()

			By("Running 'kubectl port-forward'")
			cmd := runPortForward(f.Namespace.Name, pod.Name, 80)
			defer cmd.Stop()

			By("Dialing the local port")
			addr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("127.0.0.1:%d", cmd.port))
			if err != nil {
				framework.Failf("Error resolving tcp addr: %v", err)
			}
			conn, err := net.DialTCP("tcp", nil, addr)
			if err != nil {
				framework.Failf("Couldn't connect to port %d: %v", cmd.port, err)
			}
			defer func() {
				By("Closing the connection to the local port")
				conn.Close()
			}()

			By("Sending the expected data to the local port")
			fmt.Fprint(conn, "abc")

			By("Closing the write half of the client's connection")
			conn.CloseWrite()

			By("Reading data from the local port")
			fromServer, err := ioutil.ReadAll(conn)
			if err != nil {
				framework.Failf("Unexpected error reading data from the server: %v", err)
			}

			if e, a := strings.Repeat("x", 100), string(fromServer); e != a {
				framework.Failf("Expected %q from server, got %q", e, a)
			}

			By("Waiting for the target pod to stop running")
			if err := f.WaitForPodNoLongerRunning(pod.Name); err != nil {
				framework.Failf("Pod did not stop running: %v", err)
			}

			By("Verifying logs")
			logOutput, err := framework.GetPodLogs(f.Client, f.Namespace.Name, pod.Name, "portforwardtester")
			if err != nil {
				framework.Failf("Error retrieving pod logs: %v", err)
			}
			verifyLogMessage(logOutput, "^Accepted client connection$")
			verifyLogMessage(logOutput, "^Received expected client data$")
			verifyLogMessage(logOutput, "^Done$")
		})
	})
	framework.KubeDescribe("With a server that expects no client request", func() {
		It("should support a client that connects, sends no data, and disconnects [Conformance]", func() {
			By("creating the target pod")
			pod := pfPod("", "10", "10", "100")
			if _, err := f.Client.Pods(f.Namespace.Name).Create(pod); err != nil {
				framework.Failf("Couldn't create pod: %v", err)
			}
			if err := f.WaitForPodRunning(pod.Name); err != nil {
				framework.Failf("Pod did not start running: %v", err)
			}
			defer func() {
				logs, err := framework.GetPodLogs(f.Client, f.Namespace.Name, pod.Name, "portforwardtester")
				if err != nil {
					framework.Logf("Error getting pod log: %v", err)
				} else {
					framework.Logf("Pod log:\n%s", logs)
				}
			}()

			By("Running 'kubectl port-forward'")
			cmd := runPortForward(f.Namespace.Name, pod.Name, 80)
			defer cmd.Stop()

			By("Dialing the local port")
			conn, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", cmd.port))
			if err != nil {
				framework.Failf("Couldn't connect to port %d: %v", cmd.port, err)
			}
			defer func() {
				By("Closing the connection to the local port")
				conn.Close()
			}()

			By("Reading data from the local port")
			fromServer, err := ioutil.ReadAll(conn)
			if err != nil {
				framework.Failf("Unexpected error reading data from the server: %v", err)
			}

			if e, a := strings.Repeat("x", 100), string(fromServer); e != a {
				framework.Failf("Expected %q from server, got %q", e, a)
			}

			By("Waiting for the target pod to stop running")
			if err := f.WaitForPodNoLongerRunning(pod.Name); err != nil {
				framework.Failf("Pod did not stop running: %v", err)
			}

			By("Verifying logs")
			logOutput, err := framework.GetPodLogs(f.Client, f.Namespace.Name, pod.Name, "portforwardtester")
			if err != nil {
				framework.Failf("Error retrieving pod logs: %v", err)
			}
			verifyLogMessage(logOutput, "Accepted client connection")
			verifyLogMessage(logOutput, "Done")
		})
	})
})

func verifyLogMessage(log, expected string) {
	re := regexp.MustCompile(expected)
	lines := strings.Split(log, "\n")
	for i := range lines {
		if re.MatchString(lines[i]) {
			return
		}
	}
	framework.Failf("Missing %q from log: %s", expected, log)
}
<commit_msg>Wait for the port to be ready before starting<commit_after>/*
Copyright 2015 The Kubernetes Authors.

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

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

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

package e2e

import (
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"syscall"
	"time"

	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/util/wait"
	"k8s.io/kubernetes/pkg/version"
	"k8s.io/kubernetes/test/e2e/framework"
	testutils "k8s.io/kubernetes/test/utils"

	. "github.com/onsi/ginkgo"
)

const (
	podName = "pfpod"
)

// TODO support other ports besides 80
var (
	portForwardRegexp        = regexp.MustCompile("Forwarding from 127.0.0.1:([0-9]+) -> 80")
	portForwardPortToStdOutV = version.MustParse("v1.3.0-alpha.4")
)

func pfPod(expectedClientData, chunks, chunkSize, chunkIntervalMillis string) *api.Pod {
	return &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:   podName,
			Labels: map[string]string{"name": podName},
		},
		Spec: api.PodSpec{
			Containers: []api.Container{
				{
					Name:  "readiness",
					Image: "gcr.io/google_containers/netexec:1.7",
					ReadinessProbe: &api.Probe{
						Handler: api.Handler{
							Exec: &api.ExecAction{
								Command: []string{
									"sh", "-c", "netstat -na | grep LISTEN | grep -v 8080 | grep 80",
								}},
						},
						InitialDelaySeconds: 5,
						TimeoutSeconds:      60,
						PeriodSeconds:       1,
					},
				},
				{
					Name:  "portforwardtester",
					Image: "gcr.io/google_containers/portforwardtester:1.2",
					Env: []api.EnvVar{
						{
							Name:  "BIND_PORT",
							Value: "80",
						},
						{
							Name:  "EXPECTED_CLIENT_DATA",
							Value: expectedClientData,
						},
						{
							Name:  "CHUNKS",
							Value: chunks,
						},
						{
							Name:  "CHUNK_SIZE",
							Value: chunkSize,
						},
						{
							Name:  "CHUNK_INTERVAL",
							Value: chunkIntervalMillis,
						},
					},
				},
			},
			RestartPolicy: api.RestartPolicyNever,
		},
	}
}

func WaitForTerminatedContainer(f *framework.Framework, pod *api.Pod, containerName string) error {
	return framework.WaitForPodCondition(f.ClientSet, f.Namespace.Name, pod.Name, "container terminated", framework.PodStartTimeout, func(pod *api.Pod) (bool, error) {
		if len(testutils.TerminatedContainers(pod)[containerName]) > 0 {
			return true, nil
		}
		return false, nil
	})
}

type portForwardCommand struct {
	cmd  *exec.Cmd
	port int
}

// Stop attempts to gracefully stop `kubectl port-forward`, only killing it if necessary.
// This helps avoid spdy goroutine leaks in the Kubelet.
func (c *portForwardCommand) Stop() {
	// SIGINT signals that kubectl port-forward should gracefully terminate
	if err := c.cmd.Process.Signal(syscall.SIGINT); err != nil {
		framework.Logf("error sending SIGINT to kubectl port-forward: %v", err)
	}

	// try to wait for a clean exit
	done := make(chan error)
	go func() {
		done <- c.cmd.Wait()
	}()

	expired := time.NewTimer(wait.ForeverTestTimeout)
	defer expired.Stop()

	select {
	case err := <-done:
		if err == nil {
			// success
			return
		}
		framework.Logf("error waiting for kubectl port-forward to exit: %v", err)
	case <-expired.C:
		framework.Logf("timed out waiting for kubectl port-forward to exit")
	}

	framework.Logf("trying to forcibly kill kubectl port-forward")
	framework.TryKill(c.cmd)
}

func runPortForward(ns, podName string, port int) *portForwardCommand {
	cmd := framework.KubectlCmd("port-forward", fmt.Sprintf("--namespace=%v", ns), podName, fmt.Sprintf(":%d", port))
	// This is somewhat ugly but is the only way to retrieve the port that was picked
	// by the port-forward command. We don't want to hard code the port as we have no
	// way of guaranteeing we can pick one that isn't in use, particularly on Jenkins.
	framework.Logf("starting port-forward command and streaming output")
	stdout, stderr, err := framework.StartCmdAndStreamOutput(cmd)
	if err != nil {
		framework.Failf("Failed to start port-forward command: %v", err)
	}

	buf := make([]byte, 128)

	// After v1.3.0-alpha.4 (#17030), kubectl port-forward outputs port
	// info to stdout, not stderr, so for version-skewed tests, look there
	// instead.
	var portOutput io.ReadCloser
	if useStdOut, err := framework.KubectlVersionGTE(portForwardPortToStdOutV); err != nil {
		framework.Failf("Failed to get kubectl version: %v", err)
	} else if useStdOut {
		portOutput = stdout
	} else {
		portOutput = stderr
	}

	var n int
	framework.Logf("reading from `kubectl port-forward` command's stdout")
	if n, err = portOutput.Read(buf); err != nil {
		framework.Failf("Failed to read from kubectl port-forward stdout: %v", err)
	}
	portForwardOutput := string(buf[:n])
	match := portForwardRegexp.FindStringSubmatch(portForwardOutput)
	if len(match) != 2 {
		framework.Failf("Failed to parse kubectl port-forward output: %s", portForwardOutput)
	}

	listenPort, err := strconv.Atoi(match[1])
	if err != nil {
		framework.Failf("Error converting %s to an int: %v", match[1], err)
	}

	return &portForwardCommand{
		cmd:  cmd,
		port: listenPort,
	}
}

var _ = framework.KubeDescribe("Port forwarding", func() {
	f := framework.NewDefaultFramework("port-forwarding")

	framework.KubeDescribe("With a server that expects a client request", func() {
		It("should support a client that connects, sends no data, and disconnects [Conformance]", func() {
			By("creating the target pod")
			pod := pfPod("abc", "1", "1", "1")
			if _, err := f.Client.Pods(f.Namespace.Name).Create(pod); err != nil {
				framework.Failf("Couldn't create pod: %v", err)
			}
			if err := f.WaitForPodReady(pod.Name); err != nil {
				framework.Failf("Pod did not start running: %v", err)
			}
			defer func() {
				logs, err := framework.GetPodLogs(f.Client, f.Namespace.Name, pod.Name, "portforwardtester")
				if err != nil {
					framework.Logf("Error getting pod log: %v", err)
				} else {
					framework.Logf("Pod log:\n%s", logs)
				}
			}()

			By("Running 'kubectl port-forward'")
			cmd := runPortForward(f.Namespace.Name, pod.Name, 80)
			defer cmd.Stop()

			By("Dialing the local port")
			conn, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", cmd.port))
			if err != nil {
				framework.Failf("Couldn't connect to port %d: %v", cmd.port, err)
			}

			By("Closing the connection to the local port")
			conn.Close()

			By("Waiting for the target pod to stop running")
			if err := WaitForTerminatedContainer(f, pod, "portforwardtester"); err != nil {
				framework.Failf("Container did not terminate: %v", err)
			}

			By("Verifying logs")
			logOutput, err := framework.GetPodLogs(f.Client, f.Namespace.Name, pod.Name, "portforwardtester")
			if err != nil {
				framework.Failf("Error retrieving pod logs: %v", err)
			}
			verifyLogMessage(logOutput, "Accepted client connection")
			verifyLogMessage(logOutput, "Expected to read 3 bytes from client, but got 0 instead")
		})

		It("should support a client that connects, sends data, and disconnects [Conformance]", func() {
			By("creating the target pod")
			pod := pfPod("abc", "10", "10", "100")
			if _, err := f.Client.Pods(f.Namespace.Name).Create(pod); err != nil {
				framework.Failf("Couldn't create pod: %v", err)
			}
			if err := f.WaitForPodReady(pod.Name); err != nil {
				framework.Failf("Pod did not start running: %v", err)
			}
			defer func() {
				logs, err := framework.GetPodLogs(f.Client, f.Namespace.Name, pod.Name, "portforwardtester")
				if err != nil {
					framework.Logf("Error getting pod log: %v", err)
				} else {
					framework.Logf("Pod log:\n%s", logs)
				}
			}()

			By("Running 'kubectl port-forward'")
			cmd := runPortForward(f.Namespace.Name, pod.Name, 80)
			defer cmd.Stop()

			By("Dialing the local port")
			addr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("127.0.0.1:%d", cmd.port))
			if err != nil {
				framework.Failf("Error resolving tcp addr: %v", err)
			}
			conn, err := net.DialTCP("tcp", nil, addr)
			if err != nil {
				framework.Failf("Couldn't connect to port %d: %v", cmd.port, err)
			}
			defer func() {
				By("Closing the connection to the local port")
				conn.Close()
			}()

			By("Sending the expected data to the local port")
			fmt.Fprint(conn, "abc")

			By("Closing the write half of the client's connection")
			conn.CloseWrite()

			By("Reading data from the local port")
			fromServer, err := ioutil.ReadAll(conn)
			if err != nil {
				framework.Failf("Unexpected error reading data from the server: %v", err)
			}

			if e, a := strings.Repeat("x", 100), string(fromServer); e != a {
				framework.Failf("Expected %q from server, got %q", e, a)
			}

			By("Waiting for the target pod to stop running")
			if err := WaitForTerminatedContainer(f, pod, "portforwardtester"); err != nil {
				framework.Failf("Container did not terminate: %v", err)
			}

			By("Verifying logs")
			logOutput, err := framework.GetPodLogs(f.Client, f.Namespace.Name, pod.Name, "portforwardtester")
			if err != nil {
				framework.Failf("Error retrieving pod logs: %v", err)
			}
			verifyLogMessage(logOutput, "^Accepted client connection$")
			verifyLogMessage(logOutput, "^Received expected client data$")
			verifyLogMessage(logOutput, "^Done$")
		})
	})
	framework.KubeDescribe("With a server that expects no client request", func() {
		It("should support a client that connects, sends no data, and disconnects [Conformance]", func() {
			By("creating the target pod")
			pod := pfPod("", "10", "10", "100")
			if _, err := f.Client.Pods(f.Namespace.Name).Create(pod); err != nil {
				framework.Failf("Couldn't create pod: %v", err)
			}
			if err := f.WaitForPodReady(pod.Name); err != nil {
				framework.Failf("Pod did not start running: %v", err)
			}
			defer func() {
				logs, err := framework.GetPodLogs(f.Client, f.Namespace.Name, pod.Name, "portforwardtester")
				if err != nil {
					framework.Logf("Error getting pod log: %v", err)
				} else {
					framework.Logf("Pod log:\n%s", logs)
				}
			}()

			By("Running 'kubectl port-forward'")
			cmd := runPortForward(f.Namespace.Name, pod.Name, 80)
			defer cmd.Stop()

			By("Dialing the local port")
			conn, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", cmd.port))
			if err != nil {
				framework.Failf("Couldn't connect to port %d: %v", cmd.port, err)
			}
			defer func() {
				By("Closing the connection to the local port")
				conn.Close()
			}()

			By("Reading data from the local port")
			fromServer, err := ioutil.ReadAll(conn)
			if err != nil {
				framework.Failf("Unexpected error reading data from the server: %v", err)
			}

			if e, a := strings.Repeat("x", 100), string(fromServer); e != a {
				framework.Failf("Expected %q from server, got %q", e, a)
			}

			By("Waiting for the target pod to stop running")
			if err := WaitForTerminatedContainer(f, pod, "portforwardtester"); err != nil {
				framework.Failf("Container did not terminate: %v", err)
			}

			By("Verifying logs")
			logOutput, err := framework.GetPodLogs(f.Client, f.Namespace.Name, pod.Name, "portforwardtester")
			if err != nil {
				framework.Failf("Error retrieving pod logs: %v", err)
			}
			verifyLogMessage(logOutput, "Accepted client connection")
			verifyLogMessage(logOutput, "Done")
		})
	})
})

func verifyLogMessage(log, expected string) {
	re := regexp.MustCompile(expected)
	lines := strings.Split(log, "\n")
	for i := range lines {
		if re.MatchString(lines[i]) {
			return
		}
	}
	framework.Failf("Missing %q from log: %s", expected, log)
}
<|endoftext|>


<commit_before>package catTracks

//Handles
import (
	"encoding/csv"
	"encoding/json"
	"fmt"
	"html/template"
	"net/http"
	"strconv"
	"time"

	"github.com/rotblauer/trackpoints/trackPoint"
	"log"
)

// the html stuff of this thing
var templates = template.Must(template.ParseGlob("templates/*.html"))

//Welcome, loads and servers all (currently) data pointers
func getIndexTemplate(w http.ResponseWriter, r *http.Request) {
	templates.ExecuteTemplate(w, "base", nil)
}
func getRaceTemplate(w http.ResponseWriter, r *http.Request) {
	templates.ExecuteTemplate(w, "race", nil)
}
func getMapTemplate(w http.ResponseWriter, r *http.Request) {
	templates.ExecuteTemplate(w, "map", nil)
}
func getLeafTemplate(w http.ResponseWriter, r *http.Request) {
	templates.ExecuteTemplate(w, "leaf", nil)
}

func socket(w http.ResponseWriter, r *http.Request) {
	// see ./socket.go
	GetMelody().HandleRequest(w, r)
}

func getRaceJSON(w http.ResponseWriter, r *http.Request) {
	var e error

	var renderer = make(map[string]interface{})
	var spans = map[string]int{
		"today": 1,
		"week":  7,
		"all":   10,
	}

	for span, spanVal := range spans {
		renderer[span], e = buildTimePeriodStats(spanVal)
		if e != nil {
			fmt.Println(e)
			http.Error(w, e.Error(), http.StatusInternalServerError)
		}
	}

	buf, e := json.Marshal(renderer)
	if e != nil {
		fmt.Println(e)
		http.Error(w, e.Error(), http.StatusInternalServerError)
	}
	w.Write(buf)
}

func getPointsJSON(w http.ResponseWriter, r *http.Request) {
	query := parseQuery(r, w)

	data, eq := getData(query)
	if eq != nil {
		http.Error(w, eq.Error(), http.StatusInternalServerError)
	}
	fmt.Println("Receive ajax get data string ")
	w.Write(data)
}
func getData(query *query) ([]byte, error) {
	var data []byte
	allPoints, e := getPointsQT(query)
	if e != nil {
		return data, e
	}
	data, err := json.Marshal(allPoints)
	if err != nil {
		return data, err
	}
	return data, nil
}

func populatePoints(w http.ResponseWriter, r *http.Request) {
	var trackPoints trackPoint.TrackPoints

	if r.Body == nil {
		http.Error(w, "Please send a request body", 500)
		return
	}
	err := json.NewDecoder(r.Body).Decode(&trackPoints)
	if err != nil {
		http.Error(w, err.Error(), 400)
		return
	}
	errS := storePoints(trackPoints)
	if errS != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
	//return json of trakcpoint if stored succcess
	// this is dumb because the ios app doesn't use the JSON at all, and only checks
	// if the response is not an error.
	// it causes the tracks POST to actually DOWNLOAD the whole set of points
	// that it just pushed.
	//if errW := json.NewEncoder(w).Encode(&trackPoints); errW != nil {
	//	http.Error(w, err.Error(), http.StatusInternalServerError)
	//}

	// don't want plain text because we're in JSON land here
	//w.Header().Set("Content-Type", "text/plain; charset=utf-8")
	//w.Header().Set("X-Content-Type-Options", "nosniff")
	//w.WriteHeader(http.StatusOK)
	//fmt.Fprintln(w, "SUCCESS")

	if errW := json.NewEncoder(w).Encode(&struct{
		Status uint
	}{
		Status: http.StatusOK,
	}); errW != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func uploadCSV(w http.ResponseWriter, r *http.Request) {
	r.ParseMultipartForm(32 << 30)
	file, _, err := r.FormFile("uploadfile")
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	defer file.Close()

	lines, err := csv.NewReader(file).ReadAll()
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	for _, line := range lines {
		var tp trackPoint.TrackPoint

		tp.Name = line[0]

		if tp.Time, err = time.Parse(time.UnixDate, line[1]); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		if tp.Lat, err = strconv.ParseFloat(line[2], 64); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		if tp.Lng, err = strconv.ParseFloat(line[3], 64); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		errS := storePoint(tp)
		if errS != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

	}

	http.Redirect(w, r, "/", 302) //the 300

}

func getLastKnown(w http.ResponseWriter, r *http.Request) {
	w.Header().Add("Access-Control-Allow-Origin","*")
	b, e := getLastKnownData()
	//b, e := json.Marshal(lastKnownMap)
	if e != nil {
		log.Println(e)
		http.Error(w, e.Error(), http.StatusInternalServerError)
	}
	fmt.Println("Got lastknown:", len(b), "bytes")
	w.Write(b)
}

func getMetaData(w http.ResponseWriter, r *http.Request) {
	w.Header().Add("Access-Control-Allow-Origin","*")

	b, e := getmetadata()
	if e != nil {
		log.Println(e)
		http.Error(w, e.Error(), http.StatusInternalServerError)
	}
	fmt.Println("Got metadata:", len(b), "bytes")
	w.Write(b)
}<commit_msg>Revert "problem: posting cattracks causes download of all just-posted tracks"<commit_after>package catTracks

//Handles
import (
	"encoding/csv"
	"encoding/json"
	"fmt"
	"html/template"
	"net/http"
	"strconv"
	"time"

	"github.com/rotblauer/trackpoints/trackPoint"
	"log"
)

// the html stuff of this thing
var templates = template.Must(template.ParseGlob("templates/*.html"))

//Welcome, loads and servers all (currently) data pointers
func getIndexTemplate(w http.ResponseWriter, r *http.Request) {
	templates.ExecuteTemplate(w, "base", nil)
}
func getRaceTemplate(w http.ResponseWriter, r *http.Request) {
	templates.ExecuteTemplate(w, "race", nil)
}
func getMapTemplate(w http.ResponseWriter, r *http.Request) {
	templates.ExecuteTemplate(w, "map", nil)
}
func getLeafTemplate(w http.ResponseWriter, r *http.Request) {
	templates.ExecuteTemplate(w, "leaf", nil)
}

func socket(w http.ResponseWriter, r *http.Request) {
	// see ./socket.go
	GetMelody().HandleRequest(w, r)
}

func getRaceJSON(w http.ResponseWriter, r *http.Request) {
	var e error

	var renderer = make(map[string]interface{})
	var spans = map[string]int{
		"today": 1,
		"week":  7,
		"all":   10,
	}

	for span, spanVal := range spans {
		renderer[span], e = buildTimePeriodStats(spanVal)
		if e != nil {
			fmt.Println(e)
			http.Error(w, e.Error(), http.StatusInternalServerError)
		}
	}

	buf, e := json.Marshal(renderer)
	if e != nil {
		fmt.Println(e)
		http.Error(w, e.Error(), http.StatusInternalServerError)
	}
	w.Write(buf)
}

func getPointsJSON(w http.ResponseWriter, r *http.Request) {
	query := parseQuery(r, w)

	data, eq := getData(query)
	if eq != nil {
		http.Error(w, eq.Error(), http.StatusInternalServerError)
	}
	fmt.Println("Receive ajax get data string ")
	w.Write(data)
}
func getData(query *query) ([]byte, error) {
	var data []byte
	allPoints, e := getPointsQT(query)
	if e != nil {
		return data, e
	}
	data, err := json.Marshal(allPoints)
	if err != nil {
		return data, err
	}
	return data, nil
}

func populatePoints(w http.ResponseWriter, r *http.Request) {
	var trackPoints trackPoint.TrackPoints

	if r.Body == nil {
		http.Error(w, "Please send a request body", 500)
		return
	}
	err := json.NewDecoder(r.Body).Decode(&trackPoints)
	if err != nil {
		http.Error(w, err.Error(), 400)
		return
	}
	errS := storePoints(trackPoints)
	if errS != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
	//return json of trakcpoint if stored succcess
	if errW := json.NewEncoder(w).Encode(&trackPoints); errW != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func uploadCSV(w http.ResponseWriter, r *http.Request) {
	r.ParseMultipartForm(32 << 30)
	file, _, err := r.FormFile("uploadfile")
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	defer file.Close()

	lines, err := csv.NewReader(file).ReadAll()
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	for _, line := range lines {
		var tp trackPoint.TrackPoint

		tp.Name = line[0]

		if tp.Time, err = time.Parse(time.UnixDate, line[1]); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		if tp.Lat, err = strconv.ParseFloat(line[2], 64); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		if tp.Lng, err = strconv.ParseFloat(line[3], 64); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		errS := storePoint(tp)
		if errS != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

	}

	http.Redirect(w, r, "/", 302) //the 300

}

func getLastKnown(w http.ResponseWriter, r *http.Request) {
	w.Header().Add("Access-Control-Allow-Origin","*")
	b, e := getLastKnownData()
	//b, e := json.Marshal(lastKnownMap)
	if e != nil {
		log.Println(e)
		http.Error(w, e.Error(), http.StatusInternalServerError)
	}
	fmt.Println("Got lastknown:", len(b), "bytes")
	w.Write(b)
}

func getMetaData(w http.ResponseWriter, r *http.Request) {
	w.Header().Add("Access-Control-Allow-Origin","*")

	b, e := getmetadata()
	if e != nil {
		log.Println(e)
		http.Error(w, e.Error(), http.StatusInternalServerError)
	}
	fmt.Println("Got metadata:", len(b), "bytes")
	w.Write(b)
}<|endoftext|>


<commit_before>package graphics

import "github.com/qlova/uct/compiler"
import "github.com/qlova/ilang/syntax/symbols"
import "github.com/qlova/ilang/syntax/errors"
import "github.com/qlova/ilang/syntax/grate"
import "github.com/qlova/ilang/syntax/update"

import "github.com/qlova/ilang/syntax/global"

import "github.com/qlova/ilang/types/text"

var Name = compiler.Translatable {
		compiler.English: "graphics",
}

var Flag = compiler.Flag {
	Name: Name,

	OnLost: func(c *compiler.Compiler) {
		c.Back()
		c.Main()

		global.Init(c)

		c.Native("py", "global_runtime = runtime")
		c.Native("py", "pyglet.clock.schedule_interval(update, 1/30.0)")
		c.Native("py", "pyglet.app.run()")

		// Call ebiten.Run to start your game loop.
		c.Native("go", `global_runtime = runtime; ebiten.Run(grate_update, 800, 600, 1, "")`)

		c.Exit()
	},
}

var Graphics = compiler.Statement {
	Name: Name,

	OnScan:  func(c *compiler.Compiler) {
		if !c.GlobalFlagExists(grate.Flag) {
			grate.Init(c)
			c.SetGlobalFlag(grate.Flag)
		}

		if !c.GlobalFlagExists(update.Flag) {
			update.Init(c)
			c.SetGlobalFlag(update.Flag)
		}

		c.Native("go", `
var global_runtime *Runtime
var grate_screen *ebiten.Image

var grate_font font.Face
var grate_font_drawer font.Drawer

func init() {
	data, err := base64.StdEncoding.DecodeString(`+"`"+Font+"`"+`)
	if err != nil {
		fmt.Println("error:", err)
		return
	}

	tt, err := truetype.Parse(data)
	if err != nil {
		println(err.Error())
	}

	const dpi = 72
	grate_font = truetype.NewFace(tt, &truetype.Options{
		Size:    24,
		DPI:     dpi,
		Hinting: font.HintingFull,
	})
	grate_font_drawer = font.Drawer{Face: grate_font}
}

func display_text() {
	var w, h = grate_screen.Size()
	var message = string(global_runtime.PullList().Bytes)

	//Measure.
	var length = grate_font_drawer.MeasureString(message)

	text.Draw(grate_screen, message, grate_font, w/2 - length.Round()/2, h/2, color.White)
}

`)

		c.Expecting(symbols.CodeBlockBegin)
		c.Code("grate_graphics")
		c.GainScope()
		c.SetFlag(Flag)
	},
}

var Display = compiler.Statement {
	Name: compiler.Translatable {
		compiler.English: "display",
	},

	OnScan: func(c *compiler.Compiler) {
		c.Expecting(symbols.FunctionCallBegin)
		var arg = c.ScanExpression()
		c.Expecting(symbols.FunctionCallEnd)

		if !arg.Equals(text.Type) {
			c.RaiseError(errors.ExpectingType(text.Type, arg))
		}

		c.Native("py", "grate_label.text = bytearray(runtime.Lists.pop()).decode('utf8')")
		c.Native("py", "grate_label.draw()")

		c.Native("go", "display_text()")
	},
}
<commit_msg>Fix python graphics without update.<commit_after>package graphics

import "github.com/qlova/uct/compiler"
import "github.com/qlova/ilang/syntax/symbols"
import "github.com/qlova/ilang/syntax/errors"
import "github.com/qlova/ilang/syntax/grate"
import "github.com/qlova/ilang/syntax/update"

import "github.com/qlova/ilang/syntax/global"

import "github.com/qlova/ilang/types/text"

var Name = compiler.Translatable {
		compiler.English: "graphics",
}

var Flag = compiler.Flag {
	Name: Name,

	OnLost: func(c *compiler.Compiler) {
		c.Back()
		c.Main()

		global.Init(c)

		c.Native("py", "global_runtime = runtime")
		c.Native("py", "try:")
		c.Native("py", "\tpyglet.clock.schedule_interval(update, 1/30.0)")
		c.Native("py", "except NameError:")
		c.Native("py", "\tpass")
		c.Native("py", "pyglet.app.run()")

		// Call ebiten.Run to start your game loop.
		c.Native("go", `global_runtime = runtime; ebiten.Run(grate_update, 800, 600, 1, "")`)

		c.Exit()
	},
}

var Graphics = compiler.Statement {
	Name: Name,

	OnScan:  func(c *compiler.Compiler) {
		if !c.GlobalFlagExists(grate.Flag) {
			grate.Init(c)
			c.SetGlobalFlag(grate.Flag)
		}

		if !c.GlobalFlagExists(update.Flag) {
			update.Init(c)
			c.SetGlobalFlag(update.Flag)
		}

		c.Native("go", `
var global_runtime *Runtime
var grate_screen *ebiten.Image

var grate_font font.Face
var grate_font_drawer font.Drawer

func init() {
	data, err := base64.StdEncoding.DecodeString(`+"`"+Font+"`"+`)
	if err != nil {
		fmt.Println("error:", err)
		return
	}

	tt, err := truetype.Parse(data)
	if err != nil {
		println(err.Error())
	}

	const dpi = 72
	grate_font = truetype.NewFace(tt, &truetype.Options{
		Size:    24,
		DPI:     dpi,
		Hinting: font.HintingFull,
	})
	grate_font_drawer = font.Drawer{Face: grate_font}
}

func display_text() {
	var w, h = grate_screen.Size()
	var message = string(global_runtime.PullList().Bytes)

	//Measure.
	var length = grate_font_drawer.MeasureString(message)

	text.Draw(grate_screen, message, grate_font, w/2 - length.Round()/2, h/2, color.White)
}

`)

		c.Expecting(symbols.CodeBlockBegin)
		c.Code("grate_graphics")
		c.GainScope()
		c.SetFlag(Flag)
	},
}

var Display = compiler.Statement {
	Name: compiler.Translatable {
		compiler.English: "display",
	},

	OnScan: func(c *compiler.Compiler) {
		c.Expecting(symbols.FunctionCallBegin)
		var arg = c.ScanExpression()
		c.Expecting(symbols.FunctionCallEnd)

		if !arg.Equals(text.Type) {
			c.RaiseError(errors.ExpectingType(text.Type, arg))
		}

		c.Native("py", "grate_label.text = bytearray(runtime.Lists.pop()).decode('utf8')")
		c.Native("py", "grate_label.draw()")

		c.Native("go", "display_text()")
	},
}
<|endoftext|>


<commit_before>// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package tables_test

import (
	"testing"

	. "github.com/pingcap/check"
	"github.com/pingcap/tidb"
	"github.com/pingcap/tidb/column"
	"github.com/pingcap/tidb/context"
	"github.com/pingcap/tidb/kv"
	"github.com/pingcap/tidb/model"
	"github.com/pingcap/tidb/mysql"
	"github.com/pingcap/tidb/sessionctx"
	"github.com/pingcap/tidb/store/localstore"
	"github.com/pingcap/tidb/store/localstore/goleveldb"
	"github.com/pingcap/tidb/table/tables"
	"github.com/pingcap/tidb/util"
)

func TestT(t *testing.T) {
	TestingT(t)
}

var _ = Suite(&testSuite{})

type testSuite struct {
	store kv.Storage
	se    tidb.Session
}

func (ts *testSuite) SetUpSuite(c *C) {
	driver := localstore.Driver{Driver: goleveldb.MemoryDriver{}}
	store, err := driver.Open("memory")
	c.Check(err, IsNil)
	ts.store = store
	ts.se, err = tidb.CreateSession(ts.store)
	c.Assert(err, IsNil)
}

func (ts *testSuite) TestBasic(c *C) {
	_, err := ts.se.Execute("CREATE TABLE test.t (a int primary key auto_increment, b varchar(255) unique)")
	c.Assert(err, IsNil)
	ctx := ts.se.(context.Context)
	dom := sessionctx.GetDomain(ctx)
	tb, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t"))
	c.Assert(err, IsNil)
	c.Assert(tb.TableID(), Greater, int64(0))
	c.Assert(tb.TableName().L, Equals, "t")
	c.Assert(tb.Meta(), NotNil)
	c.Assert(tb.Indices(), NotNil)
	c.Assert(string(tb.FirstKey()), Not(Equals), "")
	c.Assert(string(tb.IndexPrefix()), Not(Equals), "")
	c.Assert(string(tb.RecordPrefix()), Not(Equals), "")
	c.Assert(tb.FindIndexByColName("b"), NotNil)

	autoid, err := tb.AllocAutoID()
	c.Assert(err, IsNil)
	c.Assert(autoid, Greater, int64(0))

	rid, err := tb.AddRecord(ctx, []interface{}{1, "abc"})
	c.Assert(err, IsNil)
	c.Assert(rid, Greater, int64(0))
	row, err := tb.Row(ctx, rid)
	c.Assert(err, IsNil)
	c.Assert(len(row), Equals, 2)
	c.Assert(row[0], Equals, int64(1))

	_, err = tb.AddRecord(ctx, []interface{}{1, "aba"})
	c.Assert(err, NotNil)
	_, err = tb.AddRecord(ctx, []interface{}{2, "abc"})
	c.Assert(err, NotNil)

	c.Assert(tb.UpdateRecord(ctx, rid, []interface{}{1, "abc"}, []interface{}{1, "cba"}, map[int]bool{0: false, 1: true}), IsNil)

	txn, err := ctx.GetTxn(false)
	c.Assert(err, IsNil)
	tb.IterRecords(txn, tb.FirstKey(), tb.Cols(), func(h int64, data []interface{}, cols []*column.Col) (bool, error) {
		return true, nil
	})

	indexCnt := func() int {
		cnt, err2 := countEntriesWithPrefix(ctx, tb.IndexPrefix())
		c.Assert(err2, IsNil)
		return cnt
	}

	// RowWithCols test
	vals, err := tb.RowWithCols(txn, 1, tb.Cols())
	c.Assert(err, IsNil)
	c.Assert(vals, HasLen, 2)
	c.Assert(vals[0], Equals, int64(1))
	cols := []*column.Col{tb.Cols()[1]}
	vals, err = tb.RowWithCols(txn, 1, cols)
	c.Assert(err, IsNil)
	c.Assert(vals, HasLen, 1)
	c.Assert(vals[0], DeepEquals, []uint8("cba"))

	// Make sure there is index data in the storage.
	c.Assert(indexCnt(), Greater, 0)
	c.Assert(tb.RemoveRecord(ctx, rid, []interface{}{1, "cba"}), IsNil)
	// Make sure index data is also removed after tb.RemoveRecord().
	c.Assert(indexCnt(), Equals, 0)
	_, err = tb.AddRecord(ctx, []interface{}{1, "abc"})
	c.Assert(err, IsNil)
	c.Assert(indexCnt(), Greater, 0)
	// Make sure index data is also removed after tb.Truncate().
	c.Assert(tb.Truncate(txn), IsNil)
	c.Assert(indexCnt(), Equals, 0)

	_, err = ts.se.Execute("drop table test.t")
	c.Assert(err, IsNil)
}

func countEntriesWithPrefix(ctx context.Context, prefix []byte) (int, error) {
	txn, err := ctx.GetTxn(false)
	if err != nil {
		return 0, err
	}
	cnt := 0
	err = util.ScanMetaWithPrefix(txn, prefix, func(k kv.Key, v []byte) bool {
		cnt++
		return true
	})
	return cnt, err
}

func (ts *testSuite) TestTypes(c *C) {
	_, err := ts.se.Execute("CREATE TABLE test.t (c1 tinyint, c2 smallint, c3 int, c4 bigint, c5 text, c6 blob, c7 varchar(64), c8 time, c9 timestamp not null default CURRENT_TIMESTAMP, c10 decimal)")
	c.Assert(err, IsNil)
	ctx := ts.se.(context.Context)
	dom := sessionctx.GetDomain(ctx)
	_, err = dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t"))
	c.Assert(err, IsNil)
	_, err = ts.se.Execute("insert test.t values (1, 2, 3, 4, '5', '6', '7', '10:10:10', null, 1.4)")
	c.Assert(err, IsNil)
	rs, err := ts.se.Execute("select * from test.t where c1 = 1")
	c.Assert(err, IsNil)
	row, err := rs[0].FirstRow()
	c.Assert(err, IsNil)
	c.Assert(row, NotNil)
	_, err = ts.se.Execute("drop table test.t")
	c.Assert(err, IsNil)

	_, err = ts.se.Execute("CREATE TABLE test.t (c1 tinyint unsigned, c2 smallint unsigned, c3 int unsigned, c4 bigint unsigned, c5 double, c6 bit(8))")
	c.Assert(err, IsNil)
	_, err = ts.se.Execute("insert test.t values (1, 2, 3, 4, 5, 6)")
	c.Assert(err, IsNil)
	rs, err = ts.se.Execute("select * from test.t where c1 = 1")
	c.Assert(err, IsNil)
	row, err = rs[0].FirstRow()
	c.Assert(err, IsNil)
	c.Assert(row, NotNil)
	c.Assert(row[5], Equals, mysql.Bit{Value: 6, Width: 8})
	_, err = ts.se.Execute("drop table test.t")
	c.Assert(err, IsNil)

	_, err = ts.se.Execute("CREATE TABLE test.t (c1 enum('a', 'b', 'c'))")
	c.Assert(err, IsNil)
	_, err = ts.se.Execute("insert test.t values ('a'), (2), ('c')")
	c.Assert(err, IsNil)
	rs, err = ts.se.Execute("select c1 + 1 from test.t where c1 = 1")
	c.Assert(err, IsNil)
	row, err = rs[0].FirstRow()
	c.Assert(err, IsNil)
	c.Assert(row, NotNil)
	c.Assert(row[0], DeepEquals, float64(2))
	_, err = ts.se.Execute("drop table test.t")
	c.Assert(err, IsNil)
}

func (ts *testSuite) TestUniqueIndexMultipleNullEntries(c *C) {
	_, err := ts.se.Execute("CREATE TABLE test.t (a int primary key auto_increment, b varchar(255) unique)")
	c.Assert(err, IsNil)
	ctx := ts.se.(context.Context)
	dom := sessionctx.GetDomain(ctx)
	tb, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t"))
	c.Assert(err, IsNil)
	c.Assert(tb.TableID(), Greater, int64(0))
	c.Assert(tb.TableName().L, Equals, "t")
	c.Assert(tb.Meta(), NotNil)
	c.Assert(tb.Indices(), NotNil)
	c.Assert(string(tb.FirstKey()), Not(Equals), "")
	c.Assert(string(tb.IndexPrefix()), Not(Equals), "")
	c.Assert(string(tb.RecordPrefix()), Not(Equals), "")
	c.Assert(tb.FindIndexByColName("b"), NotNil)

	autoid, err := tb.AllocAutoID()
	c.Assert(err, IsNil)
	c.Assert(autoid, Greater, int64(0))

	_, err = tb.AddRecord(ctx, []interface{}{1, nil})
	c.Assert(err, IsNil)
	_, err = tb.AddRecord(ctx, []interface{}{2, nil})
	c.Assert(err, IsNil)
	_, err = ts.se.Execute("drop table test.t")
	c.Assert(err, IsNil)
}

func (ts *testSuite) TestRowKeyCodec(c *C) {
	table := []struct {
		tableID int64
		h       int64
		ID      int64
	}{
		{1, 1234567890, 0},
		{2, 1, 0},
		{3, -1, 0},
		{4, -1, 1},
	}

	for _, t := range table {
		b := tables.EncodeRecordKey(t.tableID, t.h, t.ID)
		tableID, handle, columnID, err := tables.DecodeRecordKey(b)
		c.Assert(err, IsNil)
		c.Assert(tableID, Equals, t.tableID)
		c.Assert(handle, Equals, t.h)
		c.Assert(columnID, Equals, t.ID)

		handle, err = tables.DecodeRecordKeyHandle(b)
		c.Assert(err, IsNil)
		c.Assert(handle, Equals, t.h)
	}

	// test error
	tbl := []string{
		"",
		"x",
		"t1",
		"t12345678",
		"t12345678_i",
		"t12345678_r1",
		"t12345678_r1234567",
		"t12345678_r123456781",
	}

	for _, t := range tbl {
		_, err := tables.DecodeRecordKeyHandle(kv.Key(t))
		c.Assert(err, NotNil)
	}
}
<commit_msg>table: address comments<commit_after>// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package tables_test

import (
	"testing"

	. "github.com/pingcap/check"
	"github.com/pingcap/tidb"
	"github.com/pingcap/tidb/column"
	"github.com/pingcap/tidb/context"
	"github.com/pingcap/tidb/kv"
	"github.com/pingcap/tidb/model"
	"github.com/pingcap/tidb/mysql"
	"github.com/pingcap/tidb/sessionctx"
	"github.com/pingcap/tidb/store/localstore"
	"github.com/pingcap/tidb/store/localstore/goleveldb"
	"github.com/pingcap/tidb/table/tables"
	"github.com/pingcap/tidb/util"
)

func TestT(t *testing.T) {
	TestingT(t)
}

var _ = Suite(&testSuite{})

type testSuite struct {
	store kv.Storage
	se    tidb.Session
}

func (ts *testSuite) SetUpSuite(c *C) {
	driver := localstore.Driver{Driver: goleveldb.MemoryDriver{}}
	store, err := driver.Open("memory")
	c.Check(err, IsNil)
	ts.store = store
	ts.se, err = tidb.CreateSession(ts.store)
	c.Assert(err, IsNil)
}

func (ts *testSuite) TestBasic(c *C) {
	_, err := ts.se.Execute("CREATE TABLE test.t (a int primary key auto_increment, b varchar(255) unique)")
	c.Assert(err, IsNil)
	ctx := ts.se.(context.Context)
	dom := sessionctx.GetDomain(ctx)
	tb, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t"))
	c.Assert(err, IsNil)
	c.Assert(tb.TableID(), Greater, int64(0))
	c.Assert(tb.TableName().L, Equals, "t")
	c.Assert(tb.Meta(), NotNil)
	c.Assert(tb.Indices(), NotNil)
	c.Assert(string(tb.FirstKey()), Not(Equals), "")
	c.Assert(string(tb.IndexPrefix()), Not(Equals), "")
	c.Assert(string(tb.RecordPrefix()), Not(Equals), "")
	c.Assert(tb.FindIndexByColName("b"), NotNil)

	autoid, err := tb.AllocAutoID()
	c.Assert(err, IsNil)
	c.Assert(autoid, Greater, int64(0))

	rid, err := tb.AddRecord(ctx, []interface{}{1, "abc"})
	c.Assert(err, IsNil)
	c.Assert(rid, Greater, int64(0))
	row, err := tb.Row(ctx, rid)
	c.Assert(err, IsNil)
	c.Assert(len(row), Equals, 2)
	c.Assert(row[0], Equals, int64(1))

	_, err = tb.AddRecord(ctx, []interface{}{1, "aba"})
	c.Assert(err, NotNil)
	_, err = tb.AddRecord(ctx, []interface{}{2, "abc"})
	c.Assert(err, NotNil)

	c.Assert(tb.UpdateRecord(ctx, rid, []interface{}{1, "abc"}, []interface{}{1, "cba"}, map[int]bool{0: false, 1: true}), IsNil)

	txn, err := ctx.GetTxn(false)
	c.Assert(err, IsNil)
	tb.IterRecords(txn, tb.FirstKey(), tb.Cols(), func(h int64, data []interface{}, cols []*column.Col) (bool, error) {
		return true, nil
	})

	indexCnt := func() int {
		cnt, err2 := countEntriesWithPrefix(ctx, tb.IndexPrefix())
		c.Assert(err2, IsNil)
		return cnt
	}

	// RowWithCols test
	vals, err := tb.RowWithCols(txn, 1, tb.Cols())
	c.Assert(err, IsNil)
	c.Assert(vals, HasLen, 2)
	c.Assert(vals[0], Equals, int64(1))
	cols := []*column.Col{tb.Cols()[1]}
	vals, err = tb.RowWithCols(txn, 1, cols)
	c.Assert(err, IsNil)
	c.Assert(vals, HasLen, 1)
	c.Assert(vals[0], DeepEquals, []byte("cba"))

	// Make sure there is index data in the storage.
	c.Assert(indexCnt(), Greater, 0)
	c.Assert(tb.RemoveRecord(ctx, rid, []interface{}{1, "cba"}), IsNil)
	// Make sure index data is also removed after tb.RemoveRecord().
	c.Assert(indexCnt(), Equals, 0)
	_, err = tb.AddRecord(ctx, []interface{}{1, "abc"})
	c.Assert(err, IsNil)
	c.Assert(indexCnt(), Greater, 0)
	// Make sure index data is also removed after tb.Truncate().
	c.Assert(tb.Truncate(txn), IsNil)
	c.Assert(indexCnt(), Equals, 0)

	_, err = ts.se.Execute("drop table test.t")
	c.Assert(err, IsNil)
}

func countEntriesWithPrefix(ctx context.Context, prefix []byte) (int, error) {
	txn, err := ctx.GetTxn(false)
	if err != nil {
		return 0, err
	}
	cnt := 0
	err = util.ScanMetaWithPrefix(txn, prefix, func(k kv.Key, v []byte) bool {
		cnt++
		return true
	})
	return cnt, err
}

func (ts *testSuite) TestTypes(c *C) {
	_, err := ts.se.Execute("CREATE TABLE test.t (c1 tinyint, c2 smallint, c3 int, c4 bigint, c5 text, c6 blob, c7 varchar(64), c8 time, c9 timestamp not null default CURRENT_TIMESTAMP, c10 decimal)")
	c.Assert(err, IsNil)
	ctx := ts.se.(context.Context)
	dom := sessionctx.GetDomain(ctx)
	_, err = dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t"))
	c.Assert(err, IsNil)
	_, err = ts.se.Execute("insert test.t values (1, 2, 3, 4, '5', '6', '7', '10:10:10', null, 1.4)")
	c.Assert(err, IsNil)
	rs, err := ts.se.Execute("select * from test.t where c1 = 1")
	c.Assert(err, IsNil)
	row, err := rs[0].FirstRow()
	c.Assert(err, IsNil)
	c.Assert(row, NotNil)
	_, err = ts.se.Execute("drop table test.t")
	c.Assert(err, IsNil)

	_, err = ts.se.Execute("CREATE TABLE test.t (c1 tinyint unsigned, c2 smallint unsigned, c3 int unsigned, c4 bigint unsigned, c5 double, c6 bit(8))")
	c.Assert(err, IsNil)
	_, err = ts.se.Execute("insert test.t values (1, 2, 3, 4, 5, 6)")
	c.Assert(err, IsNil)
	rs, err = ts.se.Execute("select * from test.t where c1 = 1")
	c.Assert(err, IsNil)
	row, err = rs[0].FirstRow()
	c.Assert(err, IsNil)
	c.Assert(row, NotNil)
	c.Assert(row[5], Equals, mysql.Bit{Value: 6, Width: 8})
	_, err = ts.se.Execute("drop table test.t")
	c.Assert(err, IsNil)

	_, err = ts.se.Execute("CREATE TABLE test.t (c1 enum('a', 'b', 'c'))")
	c.Assert(err, IsNil)
	_, err = ts.se.Execute("insert test.t values ('a'), (2), ('c')")
	c.Assert(err, IsNil)
	rs, err = ts.se.Execute("select c1 + 1 from test.t where c1 = 1")
	c.Assert(err, IsNil)
	row, err = rs[0].FirstRow()
	c.Assert(err, IsNil)
	c.Assert(row, NotNil)
	c.Assert(row[0], DeepEquals, float64(2))
	_, err = ts.se.Execute("drop table test.t")
	c.Assert(err, IsNil)
}

func (ts *testSuite) TestUniqueIndexMultipleNullEntries(c *C) {
	_, err := ts.se.Execute("CREATE TABLE test.t (a int primary key auto_increment, b varchar(255) unique)")
	c.Assert(err, IsNil)
	ctx := ts.se.(context.Context)
	dom := sessionctx.GetDomain(ctx)
	tb, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t"))
	c.Assert(err, IsNil)
	c.Assert(tb.TableID(), Greater, int64(0))
	c.Assert(tb.TableName().L, Equals, "t")
	c.Assert(tb.Meta(), NotNil)
	c.Assert(tb.Indices(), NotNil)
	c.Assert(string(tb.FirstKey()), Not(Equals), "")
	c.Assert(string(tb.IndexPrefix()), Not(Equals), "")
	c.Assert(string(tb.RecordPrefix()), Not(Equals), "")
	c.Assert(tb.FindIndexByColName("b"), NotNil)

	autoid, err := tb.AllocAutoID()
	c.Assert(err, IsNil)
	c.Assert(autoid, Greater, int64(0))

	_, err = tb.AddRecord(ctx, []interface{}{1, nil})
	c.Assert(err, IsNil)
	_, err = tb.AddRecord(ctx, []interface{}{2, nil})
	c.Assert(err, IsNil)
	_, err = ts.se.Execute("drop table test.t")
	c.Assert(err, IsNil)
}

func (ts *testSuite) TestRowKeyCodec(c *C) {
	table := []struct {
		tableID int64
		h       int64
		ID      int64
	}{
		{1, 1234567890, 0},
		{2, 1, 0},
		{3, -1, 0},
		{4, -1, 1},
	}

	for _, t := range table {
		b := tables.EncodeRecordKey(t.tableID, t.h, t.ID)
		tableID, handle, columnID, err := tables.DecodeRecordKey(b)
		c.Assert(err, IsNil)
		c.Assert(tableID, Equals, t.tableID)
		c.Assert(handle, Equals, t.h)
		c.Assert(columnID, Equals, t.ID)

		handle, err = tables.DecodeRecordKeyHandle(b)
		c.Assert(err, IsNil)
		c.Assert(handle, Equals, t.h)
	}

	// test error
	tbl := []string{
		"",
		"x",
		"t1",
		"t12345678",
		"t12345678_i",
		"t12345678_r1",
		"t12345678_r1234567",
		"t12345678_r123456781",
	}

	for _, t := range tbl {
		_, err := tables.DecodeRecordKeyHandle(kv.Key(t))
		c.Assert(err, NotNil)
	}
}
<|endoftext|>


<commit_before>package content

import (
	"net/http"

	"github.com/julienschmidt/httprouter"
	"github.com/octavore/naga/service"
	"github.com/octavore/nagax/logger"

	"github.com/octavore/press/db"
	"github.com/octavore/press/proto/press/models"
	"github.com/octavore/press/server/content/templates"
	"github.com/octavore/press/server/router"
)

// Module server is responsible for serving published content
type Module struct {
	Router    *router.Module
	DB        *db.Module
	Logger    *logger.Module
	Templates *templates.Module
	router    http.Handler
}

var _ service.Module = &Module{}

// Init implements service.Init
func (m *Module) Init(c *service.Config) {
	c.Start = func() {
		var err error
		m.router, _, err = m.BuildRouter()
		if err != nil {
			panic(err)
		}
		m.Router.Handle("/", m)
	}
}

// ServeHTTP is a layer of indirection to allow us
// to replace the router at runtime.
func (m *Module) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	if m.router != nil {
		m.router.ServeHTTP(rw, req)
	}
}

// BuildRouter returns a handler configured to serve content.
func (m *Module) BuildRouter() (http.Handler, map[string]bool, error) {
	rt := httprouter.New()
	routes, err := m.DB.ListRoutes()
	if err != nil {
		return nil, nil, err
	}
	activeRoutes := map[string]bool{}
	rt.NotFound = m.Templates
	for _, route := range routes {
		m.Logger.Info("found route:", route)
		if route.GetPath() == "" {
			m.Logger.Warningf("no path for route: %s", route.GetUuid())
			continue
		}
		if route.GetPath()[0] != '/' {
			m.Logger.Warningf("invalid path %q for route: %s", route.GetPath(), route.GetUuid())
			continue
		}
		if _, ok := activeRoutes[route.GetPath()]; ok {
			m.Logger.Warningf("failed to register duplicate route %q", route.GetPath())
			continue
		}
		activeRoutes[route.GetPath()] = true

		switch tgt := route.GetTarget().(type) {
		case *models.Route_File:
			m.Logger.Info("registered file route:", route.GetPath())
			rt.Handle("GET", route.GetPath(), func(rw http.ResponseWriter, req *http.Request, _ httprouter.Params) {
				http.ServeFile(rw, req, tgt.File)
			})
		case *models.Route_PageUuid:
			m.Logger.Info("registered uuid route:", route.GetPath())
			rt.Handle("GET", route.GetPath(), func(rw http.ResponseWriter, req *http.Request, _ httprouter.Params) {
				page, err := m.DB.GetPage(tgt.PageUuid)
				if page.PublishedAt == nil {
					router.NotFound(rw)
					return
				}
				if err == nil {
					err = m.render(rw, page)
				}
				if err != nil {
					m.Logger.Errorf("error serving page %+v: %+v", route, err)
				}
			})
		default:
			m.Logger.Errorf("unable to register %s", route.GetUuid())
		}
	}
	return rt, activeRoutes, nil
}
<commit_msg>server: Add ReloadRouter function.<commit_after>package content

import (
	"net/http"

	"github.com/julienschmidt/httprouter"
	"github.com/octavore/naga/service"
	"github.com/octavore/nagax/logger"

	"github.com/octavore/press/db"
	"github.com/octavore/press/proto/press/models"
	"github.com/octavore/press/server/content/templates"
	"github.com/octavore/press/server/router"
)

// Module server is responsible for serving published content
type Module struct {
	Router    *router.Module
	DB        *db.Module
	Logger    *logger.Module
	Templates *templates.Module
	router    http.Handler
}

var _ service.Module = &Module{}

// Init implements service.Init
func (m *Module) Init(c *service.Config) {
	c.Start = func() {
		var err error
		m.router, _, err = m.buildRouter()
		if err != nil {
			panic(err)
		}
		m.Router.Handle("/", m)
	}
}

// ServeHTTP is a layer of indirection to allow us
// to replace the router at runtime.
func (m *Module) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	if m.router != nil {
		m.router.ServeHTTP(rw, req)
	}
}

// ReloadRouter recreates the router to add/remove routes that have change
// and replaces the existing router.
func (m *Module) ReloadRouter() error {
	newRouter, _, err := m.buildRouter()
	if err != nil {
		return err
	}
	m.router = newRouter
	return nil
}

// buildRouter returns a handler configured to serve content.
func (m *Module) buildRouter() (http.Handler, map[string]bool, error) {
	rt := httprouter.New()
	routes, err := m.DB.ListRoutes()
	if err != nil {
		return nil, nil, err
	}
	activeRoutes := map[string]bool{}
	rt.NotFound = m.Templates
	for _, route := range routes {
		m.Logger.Info("found route:", route)
		if route.GetPath() == "" {
			m.Logger.Warningf("no path for route: %s", route.GetUuid())
			continue
		}
		if route.GetPath()[0] != '/' {
			m.Logger.Warningf("invalid path %q for route: %s", route.GetPath(), route.GetUuid())
			continue
		}
		if _, ok := activeRoutes[route.GetPath()]; ok {
			m.Logger.Warningf("failed to register duplicate route %q", route.GetPath())
			continue
		}
		activeRoutes[route.GetPath()] = true

		switch tgt := route.GetTarget().(type) {
		case *models.Route_File:
			m.Logger.Info("registered file route:", route.GetPath())
			rt.Handle("GET", route.GetPath(), func(rw http.ResponseWriter, req *http.Request, _ httprouter.Params) {
				http.ServeFile(rw, req, tgt.File)
			})
		case *models.Route_PageUuid:
			m.Logger.Info("registered uuid route:", route.GetPath())
			rt.Handle("GET", route.GetPath(), func(rw http.ResponseWriter, req *http.Request, _ httprouter.Params) {
				page, err := m.DB.GetPage(tgt.PageUuid)
				if page.PublishedAt == nil {
					router.NotFound(rw)
					return
				}
				if err == nil {
					err = m.render(rw, page)
				}
				if err != nil {
					m.Logger.Errorf("error serving page %+v: %+v", route, err)
				}
			})
		default:
			m.Logger.Errorf("unable to register %s", route.GetUuid())
		}
	}
	return rt, activeRoutes, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/bslatkin/opaque"
)

type MultiplyByX struct {
	opaque.Opaque
	x int
}

func (m *MultiplyByX) GetNumber() int {
	return m.Opaque.GetNumber() * m.x
}

// Example trying to show how to cause a runtime panic with calls to a hidden
// method on a public interface.
func main() {
	o := &MultiplyByX{Opaque: opaque.NewBasic(10), x: 3}
	fmt.Printf("My multiply by X value is %d, type is %#v\n", o.GetNumber(), o)

	s := opaque.DoSomethingWithOpaque(o)
	fmt.Println("Doing something with an opaque I get:", s)

	err, s := opaque.VerifyAndDoSomethingWithOpaque(o)
	fmt.Printf("Verifying %#v I get: %#v, %#v\n", o, err, s)

	o = &MultiplyByX{Opaque: nil, x: 3}
	err, s = opaque.VerifyAndDoSomethingWithOpaque(o)
	fmt.Printf("Verifying %#v I get: %#v, %#v\n", o, err, s)
}
<commit_msg>And clearer<commit_after>package main

import (
	"fmt"
	"github.com/bslatkin/opaque"
)

type MultiplyByX struct {
	opaque.Opaque
	x int
}

func (m *MultiplyByX) GetNumber() int {
	return m.Opaque.GetNumber() * m.x
}

// Example trying to show how to cause a runtime panic with calls to a hidden
// method on a public interface.
func main() {
	o := &MultiplyByX{Opaque: opaque.NewBasic(10), x: 3}
	fmt.Printf("My multiply by X value is %d, type is %#v\n", o.GetNumber(), o)

	s := opaque.DoSomethingWithOpaque(o)
	fmt.Println("Doing something with an opaque I get:", s)

	err, s := opaque.VerifyAndDoSomethingWithOpaque(o)
	fmt.Printf("Verifying %#v I get: %v, %#v\n", o, err, s)

	o = &MultiplyByX{Opaque: nil, x: 3}
	err, s = opaque.VerifyAndDoSomethingWithOpaque(o)
	fmt.Printf("Verifying %#v I get: %v, %#v\n", o, err, s)
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/DataDog/dd-trace-go/tracer"
	"github.com/Sirupsen/logrus"
	"github.com/flachnetz/dd-zipkin-proxy"
	"github.com/openzipkin/zipkin-go-opentracing/_thrift/gen-go/zipkincore"
	"regexp"
	"strconv"
	"strings"
)

func main() {
	converter := DefaultSpanConverter{}
	zipkinproxy.Main(converter.Convert)
}

var reHash = regexp.MustCompile("\\b(?:[a-f0-9]{32}|[a-f0-9-]{8}-[a-f0-9-]{4}-[a-f0-9-]{4}-[a-f0-9-]{4}-[a-f0-9-]{12})\\b")
var reNumber = regexp.MustCompile("\\b[0-9]{2,}\\b")
var reIwgHash = regexp.MustCompile("iwg\\.[A-Za-z0-9]{12}\\b")
var reEmail = regexp.MustCompile("emailAddress=[^%]+%40[^&]+")

func SimplifyResourceName(value string) string {
	// check if we need to apply the regexp by checking if a match is possible or not
	digitCount := 0
	hashCharCount := 0
	mightHaveEmailSign := false
	for _, char := range value {
		isDigit := char >= '0' && char <= '9'
		if isDigit {
			digitCount++
		}

		if isDigit || char >= 'a' && char <= 'f' {
			hashCharCount++
		}

		if char == '%' {
			mightHaveEmailSign = true
		}
	}

	// only search for hash, if we have enough chars for it
	if hashCharCount >= 32 {
		value = reHash.ReplaceAllString(value, "_HASH_")
	}

	// only replace numbers, if we have enough digits for a match
	if digitCount >= 2 {
		value = reNumber.ReplaceAllString(value, "_NUMBER_")
	}

	if strings.HasPrefix(value, "iwg.") {
		value = reIwgHash.ReplaceAllString(value, "iwg._HASH_")
	}

	if mightHaveEmailSign && digitCount >= 2 {
		value = reEmail.ReplaceAllString(value, "emailAddress=_EMAIL_")
	}

	return value
}

func RetractSensitiveData(value string) string {
	if strings.Contains(value, "emailAddress=") {
		value = reEmail.ReplaceAllString(value, "emailAddress=_EMAIL_")
	}

	return value
}

type DefaultSpanConverter struct {
	current  map[uint64]string
	previous map[uint64]string
}

func (converter *DefaultSpanConverter) Convert(span *zipkincore.Span) *tracer.Span {
	if span.Name == "watch-config-key-values" {
		return nil
	}

	name := SimplifyResourceName(span.Name)

	converted := &tracer.Span{
		SpanID:   uint64(span.ID),
		ParentID: uint64(span.GetParentID()),
		TraceID:  uint64(span.TraceID),
		Name:     name,
		Resource: name,
		Start:    1000 * span.GetTimestamp(),
		Duration: 1000 * span.GetDuration(),
		Sampled:  true,
	}

	// datadog traces use a trace of 0
	if converted.ParentID == converted.SpanID {
		converted.ParentID = 0
	}

	// split "http:/some/url" or "get:/some/url"
	for _, prefix := range []string{"http:/", "get:/", "post:/"} {
		if strings.HasPrefix(converted.Name, prefix) {
			converted.Resource = converted.Name[len(prefix)-1:]
			converted.Name = prefix[:len(prefix)-2]
			break
		}
	}

	// convert binary annotations (like tags)
	if len(span.BinaryAnnotations) > 0 {
		converted.Meta = make(map[string]string, len(span.BinaryAnnotations))
		for _, an := range span.BinaryAnnotations {
			if an.AnnotationType == zipkincore.AnnotationType_STRING {
				key := an.Key

				// rename keys to better match the datadog one.
				switch key {
				case "http.status":
					key = "http.status_code"

				case "client.url":
					key = "http.url"
				}

				converted.Meta[key] = string(an.Value)
			}

			if an.Host != nil && an.Host.ServiceName != "" {
				converted.Service = an.Host.ServiceName
			}
		}

		if url := converted.Meta["http.url"]; url != "" {
			converted.Resource = SimplifyResourceName(url)
			converted.Meta["http.url"] = RetractSensitiveData(url)
		}

		if status := converted.Meta["http.status_code"]; status != "" {
			if len(status) > 0 && '3' <= status[0] && status[0] <= '9' {
				if statusValue, err := strconv.Atoi(status); err == nil && statusValue >= 400 {
					converted.Error = int32(statusValue)
				}
			}
		}
	}

	extractInfoFromAnnotations(span, converted)

	// simplify some names
	if strings.HasPrefix(converted.Name, "http:") {
		converted.Service = converted.Name[5:]

	} else if converted.Name == "transaction" {
		converted.Service = "oracle"

	} else if sql := converted.Meta["sql"]; sql != "" {
		delete(converted.Meta, "sql")
		converted.Resource = sql
		converted.Service = "sql"

	} else if strings.HasPrefix(converted.Name, "redis:") {
		converted.Service = "redis"

		if key := converted.Meta["redis.key"]; key != "" {
			converted.Resource = SimplifyResourceName(key)

			// the hash is not really important later on. lets not spam datadog with it.
			delete(converted.Meta, "redis.key")
		}

	} else if converted.Service == "core-services" {
		lc := converted.Meta["lc"]

		switch {
		case strings.Contains(converted.Meta["http.url"], ":6080/"):
			converted.Service = "iwg-restrictor"
			converted.Name = iwgNameFromResource(converted.Resource, converted.Name)
			converted.Resource = dropDomainFromUrl(converted.Resource)

		case strings.Contains(converted.Meta["http.url"], ":2080/"):
			converted.Service = "instant-win-game"
			converted.Name = "iwg-game"
			converted.Resource = dropDomainFromUrl(converted.Resource)

		case lc != "" && lc != "servlet" && lc != "HttpClient":
			// TODO: find proper fix for this service name / name datadog magic
			//delete(converted.Meta, "lc")
			converted.Service = lc
		}
	}

	// If we could not get a service, we'll try to get it from the parent span.
	// Try first in the current map, then in the previous one.
	if converted.Service == "" {
		parentService := converter.current[converted.ParentID]
		if parentService != "" {
			converted.Service = parentService
		} else {
			parentService = converter.previous[converted.ParentID]
			if parentService != "" {
				converted.Service = parentService
			}
		}

		// if we did not get a service, use a fallback
		if converted.Service == "" {
			logrus.Warnf("Could not get a service for this span: %+v", span)
			converted.Service = "unknown"
		}
	}

	if lc := converted.Meta["lc"]; lc != "" {
		// TODO: here as well
		//delete(converted.Meta, "lc")

		if converted.Name == "" {
			converted.Name = lc
		}

		if lc == "consul" {
			converted.Service = "consul"
		}
	}

	if converted.Name == "transaction" || converted.Service == "redis" {
		converted.Type = "db"
	} else {
		converted.Type = "http"
	}

	if converted.Name == "hystrix" {
		converted.Resource = converted.Meta["thread"]
	} else if converted.Name == "" {
		logrus.Warnf("Could not get a name for this span: %+v converted: %+v", span, converted)
	}

	// if name and service differ than the overview page in datadog will only show the one with
	// most of the time spend. This is why we just rename it to the service here so that we can get a nice
	// overview of all resources belonging to the service. Can be removed in the future when datadog is changing things
	converted.Name = converted.Service

	// initialize history maps for span -> parent assignment
	const parentLookupMapSize = 40000
	if len(converter.current) >= parentLookupMapSize || converter.current == nil {
		converter.previous = converter.current
		converter.current = make(map[uint64]string, parentLookupMapSize)
	}

	// remember the service for a short while
	converter.current[converted.SpanID] = converted.Service

	return converted
}

func extractInfoFromAnnotations(span *zipkincore.Span, converted *tracer.Span) {
	// try to get the service from the cs/cr or sr/ss annotations
	var minTimestamp, maxTimestamp int64
	for _, an := range span.Annotations {
		if an.Value == "sr" && an.Host != nil && an.Host.ServiceName != "" {
			converted.Service = an.Host.ServiceName
		}

		if an.Timestamp < minTimestamp || minTimestamp == 0 {
			minTimestamp = an.Timestamp
		}

		if an.Timestamp > maxTimestamp {
			maxTimestamp = an.Timestamp
		}
	}

	if converted.Start == 0 {
		logrus.Warn("Span had no start/duration, guessing from annotations.")
		converted.Start = 1000 * minTimestamp
		converted.Duration = 1000 * (maxTimestamp - minTimestamp)
	}
}

func dropDomainFromUrl(url string) string {
	switch {
	case strings.HasPrefix(url, "http://"):
		index := strings.IndexRune(url[7:], '/')
		return url[7+index:]

	case strings.HasPrefix(url, "https://"):
		index := strings.IndexRune(url[8:], '/')
		return url[8+index:]
	}

	return url
}

func iwgNameFromResource(resource string, fallback string) string {
	splittedUrl := strings.Split(strings.Trim(resource, "/"), "/")
	if len(splittedUrl) == 1 && splittedUrl[0] != "" {
		return splittedUrl[0]
	} else if len(splittedUrl) > 1 {
		return splittedUrl[len(splittedUrl)-2] + "/" + splittedUrl[len(splittedUrl)-1]
	}
	return fallback
}
<commit_msg>Allow replacing of hashes with 24 chars.<commit_after>package main

import (
	"github.com/DataDog/dd-trace-go/tracer"
	"github.com/Sirupsen/logrus"
	"github.com/flachnetz/dd-zipkin-proxy"
	"github.com/openzipkin/zipkin-go-opentracing/_thrift/gen-go/zipkincore"
	"regexp"
	"strconv"
	"strings"
)

func main() {
	converter := DefaultSpanConverter{}
	zipkinproxy.Main(converter.Convert)
}

var reHash = regexp.MustCompile("\\b(?:[a-f0-9]{32}|[a-f0-9]{24}|[a-f0-9-]{8}-[a-f0-9-]{4}-[a-f0-9-]{4}-[a-f0-9-]{4}-[a-f0-9-]{12})\\b")
var reNumber = regexp.MustCompile("\\b[0-9]{2,}\\b")
var reIwgHash = regexp.MustCompile("iwg\\.[A-Za-z0-9]{12}\\b")
var reEmail = regexp.MustCompile("emailAddress=[^%]+%40[^&]+")

func SimplifyResourceName(value string) string {
	// check if we need to apply the regexp by checking if a match is possible or not
	digitCount := 0
	hashCharCount := 0
	mightHaveEmailSign := false
	for _, char := range value {
		isDigit := char >= '0' && char <= '9'
		if isDigit {
			digitCount++
		}

		if isDigit || char >= 'a' && char <= 'f' {
			hashCharCount++
		}

		if char == '%' {
			mightHaveEmailSign = true
		}
	}

	// only search for hash, if we have enough chars for it
	if hashCharCount >= 24 {
		value = reHash.ReplaceAllString(value, "_HASH_")
	}

	// only replace numbers, if we have enough digits for a match
	if digitCount >= 2 {
		value = reNumber.ReplaceAllString(value, "_NUMBER_")
	}

	if strings.HasPrefix(value, "iwg.") {
		value = reIwgHash.ReplaceAllString(value, "iwg._HASH_")
	}

	if mightHaveEmailSign && digitCount >= 2 {
		value = reEmail.ReplaceAllString(value, "emailAddress=_EMAIL_")
	}

	return value
}

func RetractSensitiveData(value string) string {
	if strings.Contains(value, "emailAddress=") {
		value = reEmail.ReplaceAllString(value, "emailAddress=_EMAIL_")
	}

	return value
}

type DefaultSpanConverter struct {
	current  map[uint64]string
	previous map[uint64]string
}

func (converter *DefaultSpanConverter) Convert(span *zipkincore.Span) *tracer.Span {
	if span.Name == "watch-config-key-values" {
		return nil
	}

	name := SimplifyResourceName(span.Name)

	converted := &tracer.Span{
		SpanID:   uint64(span.ID),
		ParentID: uint64(span.GetParentID()),
		TraceID:  uint64(span.TraceID),
		Name:     name,
		Resource: name,
		Start:    1000 * span.GetTimestamp(),
		Duration: 1000 * span.GetDuration(),
		Sampled:  true,
	}

	// datadog traces use a trace of 0
	if converted.ParentID == converted.SpanID {
		converted.ParentID = 0
	}

	// split "http:/some/url" or "get:/some/url"
	for _, prefix := range []string{"http:/", "get:/", "post:/"} {
		if strings.HasPrefix(converted.Name, prefix) {
			converted.Resource = converted.Name[len(prefix)-1:]
			converted.Name = prefix[:len(prefix)-2]
			break
		}
	}

	// convert binary annotations (like tags)
	if len(span.BinaryAnnotations) > 0 {
		converted.Meta = make(map[string]string, len(span.BinaryAnnotations))
		for _, an := range span.BinaryAnnotations {
			if an.AnnotationType == zipkincore.AnnotationType_STRING {
				key := an.Key

				// rename keys to better match the datadog one.
				switch key {
				case "http.status":
					key = "http.status_code"

				case "client.url":
					key = "http.url"
				}

				converted.Meta[key] = string(an.Value)
			}

			if an.Host != nil && an.Host.ServiceName != "" {
				converted.Service = an.Host.ServiceName
			}
		}

		if url := converted.Meta["http.url"]; url != "" {
			converted.Resource = SimplifyResourceName(url)
			converted.Meta["http.url"] = RetractSensitiveData(url)
		}

		if status := converted.Meta["http.status_code"]; status != "" {
			if len(status) > 0 && '3' <= status[0] && status[0] <= '9' {
				if statusValue, err := strconv.Atoi(status); err == nil && statusValue >= 400 {
					converted.Error = int32(statusValue)
				}
			}
		}
	}

	extractInfoFromAnnotations(span, converted)

	// simplify some names
	if strings.HasPrefix(converted.Name, "http:") {
		converted.Service = converted.Name[5:]

	} else if converted.Name == "transaction" {
		converted.Service = "oracle"

	} else if sql := converted.Meta["sql"]; sql != "" {
		delete(converted.Meta, "sql")
		converted.Resource = sql
		converted.Service = "sql"

	} else if strings.HasPrefix(converted.Name, "redis:") {
		converted.Service = "redis"

		if key := converted.Meta["redis.key"]; key != "" {
			converted.Resource = SimplifyResourceName(key)

			// the hash is not really important later on. lets not spam datadog with it.
			delete(converted.Meta, "redis.key")
		}

	} else if converted.Service == "core-services" {
		lc := converted.Meta["lc"]

		switch {
		case strings.Contains(converted.Meta["http.url"], ":6080/"):
			converted.Service = "iwg-restrictor"
			converted.Name = iwgNameFromResource(converted.Resource, converted.Name)
			converted.Resource = dropDomainFromUrl(converted.Resource)

		case strings.Contains(converted.Meta["http.url"], ":2080/"):
			converted.Service = "instant-win-game"
			converted.Name = "iwg-game"
			converted.Resource = dropDomainFromUrl(converted.Resource)

		case lc != "" && lc != "servlet" && lc != "HttpClient":
			// TODO: find proper fix for this service name / name datadog magic
			//delete(converted.Meta, "lc")
			converted.Service = lc
		}
	}

	// If we could not get a service, we'll try to get it from the parent span.
	// Try first in the current map, then in the previous one.
	if converted.Service == "" {
		parentService := converter.current[converted.ParentID]
		if parentService != "" {
			converted.Service = parentService
		} else {
			parentService = converter.previous[converted.ParentID]
			if parentService != "" {
				converted.Service = parentService
			}
		}

		// if we did not get a service, use a fallback
		if converted.Service == "" {
			logrus.Warnf("Could not get a service for this span: %+v", span)
			converted.Service = "unknown"
		}
	}

	if lc := converted.Meta["lc"]; lc != "" {
		// TODO: here as well
		//delete(converted.Meta, "lc")

		if converted.Name == "" {
			converted.Name = lc
		}

		if lc == "consul" {
			converted.Service = "consul"
		}
	}

	if converted.Name == "transaction" || converted.Service == "redis" {
		converted.Type = "db"
	} else {
		converted.Type = "http"
	}

	if converted.Name == "hystrix" {
		converted.Resource = converted.Meta["thread"]
	} else if converted.Name == "" {
		logrus.Warnf("Could not get a name for this span: %+v converted: %+v", span, converted)
	}

	// if name and service differ than the overview page in datadog will only show the one with
	// most of the time spend. This is why we just rename it to the service here so that we can get a nice
	// overview of all resources belonging to the service. Can be removed in the future when datadog is changing things
	converted.Name = converted.Service

	// initialize history maps for span -> parent assignment
	const parentLookupMapSize = 40000
	if len(converter.current) >= parentLookupMapSize || converter.current == nil {
		converter.previous = converter.current
		converter.current = make(map[uint64]string, parentLookupMapSize)
	}

	// remember the service for a short while
	converter.current[converted.SpanID] = converted.Service

	return converted
}

func extractInfoFromAnnotations(span *zipkincore.Span, converted *tracer.Span) {
	// try to get the service from the cs/cr or sr/ss annotations
	var minTimestamp, maxTimestamp int64
	for _, an := range span.Annotations {
		if an.Value == "sr" && an.Host != nil && an.Host.ServiceName != "" {
			converted.Service = an.Host.ServiceName
		}

		if an.Timestamp < minTimestamp || minTimestamp == 0 {
			minTimestamp = an.Timestamp
		}

		if an.Timestamp > maxTimestamp {
			maxTimestamp = an.Timestamp
		}
	}

	if converted.Start == 0 {
		logrus.Warn("Span had no start/duration, guessing from annotations.")
		converted.Start = 1000 * minTimestamp
		converted.Duration = 1000 * (maxTimestamp - minTimestamp)
	}
}

func dropDomainFromUrl(url string) string {
	switch {
	case strings.HasPrefix(url, "http://"):
		index := strings.IndexRune(url[7:], '/')
		return url[7+index:]

	case strings.HasPrefix(url, "https://"):
		index := strings.IndexRune(url[8:], '/')
		return url[8+index:]
	}

	return url
}

func iwgNameFromResource(resource string, fallback string) string {
	splittedUrl := strings.Split(strings.Trim(resource, "/"), "/")
	if len(splittedUrl) == 1 && splittedUrl[0] != "" {
		return splittedUrl[0]
	} else if len(splittedUrl) > 1 {
		return splittedUrl[len(splittedUrl)-2] + "/" + splittedUrl[len(splittedUrl)-1]
	}
	return fallback
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"encoding/hex"
	"errors"
	"fmt"
	"github.com/ethereum/ethdb-go"
	"github.com/ethereum/ethutil-go"
	"os"
	"strings"
)

type Console struct {
	db   *ethdb.MemDatabase
	trie *ethutil.Trie
}

func NewConsole() *Console {
	db, _ := ethdb.NewMemDatabase()
	trie := ethutil.NewTrie(db, "")

	return &Console{db: db, trie: trie}
}

func (i *Console) ValidateInput(action string, argumentLength int) error {
	err := false
	var expArgCount int

	switch {
	case action == "update" && argumentLength != 2:
		err = true
		expArgCount = 2
	case action == "get" && argumentLength != 1:
		err = true
		expArgCount = 1
	case action == "dag" && argumentLength != 2:
		err = true
		expArgCount = 2
	case action == "decode" && argumentLength != 1:
		err = true
		expArgCount = 1
	case action == "encode" && argumentLength != 1:
		err = true
		expArgCount = 1
	}

	if err {
		return errors.New(fmt.Sprintf("'%s' requires %d args, got %d", action, expArgCount, argumentLength))
	} else {
		return nil
	}
}

func (i *Console) PrintRoot() {
	root := ethutil.Conv(i.trie.RootT)
	if len(root.AsBytes()) != 0 {
		fmt.Println(hex.EncodeToString(root.AsBytes()))
	} else {
		fmt.Println(i.trie.RootT)
	}
}

func (i *Console) ParseInput(input string) bool {
	scanner := bufio.NewScanner(strings.NewReader(input))
	scanner.Split(bufio.ScanWords)

	count := 0
	var tokens []string
	for scanner.Scan() {
		count++
		tokens = append(tokens, scanner.Text())
	}
	if err := scanner.Err(); err != nil {
		fmt.Fprintln(os.Stderr, "reading input:", err)
	}

	if len(tokens) == 0 {
		return true
	}

	err := i.ValidateInput(tokens[0], count-1)
	if err != nil {
		fmt.Println(err)
	} else {
		switch tokens[0] {
		case "update":
			i.trie.UpdateT(tokens[1], tokens[2])

			i.PrintRoot()
		case "get":
			fmt.Println(i.trie.GetT(tokens[1]))
		case "root":
			i.PrintRoot()
		case "rawroot":
			fmt.Println(i.trie.RootT)
		case "print":
			i.db.Print()
		case "dag":
			fmt.Println(DaggerVerify(ethutil.Big(tokens[1]), // hash
				ethutil.BigPow(2, 36),   // diff
				ethutil.Big(tokens[2]))) // nonce
		case "decode":
			d, _ := ethutil.Decode([]byte(tokens[1]), 0)
			fmt.Printf("%q\n", d)
		case "encode":
			fmt.Printf("%q\n", ethutil.Encode(tokens[1]))
		case "exit", "quit", "q":
			return false
		case "help":
			fmt.Printf("COMMANDS:\n" +
				"\033[1m= DB =\033[0m\n" +
				"update KEY VALUE - Updates/Creates a new value for the given key\n" +
				"get KEY - Retrieves the given key\n" +
				"root - Prints the hex encoded merkle root\n" +
				"rawroot - Prints the raw merkle root\n" +
				"\033[1m= Dagger =\033[0m\n" +
				"dag HASH NONCE - Verifies a nonce with the given hash with dagger\n" +
				"\033[1m= Enroding =\033[0m\n" +
				"decode STR\n" +
				"encode STR\n")

		default:
			fmt.Println("Unknown command:", tokens[0])
		}
	}

	return true
}

func (i *Console) Start() {
	fmt.Printf("Eth Console. Type (help) for help\n")
	reader := bufio.NewReader(os.Stdin)
	for {
		fmt.Printf("eth >>> ")
		str, _, err := reader.ReadLine()
		if err != nil {
			fmt.Println("Error reading input", err)
		} else {
			if !i.ParseInput(string(str)) {
				return
			}
		}
	}
}
<commit_msg>Fixed typo (credit to comma 8)<commit_after>package main

import (
	"bufio"
	"encoding/hex"
	"errors"
	"fmt"
	"github.com/ethereum/ethdb-go"
	"github.com/ethereum/ethutil-go"
	"os"
	"strings"
)

type Console struct {
	db   *ethdb.MemDatabase
	trie *ethutil.Trie
}

func NewConsole() *Console {
	db, _ := ethdb.NewMemDatabase()
	trie := ethutil.NewTrie(db, "")

	return &Console{db: db, trie: trie}
}

func (i *Console) ValidateInput(action string, argumentLength int) error {
	err := false
	var expArgCount int

	switch {
	case action == "update" && argumentLength != 2:
		err = true
		expArgCount = 2
	case action == "get" && argumentLength != 1:
		err = true
		expArgCount = 1
	case action == "dag" && argumentLength != 2:
		err = true
		expArgCount = 2
	case action == "decode" && argumentLength != 1:
		err = true
		expArgCount = 1
	case action == "encode" && argumentLength != 1:
		err = true
		expArgCount = 1
	}

	if err {
		return errors.New(fmt.Sprintf("'%s' requires %d args, got %d", action, expArgCount, argumentLength))
	} else {
		return nil
	}
}

func (i *Console) PrintRoot() {
	root := ethutil.Conv(i.trie.RootT)
	if len(root.AsBytes()) != 0 {
		fmt.Println(hex.EncodeToString(root.AsBytes()))
	} else {
		fmt.Println(i.trie.RootT)
	}
}

func (i *Console) ParseInput(input string) bool {
	scanner := bufio.NewScanner(strings.NewReader(input))
	scanner.Split(bufio.ScanWords)

	count := 0
	var tokens []string
	for scanner.Scan() {
		count++
		tokens = append(tokens, scanner.Text())
	}
	if err := scanner.Err(); err != nil {
		fmt.Fprintln(os.Stderr, "reading input:", err)
	}

	if len(tokens) == 0 {
		return true
	}

	err := i.ValidateInput(tokens[0], count-1)
	if err != nil {
		fmt.Println(err)
	} else {
		switch tokens[0] {
		case "update":
			i.trie.UpdateT(tokens[1], tokens[2])

			i.PrintRoot()
		case "get":
			fmt.Println(i.trie.GetT(tokens[1]))
		case "root":
			i.PrintRoot()
		case "rawroot":
			fmt.Println(i.trie.RootT)
		case "print":
			i.db.Print()
		case "dag":
			fmt.Println(DaggerVerify(ethutil.Big(tokens[1]), // hash
				ethutil.BigPow(2, 36),   // diff
				ethutil.Big(tokens[2]))) // nonce
		case "decode":
			d, _ := ethutil.Decode([]byte(tokens[1]), 0)
			fmt.Printf("%q\n", d)
		case "encode":
			fmt.Printf("%q\n", ethutil.Encode(tokens[1]))
		case "exit", "quit", "q":
			return false
		case "help":
			fmt.Printf("COMMANDS:\n" +
				"\033[1m= DB =\033[0m\n" +
				"update KEY VALUE - Updates/Creates a new value for the given key\n" +
				"get KEY - Retrieves the given key\n" +
				"root - Prints the hex encoded merkle root\n" +
				"rawroot - Prints the raw merkle root\n" +
				"\033[1m= Dagger =\033[0m\n" +
				"dag HASH NONCE - Verifies a nonce with the given hash with dagger\n" +
				"\033[1m= Encoding =\033[0m\n" +
				"decode STR\n" +
				"encode STR\n")

		default:
			fmt.Println("Unknown command:", tokens[0])
		}
	}

	return true
}

func (i *Console) Start() {
	fmt.Printf("Eth Console. Type (help) for help\n")
	reader := bufio.NewReader(os.Stdin)
	for {
		fmt.Printf("eth >>> ")
		str, _, err := reader.ReadLine()
		if err != nil {
			fmt.Println("Error reading input", err)
		} else {
			if !i.ParseInput(string(str)) {
				return
			}
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"encoding/hex"
	"errors"
	"fmt"
	"github.com/ethereum/eth-go"
	"github.com/ethereum/ethchain-go"
	"github.com/ethereum/ethdb-go"
	"github.com/ethereum/ethutil-go"
	"github.com/ethereum/ethwire-go"
	_ "math/big"
	"os"
	"strings"
)

type Console struct {
	db       *ethdb.MemDatabase
	trie     *ethutil.Trie
	ethereum *eth.Ethereum
}

func NewConsole(s *eth.Ethereum) *Console {
	db, _ := ethdb.NewMemDatabase()
	trie := ethutil.NewTrie(db, "")

	return &Console{db: db, trie: trie, ethereum: s}
}

func (i *Console) ValidateInput(action string, argumentLength int) error {
	err := false
	var expArgCount int

	switch {
	case action == "update" && argumentLength != 2:
		err = true
		expArgCount = 2
	case action == "get" && argumentLength != 1:
		err = true
		expArgCount = 1
	case action == "dag" && argumentLength != 2:
		err = true
		expArgCount = 2
	case action == "decode" && argumentLength != 1:
		err = true
		expArgCount = 1
	case action == "encode" && argumentLength != 1:
		err = true
		expArgCount = 1
	case action == "gettx" && argumentLength != 1:
		err = true
		expArgCount = 1
	case action == "tx" && argumentLength != 2:
		err = true
		expArgCount = 2
	case action == "getaddr" && argumentLength != 1:
		err = true
		expArgCount = 1
	case action == "contract" && argumentLength != 1:
		err = true
		expArgCount = 1
	case action == "say" && argumentLength != 1:
		err = true
		expArgCount = 1
	case action == "addp" && argumentLength != 1:
		err = true
		expArgCount = 1
	}

	if err {
		return errors.New(fmt.Sprintf("'%s' requires %d args, got %d", action, expArgCount, argumentLength))
	} else {
		return nil
	}
}

func (i *Console) PrintRoot() {
	root := ethutil.Conv(i.trie.Root)
	if len(root.AsBytes()) != 0 {
		fmt.Println(hex.EncodeToString(root.AsBytes()))
	} else {
		fmt.Println(i.trie.Root)
	}
}

func (i *Console) ParseInput(input string) bool {
	scanner := bufio.NewScanner(strings.NewReader(input))
	scanner.Split(bufio.ScanWords)

	count := 0
	var tokens []string
	for scanner.Scan() {
		count++
		tokens = append(tokens, scanner.Text())
	}
	if err := scanner.Err(); err != nil {
		fmt.Fprintln(os.Stderr, "reading input:", err)
	}

	if len(tokens) == 0 {
		return true
	}

	err := i.ValidateInput(tokens[0], count-1)
	if err != nil {
		fmt.Println(err)
	} else {
		switch tokens[0] {
		case "update":
			i.trie.Update(tokens[1], tokens[2])

			i.PrintRoot()
		case "get":
			fmt.Println(i.trie.Get(tokens[1]))
		case "root":
			i.PrintRoot()
		case "rawroot":
			fmt.Println(i.trie.Root)
		case "print":
			i.db.Print()
		case "dag":
			fmt.Println(ethchain.DaggerVerify(ethutil.Big(tokens[1]), // hash
				ethutil.BigPow(2, 36),   // diff
				ethutil.Big(tokens[2]))) // nonce
		case "decode":
			value := ethutil.NewRlpValueFromBytes([]byte(tokens[1]))
			fmt.Println(value)
		case "getaddr":
			encoded, _ := hex.DecodeString(tokens[1])
			d := i.ethereum.BlockManager.BlockChain().CurrentBlock.State().Get(string(encoded))
			if d != "" {
				decoder := ethutil.NewRlpValueFromBytes([]byte(d))
				fmt.Println(decoder)
			} else {
				fmt.Println("getaddr: address unknown")
			}
		case "say":
			i.ethereum.Broadcast(ethwire.MsgTalkTy, []interface{}{tokens[1]})
		case "addp":
			i.ethereum.ConnectToPeer(tokens[1])
		case "pcount":
			fmt.Println("peers:", i.ethereum.Peers().Len())
		case "encode":
			fmt.Printf("%q\n", ethutil.Encode(tokens[1]))
		case "tx":
			tx := ethchain.NewTransaction(tokens[1], ethutil.Big(tokens[2]), []string{""})
			fmt.Printf("%x\n", tx.Hash())

			i.ethereum.TxPool.QueueTransaction(tx)
		case "gettx":
			addr, _ := hex.DecodeString(tokens[1])
			data, _ := ethutil.Config.Db.Get(addr)
			if len(data) != 0 {
				decoder := ethutil.NewRlpValueFromBytes(data)
				fmt.Println(decoder)
			} else {
				fmt.Println("gettx: tx not found")
			}
		case "contract":
			contract := ethchain.NewTransaction("", ethutil.Big(tokens[1]), []string{"PUSH", "1234"})
			fmt.Printf("%x\n", contract.Hash())

			i.ethereum.TxPool.QueueTransaction(contract)
		case "exit", "quit", "q":
			return false
		case "help":
			fmt.Printf("COMMANDS:\n" +
				"\033[1m= DB =\033[0m\n" +
				"update KEY VALUE - Updates/Creates a new value for the given key\n" +
				"get KEY - Retrieves the given key\n" +
				"root - Prints the hex encoded merkle root\n" +
				"rawroot - Prints the raw merkle root\n" +
				"\033[1m= Dagger =\033[0m\n" +
				"dag HASH NONCE - Verifies a nonce with the given hash with dagger\n" +
				"\033[1m= Encoding =\033[0m\n" +
				"decode STR\n" +
				"encode STR\n" +
				"\033[1m= Other =\033[0m\n" +
				"addp HOST:PORT\n" +
				"tx TO AMOUNT\n" +
				"contract AMOUNT\n")

		default:
			fmt.Println("Unknown command:", tokens[0])
		}
	}

	return true
}

func (i *Console) Start() {
	fmt.Printf("Eth Console. Type (help) for help\n")
	reader := bufio.NewReader(os.Stdin)
	for {
		fmt.Printf("eth >>> ")
		str, _, err := reader.ReadLine()
		if err != nil {
			fmt.Println("Error reading input", err)
		} else {
			if !i.ParseInput(string(str)) {
				return
			}
		}
	}
}
<commit_msg>Recipient as bytes<commit_after>package main

import (
	"bufio"
	"encoding/hex"
	"errors"
	"fmt"
	"github.com/ethereum/eth-go"
	"github.com/ethereum/ethchain-go"
	"github.com/ethereum/ethdb-go"
	"github.com/ethereum/ethutil-go"
	"github.com/ethereum/ethwire-go"
	_ "math/big"
	"os"
	"strings"
)

type Console struct {
	db       *ethdb.MemDatabase
	trie     *ethutil.Trie
	ethereum *eth.Ethereum
}

func NewConsole(s *eth.Ethereum) *Console {
	db, _ := ethdb.NewMemDatabase()
	trie := ethutil.NewTrie(db, "")

	return &Console{db: db, trie: trie, ethereum: s}
}

func (i *Console) ValidateInput(action string, argumentLength int) error {
	err := false
	var expArgCount int

	switch {
	case action == "update" && argumentLength != 2:
		err = true
		expArgCount = 2
	case action == "get" && argumentLength != 1:
		err = true
		expArgCount = 1
	case action == "dag" && argumentLength != 2:
		err = true
		expArgCount = 2
	case action == "decode" && argumentLength != 1:
		err = true
		expArgCount = 1
	case action == "encode" && argumentLength != 1:
		err = true
		expArgCount = 1
	case action == "gettx" && argumentLength != 1:
		err = true
		expArgCount = 1
	case action == "tx" && argumentLength != 2:
		err = true
		expArgCount = 2
	case action == "getaddr" && argumentLength != 1:
		err = true
		expArgCount = 1
	case action == "contract" && argumentLength != 1:
		err = true
		expArgCount = 1
	case action == "say" && argumentLength != 1:
		err = true
		expArgCount = 1
	case action == "addp" && argumentLength != 1:
		err = true
		expArgCount = 1
	}

	if err {
		return errors.New(fmt.Sprintf("'%s' requires %d args, got %d", action, expArgCount, argumentLength))
	} else {
		return nil
	}
}

func (i *Console) PrintRoot() {
	root := ethutil.Conv(i.trie.Root)
	if len(root.AsBytes()) != 0 {
		fmt.Println(hex.EncodeToString(root.AsBytes()))
	} else {
		fmt.Println(i.trie.Root)
	}
}

func (i *Console) ParseInput(input string) bool {
	scanner := bufio.NewScanner(strings.NewReader(input))
	scanner.Split(bufio.ScanWords)

	count := 0
	var tokens []string
	for scanner.Scan() {
		count++
		tokens = append(tokens, scanner.Text())
	}
	if err := scanner.Err(); err != nil {
		fmt.Fprintln(os.Stderr, "reading input:", err)
	}

	if len(tokens) == 0 {
		return true
	}

	err := i.ValidateInput(tokens[0], count-1)
	if err != nil {
		fmt.Println(err)
	} else {
		switch tokens[0] {
		case "update":
			i.trie.Update(tokens[1], tokens[2])

			i.PrintRoot()
		case "get":
			fmt.Println(i.trie.Get(tokens[1]))
		case "root":
			i.PrintRoot()
		case "rawroot":
			fmt.Println(i.trie.Root)
		case "print":
			i.db.Print()
		case "dag":
			fmt.Println(ethchain.DaggerVerify(ethutil.Big(tokens[1]), // hash
				ethutil.BigPow(2, 36),   // diff
				ethutil.Big(tokens[2]))) // nonce
		case "decode":
			value := ethutil.NewRlpValueFromBytes([]byte(tokens[1]))
			fmt.Println(value)
		case "getaddr":
			encoded, _ := hex.DecodeString(tokens[1])
			d := i.ethereum.BlockManager.BlockChain().CurrentBlock.State().Get(string(encoded))
			if d != "" {
				decoder := ethutil.NewRlpValueFromBytes([]byte(d))
				fmt.Println(decoder)
			} else {
				fmt.Println("getaddr: address unknown")
			}
		case "say":
			i.ethereum.Broadcast(ethwire.MsgTalkTy, []interface{}{tokens[1]})
		case "addp":
			i.ethereum.ConnectToPeer(tokens[1])
		case "pcount":
			fmt.Println("peers:", i.ethereum.Peers().Len())
		case "encode":
			fmt.Printf("%q\n", ethutil.Encode(tokens[1]))
		case "tx":
			recipient, _ := hex.DecodeString(tokens[1])
			tx := ethchain.NewTransaction(recipient, ethutil.Big(tokens[2]), []string{""})
			fmt.Printf("%x\n", tx.Hash())

			i.ethereum.TxPool.QueueTransaction(tx)
		case "gettx":
			addr, _ := hex.DecodeString(tokens[1])
			data, _ := ethutil.Config.Db.Get(addr)
			if len(data) != 0 {
				decoder := ethutil.NewRlpValueFromBytes(data)
				fmt.Println(decoder)
			} else {
				fmt.Println("gettx: tx not found")
			}
		case "contract":
			contract := ethchain.NewTransaction([]byte{}, ethutil.Big(tokens[1]), []string{"PUSH", "1234"})
			fmt.Printf("%x\n", contract.Hash())

			i.ethereum.TxPool.QueueTransaction(contract)
		case "exit", "quit", "q":
			return false
		case "help":
			fmt.Printf("COMMANDS:\n" +
				"\033[1m= DB =\033[0m\n" +
				"update KEY VALUE - Updates/Creates a new value for the given key\n" +
				"get KEY - Retrieves the given key\n" +
				"root - Prints the hex encoded merkle root\n" +
				"rawroot - Prints the raw merkle root\n" +
				"\033[1m= Dagger =\033[0m\n" +
				"dag HASH NONCE - Verifies a nonce with the given hash with dagger\n" +
				"\033[1m= Encoding =\033[0m\n" +
				"decode STR\n" +
				"encode STR\n" +
				"\033[1m= Other =\033[0m\n" +
				"addp HOST:PORT\n" +
				"tx TO AMOUNT\n" +
				"contract AMOUNT\n")

		default:
			fmt.Println("Unknown command:", tokens[0])
		}
	}

	return true
}

func (i *Console) Start() {
	fmt.Printf("Eth Console. Type (help) for help\n")
	reader := bufio.NewReader(os.Stdin)
	for {
		fmt.Printf("eth >>> ")
		str, _, err := reader.ReadLine()
		if err != nil {
			fmt.Println("Error reading input", err)
		} else {
			if !i.ParseInput(string(str)) {
				return
			}
		}
	}
}
<|endoftext|>


<commit_before>package main

import (

    "log"
    "fmt"
	"net/http"

    "time"

    "../../websocket-go"
)

var server *websocket.Server  // with the default configuration

func handleWebsocketConnection(c *websocket.Connection) {

    log.Println("handleWebsocketConnection")

	c.Set("test", "test value")

	c.Join("testroom")

    c.List("testroom")

	c.On("chat", func(message string) {

		c.To("testroom").Emit("chat", "fafafafafa")
	})

	c.OnDisconnect(func() {
		fmt.Printf("\nConnection with ID: %s has been disconnected!", c.ID())
	})

    // test room
    go func(c *websocket.Connection){

        time.Sleep(2 * time.Second)

        c.To("testroom").Emit("chat","fffffffff")

        log.Printf("rooms  %v", c.List("testroom"))

    }(c)

    // test namespace
    go func(){

        time.Sleep(4 * time.Second)

        server.Of("testnamespace").To("testroom").Emit("chat","fffffffffffffffff")

    }()

}

func main() {

    server = websocket.New(websocket.Config{})

	http.Handle("/testnamespace", server.Handler())

	server.OnConnection(handleWebsocketConnection)

	server.Serve()

	fmt.Println("start server ", "3000")

	http.ListenAndServe(":3000", nil)

}
<commit_msg>add max cpus<commit_after>package main

import (

    "log"
    "fmt"
	"net/http"
    "runtime"
    "time"

    "../../websocket-go"
)

var server *websocket.Server  // with the default configuration

func handleWebsocketConnection(c *websocket.Connection) {

    log.Println("handleWebsocketConnection")

	c.Set("test", "test value")

	c.Join("testroom")

    c.List("testroom")

	c.On("chat", func(message string) {

		c.To("testroom").Emit("chat", "fafafafafa")
	})

	c.OnDisconnect(func() {
		fmt.Printf("\nConnection with ID: %s has been disconnected!", c.ID())
	})

    // test room
    go func(c *websocket.Connection){

        time.Sleep(2 * time.Second)

        c.To("testroom").Emit("chat","fffffffff")

        log.Printf("rooms  %v", c.List("testroom"))

    }(c)

    // test namespace
    go func(){

        time.Sleep(4 * time.Second)

        server.Of("testnamespace").To("testroom").Emit("chat","fffffffffffffffff")

    }()

}

func main() {

    num := runtime.NumCPU()
    runtime.GOMAXPROCS(num)

    server = websocket.New(websocket.Config{})

	http.Handle("/testnamespace", server.Handler())

	server.OnConnection(handleWebsocketConnection)

	server.Serve()

	fmt.Println("start server ", "3000")

	http.ListenAndServe(":3000", nil)

}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"time"

	"./chat"
	"github.com/labstack/echo"
	"github.com/xuender/door"
)

var chats []*chat.Chat

func main() {
	chats = make([]*chat.Chat, 0)
	d := door.New()
	d.OPEN(open)
	d.POST(send, "send")
	d.PUT(nick, "nick")
	d.AddFilter(&Inline{func(c *Context) error {
		fmt.Println(1)
		err := c.Next()
		fmt.Println(-1)
		return err
	}}, "send")

	e := echo.New()
	e.GET("/ws", func(c echo.Context) error {
		return d.WebsocketHandler(c.Response().Writer, c.Request())
	})
	e.Static("/", "dist")
	e.Logger.Fatal(e.Start(":8888"))
}

func send(c door.Context) error {
	ca := &chat.Chat{}
	c.Unmarshal(ca)
	ca.Timestamp = time.Now().UnixNano()
	chats = append(chats, ca)
	if len(chats) > 20 {
		chats = chats[1:21]
	}
	for _, num := range c.Numbers() {
		c.Send(num, ca, door.MethodEnum_POST, "send")
	}
	return nil
}

func nick(c door.Context) error {
	ca := &chat.Chat{}
	c.Unmarshal(ca)
	ca.Timestamp = time.Now().UnixNano()
	ca.Context = fmt.Sprintf("欢迎 [ %s ] 进入聊天室！", ca.Nick)
	ca.Nick = "机器人"
	chats = append(chats, ca)
	if len(chats) > 20 {
		chats = chats[1:21]
	}
	for _, num := range c.Numbers() {
		c.Send(num, ca, door.MethodEnum_POST, "send")
	}
	return nil
}

func open(c door.Context) error {
	c.Revert(&chat.Chats{
		Chats: chats,
	}, door.MethodEnum_PUT, "send")
	ca := &chat.Chat{
		Nick:      "机器人",
		Context:   "你进入了一个聊天室",
		Timestamp: time.Now().UnixNano(),
	}
	c.Revert(ca, door.MethodEnum_POST, "send")
	return nil
}
<commit_msg>fix #12<commit_after>package main

import (
	"errors"
	"fmt"
	"strings"
	"time"

	"./chat"
	"github.com/labstack/echo"
	"github.com/xuender/door"
)

var chats []*chat.Chat

func main() {
	chats = make([]*chat.Chat, 0)
	d := door.New()
	d.OPEN(open)
	d.POST(send, "send")
	d.PUT(nick, "nick")
	d.AddFilter(&door.Inline{Handler: func(c *door.Context) error {
		ca := &chat.Chat{}
		c.Unmarshal(ca)
		if strings.Contains(ca.Context, "sex") {
			return errors.New("过滤词")
		}
		err := c.Next()
		return err
	}}, "send")
	d.AddFilter(&door.Inline{Handler: func(c *door.Context) error {
		ca := &chat.Chat{}
		c.Unmarshal(ca)
		ca.Nick = strings.Replace(ca.Nick, "sex", "***", -1)
		c.Marshal(ca)
		err := c.Next()
		return err
	}}, "send")

	e := echo.New()
	e.GET("/ws", func(c echo.Context) error {
		return d.WebsocketHandler(c.Response().Writer, c.Request())
	})
	e.Static("/", "dist")
	e.Logger.Fatal(e.Start(":8888"))
}

func send(c door.Context) error {
	ca := &chat.Chat{}
	c.Unmarshal(ca)
	ca.Timestamp = time.Now().UnixNano()
	chats = append(chats, ca)
	if len(chats) > 20 {
		chats = chats[1:21]
	}
	for _, num := range c.Numbers() {
		c.Send(num, ca, door.MethodEnum_POST, "send")
	}
	return nil
}

func nick(c door.Context) error {
	ca := &chat.Chat{}
	c.Unmarshal(ca)
	ca.Timestamp = time.Now().UnixNano()
	ca.Context = fmt.Sprintf("欢迎 [ %s ] 进入聊天室！", ca.Nick)
	ca.Nick = "机器人"
	chats = append(chats, ca)
	if len(chats) > 20 {
		chats = chats[1:21]
	}
	for _, num := range c.Numbers() {
		c.Send(num, ca, door.MethodEnum_POST, "send")
	}
	return nil
}

func open(c door.Context) error {
	c.Revert(&chat.Chats{
		Chats: chats,
	}, door.MethodEnum_PUT, "send")
	ca := &chat.Chat{
		Nick:      "机器人",
		Context:   "你进入了一个聊天室",
		Timestamp: time.Now().UnixNano(),
	}
	c.Revert(ca, door.MethodEnum_POST, "send")
	return nil
}
<|endoftext|>