<commit_before>package main

import (
	"encoding/binary"
	"flag"
	"fmt"
	"io"
	"os"
	"strings"
	"time"

	"github.com/bwmarrin/discordgo"
)

func init() {
	flag.StringVar(&token, "t", "", "Account Token")
	flag.Parse()
}

var token string
var buffer = make([][]byte, 0)

func main() {
	if token == "" {
		fmt.Println("No token provided. Please run: airhorn -t <bot token>")
		return
	}

	// Load the sound file.
	err := loadSound()
	if err != nil {
		fmt.Println("Error loading sound: ", err)
		fmt.Println("Please copy $GOPATH/src/github.com/bwmarrin/examples/airhorn/airhorn.dca to this directory.")
		return
	}

	// Create a new Discord session using the provided token.
	dg, err := discordgo.New(token)
	if err != nil {
		fmt.Println("Error creating Discord session: ", err)
		return
	}

	// Register ready as a callback for the ready events.
	dg.AddHandler(ready)

	// Register messageCreate as a callback for the messageCreate events.
	dg.AddHandler(messageCreate)

	// Register guildCreate as a callback for the guildCreate events.
	dg.AddHandler(guildCreate)

	// Open the websocket and begin listening.
	err = dg.Open()
	if err != nil {
		fmt.Println("Error opening Discord session: ", err)
	}

	fmt.Println("Airhorn is now running.  Press CTRL-C to exit.")
	// Simple way to keep program running until CTRL-C is pressed.
	<-make(chan struct{})
	return
}

func ready(s *discordgo.Session, event *discordgo.Ready) {
	// Set the playing status.
	_ = s.UpdateStatus(0, "!airhorn")
}

// This function will be called (due to AddHandler above) every time a new
// message is created on any channel that the autenticated bot has access to.
func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
	if strings.HasPrefix(m.Content, "!airhorn") {
		// Find the channel that the message came from.
		c, err := s.State.Channel(m.ChannelID)
		if err != nil {
			// Could not find channel.
			return
		}

		// Find the guild for that channel.
		g, err := s.State.Guild(c.GuildID)
		if err != nil {
			// Could not find guild.
			return
		}

		// Look for the message sender in that guilds current voice states.
		for _, vs := range g.VoiceStates {
			if vs.UserID == m.Author.ID {
				err = playSound(s, g.ID, vs.ChannelID)
				if err != nil {
					fmt.Println("Error playing sound:", err)
				}

				return
			}
		}
	}
}

// This function will be called (due to AddHandler above) every time a new
// guild is joined.
func guildCreate(s *discordgo.Session, event *discordgo.GuildCreate) {
	if event.Guild.Unavailable != nil {
		return
	}

	for _, channel := range event.Guild.Channels {
		if channel.ID == event.Guild.ID {
			_, _ = s.ChannelMessageSend(channel.ID, "Airhorn is ready! Type !airhorn while in a voice channel to play a sound.")
			return
		}
	}
}

// loadSound attempts to load an encoded sound file from disk.
func loadSound() error {
	file, err := os.Open("airhorn.dca")

	if err != nil {
		fmt.Println("Error opening dca file :", err)
		return err
	}

	var opuslen int16

	for {
		// Read opus frame length from dca file.
		err = binary.Read(file, binary.LittleEndian, &opuslen)

		// If this is the end of the file, just return.
		if err == io.EOF || err == io.ErrUnexpectedEOF {
			return nil
		}

		if err != nil {
			fmt.Println("Error reading from dca file :", err)
			return err
		}

		// Read encoded pcm from dca file.
		InBuf := make([]byte, opuslen)
		err = binary.Read(file, binary.LittleEndian, &InBuf)

		// Should not be any end of file errors
		if err != nil {
			fmt.Println("Error reading from dca file :", err)
			return err
		}

		// Append encoded pcm data to the buffer.
		buffer = append(buffer, InBuf)
	}
}

// playSound plays the current buffer to the provided channel.
func playSound(s *discordgo.Session, guildID, channelID string) (err error) {
	// Join the provided voice channel.
	vc, err := s.ChannelVoiceJoin(guildID, channelID, false, true)
	if err != nil {
		return err
	}

	// Sleep for a specified amount of time before playing the sound
	time.Sleep(250 * time.Millisecond)

	// Start speaking.
	_ = vc.Speaking(true)

	// Send the buffer data.
	for _, buff := range buffer {
		vc.OpusSend <- buff
	}

	// Stop speaking
	_ = vc.Speaking(false)

	// Sleep for a specificed amount of time before ending.
	time.Sleep(250 * time.Millisecond)

	// Disconnect from the provided voice channel.
	_ = vc.Disconnect()

	return nil
}
<commit_msg>Close the file after read<commit_after>package main

import (
	"encoding/binary"
	"flag"
	"fmt"
	"io"
	"os"
	"strings"
	"time"

	"github.com/bwmarrin/discordgo"
)

func init() {
	flag.StringVar(&token, "t", "", "Account Token")
	flag.Parse()
}

var token string
var buffer = make([][]byte, 0)

func main() {
	if token == "" {
		fmt.Println("No token provided. Please run: airhorn -t <bot token>")
		return
	}

	// Load the sound file.
	err := loadSound()
	if err != nil {
		fmt.Println("Error loading sound: ", err)
		fmt.Println("Please copy $GOPATH/src/github.com/bwmarrin/examples/airhorn/airhorn.dca to this directory.")
		return
	}

	// Create a new Discord session using the provided token.
	dg, err := discordgo.New(token)
	if err != nil {
		fmt.Println("Error creating Discord session: ", err)
		return
	}

	// Register ready as a callback for the ready events.
	dg.AddHandler(ready)

	// Register messageCreate as a callback for the messageCreate events.
	dg.AddHandler(messageCreate)

	// Register guildCreate as a callback for the guildCreate events.
	dg.AddHandler(guildCreate)

	// Open the websocket and begin listening.
	err = dg.Open()
	if err != nil {
		fmt.Println("Error opening Discord session: ", err)
	}

	fmt.Println("Airhorn is now running.  Press CTRL-C to exit.")
	// Simple way to keep program running until CTRL-C is pressed.
	<-make(chan struct{})
	return
}

func ready(s *discordgo.Session, event *discordgo.Ready) {
	// Set the playing status.
	_ = s.UpdateStatus(0, "!airhorn")
}

// This function will be called (due to AddHandler above) every time a new
// message is created on any channel that the autenticated bot has access to.
func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
	if strings.HasPrefix(m.Content, "!airhorn") {
		// Find the channel that the message came from.
		c, err := s.State.Channel(m.ChannelID)
		if err != nil {
			// Could not find channel.
			return
		}

		// Find the guild for that channel.
		g, err := s.State.Guild(c.GuildID)
		if err != nil {
			// Could not find guild.
			return
		}

		// Look for the message sender in that guilds current voice states.
		for _, vs := range g.VoiceStates {
			if vs.UserID == m.Author.ID {
				err = playSound(s, g.ID, vs.ChannelID)
				if err != nil {
					fmt.Println("Error playing sound:", err)
				}

				return
			}
		}
	}
}

// This function will be called (due to AddHandler above) every time a new
// guild is joined.
func guildCreate(s *discordgo.Session, event *discordgo.GuildCreate) {
	if event.Guild.Unavailable != nil {
		return
	}

	for _, channel := range event.Guild.Channels {
		if channel.ID == event.Guild.ID {
			_, _ = s.ChannelMessageSend(channel.ID, "Airhorn is ready! Type !airhorn while in a voice channel to play a sound.")
			return
		}
	}
}

// loadSound attempts to load an encoded sound file from disk.
func loadSound() error {
	file, err := os.Open("airhorn.dca")

	if err != nil {
		fmt.Println("Error opening dca file :", err)
		return err
	}

	var opuslen int16

	for {
		// Read opus frame length from dca file.
		err = binary.Read(file, binary.LittleEndian, &opuslen)

		// If this is the end of the file, just return.
		if err == io.EOF || err == io.ErrUnexpectedEOF {
			file.Close()
			if err != nil {
				return err
			}
			return nil
		}

		if err != nil {
			fmt.Println("Error reading from dca file :", err)
			return err
		}

		// Read encoded pcm from dca file.
		InBuf := make([]byte, opuslen)
		err = binary.Read(file, binary.LittleEndian, &InBuf)

		// Should not be any end of file errors
		if err != nil {
			fmt.Println("Error reading from dca file :", err)
			return err
		}

		// Append encoded pcm data to the buffer.
		buffer = append(buffer, InBuf)
	}
}

// playSound plays the current buffer to the provided channel.
func playSound(s *discordgo.Session, guildID, channelID string) (err error) {
	// Join the provided voice channel.
	vc, err := s.ChannelVoiceJoin(guildID, channelID, false, true)
	if err != nil {
		return err
	}

	// Sleep for a specified amount of time before playing the sound
	time.Sleep(250 * time.Millisecond)

	// Start speaking.
	_ = vc.Speaking(true)

	// Send the buffer data.
	for _, buff := range buffer {
		vc.OpusSend <- buff
	}

	// Stop speaking
	_ = vc.Speaking(false)

	// Sleep for a specificed amount of time before ending.
	time.Sleep(250 * time.Millisecond)

	// Disconnect from the provided voice channel.
	_ = vc.Disconnect()

	return nil
}
<|endoftext|>


<commit_before>package redis

import (
	"github.com/hoisie/redis"
	"github.com/robfig/revel"
)

var (
	Client *redis.Client
)

func Init() {
	var found bool
	var addr string
	if addr, found = revel.Config.String("redis.addr"); !found {
		revel.ERROR.Fatal("No redis.addr found")
	}
	var db int
	if db, found = revel.Config.Int("redis.db"); !found {
		revel.ERROR.Fatal("No redis.db found")
	}
	revel.INFO.Printf("Connecting to redis db %v at %v", db, addr)
	Client = &redis.Client{Addr: addr, Db: db}
}

func init() {
	revel.OnAppStart(Init)
}
<commit_msg>redis.go: configure redis pool size<commit_after>package redis

import (
	"github.com/hoisie/redis"
	"github.com/robfig/revel"
)

var (
	Client *redis.Client
)

func Init() {
	var found bool
	var addr string
	if addr, found = revel.Config.String("redis.addr"); !found {
		revel.ERROR.Fatal("No redis.addr found")
	}
	var db int
	if db, found = revel.Config.Int("redis.db"); !found {
		revel.ERROR.Fatal("No redis.db found")
	}
	poolSize := revel.Config.IntDefault("redis.poolsize", 0)
	revel.INFO.Printf("Connecting to redis db %v at %v with poolsize %v (0 = use driver default)", db, addr, poolSize)
	Client = &redis.Client{Addr: addr, Db: db, MaxPoolSize: poolSize}
}

func init() {
	revel.OnAppStart(Init)
}
<|endoftext|>


<commit_before>// Copyright 2015 Dmitry Vyukov. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package gotypes

import (
	"bytes"
	"fmt"
	"go/ast"
	"go/format"
	"go/importer"
	"go/parser"
	"go/token"
	"go/types"
	"io/ioutil"
	"os"
	"os/exec"
	"regexp"
	"strings"

	"golang.org/x/tools/go/ssa"
)

// https://github.com/golang/go/issues/11327
var bigNum = regexp.MustCompile("(\\.[0-9]*)|([0-9]+)[eE]\\-?\\+?[0-9]{3,}")
var bigNum2 = regexp.MustCompile("[0-9]+[pP][0-9]{3,}") // see issue 11364

// https://github.com/golang/go/issues/11274
var formatBug1 = regexp.MustCompile("\\*/[ \t\n\r\f\v]*;")
var formatBug2 = regexp.MustCompile(";[ \t\n\r\f\v]*/\\*")

var issue11590 = regexp.MustCompile(": cannot convert .* \\(untyped int constant .*\\) to complex")
var issue11590_2 = regexp.MustCompile(": [0-9]+ (untyped int constant) overflows complex")
var issue11370 = regexp.MustCompile("\\\"[ \t\n\r\f\v]*\\[")

var fpRounding = regexp.MustCompile(" \\(untyped float constant .*\\) truncated to ")
var something = regexp.MustCompile(" constant .* overflows ")

var gcCrash = regexp.MustCompile("\n/tmp/fuzz\\.gc[0-9]+:[0-9]+: internal compiler error: ")
var asanCrash = regexp.MustCompile("\n==[0-9]+==ERROR: AddressSanitizer: ")

