<commit_before>package column

import (
	"fmt"
	"reflect"
)

// Index is used to efficiently find the value for a database column
// in the associated field within a structure.
// In most cases an index is a single integer, which
// represents the index of the relevant field in the structure. In the
// case of fields in embedded structs, a field index consists of more than
// one integer.
type Index []int

// NewIndex returns an index with the specified values.
func NewIndex(vals ...int) Index {
	return Index(vals)
}

// Append a number to an existing index to create
// a new index. The original index ix is unchanged.
//
// If ix is nil, then Append returns an index
// with a single index value.
func (ix Index) Append(index int) Index {
	clone := ix.Clone()
	return append(clone, index)
}

// Clone creates a deep copy of ix.
func (ix Index) Clone() Index {
	// Because the main purpose of cloning is to append
	// another index, create the cloned field index to be
	// the same length, but with capacity for an additional index.
	clone := make(Index, len(ix), len(ix)+1)
	copy(clone, ix)
	return clone
}

// Equal returns true if ix is equal to v.
func (ix Index) Equal(v Index) bool {
	if len(ix) != len(v) {
		return false
	}
	for i := range ix {
		if ix[i] != v[i] {
			return false
		}
	}
	return true
}

// ValueRW returns the value of the field from the structure v.
// If any referenced field in v contains a nil pointer, then an
// empty value is created.
func (ix Index) ValueRW(v reflect.Value) reflect.Value {
	for _, i := range ix {
		v = reflect.Indirect(v).Field(i)
		// Create empty value for nil pointers, maps and slices.
		if v.Kind() == reflect.Ptr && v.IsNil() {
			a := reflect.New(v.Type().Elem())
			fmt.Printf("new a: %v\n", a.Type())
			v.Set(a)
		} else if v.Kind() == reflect.Map && v.IsNil() {
			v.Set(reflect.MakeMap(v.Type()))
		} else if v.Kind() == reflect.Slice && v.IsNil() {
			v.Set(reflect.MakeSlice(v.Type(), 0, 0))
		}
	}
	return v
}

// ValueRO returns a value from the structure v without
// checking for nil pointers.
func (ix Index) ValueRO(v reflect.Value) reflect.Value {
	for _, i := range ix {
		v = reflect.Indirect(v).Field(i)
	}
	return v
}
<commit_msg>Remove printf used for debugging.<commit_after>package column

import (
	"reflect"
)

// Index is used to efficiently find the value for a database column
// in the associated field within a structure.
// In most cases an index is a single integer, which
// represents the index of the relevant field in the structure. In the
// case of fields in embedded structs, a field index consists of more than
// one integer.
type Index []int

// NewIndex returns an index with the specified values.
func NewIndex(vals ...int) Index {
	return Index(vals)
}

// Append a number to an existing index to create
// a new index. The original index ix is unchanged.
//
// If ix is nil, then Append returns an index
// with a single index value.
func (ix Index) Append(index int) Index {
	clone := ix.Clone()
	return append(clone, index)
}

// Clone creates a deep copy of ix.
func (ix Index) Clone() Index {
	// Because the main purpose of cloning is to append
	// another index, create the cloned field index to be
	// the same length, but with capacity for an additional index.
	clone := make(Index, len(ix), len(ix)+1)
	copy(clone, ix)
	return clone
}

// Equal returns true if ix is equal to v.
func (ix Index) Equal(v Index) bool {
	if len(ix) != len(v) {
		return false
	}
	for i := range ix {
		if ix[i] != v[i] {
			return false
		}
	}
	return true
}

// ValueRW returns the value of the field from the structure v.
// If any referenced field in v contains a nil pointer, then an
// empty value is created.
func (ix Index) ValueRW(v reflect.Value) reflect.Value {
	for _, i := range ix {
		v = reflect.Indirect(v).Field(i)
		// Create empty value for nil pointers, maps and slices.
		if v.Kind() == reflect.Ptr && v.IsNil() {
			a := reflect.New(v.Type().Elem())
			v.Set(a)
		} else if v.Kind() == reflect.Map && v.IsNil() {
			v.Set(reflect.MakeMap(v.Type()))
		} else if v.Kind() == reflect.Slice && v.IsNil() {
			v.Set(reflect.MakeSlice(v.Type(), 0, 0))
		}
	}
	return v
}

// ValueRO returns a value from the structure v without
// checking for nil pointers.
func (ix Index) ValueRO(v reflect.Value) reflect.Value {
	for _, i := range ix {
		v = reflect.Indirect(v).Field(i)
	}
	return v
}
<|endoftext|>


<commit_before>// Copyright © 2015-2017 Hilko Bengen <bengen@hilluzination.de>
// All rights reserved.
//
// Use of this source code is governed by the license that can be
// found in the LICENSE file.

//+build !yara3.3,!yara3.4,!yara3.5,!yara3.6

package yara

/*
#include <yara.h>
#include <stdlib.h>

char* includeCallback(char*, char*, char*, void*);
void freeCallback(char*, void*);
*/
import "C"
import (
	"unsafe"
)

// CompilerIncludeFunc is the type of the function that can be
// registered through SetIncludeCallback. It is called for every
// include statement encountered by the compiler. The argument "name"
// specifies the rule file to be included, "filename" specifies the
// name of the rule file where the include statement has been
// encountered, and "namespace" specifies the rule namespace. The sole
// return value is a byte slice containing the contents of the
// included file. A return value of nil signals an error to the YARA
// compiler.
//
// See yr_compiler_set_include_callback
type CompilerIncludeFunc func(name, filename, namespace string) []byte

// DisableIncludes disables all include statements in the compiler.
// See yr_compiler_set_include_callbacks.
func (c *Compiler) DisableIncludes() {
	C.yr_compiler_set_include_callback(c.compiler.cptr, nil, nil, nil)
	keepAlive(c)
	return
}

//export includeCallback
func includeCallback(name, filename, namespace *C.char, user_data unsafe.Pointer) *C.char {
	id := *((*uintptr)(user_data))
	callbackFunc := callbackData.Get(id).(CompilerIncludeFunc)
	if buf := callbackFunc(
		C.GoString(name), C.GoString(filename), C.GoString(namespace),
	); buf != nil {
		buf = append(buf, 0)
		return (*C.char)(C.CBytes(buf))
	}
	return nil
}

//export freeCallback
func freeCallback(callback_result_ptr *C.char, user_data unsafe.Pointer) {
	if callback_result_ptr != nil {
		C.free(unsafe.Pointer(callback_result_ptr))
	}
	return
}

// SetIncludeCallback sets up cb as an include callback that is called
// (through Go glue code) by the YARA compiler for every include
// statement.
func (c *Compiler) SetIncludeCallback(cb CompilerIncludeFunc) {
	if cb == nil {
		c.DisableIncludes()
		return
	}
	id := callbackData.Put(cb)
	C.yr_compiler_set_include_callback(
		c.compiler.cptr,
		C.YR_COMPILER_INCLUDE_CALLBACK_FUNC(C.includeCallback),
		C.YR_COMPILER_INCLUDE_FREE_FUNC(C.freeCallback),
		unsafe.Pointer(&id),
	)
	keepAlive(c)
	return
}
<commit_msg>Make include callback functionality compatible with Go 1.6<commit_after>// Copyright © 2015-2017 Hilko Bengen <bengen@hilluzination.de>
// All rights reserved.
//
// Use of this source code is governed by the license that can be
// found in the LICENSE file.

//+build !yara3.3,!yara3.4,!yara3.5,!yara3.6

package yara

/*
#include <yara.h>
#include <stdlib.h>
#include <string.h>

char* includeCallback(char*, char*, char*, void*);
void freeCallback(char*, void*);
*/
import "C"
import (
	"unsafe"
)

// CompilerIncludeFunc is the type of the function that can be
// registered through SetIncludeCallback. It is called for every
// include statement encountered by the compiler. The argument "name"
// specifies the rule file to be included, "filename" specifies the
// name of the rule file where the include statement has been
// encountered, and "namespace" specifies the rule namespace. The sole
// return value is a byte slice containing the contents of the
// included file. A return value of nil signals an error to the YARA
// compiler.
//
// See yr_compiler_set_include_callback
type CompilerIncludeFunc func(name, filename, namespace string) []byte

// DisableIncludes disables all include statements in the compiler.
// See yr_compiler_set_include_callbacks.
func (c *Compiler) DisableIncludes() {
	C.yr_compiler_set_include_callback(c.compiler.cptr, nil, nil, nil)
	keepAlive(c)
	return
}

