<commit_before>package runner

import (
	"fmt"
	"regexp"
	"time"

	"github.com/jinzhu/gorm"
	"github.com/koding/logging"
	_ "github.com/lib/pq"
)

// Gorm is goroutines friendly, so you can create a global variable
// to keep the connection and use it everywhere in your project
var DB *gorm.DB

func MustInitDB(conf *Config, log logging.Logger, debug bool) *gorm.DB {
	connString := fmt.Sprintf(
		"host=%s port=%s user=%s password=%s dbname=%s sslmode=disable",
		conf.Postgres.Host,
		conf.Postgres.Port,
		conf.Postgres.Username,
		conf.Postgres.Password,
		conf.Postgres.DBName,
	)

	db, err := gorm.Open("postgres", connString)
	if err != nil {
		panic(fmt.Sprintf("Got error while connecting to database, the error is '%v'", err))
	}
	// By default, table name is plural of struct type, you can use struct type as table name with:
	db.SingularTable(true)

	db.SetLogger(NewGormLogger(log))

	// log queries if only in debug mode
	if debug {
		db.LogMode(true)
	}

	DB = &db
	return &db
}

func NewGormLogger(log logging.Logger) *gormLogger {
	return &gormLogger{log: log}
}

// custom logger for gorm
type gormLogger struct {
	log logging.Logger
}

// Format log
var sqlRegexp = regexp.MustCompile(`(\$\d+)|\?`)

// implement gorm logging interface
func (g *gormLogger) Print(v ...interface{}) {
	messages := []interface{}{}

	// taken from gorm log file
	if len(v) > 4 {
		messages = append(messages, fmt.Sprintf("[%.2fms] ", float64(v[2].(time.Duration).Nanoseconds()/1e4)/100.0))
		messages = append(messages, fmt.Sprintf(sqlRegexp.ReplaceAllString(v[3].(string), "'%v'"), v[4].([]interface{})...))
	} else {
		for _, message := range v {
			messages = append(messages, fmt.Sprintf("%s", message))
		}
	}

	format := ""
	for i := 0; i < len(messages); i++ {
		format += "%s"
	}

	g.log.Debug(format, messages...)
}
<commit_msg>go: set max open connections<commit_after>package runner

import (
	"fmt"
	"regexp"
	"time"

	"github.com/jinzhu/gorm"
	"github.com/koding/logging"
	_ "github.com/lib/pq"
)

// Gorm is goroutines friendly, so you can create a global variable
// to keep the connection and use it everywhere in your project
var DB *gorm.DB

func MustInitDB(conf *Config, log logging.Logger, debug bool) *gorm.DB {
	connString := fmt.Sprintf(
		"host=%s port=%s user=%s password=%s dbname=%s sslmode=disable",
		conf.Postgres.Host,
		conf.Postgres.Port,
		conf.Postgres.Username,
		conf.Postgres.Password,
		conf.Postgres.DBName,
	)

	db, err := gorm.Open("postgres", connString)
	if err != nil {
		panic(fmt.Sprintf("Got error while connecting to database, the error is '%v'", err))
	}
	// By default, table name is plural of struct type, you can use struct type as table name with:
	db.SingularTable(true)
	db.DB().SetMaxOpenConns(50)
	db.SetLogger(NewGormLogger(log))

	// log queries if only in debug mode
	if debug {
		db.LogMode(true)
	}

	DB = &db
	return &db
}

func NewGormLogger(log logging.Logger) *gormLogger {
	return &gormLogger{log: log}
}

// custom logger for gorm
type gormLogger struct {
	log logging.Logger
}

// Format log
var sqlRegexp = regexp.MustCompile(`(\$\d+)|\?`)

// implement gorm logging interface
func (g *gormLogger) Print(v ...interface{}) {
	messages := []interface{}{}

	// taken from gorm log file
	if len(v) > 4 {
		messages = append(messages, fmt.Sprintf("[%.2fms] ", float64(v[2].(time.Duration).Nanoseconds()/1e4)/100.0))
		messages = append(messages, fmt.Sprintf(sqlRegexp.ReplaceAllString(v[3].(string), "'%v'"), v[4].([]interface{})...))
	} else {
		for _, message := range v {
			messages = append(messages, fmt.Sprintf("%s", message))
		}
	}

	format := ""
	for i := 0; i < len(messages); i++ {
		format += "%s"
	}

	g.log.Debug(format, messages...)
}
<|endoftext|>


