<commit_before>package portutil

import (
	"net"
	"sync"
	"testing"
)

func TestVerifyTCP(t *testing.T) {
	testPort := 8000

	port, err := VerifyTCP(testPort)
	if err != nil {
		t.Errorf("Couldn't Verify port: %d. Error: %s", port, err)
		return
	}

	if port == 0 {
		t.Errorf("Couldn't Verify port: %d. Error: %s", port, err)
		return
	}

	if port != testPort {
		t.Errorf("testPort: %d should equal port: %d", testPort, port)
		return
	}
}

func TestVerifyUDP(t *testing.T) {
	testPort := 8000

	port, err := VerifyUDP(testPort)
	if err != nil {
		t.Errorf("Couldn't Verify port: %d. Error: %s", port, err)
		return
	}

	if port == 0 {
		t.Errorf("Couldn't Verify port: %d. Error: %s", port, err)
		return
	}

	if port != testPort {
		t.Errorf("testPort: %d should equal port: %d", testPort, port)
		return
	}
}

func TestVerify(t *testing.T) {
	testPort := 9000

	tests := []struct {
		netProto string
	}{
		{udp},
		{tcp},
	}
	for _, test := range tests {
		port, err := Verify(test.netProto, testPort)
		if err != nil {
			t.Errorf("Couldn't Verify port on UDP: %s. Error: %s", port, err)
			return
		}

		if port == 0 {
			t.Errorf("Couldn't Verify port on UDP: %d. Error: %s", port, err)
			return
		}

		if port != testPort {
			t.Errorf("testPort: %d should equal UDP port: %d", testPort, port)
			return
		}
	}
}

func TestVerifyHostPort(t *testing.T) {
	tests := []struct {
		netProto string
		address  string
		pass     bool
	}{
		{udp, "127.0.0.1:9080", true},
		{tcp, "127.0.0.1:9080", true},
		{udp, "", false},
		{tcp, "", false},
	}
	for _, test := range tests {
		addr, err := VerifyHostPort(test.netProto, test.address)
		if test.pass {
			if err != nil {
				t.Errorf("Couldn't VerifyHostPort: %s. Error: %s", addr, err)
				return
			}

			if addr == "" {
				t.Errorf("Couldn't VerifyHostPort: %s. Error: %s", addr, err)
				return
			}

			if addr != test.address {
				t.Errorf("testPort: %s should equal port: %d", test.address, addr)
				return
			}
		} else {
			if err == nil && addr != "" {
				t.Errorf("VerifyHostPort should error: %s. Error: %s", addr, err)
				return
			}
		}
	}
}

func TestGetUnique(t *testing.T) {
	// test GetUnique
	tests := []struct {
		netProto string
	}{
		{udp},
		{tcp},
	}

	port, err := GetUniqueTCP()
	if err != nil || port == 0 {
		t.Fatalf("Err getting unique port TCP: %s", err)
	}

	port, err = GetUniqueUDP()
	if err != nil || port == 0 {
		t.Fatalf("Err getting unique port UDP: %s", err)
	}

	// test GetUnique
	for _, test := range tests {
		port, err := GetUnique(test.netProto)
		if err != nil || port == 0 {
			t.Fatalf("%s: Err getting unique port: %s", test.netProto, err)
		}
	}

	// open up all ports
	listeners := openAllTCPPorts()

	port, err = GetUniqueTCP()
	if err == nil {
		t.Fatalf("All ports should be closed: %s", err)
	}

	port, err = GetUniqueUDP()
	if err == nil {
		t.Fatalf("All ports should be closed: %s", err)
	}

	// test GetUnique
	for _, test := range tests {
		_, err := GetUnique(test.netProto)
		if err == nil {
			t.Fatalf("%s: All ports should be closed: %s", test.netProto, err)
		}
	}

	// cleanup listeners
	for _, listener := range listeners {
		// close listener
		listener.Close()
	}
}

// This test creates a listener at a port and then calls Verify()
func TestPortTaken(t *testing.T) {
	tests := []struct {
		netProto string
	}{
		{udp},
		{tcp},
	}

	for _, test := range tests {
		port, _ := GetUnique(test.netProto)

		// Create a listener
		var err error
		var ln interface{}

		switch test.netProto {
		case udp:
			ln, err = newListenerUDP(port)
			if err != nil {
				t.Error("Err creating UDP listener", err)
				return
			}
			defer ln.(*net.UDPConn).Close()

			// test newListenerUDP error
			_, err = newListenerUDP(-1)
			if err == nil {
				t.Fatal("Err creating UDP listener", err)
				return
			}
		case tcp:
			ln, err = newListenerTCP(port)
			if err != nil {
				t.Error("Err creating TCP listener", err)
				return
			}
			defer ln.(net.Listener).Close()
		}

		// Now try to use the same port
		_, err = Verify(test.netProto, port)
		if err == nil {
			t.Errorf("Failed to detect port was taken.")
		}

		_, err = VerifyHostPort(test.netProto, JoinHostPort("127.0.0.1", port))
		if err == nil {
			t.Errorf("Failed to detect port was taken.")
		}

	}
}

func TestGetPortFromAddr(t *testing.T) {
	tests := []struct {
		address string
		pass    bool
	}{
		{"127.0.0.1:9080", true},
		{"", false},
		{"):*", false},
	}
	for _, test := range tests {
		port, err := GetPortFromAddr(test.address)
		if err != nil || port == 0 {
			if test.pass {
				t.Fatalf("%s: Err getting unique port: %s", test.address, err)
			}
		}
	}
}

// openAllTCPPorts tries to open all tcp ports on your computer
// and returns a slice of net.Listeners so you can close
func openAllTCPPorts() []net.Listener {
	var listeners []net.Listener
	listMutex := new(sync.Mutex)
	stopChan := make(chan bool)

	openPorts := func() {
		ln, err := newListenerTCP(0)
		if err != nil {
			stopChan <- true
			return
		}

		// append listener to slice
		listMutex.Lock()
		listeners = append(listeners, ln)
		listMutex.Unlock()
	}

	go func() {
		for {
			go openPorts()
		}
	}()
	<-stopChan

	return listeners
}
<commit_msg>Updating test<commit_after>package portutil

import (
	"net"
	"sync"
	"testing"
)

func TestVerifyTCP(t *testing.T) {
	testPort := 8000

	port, err := VerifyTCP(testPort)
	if err != nil {
		t.Errorf("Couldn't Verify port: %d. Error: %s", port, err)
		return
	}

	if port == 0 {
		t.Errorf("Couldn't Verify port: %d. Error: %s", port, err)
		return
	}

	if port != testPort {
		t.Errorf("testPort: %d should equal port: %d", testPort, port)
		return
	}
}

func TestVerifyUDP(t *testing.T) {
	testPort := 8000

	port, err := VerifyUDP(testPort)
	if err != nil {
		t.Errorf("Couldn't Verify port: %d. Error: %s", port, err)
		return
	}

	if port == 0 {
		t.Errorf("Couldn't Verify port: %d. Error: %s", port, err)
		return
	}

	if port != testPort {
		t.Errorf("testPort: %d should equal port: %d", testPort, port)
		return
	}
}

func TestVerify(t *testing.T) {
	testPort := 9000

	tests := []struct {
		netProto string
	}{
		{udp},
		{tcp},
	}
	for _, test := range tests {
		port, err := Verify(test.netProto, testPort)
		if err != nil {
			t.Errorf("Couldn't Verify port on UDP: %s. Error: %s", port, err)
			return
		}

		if port == 0 {
			t.Errorf("Couldn't Verify port on UDP: %d. Error: %s", port, err)
			return
		}

		if port != testPort {
			t.Errorf("testPort: %d should equal UDP port: %d", testPort, port)
			return
		}
	}
}

func TestVerifyHostPort(t *testing.T) {
	tests := []struct {
		netProto string
		address  string
		pass     bool
	}{
		{udp, "127.0.0.1:9080", true},
		{tcp, "127.0.0.1:9080", true},
		{tcp, ":9080", true},
		{udp, "", false},
		{tcp, "", false},
	}
	for _, test := range tests {
		addr, err := VerifyHostPort(test.netProto, test.address)
		if test.pass {
			if err != nil {
				t.Errorf("Couldn't VerifyHostPort: %s. Error: %s", addr, err)
				return
			}

			if addr == "" {
				t.Errorf("Couldn't VerifyHostPort: %s. Error: %s", addr, err)
				return
			}

			if addr != test.address {
				t.Errorf("testPort: %s should equal port: %d", test.address, addr)
				return
			}
		} else {
			if err == nil && addr != "" {
				t.Errorf("VerifyHostPort should error: %s. Error: %s", addr, err)
				return
			}
		}
	}
}

func TestGetUnique(t *testing.T) {
	// test GetUnique
	tests := []struct {
		netProto string
	}{
		{udp},
		{tcp},
	}

	port, err := GetUniqueTCP()
	if err != nil || port == 0 {
		t.Fatalf("Err getting unique port TCP: %s", err)
	}

	port, err = GetUniqueUDP()
	if err != nil || port == 0 {
		t.Fatalf("Err getting unique port UDP: %s", err)
	}

	// test GetUnique
	for _, test := range tests {
		port, err := GetUnique(test.netProto)
		if err != nil || port == 0 {
			t.Fatalf("%s: Err getting unique port: %s", test.netProto, err)
		}
	}

	// open up all ports
	listeners := openAllTCPPorts()

	port, err = GetUniqueTCP()
	if err == nil {
		t.Fatalf("All ports should be closed: %s", err)
	}

	port, err = GetUniqueUDP()
	if err == nil {
		t.Fatalf("All ports should be closed: %s", err)
	}

	// test GetUnique
	for _, test := range tests {
		_, err := GetUnique(test.netProto)
		if err == nil {
			t.Fatalf("%s: All ports should be closed: %s", test.netProto, err)
		}
	}

	// cleanup listeners
	for _, listener := range listeners {
		// close listener
		listener.Close()
	}
}

