<commit_before>package project

import (
	"bytes"
	"context"
	"errors"
	"os"
	"strings"
	"testing"

	"github.com/reviewdog/reviewdog"
)

type fakeDiffService struct {
	reviewdog.DiffService
	FakeDiff func() ([]byte, error)
}

func (f *fakeDiffService) Diff(_ context.Context) ([]byte, error) {
	return f.FakeDiff()
}

func (f *fakeDiffService) Strip() int {
	return 0
}

type fakeCommentService struct {
	reviewdog.CommentService
	FakePost func(*reviewdog.Comment) error
}

func (f *fakeCommentService) Post(_ context.Context, c *reviewdog.Comment) error {
	return f.FakePost(c)
}

func TestRun(t *testing.T) {
	ctx := context.Background()

	t.Run("empty", func(t *testing.T) {
		conf := &Config{}
		if err := Run(ctx, conf, nil, nil, nil, false, reviewdog.FilterModeAdded, false); err != nil {
			t.Error(err)
		}
	})

	t.Run("errorformat error", func(t *testing.T) {
		conf := &Config{
			Runner: map[string]*Runner{
				"test": {},
			},
		}
		if err := Run(ctx, conf, nil, nil, nil, false, reviewdog.FilterModeAdded, false); err == nil {
			t.Error("want error, got nil")
		} else {
			t.Log(err)
		}
	})

	t.Run("diff error", func(t *testing.T) {
		ds := &fakeDiffService{
			FakeDiff: func() ([]byte, error) {
				return nil, errors.New("err!")
			},
		}
		conf := &Config{
			Runner: map[string]*Runner{
				"test": {
					Cmd:         "echo 'hi'",
					Errorformat: []string{`%f:%l:%c:%m`},
				},
			},
		}
		if err := Run(ctx, conf, nil, nil, ds, false, reviewdog.FilterModeAdded, false); err == nil {
			t.Error("want error, got nil")
		} else {
			t.Log(err)
		}
	})

	t.Run("cmd error with findings (not for reviewdog to exit with error)", func(t *testing.T) {
		buf := new(bytes.Buffer)
		defaultTeeStderr = buf
		ds := &fakeDiffService{
			FakeDiff: func() ([]byte, error) {
				return []byte(""), nil
			},
		}
		cs := &fakeCommentService{
			FakePost: func(c *reviewdog.Comment) error {
				return nil
			},
		}
		conf := &Config{
			Runner: map[string]*Runner{
				"test": {
					Cmd:         "echo 'file:14:14:message'; exit 1",
					Errorformat: []string{`%f:%l:%c:%m`},
				},
			},
		}
		if err := Run(ctx, conf, nil, cs, ds, false, reviewdog.FilterModeAdded, false); err != nil {
			t.Error(err)
		}
		want := ""
		if got := buf.String(); got != want {
			t.Errorf("got stderr %q, want %q", got, want)
		}
	})

	t.Run("unexpected cmd error (reviewdog exits with error)", func(t *testing.T) {
		buf := new(bytes.Buffer)
		defaultTeeStderr = buf
		ds := &fakeDiffService{
			FakeDiff: func() ([]byte, error) {
				return []byte(""), nil
			},
		}
		cs := &fakeCommentService{
			FakePost: func(c *reviewdog.Comment) error {
				return nil
			},
		}
		conf := &Config{
			Runner: map[string]*Runner{
				"test": {
					Cmd:         "not found",
					Errorformat: []string{`%f:%l:%c:%m`},
				},
			},
		}
		if err := Run(ctx, conf, nil, cs, ds, false, reviewdog.FilterModeAdded); err == nil {
			t.Error("want error, got nil")
		} else {
			t.Log(err)
		}
	})

	t.Run("cmd error with tee", func(t *testing.T) {
		buf := new(bytes.Buffer)
		defaultTeeStderr = buf
		ds := &fakeDiffService{
			FakeDiff: func() ([]byte, error) {
				return []byte(""), nil
			},
		}
		cs := &fakeCommentService{
			FakePost: func(c *reviewdog.Comment) error {
				return nil
			},
		}
		conf := &Config{
			Runner: map[string]*Runner{
				"test": {
					Cmd:         "not found",
					Errorformat: []string{`%f:%l:%c:%m`},
				},
			},
		}
		if err := Run(ctx, conf, nil, cs, ds, true, reviewdog.FilterModeAdded, false); err == nil {
			t.Error("want error, got nil")
		} else {
			t.Log(err)
		}
		want := "sh: 1: not: not found\n"
		if got := buf.String(); got != want {
			t.Errorf("got stderr %q, want %q", got, want)
		}
	})

	t.Run("success", func(t *testing.T) {
		ds := &fakeDiffService{
			FakeDiff: func() ([]byte, error) {
				return []byte(""), nil
			},
		}
		cs := &fakeCommentService{
			FakePost: func(c *reviewdog.Comment) error {
				return nil
			},
		}
		conf := &Config{
			Runner: map[string]*Runner{
				"test": {
					Cmd:         "echo 'hi'",
					Errorformat: []string{`%f:%l:%c:%m`},
				},
			},
		}
		if err := Run(ctx, conf, nil, cs, ds, false, reviewdog.FilterModeAdded, false); err != nil {
			t.Error(err)
		}
	})

	t.Run("success with tee", func(t *testing.T) {
		buf := new(bytes.Buffer)
		defaultTeeStdout = buf
		ds := &fakeDiffService{
			FakeDiff: func() ([]byte, error) {
				return []byte(""), nil
			},
		}
		cs := &fakeCommentService{
			FakePost: func(c *reviewdog.Comment) error {
				return nil
			},
		}
		conf := &Config{
			Runner: map[string]*Runner{
				"test": {
					Cmd:         "echo 'hi'",
					Errorformat: []string{`%f:%l:%c:%m`},
				},
			},
		}
		if err := Run(ctx, conf, nil, cs, ds, true, reviewdog.FilterModeAdded, false); err != nil {
			t.Error(err)
		}
		want := "hi\n"
		if got := buf.String(); got != want {
			t.Errorf("got stdout %q, want %q", got, want)
		}
	})

	t.Run("runners", func(t *testing.T) {
		called := 0
		ds := &fakeDiffService{
			FakeDiff: func() ([]byte, error) {
				called++
				return []byte(""), nil
			},
		}
		cs := &fakeCommentService{
			FakePost: func(c *reviewdog.Comment) error {
				return nil
			},
		}
		conf := &Config{
			Runner: map[string]*Runner{
				"test1": {
					Name:        "test1",
					Cmd:         "echo 'test1'",
					Errorformat: []string{`%f:%l:%c:%m`},
				},
				"test2": {
					Name:        "test2",
					Cmd:         "echo 'test2'",
					Errorformat: []string{`%f:%l:%c:%m`},
				},
			},
		}
		if err := Run(ctx, conf, map[string]bool{"test2": true}, cs, ds, false, reviewdog.FilterModeAdded, false); err != nil {
			t.Error(err)
		}
		if called != 1 {
			t.Errorf("Diff service called %d times, want 1 time", called)
		}
	})

	t.Run("unknown runners", func(t *testing.T) {
		ds := &fakeDiffService{
			FakeDiff: func() ([]byte, error) {
				return []byte(""), nil
			},
		}
		cs := &fakeCommentService{
			FakePost: func(c *reviewdog.Comment) error {
				return nil
			},
		}
		conf := &Config{
			Runner: map[string]*Runner{
				"test1": {
					Name:        "test1",
					Cmd:         "echo 'test1'",
					Errorformat: []string{`%f:%l:%c:%m`},
				},
				"test2": {
					Name:        "test2",
					Cmd:         "echo 'test2'",
					Errorformat: []string{`%f:%l:%c:%m`},
				},
			},
		}
		if err := Run(ctx, conf, map[string]bool{"hoge": true}, cs, ds, false, reviewdog.FilterModeAdded, false); err == nil {
			t.Error("got no error but want runner not found error")
		}
	})
}

func TestFilteredEnviron(t *testing.T) {
	names := [...]string{
		"REVIEWDOG_GITHUB_API_TOKEN",
		"REVIEWDOG_GITLAB_API_TOKEN",
		"REVIEWDOG_TOKEN",
	}

	for _, name := range names {
		defer func(name, value string) {
			os.Setenv(name, value)
		}(name, os.Getenv(name))
		os.Setenv(name, "value")
	}

	filtered := filteredEnviron()
	if len(filtered) != len(os.Environ())-len(names) {
		t.Errorf("len(filtered) != len(os.Environ())-%d, %v != %v-%d", len(names), len(filtered), len(os.Environ()), len(names))
	}

	for _, kv := range filtered {
		for _, name := range names {
			if strings.HasPrefix(kv, name) && kv != name+"=" {
				t.Errorf("filtered: %v, want %v=", kv, name)
			}
		}
	}

	for _, kv := range os.Environ() {
		for _, name := range names {
			if strings.HasPrefix(kv, name) && kv != name+"=value" {
				t.Errorf("envs: %v, want %v=value", kv, name)
			}
		}
	}
}
<commit_msg>fix build<commit_after>package project

import (
	"bytes"
	"context"
	"errors"
	"os"
	"strings"
	"testing"

	"github.com/reviewdog/reviewdog"
)

type fakeDiffService struct {
	reviewdog.DiffService
	FakeDiff func() ([]byte, error)
}

func (f *fakeDiffService) Diff(_ context.Context) ([]byte, error) {
	return f.FakeDiff()
}

func (f *fakeDiffService) Strip() int {
	return 0
}

type fakeCommentService struct {
	reviewdog.CommentService
	FakePost func(*reviewdog.Comment) error
}

func (f *fakeCommentService) Post(_ context.Context, c *reviewdog.Comment) error {
	return f.FakePost(c)
}

func TestRun(t *testing.T) {
	ctx := context.Background()

	t.Run("empty", func(t *testing.T) {
		conf := &Config{}
		if err := Run(ctx, conf, nil, nil, nil, false, reviewdog.FilterModeAdded, false); err != nil {
			t.Error(err)
		}
	})

	t.Run("errorformat error", func(t *testing.T) {
		conf := &Config{
			Runner: map[string]*Runner{
				"test": {},
			},
		}
		if err := Run(ctx, conf, nil, nil, nil, false, reviewdog.FilterModeAdded, false); err == nil {
			t.Error("want error, got nil")
		} else {
			t.Log(err)
		}
	})

	t.Run("diff error", func(t *testing.T) {
		ds := &fakeDiffService{
			FakeDiff: func() ([]byte, error) {
				return nil, errors.New("err!")
			},
		}
		conf := &Config{
			Runner: map[string]*Runner{
				"test": {
					Cmd:         "echo 'hi'",
					Errorformat: []string{`%f:%l:%c:%m`},
				},
			},
		}
		if err := Run(ctx, conf, nil, nil, ds, false, reviewdog.FilterModeAdded, false); err == nil {
			t.Error("want error, got nil")
		} else {
			t.Log(err)
		}
	})

	t.Run("cmd error with findings (not for reviewdog to exit with error)", func(t *testing.T) {
		buf := new(bytes.Buffer)
		defaultTeeStderr = buf
		ds := &fakeDiffService{
			FakeDiff: func() ([]byte, error) {
				return []byte(""), nil
			},
		}
		cs := &fakeCommentService{
			FakePost: func(c *reviewdog.Comment) error {
				return nil
			},
		}
		conf := &Config{
			Runner: map[string]*Runner{
				"test": {
					Cmd:         "echo 'file:14:14:message'; exit 1",
					Errorformat: []string{`%f:%l:%c:%m`},
				},
			},
		}
		if err := Run(ctx, conf, nil, cs, ds, false, reviewdog.FilterModeAdded, false); err != nil {
			t.Error(err)
		}
		want := ""
		if got := buf.String(); got != want {
			t.Errorf("got stderr %q, want %q", got, want)
		}
	})

	t.Run("unexpected cmd error (reviewdog exits with error)", func(t *testing.T) {
		buf := new(bytes.Buffer)
		defaultTeeStderr = buf
		ds := &fakeDiffService{
			FakeDiff: func() ([]byte, error) {
				return []byte(""), nil
			},
		}
		cs := &fakeCommentService{
			FakePost: func(c *reviewdog.Comment) error {
				return nil
			},
		}
		conf := &Config{
			Runner: map[string]*Runner{
				"test": {
					Cmd:         "not found",
					Errorformat: []string{`%f:%l:%c:%m`},
				},
			},
		}
		if err := Run(ctx, conf, nil, cs, ds, false, reviewdog.FilterModeAdded, false); err == nil {
			t.Error("want error, got nil")
		} else {
			t.Log(err)
		}
	})

	t.Run("cmd error with tee", func(t *testing.T) {
		buf := new(bytes.Buffer)
		defaultTeeStderr = buf
		ds := &fakeDiffService{
			FakeDiff: func() ([]byte, error) {
				return []byte(""), nil
			},
		}
		cs := &fakeCommentService{
			FakePost: func(c *reviewdog.Comment) error {
				return nil
			},
		}
		conf := &Config{
			Runner: map[string]*Runner{
				"test": {
					Cmd:         "not found",
					Errorformat: []string{`%f:%l:%c:%m`},
				},
			},
		}
		if err := Run(ctx, conf, nil, cs, ds, true, reviewdog.FilterModeAdded, false); err == nil {
			t.Error("want error, got nil")
		} else {
			t.Log(err)
		}
		want := "sh: 1: not: not found\n"
		if got := buf.String(); got != want {
			t.Errorf("got stderr %q, want %q", got, want)
		}
	})

	t.Run("success", func(t *testing.T) {
		ds := &fakeDiffService{
			FakeDiff: func() ([]byte, error) {
				return []byte(""), nil
			},
		}
		cs := &fakeCommentService{
			FakePost: func(c *reviewdog.Comment) error {
				return nil
			},
		}
		conf := &Config{
			Runner: map[string]*Runner{
				"test": {
					Cmd:         "echo 'hi'",
					Errorformat: []string{`%f:%l:%c:%m`},
				},
			},
		}
		if err := Run(ctx, conf, nil, cs, ds, false, reviewdog.FilterModeAdded, false); err != nil {
			t.Error(err)
		}
	})

	t.Run("success with tee", func(t *testing.T) {
		buf := new(bytes.Buffer)
		defaultTeeStdout = buf
		ds := &fakeDiffService{
			FakeDiff: func() ([]byte, error) {
				return []byte(""), nil
			},
		}
		cs := &fakeCommentService{
			FakePost: func(c *reviewdog.Comment) error {
				return nil
			},
		}
		conf := &Config{
			Runner: map[string]*Runner{
				"test": {
					Cmd:         "echo 'hi'",
					Errorformat: []string{`%f:%l:%c:%m`},
				},
			},
		}
		if err := Run(ctx, conf, nil, cs, ds, true, reviewdog.FilterModeAdded, false); err != nil {
			t.Error(err)
		}
		want := "hi\n"
		if got := buf.String(); got != want {
			t.Errorf("got stdout %q, want %q", got, want)
		}
	})

	t.Run("runners", func(t *testing.T) {
		called := 0
		ds := &fakeDiffService{
			FakeDiff: func() ([]byte, error) {
				called++
				return []byte(""), nil
			},
		}
		cs := &fakeCommentService{
			FakePost: func(c *reviewdog.Comment) error {
				return nil
			},
		}
		conf := &Config{
			Runner: map[string]*Runner{
				"test1": {
					Name:        "test1",
					Cmd:         "echo 'test1'",
					Errorformat: []string{`%f:%l:%c:%m`},
				},
				"test2": {
					Name:        "test2",
					Cmd:         "echo 'test2'",
					Errorformat: []string{`%f:%l:%c:%m`},
				},
			},
		}
		if err := Run(ctx, conf, map[string]bool{"test2": true}, cs, ds, false, reviewdog.FilterModeAdded, false); err != nil {
			t.Error(err)
		}
		if called != 1 {
			t.Errorf("Diff service called %d times, want 1 time", called)
		}
	})

	t.Run("unknown runners", func(t *testing.T) {
		ds := &fakeDiffService{
			FakeDiff: func() ([]byte, error) {
				return []byte(""), nil
			},
		}
		cs := &fakeCommentService{
			FakePost: func(c *reviewdog.Comment) error {
				return nil
			},
		}
		conf := &Config{
			Runner: map[string]*Runner{
				"test1": {
					Name:        "test1",
					Cmd:         "echo 'test1'",
					Errorformat: []string{`%f:%l:%c:%m`},
				},
				"test2": {
					Name:        "test2",
					Cmd:         "echo 'test2'",
					Errorformat: []string{`%f:%l:%c:%m`},
				},
			},
		}
		if err := Run(ctx, conf, map[string]bool{"hoge": true}, cs, ds, false, reviewdog.FilterModeAdded, false); err == nil {
			t.Error("got no error but want runner not found error")
		}
	})
}