<commit_before>/*
Copyright 2011-2017 Frederic Langlet
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
you may obtain a copy of the License at

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

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

package main

import (
	"fmt"
	"io"
	"kanzi"
	kio "kanzi/io"
	"os"
	"path/filepath"
	"strings"
	"time"
)

const (
	DECOMP_DEFAULT_BUFFER_SIZE = 32768
)

// Main block decompressor struct
type BlockDecompressor struct {
	verbosity  uint
	overwrite  bool
	inputName  string
	outputName string
	jobs       uint
	listeners  []kanzi.Listener
	cpuProf    string
}

func NewBlockDecompressor(argsMap map[string]interface{}) (*BlockDecompressor, error) {
	this := new(BlockDecompressor)
	this.listeners = make([]kanzi.Listener, 0)

	this.verbosity = argsMap["verbose"].(uint)
	delete(argsMap, "verbose")

	if force, prst := argsMap["overwrite"]; prst == true {
		this.overwrite = force.(bool)
		delete(argsMap, "overwrite")
	} else {
		this.overwrite = false
	}

	this.inputName = argsMap["inputName"].(string)
	delete(argsMap, "inputName")
	this.outputName = argsMap["outputName"].(string)
	delete(argsMap, "outputName")
	this.jobs = argsMap["jobs"].(uint)
	delete(argsMap, "jobs")

	if prof, prst := argsMap["cpuProf"]; prst == true {
		this.cpuProf = prof.(string)
		delete(argsMap, "cpuProf")
	} else {
		this.cpuProf = ""
	}

	if this.verbosity > 2 {
		if listener, err := NewInfoPrinter(this.verbosity, DECODING, os.Stdout); err == nil {
			this.AddListener(listener)
		}
	}

	if this.verbosity > 0 && len(argsMap) > 0 {
		for k, _ := range argsMap {
			bd_printOut("Ignoring invalid option ["+k+"]", this.verbosity > 0)
		}
	}

	return this, nil
}

func (this *BlockDecompressor) CpuProf() string {
	return this.cpuProf
}

func (this *BlockDecompressor) AddListener(bl kanzi.Listener) bool {
	if bl == nil {
		return false
	}

	this.listeners = append(this.listeners, bl)
	return true
}

func (this *BlockDecompressor) RemoveListener(bl kanzi.Listener) bool {
	for i, e := range this.listeners {
		if e == bl {
			this.listeners = append(this.listeners[:i-1], this.listeners[i+1:]...)
			return true
		}
	}

	return false
}

// Return exit code, number of bits written
func (this *BlockDecompressor) Call() (int, uint64) {
	var msg string
	printFlag := this.verbosity > 2
	bd_printOut("Kanzi 1.2 (C) 2017,  Frederic Langlet", this.verbosity >= 1)
	bd_printOut("Input file name set to '"+this.inputName+"'", printFlag)
	bd_printOut("Output file name set to '"+this.outputName+"'", printFlag)
	msg = fmt.Sprintf("Verbosity set to %v", this.verbosity)
	bd_printOut(msg, printFlag)
	msg = fmt.Sprintf("Overwrite set to %t", this.overwrite)
	bd_printOut(msg, printFlag)

	if this.jobs > 0 {
		prefix := ""

		if this.jobs > 1 {
			prefix = "s"
		}

		msg = fmt.Sprintf("Using %d job%s", this.jobs, prefix)
		bd_printOut(msg, printFlag)
	}

	var output io.WriteCloser

	if strings.ToUpper(this.outputName) == "NONE" {
		output, _ = kio.NewNullOutputStream()
	} else if strings.ToUpper(this.outputName) == "STDOUT" {
		output = os.Stdout
	} else {
		var err error

		if output, err = os.OpenFile(this.outputName, os.O_RDWR, 666); err == nil {
			// File exists
			if this.overwrite == false {
				fmt.Printf("The output file '%v' exists and the 'overwrite' command ", this.outputName)
				fmt.Println("line option has not been provided")
				output.Close()
				return kio.ERR_OVERWRITE_FILE, 0
			}

			path1, _ := filepath.Abs(this.inputName)
			path2, _ := filepath.Abs(this.outputName)

			if path1 == path2 {
				fmt.Print("The input and output files must be different")
				return kio.ERR_CREATE_FILE, 0
			}
		} else {
			// File does not exist, create
			if output, err = os.Create(this.outputName); err != nil {
				fmt.Printf("Cannot open output file '%v' for writing: %v\n", this.outputName, err)
				return kio.ERR_CREATE_FILE, 0
			}
		}
	}

	defer func() {
		output.Close()
	}()

	// Decode
	read := int64(0)
	printFlag = this.verbosity > 1
	bd_printOut("Decoding ...", printFlag)
	var input io.ReadCloser

	if len(this.listeners) > 0 {
		evt := kanzi.NewEvent(kanzi.EVT_DECOMPRESSION_START, -1, 0, 0, false)
		bd_notifyListeners(this.listeners, evt)
	}

	if strings.ToUpper(this.inputName) == "STDIN" {
		input = os.Stdin
	} else {
		var err error

		if input, err = os.Open(this.inputName); err != nil {
			fmt.Printf("Cannot open input file '%v': %v\n", this.inputName, err)
			return kio.ERR_OPEN_FILE, read
		}

		defer func() {
			input.Close()
		}()
	}

	ctx := make(map[string]interface{})
	ctx["jobs"] = this.jobs
	cis, err := kio.NewCompressedInputStream(input, ctx)

	if err != nil {
		if err.(*kio.IOError) != nil {
			fmt.Printf("%s\n", err.(*kio.IOError).Message())
			return err.(*kio.IOError).ErrorCode(), read
		}

		fmt.Printf("Cannot create compressed stream: %v\n", err)
		return kio.ERR_CREATE_DECOMPRESSOR, read
	}

	for _, bl := range this.listeners {
		cis.AddListener(bl)
	}

	buffer := make([]byte, DECOMP_DEFAULT_BUFFER_SIZE)
	decoded := len(buffer)
	before := time.Now()

	// Decode next block
	for decoded == len(buffer) {
		if decoded, err = cis.Read(buffer); err != nil {
			if ioerr, isIOErr := err.(*kio.IOError); isIOErr == true {
				fmt.Printf("%s\n", ioerr.Message())
				return ioerr.ErrorCode(), read
			}

			fmt.Printf("An unexpected condition happened. Exiting ...\n%v\n", err)
			return kio.ERR_PROCESS_BLOCK, read
		}

		if decoded > 0 {
			_, err = output.Write(buffer[0:decoded])

			if err != nil {
				fmt.Printf("Failed to write decompressed block to file '%v': %v\n", this.outputName, err)
				return kio.ERR_WRITE_FILE, read
			}

			read += uint64(decoded)
		}
	}

	// Close streams to ensure all data are flushed
	// Deferred close is fallback for error paths
	if err := cis.Close(); err != nil {
		fmt.Printf("%v\n", err)
		return kio.ERR_PROCESS_BLOCK, read
	}

	after := time.Now()
	delta := after.Sub(before).Nanoseconds() / 1000000 // convert to ms

	bd_printOut("", this.verbosity >= 1)
	msg = fmt.Sprintf("Decoding:          %d ms", delta)
	bd_printOut(msg, printFlag)
	msg = fmt.Sprintf("Input size:        %d", cis.GetRead())
	bd_printOut(msg, printFlag)
	msg = fmt.Sprintf("Output size:       %d", read)
	bd_printOut(msg, printFlag)
	msg = fmt.Sprintf("Decoding: %v => %v bytes in %v ms", cis.GetRead(), read, delta)
	bd_printOut(msg, this.verbosity == 1)

	if delta > 0 {
		msg = fmt.Sprintf("Throughput (KB/s): %d", ((read*uint64(1000))>>10)/uint64(delta))
		bd_printOut(msg, printFlag)
	}

	bd_printOut("", this.verbosity >= 1)

	if len(this.listeners) > 0 {
		evt := kanzi.NewEvent(kanzi.EVT_DECOMPRESSION_END, -1, int64(cis.GetRead()), 0, false)
		bd_notifyListeners(this.listeners, evt)
	}

	return 0, cis.GetRead()
}

func bd_printOut(msg string, print bool) {
	if print == true {
		fmt.Println(msg)
	}
}

func bd_notifyListeners(listeners []kanzi.Listener, evt *kanzi.Event) {
	defer func() {
		if r := recover(); r != nil {
			// Ignore exceptions in listeners
		}
	}()

	for _, bl := range listeners {
		bl.ProcessEvent(evt)
	}
}
<commit_msg>Fix compilation errors due to previous change.<commit_after>/*
Copyright 2011-2017 Frederic Langlet
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
you may obtain a copy of the License at

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

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

package main

import (
	"fmt"
	"io"
	"kanzi"
	kio "kanzi/io"
	"os"
	"path/filepath"
	"strings"
	"time"
)

const (
	DECOMP_DEFAULT_BUFFER_SIZE = 32768
)

// Main block decompressor struct
type BlockDecompressor struct {
	verbosity  uint
	overwrite  bool
	inputName  string
	outputName string
	jobs       uint
	listeners  []kanzi.Listener
	cpuProf    string
}

func NewBlockDecompressor(argsMap map[string]interface{}) (*BlockDecompressor, error) {
	this := new(BlockDecompressor)
	this.listeners = make([]kanzi.Listener, 0)

	this.verbosity = argsMap["verbose"].(uint)
	delete(argsMap, "verbose")

	if force, prst := argsMap["overwrite"]; prst == true {
		this.overwrite = force.(bool)
		delete(argsMap, "overwrite")
	} else {
		this.overwrite = false
	}

	this.inputName = argsMap["inputName"].(string)
	delete(argsMap, "inputName")
	this.outputName = argsMap["outputName"].(string)
	delete(argsMap, "outputName")
	this.jobs = argsMap["jobs"].(uint)
	delete(argsMap, "jobs")

	if prof, prst := argsMap["cpuProf"]; prst == true {
		this.cpuProf = prof.(string)
		delete(argsMap, "cpuProf")
	} else {
		this.cpuProf = ""
	}

	if this.verbosity > 2 {
		if listener, err := NewInfoPrinter(this.verbosity, DECODING, os.Stdout); err == nil {
			this.AddListener(listener)
		}
	}

	if this.verbosity > 0 && len(argsMap) > 0 {
		for k, _ := range argsMap {
			bd_printOut("Ignoring invalid option ["+k+"]", this.verbosity > 0)
		}
	}

	return this, nil
}

func (this *BlockDecompressor) CpuProf() string {
	return this.cpuProf
}

func (this *BlockDecompressor) AddListener(bl kanzi.Listener) bool {
	if bl == nil {
		return false
	}

	this.listeners = append(this.listeners, bl)
	return true
}

func (this *BlockDecompressor) RemoveListener(bl kanzi.Listener) bool {
	for i, e := range this.listeners {
		if e == bl {
			this.listeners = append(this.listeners[:i-1], this.listeners[i+1:]...)
			return true
		}
	}

	return false
}

// Return exit code, number of bits written
func (this *BlockDecompressor) Call() (int, uint64) {
	var msg string
	printFlag := this.verbosity > 2
	bd_printOut("Kanzi 1.2 (C) 2017,  Frederic Langlet", this.verbosity >= 1)
	bd_printOut("Input file name set to '"+this.inputName+"'", printFlag)
	bd_printOut("Output file name set to '"+this.outputName+"'", printFlag)
	msg = fmt.Sprintf("Verbosity set to %v", this.verbosity)
	bd_printOut(msg, printFlag)
	msg = fmt.Sprintf("Overwrite set to %t", this.overwrite)
	bd_printOut(msg, printFlag)

	if this.jobs > 0 {
		prefix := ""

		if this.jobs > 1 {
			prefix = "s"
		}

		msg = fmt.Sprintf("Using %d job%s", this.jobs, prefix)
		bd_printOut(msg, printFlag)
	}

	var output io.WriteCloser

	if strings.ToUpper(this.outputName) == "NONE" {
		output, _ = kio.NewNullOutputStream()
	} else if strings.ToUpper(this.outputName) == "STDOUT" {
		output = os.Stdout
	} else {
		var err error

		if output, err = os.OpenFile(this.outputName, os.O_RDWR, 666); err == nil {
			// File exists
			if this.overwrite == false {
				fmt.Printf("The output file '%v' exists and the 'overwrite' command ", this.outputName)
				fmt.Println("line option has not been provided")
				output.Close()
				return kio.ERR_OVERWRITE_FILE, 0
			}

			path1, _ := filepath.Abs(this.inputName)
			path2, _ := filepath.Abs(this.outputName)

			if path1 == path2 {
				fmt.Print("The input and output files must be different")
				return kio.ERR_CREATE_FILE, 0
			}
		} else {
			// File does not exist, create
			if output, err = os.Create(this.outputName); err != nil {
				fmt.Printf("Cannot open output file '%v' for writing: %v\n", this.outputName, err)
				return kio.ERR_CREATE_FILE, 0
			}
		}
	}

	defer func() {
		output.Close()
	}()

	// Decode
	read := int64(0)
	printFlag = this.verbosity > 1
	bd_printOut("Decoding ...", printFlag)
	var input io.ReadCloser

	if len(this.listeners) > 0 {
		evt := kanzi.NewEvent(kanzi.EVT_DECOMPRESSION_START, -1, 0, 0, false)
		bd_notifyListeners(this.listeners, evt)
	}

	if strings.ToUpper(this.inputName) == "STDIN" {
		input = os.Stdin
	} else {
		var err error

		if input, err = os.Open(this.inputName); err != nil {
			fmt.Printf("Cannot open input file '%v': %v\n", this.inputName, err)
			return kio.ERR_OPEN_FILE, uint64(read)
		}

		defer func() {
			input.Close()
		}()
	}

	ctx := make(map[string]interface{})
	ctx["jobs"] = this.jobs
	cis, err := kio.NewCompressedInputStream(input, ctx)

	if err != nil {
		if err.(*kio.IOError) != nil {
			fmt.Printf("%s\n", err.(*kio.IOError).Message())
			return err.(*kio.IOError).ErrorCode(), uint64(read)
		}

		fmt.Printf("Cannot create compressed stream: %v\n", err)
		return kio.ERR_CREATE_DECOMPRESSOR, uint64(read)
	}

	for _, bl := range this.listeners {
		cis.AddListener(bl)
	}

	buffer := make([]byte, DECOMP_DEFAULT_BUFFER_SIZE)
	decoded := len(buffer)
	before := time.Now()

	// Decode next block
	for decoded == len(buffer) {
		if decoded, err = cis.Read(buffer); err != nil {
			if ioerr, isIOErr := err.(*kio.IOError); isIOErr == true {
				fmt.Printf("%s\n", ioerr.Message())
				return ioerr.ErrorCode(), uint64(read)
			}

			fmt.Printf("An unexpected condition happened. Exiting ...\n%v\n", err)
			return kio.ERR_PROCESS_BLOCK, uint64(read)
		}

		if decoded > 0 {
			_, err = output.Write(buffer[0:decoded])

			if err != nil {
				fmt.Printf("Failed to write decompressed block to file '%v': %v\n", this.outputName, err)
				return kio.ERR_WRITE_FILE, uint64(read)
			}

			read += int64(decoded)
		}
	}

	// Close streams to ensure all data are flushed
	// Deferred close is fallback for error paths
	if err := cis.Close(); err != nil {
		fmt.Printf("%v\n", err)
		return kio.ERR_PROCESS_BLOCK, uint64(read)
	}

	after := time.Now()
	delta := after.Sub(before).Nanoseconds() / 1000000 // convert to ms

	bd_printOut("", this.verbosity >= 1)
	msg = fmt.Sprintf("Decoding:          %d ms", delta)
	bd_printOut(msg, printFlag)
	msg = fmt.Sprintf("Input size:        %d", cis.GetRead())
	bd_printOut(msg, printFlag)
	msg = fmt.Sprintf("Output size:       %d", read)
	bd_printOut(msg, printFlag)
	msg = fmt.Sprintf("Decoding: %v => %v bytes in %v ms", cis.GetRead(), read, delta)
	bd_printOut(msg, this.verbosity == 1)

	if delta > 0 {
		msg = fmt.Sprintf("Throughput (KB/s): %d", ((read*int64(1000))>>10)/int64(delta))
		bd_printOut(msg, printFlag)
	}

	bd_printOut("", this.verbosity >= 1)

	if len(this.listeners) > 0 {
		evt := kanzi.NewEvent(kanzi.EVT_DECOMPRESSION_END, -1, int64(cis.GetRead()), 0, false)
		bd_notifyListeners(this.listeners, evt)
	}

	return 0, cis.GetRead()
}

func bd_printOut(msg string, print bool) {
	if print == true {
		fmt.Println(msg)
	}
}

func bd_notifyListeners(listeners []kanzi.Listener, evt *kanzi.Event) {
	defer func() {
		if r := recover(); r != nil {
			// Ignore exceptions in listeners
		}
	}()

	for _, bl := range listeners {
		bl.ProcessEvent(evt)
	}
}
<|endoftext|>


<commit_before>package kite

import (
	"errors"
	"fmt"
	"koding/newkite/dnode"
	"koding/newkite/dnode/rpc"
	"koding/newkite/kodingkey"
	"koding/newkite/token"
)

// kiteMethod implements dnode.Handler.
type kiteMethod struct {
	kite    *Kite
	method  string
	handler HandlerFunc
}

// WrapArgs is called before a Callback is sent to remote in order to wrap arguments.
func (m kiteMethod) WrapArgs(args []interface{}, tr dnode.Transport) []interface{} {
	return []interface{}{&callOptionsOut{
		WithArgs: args,
		CallOptions: CallOptions{
			Kite: m.kite.Kite,
		},
	}}
}

// Call is called when a method is received from remote.
func (m kiteMethod) Call(method string, args *dnode.Partial, tr dnode.Transport) {
	request, responseCallback, err := m.kite.parseRequest(method, args, tr, true)
	if err != nil {
		m.kite.Log.Notice("Did not understand request: %s", err)
		return
	}

	result, err := m.handler(request)
	if responseCallback == nil {
		return
	}

	if err != nil {
		err = responseCallback(err.Error(), result)
	} else {
		err = responseCallback(nil, result)
	}

	if err != nil {
		m.kite.Log.Error(err.Error())
	}
}

type HandlerFunc func(*Request) (response interface{}, err error)

// HandleFunc registers a handler to run when a method call is received from a Kite.
func (k *Kite) HandleFunc(method string, handler HandlerFunc) {
	k.server.Handle(method, kiteMethod{k, method, handler})
}

type Request struct {
	Method         string
	Args           *dnode.Partial
	LocalKite      *Kite
	RemoteKite     *RemoteKite
	Username       string
	Authentication *callAuthentication
	RemoteAddr     string
}

type Callback func(r *Request)

func (c Callback) MarshalJSON() ([]byte, error) {
	return []byte(`"[Function]"`), nil
}

func (c Callback) WrapArgs(args []interface{}, tr dnode.Transport) []interface{} {
	return []interface{}{&callOptionsOut{
		WithArgs: args,
		CallOptions: CallOptions{
			Kite: tr.Properties()["localKite"].(*Kite).Kite,
		},
	}}
}

// Call is called when a callback method call is received from remote.
func (c Callback) Call(method string, args *dnode.Partial, tr dnode.Transport) {
	k := tr.Properties()["localKite"].(*Kite)
	req, _, err := k.parseRequest(method, args, tr, false)
	if err != nil {
		k.Log.Notice("Did not understand callback message: %s", err)
		return
	}

	c(req)
}

// parseRequest is used to read a dnode message.
// It is called when a method or callback is received.
func (k *Kite) parseRequest(method string, arguments *dnode.Partial, tr dnode.Transport, authenticate bool) (
	request *Request, response dnode.Function, err error) {

	// Parse dnode method arguments [options, response]
	args, err := arguments.Slice()
	if err != nil {
		return
	}
	if len(args) != 1 && len(args) != 2 {
		return nil, nil, errors.New("Invalid number of arguments")
	}

	// Parse options argument
	var options CallOptions
	if err = args[0].Unmarshal(&options); err != nil {
		return
	}

	// Parse response callback if present
	if len(args) > 1 && args[1] != nil {
		if err = args[1].Unmarshal(&response); err != nil {
			return
		}
	}

	// Trust the Kite if we have initiated the connection.
	// Otherwise try to authenticate the user.
	// RemoteAddr() returns "" if this is an outgoing connection.
	// Also we do not need to authenticate requests when a callback method is received.
	if authenticate && tr.RemoteAddr() != "" {
		if err = k.authenticateUser(&options); err != nil {
			return
		}
	}

	// Properties about the client...
	properties := tr.Properties()

	// Create a new RemoteKite instance to pass it to the handler, so
	// the handler can call methods on the other site on the same connection.
	if properties["remoteKite"] == nil {
		// Do not create a new RemoteKite on every request,
		// cache it in Transport.Properties().
		client := tr.(*rpc.Client) // We only have a dnode/rpc.Client for now.
		remoteKite := k.newRemoteKiteWithClient(options.Kite, options.Authentication, client)
		properties["remoteKite"] = remoteKite

		// Notify Kite.OnConnect handlers.
		k.notifyRemoteKiteConnected(remoteKite)
	}

	request = &Request{
		Method:         method,
		Args:           options.WithArgs,
		LocalKite:      k,
		RemoteKite:     properties["remoteKite"].(*RemoteKite),
		RemoteAddr:     tr.RemoteAddr(),
		Username:       options.Kite.Username, // authenticateUser() sets it.
		Authentication: &options.Authentication,
	}

	return
}

// authenticateUser tries to authenticate the user by selecting appropriate
// authenticator function.
func (k *Kite) authenticateUser(options *CallOptions) error {
	f := k.Authenticators[options.Authentication.Type]
	if f == nil {
		return fmt.Errorf("Unknown authentication type: %s", options.Authentication.Type)
	}

	return f(options)
}

// AuthenticateFromToken is the default Authenticator for Kite.
func (k *Kite) AuthenticateFromToken(options *CallOptions) error {
	key, err := kodingkey.FromString(k.KodingKey)
	if err != nil {
		return fmt.Errorf("Invalid Koding Key: %s", k.KodingKey)
	}

	tkn, err := token.DecryptString(options.Authentication.Key, key)
	if err != nil {
		return fmt.Errorf("Invalid token: %s", options.Authentication.Key)
	}

	if !tkn.IsValid(k.ID) {
		return fmt.Errorf("Invalid token: %s", tkn)
	}

	options.Kite.Username = tkn.Username

	return nil
}

// AuthenticateFromToken authenticates user from Koding Key.
// Kontrol makes requests with a Koding Key.
func (k *Kite) AuthenticateFromKodingKey(options *CallOptions) error {
	if options.Authentication.Key != k.KodingKey {
		return fmt.Errorf("Invalid Koding Key")
	}

	// Set the username if missing.
	if options.Kite.Username == "" && k.Username != "" {
		options.Kite.Username = k.Username
	}

	return nil
}
<commit_msg>kite: fix argument name<commit_after>package kite

import (
	"errors"
	"fmt"
	"koding/newkite/dnode"
	"koding/newkite/dnode/rpc"
	"koding/newkite/kodingkey"
	"koding/newkite/token"
)

// kiteMethod implements dnode.Handler.
type kiteMethod struct {
	kite    *Kite
	method  string
	handler HandlerFunc
}

// WrapArgs is called before a Callback is sent to remote in order to wrap arguments.
func (m kiteMethod) WrapArgs(args []interface{}, tr dnode.Transport) []interface{} {
	return []interface{}{&callOptionsOut{
		WithArgs: args,
		CallOptions: CallOptions{
			Kite: m.kite.Kite,
		},
	}}
}

// Call is called when a method is received from remote.
func (m kiteMethod) Call(method string, args *dnode.Partial, tr dnode.Transport) {
	request, responseCallback, err := m.kite.parseRequest(method, args, tr, true)
	if err != nil {
		m.kite.Log.Notice("Did not understand request: %s", err)
		return
	}

	result, err := m.handler(request)
	if responseCallback == nil {
		return
	}

	if err != nil {
		err = responseCallback(err.Error(), result)
	} else {
		err = responseCallback(nil, result)
	}

	if err != nil {
		m.kite.Log.Error(err.Error())
	}
}

type HandlerFunc func(*Request) (result interface{}, err error)

// HandleFunc registers a handler to run when a method call is received from a Kite.
func (k *Kite) HandleFunc(method string, handler HandlerFunc) {
	k.server.Handle(method, kiteMethod{k, method, handler})
}

type Request struct {
	Method         string
	Args           *dnode.Partial
	LocalKite      *Kite
	RemoteKite     *RemoteKite
	Username       string
	Authentication *callAuthentication
	RemoteAddr     string
}

type Callback func(r *Request)

func (c Callback) MarshalJSON() ([]byte, error) {
	return []byte(`"[Function]"`), nil
}

func (c Callback) WrapArgs(args []interface{}, tr dnode.Transport) []interface{} {
	return []interface{}{&callOptionsOut{
		WithArgs: args,
		CallOptions: CallOptions{
			Kite: tr.Properties()["localKite"].(*Kite).Kite,
		},
	}}
}

// Call is called when a callback method call is received from remote.
func (c Callback) Call(method string, args *dnode.Partial, tr dnode.Transport) {
	k := tr.Properties()["localKite"].(*Kite)
	req, _, err := k.parseRequest(method, args, tr, false)
	if err != nil {
		k.Log.Notice("Did not understand callback message: %s", err)
		return
	}

	c(req)
}

// parseRequest is used to read a dnode message.
// It is called when a method or callback is received.
func (k *Kite) parseRequest(method string, arguments *dnode.Partial, tr dnode.Transport, authenticate bool) (
	request *Request, response dnode.Function, err error) {

	// Parse dnode method arguments [options, response]
	args, err := arguments.Slice()
	if err != nil {
		return
	}
	if len(args) != 1 && len(args) != 2 {
		return nil, nil, errors.New("Invalid number of arguments")
	}

	// Parse options argument
	var options CallOptions
	if err = args[0].Unmarshal(&options); err != nil {
		return
	}

	// Parse response callback if present
	if len(args) > 1 && args[1] != nil {
		if err = args[1].Unmarshal(&response); err != nil {
			return
		}
	}

	// Trust the Kite if we have initiated the connection.
	// Otherwise try to authenticate the user.
	// RemoteAddr() returns "" if this is an outgoing connection.
	// Also we do not need to authenticate requests when a callback method is received.
	if authenticate && tr.RemoteAddr() != "" {
		if err = k.authenticateUser(&options); err != nil {
			return
		}
	}

	// Properties about the client...
	properties := tr.Properties()

	// Create a new RemoteKite instance to pass it to the handler, so
	// the handler can call methods on the other site on the same connection.
	if properties["remoteKite"] == nil {
		// Do not create a new RemoteKite on every request,
		// cache it in Transport.Properties().
		client := tr.(*rpc.Client) // We only have a dnode/rpc.Client for now.
		remoteKite := k.newRemoteKiteWithClient(options.Kite, options.Authentication, client)
		properties["remoteKite"] = remoteKite

		// Notify Kite.OnConnect handlers.
		k.notifyRemoteKiteConnected(remoteKite)
	}

	request = &Request{
		Method:         method,
		Args:           options.WithArgs,
		LocalKite:      k,
		RemoteKite:     properties["remoteKite"].(*RemoteKite),
		RemoteAddr:     tr.RemoteAddr(),
		Username:       options.Kite.Username, // authenticateUser() sets it.
		Authentication: &options.Authentication,
	}

	return
}

// authenticateUser tries to authenticate the user by selecting appropriate
// authenticator function.
func (k *Kite) authenticateUser(options *CallOptions) error {
	f := k.Authenticators[options.Authentication.Type]
	if f == nil {
		return fmt.Errorf("Unknown authentication type: %s", options.Authentication.Type)
	}

	return f(options)
}

// AuthenticateFromToken is the default Authenticator for Kite.
func (k *Kite) AuthenticateFromToken(options *CallOptions) error {
	key, err := kodingkey.FromString(k.KodingKey)
	if err != nil {
		return fmt.Errorf("Invalid Koding Key: %s", k.KodingKey)
	}

	tkn, err := token.DecryptString(options.Authentication.Key, key)
	if err != nil {
		return fmt.Errorf("Invalid token: %s", options.Authentication.Key)
	}

	if !tkn.IsValid(k.ID) {
		return fmt.Errorf("Invalid token: %s", tkn)
	}

	options.Kite.Username = tkn.Username

	return nil
}

// AuthenticateFromToken authenticates user from Koding Key.
// Kontrol makes requests with a Koding Key.
func (k *Kite) AuthenticateFromKodingKey(options *CallOptions) error {
	if options.Authentication.Key != k.KodingKey {
		return fmt.Errorf("Invalid Koding Key")
	}

	// Set the username if missing.
	if options.Kite.Username == "" && k.Username != "" {
		options.Kite.Username = k.Username
	}

	return nil
}
<|endoftext|>


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

package binlogplayer

import (
	"fmt"

	log "github.com/golang/glog"
	"github.com/youtube/vitess/go/mysql"
	mproto "github.com/youtube/vitess/go/mysql/proto"
	"github.com/youtube/vitess/go/vt/dbconfigs"
)

// DBClient is a real VtClient backed by a mysql connection
type DBClient struct {
	dbConfig *mysql.ConnectionParams
	dbConn   *mysql.Connection
}

func NewDbClient(params *mysql.ConnectionParams) *DBClient {
	return &DBClient{
		dbConfig: params,
	}
}

func (dc *DBClient) handleError(err error) {
	// log.Errorf("in DBClient handleError %v", err.(error))
	if sqlErr, ok := err.(*mysql.SqlError); ok {
		if sqlErr.Number() >= 2000 && sqlErr.Number() <= 2018 { // mysql connection errors
			dc.Close()
		}
		if sqlErr.Number() == 1317 { // Query was interrupted
			dc.Close()
		}
	}
}

func (dc *DBClient) Connect() error {
	params, err := dbconfigs.MysqlParams(dc.dbConfig)
	if err != nil {
		return err
	}
	dc.dbConn, err = mysql.Connect(params)
	if err != nil {
		return fmt.Errorf("error in connecting to mysql db, err %v", err)
	}
	return nil
}

func (dc *DBClient) Begin() error {
	_, err := dc.dbConn.ExecuteFetch("begin", 1, false)
	if err != nil {
		log.Errorf("BEGIN failed w/ error %v", err)
		dc.handleError(err)
	}
	return err
}

func (dc *DBClient) Commit() error {
	_, err := dc.dbConn.ExecuteFetch("commit", 1, false)
	if err != nil {
		log.Errorf("COMMIT failed w/ error %v", err)
		dc.dbConn.Close()
	}
	return err
}

func (dc *DBClient) Rollback() error {
	_, err := dc.dbConn.ExecuteFetch("rollback", 1, false)
	if err != nil {
		log.Errorf("ROLLBACK failed w/ error %v", err)
		dc.dbConn.Close()
	}
	return err
}

func (dc *DBClient) Close() {
	if dc.dbConn != nil {
		dc.dbConn.Close()
		dc.dbConn = nil
	}
}

func (dc *DBClient) ExecuteFetch(query string, maxrows int, wantfields bool) (*mproto.QueryResult, error) {
	mqr, err := dc.dbConn.ExecuteFetch(query, maxrows, wantfields)
	if err != nil {
		log.Errorf("ExecuteFetch failed w/ error %v", err)
		dc.handleError(err)
		return nil, err
	}
	qr := mproto.QueryResult(*mqr)
	return &qr, nil
}
<commit_msg>Removing a useless copy.<commit_after>// Copyright 2012, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package binlogplayer

import (
	"fmt"

	log "github.com/golang/glog"
	"github.com/youtube/vitess/go/mysql"
	mproto "github.com/youtube/vitess/go/mysql/proto"
	"github.com/youtube/vitess/go/vt/dbconfigs"
)

// DBClient is a real VtClient backed by a mysql connection
type DBClient struct {
	dbConfig *mysql.ConnectionParams
	dbConn   *mysql.Connection
}

func NewDbClient(params *mysql.ConnectionParams) *DBClient {
	return &DBClient{
		dbConfig: params,
	}
}

func (dc *DBClient) handleError(err error) {
	// log.Errorf("in DBClient handleError %v", err.(error))
	if sqlErr, ok := err.(*mysql.SqlError); ok {
		if sqlErr.Number() >= 2000 && sqlErr.Number() <= 2018 { // mysql connection errors
			dc.Close()
		}
		if sqlErr.Number() == 1317 { // Query was interrupted
			dc.Close()
		}
	}
}

func (dc *DBClient) Connect() error {
	params, err := dbconfigs.MysqlParams(dc.dbConfig)
	if err != nil {
		return err
	}
	dc.dbConn, err = mysql.Connect(params)
	if err != nil {
		return fmt.Errorf("error in connecting to mysql db, err %v", err)
	}
	return nil
}

func (dc *DBClient) Begin() error {
	_, err := dc.dbConn.ExecuteFetch("begin", 1, false)
	if err != nil {
		log.Errorf("BEGIN failed w/ error %v", err)
		dc.handleError(err)
	}
	return err
}

func (dc *DBClient) Commit() error {
	_, err := dc.dbConn.ExecuteFetch("commit", 1, false)
	if err != nil {
		log.Errorf("COMMIT failed w/ error %v", err)
		dc.dbConn.Close()
	}
	return err
}

func (dc *DBClient) Rollback() error {
	_, err := dc.dbConn.ExecuteFetch("rollback", 1, false)
	if err != nil {
		log.Errorf("ROLLBACK failed w/ error %v", err)
		dc.dbConn.Close()
	}
	return err
}

func (dc *DBClient) Close() {
	if dc.dbConn != nil {
		dc.dbConn.Close()
		dc.dbConn = nil
	}
}

func (dc *DBClient) ExecuteFetch(query string, maxrows int, wantfields bool) (*mproto.QueryResult, error) {
	mqr, err := dc.dbConn.ExecuteFetch(query, maxrows, wantfields)
	if err != nil {
		log.Errorf("ExecuteFetch failed w/ error %v", err)
		dc.handleError(err)
		return nil, err
	}
	return mqr, nil
}
<|endoftext|>


<commit_before>/*                          _       _
 *__      _____  __ ___   ___  __ _| |_ ___
 *\ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \
 * \ V  V /  __/ (_| |\ V /| | (_| | ||  __/
 *  \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___|
 *
 * Copyright © 2016 - 2018 Weaviate. All rights reserved.
 * LICENSE: https://github.com/creativesoftwarefdn/weaviate/blob/develop/LICENSE.md
 * AUTHOR: Bob van Luijt (bob@kub.design)
 * See www.creativesoftwarefdn.org for details
 * Contact: @CreativeSofwFdn / bob@kub.design
 */

