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

package jsonrpc2

import (
	"bufio"
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"net/http/httptest"
	"net/rpc"
	"strings"
	"testing"
)

type Args struct {
	A, B int
}

type Reply struct {
	C int
}

type Arith int

type ArithAddResp struct {
	ID     interface{} `json:"id"`
	Result Reply       `json:"result"`
	Error  interface{} `json:"error"`
}

func (t *Arith) Add(args *Args, reply *Reply) error {
	reply.C = args.A + args.B
	return nil
}

func (t *Arith) Mul(args *Args, reply *Reply) error {
	reply.C = args.A * args.B
	return nil
}

func (t *Arith) Div(args *Args, reply *Reply) error {
	if args.B == 0 {
		return errors.New("divide by zero")
	}
	reply.C = args.A / args.B
	return nil
}

func (t *Arith) Error(args *Args, reply *Reply) error {
	panic("ERROR")
}

func init() {
	rpc.Register(new(Arith))
}

func TestServerNoParams(t *testing.T) {
	cli, srv := net.Pipe()
	defer cli.Close()
	go ServeConn(srv)
	dec := json.NewDecoder(cli)

	fmt.Fprintf(cli, `{"method": "Arith.Add", "id": "123"}`)
	var resp ArithAddResp
	if err := dec.Decode(&resp); err != nil {
		t.Fatalf("Decode after no params: %s", err)
	}
	if resp.Error == nil {
		t.Fatalf("Expected error, got nil")
	}
}

func TestServerEmptyMessage(t *testing.T) {
	cli, srv := net.Pipe()
	defer cli.Close()
	go ServeConn(srv)
	dec := json.NewDecoder(cli)

	fmt.Fprintf(cli, "{}")
	var resp ArithAddResp
	if err := dec.Decode(&resp); err != nil {
		t.Fatalf("Decode after empty: %s", err)
	}
	if resp.Error == nil {
		t.Fatalf("Expected error, got nil")
	}
}

func TestServer(t *testing.T) {
	cli, srv := net.Pipe()
	defer cli.Close()
	go ServeConn(srv)
	dec := json.NewDecoder(cli)

	// Send hand-coded requests to server, parse responses.
	for i := 0; i < 10; i++ {
		fmt.Fprintf(cli, `{"jsonrpc": "2.0", "method": "Arith.Add", "id": "\u%04d", "params": {"A": %d, "B": %d}}`, i, i, i+1)
		var resp ArithAddResp
		err := dec.Decode(&resp)
		if err != nil {
			t.Fatalf("Decode: %s", err)
		}
		if resp.Error != nil {
			t.Fatalf("resp.Error: %s", resp.Error)
		}
		if resp.ID.(string) != string(i) {
			t.Fatalf("resp: bad id %q want %q", resp.ID.(string), string(i))
		}
		if resp.Result.C != 2*i+1 {
			t.Fatalf("resp: bad result: %d+%d=%d", i, i+1, resp.Result.C)
		}
	}
}

func TestClient(t *testing.T) {
	// Assume server is okay (TestServer is above).
	// Test client against server.
	cli, srv := net.Pipe()
	go ServeConn(srv)

	client := NewClient(cli)
	defer client.Close()

	// Synchronous calls
	args := &Args{7, 8}
	reply := new(Reply)
	err := client.Call("Arith.Add", args, reply)
	if err != nil {
		t.Errorf("Add: expected no error but got string %q", err.Error())
	}
	if reply.C != args.A+args.B {
		t.Errorf("Add: got %d expected %d", reply.C, args.A+args.B)
	}

	args = &Args{7, 8}
	reply = new(Reply)
	err = client.Call("Arith.Mul", args, reply)
	if err != nil {
		t.Errorf("Mul: expected no error but got string %q", err.Error())
	}
	if reply.C != args.A*args.B {
		t.Errorf("Mul: got %d expected %d", reply.C, args.A*args.B)
	}

	// Out of order.
	args = &Args{7, 8}
	mulReply := new(Reply)
	mulCall := client.Go("Arith.Mul", args, mulReply, nil)
	addReply := new(Reply)
	addCall := client.Go("Arith.Add", args, addReply, nil)

	addCall = <-addCall.Done
	if addCall.Error != nil {
		t.Errorf("Add: expected no error but got string %q", addCall.Error.Error())
	}
	if addReply.C != args.A+args.B {
		t.Errorf("Add: got %d expected %d", addReply.C, args.A+args.B)
	}

	mulCall = <-mulCall.Done
	if mulCall.Error != nil {
		t.Errorf("Mul: expected no error but got string %q", mulCall.Error.Error())
	}
	if mulReply.C != args.A*args.B {
		t.Errorf("Mul: got %d expected %d", mulReply.C, args.A*args.B)
	}

	// Error test
	args = &Args{7, 0}
	reply = new(Reply)
	err = client.Call("Arith.Div", args, reply)
	// expect an error: zero divide
	if err == nil {
		t.Error("Div: expected error")
	} else if ServerError(err).Message != "divide by zero" {
		t.Error("Div: expected divide by zero error; got", err)
	}
}

func TestMalformedInput(t *testing.T) {
	cli, srv := net.Pipe()
	go func() {
		cli.Write([]byte(`{id:1}`)) // invalid json
		cli.Read(make([]byte, 1024))
	}()
	ServeConn(srv) // must return, not loop
}

func TestMalformedOutput(t *testing.T) {
	cli, srv := net.Pipe()
	go srv.Write([]byte(`{"id":0,"result":null,"error":null}`))
	go ioutil.ReadAll(srv)

	client := NewClient(cli)
	defer client.Close()

	args := &Args{7, 8}
	reply := new(Reply)
	err := client.Call("Arith.Add", args, reply)
	if err == nil {
		t.Error("expected error")
	}
}

func TestServerErrorHasNullResult(t *testing.T) {
	var out bytes.Buffer
	sc := NewServerCodec(struct {
		io.Reader
		io.Writer
		io.Closer
	}{
		Reader: strings.NewReader(`{"jsonrpc": "2.0", "method": "Arith.Add", "id": "123", "params": []}`),
		Writer: &out,
		Closer: ioutil.NopCloser(nil),
	}, nil)
	r := new(rpc.Request)
	if err := sc.ReadRequestHeader(r); err != nil {
		t.Fatal(err)
	}
	const valueText = "the value we don't want to see"
	const errorText = "some error"
	err := sc.WriteResponse(&rpc.Response{
		ServiceMethod: "Method",
		Seq:           1,
		Error:         errorText,
	}, valueText)
	if err != nil {
		t.Fatal(err)
	}
	if !strings.Contains(out.String(), errorText) {
		t.Fatalf("Response didn't contain expected error %q: %s", errorText, &out)
	}
	if strings.Contains(out.String(), valueText) {
		t.Errorf("Response contains both an error and value: %s", &out)
	}
}

func TestUnexpectedError(t *testing.T) {
	cli, srv := myPipe()
	go cli.PipeWriter.CloseWithError(errors.New("unexpected error")) // reader will get this error
	go cli.PipeReader.Close()                                        // writer will get ErrClosedPipe
	ServeConn(srv)                                                   // must return, not loop
}

func TestBadHTTP2Server(t *testing.T) {
	ts := httptest.NewServer(HTTPHandler(nil))
	// Don't close because of https://github.com/golang/go/issues/12262
	// defer ts.Close()
	addr := ts.URL[strings.LastIndex(ts.URL, "/")+1:]
	for _, c := range []string{"", " ", "{", `{"jsonrpc":"2.0",`} {
		conn, err := net.Dial("tcp", addr)
		if err != nil {
			t.Fatalf("Dial(%s), err = %v", addr, err)
		}
		_, err = conn.Write([]byte("POST / HTTP/1.0\r\n" +
			"Host: localhost\r\n" +
			"Content-Type: application/json\r\n" +
			"Accept: application/json\r\n" +
			"Content-Length: " + fmt.Sprintf("%d", len(c)) + "\r\n" +
			"\r\n" + c))
		if err != nil {
			t.Fatalf("[%#q] Write(), err = %v", c, err)
		}
		resp, err := http.ReadResponse(bufio.NewReader(conn), nil)
		if err != nil {
			t.Fatalf("[%#q] ReadResponse(), err = %v", c, err)
		}
		if resp.StatusCode != http.StatusOK {
			t.Errorf("[%#q] resp.StatusCode = %d, want %d", c, resp.StatusCode, http.StatusOK)
		}
		var r clientResponse
		err = json.NewDecoder(resp.Body).Decode(&r)
		if err != nil {
			t.Errorf("[%#q] Decode(), err = %v", c, err)
		}
		if r.Error == nil || r.Error.Code != errParse.Code {
			t.Errorf("[%#q] r = %v, wait errParse", c, r)
		}
	}
}

// Copied from package net.
func myPipe() (*pipe, *pipe) {
	r1, w1 := io.Pipe()
	r2, w2 := io.Pipe()

	return &pipe{r1, w2}, &pipe{r2, w1}
}

type pipe struct {
	*io.PipeReader
	*io.PipeWriter
}

type pipeAddr int

func (pipeAddr) Network() string {
	return "pipe"
}

func (pipeAddr) String() string {
	return "pipe"
}

func (p *pipe) Close() error {
	err := p.PipeReader.Close()
	err1 := p.PipeWriter.Close()
	if err == nil {
		err = err1
	}
	return err
}

func (p *pipe) LocalAddr() net.Addr {
	return pipeAddr(0)
}

func (p *pipe) RemoteAddr() net.Addr {
	return pipeAddr(0)
}

func (p *pipe) SetTimeout(nsec int64) error {
	return errors.New("net.Pipe does not support timeouts")
}

func (p *pipe) SetReadTimeout(nsec int64) error {
	return errors.New("net.Pipe does not support timeouts")
}

func (p *pipe) SetWriteTimeout(nsec int64) error {
	return errors.New("net.Pipe does not support timeouts")
}
<commit_msg>fix tests for go-1.1<commit_after>// Based on net/rpc/jsonrpc by:
// Copyright 2010 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package jsonrpc2

import (
	"bufio"
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"net/http/httptest"
	"net/rpc"
	"strings"
	"testing"
)

type Args struct {
	A, B int
}

type Reply struct {
	C int
}

type Arith int

type ArithAddResp struct {
	ID     interface{} `json:"id"`
	Result Reply       `json:"result"`
	Error  interface{} `json:"error"`
}

func (t *Arith) Add(args *Args, reply *Reply) error {
	reply.C = args.A + args.B
	return nil
}

func (t *Arith) Mul(args *Args, reply *Reply) error {
	reply.C = args.A * args.B
	return nil
}

func (t *Arith) Div(args *Args, reply *Reply) error {
	if args.B == 0 {
		return errors.New("divide by zero")
	}
	reply.C = args.A / args.B
	return nil
}

func (t *Arith) Error(args *Args, reply *Reply) error {
	panic("ERROR")
}

func init() {
	rpc.Register(new(Arith))
}

func TestServerNoParams(t *testing.T) {
	cli, srv := net.Pipe()
	defer cli.Close()
	go ServeConn(srv)
	dec := json.NewDecoder(cli)

	fmt.Fprintf(cli, `{"method": "Arith.Add", "id": "123"}`)
	var resp ArithAddResp
	if err := dec.Decode(&resp); err != nil {
		t.Fatalf("Decode after no params: %s", err)
	}
	if resp.Error == nil {
		t.Fatalf("Expected error, got nil")
	}
}

func TestServerEmptyMessage(t *testing.T) {
	cli, srv := net.Pipe()
	defer cli.Close()
	go ServeConn(srv)
	dec := json.NewDecoder(cli)

	fmt.Fprintf(cli, "{}")
	var resp ArithAddResp
	if err := dec.Decode(&resp); err != nil {
		t.Fatalf("Decode after empty: %s", err)
	}
	if resp.Error == nil {
		t.Fatalf("Expected error, got nil")
	}
}

func TestServer(t *testing.T) {
	cli, srv := net.Pipe()
	defer cli.Close()
	go ServeConn(srv)
	dec := json.NewDecoder(cli)

	// Send hand-coded requests to server, parse responses.
	for i := 0; i < 10; i++ {
		fmt.Fprintf(cli, `{"jsonrpc": "2.0", "method": "Arith.Add", "id": "\u%04d", "params": {"A": %d, "B": %d}}`, i, i, i+1)
		var resp ArithAddResp
		err := dec.Decode(&resp)
		if err != nil {
			t.Fatalf("Decode: %s", err)
		}
		if resp.Error != nil {
			t.Fatalf("resp.Error: %s", resp.Error)
		}
		if resp.ID.(string) != string(i) {
			t.Fatalf("resp: bad id %q want %q", resp.ID.(string), string(i))
		}
		if resp.Result.C != 2*i+1 {
			t.Fatalf("resp: bad result: %d+%d=%d", i, i+1, resp.Result.C)
		}
	}
}

func TestClient(t *testing.T) {
	// Assume server is okay (TestServer is above).
	// Test client against server.
	cli, srv := net.Pipe()
	go ServeConn(srv)

	client := NewClient(cli)
	defer client.Close()

	// Synchronous calls
	args := &Args{7, 8}
	reply := new(Reply)
	err := client.Call("Arith.Add", args, reply)
	if err != nil {
		t.Errorf("Add: expected no error but got string %q", err.Error())
	}
	if reply.C != args.A+args.B {
		t.Errorf("Add: got %d expected %d", reply.C, args.A+args.B)
	}

	args = &Args{7, 8}
	reply = new(Reply)
	err = client.Call("Arith.Mul", args, reply)
	if err != nil {
		t.Errorf("Mul: expected no error but got string %q", err.Error())
	}
	if reply.C != args.A*args.B {
		t.Errorf("Mul: got %d expected %d", reply.C, args.A*args.B)
	}

	// Out of order.
	args = &Args{7, 8}
	mulReply := new(Reply)
	mulCall := client.Go("Arith.Mul", args, mulReply, nil)
	addReply := new(Reply)
	addCall := client.Go("Arith.Add", args, addReply, nil)

	addCall = <-addCall.Done
	if addCall.Error != nil {
		t.Errorf("Add: expected no error but got string %q", addCall.Error.Error())
	}
	if addReply.C != args.A+args.B {
		t.Errorf("Add: got %d expected %d", addReply.C, args.A+args.B)
	}

	mulCall = <-mulCall.Done
	if mulCall.Error != nil {
		t.Errorf("Mul: expected no error but got string %q", mulCall.Error.Error())
	}
	if mulReply.C != args.A*args.B {
		t.Errorf("Mul: got %d expected %d", mulReply.C, args.A*args.B)
	}

	// Error test
	args = &Args{7, 0}
	reply = new(Reply)
	err = client.Call("Arith.Div", args, reply)
	// expect an error: zero divide
	if err == nil {
		t.Error("Div: expected error")
	} else if ServerError(err).Message != "divide by zero" {
		t.Error("Div: expected divide by zero error; got", err)
	}
}

