<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"math"
	"os"
	"os/signal"
	"runtime"
	"strings"
	"syscall"
	"testing"
	"time"

	"github.com/mackerelio/mackerel-agent/command"
)

func TestParseFlags(t *testing.T) {
	// prepare dummy config
	confFile, err := ioutil.TempFile("", "mackerel-config-test")

	if err != nil {
		t.Fatalf("Could not create temprary config file for test")
	}
	confFile.WriteString(`verbose=false
root="/hoge/fuga"
apikey="DUMMYAPIKEY"
diagnostic=false
`)
	confFile.Sync()
	confFile.Close()
	defer os.Remove(confFile.Name())
	mergedConfig, _ := resolveConfig([]string{"-conf=" + confFile.Name(), "-role=My-Service:default,INVALID#SERVICE", "-verbose", "-diagnostic"})

	t.Logf("      apibase: %v", mergedConfig.Apibase)
	t.Logf("       apikey: %v", mergedConfig.Apikey)
	t.Logf("         root: %v", mergedConfig.Root)
	t.Logf("      pidfile: %v", mergedConfig.Pidfile)
	t.Logf("   diagnostic: %v", mergedConfig.Diagnostic)
	t.Logf("roleFullnames: %v", mergedConfig.Roles)
	t.Logf("      verbose: %v", mergedConfig.Verbose)

	if mergedConfig.Root != "/hoge/fuga" {
		t.Errorf("Root(confing from file) should be /hoge/fuga but: %v", mergedConfig.Root)
	}

	if len(mergedConfig.Roles) != 1 || mergedConfig.Roles[0] != "My-Service:default" {
		t.Error("Roles(config from command line option) should be parsed")
	}

	if mergedConfig.Verbose != true {
		t.Error("Verbose(overwritten by command line option) shoud be true")
	}

	if mergedConfig.Diagnostic != true {
		t.Error("Diagnostic(overwritten by command line option) shoud be true")
	}
}

func TestParseFlagsPrintVersion(t *testing.T) {
	config, otherOptions := resolveConfig([]string{"-version"})

	if config.Verbose != false {
		t.Error("with -version args, variables of config should have default values")
	}

	if otherOptions.printVersion == false {
		t.Error("with -version args, printVersion should be true")
	}
}

func TestParseFlagsRunOnce(t *testing.T) {
	config, otherOptions := resolveConfig([]string{"-once"})

	if config.Verbose != false {
		t.Error("with -version args, variables of config should have default values")
	}

	if otherOptions.runOnce == false {
		t.Error("with -once args, RunOnce should be true")
	}
}

func TestDetectForce(t *testing.T) {
	// prepare dummy config
	confFile, err := ioutil.TempFile("", "mackerel-config-test")
	if err != nil {
		t.Fatalf("Could not create temprary config file for test")
	}
	confFile.WriteString(`apikey="DUMMYAPIKEY"
`)
	confFile.Sync()
	confFile.Close()
	defer os.Remove(confFile.Name())

	argv := []string{"-conf=" + confFile.Name()}
	conf, force, err := resolveConfigForRetire(argv)
	if force {
		t.Errorf("force should be false")
	}
	if conf.Apikey != "DUMMYAPIKEY" {
		t.Errorf("Apikey should be 'DUMMYAPIKEY'")
	}

	argv = append(argv, "-force")
	conf, force, err = resolveConfigForRetire(argv)
	if !force {
		t.Errorf("force should be true")
	}
	if conf.Apikey != "DUMMYAPIKEY" {
		t.Errorf("Apikey should be 'DUMMYAPIKEY'")
	}
}

func TestCreateAndRemovePidFile(t *testing.T) {
	file, err := ioutil.TempFile("", "")
	if err != nil {
		t.Errorf("failed to create tmpfile, %s", err)
	}
	fpath := file.Name()
	defer os.Remove(fpath)

	err = createPidFile(fpath)
	if err != nil {
		t.Errorf("pid file should be created but, %s", err)
	}

	if runtime.GOOS != "windows" {
		if err := createPidFile(fpath); err == nil || !strings.HasPrefix(err.Error(), "Pidfile found, try stopping another running mackerel-agent or delete") {
			t.Errorf("creating pid file should be failed when the running process exists, %s", err)
		}
	}

	removePidFile(fpath)
	if err := createPidFile(fpath); err != nil {
		t.Errorf("pid file should be created but, %s", err)
	}

	removePidFile(fpath)
	ioutil.WriteFile(fpath, []byte(fmt.Sprint(math.MaxInt32)), 0644)
	if err := createPidFile(fpath); err != nil {
		t.Errorf("old pid file should be ignored and new pid file should be created but, %s", err)
	}
}

func TestSignalHandler(t *testing.T) {
	ctx := &command.Context{}
	termCh := make(chan struct{})
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
	go signalHandler(c, ctx, termCh)

	resultCh := make(chan int)

	maxTerminatingInterval = 100 * time.Millisecond
	c <- os.Interrupt
	c <- os.Interrupt

	go func() {
		<-termCh
		<-termCh
		<-termCh
		<-termCh
		resultCh <- 0
	}()

	go func() {
		time.Sleep(time.Second)
		resultCh <- 1
	}()

	if r := <-resultCh; r != 0 {
		t.Errorf("Something went wrong")
	}
}

func TestConfigTestOK(t *testing.T) {
	// prepare dummy config
	confFile, err := ioutil.TempFile("", "mackerel-config-test")
	if err != nil {
		t.Fatalf("Could not create temprary config file for test")
	}
	confFile.WriteString(`apikey="DUMMYAPIKEY"
`)
	confFile.Sync()
	confFile.Close()
	defer os.Remove(confFile.Name())

	argv := []string{"-conf=" + confFile.Name()}
	status := doConfigtest(argv)

	if status != exitStatusOK {
		t.Errorf("configtest(ok) must be return exitStatusOK")
	}
}

func TestConfigTestNotFound(t *testing.T) {
	// prepare dummy config
	confFile, err := ioutil.TempFile("", "mackerel-config-test")
	if err != nil {
		t.Fatalf("Could not create temprary config file for test")
	}
	confFile.WriteString(`apikey="DUMMYAPIKEY"
`)
	confFile.Sync()
	confFile.Close()
	defer os.Remove(confFile.Name())

	argv := []string{"-conf=" + confFile.Name() + "xxx"}
	status := doConfigtest(argv)

	if status != exitStatusError {
		t.Errorf("configtest(failed) must be return existStatusError")
	}
}

func TestConfigTestInvalidFormat(t *testing.T) {
	// prepare dummy config
	confFile, err := ioutil.TempFile("", "mackerel-config-test")
	if err != nil {
		t.Fatalf("Could not create temprary config file for test")
	}
	confFile.WriteString(`apikey="DUMMYAPIKEY"
[plugin.checks.foo ]
command = "bar"
`)
	confFile.Sync()
	confFile.Close()
	defer os.Remove(confFile.Name())

	argv := []string{"-conf=" + confFile.Name()}
	status := doConfigtest(argv)

	if status != exitStatusError {
		t.Errorf("configtest(failed) must be return exitStatusError")
	}
}
<commit_msg>add test for doRetire<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"math"
	"os"
	"os/signal"
	"runtime"
	"strings"
	"syscall"
	"testing"
	"time"

	"github.com/mackerelio/mackerel-agent/command"
)

func TestParseFlags(t *testing.T) {
	// prepare dummy config
	confFile, err := ioutil.TempFile("", "mackerel-config-test")

	if err != nil {
		t.Fatalf("Could not create temprary config file for test")
	}
	confFile.WriteString(`verbose=false
root="/hoge/fuga"
apikey="DUMMYAPIKEY"
diagnostic=false
`)
	confFile.Sync()
	confFile.Close()
	defer os.Remove(confFile.Name())
	mergedConfig, _ := resolveConfig([]string{"-conf=" + confFile.Name(), "-role=My-Service:default,INVALID#SERVICE", "-verbose", "-diagnostic"})

	t.Logf("      apibase: %v", mergedConfig.Apibase)
	t.Logf("       apikey: %v", mergedConfig.Apikey)
	t.Logf("         root: %v", mergedConfig.Root)
	t.Logf("      pidfile: %v", mergedConfig.Pidfile)
	t.Logf("   diagnostic: %v", mergedConfig.Diagnostic)
	t.Logf("roleFullnames: %v", mergedConfig.Roles)
	t.Logf("      verbose: %v", mergedConfig.Verbose)

	if mergedConfig.Root != "/hoge/fuga" {
		t.Errorf("Root(confing from file) should be /hoge/fuga but: %v", mergedConfig.Root)
	}

	if len(mergedConfig.Roles) != 1 || mergedConfig.Roles[0] != "My-Service:default" {
		t.Error("Roles(config from command line option) should be parsed")
	}

	if mergedConfig.Verbose != true {
		t.Error("Verbose(overwritten by command line option) shoud be true")
	}

	if mergedConfig.Diagnostic != true {
		t.Error("Diagnostic(overwritten by command line option) shoud be true")
	}
}

func TestParseFlagsPrintVersion(t *testing.T) {
	config, otherOptions := resolveConfig([]string{"-version"})

	if config.Verbose != false {
		t.Error("with -version args, variables of config should have default values")
	}

	if otherOptions.printVersion == false {
		t.Error("with -version args, printVersion should be true")
	}
}

func TestParseFlagsRunOnce(t *testing.T) {
	config, otherOptions := resolveConfig([]string{"-once"})

	if config.Verbose != false {
		t.Error("with -version args, variables of config should have default values")
	}

	if otherOptions.runOnce == false {
		t.Error("with -once args, RunOnce should be true")
	}
}

func TestDetectForce(t *testing.T) {
	// prepare dummy config
	confFile, err := ioutil.TempFile("", "mackerel-config-test")
	if err != nil {
		t.Fatalf("Could not create temprary config file for test")
	}
	confFile.WriteString(`apikey="DUMMYAPIKEY"
`)
	confFile.Sync()
	confFile.Close()
	defer os.Remove(confFile.Name())

	argv := []string{"-conf=" + confFile.Name()}
	conf, force, err := resolveConfigForRetire(argv)
	if force {
		t.Errorf("force should be false")
	}
	if conf.Apikey != "DUMMYAPIKEY" {
		t.Errorf("Apikey should be 'DUMMYAPIKEY'")
	}

	argv = append(argv, "-force")
	conf, force, err = resolveConfigForRetire(argv)
	if !force {
		t.Errorf("force should be true")
	}
	if conf.Apikey != "DUMMYAPIKEY" {
		t.Errorf("Apikey should be 'DUMMYAPIKEY'")
	}
}

func TestResolveConfigForRetire(t *testing.T) {
	confFile, err := ioutil.TempFile("", "mackerel-config-test")
	if err != nil {
		t.Fatalf("Could not create temprary config file for test")
	}
	confFile.WriteString(`apikey="DUMMYAPIKEY"
`)
	confFile.Sync()
	confFile.Close()
	defer os.Remove(confFile.Name())

	// Allow accepting unnecessary options, pidfile, diagnostic and role.
	// Because, these options are potentially passed in initd script by using $OTHER_OPTS.
	argv := []string{
		"-conf=" + confFile.Name(),
		"-apibase=https://mackerel.io",
		"-pidfile=hoge",
		"-root=hoge",
		"-verbose",
		"-diagnostic",
		"-apikey=hogege",
		"-role=hoge:fuga",
	}

	conf, force, err := resolveConfigForRetire(argv)
	if force {
		t.Errorf("force should be false")
	}
	if conf.Apikey != "hogege" {
		t.Errorf("Apikey should be 'hogege'")
	}
}

func TestCreateAndRemovePidFile(t *testing.T) {
	file, err := ioutil.TempFile("", "")
	if err != nil {
		t.Errorf("failed to create tmpfile, %s", err)
	}
	fpath := file.Name()
	defer os.Remove(fpath)

	err = createPidFile(fpath)
	if err != nil {
		t.Errorf("pid file should be created but, %s", err)
	}

	if runtime.GOOS != "windows" {
		if err := createPidFile(fpath); err == nil || !strings.HasPrefix(err.Error(), "Pidfile found, try stopping another running mackerel-agent or delete") {
			t.Errorf("creating pid file should be failed when the running process exists, %s", err)
		}
	}

	removePidFile(fpath)
	if err := createPidFile(fpath); err != nil {
		t.Errorf("pid file should be created but, %s", err)
	}

	removePidFile(fpath)
	ioutil.WriteFile(fpath, []byte(fmt.Sprint(math.MaxInt32)), 0644)
	if err := createPidFile(fpath); err != nil {
		t.Errorf("old pid file should be ignored and new pid file should be created but, %s", err)
	}
}