//export includeCallback
func includeCallback(name, filename, namespace *C.char, user_data unsafe.Pointer) *C.char {
	id := *((*uintptr)(user_data))
	callbackFunc := callbackData.Get(id).(CompilerIncludeFunc)
	if buf := callbackFunc(
		C.GoString(name), C.GoString(filename), C.GoString(namespace),
	); buf != nil {
		outbuf := C.calloc(1, C.size_t(len(buf)+1))
		C.memcpy(outbuf, unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
		return (*C.char)(outbuf)
	}
	return nil
}

//export freeCallback
func freeCallback(callback_result_ptr *C.char, user_data unsafe.Pointer) {
	if callback_result_ptr != nil {
		C.free(unsafe.Pointer(callback_result_ptr))
	}
	return
}

// SetIncludeCallback sets up cb as an include callback that is called
// (through Go glue code) by the YARA compiler for every include
// statement.
func (c *Compiler) SetIncludeCallback(cb CompilerIncludeFunc) {
	if cb == nil {
		c.DisableIncludes()
		return
	}
	id := callbackData.Put(cb)
	C.yr_compiler_set_include_callback(
		c.compiler.cptr,
		C.YR_COMPILER_INCLUDE_CALLBACK_FUNC(C.includeCallback),
		C.YR_COMPILER_INCLUDE_FREE_FUNC(C.freeCallback),
		unsafe.Pointer(&id),
	)
	keepAlive(c)
	return
}
<|endoftext|>


<commit_before>package boardgame

//TODO: consider making ComponentChest be an interface again (in some cases it
//might be nice to be able to cast the Deck directly to its underlying type to
//minimize later casts)

//Each game has one ComponentChest, which is an immutable set of all
//components in this game, configured into 0 or more Decks. A chest has two
//phases: construction and serving. During consruction, decks may be added but
//non may be retrieved. After consruction decks may be retrieved but not
//added. This helps ensure that Decks always give a consistent view of the
//world.
type ComponentChest struct {
	initialized bool
	deckNames   []string
	decks       map[string]*Deck
	enums       *EnumSet

	manager *GameManager
}

func NewComponentChest(enums *EnumSet) *ComponentChest {
	if enums == nil {
		enums = NewEnumSet()
	}
	enums.Finish()
	return &ComponentChest{
		enums: enums,
	}
}

func (c *ComponentChest) Enums() *EnumSet {
	return c.enums
}

func (c *ComponentChest) Manager() *GameManager {
	return c.manager
}

//DeckNames returns all of the valid deck names, if the chest has finished initalization.
func (c *ComponentChest) DeckNames() []string {
	//If it's not finished being initalized then no decks are valid.
	if !c.initialized {
		return nil
	}
	return c.deckNames
}

//Deck returns the deck with a given name, if the chest has finished initalization.
func (c *ComponentChest) Deck(name string) *Deck {
	if !c.initialized {
		return nil
	}
	return c.decks[name]
}

//AddDeck adds a deck with a given name, but only if Freeze() has not yet been called.
func (c *ComponentChest) AddDeck(name string, deck *Deck) {
	//Only add the deck if we haven't finished initalizing
	if c.initialized {
		return
	}
	if c.decks == nil {
		c.decks = make(map[string]*Deck)
	}

	if name == "" {
		name = "NONAMEPROVIDED"
	}

	//Tell the deck that no more items will be added to it.
	deck.finish(c, name)

	c.decks[name] = deck

}

//Finish switches the chest from constructing to serving. Before freeze is
//called, decks may be added but not retrieved. After it is called, decks may
//be retrieved but not added. Finish() is called automatically when a Chest is
//added to a game via SetChest(), but you can call it before then if you'd
//like.
func (c *ComponentChest) Finish() {

	//Check if Finish() has already been called
	if c.initialized {
		return
	}

	c.initialized = true

	//Now that no more decks are coming, we can create deckNames once and be
	//done with it.
	c.deckNames = make([]string, len(c.decks))

	i := 0

	for name, _ := range c.decks {
		c.deckNames[i] = name
		i++
	}
}
<commit_msg>Updated doc for NewComponentChest. Part of #457.<commit_after>package boardgame

//TODO: consider making ComponentChest be an interface again (in some cases it
//might be nice to be able to cast the Deck directly to its underlying type to
//minimize later casts)

//Each game has one ComponentChest, which is an immutable set of all
//components in this game, configured into 0 or more Decks. A chest has two
//phases: construction and serving. During consruction, decks may be added but
//non may be retrieved. After consruction decks may be retrieved but not
//added. This helps ensure that Decks always give a consistent view of the
//world.
type ComponentChest struct {
	initialized bool
	deckNames   []string
	decks       map[string]*Deck
	enums       *EnumSet

	manager *GameManager
}

//NewComponentChest returns a new ComponentChest with the given enumset. If no
//enumset is provided, an empty one will be created. Calls Finish() on the
//enumset to verify that it cannot be modified.
func NewComponentChest(enums *EnumSet) *ComponentChest {
	if enums == nil {
		enums = NewEnumSet()
	}
	enums.Finish()
	return &ComponentChest{
		enums: enums,
	}
}

func (c *ComponentChest) Enums() *EnumSet {
	return c.enums
}

func (c *ComponentChest) Manager() *GameManager {
	return c.manager
}

//DeckNames returns all of the valid deck names, if the chest has finished initalization.
func (c *ComponentChest) DeckNames() []string {
	//If it's not finished being initalized then no decks are valid.
	if !c.initialized {
		return nil
	}
	return c.deckNames
}

//Deck returns the deck with a given name, if the chest has finished initalization.
func (c *ComponentChest) Deck(name string) *Deck {
	if !c.initialized {
		return nil
	}
	return c.decks[name]
}

//AddDeck adds a deck with a given name, but only if Freeze() has not yet been called.
func (c *ComponentChest) AddDeck(name string, deck *Deck) {
	//Only add the deck if we haven't finished initalizing
	if c.initialized {
		return
	}
	if c.decks == nil {
		c.decks = make(map[string]*Deck)
	}

	if name == "" {
		name = "NONAMEPROVIDED"
	}

	//Tell the deck that no more items will be added to it.
	deck.finish(c, name)

	c.decks[name] = deck

}

//Finish switches the chest from constructing to serving. Before freeze is
//called, decks may be added but not retrieved. After it is called, decks may
//be retrieved but not added. Finish() is called automatically when a Chest is
//added to a game via SetChest(), but you can call it before then if you'd
//like.
func (c *ComponentChest) Finish() {

	//Check if Finish() has already been called
	if c.initialized {
		return
	}

	c.initialized = true

	//Now that no more decks are coming, we can create deckNames once and be
	//done with it.
	c.deckNames = make([]string, len(c.decks))

	i := 0

	for name, _ := range c.decks {
		c.deckNames[i] = name
		i++
	}
}
<|endoftext|>


<commit_before>package main

import (
	"code.google.com/p/go.net/websocket"
	"fmt"
	"io"
	"net/http"
	"os"
)

func startTail(file string, ch chan string) error {
	f, err := os.Open(file)
	if err != nil {
		return err
	}
	fileInfo, err := f.Stat()
	if err != nil {
		return err
	}
	fileSize := fileInfo.Size()
	var bufSizeMax int64 = 1024
	var bufSize int64
	if fileSize > bufSizeMax {
		bufSize = bufSizeMax
	} else {
		bufSize = fileSize
	}
	go func() {
		fmt.Println("tail start")
		ch <- file
		buf := make([]byte, bufSize)
		var offset int64 = 0
		{
			n, err := f.ReadAt(buf, offset+bufSize)
			if err != nil && err != io.EOF {
				panic("reader.ReadString(): " + err.Error())
			}
			line := string(buf[0:n])
			fmt.Printf("read[%v:%v]\n", n, line)
			ch <- line
		}
		for {
			n, err := f.Read(buf)
			if err == io.EOF && n == 0 {
				continue
			}
			if err != nil {
				panic("reader.ReadString(): " + err.Error())
			}
			line := string(buf[0:n])
			fmt.Printf("read[%v:%v]\n", n, line)
			ch <- line
		}
		fmt.Println("tail end")
	}()
	return nil
}

func makeWebsocketHandlerWithChannel(ch chan string, f func(chan string, *websocket.Conn)) func(*websocket.Conn) {
	return func(ws *websocket.Conn) {
		f(ch, ws)
	}
}

type Data struct {
	Key   string `json:"key"`
	Value string `json:"value"`
}

func websocketTailHandler(ch chan string, ws *websocket.Conn) {
	fmt.Printf("tailHandler %v\n", ws)
	// send first line as file name
	fileName := <-ch
	if err := websocket.JSON.Send(ws, Data{"filename", fileName}); err != nil {
		fmt.Println("ERR:websoket.Message.Send(): " + err.Error())
	}
	for {
		line := <-ch
		if err := websocket.JSON.Send(ws, Data{"msg", line}); err != nil {
			fmt.Println("ERR:websoket.Message.Send(): " + err.Error())
		}
		fmt.Printf("tailHandler write[%v]\n", line)
	}
	fmt.Println("tailHandler finished")
}

// for debug
func pseudoSubscriber(ch chan string) {
	for {
		line := <-ch
		fmt.Println("[sub]: " + line)
	}
}

func main() {
	ch := make(chan string)
	http.Handle("/tail", websocket.Handler(makeWebsocketHandlerWithChannel(ch, websocketTailHandler)))
	http.Handle("/", http.FileServer(http.Dir("../view")))

	if err := startTail(os.Args[1], ch); err != nil {
		panic(err)
	}

	fmt.Println("start wstail...")
	err := http.ListenAndServe(":23456", nil)
	if err != nil {
		panic("ListenAndServe: " + err.Error())
	}
	//pseudoSubscriber(ch)
}
<commit_msg>add view-dir flag<commit_after>package main

import (
	"code.google.com/p/go.net/websocket"
	"flag"
	//"fmt"
	//"html/template"
	"io"
	"log"
	"net/http"
	"os"
)

var (
	viewDir = flag.String("view-dir", "", "path to view directory")
)

/*
var templates *template.Template

func loadTemplate() error {
	var err error
	t := template.New("wstail")
	templates, err = t.ParseGlob(fmt.Sprintf("%s/*.html", *viewDir))
	if err != nil {
		return err
	}
	return nil
}
*/
func startTail(file string, ch chan string) error {
	f, err := os.Open(file)
	if err != nil {
		return err
	}
	fileInfo, err := f.Stat()
	if err != nil {
		return err
	}
	fileSize := fileInfo.Size()
	var bufSizeMax int64 = 1024
	var bufSize int64
	if fileSize > bufSizeMax {
		bufSize = bufSizeMax
	} else {
		bufSize = fileSize
	}
	go func() {
		log.Println("tail start")
		ch <- file
		buf := make([]byte, bufSize)
		var offset int64 = 0
		{
			n, err := f.ReadAt(buf, offset+bufSize)
			if err != nil && err != io.EOF {
				panic("reader.ReadString(): " + err.Error())
			}
			line := string(buf[0:n])
			log.Printf("read[%v:%v]\n", n, line)
			ch <- line
		}
		for {
			n, err := f.Read(buf)
			if err == io.EOF && n == 0 {
				continue
			}
			if err != nil {
				panic("reader.ReadString(): " + err.Error())
			}
			line := string(buf[0:n])
			log.Printf("read[%v:%v]\n", n, line)
			ch <- line
		}
		log.Println("tail end")
	}()
	return nil
}

func makeWebsocketHandlerWithChannel(ch chan string, f func(chan string, *websocket.Conn)) func(*websocket.Conn) {
	return func(ws *websocket.Conn) {
		f(ch, ws)
	}
}

type Data struct {
	Key   string `json:"key"`
	Value string `json:"value"`
}

func websocketTailHandler(ch chan string, ws *websocket.Conn) {
	log.Printf("tailHandler %v\n", ws)
	// send first line as file name
	fileName := <-ch
	if err := websocket.JSON.Send(ws, Data{"filename", fileName}); err != nil {
		log.Println("ERR:websoket.Message.Send(): " + err.Error())
	}
	for {
		line := <-ch
		if err := websocket.JSON.Send(ws, Data{"msg", line}); err != nil {
			log.Println("ERR:websoket.Message.Send(): " + err.Error())
		}
		log.Printf("tailHandler write[%v]\n", line)
	}
	log.Println("tailHandler finished")
}

// for debug
func pseudoSubscriber(ch chan string) {
	for {
		line := <-ch
		log.Println("[sub]: " + line)
	}
}

func main() {
	flag.Parse()
	if *viewDir == "" {
		for _, defaultPath := range []string{"../view", "view", "/usr/local/share/wstail/view"} {
			if info, err := os.Stat(defaultPath); err == nil && info.IsDir() {
				*viewDir = defaultPath
				break
			}
		}
	}
	if *viewDir == "" {
		log.Fatalf("view dir not found")
	}
	//loadTemplate()

	ch := make(chan string)
	http.Handle("/tail", websocket.Handler(makeWebsocketHandlerWithChannel(ch, websocketTailHandler)))
	http.Handle("/", http.FileServer(http.Dir(*viewDir)))

	file := flag.Args()[0]
	if err := startTail(file, ch); err != nil {
		panic(err)
	}

	log.Println("start wstail...")
	err := http.ListenAndServe(":23456", nil)
	if err != nil {
		panic("ListenAndServe: " + err.Error())
	}
	//pseudoSubscriber(ch)
}
<|endoftext|>


<commit_before>package storage

import (
	"io"
	"time"

	"github.com/lxc/lxd/lxd/backup"
	"github.com/lxc/lxd/lxd/cluster/request"
	"github.com/lxc/lxd/lxd/instance"
	"github.com/lxc/lxd/lxd/migration"
	"github.com/lxc/lxd/lxd/operations"
	"github.com/lxc/lxd/lxd/revert"
	"github.com/lxc/lxd/lxd/state"
	"github.com/lxc/lxd/lxd/storage/drivers"
	"github.com/lxc/lxd/shared/api"
	"github.com/lxc/lxd/shared/instancewriter"
	"github.com/lxc/lxd/shared/logger"
)

type mockBackend struct {
	name   string
	state  *state.State
	logger logger.Logger
	driver drivers.Driver
}

func (b *mockBackend) ID() int64 {
	return 1 //  The tests expect the storage pool ID to be 1.
}

func (b *mockBackend) Name() string {
	return b.name
}

func (b *mockBackend) Description() string {
	return ""
}

func (b *mockBackend) ValidateName(value string) error {
	return nil
}

func (b *mockBackend) Validate(config map[string]string) error {
	return nil
}

func (b *mockBackend) Status() string {
	return api.NetworkStatusUnknown
}

func (b *mockBackend) LocalStatus() string {
	return api.NetworkStatusUnknown
}

func (b *mockBackend) ToAPI() api.StoragePool {
	return api.StoragePool{}
}

func (b *mockBackend) Driver() drivers.Driver {
	return b.driver
}

func (b *mockBackend) MigrationTypes(contentType drivers.ContentType, refresh bool) []migration.Type {
	return []migration.Type{
		{
			FSType:   FallbackMigrationType(contentType),
			Features: []string{"xattrs", "delete", "compress", "bidirectional"},
		},
	}
}

func (b *mockBackend) GetResources() (*api.ResourcesStoragePool, error) {
	return nil, nil
}

func (b *mockBackend) IsUsed() (bool, error) {
	return false, nil
}

func (b *mockBackend) Delete(clientType request.ClientType, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) Update(clientType request.ClientType, newDescription string, newConfig map[string]string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) Create(clientType request.ClientType, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) Mount() (bool, error) {
	return true, nil
}

func (b *mockBackend) Unmount() (bool, error) {
	return true, nil
}

func (b *mockBackend) ApplyPatch(name string) error {
	return nil
}

func (b *mockBackend) GetVolume(volType drivers.VolumeType, contentType drivers.ContentType, volName string, volConfig map[string]string) drivers.Volume {
	return drivers.Volume{}
}

func (b *mockBackend) CreateInstance(inst instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateInstanceFromBackup(srcBackup backup.Info, srcData io.ReadSeeker, op *operations.Operation) (func(instance.Instance) error, revert.Hook, error) {
	return nil, nil, nil
}

func (b *mockBackend) CreateInstanceFromCopy(inst instance.Instance, src instance.Instance, snapshots bool, allowInconsistent bool, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateInstanceFromImage(inst instance.Instance, fingerprint string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateInstanceFromMigration(inst instance.Instance, conn io.ReadWriteCloser, args migration.VolumeTargetArgs, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RenameInstance(inst instance.Instance, newName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) DeleteInstance(inst instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) UpdateInstance(inst instance.Instance, newDesc string, newConfig map[string]string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) GenerateInstanceBackupConfig(inst instance.Instance, snapshots bool, op *operations.Operation) (*backup.Config, error) {
	return nil, nil
}

func (b *mockBackend) UpdateInstanceBackupFile(inst instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CheckInstanceBackupFileSnapshots(backupConf *backup.Config, projectName string, deleteMissing bool, op *operations.Operation) ([]*api.InstanceSnapshot, error) {
	return nil, nil
}

func (b *mockBackend) ListUnknownVolumes(op *operations.Operation) (map[string][]*backup.Config, error) {
	return nil, nil
}

func (b *mockBackend) ImportInstance(inst instance.Instance, poolVol *backup.Config, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) MigrateInstance(inst instance.Instance, conn io.ReadWriteCloser, args *migration.VolumeSourceArgs, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RefreshCustomVolume(projectName string, srcProjectName string, volName string, desc string, config map[string]string, srcPoolName, srcVolName string, srcVolOnly bool, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RefreshInstance(inst instance.Instance, src instance.Instance, srcSnapshots []instance.Instance, allowInconsistent bool, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) BackupInstance(inst instance.Instance, tarWriter *instancewriter.InstanceTarWriter, optimized bool, snapshots bool, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) GetInstanceUsage(inst instance.Instance) (int64, error) {
	return 0, nil
}

func (b *mockBackend) SetInstanceQuota(inst instance.Instance, size string, vmStateSize string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) MountInstance(inst instance.Instance, op *operations.Operation) (*MountInfo, error) {
	return &MountInfo{}, nil
}

func (b *mockBackend) UnmountInstance(inst instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateInstanceSnapshot(i instance.Instance, src instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RenameInstanceSnapshot(inst instance.Instance, newName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) DeleteInstanceSnapshot(inst instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RestoreInstanceSnapshot(inst instance.Instance, src instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) MountInstanceSnapshot(inst instance.Instance, op *operations.Operation) (*MountInfo, error) {
	return &MountInfo{}, nil
}

func (b *mockBackend) UnmountInstanceSnapshot(inst instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) UpdateInstanceSnapshot(inst instance.Instance, newDesc string, newConfig map[string]string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) EnsureImage(fingerprint string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) DeleteImage(fingerprint string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) UpdateImage(fingerprint, newDesc string, newConfig map[string]string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateCustomVolume(projectName string, volName string, desc string, config map[string]string, contentType drivers.ContentType, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateCustomVolumeFromCopy(projectName string, srcProjectName string, volName string, desc string, config map[string]string, srcPoolName string, srcVolName string, srcVolOnly bool, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RenameCustomVolume(projectName string, volName string, newName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) UpdateCustomVolume(projectName string, volName string, newDesc string, newConfig map[string]string, op *operations.Operation) error {
	return drivers.ErrNotImplemented
}

func (b *mockBackend) DeleteCustomVolume(projectName string, volName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) MigrateCustomVolume(projectName string, conn io.ReadWriteCloser, args *migration.VolumeSourceArgs, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateCustomVolumeFromMigration(projectName string, conn io.ReadWriteCloser, args migration.VolumeTargetArgs, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) GetCustomVolumeDisk(projectName string, volName string) (string, error) {
	return "", nil
}

func (b *mockBackend) GetCustomVolumeUsage(projectName string, volName string) (int64, error) {
	return 0, nil
}

func (b *mockBackend) MountCustomVolume(projectName string, volName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) UnmountCustomVolume(projectName string, volName string, op *operations.Operation) (bool, error) {
	return true, nil
}

func (b *mockBackend) ImportCustomVolume(projectName string, poolVol *backup.Config, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateCustomVolumeSnapshot(projectName string, volName string, newSnapshotName string, expiryDate time.Time, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RenameCustomVolumeSnapshot(projectName string, volName string, newName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) DeleteCustomVolumeSnapshot(projectName string, volName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) UpdateCustomVolumeSnapshot(projectName string, volName string, newDesc string, newConfig map[string]string, expiryDate time.Time, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RestoreCustomVolume(projectName string, volName string, snapshotName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) BackupCustomVolume(projectName string, volName string, tarWriter *instancewriter.InstanceTarWriter, optimized bool, snapshots bool, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateCustomVolumeFromBackup(srcBackup backup.Info, srcData io.ReadSeeker, op *operations.Operation) error {
	return nil
}
<commit_msg>lxd/storage/backend/mock: Adds GenerateCustomVolumeBackupConfig function<commit_after>package storage

import (
	"io"
	"time"

	"github.com/lxc/lxd/lxd/backup"
	"github.com/lxc/lxd/lxd/cluster/request"
	"github.com/lxc/lxd/lxd/instance"
	"github.com/lxc/lxd/lxd/migration"
	"github.com/lxc/lxd/lxd/operations"
	"github.com/lxc/lxd/lxd/revert"
	"github.com/lxc/lxd/lxd/state"
	"github.com/lxc/lxd/lxd/storage/drivers"
	"github.com/lxc/lxd/shared/api"
	"github.com/lxc/lxd/shared/instancewriter"
	"github.com/lxc/lxd/shared/logger"
)

type mockBackend struct {
	name   string
	state  *state.State
	logger logger.Logger
	driver drivers.Driver
}

func (b *mockBackend) ID() int64 {
	return 1 //  The tests expect the storage pool ID to be 1.
}

func (b *mockBackend) Name() string {
	return b.name
}

func (b *mockBackend) Description() string {
	return ""
}

func (b *mockBackend) ValidateName(value string) error {
	return nil
}

func (b *mockBackend) Validate(config map[string]string) error {
	return nil
}

func (b *mockBackend) Status() string {
	return api.NetworkStatusUnknown
}

func (b *mockBackend) LocalStatus() string {
	return api.NetworkStatusUnknown
}

func (b *mockBackend) ToAPI() api.StoragePool {
	return api.StoragePool{}
}

func (b *mockBackend) Driver() drivers.Driver {
	return b.driver
}

func (b *mockBackend) MigrationTypes(contentType drivers.ContentType, refresh bool) []migration.Type {
	return []migration.Type{
		{
			FSType:   FallbackMigrationType(contentType),
			Features: []string{"xattrs", "delete", "compress", "bidirectional"},
		},
	}
}

func (b *mockBackend) GetResources() (*api.ResourcesStoragePool, error) {
	return nil, nil
}

func (b *mockBackend) IsUsed() (bool, error) {
	return false, nil
}

func (b *mockBackend) Delete(clientType request.ClientType, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) Update(clientType request.ClientType, newDescription string, newConfig map[string]string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) Create(clientType request.ClientType, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) Mount() (bool, error) {
	return true, nil
}

func (b *mockBackend) Unmount() (bool, error) {
	return true, nil
}

func (b *mockBackend) ApplyPatch(name string) error {
	return nil
}

func (b *mockBackend) GetVolume(volType drivers.VolumeType, contentType drivers.ContentType, volName string, volConfig map[string]string) drivers.Volume {
	return drivers.Volume{}
}

func (b *mockBackend) CreateInstance(inst instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateInstanceFromBackup(srcBackup backup.Info, srcData io.ReadSeeker, op *operations.Operation) (func(instance.Instance) error, revert.Hook, error) {
	return nil, nil, nil
}

func (b *mockBackend) CreateInstanceFromCopy(inst instance.Instance, src instance.Instance, snapshots bool, allowInconsistent bool, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateInstanceFromImage(inst instance.Instance, fingerprint string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateInstanceFromMigration(inst instance.Instance, conn io.ReadWriteCloser, args migration.VolumeTargetArgs, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RenameInstance(inst instance.Instance, newName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) DeleteInstance(inst instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) UpdateInstance(inst instance.Instance, newDesc string, newConfig map[string]string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) GenerateCustomVolumeBackupConfig(projectName string, volName string, snapshots bool, op *operations.Operation) (*backup.Config, error) {
	return nil, nil
}

func (b *mockBackend) GenerateInstanceBackupConfig(inst instance.Instance, snapshots bool, op *operations.Operation) (*backup.Config, error) {
	return nil, nil
}

func (b *mockBackend) UpdateInstanceBackupFile(inst instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CheckInstanceBackupFileSnapshots(backupConf *backup.Config, projectName string, deleteMissing bool, op *operations.Operation) ([]*api.InstanceSnapshot, error) {
	return nil, nil
}

func (b *mockBackend) ListUnknownVolumes(op *operations.Operation) (map[string][]*backup.Config, error) {
	return nil, nil
}

func (b *mockBackend) ImportInstance(inst instance.Instance, poolVol *backup.Config, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) MigrateInstance(inst instance.Instance, conn io.ReadWriteCloser, args *migration.VolumeSourceArgs, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RefreshCustomVolume(projectName string, srcProjectName string, volName string, desc string, config map[string]string, srcPoolName, srcVolName string, srcVolOnly bool, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RefreshInstance(inst instance.Instance, src instance.Instance, srcSnapshots []instance.Instance, allowInconsistent bool, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) BackupInstance(inst instance.Instance, tarWriter *instancewriter.InstanceTarWriter, optimized bool, snapshots bool, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) GetInstanceUsage(inst instance.Instance) (int64, error) {
	return 0, nil
}

func (b *mockBackend) SetInstanceQuota(inst instance.Instance, size string, vmStateSize string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) MountInstance(inst instance.Instance, op *operations.Operation) (*MountInfo, error) {
	return &MountInfo{}, nil
}

func (b *mockBackend) UnmountInstance(inst instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateInstanceSnapshot(i instance.Instance, src instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RenameInstanceSnapshot(inst instance.Instance, newName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) DeleteInstanceSnapshot(inst instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RestoreInstanceSnapshot(inst instance.Instance, src instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) MountInstanceSnapshot(inst instance.Instance, op *operations.Operation) (*MountInfo, error) {
	return &MountInfo{}, nil
}

func (b *mockBackend) UnmountInstanceSnapshot(inst instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) UpdateInstanceSnapshot(inst instance.Instance, newDesc string, newConfig map[string]string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) EnsureImage(fingerprint string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) DeleteImage(fingerprint string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) UpdateImage(fingerprint, newDesc string, newConfig map[string]string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateCustomVolume(projectName string, volName string, desc string, config map[string]string, contentType drivers.ContentType, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateCustomVolumeFromCopy(projectName string, srcProjectName string, volName string, desc string, config map[string]string, srcPoolName string, srcVolName string, srcVolOnly bool, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RenameCustomVolume(projectName string, volName string, newName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) UpdateCustomVolume(projectName string, volName string, newDesc string, newConfig map[string]string, op *operations.Operation) error {
	return drivers.ErrNotImplemented
}

func (b *mockBackend) DeleteCustomVolume(projectName string, volName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) MigrateCustomVolume(projectName string, conn io.ReadWriteCloser, args *migration.VolumeSourceArgs, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateCustomVolumeFromMigration(projectName string, conn io.ReadWriteCloser, args migration.VolumeTargetArgs, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) GetCustomVolumeDisk(projectName string, volName string) (string, error) {
	return "", nil
}

func (b *mockBackend) GetCustomVolumeUsage(projectName string, volName string) (int64, error) {
	return 0, nil
}

func (b *mockBackend) MountCustomVolume(projectName string, volName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) UnmountCustomVolume(projectName string, volName string, op *operations.Operation) (bool, error) {
	return true, nil
}

func (b *mockBackend) ImportCustomVolume(projectName string, poolVol *backup.Config, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateCustomVolumeSnapshot(projectName string, volName string, newSnapshotName string, expiryDate time.Time, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RenameCustomVolumeSnapshot(projectName string, volName string, newName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) DeleteCustomVolumeSnapshot(projectName string, volName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) UpdateCustomVolumeSnapshot(projectName string, volName string, newDesc string, newConfig map[string]string, expiryDate time.Time, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RestoreCustomVolume(projectName string, volName string, snapshotName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) BackupCustomVolume(projectName string, volName string, tarWriter *instancewriter.InstanceTarWriter, optimized bool, snapshots bool, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateCustomVolumeFromBackup(srcBackup backup.Info, srcData io.ReadSeeker, op *operations.Operation) error {
	return nil
}
<|endoftext|>


<commit_before>// Package editor enables users to create edit views from their content
// structs so that admins can manage content
package editor

import (
	"bytes"
)

// Editable ensures data is editable
type Editable interface {
	SetContentID(id int)
	ContentID() int
	ContentName() string
	SetSlug(slug string)
	Editor() *Editor
	MarshalEditor() ([]byte, error)
}

// Editor is a view containing fields to manage content
type Editor struct {
	ViewBuf *bytes.Buffer
}

// Field is used to create the editable view for a field
// within a particular content struct
type Field struct {
	View []byte
}

// Form takes editable content and any number of Field funcs to describe the edit
// page for any content struct added by a user
func Form(post Editable, fields ...Field) ([]byte, error) {
	editor := post.Editor()

	editor.ViewBuf = &bytes.Buffer{}
	editor.ViewBuf.Write([]byte(`<table><tbody class="row"><tr class="col s8"><td>`))

	for _, f := range fields {
		addFieldToEditorView(editor, f)
	}

	editor.ViewBuf.Write([]byte(`</td></tr>`))

	// content items with Item embedded have some default fields we need to render
	editor.ViewBuf.Write([]byte(`<tr class="col s4 default-fields"><td>`))
	addPostDefaultFieldsToEditorView(post, editor)

	submit := `

	<button class="right waves-effect waves-light btn green" type="submit">Save</button>
	<button class="waves-effect waves-light btn green confirm-delete" type="submit">Delete</button>

`

	editor.ViewBuf.Write([]byte(submit + `</td></tr></tbody></table>`))

	return editor.ViewBuf.Bytes(), nil
}

func addFieldToEditorView(e *Editor, f Field) {
	e.ViewBuf.Write(f.View)
}

func addPostDefaultFieldsToEditorView(p Editable, e *Editor) {
	defaults := []Field{
		Field{
			View: Input("Timestamp", p, map[string]string{
				"label": "Publish Date",
				"type":  "date",
			}),
		},
		Field{
			View: Input("Slug", p, map[string]string{
				"label":       "URL Slug",
				"type":        "text",
				"disabled":    "true",
				"placeholder": "Will be set automatically",
			}),
		},
	}

	for _, f := range defaults {
		addFieldToEditorView(e, f)
	}

}
<commit_msg>will add this using new contrib process<commit_after>// Package editor enables users to create edit views from their content
// structs so that admins can manage content
package editor

import (
	"bytes"
)

// Editable ensures data is editable
type Editable interface {
	SetContentID(id int)
	ContentID() int
	ContentName() string
	SetSlug(slug string)
	Editor() *Editor
	MarshalEditor() ([]byte, error)
}

// Editor is a view containing fields to manage content
type Editor struct {
	ViewBuf *bytes.Buffer
}

// Field is used to create the editable view for a field
// within a particular content struct
type Field struct {
	View []byte
}

// Form takes editable content and any number of Field funcs to describe the edit
// page for any content struct added by a user
func Form(post Editable, fields ...Field) ([]byte, error) {
	editor := post.Editor()

	editor.ViewBuf = &bytes.Buffer{}
	editor.ViewBuf.Write([]byte(`<table><tbody class="row"><tr class="col s8"><td>`))

	for _, f := range fields {
		addFieldToEditorView(editor, f)
	}

	editor.ViewBuf.Write([]byte(`</td></tr>`))

	// content items with Item embedded have some default fields we need to render
	editor.ViewBuf.Write([]byte(`<tr class="col s4 default-fields"><td>`))
	addPostDefaultFieldsToEditorView(post, editor)

	submit := `

	<button class="right waves-effect waves-light btn green" type="submit">Save</button>

`
	editor.ViewBuf.Write([]byte(submit + `</td></tr></tbody></table>`))

	return editor.ViewBuf.Bytes(), nil
}

func addFieldToEditorView(e *Editor, f Field) {
	e.ViewBuf.Write(f.View)
}

func addPostDefaultFieldsToEditorView(p Editable, e *Editor) {
	defaults := []Field{
		Field{
			View: Input("Timestamp", p, map[string]string{
				"label": "Publish Date",
				"type":  "date",
			}),
		},
		Field{
			View: Input("Slug", p, map[string]string{
				"label":       "URL Slug",
				"type":        "text",
				"disabled":    "true",
				"placeholder": "Will be set automatically",
			}),
		},
	}

	for _, f := range defaults {
		addFieldToEditorView(e, f)
	}

}
<|endoftext|>


<commit_before>package parser

import (
	"github.com/modest-sql/common"
)

type statement interface {
	execute() error
	convert() interface{}
}

type statementList []statement

func (sl statementList) convert() (commands []interface{}) {
	for _, statement := range sl {
		command := statement.convert()

		if command != nil {
			commands = append(commands, command)
		}
	}
	return commands
}

func (sl statementList) execute() error {
	for _, statement := range sl {
		if err := statement.execute(); err != nil {
			panic(err)
		}
	}

	return nil
}

type createStatement struct {
	identifier        string
	columnDefinitions columnDefinitions
}

func (s *createStatement) convert() interface{} {
	return common.NewCreateTableCommand(s.identifier, s.columnDefinitions.convert())
}

func (s *createStatement) execute() error {
	return nil
}

type dropStatement struct {
	identifier string
}

func (s *dropStatement) convert() interface{} {
	return nil
}

func (s *dropStatement) execute() error {
	return nil
}

type insertStatement struct {
	table       string
	columnNames []string
	values      []interface{}
}

func (s *insertStatement) convert() interface{} {
	return nil
}

func (s *insertStatement) execute() error {
	return nil
}

type updateStatement struct {
	table           string
	assignments     []assignment
	whereExpression expression
}

func (s *updateStatement) convert() interface{} {
	return nil
}

func (s *updateStatement) execute() error {
	return nil
}

type deleteStatement struct {
	table           string
	alias           string
	whereExpression expression
}

func (s *deleteStatement) convert() interface{} {
	return nil
}

func (s *deleteStatement) execute() error {
	return nil
}

type columnSpec struct {
	isStar bool
	table  string
	column string
	alias  string
}

type selectStatement struct {
	table           string
	alias           string
	selectColumns   []columnSpec
	whereExpression expression
}

func (s *selectStatement) convert() interface{} {
	return nil
}

func (s *selectStatement) execute() error {
	return nil
}

type alterStatement struct {
	table       string
	instruction interface{}
}

func (s *alterStatement) convert() interface{} {
	return nil
}

func (s *alterStatement) execute() error {
	return nil
}

type alterDrop struct {
	table string
}
type alterAdd struct {
	table             string
	dataType          dataType
	columnConstraints []interface{}
}
<commit_msg>Added conversion for Insert and Select<commit_after>package parser

import (
	"github.com/modest-sql/common"
)

type statement interface {
	execute() error
	convert() interface{}
}

type statementList []statement

func (sl statementList) convert() (commands []interface{}) {
	for _, statement := range sl {
		command := statement.convert()

		if command != nil {
			commands = append(commands, command)
		}
	}
	return commands
}

func (sl statementList) execute() error {
	for _, statement := range sl {
		if err := statement.execute(); err != nil {
			panic(err)
		}
	}

	return nil
}

type createStatement struct {
	identifier        string
	columnDefinitions columnDefinitions
}

func (s *createStatement) convert() interface{} {
	return common.NewCreateTableCommand(s.identifier, s.columnDefinitions.convert())
}

func (s *createStatement) execute() error {
	return nil
}

type dropStatement struct {
	identifier string
}

func (s *dropStatement) convert() interface{} {
	return nil
}

func (s *dropStatement) execute() error {
	return nil
}

type insertStatement struct {
	table       string
	columnNames []string
	values      []interface{}
}

func (s *insertStatement) convert() interface{} {
	values := map[string]interface{}{}

	for i, columnName := range s.columnNames {
		values[columnName] = s.values[i]
	}

	return common.NewInsertCommand(s.table, values)
}

func (s *insertStatement) execute() error {
	return nil
}

type updateStatement struct {
	table           string
	assignments     []assignment
	whereExpression expression
}

func (s *updateStatement) convert() interface{} {
	return nil
}

func (s *updateStatement) execute() error {
	return nil
}

type deleteStatement struct {
	table           string
	alias           string
	whereExpression expression
}

func (s *deleteStatement) convert() interface{} {
	return nil
}

func (s *deleteStatement) execute() error {
	return nil
}

type columnSpec struct {
	isStar bool
	table  string
	column string
	alias  string
}

type selectStatement struct {
	table           string
	alias           string
	selectColumns   []columnSpec
	whereExpression expression
}

func (s *selectStatement) convert() interface{} {
	return common.NewSelectTableCommand(s.table)
}

func (s *selectStatement) execute() error {
	return nil
}

type alterStatement struct {
	table       string
	instruction interface{}
}

func (s *alterStatement) convert() interface{} {
	return nil
}

func (s *alterStatement) execute() error {
	return nil
}

type alterDrop struct {
	table string
}
type alterAdd struct {
	table             string
	dataType          dataType
	columnConstraints []interface{}
}
<|endoftext|>


<commit_before>package stats

import (
	"math"
	"reflect"
	"sort"
	"testing"
)

func TestMin(t *testing.T) {
	m := Min([]float64{1.1, 2, 3, 4, 5})
	if m != 1.1 {
		t.Errorf("%.1f != %.1f", m, 1.1)
	}

	m = Min([]float64{10.534, 3, 5, 7, 9})
	if m != 3.0 {
		t.Errorf("%.1fx != %.1f", m, 3.0)
	}

	m = Min([]float64{-5, 1, 5})
	if m != -5.0 {
		t.Errorf("%.1f != %.1f", m, -5.0)
	}
}

func TestMax(t *testing.T) {
	m := Max([]float64{1, 2, 3, 4, 5})
	if m != 5.0 {
		t.Errorf("%.1f != %.1f", m, 5.0)
	}

	m = Max([]float64{10.5, 3, 5, 7, 9})
	if m != 10.5 {
		t.Errorf("%.1f != %.1f", m, 10.5)
	}

	m = Max([]float64{-20, -1, -5.5})
	if m != -1.0 {
		t.Errorf("%.1f != %.1f", m, -1.0)
	}
}

func TestMean(t *testing.T) {
	m := Mean([]float64{1, 2, 3, 4, 5})
	if m != 3.0 {
		t.Errorf("%.1f != %.1f", m, 3.0)
	}

	m = Mean([]float64{1, 2, 3, 4, 5, 6})
	if m != 3.5 {
		t.Errorf("%.1f != %.1f", m, 3.5)
	}

	m = Mean([]float64{1})
	if m != 1.0 {
		t.Errorf("%.1f != %.1f", m, 1.0)
	}

	m = Mean([]float64{})
	if m != 0.0 {
		t.Errorf("%.1f != %.1f", m, 0.0)
	}
}

func TestMedian(t *testing.T) {
	m := Median([]float64{5, 3, 4, 2, 1})
	if m != 3.0 {
		t.Errorf("%.1f != %.1f", m, 3.0)
	}

	m = Median([]float64{6, 3, 2, 4, 5, 1})
	if m != 3.5 {
		t.Errorf("%.1f != %.1f", m, 3.5)
	}

	m = Median([]float64{1})
	if m != 1.0 {
		t.Errorf("%.1f != %.1f", m, 1.0)
	}

	m = Median([]float64{})
	if m != 0.0 {
		t.Errorf("%.1f != %.1f", m, 0.0)
	}
}

func TestMode(t *testing.T) {
	m := Mode([]float64{5, 3, 4, 2, 1})
	a := []float64{}
	if !reflect.DeepEqual(m, a) {
		t.Errorf("%.1f != %.1f", m, a)
	}

	m = Mode([]float64{5, 5, 3, 4, 2, 1})
	a = []float64{5}
	if !reflect.DeepEqual(m, a) {
		t.Errorf("%.1f != %.1f", m, a)
	}

	m = Mode([]float64{5, 5, 3, 3, 4, 2, 1})
	sort.Float64s(m)
	a = []float64{3, 5}
	if !reflect.DeepEqual(m, a) {
		t.Errorf("%.1f != %.1f", m, a)
	}

	m = Mode([]float64{5, 5, 3, 3, 4, 2, 1, 1, 1})
	a = []float64{1}
	if !reflect.DeepEqual(m, a) {
		t.Errorf("%.1f != %.1f", m, a)
	}
}

func TestSum(t *testing.T) {
	m := Sum([]float64{})
	if m != 0.0 {
		t.Errorf("%.1f != %.1f", m, 0.0)
	}

	m = Sum([]float64{1, 2, 3})
	if m != 6.0 {
		t.Errorf("%.1f != %.1f", m, 6.0)
	}

	m = Sum([]float64{1.0, 1.1, 1.2, 2.2})
	if m != 5.5 {
		t.Errorf("%.1f != %.1f", m, 5.5)
	}
}

func TestVariance(t *testing.T) {
	m := Variance([]float64{}, 0)
	if m != 0.0 {
		t.Errorf("%.1f != %.1f", m, 0.0)
	}
	m = Variance([]float64{}, 1)
	if m != 0.0 {
		t.Errorf("%.1f != %.1f", m, 0.0)
	}
	m = Round(Variance([]float64{1, 2, 3}, 0), 1)
	if m != 0.7 {
		t.Errorf("%.1f != %.1f", m, 0.7)
	}
	m = Variance([]float64{1, 2, 3}, 1)
	if m != 1.0 {
		t.Errorf("%.1f != %.1f", m, 1.0)
	}
}

func TestVarP(t *testing.T) {
	m := VarP([]float64{})
	if m != 0.0 {
		t.Errorf("%.1f != %.1f", m, 0.0)
	}
	m = Round(VarP([]float64{1, 2, 3}), 1)
	if m != 0.7 {
		t.Errorf("%.1f != %.1f", m, 0.7)
	}
}

func TestVarS(t *testing.T) {
	m := VarS([]float64{})
	if m != 0.0 {
		t.Errorf("%.1f != %.1f", m, 0.0)
	}
	m = VarS([]float64{1, 2, 3})
	if m != 1.0 {
		t.Errorf("%.1f != %.1f", m, 1.0)
	}
}

func TestStdDevP(t *testing.T) {
	m := Round(StdDevP([]float64{1, 2, 3}), 2)
	if m != 0.82 {
		t.Errorf("%.10f != %.10f", m, 0.82)
	}

	m = Round(StdDevP([]float64{-1, -2, -3.3}), 2)
	if m != 0.94 {
		t.Errorf("%.10f != %.10f", m, 0.94)
	}

	m = StdDevP([]float64{})
	if m != 0.0 {
		t.Errorf("%.1f != %.1f", m, 0.0)
	}
}

func TestStdDevS(t *testing.T) {
	m := Round(StdDevS([]float64{1, 2, 3}), 2)
	if m != 1.0 {
		t.Errorf("%.10f != %.10f", m, 1.0)
	}

	m = Round(StdDevS([]float64{-1, -2, -3.3}), 2)
	if m != 1.15 {
		t.Errorf("%.10f != %.10f", m, 1.15)
	}

	m = StdDevS([]float64{})
	if m != 0.0 {
		t.Errorf("%.1f != %.1f", m, 0.0)
	}
}

func TestRound(t *testing.T) {
	m := Round(0.1111, 1)
	if m != 0.1 {
		t.Errorf("%.1f != %.1f", m, 0.1)
	}

	m = Round(-0.1111, 2)
	if m != -0.11 {
		t.Errorf("%.1f != %.1f", m, -0.11)
	}

	m = Round(5.3253, 3)
	if m != 5.325 {
		t.Errorf("%.1f != %.1f", m, 5.325)
	}

	m = Round(5.3253, 0)
	if m != 5.0 {
		t.Errorf("%.1f != %.1f", m, 5.0)
	}

	m = Round(math.NaN(), 2)
	if !math.IsNaN(m) {
		t.Errorf("%.1f != %.1f", m, math.NaN())
	}
}

func TestPercentile(t *testing.T) {
	m := Percentile([]float64{43, 54, 56, 61, 62, 66}, 90)
	if m != 62.0 {
		t.Errorf("%.1f != %.1f", m, 62.0)
	}
	m = Percentile([]float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 50)
	if m != 5.5 {
		t.Errorf("%.1f != %.1f", m, 5.5)
	}
	m = Percentile([]float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 99.9)
	if m != 10.0 {
		t.Errorf("%.1f != %.1f", m, 10.0)
	}
}

func TestFloat64ToInt(t *testing.T) {
	m := Float64ToInt(234.0234)
	if m != 234 {
		t.Errorf("%x != %x", m, 234)
	}
	m = Float64ToInt(-234.0234)
	if m != -234 {
		t.Errorf("%x != %x", m, -234)
	}
	m = Float64ToInt(1)
	if m != 1 {
		t.Errorf("%x != %x", m, 1)
	}
}
<commit_msg>table testing style<commit_after>package stats

import (
	"math"
	"reflect"
	"sort"
	"testing"
)

func TestMin(t *testing.T) {
  for _, c := range []struct {
    in []float64
    out float64
  }{
    {[]float64{1.1, 2, 3, 4, 5}, 1.1},
    {[]float64{10.534, 3, 5, 7, 9}, 3.0},
    {[]float64{-5, 1, 5}, -5.0},
  } {
    got := Min(c.in)
    if got != c.out {
      t.Errorf("Min(%.1f) => %.1f != %.1f", c.in, c.out, got)
    }
  }
}

func TestMax(t *testing.T) {
  for _, c := range []struct {
    in []float64
    out float64
  }{
    {[]float64{1, 2, 3, 4, 5}, 5.0},
    {[]float64{10.5, 3, 5, 7, 9}, 10.5},
    {[]float64{-20, -1, -5.5}, -1.0},
  } {
    got := Max(c.in)
    if got != c.out {
      t.Errorf("Max(%.1f) => %.1f != %.1f", c.in, c.out, got)
    }
  }
}

func TestMean(t *testing.T) {
  for _, c := range []struct {
    in []float64
    out float64
  }{
    {[]float64{1, 2, 3, 4, 5}, 3.0},
    {[]float64{1, 2, 3, 4, 5, 6}, 3.5},
    {[]float64{1}, 1.0},
    {[]float64{}, 0.0},
  } {
    got := Mean(c.in)
    if got != c.out {
      t.Errorf("Mean(%.1f) => %.1f != %.1f", c.in, c.out, got)
    }
  }
}

func TestMedian(t *testing.T) {
  for _, c := range []struct {
    in []float64
    out float64
  }{
    {[]float64{5, 3, 4, 2, 1}, 3.0},
    {[]float64{6, 3, 2, 4, 5, 1}, 3.5},
    {[]float64{1}, 1.0},
    {[]float64{}, 0.0},
  } {
    got := Median(c.in)
    if got != c.out {
      t.Errorf("Median(%.1f) => %.1f != %.1f", c.in, c.out, got)
    }
  }
}

func TestMode(t *testing.T) {
  for _, c := range []struct {
    in []float64
    out []float64
  }{
    {[]float64{5, 3, 4, 2, 1}, []float64{}},
    {[]float64{5, 5, 3, 4, 2, 1}, []float64{5}},
    {[]float64{5, 5, 3, 3, 4, 2, 1}, []float64{3, 5}},
    {[]float64{1}, []float64{1}},
  } {
    got := Mode(c.in)
    sort.Float64s(got)
    if !reflect.DeepEqual(c.out, got) {
      t.Errorf("Mode(%.1f) => %.1f != %.1f", c.in, got, c.out)
    }
  }
}

func TestSum(t *testing.T) {
	m := Sum([]float64{})
	if m != 0.0 {
		t.Errorf("%.1f != %.1f", m, 0.0)
	}

	m = Sum([]float64{1, 2, 3})
	if m != 6.0 {
		t.Errorf("%.1f != %.1f", m, 6.0)
	}

	m = Sum([]float64{1.0, 1.1, 1.2, 2.2})
	if m != 5.5 {
		t.Errorf("%.1f != %.1f", m, 5.5)
	}
}

func TestVariance(t *testing.T) {
	m := Variance([]float64{}, 0)
	if m != 0.0 {
		t.Errorf("%.1f != %.1f", m, 0.0)
	}
	m = Variance([]float64{}, 1)
	if m != 0.0 {
		t.Errorf("%.1f != %.1f", m, 0.0)
	}
	m = Round(Variance([]float64{1, 2, 3}, 0), 1)
	if m != 0.7 {
		t.Errorf("%.1f != %.1f", m, 0.7)
	}
	m = Variance([]float64{1, 2, 3}, 1)
	if m != 1.0 {
		t.Errorf("%.1f != %.1f", m, 1.0)
	}
}

func TestVarP(t *testing.T) {
	m := VarP([]float64{})
	if m != 0.0 {
		t.Errorf("%.1f != %.1f", m, 0.0)
	}
	m = Round(VarP([]float64{1, 2, 3}), 1)
	if m != 0.7 {
		t.Errorf("%.1f != %.1f", m, 0.7)
	}
}

func TestVarS(t *testing.T) {
	m := VarS([]float64{})
	if m != 0.0 {
		t.Errorf("%.1f != %.1f", m, 0.0)
	}
	m = VarS([]float64{1, 2, 3})
	if m != 1.0 {
		t.Errorf("%.1f != %.1f", m, 1.0)
	}
}

func TestStdDevP(t *testing.T) {
	m := Round(StdDevP([]float64{1, 2, 3}), 2)
	if m != 0.82 {
		t.Errorf("%.10f != %.10f", m, 0.82)
	}

	m = Round(StdDevP([]float64{-1, -2, -3.3}), 2)
	if m != 0.94 {
		t.Errorf("%.10f != %.10f", m, 0.94)
	}

	m = StdDevP([]float64{})
	if m != 0.0 {
		t.Errorf("%.1f != %.1f", m, 0.0)
	}
}

func TestStdDevS(t *testing.T) {
	m := Round(StdDevS([]float64{1, 2, 3}), 2)
	if m != 1.0 {
		t.Errorf("%.10f != %.10f", m, 1.0)
	}

	m = Round(StdDevS([]float64{-1, -2, -3.3}), 2)
	if m != 1.15 {
		t.Errorf("%.10f != %.10f", m, 1.15)
	}

	m = StdDevS([]float64{})
	if m != 0.0 {
		t.Errorf("%.1f != %.1f", m, 0.0)
	}
}

func TestRound(t *testing.T) {
	m := Round(0.1111, 1)
	if m != 0.1 {
		t.Errorf("%.1f != %.1f", m, 0.1)
	}

	m = Round(-0.1111, 2)
	if m != -0.11 {
		t.Errorf("%.1f != %.1f", m, -0.11)
	}

	m = Round(5.3253, 3)
	if m != 5.325 {
		t.Errorf("%.1f != %.1f", m, 5.325)
	}

	m = Round(5.3253, 0)
	if m != 5.0 {
		t.Errorf("%.1f != %.1f", m, 5.0)
	}

	m = Round(math.NaN(), 2)
	if !math.IsNaN(m) {
		t.Errorf("%.1f != %.1f", m, math.NaN())
	}
}

func TestPercentile(t *testing.T) {
	m := Percentile([]float64{43, 54, 56, 61, 62, 66}, 90)
	if m != 62.0 {
		t.Errorf("%.1f != %.1f", m, 62.0)
	}
	m = Percentile([]float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 50)
	if m != 5.5 {
		t.Errorf("%.1f != %.1f", m, 5.5)
	}
	m = Percentile([]float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 99.9)
	if m != 10.0 {
		t.Errorf("%.1f != %.1f", m, 10.0)
	}
}

func TestFloat64ToInt(t *testing.T) {
	m := Float64ToInt(234.0234)
	if m != 234 {
		t.Errorf("%x != %x", m, 234)
	}
	m = Float64ToInt(-234.0234)
	if m != -234 {
		t.Errorf("%x != %x", m, -234)
	}
	m = Float64ToInt(1)
	if m != 1 {
		t.Errorf("%x != %x", m, 1)
	}
}
<|endoftext|>


<commit_before>package playground

import "errors"

var ErrInvalidDirection = errors.New("Invalid direction")

// Direction indicates movement direction
type Direction uint8

const (
	DIR_NORTH = iota
	DIR_EAST
	DIR_SOUTH
	DIR_WEST
	_DIR_COUNT
)

// RandomDirection returns random direction
func RandomDirection() Direction {
	return Direction(random.Intn(_DIR_COUNT))
}

// ValidDirection returns true if passed direction is valid
func ValidDirection(dir Direction) bool {
	switch dir {
	case DIR_NORTH, DIR_EAST, DIR_SOUTH, DIR_WEST:
		return true
	}
	return false
}

// Implementing json.Marshaler interface
func (dir Direction) MarshalJSON() ([]byte, error) {
	switch dir {
	case DIR_NORTH:
		return []byte(`"n"`), nil
	case DIR_SOUTH:
		return []byte(`"s"`), nil
	case DIR_EAST:
		return []byte(`"e"`), nil
	case DIR_WEST:
		return []byte(`"w"`), nil
	}
	return nil, ErrInvalidDirection
}
<commit_msg>fixed direction verifing<commit_after>package playground

import "errors"

var ErrInvalidDirection = errors.New("Invalid direction")

// Direction indicates movement direction
type Direction uint8

const (
	DIR_NORTH = iota
	DIR_EAST
	DIR_SOUTH
	DIR_WEST
	_DIR_COUNT
)

// RandomDirection returns random direction
func RandomDirection() Direction {
	return Direction(random.Intn(_DIR_COUNT))
}

// ValidDirection returns true if passed direction is valid
func ValidDirection(dir Direction) bool {
	return _DIR_COUNT > dir
}

// Implementing json.Marshaler interface
func (dir Direction) MarshalJSON() ([]byte, error) {
	switch dir {
	case DIR_NORTH:
		return []byte(`"n"`), nil
	case DIR_SOUTH:
		return []byte(`"s"`), nil
	case DIR_EAST:
		return []byte(`"e"`), nil
	case DIR_WEST:
		return []byte(`"w"`), nil
	}
	return nil, ErrInvalidDirection
}
<|endoftext|>


<commit_before>package engine

import (
	"testing"

	"github.com/keybase/client/go/libkb"
	"golang.org/x/crypto/openpgp"
)

func doUpdate(fingerprints []string, all bool, fu *FakeUser, tc libkb.TestContext) (err error) {
	eng := NewPGPUpdateEngine(fingerprints, all, tc.G)
	ctx := Context{
		LogUI:    tc.G.UI.GetLogUI(),
		SecretUI: fu.NewSecretUI(),
	}
	err = RunEngine(eng, &ctx)
	return
}

func getFakeUsersKeyBundleFromServer(t *testing.T, fu *FakeUser) *libkb.PGPKeyBundle {
	user, err := libkb.LoadUser(libkb.LoadUserArg{
		Name:        fu.Username,
		ForceReload: true,
	})
	if err != nil {
		t.Fatal("Failed loading user", err)
	}
	ckf := user.GetComputedKeyFamily()
	keys := ckf.GetActivePGPKeys(true /* sibkeys */)
	if len(keys) != 1 {
		t.Fatal("Expected only one key.")
	}
	return keys[0]
}

func getFakeUsersBundlesList(t *testing.T, fu *FakeUser) []string {
	user, err := libkb.LoadUser(libkb.LoadUserArg{
		Name:        fu.Username,
		ForceReload: true,
	})
	if err != nil {
		t.Fatal("Failed loading user", err)
	}
	return user.GetKeyFamily().BundlesForTesting
}

func TestPGPUpdate(t *testing.T) {
	tc := SetupEngineTest(t, "pgp_update")
	defer tc.Cleanup()

	// Note that this user's key is not created in the GPG keyring. For the
	// purposes of this test that's ok.
	fakeUser := createFakeUserWithPGPSibkey(tc)
	bundle := getFakeUsersKeyBundleFromServer(t, fakeUser)
	if len(bundle.Subkeys) != 1 {
		t.Fatal("expected exactly 1 subkey")
	}
	originalBundlesLen := len(getFakeUsersBundlesList(t, fakeUser))

	// Modify the key by deleting the subkey.
	bundle.Subkeys = []openpgp.Subkey{}

	gpgCLI := libkb.NewGpgCLI(libkb.GpgCLIArg{
		LogUI: tc.G.UI.GetLogUI(),
	})
	_, err := gpgCLI.Configure()
	if err != nil {
		t.Fatal("erorr initializing GpgCLI", err)
	}

	// Add the modified key to the gpg keyring
	if err := gpgCLI.ExportKey(*bundle); err != nil {
		t.Fatal(err)
	}

	// Now run `client pgp update` with a fingerprint that doesn't match.
	err = doUpdate([]string{"not_a_real_fingerprint"}, false, fakeUser, tc)
	if err != nil {
		t.Fatal("Error in PGPUpdateEngine:", err)
	}
	// Get the list of bundles from the server.
	bundles := getFakeUsersBundlesList(t, fakeUser)
	// Check that the key hasn't been modified.
	if len(bundles) != originalBundlesLen {
		t.Fatal("Key changes should not have been uploaded.")
	}

	// Do the same thing without the fingerprint. It should go through this time.
	err = doUpdate([]string{}, false, fakeUser, tc)
	if err != nil {
		t.Fatal("Error in PGPUpdateEngine:", err)
	}
	// Load the user from the server again.
	reloadedBundles := getFakeUsersBundlesList(t, fakeUser)
	// Check that the key hasn't been modified.
	if len(reloadedBundles) != originalBundlesLen+1 {
		t.Fatal("Key changes should have been uploaded.")
	}
}

func TestPGPUpdateMultiKey(t *testing.T) {
	tc := SetupEngineTest(t, "pgp_update")
	defer tc.Cleanup()

	// Get a user with one PGP sibkey. Note that this user's key is not created
	// in the GPG keyring. For the purposes of this test that's ok.
	fu := createFakeUserWithPGPSibkey(tc)

	// Generate a second PGP sibkey.
	arg := PGPKeyImportEngineArg{
		AllowMulti: true,
		Gen: &libkb.PGPGenArg{
			PrimaryBits: 768,
			SubkeyBits:  768,
		},
	}
	arg.Gen.MakeAllIds()
	ctx := Context{
		LogUI:    tc.G.UI.GetLogUI(),
		SecretUI: fu.NewSecretUI(),
	}
	eng := NewPGPKeyImportEngine(arg)
	err := RunEngine(eng, &ctx)
	if err != nil {
		tc.T.Fatal(err)
	}

	// `client pgp update` should fail by default, because there are multiple keys.
	err = doUpdate([]string{}, false /* all */, fu, tc)
	if err == nil {
		t.Fatal("Update should fail with multiple keys and no --all.")
	}

	// `client pgp update` should fail with both specific fingerprints and --all.
	err = doUpdate([]string{"foo"}, true /* all */, fu, tc)
	if err == nil {
		t.Fatal("Update should fail with explicit fingerprint and --all.")
	}

	// It should finally succeed with just --all.
	err = doUpdate([]string{}, true /* all */, fu, tc)
	if err != nil {
		t.Fatal("Update should succeed with --all.")
	}
}
<commit_msg>Log the error<commit_after>package engine

import (
	"testing"

	"github.com/keybase/client/go/libkb"
	"golang.org/x/crypto/openpgp"
)

func doUpdate(fingerprints []string, all bool, fu *FakeUser, tc libkb.TestContext) (err error) {
	eng := NewPGPUpdateEngine(fingerprints, all, tc.G)
	ctx := Context{
		LogUI:    tc.G.UI.GetLogUI(),
		SecretUI: fu.NewSecretUI(),
	}
	err = RunEngine(eng, &ctx)
	return
}

func getFakeUsersKeyBundleFromServer(t *testing.T, fu *FakeUser) *libkb.PGPKeyBundle {
	user, err := libkb.LoadUser(libkb.LoadUserArg{
		Name:        fu.Username,
		ForceReload: true,
	})
	if err != nil {
		t.Fatal("Failed loading user", err)
	}
	ckf := user.GetComputedKeyFamily()
	keys := ckf.GetActivePGPKeys(true /* sibkeys */)
	if len(keys) != 1 {
		t.Fatal("Expected only one key.")
	}
	return keys[0]
}

func getFakeUsersBundlesList(t *testing.T, fu *FakeUser) []string {
	user, err := libkb.LoadUser(libkb.LoadUserArg{
		Name:        fu.Username,
		ForceReload: true,
	})
	if err != nil {
		t.Fatal("Failed loading user", err)
	}
	return user.GetKeyFamily().BundlesForTesting
}

func TestPGPUpdate(t *testing.T) {
	tc := SetupEngineTest(t, "pgp_update")
	defer tc.Cleanup()

	// Note that this user's key is not created in the GPG keyring. For the
	// purposes of this test that's ok.
	fakeUser := createFakeUserWithPGPSibkey(tc)
	bundle := getFakeUsersKeyBundleFromServer(t, fakeUser)
	if len(bundle.Subkeys) != 1 {
		t.Fatal("expected exactly 1 subkey")
	}
	originalBundlesLen := len(getFakeUsersBundlesList(t, fakeUser))

	// Modify the key by deleting the subkey.
	bundle.Subkeys = []openpgp.Subkey{}

	gpgCLI := libkb.NewGpgCLI(libkb.GpgCLIArg{
		LogUI: tc.G.UI.GetLogUI(),
	})
	_, err := gpgCLI.Configure()
	if err != nil {
		t.Fatal("erorr initializing GpgCLI", err)
	}

	// Add the modified key to the gpg keyring
	if err := gpgCLI.ExportKey(*bundle); err != nil {
		t.Fatal(err)
	}

	// Now run `client pgp update` with a fingerprint that doesn't match.
	err = doUpdate([]string{"not_a_real_fingerprint"}, false, fakeUser, tc)
	if err != nil {
		t.Fatal("Error in PGPUpdateEngine:", err)
	}
	// Get the list of bundles from the server.
	bundles := getFakeUsersBundlesList(t, fakeUser)
	// Check that the key hasn't been modified.
	if len(bundles) != originalBundlesLen {
		t.Fatal("Key changes should not have been uploaded.")
	}

	// Do the same thing without the fingerprint. It should go through this time.
	err = doUpdate([]string{}, false, fakeUser, tc)
	if err != nil {
		t.Fatal("Error in PGPUpdateEngine:", err)
	}
	// Load the user from the server again.
	reloadedBundles := getFakeUsersBundlesList(t, fakeUser)
	// Check that the key hasn't been modified.
	if len(reloadedBundles) != originalBundlesLen+1 {
		t.Fatal("Key changes should have been uploaded.")
	}
}

func TestPGPUpdateMultiKey(t *testing.T) {
	tc := SetupEngineTest(t, "pgp_update")
	defer tc.Cleanup()

	// Get a user with one PGP sibkey. Note that this user's key is not created
	// in the GPG keyring. For the purposes of this test that's ok.
	fu := createFakeUserWithPGPSibkey(tc)

	// Generate a second PGP sibkey.
	arg := PGPKeyImportEngineArg{
		AllowMulti: true,
		Gen: &libkb.PGPGenArg{
			PrimaryBits: 768,
			SubkeyBits:  768,
		},
	}
	arg.Gen.MakeAllIds()
	ctx := Context{
		LogUI:    tc.G.UI.GetLogUI(),
		SecretUI: fu.NewSecretUI(),
	}
	eng := NewPGPKeyImportEngine(arg)
	err := RunEngine(eng, &ctx)
	if err != nil {
		tc.T.Fatal(err)
	}

	// `client pgp update` should fail by default, because there are multiple keys.
	err = doUpdate([]string{}, false /* all */, fu, tc)
	if err == nil {
		t.Fatal("Update should fail with multiple keys and no --all.")
	}

	// `client pgp update` should fail with both specific fingerprints and --all.
	err = doUpdate([]string{"foo"}, true /* all */, fu, tc)
	if err == nil {
		t.Fatal("Update should fail with explicit fingerprint and --all.")
	}

	// It should finally succeed with just --all.
	err = doUpdate([]string{}, true /* all */, fu, tc)
	if err != nil {
		t.Fatal("Update should succeed with --all. Error:", err)
	}
}
<|endoftext|>


<commit_before>package eventbus

import (
	"fmt"
	"sort"
	"sync"
	"testing"
	"time"

	"go.skia.org/infra/go/geventbus"
	"go.skia.org/infra/go/testutils"
	"go.skia.org/infra/go/util"

	assert "github.com/stretchr/testify/require"
)

const GLOBAL_TOPIC = "global-topic"
const LOCAL_TOPIC = "local-topic"
const SYNC_MSG = -1

const NSQD_ADDR = "127.0.0.1:4150"

type testType struct {
	ID    int
	Value string
}

func init() {
	RegisterGlobalEvent(GLOBAL_TOPIC, util.JSONCodec(&testType{}))
}

func TestEventBus(t *testing.T) {
	eventBus := New(nil)

	ch := make(chan int, 5)
	eventBus.SubscribeAsync("topic1", func(e interface{}) { ch <- 1 })
	eventBus.SubscribeAsync("topic2", func(e interface{}) { ch <- (e.(int)) + 1 })
	eventBus.SubscribeAsync("topic2", func(e interface{}) { ch <- e.(int) })

	eventBus.Publish("topic1", nil)
	eventBus.Publish("topic2", 2)
	eventBus.Wait("topic1")
	eventBus.Wait("topic2")
	assert.Equal(t, 3, len(ch))

	vals := []int{<-ch, <-ch, <-ch}
	sort.Ints(vals)
	assert.Equal(t, []int{1, 2, 3}, vals)
}

func TestEventBusGlobally(t *testing.T) {
	testutils.SkipIfShort(t)

	messages := []*testType{
		&testType{0, "message-1"},
		&testType{1, "message-2"},
		&testType{2, "message-3"},
		&testType{3, "message-4"},
	}

	globalEventBus, err := geventbus.NewNSQEventBus(NSQD_ADDR)
	assert.Nil(t, err)

	secondGlobalBus, err := geventbus.NewNSQEventBus(NSQD_ADDR)
	assert.Nil(t, err)

	// Use atomic ints to sync the callback functions.
	firstMap := newAtomicMap()
	firstEventBus := New(globalEventBus)
	firstEventBus.SubscribeAsync(GLOBAL_TOPIC, func(e interface{}) {
		data := e.(*testType)
		if data.ID == SYNC_MSG {
			firstMap.setReady()
			return
		}
		firstMap.Add(data.ID, data)
	})

	secondMap := newAtomicMap()
	errCh := make(chan error, 100)
	assert.Nil(t, secondGlobalBus.SubscribeAsync(GLOBAL_TOPIC, geventbus.JSONCallback(&testType{}, func(data interface{}, err error) {
		if err != nil {
			errCh <- err
			return
		}

		if data.(*testType).ID == SYNC_MSG {
			secondMap.setReady()
			return
		}

		d := data.(*testType)
		secondMap.Add(d.ID, d)
	})))

	for !firstMap.isReady() && !secondMap.isReady() {
		firstEventBus.Publish(GLOBAL_TOPIC, &testType{SYNC_MSG, "ignore"})
	}

	for _, m := range messages {
		firstEventBus.Publish(GLOBAL_TOPIC, m)
	}

	lmsg := len(messages)
	for ((firstMap.Len() < lmsg) || (secondMap.Len() < lmsg)) && (len(errCh) == 0) {
		time.Sleep(time.Millisecond * 10)
	}

	if len(errCh) > 0 {
		close(errCh)
		for err = range errCh {
			fmt.Printf("Error: %s\n", err)
		}
		assert.Fail(t, "Received too many error messages.")
	}
}

func TestSubTopics(t *testing.T) {
	testutils.SkipIfShort(t)

	const N_NUMBERS = 200
	const ALL_NUMBERS_EVENT = "allNumbers"
	const EVEN_NUMBERS_EVENT = "evenNumbers"

	RegisterSubTopic(ALL_NUMBERS_EVENT, EVEN_NUMBERS_EVENT, func(data interface{}) bool {
		i, ok := data.(int)
		if !ok {
			return false
		}
		return i%2 == 0
	})

	eventBus := New(nil)
	allCh := make(chan int, N_NUMBERS*3)
	evenCh := make(chan int, N_NUMBERS*3)
	eventBus.SubscribeAsync(ALL_NUMBERS_EVENT, func(e interface{}) { allCh <- e.(int) })
	eventBus.SubscribeAsync(EVEN_NUMBERS_EVENT, func(e interface{}) { evenCh <- e.(int) })

	allExpected := []int{}
	evenExpected := []int{}
	for i := 0; i < N_NUMBERS; i++ {
		eventBus.Publish(ALL_NUMBERS_EVENT, i)
		allExpected = append(allExpected, i)
		if i%2 == 0 {
			evenExpected = append(evenExpected, i)
		}
	}

	eventBus.Wait(ALL_NUMBERS_EVENT)
	close(allCh)
	close(evenCh)

	assert.Equal(t, N_NUMBERS, len(allCh))
	compChan(t, allExpected, allCh)
	compChan(t, evenExpected, evenCh)
}

func compChan(t assert.TestingT, exp []int, ch <-chan int) {
	actual := []int{}
	for v := range ch {
		actual = append(actual, v)
	}
	sort.Ints(actual)
	assert.Equal(t, exp, actual)
}

type atomicMap struct {
	m     map[int]*testType
	mutex sync.Mutex
	ready bool
}

func newAtomicMap() *atomicMap {
	return &atomicMap{
		m:     map[int]*testType{},
		ready: false,
	}
}

func (a *atomicMap) Add(k int, v *testType) {
	a.mutex.Lock()
	defer a.mutex.Unlock()
	a.m[k] = v
}

func (a *atomicMap) Len() int {
	a.mutex.Lock()
	defer a.mutex.Unlock()
	return len(a.m)
}

func (a *atomicMap) setReady() {
	a.mutex.Lock()
	defer a.mutex.Unlock()
	a.ready = true
}

func (a *atomicMap) isReady() bool {
	a.mutex.Lock()
	defer a.mutex.Unlock()
	return a.ready
}
<commit_msg>Fix TestEventBusGlobally from occasionally timing out<commit_after>package eventbus

import (
	"fmt"
	"sort"
	"sync"
	"testing"
	"time"

	"go.skia.org/infra/go/geventbus"
	"go.skia.org/infra/go/testutils"
	"go.skia.org/infra/go/util"

	assert "github.com/stretchr/testify/require"
)

const GLOBAL_TOPIC = "global-topic"
const LOCAL_TOPIC = "local-topic"
const SYNC_MSG = -1

const NSQD_ADDR = "127.0.0.1:4150"

type testType struct {
	ID    int
	Value string
}

func init() {
	RegisterGlobalEvent(GLOBAL_TOPIC, util.JSONCodec(&testType{}))
}

func TestEventBus(t *testing.T) {
	eventBus := New(nil)

	ch := make(chan int, 5)
	eventBus.SubscribeAsync("topic1", func(e interface{}) { ch <- 1 })
	eventBus.SubscribeAsync("topic2", func(e interface{}) { ch <- (e.(int)) + 1 })
	eventBus.SubscribeAsync("topic2", func(e interface{}) { ch <- e.(int) })

	eventBus.Publish("topic1", nil)
	eventBus.Publish("topic2", 2)
	eventBus.Wait("topic1")
	eventBus.Wait("topic2")
	assert.Equal(t, 3, len(ch))

	vals := []int{<-ch, <-ch, <-ch}
	sort.Ints(vals)
	assert.Equal(t, []int{1, 2, 3}, vals)
}

func TestEventBusGlobally(t *testing.T) {
	testutils.SkipIfShort(t)

	messages := []*testType{
		&testType{0, "message-1"},
		&testType{1, "message-2"},
		&testType{2, "message-3"},
		&testType{3, "message-4"},
	}

	globalEventBus, err := geventbus.NewNSQEventBus(NSQD_ADDR)
	assert.Nil(t, err)

	secondGlobalBus, err := geventbus.NewNSQEventBus(NSQD_ADDR)
	assert.Nil(t, err)

	// Use atomic ints to sync the callback functions.
	firstMap := newAtomicMap()
	firstEventBus := New(globalEventBus)
	firstEventBus.SubscribeAsync(GLOBAL_TOPIC, func(e interface{}) {
		data := e.(*testType)
		if data.ID == SYNC_MSG {
			firstMap.setReady()
			return
		}
		firstMap.Add(data.ID, data)
	})

	secondMap := newAtomicMap()
	errCh := make(chan error, 100)
	assert.Nil(t, secondGlobalBus.SubscribeAsync(GLOBAL_TOPIC, geventbus.JSONCallback(&testType{}, func(data interface{}, err error) {
		if err != nil {
			errCh <- err
			return
		}

		if data.(*testType).ID == SYNC_MSG {
			secondMap.setReady()
			return
		}

		d := data.(*testType)
		secondMap.Add(d.ID, d)
	})))

	// Wait until both buses are ready before sending real data.  Otherwise, the first few messages
	// may get lost and we will be stuck in an infinite loop waiting for there to
	// be 4 recieved messages.
	for !firstMap.isReady() || !secondMap.isReady() {
		firstEventBus.Publish(GLOBAL_TOPIC, &testType{SYNC_MSG, "ignore"})
	}

	for _, m := range messages {
		firstEventBus.Publish(GLOBAL_TOPIC, m)
	}

	lmsg := len(messages)
	for ((firstMap.Len() < lmsg) || (secondMap.Len() < lmsg)) && (len(errCh) == 0) {
		time.Sleep(time.Millisecond * 10)
	}

	if len(errCh) > 0 {
		close(errCh)
		for err = range errCh {
			fmt.Printf("Error: %s\n", err)
		}
		assert.Fail(t, "Received too many error messages.")
	}
}

func TestSubTopics(t *testing.T) {
	testutils.SkipIfShort(t)

	const N_NUMBERS = 200
	const ALL_NUMBERS_EVENT = "allNumbers"
	const EVEN_NUMBERS_EVENT = "evenNumbers"

	RegisterSubTopic(ALL_NUMBERS_EVENT, EVEN_NUMBERS_EVENT, func(data interface{}) bool {
		i, ok := data.(int)
		if !ok {
			return false
		}
		return i%2 == 0
	})

	eventBus := New(nil)
	allCh := make(chan int, N_NUMBERS*3)
	evenCh := make(chan int, N_NUMBERS*3)
	eventBus.SubscribeAsync(ALL_NUMBERS_EVENT, func(e interface{}) { allCh <- e.(int) })
	eventBus.SubscribeAsync(EVEN_NUMBERS_EVENT, func(e interface{}) { evenCh <- e.(int) })

	allExpected := []int{}
	evenExpected := []int{}
	for i := 0; i < N_NUMBERS; i++ {
		eventBus.Publish(ALL_NUMBERS_EVENT, i)
		allExpected = append(allExpected, i)
		if i%2 == 0 {
			evenExpected = append(evenExpected, i)
		}
	}

	eventBus.Wait(ALL_NUMBERS_EVENT)
	close(allCh)
	close(evenCh)

	assert.Equal(t, N_NUMBERS, len(allCh))
	compChan(t, allExpected, allCh)
	compChan(t, evenExpected, evenCh)
}

func compChan(t assert.TestingT, exp []int, ch <-chan int) {
	actual := []int{}
	for v := range ch {
		actual = append(actual, v)
	}
	sort.Ints(actual)
	assert.Equal(t, exp, actual)
}

type atomicMap struct {
	m     map[int]*testType
	mutex sync.Mutex
	ready bool
}

func newAtomicMap() *atomicMap {
	return &atomicMap{
		m:     map[int]*testType{},
		ready: false,
	}
}

func (a *atomicMap) Add(k int, v *testType) {
	a.mutex.Lock()
	defer a.mutex.Unlock()
	a.m[k] = v
}

func (a *atomicMap) Len() int {
	a.mutex.Lock()
	defer a.mutex.Unlock()
	return len(a.m)
}

func (a *atomicMap) setReady() {
	a.mutex.Lock()
	defer a.mutex.Unlock()
	a.ready = true
}

func (a *atomicMap) isReady() bool {
	a.mutex.Lock()
	defer a.mutex.Unlock()
	return a.ready
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/tls"
	"encoding/json"
	"github.com/gorilla/mux"
	"github.com/streadway/amqp"
	"koding/fujin/fastproxy"
	"koding/fujin/proxyconfig"
	"koding/tools/config"
	"log"
	"net"
	"net/http"
	"net/http/httputil"
	"net/url"
	"os"
	"strings"
	"time"
)

func init() {
	log.SetPrefix("fujin ")
}

type IncomingMessage struct {
	ProxyResponse *proxyconfig.ProxyResponse
}

var proxy proxyconfig.Proxy // this will be only updated whenever we receive a msg from kontrold
var proxyDB *proxyconfig.ProxyConfiguration
var amqpStream *AmqpStream
var start chan bool
var first bool = true

func main() {
	log.Printf("fujin proxy started ")
	start = make(chan bool)

	// open kontrol-daemon database connection
	var err error
	proxyDB, err = proxyconfig.Connect()
	if err != nil {
		log.Fatalf("proxyconfig mongodb connect: %s", err)
	}

	// register fujin instance to kontrol-daemon
	amqpStream = setupAmqp()
	log.Printf("register fujin to kontrold with uuid '%s'", amqpStream.uuid)
	amqpStream.Publish(buildProxyCmd("addProxy", amqpStream.uuid))
	log.Println("register command is send. waiting for response from kontrold...")
	go handleInput(amqpStream.input, amqpStream.uuid)

	select {
	case <-time.After(time.Second * 15):
		log.Fatalf("ERROR: no repsonse received from kontrold, aborting process.")
		os.Exit(1)
	case <-start: // wait until we got message from kontrold or exit via above chan
	}

	// addHTTP, err := net.ResolveTCPAddr("tcp", ":"+config.HttpPort)
	// if err != nil {
	// 	log.Println(err)
	// 	return
	// }

	// addHTTPS, err := net.ResolveTCPAddr("tcp", ":"+config.HttpsPort)
	// if err != nil {
	// 	log.Println(err)
	// 	return
	// }

	// cert, err := tls.LoadX509KeyPair("cert.pem", "key.pem")
	// if err != nil {
	// 	log.Println("https mode is disabled. please add cert.pem and key.pem files.")
	// } else {
	// 	log.Printf("https mode is enabled. serving at :%s ...", config.HttpsPort)
	// 	go listenProxy(addHTTPS, &cert, amqpStream.uuid)
	// }

	// log.Printf("normal mode is enabled. serving at :%s ...", config.HttpPort)
	// listenProxy(addHTTP, nil, amqpStream.uuid)

	// start one with go in order not to block the other one

	r := mux.NewRouter()
	r.Handle("/", newReverseProxy())
	http.Handle("/", r)

	go func() {
		err = http.ListenAndServeTLS(":"+config.HttpsPort, "cert.pem", "key.pem", nil)
		if err != nil {
			log.Println("https mode is disabled. please add cert.pem and key.pem files.")
		} else {
			log.Printf("https mode is enabled. serving at :%s ...", config.HttpsPort)
		}
	}()

	log.Printf("normal mode is enabled. serving at :%s ...", config.HttpPort)
	http.ListenAndServe(":"+config.HttpPort, nil)
}

func newReverseProxy() *httputil.ReverseProxy {
	director := func(req *http.Request) {
		log.Println("HOST:", req.RequestURI, req.Host)
		var deaths int
		name, key := parseKey(req.Host)
		if name == "homepage" {
			log.Println("Hello world!")
			return
		}

		target := targetUrl(deaths, name, key)

		targetQuery := target.RawQuery

		req.URL.Scheme = target.Scheme
		req.URL.Host = target.Host
		req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path)
		if targetQuery == "" || req.URL.RawQuery == "" {
			req.URL.RawQuery = targetQuery + req.URL.RawQuery
		} else {
			req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
		}
	}

	return &httputil.ReverseProxy{Director: director}
}

func listenProxy(localAddr *net.TCPAddr, cert *tls.Certificate, uuid string) {
	err := fastproxy.Listen(localAddr, cert, func(req fastproxy.Request) {
		var deaths int
		name, key := parseKey(req.Host)
		if name == "homepage" {
			req.Write("Hello fujin proxy!")
			return
		}

		target := targetUrl(deaths, name, key)
		remoteAddr, err := net.ResolveTCPAddr("tcp", target.Host)
		if err != nil {
			log.Println(err)
			return
		}

		if err := req.Relay(remoteAddr); err != nil {
			log.Println(err)
			req.Redirect("http://example.com")
		}
	})

	if err != nil {
		log.Fatalf("FATAL ERROR: %s", err)
	}
}

func parseKey(host string) (string, string) {
	log.Println("HOST string", host)
	counts := strings.Count(host, "-")
	log.Println("count string", counts)
	if counts == 0 {
		return "homepage", ""
	}

	partsFirst := strings.Split(host, ".")
	firstSub := partsFirst[0]

	partsSecond := strings.Split(firstSub, "-")
	name := partsSecond[0]
	key := partsSecond[1]

	return name, key
}

func handleInput(input <-chan amqp.Delivery, uuid string) {
	for {
		select {
		case d := <-input:
			// log.Printf("got %dB message data: [%v] %s",
			// 	len(d.Body),
			// 	d.DeliveryTag,
			// 	d.Body)

			var msg IncomingMessage

			err := json.Unmarshal(d.Body, &msg)
			if err != nil {
				log.Print("bad json incoming msg: ", err)
			}

			if msg.ProxyResponse != nil {
				if msg.ProxyResponse.Action == "updateProxy" {
					log.Println("update action received from kontrold. updating proxy route table")
					var err error
					proxy, err = proxyDB.GetProxy(uuid)
					if err != nil {
						log.Println(err)
					}

					if first {
						start <- true
						first = false
						log.Println("routing tables updated. ready to start servers.")
					}

				}

			} else {
				log.Println("incoming message is in wrong format")
			}
		}
	}
}

func targetUrl(numberOfDeaths int, name, key string) *url.URL {
	var target *url.URL
	var err error
	host := targetHost(name, key)

	keyRoutingTable := proxy.Services[name]
	v := len(keyRoutingTable.Keys[key])
	if v == numberOfDeaths {
		log.Println("All given servers are death. Fallback to localhost:8000")
		target, err = url.Parse("http://localhost:8000")
		if err != nil {
			log.Fatal(err)
		}
		return target
	}

	err = checkServer(host)
	if err != nil {
		log.Println(err)
		log.Printf("Server is death: %s. Trying to get another one", host)
		numberOfDeaths++

		target = targetUrl(numberOfDeaths, name, key)
	} else {
		target, err = url.Parse("http://" + host)
		if err != nil {
			log.Fatal(err)
		}

		log.Printf("got / request. using proxy to %s (key: %s)", target.Host, key)
	}
	return target
}

// Implement with fastProxy ...
func checkServer(host string) error {
	remoteAddr, err := net.ResolveTCPAddr("tcp", host)
	if err != nil {
		return err
	}

	remoteConn, err := net.DialTCP("tcp", nil, remoteAddr)
	if err != nil {
		return err
	}

	remoteConn.Close()
	return nil
}

func targetHost(name, key string) string {
	var hostname string

	keyRoutingTable := proxy.Services[name]

	v := len(keyRoutingTable.Keys)
	if v == 0 {
		hostname = "localhost:8000"
		log.Println("no keys are added, using default url ", hostname)
	} else {
		// use round-robin algorithm for each hostname
		for i, value := range keyRoutingTable.Keys[key] {
			currentIndex := value.CurrentIndex
			if currentIndex == i {
				hostname = value.Host
				for k, _ := range keyRoutingTable.Keys[key] {
					if len(keyRoutingTable.Keys[key])-1 == currentIndex {
						keyRoutingTable.Keys[key][k].CurrentIndex = 0 // reached end
					} else {
						keyRoutingTable.Keys[key][k].CurrentIndex = currentIndex + 1
					}
				}
				break
			}
		}
	}

	return hostname
}

func buildProxyCmd(action, uuid string) []byte {
	var req proxyconfig.ProxyMessage
	req.Action = action
	req.Uuid = uuid

	data, err := json.Marshal(req)
	if err != nil {
		log.Println("json marshall error", err)
	}

	return data
}

// this is from ReverseProxy.go, can change..
func singleJoiningSlash(a, b string) string {
	aslash := strings.HasSuffix(a, "/")
	bslash := strings.HasPrefix(b, "/")
	switch {
	case aslash && bslash:
		return a + b[1:]
	case !aslash && !bslash:
		return a + "/" + b
	}
	return a + b
}
<commit_msg>Modify and include go's own reverse proxy code<commit_after>package main

import (
	"crypto/tls"
	"encoding/json"
	"errors"
	"github.com/streadway/amqp"
	"io"
	"koding/fujin/fastproxy"
	"koding/fujin/proxyconfig"
	"koding/tools/config"
	"log"
	"net"
	"net/http"
	"net/url"
	"os"
	"strings"
	"sync"
	"time"
)

func init() {
	log.SetPrefix("fujin ")
}

type IncomingMessage struct {
	ProxyResponse *proxyconfig.ProxyResponse
}

var proxy proxyconfig.Proxy // this will be only updated whenever we receive a msg from kontrold
var proxyDB *proxyconfig.ProxyConfiguration
var amqpStream *AmqpStream
var start chan bool
var first bool = true

func main() {
	log.Printf("fujin proxy started ")
	start = make(chan bool)

	// open kontrol-daemon database connection
	var err error
	proxyDB, err = proxyconfig.Connect()
	if err != nil {
		log.Fatalf("proxyconfig mongodb connect: %s", err)
	}

	// register fujin instance to kontrol-daemon
	amqpStream = setupAmqp()
	log.Printf("register fujin to kontrold with uuid '%s'", amqpStream.uuid)
	amqpStream.Publish(buildProxyCmd("addProxy", amqpStream.uuid))
	log.Println("register command is send. waiting for response from kontrold...")
	go handleInput(amqpStream.input, amqpStream.uuid)

	select {
	case <-time.After(time.Second * 15):
		log.Fatalf("ERROR: no repsonse received from kontrold, aborting process.")
		os.Exit(1)
	case <-start: // wait until we got message from kontrold or exit via above chan
	}

	// addHTTP, err := net.ResolveTCPAddr("tcp", ":"+config.HttpPort)
	// if err != nil {
	// 	log.Println(err)
	// 	return
	// }

	// addHTTPS, err := net.ResolveTCPAddr("tcp", ":"+config.HttpsPort)
	// if err != nil {
	// 	log.Println(err)
	// 	return
	// }

	// cert, err := tls.LoadX509KeyPair("cert.pem", "key.pem")
	// if err != nil {
	// 	log.Println("https mode is disabled. please add cert.pem and key.pem files.")
	// } else {
	// 	log.Printf("https mode is enabled. serving at :%s ...", config.HttpsPort)
	// 	go listenProxy(addHTTPS, &cert, amqpStream.uuid)
	// }

	// log.Printf("normal mode is enabled. serving at :%s ...", config.HttpPort)
	// listenProxy(addHTTP, nil, amqpStream.uuid)

	reverseProxy := NewSingleHostReverseProxy()
	http.Handle("/", reverseProxy)

	// http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
	// 	fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
	// })

	// start one with go in order not to block the other one
	go func() {
		err = http.ListenAndServeTLS(":"+config.HttpsPort, "cert.pem", "key.pem", nil)
		if err != nil {
			log.Println("https mode is disabled. please add cert.pem and key.pem files.")
		} else {
			log.Printf("https mode is enabled. serving at :%s ...", config.HttpsPort)
		}
	}()

	log.Printf("normal mode is enabled. serving at :%s ...", config.HttpPort)
	http.ListenAndServe(":"+config.HttpPort, nil)
}

func Handler(writer http.ResponseWriter, req *http.Request) {

	// writer.Write([]byte(data))
}

// func newReverseProxy() *httputil.ReverseProxy {
// 	director := func(req *http.Request) {
// 		log.Println("HOST:", req.RequestURI, req.Host)
// 		var deaths int
// 		name, key := parseKey(req.Host)
// 		if name == "homepage" {
// 			log.Println("hello world!")
// 			return
// 		}
//
// 		target := targetUrl(deaths, name, key)
//
// 		targetQuery := target.RawQuery
//
// 		req.URL.Scheme = target.Scheme
// 		req.URL.Host = target.Host
// 		req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path)
// 		if targetQuery == "" || req.URL.RawQuery == "" {
// 			req.URL.RawQuery = targetQuery + req.URL.RawQuery
// 		} else {
// 			req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
// 		}
// 	}
//
// 	reverseProxy := &httputil.ReverseProxy{Director: director}
//
// 	return reverseProxy
// }

func listenProxy(localAddr *net.TCPAddr, cert *tls.Certificate, uuid string) {
	err := fastproxy.Listen(localAddr, cert, func(req fastproxy.Request) {
		var deaths int
		name, key := parseKey(req.Host)
		if name == "homepage" {
			req.Write("Hello fujin proxy!")
			return
		}

		target := targetUrl(deaths, name, key)
		remoteAddr, err := net.ResolveTCPAddr("tcp", target.Host)
		if err != nil {
			log.Println(err)
			return
		}

		if err := req.Relay(remoteAddr); err != nil {
			log.Println(err)
			req.Redirect("http://example.com")
		}
	})

	if err != nil {
		log.Fatalf("FATAL ERROR: %s", err)
	}
}

func parseKey(host string) (string, string) {
	counts := strings.Count(host, "-")
	if counts == 0 {
		return "homepage", ""
	}

	partsFirst := strings.Split(host, ".")
	firstSub := partsFirst[0]

	partsSecond := strings.Split(firstSub, "-")
	name := partsSecond[0]
	key := partsSecond[1]

	return name, key
}

func handleInput(input <-chan amqp.Delivery, uuid string) {
	for {
		select {
		case d := <-input:
			// log.Printf("got %dB message data: [%v] %s",
			// 	len(d.Body),
			// 	d.DeliveryTag,
			// 	d.Body)

			var msg IncomingMessage

			err := json.Unmarshal(d.Body, &msg)
			if err != nil {
				log.Print("bad json incoming msg: ", err)
			}

			if msg.ProxyResponse != nil {
				if msg.ProxyResponse.Action == "updateProxy" {
					log.Println("update action received from kontrold. updating proxy route table")
					var err error
					proxy, err = proxyDB.GetProxy(uuid)
					if err != nil {
						log.Println(err)
					}

					if first {
						start <- true
						first = false
						log.Println("routing tables updated. ready to start servers.")
					}

				}

			} else {
				log.Println("incoming message is in wrong format")
			}
		}
	}
}

func targetUrl(numberOfDeaths int, name, key string) *url.URL {
	var target *url.URL
	var err error
	host := targetHost(name, key)

	keyRoutingTable := proxy.Services[name]
	v := len(keyRoutingTable.Keys[key])
	if v == numberOfDeaths {
		log.Println("All given servers are death. Fallback to localhost:8000")
		target, err = url.Parse("http://localhost:8000")
		if err != nil {
			log.Fatal(err)
		}
		return target
	}

	err = checkServer(host)
	if err != nil {
		log.Println(err)
		log.Printf("Server is death: %s. Trying to get another one", host)
		numberOfDeaths++

		target = targetUrl(numberOfDeaths, name, key)
	} else {
		target, err = url.Parse("http://" + host)
		if err != nil {
			log.Fatal(err)
		}

		log.Printf("got / request. using proxy to %s (key: %s)", target.Host, key)
	}
	return target
}

// Implement with fastProxy ...
func checkServer(host string) error {
	remoteAddr, err := net.ResolveTCPAddr("tcp", host)
	if err != nil {
		return err
	}

	remoteConn, err := net.DialTCP("tcp", nil, remoteAddr)
	if err != nil {
		return err
	}

	remoteConn.Close()
	return nil
}

func targetHost(name, key string) string {
	var hostname string

	keyRoutingTable := proxy.Services[name]

	v := len(keyRoutingTable.Keys)
	if v == 0 {
		hostname = "localhost:8000"
		log.Println("no keys are added, using default url ", hostname)
	} else {
		// use round-robin algorithm for each hostname
		for i, value := range keyRoutingTable.Keys[key] {
			currentIndex := value.CurrentIndex
			if currentIndex == i {
				hostname = value.Host
				for k, _ := range keyRoutingTable.Keys[key] {
					if len(keyRoutingTable.Keys[key])-1 == currentIndex {
						keyRoutingTable.Keys[key][k].CurrentIndex = 0 // reached end
					} else {
						keyRoutingTable.Keys[key][k].CurrentIndex = currentIndex + 1
					}
				}
				break
			}
		}
	}

	return hostname
}

func buildProxyCmd(action, uuid string) []byte {
	var req proxyconfig.ProxyMessage
	req.Action = action
	req.Uuid = uuid

	data, err := json.Marshal(req)
	if err != nil {
		log.Println("json marshall error", err)
	}

	return data
}

/*************************************************
*
*  modified version of go's reverseProxy source code
*  has support for dynamic url and websockets
*
*  - arslan
*************************************************/

// onExitFlushLoop is a callback set by tests to detect the state of the
// flushLoop() goroutine.
var onExitFlushLoop func()

// ReverseProxy is an HTTP Handler that takes an incoming request and
// sends it to another server, proxying the response back to the
// client.
type ReverseProxy struct {
	// Director must be a function which modifies
	// the request into a new request to be sent
	// using Transport. Its response is then copied
	// back to the original client unmodified.
	Director func(*http.Request)

	// The transport used to perform proxy requests.
	// If nil, http.DefaultTransport is used.
	Transport http.RoundTripper

	// FlushInterval specifies the flush interval
	// to flush to the client while copying the
	// response body.
	// If zero, no periodic flushing is done.
	FlushInterval time.Duration
}

func singleJoiningSlash(a, b string) string {
	aslash := strings.HasSuffix(a, "/")
	bslash := strings.HasPrefix(b, "/")
	switch {
	case aslash && bslash:
		return a + b[1:]
	case !aslash && !bslash:
		return a + "/" + b
	}
	return a + b
}

// NewSingleHostReverseProxy returns a new ReverseProxy that rewrites
// URLs to the scheme, host, and base path provided in target. If the
// target's path is "/base" and the incoming request was for "/dir",
// the target request will be for /base/dir.
func NewSingleHostReverseProxy() *ReverseProxy {
	director := func(req *http.Request) {
		log.Println("HOST:", req.RequestURI, req.Host)
		var deaths int
		name, key := parseKey(req.Host)
		if name == "homepage" {
			log.Println("hello world!")
			return
		}

		target := targetUrl(deaths, name, key)

		targetQuery := target.RawQuery

		req.URL.Scheme = target.Scheme
		req.URL.Host = target.Host
		req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path)
		if targetQuery == "" || req.URL.RawQuery == "" {
			req.URL.RawQuery = targetQuery + req.URL.RawQuery
		} else {
			req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
		}
	}

	return &ReverseProxy{Director: director}
}

func copyHeader(dst, src http.Header) {
	for k, vv := range src {
		for _, v := range vv {
			dst.Add(k, v)
		}
	}
}

// Hop-by-hop headers. These are removed when sent to the backend.
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html
var hopHeaders = []string{
	"Connection",
	"Keep-Alive",
	"Proxy-Authenticate",
	"Proxy-Authorization",
	"Te", // canonicalized version of "TE"
	"Trailers",
	"Transfer-Encoding",
	"Upgrade",
}

func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	reqHost, err := net.ResolveTCPAddr("tcp", req.Host)
	if err != nil {
		log.Println(err)
		return
	}
	localHost, err := localIP()

	if localHost.String() == reqHost.IP.String() {
		io.WriteString(rw, "hello, world!\n")
		return
	}

	transport := p.Transport
	if transport == nil {
		transport = http.DefaultTransport
	}

	outreq := new(http.Request)
	*outreq = *req // includes shallow copies of maps, but okay

	p.Director(outreq)
	outreq.Proto = "HTTP/1.1"
	outreq.ProtoMajor = 1
	outreq.ProtoMinor = 1
	outreq.Close = false

	// Remove hop-by-hop headers to the backend.  Especially
	// important is "Connection" because we want a persistent
	// connection, regardless of what the client sent to us.  This
	// is modifying the same underlying map from req (shallow
	// copied above) so we only copy it if necessary.
	copiedHeaders := false
	for _, h := range hopHeaders {
		if outreq.Header.Get(h) != "" {
			if !copiedHeaders {
				outreq.Header = make(http.Header)
				copyHeader(outreq.Header, req.Header)
				copiedHeaders = true
			}
			outreq.Header.Del(h)
		}
	}

	if clientIP, _, err := net.SplitHostPort(req.RemoteAddr); err == nil {
		// If we aren't the first proxy retain prior
		// X-Forwarded-For information as a comma+space
		// separated list and fold multiple headers into one.
		if prior, ok := outreq.Header["X-Forwarded-For"]; ok {
			clientIP = strings.Join(prior, ", ") + ", " + clientIP
		}
		outreq.Header.Set("X-Forwarded-For", clientIP)
	}

	res, err := transport.RoundTrip(outreq)
	if err != nil {
		log.Printf("http: proxy error: %v", err)
		rw.WriteHeader(http.StatusInternalServerError)
		return
	}
	defer res.Body.Close()

	copyHeader(rw.Header(), res.Header)

	rw.WriteHeader(res.StatusCode)
	p.copyResponse(rw, res.Body)
}

func (p *ReverseProxy) copyResponse(dst io.Writer, src io.Reader) {
	if p.FlushInterval != 0 {
		if wf, ok := dst.(writeFlusher); ok {
			mlw := &maxLatencyWriter{
				dst:     wf,
				latency: p.FlushInterval,
				done:    make(chan bool),
			}
			go mlw.flushLoop()
			defer mlw.stop()
			dst = mlw
		}
	}

	io.Copy(dst, src)
}

type writeFlusher interface {
	io.Writer
	http.Flusher
}

type maxLatencyWriter struct {
	dst     writeFlusher
	latency time.Duration

	lk   sync.Mutex // protects Write + Flush
	done chan bool
}

func (m *maxLatencyWriter) Write(p []byte) (int, error) {
	m.lk.Lock()
	defer m.lk.Unlock()
	return m.dst.Write(p)
}

func (m *maxLatencyWriter) flushLoop() {
	t := time.NewTicker(m.latency)
	defer t.Stop()
	for {
		select {
		case <-m.done:
			if onExitFlushLoop != nil {
				onExitFlushLoop()
			}
			return
		case <-t.C:
			m.lk.Lock()
			m.dst.Flush()
			m.lk.Unlock()
		}
	}
}

func (m *maxLatencyWriter) stop() { m.done <- true }

func localIP() (net.IP, error) {
	tt, err := net.Interfaces()
	if err != nil {
		return nil, err
	}
	for _, t := range tt {
		aa, err := t.Addrs()
		if err != nil {
			return nil, err
		}
		for _, a := range aa {
			ipnet, ok := a.(*net.IPNet)
			if !ok {
				continue
			}
			v4 := ipnet.IP.To4()
			if v4 == nil || v4[0] == 127 { // loopback address
				continue
			}
			return v4, nil
		}
	}
	return nil, errors.New("cannot find local IP address")
}
<|endoftext|>