func TestFilteredEnviron(t *testing.T) {
	names := [...]string{
		"REVIEWDOG_GITHUB_API_TOKEN",
		"REVIEWDOG_GITLAB_API_TOKEN",
		"REVIEWDOG_TOKEN",
	}

	for _, name := range names {
		defer func(name, value string) {
			os.Setenv(name, value)
		}(name, os.Getenv(name))
		os.Setenv(name, "value")
	}

	filtered := filteredEnviron()
	if len(filtered) != len(os.Environ())-len(names) {
		t.Errorf("len(filtered) != len(os.Environ())-%d, %v != %v-%d", len(names), len(filtered), len(os.Environ()), len(names))
	}

	for _, kv := range filtered {
		for _, name := range names {
			if strings.HasPrefix(kv, name) && kv != name+"=" {
				t.Errorf("filtered: %v, want %v=", kv, name)
			}
		}
	}

	for _, kv := range os.Environ() {
		for _, name := range names {
			if strings.HasPrefix(kv, name) && kv != name+"=value" {
				t.Errorf("envs: %v, want %v=value", kv, name)
			}
		}
	}
}
<|endoftext|>


<commit_before>package manta

import (
	"math"
	"strconv"
)

func decodeHandle(r *Reader, f *dt_field) interface{} {
	return r.readVarUint32()
}

func decodeByte(r *Reader, f *dt_field) interface{} {
	return r.readBits(8)
}

func decodeShort(r *Reader, f *dt_field) interface{} {
	return r.readBits(16)
}

func decodeUnsigned(r *Reader, f *dt_field) interface{} {
	return r.readVarUint64()
}

func decodeSigned(r *Reader, f *dt_field) interface{} {
	return r.readVarInt32()
}

func decodeSigned64(r *Reader, f *dt_field) interface{} {
	return r.readVarInt64()
}

func decodeBoolean(r *Reader, f *dt_field) interface{} {
	return r.readBoolean()
}

func decodeFloat(r *Reader, f *dt_field) interface{} {
	// Parse specific encoders
	switch f.Encoder {
	case "coord":
		return r.readCoord()
	}

	if f.BitCount != nil {
		// equivalent to the old noscale
		return decodeFloatNoscale(r, f)
	} else {
		return r.readVarUint32()
	}
}

func decodeFloatNoscale(r *Reader, f *dt_field) interface{} {
	return math.Float32frombits(r.readBits(int(*f.BitCount)))
}

// A list of field -> encoder types
var qmap map[*dt_field]*QuantizedFloatDecoder

func decodeQuantized(r *Reader, f *dt_field) interface{} {
	if qmap == nil {
		qmap = make(map[*dt_field]*QuantizedFloatDecoder, 0)
	}

	// Get the correct decoder
	q, ok := qmap[f]

	if !ok {
		qmap[f] = InitQFD(f)
		q = qmap[f]
	}

	// Decode value
	_debugf(
		"Bitcount: %v, Low: %v, High: %v, Flags: %v",
		q.Bitcount,
		q.Low,
		q.High,
		strconv.FormatInt(int64(q.Flags), 2),
	)

	return q.Decode(r)
}

func decodeSimTime(r *Reader, f *dt_field) interface{} {
	return float32(r.readVarUint32()) * (1.0 / 30)
}

func decodeString(r *Reader, f *dt_field) interface{} {
	return r.readString()
}

func decodeVector(r *Reader, f *dt_field) interface{} {
	size := r.readVarUint32()

	if size > 0 {
		_panicf("Ive been called, %v", size)
	}

	return 0
}

func decodeClass(r *Reader, f *dt_field) interface{} {
	return r.readVarUint32()
}

func decodeFVector(r *Reader, f *dt_field) interface{} {
	// Parse specific encoders
	switch f.Encoder {
	case "normal":
		return r.read3BitNormal()
	}

	return []float32{decodeFloat(r, f).(float32), decodeFloat(r, f).(float32), decodeFloat(r, f).(float32)}
}

func decodeNop(r *Reader, f *dt_field) interface{} {
	return 0
}

func decodePointer(r *Reader, f *dt_field) interface{} {
	// Seems to be encoded as a single bit, not sure what to make of it
	if !r.readBoolean() {
		_panicf("Figure out how this works")
	}

	return 0
}

func decodeQAngle(r *Reader, f *dt_field) interface{} {
	ret := [3]float32{0.0, 0.0, 0.0}

	// Parse specific encoders
	switch f.Encoder {
	case "qangle_pitch_yaw":
		if f.BitCount != nil && f.Flags != nil && (*f.Flags&0x20 != 0) {
			_panicf("Special Case: Unkown for now")
		}

		ret[0] = r.readAngle(uint(*f.BitCount))
		ret[1] = r.readAngle(uint(*f.BitCount))
		return ret
	}

	// Parse a standard angle
	if f.BitCount != nil && *f.BitCount == 32 {
		_panicf("Special Case: Unkown for now")
	} else if f.BitCount != nil && *f.BitCount != 0 {
		ret[0] = r.readAngle(uint(*f.BitCount))
		ret[1] = r.readAngle(uint(*f.BitCount))
		ret[2] = r.readAngle(uint(*f.BitCount))

		return ret
	} else {
		rX := r.readBoolean()
		rY := r.readBoolean()
		rZ := r.readBoolean()

		if rX {
			ret[0] = r.readCoord()
		}

		if rY {
			ret[1] = r.readCoord()
		}

		if rZ {
			ret[2] = r.readCoord()
		}

		return ret
	}

	_panicf("No valid encoding determined")
	return ret
}

func decodeComponent(r *Reader, f *dt_field) interface{} {
	_debugf(
		"Bitcount: %v, Low: %v, High: %v, Flags: %v",
		saveReturnInt32(f.BitCount),
		saveReturnFloat32(f.LowValue, "nil"),
		saveReturnFloat32(f.HighValue, "nil"),
		strconv.FormatInt(int64(saveReturnInt32(f.Flags)), 2),
	)

	return r.readBits(1)
}

func decodeHSequence(r *Reader, f *dt_field) interface{} {
	// wrong, just testing
	return r.readBits(1)
}
<commit_msg>Vector only reads a varint<commit_after>package manta

import (
	"math"
	"strconv"
)

func decodeHandle(r *Reader, f *dt_field) interface{} {
	return r.readVarUint32()
}

func decodeByte(r *Reader, f *dt_field) interface{} {
	return r.readBits(8)
}

func decodeShort(r *Reader, f *dt_field) interface{} {
	return r.readBits(16)
}

func decodeUnsigned(r *Reader, f *dt_field) interface{} {
	return r.readVarUint64()
}

func decodeSigned(r *Reader, f *dt_field) interface{} {
	return r.readVarInt32()
}

func decodeSigned64(r *Reader, f *dt_field) interface{} {
	return r.readVarInt64()
}

func decodeBoolean(r *Reader, f *dt_field) interface{} {
	return r.readBoolean()
}

func decodeFloat(r *Reader, f *dt_field) interface{} {
	// Parse specific encoders
	switch f.Encoder {
	case "coord":
		return r.readCoord()
	}

	if f.BitCount != nil {
		// equivalent to the old noscale
		return decodeFloatNoscale(r, f)
	} else {
		return r.readVarUint32()
	}
}

func decodeFloatNoscale(r *Reader, f *dt_field) interface{} {
	return math.Float32frombits(r.readBits(int(*f.BitCount)))
}

// A list of field -> encoder types
var qmap map[*dt_field]*QuantizedFloatDecoder

func decodeQuantized(r *Reader, f *dt_field) interface{} {
	if qmap == nil {
		qmap = make(map[*dt_field]*QuantizedFloatDecoder, 0)
	}

	// Get the correct decoder
	q, ok := qmap[f]

	if !ok {
		qmap[f] = InitQFD(f)
		q = qmap[f]
	}

	// Decode value
	_debugf(
		"Bitcount: %v, Low: %v, High: %v, Flags: %v",
		q.Bitcount,
		q.Low,
		q.High,
		strconv.FormatInt(int64(q.Flags), 2),
	)

	return q.Decode(r)
}

func decodeSimTime(r *Reader, f *dt_field) interface{} {
	return float32(r.readVarUint32()) * (1.0 / 30)
}

func decodeString(r *Reader, f *dt_field) interface{} {
	return r.readString()
}

func decodeVector(r *Reader, f *dt_field) interface{} {

	return r.readVarUint32()
}

func decodeClass(r *Reader, f *dt_field) interface{} {
	return r.readVarUint32()
}

func decodeFVector(r *Reader, f *dt_field) interface{} {
	// Parse specific encoders
	switch f.Encoder {
	case "normal":
		return r.read3BitNormal()
	}

	return []float32{decodeFloat(r, f).(float32), decodeFloat(r, f).(float32), decodeFloat(r, f).(float32)}
}

func decodeNop(r *Reader, f *dt_field) interface{} {
	return 0
}

func decodePointer(r *Reader, f *dt_field) interface{} {
	// Seems to be encoded as a single bit, not sure what to make of it
	if !r.readBoolean() {
		_panicf("Figure out how this works")
	}

	return 0
}

func decodeQAngle(r *Reader, f *dt_field) interface{} {
	ret := [3]float32{0.0, 0.0, 0.0}

	// Parse specific encoders
	switch f.Encoder {
	case "qangle_pitch_yaw":
		if f.BitCount != nil && f.Flags != nil && (*f.Flags&0x20 != 0) {
			_panicf("Special Case: Unkown for now")
		}

		ret[0] = r.readAngle(uint(*f.BitCount))
		ret[1] = r.readAngle(uint(*f.BitCount))
		return ret
	}

	// Parse a standard angle
	if f.BitCount != nil && *f.BitCount == 32 {
		_panicf("Special Case: Unkown for now")
	} else if f.BitCount != nil && *f.BitCount != 0 {
		ret[0] = r.readAngle(uint(*f.BitCount))
		ret[1] = r.readAngle(uint(*f.BitCount))
		ret[2] = r.readAngle(uint(*f.BitCount))

		return ret
	} else {
		rX := r.readBoolean()
		rY := r.readBoolean()
		rZ := r.readBoolean()

		if rX {
			ret[0] = r.readCoord()
		}

		if rY {
			ret[1] = r.readCoord()
		}

		if rZ {
			ret[2] = r.readCoord()
		}

		return ret
	}

	_panicf("No valid encoding determined")
	return ret
}