// Package network provides the network graphql endpoint for Weaviate
package network

import (
	"fmt"

	"github.com/creativesoftwarefdn/weaviate/graphqlapi/descriptions"
	"github.com/creativesoftwarefdn/weaviate/graphqlapi/local/common_filters"
	"github.com/creativesoftwarefdn/weaviate/graphqlapi/utils"
	"github.com/graphql-go/graphql"
)

func genNetworkWhereOperatorEnum() *graphql.Enum {
	enumConf := graphql.EnumConfig{
		Name: "NetworkWhereOperatorEnum",
		Values: graphql.EnumValueConfigMap{
			"And":              &graphql.EnumValueConfig{},
			"Or":               &graphql.EnumValueConfig{},
			"Equal":            &graphql.EnumValueConfig{},
			"Not":              &graphql.EnumValueConfig{},
			"NotEqual":         &graphql.EnumValueConfig{},
			"GreaterThan":      &graphql.EnumValueConfig{},
			"GreaterThanEqual": &graphql.EnumValueConfig{},
			"LessThan":         &graphql.EnumValueConfig{},
			"LessThanEqual":    &graphql.EnumValueConfig{},
		},
		Description: descriptions.WhereOperatorEnumDesc,
	}

	return graphql.NewEnum(enumConf)
}