func TestMalformedInput(t *testing.T) {
	cli, srv := net.Pipe()
	go func() {
		cli.Write([]byte(`{id:1}`)) // invalid json
		cli.Read(make([]byte, 1024))
	}()
	ServeConn(srv) // must return, not loop
}

func TestMalformedOutput(t *testing.T) {
	cli, srv := net.Pipe()
	go srv.Write([]byte(`{"id":0,"result":null,"error":null}`))
	go ioutil.ReadAll(srv)

	client := NewClient(cli)
	defer client.Close()

	args := &Args{7, 8}
	reply := new(Reply)
	err := client.Call("Arith.Add", args, reply)
	if err == nil {
		t.Error("expected error")
	}
}

func TestServerErrorHasNullResult(t *testing.T) {
	var out bytes.Buffer
	sc := NewServerCodec(struct {
		io.Reader
		io.Writer
		io.Closer
	}{
		Reader: strings.NewReader(`{"jsonrpc": "2.0", "method": "Arith.Add", "id": "123", "params": []}`),
		Writer: &out,
		Closer: ioutil.NopCloser(nil),
	}, nil)
	r := new(rpc.Request)
	if err := sc.ReadRequestHeader(r); err != nil {
		t.Fatal(err)
	}
	const valueText = "the value we don't want to see"
	const errorText = "some error"
	err := sc.WriteResponse(&rpc.Response{
		ServiceMethod: "Method",
		Seq:           1,
		Error:         errorText,
	}, valueText)
	if err != nil {
		t.Fatal(err)
	}
	if !strings.Contains(out.String(), errorText) {
		t.Fatalf("Response didn't contain expected error %q: %s", errorText, &out)
	}
	if strings.Contains(out.String(), valueText) {
		t.Errorf("Response contains both an error and value: %s", &out)
	}
}

func TestUnexpectedError(t *testing.T) {
	cli, srv := myPipe()
	go cli.PipeWriter.CloseWithError(errors.New("unexpected error")) // reader will get this error
	go cli.PipeReader.Close()                                        // writer will get ErrClosedPipe
	ServeConn(srv)                                                   // must return, not loop
}

func TestBadHTTP2Server(t *testing.T) {
	ts := httptest.NewServer(HTTPHandler(nil))
	// Don't close because of https://github.com/golang/go/issues/12262
	// defer ts.Close()
	addr := ts.URL[strings.LastIndex(ts.URL, "/")+1:]
	for _, c := range []string{"", " ", "{", `{"jsonrpc":"2.0",`} {
		conn, err := net.Dial("tcp", addr)
		if err != nil {
			t.Fatalf("Dial(%s), err = %v", addr, err)
		}
		_, err = conn.Write([]byte("POST / HTTP/1.0\r\n" +
			"Host: localhost\r\n" +
			"Content-Type: application/json\r\n" +
			"Accept: application/json\r\n" +
			"Content-Length: " + fmt.Sprintf("%d", len(c)) + "\r\n" +
			"\r\n" + c))
		if err != nil {
			t.Fatalf("[%#q] Write(), err = %v", c, err)
		}
		req, err := http.NewRequest("POST", ts.URL, strings.NewReader(c))
		if err != nil {
			t.Errorf("[%#q] NewRequest(), err = %v", c, err)
		}
		resp, err := http.ReadResponse(bufio.NewReader(conn), req)
		if err != nil {
			t.Fatalf("[%#q] ReadResponse(), err = %v", c, err)
		}
		if resp.StatusCode != http.StatusOK {
			t.Errorf("[%#q] resp.StatusCode = %d, want %d", c, resp.StatusCode, http.StatusOK)
		}
		var r clientResponse
		err = json.NewDecoder(resp.Body).Decode(&r)
		if err != nil {
			t.Errorf("[%#q] Decode(), err = %v", c, err)
		}
		if r.Error == nil || r.Error.Code != errParse.Code {
			t.Errorf("[%#q] r = %v, wait errParse", c, r)
		}
	}
}

// Copied from package net.
func myPipe() (*pipe, *pipe) {
	r1, w1 := io.Pipe()
	r2, w2 := io.Pipe()

	return &pipe{r1, w2}, &pipe{r2, w1}
}

type pipe struct {
	*io.PipeReader
	*io.PipeWriter
}

type pipeAddr int

func (pipeAddr) Network() string {
	return "pipe"
}

func (pipeAddr) String() string {
	return "pipe"
}

func (p *pipe) Close() error {
	err := p.PipeReader.Close()
	err1 := p.PipeWriter.Close()
	if err == nil {
		err = err1
	}
	return err
}

func (p *pipe) LocalAddr() net.Addr {
	return pipeAddr(0)
}

func (p *pipe) RemoteAddr() net.Addr {
	return pipeAddr(0)
}

func (p *pipe) SetTimeout(nsec int64) error {
	return errors.New("net.Pipe does not support timeouts")
}

func (p *pipe) SetReadTimeout(nsec int64) error {
	return errors.New("net.Pipe does not support timeouts")
}

func (p *pipe) SetWriteTimeout(nsec int64) error {
	return errors.New("net.Pipe does not support timeouts")
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"net"
	"syscall"
	//"golang.org/x/net/ipv4"
)

/*type Network_Reader_IP struct {
    dst string
    protocol uint8
    buffer chan []byte
}

func NewNetwork_Reader_IP(dst string, protocol uint8) (*Network_Reader_IP, error) {

}*/

type Network_Reader struct {
	fd      int
	buffers map[string](map[uint8](chan []byte))
	//buffers map[uint8](chan []byte)
}

const MAX_IP_PACKET_LEN = 65535

func NewNetwork_Reader() (*Network_Reader, error) {
	// 768 = htons(ETH_P_ALL) = htons(3)
	// see http://ideone.com/2eunQu

	// 17 = AF_PACKET
	// see http://ideone.com/TGYlGc
	fd, err := syscall.Socket(17, syscall.SOCK_DGRAM, 768)

	if err != nil {
		fmt.Println("AF_PACKET socket connection")
		return nil, err
	}

	nr := &Network_Reader{
		fd: fd,
		//buffers: make(map[uint8](chan []byte)),
		buffers: make(map[string](map[uint8](chan []byte))),
	}
	go nr.readAll()

	return nr, nil
}

func (nr *Network_Reader) readAll() {
	for {
		buf := make([]byte, MAX_IP_PACKET_LEN)
		ln, err := nr.getNextPacket(buf)

		if err != nil {
			fmt.Println(err)
		}

		buf = buf[:ln]
		if len(buf) <= 20 {
			continue
		}

		// TODO: assemble IP fragments

		protocol := uint8(buf[9])
		ip := net.IPv4(buf[12], buf[13], buf[14], buf[15]).String()

		if protoBuf, found := nr.buffers[ip]; found {
			if c, foundProto := protoBuf[protocol]; foundProto {
				go func() { c <- buf }()
			}
		}
	}
}

func (nr *Network_Reader) bind(ip string, protocol uint8) (<-chan []byte, error) {
	// TODO: implement forwarding
	_, ipOk := nr.buffers[ip]
	if !ipOk {
		nr.buffers[ip] = make(map[uint8](chan []byte))
	}
	protoBuf, _ := nr.buffers[ip]
	if _, ok := protoBuf[protocol]; !ok {
		// doesn't exist in map already
		protoBuf[protocol] = make(chan []byte, 1)

		ret, _ := protoBuf[protocol]
		return ret, nil
	}
	return nil, errors.New("Protocol already binded to.")
}

func (nr *Network_Reader) unbind(ip string, protocol uint8) error {
	// TODO: take into account the protocol

	protoBuf, ipOk := nr.buffers[ip]
	if !ipOk {
		return errors.New("IP not bound, cannot unbind")
	}

	if _, ok := protoBuf[protocol]; ok {
		delete(protoBuf, protocol)
		if len(protoBuf) == 0 {
			delete(nr.buffers, ip)
		}
		return nil
	}
	return errors.New("Not binded, can't unbind.")
}

func (nr *Network_Reader) getNextPacket(buf []byte) (int, error) {
	return syscall.Read(nr.fd, buf)
}
<commit_msg>Random comments and stuff<commit_after>package main

import (
	"errors"
	"fmt"
	"net"
	"syscall"
	//"golang.org/x/net/ipv4"
)

/*type Network_Reader_IP struct {
    dst string
    protocol uint8
    buffer chan []byte
}

func NewNetwork_Reader_IP(dst string, protocol uint8) (*Network_Reader_IP, error) {

}*/

type Network_Reader struct {
	fd      int
	buffers map[string](map[uint8](chan []byte))
	//buffers map[uint8](chan []byte)
}

const MAX_IP_PACKET_LEN = 65535

func NewNetwork_Reader() (*Network_Reader, error) {
	// 768 = htons(ETH_P_ALL) = htons(3)
	// see http://ideone.com/2eunQu

	// 17 = AF_PACKET
	// see http://ideone.com/TGYlGc
	fd, err := syscall.Socket(17, syscall.SOCK_RAW, 768)

	if err != nil {
		fmt.Println("AF_PACKET socket connection")
		return nil, err
	}

	nr := &Network_Reader{
		fd: fd,
		//buffers: make(map[uint8](chan []byte)),
		buffers: make(map[string](map[uint8](chan []byte))),
	}
	go nr.readAll()

	return nr, nil
}

func (nr *Network_Reader) readAll() {
	for {
		buf := make([]byte, MAX_IP_PACKET_LEN)
		ln, err := nr.getNextPacket(buf)

		if err != nil {
			fmt.Println(err)
		}

		buf = buf[:ln]
		if len(buf) <= 20 {
			continue
		}

		// TODO: assemble IP fragments

		protocol := uint8(buf[9])
		ip := net.IPv4(buf[12], buf[13], buf[14], buf[15]).String()

		if protoBuf, found := nr.buffers[ip]; found {
			if c, foundProto := protoBuf[protocol]; foundProto {
				go func() { c <- buf }()
			}
		}
	}
}

func (nr *Network_Reader) bind(ip string, protocol uint8) (<-chan []byte, error) {
	// TODO: implement forwarding
	_, ipOk := nr.buffers[ip]
	if !ipOk {
		nr.buffers[ip] = make(map[uint8](chan []byte))
	}
	protoBuf, _ := nr.buffers[ip]
	if _, ok := protoBuf[protocol]; !ok {
		// doesn't exist in map already
		protoBuf[protocol] = make(chan []byte, 1)

		ret, _ := protoBuf[protocol]
		return ret, nil
	}
	return nil, errors.New("Protocol already bound.")
}

func (nr *Network_Reader) unbind(ip string, protocol uint8) error {
	// TODO: take into account the protocol

	protoBuf, ipOk := nr.buffers[ip]
	if !ipOk {
		return errors.New("IP not bound, cannot unbind")
	}

	if _, ok := protoBuf[protocol]; ok {
		delete(protoBuf, protocol)
		if len(protoBuf) == 0 {
			delete(nr.buffers, ip)
		}
		return nil
	}
	return errors.New("Not bound, can't unbind.")
}

func (nr *Network_Reader) getNextPacket(buf []byte) (int, error) {
	return syscall.Read(nr.fd, buf)
}
<|endoftext|>


<commit_before>//
// Arpapp
//

package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/exec"
	"regexp"
	"sort"
	"strconv"
	"time"
)

type ArpEntry struct {
	online bool
	stamp  time.Time
}

const (
	ARPREGEX  = ".*? \\((.*?)\\) "
	LOGSIZE   = 16
	HTMLSTART = `<title>arpapp</title>

arpapp

`
	HTMLEND = `</pre></body></html>`
)

var (
	host     string
	port     int
	interval time.Duration
	arplog   map[string]ArpEntry
	arpregex *regexp.Regexp
)

func die(msg string, code int) {
	log.Fatalln(msg)
	os.Exit(code)
}

func setup() {
	var err error
	var intervalstr string

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s [options] PORT\n", os.Args[0])
		flag.PrintDefaults()
	}

	flag.StringVar(&host, "h", "127.0.0.1", "HTTP server bind HOST")
	flag.StringVar(&intervalstr, "i", "10m", "Scan INTERVAL")
	flag.Parse()

	if len(flag.Args()) < 1 {
		die("You have to specify a port!", 2)
	}

	interval, err = time.ParseDuration(intervalstr)
	if err != nil {
		die("Couldn't parse interval!", 2)
	}

	port, err = strconv.Atoi(flag.Args()[0])
	if err != nil || port <= 0 {
		die("Port has to be a positive integer!", 2)
	}

	arpregex = regexp.MustCompile(ARPREGEX)
	arplog = make(map[string]ArpEntry, LOGSIZE)
}

func scan() {
	data, err := exec.Command("arp", "-a").Output()
	if err != nil {
		log.Println("ERROR: running 'arp -a'")
		return
	}

	matches := arpregex.FindAllStringSubmatch(string(data), -1)
	seen := make(map[string]bool, len(matches))
	for i := 0; i < len(matches); i++ {
		ip := matches[i][1]
		if exec.Command("ping", "-c1", "-W1", ip).Run() == nil {
			seen[ip] = true
		} else {
			continue
		}
	}
	for ip, _ := range seen {
		if _, present := arplog[ip]; present {
			if !arplog[ip].online {
				arplog[ip] = ArpEntry{online: true, stamp: time.Now()}
			}
		} else {
			arplog[ip] = ArpEntry{online: true, stamp: time.Now()}
		}
	}
	for ip, entry := range arplog {
		if _, present := seen[ip]; !present {
			if entry.online {
				arplog[ip] = ArpEntry{online: false, stamp: time.Now()}
			}
		}
	}
}