// This test creates a listener at a port and then calls Verify()
func TestPortTaken(t *testing.T) {
	tests := []struct {
		netProto string
	}{
		{udp},
		{tcp},
	}

	for _, test := range tests {
		port, _ := GetUnique(test.netProto)

		// Create a listener
		var err error
		var ln interface{}

		switch test.netProto {
		case udp:
			ln, err = newListenerUDP(port)
			if err != nil {
				t.Error("Err creating UDP listener", err)
				return
			}
			defer ln.(*net.UDPConn).Close()

			// test newListenerUDP error
			_, err = newListenerUDP(-1)
			if err == nil {
				t.Fatal("Err creating UDP listener", err)
				return
			}
		case tcp:
			ln, err = newListenerTCP(port)
			if err != nil {
				t.Error("Err creating TCP listener", err)
				return
			}
			defer ln.(net.Listener).Close()
		}

		// Now try to use the same port
		_, err = Verify(test.netProto, port)
		if err == nil {
			t.Errorf("Failed to detect port was taken.")
		}

		_, err = VerifyHostPort(test.netProto, JoinHostPort("127.0.0.1", port))
		if err == nil {
			t.Errorf("Failed to detect port was taken.")
		}

	}
}

func TestGetPortFromAddr(t *testing.T) {
	tests := []struct {
		address string
		pass    bool
	}{
		{"127.0.0.1:9080", true},
		{"", false},
		{"):*", false},
	}
	for _, test := range tests {
		port, err := GetPortFromAddr(test.address)
		if err != nil || port == 0 {
			if test.pass {
				t.Fatalf("%s: Err getting unique port: %s", test.address, err)
			}
		}
	}
}

// openAllTCPPorts tries to open all tcp ports on your computer
// and returns a slice of net.Listeners so you can close
func openAllTCPPorts() []net.Listener {
	var listeners []net.Listener
	listMutex := new(sync.Mutex)
	stopChan := make(chan bool)

	openPorts := func() {
		ln, err := newListenerTCP(0)
		if err != nil {
			stopChan <- true
			return
		}

		// append listener to slice
		listMutex.Lock()
		listeners = append(listeners, ln)
		listMutex.Unlock()
	}

	go func() {
		for {
			go openPorts()
		}
	}()
	<-stopChan

	return listeners
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) Paul R. Tagliamonte, 2015
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE. */

package dictd

/* commands.go - protocol handlers for the core functions of the dict protocol
 *
 * This contains the core protocol implementaion, including syntax error
 * handlers, the initial handshake, and the core MUST-haves */

/*
 *
 */
func unknownCommandHandler(session *Session, command Command) {
	session.Connection.Writer.PrintfLine("%d %s", 500, "unknown command")
}

/*
 *
 */
func handshakeHandler(session *Session) {
	session.Connection.Writer.PrintfLine("%d %s <%s> <%s>",
		220,
		"pault.ag dictd proto",
		"mime",
		session.MsgId,
	)
}

/*
 */
func clientCommandHandler(session *Session, command Command) {
	// session.Client
	session.Connection.Writer.PrintfLine("%d %s", 250, "ok")

}

/*
 */
func defineCommandHandler(session *Session, command Command) {

	if len(command.Params) <= 1 {
		session.Connection.Writer.PrintfLine(
			"%d syntax error, illegal parameters",
			501,
		)
		return
	}

	database := command.Params[0]
	word := command.Params[1]

	/*
	 * Dispatch on ! or * for those behaviors
	 */

	databaseBackend := session.DictServer.GetDatabase(database)
	if databaseBackend == nil {
		session.Connection.Writer.PrintfLine("%d invalid database", 550)
		return
	}

	words := databaseBackend.Define(word)
	session.Connection.Writer.PrintfLine(
		"150 %d definitions retrieved",
		len(words),
	)

	for _, el := range words {
		session.Connection.Writer.PrintfLine(
			"151 \"%s\" %s \"%s\"",
			word,
			database,
			databaseBackend.Description(),
		)
		writer := session.Connection.Writer.DotWriter()
		writer.Write([]byte(el.Definition))
		writer.Close()
	}
	session.Connection.Writer.PrintfLine("250 ok")
}

/*
 *
 */
func registerDefaultHandlers(server *Server) {
	server.RegisterHandler("CLIENT", clientCommandHandler)
	server.RegisterHandler("DEFINE", defineCommandHandler)
}
<commit_msg>Replace param'd %d for the number.<commit_after>/**
 * Copyright (c) Paul R. Tagliamonte, 2015
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE. */

package dictd

/* commands.go - protocol handlers for the core functions of the dict protocol
 *
 * This contains the core protocol implementaion, including syntax error
 * handlers, the initial handshake, and the core MUST-haves */

/*
 *
 */
func unknownCommandHandler(session *Session, command Command) {
	session.Connection.Writer.PrintfLine("500 %s", "unknown command")
}

/*
 *
 */
func handshakeHandler(session *Session) {
	session.Connection.Writer.PrintfLine("220 %s <%s> <%s>",
		"pault.ag dictd proto",
		"mime",
		session.MsgId,
	)
}

/*
 */
func clientCommandHandler(session *Session, command Command) {
	// session.Client
	session.Connection.Writer.PrintfLine("250 %s", "ok")

}

/*
 */
func defineCommandHandler(session *Session, command Command) {

	if len(command.Params) <= 1 {
		session.Connection.Writer.PrintfLine(
			"501 syntax error, illegal parameters",
		)
		return
	}

	database := command.Params[0]
	word := command.Params[1]

	/*
	 * Dispatch on ! or * for those behaviors
	 */

	databaseBackend := session.DictServer.GetDatabase(database)
	if databaseBackend == nil {
		session.Connection.Writer.PrintfLine("550 invalid database")
		return
	}

	words := databaseBackend.Define(word)
	session.Connection.Writer.PrintfLine(
		"150 %d definitions retrieved",
		len(words),
	)

	for _, el := range words {
		session.Connection.Writer.PrintfLine(
			"151 \"%s\" %s \"%s\"",
			word,
			database,
			databaseBackend.Description(),
		)
		writer := session.Connection.Writer.DotWriter()
		writer.Write([]byte(el.Definition))
		writer.Close()
	}
	session.Connection.Writer.PrintfLine("250 ok")
}

/*
 *
 */
func registerDefaultHandlers(server *Server) {
	server.RegisterHandler("CLIENT", clientCommandHandler)
	server.RegisterHandler("DEFINE", defineCommandHandler)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/http"
	"os"
	"draringi/codejam2013/src/web"
)

func main() {
	machine := new(web.MachineInterface)
	dashboard := new(web.Dashboard)
	http.Handle("/upload", machine)
	http.Handle("/", dashboard)
    http.Handle("/data", dashboard.JSONAid)
    http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
	fmt.Println("listening...")
	err := http.ListenAndServe(os.Getenv("HOST")+":"+os.Getenv("PORT"), nil)
	if err != nil {
		panic(err)
	}
}
<commit_msg>So the issue all along was that I forgot to call the Init function...<commit_after>package main

import (
	"fmt"
	"net/http"
	"os"
	"draringi/codejam2013/src/web"
)