// This is an exact translation of the Prototype from JS to Go. In the prototype some filter elements are declared as global variables, this is recreated here.
func genGlobalNetworkFilterElements(filterContainer *utils.FilterContainer) {
	filterContainer.WeaviateNetworkWhereKeywordsInpObj = genWeaviateNetworkWhereNameKeywordsInpObj()
	filterContainer.WeaviateNetworkIntrospectPropertiesObjField = genWeaviateNetworkIntrospectPropertiesObjField()
}

func genWeaviateNetworkWhereNameKeywordsInpObj() *graphql.InputObject {
	weaviateNetworkWhereNameKeywordsInpObj := graphql.NewInputObject(
		graphql.InputObjectConfig{
			Name: "WeaviateNetworkWhereNameKeywordsInpObj",
			Fields: graphql.InputObjectConfigFieldMap{
				"value": &graphql.InputObjectFieldConfig{
					Type:        graphql.String,
					Description: descriptions.WhereKeywordsValueDesc,
				},
				"weight": &graphql.InputObjectFieldConfig{
					Type:        graphql.Float,
					Description: descriptions.WhereKeywordsWeightDesc,
				},
			},
			Description: descriptions.WhereKeywordsInpObjDesc,
		},
	)
	return weaviateNetworkWhereNameKeywordsInpObj
}

func genWeaviateNetworkIntrospectPropertiesObjField() *graphql.Field {
	weaviateNetworkIntrospectPropertiesObject := graphql.NewObject(
		graphql.ObjectConfig{
			Name: "WeaviateNetworkIntrospectPropertiesObj",
			Fields: graphql.Fields{
				"propertyName": &graphql.Field{
					Type:        graphql.String,
					Description: descriptions.WherePropertiesPropertyNameDesc,
				},
				"certainty": &graphql.Field{
					Type:        graphql.Float,
					Description: descriptions.WhereCertaintyDesc,
				},
			},
			Description: descriptions.WherePropertiesObjDesc,
		},
	)

	weaviateNetworkIntrospectPropertiesObjField := &graphql.Field{
		Name:        "WeaviateNetworkIntrospectPropertiesObj",
		Description: descriptions.WherePropertiesObjDesc,
		Type:        graphql.NewList(weaviateNetworkIntrospectPropertiesObject),
		Resolve: func(p graphql.ResolveParams) (interface{}, error) {
			return nil, fmt.Errorf("not supported")
		},
	}

	return weaviateNetworkIntrospectPropertiesObjField

}

func genNetworkFetchThingsAndActionsFilterFields(filterContainer *utils.FilterContainer) graphql.InputObjectConfigFieldMap {
	networkFetchWhereInpObjPropertiesObj := genNetworkFetchWhereInpObjPropertiesObj(filterContainer)
	networkFetchWhereInpObjClassInpObj := genNetworkFetchWhereInpObjClassInpObj(filterContainer)

	networkFetchThingsAndActionsFilterFields := graphql.InputObjectConfigFieldMap{
		"class": &graphql.InputObjectFieldConfig{
			Type:        graphql.NewList(networkFetchWhereInpObjClassInpObj),
			Description: descriptions.WhereClassDesc,
		},
		"properties": &graphql.InputObjectFieldConfig{
			Type:        graphql.NewList(networkFetchWhereInpObjPropertiesObj),
			Description: descriptions.WherePropertiesDesc,
		},
		"first": &graphql.InputObjectFieldConfig{
			Type:        graphql.Int,
			Description: descriptions.FirstDesc,
		},
	}

	return networkFetchThingsAndActionsFilterFields
}

func genNetworkFetchWhereInpObjPropertiesObj(filterContainer *utils.FilterContainer) *graphql.InputObject {
	filterPropertiesElements := common_filters.BuildNew("WeaviateNetworkFetch")

	// Remove path and operands fields as they are not required here
	delete(filterPropertiesElements, "path")
	delete(filterPropertiesElements, "operands")

	filterPropertiesElements["certainty"] = &graphql.InputObjectFieldConfig{
		Type:        graphql.Float,
		Description: descriptions.WhereCertaintyDesc,
	}
	filterPropertiesElements["name"] = &graphql.InputObjectFieldConfig{
		Type:        graphql.String,
		Description: descriptions.WhereNameDesc,
	}
	filterPropertiesElements["keywords"] = &graphql.InputObjectFieldConfig{
		Type:        graphql.NewList(genNetworkFetchWherePropertyWhereKeywordsInpObj()),
		Description: descriptions.WhereKeywordsDesc,
	}

	networkFetchWhereInpObjPropertiesObj := graphql.NewInputObject(
		graphql.InputObjectConfig{
			Name:        "WeaviateNetworkFetchWhereInpObjProperties",
			Fields:      filterPropertiesElements,
			Description: descriptions.WherePropertiesDesc,
		},
	)

	return networkFetchWhereInpObjPropertiesObj
}

func genNetworkFetchWherePropertyWhereKeywordsInpObj() *graphql.InputObject {
	outputObject := graphql.NewInputObject(
		graphql.InputObjectConfig{
			Name: "NetworkFetchWherePropertyWhereKeywordsInpObj",
			Fields: graphql.InputObjectConfigFieldMap{
				"value": &graphql.InputObjectFieldConfig{
					Type:        graphql.String,
					Description: descriptions.WhereKeywordsValueDesc,
				},
				"weight": &graphql.InputObjectFieldConfig{
					Type:        graphql.Float,
					Description: descriptions.WhereKeywordsWeightDesc,
				},
			},
			Description: descriptions.WhereKeywordsInpObjDesc,
		},
	)
	return outputObject
}

func genNetworkFetchWhereInpObjClassInpObj(filterContainer *utils.FilterContainer) *graphql.InputObject {
	filterClassElements := graphql.InputObjectConfigFieldMap{
		"name": &graphql.InputObjectFieldConfig{
			Type:        graphql.String,
			Description: descriptions.WhereNameDesc,
		},
		"certainty": &graphql.InputObjectFieldConfig{
			Type:        graphql.Float,
			Description: descriptions.WhereCertaintyDesc,
		},
		"keywords": &graphql.InputObjectFieldConfig{
			Type:        graphql.NewList(filterContainer.WeaviateNetworkWhereKeywordsInpObj),
			Description: descriptions.WhereKeywordsDesc,
		},
		"first": &graphql.InputObjectFieldConfig{
			Type:        graphql.Int,
			Description: descriptions.FirstDesc,
		},
	}

	networkFetchWhereInpObjClassInpObj := graphql.NewInputObject(
		graphql.InputObjectConfig{
			Name:        "WeaviateNetworkFetchWhereInpObjClassInpObj",
			Fields:      filterClassElements,
			Description: descriptions.WhereClassDesc,
		},
	)
	return networkFetchWhereInpObjClassInpObj
}

func genNetworkIntrospectThingsAndActionsFilterFields(filterContainer *utils.FilterContainer) graphql.InputObjectConfigFieldMap {
	weaviateNetworkIntrospectWherePropertiesObj := genWeaviateNetworkIntrospectWherePropertiesObj(filterContainer)
	weaviateNetworkIntrospectWhereClassObj := genWeaviateNetworkIntrospectWhereClassObj(filterContainer)

	networkIntrospectThingsAndActionsFilterFields := graphql.InputObjectConfigFieldMap{
		"class": &graphql.InputObjectFieldConfig{
			Type:        graphql.NewList(weaviateNetworkIntrospectWhereClassObj),
			Description: descriptions.WhereClassDesc,
		},
		"properties": &graphql.InputObjectFieldConfig{
			Type:        graphql.NewList(weaviateNetworkIntrospectWherePropertiesObj),
			Description: descriptions.WherePropertiesDesc,
		},
	}

	return networkIntrospectThingsAndActionsFilterFields
}

func genWeaviateNetworkIntrospectWherePropertiesObj(filterContainer *utils.FilterContainer) *graphql.InputObject {
	filterPropertiesElements := graphql.InputObjectConfigFieldMap{
		"first": &graphql.InputObjectFieldConfig{
			Type:        graphql.Int,
			Description: descriptions.FirstDesc,
		},
		"certainty": &graphql.InputObjectFieldConfig{
			Type:        graphql.Float,
			Description: descriptions.WhereCertaintyDesc,
		},
		"name": &graphql.InputObjectFieldConfig{
			Type:        graphql.String,
			Description: descriptions.WhereNameDesc,
		},
		"keywords": &graphql.InputObjectFieldConfig{
			Type:        graphql.NewList(filterContainer.WeaviateNetworkWhereKeywordsInpObj),
			Description: descriptions.WhereKeywordsDesc,
		},
	}

	weaviateNetworkIntrospectWherePropertiesObj := graphql.NewInputObject(
		graphql.InputObjectConfig{
			Name:        "WeaviateNetworkIntrospectWherePropertiesObj",
			Fields:      filterPropertiesElements,
			Description: descriptions.WherePropertiesObjDesc,
		},
	)

	return weaviateNetworkIntrospectWherePropertiesObj
}

func genWeaviateNetworkIntrospectWhereClassObj(filterContainer *utils.FilterContainer) *graphql.InputObject {
	filterClassElements := graphql.InputObjectConfigFieldMap{
		"name": &graphql.InputObjectFieldConfig{
			Type:        graphql.String,
			Description: descriptions.WhereNameDesc,
		},
		"certainty": &graphql.InputObjectFieldConfig{
			Type:        graphql.Float,
			Description: descriptions.WhereCertaintyDesc,
		},
		"keywords": &graphql.InputObjectFieldConfig{
			Type:        graphql.NewList(filterContainer.WeaviateNetworkWhereKeywordsInpObj),
			Description: descriptions.WhereKeywordsDesc,
		},
		"first": &graphql.InputObjectFieldConfig{
			Type:        graphql.Int,
			Description: descriptions.FirstDesc,
		},
	}

	weaviateNetworkIntrospectWhereClassObj := graphql.NewInputObject(
		graphql.InputObjectConfig{
			Name:        "WeaviateNetworkIntrospectWhereClassObj",
			Fields:      filterClassElements,
			Description: descriptions.WherePropertiesObjDesc,
		},
	)
	return weaviateNetworkIntrospectWhereClassObj
}
<commit_msg>PR: cosmetic change to rerun travis, hoping the travis.yml file no longer messes up the schema acceptance test<commit_after>/*                          _       _
 *__      _____  __ ___   ___  __ _| |_ ___
 *\ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \
 * \ V  V /  __/ (_| |\ V /| | (_| | ||  __/
 *  \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___|
 *
 * Copyright © 2016 - 2018 Weaviate. All rights reserved.
 * LICENSE: https://github.com/creativesoftwarefdn/weaviate/blob/develop/LICENSE.md
 * AUTHOR: Bob van Luijt (bob@kub.design)
 * See www.creativesoftwarefdn.org for details
 * Contact: @CreativeSofwFdn / bob@kub.design
 */

// Package network provides the network graphql endpoint for Weaviate
package network

import (
	"fmt"

	"github.com/creativesoftwarefdn/weaviate/graphqlapi/descriptions"
	"github.com/creativesoftwarefdn/weaviate/graphqlapi/local/common_filters"
	"github.com/creativesoftwarefdn/weaviate/graphqlapi/utils"
	"github.com/graphql-go/graphql"
)

func genNetworkWhereOperatorEnum() *graphql.Enum {
	enumConf := graphql.EnumConfig{
		Name: "NetworkWhereOperatorEnum",
		Values: graphql.EnumValueConfigMap{
			"And":              &graphql.EnumValueConfig{},
			"Or":               &graphql.EnumValueConfig{},
			"Equal":            &graphql.EnumValueConfig{},
			"Not":              &graphql.EnumValueConfig{},
			"NotEqual":         &graphql.EnumValueConfig{},
			"GreaterThan":      &graphql.EnumValueConfig{},
			"GreaterThanEqual": &graphql.EnumValueConfig{},
			"LessThan":         &graphql.EnumValueConfig{},
			"LessThanEqual":    &graphql.EnumValueConfig{},
		},
		Description: descriptions.WhereOperatorEnumDesc,
	}

	return graphql.NewEnum(enumConf)
}

// This is a translation of the Prototype from JS to Go. In the prototype some filter elements are declared as global variables, this is recreated here.
func genGlobalNetworkFilterElements(filterContainer *utils.FilterContainer) {
	filterContainer.WeaviateNetworkWhereKeywordsInpObj = genWeaviateNetworkWhereNameKeywordsInpObj()
	filterContainer.WeaviateNetworkIntrospectPropertiesObjField = genWeaviateNetworkIntrospectPropertiesObjField()
}

func genWeaviateNetworkWhereNameKeywordsInpObj() *graphql.InputObject {
	weaviateNetworkWhereNameKeywordsInpObj := graphql.NewInputObject(
		graphql.InputObjectConfig{
			Name: "WeaviateNetworkWhereNameKeywordsInpObj",
			Fields: graphql.InputObjectConfigFieldMap{
				"value": &graphql.InputObjectFieldConfig{
					Type:        graphql.String,
					Description: descriptions.WhereKeywordsValueDesc,
				},
				"weight": &graphql.InputObjectFieldConfig{
					Type:        graphql.Float,
					Description: descriptions.WhereKeywordsWeightDesc,
				},
			},
			Description: descriptions.WhereKeywordsInpObjDesc,
		},
	)
	return weaviateNetworkWhereNameKeywordsInpObj
}