func render(out http.ResponseWriter, req *http.Request) {
	keys := make([]string, len(arplog))
	i := 0
	for ip, _ := range arplog {
		keys[i] = ip
		i++
	}
	sort.Strings(keys)

	fmt.Fprintf(out, HTMLSTART)
	for _, ip := range keys {
		entry := arplog[ip]
		duration := time.Since(entry.stamp)

		fmt.Fprintf(out, "%-15s since %s (%s)\n", ip, entry.stamp.Format("2006-01-02 15:04:05 MST"), duration.String())
	}
	fmt.Fprintf(out, "\ninterval: %s", interval)
	fmt.Fprintf(out, HTMLEND)
}

func main() {
	setup()

	http.HandleFunc("/", render)
	go http.ListenAndServe(fmt.Sprintf("%s:%d", host, port), nil)

	for {
		scan()
		time.Sleep(interval)
	}
}
<commit_msg>Add decay for arpapp<commit_after>//
// Arpapp
//

package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/exec"
	"regexp"
	"sort"
	"strconv"
	"time"
)

type ArpEntry struct {
	online bool
	stamp  time.Time
}

const (
	ARPREGEX  = ".*? \\((.*?)\\) "
	LOGSIZE   = 16
	HTMLSTART = `<title>arpapp</title>

arpapp

`
	HTMLEND = `</pre></body></html>`
)

var (
	host     string
	port     int
	interval time.Duration
	decay    int
	arplog   map[string]ArpEntry
	arpregex *regexp.Regexp
	decayrex *regexp.Regexp
)

func die(msg string, code int) {
	log.Fatalln(msg)
	os.Exit(code)
}

func setup() {
	var err error
	var intervalstr string
	var decayrexstr string

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s [options] PORT\n", os.Args[0])
		flag.PrintDefaults()
	}

	flag.StringVar(&host, "h", "127.0.0.1", "HTTP server bind HOST")
	flag.StringVar(&intervalstr, "i", "10m", "Scan INTERVAL")
	flag.IntVar(&decay, "d", 72, "Forget after DECAY hours")
	flag.StringVar(&decayrexstr, "r", "", "Decay only IPs matching REGEXP")
	flag.Parse()

	if len(flag.Args()) < 1 {
		die("You have to specify a port!", 2)
	}

	interval, err = time.ParseDuration(intervalstr)
	if err != nil {
		die("Couldn't parse interval!", 2)
	}

	port, err = strconv.Atoi(flag.Args()[0])
	if err != nil || port <= 0 {
		die("Port has to be a positive integer!", 2)
	}

	if (len(decayrexstr) > 0) && (decay > 0) {
		decayrex, err = regexp.Compile(decayrexstr)
		if err != nil {
			die("Failed to compile regexp '"+decayrexstr+"'!", 2)
		}
	} else {
		decayrex = nil
	}

	arpregex = regexp.MustCompile(ARPREGEX)
	arplog = make(map[string]ArpEntry, LOGSIZE)
}

func scan() {
	data, err := exec.Command("arp", "-a").Output()
	if err != nil {
		log.Println("ERROR: running 'arp -a'")
		return
	}

	matches := arpregex.FindAllStringSubmatch(string(data), -1)
	seen := make(map[string]bool, len(matches))
	for i := 0; i < len(matches); i++ {
		ip := matches[i][1]
		if exec.Command("ping", "-c1", "-W1", ip).Run() == nil {
			seen[ip] = true
		} else {
			continue
		}
	}
	for ip, _ := range seen {
		if _, present := arplog[ip]; present {
			if !arplog[ip].online {
				arplog[ip] = ArpEntry{online: true, stamp: time.Now()}
			}
		} else {
			arplog[ip] = ArpEntry{online: true, stamp: time.Now()}
		}
	}
	for ip, entry := range arplog {
		if _, present := seen[ip]; !present {
			if entry.online {
				arplog[ip] = ArpEntry{online: false, stamp: time.Now()}
			}
		}
		if (decayrex != nil) && !entry.online {
			if decayrex.MatchString(ip) {
				duration := time.Since(entry.stamp)
				if duration.Hours() >= float64(decay) {
					delete(arplog, ip)
				}
			}
		}
	}
}

func render(out http.ResponseWriter, req *http.Request) {
	keys := make([]string, len(arplog))
	i := 0
	for ip, _ := range arplog {
		keys[i] = ip
		i++
	}
	sort.Strings(keys)

	fmt.Fprintf(out, HTMLSTART)
	for _, ip := range keys {
		entry := arplog[ip]
		duration := time.Since(entry.stamp)

		fmt.Fprintf(out, "%-15s since %s (%s)\n", ip, entry.stamp.Format("2006-01-02 15:04:05 MST"), duration.String())
	}
	fmt.Fprintf(out, "\ninterval: %s", interval)
	fmt.Fprintf(out, HTMLEND)
}

func main() {
	setup()

	http.HandleFunc("/", render)
	go http.ListenAndServe(fmt.Sprintf("%s:%d", host, port), nil)

	for {
		scan()
		time.Sleep(interval)
	}
}
<|endoftext|>


<commit_before>package customerio

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"net/http"
	"path"
	"strconv"
)

// CustomerIO wraps the customer.io API, see: http://customer.io/docs/api/rest.html
type CustomerIO struct {
	siteID string
	apiKey string
	Host   string
	SSL    bool
}

// CustomerIOError is returned by any method that fails at the API level
type CustomerIOError struct {
	status int
	url    string
	body   []byte
}

func (e *CustomerIOError) Error() string {
	return fmt.Sprintf("%v: %v %v", e.status, e.url, string(e.body))
}

// NewCustomerIO creates a new CustomerIO object to perform requests on the supplied credentials
func NewCustomerIO(siteID, apiKey string) *CustomerIO {
	return &CustomerIO{siteID, apiKey, "track.customer.io", true}
}

// Identify identifies a customer and sets their attributes
func (c *CustomerIO) Identify(customerID string, attributes map[string]interface{}) error {
	j, err := json.Marshal(attributes)

	if err != nil {
		return err
	}

	status, responseBody, err := c.request("PUT", c.customerURL(customerID), j)

	if err != nil {
		return err
	} else if status != 200 {
		return &CustomerIOError{status, c.customerURL(customerID), responseBody}
	}

	return nil
}

// Track sends a single event to Customer.io for the supplied user
func (c *CustomerIO) Track(customerID string, eventName string, data map[string]interface{}) error {

	body := map[string]interface{}{"name": eventName, "data": data}
	j, err := json.Marshal(body)

	if err != nil {
		return err
	}

	status, responseBody, err := c.request("POST", c.eventURL(customerID), j)

	if err != nil {
		return err
	} else if status != 200 {
		return &CustomerIOError{status, c.eventURL(customerID), responseBody}
	}

	return nil
}

// Delete deletes a customer
func (c *CustomerIO) Delete(customerID string) error {
	status, responseBody, err := c.request("DELETE", c.customerURL(customerID), []byte{})

	if err != nil {
		return err
	} else if status != 200 {
		return &CustomerIOError{status, c.customerURL(customerID), responseBody}
	}

	return nil
}

func (c *CustomerIO) auth() string {
	return base64.URLEncoding.EncodeToString([]byte(fmt.Sprintf("%v:%v", c.siteID, c.apiKey)))
}

func (c *CustomerIO) protocol() string {
	if !c.SSL {
		return "http://"
	}
	return "https://"
}

func (c *CustomerIO) customerURL(customerID string) string {
	return c.protocol() + path.Join(c.Host, "api/v1", "customers", customerID)
}

func (c *CustomerIO) eventURL(customerID string) string {
	return c.protocol() + path.Join(c.Host, "api/v1", "customers", customerID, "events")
}

func (c *CustomerIO) request(method, url string, body []byte) (status int, responseBody []byte, err error) {

	req, err := http.NewRequest(method, url, bytes.NewBuffer(body))
	if err != nil {
		return
	}
	req.Header.Add("Authorization", fmt.Sprintf("Basic %v", c.auth()))
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Content-Length", strconv.Itoa(len(body)))

	resp, err := http.DefaultClient.Do(req)
	status = resp.StatusCode
	if err == nil {
		defer resp.Body.Close()

		responseBody = make([]byte, resp.ContentLength)
		resp.Body.Read(responseBody)
	}

	return

}
<commit_msg>check for ContentLength before trying to read the body<commit_after>package customerio

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"net/http"
	"path"
	"strconv"
)

// CustomerIO wraps the customer.io API, see: http://customer.io/docs/api/rest.html
type CustomerIO struct {
	siteID string
	apiKey string
	Host   string
	SSL    bool
}

// CustomerIOError is returned by any method that fails at the API level
type CustomerIOError struct {
	status int
	url    string
	body   []byte
}

func (e *CustomerIOError) Error() string {
	return fmt.Sprintf("%v: %v %v", e.status, e.url, string(e.body))
}

// NewCustomerIO creates a new CustomerIO object to perform requests on the supplied credentials
func NewCustomerIO(siteID, apiKey string) *CustomerIO {
	return &CustomerIO{siteID, apiKey, "track.customer.io", true}
}

// Identify identifies a customer and sets their attributes
func (c *CustomerIO) Identify(customerID string, attributes map[string]interface{}) error {
	j, err := json.Marshal(attributes)

	if err != nil {
		return err
	}

	status, responseBody, err := c.request("PUT", c.customerURL(customerID), j)

	if err != nil {
		return err
	} else if status != 200 {
		return &CustomerIOError{status, c.customerURL(customerID), responseBody}
	}

	return nil
}

// Track sends a single event to Customer.io for the supplied user
func (c *CustomerIO) Track(customerID string, eventName string, data map[string]interface{}) error {

	body := map[string]interface{}{"name": eventName, "data": data}
	j, err := json.Marshal(body)

	if err != nil {
		return err
	}

	status, responseBody, err := c.request("POST", c.eventURL(customerID), j)

	if err != nil {
		return err
	} else if status != 200 {
		return &CustomerIOError{status, c.eventURL(customerID), responseBody}
	}

	return nil
}

// Delete deletes a customer
func (c *CustomerIO) Delete(customerID string) error {
	status, responseBody, err := c.request("DELETE", c.customerURL(customerID), []byte{})

	if err != nil {
		return err
	} else if status != 200 {
		return &CustomerIOError{status, c.customerURL(customerID), responseBody}
	}

	return nil
}

func (c *CustomerIO) auth() string {
	return base64.URLEncoding.EncodeToString([]byte(fmt.Sprintf("%v:%v", c.siteID, c.apiKey)))
}

func (c *CustomerIO) protocol() string {
	if !c.SSL {
		return "http://"
	}
	return "https://"
}

func (c *CustomerIO) customerURL(customerID string) string {
	return c.protocol() + path.Join(c.Host, "api/v1", "customers", customerID)
}

func (c *CustomerIO) eventURL(customerID string) string {
	return c.protocol() + path.Join(c.Host, "api/v1", "customers", customerID, "events")
}

func (c *CustomerIO) request(method, url string, body []byte) (status int, responseBody []byte, err error) {

	req, err := http.NewRequest(method, url, bytes.NewBuffer(body))
	if err != nil {
		return
	}
	req.Header.Add("Authorization", fmt.Sprintf("Basic %v", c.auth()))
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Content-Length", strconv.Itoa(len(body)))

	resp, err := http.DefaultClient.Do(req)
	status = resp.StatusCode
	if err == nil {
		defer resp.Body.Close()

		if resp.ContentLength >= 0 {
			responseBody = make([]byte, resp.ContentLength)
			resp.Body.Read(responseBody)
		}
	}

	return

}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013 IBM Corp.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Seth Hoenig
 *    Allan Stockdill-Mander
 *    Mike Robertson
 */

// Package mqtt provides an MQTT v3.1 client library.
package mqtt

import (
	"bufio"
	"errors"
	"math/rand"
	"net"
	"sync"
	"time"
)

// MqttClient is a lightweight MQTT v3.1 Client for communicating
// with an MQTT server using non-blocking methods that allow work
// to be done in the background.

// An application may connect to an MQTT server using:
//   A plain TCP socket
//   A secure SSL/TLS socket
//   A websocket

// To enable ensured message delivery at Quality of Service (QoS) levels
// described in the MQTT spec, a message persistence mechanism must be
// used. This is done by providing a type which implements the Store
// interface. For convenience, FileStore and MemoryStore are provided
// implementations that should be sufficient for most use cases. More
// information can be found in their respective documentation.

// Numerous connection options may be specified by configuring a
// and then supplying a ClientOptions type.
type MqttClient struct {
	sync.RWMutex
	conn            net.Conn
	bufferedConn    *bufio.ReadWriter
	ibound          chan *Message
	obound          chan sendable
	oboundP         chan *Message
	begin           chan ConnRC
	errors          chan error
	stop            chan struct{}
	receipts        *receiptMap
	t               *Tracer
	sessId          uint
	persist         Store
	options         ClientOptions
	lastContact     lastcontact
	pingOutstanding bool
	connected       bool
}

// NewClient will create an MQTT v3.1 client with all of the options specified
// in the provided ClientOptions. The client must have the Start method called
// on it before it may be used. This is to make sure resources (such as a net
// connection) are created before the application is actually ready.
func NewClient(ops *ClientOptions) *MqttClient {
	c := &MqttClient{}
	c.sessId = uint(rand.Int())
	c.sessId = 0
	c.options = *ops

	if c.options.store == nil {
		c.options.store = NewMemoryStore()
	}
	c.persist = c.options.store
	c.connected = false
	return c
}

func (c *MqttClient) IsConnected() bool {
	c.RLock()
	defer c.RUnlock()
	return c.connected
}