func main() {
	machine := new(web.MachineInterface)
	dashboard := new(web.Dashboard)
    dashboard.Init()
	http.Handle("/upload", machine)
	http.Handle("/", dashboard)
    http.Handle("/data", dashboard.JSONAid)
    http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
	fmt.Println("listening...")
	err := http.ListenAndServe(os.Getenv("HOST")+":"+os.Getenv("PORT"), nil)
	if err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>package elastic

import (
	"testing"

	"github.com/index0h/go-tracker/entities"
	"github.com/index0h/go-tracker/dao"
	driver "github.com/olivere/elastic"
	"github.com/index0h/go-tracker/dao/uuid"
	"github.com/stretchr/testify/assert"
	"time"
)

func Test_VisitRepository_Interface(t *testing.T) {
	func(event dao.VisitRepositoryInterface) {}(&VisitRepository{})
}

func Test_Visit_Repository_FindClientID(t *testing.T) {
	client, repository := visitRepository_CreateRepository()
	visitID := uuid.New().Generate()
	sessionID := uuid.New().Generate()
	clientID := "test_FindClientID"

	indexName := repository.indexName()

	_, _ = client.DeleteIndex(indexName).Do()

	visit, _ := entities.NewVisit(visitID, int64(15), sessionID, clientID, map[string]string{}, []string{})

	_ = repository.Insert(visit)

	// Used to wait for document is saved
	time.Sleep(1 * time.Second)

	foundClientID, err := repository.FindClientID(sessionID)
	assert.Nil(t, err)
	assert.Equal(t, clientID, foundClientID)
}

func Test_VisitRepository_FindClientID_Empty(t *testing.T) {
	_, repository := visitRepository_CreateRepository()

	foundClientID, err := repository.FindClientID([16]byte{})
	assert.NotNil(t, err)
	assert.Empty(t, foundClientID)
}

func Test_VisitRepository_FindClientID_WrongSessionID(t *testing.T) {
	client, repository := visitRepository_CreateRepository()
	visitID := uuid.New().Generate()
	sessionID := uuid.New().Generate()
	clientID := "test_FindClientID"

	indexName := repository.indexName()

	_, _ = client.DeleteIndex(indexName).Do()

	visit, _ := entities.NewVisit(visitID, int64(15), sessionID, clientID, map[string]string{}, []string{})

	_ = repository.Insert(visit)

	// Used to wait for document is saved
	time.Sleep(1 * time.Second)

	foundClientID, err := repository.FindClientID(uuid.New().Generate())
	assert.Nil(t, err)
	assert.Empty(t, foundClientID)
}

func Test_VisitRepository_Verify(t *testing.T) {
	client, repository := visitRepository_CreateRepository()
	visitID := uuid.New().Generate()
	sessionID := uuid.New().Generate()
	clientID := "test_FindClientID"

	indexName := repository.indexName()

	_, _ = client.DeleteIndex(indexName).Do()

	visit, _ := entities.NewVisit(visitID, int64(15), sessionID, clientID, map[string]string{}, []string{})

	_ = repository.Insert(visit)

	// Used to wait for document is saved
	time.Sleep(1 * time.Second)

	ok, err := repository.Verify(sessionID, clientID)
	assert.Nil(t, err)
	assert.True(t, ok)
}

func Test_VisitRepository_Verify_WrongClientID(t *testing.T) {
	client, repository := visitRepository_CreateRepository()
	visitID := uuid.New().Generate()
	sessionID := uuid.New().Generate()
	clientID := "test_FindClientID"

	indexName := repository.indexName()

	_, _ = client.DeleteIndex(indexName).Do()

	visit, _ := entities.NewVisit(visitID, int64(15), sessionID, clientID, map[string]string{}, []string{})

	_ = repository.Insert(visit)

	// Used to wait for document is saved
	time.Sleep(1 * time.Second)

	ok, err := repository.Verify(sessionID, "Some another client ID")
	assert.Nil(t, err)
	assert.False(t, ok)
}

func Test_VisitRepository_Verify_WrongSessionID(t *testing.T) {
	client, repository := visitRepository_CreateRepository()
	visitID := uuid.New().Generate()
	sessionID := uuid.New().Generate()
	clientID := "test_FindClientID"

	indexName := repository.indexName()

	_, _ = client.DeleteIndex(indexName).Do()

	visit, _ := entities.NewVisit(visitID, int64(15), sessionID, clientID, map[string]string{}, []string{})

	_ = repository.Insert(visit)

	// Used to wait for document is saved
	time.Sleep(1 * time.Second)

	ok, err := repository.Verify(uuid.New().Generate(), clientID)
	assert.Nil(t, err)
	assert.True(t, ok)
}

func Test_VisitRepository_Verify_EmptyClientID(t *testing.T) {
	client, repository := visitRepository_CreateRepository()
	visitID := uuid.New().Generate()
	sessionID := uuid.New().Generate()
	clientID := "test_FindClientID"

	indexName := repository.indexName()

	_, _ = client.DeleteIndex(indexName).Do()

	visit, _ := entities.NewVisit(visitID, int64(15), sessionID, clientID, map[string]string{}, []string{})

	_ = repository.Insert(visit)

	// Used to wait for document is saved
	time.Sleep(1 * time.Second)

	ok, err := repository.Verify(uuid.New().Generate(), "")
	assert.NotNil(t, err)
	assert.False(t, ok)
}

func Test_VisitRepository_Verify_EmptySessionID(t *testing.T) {
	client, repository := visitRepository_CreateRepository()
	visitID := uuid.New().Generate()
	sessionID := uuid.New().Generate()
	clientID := "test_FindClientID"

	indexName := repository.indexName()

	_, _ = client.DeleteIndex(indexName).Do()

	visit, _ := entities.NewVisit(visitID, int64(15), sessionID, clientID, map[string]string{}, []string{})

	_ = repository.Insert(visit)

	// Used to wait for document is saved
	time.Sleep(1 * time.Second)

	ok, err := repository.Verify([16]byte{}, clientID)
	assert.NotNil(t, err)
	assert.False(t, ok)
}

func Test_VisitRepository_Insert(t *testing.T) {
	client, repository := visitRepository_CreateRepository()
	visitID := uuid.New().Generate()
	sessionID := uuid.New().Generate()
	clientID := "clientID"
	data := map[string]string{"data": "here"}
	warnings := []string{"i'm warning"}
	timestamp := int64(15)

	indexName := repository.indexName()
	typeName := repository.typeName

	_, _ = client.DeleteIndex(indexName).Do()

	visit, _ := entities.NewVisit(visitID, timestamp, sessionID, clientID, data, warnings)

	err := repository.Insert(visit)

	assert.Nil(t, err)

	indexExists, err := client.IndexExists(indexName).Do()
	assert.True(t, indexExists)
	assert.Nil(t, err)

	foundRawVisit, err := client.Get().
		Index(indexName).
		Type(typeName).
		Id(uuid.New().ToString(visitID)).
		Do()

	assert.Nil(t, err)
	assert.NotEmpty(t, *foundRawVisit.Source)

	foundVisit, err := repository.byteToVisit(*foundRawVisit.Source)

	assert.Nil(t, err)
	assert.Equal(t, visit.VisitID(), foundVisit.VisitID())
	assert.Equal(t, visit.Timestamp(), foundVisit.Timestamp())
	assert.Equal(t, visit.SessionID(), foundVisit.SessionID())
	assert.Equal(t, visit.ClientID(), foundVisit.ClientID())
	assert.Equal(t, visit.Data(), foundVisit.Data())
	assert.Equal(t, visit.Warnings(), foundVisit.Warnings())
}

func Test_VisitRepository_Insert_Nil(t *testing.T) {
	_, repository := visitRepository_CreateRepository()

	err := repository.Insert(nil)

	assert.NotNil(t, err)
}

func visitRepository_CreateRepository() (*driver.Client, *VisitRepository) {
	//client, _ := driver.NewClient(driver.SetTraceLog(log.New(os.Stdout, "logger: ", log.Lshortfile)))
	client, _ := driver.NewClient()
	repository := NewVisitRepository(client, uuid.New())
	repository.indexPrefix = "tracker-test-"

	return client, repository
}<commit_msg>fix sleep for elastic tests in travis<commit_after>package elastic

import (
	"testing"

	"github.com/index0h/go-tracker/entities"
	"github.com/index0h/go-tracker/dao"
	driver "github.com/olivere/elastic"
	"github.com/index0h/go-tracker/dao/uuid"
	"github.com/stretchr/testify/assert"
	"time"
)

func Test_VisitRepository_Interface(t *testing.T) {
	func(event dao.VisitRepositoryInterface) {}(&VisitRepository{})
}

func Test_VisitRepository_FindClientID(t *testing.T) {
	client, repository := visitRepository_CreateRepository()
	visitID := uuid.New().Generate()
	sessionID := uuid.New().Generate()
	clientID := "test_FindClientID"

	indexName := repository.indexName()

	_, _ = client.DeleteIndex(indexName).Do()

	visit, _ := entities.NewVisit(visitID, int64(15), sessionID, clientID, map[string]string{}, []string{})

	_ = repository.Insert(visit)

	visitRepository_Sleep()

	foundClientID, err := repository.FindClientID(sessionID)
	assert.Nil(t, err)
	assert.Equal(t, clientID, foundClientID)
}

func Test_VisitRepository_FindClientID_Empty(t *testing.T) {
	_, repository := visitRepository_CreateRepository()

	foundClientID, err := repository.FindClientID([16]byte{})
	assert.NotNil(t, err)
	assert.Empty(t, foundClientID)
}

func Test_VisitRepository_FindClientID_WrongSessionID(t *testing.T) {
	client, repository := visitRepository_CreateRepository()
	visitID := uuid.New().Generate()
	sessionID := uuid.New().Generate()
	clientID := "test_FindClientID"

	indexName := repository.indexName()

	_, _ = client.DeleteIndex(indexName).Do()

	visit, _ := entities.NewVisit(visitID, int64(15), sessionID, clientID, map[string]string{}, []string{})

	_ = repository.Insert(visit)

	visitRepository_Sleep()

	foundClientID, err := repository.FindClientID(uuid.New().Generate())
	assert.Nil(t, err)
	assert.Empty(t, foundClientID)
}

func Test_VisitRepository_Verify(t *testing.T) {
	client, repository := visitRepository_CreateRepository()
	visitID := uuid.New().Generate()
	sessionID := uuid.New().Generate()
	clientID := "test_FindClientID"

	indexName := repository.indexName()

	_, _ = client.DeleteIndex(indexName).Do()

	visit, _ := entities.NewVisit(visitID, int64(15), sessionID, clientID, map[string]string{}, []string{})

	_ = repository.Insert(visit)

	visitRepository_Sleep()

	ok, err := repository.Verify(sessionID, clientID)
	assert.Nil(t, err)
	assert.True(t, ok)
}

func Test_VisitRepository_Verify_WrongClientID(t *testing.T) {
	client, repository := visitRepository_CreateRepository()
	visitID := uuid.New().Generate()
	sessionID := uuid.New().Generate()
	clientID := "test_FindClientID"

	indexName := repository.indexName()

	_, _ = client.DeleteIndex(indexName).Do()

	visit, _ := entities.NewVisit(visitID, int64(15), sessionID, clientID, map[string]string{}, []string{})

	_ = repository.Insert(visit)

	visitRepository_Sleep()

	ok, err := repository.Verify(sessionID, "Some another client ID")
	assert.Nil(t, err)
	assert.False(t, ok)
}

func Test_VisitRepository_Verify_WrongSessionID(t *testing.T) {
	client, repository := visitRepository_CreateRepository()
	visitID := uuid.New().Generate()
	sessionID := uuid.New().Generate()
	clientID := "test_FindClientID"

	indexName := repository.indexName()

	_, _ = client.DeleteIndex(indexName).Do()

	visit, _ := entities.NewVisit(visitID, int64(15), sessionID, clientID, map[string]string{}, []string{})

	_ = repository.Insert(visit)

	ok, err := repository.Verify(uuid.New().Generate(), clientID)
	assert.Nil(t, err)
	assert.True(t, ok)
}

func Test_VisitRepository_Verify_EmptyClientID(t *testing.T) {
	client, repository := visitRepository_CreateRepository()
	visitID := uuid.New().Generate()
	sessionID := uuid.New().Generate()
	clientID := "test_FindClientID"

	indexName := repository.indexName()

	_, _ = client.DeleteIndex(indexName).Do()

	visit, _ := entities.NewVisit(visitID, int64(15), sessionID, clientID, map[string]string{}, []string{})

	_ = repository.Insert(visit)

	visitRepository_Sleep()

	ok, err := repository.Verify(uuid.New().Generate(), "")
	assert.NotNil(t, err)
	assert.False(t, ok)
}

func Test_VisitRepository_Verify_EmptySessionID(t *testing.T) {
	client, repository := visitRepository_CreateRepository()
	visitID := uuid.New().Generate()
	sessionID := uuid.New().Generate()
	clientID := "test_FindClientID"

	indexName := repository.indexName()

	_, _ = client.DeleteIndex(indexName).Do()

	visit, _ := entities.NewVisit(visitID, int64(15), sessionID, clientID, map[string]string{}, []string{})

	_ = repository.Insert(visit)

	visitRepository_Sleep()

	ok, err := repository.Verify([16]byte{}, clientID)
	assert.NotNil(t, err)
	assert.False(t, ok)
}

func Test_VisitRepository_Insert(t *testing.T) {
	client, repository := visitRepository_CreateRepository()
	visitID := uuid.New().Generate()
	sessionID := uuid.New().Generate()
	clientID := "clientID"
	data := map[string]string{"data": "here"}
	warnings := []string{"i'm warning"}
	timestamp := int64(15)

	indexName := repository.indexName()
	typeName := repository.typeName

	_, _ = client.DeleteIndex(indexName).Do()

	visit, _ := entities.NewVisit(visitID, timestamp, sessionID, clientID, data, warnings)

	err := repository.Insert(visit)

	assert.Nil(t, err)

	indexExists, err := client.IndexExists(indexName).Do()
	assert.True(t, indexExists)
	assert.Nil(t, err)

	foundRawVisit, err := client.Get().
		Index(indexName).
		Type(typeName).
		Id(uuid.New().ToString(visitID)).
		Do()

	assert.Nil(t, err)
	assert.NotEmpty(t, *foundRawVisit.Source)

	foundVisit, err := repository.byteToVisit(*foundRawVisit.Source)

	assert.Nil(t, err)
	assert.Equal(t, visit.VisitID(), foundVisit.VisitID())
	assert.Equal(t, visit.Timestamp(), foundVisit.Timestamp())
	assert.Equal(t, visit.SessionID(), foundVisit.SessionID())
	assert.Equal(t, visit.ClientID(), foundVisit.ClientID())
	assert.Equal(t, visit.Data(), foundVisit.Data())
	assert.Equal(t, visit.Warnings(), foundVisit.Warnings())
}

func Test_VisitRepository_Insert_Nil(t *testing.T) {
	_, repository := visitRepository_CreateRepository()

	err := repository.Insert(nil)

	assert.NotNil(t, err)
}

func visitRepository_CreateRepository() (*driver.Client, *VisitRepository) {
	//client, _ := driver.NewClient(driver.SetTraceLog(log.New(os.Stdout, "logger: ", log.Lshortfile)))
	client, _ := driver.NewClient()
	repository := NewVisitRepository(client, uuid.New())
	repository.indexPrefix = "tracker-test-"

	return client, repository
}

// Used to wait for document is saved
func visitRepository_Sleep() {
	time.Sleep(1500 * time.Millisecond)
}
<|endoftext|>


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

package pretty

import (
	"bytes"
	"fmt"
	"io"
	"net"
	"reflect"
	"time"

	"github.com/kylelemons/godebug/diff"
)

// A Config represents optional configuration parameters for formatting.
//
// Some options, notably ShortList, dramatically increase the overhead
// of pretty-printing a value.
type Config struct {
	// Verbosity options
	Compact  bool // One-line output. Overrides Diffable.
	Diffable bool // Adds extra newlines for more easily diffable output.

	// Field and value options
	IncludeUnexported   bool // Include unexported fields in output
	PrintStringers      bool // Call String on a fmt.Stringer
	PrintTextMarshalers bool // Call MarshalText on an encoding.TextMarshaler
	SkipZeroFields      bool // Skip struct fields that have a zero value.

	// Output transforms
	ShortList int // Maximum character length for short lists if nonzero.

	// Type-specific overrides
	//
	// Formatter maps a type to a function that will provide a one-line string
	// representation of the input value.  Conceptually:
	//   Formatter[reflect.TypeOf(v)](v) = "v as a string"
	//
	// Note that the first argument need not explicitly match the type, it must
	// merely be callable with it.
	//
	// When processing an input value, if its type exists as a key in Formatter:
	//   1) If the value is nil, no stringification is performed.
	//      This allows overriding of PrintStringers and PrintTextMarshalers.
	//   2) The value will be called with the input as its only argument.
	//      The function must return a string as its first return value.
	//
	// In addition to func literals, two common values for this will be:
	//   fmt.Sprint        (function) func Sprint(...interface{}) string
	//   Type.String         (method) func (Type) String() string
	//
	// Note that neither of these work if the String method is a pointer
	// method and the input will be provided as a value.  In that case,
	// use a function that calls .String on the formal value parameter.
	Formatter map[reflect.Type]interface{}

	// If TrackCycles is enabled, pretty will detect and track
	// self-referential structures. If a self-referential structure (aka a
	// "recursive" value) is detected, numbered placeholders will be emitted.
	//
	// Pointer tracking is disabled by default for performance reasons.
	TrackCycles bool
}

// Default Config objects
var (
	// DefaultFormatter is the default set of overrides for stringification.
	DefaultFormatter = map[reflect.Type]interface{}{
		reflect.TypeOf(time.Time{}):          fmt.Sprint,
		reflect.TypeOf(net.IP{}):             fmt.Sprint,
		reflect.TypeOf((*error)(nil)).Elem(): fmt.Sprint,
	}

	// CompareConfig is the default configuration used for Compare.
	CompareConfig = &Config{
		Diffable:          true,
		IncludeUnexported: true,
		Formatter:         DefaultFormatter,
	}

	// DefaultConfig is the default configuration used for all other top-level functions.
	DefaultConfig = &Config{
		Formatter: DefaultFormatter,
	}

	// CycleTracker is a convenience config for formatting and comparing recursive structures.
	CycleTracker = &Config{
		Diffable:    true,
		Formatter:   DefaultFormatter,
		TrackCycles: true,
	}
)

func (cfg *Config) fprint(buf *bytes.Buffer, vals ...interface{}) {
	ref := &reflector{
		Config: cfg,
	}
	if cfg.TrackCycles {
		ref.pointerTracker = new(pointerTracker)
	}
	for i, val := range vals {
		if i > 0 {
			buf.WriteByte('\n')
		}
		newFormatter(cfg, buf).write(ref.val2node(reflect.ValueOf(val)))
	}
}

// Print writes the DefaultConfig representation of the given values to standard output.
func Print(vals ...interface{}) {
	DefaultConfig.Print(vals...)
}

// Print writes the configured presentation of the given values to standard output.
func (cfg *Config) Print(vals ...interface{}) {
	fmt.Println(cfg.Sprint(vals...))
}

// Sprint returns a string representation of the given value according to the DefaultConfig.
func Sprint(vals ...interface{}) string {
	return DefaultConfig.Sprint(vals...)
}

// Sprint returns a string representation of the given value according to cfg.
func (cfg *Config) Sprint(vals ...interface{}) string {
	buf := new(bytes.Buffer)
	cfg.fprint(buf, vals...)
	return buf.String()
}

// Fprint writes the representation of the given value to the writer according to the DefaultConfig.
func Fprint(w io.Writer, vals ...interface{}) (n int64, err error) {
	return DefaultConfig.Fprint(w, vals...)
}

// Fprint writes the representation of the given value to the writer according to the cfg.
func (cfg *Config) Fprint(w io.Writer, vals ...interface{}) (n int64, err error) {
	buf := new(bytes.Buffer)
	cfg.fprint(buf, vals...)
	return buf.WriteTo(w)
}

// Compare returns a string containing a line-by-line unified diff of the
// values in a and b, using the CompareConfig.
//
// Each line in the output is prefixed with '+', '-', or ' ' to indicate which
// side it's from. Lines from the a side are marked with '-', lines from the
// b side are marked with '+' and lines that are the same on both sides are
// marked with ' '.
func Compare(a, b interface{}) string {
	return CompareConfig.Compare(a, b)
}

// Compare returns a string containing a line-by-line unified diff of the
// values in got and want according to the cfg.
func (cfg *Config) Compare(a, b interface{}) string {
	diffCfg := *cfg
	diffCfg.Diffable = true
	return diff.Diff(cfg.Sprint(a), cfg.Sprint(b))
}
<commit_msg>pretty: Note that Compare doesn't compare types.<commit_after>// Copyright 2013 Google Inc.  All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package pretty

import (
	"bytes"
	"fmt"
	"io"
	"net"
	"reflect"
	"time"

	"github.com/kylelemons/godebug/diff"
)

// A Config represents optional configuration parameters for formatting.
//
// Some options, notably ShortList, dramatically increase the overhead
// of pretty-printing a value.
type Config struct {
	// Verbosity options
	Compact  bool // One-line output. Overrides Diffable.
	Diffable bool // Adds extra newlines for more easily diffable output.

	// Field and value options
	IncludeUnexported   bool // Include unexported fields in output
	PrintStringers      bool // Call String on a fmt.Stringer
	PrintTextMarshalers bool // Call MarshalText on an encoding.TextMarshaler
	SkipZeroFields      bool // Skip struct fields that have a zero value.

	// Output transforms
	ShortList int // Maximum character length for short lists if nonzero.

	// Type-specific overrides
	//
	// Formatter maps a type to a function that will provide a one-line string
	// representation of the input value.  Conceptually:
	//   Formatter[reflect.TypeOf(v)](v) = "v as a string"
	//
	// Note that the first argument need not explicitly match the type, it must
	// merely be callable with it.
	//
	// When processing an input value, if its type exists as a key in Formatter:
	//   1) If the value is nil, no stringification is performed.
	//      This allows overriding of PrintStringers and PrintTextMarshalers.
	//   2) The value will be called with the input as its only argument.
	//      The function must return a string as its first return value.
	//
	// In addition to func literals, two common values for this will be:
	//   fmt.Sprint        (function) func Sprint(...interface{}) string
	//   Type.String         (method) func (Type) String() string
	//
	// Note that neither of these work if the String method is a pointer
	// method and the input will be provided as a value.  In that case,
	// use a function that calls .String on the formal value parameter.
	Formatter map[reflect.Type]interface{}

	// If TrackCycles is enabled, pretty will detect and track
	// self-referential structures. If a self-referential structure (aka a
	// "recursive" value) is detected, numbered placeholders will be emitted.
	//
	// Pointer tracking is disabled by default for performance reasons.
	TrackCycles bool
}

// Default Config objects
var (
	// DefaultFormatter is the default set of overrides for stringification.
	DefaultFormatter = map[reflect.Type]interface{}{
		reflect.TypeOf(time.Time{}):          fmt.Sprint,
		reflect.TypeOf(net.IP{}):             fmt.Sprint,
		reflect.TypeOf((*error)(nil)).Elem(): fmt.Sprint,
	}

	// CompareConfig is the default configuration used for Compare.
	CompareConfig = &Config{
		Diffable:          true,
		IncludeUnexported: true,
		Formatter:         DefaultFormatter,
	}

	// DefaultConfig is the default configuration used for all other top-level functions.
	DefaultConfig = &Config{
		Formatter: DefaultFormatter,
	}

	// CycleTracker is a convenience config for formatting and comparing recursive structures.
	CycleTracker = &Config{
		Diffable:    true,
		Formatter:   DefaultFormatter,
		TrackCycles: true,
	}
)

func (cfg *Config) fprint(buf *bytes.Buffer, vals ...interface{}) {
	ref := &reflector{
		Config: cfg,
	}
	if cfg.TrackCycles {
		ref.pointerTracker = new(pointerTracker)
	}
	for i, val := range vals {
		if i > 0 {
			buf.WriteByte('\n')
		}
		newFormatter(cfg, buf).write(ref.val2node(reflect.ValueOf(val)))
	}
}

// Print writes the DefaultConfig representation of the given values to standard output.
func Print(vals ...interface{}) {
	DefaultConfig.Print(vals...)
}

// Print writes the configured presentation of the given values to standard output.
func (cfg *Config) Print(vals ...interface{}) {
	fmt.Println(cfg.Sprint(vals...))
}

// Sprint returns a string representation of the given value according to the DefaultConfig.
func Sprint(vals ...interface{}) string {
	return DefaultConfig.Sprint(vals...)
}

// Sprint returns a string representation of the given value according to cfg.
func (cfg *Config) Sprint(vals ...interface{}) string {
	buf := new(bytes.Buffer)
	cfg.fprint(buf, vals...)
	return buf.String()
}

// Fprint writes the representation of the given value to the writer according to the DefaultConfig.
func Fprint(w io.Writer, vals ...interface{}) (n int64, err error) {
	return DefaultConfig.Fprint(w, vals...)
}

// Fprint writes the representation of the given value to the writer according to the cfg.
func (cfg *Config) Fprint(w io.Writer, vals ...interface{}) (n int64, err error) {
	buf := new(bytes.Buffer)
	cfg.fprint(buf, vals...)
	return buf.WriteTo(w)
}

// Compare returns a string containing a line-by-line unified diff of the
// values in a and b, using the CompareConfig.
//
// Each line in the output is prefixed with '+', '-', or ' ' to indicate which
// side it's from. Lines from the a side are marked with '-', lines from the
// b side are marked with '+' and lines that are the same on both sides are
// marked with ' '.
//
// The comparison is based on the intentionally-untyped output of Print, and as
// such this comparison is pretty forviving.  In particular, if the types of or
// types within in a and b are different but have the same representation,
// Compare will not indicate any differences between them.
func Compare(a, b interface{}) string {
	return CompareConfig.Compare(a, b)
}

// Compare returns a string containing a line-by-line unified diff of the
// values in got and want according to the cfg.
//
// Each line in the output is prefixed with '+', '-', or ' ' to indicate which
// side it's from. Lines from the a side are marked with '-', lines from the
// b side are marked with '+' and lines that are the same on both sides are
// marked with ' '.
//
// The comparison is based on the intentionally-untyped output of Print, and as
// such this comparison is pretty forviving.  In particular, if the types of or
// types within in a and b are different but have the same representation,
// Compare will not indicate any differences between them.
func (cfg *Config) Compare(a, b interface{}) string {
	diffCfg := *cfg
	diffCfg.Diffable = true
	return diff.Diff(cfg.Sprint(a), cfg.Sprint(b))
}
<|endoftext|>


<commit_before>package cucumberexpressions

import (
	"fmt"
	"reflect"
	"regexp"
	"strings"
)

var ESCAPE_REGEXP = regexp.MustCompile(`([\\^[$.|?*+])`)
var PARAMETER_REGEXP = regexp.MustCompile(`(\\\\\\\\)?{([^}]*)}`)
var OPTIONAL_REGEXP = regexp.MustCompile(`(\\\\\\\\)?\([^)]+\)`)
var ALTERNATIVE_NON_WHITESPACE_TEXT_REGEXP = regexp.MustCompile(`([^\s^/]+)((/[^\s^/]+)+)`)
var DOUBLE_ESCAPE = `\\\\`

type CucumberExpression struct {
	source                string
	parameterTypes        []*ParameterType
	treeRegexp            *TreeRegexp
	parameterTypeRegistry *ParameterTypeRegistry
}

func NewCucumberExpression(expression string, parameterTypeRegistry *ParameterTypeRegistry) (Expression, error) {
	result := &CucumberExpression{source: expression, parameterTypeRegistry: parameterTypeRegistry}

	expression = result.processEscapes(expression)

	expression, err := result.processOptional(expression)
	if err != nil {
		return nil, err
	}

	expression, err = result.processAlteration(expression)
	if err != nil {
		return nil, err
	}

	expression, err = result.processParameters(expression, parameterTypeRegistry)
	if err != nil {
		return nil, err
	}

	expression = "^" + expression + "$"

	result.treeRegexp = NewTreeRegexp(regexp.MustCompile(expression))
	return result, nil
}

func (c *CucumberExpression) Match(text string, typeHints ...reflect.Type) ([]*Argument, error) {
	parameterTypes := make([]*ParameterType, len(c.parameterTypes))
	copy(parameterTypes, c.parameterTypes)
	for i := 0; i < len(parameterTypes); i++ {
		if parameterTypes[i].isAnonymous() {
			typeHint := hintOrDefault(i, typeHints...)
			parameterType, err := parameterTypes[i].deAnonymize(typeHint, c.objectMapperTransformer(typeHint))
			if err != nil {
				return nil, err
			}
			parameterTypes[i] = parameterType
		}
	}
	return BuildArguments(c.treeRegexp, text, parameterTypes), nil
}

func hintOrDefault(i int, typeHints ...reflect.Type) reflect.Type {
	typeHint := reflect.TypeOf("")
	if i < len(typeHints) {
		typeHint = typeHints[i]
	}
	return typeHint
}

func (c *CucumberExpression) Regexp() *regexp.Regexp {
	return c.treeRegexp.Regexp()
}

func (c *CucumberExpression) Source() string {
	return c.source
}

func (c *CucumberExpression) processEscapes(expression string) string {
	return ESCAPE_REGEXP.ReplaceAllString(expression, `\$1`)
}

func (c *CucumberExpression) processOptional(expression string) (string, error) {
	var err error
	result := OPTIONAL_REGEXP.ReplaceAllStringFunc(expression, func(match string) string {
		if strings.HasPrefix(match, DOUBLE_ESCAPE) {
			return fmt.Sprintf(`\(%s\)`, match[5:len(match)-1])
		}
		if PARAMETER_REGEXP.MatchString(match) {
			err = NewCucumberExpressionError(fmt.Sprintf("Parameter types cannot be optional: %s", c.source))
			return match
		}
		return fmt.Sprintf("(?:%s)?", match[1:len(match)-1])
	})
	return result, err
}

func (c *CucumberExpression) processAlteration(expression string) (string, error) {
	var err error
	result := ALTERNATIVE_NON_WHITESPACE_TEXT_REGEXP.ReplaceAllStringFunc(expression, func(match string) string {
		// replace \/ with /
		// replace / with |
		replacement := strings.Replace(match, "/", "|", -1)
		replacement = strings.Replace(replacement, `\\\\|`, "/", -1)

		if strings.Contains(replacement, "|") {
			parts := strings.Split(replacement, ":")
			for _, part := range parts {
				if PARAMETER_REGEXP.MatchString(part) {
					err = NewCucumberExpressionError(fmt.Sprintf("Parameter types cannot be alternative: %s", c.source))
					return match
				}
			}
			return fmt.Sprintf("(?:%s)", replacement)
		}

		return replacement
	})
	return result, err
}

func (c *CucumberExpression) processParameters(expression string, parameterTypeRegistry *ParameterTypeRegistry) (string, error) {
	var err error
	result := PARAMETER_REGEXP.ReplaceAllStringFunc(expression, func(match string) string {
		if strings.HasPrefix(match, DOUBLE_ESCAPE) {
			return fmt.Sprintf(`\{%s\}`, match[5:len(match)-1])
		}

		typeName := match[1 : len(match)-1]
		err = CheckParameterTypeName(typeName)
		if err != nil {
			return ""
		}
		parameterType := parameterTypeRegistry.LookupByTypeName(typeName)
		if parameterType == nil {
			err = NewUndefinedParameterTypeError(typeName)
			return match
		}
		c.parameterTypes = append(c.parameterTypes, parameterType)
		return buildCaptureRegexp(parameterType.regexps)
	})
	return result, err
}

func buildCaptureRegexp(regexps []*regexp.Regexp) string {
	if len(regexps) == 1 {
		return fmt.Sprintf("(%s)", regexps[0].String())
	}

	captureGroups := make([]string, len(regexps))
	for i, r := range regexps {
		captureGroups[i] = fmt.Sprintf("(?:%s)", r.String())
	}

	return fmt.Sprintf("(%s)", strings.Join(captureGroups, "|"))
}

func (r *CucumberExpression) objectMapperTransformer(typeHint reflect.Type) func(args ...*string) interface{} {
	return func(args ...*string) interface{} {
		i, err := r.parameterTypeRegistry.defaultTransformer.Transform(*args[0], typeHint)
		if err != nil {
			panic(err)
		}
		return i
	}
}
<commit_msg>WIP Golang impl<commit_after>package cucumberexpressions

import (
	"fmt"
	"reflect"
	"regexp"
	"strings"
)

const alternativesMayNotBeEmpty = "Alternatives may not be empty: %s"
const parameterTypesCanNotBeAlternative = "Parameter types cannot be alternative: %s"

var escapeRegexp = regexp.MustCompile(`([\\^[({$.|?*+})\]])`)
var parameterRegexp = regexp.MustCompile(`(\\\\\\\\)?{([^}]*)}`)
var optionalRegexp = regexp.MustCompile(`(\\\\\\\\)?\([^)]+\)`)
var alternativeNonWhitespaceTextRegexp = regexp.MustCompile(`([^\s^/]+)((/[^\s^/]+)+)`)

const doubleEscape = `\\`
const parameterTypesCanNotBeOptional = "Parameter types cannot be optional: %s"

type tokenType int

const (
	text        tokenType = 0
	optional    tokenType = 1
	alternation tokenType = 2
	parameter   tokenType = 3
)

type token struct {
	text      string
	tokenType tokenType
}

type CucumberExpression struct {
	source                string
	parameterTypes        []*ParameterType
	treeRegexp            *TreeRegexp
	parameterTypeRegistry *ParameterTypeRegistry
}

func NewCucumberExpression(expression string, parameterTypeRegistry *ParameterTypeRegistry) (Expression, error) {
	result := &CucumberExpression{source: expression, parameterTypeRegistry: parameterTypeRegistry}

	tokens := make([]token, 1)
	tokens = append(tokens, token{expression, text})

	tokens, err := result.processOptional(tokens)
	if err != nil {
		return nil, err
	}

	tokens, err = result.processAlteration(tokens)
	if err != nil {
		return nil, err
	}

	tokens, err = result.processParameters(tokens, parameterTypeRegistry)
	if err != nil {
		return nil, err
	}

	expression = "^" + expression + "$"

	result.treeRegexp = NewTreeRegexp(regexp.MustCompile(expression))
	return result, nil
}

func (c *CucumberExpression) Match(text string, typeHints ...reflect.Type) ([]*Argument, error) {
	parameterTypes := make([]*ParameterType, len(c.parameterTypes))
	copy(parameterTypes, c.parameterTypes)
	for i := 0; i < len(parameterTypes); i++ {
		if parameterTypes[i].isAnonymous() {
			typeHint := hintOrDefault(i, typeHints...)
			parameterType, err := parameterTypes[i].deAnonymize(typeHint, c.objectMapperTransformer(typeHint))
			if err != nil {
				return nil, err
			}
			parameterTypes[i] = parameterType
		}
	}
	return BuildArguments(c.treeRegexp, text, parameterTypes), nil
}

func hintOrDefault(i int, typeHints ...reflect.Type) reflect.Type {
	typeHint := reflect.TypeOf("")
	if i < len(typeHints) {
		typeHint = typeHints[i]
	}
	return typeHint
}

func (c *CucumberExpression) Regexp() *regexp.Regexp {
	return c.treeRegexp.Regexp()
}

func (c *CucumberExpression) Source() string {
	return c.source
}

func (c *CucumberExpression) processEscapes(expression string) string {
	return escapeRegexp.ReplaceAllString(expression, `\$1`)
}

func (c *CucumberExpression) processOptional(expression []token) ([]token, error) {
	var err error
	result := splitTextTokens(expression, optionalRegexp, func(match string) (token) {
		// look for double-escaped parentheses
		if strings.HasPrefix(match, doubleEscape) {
			return token{fmt.Sprintf(`(%s)`, match[5:len(match)-1]), text}
		}
		if parameterRegexp.MatchString(match) {
			err = NewCucumberExpressionError(fmt.Sprintf(parameterTypesCanNotBeOptional, c.source))
		}
		return token{fmt.Sprintf("(?:%s)?", match[1:len(match)-1]), optional}
	})
	return result, err
}

func (c *CucumberExpression) processAlteration(expression []token) ([]token, error) {
	var err error
	result := splitTextTokens(expression, alternativeNonWhitespaceTextRegexp, func(match string) token {
		// replace \/ with /
		// replace / with |
		replacement := strings.Replace(match, "/", "|", -1)
		replacement = strings.Replace(replacement, `\\\\|`, "/", -1)

		if !strings.Contains(replacement, "|") {
			// All / were escaped
			return token{replacement, text}
		}

		// Make sure the alternative parts aren't empty and don't contain parameter types
		parts := strings.Split(replacement, "|")

		if len(parts) == 0 {
			err = NewCucumberExpressionError(fmt.Sprintf(alternativesMayNotBeEmpty, c.source))
		}
		for _, part := range parts {
			if len(part) == 0 {
				err = NewCucumberExpressionError(fmt.Sprintf(alternativesMayNotBeEmpty, c.source))
			}
			if parameterRegexp.MatchString(part) {
				err = NewCucumberExpressionError(fmt.Sprintf(parameterTypesCanNotBeAlternative, c.source))
			}
		}
		return token{fmt.Sprintf("(?:%s)", replacement), alternation}

	})
	return result, err
}

func (c *CucumberExpression) processParameters(expression []token, parameterTypeRegistry *ParameterTypeRegistry) ([]token, error) {
	var err error
	result := splitTextTokens(expression, alternativeNonWhitespaceTextRegexp, func(match string) token {
		if strings.HasPrefix(match, doubleEscape) {
			return token{fmt.Sprintf(`{%s}`, match[5:len(match)-1]), text}
		}
		typeName := match[1 : len(match)-1]
		err = CheckParameterTypeName(typeName)
		if err != nil {
			return token{match, parameter}
		}
		parameterType := parameterTypeRegistry.LookupByTypeName(typeName)
		if parameterType == nil {
			err = NewUndefinedParameterTypeError(typeName)
			return token{match, parameter}
		}
		c.parameterTypes = append(c.parameterTypes, parameterType)
		return token{buildCaptureRegexp(parameterType.regexps), parameter}
	})
	return result, err
}

func splitTextTokens(tokens []token, regexp *regexp.Regexp, processor func(string) (token)) ([]token) {
	newTokens := make([]token, len(tokens))
	for _, token := range tokens {
		if token.tokenType != text {
			newTokens = append(newTokens, token)
			continue
		}
		regexp.FindAllStringSubmatchIndex()
			//TODO: You wer here.
	}

	return newTokens
}

func buildCaptureRegexp(regexps []*regexp.Regexp) string {
	if len(regexps) == 1 {
		return fmt.Sprintf("(%s)", regexps[0].String())
	}

	captureGroups := make([]string, len(regexps))
	for i, r := range regexps {
		captureGroups[i] = fmt.Sprintf("(?:%s)", r.String())
	}

	return fmt.Sprintf("(%s)", strings.Join(captureGroups, "|"))
}

func (r *CucumberExpression) objectMapperTransformer(typeHint reflect.Type) func(args ...*string) interface{} {
	return func(args ...*string) interface{} {
		i, err := r.parameterTypeRegistry.defaultTransformer.Transform(*args[0], typeHint)
		if err != nil {
			panic(err)
		}
		return i
	}
}
<|endoftext|>


<commit_before>package parse

import (
	"bufio"
	"fmt"
	"go/ast"
	"go/format"
	"go/parser"
	"go/token"
	"io"
	"os"
	"regexp"
	"strings"
)

var (
	subrecordDef = regexp.MustCompile(`type ([a-zA-Z0-9]+) subrecord {`)
	mixinDef     = regexp.MustCompile(`type ([a-zA-Z0-9]+) mixin {`)
	tableDef     = regexp.MustCompile(`type ([a-zA-Z0-9]+) table {`)
)

func (pkg *Package) ParseSrc(src ...*os.File) error {
	fset := token.NewFileSet()

	// process files
	for _, file := range src {
		err := pkg.processFile(fset, file)
		if err != nil {
			return err
		}
	}

	// process mixins
	pkg.exciseMixins()
	for _, table := range pkg.Tables {
		pkg.processForMixins(table)
	}
	for _, subrecord := range pkg.Subrecords {
		pkg.processForMixins(subrecord)
	}

	// Write out processed files
	for _, active := range pkg.ActiveFiles {
		f, err := os.Create(active.DefName())
		if err != nil {
			return err
		}
		format.Node(f, fset, active.AST)
		f.Close()

	}
	pkg.WriteSchema()

	return nil
}

func (pkg *Package) processForMixins(mx Mixinable) {
	if st, ok := mx.Spec().Type.(*ast.StructType); ok {
		fields := []*ast.Field{}
	SRFieldLoop:
		for _, field := range st.Fields.List {
			ft := fmt.Sprint(field.Type)
			for _, mixin := range pkg.Mixins {
				if mixin.Name == ft {
					fields = append(fields, mixin.Fields()...)
					for _, mfunc := range pkg.Funcs[mixin.Name] {
						tident := ast.NewIdent(mx.Name())
						tfunc := &ast.FuncDecl{
							Doc: mfunc.Spec.Doc,
							Recv: &ast.FieldList{
								Opening: mfunc.Spec.Recv.Opening,
								List: []*ast.Field{
									&ast.Field{
										Doc:   mfunc.Spec.Recv.List[0].Doc,
										Names: mfunc.Spec.Recv.List[0].Names,
										Type: &ast.Ident{
											NamePos: mfunc.Spec.Recv.List[0].Type.(*ast.Ident).NamePos,
											Name:    mx.Name(),
											Obj:     tident.Obj,
										},
										Tag:     mfunc.Spec.Recv.List[0].Tag,
										Comment: mfunc.Spec.Recv.List[0].Comment,
									},
								},
								Closing: mfunc.Spec.Recv.Closing,
							},
							Name: mfunc.Spec.Name,
							Type: mfunc.Spec.Type,
							Body: mfunc.Spec.Body,
						}
						mx.File().Decls = append(mx.File().Decls, tfunc)
					}
					continue SRFieldLoop
				}
			}
			fields = append(fields, field)
		}
		st.Fields.List = fields
	}
}

func (pkg *Package) exciseMixins() {
	// remove mixins from file
	for _, mixin := range pkg.Mixins {
		decls := []ast.Decl{}
		for _, decl := range mixin.File.Decls {
			if gd, ok := decl.(*ast.GenDecl); ok && gd.Tok == token.TYPE {
				if td, ok := gd.Specs[0].(*ast.TypeSpec); ok && td == mixin.Spec {
				} else {
					decls = append(decls, decl)
				}
			} else {
				decls = append(decls, decl)
			}
		}
		mixin.File.Decls = decls

		for _, mfunc := range pkg.Funcs[mixin.Name] {
			decls = []ast.Decl{}
			for _, decl := range mfunc.File.Decls {
				if fd, ok := decl.(*ast.FuncDecl); ok {
					if fd != mfunc.Spec {
						decls = append(decls, decl)
					}
				} else {
					decls = append(decls, decl)
				}
			}
			mfunc.File.Decls = decls
		}
	}
}

func (pkg *Package) processFile(fset *token.FileSet, file *os.File) error {
	tables, mixins, subrecords := []string{}, []string{}, []string{}
	output := []string{}

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		text := scanner.Text()

		switch {
		case subrecordDef.MatchString(text):
			subrecord := subrecordDef.FindStringSubmatch(text)[1]
			subrecords = append(subrecords, subrecord)
			text = strings.Replace(text, " subrecord ", " struct ", 1)
		case mixinDef.MatchString(text):
			mixin := mixinDef.FindStringSubmatch(text)[1]
			mixins = append(mixins, mixin)
			text = strings.Replace(text, " mixin ", " struct ", 1)
		case tableDef.MatchString(text):
			table := tableDef.FindStringSubmatch(text)[1]
			tables = append(tables, table)
			text = strings.Replace(text, " table ", " struct ", 1)
		}

		output = append(output, text)
	}

	fa, err := parser.ParseFile(fset, file.Name(), strings.Join(output, "\n"), parser.ParseComments)
	if err != nil {
		return err
	}

	active := false
DeclLoop:
	for _, decl := range fa.Decls {
		if gd, ok := decl.(*ast.GenDecl); ok && gd.Tok == token.TYPE {
			if td, ok := gd.Specs[0].(*ast.TypeSpec); ok {
				name := td.Name.Name
				for _, subrecord := range subrecords {
					if subrecord == name {
						pkg.Subrecords = append(pkg.Subrecords, Subrecord{name, td, fa})
						active = true
						continue DeclLoop
					}
				}
				for _, mixin := range mixins {
					if mixin == name {
						pkg.Mixins = append(pkg.Mixins, Mixin{name, td, fa})
						active = true
						continue DeclLoop
					}
				}
				for _, table := range tables {
					if table == name {
						pkg.Tables = append(pkg.Tables, Table{name, td, fa})
						active = true
						continue DeclLoop
					}
				}
			}
		} else if fd, ok := decl.(*ast.FuncDecl); ok {
			if fd.Recv.NumFields() > 0 {
				name := fmt.Sprint(fd.Recv.List[0].Type)
				pkg.Funcs[name] = append(pkg.Funcs[name], Func{name, fd, fa})
			}
		}
	}
	if active {
		pkg.ActiveFiles = append(pkg.ActiveFiles, ActiveFile{file.Name(), fa})
	}

	return nil
}