func decodeComponent(r *Reader, f *dt_field) interface{} {
	_debugf(
		"Bitcount: %v, Low: %v, High: %v, Flags: %v",
		saveReturnInt32(f.BitCount),
		saveReturnFloat32(f.LowValue, "nil"),
		saveReturnFloat32(f.HighValue, "nil"),
		strconv.FormatInt(int64(saveReturnInt32(f.Flags)), 2),
	)

	return r.readBits(1)
}

func decodeHSequence(r *Reader, f *dt_field) interface{} {
	// wrong, just testing
	return r.readBits(1)
}
<|endoftext|>


<commit_before>//
// Copyright © 2016 Bryan T. Meyers <bmeyers@datadrake.com>
//
// 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 providers

import (
	"encoding/json"
	"fmt"
	"github.com/DataDrake/cuppa/results"
	"net/http"
	"net/url"
	"regexp"
	"time"
)

var githubAPILatest = "https://api.github.com/repos/%s/releases/latest"
var githubAPIReleases = "https://api.github.com/repos/%s/releases"
var githubSource = "https://github.com/%s/archive/%s.tar.gz"
var githubRegex = regexp.MustCompilePOSIX("https?://github.com/(.*)/.*?.tar.gz")

type githubRelease struct {
	CreatedAt  string `json:"created_at"`
	Name       string `json:"name"`
	PreRelease bool   `json:"prerelease"`
	Tag        string `json:"tag_name"`
}

func (cr *githubRelease) Convert(name string) *results.Result {
	if cr.PreRelease {
		return nil
	}
	r := &results.Result{}
	r.Name = cr.Name
	r.Version = cr.Tag
	r.Published, _ = time.Parse(time.RFC3339, cr.CreatedAt)
	r.Location, _ = url.Parse(fmt.Sprintf(githubSource, name, cr.Tag))
	return r
}

type githubResultSet []githubRelease

func (crs *githubResultSet) Convert(name string) *results.ResultSet {
	rs := results.NewResultSet(name)
	for _, rel := range *crs {
		r := rel.Convert(name)
		if r != nil {
			rs.AddResult(r)
		}
	}
	return rs
}

/*
GitHubProvider is the upstream provider interface for github
*/
type GitHubProvider struct{}

/*
Latest finds the newest release for a github package
*/
func (c GitHubProvider) Latest(name string) (r *results.Result, s results.Status) {
	//Query the API
	resp, err := http.Get(fmt.Sprintf(githubAPILatest, name))
	if err != nil {
		panic(err.Error())
	}
	defer resp.Body.Close()
	//Translate Status Code
	switch resp.StatusCode {
	case 200:
		s = results.OK
	case 404:
		s = results.NotFound
	default:
		s = results.Unavailable
	}

	//Fail if not OK
	if s != results.OK {
		return
	}

	dec := json.NewDecoder(resp.Body)
	cr := &githubRelease{}
	err = dec.Decode(cr)
	if err != nil {
		panic(err.Error())
	}
	r = cr.Convert(name)
	return
}

/*
Match checks to see if this provider can handle this kind of query
*/
func (c GitHubProvider) Match(query string) string {
	sm := githubRegex.FindStringSubmatch(query)
	if len(sm) != 2 {
		return ""
	}
	return sm[1]
}

/*
Name gives the name of this provider
*/
func (c GitHubProvider) Name() string {
	return "GitHub"
}

/*
Releases finds all matching releases for a github package
*/
func (c GitHubProvider) Releases(name string) (rs *results.ResultSet, s results.Status) {
	//Query the API
	resp, err := http.Get(fmt.Sprintf(githubAPIReleases, name))
	if err != nil {
		panic(err.Error())
	}
	defer resp.Body.Close()
	//Translate Status Code
	switch resp.StatusCode {
	case 200:
		s = results.OK
	case 404:
		s = results.NotFound
	default:
		s = results.Unavailable
	}

	//Fail if not OK
	if s != results.OK {
		return
	}

	dec := json.NewDecoder(resp.Body)
	crs := make(githubResultSet, 0)
	err = dec.Decode(&crs)
	if err != nil {
		panic(err.Error())
	}
	if len(crs) == 0 {
		s = results.NotFound
		return
	}
	rs = crs.Convert(name)
	return
}
<commit_msg>Added version stripping of tags for GitHub Provider<commit_after>//
// Copyright © 2016 Bryan T. Meyers <bmeyers@datadrake.com>
//
// 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 providers

import (
	"encoding/json"
	"fmt"
	"github.com/DataDrake/cuppa/results"
	"net/http"
	"net/url"
	"regexp"
	"time"
)

var githubAPILatest = "https://api.github.com/repos/%s/releases/latest"
var githubAPIReleases = "https://api.github.com/repos/%s/releases"
var githubSource = "https://github.com/%s/archive/%s.tar.gz"
var githubRegex = regexp.MustCompile("https?://github.com/(.*)/.*?.tar.gz")
var githubVersionRegex = regexp.MustCompile("(?:\\d+\\.)*\\d+\\w*")

type githubRelease struct {
	CreatedAt  string `json:"created_at"`
	Name       string `json:"name"`
	PreRelease bool   `json:"prerelease"`
	Tag        string `json:"tag_name"`
}

func (cr *githubRelease) Convert(name string) *results.Result {
	if cr.PreRelease {
		return nil
	}
	r := &results.Result{}
	r.Name = cr.Name
	r.Version = githubVersionRegex.FindString(cr.Tag)
	r.Published, _ = time.Parse(time.RFC3339, cr.CreatedAt)
	r.Location, _ = url.Parse(fmt.Sprintf(githubSource, name, cr.Tag))
	return r
}

type githubResultSet []githubRelease

func (crs *githubResultSet) Convert(name string) *results.ResultSet {
	rs := results.NewResultSet(name)
	for _, rel := range *crs {
		r := rel.Convert(name)
		if r != nil {
			rs.AddResult(r)
		}
	}
	return rs
}

/*
GitHubProvider is the upstream provider interface for github
*/
type GitHubProvider struct{}

/*
Latest finds the newest release for a github package
*/
func (c GitHubProvider) Latest(name string) (r *results.Result, s results.Status) {
	//Query the API
	resp, err := http.Get(fmt.Sprintf(githubAPILatest, name))
	if err != nil {
		panic(err.Error())
	}
	defer resp.Body.Close()
	//Translate Status Code
	switch resp.StatusCode {
	case 200:
		s = results.OK
	case 404:
		s = results.NotFound
	default:
		s = results.Unavailable
	}

	//Fail if not OK
	if s != results.OK {
		return
	}

	dec := json.NewDecoder(resp.Body)
	cr := &githubRelease{}
	err = dec.Decode(cr)
	if err != nil {
		panic(err.Error())
	}
	r = cr.Convert(name)
	return
}

/*
Match checks to see if this provider can handle this kind of query
*/
func (c GitHubProvider) Match(query string) string {
	sm := githubRegex.FindStringSubmatch(query)
	if len(sm) != 2 {
		return ""
	}
	return sm[1]
}

/*
Name gives the name of this provider
*/
func (c GitHubProvider) Name() string {
	return "GitHub"
}

/*
Releases finds all matching releases for a github package
*/
func (c GitHubProvider) Releases(name string) (rs *results.ResultSet, s results.Status) {
	//Query the API
	resp, err := http.Get(fmt.Sprintf(githubAPIReleases, name))
	if err != nil {
		panic(err.Error())
	}
	defer resp.Body.Close()
	//Translate Status Code
	switch resp.StatusCode {
	case 200:
		s = results.OK
	case 404:
		s = results.NotFound
	default:
		s = results.Unavailable
	}

	//Fail if not OK
	if s != results.OK {
		return
	}

	dec := json.NewDecoder(resp.Body)
	crs := make(githubResultSet, 0)
	err = dec.Decode(&crs)
	if err != nil {
		panic(err.Error())
	}
	if len(crs) == 0 {
		s = results.NotFound
		return
	}
	rs = crs.Convert(name)
	return
}
<|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 kube

import (
	"errors"
	"fmt"
	"io/ioutil"

	"github.com/sirupsen/logrus"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
	clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
)

// LoadClusterConfigs loads rest.Configs for creation of clients, by using either a normal
// .kube/config file, a custom `Cluster` file, or both. The configs are returned in a mapping
// of context --> config. The default context is included in this mapping and specified as a
// return vaule. Errors are returned if .kube/config is specified and invalid or if no valid
// contexts are found.
func LoadClusterConfigs(kubeconfig, buildCluster string) (configurations map[string]rest.Config, defaultContext string, err error) {
	logrus.Infof("Loading cluster contexts...")
	configs := map[string]rest.Config{}
	var defCtx *string
	// This will work if we are running inside kubernetes
	if localCfg, err := rest.InClusterConfig(); err != nil {
		logrus.Warnf("Failed to create in-cluster config: %v", err)
	} else {
		defCtx = new(string)
		// TODO convert the default cluster alias into a default in-cluster context
		*defCtx = DefaultClusterAlias
		logrus.Info("* in-cluster")
		configs[*defCtx] = *localCfg
		configs[""] = *localCfg
	}

	// Attempt to load external clusters too
	var loader clientcmd.ClientConfigLoader
	if kubeconfig != "" { // load from --kubeconfig
		loader = &clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeconfig}
	} else {
		loader = clientcmd.NewDefaultClientConfigLoadingRules()
	}

	cfg, err := loader.Load()
	switch {
	case err != nil && kubeconfig != "":
		return nil, "", fmt.Errorf("load %s kubecfg: %v", kubeconfig, err)
	case err != nil:
		logrus.Warnf("failed to load any kubecfg files: %v", err)
	default:
		// normally defCtx is in cluster (""), but we may be a dev running on their workstation
		// in which case rest.InClusterConfig() will fail, so use the current context as default
		// (which is where we look for prowjobs)
		if defCtx == nil && cfg.CurrentContext != "" {
			defCtx = &cfg.CurrentContext
		}

		for context := range cfg.Contexts {
			logrus.Infof("* %s", context)
			contextCfg, err := clientcmd.NewNonInteractiveClientConfig(*cfg, context, &clientcmd.ConfigOverrides{}, loader).ClientConfig()
			if err != nil {
				return nil, "", fmt.Errorf("create %s client: %v", context, err)
			}
			configs[context] = *contextCfg
		}
	}

	if buildCluster != "" { // load from --build-cluster
		data, err := ioutil.ReadFile(buildCluster)
		if err != nil {
			return nil, "", fmt.Errorf("read build clusters: %v", err)
		}
		raw, err := UnmarshalClusterMap(data)
		if err != nil {
			return nil, "", fmt.Errorf("unmarshal build clusters: %v", err)
		}
		cfg = &clientcmdapi.Config{
			Clusters:  map[string]*clientcmdapi.Cluster{},
			AuthInfos: map[string]*clientcmdapi.AuthInfo{},
			Contexts:  map[string]*clientcmdapi.Context{},
		}
		for alias, config := range raw {
			cfg.Clusters[alias] = &clientcmdapi.Cluster{
				Server:                   config.Endpoint,
				CertificateAuthorityData: config.ClusterCACertificate,
			}
			cfg.AuthInfos[alias] = &clientcmdapi.AuthInfo{
				ClientCertificateData: config.ClientCertificate,
				ClientKeyData:         config.ClientKey,
			}
			cfg.Contexts[alias] = &clientcmdapi.Context{
				Cluster:  alias,
				AuthInfo: alias,
				// TODO(fejta): Namespace?
			}
		}
		for context := range cfg.Contexts {
			logrus.Infof("* %s", context)
			contextCfg, err := clientcmd.NewNonInteractiveClientConfig(*cfg, context, &clientcmd.ConfigOverrides{}, nil).ClientConfig()
			if err != nil {
				return nil, "", fmt.Errorf("create %s client: %v", context, err)
			}
			configs[context] = *contextCfg
		}
	}

	if len(configs) == 0 {
		return nil, "", errors.New("no clients found")
	}
	return configs, *defCtx, nil
}
<commit_msg>Revert "Merge pull request #11547 from ccojocar/fix-default-ctx-build"<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 kube

import (
	"errors"
	"fmt"
	"io/ioutil"

	"github.com/sirupsen/logrus"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
	clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
)