// Start will create a connection to the message broker
// If clean session is false, then a slice will
// be returned containing Receipts for all messages
// that were in-flight at the last disconnect.
// If clean session is true, then any existing client
// state will be removed.
func (c *MqttClient) Start() ([]Receipt, error) {

	c.t = &Tracer{
		c.options.tracelevel,
		c.options.tracefile,
		c.options.clientId,
	}

	c.options.store.SetTracer(c.t)

	c.trace_v(CLI, "Start()")

	c1, err1 := openConnection(c.options.server, c.options.tlsconfig)
	if err1 != nil {
		c.trace_w(CLI, "failed to connect to primary broker")
		if c.options.server2 != nil {
			c2, err2 := openConnection(c.options.server2, c.options.tlsconfig)
			if err2 != nil {
				c.trace_w(CLI, "failed to connect to standby broker")
				return nil, err1
			}
			c.conn = c2
			c.trace_v(CLI, "connected to standby broker")
		} else {
			c.trace_w(CLI, "standby broker is not configured")
			return nil, err1
		}
	} else {
		c.conn = c1
		c.trace_v(CLI, "connected to primary broker")
	}

	if c.conn == nil {
		c.trace_e(CLI, "Failed to connect to a broker")
		return nil, errors.New("Failed to connect to a broker")
	}
	c.bufferedConn = bufio.NewReadWriter(bufio.NewReader(c.conn), bufio.NewWriter(c.conn))

	c.persist.Open()
	c.receipts = newReceiptMap()

	c.trace_v(CLI, "about to start generateMsgIds")
	c.options.mids.generateMsgIds()

	c.obound = make(chan sendable)
	c.ibound = make(chan *Message)
	c.oboundP = make(chan *Message)
	c.errors = make(chan error)
	c.stop = make(chan struct{})

	go outgoing(c)
	go alllogic(c)

	cm := newConnectMsgFromOptions(c.options)
	c.trace_v(CLI, "about to write new connect msg")
	c.oboundP <- cm

	rc := connect(c)
	if rc != CONN_ACCEPTED {
		c.trace_c(CLI, "CONNACK was not CONN_ACCEPTED, but rather %s", rc2str(rc))
		return nil, chkrc(rc)
	}

	c.options.pubChanZero = make(chan *Message, 1000)
	c.options.pubChanOne = make(chan *Message, 1000)
	c.options.pubChanTwo = make(chan *Message, 1000)
	c.options.msgRouter.matchAndDispatch(c.options.pubChanZero, c.options.order, c)
	c.options.msgRouter.matchAndDispatch(c.options.pubChanOne, c.options.order, c)
	c.options.msgRouter.matchAndDispatch(c.options.pubChanTwo, c.options.order, c)

	c.connected = true
	c.trace_v(CLI, "client is connected")

	if c.options.timeout != 0 {
		go keepalive(c)
	}

	// Take care of any messages in the store
	var leftovers []Receipt
	if c.options.cleanses == false {
		leftovers = c.resume()
	} else {
		c.persist.Reset()
	}

	// Do not start incoming until resume has completed
	go incoming(c)

	c.trace_v(CLI, "exit startMqttClient")
	return leftovers, chkrc(rc)
}

// Disconnect will end the connection with the server, but not before waiting
// the specified number of milliseconds to wait for existing work to be
// completed.
func (c *MqttClient) Disconnect(quiesce uint) {
	if !c.IsConnected() {
		c.trace_w(CLI, "already disconnected")
		return
	}
	c.trace_v(CLI, "disconnecting")
	c.connected = false

	// wait for work to finish, or quiesce time consumed
	end := time.After(time.Duration(quiesce) * time.Millisecond)

	// for now we just wait for the time specified and hope the work is done
	select {
	case <-end:
		c.trace_v(CLI, "quiesce expired, forcing disconnect")
		// case <- other:
		// 	c.trace_v(CLI, "finished processing work, graceful disconnect")
	}
	c.disconnect()
}

// ForceDisconnect will end the connection with the mqtt broker immediately.
func (c *MqttClient) ForceDisconnect() {
	if !c.IsConnected() {
		c.trace_w(CLI, "already disconnected")
		return
	}
	c.trace_v(CLI, "forcefully disconnecting")
	c.disconnect()
}

func (c *MqttClient) disconnect() {
	c.connected = false
	dm := newDisconnectMsg()

	// Stop all go routines except outgoing
	close(c.stop)

	// Send disconnect message and stop outgoing
	c.oboundP <- dm

	c.trace_v(CLI, "disconnected")
	c.persist.Close()
}

// Publish will publish a message with the specified QoS
// and content to the specified topic.
// Returns a read only channel used to track
// the delivery of the message.
func (c *MqttClient) Publish(qos QoS, topic string, payload interface{}) <-chan Receipt {
	var pub *Message
	switch payload.(type) {
	case string:
		pub = newPublishMsg(qos, topic, []byte(payload.(string)))
	case []byte:
		pub = newPublishMsg(qos, topic, payload.([]byte))
	default:
		return nil
	}

	r := make(chan Receipt, 1)
	c.trace_v(CLI, "sending publish message, topic: %s", topic)

	select {
	case c.obound <- sendable{pub, r}:
	case <-time.After(time.Second):
		close(r)
	}
	return r
}

// PublishMessage will publish a Message to the specified topic.
// Returns a read only channel used to track
// the delivery of the message.
func (c *MqttClient) PublishMessage(topic string, message *Message) <-chan Receipt {
	// Just reuse pieces from the existing message
	// so that message id etc aren't set
	pub := newPublishMsg(message.QoS(), topic, message.payload)
	pub.SetRetainedFlag(message.RetainedFlag())

	r := make(chan Receipt, 1)

	c.trace_v(CLI, "sending publish message, topic: %s", topic)

	select {
	case c.obound <- sendable{pub, r}:
		return r
	case <-time.After(time.Second):
		close(r)
		return nil
	}
}

// Start a new subscription. Provide a MessageHandler to be executed when
// a message is published on one of the topics provided.
func (c *MqttClient) StartSubscription(callback MessageHandler, filters ...*TopicFilter) (<-chan Receipt, error) {
	if !c.IsConnected() {
		return nil, ErrNotConnected
	}
	c.trace_v(CLI, "enter StartSubscription")
	submsg := newSubscribeMsg(filters...)
	chkcond(submsg != nil)

	if callback != nil {
		for i := range filters {
			c.options.msgRouter.addRoute(filters[i].string, callback)
		}
	}

	r := make(chan Receipt, 1)

	c.obound <- sendable{submsg, r}

	c.trace_v(CLI, "exit StartSubscription")
	return r, nil
}

// EndSubscription will end the subscription from each of the topics provided.
// Messages published to those topics from other clients will no longer be
// received.
func (c *MqttClient) EndSubscription(topics ...string) (<-chan Receipt, error) {
	if !c.IsConnected() {
		return nil, ErrNotConnected
	}
	c.trace_v(CLI, "enter EndSubscription")
	usmsg := newUnsubscribeMsg(topics...)

	r := make(chan Receipt, 1)

	c.obound <- sendable{usmsg, r}
	for _, topic := range topics {
		c.options.msgRouter.deleteRoute(topic)
	}

	c.trace_v(CLI, "exit EndSubscription")
	return r, nil
}
<commit_msg>Closing the connection if client.Start returns an error.<commit_after>/*
 * Copyright (c) 2013 IBM Corp.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Seth Hoenig
 *    Allan Stockdill-Mander
 *    Mike Robertson
 */

// Package mqtt provides an MQTT v3.1 client library.
package mqtt

import (
	"bufio"
	"errors"
	"math/rand"
	"net"
	"sync"
	"time"
)

// MqttClient is a lightweight MQTT v3.1 Client for communicating
// with an MQTT server using non-blocking methods that allow work
// to be done in the background.

// An application may connect to an MQTT server using:
//   A plain TCP socket
//   A secure SSL/TLS socket
//   A websocket

// To enable ensured message delivery at Quality of Service (QoS) levels
// described in the MQTT spec, a message persistence mechanism must be
// used. This is done by providing a type which implements the Store
// interface. For convenience, FileStore and MemoryStore are provided
// implementations that should be sufficient for most use cases. More
// information can be found in their respective documentation.

// Numerous connection options may be specified by configuring a
// and then supplying a ClientOptions type.
type MqttClient struct {
	sync.RWMutex
	conn            net.Conn
	bufferedConn    *bufio.ReadWriter
	ibound          chan *Message
	obound          chan sendable
	oboundP         chan *Message
	begin           chan ConnRC
	errors          chan error
	stop            chan struct{}
	receipts        *receiptMap
	t               *Tracer
	sessId          uint
	persist         Store
	options         ClientOptions
	lastContact     lastcontact
	pingOutstanding bool
	connected       bool
}

// NewClient will create an MQTT v3.1 client with all of the options specified
// in the provided ClientOptions. The client must have the Start method called
// on it before it may be used. This is to make sure resources (such as a net
// connection) are created before the application is actually ready.
func NewClient(ops *ClientOptions) *MqttClient {
	c := &MqttClient{}
	c.sessId = uint(rand.Int())
	c.sessId = 0
	c.options = *ops

	if c.options.store == nil {
		c.options.store = NewMemoryStore()
	}
	c.persist = c.options.store
	c.connected = false
	return c
}

func (c *MqttClient) IsConnected() bool {
	c.RLock()
	defer c.RUnlock()
	return c.connected
}

// Start will create a connection to the message broker
// If clean session is false, then a slice will
// be returned containing Receipts for all messages
// that were in-flight at the last disconnect.
// If clean session is true, then any existing client
// state will be removed.
func (c *MqttClient) Start() ([]Receipt, error) {

	c.t = &Tracer{
		c.options.tracelevel,
		c.options.tracefile,
		c.options.clientId,
	}

	c.options.store.SetTracer(c.t)

	c.trace_v(CLI, "Start()")

	c1, err1 := openConnection(c.options.server, c.options.tlsconfig)
	if err1 != nil {
		c.trace_w(CLI, "failed to connect to primary broker")
		if c.options.server2 != nil {
			c2, err2 := openConnection(c.options.server2, c.options.tlsconfig)
			if err2 != nil {
				c.trace_w(CLI, "failed to connect to standby broker")
				return nil, err1
			}
			c.conn = c2
			c.trace_v(CLI, "connected to standby broker")
		} else {
			c.trace_w(CLI, "standby broker is not configured")
			return nil, err1
		}
	} else {
		c.conn = c1
		c.trace_v(CLI, "connected to primary broker")
	}

	if c.conn == nil {
		c.trace_e(CLI, "Failed to connect to a broker")
		return nil, errors.New("Failed to connect to a broker")
	}
	c.bufferedConn = bufio.NewReadWriter(bufio.NewReader(c.conn), bufio.NewWriter(c.conn))

	c.persist.Open()
	c.receipts = newReceiptMap()

	c.trace_v(CLI, "about to start generateMsgIds")
	c.options.mids.generateMsgIds()

	c.obound = make(chan sendable)
	c.ibound = make(chan *Message)
	c.oboundP = make(chan *Message)
	c.errors = make(chan error)
	c.stop = make(chan struct{})

	go outgoing(c)
	go alllogic(c)

	cm := newConnectMsgFromOptions(c.options)
	c.trace_v(CLI, "about to write new connect msg")
	c.oboundP <- cm

	rc := connect(c)
	if rc != CONN_ACCEPTED {
		c.trace_c(CLI, "CONNACK was not CONN_ACCEPTED, but rather %s", rc2str(rc))
		// Stop all go routines except outgoing
		close(c.stop)
		c.conn.Close()
		return nil, chkrc(rc)
	}

	c.options.pubChanZero = make(chan *Message, 1000)
	c.options.pubChanOne = make(chan *Message, 1000)
	c.options.pubChanTwo = make(chan *Message, 1000)
	c.options.msgRouter.matchAndDispatch(c.options.pubChanZero, c.options.order, c)
	c.options.msgRouter.matchAndDispatch(c.options.pubChanOne, c.options.order, c)
	c.options.msgRouter.matchAndDispatch(c.options.pubChanTwo, c.options.order, c)

	c.connected = true
	c.trace_v(CLI, "client is connected")

	if c.options.timeout != 0 {
		go keepalive(c)
	}

	// Take care of any messages in the store
	var leftovers []Receipt
	if c.options.cleanses == false {
		leftovers = c.resume()
	} else {
		c.persist.Reset()
	}

	// Do not start incoming until resume has completed
	go incoming(c)

	c.trace_v(CLI, "exit startMqttClient")
	if chkrc(rc) != nil {
		// Cleanup before returning.
		close(c.stop)
		c.conn.Close()
	}
	return leftovers, chkrc(rc)
}

// Disconnect will end the connection with the server, but not before waiting
// the specified number of milliseconds to wait for existing work to be
// completed.
func (c *MqttClient) Disconnect(quiesce uint) {
	if !c.IsConnected() {
		c.trace_w(CLI, "already disconnected")
		return
	}
	c.trace_v(CLI, "disconnecting")
	c.connected = false

	// wait for work to finish, or quiesce time consumed
	end := time.After(time.Duration(quiesce) * time.Millisecond)

	// for now we just wait for the time specified and hope the work is done
	select {
	case <-end:
		c.trace_v(CLI, "quiesce expired, forcing disconnect")
		// case <- other:
		// 	c.trace_v(CLI, "finished processing work, graceful disconnect")
	}
	c.disconnect()
}

// ForceDisconnect will end the connection with the mqtt broker immediately.
func (c *MqttClient) ForceDisconnect() {
	if !c.IsConnected() {
		c.trace_w(CLI, "already disconnected")
		return
	}
	c.trace_v(CLI, "forcefully disconnecting")
	c.disconnect()
}

func (c *MqttClient) disconnect() {
	c.connected = false
	dm := newDisconnectMsg()

	// Stop all go routines except outgoing
	close(c.stop)

	// Send disconnect message and stop outgoing
	c.oboundP <- dm

	c.trace_v(CLI, "disconnected")
	c.persist.Close()
}

// Publish will publish a message with the specified QoS
// and content to the specified topic.
// Returns a read only channel used to track
// the delivery of the message.
func (c *MqttClient) Publish(qos QoS, topic string, payload interface{}) <-chan Receipt {
	var pub *Message
	switch payload.(type) {
	case string:
		pub = newPublishMsg(qos, topic, []byte(payload.(string)))
	case []byte:
		pub = newPublishMsg(qos, topic, payload.([]byte))
	default:
		return nil
	}

	r := make(chan Receipt, 1)
	c.trace_v(CLI, "sending publish message, topic: %s", topic)

	select {
	case c.obound <- sendable{pub, r}:
	case <-time.After(time.Second):
		close(r)
	}
	return r
}