func genWeaviateNetworkIntrospectPropertiesObjField() *graphql.Field {
	weaviateNetworkIntrospectPropertiesObject := graphql.NewObject(
		graphql.ObjectConfig{
			Name: "WeaviateNetworkIntrospectPropertiesObj",
			Fields: graphql.Fields{
				"propertyName": &graphql.Field{
					Type:        graphql.String,
					Description: descriptions.WherePropertiesPropertyNameDesc,
				},
				"certainty": &graphql.Field{
					Type:        graphql.Float,
					Description: descriptions.WhereCertaintyDesc,
				},
			},
			Description: descriptions.WherePropertiesObjDesc,
		},
	)

	weaviateNetworkIntrospectPropertiesObjField := &graphql.Field{
		Name:        "WeaviateNetworkIntrospectPropertiesObj",
		Description: descriptions.WherePropertiesObjDesc,
		Type:        graphql.NewList(weaviateNetworkIntrospectPropertiesObject),
		Resolve: func(p graphql.ResolveParams) (interface{}, error) {
			return nil, fmt.Errorf("not supported")
		},
	}

	return weaviateNetworkIntrospectPropertiesObjField

}

func genNetworkFetchThingsAndActionsFilterFields(filterContainer *utils.FilterContainer) graphql.InputObjectConfigFieldMap {
	networkFetchWhereInpObjPropertiesObj := genNetworkFetchWhereInpObjPropertiesObj(filterContainer)
	networkFetchWhereInpObjClassInpObj := genNetworkFetchWhereInpObjClassInpObj(filterContainer)

	networkFetchThingsAndActionsFilterFields := graphql.InputObjectConfigFieldMap{
		"class": &graphql.InputObjectFieldConfig{
			Type:        graphql.NewList(networkFetchWhereInpObjClassInpObj),
			Description: descriptions.WhereClassDesc,
		},
		"properties": &graphql.InputObjectFieldConfig{
			Type:        graphql.NewList(networkFetchWhereInpObjPropertiesObj),
			Description: descriptions.WherePropertiesDesc,
		},
		"first": &graphql.InputObjectFieldConfig{
			Type:        graphql.Int,
			Description: descriptions.FirstDesc,
		},
	}

	return networkFetchThingsAndActionsFilterFields
}

func genNetworkFetchWhereInpObjPropertiesObj(filterContainer *utils.FilterContainer) *graphql.InputObject {
	filterPropertiesElements := common_filters.BuildNew("WeaviateNetworkFetch")

	// Remove path and operands fields as they are not required here
	delete(filterPropertiesElements, "path")
	delete(filterPropertiesElements, "operands")

	filterPropertiesElements["certainty"] = &graphql.InputObjectFieldConfig{
		Type:        graphql.Float,
		Description: descriptions.WhereCertaintyDesc,
	}
	filterPropertiesElements["name"] = &graphql.InputObjectFieldConfig{
		Type:        graphql.String,
		Description: descriptions.WhereNameDesc,
	}
	filterPropertiesElements["keywords"] = &graphql.InputObjectFieldConfig{
		Type:        graphql.NewList(genNetworkFetchWherePropertyWhereKeywordsInpObj()),
		Description: descriptions.WhereKeywordsDesc,
	}

	networkFetchWhereInpObjPropertiesObj := graphql.NewInputObject(
		graphql.InputObjectConfig{
			Name:        "WeaviateNetworkFetchWhereInpObjProperties",
			Fields:      filterPropertiesElements,
			Description: descriptions.WherePropertiesDesc,
		},
	)

	return networkFetchWhereInpObjPropertiesObj
}

func genNetworkFetchWherePropertyWhereKeywordsInpObj() *graphql.InputObject {
	outputObject := graphql.NewInputObject(
		graphql.InputObjectConfig{
			Name: "NetworkFetchWherePropertyWhereKeywordsInpObj",
			Fields: graphql.InputObjectConfigFieldMap{
				"value": &graphql.InputObjectFieldConfig{
					Type:        graphql.String,
					Description: descriptions.WhereKeywordsValueDesc,
				},
				"weight": &graphql.InputObjectFieldConfig{
					Type:        graphql.Float,
					Description: descriptions.WhereKeywordsWeightDesc,
				},
			},
			Description: descriptions.WhereKeywordsInpObjDesc,
		},
	)
	return outputObject
}

func genNetworkFetchWhereInpObjClassInpObj(filterContainer *utils.FilterContainer) *graphql.InputObject {
	filterClassElements := graphql.InputObjectConfigFieldMap{
		"name": &graphql.InputObjectFieldConfig{
			Type:        graphql.String,
			Description: descriptions.WhereNameDesc,
		},
		"certainty": &graphql.InputObjectFieldConfig{
			Type:        graphql.Float,
			Description: descriptions.WhereCertaintyDesc,
		},
		"keywords": &graphql.InputObjectFieldConfig{
			Type:        graphql.NewList(filterContainer.WeaviateNetworkWhereKeywordsInpObj),
			Description: descriptions.WhereKeywordsDesc,
		},
		"first": &graphql.InputObjectFieldConfig{
			Type:        graphql.Int,
			Description: descriptions.FirstDesc,
		},
	}

	networkFetchWhereInpObjClassInpObj := graphql.NewInputObject(
		graphql.InputObjectConfig{
			Name:        "WeaviateNetworkFetchWhereInpObjClassInpObj",
			Fields:      filterClassElements,
			Description: descriptions.WhereClassDesc,
		},
	)
	return networkFetchWhereInpObjClassInpObj
}

func genNetworkIntrospectThingsAndActionsFilterFields(filterContainer *utils.FilterContainer) graphql.InputObjectConfigFieldMap {
	weaviateNetworkIntrospectWherePropertiesObj := genWeaviateNetworkIntrospectWherePropertiesObj(filterContainer)
	weaviateNetworkIntrospectWhereClassObj := genWeaviateNetworkIntrospectWhereClassObj(filterContainer)

	networkIntrospectThingsAndActionsFilterFields := graphql.InputObjectConfigFieldMap{
		"class": &graphql.InputObjectFieldConfig{
			Type:        graphql.NewList(weaviateNetworkIntrospectWhereClassObj),
			Description: descriptions.WhereClassDesc,
		},
		"properties": &graphql.InputObjectFieldConfig{
			Type:        graphql.NewList(weaviateNetworkIntrospectWherePropertiesObj),
			Description: descriptions.WherePropertiesDesc,
		},
	}

	return networkIntrospectThingsAndActionsFilterFields
}

func genWeaviateNetworkIntrospectWherePropertiesObj(filterContainer *utils.FilterContainer) *graphql.InputObject {
	filterPropertiesElements := graphql.InputObjectConfigFieldMap{
		"first": &graphql.InputObjectFieldConfig{
			Type:        graphql.Int,
			Description: descriptions.FirstDesc,
		},
		"certainty": &graphql.InputObjectFieldConfig{
			Type:        graphql.Float,
			Description: descriptions.WhereCertaintyDesc,
		},
		"name": &graphql.InputObjectFieldConfig{
			Type:        graphql.String,
			Description: descriptions.WhereNameDesc,
		},
		"keywords": &graphql.InputObjectFieldConfig{
			Type:        graphql.NewList(filterContainer.WeaviateNetworkWhereKeywordsInpObj),
			Description: descriptions.WhereKeywordsDesc,
		},
	}

	weaviateNetworkIntrospectWherePropertiesObj := graphql.NewInputObject(
		graphql.InputObjectConfig{
			Name:        "WeaviateNetworkIntrospectWherePropertiesObj",
			Fields:      filterPropertiesElements,
			Description: descriptions.WherePropertiesObjDesc,
		},
	)

	return weaviateNetworkIntrospectWherePropertiesObj
}

func genWeaviateNetworkIntrospectWhereClassObj(filterContainer *utils.FilterContainer) *graphql.InputObject {
	filterClassElements := graphql.InputObjectConfigFieldMap{
		"name": &graphql.InputObjectFieldConfig{
			Type:        graphql.String,
			Description: descriptions.WhereNameDesc,
		},
		"certainty": &graphql.InputObjectFieldConfig{
			Type:        graphql.Float,
			Description: descriptions.WhereCertaintyDesc,
		},
		"keywords": &graphql.InputObjectFieldConfig{
			Type:        graphql.NewList(filterContainer.WeaviateNetworkWhereKeywordsInpObj),
			Description: descriptions.WhereKeywordsDesc,
		},
		"first": &graphql.InputObjectFieldConfig{
			Type:        graphql.Int,
			Description: descriptions.FirstDesc,
		},
	}

	weaviateNetworkIntrospectWhereClassObj := graphql.NewInputObject(
		graphql.InputObjectConfig{
			Name:        "WeaviateNetworkIntrospectWhereClassObj",
			Fields:      filterClassElements,
			Description: descriptions.WherePropertiesObjDesc,
		},
	)
	return weaviateNetworkIntrospectWhereClassObj
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/gin-gonic/gin"
	"io"
	"os"
	"github.com/feixiao/log4go"
)

func main() {

	log4go.LoadConfiguration("./log.xml")

	gin.DefaultWriter = io.MultiWriter(os.Stdout,&GinLogger{})

	r := gin.Default()

	r.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
		})
	})
	r.Run() // listen and serve on 0.0.0.0:8080
}<commit_msg>support cors<commit_after>package main

import (
	"github.com/gin-gonic/gin"
	"io"
	"os"
	"github.com/feixiao/log4go"
	"github.com/gin-contrib/cors"
	"time"
)

func main() {

	log4go.LoadConfiguration("./log.xml")

	gin.DefaultWriter = io.MultiWriter(os.Stdout,&GinLogger{})

	r := gin.Default()

	config := cors.Config{
		AllowAllOrigins: true,
		AllowCredentials: false,
		MaxAge: 12 * time.Hour,
	}

	// "Origin,No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With, userId, token"
	config.AddAllowHeaders("token","x-access-token","x-url-path")

	r.Use(cors.New(config))

	r.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
		})
	})
	r.Run() // listen and serve on 0.0.0.0:8080
}<|endoftext|>


<commit_before>package gin

import (
	"html/template"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"os"
	"path"
	"strings"
	"testing"
)

// TestRouterGroupGETRouteOK tests that GET route is correctly invoked.
func TestRouterGroupGETRouteOK(t *testing.T) {
	req, _ := http.NewRequest("GET", "/test", nil)
	w := httptest.NewRecorder()
	passed := false

	r := Default()
	r.GET("/test", func(c *Context) {
		passed = true
	})

	r.ServeHTTP(w, req)

	if passed == false {
		t.Errorf("GET route handler was not invoked.")
	}

	if w.Code != http.StatusOK {
		t.Errorf("Status code should be %v, was %d", http.StatusOK, w.Code)
	}
}

// TestRouterGroupGETNoRootExistsRouteOK tests that a GET requse to root is correctly
// handled (404) when no root route exists.
func TestRouterGroupGETNoRootExistsRouteOK(t *testing.T) {
	req, _ := http.NewRequest("GET", "/", nil)
	w := httptest.NewRecorder()

	r := Default()
	r.GET("/test", func(c *Context) {
	})

	r.ServeHTTP(w, req)

	if w.Code != http.StatusNotFound {
		// If this fails, it's because httprouter needs to be updated to at least f78f58a0db
		t.Errorf("Status code should be %v, was %d. Location: %s", http.StatusNotFound, w.Code, w.HeaderMap.Get("Location"))
	}
}

// TestRouterGroupPOSTRouteOK tests that POST route is correctly invoked.
func TestRouterGroupPOSTRouteOK(t *testing.T) {
	req, _ := http.NewRequest("POST", "/test", nil)
	w := httptest.NewRecorder()
	passed := false

	r := Default()
	r.POST("/test", func(c *Context) {
		passed = true
	})

	r.ServeHTTP(w, req)

	if passed == false {
		t.Errorf("POST route handler was not invoked.")
	}

	if w.Code != http.StatusOK {
		t.Errorf("Status code should be %v, was %d", http.StatusOK, w.Code)
	}
}

// TestRouterGroupDELETERouteOK tests that DELETE route is correctly invoked.
func TestRouterGroupDELETERouteOK(t *testing.T) {
	req, _ := http.NewRequest("DELETE", "/test", nil)
	w := httptest.NewRecorder()
	passed := false

	r := Default()
	r.DELETE("/test", func(c *Context) {
		passed = true
	})

	r.ServeHTTP(w, req)

	if passed == false {
		t.Errorf("DELETE route handler was not invoked.")
	}

	if w.Code != http.StatusOK {
		t.Errorf("Status code should be %v, was %d", http.StatusOK, w.Code)
	}
}

// TestRouterGroupPATCHRouteOK tests that PATCH route is correctly invoked.
func TestRouterGroupPATCHRouteOK(t *testing.T) {
	req, _ := http.NewRequest("PATCH", "/test", nil)
	w := httptest.NewRecorder()
	passed := false

	r := Default()
	r.PATCH("/test", func(c *Context) {
		passed = true
	})

	r.ServeHTTP(w, req)

	if passed == false {
		t.Errorf("PATCH route handler was not invoked.")
	}

	if w.Code != http.StatusOK {
		t.Errorf("Status code should be %v, was %d", http.StatusOK, w.Code)
	}
}