const (
	GenerateWarning = `/*
  This code was generated from the Doc ORM Generator and isn't meant to be edited.
	If at all possible, please regenerate this file from your gp files instead of
	trying to edit it.
*/`
	BasicScopes = `Eq(vals ...interface{}) %[1]sScope
Neq(vals ...interface{}) %[1]sScope
Gt(vals interface{}) %[1]sScope
Gte(vals interface{}) %[1]sScope
Lt(vals interface{}) %[1]sScope
Lte(vals interface{}) %[1]sScope
Between(lower, upper interface{}) %[1]sScope
In(vals ...interface{}) %[1]sScope
NotIn(vals ...interface{}) %[1]sScope
Order(ordering string) %[1]sScope
Desc() %[1]sScope
Asc() %[1]sScope
Count() int64
Having(sql string, vals ...interface{}) %[1]sScope
// GroupBy(???) %[1]sScope
Limit(limit int64) %[1]sScope
Clear() %[1]sScope
Find(id interface{}) %[1]s
Retrieve() %[1]s
RetrieveAll() []%[1]s
Delete() error
UpdateSQL(sql string, vals ...interface{}) error
PluckString() ([]string, error)
PluckInt() ([]int64, error)
PluckTime() ([]time.Time, error)
PluckStuct(result interface{}) error
SaveAll(vals []%[1]s) error
`
)