// PublishMessage will publish a Message to the specified topic.
// Returns a read only channel used to track
// the delivery of the message.
func (c *MqttClient) PublishMessage(topic string, message *Message) <-chan Receipt {
	// Just reuse pieces from the existing message
	// so that message id etc aren't set
	pub := newPublishMsg(message.QoS(), topic, message.payload)
	pub.SetRetainedFlag(message.RetainedFlag())

	r := make(chan Receipt, 1)

	c.trace_v(CLI, "sending publish message, topic: %s", topic)

	select {
	case c.obound <- sendable{pub, r}:
		return r
	case <-time.After(time.Second):
		close(r)
		return nil
	}
}

// Start a new subscription. Provide a MessageHandler to be executed when
// a message is published on one of the topics provided.
func (c *MqttClient) StartSubscription(callback MessageHandler, filters ...*TopicFilter) (<-chan Receipt, error) {
	if !c.IsConnected() {
		return nil, ErrNotConnected
	}
	c.trace_v(CLI, "enter StartSubscription")
	submsg := newSubscribeMsg(filters...)
	chkcond(submsg != nil)

	if callback != nil {
		for i := range filters {
			c.options.msgRouter.addRoute(filters[i].string, callback)
		}
	}

	r := make(chan Receipt, 1)

	c.obound <- sendable{submsg, r}

	c.trace_v(CLI, "exit StartSubscription")
	return r, nil
}

// EndSubscription will end the subscription from each of the topics provided.
// Messages published to those topics from other clients will no longer be
// received.
func (c *MqttClient) EndSubscription(topics ...string) (<-chan Receipt, error) {
	if !c.IsConnected() {
		return nil, ErrNotConnected
	}
	c.trace_v(CLI, "enter EndSubscription")
	usmsg := newUnsubscribeMsg(topics...)

	r := make(chan Receipt, 1)

	c.obound <- sendable{usmsg, r}
	for _, topic := range topics {
		c.options.msgRouter.deleteRoute(topic)
	}

	c.trace_v(CLI, "exit EndSubscription")
	return r, nil
}
<|endoftext|>


<commit_before>package cannula

import (
	"fmt"
	"net"
	"net/http"
	"sort"
	"sync"

	"github.com/retailnext/cannula/expvar"
	"github.com/retailnext/cannula/internal/net/http/pprof"
)

var (
	defaultServer = newServer()
)

func Start(listener net.Listener) error {
	httpServer := http.Server{Handler: defaultServer.mux}
	return httpServer.Serve(listener)
}

func HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request)) {
	Handle(pattern, http.HandlerFunc(handler))
}

func Handle(pattern string, handler http.Handler) {
	defaultServer.mux.Handle(pattern, handler)
}

type server struct {
	sync.Mutex
	mux   *http.ServeMux
	paths []string
}

func newServer() *server {
	s := &server{
		mux: http.NewServeMux(),
	}

	s.mux.HandleFunc("/", s.index)

	// install net/http/pprof handlers also
	s.Handle("/debug/pprof/", http.HandlerFunc(pprof.Index))
	s.Handle("/debug/pprof/cmdline", http.HandlerFunc(pprof.Cmdline))
	s.Handle("/debug/pprof/profile", http.HandlerFunc(pprof.Profile))
	s.Handle("/debug/pprof/symbol", http.HandlerFunc(pprof.Symbol))
	s.Handle("/debug/pprof/trace", http.HandlerFunc(pprof.Trace))

	s.Handle("/debug/vars", http.HandlerFunc(expvar.Handler))

	return s
}

func (s *server) index(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusNotFound)
	fmt.Fprintln(w, "Available handlers:")

	s.Lock()
	defer s.Unlock()
	sort.Strings(s.paths)
	for _, path := range s.paths {
		fmt.Fprintln(w, path)
	}
}

func (s *server) Handle(pattern string, handler http.Handler) {
	s.mux.Handle(pattern, handler)

	s.Lock()
	defer s.Unlock()
	s.paths = append(s.paths, pattern)
}
<commit_msg>Make the Start function take a unix socket path.<commit_after>package cannula

import (
	"fmt"
	"net"
	"net/http"
	"os"
	"sort"
	"sync"

	"github.com/retailnext/cannula/expvar"
	"github.com/retailnext/cannula/internal/net/http/pprof"
)

var (
	defaultServer = newServer()
)

// Start listens on the unix socket specified by path and then calls Serve.
func Start(path string) error {
	// cleanup old instances of our domain socket
	os.Remove(path)

	ln, err := net.Listen("unix", path)
	if err != nil {
		return err
	}

	return Serve(ln)
}

// Serve starts serving debug http requests on listener.
func Serve(listener net.Listener) error {
	httpServer := http.Server{Handler: defaultServer.mux}
	return httpServer.Serve(listener)
}

// HandleFunc registers a new debug http.HandlerFunc.
func HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request)) {
	Handle(pattern, http.HandlerFunc(handler))
}

// Handle registers a new debug handler.
func Handle(pattern string, handler http.Handler) {
	defaultServer.mux.Handle(pattern, handler)
}

type server struct {
	sync.Mutex
	mux   *http.ServeMux
	paths []string
}

func newServer() *server {
	s := &server{
		mux: http.NewServeMux(),
	}

	s.mux.HandleFunc("/", s.index)

	// install net/http/pprof handlers also
	s.Handle("/debug/pprof/", http.HandlerFunc(pprof.Index))
	s.Handle("/debug/pprof/cmdline", http.HandlerFunc(pprof.Cmdline))
	s.Handle("/debug/pprof/profile", http.HandlerFunc(pprof.Profile))
	s.Handle("/debug/pprof/symbol", http.HandlerFunc(pprof.Symbol))
	s.Handle("/debug/pprof/trace", http.HandlerFunc(pprof.Trace))

	s.Handle("/debug/vars", http.HandlerFunc(expvar.Handler))

	return s
}

func (s *server) index(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusNotFound)
	fmt.Fprintln(w, "Available handlers:")

	s.Lock()
	defer s.Unlock()
	sort.Strings(s.paths)
	for _, path := range s.paths {
		fmt.Fprintln(w, path)
	}
}

func (s *server) Handle(pattern string, handler http.Handler) {
	s.mux.Handle(pattern, handler)

	s.Lock()
	defer s.Unlock()
	s.paths = append(s.paths, pattern)
}
<|endoftext|>


<commit_before>package sudoku

import (
	"testing"
	"time"
)

func BenchmarkHumanSolve(b *testing.B) {
	for i := 0; i < b.N; i++ {
		grid := NewGrid()
		defer grid.Done()
		grid.Load(TEST_GRID)
		grid.HumanSolve()
	}
}

func TestHumanSolve(t *testing.T) {
	grid := NewGrid()
	defer grid.Done()
	grid.Load(TEST_GRID)

	steps := grid.HumanSolution()

	if steps == nil {
		t.Log("Human solution returned 0 techniques.")
		t.Fail()
	}

	if grid.Solved() {
		t.Log("Human Solutions mutated the grid.")
		t.Fail()
	}

	steps = grid.HumanSolve()
	//TODO: test to make sure that we use a wealth of different techniques. This will require a cooked random for testing.
	if steps == nil {
		t.Log("Human solve returned 0 techniques")
		t.Fail()
	}
	if !grid.Solved() {
		t.Log("Human solve failed to solve the simple grid.")
		t.Fail()
	}

}

func TestHumanSolveWithGuess(t *testing.T) {

	grid := NewGrid()
	defer grid.Done()

	if !grid.LoadFromFile(puzzlePath("harddifficulty.sdk")) {
		t.Fatal("harddifficulty.sdk wasn't loaded")
	}

	steps := grid.HumanSolution()

	if steps == nil {
		t.Fatal("Didn't find a solution to a grid that should have needed a guess")
	}

	foundGuess := false
	for i, step := range steps {
		if step.Technique.Name() == "Guess" {
			foundGuess = true
		}
		step.Apply(grid)
		if grid.Invalid() {
			t.Fatal("A solution with a guess in it got us into an invalid grid state. step", i)
		}
	}

	if !foundGuess {
		t.Error("Solution that should have used guess didn't have any guess.")
	}

	if !grid.Solved() {
		t.Error("A solution with a guess said it should solve the puzzle, but it didn't.")
	}

}

func TestStepsDescription(t *testing.T) {

	grid := NewGrid()
	defer grid.Done()

	//It's really brittle that we load techniques in this way... it changes every time we add a new early technique!
	steps := SolveDirections{
		&SolveStep{
			CellList{
				grid.Cell(0, 0),
			},
			nil,
			IntSlice{1},
			nil,
			Techniques[3],
		},
		&SolveStep{
			CellList{
				grid.Cell(1, 0),
				grid.Cell(1, 1),
			},
			CellList{
				grid.Cell(1, 3),
				grid.Cell(1, 4),
			},
			IntSlice{1, 2},
			nil,
			Techniques[8],
		},
		&SolveStep{
			CellList{
				grid.Cell(2, 0),
			},
			nil,
			IntSlice{2},
			nil,
			Techniques[3],
		},
	}

	descriptions := steps.Description()

	GOLDEN_DESCRIPTIONS := []string{
		"First, we put 1 in cell (0,0) because 1 is the only remaining valid number for that cell.",
		"Next, we remove the possibilities 1 and 2 from cells (1,0) and (1,1) because 1 is only possible in column 0 of block 1, which means it can't be in any other cell in that column not in that block.",
		"Finally, we put 2 in cell (2,0) because 2 is the only remaining valid number for that cell.",
	}

	for i := 0; i < len(GOLDEN_DESCRIPTIONS); i++ {
		if descriptions[i] != GOLDEN_DESCRIPTIONS[i] {
			t.Log("Got wrong human solve description: ", descriptions[i])
			t.Fail()
		}
	}
}

func TestPuzzleDifficulty(t *testing.T) {
	grid := NewGrid()
	defer grid.Done()
	grid.Load(TEST_GRID)

	//We use the cheaper one for testing so it completes faster.
	difficulty := grid.calcluateDifficulty(false)

	if grid.Solved() {
		t.Log("Difficulty shouldn't have changed the underlying grid, but it did.")
		t.Fail()
	}

	if difficulty < 0.0 || difficulty > 1.0 {
		t.Log("The grid's difficulty was outside of allowed bounds.")
		t.Fail()
	}

	puzzleFilenames := []string{"harddifficulty.sdk", "harddifficulty2.sdk"}

	for _, filename := range puzzleFilenames {
		puzzleDifficultyHelper(filename, t)
	}
}

func puzzleDifficultyHelper(filename string, t *testing.T) {
	otherGrid := NewGrid()
	if !otherGrid.LoadFromFile(puzzlePath(filename)) {
		t.Log("Whoops, couldn't load the file to test:", filename)
		t.Fail()
	}

	after := time.After(time.Second * 60)

	done := make(chan bool)

	go func() {
		//We use the cheaper one for testing so it completes faster
		_ = otherGrid.calcluateDifficulty(false)
		done <- true
	}()

	select {
	case <-done:
		//totally fine.
	case <-after:
		//Uh oh.
		t.Log("We never finished solving the hard difficulty puzzle: ", filename)
		t.Fail()
	}
}
<commit_msg>Implemented a test for TweakChainedSolveSteps<commit_after>package sudoku

import (
	"testing"
	"time"
)

func BenchmarkHumanSolve(b *testing.B) {
	for i := 0; i < b.N; i++ {
		grid := NewGrid()
		defer grid.Done()
		grid.Load(TEST_GRID)
		grid.HumanSolve()
	}
}

func TestHumanSolve(t *testing.T) {
	grid := NewGrid()
	defer grid.Done()
	grid.Load(TEST_GRID)

	steps := grid.HumanSolution()

	if steps == nil {
		t.Log("Human solution returned 0 techniques.")
		t.Fail()
	}

	if grid.Solved() {
		t.Log("Human Solutions mutated the grid.")
		t.Fail()
	}

	steps = grid.HumanSolve()
	//TODO: test to make sure that we use a wealth of different techniques. This will require a cooked random for testing.
	if steps == nil {
		t.Log("Human solve returned 0 techniques")
		t.Fail()
	}
	if !grid.Solved() {
		t.Log("Human solve failed to solve the simple grid.")
		t.Fail()
	}

}

func TestHumanSolveWithGuess(t *testing.T) {

	grid := NewGrid()
	defer grid.Done()

	if !grid.LoadFromFile(puzzlePath("harddifficulty.sdk")) {
		t.Fatal("harddifficulty.sdk wasn't loaded")
	}

	steps := grid.HumanSolution()

	if steps == nil {
		t.Fatal("Didn't find a solution to a grid that should have needed a guess")
	}

	foundGuess := false
	for i, step := range steps {
		if step.Technique.Name() == "Guess" {
			foundGuess = true
		}
		step.Apply(grid)
		if grid.Invalid() {
			t.Fatal("A solution with a guess in it got us into an invalid grid state. step", i)
		}
	}

	if !foundGuess {
		t.Error("Solution that should have used guess didn't have any guess.")
	}

	if !grid.Solved() {
		t.Error("A solution with a guess said it should solve the puzzle, but it didn't.")
	}

}

func TestStepsDescription(t *testing.T) {

	grid := NewGrid()
	defer grid.Done()

	//It's really brittle that we load techniques in this way... it changes every time we add a new early technique!
	steps := SolveDirections{
		&SolveStep{
			CellList{
				grid.Cell(0, 0),
			},
			nil,
			IntSlice{1},
			nil,
			Techniques[3],
		},
		&SolveStep{
			CellList{
				grid.Cell(1, 0),
				grid.Cell(1, 1),
			},
			CellList{
				grid.Cell(1, 3),
				grid.Cell(1, 4),
			},
			IntSlice{1, 2},
			nil,
			Techniques[8],
		},
		&SolveStep{
			CellList{
				grid.Cell(2, 0),
			},
			nil,
			IntSlice{2},
			nil,
			Techniques[3],
		},
	}

	descriptions := steps.Description()

	GOLDEN_DESCRIPTIONS := []string{
		"First, we put 1 in cell (0,0) because 1 is the only remaining valid number for that cell.",
		"Next, we remove the possibilities 1 and 2 from cells (1,0) and (1,1) because 1 is only possible in column 0 of block 1, which means it can't be in any other cell in that column not in that block.",
		"Finally, we put 2 in cell (2,0) because 2 is the only remaining valid number for that cell.",
	}

	for i := 0; i < len(GOLDEN_DESCRIPTIONS); i++ {
		if descriptions[i] != GOLDEN_DESCRIPTIONS[i] {
			t.Log("Got wrong human solve description: ", descriptions[i])
			t.Fail()
		}
	}
}