func Fuzz(data []byte) int {
	if bigNum.Match(data) || bigNum2.Match(data) {
		return 0
	}
	goErr := gotypes(data)
	gcErr := gc(data)
	gccgoErr := gccgo(data)
	if goErr == nil && gcErr != nil {
		if strings.Contains(gcErr.Error(), "line number out of range") {
			// https://github.com/golang/go/issues/11329
			return 0
		}
		if strings.Contains(gcErr.Error(), "overflow in int -> string") {
			// https://github.com/golang/go/issues/11330
			return 0
		}
		if strings.Contains(gcErr.Error(), "larger than address space") {
			// Gc is more picky at rejecting huge objects.
			return 0
		}
		if strings.Contains(gcErr.Error(), "non-canonical import path") {
			return 0
		}
		if strings.Contains(gcErr.Error(), "constant shift overflow") {
			// ???
			return 0
		}
		if something.MatchString(gcErr.Error()) {
			// ???
			return 0
		}
	}

	if gcErr == nil && goErr != nil {
		if strings.Contains(goErr.Error(), "illegal character U+") {
			// https://github.com/golang/go/issues/11359
			return 0
		}
		if issue11590.MatchString(goErr.Error()) || issue11590_2.MatchString(goErr.Error()) {
			// https://github.com/golang/go/issues/11590
			return 0
		}
		if issue11370.MatchString(goErr.Error()) {
			return 0
		}
	}

	if gccgoErr == nil && goErr != nil {
		if strings.Contains(goErr.Error(), "invalid operation: stupid shift count") {
			// https://github.com/golang/go/issues/11524
			return 0
		}
		if (bytes.Contains(data, []byte("//line")) || bytes.Contains(data, []byte("/*"))) &&
			(strings.Contains(goErr.Error(), "illegal UTF-8 encoding") ||
				strings.Contains(goErr.Error(), "illegal character NUL")) {
			// https://github.com/golang/go/issues/11527
			return 0
		}
		if fpRounding.MatchString(goErr.Error()) {
			// gccgo has different rounding
			return 0
		}
		if strings.Contains(goErr.Error(), "operator | not defined for") {
			// https://github.com/golang/go/issues/11566
			return 0
		}
		if strings.Contains(goErr.Error(), "illegal byte order mark") {
			// on "package\rG\n//line \ufeff:1" input, not filed.
			return 0
		}
	}

	if goErr == nil && gccgoErr != nil {
		if strings.Contains(gccgoErr.Error(), "error: integer constant overflow") {
			// https://github.com/golang/go/issues/11525
			return 0
		}
		if bytes.Contains(data, []byte("0i")) &&
			(strings.Contains(gccgoErr.Error(), "incompatible types in binary expression") ||
				strings.Contains(gccgoErr.Error(), "initialization expression has wrong type")) {
			// https://github.com/golang/go/issues/11564
			// https://github.com/golang/go/issues/11563
			return 0
		}
	}

	// go-fuzz is too smart so it can generate a program that contains "internal compiler error" in an error message :)
	if gcErr != nil && (gcCrash.MatchString(gcErr.Error()) ||
		strings.Contains(gcErr.Error(), "\nruntime error: ") ||
		strings.HasPrefix(gcErr.Error(), "runtime error: ") ||
		strings.Contains(gcErr.Error(), "%!")) { // bad format string
		if strings.Contains(gcErr.Error(), "internal compiler error: out of fixed registers") {
			// https://github.com/golang/go/issues/11352
			return 0
		}
		if strings.Contains(gcErr.Error(), "internal compiler error: treecopy Name") {
			// https://github.com/golang/go/issues/11361
			return 0
		}
		if strings.Contains(gcErr.Error(), "internal compiler error: newname nil") {
			// https://github.com/golang/go/issues/11610
			return 0
		}
		fmt.Printf("gc result: %v\n", gcErr)
		panic("gc compiler crashed")
	}

	const gccgoCrash = "go1: internal compiler error:"
	if gccgoErr != nil && (strings.HasPrefix(gccgoErr.Error(), gccgoCrash) || strings.Contains(gccgoErr.Error(), "\n"+gccgoCrash)) {
		if strings.Contains(gccgoErr.Error(), "go1: internal compiler error: in check_bounds, at go/gofrontend/expressions.cc") {
			// https://github.com/golang/go/issues/11545
			return 0
		}
		if strings.Contains(gccgoErr.Error(), "go1: internal compiler error: in do_export, at go/gofrontend/types.cc") {
			// https://github.com/golang/go/issues/12321
			return 0
		}
		if strings.Contains(gccgoErr.Error(), "go1: internal compiler error: in do_lower, at go/gofrontend/expressions.cc") {
			// https://github.com/golang/go/issues/12615
			return 0
		}
		if strings.Contains(gccgoErr.Error(), "go1: internal compiler error: in insert, at go/gofrontend/gogo.cc") {
			// https://github.com/golang/go/issues/12616
			return 0
		}
		if strings.Contains(gccgoErr.Error(), "go1: internal compiler error: in do_get_backend, at go/gofrontend/expressions.cc") ||
			strings.Contains(gccgoErr.Error(), "go1: internal compiler error: in do_get_backend, at go/gofrontend/types.cc") {
			// https://github.com/golang/go/issues/12617
			return 0
		}
		if strings.Contains(gccgoErr.Error(), "go1: internal compiler error: in wide_int_to_tree, at tree.c") {
			// https://github.com/golang/go/issues/12618
			return 0
		}
		fmt.Printf("gccgo result: %v\n", gccgoErr)
		panic("gccgo compiler crashed")
	}

	if gccgoErr != nil && asanCrash.MatchString(gccgoErr.Error()) {
		fmt.Printf("gccgo result: %v\n", gccgoErr)
		panic("gccgo compiler crashed")
	}

	if gcErr == nil && goErr == nil && gccgoErr != nil && strings.Contains(gccgoErr.Error(), "0x124a4") {
		// https://github.com/golang/go/issues/12322
		return 0
	}

	if (goErr == nil) != (gcErr == nil) || (goErr == nil) != (gccgoErr == nil) {
		fmt.Printf("go/types result: %v\n", goErr)
		fmt.Printf("gc result: %v\n", gcErr)
		fmt.Printf("gccgo result: %v\n", gccgoErr)
		panic("gc, gccgo and go/types disagree")
	}
	if goErr != nil {
		return 0

	}
	if formatBug1.Match(data) || formatBug2.Match(data) {
		return 1
	}
	// https://github.com/golang/go/issues/11274
	data = bytes.Replace(data, []byte{'\r'}, []byte{' '}, -1)
	data1, err := format.Source(data)
	if err != nil {
		panic(err)
	}
	if false {
		err = gotypes(data1)
		if err != nil {
			fmt.Printf("new: %q\n", data1)
			fmt.Printf("err: %v\n", err)
			panic("program become invalid after gofmt")
		}
	}
	return 1
}

func gotypes(data []byte) (err error) {
	fset := token.NewFileSet()
	var f *ast.File
	f, err = parser.ParseFile(fset, "src.go", data, parser.ParseComments|parser.DeclarationErrors|parser.AllErrors)
	if err != nil {
		return
	}
	// provide error handler
	// initialize maps in config
	conf := &types.Config{
		Error:    func(err error) {},
		Sizes:    &types.StdSizes{8, 8},
		Importer: importer.For("gc", nil),
	}
	_, err = conf.Check("pkg", fset, []*ast.File{f}, nil)
	if err != nil {
		return
	}
	prog := ssa.NewProgram(fset, ssa.BuildSerially|ssa.SanityCheckFunctions|ssa.GlobalDebug)
	prog.BuildAll()
	for _, pkg := range prog.AllPackages() {
		_, err := pkg.WriteTo(ioutil.Discard)
		if err != nil {
			panic(err)
		}
	}
	return
}

func gc(data []byte) error {
	f, err := ioutil.TempFile("", "fuzz.gc")
	if err != nil {
		return err
	}
	defer os.Remove(f.Name())
	defer f.Close()
	_, err = f.Write(data)
	if err != nil {
		return err
	}
	f.Close()
	out, err := exec.Command("compile", f.Name()).CombinedOutput()
	if err != nil {
		return fmt.Errorf("%s\n%s", out, err)
	}
	return nil
}

func gccgo(data []byte) error {
	cmd := exec.Command("gccgo", "-c", "-x", "go", "-O3", "-o", "/dev/null", "-")
	cmd.Stdin = bytes.NewReader(data)
	out, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("%s\n%s", out, err)
	}
	return nil
}
<commit_msg>remove a suppression for fixed bug<commit_after>// Copyright 2015 Dmitry Vyukov. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package gotypes

import (
	"bytes"
	"fmt"
	"go/ast"
	"go/format"
	"go/importer"
	"go/parser"
	"go/token"
	"go/types"
	"io/ioutil"
	"os"
	"os/exec"
	"regexp"
	"strings"

	"golang.org/x/tools/go/ssa"
)

// https://github.com/golang/go/issues/11327
var bigNum = regexp.MustCompile("(\\.[0-9]*)|([0-9]+)[eE]\\-?\\+?[0-9]{3,}")
var bigNum2 = regexp.MustCompile("[0-9]+[pP][0-9]{3,}") // see issue 11364

// https://github.com/golang/go/issues/11274
var formatBug1 = regexp.MustCompile("\\*/[ \t\n\r\f\v]*;")
var formatBug2 = regexp.MustCompile(";[ \t\n\r\f\v]*/\\*")

var issue11590 = regexp.MustCompile(": cannot convert .* \\(untyped int constant .*\\) to complex")
var issue11590_2 = regexp.MustCompile(": [0-9]+ (untyped int constant) overflows complex")
var issue11370 = regexp.MustCompile("\\\"[ \t\n\r\f\v]*\\[")

var fpRounding = regexp.MustCompile(" \\(untyped float constant .*\\) truncated to ")
var something = regexp.MustCompile(" constant .* overflows ")

var gcCrash = regexp.MustCompile("\n/tmp/fuzz\\.gc[0-9]+:[0-9]+: internal compiler error: ")
var asanCrash = regexp.MustCompile("\n==[0-9]+==ERROR: AddressSanitizer: ")

func Fuzz(data []byte) int {
	if bigNum.Match(data) || bigNum2.Match(data) {
		return 0
	}
	goErr := gotypes(data)
	gcErr := gc(data)
	gccgoErr := gccgo(data)
	if goErr == nil && gcErr != nil {
		if strings.Contains(gcErr.Error(), "line number out of range") {
			// https://github.com/golang/go/issues/11329
			return 0
		}
		if strings.Contains(gcErr.Error(), "overflow in int -> string") {
			// https://github.com/golang/go/issues/11330
			return 0
		}
		if strings.Contains(gcErr.Error(), "larger than address space") {
			// Gc is more picky at rejecting huge objects.
			return 0
		}
		if strings.Contains(gcErr.Error(), "non-canonical import path") {
			return 0
		}
		if strings.Contains(gcErr.Error(), "constant shift overflow") {
			// ???
			return 0
		}
		if something.MatchString(gcErr.Error()) {
			// ???
			return 0
		}
	}

	if gcErr == nil && goErr != nil {
		if strings.Contains(goErr.Error(), "illegal character U+") {
			// https://github.com/golang/go/issues/11359
			return 0
		}
		if issue11590.MatchString(goErr.Error()) || issue11590_2.MatchString(goErr.Error()) {
			// https://github.com/golang/go/issues/11590
			return 0
		}
		if issue11370.MatchString(goErr.Error()) {
			return 0
		}
	}

	if gccgoErr == nil && goErr != nil {
		if strings.Contains(goErr.Error(), "invalid operation: stupid shift count") {
			// https://github.com/golang/go/issues/11524
			return 0
		}
		if (bytes.Contains(data, []byte("//line")) || bytes.Contains(data, []byte("/*"))) &&
			(strings.Contains(goErr.Error(), "illegal UTF-8 encoding") ||
				strings.Contains(goErr.Error(), "illegal character NUL")) {
			// https://github.com/golang/go/issues/11527
			return 0
		}
		if fpRounding.MatchString(goErr.Error()) {
			// gccgo has different rounding
			return 0
		}
		if strings.Contains(goErr.Error(), "operator | not defined for") {
			// https://github.com/golang/go/issues/11566
			return 0
		}
		if strings.Contains(goErr.Error(), "illegal byte order mark") {
			// on "package\rG\n//line \ufeff:1" input, not filed.
			return 0
		}
	}

	if goErr == nil && gccgoErr != nil {
		if strings.Contains(gccgoErr.Error(), "error: integer constant overflow") {
			// https://github.com/golang/go/issues/11525
			return 0
		}
		if bytes.Contains(data, []byte("0i")) &&
			(strings.Contains(gccgoErr.Error(), "incompatible types in binary expression") ||
				strings.Contains(gccgoErr.Error(), "initialization expression has wrong type")) {
			// https://github.com/golang/go/issues/11564
			// https://github.com/golang/go/issues/11563
			return 0
		}
	}

	// go-fuzz is too smart so it can generate a program that contains "internal compiler error" in an error message :)
	if gcErr != nil && (gcCrash.MatchString(gcErr.Error()) ||
		strings.Contains(gcErr.Error(), "\nruntime error: ") ||
		strings.HasPrefix(gcErr.Error(), "runtime error: ") ||
		strings.Contains(gcErr.Error(), "%!")) { // bad format string
		if strings.Contains(gcErr.Error(), "internal compiler error: out of fixed registers") {
			// https://github.com/golang/go/issues/11352
			return 0
		}
		if strings.Contains(gcErr.Error(), "internal compiler error: treecopy Name") {
			// https://github.com/golang/go/issues/11361
			return 0
		}
		if strings.Contains(gcErr.Error(), "internal compiler error: newname nil") {
			// https://github.com/golang/go/issues/11610
			return 0
		}
		fmt.Printf("gc result: %v\n", gcErr)
		panic("gc compiler crashed")
	}

	const gccgoCrash = "go1: internal compiler error:"
	if gccgoErr != nil && (strings.HasPrefix(gccgoErr.Error(), gccgoCrash) || strings.Contains(gccgoErr.Error(), "\n"+gccgoCrash)) {
		if strings.Contains(gccgoErr.Error(), "go1: internal compiler error: in check_bounds, at go/gofrontend/expressions.cc") {
			// https://github.com/golang/go/issues/11545
			return 0
		}
		if strings.Contains(gccgoErr.Error(), "go1: internal compiler error: in do_export, at go/gofrontend/types.cc") {
			// https://github.com/golang/go/issues/12321
			return 0
		}
		if strings.Contains(gccgoErr.Error(), "go1: internal compiler error: in do_lower, at go/gofrontend/expressions.cc") {
			// https://github.com/golang/go/issues/12615
			return 0
		}
		if strings.Contains(gccgoErr.Error(), "go1: internal compiler error: in insert, at go/gofrontend/gogo.cc") {
			// https://github.com/golang/go/issues/12616
			return 0
		}
		if strings.Contains(gccgoErr.Error(), "go1: internal compiler error: in wide_int_to_tree, at tree.c") {
			// https://github.com/golang/go/issues/12618
			return 0
		}
		fmt.Printf("gccgo result: %v\n", gccgoErr)
		panic("gccgo compiler crashed")
	}

	if gccgoErr != nil && asanCrash.MatchString(gccgoErr.Error()) {
		fmt.Printf("gccgo result: %v\n", gccgoErr)
		panic("gccgo compiler crashed")
	}

	if gcErr == nil && goErr == nil && gccgoErr != nil && strings.Contains(gccgoErr.Error(), "0x124a4") {
		// https://github.com/golang/go/issues/12322
		return 0
	}

	if (goErr == nil) != (gcErr == nil) || (goErr == nil) != (gccgoErr == nil) {
		fmt.Printf("go/types result: %v\n", goErr)
		fmt.Printf("gc result: %v\n", gcErr)
		fmt.Printf("gccgo result: %v\n", gccgoErr)
		panic("gc, gccgo and go/types disagree")
	}
	if goErr != nil {
		return 0

	}
	if formatBug1.Match(data) || formatBug2.Match(data) {
		return 1
	}
	// https://github.com/golang/go/issues/11274
	data = bytes.Replace(data, []byte{'\r'}, []byte{' '}, -1)
	data1, err := format.Source(data)
	if err != nil {
		panic(err)
	}
	if false {
		err = gotypes(data1)
		if err != nil {
			fmt.Printf("new: %q\n", data1)
			fmt.Printf("err: %v\n", err)
			panic("program become invalid after gofmt")
		}
	}
	return 1
}