// TestRouterGroupPUTRouteOK tests that PUT route is correctly invoked.
func TestRouterGroupPUTRouteOK(t *testing.T) {
	req, _ := http.NewRequest("PUT", "/test", nil)
	w := httptest.NewRecorder()
	passed := false

	r := Default()
	r.PUT("/test", func(c *Context) {
		passed = true
	})

	r.ServeHTTP(w, req)

	if passed == false {
		t.Errorf("PUT route handler was not invoked.")
	}

	if w.Code != http.StatusOK {
		t.Errorf("Status code should be %v, was %d", http.StatusOK, w.Code)
	}
}

// TestRouterGroupOPTIONSRouteOK tests that OPTIONS route is correctly invoked.
func TestRouterGroupOPTIONSRouteOK(t *testing.T) {
	req, _ := http.NewRequest("OPTIONS", "/test", nil)
	w := httptest.NewRecorder()
	passed := false

	r := Default()
	r.OPTIONS("/test", func(c *Context) {
		passed = true
	})

	r.ServeHTTP(w, req)

	if passed == false {
		t.Errorf("OPTIONS route handler was not invoked.")
	}

	if w.Code != http.StatusOK {
		t.Errorf("Status code should be %v, was %d", http.StatusOK, w.Code)
	}
}

// TestRouterGroupHEADRouteOK tests that HEAD route is correctly invoked.
func TestRouterGroupHEADRouteOK(t *testing.T) {
	req, _ := http.NewRequest("HEAD", "/test", nil)
	w := httptest.NewRecorder()
	passed := false

	r := Default()
	r.HEAD("/test", func(c *Context) {
		passed = true
	})

	r.ServeHTTP(w, req)

	if passed == false {
		t.Errorf("HEAD route handler was not invoked.")
	}

	if w.Code != http.StatusOK {
		t.Errorf("Status code should be %v, was %d", http.StatusOK, w.Code)
	}
}

// TestRouterGroup404 tests that 404 is returned for a route that does not exist.
func TestEngine404(t *testing.T) {
	req, _ := http.NewRequest("GET", "/", nil)
	w := httptest.NewRecorder()

	r := Default()
	r.ServeHTTP(w, req)

	if w.Code != http.StatusNotFound {
		t.Errorf("Response code should be %v, was %d", http.StatusNotFound, w.Code)
	}
}

// TestContextParamsGet tests that a parameter can be parsed from the URL.
func TestContextParamsByName(t *testing.T) {
	req, _ := http.NewRequest("GET", "/test/alexandernyquist", nil)
	w := httptest.NewRecorder()
	name := ""

	r := Default()
	r.GET("/test/:name", func(c *Context) {
		name = c.Params.ByName("name")
	})

	r.ServeHTTP(w, req)

	if name != "alexandernyquist" {
		t.Errorf("Url parameter was not correctly parsed. Should be alexandernyquist, was %s.", name)
	}
}

// TestContextSetGet tests that a parameter is set correctly on the
// current context and can be retrieved using Get.
func TestContextSetGet(t *testing.T) {
	req, _ := http.NewRequest("GET", "/test", nil)
	w := httptest.NewRecorder()

	r := Default()
	r.GET("/test", func(c *Context) {
		// Key should be lazily created
		if c.Keys != nil {
			t.Error("Keys should be nil")
		}

		// Set
		c.Set("foo", "bar")

		v, err := c.Get("foo")
		if err != nil {
			t.Errorf("Error on exist key")
		}
		if v != "bar" {
			t.Errorf("Value should be bar, was %s", v)
		}
	})

	r.ServeHTTP(w, req)
}

// TestContextJSON tests that the response is serialized as JSON
// and Content-Type is set to application/json
func TestContextJSON(t *testing.T) {
	req, _ := http.NewRequest("GET", "/test", nil)
	w := httptest.NewRecorder()

	r := Default()
	r.GET("/test", func(c *Context) {
		c.JSON(200, H{"foo": "bar"})
	})

	r.ServeHTTP(w, req)

	if w.Body.String() != "{\"foo\":\"bar\"}\n" {
		t.Errorf("Response should be {\"foo\":\"bar\"}, was: %s", w.Body.String())
	}

	if w.HeaderMap.Get("Content-Type") != "application/json" {
		t.Errorf("Content-Type should be application/json, was %s", w.HeaderMap.Get("Content-Type"))
	}
}

// TestContextHTML tests that the response executes the templates
// and responds with Content-Type set to text/html
func TestContextHTML(t *testing.T) {
	req, _ := http.NewRequest("GET", "/test", nil)
	w := httptest.NewRecorder()

	r := Default()
	templ, _ := template.New("t").Parse(`Hello {{.Name}}`)
	r.SetHTMLTemplate(templ)

	type TestData struct{ Name string }

	r.GET("/test", func(c *Context) {
		c.HTML(200, "t", TestData{"alexandernyquist"})
	})

	r.ServeHTTP(w, req)

	if w.Body.String() != "Hello alexandernyquist" {
		t.Errorf("Response should be Hello alexandernyquist, was: %s", w.Body.String())
	}

	if w.HeaderMap.Get("Content-Type") != "text/html" {
		t.Errorf("Content-Type should be text/html, was %s", w.HeaderMap.Get("Content-Type"))
	}
}

// TestContextString tests that the response is returned
// with Content-Type set to text/plain
func TestContextString(t *testing.T) {
	req, _ := http.NewRequest("GET", "/test", nil)
	w := httptest.NewRecorder()

	r := Default()
	r.GET("/test", func(c *Context) {
		c.String(200, "test")
	})

	r.ServeHTTP(w, req)

	if w.Body.String() != "test" {
		t.Errorf("Response should be test, was: %s", w.Body.String())
	}

	if w.HeaderMap.Get("Content-Type") != "text/plain" {
		t.Errorf("Content-Type should be text/plain, was %s", w.HeaderMap.Get("Content-Type"))
	}
}

// TestHandleStaticFile - ensure the static file handles properly
func TestHandleStaticFile(t *testing.T) {

	testRoot, _ := os.Getwd()

	f, err := ioutil.TempFile(testRoot, "")
	defer os.Remove(f.Name())

	if err != nil {
		t.Error(err)
	}

	filePath := path.Join("/", path.Base(f.Name()))
	req, _ := http.NewRequest("GET", filePath, nil)

	f.WriteString("Gin Web Framework")
	f.Close()

	w := httptest.NewRecorder()

	r := Default()
	r.Static("./", testRoot)

	r.ServeHTTP(w, req)

	if w.Code != 200 {
		t.Errorf("Response code should be Ok, was: %s", w.Code)
	}

	if w.Body.String() != "Gin Web Framework" {
		t.Errorf("Response should be test, was: %s", w.Body.String())
	}

	if w.HeaderMap.Get("Content-Type") != "text/plain; charset=utf-8" {
		t.Errorf("Content-Type should be text/plain, was %s", w.HeaderMap.Get("Content-Type"))
	}
}

// TestHandleStaticDir - ensure the root/sub dir handles properly
func TestHandleStaticDir(t *testing.T) {

	req, _ := http.NewRequest("GET", "/", nil)

	w := httptest.NewRecorder()

	r := Default()
	r.Static("/", "./")

	r.ServeHTTP(w, req)

	if w.Code != 200 {
		t.Errorf("Response code should be Ok, was: %s", w.Code)
	}

	bodyAsString := w.Body.String()

	if len(bodyAsString) == 0 {
		t.Errorf("Got empty body instead of file tree")
	}

	if !strings.Contains(bodyAsString, "gin.go") {
		t.Errorf("Can't find:`gin.go` in file tree: %s", bodyAsString)
	}

	if w.HeaderMap.Get("Content-Type") != "text/html; charset=utf-8" {
		t.Errorf("Content-Type should be text/plain, was %s", w.HeaderMap.Get("Content-Type"))
	}
}
<commit_msg>Added dummy tests for middleware<commit_after>package gin

import (
	"errors"
	"html/template"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"os"
	"path"
	"strings"
	"testing"
)

// TestRouterGroupGETRouteOK tests that GET route is correctly invoked.
func TestRouterGroupGETRouteOK(t *testing.T) {
	req, _ := http.NewRequest("GET", "/test", nil)
	w := httptest.NewRecorder()
	passed := false

	r := Default()
	r.GET("/test", func(c *Context) {
		passed = true
	})

	r.ServeHTTP(w, req)

	if passed == false {
		t.Errorf("GET route handler was not invoked.")
	}

	if w.Code != http.StatusOK {
		t.Errorf("Status code should be %v, was %d", http.StatusOK, w.Code)
	}
}

// TestRouterGroupGETNoRootExistsRouteOK tests that a GET requse to root is correctly
// handled (404) when no root route exists.
func TestRouterGroupGETNoRootExistsRouteOK(t *testing.T) {
	req, _ := http.NewRequest("GET", "/", nil)
	w := httptest.NewRecorder()

	r := Default()
	r.GET("/test", func(c *Context) {
	})

	r.ServeHTTP(w, req)

	if w.Code != http.StatusNotFound {
		// If this fails, it's because httprouter needs to be updated to at least f78f58a0db
		t.Errorf("Status code should be %v, was %d. Location: %s", http.StatusNotFound, w.Code, w.HeaderMap.Get("Location"))
	}
}

// TestRouterGroupPOSTRouteOK tests that POST route is correctly invoked.
func TestRouterGroupPOSTRouteOK(t *testing.T) {
	req, _ := http.NewRequest("POST", "/test", nil)
	w := httptest.NewRecorder()
	passed := false

	r := Default()
	r.POST("/test", func(c *Context) {
		passed = true
	})

	r.ServeHTTP(w, req)

	if passed == false {
		t.Errorf("POST route handler was not invoked.")
	}

	if w.Code != http.StatusOK {
		t.Errorf("Status code should be %v, was %d", http.StatusOK, w.Code)
	}
}

// TestRouterGroupDELETERouteOK tests that DELETE route is correctly invoked.
func TestRouterGroupDELETERouteOK(t *testing.T) {
	req, _ := http.NewRequest("DELETE", "/test", nil)
	w := httptest.NewRecorder()
	passed := false

	r := Default()
	r.DELETE("/test", func(c *Context) {
		passed = true
	})

	r.ServeHTTP(w, req)

	if passed == false {
		t.Errorf("DELETE route handler was not invoked.")
	}

	if w.Code != http.StatusOK {
		t.Errorf("Status code should be %v, was %d", http.StatusOK, w.Code)
	}
}

// TestRouterGroupPATCHRouteOK tests that PATCH route is correctly invoked.
func TestRouterGroupPATCHRouteOK(t *testing.T) {
	req, _ := http.NewRequest("PATCH", "/test", nil)
	w := httptest.NewRecorder()
	passed := false

	r := Default()
	r.PATCH("/test", func(c *Context) {
		passed = true
	})

	r.ServeHTTP(w, req)

	if passed == false {
		t.Errorf("PATCH route handler was not invoked.")
	}

	if w.Code != http.StatusOK {
		t.Errorf("Status code should be %v, was %d", http.StatusOK, w.Code)
	}
}

// TestRouterGroupPUTRouteOK tests that PUT route is correctly invoked.
func TestRouterGroupPUTRouteOK(t *testing.T) {
	req, _ := http.NewRequest("PUT", "/test", nil)
	w := httptest.NewRecorder()
	passed := false

	r := Default()
	r.PUT("/test", func(c *Context) {
		passed = true
	})

	r.ServeHTTP(w, req)

	if passed == false {
		t.Errorf("PUT route handler was not invoked.")
	}

	if w.Code != http.StatusOK {
		t.Errorf("Status code should be %v, was %d", http.StatusOK, w.Code)
	}
}

// TestRouterGroupOPTIONSRouteOK tests that OPTIONS route is correctly invoked.
func TestRouterGroupOPTIONSRouteOK(t *testing.T) {
	req, _ := http.NewRequest("OPTIONS", "/test", nil)
	w := httptest.NewRecorder()
	passed := false

	r := Default()
	r.OPTIONS("/test", func(c *Context) {
		passed = true
	})

	r.ServeHTTP(w, req)

	if passed == false {
		t.Errorf("OPTIONS route handler was not invoked.")
	}

	if w.Code != http.StatusOK {
		t.Errorf("Status code should be %v, was %d", http.StatusOK, w.Code)
	}
}

// TestRouterGroupHEADRouteOK tests that HEAD route is correctly invoked.
func TestRouterGroupHEADRouteOK(t *testing.T) {
	req, _ := http.NewRequest("HEAD", "/test", nil)
	w := httptest.NewRecorder()
	passed := false

	r := Default()
	r.HEAD("/test", func(c *Context) {
		passed = true
	})

	r.ServeHTTP(w, req)

	if passed == false {
		t.Errorf("HEAD route handler was not invoked.")
	}

	if w.Code != http.StatusOK {
		t.Errorf("Status code should be %v, was %d", http.StatusOK, w.Code)
	}
}

// TestRouterGroup404 tests that 404 is returned for a route that does not exist.
func TestEngine404(t *testing.T) {
	req, _ := http.NewRequest("GET", "/", nil)
	w := httptest.NewRecorder()

	r := Default()
	r.ServeHTTP(w, req)

	if w.Code != http.StatusNotFound {
		t.Errorf("Response code should be %v, was %d", http.StatusNotFound, w.Code)
	}
}

// TestContextParamsGet tests that a parameter can be parsed from the URL.
func TestContextParamsByName(t *testing.T) {
	req, _ := http.NewRequest("GET", "/test/alexandernyquist", nil)
	w := httptest.NewRecorder()
	name := ""

	r := Default()
	r.GET("/test/:name", func(c *Context) {
		name = c.Params.ByName("name")
	})

	r.ServeHTTP(w, req)

	if name != "alexandernyquist" {
		t.Errorf("Url parameter was not correctly parsed. Should be alexandernyquist, was %s.", name)
	}
}