//TODO: this is useful. Should we use this in other tests?
func cellRefsToCells(refs []cellRef, grid *Grid) CellList {
	var result CellList
	for _, ref := range refs {
		result = append(result, ref.Cell(grid))
	}
	return result
}

func TestTweakChainedStepsWeights(t *testing.T) {

	//TODO: test other, harder cases as well.
	grid := NewGrid()
	lastStep := &SolveStep{
		cellRefsToCells([]cellRef{
			{0, 0},
		}, grid),
		nil,
		nil,
		nil,
		nil,
	}
	possibilities := []*SolveStep{
		&SolveStep{
			cellRefsToCells([]cellRef{
				{1, 0},
			}, grid),
			nil,
			nil,
			nil,
			nil,
		},
		&SolveStep{
			cellRefsToCells([]cellRef{
				{7, 7},
			}, grid),
			nil,
			nil,
			nil,
			nil,
		},
	}
	weights := []float64{
		10.0,
		10.0,
	}
	tweakRelatedStepsWeights(lastStep, possibilities, weights)

	if weights[0] >= weights[1] {
		t.Error("Tweak Chained Steps Weights didn't tweak things in the right direction: ", weights)
	}
}

func TestPuzzleDifficulty(t *testing.T) {
	grid := NewGrid()
	defer grid.Done()
	grid.Load(TEST_GRID)

	//We use the cheaper one for testing so it completes faster.
	difficulty := grid.calcluateDifficulty(false)

	if grid.Solved() {
		t.Log("Difficulty shouldn't have changed the underlying grid, but it did.")
		t.Fail()
	}

	if difficulty < 0.0 || difficulty > 1.0 {
		t.Log("The grid's difficulty was outside of allowed bounds.")
		t.Fail()
	}

	puzzleFilenames := []string{"harddifficulty.sdk", "harddifficulty2.sdk"}

	for _, filename := range puzzleFilenames {
		puzzleDifficultyHelper(filename, t)
	}
}

func puzzleDifficultyHelper(filename string, t *testing.T) {
	otherGrid := NewGrid()
	if !otherGrid.LoadFromFile(puzzlePath(filename)) {
		t.Log("Whoops, couldn't load the file to test:", filename)
		t.Fail()
	}

	after := time.After(time.Second * 60)

	done := make(chan bool)

	go func() {
		//We use the cheaper one for testing so it completes faster
		_ = otherGrid.calcluateDifficulty(false)
		done <- true
	}()

	select {
	case <-done:
		//totally fine.
	case <-after:
		//Uh oh.
		t.Log("We never finished solving the hard difficulty puzzle: ", filename)
		t.Fail()
	}
}
<|endoftext|>


<commit_before>package router

import (
	"errors"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"github.com/oursky/skygear/skyerr"
	. "github.com/smartystreets/goconvey/convey"
)

type MockHander struct {
	outputs Response
}

func (m *MockHander) handle(p *Payload, r *Response) {
	r.Result = m.outputs.Result
	return
}

type ErrHandler struct {
	Err skyerr.Error
}

func (h *ErrHandler) handle(p *Payload, r *Response) {
	r.Err = h.Err
}

func TestRouterMap(t *testing.T) {
	mockResp := Response{}
	type exampleResp struct {
		Username string `json:"username"`
	}
	mockResp.Result = exampleResp{
		Username: "example",
	}
	mockHander := MockHander{
		outputs: mockResp,
	}
	r := NewRouter()
	r.Map("mock:map", mockHander.handle)
	var mockJSON = `{
	"action": "mock:map"
}`

	req, _ := http.NewRequest(
		"POST",
		"http://skygear.dev/api/v1",
		strings.NewReader(mockJSON),
	)
	req.Header.Set("Content-Type", "application/json")
	resp := httptest.NewRecorder()
	r.ServeHTTP(resp, req)

	if resp.Header().Get("Content-Type") != "application/json" {
		t.Fatalf("Unexpected Content-Type in header %v", resp.Header().Get("Content-Type"))
	}
	if resp.Body.String() != "{\"result\":{\"username\":\"example\"}}\n" {
		t.Fatalf("Simple map failed %v", resp.Body.String())
	}
}

func TestRouterMapMissing(t *testing.T) {
	mockHander := MockHander{
		outputs: Response{},
	}
	r := NewRouter()
	r.Map("mock:map", mockHander.handle)
	var mockJSON = `{
	"action": "missing"
}`

	req, _ := http.NewRequest(
		"POST",
		"http://skygear.dev/api/v1",
		strings.NewReader(mockJSON),
	)
	req.Header.Set("Content-Type", "application/json")
	resp := httptest.NewRecorder()
	r.ServeHTTP(resp, req)

	expectedBody := `{"error":{"name":"UndefinedOperation","code":117,"message":"route unmatched"}}
`
	if resp.Body.String() != expectedBody {
		t.Fatalf("want resp.Body.String() = %#v, got %#v", expectedBody, resp.Body.String())
	}
}

type getPreprocessor struct {
	Status int
	Err    skyerr.Error
}

func (p *getPreprocessor) Preprocess(payload *Payload, response *Response) int {
	response.Err = p.Err
	return p.Status
}

func TestErrorHandler(t *testing.T) {
	Convey("Router", t, func() {
		r := NewRouter()

		Convey("returns 400 if handler sets Response.Err", func() {
			errHandler := &ErrHandler{
				Err: skyerr.NewError(skyerr.UnexpectedError, "some error"),
			}
			r.Map("mock:handler", errHandler.handle)

			req, _ := http.NewRequest(
				"POST",
				"http://skygear.dev/api/v1",
				strings.NewReader(`{"action": "mock:handler"}`),
			)
			req.Header.Set("Content-Type", "application/json")

			resp := httptest.NewRecorder()

			r.ServeHTTP(resp, req)

			So(resp.Code, ShouldEqual, http.StatusBadRequest)
		})
	})
}

func TestPreprocess(t *testing.T) {
	r := NewRouter()
	mockHandler := MockHander{outputs: Response{
		Result: "ok",
	}}
	mockPreprocessor := getPreprocessor{}

	r.Map("mock:preprocess", mockHandler.handle, mockPreprocessor.Preprocess)

	Convey("Given a router with a preprocessor", t, func() {
		req, _ := http.NewRequest(
			"POST",
			"http://skygear.dev/api/v1",
			strings.NewReader(`{"action": "mock:preprocess"}`),
		)
		req.Header.Set("Content-Type", "application/json")
		resp := httptest.NewRecorder()

		Convey("When preprocessor lets go", func() {
			mockPreprocessor.Status = http.StatusOK
			mockPreprocessor.Err = nil

			r.ServeHTTP(resp, req)

			Convey("it returns ok", func() {
				So(resp.Body.String(), ShouldEqual, "{\"result\":\"ok\"}\n")
			})

			Convey("it has status code = 200", func() {
				So(resp.Code, ShouldEqual, http.StatusOK)
			})
		})

		Convey("When preprocessor gives an err", func() {
			mockPreprocessor.Status = http.StatusInternalServerError
			mockPreprocessor.Err = skyerr.NewError(skyerr.UnexpectedError, "err")

			r.ServeHTTP(resp, req)

			Convey("it has \"err\" as body", func() {
				So(resp.Body.String(), ShouldEqual, `{"error":{"name":"UnexpectedError","code":10000,"message":"err"}}
`)
			})

			Convey("it has status code = 500", func() {
				So(resp.Code, ShouldEqual, http.StatusInternalServerError)
			})
		})

		Convey("When preprocessor gives an skyerr preprocessor", func() {
			mockPreprocessor.Status = http.StatusInternalServerError
			mockPreprocessor.Err = skyerr.NewUnknownErr(errors.New("skyerr"))

			r.ServeHTTP(resp, req)

			Convey("it has \"err\" as body", func() {
				So(resp.Body.String(), ShouldEqual, `{"error":{"name":"UnexpectedError","code":10000,"message":"skyerr"}}
`)
			})

			Convey("it has status code = 500", func() {
				So(resp.Code, ShouldEqual, http.StatusInternalServerError)
			})
		})
	})
}

// TODO(limouren): fix this test case
// func TestRouterCheckAuth(t *testing.T) {
// 	mockResp := Response{}
// 	type exampleResp struct {
// 		Auth string `json:"auth"`
// 	}
// 	mockResp.Result = exampleResp{
// 		Auth: "ok",
// 	}
// 	mockHander := MockHander{
// 		outputs: mockResp,
// 	}
// 	r := NewRouter()
// 	r.Map("mock:map", mockHander.handle)
// 	r.Preprocess(CheckAuth)

// 	// Positive test
// 	var mockJSON = `{
// 	"action": "mock:map",
// 	"access_token": "validToken"
// }`

// 	req, _ := http.NewRequest(
// 		"POST",
// 		"http://skygear.dev/api/v1",
// 		strings.NewReader(mockJSON),
// 	)
// 	req.Header.Set("Content-Type", "application/json")
// 	resp := httptest.NewRecorder()
// 	r.ServeHTTP(resp, req)

// 	if resp.Body.String() != "{\"result\":{\"auth\":\"ok\"}}" {
// 		t.Fatalf("CheckAuth failed: %v", resp.Body.String())
// 	}

// 	// Negative test
// 	var mockJSON2 = `{
// 	"action": "mock:map",
// 	"access_token": "InValidToken"
// }`

// 	req2, _ := http.NewRequest(
// 		"POST",
// 		"http://skygear.dev/api/v1",
// 		strings.NewReader(mockJSON2),
// 	)
// 	req2.Header.Set("Content-Type", "application/json")
// 	resp2 := httptest.NewRecorder()
// 	r.ServeHTTP(resp2, req2)

// 	if resp2.Body.String() != "Unauthorized request" {
// 		t.Fatalf(
// 			"CheckAuth failed to reject unauthorized request: %v",
// 			resp2.Body.String())
// 	}
// }
<commit_msg>Use ShouldEqualJSON in tests to compare response<commit_after>package router

import (
	"errors"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"github.com/oursky/skygear/skyerr"
	. "github.com/oursky/skygear/skytest"
	. "github.com/smartystreets/goconvey/convey"
)

type MockHander struct {
	outputs Response
}

func (m *MockHander) handle(p *Payload, r *Response) {
	r.Result = m.outputs.Result
	return
}

type ErrHandler struct {
	Err skyerr.Error
}

func (h *ErrHandler) handle(p *Payload, r *Response) {
	r.Err = h.Err
}

func TestRouterMap(t *testing.T) {
	mockResp := Response{}
	type exampleResp struct {
		Username string `json:"username"`
	}
	mockResp.Result = exampleResp{
		Username: "example",
	}
	mockHander := MockHander{
		outputs: mockResp,
	}
	r := NewRouter()
	r.Map("mock:map", mockHander.handle)
	var mockJSON = `{
	"action": "mock:map"
}`

	req, _ := http.NewRequest(
		"POST",
		"http://skygear.dev/api/v1",
		strings.NewReader(mockJSON),
	)
	req.Header.Set("Content-Type", "application/json")
	resp := httptest.NewRecorder()
	r.ServeHTTP(resp, req)

	if resp.Header().Get("Content-Type") != "application/json" {
		t.Fatalf("Unexpected Content-Type in header %v", resp.Header().Get("Content-Type"))
	}
	if resp.Body.String() != "{\"result\":{\"username\":\"example\"}}\n" {
		t.Fatalf("Simple map failed %v", resp.Body.String())
	}
}

func TestRouterMapMissing(t *testing.T) {
	mockHander := MockHander{
		outputs: Response{},
	}
	r := NewRouter()
	r.Map("mock:map", mockHander.handle)
	var mockJSON = `{
	"action": "missing"
}`

	req, _ := http.NewRequest(
		"POST",
		"http://skygear.dev/api/v1",
		strings.NewReader(mockJSON),
	)
	req.Header.Set("Content-Type", "application/json")
	resp := httptest.NewRecorder()
	r.ServeHTTP(resp, req)

	expectedBody := `{"error":{"name":"UndefinedOperation","code":117,"message":"route unmatched"}}
`
	if resp.Body.String() != expectedBody {
		t.Fatalf("want resp.Body.String() = %#v, got %#v", expectedBody, resp.Body.String())
	}
}

type getPreprocessor struct {
	Status int
	Err    skyerr.Error
}

func (p *getPreprocessor) Preprocess(payload *Payload, response *Response) int {
	response.Err = p.Err
	return p.Status
}

func TestErrorHandler(t *testing.T) {
	Convey("Router", t, func() {
		r := NewRouter()

		Convey("returns 400 if handler sets Response.Err", func() {
			errHandler := &ErrHandler{
				Err: skyerr.NewError(skyerr.UnexpectedError, "some error"),
			}
			r.Map("mock:handler", errHandler.handle)

			req, _ := http.NewRequest(
				"POST",
				"http://skygear.dev/api/v1",
				strings.NewReader(`{"action": "mock:handler"}`),
			)
			req.Header.Set("Content-Type", "application/json")

			resp := httptest.NewRecorder()

			r.ServeHTTP(resp, req)

			So(resp.Code, ShouldEqual, http.StatusBadRequest)
		})
	})
}