func gotypes(data []byte) (err error) {
	fset := token.NewFileSet()
	var f *ast.File
	f, err = parser.ParseFile(fset, "src.go", data, parser.ParseComments|parser.DeclarationErrors|parser.AllErrors)
	if err != nil {
		return
	}
	// provide error handler
	// initialize maps in config
	conf := &types.Config{
		Error:    func(err error) {},
		Sizes:    &types.StdSizes{8, 8},
		Importer: importer.For("gc", nil),
	}
	_, err = conf.Check("pkg", fset, []*ast.File{f}, nil)
	if err != nil {
		return
	}
	prog := ssa.NewProgram(fset, ssa.BuildSerially|ssa.SanityCheckFunctions|ssa.GlobalDebug)
	prog.BuildAll()
	for _, pkg := range prog.AllPackages() {
		_, err := pkg.WriteTo(ioutil.Discard)
		if err != nil {
			panic(err)
		}
	}
	return
}

func gc(data []byte) error {
	f, err := ioutil.TempFile("", "fuzz.gc")
	if err != nil {
		return err
	}
	defer os.Remove(f.Name())
	defer f.Close()
	_, err = f.Write(data)
	if err != nil {
		return err
	}
	f.Close()
	out, err := exec.Command("compile", f.Name()).CombinedOutput()
	if err != nil {
		return fmt.Errorf("%s\n%s", out, err)
	}
	return nil
}

func gccgo(data []byte) error {
	cmd := exec.Command("gccgo", "-c", "-x", "go", "-O3", "-o", "/dev/null", "-")
	cmd.Stdin = bytes.NewReader(data)
	out, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("%s\n%s", out, err)
	}
	return nil
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Kubernetes Authors.

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

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

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

package cache

import (
	"time"

	"k8s.io/component-base/metrics"
	"k8s.io/component-base/metrics/legacyregistry"
)

var (
	requestLatency = metrics.NewHistogramVec(
		&metrics.HistogramOpts{
			Namespace:      "authentication",
			Subsystem:      "token_cache",
			Name:           "request_duration_seconds",
			StabilityLevel: metrics.ALPHA,
		},
		[]string{"status"},
	)
	requestCount = metrics.NewCounterVec(
		&metrics.CounterOpts{
			Namespace:      "authentication",
			Subsystem:      "token_cache",
			Name:           "request_count",
			StabilityLevel: metrics.ALPHA,
		},
		[]string{"status"},
	)
	fetchCount = metrics.NewGaugeVec(
		&metrics.GaugeOpts{
			Namespace:      "authentication",
			Subsystem:      "token_cache",
			Name:           "fetch_count",
			StabilityLevel: metrics.ALPHA,
		},
		[]string{"status"},
	)
	blockCount = metrics.NewGauge(
		&metrics.GaugeOpts{
			Namespace:      "authentication",
			Subsystem:      "token_cache",
			Name:           "block_count",
			StabilityLevel: metrics.ALPHA,
		},
	)
)

func init() {
	legacyregistry.MustRegister(
		requestLatency,
		requestCount,
		fetchCount,
		blockCount,
	)
}

const (
	hitTag  = "hit"
	missTag = "miss"

	fetchActiveTag = "active"
	fetchFailedTag = "error"
	fetchOkTag     = "ok"
)

type statsCollector struct{}

var stats = statsCollector{}

func (statsCollector) authenticating() func(hit bool) {
	start := time.Now()
	return func(hit bool) {
		var tag string
		if hit {
			tag = hitTag
		} else {
			tag = missTag
		}

		latency := time.Since(start)

		requestCount.WithLabelValues(tag).Inc()
		requestLatency.WithLabelValues(tag).Observe(float64(latency.Milliseconds()) / 1000)
	}
}

func (statsCollector) blocking() func() {
	blockCount.Inc()
	return blockCount.Dec
}