func TestSignalHandler(t *testing.T) {
	ctx := &command.Context{}
	termCh := make(chan struct{})
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
	go signalHandler(c, ctx, termCh)

	resultCh := make(chan int)

	maxTerminatingInterval = 100 * time.Millisecond
	c <- os.Interrupt
	c <- os.Interrupt

	go func() {
		<-termCh
		<-termCh
		<-termCh
		<-termCh
		resultCh <- 0
	}()

	go func() {
		time.Sleep(time.Second)
		resultCh <- 1
	}()

	if r := <-resultCh; r != 0 {
		t.Errorf("Something went wrong")
	}
}

func TestConfigTestOK(t *testing.T) {
	// prepare dummy config
	confFile, err := ioutil.TempFile("", "mackerel-config-test")
	if err != nil {
		t.Fatalf("Could not create temprary config file for test")
	}
	confFile.WriteString(`apikey="DUMMYAPIKEY"
`)
	confFile.Sync()
	confFile.Close()
	defer os.Remove(confFile.Name())

	argv := []string{"-conf=" + confFile.Name()}
	status := doConfigtest(argv)

	if status != exitStatusOK {
		t.Errorf("configtest(ok) must be return exitStatusOK")
	}
}

func TestConfigTestNotFound(t *testing.T) {
	// prepare dummy config
	confFile, err := ioutil.TempFile("", "mackerel-config-test")
	if err != nil {
		t.Fatalf("Could not create temprary config file for test")
	}
	confFile.WriteString(`apikey="DUMMYAPIKEY"
`)
	confFile.Sync()
	confFile.Close()
	defer os.Remove(confFile.Name())

	argv := []string{"-conf=" + confFile.Name() + "xxx"}
	status := doConfigtest(argv)

	if status != exitStatusError {
		t.Errorf("configtest(failed) must be return existStatusError")
	}
}

func TestConfigTestInvalidFormat(t *testing.T) {
	// prepare dummy config
	confFile, err := ioutil.TempFile("", "mackerel-config-test")
	if err != nil {
		t.Fatalf("Could not create temprary config file for test")
	}
	confFile.WriteString(`apikey="DUMMYAPIKEY"
[plugin.checks.foo ]
command = "bar"
`)
	confFile.Sync()
	confFile.Close()
	defer os.Remove(confFile.Name())

	argv := []string{"-conf=" + confFile.Name()}
	status := doConfigtest(argv)

	if status != exitStatusError {
		t.Errorf("configtest(failed) must be return exitStatusError")
	}
}
<|endoftext|>


<commit_before>package main

import(
	"regexp"
)

const(
	regex_date = `\d{4}[-/\.]\d{2}[-/\.]\d{2}`
	regex_xp = `\(?\d*xp\)?`
	regex_mark = `[\*\+\-]`
	regex_value = `([\+\-])?\d{1,2}`
	regex_blank = `[\t ]*`
	regex_date_separator = `[/-\.]`
	date_format = `2006/02/03`
)

type Line struct {
	raw	string
}

// creates a new line given a raw value
func NewLine(raw string) *Line {
	return &Line{
		raw: raw,
	}
}

// returns true if the line contains a date
func (l *line) HasDate() (m bool) {
	m, _ regexp.MatchString(`^` + regex_blank + regex_date, l.raw)
	return
}

// returns the date within the line and removes it
func (l *line) GetDate() (s string) {
	if !l.HasDate() {
		return
	}
	r := regexp.MustCompile(`^` + regex_blank + regex_date)
	s = r.FindString(l.raw)
	r := regexp.MustCompile(regex_date_separator)
	l.raw = strings.Replace(l.raw, s, "", 1)
	s = r.ReplaceAllString(s, "/")
	s = strings.TrimSpace(s)
}

// returns true if the line contains xp
func (l *line) HasXp() (m bool) {
	m, _ regexp.MatchString(regex_xp, l.raw)
	return
}

// returns the xp within the line and removes it
func (l *line) GetXp() (s string) {
	if !l.HasXp() {
		return
	}
	r := regexp.MustCompile(regex_xp)
	s = r.FindString(l.raw)
	l.raw = strings.Replace(l.raw, s, "", 1)
	s = regexp.MustCompile(`\d*`).FindString(s)
}

// returns true if the line contains mark
func (l *line) HasMark() (m bool) {
	m, _ regexp.MatchString(regex_mark, l.raw)
	return
}

// returns the mark within the line and removes it
func (l *line) GetMark() (s string) {
	if !l.HasMark() {
		return
	}
	r := regexp.MustCompile(regex_mark)
	s = r.FindString(l.raw)
	l.raw = strings.Replace(l.raw, s, "", 1)
	s = strings.TrimSpace(s)
}

// returns true if the line contains value
func (l *line) HasValue() (m bool) {
	m, _ regexp.MatchString(regex_value, l.raw)
	return
}

// returns the value within the line and removes it
func (l *line) GetValue() (s string) {
	if !l.HasValue() {
		return
	}
	r = regexp.MustCompile(regex_value)
	s = r.FindString(l.raw)
	l.raw = strings.Replace(l.raw, s, "", 1)
}

// returns true if the line contains an label
func (l *line) HasKey() bool {
	return strings.Contains(l.raw, ":")
}

// returns the key within the line and removes it
func (l *line) GetKey() (s string) {
	if !l.HasKey() {
		return
	}
	split := strings.SplitN(l.raw, ":", 2)
	s = split[0]
	l.raw = split[1]
	s = strings.TrimSpace(s)
	return
}

// returns the label within the line and removes it
func (l *line) GetLabel() (s string) {
	return strings.TrimSpace(l.raw)
}<commit_msg>Removes useless constant.<commit_after>package main

import(
	"regexp"
)

const(
	regex_date = `^[\t ]*\d{4}[-/\.]\d{2}[-/\.]\d{2}`
	regex_xp = `\(?\d*xp\)?`
	regex_mark = `[\*\+\-]`
	regex_value = `([\+\-])?\d{1,2}`
	regex_date_separator = `[/-\.]`
	date_format = `2006/02/03`
)

type Line struct {
	raw	string
}

// creates a new line given a raw value
func NewLine(raw string) *Line {
	return &Line{
		raw: raw,
	}
}

// returns true if the line contains a date
func (l *line) HasDate() (m bool) {
	m, _ regexp.MatchString(regex_date, l.raw)
	return
}

// returns the date within the line and removes it
func (l *line) GetDate() (s string) {
	if !l.HasDate() {
		return
	}
	r := regexp.MustCompile(regex_date)
	s = r.FindString(l.raw)
	r := regexp.MustCompile(regex_date_separator)
	l.raw = strings.Replace(l.raw, s, "", 1)
	s = r.ReplaceAllString(s, "/")
	s = strings.TrimSpace(s)
}

// returns true if the line contains xp
func (l *line) HasXp() (m bool) {
	m, _ regexp.MatchString(regex_xp, l.raw)
	return
}

// returns the xp within the line and removes it
func (l *line) GetXp() (s string) {
	if !l.HasXp() {
		return
	}
	r := regexp.MustCompile(regex_xp)
	s = r.FindString(l.raw)
	l.raw = strings.Replace(l.raw, s, "", 1)
	s = regexp.MustCompile(`\d*`).FindString(s)
}

// returns true if the line contains mark
func (l *line) HasMark() (m bool) {
	m, _ regexp.MatchString(regex_mark, l.raw)
	return
}

// returns the mark within the line and removes it
func (l *line) GetMark() (s string) {
	if !l.HasMark() {
		return
	}
	r := regexp.MustCompile(regex_mark)
	s = r.FindString(l.raw)
	l.raw = strings.Replace(l.raw, s, "", 1)
	s = strings.TrimSpace(s)
}

// returns true if the line contains value
func (l *line) HasValue() (m bool) {
	m, _ regexp.MatchString(regex_value, l.raw)
	return
}

// returns the value within the line and removes it
func (l *line) GetValue() (s string) {
	if !l.HasValue() {
		return
	}
	r = regexp.MustCompile(regex_value)
	s = r.FindString(l.raw)
	l.raw = strings.Replace(l.raw, s, "", 1)
}

// returns true if the line contains an label
func (l *line) HasKey() bool {
	return strings.Contains(l.raw, ":")
}

// returns the key within the line and removes it
func (l *line) GetKey() (s string) {
	if !l.HasKey() {
		return
	}
	split := strings.SplitN(l.raw, ":", 2)
	s = split[0]
	l.raw = split[1]
	s = strings.TrimSpace(s)
	return
}

// returns the label within the line and removes it
func (l *line) GetLabel() (s string) {
	return strings.TrimSpace(l.raw)
}<|endoftext|>


<commit_before>package main

import (
	"github.com/stretchr/testify/assert"
	"testing"
)

func TestReadLines(t *testing.T) {

	assert := assert.New(t)
	lines, err := readLines("./test.chordpro")

	assert.Nil(err)
	assert.Equal("{t: Hello world}", lines[0], "they should be equal")
	assert.Equal("", lines[4], "they should be equal")
	assert.Equal("[G]Lorem ipsum dolor sit amet, [D/F#]consectetur adipiscing elit. Don[Em]ec a diam lectus.", lines[5], "they should be equal")
}
<commit_msg>:white_check_mark: Add test for getLineType<commit_after>package main

import (
	"github.com/stretchr/testify/assert"
	"testing"
)

func TestReadLines(t *testing.T) {

	assert := assert.New(t)
	lines, err := readLines("./test.chordpro")

	assert.Nil(err)
	assert.Equal("{t: Hello world}", lines[0], "they should be equal")
	assert.Equal("", lines[4], "they should be equal")
	assert.Equal("[G]Lorem ipsum dolor sit amet, [D/F#]consectetur adipiscing elit. Don[Em]ec a diam lectus.", lines[5], "they should be equal")

}

func TestGetLineType(t *testing.T) {

	assert := assert.New(t)
	lines, err := readLines("./test.chordpro")

	assert.Nil(err)

	// Testing title type
	titleType, _, _ := getLineType(lines[0])
	assert.Equal("title", titleType, "they should have the same type")

	// Testing subtitle type
	stType, _, _ := getLineType(lines[1])
	assert.Equal("subtitle", stType, "they should have the same type")

	// Testing comment type
	commentType, _, _ := getLineType(lines[3])
	assert.Equal("comment", commentType, "they should have the same type")

	// Testing verse type
	verseType, _, _ := getLineType(lines[5])
	assert.Equal("verse", verseType, "they should have the same type")
}
<|endoftext|>


<commit_before>package thermal

type line struct {
	id           [16]byte
	at           int
	sharedSecret [32]byte
}

type lineSession struct {
	localLine     line
	remoteLine    line
	encryptionKey [32]byte
	decryptionKey [32]byte
}

type lineMap map[string]lineSession
<commit_msg>adjust names<commit_after>package thermal

type lineHalf struct {
	id           [16]byte
	at           int
	sharedSecret [32]byte
}

type lineSession struct {
	local         lineHalf
	remote        lineHalf
	encryptionKey [32]byte
	decryptionKey [32]byte
}

type lineMap map[string]lineSession
<|endoftext|>


<commit_before>package tachymeter_test

import (
	"testing"
	"time"

	"github.com/jamiealquiza/tachymeter"
)

func TestReset(t *testing.T) {
	ta := tachymeter.New(&tachymeter.Config{Size: 3})

	ta.AddTime(time.Second)
	ta.AddTime(time.Second)
	ta.AddTime(time.Second)
	ta.Reset()

	if ta.Count != 0 {
		t.Fail()
	}
}

func TestAddTime(t *testing.T) {
	ta := tachymeter.New(&tachymeter.Config{Size: 3})

	ta.AddTime(time.Millisecond)

	if ta.Times[0] != time.Millisecond {
		t.Fail()
	}
}

func TestSetWallTime(t *testing.T) {
	ta := tachymeter.New(&tachymeter.Config{Size: 3})

	ta.SetWallTime(time.Millisecond)

	if ta.WallTime != time.Millisecond {
		t.Fail()
	}
}
<commit_msg>added AddTime benches to test<commit_after>package tachymeter_test

import (
	"testing"
	"time"

	"github.com/jamiealquiza/tachymeter"
)

func BenchmarkAddTime(b *testing.B) {
	b.StopTimer()

	ta := tachymeter.New(&tachymeter.Config{Size: b.N})
	d := time.Millisecond

	b.StartTimer()
	for i := 0; i < b.N; i++ {
		ta.AddTime(d)
	}
}