// LoadClusterConfigs loads rest.Configs for creation of clients, by using either a normal
// .kube/config file, a custom `Cluster` file, or both. The configs are returned in a mapping
// of context --> config. The default context is included in this mapping and specified as a
// return vaule. Errors are returned if .kube/config is specified and invalid or if no valid
// contexts are found.
func LoadClusterConfigs(kubeconfig, buildCluster string) (configurations map[string]rest.Config, defaultContext string, err error) {
	logrus.Infof("Loading cluster contexts...")
	configs := map[string]rest.Config{}
	var defCtx *string
	// This will work if we are running inside kubernetes
	if localCfg, err := rest.InClusterConfig(); err != nil {
		logrus.Warnf("Failed to create in-cluster config: %v", err)
	} else {
		defCtx = new(string)
		logrus.Info("* in-cluster")
		configs[*defCtx] = *localCfg
	}

	// Attempt to load external clusters too
	var loader clientcmd.ClientConfigLoader
	if kubeconfig != "" { // load from --kubeconfig
		loader = &clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeconfig}
	} else {
		loader = clientcmd.NewDefaultClientConfigLoadingRules()
	}

	cfg, err := loader.Load()
	switch {
	case err != nil && kubeconfig != "":
		return nil, "", fmt.Errorf("load %s kubecfg: %v", kubeconfig, err)
	case err != nil:
		logrus.Warnf("failed to load any kubecfg files: %v", err)
	default:
		// normally defCtx is in cluster (""), but we may be a dev running on their workstation
		// in which case rest.InClusterConfig() will fail, so use the current context as default
		// (which is where we look for prowjobs)
		if defCtx == nil && cfg.CurrentContext != "" {
			defCtx = &cfg.CurrentContext
		}

		for context := range cfg.Contexts {
			logrus.Infof("* %s", context)
			contextCfg, err := clientcmd.NewNonInteractiveClientConfig(*cfg, context, &clientcmd.ConfigOverrides{}, loader).ClientConfig()
			if err != nil {
				return nil, "", fmt.Errorf("create %s client: %v", context, err)
			}
			configs[context] = *contextCfg
		}
	}

	if buildCluster != "" { // load from --build-cluster
		data, err := ioutil.ReadFile(buildCluster)
		if err != nil {
			return nil, "", fmt.Errorf("read build clusters: %v", err)
		}
		raw, err := UnmarshalClusterMap(data)
		if err != nil {
			return nil, "", fmt.Errorf("unmarshal build clusters: %v", err)
		}
		cfg = &clientcmdapi.Config{
			Clusters:  map[string]*clientcmdapi.Cluster{},
			AuthInfos: map[string]*clientcmdapi.AuthInfo{},
			Contexts:  map[string]*clientcmdapi.Context{},
		}
		for alias, config := range raw {
			cfg.Clusters[alias] = &clientcmdapi.Cluster{
				Server:                   config.Endpoint,
				CertificateAuthorityData: config.ClusterCACertificate,
			}
			cfg.AuthInfos[alias] = &clientcmdapi.AuthInfo{
				ClientCertificateData: config.ClientCertificate,
				ClientKeyData:         config.ClientKey,
			}
			cfg.Contexts[alias] = &clientcmdapi.Context{
				Cluster:  alias,
				AuthInfo: alias,
				// TODO(fejta): Namespace?
			}
		}
		for context := range cfg.Contexts {
			logrus.Infof("* %s", context)
			contextCfg, err := clientcmd.NewNonInteractiveClientConfig(*cfg, context, &clientcmd.ConfigOverrides{}, nil).ClientConfig()
			if err != nil {
				return nil, "", fmt.Errorf("create %s client: %v", context, err)
			}
			configs[context] = *contextCfg
		}
	}

	if len(configs) == 0 {
		return nil, "", errors.New("no clients found")
	}
	return configs, *defCtx, nil
}
<|endoftext|>


<commit_before>package proxy

import (
	"bufio"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
)

// msgReader is a helper that reads values from a PostgreSQL message.
type msgReader struct {
	reader            *bufio.Reader
	buf               [128]byte
	msgBytesRemaining int32
	err               error
}

// Err returns any error that the msgReader has experienced
func (r *msgReader) Err() error {
	return r.err
}

// fatal tells r that a Fatal error has occurred
func (r *msgReader) fatal(err error) {
	r.err = err
}

// rxMsg reads the type and size of the next message.
func (r *msgReader) rxMsg() (t byte, err error) {
	if r.err != nil {
		return 0, err
	}
	if r.msgBytesRemaining > 0 {
		io.CopyN(ioutil.Discard, r.reader, int64(r.msgBytesRemaining))
	}
	b := r.buf[0:5]
	fmt.Println("1")
	min := len(b)
	fmt.Println(len(b))
	fmt.Println("2")
	var n int
	for n < min && err == nil {
		var nn int
		nn, err = r.reader.Read(b[n:])
		n += nn
		fmt.Println("3")
	}
	fmt.Println("4")
	if n >= min {
		err = nil
	} else if n > 0 && err == io.EOF {
		err = io.ErrUnexpectedEOF
	}
	// a, err := io.ReadAtLeast(r.reader, b, len(b))
	// ReadFull(r.reader, b)
	fmt.Printf("a: %#v\n", n)
	fmt.Println(err)
	if r.err != nil {
		fmt.Println(err)
	}
	r.msgBytesRemaining = int32(binary.BigEndian.Uint32(b[1:])) - 4
	return b[0], err
}

func (r *msgReader) readByte() byte {
	if r.err != nil {
		return 0
	}

	r.msgBytesRemaining -= 1
	if r.msgBytesRemaining < 0 {
		r.fatal(errors.New("read past end of message"))
		return 0
	}

	b, err := r.reader.ReadByte()
	if err != nil {
		r.fatal(err)
		return 0
	}

	return b
}

func (r *msgReader) readInt16() int16 {
	if r.err != nil {
		return 0
	}

	r.msgBytesRemaining -= 2
	if r.msgBytesRemaining < 0 {
		r.fatal(errors.New("read past end of message"))
		return 0
	}

	b := r.buf[0:2]
	_, err := io.ReadFull(r.reader, b)
	if err != nil {
		r.fatal(err)
		return 0
	}

	return int16(binary.BigEndian.Uint16(b))
}

func (r *msgReader) readInt32() int32 {
	if r.err != nil {
		return 0
	}

	r.msgBytesRemaining -= 4
	if r.msgBytesRemaining < 0 {
		r.fatal(errors.New("read past end of message"))
		return 0
	}

	b := r.buf[0:4]
	_, err := io.ReadFull(r.reader, b)
	if err != nil {
		r.fatal(err)
		return 0
	}

	return int32(binary.BigEndian.Uint32(b))
}

func (r *msgReader) readInt64() int64 {
	if r.err != nil {
		return 0
	}

	r.msgBytesRemaining -= 8
	if r.msgBytesRemaining < 0 {
		r.fatal(errors.New("read past end of message"))
		return 0
	}

	b := r.buf[0:8]
	_, err := io.ReadFull(r.reader, b)
	if err != nil {
		r.fatal(err)
		return 0
	}

	return int64(binary.BigEndian.Uint64(b))
}

func (r *msgReader) readOid() Oid {
	return Oid(r.readInt32())
}

// readCString reads a null terminated string
func (r *msgReader) readCString() string {
	if r.err != nil {
		return ""
	}

	b, err := r.reader.ReadBytes(0)
	if err != nil {
		r.fatal(err)
		return ""
	}

	r.msgBytesRemaining -= int32(len(b))
	if r.msgBytesRemaining < 0 {
		r.fatal(errors.New("read past end of message"))
		return ""
	}

	return string(b[0 : len(b)-1])
}

// readString reads count bytes and returns as string
func (r *msgReader) readString(count int32) string {
	if r.err != nil {
		return ""
	}

	r.msgBytesRemaining -= count
	if r.msgBytesRemaining < 0 {
		r.fatal(errors.New("read past end of message"))
		return ""
	}

	var b []byte
	if count <= int32(len(r.buf)) {
		b = r.buf[0:int(count)]
	} else {
		b = make([]byte, int(count))
	}

	_, err := io.ReadFull(r.reader, b)
	if err != nil {
		r.fatal(err)
		return ""
	}

	return string(b)
}

// readBytes reads count bytes and returns as []byte
func (r *msgReader) readBytes(count int32) []byte {
	if r.err != nil {
		return nil
	}

	r.msgBytesRemaining -= count
	if r.msgBytesRemaining < 0 {
		r.fatal(errors.New("read past end of message"))
		return nil
	}

	b := make([]byte, int(count))

	_, err := io.ReadFull(r.reader, b)
	if err != nil {
		r.fatal(err)
		return nil
	}

	return b
}
<commit_msg>Update<commit_after>package proxy

import (
	"bufio"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
)

// msgReader is a helper that reads values from a PostgreSQL message.
type msgReader struct {
	reader            *bufio.Reader
	buf               [128]byte
	msgBytesRemaining int32
	err               error
}

// Err returns any error that the msgReader has experienced
func (r *msgReader) Err() error {
	return r.err
}

// fatal tells r that a Fatal error has occurred
func (r *msgReader) fatal(err error) {
	r.err = err
}

// rxMsg reads the type and size of the next message.
func (r *msgReader) rxMsg() (t byte, err error) {
	if r.err != nil {
		return 0, err
	}
	if r.msgBytesRemaining > 0 {
		io.CopyN(ioutil.Discard, r.reader, int64(r.msgBytesRemaining))
	}
	b := r.buf[0:5]
	fmt.Println("1")
	min := len(b)
	var n int
	fmt.Println(len(b))
	for n < min && err == nil {
		var nn int
		fmt.Println("2")
		nn, err = r.reader.Read(b[n:])
		fmt.Println("3")
		n += nn
	}
	fmt.Println("4")
	if n >= min {
		err = nil
	} else if n > 0 && err == io.EOF {
		err = io.ErrUnexpectedEOF
	}
	// a, err := io.ReadAtLeast(r.reader, b, len(b))
	// ReadFull(r.reader, b)
	fmt.Printf("a: %#v\n", n)
	fmt.Println(err)
	if r.err != nil {
		fmt.Println(err)
	}
	r.msgBytesRemaining = int32(binary.BigEndian.Uint32(b[1:])) - 4
	return b[0], err
}

func (r *msgReader) readByte() byte {
	if r.err != nil {
		return 0
	}

	r.msgBytesRemaining -= 1
	if r.msgBytesRemaining < 0 {
		r.fatal(errors.New("read past end of message"))
		return 0
	}

	b, err := r.reader.ReadByte()
	if err != nil {
		r.fatal(err)
		return 0
	}

	return b
}

func (r *msgReader) readInt16() int16 {
	if r.err != nil {
		return 0
	}

	r.msgBytesRemaining -= 2
	if r.msgBytesRemaining < 0 {
		r.fatal(errors.New("read past end of message"))
		return 0
	}

	b := r.buf[0:2]
	_, err := io.ReadFull(r.reader, b)
	if err != nil {
		r.fatal(err)
		return 0
	}

	return int16(binary.BigEndian.Uint16(b))
}

func (r *msgReader) readInt32() int32 {
	if r.err != nil {
		return 0
	}

	r.msgBytesRemaining -= 4
	if r.msgBytesRemaining < 0 {
		r.fatal(errors.New("read past end of message"))
		return 0
	}

	b := r.buf[0:4]
	_, err := io.ReadFull(r.reader, b)
	if err != nil {
		r.fatal(err)
		return 0
	}

	return int32(binary.BigEndian.Uint32(b))
}

func (r *msgReader) readInt64() int64 {
	if r.err != nil {
		return 0
	}

	r.msgBytesRemaining -= 8
	if r.msgBytesRemaining < 0 {
		r.fatal(errors.New("read past end of message"))
		return 0
	}

	b := r.buf[0:8]
	_, err := io.ReadFull(r.reader, b)
	if err != nil {
		r.fatal(err)
		return 0
	}

	return int64(binary.BigEndian.Uint64(b))
}

func (r *msgReader) readOid() Oid {
	return Oid(r.readInt32())
}

// readCString reads a null terminated string
func (r *msgReader) readCString() string {
	if r.err != nil {
		return ""
	}

	b, err := r.reader.ReadBytes(0)
	if err != nil {
		r.fatal(err)
		return ""
	}

	r.msgBytesRemaining -= int32(len(b))
	if r.msgBytesRemaining < 0 {
		r.fatal(errors.New("read past end of message"))
		return ""
	}

	return string(b[0 : len(b)-1])
}

// readString reads count bytes and returns as string
func (r *msgReader) readString(count int32) string {
	if r.err != nil {
		return ""
	}

	r.msgBytesRemaining -= count
	if r.msgBytesRemaining < 0 {
		r.fatal(errors.New("read past end of message"))
		return ""
	}

	var b []byte
	if count <= int32(len(r.buf)) {
		b = r.buf[0:int(count)]
	} else {
		b = make([]byte, int(count))
	}

	_, err := io.ReadFull(r.reader, b)
	if err != nil {
		r.fatal(err)
		return ""
	}

	return string(b)
}

// readBytes reads count bytes and returns as []byte
func (r *msgReader) readBytes(count int32) []byte {
	if r.err != nil {
		return nil
	}

	r.msgBytesRemaining -= count
	if r.msgBytesRemaining < 0 {
		r.fatal(errors.New("read past end of message"))
		return nil
	}

	b := make([]byte, int(count))

	_, err := io.ReadFull(r.reader, b)
	if err != nil {
		r.fatal(err)
		return nil
	}

	return b
}
<|endoftext|>


<commit_before>package data

import (
	"time"

	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
)

type Project struct {
	ID             bson.ObjectId   `bson:"_id"`
	Name           string          `bson:"name"`
	OwnerID        bson.ObjectId   `bson:"owner_id"`
	OrganizationID bson.ObjectId   `bson:"organization_id"`
	MemberIDs      []bson.ObjectId `bson:"member_ids"`
	CreatedAt      time.Time       `bson:"created_at"`
	ModifiedAt     time.Time       `bson:"modified_at"`
}

func ListProjectsOrganization(orgID bson.ObjectId, skip, limit int) ([]Project, error) {
	prjs := []Project{}

	err := sess.DB("").C(projectC).
		Find(bson.M{"organization_id": orgID}).
		Skip(skip).
		Limit(limit).
		Sort("-created_at").
		All(&prjs)
	if err != nil {
		return nil, err
	}

	return prjs, nil
}

func GetProject(id bson.ObjectId) (*Project, error) {
	pro := Project{}
	err := sess.DB("").C(projectC).FindId(id).One(&pro)
	if err == mgo.ErrNotFound {
		return nil, nil
	}
	if err != nil {
		return nil, err
	}
	return &pro, nil
}

func (p *Project) Members() ([]Memeber, error) {
	mems := []Memeber{}
	err := sess.DB("").C(memberC).
		Find(bson.M{"_id": bson.M{"$in": p.MemberIDs}}).
		All(&mems)

	if err != nil {
		return nil, err
	}
	return mems, nil
}

func (p *Project) Organization() (*Organization, error) {
	return GetOraganization(p.OrganizationID)
}

func (p *Project) Owner() (*Account, error) {
	return GetAccount(p.OwnerID)
}