func (statsCollector) fetching() func(ok bool) {
	fetchCount.WithLabelValues(fetchActiveTag).Inc()
	return func(ok bool) {
		var tag string
		if ok {
			tag = fetchOkTag
		} else {
			tag = fetchFailedTag
		}

		fetchCount.WithLabelValues(tag).Dec()
	}
}
<commit_msg>rename _count to _total in a few metrics<commit_after>/*
Copyright 2019 The Kubernetes Authors.

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

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

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

package cache

import (
	"time"

	"k8s.io/component-base/metrics"
	"k8s.io/component-base/metrics/legacyregistry"
)

var (
	requestLatency = metrics.NewHistogramVec(
		&metrics.HistogramOpts{
			Namespace:      "authentication",
			Subsystem:      "token_cache",
			Name:           "request_duration_seconds",
			StabilityLevel: metrics.ALPHA,
		},
		[]string{"status"},
	)
	requestCount = metrics.NewCounterVec(
		&metrics.CounterOpts{
			Namespace:      "authentication",
			Subsystem:      "token_cache",
			Name:           "request_total",
			StabilityLevel: metrics.ALPHA,
		},
		[]string{"status"},
	)
	fetchCount = metrics.NewGaugeVec(
		&metrics.GaugeOpts{
			Namespace:      "authentication",
			Subsystem:      "token_cache",
			Name:           "fetch_total",
			StabilityLevel: metrics.ALPHA,
		},
		[]string{"status"},
	)
	blockCount = metrics.NewGauge(
		&metrics.GaugeOpts{
			Namespace:      "authentication",
			Subsystem:      "token_cache",
			Name:           "block_count",
			StabilityLevel: metrics.ALPHA,
		},
	)
)

func init() {
	legacyregistry.MustRegister(
		requestLatency,
		requestCount,
		fetchCount,
		blockCount,
	)
}

const (
	hitTag  = "hit"
	missTag = "miss"

	fetchActiveTag = "active"
	fetchFailedTag = "error"
	fetchOkTag     = "ok"
)

type statsCollector struct{}

var stats = statsCollector{}

func (statsCollector) authenticating() func(hit bool) {
	start := time.Now()
	return func(hit bool) {
		var tag string
		if hit {
			tag = hitTag
		} else {
			tag = missTag
		}

		latency := time.Since(start)

		requestCount.WithLabelValues(tag).Inc()
		requestLatency.WithLabelValues(tag).Observe(float64(latency.Milliseconds()) / 1000)
	}
}

func (statsCollector) blocking() func() {
	blockCount.Inc()
	return blockCount.Dec
}

func (statsCollector) fetching() func(ok bool) {
	fetchCount.WithLabelValues(fetchActiveTag).Inc()
	return func(ok bool) {
		var tag string
		if ok {
			tag = fetchOkTag
		} else {
			tag = fetchFailedTag
		}

		fetchCount.WithLabelValues(tag).Dec()
	}
}
<|endoftext|>


<commit_before>package ddtxn

import (
	"container/heap"
	"ddtxn/dlog"
	"fmt"
	"sync/atomic"
	"time"
	"unsafe"
)

const (
	BUMP_EPOCH_MS = 80
	EPOCH_INCR    = 1 << 32
	TXID_MASK     = 0x00000000ffffffff
	CLEAR_TID     = 0xffffffff00000000
)

type Coordinator struct {
	n        int
	Workers  []*Worker
	epochTID TID // Global TID, atomically incremented and read

	// Notify workers
	wsafe  []chan bool
	wepoch []chan bool
	wgo    []chan bool
	wdone  []chan bool

	Done       chan chan bool
	Accelerate chan bool
}

func NewCoordinator(n int, s *Store) *Coordinator {
	c := &Coordinator{
		n:          n,
		Workers:    make([]*Worker, n),
		epochTID:   EPOCH_INCR,
		wepoch:     make([]chan bool, n),
		wsafe:      make([]chan bool, n),
		wgo:        make([]chan bool, n),
		wdone:      make([]chan bool, n),
		Done:       make(chan chan bool),
		Accelerate: make(chan bool),
	}
	for i := 0; i < n; i++ {
		c.wepoch[i] = make(chan bool)
		c.wsafe[i] = make(chan bool)
		c.wgo[i] = make(chan bool)
		c.wdone[i] = make(chan bool)
		c.Workers[i] = NewWorker(i, s, c)
	}
	dlog.Printf("[coordinator] %v workers\n", n)
	go c.Process()
	return c
}

var NextEpoch int64

func (c *Coordinator) NextGlobalTID() TID {
	NextEpoch++
	x := atomic.AddUint64((*uint64)(unsafe.Pointer(&c.epochTID)), EPOCH_INCR)
	return TID(x)
}

func (c *Coordinator) GetEpoch() TID {
	x := atomic.LoadUint64((*uint64)(unsafe.Pointer(&c.epochTID)))
	return TID(x)
}

var RMoved int64
var WMoved int64
var Time_in_IE time.Duration
var Time_in_IE1 time.Duration

func (c *Coordinator) IncrementEpoch() {
	start := time.Now()
	c.NextGlobalTID()

	// Wait for everyone to merge the previous epoch
	for i := 0; i < c.n; i++ {
		<-c.wepoch[i]
		//dlog.Printf("%v merged for %v\n", i, c.epochTID)
	}

	// All merged.  The previous epoch is now safe; tell everyone to
	// do their reads.
	for i := 0; i < c.n; i++ {
		c.wsafe[i] <- true
	}
	for i := 0; i < c.n; i++ {
		<-c.wdone[i]
		//dlog.Printf("Got done from %v for %v\n", i, c.epochTID)
	}

	start2 := time.Now()
	// Reads done!  Check stats
	s := c.Workers[0].store
	if c.epochTID%(10*EPOCH_INCR) == 0 {
		for i := 0; i < c.n; i++ {
			w := c.Workers[i]
			s.cand.Merge(w.local_store.candidates)
		}
		xx := len(*s.cand.h)
		dlog.Printf("Number of potential keys: %v; keys %v\n", xx, *s.cand.h)
		for i := 0; i < xx; i++ {
			o := heap.Pop(s.cand.h).(*OneStat)
			x, y := UndoCKey(o.k)
			dlog.Printf("%v Considering key %v %v; ratio %v\n", i, x, y, o.ratio())
			br, _ := s.getKey(o.k)
			if !br.dd {
				br.dd = true
				WMoved += 1
				dlog.Printf("Moved %v %v to split %v\n", x, y, o.ratio())
				s.dd = append(s.dd, o.k)
			} else {
				dlog.Printf("No need to Move %v %v to split; already dd\n", x, y)
			}
		}
		for i := 0; i < len(s.dd); i++ {
			o, ok := s.cand.m[s.dd[i]]
			if !ok {
				br, _ := s.getKey(s.dd[i])
				x, y := UndoCKey(br.key)
				fmt.Printf("Key %v %v was split but now is not in store candidates\n", x, y)
				continue
			}
			if o.ratio() < (*WRRatio)/2 {
				br, _ := s.getKey(s.dd[i])
				br.dd = false
				RMoved += 1
				x, y := UndoCKey(o.k)
				fmt.Printf("Moved %v %v from split ratio %v\n", x, y, o.ratio())
				s.dd[i], s.dd = s.dd[len(s.dd)-1], s.dd[:len(s.dd)-1]
			}
		}
		for i := 0; i < c.n; i++ {
			// Reset local stores
			w := c.Workers[i]
			x := make([]*OneStat, 0)
			sh := StatsHeap(x)
			w.local_store.candidates = &Candidates{make(map[Key]*OneStat), &sh}
		}
		// Reset global store
		x := make([]*OneStat, 0)
		sh := StatsHeap(x)
		s.cand = &Candidates{make(map[Key]*OneStat), &sh}
	}
	end := time.Since(start2)
	Time_in_IE1 += end

	for i := 0; i < c.n; i++ {
		c.wgo[i] <- true
		//dlog.Printf("Sent go to %v for %v\n", i, c.epochTID)
	}
	end = time.Since(start)
	Time_in_IE += end
}

func (c *Coordinator) Finish() {
	dlog.Printf("Coordinator finishing\n")
	x := make(chan bool)
	c.Done <- x
	<-x
}

func (c *Coordinator) Process() {
	tm := time.NewTicker(time.Duration(BUMP_EPOCH_MS) * time.Millisecond).C
	for {
		select {
		case x := <-c.Done:
			for i := 0; i < c.n; i++ {
				txn := Query{W: make(chan *Result)}
				c.Workers[i].done <- txn
				<-txn.W
				dlog.Printf("Worker %v finished\n", i)
			}
			x <- true
			return
		case <-tm:
			if *SysType == DOPPEL {
				c.IncrementEpoch()
			}
		case <-c.Accelerate:
			if *SysType == DOPPEL {
				dlog.Printf("Accelerating\n")
				c.IncrementEpoch()
			}
		}
	}
}
<commit_msg>fmt->dlog<commit_after>package ddtxn

import (
	"container/heap"
	"ddtxn/dlog"
	"sync/atomic"
	"time"
	"unsafe"
)

const (
	BUMP_EPOCH_MS = 80
	EPOCH_INCR    = 1 << 32
	TXID_MASK     = 0x00000000ffffffff
	CLEAR_TID     = 0xffffffff00000000
)

type Coordinator struct {
	n        int
	Workers  []*Worker
	epochTID TID // Global TID, atomically incremented and read

	// Notify workers
	wsafe  []chan bool
	wepoch []chan bool
	wgo    []chan bool
	wdone  []chan bool

	Done       chan chan bool
	Accelerate chan bool
}

func NewCoordinator(n int, s *Store) *Coordinator {
	c := &Coordinator{
		n:          n,
		Workers:    make([]*Worker, n),
		epochTID:   EPOCH_INCR,
		wepoch:     make([]chan bool, n),
		wsafe:      make([]chan bool, n),
		wgo:        make([]chan bool, n),
		wdone:      make([]chan bool, n),
		Done:       make(chan chan bool),
		Accelerate: make(chan bool),
	}
	for i := 0; i < n; i++ {
		c.wepoch[i] = make(chan bool)
		c.wsafe[i] = make(chan bool)
		c.wgo[i] = make(chan bool)
		c.wdone[i] = make(chan bool)
		c.Workers[i] = NewWorker(i, s, c)
	}
	dlog.Printf("[coordinator] %v workers\n", n)
	go c.Process()
	return c
}

var NextEpoch int64

func (c *Coordinator) NextGlobalTID() TID {
	NextEpoch++
	x := atomic.AddUint64((*uint64)(unsafe.Pointer(&c.epochTID)), EPOCH_INCR)
	return TID(x)
}

func (c *Coordinator) GetEpoch() TID {
	x := atomic.LoadUint64((*uint64)(unsafe.Pointer(&c.epochTID)))
	return TID(x)
}

var RMoved int64
var WMoved int64
var Time_in_IE time.Duration
var Time_in_IE1 time.Duration

func (c *Coordinator) IncrementEpoch() {
	start := time.Now()
	c.NextGlobalTID()

	// Wait for everyone to merge the previous epoch
	for i := 0; i < c.n; i++ {
		<-c.wepoch[i]
		//dlog.Printf("%v merged for %v\n", i, c.epochTID)
	}

	// All merged.  The previous epoch is now safe; tell everyone to
	// do their reads.
	for i := 0; i < c.n; i++ {
		c.wsafe[i] <- true
	}
	for i := 0; i < c.n; i++ {
		<-c.wdone[i]
		//dlog.Printf("Got done from %v for %v\n", i, c.epochTID)
	}

	start2 := time.Now()
	// Reads done!  Check stats
	s := c.Workers[0].store
	if c.epochTID%(10*EPOCH_INCR) == 0 {
		for i := 0; i < c.n; i++ {
			w := c.Workers[i]
			s.cand.Merge(w.local_store.candidates)
		}
		xx := len(*s.cand.h)
		dlog.Printf("Number of potential keys: %v; keys %v\n", xx, *s.cand.h)
		for i := 0; i < xx; i++ {
			o := heap.Pop(s.cand.h).(*OneStat)
			x, y := UndoCKey(o.k)
			dlog.Printf("%v Considering key %v %v; ratio %v\n", i, x, y, o.ratio())
			br, _ := s.getKey(o.k)
			if !br.dd {
				br.dd = true
				WMoved += 1
				dlog.Printf("Moved %v %v to split %v\n", x, y, o.ratio())
				s.dd = append(s.dd, o.k)
			} else {
				dlog.Printf("No need to Move %v %v to split; already dd\n", x, y)
			}
		}
		for i := 0; i < len(s.dd); i++ {
			o, ok := s.cand.m[s.dd[i]]
			if !ok {
				br, _ := s.getKey(s.dd[i])
				x, y := UndoCKey(br.key)
				dlog.Printf("Key %v %v was split but now is not in store candidates\n", x, y)
				continue
			}
			if o.ratio() < (*WRRatio)/2 {
				br, _ := s.getKey(s.dd[i])
				br.dd = false
				RMoved += 1
				x, y := UndoCKey(o.k)
				dlog.Printf("Moved %v %v from split ratio %v\n", x, y, o.ratio())
				s.dd[i], s.dd = s.dd[len(s.dd)-1], s.dd[:len(s.dd)-1]
			}
		}
		for i := 0; i < c.n; i++ {
			// Reset local stores
			w := c.Workers[i]
			x := make([]*OneStat, 0)
			sh := StatsHeap(x)
			w.local_store.candidates = &Candidates{make(map[Key]*OneStat), &sh}
		}
		// Reset global store
		x := make([]*OneStat, 0)
		sh := StatsHeap(x)
		s.cand = &Candidates{make(map[Key]*OneStat), &sh}
	}
	end := time.Since(start2)
	Time_in_IE1 += end

	for i := 0; i < c.n; i++ {
		c.wgo[i] <- true
		//dlog.Printf("Sent go to %v for %v\n", i, c.epochTID)
	}
	end = time.Since(start)
	Time_in_IE += end
}

func (c *Coordinator) Finish() {
	dlog.Printf("Coordinator finishing\n")
	x := make(chan bool)
	c.Done <- x
	<-x
}

func (c *Coordinator) Process() {
	tm := time.NewTicker(time.Duration(BUMP_EPOCH_MS) * time.Millisecond).C
	for {
		select {
		case x := <-c.Done:
			for i := 0; i < c.n; i++ {
				txn := Query{W: make(chan *Result)}
				c.Workers[i].done <- txn
				<-txn.W
				dlog.Printf("Worker %v finished\n", i)
			}
			x <- true
			return
		case <-tm:
			if *SysType == DOPPEL {
				c.IncrementEpoch()
			}
		case <-c.Accelerate:
			if *SysType == DOPPEL {
				dlog.Printf("Accelerating\n")
				c.IncrementEpoch()
			}
		}
	}
}
<|endoftext|>


<commit_before>package wikiparse

import (
	"math"
	"strings"
	"testing"
)

type testinput struct {
	input string
	lat   float64
	lon   float64
	err   string
}

var testdata = []testinput{
	testinput{
		"{{coord|61.1631|-149.9721|type:landmark_globe:earth_region:US-AK_scale:150000_source:gnis|name=Kulis Air National Guard Base}}",
		61.1631,
		-149.9721,
		"",
	},
	testinput{
		"{{coord|29.5734571|N|2.3730469|E|scale:10000000|format=dms|display=title}}",
		29.5734571,
		2.3730469,
		"",
	},
	testinput{
		"{{coord|27|59|16|N|86|56|40|E}}",
		27.98777777,
		86.94444444,
		"",
	},
	testinput{
		"{{coord|27|59|16|S|86|56|40|E}}",
		-27.98777777,
		86.94444444,
		"",
	},
	testinput{
		"{{coord|27|59|16|N|86|56|40|W}}",
		27.98777777,
		-86.94444444,
		"",
	},
	testinput{
		"{{coord|27|59|16|S|86|56|40|W}}",
		-27.98777777,
		-86.94444444,
		"",
	},
	testinput{
		"{{Coord|display=title|45|N|114|W|region:US-ID_type:adm1st_scale:3000000}}",
		45,
		-114,
		"",
	},
	testinput{
		"{{Coord|42||N|82||W|}}",
		42,
		-82,
		"",
	},
	testinput{
		"{{Coord|display=title|41.762736| -72.674286}}",
		41.762736,
		-72.674286,
		"",
	},
	testinput{
		"North Maple in Russell ({{coord|38.895352|-98.861034}}) and it remained his " +
			"official residence throughout his political career." +
			"<ref>{{cite news| url=http://www.time.com/}}",
		38.895352,
		-98.861034,
		"",
	},
	testinput{
		"{{coord|97|59|16|S|86|56|40|W|invalid lat}}",
		-97.98777777,
		-86.94444444,
		"Invalid latitude: -97.98777",
	},
	testinput{
		"{{coord|27|59|16|S|186|56|40|W|invalid long}}",
		-27.98777777,
		-186.94444444,
		"Invalid longitude: -186.9444",
	},
	testinput{
		"<nowiki>{{coord|27|59|16|N|86|56|40|E}}</nowiki>",
		0,
		0,
		"No coord data found.",
	},
	testinput{
		`<nowiki>
{{coord|27|59|16|N|86|56|40|E}}
</nowiki>`,
		0,
		0,
		"No coord data found.",
	},
	testinput{
		"<!-- {{coord|27|59|16|N|86|56|40|E}} -->",
		0,
		0,
		"No coord data found.",
	},
	testinput{
		`<!--
{{coord|27|59|16|N|86|56|40|E}}
-->`,
		0,
		0,
		"No coord data found.",
	},
}

func assertEpsilon(t *testing.T, input, field string, expected, got float64) {
	if math.Abs(got-expected) > 0.00001 {
		t.Fatalf("Expected %v for %v of %v, got %v",
			expected, field, input, got)
	}
}

func testOne(t *testing.T, ti testinput, input string) {
	coord, err := ParseCoords(input)
	switch {
	case err != nil && ti.err == "":
		t.Fatalf("Unexpected error on %v, got %v, wanted %q", input, err, ti.err)
	case err != nil && strings.HasPrefix(err.Error(), ti.err):
		// ok
	case err == nil && ti.err == "":
		// ok
	case err == nil && ti.err != "":
		t.Fatalf("Expected error %q on %v", ti.err, input)
	default:
		t.Fatalf("Wanted %v,%v with error %v, got %#v with error %v",
			ti.lat, ti.lon, ti.err, coord, err)
	}
	t.Logf("Parsed %#v with %v", coord, err)
	assertEpsilon(t, input, "lon", ti.lon, coord.Lon)
	assertEpsilon(t, input, "lat", ti.lat, coord.Lat)
	t.Logf("Results for %s:  %#v", input, coord)
}

func TestCoordSimple(t *testing.T) {
	for _, ti := range testdata {
		testOne(t, ti, ti.input)
	}
}

func TestCoordWithGarbage(t *testing.T) {
	for _, ti := range testdata {
		input := " some random garbage " + ti.input + " and stuff"
		testOne(t, ti, input)
	}
}

func TestCoordMultiline(t *testing.T) {
	for _, ti := range testdata {
		input := " some random garbage\n\nnewlines\n" + ti.input + " and stuff"
		testOne(t, ti, input)
	}
}
<commit_msg>Mark a couple tests as parallelizable.<commit_after>package wikiparse

import (
	"math"
	"strings"
	"testing"
)

type testinput struct {
	input string
	lat   float64
	lon   float64
	err   string
}

var testdata = []testinput{
	testinput{
		"{{coord|61.1631|-149.9721|type:landmark_globe:earth_region:US-AK_scale:150000_source:gnis|name=Kulis Air National Guard Base}}",
		61.1631,
		-149.9721,
		"",
	},
	testinput{
		"{{coord|29.5734571|N|2.3730469|E|scale:10000000|format=dms|display=title}}",
		29.5734571,
		2.3730469,
		"",
	},
	testinput{
		"{{coord|27|59|16|N|86|56|40|E}}",
		27.98777777,
		86.94444444,
		"",
	},
	testinput{
		"{{coord|27|59|16|S|86|56|40|E}}",
		-27.98777777,
		86.94444444,
		"",
	},
	testinput{
		"{{coord|27|59|16|N|86|56|40|W}}",
		27.98777777,
		-86.94444444,
		"",
	},
	testinput{
		"{{coord|27|59|16|S|86|56|40|W}}",
		-27.98777777,
		-86.94444444,
		"",
	},
	testinput{
		"{{Coord|display=title|45|N|114|W|region:US-ID_type:adm1st_scale:3000000}}",
		45,
		-114,
		"",
	},
	testinput{
		"{{Coord|42||N|82||W|}}",
		42,
		-82,
		"",
	},
	testinput{
		"{{Coord|display=title|41.762736| -72.674286}}",
		41.762736,
		-72.674286,
		"",
	},
	testinput{
		"North Maple in Russell ({{coord|38.895352|-98.861034}}) and it remained his " +
			"official residence throughout his political career." +
			"<ref>{{cite news| url=http://www.time.com/}}",
		38.895352,
		-98.861034,
		"",
	},
	testinput{
		"{{coord|97|59|16|S|86|56|40|W|invalid lat}}",
		-97.98777777,
		-86.94444444,
		"Invalid latitude: -97.98777",
	},
	testinput{
		"{{coord|27|59|16|S|186|56|40|W|invalid long}}",
		-27.98777777,
		-186.94444444,
		"Invalid longitude: -186.9444",
	},
	testinput{
		"<nowiki>{{coord|27|59|16|N|86|56|40|E}}</nowiki>",
		0,
		0,
		"No coord data found.",
	},
	testinput{
		`<nowiki>
{{coord|27|59|16|N|86|56|40|E}}
</nowiki>`,
		0,
		0,
		"No coord data found.",
	},
	testinput{
		"<!-- {{coord|27|59|16|N|86|56|40|E}} -->",
		0,
		0,
		"No coord data found.",
	},
	testinput{
		`<!--
{{coord|27|59|16|N|86|56|40|E}}
-->`,
		0,
		0,
		"No coord data found.",
	},
}

func assertEpsilon(t *testing.T, input, field string, expected, got float64) {
	if math.Abs(got-expected) > 0.00001 {
		t.Fatalf("Expected %v for %v of %v, got %v",
			expected, field, input, got)
	}
}

func testOne(t *testing.T, ti testinput, input string) {
	coord, err := ParseCoords(input)
	switch {
	case err != nil && ti.err == "":
		t.Fatalf("Unexpected error on %v, got %v, wanted %q", input, err, ti.err)
	case err != nil && strings.HasPrefix(err.Error(), ti.err):
		// ok
	case err == nil && ti.err == "":
		// ok
	case err == nil && ti.err != "":
		t.Fatalf("Expected error %q on %v", ti.err, input)
	default:
		t.Fatalf("Wanted %v,%v with error %v, got %#v with error %v",
			ti.lat, ti.lon, ti.err, coord, err)
	}
	t.Logf("Parsed %#v with %v", coord, err)
	assertEpsilon(t, input, "lon", ti.lon, coord.Lon)
	assertEpsilon(t, input, "lat", ti.lat, coord.Lat)
	t.Logf("Results for %s:  %#v", input, coord)
}

func TestCoordSimple(t *testing.T) {
	t.Parallel()
	for _, ti := range testdata {
		testOne(t, ti, ti.input)
	}
}

func TestCoordWithGarbage(t *testing.T) {
	t.Parallel()
	for _, ti := range testdata {
		input := " some random garbage " + ti.input + " and stuff"
		testOne(t, ti, input)
	}
}

func TestCoordMultiline(t *testing.T) {
	t.Parallel()
	for _, ti := range testdata {
		input := " some random garbage\n\nnewlines\n" + ti.input + " and stuff"
		testOne(t, ti, input)
	}
}
<|endoftext|>


<commit_before>package core

import (
	"sync"
	"time"

	"golang.org/x/net/context"

	"chain/core/asset"
	"chain/cos/bc"
	"chain/crypto/ed25519/hd25519"
	"chain/errors"
	"chain/metrics"
	"chain/net/http/httpjson"
)

type assetResponse struct {
	ID         bc.AssetID             `json:"id"`
	XPubs      []*hd25519.XPub        `json:"xpubs"`
	Quorum     int                    `json:"quorum"`
	Definition map[string]interface{} `json:"definition"`
	Tags       map[string]interface{} `json:"tags"`
}

// POST /list-assets
func (a *api) listAssets(ctx context.Context, query requestQuery) (page, error) {
	limit := defAccountPageSize

	assets, cursor, err := asset.List(ctx, query.Cursor, limit)
	if err != nil {
		return page{}, err
	}

	var items []assetResponse
	for _, asset := range assets {
		items = append(items, assetResponse{
			ID:         asset.AssetID,
			XPubs:      asset.Signer.XPubs,
			Quorum:     asset.Signer.Quorum,
			Definition: asset.Definition,
		})
	}

	query.Cursor = cursor
	return page{
		Items:    httpjson.Array(items),
		LastPage: len(assets) < limit,
		Query:    query,
	}, nil
}

// POST /update-asset
func setAssetTags(ctx context.Context, in struct {
	AssetID string `json:"asset_id"`
	Tags    map[string]interface{}
}) (interface{}, error) {
	var decodedAssetID bc.AssetID
	err := decodedAssetID.UnmarshalText([]byte(in.AssetID))
	if err != nil {
		return nil, errors.WithDetailf(httpjson.ErrBadRequest, "%q is an invalid asset ID", in.AssetID)
	}
	return asset.SetTags(ctx, decodedAssetID, in.Tags)
}

type assetResponseOrError struct {
	*assetResponse
	*detailedError
}

// POST /create-asset
func (a *api) createAsset(ctx context.Context, ins []struct {
	XPubs      []string
	Quorum     int
	Definition map[string]interface{}
	Tags       map[string]interface{}

	// ClientToken is the application's unique token for the asset. Every asset
	// should have a unique client token. The client token is used to ensure
	// idempotency of create asset requests. Duplicate create asset requests
	// with the same client_token will only create one asset.
	ClientToken *string `json:"client_token"`
}) ([]assetResponseOrError, error) {
	defer metrics.RecordElapsed(time.Now())

	genesis, err := a.store.GetBlock(ctx, 1)
	if err != nil {
		return nil, err
	}

	responses := make([]assetResponseOrError, len(ins))
	var wg sync.WaitGroup
	wg.Add(len(responses))

	for i := 0; i < len(responses); i++ {
		go func(i int) {
			defer wg.Done()
			asset, err := asset.Define(
				ctx,
				ins[i].XPubs,
				ins[i].Quorum,
				ins[i].Definition,
				genesis.Hash(),
				ins[i].Tags,
				ins[i].ClientToken,
			)
			if err != nil {
				logHTTPError(ctx, err)
				res, _ := errInfo(err)
				responses[i] = assetResponseOrError{detailedError: &res}
			} else {
				responses[i] = assetResponseOrError{
					assetResponse: &assetResponse{
						ID:         asset.AssetID,
						XPubs:      asset.Signer.XPubs,
						Quorum:     asset.Signer.Quorum,
						Definition: asset.Definition,
						Tags:       asset.Tags,
					},
				}
			}
		}(i)
	}

	wg.Wait()
	return responses, nil
}

// DELETE /v3/assets/:assetID
// Idempotent
func archiveAsset(ctx context.Context, assetID string) error {
	var decodedAssetID bc.AssetID
	err := decodedAssetID.UnmarshalText([]byte(assetID))
	if err != nil {
		return errors.WithDetailf(httpjson.ErrBadRequest, "%q is an invalid asset ID", assetID)
	}
	return asset.Archive(ctx, decodedAssetID)
}
<commit_msg>core/asset: make asset response match spec<commit_after>package core

import (
	"sync"
	"time"

	"golang.org/x/net/context"

	"chain/core/asset"
	"chain/cos/bc"
	"chain/errors"
	"chain/metrics"
	"chain/net/http/httpjson"
)

type assetResponse struct {
	ID              bc.AssetID             `json:"id"`
	IssuanceProgram []byte                 `json:"issuance_program"`
	Definition      map[string]interface{} `json:"definition"`
	Tags            map[string]interface{} `json:"tags"`
}

// POST /list-assets
func (a *api) listAssets(ctx context.Context, query requestQuery) (page, error) {
	limit := defAccountPageSize

	assets, cursor, err := asset.List(ctx, query.Cursor, limit)
	if err != nil {
		return page{}, err
	}

	var items []assetResponse
	for _, asset := range assets {
		items = append(items, assetResponse{
			ID:              asset.AssetID,
			IssuanceProgram: asset.IssuanceProgram,
			Definition:      asset.Definition,
			Tags:            asset.Tags,
		})
	}

	query.Cursor = cursor
	return page{
		Items:    httpjson.Array(items),
		LastPage: len(assets) < limit,
		Query:    query,
	}, nil
}

// POST /update-asset
func setAssetTags(ctx context.Context, in struct {
	AssetID string `json:"asset_id"`
	Tags    map[string]interface{}
}) (interface{}, error) {
	var decodedAssetID bc.AssetID
	err := decodedAssetID.UnmarshalText([]byte(in.AssetID))
	if err != nil {
		return nil, errors.WithDetailf(httpjson.ErrBadRequest, "%q is an invalid asset ID", in.AssetID)
	}
	return asset.SetTags(ctx, decodedAssetID, in.Tags)
}

type assetResponseOrError struct {
	*assetResponse
	*detailedError
}

// POST /create-asset
func (a *api) createAsset(ctx context.Context, ins []struct {
	XPubs      []string
	Quorum     int
	Definition map[string]interface{}
	Tags       map[string]interface{}

	// ClientToken is the application's unique token for the asset. Every asset
	// should have a unique client token. The client token is used to ensure
	// idempotency of create asset requests. Duplicate create asset requests
	// with the same client_token will only create one asset.
	ClientToken *string `json:"client_token"`
}) ([]assetResponseOrError, error) {
	defer metrics.RecordElapsed(time.Now())

	genesis, err := a.store.GetBlock(ctx, 1)
	if err != nil {
		return nil, err
	}

	responses := make([]assetResponseOrError, len(ins))
	var wg sync.WaitGroup
	wg.Add(len(responses))

	for i := 0; i < len(responses); i++ {
		go func(i int) {
			defer wg.Done()
			asset, err := asset.Define(
				ctx,
				ins[i].XPubs,
				ins[i].Quorum,
				ins[i].Definition,
				genesis.Hash(),
				ins[i].Tags,
				ins[i].ClientToken,
			)
			if err != nil {
				logHTTPError(ctx, err)
				res, _ := errInfo(err)
				responses[i] = assetResponseOrError{detailedError: &res}
			} else {
				responses[i] = assetResponseOrError{
					assetResponse: &assetResponse{
						ID:              asset.AssetID,
						IssuanceProgram: asset.IssuanceProgram,
						Definition:      asset.Definition,
						Tags:            asset.Tags,
					},
				}
			}
		}(i)
	}

	wg.Wait()
	return responses, nil
}

// DELETE /v3/assets/:assetID
// Idempotent
func archiveAsset(ctx context.Context, assetID string) error {
	var decodedAssetID bc.AssetID
	err := decodedAssetID.UnmarshalText([]byte(assetID))
	if err != nil {
		return errors.WithDetailf(httpjson.ErrBadRequest, "%q is an invalid asset ID", assetID)
	}
	return asset.Archive(ctx, decodedAssetID)
}
<|endoftext|>


<commit_before>package command

import (
	"strings"
	"testing"
	"time"

	"github.com/mitchellh/cli"
)

func TestOperator_Autopilot_SetConfig_Implements(t *testing.T) {
	t.Parallel()
	var _ cli.Command = &OperatorRaftListCommand{}
}

func TestOperatorAutopilotSetConfigCommmand(t *testing.T) {
	t.Parallel()
	s, _, addr := testServer(t, false, nil)
	defer s.Shutdown()

	ui := new(cli.MockUi)
	c := &OperatorAutopilotSetCommand{Meta: Meta{Ui: ui}}
	args := []string{
		"-address=" + addr,
		"-cleanup-dead-servers=false",
		"-max-trailing-logs=99",
		"-last-contact-threshold=123ms",
		"-server-stabilization-time=123ms",
	}

	code := c.Run(args)
	if code != 0 {
		t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
	}
	output := strings.TrimSpace(ui.OutputWriter.String())
	if !strings.Contains(output, "Configuration updated") {
		t.Fatalf("bad: %s", output)
	}

	client, err := c.Client()
	if err != nil {
		t.Fatal(err)
	}

	conf, _, err := client.Operator().AutopilotGetConfiguration(nil)
	if err != nil {
		t.Fatal(err)
	}

	if conf.CleanupDeadServers {
		t.Fatalf("bad: %#v", conf)
	}
	if conf.MaxTrailingLogs != 99 {
		t.Fatalf("bad: %#v", conf)
	}
	if conf.LastContactThreshold != 123*time.Millisecond {
		t.Fatalf("bad: %#v", conf)
	}
	if conf.ServerStabilizationTime != 123*time.Millisecond {
		t.Fatalf("bad: %#v", conf)
	}
}
<commit_msg>spelling: command<commit_after>package command

import (
	"strings"
	"testing"
	"time"

	"github.com/mitchellh/cli"
)

func TestOperator_Autopilot_SetConfig_Implements(t *testing.T) {
	t.Parallel()
	var _ cli.Command = &OperatorRaftListCommand{}
}

func TestOperatorAutopilotSetConfigCommand(t *testing.T) {
	t.Parallel()
	s, _, addr := testServer(t, false, nil)
	defer s.Shutdown()

	ui := new(cli.MockUi)
	c := &OperatorAutopilotSetCommand{Meta: Meta{Ui: ui}}
	args := []string{
		"-address=" + addr,
		"-cleanup-dead-servers=false",
		"-max-trailing-logs=99",
		"-last-contact-threshold=123ms",
		"-server-stabilization-time=123ms",
	}

	code := c.Run(args)
	if code != 0 {
		t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
	}
	output := strings.TrimSpace(ui.OutputWriter.String())
	if !strings.Contains(output, "Configuration updated") {
		t.Fatalf("bad: %s", output)
	}

	client, err := c.Client()
	if err != nil {
		t.Fatal(err)
	}

	conf, _, err := client.Operator().AutopilotGetConfiguration(nil)
	if err != nil {
		t.Fatal(err)
	}

	if conf.CleanupDeadServers {
		t.Fatalf("bad: %#v", conf)
	}
	if conf.MaxTrailingLogs != 99 {
		t.Fatalf("bad: %#v", conf)
	}
	if conf.LastContactThreshold != 123*time.Millisecond {
		t.Fatalf("bad: %#v", conf)
	}
	if conf.ServerStabilizationTime != 123*time.Millisecond {
		t.Fatalf("bad: %#v", conf)
	}
}
<|endoftext|>


<commit_before>package v7

import (
	"fmt"

	"code.cloudfoundry.org/cli/actor/sharedaction"
	"code.cloudfoundry.org/cli/actor/v7action"
	"code.cloudfoundry.org/cli/command"
	"code.cloudfoundry.org/cli/command/flag"
	"code.cloudfoundry.org/cli/command/v7/shared"
	"code.cloudfoundry.org/cli/util/ui"
)

//go:generate counterfeiter . GetHealthCheckActor

type GetHealthCheckActor interface {
	CloudControllerAPIVersion() string
	GetApplicationProcessHealthChecksByNameAndSpace(appName string, spaceGUID string) ([]v7action.ProcessHealthCheck, v7action.Warnings, error)
}

type GetHealthCheckCommand struct {
	RequiredArgs flag.AppName `positional-args:"yes"`
	usage        interface{}  `usage:"CF_NAME get-health-check APP_NAME"`

	UI          command.UI
	Config      command.Config
	SharedActor command.SharedActor
	Actor       GetHealthCheckActor
}

func (cmd *GetHealthCheckCommand) Setup(config command.Config, ui command.UI) error {
	cmd.UI = ui
	cmd.Config = config
	cmd.SharedActor = sharedaction.NewActor(config)

	ccClient, _, err := shared.NewClients(config, ui, true, "")
	if err != nil {
		return err
	}
	cmd.Actor = v7action.NewActor(ccClient, config, nil, nil)

	return nil
}

func (cmd GetHealthCheckCommand) Execute(args []string) error {
	err := cmd.SharedActor.CheckTarget(true, true)
	if err != nil {
		return err
	}

	user, err := cmd.Config.CurrentUser()
	if err != nil {
		return err
	}

	cmd.UI.DisplayTextWithFlavor("Getting health check type for app {{.AppName}} in org {{.OrgName}} / space {{.SpaceName}} as {{.Username}}...", map[string]interface{}{
		"AppName":   cmd.RequiredArgs.AppName,
		"OrgName":   cmd.Config.TargetedOrganization().Name,
		"SpaceName": cmd.Config.TargetedSpace().Name,
		"Username":  user.Name,
	})
	cmd.UI.DisplayNewline()

	processHealthChecks, warnings, err := cmd.Actor.GetApplicationProcessHealthChecksByNameAndSpace(cmd.RequiredArgs.AppName, cmd.Config.TargetedSpace().GUID)
	cmd.UI.DisplayWarnings(warnings)
	if err != nil {
		return err
	}

	if len(processHealthChecks) == 0 {
		cmd.UI.DisplayNewline()
		cmd.UI.DisplayText("App has no processes")
		return nil
	}

	table := [][]string{
		{
			cmd.UI.TranslateText("process"),
			cmd.UI.TranslateText("health check"),
			cmd.UI.TranslateText("endpoint (for http)"),
			cmd.UI.TranslateText("invocation timeout"),
		},
	}

	for _, healthCheck := range processHealthChecks {
		invocationTimeout := healthCheck.InvocationTimeout
		if invocationTimeout == 0 {
			invocationTimeout = 1
		}

		table = append(table, []string{
			healthCheck.ProcessType,
			healthCheck.HealthCheckType,
			healthCheck.Endpoint,
			fmt.Sprint(invocationTimeout),
		})
	}

	cmd.UI.DisplayTableWithHeader("", table, ui.DefaultTableSpacePadding)

	return nil
}
<commit_msg>adjust spacing between flavor text and rest of display<commit_after>package v7

import (
	"fmt"

	"code.cloudfoundry.org/cli/actor/sharedaction"
	"code.cloudfoundry.org/cli/actor/v7action"
	"code.cloudfoundry.org/cli/command"
	"code.cloudfoundry.org/cli/command/flag"
	"code.cloudfoundry.org/cli/command/v7/shared"
	"code.cloudfoundry.org/cli/util/ui"
)

//go:generate counterfeiter . GetHealthCheckActor

type GetHealthCheckActor interface {
	CloudControllerAPIVersion() string
	GetApplicationProcessHealthChecksByNameAndSpace(appName string, spaceGUID string) ([]v7action.ProcessHealthCheck, v7action.Warnings, error)
}

type GetHealthCheckCommand struct {
	RequiredArgs flag.AppName `positional-args:"yes"`
	usage        interface{}  `usage:"CF_NAME get-health-check APP_NAME"`

	UI          command.UI
	Config      command.Config
	SharedActor command.SharedActor
	Actor       GetHealthCheckActor
}

func (cmd *GetHealthCheckCommand) Setup(config command.Config, ui command.UI) error {
	cmd.UI = ui
	cmd.Config = config
	cmd.SharedActor = sharedaction.NewActor(config)

	ccClient, _, err := shared.NewClients(config, ui, true, "")
	if err != nil {
		return err
	}
	cmd.Actor = v7action.NewActor(ccClient, config, nil, nil)

	return nil
}

func (cmd GetHealthCheckCommand) Execute(args []string) error {
	err := cmd.SharedActor.CheckTarget(true, true)
	if err != nil {
		return err
	}

	user, err := cmd.Config.CurrentUser()
	if err != nil {
		return err
	}

	cmd.UI.DisplayTextWithFlavor("Getting health check type for app {{.AppName}} in org {{.OrgName}} / space {{.SpaceName}} as {{.Username}}...", map[string]interface{}{
		"AppName":   cmd.RequiredArgs.AppName,
		"OrgName":   cmd.Config.TargetedOrganization().Name,
		"SpaceName": cmd.Config.TargetedSpace().Name,
		"Username":  user.Name,
	})

	processHealthChecks, warnings, err := cmd.Actor.GetApplicationProcessHealthChecksByNameAndSpace(cmd.RequiredArgs.AppName, cmd.Config.TargetedSpace().GUID)
	cmd.UI.DisplayWarnings(warnings)
	if err != nil {
		return err
	}

	cmd.UI.DisplayNewline()

	if len(processHealthChecks) == 0 {
		cmd.UI.DisplayText("App has no processes")
		return nil
	}

	return cmd.DisplayProcessTable(processHealthChecks)
}

func (cmd GetHealthCheckCommand) DisplayProcessTable(processHealthChecks []v7action.ProcessHealthCheck) error {
	table := [][]string{
		{
			cmd.UI.TranslateText("process"),
			cmd.UI.TranslateText("health check"),
			cmd.UI.TranslateText("endpoint (for http)"),
			cmd.UI.TranslateText("invocation timeout"),
		},
	}

	for _, healthCheck := range processHealthChecks {
		invocationTimeout := healthCheck.InvocationTimeout
		if invocationTimeout == 0 {
			invocationTimeout = 1
		}

		table = append(table, []string{
			healthCheck.ProcessType,
			healthCheck.HealthCheckType,
			healthCheck.Endpoint,
			fmt.Sprint(invocationTimeout),
		})
	}

	cmd.UI.DisplayTableWithHeader("", table, ui.DefaultTableSpacePadding)

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"math"
	"sync"

	"log"

	"github.com/NeilVallon/blstr"
)

type Node struct {
	id  int
	hub *blstr.ByteHub
}

type Layer []Node
type Tree []Layer

//      0
//    /   \
//   1     2
//  / \   / \
// *   4 5   *
//
// main builds a tree of hubs and atempts to send a message between
// the two furthest leaf nodes.
func main() {
	tree := BuildTree(4, 4)

	// Get bottom layer of tree
	edge := tree[len(tree)-1]

	// Find far left and far right nodes
	left, right := edge[0], edge[len(edge)-1]
	log.Printf("sending message from node %d to %d", right.id, left.id)

	// Subscribe to left
	ch := make(chan []byte, 1)
	left.hub.Subscribe(-1, ch)

	// Send on right
	right.hub.Flood(-1, []byte("Hello, World!"))

	// Wait for propogation and print
	msg := <-ch
	log.Printf("%s\n", msg)
}

func BuildTree(layers, fanout int) Tree {
	// Make a single layer to hold all nodes of the final tree
	accum := make(Layer, totalNodes(layers, fanout))

	// Set root 0 Node
	accum[0] = Node{hub: blstr.New()}

	var wg sync.WaitGroup
	defer wg.Wait()

	buildTree(accum[0], layers, fanout, accum, &wg)

	// Form final tree by slicing out layers from the accumulator
	tree := make(Tree, layers)
	for i := 1; i <= layers; i++ {
		s, e := totalNodes(i-1, fanout), totalNodes(i, fanout)
		tree[i-1] = accum[s:e]
	}

	return tree
}

func totalNodes(layers, fanout int) int {
	return int(math.Pow(float64(fanout), float64(layers))-1) / (fanout - 1)
}

func buildTree(p Node, layers, fanout int, accum Layer, wg *sync.WaitGroup) {
	if layers == 1 {
		accum[p.id] = p
		return
	}

	for i := 0; i < fanout; i++ {
		n := Node{
			id:  p.id*fanout + i + 1,
			hub: blstr.New(),
		}

		// Forward messages between parent and new node
		wg.Add(2)
		go connect(&p, &n, wg)
		go connect(&n, &p, wg)

		accum[n.id] = n

		// make subtree bellow new node
		buildTree(n, layers-1, fanout, accum, wg)
	}
}

func connect(n1, n2 *Node, wg *sync.WaitGroup) {
	ch := make(chan []byte, 1)
	n2.hub.Subscribe(n1.id, ch)

	wg.Done()
	for msg := range ch {
		log.Printf("node %d forwarding to node %d", n2.id, n1.id)
		n1.hub.Flood(n2.id, msg)
	}
}
<commit_msg>Log timings<commit_after>package main

import (
	"math"
	"sync"
	"time"

	"log"

	"github.com/NeilVallon/blstr"
)

type Node struct {
	id  int
	hub *blstr.ByteHub
}

type Layer []Node
type Tree []Layer

//      0
//    /   \
//   1     2
//  / \   / \
// *   4 5   *
//
// main builds a tree of hubs and atempts to send a message between
// the two furthest leaf nodes.
func main() {
	t1 := time.Now()
	tree := BuildTree(4, 4)
	log.Println("tree Generated in", time.Now().Sub(t1))

	// Get bottom layer of tree
	edge := tree[len(tree)-1]

	// Find far left and far right nodes
	left, right := edge[0], edge[len(edge)-1]
	log.Printf("sending message from node %d to %d", right.id, left.id)

	// Subscribe to left
	ch := make(chan []byte, 1)
	left.hub.Subscribe(-1, ch)

	t2 := time.Now()

	// Send on right
	right.hub.Flood(-1, []byte("Hello, World!"))

	// Wait for propogation and print
	msg := <-ch
	log.Printf("%q propagated in %s\n", msg, time.Now().Sub(t2))
}

func BuildTree(layers, fanout int) Tree {
	// Make a single layer to hold all nodes of the final tree
	accum := make(Layer, totalNodes(layers, fanout))

	// Set root 0 Node
	accum[0] = Node{hub: blstr.New()}

	var wg sync.WaitGroup
	defer wg.Wait()

	buildTree(accum[0], layers, fanout, accum, &wg)

	// Form final tree by slicing out layers from the accumulator
	tree := make(Tree, layers)
	for i := 1; i <= layers; i++ {
		s, e := totalNodes(i-1, fanout), totalNodes(i, fanout)
		tree[i-1] = accum[s:e]
	}

	return tree
}

func totalNodes(layers, fanout int) int {
	return int(math.Pow(float64(fanout), float64(layers))-1) / (fanout - 1)
}

func buildTree(p Node, layers, fanout int, accum Layer, wg *sync.WaitGroup) {
	if layers == 1 {
		accum[p.id] = p
		return
	}

	for i := 0; i < fanout; i++ {
		n := Node{
			id:  p.id*fanout + i + 1,
			hub: blstr.New(),
		}

		// Forward messages between parent and new node
		wg.Add(2)
		go connect(&p, &n, wg)
		go connect(&n, &p, wg)

		accum[n.id] = n

		// make subtree bellow new node
		buildTree(n, layers-1, fanout, accum, wg)
	}
}

func connect(n1, n2 *Node, wg *sync.WaitGroup) {
	ch := make(chan []byte, 1)
	n2.hub.Subscribe(n1.id, ch)

	wg.Done()
	for msg := range ch {
		log.Printf("node %d forwarding to node %d", n2.id, n1.id)
		n1.hub.Flood(n2.id, msg)
	}
}
<|endoftext|>


<commit_before>package bots

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"runtime/debug"
	"strings"
	"time"

	"github.com/DebtsTracker/translations/emoji"
	"github.com/julienschmidt/httprouter"
	"github.com/pkg/errors"
	"github.com/strongo/app"
	"github.com/strongo/gamp"
	"github.com/strongo/log"
	"context"
)

// WebhookDriver is doing initial request & final response processing.
// That includes logging, creating input messages in a general format, sending response.
type WebhookDriver interface {
	RegisterWebhookHandlers(httpRouter *httprouter.Router, pathPrefix string, webhookHandlers ...WebhookHandler)
	HandleWebhook(w http.ResponseWriter, r *http.Request, webhookHandler WebhookHandler)
}

// BotDriver keeps information about bots and map requests to appropriate handlers
type BotDriver struct {
	Analytics  AnalyticsSettings
	botHost    BotHost
	appContext BotAppContext
	//router          *WebhooksRouter
	panicTextFooter string
}

var _ WebhookDriver = (*BotDriver)(nil) // Ensure BotDriver is implementing interface WebhookDriver

// AnalyticsSettings keeps data for Google Analytics
type AnalyticsSettings struct {
	GaTrackingID string // TODO: Refactor to list of analytics providers
	Enabled      func(r *http.Request) bool
}

// NewBotDriver registers new bot driver (TODO: describe why we need it)
func NewBotDriver(gaSettings AnalyticsSettings, appContext BotAppContext, host BotHost, panicTextFooter string) WebhookDriver {
	if appContext.AppUserEntityKind() == "" {
		panic("appContext.AppUserEntityKind() is empty")
	}
	if host == nil {
		panic("BotHost == nil")
	}
	return BotDriver{
		Analytics:  gaSettings,
		appContext: appContext,
		botHost:    host,
		//router: router,
		panicTextFooter: panicTextFooter,
	}
}

// RegisterWebhookHandlers adds handlers to a bot driver
func (d BotDriver) RegisterWebhookHandlers(httpRouter *httprouter.Router, pathPrefix string, webhookHandlers ...WebhookHandler) {
	for _, webhookHandler := range webhookHandlers {
		webhookHandler.RegisterWebhookHandler(d, d.botHost, httpRouter, pathPrefix)
	}
}

// HandleWebhook takes and HTTP request and process it
func (d BotDriver) HandleWebhook(w http.ResponseWriter, r *http.Request, webhookHandler WebhookHandler) {
	started := time.Now()
	c := d.botHost.Context(r)
	//log.Debugf(c, "BotDriver.HandleWebhook()")
	if w == nil {
		panic("Parameter 'w http.ResponseWriter' is nil")
	}
	if r == nil {
		panic("Parameter 'r *http.Request' is nil")
	}
	if webhookHandler == nil {
		panic("Parameter 'webhookHandler WebhookHandler' is nil")
	}

	botContext, entriesWithInputs, err := webhookHandler.GetBotContextAndInputs(c, r)

	if d.invalidContextOrInputs(c, w, r, botContext, entriesWithInputs, err) {
		return
	}

	log.Debugf(c, "BotDriver.HandleWebhook() => botCode=%v, len(entriesWithInputs): %d", botContext.BotSettings.Code, len(entriesWithInputs))

	var (
		whc               WebhookContext // TODO: How do deal with Facebook multiple entries per request?
		measurementSender *gamp.BufferedClient
	)

	var sendStats bool
	{ // Initiate Google Analytics Measurement API client
		if d.Analytics.Enabled == nil {
			sendStats = botContext.BotSettings.Env == strongo.EnvProduction
			//log.Debugf(c, "d.AnalyticsSettings.Enabled == nil, botContext.BotSettings.Env: %v, sendStats: %v", strongo.EnvironmentNames[botContext.BotSettings.Env], sendStats)
		} else {
			sendStats = d.Analytics.Enabled(r)
			//log.Debugf(c, "d.AnalyticsSettings.Enabled != nil, sendStats: %v", sendStats)
		}
		if sendStats {
			botHost := botContext.BotHost
			measurementSender = gamp.NewBufferedClient("", botHost.GetHttpClient(c), nil)
		}
	}

	defer func() {
		log.Debugf(c, "driver.deferred(recover) - checking for panic & flush GA")
		if sendStats {
			measurementSender.Queue(gamp.NewTiming(time.Now().Sub(started)))
		}

		reportError := func(recovered interface{}) {
			messageText := fmt.Sprintf("Server error (panic): %v\n\n%v", recovered, d.panicTextFooter)
			log.Criticalf(c, "Panic recovered: %s\n%s", messageText, debug.Stack())

			if sendStats { // Zero if GA is disabled
				d.reportErrorToGA(whc, measurementSender, messageText)
			}

			if whc != nil {
				if chatID, err := whc.BotChatID(); err == nil && chatID != "" {
					if responder := whc.Responder(); responder != nil {
						if _, err := responder.SendMessage(c, whc.NewMessage(emoji.ERROR_ICON+" "+messageText), BotApiSendMessageOverResponse); err != nil {
							log.Errorf(c, errors.WithMessage(err, "failed to report error to user").Error())
						}
					}
				}
			}
		}

		if recovered := recover(); recovered != nil {
			reportError(recovered)
		} else if sendStats {
			if err = measurementSender.Flush(); err != nil {
				log.Warningf(c, "Failed to flush to GA: %v", err)
			} else {
				log.Debugf(c, "Sent to GA: %v items", measurementSender.QueueDepth())
			}
		}
	}()

	if err != nil {
		log.Errorf(c, "Failed to create new WebhookContext: %v", err)
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}

	botCoreStores := webhookHandler.CreateBotCoreStores(d.appContext, r)
	defer func() {
		if whc != nil { // TODO: How do deal with Facebook multiple entries per request?
			//log.Debugf(c, "Closing BotChatStore...")
			//chatEntity := whc.ChatEntity()
			//if chatEntity != nil && chatEntity.GetPreferredLanguage() == "" {
			//	chatEntity.SetPreferredLanguage(whc.Locale().Code5)
			//}
			if err := botCoreStores.BotChatStore.Close(c); err != nil {
				log.Errorf(c, "Failed to close BotChatStore: %v", err)
				var m MessageFromBot
				m.Text = emoji.ERROR_ICON + " ERROR: Service is temporary unavailable. Probably a global outage, status at https://status.cloud.google.com/"
				if _, err := whc.Responder().SendMessage(c, m, BotApiSendMessageOverHTTPS); err != nil {
					log.Errorf(c, "Failed to report outage: %v", err)
				}
			}
		}
	}()

	for _, entryWithInputs := range entriesWithInputs {
		for i, input := range entryWithInputs.Inputs {
			if input == nil {
				panic(fmt.Sprintf("entryWithInputs.Inputs[%d] == nil", i))
			}
			d.logInput(c, i, input)
			whc = webhookHandler.CreateWebhookContext(d.appContext, r, *botContext, input, botCoreStores, measurementSender)
			responder := webhookHandler.GetResponder(w, whc) // TODO: Move inside webhookHandler.CreateWebhookContext()?
			botContext.BotSettings.Router.Dispatch(responder, whc)
		}
	}
}

func (BotDriver) invalidContextOrInputs(c context.Context, w http.ResponseWriter, r *http.Request, botContext *BotContext, entriesWithInputs []EntryInputs, err error) bool {
	if err != nil {
		if _, ok := err.(ErrAuthFailed); ok {
			log.Warningf(c, "Auth failed: %v", err)
			http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
		} else if errors.Cause(err) == ErrNotImplemented {
			log.Debugf(c, err.Error())
			w.WriteHeader(http.StatusNoContent)
			//http.Error(w, "", http.StatusOK) // TODO: Decide how to handle it properly, return http.StatusNotImplemented?
		} else if _, ok := err.(*json.SyntaxError); ok {
			log.Debugf(c, errors.Wrap(err, "Request body is not valid JSON").Error())
			http.Error(w, err.Error(), http.StatusBadRequest)
		} else {
			log.Errorf(c, "Failed to call webhookHandler.GetBotContextAndInputs(router): %v", err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
		return true
	} else if botContext == nil {
		if entriesWithInputs == nil {
			log.Warningf(c, "botContext == nil, entriesWithInputs == nil")
		} else if len(entriesWithInputs) == 0 {
			log.Warningf(c, "botContext == nil, len(entriesWithInputs) == 0")
		} else {
			log.Errorf(c, "botContext == nil, len(entriesWithInputs) == %v", len(entriesWithInputs))
		}
		return true
	} else if entriesWithInputs == nil {
		log.Errorf(c, "entriesWithInputs == nil")
		return true
	}

	switch botContext.BotSettings.Env {
	case strongo.EnvLocal:
		if r.Host != "localhost" && !strings.HasSuffix(r.Host, ".ngrok.io") {
			log.Warningf(c, "whc.GetBotSettings().Mode == Local, host: %v", r.Host)
			w.WriteHeader(http.StatusBadRequest)
			return true
		}
	case strongo.EnvProduction:
		if r.Host == "localhost" || strings.HasSuffix(r.Host, ".ngrok.io") {
			log.Warningf(c, "whc.GetBotSettings().Mode == Production, host: %v", r.Host)
			w.WriteHeader(http.StatusBadRequest)
			return true
		}
	}

	return false
}

func (BotDriver) reportErrorToGA(whc WebhookContext, measurementSender *gamp.BufferedClient, messageText string) {
	gaMessage := gamp.NewException(messageText, true)

	if whc != nil { // TODO: How do deal with Facebook multiple entries per request?
		gaMessage.Common = whc.GaCommon()
	} else {
		gaMessage.Common.ClientID = "c7ea15eb-3333-4d47-a002-9d1a14996371" // TODO: move hardcoded value
		gaMessage.Common.DataSource = "bot-" + whc.BotPlatform().Id()
	}

	c := whc.Context()
	if err := measurementSender.Queue(gaMessage); err != nil {
		log.Errorf(c, "Failed to queue exception details for GA: %v", err)
	} else {
		log.Debugf(c, "Exception details queued for GA.")
	}

	if err := measurementSender.Flush(); err != nil {
		log.Errorf(c, "Failed to send exception details to GA: %v", err)
	} else {
		log.Debugf(c, "Exception details sent to GA.")
	}
}

func (BotDriver) logInput(c context.Context, i int, input WebhookInput) {
	switch input.(type) {
	case WebhookTextMessage:
		sender := input.GetSender()
		log.Debugf(c, "BotUser#%v(%v %v) => text: %v", sender.GetID(), sender.GetFirstName(), sender.GetLastName(), input.(WebhookTextMessage).Text())
	case WebhookNewChatMembersMessage:
		newMembers := input.(WebhookNewChatMembersMessage).NewChatMembers()
		var b bytes.Buffer
		b.WriteString(fmt.Sprintf("NewChatMembers: %d", len(newMembers)))
		for i, member := range newMembers {
			b.WriteString(fmt.Sprintf("\t%d: (%v) - %v %v", i+1, member.GetUserName(), member.GetFirstName(), member.GetLastName()))
		}
		log.Debugf(c, b.String())
	case WebhookContactMessage:
		sender := input.GetSender()
		contactMessage := input.(WebhookContactMessage)
		log.Debugf(c, "BotUser#%v(%v %v) => Contact(name: %v|%v, phone number: %v)", sender.GetID(), sender.GetFirstName(), sender.GetLastName(), contactMessage.FirstName(), contactMessage.LastName(), contactMessage.PhoneNumber())
	case WebhookCallbackQuery:
		callbackQuery := input.(WebhookCallbackQuery)
		callbackData := callbackQuery.GetData()
		sender := input.GetSender()
		log.Debugf(c, "BotUser#%v(%v %v) => callback: %v", sender.GetID(), sender.GetFirstName(), sender.GetLastName(), callbackData)
	case WebhookInlineQuery:
		sender := input.GetSender()
		log.Debugf(c, "BotUser#%v(%v %v) => inline query: %v", sender.GetID(), sender.GetFirstName(), sender.GetLastName(), input.(WebhookInlineQuery).GetQuery())
	case WebhookChosenInlineResult:
		sender := input.GetSender()
		log.Debugf(c, "BotUser#%v(%v %v) => chosen InlineMessageID: %v", sender.GetID(), sender.GetFirstName(), sender.GetLastName(), input.(WebhookChosenInlineResult).GetInlineMessageID())
	case WebhookReferralMessage:
		sender := input.GetSender()
		log.Debugf(c, "BotUser#%v(%v %v) => text: %v", sender.GetID(), sender.GetFirstName(), sender.GetLastName(), input.(WebhookTextMessage).Text())
	default:
		log.Warningf(c, "Unhandled input[%v] type: %T", i, input)
	}
}
<commit_msg>get rid of unneeded dependency<commit_after>package bots

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"runtime/debug"
	"strings"
	"time"

	"github.com/julienschmidt/httprouter"
	"github.com/pkg/errors"
	"github.com/strongo/app"
	"github.com/strongo/gamp"
	"github.com/strongo/log"
	"context"
)

// ErrorIcon is used to report errors to user
var ErrorIcon = "🚨"

// WebhookDriver is doing initial request & final response processing.
// That includes logging, creating input messages in a general format, sending response.
type WebhookDriver interface {
	RegisterWebhookHandlers(httpRouter *httprouter.Router, pathPrefix string, webhookHandlers ...WebhookHandler)
	HandleWebhook(w http.ResponseWriter, r *http.Request, webhookHandler WebhookHandler)
}

// BotDriver keeps information about bots and map requests to appropriate handlers
type BotDriver struct {
	Analytics  AnalyticsSettings
	botHost    BotHost
	appContext BotAppContext
	//router          *WebhooksRouter
	panicTextFooter string
}

var _ WebhookDriver = (*BotDriver)(nil) // Ensure BotDriver is implementing interface WebhookDriver

// AnalyticsSettings keeps data for Google Analytics
type AnalyticsSettings struct {
	GaTrackingID string // TODO: Refactor to list of analytics providers
	Enabled      func(r *http.Request) bool
}

// NewBotDriver registers new bot driver (TODO: describe why we need it)
func NewBotDriver(gaSettings AnalyticsSettings, appContext BotAppContext, host BotHost, panicTextFooter string) WebhookDriver {
	if appContext.AppUserEntityKind() == "" {
		panic("appContext.AppUserEntityKind() is empty")
	}
	if host == nil {
		panic("BotHost == nil")
	}
	return BotDriver{
		Analytics:  gaSettings,
		appContext: appContext,
		botHost:    host,
		//router: router,
		panicTextFooter: panicTextFooter,
	}
}

// RegisterWebhookHandlers adds handlers to a bot driver
func (d BotDriver) RegisterWebhookHandlers(httpRouter *httprouter.Router, pathPrefix string, webhookHandlers ...WebhookHandler) {
	for _, webhookHandler := range webhookHandlers {
		webhookHandler.RegisterWebhookHandler(d, d.botHost, httpRouter, pathPrefix)
	}
}

// HandleWebhook takes and HTTP request and process it
func (d BotDriver) HandleWebhook(w http.ResponseWriter, r *http.Request, webhookHandler WebhookHandler) {
	started := time.Now()
	c := d.botHost.Context(r)
	//log.Debugf(c, "BotDriver.HandleWebhook()")
	if w == nil {
		panic("Parameter 'w http.ResponseWriter' is nil")
	}
	if r == nil {
		panic("Parameter 'r *http.Request' is nil")
	}
	if webhookHandler == nil {
		panic("Parameter 'webhookHandler WebhookHandler' is nil")
	}

	botContext, entriesWithInputs, err := webhookHandler.GetBotContextAndInputs(c, r)

	if d.invalidContextOrInputs(c, w, r, botContext, entriesWithInputs, err) {
		return
	}

	log.Debugf(c, "BotDriver.HandleWebhook() => botCode=%v, len(entriesWithInputs): %d", botContext.BotSettings.Code, len(entriesWithInputs))

	var (
		whc               WebhookContext // TODO: How do deal with Facebook multiple entries per request?
		measurementSender *gamp.BufferedClient
	)

	var sendStats bool
	{ // Initiate Google Analytics Measurement API client
		if d.Analytics.Enabled == nil {
			sendStats = botContext.BotSettings.Env == strongo.EnvProduction
			//log.Debugf(c, "d.AnalyticsSettings.Enabled == nil, botContext.BotSettings.Env: %v, sendStats: %v", strongo.EnvironmentNames[botContext.BotSettings.Env], sendStats)
		} else {
			sendStats = d.Analytics.Enabled(r)
			//log.Debugf(c, "d.AnalyticsSettings.Enabled != nil, sendStats: %v", sendStats)
		}
		if sendStats {
			botHost := botContext.BotHost
			measurementSender = gamp.NewBufferedClient("", botHost.GetHttpClient(c), nil)
		}
	}

	defer func() {
		log.Debugf(c, "driver.deferred(recover) - checking for panic & flush GA")
		if sendStats {
			measurementSender.Queue(gamp.NewTiming(time.Now().Sub(started)))
		}

		reportError := func(recovered interface{}) {
			messageText := fmt.Sprintf("Server error (panic): %v\n\n%v", recovered, d.panicTextFooter)
			log.Criticalf(c, "Panic recovered: %s\n%s", messageText, debug.Stack())

			if sendStats { // Zero if GA is disabled
				d.reportErrorToGA(whc, measurementSender, messageText)
			}

			if whc != nil {
				if chatID, err := whc.BotChatID(); err == nil && chatID != "" {
					if responder := whc.Responder(); responder != nil {
						if _, err := responder.SendMessage(c, whc.NewMessage(ErrorIcon+" "+messageText), BotApiSendMessageOverResponse); err != nil {
							log.Errorf(c, errors.WithMessage(err, "failed to report error to user").Error())
						}
					}
				}
			}
		}

		if recovered := recover(); recovered != nil {
			reportError(recovered)
		} else if sendStats {
			if err = measurementSender.Flush(); err != nil {
				log.Warningf(c, "Failed to flush to GA: %v", err)
			} else {
				log.Debugf(c, "Sent to GA: %v items", measurementSender.QueueDepth())
			}
		}
	}()

	if err != nil {
		log.Errorf(c, "Failed to create new WebhookContext: %v", err)
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}

	botCoreStores := webhookHandler.CreateBotCoreStores(d.appContext, r)
	defer func() {
		if whc != nil { // TODO: How do deal with Facebook multiple entries per request?
			//log.Debugf(c, "Closing BotChatStore...")
			//chatEntity := whc.ChatEntity()
			//if chatEntity != nil && chatEntity.GetPreferredLanguage() == "" {
			//	chatEntity.SetPreferredLanguage(whc.Locale().Code5)
			//}
			if err := botCoreStores.BotChatStore.Close(c); err != nil {
				log.Errorf(c, "Failed to close BotChatStore: %v", err)
				var m MessageFromBot
				m.Text = ErrorIcon + " ERROR: Service is temporary unavailable. Probably a global outage, status at https://status.cloud.google.com/"
				if _, err := whc.Responder().SendMessage(c, m, BotApiSendMessageOverHTTPS); err != nil {
					log.Errorf(c, "Failed to report outage: %v", err)
				}
			}
		}
	}()

	for _, entryWithInputs := range entriesWithInputs {
		for i, input := range entryWithInputs.Inputs {
			if input == nil {
				panic(fmt.Sprintf("entryWithInputs.Inputs[%d] == nil", i))
			}
			d.logInput(c, i, input)
			whc = webhookHandler.CreateWebhookContext(d.appContext, r, *botContext, input, botCoreStores, measurementSender)
			responder := webhookHandler.GetResponder(w, whc) // TODO: Move inside webhookHandler.CreateWebhookContext()?
			botContext.BotSettings.Router.Dispatch(responder, whc)
		}
	}
}

func (BotDriver) invalidContextOrInputs(c context.Context, w http.ResponseWriter, r *http.Request, botContext *BotContext, entriesWithInputs []EntryInputs, err error) bool {
	if err != nil {
		if _, ok := err.(ErrAuthFailed); ok {
			log.Warningf(c, "Auth failed: %v", err)
			http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
		} else if errors.Cause(err) == ErrNotImplemented {
			log.Debugf(c, err.Error())
			w.WriteHeader(http.StatusNoContent)
			//http.Error(w, "", http.StatusOK) // TODO: Decide how to handle it properly, return http.StatusNotImplemented?
		} else if _, ok := err.(*json.SyntaxError); ok {
			log.Debugf(c, errors.Wrap(err, "Request body is not valid JSON").Error())
			http.Error(w, err.Error(), http.StatusBadRequest)
		} else {
			log.Errorf(c, "Failed to call webhookHandler.GetBotContextAndInputs(router): %v", err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
		return true
	} else if botContext == nil {
		if entriesWithInputs == nil {
			log.Warningf(c, "botContext == nil, entriesWithInputs == nil")
		} else if len(entriesWithInputs) == 0 {
			log.Warningf(c, "botContext == nil, len(entriesWithInputs) == 0")
		} else {
			log.Errorf(c, "botContext == nil, len(entriesWithInputs) == %v", len(entriesWithInputs))
		}
		return true
	} else if entriesWithInputs == nil {
		log.Errorf(c, "entriesWithInputs == nil")
		return true
	}

	switch botContext.BotSettings.Env {
	case strongo.EnvLocal:
		if r.Host != "localhost" && !strings.HasSuffix(r.Host, ".ngrok.io") {
			log.Warningf(c, "whc.GetBotSettings().Mode == Local, host: %v", r.Host)
			w.WriteHeader(http.StatusBadRequest)
			return true
		}
	case strongo.EnvProduction:
		if r.Host == "localhost" || strings.HasSuffix(r.Host, ".ngrok.io") {
			log.Warningf(c, "whc.GetBotSettings().Mode == Production, host: %v", r.Host)
			w.WriteHeader(http.StatusBadRequest)
			return true
		}
	}

	return false
}

func (BotDriver) reportErrorToGA(whc WebhookContext, measurementSender *gamp.BufferedClient, messageText string) {
	gaMessage := gamp.NewException(messageText, true)

	if whc != nil { // TODO: How do deal with Facebook multiple entries per request?
		gaMessage.Common = whc.GaCommon()
	} else {
		gaMessage.Common.ClientID = "c7ea15eb-3333-4d47-a002-9d1a14996371" // TODO: move hardcoded value
		gaMessage.Common.DataSource = "bot-" + whc.BotPlatform().Id()
	}

	c := whc.Context()
	if err := measurementSender.Queue(gaMessage); err != nil {
		log.Errorf(c, "Failed to queue exception details for GA: %v", err)
	} else {
		log.Debugf(c, "Exception details queued for GA.")
	}

	if err := measurementSender.Flush(); err != nil {
		log.Errorf(c, "Failed to send exception details to GA: %v", err)
	} else {
		log.Debugf(c, "Exception details sent to GA.")
	}
}

func (BotDriver) logInput(c context.Context, i int, input WebhookInput) {
	switch input.(type) {
	case WebhookTextMessage:
		sender := input.GetSender()
		log.Debugf(c, "BotUser#%v(%v %v) => text: %v", sender.GetID(), sender.GetFirstName(), sender.GetLastName(), input.(WebhookTextMessage).Text())
	case WebhookNewChatMembersMessage:
		newMembers := input.(WebhookNewChatMembersMessage).NewChatMembers()
		var b bytes.Buffer
		b.WriteString(fmt.Sprintf("NewChatMembers: %d", len(newMembers)))
		for i, member := range newMembers {
			b.WriteString(fmt.Sprintf("\t%d: (%v) - %v %v", i+1, member.GetUserName(), member.GetFirstName(), member.GetLastName()))
		}
		log.Debugf(c, b.String())
	case WebhookContactMessage:
		sender := input.GetSender()
		contactMessage := input.(WebhookContactMessage)
		log.Debugf(c, "BotUser#%v(%v %v) => Contact(name: %v|%v, phone number: %v)", sender.GetID(), sender.GetFirstName(), sender.GetLastName(), contactMessage.FirstName(), contactMessage.LastName(), contactMessage.PhoneNumber())
	case WebhookCallbackQuery:
		callbackQuery := input.(WebhookCallbackQuery)
		callbackData := callbackQuery.GetData()
		sender := input.GetSender()
		log.Debugf(c, "BotUser#%v(%v %v) => callback: %v", sender.GetID(), sender.GetFirstName(), sender.GetLastName(), callbackData)
	case WebhookInlineQuery:
		sender := input.GetSender()
		log.Debugf(c, "BotUser#%v(%v %v) => inline query: %v", sender.GetID(), sender.GetFirstName(), sender.GetLastName(), input.(WebhookInlineQuery).GetQuery())
	case WebhookChosenInlineResult:
		sender := input.GetSender()
		log.Debugf(c, "BotUser#%v(%v %v) => chosen InlineMessageID: %v", sender.GetID(), sender.GetFirstName(), sender.GetLastName(), input.(WebhookChosenInlineResult).GetInlineMessageID())
	case WebhookReferralMessage:
		sender := input.GetSender()
		log.Debugf(c, "BotUser#%v(%v %v) => text: %v", sender.GetID(), sender.GetFirstName(), sender.GetLastName(), input.(WebhookTextMessage).Text())
	default:
		log.Warningf(c, "Unhandled input[%v] type: %T", i, input)
	}
}
<|endoftext|>


<commit_before>package core

import (
	"bytes"
	"math"

	"github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/state"
)

type AccountChange struct {
	Address, StateAddress []byte
}

type FilterOptions struct {
	Earliest int64
	Latest   int64

	Address []byte
	Topics  [][]byte

	Skip int
	Max  int
}

// Filtering interface
type Filter struct {
	eth      EthManager
	earliest int64
	latest   int64
	skip     int
	address  []byte
	max      int
	topics   [][]byte

	BlockCallback   func(*types.Block)
	PendingCallback func(*types.Block)
	LogsCallback    func(state.Logs)
}

// Create a new filter which uses a bloom filter on blocks to figure out whether a particular block
// is interesting or not.
func NewFilter(eth EthManager) *Filter {
	return &Filter{eth: eth}
}

func (self *Filter) SetOptions(options FilterOptions) {
	self.earliest = options.Earliest
	self.latest = options.Latest
	self.skip = options.Skip
	self.max = options.Max
	self.address = options.Address
	self.topics = options.Topics

}

// Set the earliest and latest block for filtering.
// -1 = latest block (i.e., the current block)
// hash = particular hash from-to
func (self *Filter) SetEarliestBlock(earliest int64) {
	self.earliest = earliest
}

func (self *Filter) SetLatestBlock(latest int64) {
	self.latest = latest
}

func (self *Filter) SetAddress(addr []byte) {
	self.address = addr
}

func (self *Filter) SetTopics(topics [][]byte) {
	self.topics = topics
}

func (self *Filter) SetMax(max int) {
	self.max = max
}

func (self *Filter) SetSkip(skip int) {
	self.skip = skip
}

// Run filters logs with the current parameters set
func (self *Filter) Find() state.Logs {
	earliestBlock := self.eth.ChainManager().CurrentBlock()
	var earliestBlockNo uint64 = uint64(self.earliest)
	if self.earliest == -1 {
		earliestBlockNo = earliestBlock.NumberU64()
	}
	var latestBlockNo uint64 = uint64(self.latest)
	if self.latest == -1 {
		latestBlockNo = earliestBlock.NumberU64()
	}

	var (
		logs  state.Logs
		block = self.eth.ChainManager().GetBlockByNumber(latestBlockNo)
		quit  bool
	)
	for i := 0; !quit && block != nil; i++ {
		// Quit on latest
		switch {
		case block.NumberU64() == earliestBlockNo, block.NumberU64() == 0:
			quit = true
		case self.max <= len(logs):
			break
		}

		// Use bloom filtering to see if this block is interesting given the
		// current parameters
		if self.bloomFilter(block) {
			// Get the logs of the block
			logs, err := self.eth.BlockProcessor().GetLogs(block)
			if err != nil {
				chainlogger.Warnln("err: filter get logs ", err)

				break
			}

			logs = append(logs, self.FilterLogs(logs)...)
		}

		block = self.eth.ChainManager().GetBlock(block.ParentHash())
	}

	skip := int(math.Min(float64(len(logs)), float64(self.skip)))

	return logs[skip:]
}

func includes(addresses [][]byte, a []byte) bool {
	for _, addr := range addresses {
		if !bytes.Equal(addr, a) {
			return false
		}
	}

	return true
}

func (self *Filter) FilterLogs(logs state.Logs) state.Logs {
	var ret state.Logs

	// Filter the logs for interesting stuff
Logs:
	for _, log := range logs {
		if len(self.address) > 0 && !bytes.Equal(self.address, log.Address()) {
			continue
		}

		max := int(math.Min(float64(len(self.topics)), float64(len(log.Topics()))))
		for i := 0; i < max; i++ {
			if !bytes.Equal(log.Topics()[i], self.topics[i]) {
				continue Logs
			}
		}

		ret = append(ret, log)
	}

	return ret
}

func (self *Filter) bloomFilter(block *types.Block) bool {
	if len(self.address) > 0 && !types.BloomLookup(block.Bloom(), self.address) {
		return false
	}

	for _, topic := range self.topics {
		if !types.BloomLookup(block.Bloom(), topic) {
			return false
		}
	}

	return true
}
<commit_msg>Compare regardless of length<commit_after>package core

import (
	"bytes"
	"math"

	"github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/state"
)

type AccountChange struct {
	Address, StateAddress []byte
}

type FilterOptions struct {
	Earliest int64
	Latest   int64

	Address []byte
	Topics  [][]byte

	Skip int
	Max  int
}

// Filtering interface
type Filter struct {
	eth      EthManager
	earliest int64
	latest   int64
	skip     int
	address  []byte
	max      int
	topics   [][]byte

	BlockCallback   func(*types.Block)
	PendingCallback func(*types.Block)
	LogsCallback    func(state.Logs)
}

// Create a new filter which uses a bloom filter on blocks to figure out whether a particular block
// is interesting or not.
func NewFilter(eth EthManager) *Filter {
	return &Filter{eth: eth}
}

func (self *Filter) SetOptions(options FilterOptions) {
	self.earliest = options.Earliest
	self.latest = options.Latest
	self.skip = options.Skip
	self.max = options.Max
	self.address = options.Address
	self.topics = options.Topics

}

// Set the earliest and latest block for filtering.
// -1 = latest block (i.e., the current block)
// hash = particular hash from-to
func (self *Filter) SetEarliestBlock(earliest int64) {
	self.earliest = earliest
}

func (self *Filter) SetLatestBlock(latest int64) {
	self.latest = latest
}

func (self *Filter) SetAddress(addr []byte) {
	self.address = addr
}

func (self *Filter) SetTopics(topics [][]byte) {
	self.topics = topics
}

func (self *Filter) SetMax(max int) {
	self.max = max
}

func (self *Filter) SetSkip(skip int) {
	self.skip = skip
}

// Run filters logs with the current parameters set
func (self *Filter) Find() state.Logs {
	earliestBlock := self.eth.ChainManager().CurrentBlock()
	var earliestBlockNo uint64 = uint64(self.earliest)
	if self.earliest == -1 {
		earliestBlockNo = earliestBlock.NumberU64()
	}
	var latestBlockNo uint64 = uint64(self.latest)
	if self.latest == -1 {
		latestBlockNo = earliestBlock.NumberU64()
	}

	var (
		logs  state.Logs
		block = self.eth.ChainManager().GetBlockByNumber(latestBlockNo)
		quit  bool
	)
	for i := 0; !quit && block != nil; i++ {
		// Quit on latest
		switch {
		case block.NumberU64() == earliestBlockNo, block.NumberU64() == 0:
			quit = true
		case self.max <= len(logs):
			break
		}

		// Use bloom filtering to see if this block is interesting given the
		// current parameters
		if self.bloomFilter(block) {
			// Get the logs of the block
			logs, err := self.eth.BlockProcessor().GetLogs(block)
			if err != nil {
				chainlogger.Warnln("err: filter get logs ", err)

				break
			}

			logs = append(logs, self.FilterLogs(logs)...)
		}

		block = self.eth.ChainManager().GetBlock(block.ParentHash())
	}

	skip := int(math.Min(float64(len(logs)), float64(self.skip)))

	return logs[skip:]
}

func includes(addresses [][]byte, a []byte) bool {
	for _, addr := range addresses {
		if !bytes.Equal(addr, a) {
			return false
		}
	}

	return true
}

func (self *Filter) FilterLogs(logs state.Logs) state.Logs {
	var ret state.Logs

	// Filter the logs for interesting stuff
Logs:
	for _, log := range logs {
		if !bytes.Equal(self.address, log.Address()) {
			continue
		}

		max := int(math.Min(float64(len(self.topics)), float64(len(log.Topics()))))
		for i := 0; i < max; i++ {
			if !bytes.Equal(log.Topics()[i], self.topics[i]) {
				continue Logs
			}
		}

		ret = append(ret, log)
	}

	return ret
}

func (self *Filter) bloomFilter(block *types.Block) bool {
	if len(self.address) > 0 && !types.BloomLookup(block.Bloom(), self.address) {
		return false
	}

	for _, topic := range self.topics {
		if !types.BloomLookup(block.Bloom(), topic) {
			return false
		}
	}

	return true
}
<|endoftext|>