// TestContextSetGet tests that a parameter is set correctly on the
// current context and can be retrieved using Get.
func TestContextSetGet(t *testing.T) {
	req, _ := http.NewRequest("GET", "/test", nil)
	w := httptest.NewRecorder()

	r := Default()
	r.GET("/test", func(c *Context) {
		// Key should be lazily created
		if c.Keys != nil {
			t.Error("Keys should be nil")
		}

		// Set
		c.Set("foo", "bar")

		v, err := c.Get("foo")
		if err != nil {
			t.Errorf("Error on exist key")
		}
		if v != "bar" {
			t.Errorf("Value should be bar, was %s", v)
		}
	})

	r.ServeHTTP(w, req)
}

// TestContextJSON tests that the response is serialized as JSON
// and Content-Type is set to application/json
func TestContextJSON(t *testing.T) {
	req, _ := http.NewRequest("GET", "/test", nil)
	w := httptest.NewRecorder()

	r := Default()
	r.GET("/test", func(c *Context) {
		c.JSON(200, H{"foo": "bar"})
	})

	r.ServeHTTP(w, req)

	if w.Body.String() != "{\"foo\":\"bar\"}\n" {
		t.Errorf("Response should be {\"foo\":\"bar\"}, was: %s", w.Body.String())
	}

	if w.HeaderMap.Get("Content-Type") != "application/json" {
		t.Errorf("Content-Type should be application/json, was %s", w.HeaderMap.Get("Content-Type"))
	}
}

// TestContextHTML tests that the response executes the templates
// and responds with Content-Type set to text/html
func TestContextHTML(t *testing.T) {
	req, _ := http.NewRequest("GET", "/test", nil)
	w := httptest.NewRecorder()

	r := Default()
	templ, _ := template.New("t").Parse(`Hello {{.Name}}`)
	r.SetHTMLTemplate(templ)

	type TestData struct{ Name string }

	r.GET("/test", func(c *Context) {
		c.HTML(200, "t", TestData{"alexandernyquist"})
	})

	r.ServeHTTP(w, req)

	if w.Body.String() != "Hello alexandernyquist" {
		t.Errorf("Response should be Hello alexandernyquist, was: %s", w.Body.String())
	}

	if w.HeaderMap.Get("Content-Type") != "text/html" {
		t.Errorf("Content-Type should be text/html, was %s", w.HeaderMap.Get("Content-Type"))
	}
}

// TestContextString tests that the response is returned
// with Content-Type set to text/plain
func TestContextString(t *testing.T) {
	req, _ := http.NewRequest("GET", "/test", nil)
	w := httptest.NewRecorder()

	r := Default()
	r.GET("/test", func(c *Context) {
		c.String(200, "test")
	})

	r.ServeHTTP(w, req)

	if w.Body.String() != "test" {
		t.Errorf("Response should be test, was: %s", w.Body.String())
	}

	if w.HeaderMap.Get("Content-Type") != "text/plain" {
		t.Errorf("Content-Type should be text/plain, was %s", w.HeaderMap.Get("Content-Type"))
	}
}

// TestHandleStaticFile - ensure the static file handles properly
func TestHandleStaticFile(t *testing.T) {

	testRoot, _ := os.Getwd()

	f, err := ioutil.TempFile(testRoot, "")
	defer os.Remove(f.Name())

	if err != nil {
		t.Error(err)
	}

	filePath := path.Join("/", path.Base(f.Name()))
	req, _ := http.NewRequest("GET", filePath, nil)

	f.WriteString("Gin Web Framework")
	f.Close()

	w := httptest.NewRecorder()

	r := Default()
	r.Static("./", testRoot)

	r.ServeHTTP(w, req)

	if w.Code != 200 {
		t.Errorf("Response code should be Ok, was: %s", w.Code)
	}

	if w.Body.String() != "Gin Web Framework" {
		t.Errorf("Response should be test, was: %s", w.Body.String())
	}

	if w.HeaderMap.Get("Content-Type") != "text/plain; charset=utf-8" {
		t.Errorf("Content-Type should be text/plain, was %s", w.HeaderMap.Get("Content-Type"))
	}
}

// TestHandleStaticDir - ensure the root/sub dir handles properly
func TestHandleStaticDir(t *testing.T) {

	req, _ := http.NewRequest("GET", "/", nil)

	w := httptest.NewRecorder()

	r := Default()
	r.Static("/", "./")

	r.ServeHTTP(w, req)

	if w.Code != 200 {
		t.Errorf("Response code should be Ok, was: %s", w.Code)
	}

	bodyAsString := w.Body.String()

	if len(bodyAsString) == 0 {
		t.Errorf("Got empty body instead of file tree")
	}

	if !strings.Contains(bodyAsString, "gin.go") {
		t.Errorf("Can't find:`gin.go` in file tree: %s", bodyAsString)
	}

	if w.HeaderMap.Get("Content-Type") != "text/html; charset=utf-8" {
		t.Errorf("Content-Type should be text/plain, was %s", w.HeaderMap.Get("Content-Type"))
	}
}

// TestHandleHeadToDir - ensure the root/sub dir handles properly
func TestHandleHeadToDir(t *testing.T) {

	req, _ := http.NewRequest("HEAD", "/", nil)

	w := httptest.NewRecorder()

	r := Default()
	r.Static("/", "./")

	r.ServeHTTP(w, req)

	if w.Code != 200 {
		t.Errorf("Response code should be Ok, was: %s", w.Code)
	}

	bodyAsString := w.Body.String()

	if len(bodyAsString) == 0 {
		t.Errorf("Got empty body instead of file tree")
	}
	if !strings.Contains(bodyAsString, "gin.go") {
		t.Errorf("Can't find:`gin.go` in file tree: %s", bodyAsString)
	}

	if w.HeaderMap.Get("Content-Type") != "text/html; charset=utf-8" {
		t.Errorf("Content-Type should be text/plain, was %s", w.HeaderMap.Get("Content-Type"))
	}
}

// TestHandlerFunc - ensure that custom middleware works properly
func TestHandlerFunc(t *testing.T) {

	req, _ := http.NewRequest("GET", "/", nil)
	w := httptest.NewRecorder()

	r := Default()
	var stepsPassed int = 0

	r.Use(func(context *Context) {
		stepsPassed += 1
		context.Next()
		stepsPassed += 1
	})

	r.ServeHTTP(w, req)

	if w.Code != 404 {
		t.Errorf("Response code should be Not found, was: %s", w.Code)
	}

	if stepsPassed != 2 {
		t.Errorf("Falied to switch context in handler function: %s", stepsPassed)
	}
}

// TestBadAbortHandlersChain - ensure that Abort after switch context will not interrupt pending handlers
func TestBadAbortHandlersChain(t *testing.T) {

	req, _ := http.NewRequest("GET", "/", nil)
	w := httptest.NewRecorder()

	r := Default()
	var stepsPassed int = 0

	r.Use(func(context *Context) {
		stepsPassed += 1
		context.Next()
		stepsPassed += 1
		// after check and abort
		context.Abort(409)
	},
		func(context *Context) {
			stepsPassed += 1
			context.Next()
			stepsPassed += 1
			context.Abort(403)
		},
	)

	r.ServeHTTP(w, req)

	if w.Code != 403 {
		t.Errorf("Response code should be Forbiden, was: %s", w.Code)
	}

	if stepsPassed != 4 {
		t.Errorf("Falied to switch context in handler function: %s", stepsPassed)
	}
}

// TestAbortHandlersChain - ensure that Abort interrupt used middlewares in fifo order
func TestAbortHandlersChain(t *testing.T) {

	req, _ := http.NewRequest("GET", "/", nil)
	w := httptest.NewRecorder()

	r := Default()
	var stepsPassed int = 0

	r.Use(func(context *Context) {
		stepsPassed += 1
		context.Abort(409)
	},
		func(context *Context) {
			stepsPassed += 1
			context.Next()
			stepsPassed += 1
		},
	)

	r.ServeHTTP(w, req)

	if w.Code != 409 {
		t.Errorf("Response code should be Conflict, was: %s", w.Code)
	}

	if stepsPassed != 1 {
		t.Errorf("Falied to switch context in handler function: %s", stepsPassed)
	}
}

// TestFailHandlersChain - ensure that Fail interrupt used middlewares in fifo order as
// as well as Abort
func TestFailHandlersChain(t *testing.T) {

	req, _ := http.NewRequest("GET", "/", nil)
	w := httptest.NewRecorder()

	r := Default()
	var stepsPassed int = 0

	r.Use(func(context *Context) {
		stepsPassed += 1

		context.Fail(500, errors.New("foo"))
	},
		func(context *Context) {
			stepsPassed += 1
			context.Next()
			stepsPassed += 1
		},
	)

	r.ServeHTTP(w, req)

	if w.Code != 500 {
		t.Errorf("Response code should be Server error, was: %s", w.Code)
	}

	if stepsPassed != 1 {
		t.Errorf("Falied to switch context in handler function: %s", stepsPassed)
	}

}
<|endoftext|>


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

// Package tasks contains task queue implementations.
package tasks

import (
	"context"
	"encoding/json"
	"fmt"

	"google.golang.org/protobuf/proto"

	"go.chromium.org/luci/common/errors"
	"go.chromium.org/luci/common/logging"
	"go.chromium.org/luci/server/tq"

	taskdefs "go.chromium.org/luci/buildbucket/appengine/tasks/defs"

	// Enable datastore transactional tasks support.
	_ "go.chromium.org/luci/server/tq/txn/datastore"
)

// rejectionHandler returns a tq.Handler which rejects the given task.
// Used by tasks which are handled in Python.
// TODO(crbug/1042991): Remove once all handlers are implemented in Go.
func rejectionHandler(tq string) tq.Handler {
	return func(ctx context.Context, payload proto.Message) error {
		logging.Errorf(ctx, "tried to handle %s: %q", tq, payload)
		return errors.Reason("handler called").Err()
	}
}

func init() {
	tq.RegisterTaskClass(tq.TaskClass{
		ID: "cancel-swarming-task",
		Custom: func(ctx context.Context, m proto.Message) (*tq.CustomPayload, error) {
			task := m.(*taskdefs.CancelSwarmingTask)
			body, err := json.Marshal(map[string]interface{}{
				"hostname": task.Hostname,
				"task_id":  task.TaskId,
				"realm":    task.Realm,
			})
			if err != nil {
				return nil, errors.Annotate(err, "error marshaling payload").Err()
			}
			return &tq.CustomPayload{
				Body:        body,
				Method:      "POST",
				RelativeURI: fmt.Sprintf("/internal/task/buildbucket/cancel_swarming_task/%s/%s", task.Hostname, task.TaskId),
			}, nil
		},
		Handler:   rejectionHandler("cancel-swarming-task"),
		Kind:      tq.Transactional,
		Prototype: (*taskdefs.CancelSwarmingTask)(nil),
		Queue:     "backend-default",
	})

	tq.RegisterTaskClass(tq.TaskClass{
		ID: "create-swarming-task",
		Custom: func(ctx context.Context, m proto.Message) (*tq.CustomPayload, error) {
			task := m.(*taskdefs.CreateSwarmingTask)
			body, err := json.Marshal(map[string]interface{}{
				"generation": 0,
				"id":    task.BuildId,
			})
			if err != nil {
				return nil, errors.Annotate(err, "error marshaling payload").Err()
			}
			return &tq.CustomPayload{
				Body:        body,
				Method:      "POST",
				RelativeURI: fmt.Sprintf("/internal/task/swarming/sync-build/%d", task.BuildId),
			}, nil
		},
		Handler:   rejectionHandler("create-swarming-task"),
		Kind:      tq.Transactional,
		Prototype: (*taskdefs.CreateSwarmingTask)(nil),
		Queue:     "backend-default",
	})

	tq.RegisterTaskClass(tq.TaskClass{
		ID: "export-bigquery",
		Custom: func(ctx context.Context, m proto.Message) (*tq.CustomPayload, error) {
			task := m.(*taskdefs.ExportBigQuery)
			body, err := json.Marshal(map[string]interface{}{
				"id": task.BuildId,
			})
			if err != nil {
				return nil, errors.Annotate(err, "error marshaling payload").Err()
			}
			return &tq.CustomPayload{
				Body:        body,
				Method:      "POST",
				RelativeURI: fmt.Sprintf("/internal/task/bq/export/%d", task.BuildId),
			}, nil
		},
		Handler:   rejectionHandler("export-bigquery"),
		Kind:      tq.Transactional,
		Prototype: (*taskdefs.ExportBigQuery)(nil),
		Queue:     "backend-default",
	})

	tq.RegisterTaskClass(tq.TaskClass{
		ID: "finalize-resultdb",
		Custom: func(ctx context.Context, m proto.Message) (*tq.CustomPayload, error) {
			task := m.(*taskdefs.FinalizeResultDB)
			body, err := json.Marshal(map[string]interface{}{
				"id": task.BuildId,
			})
			if err != nil {
				return nil, errors.Annotate(err, "error marshaling payload").Err()
			}
			return &tq.CustomPayload{
				Body:        body,
				Method:      "POST",
				RelativeURI: fmt.Sprintf("/internal/task/resultdb/finalize/%d", task.BuildId),
			}, nil
		},
		Handler:   rejectionHandler("finalize-resultdb"),
		Kind:      tq.Transactional,
		Prototype: (*taskdefs.FinalizeResultDB)(nil),
		Queue:     "backend-default",
	})

	tq.RegisterTaskClass(tq.TaskClass{
		ID: "notify-pubsub",
		Custom: func(ctx context.Context, m proto.Message) (*tq.CustomPayload, error) {
			task := m.(*taskdefs.NotifyPubSub)
			mode := "global"
			if task.Callback {
				mode = "callback"
			}
			body, err := json.Marshal(map[string]interface{}{
				"id":   task.BuildId,
				"mode": mode,
			})
			if err != nil {
				return nil, errors.Annotate(err, "error marshaling payload").Err()
			}
			return &tq.CustomPayload{
				Body:        body,
				Method:      "POST",
				RelativeURI: fmt.Sprintf("/internal/task/buildbucket/notify/%d", task.BuildId),
			}, nil
		},
		Handler:   rejectionHandler("notify-pubsub"),
		Kind:      tq.Transactional,
		Prototype: (*taskdefs.NotifyPubSub)(nil),
		Queue:     "backend-default",
	})
}