func (p *Project) Put() error {
	p.ModifiedAt = time.Now()

	if p.ID == "" {
		p.ID = bson.NewObjectId()
		p.CreatedAt = p.ModifiedAt
	}
	_, err := sess.DB("").C(organizationC).UpsertId(p.ID, p)
	return err
}
<commit_msg>Change Members method in project<commit_after>package data

import (
	"time"

	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
)

type Project struct {
	ID             bson.ObjectId   `bson:"_id"`
	Name           string          `bson:"name"`
	OwnerID        bson.ObjectId   `bson:"owner_id"`
	OrganizationID bson.ObjectId   `bson:"organization_id"`
	MemberIDs      []bson.ObjectId `bson:"member_ids"`
	CreatedAt      time.Time       `bson:"created_at"`
	ModifiedAt     time.Time       `bson:"modified_at"`
}

func ListProjectsOrganization(orgID bson.ObjectId, skip, limit int) ([]Project, error) {
	prjs := []Project{}

	err := sess.DB("").C(projectC).
		Find(bson.M{"organization_id": orgID}).
		Skip(skip).
		Limit(limit).
		Sort("-created_at").
		All(&prjs)
	if err != nil {
		return nil, err
	}

	return prjs, nil
}

func GetProject(id bson.ObjectId) (*Project, error) {
	pro := Project{}
	err := sess.DB("").C(projectC).FindId(id).One(&pro)
	if err == mgo.ErrNotFound {
		return nil, nil
	}
	if err != nil {
		return nil, err
	}
	return &pro, nil
}

func (p *Project) Members() ([]Memeber, error) {
	mems := []Memeber{}
	err := sess.DB("").C(memberC).
		Find(bson.M{"project_id": p.ID}).
		All(&mems)

	if err != nil {
		return nil, err
	}
	return mems, nil
}

func (p *Project) Organization() (*Organization, error) {
	return GetOraganization(p.OrganizationID)
}

func (p *Project) Owner() (*Account, error) {
	return GetAccount(p.OwnerID)
}

func (p *Project) Put() error {
	p.ModifiedAt = time.Now()

	if p.ID == "" {
		p.ID = bson.NewObjectId()
		p.CreatedAt = p.ModifiedAt
	}
	_, err := sess.DB("").C(organizationC).UpsertId(p.ID, p)
	return err
}
<|endoftext|>