func (pkg *Package) WriteSchema() {
	f, err := os.Create(pkg.ActiveFiles[0].AST.Name.Name + "_gen.go")
	if err != nil {
		fmt.Println("Could not write schema file")
	}
	defer f.Close()

	io.WriteString(f, GenerateWarning)
	fmt.Fprintf(f, "\n\npackage %s\n", pkg.ActiveFiles[0].AST.Name.Name)

	pkg.WriteTableScopes(f)
	pkg.WriteConnDefinition(f)

}

// WriteTableScopes writes out the scope definition for each
// of the tables. Some of the scopes are from columsn and others
// are from the base scopes of doc.
func (pkg *Package) WriteTableScopes(f io.Writer) {
	for _, table := range pkg.Tables {
		fmt.Fprintln(f, "*/")
		fmt.Fprintf(f, "type %sScope interface {\n", table.Name())
		for _, field := range table.Spec().Type.(*ast.StructType).Fields.List {
			for _, name := range field.Names {
				fmt.Fprintf(f, "\t%s() %sScope\n", name.Name, table.Name())
			}
		}
		fmt.Fprintf(f, BasicScopes, table.Name())
		fmt.Fprintln(f, "}\n\n")
	}
}

// WriteConnDefinition will build a conn struct that the user can use
// to access the scopes.
func (pkg *Package) WriteConnDefinition(f io.Writer) {
}
<commit_msg>Add imports formatting from go.tools<commit_after>package parse