func BenchmarkAddTimeSampling(b *testing.B) {
	b.StopTimer()

	ta := tachymeter.New(&tachymeter.Config{Size: 100})
	d := time.Millisecond

	b.StartTimer()
	for i := 0; i < b.N; i++ {
		ta.AddTime(d)
	}
}

func TestReset(t *testing.T) {
	ta := tachymeter.New(&tachymeter.Config{Size: 3})

	ta.AddTime(time.Second)
	ta.AddTime(time.Second)
	ta.AddTime(time.Second)
	ta.Reset()

	if ta.Count != 0 {
		t.Fail()
	}
}

func TestAddTime(t *testing.T) {
	ta := tachymeter.New(&tachymeter.Config{Size: 3})

	ta.AddTime(time.Millisecond)

	if ta.Times[0] != time.Millisecond {
		t.Fail()
	}
}

func TestSetWallTime(t *testing.T) {
	ta := tachymeter.New(&tachymeter.Config{Size: 3})

	ta.SetWallTime(time.Millisecond)

	if ta.WallTime != time.Millisecond {
		t.Fail()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"errors"
	"os"
	"testing"
)

const PlaybookFilename = "test-playbook.yml"
const ManifestFilename = "test-manifest.yml"
const PlaybookContents string = `---
name: The Project
meta:
  team: Project Devs
  email: devs@project.com
  slack: devs
vars:
  - version
  - assets_version
  - owner
tasks:
  - name: Deploy Postgres
    manifests:
      - test-manifest.yml
      - test-manifest.yml
  - name: Deploy Redis
    manifests:
      - test-manifest.yml
      - test-manifest.yml
  - name: Database Setup
    pod_manifest: test-manifest.yml
    wait_for:
      - success
    when: new_deployment
  - name: Database Migration
    pod_manifest: test-manifest.yml
    wait_for:
      - success
  - name: Deploy Project
    manifests:
      - test-manifest.yml
      - test-manifest.yml
      - test-manifest.yml
`

var PlaybookBytes = []byte(PlaybookContents)

const PlaybookContentsIncomplete = `---
name: The Project
`

var IncompletePlaybookBytes = []byte(PlaybookContentsIncomplete)

func TestMain(m *testing.M) {
	f, _ := os.Create(PlaybookFilename)
	f.Write(PlaybookBytes)
	f.Close()

	f, _ = os.Create(ManifestFilename)
	f.Close()

	testresult := m.Run()
	teardown()
	os.Exit(testresult)
}
func teardown() {
	os.Remove(PlaybookFilename)
	os.Remove(ManifestFilename)
}

func TestReadPlaybookFromDisk(t *testing.T) {
	playbook, err := ReadPlaybookFromDisk(PlaybookFilename)
	if err != nil {
		t.Error(err)
	}
	if !bytes.Equal(playbook, PlaybookBytes) {
		t.Error(errors.New("Playbook read from disk differs from Playbook written to disk"))
	}
}

func TestParsePlaybook(t *testing.T) {
	var err error
	ParsedPlaybook, err := ParsePlaybook(PlaybookBytes)
	if err != nil {
		t.Error(err)
	}
	if ParsedPlaybook.Name != "The Project" {
		t.Error(errors.New("Parsed Playbook has incorrect Name field"))
	}
}

func TestParsePlaybookMalformed(t *testing.T) {
	_, err := ParsePlaybook([]byte("asdf"))
	if err == nil {
		t.Error(errors.New("Parsing asdf succeeded, expected failure"))
	}
}

func TestParsePlaybookIncomplete(t *testing.T) {
	_, err := ParsePlaybook(IncompletePlaybookBytes)
	if err != nil {
		t.Error(errors.New("Parsing well-formed, incomplete playbook failed, expected success"))
	}
}

func TestValidatePlaybook(t *testing.T) {
	ParsedPlaybook1, _ := ParsePlaybook(PlaybookBytes)
	if err := ParsedPlaybook1.Validate(); err != nil {
		t.Error(err)
	}

	ParsedPlaybook2, _ := ParsePlaybook(IncompletePlaybookBytes)
	if err := ParsedPlaybook2.Validate(); err == nil {
		t.Errorf("Validation of incomplete playbook succeeded, expected error")
	}

	ParsedPlaybook3 := ParsedPlaybook1
	ParsedPlaybook3.Tasks = []Task{
		{
			Manifests: []string{ManifestFilename},
		},
	}
	if err := ParsedPlaybook3.Validate(); err == nil {
		t.Errorf("Validation of playbook with a task missing a name succeeded, expected error")
	}
}

func TestTaskManifestsPresent(t *testing.T) {
	testcases := []struct {
		scenario    string
		task        Task
		errExpected bool
	}{
		{
			"Task With Missing Manifests",
			Task{
				Name:      "task 1",
				Manifests: []string{"pod0"},
			},
			true,
		},
		{
			"Task With Existing Manifests",
			Task{
				Name:      "task 2",
				Manifests: []string{ManifestFilename},
			},
			false,
		},
		{
			"Task With Only Pod Manifest",
			Task{
				Name:        "task 2",
				PodManifest: ManifestFilename,
			},
			false,
		},
	}

	for _, testcase := range testcases {
		task := testcase.task
		err := task.ManifestsPresent()
		if testcase.errExpected {
			if !os.IsNotExist(err) { // it was the wrong error!
				t.Errorf("Scenario %s: Got %s, expected 'not found'", testcase.scenario, err)
			}
		} else if err != nil {
			t.Errorf("Scenario %s: Got %s, expected success", testcase.scenario, err)
		}
	}
}
<commit_msg>Add testcases for playbook validation<commit_after>package main

import (
	"bytes"
	"errors"
	"os"
	"testing"
)

const PlaybookFilename = "test-playbook.yml"
const ManifestFilename = "test-manifest.yml"
const PlaybookContents string = `---
name: The Project
meta:
  team: Project Devs
  email: devs@project.com
  slack: devs
vars:
  - version
  - assets_version
  - owner
tasks:
  - name: Deploy Postgres
    manifests:
      - test-manifest.yml
      - test-manifest.yml
  - name: Deploy Redis
    manifests:
      - test-manifest.yml
      - test-manifest.yml
  - name: Database Setup
    pod_manifest: test-manifest.yml
    wait_for:
      - success
    when: new_deployment
  - name: Database Migration
    pod_manifest: test-manifest.yml
    wait_for:
      - success
  - name: Deploy Project
    manifests:
      - test-manifest.yml
      - test-manifest.yml
      - test-manifest.yml
`

var PlaybookBytes = []byte(PlaybookContents)

const PlaybookContentsIncomplete = `---
name: The Project
`

var IncompletePlaybookBytes = []byte(PlaybookContentsIncomplete)

func TestMain(m *testing.M) {
	f, _ := os.Create(PlaybookFilename)
	f.Write(PlaybookBytes)
	f.Close()

	f, _ = os.Create(ManifestFilename)
	f.Close()

	testresult := m.Run()
	teardown()
	os.Exit(testresult)
}
func teardown() {
	os.Remove(PlaybookFilename)
	os.Remove(ManifestFilename)
}

func TestReadPlaybookFromDisk(t *testing.T) {
	playbook, err := ReadPlaybookFromDisk(PlaybookFilename)
	if err != nil {
		t.Error(err)
	}
	if !bytes.Equal(playbook, PlaybookBytes) {
		t.Error(errors.New("Playbook read from disk differs from Playbook written to disk"))
	}
}

func TestParsePlaybook(t *testing.T) {
	var err error
	ParsedPlaybook, err := ParsePlaybook(PlaybookBytes)
	if err != nil {
		t.Error(err)
	}
	if ParsedPlaybook.Name != "The Project" {
		t.Error(errors.New("Parsed Playbook has incorrect Name field"))
	}
}

func TestParsePlaybookMalformed(t *testing.T) {
	_, err := ParsePlaybook([]byte("asdf"))
	if err == nil {
		t.Error(errors.New("Parsing asdf succeeded, expected failure"))
	}
}

func TestParsePlaybookIncomplete(t *testing.T) {
	_, err := ParsePlaybook(IncompletePlaybookBytes)
	if err != nil {
		t.Error(errors.New("Parsing well-formed, incomplete playbook failed, expected success"))
	}
}

func TestValidatePlaybook(t *testing.T) {
	ValidTask := Task{
		Name:      "task",
		Manifests: []string{ManifestFilename},
	}
	InvalidTask1 := Task{
		Manifests: []string{ManifestFilename},
	}
	InvalidTask2 := Task{
		Name: "task",
	}

	testcases := []struct {
		scenario    string
		playbook    Playbook
		errExpected bool
	}{
		{
			"Validate Valid Playbook",
			Playbook{
				Name:  "playbook 1",
				Tasks: []Task{ValidTask},
			},
			false,
		},
		{
			"Validate Empty Playbook",
			Playbook{},
			true,
		},
		{
			"Validate Playbook With Tasks Missing Names",
			Playbook{
				Name:  "playbook 1",
				Tasks: []Task{InvalidTask1},
			},
			true,
		},
		{
			"Validate Playbook With Tasks Missing Manifests",
			Playbook{
				Name:  "playbook 1",
				Tasks: []Task{InvalidTask2},
			},
			true,
		},
	}

	for _, testcase := range testcases {
		playbook := testcase.playbook
		err := playbook.Validate()
		if testcase.errExpected && err != nil {
			continue
		} else if testcase.errExpected && err == nil {
			t.Errorf("Scenario %s: Succeeded, expected failure", testcase.scenario)
		} else if err != nil {
			t.Errorf("Scenario %s: Failed with %s, expected success", testcase.scenario, err)
		}
	}
}

func TestTaskManifestsPresent(t *testing.T) {
	testcases := []struct {
		scenario    string
		task        Task
		errExpected bool
	}{
		{
			"Task With Missing Manifests",
			Task{
				Name:      "task 1",
				Manifests: []string{"pod0"},
			},
			true,
		},
		{
			"Task With Existing Manifests",
			Task{
				Name:      "task 2",
				Manifests: []string{ManifestFilename},
			},
			false,
		},
		{
			"Task With Only Pod Manifest",
			Task{
				Name:        "task 2",
				PodManifest: ManifestFilename,
			},
			false,
		},
	}

	for _, testcase := range testcases {
		task := testcase.task
		err := task.ManifestsPresent()
		if testcase.errExpected {
			if !os.IsNotExist(err) { // it was the wrong error!
				t.Errorf("Scenario %s: Got %s, expected 'not found'", testcase.scenario, err)
			}
		} else if err != nil {
			t.Errorf("Scenario %s: Got %s, expected success", testcase.scenario, err)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"path"
	"testing"

	"github.com/intelsdi-x/pulse/control"
	"github.com/intelsdi-x/pulse/plugin/helper"
	. "github.com/smartystreets/goconvey/convey"
)

var (
	PluginName = "pulse-publisher-hana"
	PluginType = "publisher"
	PulsePath  = os.Getenv("PULSE_PATH")
	PluginPath = path.Join(PulsePath, "plugin", PluginName)
)

func TestHANAPublisherLoad(t *testing.T) {
	// These tests only work if PULSE_PATH is known.
	// It is the responsibility of the testing framework to
	// build the plugins first into the build dir.
	if PulsePath != "" {
		// Helper plugin trigger build if possible for this plugin
		helper.BuildPlugin(PluginType, PluginName)
		//
		//TODO cannot test this locally. We need AMQP and integration tests.
		SkipConvey("ensure plugin loads and responds", t, func() {
			c := control.New()
			c.Start()
			_, err := c.Load(PluginPath)

			So(err, ShouldBeNil)
		})
	} else {
		fmt.Printf("PULSE_PATH not set. Cannot test %s plugin.\n", PluginName)
	}
}

func TestMain(t *testing.T) {
	Convey("ensure plugin loads and responds", t, func() {
		os.Args = []string{"", "{\"NoDaemon\": true}"}
		So(func() { main() }, ShouldNotPanic)
	})
}
<commit_msg>Update main_test.go to align with other plugins<commit_after>// +build unit

package main

import (
	"os"
	"testing"

	. "github.com/smartystreets/goconvey/convey"
)

func TestMain(t *testing.T) {
	Convey("ensure plugin loads and responds", t, func() {
		os.Args = []string{"", "{\"NoDaemon\": true}"}
		So(func() { main() }, ShouldNotPanic)
	})
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/gocql/gocql"
	"log"
	"os"
	"strings"
	"testing"
)

func setup() {
	log.Println("SETTING UP")

	_, testSession := createTestConnection()
	session = testSession
	connectionEstablished = true
}

func tearDown() {
	log.Println("TEARING DOWN")

	destroyTestConnection(session)
}

func TestMain(m *testing.M) {
	setup()

	retCode := m.Run()

	tearDown()

	os.Exit(retCode)
}

var test_keyspace = "test_keyspace"

func testInitialQuery() string {
	return `
    CREATE KEYSPACE IF NOT EXISTS ` + test_keyspace + ` WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 };
    CREATE TABLE IF NOT EXISTS ` + test_keyspace + `.alert (
      id timeuuid PRIMARY KEY,
      name varchar,
      required_criteria text,
      nice_to_have_criteria text,
      excluded_criteria text,
      owner_id int,
      status int,
      threshold int
    );
    CREATE INDEX IF NOT EXISTS by_owner_id ON ` + test_keyspace + `.alert("owner_id");`
}

func createTestConnection() (*gocql.ClusterConfig, *gocql.Session) {
	cassandraNodes := "localhost:9042"
	cluster := gocql.NewCluster(strings.Split(cassandraNodes, ",")...)

	cluster.Timeout = cassandraConnectTimeout
	cluster.DisableInitialHostLookup = true

	var sessionErr error
	initSession, sessionErr := cluster.CreateSession()

	if sessionErr != nil {
		log.Fatal("Could NOT create test Cassandra session: " + sessionErr.Error())
	}

	executeInitialQuery(initSession, testInitialQuery())
	initSession.Close()

	cluster.Keyspace = test_keyspace
	session, _ := cluster.CreateSession()

	return cluster, session
}

func destroyTestConnection(session *gocql.Session) {
	defer session.Close()

	session.Query("truncate " + test_keyspace + ".alert").Exec()
	session.Query("drop keyspace " + test_keyspace).Exec()
}
<commit_msg>#0 add env variable for cassandra nodes for testing (#13)<commit_after>package main

import (
	"github.com/gocql/gocql"
	"log"
	"os"
	"strings"
	"testing"
)

func setup() {
	log.Println("SETTING UP")

	_, testSession := createTestConnection()
	session = testSession
	connectionEstablished = true
}

func TestMain(m *testing.M) {
	setup()

	retCode := m.Run()

	tearDown()

	os.Exit(retCode)
}

func tearDown() {
	log.Println("TEARING DOWN")

	destroyTestConnection(session)
}

var test_keyspace = "test_keyspace"

func testInitialQuery() string {
	return `
    CREATE KEYSPACE IF NOT EXISTS ` + test_keyspace + ` WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 };
    CREATE TABLE IF NOT EXISTS ` + test_keyspace + `.alert (
      id timeuuid PRIMARY KEY,
      name varchar,
      required_criteria text,
      nice_to_have_criteria text,
      excluded_criteria text,
      owner_id int,
      status int,
      threshold int
    );
    CREATE INDEX IF NOT EXISTS by_owner_id ON ` + test_keyspace + `.alert("owner_id");`
}

func createTestConnection() (*gocql.ClusterConfig, *gocql.Session) {
	cassandraNodes := os.Getenv("CASSANDRA_NODES_TEST")

	if cassandraNodes == "" {
		log.Fatal("Please specify CASSANDRA_NODES_TEST env variable for testing")
	}

	cluster := gocql.NewCluster(strings.Split(cassandraNodes, ",")...)

	cluster.Timeout = cassandraConnectTimeout
	cluster.DisableInitialHostLookup = true

	var sessionErr error
	initSession, sessionErr := cluster.CreateSession()

	if sessionErr != nil {
		log.Fatal("Could NOT create test Cassandra session: " + sessionErr.Error())
	}

	executeInitialQuery(initSession, testInitialQuery())
	initSession.Close()

	cluster.Keyspace = test_keyspace
	session, _ := cluster.CreateSession()

	return cluster, session
}

func destroyTestConnection(session *gocql.Session) {
	defer session.Close()

	session.Query("truncate " + test_keyspace + ".alert").Exec()
	session.Query("drop keyspace " + test_keyspace).Exec()
}
<|endoftext|>


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

package main

import (
	"bytes"
	"encoding/json"
	"os"
	"os/exec"
	"testing"
)

const apigeecli = "./apigeecli"

var token = os.Getenv("APIGEE_TOKEN")
var env = os.Getenv("APIGEE_ENV")
var org = os.Getenv("APIGEE_ORG")

const email = "test@gmail.com"
const name = "test"
const attrs = "\"foo1=bar1,foo2=bar2\""
const envs = "test"

var appID string

func TestMain(t *testing.T) {
	cmd := exec.Command(apigeecli)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

// orgs test
func TestListOrgs(t *testing.T) {
	cmd := exec.Command(apigeecli, "orgs", "list", "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestGetOrg(t *testing.T) {
	cmd := exec.Command(apigeecli, "orgs", "get", "-o", org, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

// env tests
func TestListEnvs(t *testing.T) {
	cmd := exec.Command(apigeecli, "envs", "list", "-o", org, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestGetEnv(t *testing.T) {
	cmd := exec.Command(apigeecli, "envs", "get", "-o", org, "-e", env, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

// developers test
func TestCreateDeveloper(t *testing.T) {
	first := "frstname"
	last := "lastname"
	user := "username"

	cmd := exec.Command(apigeecli, "developers", "create", "-o", org, "-n", email, "-f", first, "-s",
		last, "-u", user, "--attrs", attrs, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestGetDeveloper(t *testing.T) {

	cmd := exec.Command(apigeecli, "developers", "get", "-o", org, "-n", email, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestListDeveloper(t *testing.T) {

	cmd := exec.Command(apigeecli, "developers", "list", "-o", org, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestListExpandDeveloper(t *testing.T) {
	expand := "true"

	cmd := exec.Command(apigeecli, "developers", "list", "-o", org, "-x", expand, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

// kvm test
func TestCreateKVM(t *testing.T) {

	cmd := exec.Command(apigeecli, "kvms", "create", "-o", org, "-e", env, "-n", name, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestListKVM(t *testing.T) {

	cmd := exec.Command(apigeecli, "kvms", "list", "-o", org, "-e", env, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

// sync tests
func TestGetSync(t *testing.T) {

	cmd := exec.Command(apigeecli, "sync", "get", "-o", org, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestSetSync(t *testing.T) {
	ity := "test@gmail.com"
	cmd := exec.Command(apigeecli, "sync", "set", "-o", org, "-i", ity, "-t", token)
	err := cmd.Run()
	if err == nil {
		t.Fatal("Invalid identity test should have failed")
	}
}

func TestCreateProxy(t *testing.T) {
	cmd := exec.Command(apigeecli, "apis", "create", "-o", org, "-n", name, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestCreateProductLegacy(t *testing.T) {
	proxy := "test"
	approval := "auto"

	cmd := exec.Command(apigeecli, "products", "create", "-o", org, "-n", name+"-legacy", "-e", envs, "-p", proxy,
		"-f", approval, "--attrs", attrs, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestCreateProductGroup(t *testing.T) {
	proxy := "test"
	approval := "auto"
	operationGroupFile := "./test/apiproduct-op-group.json"

	cmd := exec.Command(apigeecli, "products", "create", "-o", org, "-n", name+"-group", "-e", envs,
		"-g", operationGroupFile, "-f", approval, "--attrs", attrs, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestCreateApp(t *testing.T) {
	product := "test"

	cmd := exec.Command(apigeecli, "apps", "create", "-o", org, "-n", name, "-e", email, "-p", product,
		"--attrs", attrs, "-t", token)

	var out bytes.Buffer
	cmd.Stdout = &out

	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}

	var outputMap map[string]string
	_ = json.Unmarshal(out.Bytes(), &outputMap)
	appID = outputMap["appId"]
}

func TestListApp(t *testing.T) {

	cmd := exec.Command(apigeecli, "apps", "list", "-o", org, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}

}

func TestGetProduct(t *testing.T) {

	cmd := exec.Command(apigeecli, "products", "get", "-o", org, "-n", name, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestListProduct(t *testing.T) {

	cmd := exec.Command(apigeecli, "products", "list", "-o", org, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestDeleteDeveloper(t *testing.T) {

	cmd := exec.Command(apigeecli, "developers", "delete", "-o", org, "-n", email, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestCreateTS(t *testing.T) {
	host := "example.com"

	cmd := exec.Command(apigeecli, "targetservers", "create", "-o", org, "-n", name, "-e", env, "-s",
		host, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}

}

func TestGetTS(t *testing.T) {

	cmd := exec.Command(apigeecli, "targetservers", "get", "-o", org, "-e", env, "-n", name, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}

}

func TestListTS(t *testing.T) {

	cmd := exec.Command(apigeecli, "targetservers", "list", "-o", org, "-e", env, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}

}

func TestDeleteTS(t *testing.T) {

	cmd := exec.Command(apigeecli, "targetservers", "delete", "-o", org, "-e", env, "-n", name, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}

}

func TestExportProducts(t *testing.T) {

	cmd := exec.Command(apigeecli, "products", "export", "-o", org, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestDeleteKVM(t *testing.T) {

	cmd := exec.Command(apigeecli, "kvms", "delete", "-o", org, "-e", env, "-n", name, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestDeleteProduct(t *testing.T) {

	cmd := exec.Command(apigeecli, "products", "delete", "-o", org, "-n", name, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestCreateEncKVM(t *testing.T) {
	name := "testEnc"

	cmd := exec.Command(apigeecli, "kvms", "create", "-o", org, "-e", env, "-n", name, "-c", "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestDeleteEncKVM(t *testing.T) {
	name := "testEnc"

	cmd := exec.Command(apigeecli, "kvms", "delete", "-o", org, "-e", env, "-n", name, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestDeleteProxy(t *testing.T) {
	cmd := exec.Command(apigeecli, "apis", "delete", "-o", org, "-n", name, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestCreateResource(t *testing.T) {
	name := "test.js"
	resType := "jsc"
	resPath := "./test/test.js"
	cmd := exec.Command(apigeecli, "resources", "create", "-o", org, "-e", env, "-n", name, "-p", resType, "-r", resPath)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestGetResource(t *testing.T) {
	name := "test.js"
	resType := "jsc"
	cmd := exec.Command(apigeecli, "resources", "get", "-o", org, "-e", env, "-n", name, "-p", resType)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestListResources(t *testing.T) {
	cmd := exec.Command(apigeecli, "resources", "list", "-o", org, "-e", env)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestDeleteResource(t *testing.T) {
	name := "test.js"
	resType := "jsc"
	cmd := exec.Command(apigeecli, "resources", "delete", "-o", org, "-e", env, "-n", name, "-p", resType)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

/*func TestCreateKeyStore(t *testing.T) {
	name := "testkeystore"
	cmd := exec.Command(apigeecli, "keystores", "create", "-o", org, "-e", env,
		"-n", name)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestCreateKeyAliasSelfSigned(t *testing.T) {
	payload := "{\"alias\": \"self\",\"keySize\": \"2048\",\"sigAlg\": \"SHA256withRSA\",\"subject\"" +
		"{\"commonName\": \"nandan\",\"email\": \"test@test.com\"},\"certValidityInDays\": \"10\"}"
	name := "testkeystore"
	keyaliasname := "selfkeyalias"
	cmd := exec.Command(apigeecli, "keyaliases", "create-self-signed", "-o", org, "-e", env,
		"-n", name, "-s", keyaliasname, "-c", payload)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}*/

//get requires an app id. run list and get an app id or get it from create
/*func TestGetApp(t *testing.T) {
	cmd := exec.Command(apigeecli, "apps", "get", "-o", org, "-i", appID, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}

}*/

/*func TestSetMart(t *testing.T) {
	mart := os.Getenv("MART")
	if mart == "" {
		t.Log("MART not set, skipping")
	} else {
		cmd := exec.Command(apigeecli, "orgs", "setmart", "-o", org, "-m", mart, "-t", token)
		err := cmd.Run()
		if err != nil {
			t.Fatal(err)
		}
	}
}

func TestSetMartWhiteList(t *testing.T) {
	mart := os.Getenv("MART")
	if mart == "" {
		t.Log("MART not set, skipping")
	} else {
		cmd := exec.Command(apigeecli, "orgs", "setmart", "-o", org, "-m", mart, "-w", "false", "-t", token)
		err := cmd.Run()
		if err != nil {
			t.Fatal(err)
		}
	}
}

func TestDeleteApp(t *testing.T) {

	cmd := exec.Command(apigeecli, "apps", "delete", "-o", org, "-n", name, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}

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

package main

import (
	"bytes"
	"encoding/json"
	"os"
	"os/exec"
	"testing"
)

const apigeecli = "./apigeecli"

var token = os.Getenv("APIGEE_TOKEN")
var env = os.Getenv("APIGEE_ENV")
var org = os.Getenv("APIGEE_ORG")

const email = "test@gmail.com"
const name = "test"
const attrs = "\"foo1=bar1,foo2=bar2\""
const envs = "test"

var appID string

func TestMain(t *testing.T) {
	cmd := exec.Command(apigeecli)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

// orgs test
func TestListOrgs(t *testing.T) {
	cmd := exec.Command(apigeecli, "orgs", "list", "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestGetOrg(t *testing.T) {
	cmd := exec.Command(apigeecli, "orgs", "get", "-o", org, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

// env tests
func TestListEnvs(t *testing.T) {
	cmd := exec.Command(apigeecli, "envs", "list", "-o", org, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestGetEnv(t *testing.T) {
	cmd := exec.Command(apigeecli, "envs", "get", "-o", org, "-e", env, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

// developers test
func TestCreateDeveloper(t *testing.T) {
	first := "frstname"
	last := "lastname"
	user := "username"

	cmd := exec.Command(apigeecli, "developers", "create", "-o", org, "-n", email, "-f", first, "-s",
		last, "-u", user, "--attrs", attrs, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestGetDeveloper(t *testing.T) {

	cmd := exec.Command(apigeecli, "developers", "get", "-o", org, "-n", email, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestListDeveloper(t *testing.T) {

	cmd := exec.Command(apigeecli, "developers", "list", "-o", org, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestListExpandDeveloper(t *testing.T) {
	expand := "true"

	cmd := exec.Command(apigeecli, "developers", "list", "-o", org, "-x", expand, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

// kvm test
func TestCreateKVM(t *testing.T) {

	cmd := exec.Command(apigeecli, "kvms", "create", "-o", org, "-e", env, "-n", name, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestListKVM(t *testing.T) {

	cmd := exec.Command(apigeecli, "kvms", "list", "-o", org, "-e", env, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

// sync tests
func TestGetSync(t *testing.T) {

	cmd := exec.Command(apigeecli, "sync", "get", "-o", org, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestSetSync(t *testing.T) {
	ity := "test@gmail.com"
	cmd := exec.Command(apigeecli, "sync", "set", "-o", org, "-i", ity, "-t", token)
	err := cmd.Run()
	if err == nil {
		t.Fatal("Invalid identity test should have failed")
	}
}

func TestCreateProxy(t *testing.T) {
	cmd := exec.Command(apigeecli, "apis", "create", "-o", org, "-n", name, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestCreateProductLegacy(t *testing.T) {
	proxy := "test"
	approval := "auto"

	cmd := exec.Command(apigeecli, "products", "create", "-o", org, "-n", name+"-legacy", "-e", envs, "-p", proxy,
		"-f", approval, "--attrs", attrs, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestCreateProductGroup(t *testing.T) {
	approval := "auto"
	operationGroupFile := "./test/apiproduct-op-group.json"

	cmd := exec.Command(apigeecli, "products", "create", "-o", org, "-n", name+"-group", "-e", envs,
		"-g", operationGroupFile, "-f", approval, "--attrs", attrs, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestCreateApp(t *testing.T) {
	product := "test"

	cmd := exec.Command(apigeecli, "apps", "create", "-o", org, "-n", name, "-e", email, "-p", product,
		"--attrs", attrs, "-t", token)

	var out bytes.Buffer
	cmd.Stdout = &out

	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}

	var outputMap map[string]string
	_ = json.Unmarshal(out.Bytes(), &outputMap)
	appID = outputMap["appId"]
}

func TestListApp(t *testing.T) {

	cmd := exec.Command(apigeecli, "apps", "list", "-o", org, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}

}

func TestGetProduct(t *testing.T) {

	cmd := exec.Command(apigeecli, "products", "get", "-o", org, "-n", name, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestListProduct(t *testing.T) {

	cmd := exec.Command(apigeecli, "products", "list", "-o", org, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestDeleteDeveloper(t *testing.T) {

	cmd := exec.Command(apigeecli, "developers", "delete", "-o", org, "-n", email, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestCreateTS(t *testing.T) {
	host := "example.com"

	cmd := exec.Command(apigeecli, "targetservers", "create", "-o", org, "-n", name, "-e", env, "-s",
		host, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}

}

func TestGetTS(t *testing.T) {

	cmd := exec.Command(apigeecli, "targetservers", "get", "-o", org, "-e", env, "-n", name, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}

}

func TestListTS(t *testing.T) {

	cmd := exec.Command(apigeecli, "targetservers", "list", "-o", org, "-e", env, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}

}

func TestDeleteTS(t *testing.T) {

	cmd := exec.Command(apigeecli, "targetservers", "delete", "-o", org, "-e", env, "-n", name, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}

}

func TestExportProducts(t *testing.T) {

	cmd := exec.Command(apigeecli, "products", "export", "-o", org, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestDeleteKVM(t *testing.T) {

	cmd := exec.Command(apigeecli, "kvms", "delete", "-o", org, "-e", env, "-n", name, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestDeleteProduct(t *testing.T) {

	cmd := exec.Command(apigeecli, "products", "delete", "-o", org, "-n", name, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestCreateEncKVM(t *testing.T) {
	name := "testEnc"

	cmd := exec.Command(apigeecli, "kvms", "create", "-o", org, "-e", env, "-n", name, "-c", "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestDeleteEncKVM(t *testing.T) {
	name := "testEnc"

	cmd := exec.Command(apigeecli, "kvms", "delete", "-o", org, "-e", env, "-n", name, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestDeleteProxy(t *testing.T) {
	cmd := exec.Command(apigeecli, "apis", "delete", "-o", org, "-n", name, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestCreateResource(t *testing.T) {
	name := "test.js"
	resType := "jsc"
	resPath := "./test/test.js"
	cmd := exec.Command(apigeecli, "resources", "create", "-o", org, "-e", env, "-n", name, "-p", resType, "-r", resPath)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestGetResource(t *testing.T) {
	name := "test.js"
	resType := "jsc"
	cmd := exec.Command(apigeecli, "resources", "get", "-o", org, "-e", env, "-n", name, "-p", resType)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestListResources(t *testing.T) {
	cmd := exec.Command(apigeecli, "resources", "list", "-o", org, "-e", env)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestDeleteResource(t *testing.T) {
	name := "test.js"
	resType := "jsc"
	cmd := exec.Command(apigeecli, "resources", "delete", "-o", org, "-e", env, "-n", name, "-p", resType)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

/*func TestCreateKeyStore(t *testing.T) {
	name := "testkeystore"
	cmd := exec.Command(apigeecli, "keystores", "create", "-o", org, "-e", env,
		"-n", name)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}

func TestCreateKeyAliasSelfSigned(t *testing.T) {
	payload := "{\"alias\": \"self\",\"keySize\": \"2048\",\"sigAlg\": \"SHA256withRSA\",\"subject\"" +
		"{\"commonName\": \"nandan\",\"email\": \"test@test.com\"},\"certValidityInDays\": \"10\"}"
	name := "testkeystore"
	keyaliasname := "selfkeyalias"
	cmd := exec.Command(apigeecli, "keyaliases", "create-self-signed", "-o", org, "-e", env,
		"-n", name, "-s", keyaliasname, "-c", payload)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
}*/

//get requires an app id. run list and get an app id or get it from create
/*func TestGetApp(t *testing.T) {
	cmd := exec.Command(apigeecli, "apps", "get", "-o", org, "-i", appID, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}

}*/

/*func TestSetMart(t *testing.T) {
	mart := os.Getenv("MART")
	if mart == "" {
		t.Log("MART not set, skipping")
	} else {
		cmd := exec.Command(apigeecli, "orgs", "setmart", "-o", org, "-m", mart, "-t", token)
		err := cmd.Run()
		if err != nil {
			t.Fatal(err)
		}
	}
}

func TestSetMartWhiteList(t *testing.T) {
	mart := os.Getenv("MART")
	if mart == "" {
		t.Log("MART not set, skipping")
	} else {
		cmd := exec.Command(apigeecli, "orgs", "setmart", "-o", org, "-m", mart, "-w", "false", "-t", token)
		err := cmd.Run()
		if err != nil {
			t.Fatal(err)
		}
	}
}

func TestDeleteApp(t *testing.T) {

	cmd := exec.Command(apigeecli, "apps", "delete", "-o", org, "-n", name, "-t", token)
	err := cmd.Run()
	if err != nil {
		t.Fatal(err)
	}

}
*/
<|endoftext|>


<commit_before>package lfs

import (
	"errors"
	"fmt"
	"github.com/github/git-lfs/git"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
)

var (
	valueRegexp           = regexp.MustCompile("\\Agit[\\-\\s]media")
	prePushHook           = []byte("#!/bin/sh\ngit lfs push --stdin $*\n")
	NotInARepositoryError = errors.New("Not in a repository")
)

type HookExists struct {
	Name string
	Path string
}

func (e *HookExists) Error() string {
	return fmt.Sprintf("Hook already exists: %s", e.Name)
}

func InstallHooks(force bool) error {
	if !InRepo() {
		return NotInARepositoryError
	}

	if err := os.MkdirAll(filepath.Join(LocalGitDir, "hooks"), 0755); err != nil {
		return err
	}

	hookPath := filepath.Join(LocalGitDir, "hooks", "pre-push")
	if _, err := os.Stat(hookPath); err == nil && !force {
		return &HookExists{"pre-push", hookPath}
	} else {
		return ioutil.WriteFile(hookPath, prePushHook, 0755)
	}
}

func InstallFilters() error {
	var err error
	err = setFilter("clean")
	if err == nil {
		err = setFilter("smudge")
	}
	if err == nil {
		err = requireFilters()
	}
	return err
}

func setFilter(filterName string) error {
	key := fmt.Sprintf("filter.lfs.%s", filterName)
	value := fmt.Sprintf("git lfs %s %%f", filterName)

	existing := git.Config.Find(key)
	if shouldReset(existing) {
		git.Config.UnsetGlobal(key)
		git.Config.SetGlobal(key, value)
	} else if existing != value {
		return fmt.Errorf("The %s filter should be \"%s\" but is \"%s\"", filterName, value, existing)
	}

	return nil
}

func requireFilters() error {
	key := "filter.lfs.required"
	value := "true"

	existing := git.Config.Find(key)
	if shouldReset(existing) {
		git.Config.UnsetGlobal(key)
		git.Config.SetGlobal(key, value)
	} else if existing != value {
		return errors.New("Git LFS filters should be required but are not.")
	}

	return nil
}

func shouldReset(value string) bool {
	if len(value) == 0 {
		return true
	}
	return valueRegexp.MatchString(value)
}
<commit_msg>アー アアアア アーアー<commit_after>package lfs

import (
	"errors"
	"fmt"
	"github.com/github/git-lfs/git"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
)

var (
	valueRegexp           = regexp.MustCompile("\\Agit[\\-\\s]media")
	prePushHook           = []byte("#!/bin/sh\ngit lfs push --stdin \"$@\"\n")
	NotInARepositoryError = errors.New("Not in a repository")
)

type HookExists struct {
	Name string
	Path string
}

func (e *HookExists) Error() string {
	return fmt.Sprintf("Hook already exists: %s", e.Name)
}

func InstallHooks(force bool) error {
	if !InRepo() {
		return NotInARepositoryError
	}

	if err := os.MkdirAll(filepath.Join(LocalGitDir, "hooks"), 0755); err != nil {
		return err
	}

	hookPath := filepath.Join(LocalGitDir, "hooks", "pre-push")
	if _, err := os.Stat(hookPath); err == nil && !force {
		return &HookExists{"pre-push", hookPath}
	} else {
		return ioutil.WriteFile(hookPath, prePushHook, 0755)
	}
}

func InstallFilters() error {
	var err error
	err = setFilter("clean")
	if err == nil {
		err = setFilter("smudge")
	}
	if err == nil {
		err = requireFilters()
	}
	return err
}

func setFilter(filterName string) error {
	key := fmt.Sprintf("filter.lfs.%s", filterName)
	value := fmt.Sprintf("git lfs %s %%f", filterName)

	existing := git.Config.Find(key)
	if shouldReset(existing) {
		git.Config.UnsetGlobal(key)
		git.Config.SetGlobal(key, value)
	} else if existing != value {
		return fmt.Errorf("The %s filter should be \"%s\" but is \"%s\"", filterName, value, existing)
	}

	return nil
}

func requireFilters() error {
	key := "filter.lfs.required"
	value := "true"

	existing := git.Config.Find(key)
	if shouldReset(existing) {
		git.Config.UnsetGlobal(key)
		git.Config.SetGlobal(key, value)
	} else if existing != value {
		return errors.New("Git LFS filters should be required but are not.")
	}

	return nil
}

func shouldReset(value string) bool {
	if len(value) == 0 {
		return true
	}
	return valueRegexp.MatchString(value)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"text/template"

	"github.com/PuerkitoBio/goquery"
	"github.com/avelino/slugify"
)

type Link struct {
	Title       string
	Url         string
	Description string
}

type Object struct {
	Title       string
	Slug        string
	Description string
	Items       []Link
}

func main() {
	GenerateHTML()
	input, err := ioutil.ReadFile("./tmpl/index.html")
	if err != nil {
		panic(err)
	}
	buf := bytes.NewBuffer(input)
	query, err := goquery.NewDocumentFromReader(buf)
	if err != nil {
		panic(err)
	}

	objs := []Object{}
	query.Find("body #content ul ul").First().Each(func(_ int, s *goquery.Selection) {

		s.Find("li a").Each(func(_ int, s *goquery.Selection) {
			selector, _ := s.Attr("href")
			obj := makeObjById(selector, query.Find("body"))
			objs = append(objs, obj)
		})
	})

	makeSiteStruct(objs)
	makeSitemap(objs)
}

func makeSiteStruct(objs []Object) {
	for _, obj := range objs {
		folder := fmt.Sprintf("tmpl/%s", obj.Slug)
		fmt.Println(folder)

		err := os.Mkdir(folder, 0755)
		if err != nil {
			log.Println(err)
		}

		t := template.Must(template.ParseFiles("tmpl/cat-tmpl.html"))
		f, _ := os.Create(fmt.Sprintf("%s/index.html", folder))
		t.Execute(f, obj)
	}
}

func makeSitemap(objs []Object) {
	t := template.Must(template.ParseFiles("tmpl/sitemap-tmpl.xml"))
	f, _ := os.Create("tmpl/sitemap.xml")
	t.Execute(f, objs)
}

func makeObjById(selector string, s *goquery.Selection) (obj Object) {
	s.Find(selector).Each(func(_ int, s *goquery.Selection) {
		desc := s.NextFiltered("p")
		ul := desc.NextFiltered("ul")

		links := []Link{}
		ul.Find("li").Each(func(_ int, s *goquery.Selection) {
			url, _ := s.Find("a").Attr("href")
			link := Link{
				Title:       s.Find("a").Text(),
				Description: s.Text(),
				Url:         url,
			}
			links = append(links, link)
		})
		obj = Object{
			Slug:        slugify.Slugify(s.Text()),
			Title:       s.Text(),
			Description: desc.Text(),
			Items:       links,
		}
	})
	return
}
<commit_msg>remove debug/print<commit_after>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"text/template"

	"github.com/PuerkitoBio/goquery"
	"github.com/avelino/slugify"
)

type Link struct {
	Title       string
	Url         string
	Description string
}

type Object struct {
	Title       string
	Slug        string
	Description string
	Items       []Link
}

func main() {
	GenerateHTML()
	input, err := ioutil.ReadFile("./tmpl/index.html")
	if err != nil {
		panic(err)
	}
	buf := bytes.NewBuffer(input)
	query, err := goquery.NewDocumentFromReader(buf)
	if err != nil {
		panic(err)
	}

	objs := []Object{}
	query.Find("body #content ul ul").First().Each(func(_ int, s *goquery.Selection) {

		s.Find("li a").Each(func(_ int, s *goquery.Selection) {
			selector, _ := s.Attr("href")
			obj := makeObjById(selector, query.Find("body"))
			objs = append(objs, obj)
		})
	})

	makeSiteStruct(objs)
	makeSitemap(objs)
}

func makeSiteStruct(objs []Object) {
	for _, obj := range objs {
		folder := fmt.Sprintf("tmpl/%s", obj.Slug)
		err := os.Mkdir(folder, 0755)
		if err != nil {
			log.Println(err)
		}

		t := template.Must(template.ParseFiles("tmpl/cat-tmpl.html"))
		f, _ := os.Create(fmt.Sprintf("%s/index.html", folder))
		t.Execute(f, obj)
	}
}

func makeSitemap(objs []Object) {
	t := template.Must(template.ParseFiles("tmpl/sitemap-tmpl.xml"))
	f, _ := os.Create("tmpl/sitemap.xml")
	t.Execute(f, objs)
}

func makeObjById(selector string, s *goquery.Selection) (obj Object) {
	s.Find(selector).Each(func(_ int, s *goquery.Selection) {
		desc := s.NextFiltered("p")
		ul := desc.NextFiltered("ul")

		links := []Link{}
		ul.Find("li").Each(func(_ int, s *goquery.Selection) {
			url, _ := s.Find("a").Attr("href")
			link := Link{
				Title:       s.Find("a").Text(),
				Description: s.Text(),
				Url:         url,
			}
			links = append(links, link)
		})
		obj = Object{
			Slug:        slugify.Slugify(s.Text()),
			Title:       s.Text(),
			Description: desc.Text(),
			Items:       links,
		}
	})
	return
}
<|endoftext|>


<commit_before>package srcgraph

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"sync"

	"sourcegraph.com/sourcegraph/srcgraph/buildstore"
	"sourcegraph.com/sourcegraph/srcgraph/util2"

	"testing"

	"github.com/aybabtme/color/brush"
)

var mode = flag.String("test.mode", "test", "[test|keep|gen] 'test' runs test as normal; keep keeps around generated test files for inspection after tests complete; 'gen' generates new expected test data")
var repoMatch = flag.String("test.repo", "", "only test `srcgraph make` for repos that contain this string")

func TestMakeCmd(t *testing.T) {
	// Since we exec `srcgraph`, make sure it's up-to-date.
	if out, err := exec.Command("make", "-C", "..", "srcgraph").CombinedOutput(); err != nil {
		t.Errorf("Failed to build srcgraph for `srcgraph make` tests: %s.\n\nOutput was:\n%s", err, out)
		return
	}

	cmd := exec.Command("git", "submodule", "update", "--init", "srcgraph/testdata/repos")
	cmd.Dir = ".."
	if out, err := cmd.CombinedOutput(); err != nil {
		t.Errorf("Failed to update or init git submodules: %s.\n\nOutput was:\n%s", err, out)
		return
	}

	const testReposDir = "testdata/repos"
	fis, err := ioutil.ReadDir("testdata/repos")
	if err != nil {
		t.Fatal(err)
	}
	n := 0
	var wg sync.WaitGroup
	for _, fi := range fis {
		if repoDir := fi.Name(); strings.Contains(repoDir, *repoMatch) {
			fullRepoDir := filepath.Join(testReposDir, repoDir)
			wg.Add(1)
			go func() {
				defer wg.Done()
				testMakeCmd(t, fullRepoDir)
			}()
			n++
		}
	}
	wg.Wait()
	if n == 0 {
		t.Errorf("No TestMakeCmd cases were run. Did none match your constraint -test.match=%q?", *repoMatch)
	}
}

func testMakeCmd(t *testing.T, repoDir string) {
	repoName := filepath.Base(repoDir)

	// Directories for the actual ("got") and expected ("want") outputs.
	gotOutputDir := filepath.Join(repoDir, "../../repos-output/got", repoName)
	wantOutputDir := filepath.Join(repoDir, "../../repos-output/want", repoName)

	// Determine and wipe the desired output dir.
	var outputDir string
	if *mode == "gen" {
		outputDir = wantOutputDir
	} else {
		outputDir = gotOutputDir
	}
	outputDir, _ = filepath.Abs(outputDir)
	if err := os.RemoveAll(outputDir); err != nil {
		t.Fatal(err)
	}
	if err := os.MkdirAll(outputDir, 0755); err != nil {
		t.Fatal(err)
	}

	// Symlink ${repoDir}/.sourcegraph-data/${commitID} to the desired output dir.
	origOutputDestDir := filepath.Join(repoDir, buildstore.BuildDataDirName, getHEADOrTipCommitID(t, repoDir))
	if err := os.Mkdir(filepath.Dir(origOutputDestDir), 0755); err != nil && !os.IsExist(err) {
		t.Fatal(err)
	}
	if err := os.Remove(origOutputDestDir); err != nil && !os.IsNotExist(err) {
		t.Fatal(err)
	}
	if err := os.Symlink(outputDir, origOutputDestDir); err != nil {
		t.Error(err)
		return
	}
	defer func() {
		// Remove the symlink when we're done so the repo doesn't have
		// uncommitted changes.
		if err := os.Remove(origOutputDestDir); err != nil {
			t.Fatal(err)
		}
	}()

	// Run `srcgraph make`.
	var w io.Writer
	var buf bytes.Buffer
	if testing.Verbose() {
		w = io.MultiWriter(&buf, os.Stderr)
	} else {
		w = &buf
	}
	cmd := exec.Command("srcgraph", "-v", "make")
	cmd.Stderr, cmd.Stdout = w, w
	cmd.Dir = repoDir

	err := cmd.Run()
	if err != nil {
		t.Errorf("Command %v in %s failed: %s.\n\nOutput was:\n%s", cmd.Args, repoDir, err, buf.String())
		return
	}

	if *mode == "gen" {
		t.Errorf("Successfully generated expected output for %s in %s. (Triggering test error so you won't mistakenly interpret a 0 return code as a test success. Run without -test.mode=gen to run the test.)", repoName, wantOutputDir)
	} else {
		checkResults(t, buf, repoName, gotOutputDir, wantOutputDir)
	}
}

func checkResults(t *testing.T, output bytes.Buffer, repoName, gotOutputDir, wantOutputDir string) {
	out, err := exec.Command("diff", "-ur", wantOutputDir, gotOutputDir).CombinedOutput()
	if err != nil || len(out) > 0 {
		t.Logf(brush.Red(repoName + " FAIL").String())
		t.Errorf("Diff failed for %s: %s.", repoName, err)
		if len(out) > 0 {
			fmt.Println(brush.Red(repoName + "FAIL"))
			fmt.Println(output.String())
			fmt.Println(string(util2.ColorizeDiff(out)))
			t.Errorf("Output for %s differed from expected.", repoName)
		}
	} else {
		t.Logf(brush.Green(repoName + " PASS").String())
	}
}

func getHEADOrTipCommitID(t *testing.T, repoDir string) string {
	// TODO(sqs): assumes git
	cmd := exec.Command("git", "rev-parse", "HEAD")
	cmd.Dir = repoDir
	out, err := cmd.Output()
	if err != nil {
		t.Fatal(err)
	}
	return string(bytes.TrimSpace(out))
}
<commit_msg>skip srcgraph make tests if -test.short is set<commit_after>package srcgraph

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"sync"

	"sourcegraph.com/sourcegraph/srcgraph/buildstore"
	"sourcegraph.com/sourcegraph/srcgraph/util2"

	"testing"

	"github.com/aybabtme/color/brush"
)

var mode = flag.String("test.mode", "test", "[test|keep|gen] 'test' runs test as normal; keep keeps around generated test files for inspection after tests complete; 'gen' generates new expected test data")
var repoMatch = flag.String("test.repo", "", "only test `srcgraph make` for repos that contain this string")

func TestMakeCmd(t *testing.T) {
	if testing.Short() {
		t.Skip("srcgraph make tests take a long time; skipping for -test.short")
	}

	// Since we exec `srcgraph`, make sure it's up-to-date.
	if out, err := exec.Command("make", "-C", "..", "srcgraph").CombinedOutput(); err != nil {
		t.Errorf("Failed to build srcgraph for `srcgraph make` tests: %s.\n\nOutput was:\n%s", err, out)
		return
	}

	cmd := exec.Command("git", "submodule", "update", "--init", "srcgraph/testdata/repos")
	cmd.Dir = ".."
	if out, err := cmd.CombinedOutput(); err != nil {
		t.Errorf("Failed to update or init git submodules: %s.\n\nOutput was:\n%s", err, out)
		return
	}

	const testReposDir = "testdata/repos"
	fis, err := ioutil.ReadDir("testdata/repos")
	if err != nil {
		t.Fatal(err)
	}
	n := 0
	var wg sync.WaitGroup
	for _, fi := range fis {
		if repoDir := fi.Name(); strings.Contains(repoDir, *repoMatch) {
			fullRepoDir := filepath.Join(testReposDir, repoDir)
			wg.Add(1)
			go func() {
				defer wg.Done()
				testMakeCmd(t, fullRepoDir)
			}()
			n++
		}
	}
	wg.Wait()
	if n == 0 {
		t.Errorf("No TestMakeCmd cases were run. Did none match your constraint -test.match=%q?", *repoMatch)
	}
}

func testMakeCmd(t *testing.T, repoDir string) {
	repoName := filepath.Base(repoDir)

	// Directories for the actual ("got") and expected ("want") outputs.
	gotOutputDir := filepath.Join(repoDir, "../../repos-output/got", repoName)
	wantOutputDir := filepath.Join(repoDir, "../../repos-output/want", repoName)

	// Determine and wipe the desired output dir.
	var outputDir string
	if *mode == "gen" {
		outputDir = wantOutputDir
	} else {
		outputDir = gotOutputDir
	}
	outputDir, _ = filepath.Abs(outputDir)
	if err := os.RemoveAll(outputDir); err != nil {
		t.Fatal(err)
	}
	if err := os.MkdirAll(outputDir, 0755); err != nil {
		t.Fatal(err)
	}

	// Symlink ${repoDir}/.sourcegraph-data/${commitID} to the desired output dir.
	origOutputDestDir := filepath.Join(repoDir, buildstore.BuildDataDirName, getHEADOrTipCommitID(t, repoDir))
	if err := os.Mkdir(filepath.Dir(origOutputDestDir), 0755); err != nil && !os.IsExist(err) {
		t.Fatal(err)
	}
	if err := os.Remove(origOutputDestDir); err != nil && !os.IsNotExist(err) {
		t.Fatal(err)
	}
	if err := os.Symlink(outputDir, origOutputDestDir); err != nil {
		t.Error(err)
		return
	}
	defer func() {
		// Remove the symlink when we're done so the repo doesn't have
		// uncommitted changes.
		if err := os.Remove(origOutputDestDir); err != nil {
			t.Fatal(err)
		}
	}()

	// Run `srcgraph make`.
	var w io.Writer
	var buf bytes.Buffer
	if testing.Verbose() {
		w = io.MultiWriter(&buf, os.Stderr)
	} else {
		w = &buf
	}
	cmd := exec.Command("srcgraph", "-v", "make")
	cmd.Stderr, cmd.Stdout = w, w
	cmd.Dir = repoDir

	err := cmd.Run()
	if err != nil {
		t.Errorf("Command %v in %s failed: %s.\n\nOutput was:\n%s", cmd.Args, repoDir, err, buf.String())
		return
	}

	if *mode == "gen" {
		t.Errorf("Successfully generated expected output for %s in %s. (Triggering test error so you won't mistakenly interpret a 0 return code as a test success. Run without -test.mode=gen to run the test.)", repoName, wantOutputDir)
	} else {
		checkResults(t, buf, repoName, gotOutputDir, wantOutputDir)
	}
}

func checkResults(t *testing.T, output bytes.Buffer, repoName, gotOutputDir, wantOutputDir string) {
	out, err := exec.Command("diff", "-ur", wantOutputDir, gotOutputDir).CombinedOutput()
	if err != nil || len(out) > 0 {
		t.Logf(brush.Red(repoName + " FAIL").String())
		t.Errorf("Diff failed for %s: %s.", repoName, err)
		if len(out) > 0 {
			fmt.Println(brush.Red(repoName + "FAIL"))
			fmt.Println(output.String())
			fmt.Println(string(util2.ColorizeDiff(out)))
			t.Errorf("Output for %s differed from expected.", repoName)
		}
	} else {
		t.Logf(brush.Green(repoName + " PASS").String())
	}
}

func getHEADOrTipCommitID(t *testing.T, repoDir string) string {
	// TODO(sqs): assumes git
	cmd := exec.Command("git", "rev-parse", "HEAD")
	cmd.Dir = repoDir
	out, err := cmd.Output()
	if err != nil {
		t.Fatal(err)
	}
	return string(bytes.TrimSpace(out))
}
<|endoftext|>


<commit_before>package bot

import (
	"bitbucket.org/mrd0ll4r/tbotapi"
	"fmt"
	"log"
	"math/rand"
	"os"
	"strings"
	"sync"
	"time"
)

type command string

const (
	cmdStart   = command("start")
	cmdStop    = command("stop")
	cmdNew     = command("new")
	cmdJoin    = command("join")
	cmdAbort   = command("abort")
	cmdUnknown = command("unknown")
)

func parseCommand(text string) command {
	text = strings.ToLower(text)
	if !strings.HasPrefix(text, "/") {
		return cmdUnknown
	}

	text = text[1:]
	switch text {
	case "new", "n", "new@" + api.Username:
		return cmdNew
	case "join", "j", "join@" + api.Username:
		return cmdJoin
	case "abort", "a", "abort@" + api.Username:
		return cmdAbort
	case "start", "start@" + api.Username:
		return cmdStart
	case "stop", "stop@" + api.Username:
		return cmdStop
	default:
		return cmdUnknown
	}
}

type choice string

const (
	choiceRock     = choice("rock")
	choicePaper    = choice("paper")
	choiceScissors = choice("scissors")
	choiceUnknown  = choice("unknown")
)

func parseChoice(text string) choice {
	text = strings.ToLower(text)
	switch text {
	case "rock", "r":
		return choiceRock
	case "paper", "p":
		return choicePaper
	case "scissors", "s":
		return choiceScissors
	default:
		return choiceUnknown
	}
}

var api *tbotapi.TelegramBotAPI

// RunBot runs a bot.
// It will block until either something very bad happens or closing is closed.
func RunBot(apiKey string, closing chan struct{}) {
	fmt.Println("Starting...")
	if fileExists("chats.json") {
		fmt.Println("Loading chats...")
		err := loadChatsFromFile("chats.json")
		if err != nil {
			fmt.Println("Could not load:", err.Error())
		}
	}

	fmt.Println("Starting bot...")
	api, err := tbotapi.New(apiKey)
	if err != nil {
		log.Fatal(err)
	}

	// just to show its working
	fmt.Printf("User ID: %d\n", api.ID)
	fmt.Printf("Bot Name: %s\n", api.Name)
	fmt.Printf("Bot Username: %s\n", api.Username)

	closed := make(chan struct{})
	wg := &sync.WaitGroup{}

	wg.Add(1)
	go func() {
		defer wg.Done()
		for {
			select {
			case <-closed:
				return
			case update := <-api.Updates:
				if update.Error() != nil {
					fmt.Printf("Update error: %s\n", update.Error())
					continue
				}

				upd := update.Update()
				switch upd.Type() {
				case tbotapi.MessageUpdate:
					handleMessage(*update.Update().Message, api)
				case tbotapi.InlineQueryUpdate, tbotapi.ChosenInlineResultUpdate:
				// ignore
				default:
					fmt.Printf("Ignoring unknown Update type.")
				}
			}
		}
	}()

	wg.Add(1)
	go func() {
		defer wg.Done()
		for {
			select {
			case <-closed:
				return
			case <-time.After(10 * time.Minute):
				fmt.Println("Saving db...")
				err = dumpChatsToFile("chats.json")
				if err != nil {
					fmt.Println("Could not save:", err.Error())
				}
			}
		}
	}()

	// wait for the signal
	<-closing
	fmt.Println("Closing...")

	fmt.Println("Saving db...")
	err = dumpChatsToFile("chats.json")
	if err != nil {
		fmt.Println("Could not save:", err.Error())
	}

	fmt.Println("Closing bot...")
	// always close the API first, let it clean up the update loop
	api.Close() //this might take a while
	close(closed)
	wg.Wait()
}

func fileExists(filename string) bool {
	fi, err := os.Lstat(filename)
	if fi != nil || (err != nil && !os.IsNotExist(err)) {
		return true
	}
	return false
}

func handleMessage(msg tbotapi.Message, api *tbotapi.TelegramBotAPI) {
	typ := msg.Type()
	if typ != tbotapi.TextMessage {
		//ignore non-text messages for now
		return
	}
	text := *msg.Text
	if msg.Chat.IsPrivateChat() {
		fmt.Printf("<-%d, %s,\t%q\n", msg.ID, msg.Chat, text)
	} else {
		fmt.Printf("<-%d, %s(%s),\t%q\n", msg.ID, msg.Chat, msg.From, text)
	}

	if msg.Chat.IsPrivateChat() {
		//always update the list of private chats
		putChat(msg.From.ID, msg.Chat.ID)
	}

	if strings.HasPrefix(text, "/") {
		//command
		cmd := parseCommand(text)
		if cmd == cmdNew {
			game(msg, api)
			return
		}

		groupsLock.RLock()
		if c, ok := groups[msg.Chat.ID]; ok {
			c <- msg
		}
		groupsLock.RUnlock()
	} else {
		if msg.Chat.IsPrivateChat() {
			uid := msg.From.ID
			expectsLock.Lock()
			if expect, ok := expects[uid]; ok {
				switch parseChoice(text) {
				case choiceRock, choicePaper, choiceScissors:
					expect <- parseChoice(text)
					delete(expects, uid)
				default:
					reply(msg, api, "No understand")
				}
			}
			expectsLock.Unlock()
		}
	}
}

func game(msg tbotapi.Message, api *tbotapi.TelegramBotAPI) {
	if hasExpect(msg.From.ID) {
		reply(msg, api, "You are already in a game right now")
		return
	}

	if msg.Chat.IsPrivateChat() {
		reply(msg, api, "You will play against the bot. Make your choice! ([r]ock, [p]aper or [s]cissors)")

		eChan := make(chan choice)
		expectsLock.Lock()
		expects[msg.From.ID] = eChan
		expectsLock.Unlock()

		go func(original tbotapi.Message, api *tbotapi.TelegramBotAPI, expected chan choice) {
			choice := <-eChan

			botChoice := rand.Float64()

			var resp string
			if botChoice < (float64(1) / float64(3)) {
				resp = formatResponse("the bot", "you", choiceRock, choice)
			} else if botChoice < (float64(2) / float64(3)) {
				resp = formatResponse("the bot", "you", choicePaper, choice)
			} else {
				resp = formatResponse("the bot", "you", choiceScissors, choice)
			}

			reply(original, api, resp)
		}(msg, api, eChan)

	} else {
		//group mode

		if !hasChat(msg.From.ID) {
			reply(msg, api, "I have lost track of our private chat. Please write me personally and try again")
			return
		}

		if hasGroup(msg.Chat.ID) {
			reply(msg, api, "This group already has an open game.")
			return
		}

		messages := make(chan tbotapi.Message)
		groups[msg.Chat.ID] = messages
		reply(msg, api, "Game opened. Join with /join, abort with /abort")

		go func(original tbotapi.Message, api *tbotapi.TelegramBotAPI, messages chan tbotapi.Message) {
			var p1, p2 chan choice
			var partner tbotapi.User

		loop:
			for {
				msg := <-messages
				if msg.Type() != tbotapi.TextMessage {
					continue
				}
				text := *msg.Text
				switch parseCommand(text) {
				case cmdJoin:
					if msg.From.ID == original.From.ID {
						reply(original, api, "The creator is already in the game, idiot")
					} else {
						expectsLock.Lock()
						if _, ok := expects[original.From.ID]; ok {
							reply(msg, api, "The creator is already in a game right now, game will remain open...")
							expectsLock.Unlock()
							continue loop
						}

						if _, ok := expects[msg.From.ID]; ok {
							reply(msg, api, "You are already in a game right now, game will remain open...")
							expectsLock.Unlock()
							continue loop
						}

						if !hasChat(msg.From.ID) {
							reply(msg, api, "I have lost track of our private chat. Please write me personally and try again")
							expectsLock.Unlock()
							continue loop
						}

						groupsLock.Lock()
						delete(groups, original.Chat.ID)
						groupsLock.Unlock()
						p1 = make(chan choice)
						expects[original.From.ID] = p1
						p2 = make(chan choice)
						expects[msg.From.ID] = p2
						expectsLock.Unlock()

						p1Chat := chats[original.From.ID]
						p2Chat := chats[msg.From.ID]

						partner = msg.From

						sendTo(p1Chat, api, "Waiting for your choice. ([r]ock, [p]aper, [s]cissors)")
						sendTo(p2Chat, api, "Waiting for your choice. ([r]ock, [p]aper, [s]cissors)")
						reply(original, api, "Game started, send me your choices in a private chat.")

						break loop
					}
				case cmdAbort:
					if msg.From.ID == original.From.ID {
						groupsLock.Lock()
						delete(groups, original.Chat.ID)
						groupsLock.Unlock()
						reply(original, api, "Game aborted.")
						return
					} else {
						reply(original, api, "Only the creator can abort a game")
					}
				}
			}

			// game running

			var choice1, choice2 choice

		nextloop:
			for {
				select {
				case choice1 = <-p1:
					if choice2 != "" {
						break nextloop
					}
				case choice2 = <-p2:
					if choice1 != "" {
						break nextloop
					}
				}
			}

			resp := formatResponse(original.From.String(), partner.String(), choice1, choice2)

			reply(original, api, resp)

		}(msg, api, messages)
	}
}

func formatResponse(part1, part2 string, choice1, choice2 choice) string {
	var res string
	switch choice1 {
	case choiceRock:
		switch choice2 {
		case choiceRock:
			res = "tie"
		case choicePaper:
			res = part2 + " wins"
		case choiceScissors:
			res = part1 + " wins"
		}
	case choicePaper:
		switch choice2 {
		case choiceRock:
			res = part1 + " wins"
		case choicePaper:
			res = "tie"
		case choiceScissors:
			res = part2 + " wins"
		}
	case choiceScissors:
		switch choice2 {
		case choiceRock:
			res = part2 + " wins"
		case choicePaper:
			res = part1 + " wins"
		case choiceScissors:
			res = "tie"
		}
	}

	return fmt.Sprintf("%s chose %s, %s chose %s: %s", part1, choice1, part2, choice2, res)
}

func sendTo(chat int, api *tbotapi.TelegramBotAPI, text string) error {
	outMsg, err := api.NewOutgoingMessage(tbotapi.NewChatRecipient(chat), text).Send()
	if err != nil {
		return err
	}

	fmt.Printf("->%d, %s,\t%q\n", outMsg.Message.ID, outMsg.Message.Chat, *outMsg.Message.Text)
	return nil
}

func reply(msg tbotapi.Message, api *tbotapi.TelegramBotAPI, text string) error {
	return sendTo(msg.Chat.ID, api, text)
}
<commit_msg>more constants<commit_after>package bot

import (
	"bitbucket.org/mrd0ll4r/tbotapi"
	"fmt"
	"log"
	"math/rand"
	"os"
	"strings"
	"sync"
	"time"
)

const (
	msgChoices                     = "([r]ock, [p]aper or [s]cissors)"
	msgChoose                      = "Make your choice! " + msgChoices
	msgNoPrivateChat               = "I have lost track of our private chat. Please write me in a private chat and try again"
	msgAlreadyIngame               = "You are already in a game right now, finish that first."
	msgAlreadyIngameWillRemainOpen = msgAlreadyIngame + " Game will remain open..."
	msgGameOpened                  = "Game opened! Join with /join, abort with /abort"
	msgGameStarted                 = "Game started! Waiting for your choices in our private chats..."
	msgGameAborted                 = "Game aborted"
	msgOnlyCreatorCanAbort         = "Only the creator can abort a game"
	msgCreatorAlreadyInGame        = "The creator is already in the game, idiot"
)

type command string

const (
	cmdStart   = command("start")
	cmdStop    = command("stop")
	cmdNew     = command("new")
	cmdJoin    = command("join")
	cmdAbort   = command("abort")
	cmdUnknown = command("unknown")
)

func parseCommand(text string) command {
	text = strings.ToLower(text)
	if !strings.HasPrefix(text, "/") {
		return cmdUnknown
	}

	text = text[1:]
	switch text {
	case "new", "n", "new@" + api.Username:
		return cmdNew
	case "join", "j", "join@" + api.Username:
		return cmdJoin
	case "abort", "a", "abort@" + api.Username:
		return cmdAbort
	case "start", "start@" + api.Username:
		return cmdStart
	case "stop", "stop@" + api.Username:
		return cmdStop
	default:
		return cmdUnknown
	}
}

type choice string

const (
	choiceRock     = choice("rock")
	choicePaper    = choice("paper")
	choiceScissors = choice("scissors")
	choiceUnknown  = choice("unknown")
)

func parseChoice(text string) choice {
	text = strings.ToLower(text)
	switch text {
	case "rock", "r":
		return choiceRock
	case "paper", "p":
		return choicePaper
	case "scissors", "s":
		return choiceScissors
	default:
		return choiceUnknown
	}
}

var api *tbotapi.TelegramBotAPI

// RunBot runs a bot.
// It will block until either something very bad happens or closing is closed.
func RunBot(apiKey string, closing chan struct{}) {
	fmt.Println("Starting...")
	if fileExists("chats.json") {
		fmt.Println("Loading chats...")
		err := loadChatsFromFile("chats.json")
		if err != nil {
			fmt.Println("Could not load:", err.Error())
		}
	}

	fmt.Println("Starting bot...")
	api, err := tbotapi.New(apiKey)
	if err != nil {
		log.Fatal(err)
	}

	// just to show its working
	fmt.Printf("User ID: %d\n", api.ID)
	fmt.Printf("Bot Name: %s\n", api.Name)
	fmt.Printf("Bot Username: %s\n", api.Username)

	closed := make(chan struct{})
	wg := &sync.WaitGroup{}

	wg.Add(1)
	go func() {
		defer wg.Done()
		for {
			select {
			case <-closed:
				return
			case update := <-api.Updates:
				if update.Error() != nil {
					fmt.Printf("Update error: %s\n", update.Error())
					continue
				}

				upd := update.Update()
				switch upd.Type() {
				case tbotapi.MessageUpdate:
					handleMessage(*update.Update().Message, api)
				case tbotapi.InlineQueryUpdate, tbotapi.ChosenInlineResultUpdate:
				// ignore
				default:
					fmt.Printf("Ignoring unknown Update type.")
				}
			}
		}
	}()

	wg.Add(1)
	go func() {
		defer wg.Done()
		for {
			select {
			case <-closed:
				return
			case <-time.After(10 * time.Minute):
				fmt.Println("Saving db...")
				err = dumpChatsToFile("chats.json")
				if err != nil {
					fmt.Println("Could not save:", err.Error())
				}
			}
		}
	}()

	// wait for the signal
	<-closing
	fmt.Println("Closing...")

	fmt.Println("Saving db...")
	err = dumpChatsToFile("chats.json")
	if err != nil {
		fmt.Println("Could not save:", err.Error())
	}

	fmt.Println("Closing bot...")
	// always close the API first, let it clean up the update loop
	api.Close() //this might take a while
	close(closed)
	wg.Wait()
}

func fileExists(filename string) bool {
	fi, err := os.Lstat(filename)
	if fi != nil || (err != nil && !os.IsNotExist(err)) {
		return true
	}
	return false
}

func handleMessage(msg tbotapi.Message, api *tbotapi.TelegramBotAPI) {
	typ := msg.Type()
	if typ != tbotapi.TextMessage {
		//ignore non-text messages for now
		return
	}
	text := *msg.Text
	if msg.Chat.IsPrivateChat() {
		fmt.Printf("<-%d, %s,\t%q\n", msg.ID, msg.Chat, text)
	} else {
		fmt.Printf("<-%d, %s(%s),\t%q\n", msg.ID, msg.Chat, msg.From, text)
	}

	if msg.Chat.IsPrivateChat() {
		//always update the list of private chats
		putChat(msg.From.ID, msg.Chat.ID)
	}

	if strings.HasPrefix(text, "/") {
		//command
		cmd := parseCommand(text)
		if cmd == cmdNew {
			game(msg, api)
			return
		}

		groupsLock.RLock()
		if c, ok := groups[msg.Chat.ID]; ok {
			c <- msg
		}
		groupsLock.RUnlock()
	} else {
		if msg.Chat.IsPrivateChat() {
			uid := msg.From.ID
			expectsLock.Lock()
			if expect, ok := expects[uid]; ok {
				switch parseChoice(text) {
				case choiceRock, choicePaper, choiceScissors:
					expect <- parseChoice(text)
					delete(expects, uid)
				default:
					reply(msg, api, "No understand")
				}
			}
			expectsLock.Unlock()
		}
	}
}

func game(msg tbotapi.Message, api *tbotapi.TelegramBotAPI) {
	if hasExpect(msg.From.ID) {
		reply(msg, api, msgAlreadyIngame)
		return
	}

	if msg.Chat.IsPrivateChat() {
		reply(msg, api, "You will play against the bot. "+msgChoose)

		eChan := make(chan choice)
		expectsLock.Lock()
		expects[msg.From.ID] = eChan
		expectsLock.Unlock()

		go func(original tbotapi.Message, api *tbotapi.TelegramBotAPI, expected chan choice) {
			choice := <-eChan

			botChoice := rand.Float64()

			var resp string
			if botChoice < (float64(1) / float64(3)) {
				resp = formatResponse("the bot", "you", choiceRock, choice)
			} else if botChoice < (float64(2) / float64(3)) {
				resp = formatResponse("the bot", "you", choicePaper, choice)
			} else {
				resp = formatResponse("the bot", "you", choiceScissors, choice)
			}

			reply(original, api, resp)
		}(msg, api, eChan)

	} else {
		//group mode

		if !hasChat(msg.From.ID) {
			reply(msg, api, msgNoPrivateChat)
			return
		}

		if hasGroup(msg.Chat.ID) {
			reply(msg, api, "This group already has an open game.")
			return
		}

		messages := make(chan tbotapi.Message)
		groups[msg.Chat.ID] = messages
		reply(msg, api, msgGameOpened)

		go func(original tbotapi.Message, api *tbotapi.TelegramBotAPI, messages chan tbotapi.Message) {
			var p1, p2 chan choice
			var partner tbotapi.User

		loop:
			for {
				msg := <-messages
				if msg.Type() != tbotapi.TextMessage {
					continue
				}
				text := *msg.Text
				switch parseCommand(text) {
				case cmdJoin:
					if msg.From.ID == original.From.ID {
						reply(original, api, msgCreatorAlreadyInGame)
					} else {
						expectsLock.Lock()
						if _, ok := expects[original.From.ID]; ok {
							reply(msg, api, msgAlreadyIngameWillRemainOpen)
							expectsLock.Unlock()
							continue loop
						}

						if _, ok := expects[msg.From.ID]; ok {
							reply(msg, api, msgAlreadyIngameWillRemainOpen)
							expectsLock.Unlock()
							continue loop
						}

						if !hasChat(msg.From.ID) {
							reply(msg, api, msgNoPrivateChat)
							expectsLock.Unlock()
							continue loop
						}

						groupsLock.Lock()
						delete(groups, original.Chat.ID)
						groupsLock.Unlock()
						p1 = make(chan choice)
						expects[original.From.ID] = p1
						p2 = make(chan choice)
						expects[msg.From.ID] = p2
						expectsLock.Unlock()

						p1Chat := chats[original.From.ID]
						p2Chat := chats[msg.From.ID]

						partner = msg.From

						sendTo(p1Chat, api, msgChoose)
						sendTo(p2Chat, api, msgChoose)
						reply(original, api, msgGameStarted)

						break loop
					}
				case cmdAbort:
					if msg.From.ID == original.From.ID {
						groupsLock.Lock()
						delete(groups, original.Chat.ID)
						groupsLock.Unlock()
						reply(original, api, msgGameAborted)
						return
					} else {
						reply(original, api, msgOnlyCreatorCanAbort)
					}
				}
			}

			// game running

			var choice1, choice2 choice

		nextloop:
			for {
				select {
				case choice1 = <-p1:
					if choice2 != "" {
						break nextloop
					}
				case choice2 = <-p2:
					if choice1 != "" {
						break nextloop
					}
				}
			}

			resp := formatResponse(original.From.String(), partner.String(), choice1, choice2)

			reply(original, api, resp)

		}(msg, api, messages)
	}
}

func formatResponse(part1, part2 string, choice1, choice2 choice) string {
	var res string
	switch choice1 {
	case choiceRock:
		switch choice2 {
		case choiceRock:
			res = "tie"
		case choicePaper:
			res = part2 + " wins"
		case choiceScissors:
			res = part1 + " wins"
		}
	case choicePaper:
		switch choice2 {
		case choiceRock:
			res = part1 + " wins"
		case choicePaper:
			res = "tie"
		case choiceScissors:
			res = part2 + " wins"
		}
	case choiceScissors:
		switch choice2 {
		case choiceRock:
			res = part2 + " wins"
		case choicePaper:
			res = part1 + " wins"
		case choiceScissors:
			res = "tie"
		}
	}

	return fmt.Sprintf("%s chose %s, %s chose %s: %s", part1, choice1, part2, choice2, res)
}

func sendTo(chat int, api *tbotapi.TelegramBotAPI, text string) error {
	outMsg, err := api.NewOutgoingMessage(tbotapi.NewChatRecipient(chat), text).Send()
	if err != nil {
		return err
	}

	fmt.Printf("->%d, %s,\t%q\n", outMsg.Message.ID, outMsg.Message.Chat, *outMsg.Message.Text)
	return nil
}

func reply(msg tbotapi.Message, api *tbotapi.TelegramBotAPI, text string) error {
	return sendTo(msg.Chat.ID, api, text)
}
<|endoftext|>