<commit_before>/*
Copyright 2017 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 client

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"time"

	"k8s.io/test-infra/boskos/common"
)

// Public Boskos client object
type Client struct {
	url       string
	resources []string
	owner     string
}

// NewClient creates a boskos client, with boskos url and owner of the client.
func NewClient(owner string, url string) *Client {

	client := &Client{
		url:   url,
		owner: owner,
	}

	return client
}

// public method

// Acquire asks boskos for a resource of certain type in certain state.
// Returns name of the resource on success.
func (c *Client) Acquire(rtype string, state string) (string, error) {
	r, err := c.acquire(rtype, state)
	if err != nil {
		return "", err
	}

	c.resources = append(c.resources, r)
	return r, nil
}

// ReleaseAll returns all resource hold by the client back to boskos and set them to dest state.
func (c *Client) ReleaseAll(dest string) error {
	if len(c.resources) == 0 {
		return fmt.Errorf("No holding resource")
	}

	for {
		r, ok := c.popResource()
		if !ok {
			break
		}

		if err := c.release(r, dest); err != nil {
			return err
		}
	}

	return nil
}

// ReleaseOne returns one of owned resource back to boskos and set it to dest state.
func (c *Client) ReleaseOne(name string, dest string) error {

	for idx, r := range c.resources {
		if r == name {
			c.resources[idx] = c.resources[len(c.resources)-1]
			c.resources = c.resources[:len(c.resources)-1]
			if err := c.release(r, dest); err != nil {
				return err
			}
			return nil
		}
	}

	return fmt.Errorf("No resource name %v", name)
}

// UpdateAll signals update for all resources hold by the client.
func (c *Client) UpdateAll(state string) error {
	if len(c.resources) == 0 {
		return fmt.Errorf("No holding resource")
	}

	for _, r := range c.resources {
		if err := c.update(r, state); err != nil {
			return err
		}
	}

	return nil
}

// UpdateOne signals update for one of the resource hold by the client.
func (c *Client) UpdateOne(name string, state string) error {
	for _, r := range c.resources {
		if r == name {
			if err := c.update(r, state); err != nil {
				return err
			}
			return nil
		}
	}

	return fmt.Errorf("No resource name %v", name)
}

// Reset will scan all boskos resources of type, in state, last updated before expire, and set them to dest state.
// Returns a map of {resourceName:owner} for further actions.
func (c *Client) Reset(rtype string, state string, expire time.Duration, dest string) (map[string]string, error) {
	return c.reset(rtype, state, expire, dest)
}

// private methods

func (c *Client) popResource() (string, bool) {
	if len(c.resources) == 0 {
		return "", false
	}

	r := c.resources[len(c.resources)-1]
	c.resources = c.resources[:len(c.resources)-1]
	return r, true
}

func (c *Client) acquire(rtype string, state string) (string, error) {
	resp, err := http.Get(fmt.Sprintf("%v/acquire?type=%v&state=%v&owner=%v", c.url, rtype, state, c.owner))
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	if resp.StatusCode == 200 {
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return "", err
		}

		var res = new(common.Resource)
		err = json.Unmarshal(body, &res)
		if err != nil {
			return "", err
		}
		return res.Name, nil
	}

	return "", fmt.Errorf("Status %s, StatusCode %v", resp.Status, resp.StatusCode)
}

func (c *Client) release(name string, dest string) error {
	resp, err := http.Get(fmt.Sprintf("%v/release?name=%v&dest=%v&owner=%v", c.url, name, dest, c.owner))
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		return fmt.Errorf("Status %s, StatusCode %v", resp.Status, resp.StatusCode)
	}
	return nil
}

func (c *Client) update(name string, state string) error {
	resp, err := http.Get(fmt.Sprintf("%v/update?name=%v&owner=%v&state=%v", c.url, name, c.owner, state))
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		return fmt.Errorf("Status %s, StatusCode %v", resp.Status, resp.StatusCode)
	}
	return nil
}

func (c *Client) reset(rtype string, state string, expire time.Duration, dest string) (map[string]string, error) {
	rmap := make(map[string]string)
	resp, err := http.Get(fmt.Sprintf("%v/reset?type=%v&state=%v&expire=%v&dest=%v", c.url, rtype, state, expire.String(), dest))
	if err != nil {
		return rmap, err
	}
	defer resp.Body.Close()

	if resp.StatusCode == 200 {
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return rmap, err
		}

		err = json.Unmarshal(body, &rmap)
		if err != nil {
			return rmap, err
		}
		return rmap, nil
	}

	return rmap, fmt.Errorf("Status %s, StatusCode %v", resp.Status, resp.StatusCode)
}
<commit_msg>Use POST method (#2600)<commit_after>/*
Copyright 2017 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 client

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"time"

	"k8s.io/test-infra/boskos/common"
)

// Public Boskos client object
type Client struct {
	url       string
	resources []string
	owner     string
}

// NewClient creates a boskos client, with boskos url and owner of the client.
func NewClient(owner string, url string) *Client {

	client := &Client{
		url:   url,
		owner: owner,
	}

	return client
}

// public method

// Acquire asks boskos for a resource of certain type in certain state.
// Returns name of the resource on success.
func (c *Client) Acquire(rtype string, state string) (string, error) {
	r, err := c.acquire(rtype, state)
	if err != nil {
		return "", err
	}

	c.resources = append(c.resources, r)
	return r, nil
}

// ReleaseAll returns all resource hold by the client back to boskos and set them to dest state.
func (c *Client) ReleaseAll(dest string) error {
	if len(c.resources) == 0 {
		return fmt.Errorf("No holding resource")
	}

	for {
		r, ok := c.popResource()
		if !ok {
			break
		}

		if err := c.release(r, dest); err != nil {
			return err
		}
	}

	return nil
}

// ReleaseOne returns one of owned resource back to boskos and set it to dest state.
func (c *Client) ReleaseOne(name string, dest string) error {

	for idx, r := range c.resources {
		if r == name {
			c.resources[idx] = c.resources[len(c.resources)-1]
			c.resources = c.resources[:len(c.resources)-1]
			if err := c.release(r, dest); err != nil {
				return err
			}
			return nil
		}
	}

	return fmt.Errorf("No resource name %v", name)
}

// UpdateAll signals update for all resources hold by the client.
func (c *Client) UpdateAll(state string) error {
	if len(c.resources) == 0 {
		return fmt.Errorf("No holding resource")
	}

	for _, r := range c.resources {
		if err := c.update(r, state); err != nil {
			return err
		}
	}

	return nil
}

// UpdateOne signals update for one of the resource hold by the client.
func (c *Client) UpdateOne(name string, state string) error {
	for _, r := range c.resources {
		if r == name {
			if err := c.update(r, state); err != nil {
				return err
			}
			return nil
		}
	}

	return fmt.Errorf("No resource name %v", name)
}

// Reset will scan all boskos resources of type, in state, last updated before expire, and set them to dest state.
// Returns a map of {resourceName:owner} for further actions.
func (c *Client) Reset(rtype string, state string, expire time.Duration, dest string) (map[string]string, error) {
	return c.reset(rtype, state, expire, dest)
}

// private methods

func (c *Client) popResource() (string, bool) {
	if len(c.resources) == 0 {
		return "", false
	}

	r := c.resources[len(c.resources)-1]
	c.resources = c.resources[:len(c.resources)-1]
	return r, true
}

func (c *Client) acquire(rtype string, state string) (string, error) {
	resp, err := http.Post(fmt.Sprintf("%v/acquire?type=%v&state=%v&owner=%v", c.url, rtype, state, c.owner), "", nil)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	if resp.StatusCode == 200 {
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return "", err
		}

		var res = new(common.Resource)
		err = json.Unmarshal(body, &res)
		if err != nil {
			return "", err
		}
		return res.Name, nil
	}

	return "", fmt.Errorf("Status %s, StatusCode %v", resp.Status, resp.StatusCode)
}

func (c *Client) release(name string, dest string) error {
	resp, err := http.Post(fmt.Sprintf("%v/release?name=%v&dest=%v&owner=%v", c.url, name, dest, c.owner), "", nil)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		return fmt.Errorf("Status %s, StatusCode %v", resp.Status, resp.StatusCode)
	}
	return nil
}

func (c *Client) update(name string, state string) error {
	resp, err := http.Post(fmt.Sprintf("%v/update?name=%v&owner=%v&state=%v", c.url, name, c.owner, state), "", nil)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		return fmt.Errorf("Status %s, StatusCode %v", resp.Status, resp.StatusCode)
	}
	return nil
}

func (c *Client) reset(rtype string, state string, expire time.Duration, dest string) (map[string]string, error) {
	rmap := make(map[string]string)
	resp, err := http.Post(fmt.Sprintf("%v/reset?type=%v&state=%v&expire=%v&dest=%v", c.url, rtype, state, expire.String(), dest), "", nil)
	if err != nil {
		return rmap, err
	}
	defer resp.Body.Close()

	if resp.StatusCode == 200 {
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return rmap, err
		}

		err = json.Unmarshal(body, &rmap)
		if err != nil {
			return rmap, err
		}
		return rmap, nil
	}

	return rmap, fmt.Errorf("Status %s, StatusCode %v", resp.Status, resp.StatusCode)
}
<|endoftext|>


<commit_before>package bot

/////////////////////////////////////////////////////////////////////////////
// default event handlers
func HandleUserJoin(data interface{}) {
	var join *UserJoinData

	join = data.(*UserJoinData)

	join.bot.Logger().Printf("%s joined %s", join.nick, join.channel)
}

func HandleUserPart(data interface{}) {
	var part *UserPartData

	part = data.(*UserPartData)

	part.bot.Logger().Printf("%s parted %s: %s", part.nick, part.channel, part.msg)
}

func HandleUserQuit(data interface{}) {
	var quit *UserQuitData

	quit = data.(*UserQuitData)

	quit.bot.Logger().Printf("%s quited: %s", quit.nick, quit.msg)
}

func HandleUserNick(data interface{}) {
	var nick *UserNickData

	nick = data.(*UserNickData)

	nick.bot.Logger().Printf("%s changed nick %s", nick.nick, nick.newNick)
}

func HandlePong(data interface{}) {
	var pong *PongData

	pong = data.(*PongData)

	pong.bot.Logger().Printf("pong from %s: %s", pong.from, pong.origin)
}
<commit_msg>Do nothing in default handlers<commit_after>package bot

/////////////////////////////////////////////////////////////////////////////
// default event handlers
func HandleUserJoin(data interface{}) {
	var join *UserJoinData

	join = data.(*UserJoinData)

	NewNopLogger(nil, "").Printf("%s joined %s", join.nick, join.channel)
}

func HandleUserPart(data interface{}) {
	var part *UserPartData

	part = data.(*UserPartData)

	NewNopLogger(nil, "").Printf("%s parted %s: %s", part.nick, part.channel, part.msg)
}

func HandleUserQuit(data interface{}) {
	var quit *UserQuitData

	quit = data.(*UserQuitData)

	NewNopLogger(nil, "").Printf("%s quited: %s", quit.nick, quit.msg)
}

func HandleUserNick(data interface{}) {
	var nick *UserNickData

	nick = data.(*UserNickData)

	NewNopLogger(nil, "").Printf("%s changed nick %s", nick.nick, nick.newNick)
}

func HandlePong(data interface{}) {
	var pong *PongData

	pong = data.(*PongData)

	NewNopLogger(nil, "").Printf("pong from %s: %s", pong.from, pong.origin)
}
<|endoftext|>


<commit_before>package tgbotapi_test

import (
	"testing"
	"time"

	"github.com/go-telegram-bot-api/telegram-bot-api"
)

func TestUserStringWith(t *testing.T) {
	user := tgbotapi.User{0, "Test", "Test", "", "en"}

	if user.String() != "Test Test" {
		t.Fail()
	}
}

func TestUserStringWithUserName(t *testing.T) {
	user := tgbotapi.User{0, "Test", "Test", "@test", "en"}

	if user.String() != "@test" {
		t.Fail()
	}
}

func TestMessageTime(t *testing.T) {
	message := tgbotapi.Message{Date: 0}

	date := time.Unix(0, 0)
	if message.Time() != date {
		t.Fail()
	}
}

func TestMessageIsCommandWithCommand(t *testing.T) {
	message := tgbotapi.Message{Text: "/command"}
	message.Entities = &[]tgbotapi.MessageEntity{{Type: "bot_command", Offset: 0, Length: 8}}

	if message.IsCommand() != true {
		t.Fail()
	}
}

func TestIsCommandWithText(t *testing.T) {
	message := tgbotapi.Message{Text: "some text"}

	if message.IsCommand() != false {
		t.Fail()
	}
}

func TestIsCommandWithEmptyText(t *testing.T) {
	message := tgbotapi.Message{Text: ""}

	if message.IsCommand() != false {
		t.Fail()
	}
}

func TestCommandWithCommand(t *testing.T) {
	message := tgbotapi.Message{Text: "/command"}
	message.Entities = &[]tgbotapi.MessageEntity{{Type: "bot_command", Offset: 0, Length: 8}}

	if message.Command() != "command" {
		t.Fail()
	}
}

func TestCommandWithEmptyText(t *testing.T) {
	message := tgbotapi.Message{Text: ""}

	if message.Command() != "" {
		t.Fail()
	}
}

func TestCommandWithNonCommand(t *testing.T) {
	message := tgbotapi.Message{Text: "test text"}

	if message.Command() != "" {
		t.Fail()
	}
}

func TestCommandWithBotName(t *testing.T) {
	message := tgbotapi.Message{Text: "/command@testbot"}
	message.Entities = &[]tgbotapi.MessageEntity{{Type: "bot_command", Offset: 0, Length: 16}}

	if message.Command() != "command" {
		t.Fail()
	}
}

func TestMessageCommandArgumentsWithArguments(t *testing.T) {
	message := tgbotapi.Message{Text: "/command with arguments"}
	message.Entities = &[]tgbotapi.MessageEntity{{Type: "bot_command", Offset: 0, Length: 8}}
	if message.CommandArguments() != "with arguments" {
		t.Fail()
	}
}

func TestMessageCommandArgumentsWithoutArguments(t *testing.T) {
	message := tgbotapi.Message{Text: "/command"}
	if message.CommandArguments() != "" {
		t.Fail()
	}
}

func TestMessageCommandArgumentsForNonCommand(t *testing.T) {
	message := tgbotapi.Message{Text: "test text"}
	if message.CommandArguments() != "" {
		t.Fail()
	}
}

func TestMessageEntityParseURLGood(t *testing.T) {
	entity := tgbotapi.MessageEntity{URL: "https://www.google.com"}

	if _, err := entity.ParseURL(); err != nil {
		t.Fail()
	}
}

func TestMessageEntityParseURLBad(t *testing.T) {
	entity := tgbotapi.MessageEntity{URL: ""}

	if _, err := entity.ParseURL(); err == nil {
		t.Fail()
	}
}

func TestChatIsPrivate(t *testing.T) {
	chat := tgbotapi.Chat{ID: 10, Type: "private"}

	if chat.IsPrivate() != true {
		t.Fail()
	}
}

func TestChatIsGroup(t *testing.T) {
	chat := tgbotapi.Chat{ID: 10, Type: "group"}

	if chat.IsGroup() != true {
		t.Fail()
	}
}

func TestChatIsChannel(t *testing.T) {
	chat := tgbotapi.Chat{ID: 10, Type: "channel"}

	if chat.IsChannel() != true {
		t.Fail()
	}
}

func TestChatIsSuperGroup(t *testing.T) {
	chat := tgbotapi.Chat{ID: 10, Type: "supergroup"}

	if !chat.IsSuperGroup() {
		t.Fail()
	}
}

func TestFileLink(t *testing.T) {
	file := tgbotapi.File{FilePath: "test/test.txt"}

	if file.Link("token") != "https://api.telegram.org/file/bottoken/test/test.txt" {
		t.Fail()
	}
}
<commit_msg>Add missing tests<commit_after>package tgbotapi_test

import (
	"testing"
	"time"

	"github.com/go-telegram-bot-api/telegram-bot-api"
)

func TestUserStringWith(t *testing.T) {
	user := tgbotapi.User{0, "Test", "Test", "", "en"}

	if user.String() != "Test Test" {
		t.Fail()
	}
}

func TestUserStringWithUserName(t *testing.T) {
	user := tgbotapi.User{0, "Test", "Test", "@test", "en"}

	if user.String() != "@test" {
		t.Fail()
	}
}

func TestMessageTime(t *testing.T) {
	message := tgbotapi.Message{Date: 0}

	date := time.Unix(0, 0)
	if message.Time() != date {
		t.Fail()
	}
}

func TestMessageIsCommandWithCommand(t *testing.T) {
	message := tgbotapi.Message{Text: "/command"}
	message.Entities = &[]tgbotapi.MessageEntity{{Type: "bot_command", Offset: 0, Length: 8}}

	if message.IsCommand() != true {
		t.Fail()
	}
}

func TestIsCommandWithText(t *testing.T) {
	message := tgbotapi.Message{Text: "some text"}

	if message.IsCommand() != false {
		t.Fail()
	}
}

func TestIsCommandWithEmptyText(t *testing.T) {
	message := tgbotapi.Message{Text: ""}

	if message.IsCommand() != false {
		t.Fail()
	}
}

func TestCommandWithCommand(t *testing.T) {
	message := tgbotapi.Message{Text: "/command"}
	message.Entities = &[]tgbotapi.MessageEntity{{Type: "bot_command", Offset: 0, Length: 8}}

	if message.Command() != "command" {
		t.Fail()
	}
}

func TestCommandWithEmptyText(t *testing.T) {
	message := tgbotapi.Message{Text: ""}

	if message.Command() != "" {
		t.Fail()
	}
}

func TestCommandWithNonCommand(t *testing.T) {
	message := tgbotapi.Message{Text: "test text"}

	if message.Command() != "" {
		t.Fail()
	}
}

func TestCommandWithBotName(t *testing.T) {
	message := tgbotapi.Message{Text: "/command@testbot"}
	message.Entities = &[]tgbotapi.MessageEntity{{Type: "bot_command", Offset: 0, Length: 16}}

	if message.Command() != "command" {
		t.Fail()
	}
}

func TestCommandWithAtWithBotName(t *testing.T) {
	message := tgbotapi.Message{Text: "/command@testbot"}
	message.Entities = &[]tgbotapi.MessageEntity{{Type: "bot_command", Offset: 0, Length: 16}}

	if message.CommandWithAt() != "command@testbot" {
		t.Fail()
	}
}

func TestMessageCommandArgumentsWithArguments(t *testing.T) {
	message := tgbotapi.Message{Text: "/command with arguments"}
	message.Entities = &[]tgbotapi.MessageEntity{{Type: "bot_command", Offset: 0, Length: 8}}
	if message.CommandArguments() != "with arguments" {
		t.Fail()
	}
}

func TestMessageCommandArgumentsWithMalformedArguments(t *testing.T) {
	message := tgbotapi.Message{Text: "/command-without argument space"}
	message.Entities = &[]tgbotapi.MessageEntity{{Type: "bot_command", Offset: 0, Length: 8}}
	if message.CommandArguments() != "without argument space" {
		t.Fail()
	}
}

func TestMessageCommandArgumentsWithoutArguments(t *testing.T) {
	message := tgbotapi.Message{Text: "/command"}
	if message.CommandArguments() != "" {
		t.Fail()
	}
}

func TestMessageCommandArgumentsForNonCommand(t *testing.T) {
	message := tgbotapi.Message{Text: "test text"}
	if message.CommandArguments() != "" {
		t.Fail()
	}
}

func TestMessageEntityParseURLGood(t *testing.T) {
	entity := tgbotapi.MessageEntity{URL: "https://www.google.com"}

	if _, err := entity.ParseURL(); err != nil {
		t.Fail()
	}
}

func TestMessageEntityParseURLBad(t *testing.T) {
	entity := tgbotapi.MessageEntity{URL: ""}

	if _, err := entity.ParseURL(); err == nil {
		t.Fail()
	}
}

func TestChatIsPrivate(t *testing.T) {
	chat := tgbotapi.Chat{ID: 10, Type: "private"}

	if chat.IsPrivate() != true {
		t.Fail()
	}
}

func TestChatIsGroup(t *testing.T) {
	chat := tgbotapi.Chat{ID: 10, Type: "group"}

	if chat.IsGroup() != true {
		t.Fail()
	}
}

func TestChatIsChannel(t *testing.T) {
	chat := tgbotapi.Chat{ID: 10, Type: "channel"}

	if chat.IsChannel() != true {
		t.Fail()
	}
}

func TestChatIsSuperGroup(t *testing.T) {
	chat := tgbotapi.Chat{ID: 10, Type: "supergroup"}

	if !chat.IsSuperGroup() {
		t.Fail()
	}
}

func TestFileLink(t *testing.T) {
	file := tgbotapi.File{FilePath: "test/test.txt"}

	if file.Link("token") != "https://api.telegram.org/file/bottoken/test/test.txt" {
		t.Fail()
	}
}
<|endoftext|>


<commit_before>package slack

import (
	"fmt"
	"log"
	"regexp"
	"strconv"
	"time"

	"github.com/netflix/hal-9001/hal"
	"github.com/nlopes/slack"
)

// Broker interacts with the slack service.
type Broker struct {
	Client  *slack.Client     // slack API object
	RTM     *slack.RTM        // slack RTM object
	inst    string            // broker instance name
	i2u     map[string]string // id->name cache
	i2c     map[string]string // id->name cache
	u2i     map[string]string // name->id cache
	c2i     map[string]string // name->id cache
	idRegex *regexp.Regexp    // compiled RE to match user/channel ids
}

type Config struct {
	Token string
}

func (c Config) NewBroker(name string) Broker {
	client := slack.New(c.Token)
	// TODO: check for failures and log.Fatalf()
	rtm := client.NewRTM()

	sb := Broker{
		Client:  client,
		RTM:     rtm,
		inst:    name,
		i2u:     make(map[string]string),
		i2c:     make(map[string]string),
		u2i:     make(map[string]string),
		c2i:     make(map[string]string),
		idRegex: regexp.MustCompile("^[UC][A-Z0-9]{8}$"),
	}

	// fill the caches at startup to cut down on API requests
	sb.FillUserCache()
	sb.FillChannelCache()

	go rtm.ManageConnection()

	return sb
}

// Name returns the name of the broker as set in NewBroker.
func (sb Broker) Name() string {
	return sb.inst
}

func (sb Broker) Send(evt hal.Evt) {
	// make sure the channel is an ID and not the name
	// TODO: go through plugins, etc and see if there's a sane way to make the ID persist through
	// the system and have the name only resolve in and out of the genericbroker and in plugins
	// but probably not ... this should be fine
	var channel string
	if sb.idRegex.MatchString(evt.Channel) {
		channel = evt.Channel
	} else {
		channel = sb.ChannelNameToId(evt.Channel)
	}

	om := sb.RTM.NewOutgoingMessage(evt.Body, channel)
	sb.RTM.SendMessage(om)
}

// checks the cache to see if the channel is known to this broker
func (sb Broker) HasChannel(channel string) bool {
	if sb.idRegex.MatchString(channel) {
		_, exists := sb.i2c[channel]
		return exists
	} else {
		_, exists := sb.c2i[channel]
		return exists
	}
}

// Stream is an event loop for Slack events & messages from the RTM API.
// Events are copied to a hal.Evt and forwarded to the exchange where they
// can be processed by registered handlers.
func (sb Broker) Stream(out chan *hal.Evt) {
	for {
		select {
		case msg := <-sb.RTM.IncomingEvents:
			switch ev := msg.Data.(type) {
			case *slack.HelloEvent:
				log.Println("slack.HelloEvent") // ignored

			case *slack.ConnectedEvent:
				log.Printf("slack.ConnectedEvent (%s)\n", msg.Type) // ignored

			case *slack.MessageEvent:
				m := msg.Data.(*slack.MessageEvent)
				e := hal.Evt{
					Body:      m.Text,
					Channel:   sb.ChannelIdToName(m.Channel),
					ChannelId: m.Channel,
					From:      sb.UserIdToName(m.User),
					FromId:    m.User,
					Broker:    sb,
					Time:      slackTime(m.Timestamp),
					IsGeneric: true,
					Original:  m,
				}

				out <- &e

			case *slack.StarAddedEvent:
				sae := msg.Data.(*slack.StarAddedEvent)
				user := sb.UserIdToName(sae.User)

				e := hal.Evt{
					Body:      fmt.Sprintf("%q added a star", user),
					Channel:   sb.ChannelIdToName(sae.Item.Channel),
					ChannelId: sae.Item.Channel,
					From:      user,
					FromId:    sae.User,
					Broker:    sb,
					Time:      slackTime(sae.EventTimestamp),
					IsGeneric: false, // only available to slack-aware plugins
					Original:  sae,
				}

				out <- &e

			case *slack.StarRemovedEvent:
				sre := msg.Data.(*slack.StarRemovedEvent)
				user := sb.UserIdToName(sre.User)

				e := hal.Evt{
					Body:      fmt.Sprintf("%q removed a star", user),
					Channel:   sb.ChannelIdToName(sre.Item.Channel),
					ChannelId: sre.Item.Channel,
					From:      user,
					FromId:    sre.User,
					Broker:    sb,
					Time:      slackTime(sre.EventTimestamp),
					IsGeneric: false, // only available to slack-aware plugins
					Original:  sre,
				}

				out <- &e

			case *slack.ReactionAddedEvent:
				rae := msg.Data.(*slack.ReactionAddedEvent)
				user := sb.UserIdToName(rae.User)

				e := hal.Evt{
					Body:      fmt.Sprintf("%q added reaction %q", user, rae.Reaction),
					Channel:   sb.ChannelIdToName(rae.Item.Channel),
					ChannelId: rae.Item.Channel,
					From:      user,
					FromId:    rae.User,
					Broker:    sb,
					Time:      slackTime(rae.EventTimestamp),
					IsGeneric: false, // only available to slack-aware plugins
					Original:  rae,
				}

				out <- &e

			case *slack.ReactionRemovedEvent:
				rre := msg.Data.(*slack.ReactionAddedEvent)
				user := sb.UserIdToName(rre.User)

				e := hal.Evt{
					Body:      fmt.Sprintf("%q removed reaction %q", user, rre.Reaction),
					Channel:   sb.ChannelIdToName(rre.Item.Channel),
					ChannelId: rre.Item.Channel,
					From:      user,
					FromId:    rre.User,
					Broker:    sb,
					Time:      slackTime(rre.EventTimestamp),
					IsGeneric: false, // only available to slack-aware plugins
					Original:  rre,
				}

				out <- &e

			case *slack.PresenceChangeEvent:
				// ignored

			case *slack.LatencyReport:
				// ignored

			case *slack.RTMError:
				log.Printf("slack.RTMError: %s\n", ev.Error())

			case *slack.InvalidAuthEvent:
				log.Println("slack.InvalidAuthEvent")
				break

			default:
				log.Printf("Unexpected: %v\n", msg.Data)
			}
		}
	}
}

// slackTime converts the timestamp string to time.Time
// cribbed from: https://github.com/nlopes/slack/commit/17d746b30caa733b519f79fe372fd509bd6fc9fd
func slackTime(t string) time.Time {
	if t == "" {
		return time.Now()
	}

	floatN, err := strconv.ParseFloat(t, 64)
	if err != nil {
		log.Println("Error parsing Slack time string %q:", t, err)
		return time.Now()
	}

	return time.Unix(int64(floatN), 0)
}

func (sb *Broker) FillUserCache() {
	users, err := sb.Client.GetUsers()
	if err != nil {
		log.Printf("Failed to fetch user list: %s", err)
		return
	}

	for _, user := range users {
		sb.u2i[user.Name] = user.ID
		sb.i2u[user.ID] = user.Name
	}
}

func (sb *Broker) FillChannelCache() {
	channels, err := sb.Client.GetChannels(true)
	if err != nil {
		log.Printf("Failed to fetch channel list: %s", err)
		return
	}

	for _, channel := range channels {
		sb.c2i[channel.Name] = channel.ID
		sb.i2c[channel.ID] = channel.Name
	}
}

// UserIdToName gets the human-readable username for a user ID using an
// in-memory cache that falls through to the Slack API
func (sb Broker) UserIdToName(id string) string {
	if id == "" {
		log.Println("broker/slack/UserIdToName(): Cannot look up empty string!")
		return ""
	}

	if name, exists := sb.i2u[id]; exists {
		return name
	} else {
		user, err := sb.Client.GetUserInfo(id)
		if err != nil {
			log.Printf("Could not retrieve user info for '%s' from the slack API: %s\n", id, err)
			return ""
		}

		// TODO: verify if channel/user names are enforced unique in slack or if this is madness
		// remove this if it proves unnecessary (tobert/2016-03-02)
		if _, exists := sb.u2i[user.Name]; exists {
			if sb.u2i[user.Name] != user.ID {
				log.Fatalf("BUG: found a non-unique user name:ID pair. Had: %q/%q. Got: %q/%q",
					user.Name, sb.u2i[user.Name], user.Name, user.ID)
			}
		}

		sb.i2u[user.ID] = user.Name
		sb.i2u[user.Name] = user.ID

		return user.Name
	}
}

// ChannelIdToName gets the human-readable channel name for a user ID using an
// in-memory cache that falls through to the Slack API
func (sb Broker) ChannelIdToName(id string) string {
	if id == "" {
		log.Println("broker/slack/ChannelIdToName(): Cannot look up empty string!")
		return ""
	}

	if name, exists := sb.i2c[id]; exists {
		return name
	} else {
		channel, err := sb.Client.GetChannelInfo(id)
		if err != nil {
			log.Printf("Could not retrieve channel info for '%s' from the slack API: %s\n", id, err)
			return ""
		}

		// TODO: verify if channel/user names are enforced unique in slack or if this is madness
		// remove this if it proves unnecessary (tobert/2016-03-02)
		if _, exists := sb.c2i[channel.Name]; exists {
			if sb.c2i[channel.Name] != channel.ID {
				log.Fatalf("BUG: found a non-unique channel name:ID pair. Had: %q/%q. Got: %q/%q",
					channel.Name, sb.c2i[channel.Name], channel.Name, channel.ID)
			}
		}

		sb.i2c[channel.ID] = channel.Name
		sb.c2i[channel.Name] = channel.ID

		return channel.Name
	}
}

// UserNameToId gets the human-readable username for a user ID using an
// in-memory cache that falls through to the Slack API
func (sb Broker) UserNameToId(name string) string {
	if name == "" {
		log.Println("broker/slack/UserNameToId(): Cannot look up empty string!")
		return ""
	}

	if id, exists := sb.u2i[name]; exists {
		return id
	} else {
		// there doesn't seem to be a name->id lookup so refresh the cache
		// and try again if we get here
		sb.FillUserCache()
		if id, exists := sb.u2i[name]; exists {
			return id
		}

		log.Printf("Slack does not seem to have knowledge of username %q", name)
		return ""
	}
}

// ChannelNameToId gets the human-readable channel name for a user ID using an
// in-memory cache that falls through to the Slack API
func (sb Broker) ChannelNameToId(name string) string {
	if name == "" {
		log.Println("broker/slack/ChannelNameToId(): Cannot look up empty string!")
		return ""
	}

	if id, exists := sb.c2i[name]; exists {
		return id
	} else {
		sb.FillChannelCache()
		if id, exists := sb.c2i[name]; exists {
			return id
		}

		log.Printf("Slack does not seem to have knowledge of channel name %q", name)
		return ""
	}
}
<commit_msg>update log messages so it's clear they're from brokers/slack<commit_after>package slack

import (
	"fmt"
	"log"
	"regexp"
	"strconv"
	"time"

	"github.com/netflix/hal-9001/hal"
	"github.com/nlopes/slack"
)

// Broker interacts with the slack service.
type Broker struct {
	Client  *slack.Client     // slack API object
	RTM     *slack.RTM        // slack RTM object
	inst    string            // broker instance name
	i2u     map[string]string // id->name cache
	i2c     map[string]string // id->name cache
	u2i     map[string]string // name->id cache
	c2i     map[string]string // name->id cache
	idRegex *regexp.Regexp    // compiled RE to match user/channel ids
}

type Config struct {
	Token string
}

func (c Config) NewBroker(name string) Broker {
	client := slack.New(c.Token)
	// TODO: check for failures and log.Fatalf()
	rtm := client.NewRTM()

	sb := Broker{
		Client:  client,
		RTM:     rtm,
		inst:    name,
		i2u:     make(map[string]string),
		i2c:     make(map[string]string),
		u2i:     make(map[string]string),
		c2i:     make(map[string]string),
		idRegex: regexp.MustCompile("^[UC][A-Z0-9]{8}$"),
	}

	// fill the caches at startup to cut down on API requests
	sb.FillUserCache()
	sb.FillChannelCache()

	go rtm.ManageConnection()

	return sb
}

// Name returns the name of the broker as set in NewBroker.
func (sb Broker) Name() string {
	return sb.inst
}

func (sb Broker) Send(evt hal.Evt) {
	// make sure the channel is an ID and not the name
	// TODO: go through plugins, etc and see if there's a sane way to make the ID persist through
	// the system and have the name only resolve in and out of the genericbroker and in plugins
	// but probably not ... this should be fine
	var channel string
	if sb.idRegex.MatchString(evt.Channel) {
		channel = evt.Channel
	} else {
		channel = sb.ChannelNameToId(evt.Channel)
	}

	om := sb.RTM.NewOutgoingMessage(evt.Body, channel)
	sb.RTM.SendMessage(om)
}

// checks the cache to see if the channel is known to this broker
func (sb Broker) HasChannel(channel string) bool {
	if sb.idRegex.MatchString(channel) {
		_, exists := sb.i2c[channel]
		return exists
	} else {
		_, exists := sb.c2i[channel]
		return exists
	}
}

// Stream is an event loop for Slack events & messages from the RTM API.
// Events are copied to a hal.Evt and forwarded to the exchange where they
// can be processed by registered handlers.
func (sb Broker) Stream(out chan *hal.Evt) {
	for {
		select {
		case msg := <-sb.RTM.IncomingEvents:
			switch ev := msg.Data.(type) {
			case *slack.HelloEvent:
				log.Println("brokers/slack ignoring HelloEvent")

			case *slack.ConnectedEvent:
				log.Printf("brokers/slack ignoring ConnectedEvent")

			case *slack.MessageEvent:
				m := msg.Data.(*slack.MessageEvent)
				e := hal.Evt{
					Body:      m.Text,
					Channel:   sb.ChannelIdToName(m.Channel),
					ChannelId: m.Channel,
					From:      sb.UserIdToName(m.User),
					FromId:    m.User,
					Broker:    sb,
					Time:      slackTime(m.Timestamp),
					IsGeneric: true,
					Original:  m,
				}

				out <- &e

			case *slack.StarAddedEvent:
				sae := msg.Data.(*slack.StarAddedEvent)
				user := sb.UserIdToName(sae.User)

				e := hal.Evt{
					Body:      fmt.Sprintf("%q added a star", user),
					Channel:   sb.ChannelIdToName(sae.Item.Channel),
					ChannelId: sae.Item.Channel,
					From:      user,
					FromId:    sae.User,
					Broker:    sb,
					Time:      slackTime(sae.EventTimestamp),
					IsGeneric: false, // only available to slack-aware plugins
					Original:  sae,
				}

				out <- &e

			case *slack.StarRemovedEvent:
				sre := msg.Data.(*slack.StarRemovedEvent)
				user := sb.UserIdToName(sre.User)

				e := hal.Evt{
					Body:      fmt.Sprintf("%q removed a star", user),
					Channel:   sb.ChannelIdToName(sre.Item.Channel),
					ChannelId: sre.Item.Channel,
					From:      user,
					FromId:    sre.User,
					Broker:    sb,
					Time:      slackTime(sre.EventTimestamp),
					IsGeneric: false, // only available to slack-aware plugins
					Original:  sre,
				}

				out <- &e

			case *slack.ReactionAddedEvent:
				rae := msg.Data.(*slack.ReactionAddedEvent)
				user := sb.UserIdToName(rae.User)

				e := hal.Evt{
					Body:      fmt.Sprintf("%q added reaction %q", user, rae.Reaction),
					Channel:   sb.ChannelIdToName(rae.Item.Channel),
					ChannelId: rae.Item.Channel,
					From:      user,
					FromId:    rae.User,
					Broker:    sb,
					Time:      slackTime(rae.EventTimestamp),
					IsGeneric: false, // only available to slack-aware plugins
					Original:  rae,
				}

				out <- &e

			case *slack.ReactionRemovedEvent:
				rre := msg.Data.(*slack.ReactionAddedEvent)
				user := sb.UserIdToName(rre.User)

				e := hal.Evt{
					Body:      fmt.Sprintf("%q removed reaction %q", user, rre.Reaction),
					Channel:   sb.ChannelIdToName(rre.Item.Channel),
					ChannelId: rre.Item.Channel,
					From:      user,
					FromId:    rre.User,
					Broker:    sb,
					Time:      slackTime(rre.EventTimestamp),
					IsGeneric: false, // only available to slack-aware plugins
					Original:  rre,
				}

				out <- &e

			case *slack.PresenceChangeEvent:
				// ignored

			case *slack.LatencyReport:
				// ignored

			case *slack.RTMError:
				log.Printf("brokers/slack ignoring RTMError: %s\n", ev.Error())

			case *slack.InvalidAuthEvent:
				log.Println("brokers/slack InvalidAuthEvent")
				break

			default:
				log.Printf("brokers/slack: unexpected message: %+v\n", msg)
			}
		}
	}
}

// slackTime converts the timestamp string to time.Time
// cribbed from: https://github.com/nlopes/slack/commit/17d746b30caa733b519f79fe372fd509bd6fc9fd
func slackTime(t string) time.Time {
	if t == "" {
		return time.Now()
	}

	floatN, err := strconv.ParseFloat(t, 64)
	if err != nil {
		log.Println("brokers/slack error parsing Slack time string %q:", t, err)
		return time.Now()
	}

	return time.Unix(int64(floatN), 0)
}

func (sb *Broker) FillUserCache() {
	users, err := sb.Client.GetUsers()
	if err != nil {
		log.Printf("brokers/slack failed to fetch user list: %s", err)
		return
	}

	for _, user := range users {
		sb.u2i[user.Name] = user.ID
		sb.i2u[user.ID] = user.Name
	}
}

func (sb *Broker) FillChannelCache() {
	channels, err := sb.Client.GetChannels(true)
	if err != nil {
		log.Printf("brokers/slack failed to fetch channel list: %s", err)
		return
	}

	for _, channel := range channels {
		sb.c2i[channel.Name] = channel.ID
		sb.i2c[channel.ID] = channel.Name
	}
}

// UserIdToName gets the human-readable username for a user ID using an
// in-memory cache that falls through to the Slack API
func (sb Broker) UserIdToName(id string) string {
	if id == "" {
		log.Println("broker/slack/UserIdToName(): Cannot look up empty string!")
		return ""
	}

	if name, exists := sb.i2u[id]; exists {
		return name
	} else {
		user, err := sb.Client.GetUserInfo(id)
		if err != nil {
			log.Printf("brokers/slack could not retrieve user info for '%s' via API: %s\n", id, err)
			return ""
		}

		// TODO: verify if channel/user names are enforced unique in slack or if this is madness
		// remove this if it proves unnecessary (tobert/2016-03-02)
		if _, exists := sb.u2i[user.Name]; exists {
			if sb.u2i[user.Name] != user.ID {
				log.Fatalf("BUG(brokers/slack): found a non-unique user name:ID pair. Had: %q/%q. Got: %q/%q",
					user.Name, sb.u2i[user.Name], user.Name, user.ID)
			}
		}

		sb.i2u[user.ID] = user.Name
		sb.i2u[user.Name] = user.ID

		return user.Name
	}
}

// ChannelIdToName gets the human-readable channel name for a user ID using an
// in-memory cache that falls through to the Slack API
func (sb Broker) ChannelIdToName(id string) string {
	if id == "" {
		log.Println("broker/slack/ChannelIdToName(): Cannot look up empty string!")
		return ""
	}

	if name, exists := sb.i2c[id]; exists {
		return name
	} else {
		channel, err := sb.Client.GetChannelInfo(id)
		if err != nil {
			log.Printf("brokers/slack could not retrieve channel info for '%s' via API: %s\n", id, err)
			return ""
		}

		// TODO: verify if channel/user names are enforced unique in slack or if this is madness
		// remove this if it proves unnecessary (tobert/2016-03-02)
		if _, exists := sb.c2i[channel.Name]; exists {
			if sb.c2i[channel.Name] != channel.ID {
				log.Fatalf("BUG(brokers/slack): found a non-unique channel name:ID pair. Had: %q/%q. Got: %q/%q",
					channel.Name, sb.c2i[channel.Name], channel.Name, channel.ID)
			}
		}

		sb.i2c[channel.ID] = channel.Name
		sb.c2i[channel.Name] = channel.ID

		return channel.Name
	}
}

// UserNameToId gets the human-readable username for a user ID using an
// in-memory cache that falls through to the Slack API
func (sb Broker) UserNameToId(name string) string {
	if name == "" {
		log.Println("broker/slack/UserNameToId(): Cannot look up empty string!")
		return ""
	}

	if id, exists := sb.u2i[name]; exists {
		return id
	} else {
		// there doesn't seem to be a name->id lookup so refresh the cache
		// and try again if we get here
		sb.FillUserCache()
		if id, exists := sb.u2i[name]; exists {
			return id
		}

		log.Printf("brokers/slack service does not seem to have knowledge of username %q", name)
		return ""
	}
}

// ChannelNameToId gets the human-readable channel name for a user ID using an
// in-memory cache that falls through to the Slack API
func (sb Broker) ChannelNameToId(name string) string {
	if name == "" {
		log.Println("broker/slack/ChannelNameToId(): Cannot look up empty string!")
		return ""
	}

	if id, exists := sb.c2i[name]; exists {
		return id
	} else {
		sb.FillChannelCache()
		if id, exists := sb.c2i[name]; exists {
			return id
		}

		log.Printf("brokers/slack service does not seem to have knowledge of channel name %q", name)
		return ""
	}
}
<|endoftext|>


<commit_before>package main

import "fmt"

func main() {
	fmt.Println("echo client")
}
<commit_msg>Add echo-client implementation in golang<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"net"
	"os"
	"strings"
)

func serve(conn net.Conn) {

}

func main() {
	flag.Parse()
	ip := flag.Arg(0)
	port := flag.Arg(1)
	if ip == "" || port == "" {
		fmt.Println("Usage: client ip port")
		return
	}

	addr := ip + ":" + port

	fmt.Printf("Connecting to %s ...", addr)
	conn, err := net.Dial("tcp", addr)
	if err != nil {
		fmt.Printf("Failed to connect due to: %v\n", err)
		return
	}

	fmt.Printf("Connected\n")

	defer conn.Close()

	cin := bufio.NewReader(os.Stdin)
	buf := make([]byte, 64)

	for {
		msg, err := cin.ReadString('\n')
		if err != nil {
			fmt.Println("Bye-bye")
			return
		}

		msg = strings.TrimRight(msg, "\n")

		if _, err = conn.Write([]byte(msg)); err != nil {
			fmt.Printf("Failed to write to %s due to: %v\n", addr, err)
			break
		}

		n, err := conn.Read(buf)
		if err != nil {
			fmt.Printf("Failed to write to %s due to: %v\n", addr, err)
			break
		}

		fmt.Println(string(buf[:n]))
	}
}
<|endoftext|>


<commit_before>package chain

type Direction int

const (
	up   Direction = iota
	down Direction = iota
)

type Chain struct {
	ref      string
	backref  *Chain
	hasDown  bool
	downFile string
	upFile   string
}

type Meta struct {
	ref       string
	backref   string
	direction Direction
	filename  string
}

func fileList() /*[]string*/ {

}