import (
	"bufio"
	"bytes"
	"fmt"
	"go/ast"
	"go/format"
	"go/parser"
	"go/token"
	"io"
	"log"
	"os"
	"regexp"
	"strings"

	"code.google.com/p/go.tools/imports"
)

var (
	subrecordDef = regexp.MustCompile(`type ([a-zA-Z0-9]+) subrecord {`)
	mixinDef     = regexp.MustCompile(`type ([a-zA-Z0-9]+) mixin {`)
	tableDef     = regexp.MustCompile(`type ([a-zA-Z0-9]+) table {`)
)

func (pkg *Package) ParseSrc(src ...*os.File) error {
	fset := token.NewFileSet()

	// process files
	for _, file := range src {
		err := pkg.processFile(fset, file)
		if err != nil {
			return err
		}
	}

	// process mixins
	pkg.exciseMixins()
	for _, table := range pkg.Tables {
		pkg.processForMixins(table)
	}
	for _, subrecord := range pkg.Subrecords {
		pkg.processForMixins(subrecord)
	}

	// Write out processed files
	for _, active := range pkg.ActiveFiles {
		f, err := os.Create(active.DefName())
		if err != nil {
			return err
		}
		format.Node(f, fset, active.AST)
		f.Close()

	}
	pkg.WriteSchema()

	return nil
}