func TestPreprocess(t *testing.T) {
	r := NewRouter()
	mockHandler := MockHander{outputs: Response{
		Result: "ok",
	}}
	mockPreprocessor := getPreprocessor{}

	r.Map("mock:preprocess", mockHandler.handle, mockPreprocessor.Preprocess)

	Convey("Given a router with a preprocessor", t, func() {
		req, _ := http.NewRequest(
			"POST",
			"http://skygear.dev/api/v1",
			strings.NewReader(`{"action": "mock:preprocess"}`),
		)
		req.Header.Set("Content-Type", "application/json")
		resp := httptest.NewRecorder()

		Convey("When preprocessor lets go", func() {
			mockPreprocessor.Status = http.StatusOK
			mockPreprocessor.Err = nil

			r.ServeHTTP(resp, req)

			Convey("it returns ok", func() {
				So(resp.Body.String(), ShouldEqual, "{\"result\":\"ok\"}\n")
			})

			Convey("it has status code = 200", func() {
				So(resp.Code, ShouldEqual, http.StatusOK)
			})
		})

		Convey("When preprocessor gives an err", func() {
			mockPreprocessor.Status = http.StatusInternalServerError
			mockPreprocessor.Err = skyerr.NewError(skyerr.UnexpectedError, "err")

			r.ServeHTTP(resp, req)

			Convey("it has \"err\" as body", func() {
				So(resp.Body.Bytes(), ShouldEqualJSON, `{"error":{"name":"UnexpectedError","code":10000,"message":"err"}}
`)
			})

			Convey("it has status code = 500", func() {
				So(resp.Code, ShouldEqual, http.StatusInternalServerError)
			})
		})

		Convey("When preprocessor gives an skyerr preprocessor", func() {
			mockPreprocessor.Status = http.StatusInternalServerError
			mockPreprocessor.Err = skyerr.NewUnknownErr(errors.New("skyerr"))

			r.ServeHTTP(resp, req)

			Convey("it has \"err\" as body", func() {
				So(resp.Body.Bytes(), ShouldEqualJSON, `{"error":{"name":"UnexpectedError","code":10000,"message":"skyerr"}}
`)
			})

			Convey("it has status code = 500", func() {
				So(resp.Code, ShouldEqual, http.StatusInternalServerError)
			})
		})
	})
}

// TODO(limouren): fix this test case
// func TestRouterCheckAuth(t *testing.T) {
// 	mockResp := Response{}
// 	type exampleResp struct {
// 		Auth string `json:"auth"`
// 	}
// 	mockResp.Result = exampleResp{
// 		Auth: "ok",
// 	}
// 	mockHander := MockHander{
// 		outputs: mockResp,
// 	}
// 	r := NewRouter()
// 	r.Map("mock:map", mockHander.handle)
// 	r.Preprocess(CheckAuth)

// 	// Positive test
// 	var mockJSON = `{
// 	"action": "mock:map",
// 	"access_token": "validToken"
// }`

// 	req, _ := http.NewRequest(
// 		"POST",
// 		"http://skygear.dev/api/v1",
// 		strings.NewReader(mockJSON),
// 	)
// 	req.Header.Set("Content-Type", "application/json")
// 	resp := httptest.NewRecorder()
// 	r.ServeHTTP(resp, req)

// 	if resp.Body.String() != "{\"result\":{\"auth\":\"ok\"}}" {
// 		t.Fatalf("CheckAuth failed: %v", resp.Body.String())
// 	}

// 	// Negative test
// 	var mockJSON2 = `{
// 	"action": "mock:map",
// 	"access_token": "InValidToken"
// }`

// 	req2, _ := http.NewRequest(
// 		"POST",
// 		"http://skygear.dev/api/v1",
// 		strings.NewReader(mockJSON2),
// 	)
// 	req2.Header.Set("Content-Type", "application/json")
// 	resp2 := httptest.NewRecorder()
// 	r.ServeHTTP(resp2, req2)

// 	if resp2.Body.String() != "Unauthorized request" {
// 		t.Fatalf(
// 			"CheckAuth failed to reject unauthorized request: %v",
// 			resp2.Body.String())
// 	}
// }
<|endoftext|>


<commit_before>package maptiles

import (
	"log"
	"net/http"
	"regexp"
	"strconv"
	"strings"
	"encoding/json"
	// "database/sql"
	// "fmt"
	// "os"

	// _ "github.com/mattn/go-sqlite3"
)

// TODO serve list of registered layers per HTTP (preferably leafletjs-compatible js-array)

// Handles HTTP requests for map tiles, caching any produced tiles
// in an MBtiles 1.2 compatible sqlite db.
type TileServer struct {
	m         *TileDb
	lmp       *LayerMultiplex
	TmsSchema bool
}

func NewTileServer(cacheFile string) *TileServer {
	t := TileServer{}
	t.lmp = NewLayerMultiplex()
	t.m = NewTileDb(cacheFile)

	return &t
}

func (t *TileServer) AddMapnikLayer(layerName string, stylesheet string) {
	t.lmp.AddRenderer(layerName, stylesheet)
}

var pathRegex = regexp.MustCompile(`/([A-Za-z0-9]+)/([0-9]+)/([0-9]+)/([0-9]+)\.png`)

func (t *TileServer) ServeTileRequest(w http.ResponseWriter, r *http.Request, tc TileCoord) {
	log.Println(r.RemoteAddr, tc)
	ch := make(chan TileFetchResult)

	tr := TileFetchRequest{tc, ch}
	t.m.RequestQueue() <- tr

	result := <-ch
	needsInsert := false

	if result.BlobPNG == nil {
		// Tile was not provided by DB, so submit the tile request to the renderer
		t.lmp.SubmitRequest(tr)
		result = <-ch
		if result.BlobPNG == nil {
			// The tile could not be rendered, now we need to bail out.
			http.NotFound(w, r)
			return
		}
		needsInsert = true
	}

	w.Header().Set("Content-Type", "image/png")
	_, err := w.Write(result.BlobPNG)
	if err != nil {
		log.Println(err)
	}
	if needsInsert {
		t.m.InsertQueue() <- result // insert newly rendered tile into cache db
	}
}