// CancelSwarmingTask enqueues a task queue task to cancel the given Swarming
// task.
func CancelSwarmingTask(ctx context.Context, task *taskdefs.CancelSwarmingTask) error {
	switch {
	case task.GetHostname() == "":
		return errors.Reason("hostname is required").Err()
	case task.TaskId == "":
		return errors.Reason("task_id is required").Err()
	}
	return tq.AddTask(ctx, &tq.Task{
		Payload: task,
	})
}

// CreateSwarmingTask enqueues a task queue task to create a Swarming task from
// the given build.
func CreateSwarmingTask(ctx context.Context, task *taskdefs.CreateSwarmingTask) error {
	if task.GetBuildId() == 0 {
		return errors.Reason("build_id is required").Err()
	}
	return tq.AddTask(ctx, &tq.Task{
		Payload: task,
	})
}

// ExportBigQuery enqueues a task queue task to export the given build to
// BigQuery.
func ExportBigQuery(ctx context.Context, task *taskdefs.ExportBigQuery) error {
	if task.GetBuildId() == 0 {
		return errors.Reason("build_id is required").Err()
	}
	return tq.AddTask(ctx, &tq.Task{
		Payload: task,
	})
}

// FinalizeResultDB enqueues a task queue task to finalize the invocation for
// the given build in ResultDB.
func FinalizeResultDB(ctx context.Context, task *taskdefs.FinalizeResultDB) error {
	if task.GetBuildId() == 0 {
		return errors.Reason("build_id is required").Err()
	}
	return tq.AddTask(ctx, &tq.Task{
		Payload: task,
	})
}

// NotifyPubSub enqueues a task queue task to notify Pub/Sub about the given
// build.
func NotifyPubSub(ctx context.Context, task *taskdefs.NotifyPubSub) error {
	if task.GetBuildId() == 0 {
		return errors.Reason("build_id is required").Err()
	}
	return tq.AddTask(ctx, &tq.Task{
		Payload: task,
	})
}
<commit_msg>[buildbucket] Target Swarming task creation queue<commit_after>// Copyright 2020 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package tasks contains task queue implementations.
package tasks

import (
	"context"
	"encoding/json"
	"fmt"

	"google.golang.org/protobuf/proto"

	"go.chromium.org/luci/common/errors"
	"go.chromium.org/luci/common/logging"
	"go.chromium.org/luci/server/tq"

	taskdefs "go.chromium.org/luci/buildbucket/appengine/tasks/defs"

	// Enable datastore transactional tasks support.
	_ "go.chromium.org/luci/server/tq/txn/datastore"
)

// rejectionHandler returns a tq.Handler which rejects the given task.
// Used by tasks which are handled in Python.
// TODO(crbug/1042991): Remove once all handlers are implemented in Go.
func rejectionHandler(tq string) tq.Handler {
	return func(ctx context.Context, payload proto.Message) error {
		logging.Errorf(ctx, "tried to handle %s: %q", tq, payload)
		return errors.Reason("handler called").Err()
	}
}

func init() {
	tq.RegisterTaskClass(tq.TaskClass{
		ID: "cancel-swarming-task",
		Custom: func(ctx context.Context, m proto.Message) (*tq.CustomPayload, error) {
			task := m.(*taskdefs.CancelSwarmingTask)
			body, err := json.Marshal(map[string]interface{}{
				"hostname": task.Hostname,
				"task_id":  task.TaskId,
				"realm":    task.Realm,
			})
			if err != nil {
				return nil, errors.Annotate(err, "error marshaling payload").Err()
			}
			return &tq.CustomPayload{
				Body:        body,
				Method:      "POST",
				RelativeURI: fmt.Sprintf("/internal/task/buildbucket/cancel_swarming_task/%s/%s", task.Hostname, task.TaskId),
			}, nil
		},
		Handler:   rejectionHandler("cancel-swarming-task"),
		Kind:      tq.Transactional,
		Prototype: (*taskdefs.CancelSwarmingTask)(nil),
		Queue:     "backend-default",
	})

	tq.RegisterTaskClass(tq.TaskClass{
		ID: "create-swarming-task",
		Custom: func(ctx context.Context, m proto.Message) (*tq.CustomPayload, error) {
			task := m.(*taskdefs.CreateSwarmingTask)
			body, err := json.Marshal(map[string]interface{}{
				"generation": 0,
				"id":         task.BuildId,
			})
			if err != nil {
				return nil, errors.Annotate(err, "error marshaling payload").Err()
			}
			return &tq.CustomPayload{
				Body:        body,
				Method:      "POST",
				RelativeURI: fmt.Sprintf("/internal/task/swarming/sync-build/%d", task.BuildId),
			}, nil
		},
		Handler:   rejectionHandler("create-swarming-task"),
		Kind:      tq.Transactional,
		Prototype: (*taskdefs.CreateSwarmingTask)(nil),
		Queue:     "swarming-build-create",
	})

	tq.RegisterTaskClass(tq.TaskClass{
		ID: "export-bigquery",
		Custom: func(ctx context.Context, m proto.Message) (*tq.CustomPayload, error) {
			task := m.(*taskdefs.ExportBigQuery)
			body, err := json.Marshal(map[string]interface{}{
				"id": task.BuildId,
			})
			if err != nil {
				return nil, errors.Annotate(err, "error marshaling payload").Err()
			}
			return &tq.CustomPayload{
				Body:        body,
				Method:      "POST",
				RelativeURI: fmt.Sprintf("/internal/task/bq/export/%d", task.BuildId),
			}, nil
		},
		Handler:   rejectionHandler("export-bigquery"),
		Kind:      tq.Transactional,
		Prototype: (*taskdefs.ExportBigQuery)(nil),
		Queue:     "backend-default",
	})

	tq.RegisterTaskClass(tq.TaskClass{
		ID: "finalize-resultdb",
		Custom: func(ctx context.Context, m proto.Message) (*tq.CustomPayload, error) {
			task := m.(*taskdefs.FinalizeResultDB)
			body, err := json.Marshal(map[string]interface{}{
				"id": task.BuildId,
			})
			if err != nil {
				return nil, errors.Annotate(err, "error marshaling payload").Err()
			}
			return &tq.CustomPayload{
				Body:        body,
				Method:      "POST",
				RelativeURI: fmt.Sprintf("/internal/task/resultdb/finalize/%d", task.BuildId),
			}, nil
		},
		Handler:   rejectionHandler("finalize-resultdb"),
		Kind:      tq.Transactional,
		Prototype: (*taskdefs.FinalizeResultDB)(nil),
		Queue:     "backend-default",
	})

	tq.RegisterTaskClass(tq.TaskClass{
		ID: "notify-pubsub",
		Custom: func(ctx context.Context, m proto.Message) (*tq.CustomPayload, error) {
			task := m.(*taskdefs.NotifyPubSub)
			mode := "global"
			if task.Callback {
				mode = "callback"
			}
			body, err := json.Marshal(map[string]interface{}{
				"id":   task.BuildId,
				"mode": mode,
			})
			if err != nil {
				return nil, errors.Annotate(err, "error marshaling payload").Err()
			}
			return &tq.CustomPayload{
				Body:        body,
				Method:      "POST",
				RelativeURI: fmt.Sprintf("/internal/task/buildbucket/notify/%d", task.BuildId),
			}, nil
		},
		Handler:   rejectionHandler("notify-pubsub"),
		Kind:      tq.Transactional,
		Prototype: (*taskdefs.NotifyPubSub)(nil),
		Queue:     "backend-default",
	})
}

// CancelSwarmingTask enqueues a task queue task to cancel the given Swarming
// task.
func CancelSwarmingTask(ctx context.Context, task *taskdefs.CancelSwarmingTask) error {
	switch {
	case task.GetHostname() == "":
		return errors.Reason("hostname is required").Err()
	case task.TaskId == "":
		return errors.Reason("task_id is required").Err()
	}
	return tq.AddTask(ctx, &tq.Task{
		Payload: task,
	})
}

// CreateSwarmingTask enqueues a task queue task to create a Swarming task from
// the given build.
func CreateSwarmingTask(ctx context.Context, task *taskdefs.CreateSwarmingTask) error {
	if task.GetBuildId() == 0 {
		return errors.Reason("build_id is required").Err()
	}
	return tq.AddTask(ctx, &tq.Task{
		Payload: task,
	})
}

// ExportBigQuery enqueues a task queue task to export the given build to
// BigQuery.
func ExportBigQuery(ctx context.Context, task *taskdefs.ExportBigQuery) error {
	if task.GetBuildId() == 0 {
		return errors.Reason("build_id is required").Err()
	}
	return tq.AddTask(ctx, &tq.Task{
		Payload: task,
	})
}

// FinalizeResultDB enqueues a task queue task to finalize the invocation for
// the given build in ResultDB.
func FinalizeResultDB(ctx context.Context, task *taskdefs.FinalizeResultDB) error {
	if task.GetBuildId() == 0 {
		return errors.Reason("build_id is required").Err()
	}
	return tq.AddTask(ctx, &tq.Task{
		Payload: task,
	})
}

// NotifyPubSub enqueues a task queue task to notify Pub/Sub about the given
// build.
func NotifyPubSub(ctx context.Context, task *taskdefs.NotifyPubSub) error {
	if task.GetBuildId() == 0 {
		return errors.Reason("build_id is required").Err()
	}
	return tq.AddTask(ctx, &tq.Task{
		Payload: task,
	})
}
<|endoftext|>


<commit_before>package lang

import (
  // "fmt"
  "testing"
)

func saneQueryTest(query, expected string, t *testing.T, env *LangEnv) {
  val := Eval(query, env)
  if val.Val == nil || val.Err != nil {
    t.Errorf("Expected %s to not be nil", query)
  } else {
    if val.Val.Str() != expected {
      t.Errorf("Expected %s to be %s, but was %s", query, expected, val.Val.Str())
    }
  }
}

func malformedQueryTest(query string, t *testing.T, env *LangEnv) {
  val := Eval(query, env)
  if val.Val != nil {
    t.Errorf("Expected value of %s to be nil, was %s", val.Val.Str())
  } else if  val.Err == nil {
    t.Errorf("Expected %s to return a non-nil error")
  }
}

func TestBasicLang(t *testing.T) {
  env := new(LangEnv)
  env.Init()

  saneQueryTest("(+ 1 2)", "3", t, env)
  saneQueryTest("(- 1 2)", "-1", t, env)
  saneQueryTest("(* 1 2)", "2", t, env)
  saneQueryTest("(/ 1 2)", "0", t, env)

  saneQueryTest("(+ 1.1 2.1)", "3.2", t, env)
  saneQueryTest("(- 1.3 2.1)", "-0.8", t, env)
  saneQueryTest("(* 1.3 2)", "2.6", t, env)
  saneQueryTest("(/ 1.3 2)", "0.65", t, env)

  malformedQueryTest(")(", t, env)
  malformedQueryTest(")", t, env)
  malformedQueryTest("(", t, env)
  malformedQueryTest("]]]", t, env)
}
<commit_msg>More tests<commit_after>package lang

import (
  // "fmt"
  "testing"
)

func saneQueryTest(query, expected string, t *testing.T, env *LangEnv) {
  val := Eval(query, env)
  if val.Val == nil || val.Err != nil {
    t.Errorf("Expected %s to not be nil", query)
  } else {
    if val.Val.Str() != expected {
      t.Errorf("Expected %s to be %s, but was %s", query, expected, val.Val.Str())
    }
  }
}

func malformedQueryTest(query string, t *testing.T, env *LangEnv) {
  val := Eval(query, env)
  if val.Val != nil {
    t.Errorf("Expected value of %s to be nil, was %s", val.Val.Str())
  } else if  val.Err == nil {
    t.Errorf("Expected %s to return a non-nil error")
  }
}

func TestBasicLang(t *testing.T) {
  env := new(LangEnv)
  env.Init()

  saneQueryTest("(+ 1 2)", "3", t, env)
  saneQueryTest("(- 1 2)", "-1", t, env)
  saneQueryTest("(* 1 2)", "2", t, env)
  saneQueryTest("(/ 1 2)", "0", t, env)

  saneQueryTest("(+ 1.1 2.1)", "3.2", t, env)
  saneQueryTest("(- 1.3 2.1)", "-0.8", t, env)
  saneQueryTest("(* 1.3 2)", "2.6", t, env)
  saneQueryTest("(/ 1.3 2)", "0.65", t, env)

  malformedQueryTest(")(", t, env)
  malformedQueryTest(")", t, env)
  malformedQueryTest("(", t, env)
  malformedQueryTest("]]]", t, env)

  malformedQueryTest("(/ 1 0)", t, env)
}
<|endoftext|>