func (pkg *Package) processForMixins(mx Mixinable) {
	if st, ok := mx.Spec().Type.(*ast.StructType); ok {
		fields := []*ast.Field{}
	SRFieldLoop:
		for _, field := range st.Fields.List {
			ft := fmt.Sprint(field.Type)
			for _, mixin := range pkg.Mixins {
				if mixin.Name == ft {
					fields = append(fields, mixin.Fields()...)
					for _, mfunc := range pkg.Funcs[mixin.Name] {
						tident := ast.NewIdent(mx.Name())
						tfunc := &ast.FuncDecl{
							Doc: mfunc.Spec.Doc,
							Recv: &ast.FieldList{
								Opening: mfunc.Spec.Recv.Opening,
								List: []*ast.Field{
									&ast.Field{
										Doc:   mfunc.Spec.Recv.List[0].Doc,
										Names: mfunc.Spec.Recv.List[0].Names,
										Type: &ast.Ident{
											NamePos: mfunc.Spec.Recv.List[0].Type.(*ast.Ident).NamePos,
											Name:    mx.Name(),
											Obj:     tident.Obj,
										},
										Tag:     mfunc.Spec.Recv.List[0].Tag,
										Comment: mfunc.Spec.Recv.List[0].Comment,
									},
								},
								Closing: mfunc.Spec.Recv.Closing,
							},
							Name: mfunc.Spec.Name,
							Type: mfunc.Spec.Type,
							Body: mfunc.Spec.Body,
						}
						mx.File().Decls = append(mx.File().Decls, tfunc)
					}
					continue SRFieldLoop
				}
			}
			fields = append(fields, field)
		}
		st.Fields.List = fields
	}
}

func (pkg *Package) exciseMixins() {
	// remove mixins from file
	for _, mixin := range pkg.Mixins {
		decls := []ast.Decl{}
		for _, decl := range mixin.File.Decls {
			if gd, ok := decl.(*ast.GenDecl); ok && gd.Tok == token.TYPE {
				if td, ok := gd.Specs[0].(*ast.TypeSpec); ok && td == mixin.Spec {
				} else {
					decls = append(decls, decl)
				}
			} else {
				decls = append(decls, decl)
			}
		}
		mixin.File.Decls = decls

		for _, mfunc := range pkg.Funcs[mixin.Name] {
			decls = []ast.Decl{}
			for _, decl := range mfunc.File.Decls {
				if fd, ok := decl.(*ast.FuncDecl); ok {
					if fd != mfunc.Spec {
						decls = append(decls, decl)
					}
				} else {
					decls = append(decls, decl)
				}
			}
			mfunc.File.Decls = decls
		}
	}
}

func (pkg *Package) processFile(fset *token.FileSet, file *os.File) error {
	tables, mixins, subrecords := []string{}, []string{}, []string{}
	output := []string{}

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		text := scanner.Text()

		switch {
		case subrecordDef.MatchString(text):
			subrecord := subrecordDef.FindStringSubmatch(text)[1]
			subrecords = append(subrecords, subrecord)
			text = strings.Replace(text, " subrecord ", " struct ", 1)
		case mixinDef.MatchString(text):
			mixin := mixinDef.FindStringSubmatch(text)[1]
			mixins = append(mixins, mixin)
			text = strings.Replace(text, " mixin ", " struct ", 1)
		case tableDef.MatchString(text):
			table := tableDef.FindStringSubmatch(text)[1]
			tables = append(tables, table)
			text = strings.Replace(text, " table ", " struct ", 1)
		}

		output = append(output, text)
	}

	fa, err := parser.ParseFile(fset, file.Name(), strings.Join(output, "\n"), parser.ParseComments)
	if err != nil {
		return err
	}

	active := false
DeclLoop:
	for _, decl := range fa.Decls {
		if gd, ok := decl.(*ast.GenDecl); ok && gd.Tok == token.TYPE {
			if td, ok := gd.Specs[0].(*ast.TypeSpec); ok {
				name := td.Name.Name
				for _, subrecord := range subrecords {
					if subrecord == name {
						pkg.Subrecords = append(pkg.Subrecords, Subrecord{name, td, fa})
						active = true
						continue DeclLoop
					}
				}
				for _, mixin := range mixins {
					if mixin == name {
						pkg.Mixins = append(pkg.Mixins, Mixin{name, td, fa})
						active = true
						continue DeclLoop
					}
				}
				for _, table := range tables {
					if table == name {
						pkg.Tables = append(pkg.Tables, Table{name, td, fa})
						active = true
						continue DeclLoop
					}
				}
			}
		} else if fd, ok := decl.(*ast.FuncDecl); ok {
			if fd.Recv.NumFields() > 0 {
				name := fmt.Sprint(fd.Recv.List[0].Type)
				pkg.Funcs[name] = append(pkg.Funcs[name], Func{name, fd, fa})
			}
		}
	}
	if active {
		pkg.ActiveFiles = append(pkg.ActiveFiles, ActiveFile{file.Name(), fa})
	}

	return nil
}

const (
	GenerateWarning = `/*
  This code was generated from the Doc ORM Generator and isn't meant to be edited.
	If at all possible, please regenerate this file from your gp files instead of
	trying to edit it.
*/`
	BasicScopes = `Eq(vals ...interface{}) %[1]sScope
Neq(vals ...interface{}) %[1]sScope
Gt(vals interface{}) %[1]sScope
Gte(vals interface{}) %[1]sScope
Lt(vals interface{}) %[1]sScope
Lte(vals interface{}) %[1]sScope
Between(lower, upper interface{}) %[1]sScope
In(vals ...interface{}) %[1]sScope
NotIn(vals ...interface{}) %[1]sScope
Order(ordering string) %[1]sScope
Desc() %[1]sScope
Asc() %[1]sScope
Count() int64
Having(sql string, vals ...interface{}) %[1]sScope
// GroupBy(???) %[1]sScope
Limit(limit int64) %[1]sScope
Clear() %[1]sScope
Find(id interface{}) %[1]s
Retrieve() %[1]s
RetrieveAll() []%[1]s
Delete() error
UpdateSQL(sql string, vals ...interface{}) error
PluckString() ([]string, error)
PluckInt() ([]int64, error)
PluckTime() ([]time.Time, error)
PluckStuct(result interface{}) error
SaveAll(vals []%[1]s) error
`
)