func cwdIsSchemaDir() /*bool*/ {

}

func parseMeta(filepath string) /* *Meta*/ {

}
<commit_msg>Chain - Utility Functions<commit_after>package chain

import (
	"errors"
	"os"
)

type Direction int

const (
	up   Direction = iota
	down Direction = iota
)

var (
	ErrNotSchemaDir = errors.New(
		"user: current directory is not a valid schema directory")
)

const metaFileName = ".schema.meta"

type Chain struct {
	ref      string
	backref  *Chain
	hasDown  bool
	downFile string
	upFile   string
}

type Meta struct {
	ref       string
	backref   string
	direction Direction
	filename  string
}

/**
 * For the current working directory, return a list of files that meet
 * the criteria to be an alter (fit the naming convention) if the CWD
 * is a schema directory. If the current directory is not a schema dir,
 * then return and error
 */
func fileList() ([]string, error) {
	if cwdIsSchemaDir() {
		return nil, ErrNotSchemaDir
	}
	return []string{}, nil
}

/**
 * Check whether the current working directory is a schema directory. This
 * can be checked by looking for the .schema.meta file within the CWD.
 */
func cwdIsSchemaDir() bool {
	if currDir, err := os.Getwd(); err == nil {
		metaFile := currDir + string(os.PathSeparator) + metaFileName

		_, err = os.Stat(metaFile)
        return err == nil
	}
	return false
}