func (t *TileServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {

	log.Println(r.RemoteAddr, r.URL.Path)

	if r.URL.Path == "/" {
		w.Header().Set("Content-Type", "application/json")
		w.Header().Set("Access-Control-Allow-Origin", "*")

		response_wrapper := make(map[string]interface{})
		response_wrapper["status"] = "ok"
		response_wrapper["data"] = make(map[string]interface{})
		response_wrapper["data"]["message"] = "Hello!"

		js, err := json.Marshal(response_wrapper)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		w.Write(js)
		return;
	} else if strings.Contains(r.URL.Path, "metadata") {
		// todo: include layer
		metadata := t.m.MetaDataHandler()
		w.Header().Set("Content-Type", "application/json")
		w.Header().Set("Access-Control-Allow-Origin", "*")

		response_wrapper := make(map[string]interface{})
		response_wrapper["status"] = "ok"
		response_wrapper["data"] = metadata

		js, err := json.Marshal(response_wrapper)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		w.Write(js)
		return;
	}

	path := pathRegex.FindStringSubmatch(r.URL.Path)

	if path == nil {
		http.NotFound(w, r)
		return
	}

	l := path[1]
	z, _ := strconv.ParseUint(path[2], 10, 64)
	x, _ := strconv.ParseUint(path[3], 10, 64)
	y, _ := strconv.ParseUint(path[4], 10, 64)

	t.ServeTileRequest(w, r, TileCoord{x, y, z, t.TmsSchema, l})
}

// func (t *TileServer) MetaDataHandler(w http.ResponseWriter, r *http.Request) {
// 	// Set headers
// 	w.Header().Set("Content-Type", "application/json")
// 	w.Header().Set("Access-Control-Allow-Origin", "*")

// 	// Get params
// 	vars := mux.Vars(r)
// 	dbname := vars["db"]

// 	// check for file
// 	if _, err := os.Stat(dbname+".mbtiles"); os.IsNotExist(err) {
// 		fmt.Println("File not found [" + dbname + ".mbtiles]")
// 		http.Error(w, err.Error(), http.StatusNotFound)
// 		return
// 	}

// 	// Open database
// 	db, _ := sql.Open("sqlite3", "./"+dbname+".mbtiles")
// 	rows, _ := db.Query("SELECT * FROM metadata")

// 	metadata :=  make(map[string]string)

// 	for rows.Next() {

// 		var name string
// 		var value string
// 		rows.Scan(&name, &value)

// 		metadata[name] = value
// 	}

// 	db.Close()

// 	response_wrapper := make(map[string]interface{})
// 	response_wrapper["status"] = "success"
// 	response_wrapper["data"] = metadata

// 	js, err := json.Marshal(response_wrapper)
// 	if err != nil {
// 		http.Error(w, err.Error(), http.StatusInternalServerError)
// 		return
// 	}

// 	w.Write(js)

// }
<commit_msg>tile server logging<commit_after>package maptiles

import (
	"log"
	"net/http"
	"regexp"
	"strconv"
	"strings"
	"encoding/json"
	// "database/sql"
	// "fmt"
	// "os"

	// _ "github.com/mattn/go-sqlite3"
)

// TODO serve list of registered layers per HTTP (preferably leafletjs-compatible js-array)

// Handles HTTP requests for map tiles, caching any produced tiles
// in an MBtiles 1.2 compatible sqlite db.
type TileServer struct {
	m         *TileDb
	lmp       *LayerMultiplex
	TmsSchema bool
}

func NewTileServer(cacheFile string) *TileServer {
	t := TileServer{}
	t.lmp = NewLayerMultiplex()
	t.m = NewTileDb(cacheFile)

	return &t
}

func (t *TileServer) AddMapnikLayer(layerName string, stylesheet string) {
	t.lmp.AddRenderer(layerName, stylesheet)
}

var pathRegex = regexp.MustCompile(`/([A-Za-z0-9]+)/([0-9]+)/([0-9]+)/([0-9]+)\.png`)

func (t *TileServer) ServeTileRequest(w http.ResponseWriter, r *http.Request, tc TileCoord) {
	log.Println(r.RemoteAddr, tc)
	ch := make(chan TileFetchResult)

	tr := TileFetchRequest{tc, ch}
	t.m.RequestQueue() <- tr

	result := <-ch
	needsInsert := false

	if result.BlobPNG == nil {
		// Tile was not provided by DB, so submit the tile request to the renderer
		t.lmp.SubmitRequest(tr)
		result = <-ch
		if result.BlobPNG == nil {
			// The tile could not be rendered, now we need to bail out.
			http.NotFound(w, r)
			return
		}
		needsInsert = true
	}

	w.Header().Set("Content-Type", "image/png")
	_, err := w.Write(result.BlobPNG)
	if err != nil {
		log.Println(err)
	}
	if needsInsert {
		t.m.InsertQueue() <- result // insert newly rendered tile into cache db
	}
}

func (t *TileServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {

	log.Println(r.RemoteAddr, r.URL.Path)

	if r.URL.Path == "/" {
		w.Header().Set("Content-Type", "application/json")
		w.Header().Set("Access-Control-Allow-Origin", "*")

		response_wrapper := make(map[string]interface{})
		response_wrapper["status"] = "ok"
		// response_wrapper["data"] = make(map[string]interface{})
		// response_wrapper["data"]["message"] = "Hello!"
		response_wrapper["data"] = `{"message":"Hello!"}`

		js, err := json.Marshal(response_wrapper)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		w.Write(js)
		return;
	} else if strings.Contains(r.URL.Path, "metadata") {
		// todo: include layer
		metadata := t.m.MetaDataHandler()
		w.Header().Set("Content-Type", "application/json")
		w.Header().Set("Access-Control-Allow-Origin", "*")

		response_wrapper := make(map[string]interface{})
		response_wrapper["status"] = "ok"
		response_wrapper["data"] = metadata

		js, err := json.Marshal(response_wrapper)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		w.Write(js)
		return;
	}

	path := pathRegex.FindStringSubmatch(r.URL.Path)

	if path == nil {
		http.NotFound(w, r)
		return
	}

	l := path[1]
	z, _ := strconv.ParseUint(path[2], 10, 64)
	x, _ := strconv.ParseUint(path[3], 10, 64)
	y, _ := strconv.ParseUint(path[4], 10, 64)

	t.ServeTileRequest(w, r, TileCoord{x, y, z, t.TmsSchema, l})
}

// func (t *TileServer) MetaDataHandler(w http.ResponseWriter, r *http.Request) {
// 	// Set headers
// 	w.Header().Set("Content-Type", "application/json")
// 	w.Header().Set("Access-Control-Allow-Origin", "*")

// 	// Get params
// 	vars := mux.Vars(r)
// 	dbname := vars["db"]

// 	// check for file
// 	if _, err := os.Stat(dbname+".mbtiles"); os.IsNotExist(err) {
// 		fmt.Println("File not found [" + dbname + ".mbtiles]")
// 		http.Error(w, err.Error(), http.StatusNotFound)
// 		return
// 	}

// 	// Open database
// 	db, _ := sql.Open("sqlite3", "./"+dbname+".mbtiles")
// 	rows, _ := db.Query("SELECT * FROM metadata")

// 	metadata :=  make(map[string]string)

// 	for rows.Next() {

// 		var name string
// 		var value string
// 		rows.Scan(&name, &value)

// 		metadata[name] = value
// 	}

// 	db.Close()

// 	response_wrapper := make(map[string]interface{})
// 	response_wrapper["status"] = "success"
// 	response_wrapper["data"] = metadata

// 	js, err := json.Marshal(response_wrapper)
// 	if err != nil {
// 		http.Error(w, err.Error(), http.StatusInternalServerError)
// 		return
// 	}

// 	w.Write(js)

// }
<|endoftext|>


<commit_before>// Copyright 2017 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 expression

import (
	"encoding/hex"
	"strings"

	. "github.com/pingcap/check"
	"github.com/pingcap/tidb/ast"
	"github.com/pingcap/tidb/util/hack"
	"github.com/pingcap/tidb/util/testleak"
	"github.com/pingcap/tidb/util/types"
)

var aesCases = []struct {
	origin interface{}
	key    interface{}
	crypt  interface{}
}{
	{"pingcap", "1234567890123456", "697BFE9B3F8C2F289DD82C88C7BC95C4"},
	{"pingcap123", "1234567890123456", "CEC348F4EF5F84D3AA6C4FA184C65766"},
	{"pingcap", "123456789012345678901234", "6F1589686860C8E8C7A40A78B25FF2C0"},
	{"pingcap", "123", "996E0CA8688D7AD20819B90B273E01C6"},
	{"pingcap", 123, "996E0CA8688D7AD20819B90B273E01C6"},
	{nil, 123, nil},
}

func (s *testEvaluatorSuite) TestAESEncrypt(c *C) {
	defer testleak.AfterTest(c)()
	fc := funcs[ast.AesEncrypt]
	for _, test := range aesCases {
		str := types.NewDatum(test.origin)
		key := types.NewDatum(test.key)
		f, err := fc.getFunction(datumsToConstants([]types.Datum{str, key}), s.ctx)
		crypt, err := f.eval(nil)
		c.Assert(err, IsNil)
		c.Assert(toHex(crypt), DeepEquals, types.NewDatum(test.crypt))
	}
	s.testNullInput(c, ast.AesDecrypt)
}

func (s *testEvaluatorSuite) TestAESDecrypt(c *C) {
	defer testleak.AfterTest(c)()
	fc := funcs[ast.AesDecrypt]
	for _, test := range aesCases {
		cryptStr := fromHex(test.crypt)
		key := types.NewDatum(test.key)
		f, err := fc.getFunction(datumsToConstants([]types.Datum{cryptStr, key}), s.ctx)
		str, err := f.eval(nil)
		c.Assert(err, IsNil)
		c.Assert(str, DeepEquals, types.NewDatum(test.origin))
	}
	s.testNullInput(c, ast.AesDecrypt)
}

func (s *testEvaluatorSuite) testNullInput(c *C, fnName string) {
	fc := funcs[fnName]
	arg := types.NewStringDatum("str")
	var argNull types.Datum
	f, err := fc.getFunction(datumsToConstants([]types.Datum{arg, argNull}), s.ctx)
	crypt, err := f.eval(nil)
	c.Assert(err, IsNil)
	c.Assert(crypt.IsNull(), IsTrue)

	f, err = fc.getFunction(datumsToConstants([]types.Datum{argNull, arg}), s.ctx)
	crypt, err = f.eval(nil)
	c.Assert(err, IsNil)
	c.Assert(crypt.IsNull(), IsTrue)
}

func toHex(d types.Datum) (h types.Datum) {
	if d.IsNull() {
		return
	}
	x, _ := d.ToString()
	h.SetString(strings.ToUpper(hex.EncodeToString(hack.Slice(x))))
	return
}

func fromHex(str interface{}) (d types.Datum) {
	if str == nil {
		return
	}
	if s, ok := str.(string); ok {
		h, _ := hex.DecodeString(s)
		d.SetBytes(h)
	}
	return d
}

var shaCases = []struct {
	origin interface{}
	crypt  string
}{
	{"test", "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3"},
	{"c4pt0r", "034923dcabf099fc4c8917c0ab91ffcd4c2578a6"},
	{"pingcap", "73bf9ef43a44f42e2ea2894d62f0917af149a006"},
	{"foobar", "8843d7f92416211de9ebb963ff4ce28125932878"},
	{1024, "128351137a9c47206c4507dcf2e6fbeeca3a9079"},
	{123.45, "22f8b438ad7e89300b51d88684f3f0b9fa1d7a32"},
}

func (s *testEvaluatorSuite) TestShaEncrypt(c *C) {
	defer testleak.AfterTest(c)()
	fc := funcs[ast.SHA]
	for _, test := range shaCases {
		in := types.NewDatum(test.origin)
		f, _ := fc.getFunction(datumsToConstants([]types.Datum{in}), s.ctx)
		crypt, err := f.eval(nil)
		c.Assert(err, IsNil)
		res, err := crypt.ToString()
		c.Assert(err, IsNil)
		c.Assert(res, Equals, test.crypt)
	}
	// test NULL input for sha
	var argNull types.Datum
	f, _ := fc.getFunction(datumsToConstants([]types.Datum{argNull}), s.ctx)
	crypt, err := f.eval(nil)
	c.Assert(err, IsNil)
	c.Assert(crypt.IsNull(), IsTrue)
}

type md5Test struct {
	out interface{}
	in  interface{}
}

var md5Cases = []md5Test{
	{"d41d8cd98f00b204e9800998ecf8427e", ""},
	{"0cc175b9c0f1b6a831c399e269772661", "a"},
	{"187ef4436122d1cc2f40dc2b92f0eba0", "ab"},
	{"900150983cd24fb0d6963f7d28e17f72", "abc"},
	{"202cb962ac59075b964b07152d234b70", 123},
	{"202cb962ac59075b964b07152d234b70", "123"},
	{"46ddc40585caa8abc07c460b3485781e", 123.123},
	{nil, nil},
}

func (s *testEvaluatorSuite) TestMD5(c *C) {
	defer testleak.AfterTest(c)()
	fc := funcs[ast.MD5]
	for _, test := range md5Cases {
		arg := types.NewDatum(test.in)
		f, err := fc.getFunction(datumsToConstants([]types.Datum{arg}), s.ctx)
		c.Assert(err, IsNil)
		out, err := f.eval(nil)
		c.Assert(err, IsNil)
		c.Assert(out, DeepEquals, types.NewDatum(test.out))
	}
	s.testNullInput(c, ast.AesDecrypt)
}

type compressTest struct {
	in  interface{}
	out interface{}
}

var compressCases = []compressTest{
	{[]byte("hello world"), []byte{120, 156, 202, 72, 205, 201, 201, 87, 40, 207, 47, 202, 73, 1, 4, 0, 0, 255, 255, 26, 11, 4, 93}},
	{[]byte("i love you)"), []byte{120, 156, 202, 84, 200, 201, 47, 75, 85, 168, 204, 47, 213, 4, 4, 0, 0, 255, 255, 23, 142, 3, 230}},
	{nil, nil},
}

func (s *testEvaluatorSuite) TestCompress(c *C) {
	defer testleak.AfterTest(c)()
	fc := funcs[ast.Compress]
	for _, test := range compressCases {
		arg := types.NewDatum(test.in)
		f, err := fc.getFunction(datumsToConstants([]types.Datum{arg}), s.ctx)
		c.Assert(err, IsNil)
		out, err := f.eval(nil)
		c.Assert(err, IsNil)
		c.Assert(out, DeepEquals, types.NewDatum(test.out))
	}
	var argNull types.Datum
	f, _ := fc.getFunction(datumsToConstants([]types.Datum{argNull}), s.ctx)
	compress, err := f.eval(nil)
	c.Assert(err, IsNil)
	c.Assert(compress.IsNull(), IsTrue)
<commit_msg>Update builtin_encryption_test.go<commit_after>// Copyright 2017 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 expression

import (
	"encoding/hex"
	"strings"

	. "github.com/pingcap/check"
	"github.com/pingcap/tidb/ast"
	"github.com/pingcap/tidb/util/hack"
	"github.com/pingcap/tidb/util/testleak"
	"github.com/pingcap/tidb/util/types"
)

var aesCases = []struct {
	origin interface{}
	key    interface{}
	crypt  interface{}
}{
	{"pingcap", "1234567890123456", "697BFE9B3F8C2F289DD82C88C7BC95C4"},
	{"pingcap123", "1234567890123456", "CEC348F4EF5F84D3AA6C4FA184C65766"},
	{"pingcap", "123456789012345678901234", "6F1589686860C8E8C7A40A78B25FF2C0"},
	{"pingcap", "123", "996E0CA8688D7AD20819B90B273E01C6"},
	{"pingcap", 123, "996E0CA8688D7AD20819B90B273E01C6"},
	{nil, 123, nil},
}

func (s *testEvaluatorSuite) TestAESEncrypt(c *C) {
	defer testleak.AfterTest(c)()
	fc := funcs[ast.AesEncrypt]
	for _, test := range aesCases {
		str := types.NewDatum(test.origin)
		key := types.NewDatum(test.key)
		f, err := fc.getFunction(datumsToConstants([]types.Datum{str, key}), s.ctx)
		crypt, err := f.eval(nil)
		c.Assert(err, IsNil)
		c.Assert(toHex(crypt), DeepEquals, types.NewDatum(test.crypt))
	}
	s.testNullInput(c, ast.AesDecrypt)
}

func (s *testEvaluatorSuite) TestAESDecrypt(c *C) {
	defer testleak.AfterTest(c)()
	fc := funcs[ast.AesDecrypt]
	for _, test := range aesCases {
		cryptStr := fromHex(test.crypt)
		key := types.NewDatum(test.key)
		f, err := fc.getFunction(datumsToConstants([]types.Datum{cryptStr, key}), s.ctx)
		str, err := f.eval(nil)
		c.Assert(err, IsNil)
		c.Assert(str, DeepEquals, types.NewDatum(test.origin))
	}
	s.testNullInput(c, ast.AesDecrypt)
}

func (s *testEvaluatorSuite) testNullInput(c *C, fnName string) {
	fc := funcs[fnName]
	arg := types.NewStringDatum("str")
	var argNull types.Datum
	f, err := fc.getFunction(datumsToConstants([]types.Datum{arg, argNull}), s.ctx)
	crypt, err := f.eval(nil)
	c.Assert(err, IsNil)
	c.Assert(crypt.IsNull(), IsTrue)

	f, err = fc.getFunction(datumsToConstants([]types.Datum{argNull, arg}), s.ctx)
	crypt, err = f.eval(nil)
	c.Assert(err, IsNil)
	c.Assert(crypt.IsNull(), IsTrue)
}

func toHex(d types.Datum) (h types.Datum) {
	if d.IsNull() {
		return
	}
	x, _ := d.ToString()
	h.SetString(strings.ToUpper(hex.EncodeToString(hack.Slice(x))))
	return
}

func fromHex(str interface{}) (d types.Datum) {
	if str == nil {
		return
	}
	if s, ok := str.(string); ok {
		h, _ := hex.DecodeString(s)
		d.SetBytes(h)
	}
	return d
}

var shaCases = []struct {
	origin interface{}
	crypt  string
}{
	{"test", "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3"},
	{"c4pt0r", "034923dcabf099fc4c8917c0ab91ffcd4c2578a6"},
	{"pingcap", "73bf9ef43a44f42e2ea2894d62f0917af149a006"},
	{"foobar", "8843d7f92416211de9ebb963ff4ce28125932878"},
	{1024, "128351137a9c47206c4507dcf2e6fbeeca3a9079"},
	{123.45, "22f8b438ad7e89300b51d88684f3f0b9fa1d7a32"},
}

func (s *testEvaluatorSuite) TestShaEncrypt(c *C) {
	defer testleak.AfterTest(c)()
	fc := funcs[ast.SHA]
	for _, test := range shaCases {
		in := types.NewDatum(test.origin)
		f, _ := fc.getFunction(datumsToConstants([]types.Datum{in}), s.ctx)
		crypt, err := f.eval(nil)
		c.Assert(err, IsNil)
		res, err := crypt.ToString()
		c.Assert(err, IsNil)
		c.Assert(res, Equals, test.crypt)
	}
	// test NULL input for sha
	var argNull types.Datum
	f, _ := fc.getFunction(datumsToConstants([]types.Datum{argNull}), s.ctx)
	crypt, err := f.eval(nil)
	c.Assert(err, IsNil)
	c.Assert(crypt.IsNull(), IsTrue)
}

type md5Test struct {
	out interface{}
	in  interface{}
}

var md5Cases = []md5Test{
	{"d41d8cd98f00b204e9800998ecf8427e", ""},
	{"0cc175b9c0f1b6a831c399e269772661", "a"},
	{"187ef4436122d1cc2f40dc2b92f0eba0", "ab"},
	{"900150983cd24fb0d6963f7d28e17f72", "abc"},
	{"202cb962ac59075b964b07152d234b70", 123},
	{"202cb962ac59075b964b07152d234b70", "123"},
	{"46ddc40585caa8abc07c460b3485781e", 123.123},
	{nil, nil},
}

func (s *testEvaluatorSuite) TestMD5(c *C) {
	defer testleak.AfterTest(c)()
	fc := funcs[ast.MD5]
	for _, test := range md5Cases {
		arg := types.NewDatum(test.in)
		f, err := fc.getFunction(datumsToConstants([]types.Datum{arg}), s.ctx)
		c.Assert(err, IsNil)
		out, err := f.eval(nil)
		c.Assert(err, IsNil)
		c.Assert(out, DeepEquals, types.NewDatum(test.out))
	}
	s.testNullInput(c, ast.AesDecrypt)
}

type compressTest struct {
	in  interface{}
	out interface{}
}

var compressCases = []compressTest{
	{[]byte("hello world"), []byte{120, 156, 202, 72, 205, 201, 201, 87, 40, 207, 47, 202, 73, 1, 4, 0, 0, 255, 255, 26, 11, 4, 93}},
	{[]byte("i love you)"), []byte{120, 156, 202, 84, 200, 201, 47, 75, 85, 168, 204, 47, 213, 4, 4, 0, 0, 255, 255, 23, 142, 3, 230}},
	{nil, nil},
}

func (s *testEvaluatorSuite) TestCompress(c *C) {
	defer testleak.AfterTest(c)()
	fc := funcs[ast.Compress]
	for _, test := range compressCases {
		arg := types.NewDatum(test.in)
		f, err := fc.getFunction(datumsToConstants([]types.Datum{arg}), s.ctx)
		c.Assert(err, IsNil)
		out, err := f.eval(nil)
		c.Assert(err, IsNil)
		c.Assert(out, DeepEquals, types.NewDatum(test.out))
	}

	var argNull types.Datum
	f, _ := fc.getFunction(datumsToConstants([]types.Datum{argNull}), s.ctx)
	compress, err := f.eval(nil)
	c.Assert(err, IsNil)
	c.Assert(compress.IsNull(), IsTrue)
<|endoftext|>


<commit_before>package babble

import (
	"math/rand"
	"strings"
	"time"
)

func init() {
	rand.Seed(time.Now().Unix())
}

type Babbler struct {
	Count int
	Separator string
	Words []string
}

func NewBabbler() (b Babbler) {
	b.Count = 2
	b.Separator = "-"
	b.Words = readAvailableDictionary()
	return
}

func (this Babbler) Babble() string {
	pieces := []string{}
	for i := 0; i < this.Count ; i++ {
		pieces = append(pieces, this.Words[rand.Int()%len(this.Words)])
	}

	return strings.Join(pieces, this.Separator)
}
<commit_msg>Seed random with current nanoseconds<commit_after>package babble

import (
	"math/rand"
	"strings"
	"time"
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

type Babbler struct {
	Count int
	Separator string
	Words []string
}

func NewBabbler() (b Babbler) {
	b.Count = 2
	b.Separator = "-"
	b.Words = readAvailableDictionary()
	return
}

func (this Babbler) Babble() string {
	pieces := []string{}
	for i := 0; i < this.Count ; i++ {
		pieces = append(pieces, this.Words[rand.Int()%len(this.Words)])
	}

	return strings.Join(pieces, this.Separator)
}
<|endoftext|>