func (pkg *Package) WriteSchema() {
	b := &bytes.Buffer{}
	io.WriteString(b, GenerateWarning)
	fmt.Fprintf(b, "\n\npackage %s\n", pkg.ActiveFiles[0].AST.Name.Name)

	pkg.WriteTableScopes(b)
	pkg.WriteConnDefinition(b)

	f, err := os.Create(pkg.ActiveFiles[0].AST.Name.Name + "_gen.go")
	if err != nil {
		fmt.Println("Could not write schema file")
	}
	defer f.Close()

	ib, err := imports.Process(pkg.ActiveFiles[0].AST.Name.Name+"_gen.go", b.Bytes(), nil)
	if err != nil {
		log.Fatal(err)
	}

	f.Write(ib)
}

// WriteTableScopes writes out the scope definition for each
// of the tables. Some of the scopes are from columsn and others
// are from the base scopes of doc.
func (pkg *Package) WriteTableScopes(f io.Writer) {
	for _, table := range pkg.Tables {
		fmt.Fprintf(f, "type %sScope interface {\n", table.Name())
		for _, field := range table.Spec().Type.(*ast.StructType).Fields.List {
			for _, name := range field.Names {
				fmt.Fprintf(f, "\t%s() %sScope\n", name.Name, table.Name())
			}
		}
		fmt.Fprintf(f, BasicScopes, table.Name())
		fmt.Fprintln(f, "}\n\n")
	}
}

// WriteConnDefinition will build a conn struct that the user can use
// to access the scopes.
func (pkg *Package) WriteConnDefinition(f io.Writer) {
	io.WriteString(f, "type Conn struct {\n")
	for _, table := range pkg.Tables {
		fmt.Fprintf(f, "\t%[1]s  %[1]sScope\n", table.Name())
	}
	io.WriteString(f, "}\n\n")
}
<|endoftext|>


<commit_before>package flickr

import (
	"bytes"
	"io"
	"mime/multipart"
	"os"
	"path/filepath"
	"strconv"
	"strings"
)

// Encode the file and request parameters in a multipart body
func getUploadBody(client *FlickrClient, photo io.Reader, fileName string) (*bytes.Buffer, string, error) {
	// instance an empty request body
	body := &bytes.Buffer{}
	// multipart writer to fill the body
	writer := multipart.NewWriter(body)
	// dump the file in the "photo" field
	part, err := writer.CreateFormFile("photo", filepath.Base(fileName))
	if err != nil {
		return nil, "", err
	}
	_, err = io.Copy(part, photo)
	// dump other params
	for key, val := range client.Args {
		_ = writer.WriteField(key, val[0])
	}
	err = writer.Close()
	if err != nil {
		return nil, "", err
	}
	// evaluate the content type and the boundary
	contentType := writer.FormDataContentType()

	return body, contentType, nil
}

// A convenience struct wrapping all optional upload parameters
type UploadParams struct {
	Title, Description           string
	Tags                         []string
	IsPublic, IsFamily, IsFriend bool
	ContentType                  int
	Hidden                       int
	SafetyLevel                  int
}

// Provide meaningful default values
func NewUploadParams() *UploadParams {
	ret := &UploadParams{}
	ret.ContentType = 1 // photo
	ret.Hidden = 2      // hidden from public searchesi
	ret.SafetyLevel = 1 // safe
	return ret
}

// Type representing a successful upload response from the api
type UploadResponse struct {
	BasicResponse
	Id string `xml:"photoid"`
}

// Set client query arguments based on the contents of the UploadParams struct
func fillArgsWithParams(client *FlickrClient, params *UploadParams) {
	if params.Title != "" {
		client.Args.Set("title", params.Title)
	}

	if params.Description != "" {
		client.Args.Set("description", params.Description)
	}

	if len(params.Tags) > 0 {
		client.Args.Set("tags", strings.Join(params.Tags, " "))
	}

	var boolString = func(b bool) string {
		if b {
			return "1"
		}
		return "0"
	}
	client.Args.Set("is_public", boolString(params.IsPublic))
	client.Args.Set("is_friend", boolString(params.IsFriend))
	client.Args.Set("is_family", boolString(params.IsFamily))

	if params.ContentType >= 1 && params.ContentType <= 3 {
		client.Args.Set("content_type", strconv.Itoa(params.ContentType))
	}

	if params.Hidden >= 1 && params.Hidden <= 2 {
		client.Args.Set("hidden", strconv.Itoa(params.Hidden))
	}

	if params.SafetyLevel >= 1 && params.SafetyLevel <= 3 {
		client.Args.Set("safety_level", strconv.Itoa(params.SafetyLevel))
	}
}

// Perform a file upload using the Flickr API. If optionalParams is nil,
// no parameters will be added to the request and Flickr will set User's
// default preferences.
// This call must be signed with write permissions
func UploadFile(client *FlickrClient, path string, optionalParams *UploadParams) (*UploadResponse, error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	return UploadReader(client, file, file.Name(), optionalParams)
}

//
func UploadReader(client *FlickrClient, photoReader io.Reader, name string, optionalParams *UploadParams) (*UploadResponse, error) {
	client.Init()
	client.EndpointUrl = UPLOAD_ENDPOINT
	client.HTTPVerb = "POST"

	if optionalParams != nil {
		fillArgsWithParams(client, optionalParams)
	}

	client.OAuthSign()

	body, ctype, err := getUploadBody(client, photoReader, name)
	if err != nil {
		return nil, err
	}

	resp := &UploadResponse{}
	err = DoPostBody(client, body, ctype, resp)
	return resp, err
}
<commit_msg>upload refactoring using io.Pipe<commit_after>package flickr

import (
	"crypto/rand"
	"fmt"
	"io"
	"log"
	"mime/multipart"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
	"strings"
)

func randomBoundary() string {
	var buf [30]byte
	_, err := io.ReadFull(rand.Reader, buf[:])
	if err != nil {
		panic(err)
	}
	return fmt.Sprintf("%x", buf[:])
}

// Encode the file and request parameters in a multipart body
func streamUploadBody(client *FlickrClient, photo io.Reader, body *io.PipeWriter, fileName string, boundary string) {
	// multipart writer to fill the body
	defer body.Close()
	writer := multipart.NewWriter(body)
	writer.SetBoundary(boundary)

	// create the "photo" field
	part, err := writer.CreateFormFile("photo", filepath.Base(fileName))
	if err != nil {
		log.Fatal(err)
		return
	}

	// fill the photo field
	_, err = io.Copy(part, photo)
	if err != nil {
		log.Fatal(err)
		return
	}

	// dump other params
	for key, val := range client.Args {
		_ = writer.WriteField(key, val[0])
	}

	// close the form writer
	err = writer.Close()
	if err != nil {
		log.Fatal(err)
		return
	}
}

// A convenience struct wrapping all optional upload parameters
type UploadParams struct {
	Title, Description           string
	Tags                         []string
	IsPublic, IsFamily, IsFriend bool
	ContentType                  int
	Hidden                       int
	SafetyLevel                  int
}

// Provide meaningful default values
func NewUploadParams() *UploadParams {
	ret := &UploadParams{}
	ret.ContentType = 1 // photo
	ret.Hidden = 2      // hidden from public searchesi
	ret.SafetyLevel = 1 // safe
	return ret
}

// Type representing a successful upload response from the api
type UploadResponse struct {
	BasicResponse
	Id string `xml:"photoid"`
}

// Set client query arguments based on the contents of the UploadParams struct
func fillArgsWithParams(client *FlickrClient, params *UploadParams) {
	if params.Title != "" {
		client.Args.Set("title", params.Title)
	}

	if params.Description != "" {
		client.Args.Set("description", params.Description)
	}

	if len(params.Tags) > 0 {
		client.Args.Set("tags", strings.Join(params.Tags, " "))
	}

	var boolString = func(b bool) string {
		if b {
			return "1"
		}
		return "0"
	}
	client.Args.Set("is_public", boolString(params.IsPublic))
	client.Args.Set("is_friend", boolString(params.IsFriend))
	client.Args.Set("is_family", boolString(params.IsFamily))

	if params.ContentType >= 1 && params.ContentType <= 3 {
		client.Args.Set("content_type", strconv.Itoa(params.ContentType))
	}

	if params.Hidden >= 1 && params.Hidden <= 2 {
		client.Args.Set("hidden", strconv.Itoa(params.Hidden))
	}

	if params.SafetyLevel >= 1 && params.SafetyLevel <= 3 {
		client.Args.Set("safety_level", strconv.Itoa(params.SafetyLevel))
	}
}

// Perform a file upload using the Flickr API. If optionalParams is nil,
// no parameters will be added to the request and Flickr will set User's
// default preferences.
// This call must be signed with write permissions
func UploadFile(client *FlickrClient, path string, optionalParams *UploadParams) (*UploadResponse, error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	return UploadReader(client, file, file.Name(), optionalParams)
}

//
func UploadReader(client *FlickrClient, photoReader io.Reader, name string, optionalParams *UploadParams) (*UploadResponse, error) {
	client.Init()
	client.EndpointUrl = UPLOAD_ENDPOINT
	client.HTTPVerb = "POST"

	if optionalParams != nil {
		fillArgsWithParams(client, optionalParams)
	}

	client.OAuthSign()

	// write request body in a Pipe
	boundary := randomBoundary()
	r, w := io.Pipe()
	go streamUploadBody(client, photoReader, w, name, boundary)

	// create an HTTP Request
	req, err := http.NewRequest("POST", client.EndpointUrl, r)
	if err != nil {
		return nil, err
	}

	// set content-type
	req.Header.Set("Content-Type", "multipart/form-data; boundary="+boundary)

	// instance HTTP client
	http_client := &http.Client{}
	resp, err := http_client.Do(req)
	if err != nil {
		return nil, err
	}

	api_resp := &UploadResponse{}
	err = parseApiResponse(resp, api_resp)
	return api_resp, err
}
<|endoftext|>