/**
 * Given a (valid) path to a file, read through the file and return a Meta
 * object. If no file is returned, then a nil Meta object may be returned.
 */
func parseMeta(filepath string) /* *Meta*/ {

}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"log"
	"net/http"
	"os"

	"github.com/yinqiwen/gotoolkit/ots"
	"github.com/yinqiwen/gsnova/remote"
)

// hello world, the web server
func indexCallback(w http.ResponseWriter, req *http.Request) {
	io.WriteString(w, html)
}

func statCallback(w http.ResponseWriter, req *http.Request) {
	w.WriteHeader(200)
	fmt.Fprintf(w, "NumSession: %d\n", remote.GetSessionTableSize())
	ots.Handle("stat", w)
}

func stackdumpCallback(w http.ResponseWriter, req *http.Request) {
	w.WriteHeader(200)
	ots.Handle("stackdump", w)
}

func main() {
	port := os.Getenv("PORT")
	if port == "" {
		port = os.Getenv("OPENSHIFT_GO_PORT")
	}
	if port == "" {
		port = "8080"
	}
	host := os.Getenv("OPENSHIFT_GO_IP")

	mux := http.NewServeMux()
	mux.HandleFunc("/", indexCallback)
	mux.HandleFunc("/stat", statCallback)
	mux.HandleFunc("/stackdump", stackdumpCallback)
	mux.HandleFunc("/ws", websocketInvoke)
	mux.HandleFunc("/http/pull", httpInvoke)
	mux.HandleFunc("/http/push", httpInvoke)

	log.Println("Listening on " + host + ":" + port)
	err := http.ListenAndServe(host+":"+port, mux)
	if nil != err {
		fmt.Printf("Listen server error:%v", err)
	}
}

const html = `
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
	<title>GSnova PAAS Server</title>

GSnova
      by @yinqiwen

      Welcome to use GSnova PAAS Server(V1.0)!

Code

You can clone the project with Git
      by running:

$ git clone git://github.com/yinqiwen/gsnova.git

      get the source code on GitHub : yinqiwen/gsnova

`
<commit_msg>add bluemix paas support<commit_after>package main

import (
	"fmt"
	"io"
	"log"
	"net/http"
	"os"

	"github.com/yinqiwen/gotoolkit/ots"
	"github.com/yinqiwen/gsnova/remote"
)

// hello world, the web server
func indexCallback(w http.ResponseWriter, req *http.Request) {
	io.WriteString(w, html)
}

func statCallback(w http.ResponseWriter, req *http.Request) {
	w.WriteHeader(200)
	fmt.Fprintf(w, "NumSession: %d\n", remote.GetSessionTableSize())
	ots.Handle("stat", w)
}

func stackdumpCallback(w http.ResponseWriter, req *http.Request) {
	w.WriteHeader(200)
	ots.Handle("stackdump", w)
}

func main() {
	port := os.Getenv("PORT")
	if port == "" {
		port = os.Getenv("OPENSHIFT_GO_PORT")
	}
	if port == "" {
		port = os.Getenv("VCAP_APP_PORT")
	}
	if port == "" {
		port = "8080"
	}
	host := os.Getenv("OPENSHIFT_GO_IP")

	mux := http.NewServeMux()
	mux.HandleFunc("/", indexCallback)
	mux.HandleFunc("/stat", statCallback)
	mux.HandleFunc("/stackdump", stackdumpCallback)
	mux.HandleFunc("/ws", websocketInvoke)
	mux.HandleFunc("/http/pull", httpInvoke)
	mux.HandleFunc("/http/push", httpInvoke)

	log.Println("Listening on " + host + ":" + port)
	err := http.ListenAndServe(host+":"+port, mux)
	if nil != err {
		fmt.Printf("Listen server error:%v", err)
	}
}

const html = `
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
	<title>GSnova PAAS Server</title>

GSnova
      by @yinqiwen

      Welcome to use GSnova PAAS Server(V1.0)!

Code

You can clone the project with Git
      by running:

$ git clone git://github.com/yinqiwen/gsnova.git

      get the source code on GitHub : yinqiwen/gsnova

`
<|endoftext|>


<commit_before>package reply_test

import (
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/aukbit/pluto/reply"
	"github.com/paulormart/assert"
)

func TestAll(t *testing.T) {

	// Table tests
	var tests = []struct {
		Fn func(w http.ResponseWriter, r *http.Request)
		S  int    // status code
		B  string //body
	}{{
		Fn: func(w http.ResponseWriter, r *http.Request) {
			reply.Json(w, r, http.StatusOK, "Hello World")
		},
		S: 200,
		B: `"Hello World"`,
	}, {
		Fn: func(w http.ResponseWriter, r *http.Request) {
			reply.Json(w, r, http.StatusNotFound, "not found")
		},
		S: http.StatusNotFound,
		B: `"not found"`,
	}, {
		Fn: func(w http.ResponseWriter, r *http.Request) {
			data := map[string]interface{}{"url": "golang.org"}
			reply.Json(w, r, http.StatusCreated, data)
		},
		S: http.StatusCreated,
		B: `{"url":"golang.org"}`,
	}}

	for _, test := range tests {
		w := httptest.NewRecorder()
		test.Fn(w, nil)

		assert.Equal(t, w.Header().Get("Content-Type"), "application/json")
		assert.Equal(t, test.S, w.Code)
		assert.Equal(t, test.B, w.Body.String())
	}

}
<commit_msg>reply TestReply<commit_after>package reply_test

import (
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/aukbit/pluto/reply"
	"github.com/paulormart/assert"
)

func TestReply(t *testing.T) {

	// Table tests
	var tests = []struct {
		Fn func(w http.ResponseWriter, r *http.Request)
		S  int    // status code
		B  string //body
	}{{
		Fn: func(w http.ResponseWriter, r *http.Request) {
			reply.Json(w, r, http.StatusOK, "Hello World")
		},
		S: 200,
		B: `"Hello World"`,
	}, {
		Fn: func(w http.ResponseWriter, r *http.Request) {
			reply.Json(w, r, http.StatusNotFound, "not found")
		},
		S: http.StatusNotFound,
		B: `"not found"`,
	}, {
		Fn: func(w http.ResponseWriter, r *http.Request) {
			data := map[string]interface{}{"url": "golang.org"}
			reply.Json(w, r, http.StatusCreated, data)
		},
		S: http.StatusCreated,
		B: `{"url":"golang.org"}`,
	}}

	for _, test := range tests {
		w := httptest.NewRecorder()
		test.Fn(w, nil)

		assert.Equal(t, w.Header().Get("Content-Type"), "application/json")
		assert.Equal(t, test.S, w.Code)
		assert.Equal(t, test.B, w.Body.String())
	}

}
<|endoftext|>