<commit_before>// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package seelog

import (
	"net"
	"syscall"
	"testing"
	"time"
)

type testObj struct {
	Num  int
	Str  string
	Val  float32
	Time time.Time
}

var (
	connWriterLog1 = "Testasasaafasf"
	connWriterLog2 = "fgrehgsnkmrgergerg[234%:dfsads:2]"
	connWriterLog3 = " 3242 3 24.df.we"
	connWriterLog  = connWriterLog1 + connWriterLog2 + connWriterLog3
	obj            = &testObj{11, "sdfasd", 12.5, time.Now()}
)

func TestConnWriter_ReconnectOnMessage(t *testing.T) {
	server, err := startTcpServer(t)
	if err != nil {
		t.Fatal(err)
		return
	}

	server.Expect(connWriterLog)

	writer := newConnWriter("tcp4", ":"+server.port, true)
	defer writer.Close()

	_, err = writer.Write([]byte(connWriterLog))
	if err != nil {
		t.Fatal(err)
		return
	}

	server.Wait()
	server.Close()
}

func TestConnWriter_OneConnect(t *testing.T) {
	server, err := startTcpServer(t)
	if err != nil {
		t.Fatal(err)
		return
	}

	server.Expect(connWriterLog)

	writer := newConnWriter("tcp4", ":"+server.port, false)

	_, err = writer.Write([]byte(connWriterLog1))
	if err != nil {
		t.Fatal(err)
		return
	}

	_, err = writer.Write([]byte(connWriterLog2))
	if err != nil {
		t.Fatal(err)
		return
	}

	_, err = writer.Write([]byte(connWriterLog3))
	if err != nil {
		t.Fatal(err)
		return
	}

	writer.Close()

	server.Wait()
	server.Close()
}

func TestConnWriter_ReconnectOnMessage_WriteError(t *testing.T) {
	server, err := startTcpServer(t)
	if err != nil {
		t.Fatal(err)
		return
	}

	server.Expect(connWriterLog)

	writer := newConnWriter("tcp4", ":"+server.port, true)
	defer writer.Close()

	_, err = writer.Write([]byte(connWriterLog))
	if err != nil {
		t.Fatal(err)
		return
	}

	server.Wait()
	server.Close()

	_, err = writer.Write([]byte(connWriterLog))
	if err == nil {
		t.Fatal("Write to closed server must return error")
		return
	}

	operr, ok := err.(*net.OpError)
	if !ok {
		t.Fatalf("Expected *net.OpError. Got: %v", err)
		return
	}

	errno, ok := operr.Err.(syscall.Errno)
	if !ok {
		t.Fatalf("Expected syscall.Errno. Got %v", operr)
		return
	}

	if errno != syscall.ECONNREFUSED {
		t.Fatalf("Expected syscall.ECONNREFUSED. Got %v", errno)
		return
	}

	err = server.Start()
	if err != nil {
		t.Fatal(err)
		return
	}

	server.Expect(connWriterLog)

	_, err = writer.Write([]byte(connWriterLog))
	if err != nil {
		t.Fatal(err)
		return
	}

	server.Wait()
	server.Close()
}
<commit_msg>Fixed nil IP address bug. Changed the way how the test TCP address is built.<commit_after>// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package seelog

import (
	"net"
	"syscall"
	"testing"
	"time"
)

type testObj struct {
	Num  int
	Str  string
	Val  float32
	Time time.Time
}

const (
	testIPAddress = "localhost"
)

var (
	connWriterLog1 = "Testasasaafasf"
	connWriterLog2 = "fgrehgsnkmrgergerg[234%:dfsads:2]"
	connWriterLog3 = " 3242 3 24.df.we"
	connWriterLog  = connWriterLog1 + connWriterLog2 + connWriterLog3
	obj            = &testObj{11, "sdfasd", 12.5, time.Now()}
)

func getTestTCPAddress(port string) string {
	return testIPAddress + ":" + port
}

func TestConnWriter_ReconnectOnMessage(t *testing.T) {
	server, err := startTcpServer(t)
	if err != nil {
		t.Fatal(err)
		return
	}

	server.Expect(connWriterLog)

	writer := newConnWriter("tcp4", getTestTCPAddress(server.port), true)
	defer writer.Close()

	_, err = writer.Write([]byte(connWriterLog))
	if err != nil {
		t.Fatal(err)
		return
	}

	server.Wait()
	server.Close()
}

func TestConnWriter_OneConnect(t *testing.T) {
	server, err := startTcpServer(t)
	if err != nil {
		t.Fatal(err)
		return
	}

	server.Expect(connWriterLog)

	writer := newConnWriter("tcp4", getTestTCPAddress(server.port), false)

	_, err = writer.Write([]byte(connWriterLog1))
	if err != nil {
		t.Fatal(err)
		return
	}

	_, err = writer.Write([]byte(connWriterLog2))
	if err != nil {
		t.Fatal(err)
		return
	}

	_, err = writer.Write([]byte(connWriterLog3))
	if err != nil {
		t.Fatal(err)
		return
	}

	writer.Close()

	server.Wait()
	server.Close()
}

func TestConnWriter_ReconnectOnMessage_WriteError(t *testing.T) {
	server, err := startTcpServer(t)
	if err != nil {
		t.Fatal(err)
		return
	}

	server.Expect(connWriterLog)

	writer := newConnWriter("tcp4", getTestTCPAddress(server.port), true)
	defer writer.Close()

	_, err = writer.Write([]byte(connWriterLog))
	if err != nil {
		t.Fatal(err)
		return
	}

	server.Wait()
	server.Close()

	_, err = writer.Write([]byte(connWriterLog))
	if err == nil {
		t.Fatal("Write to closed server must return error")
		return
	}

	operr, ok := err.(*net.OpError)
	if !ok {
		t.Fatalf("Expected *net.OpError. Got: %v", err)
		return
	}

	errno, ok := operr.Err.(syscall.Errno)
	if !ok {
		t.Fatalf("Expected syscall.Errno. Got %v", operr)
		return
	}

	if errno != syscall.ECONNREFUSED {
		t.Fatalf("Expected syscall.ECONNREFUSED. Got %v", errno)
		return
	}

	err = server.Start()
	if err != nil {
		t.Fatal(err)
		return
	}

	server.Expect(connWriterLog)

	_, err = writer.Write([]byte(connWriterLog))
	if err != nil {
		t.Fatal(err)
		return
	}

	server.Wait()
	server.Close()
}
<|endoftext|>


<commit_before>package dns

import (
	"testing"
)

func TestRadixName(t *testing.T) {
	tests := map[string]string{".": ".",
		"www.miek.nl.": ".nl.miek.www",
		"miek.nl.":     ".nl.miek",
		"mi\\.ek.nl.":  ".nl.mi\\.ek",
		`mi\\.ek.nl.`:  `.nl.ek.mi\\`,
		"":             "."}
	for i, o := range tests {
		t.Logf("%s %v\n", i, SplitLabels(i))
		if x := toRadixName(i); x != o {
			t.Logf("%s should convert to %s, not %s\n", i, o, x)
			t.Fail()
		}
	}
}

func TestInsert(t *testing.T) {
}
func TestRemove(t *testing.T) {
}
<commit_msg>Add zone test from Alex Polvi<commit_after>package dns

import (
	"testing"
)

func TestRadixName(t *testing.T) {
	tests := map[string]string{".": ".",
		"www.miek.nl.": ".nl.miek.www",
		"miek.nl.":     ".nl.miek",
		"mi\\.ek.nl.":  ".nl.mi\\.ek",
		`mi\\.ek.nl.`:  `.nl.ek.mi\\`,
		"":             "."}
	for i, o := range tests {
		t.Logf("%s %v\n", i, SplitLabels(i))
		if x := toRadixName(i); x != o {
			t.Logf("%s should convert to %s, not %s\n", i, o, x)
			t.Fail()
		}
	}
}

func TestInsert(t *testing.T) {
	z := NewZone("miek.nl.")
	mx, _ := NewRR("foo.miek.nl. MX 10 mx.miek.nl.")
	z.Insert(mx)
	zd, exact := z.Find("foo.miek.nl.")
	if exact != true {
		t.Fail() // insert broken?
	}
}

func TestRemove(t *testing.T) {
	z := NewZone("miek.nl.")
	mx, _ := NewRR("foo.miek.nl. MX 10 mx.miek.nl.")
	z.Insert(mx)
	zd, exact := z.Find("foo.miek.nl.")
	if exact != true {
		t.Fail() // insert broken?
	}
	z.Remove(mx)
	zd, exact = z.Find("foo.miek.nl.")
	if exact != false {
		t.Errorf("zd(%s) exact(%s) still exists", zd, exact) // it should no longer be in the zone
	}
}
<|endoftext|>


<commit_before>package radix_sort

import "math"

func Sort(a []int) []int {
	negative, positive := splitSign(a)
	sortedNegative := reverse(radixSort(negative))
	sortedPositive := radixSort(positive)
	return append(sortedNegative, sortedPositive...)
}

// radixSort returns a copy of a, sorted in increasing absolute value order.
func radixSort(a []int) []int {
	base := 10
	d := maxDigits(a, base)
	for n := 0; n < d; n++ {
		a = concat(buckets(a, base, n))
	}
	return a
}

// reverse returns a reversed copy of a.
func reverse(a []int) []int {
	l := len(a)
	b := make([]int, l)
	for i, v := range a {
		b[l-i-1] = v
	}
	return b
}

// splitSign returns two slices: one slice containing all negative elements of a, and one slice
// containing all positive elements of a.
func splitSign(a []int) (negative, positive []int) {
	for _, v := range a {
		if v < 0 {
			negative = append(negative, v)
		} else {
			positive = append(positive, v)
		}
	}
	return
}

// buckets returns a slice of b buckets, where the kth bucket contains all the elements of a whose
// nth digit in base-b representation is k.
func buckets(a []int, b, n int) [][]int {
	buckets := make([][]int, b)
	for _, v := range a {
		d := digit(v, b, n)
		buckets[d] = append(buckets[d], v)
	}
	return buckets
}

// concat returns the concatenation of all buckets.
func concat(buckets [][]int) []int {
	a := []int{}
	for _, bucket := range buckets {
		a = append(a, bucket...)
	}
	return a
}

// maxDigits returns the maximum number of digits of any element in a, in base-b representation.
func maxDigits(a []int, b int) int {
	max := 0
	for _, v := range a {
		if av := abs(v); av > max {
			max = av
		}
	}
	return digits(max, b)
}

// digits returns the number of digits of a, in base-b representation.
func digits(a, b int) int {
	return int(log(abs(a), b)) + 1
}

// digit returns the nth digit of a, in base-b representation.
func digit(a, b, n int) int {
	return int(abs(a) / pow(b, n) % b)
}

// log returns the logarithm of a in base b.
func log(a, b int) float64 {
	return math.Log(float64(a)) / math.Log(float64(b))
}

// pow returns the base-b exponential of n (often written as b**n or b^n).
func pow(b, n int) int {
	return int(math.Pow(float64(b), float64(n)))
}

// abs returns the absolute value of a.
func abs(a int) int {
	if a < 0 {
		return -a
	}
	return a
}
<commit_msg>[radix_sort/go] Rename radixSort to sortAbs<commit_after>package radix_sort

import "math"

func Sort(a []int) []int {
	negative, positive := splitSign(a)
	sortedNegative := reverse(sortAbs(negative))
	sortedPositive := sortAbs(positive)
	return append(sortedNegative, sortedPositive...)
}

// sortAbs returns a copy of a, sorted in increasing absolute value order.
func sortAbs(a []int) []int {
	base := 10
	d := maxDigits(a, base)
	for n := 0; n < d; n++ {
		a = concat(buckets(a, base, n))
	}
	return a
}

// reverse returns a reversed copy of a.
func reverse(a []int) []int {
	l := len(a)
	b := make([]int, l)
	for i, v := range a {
		b[l-i-1] = v
	}
	return b
}

// splitSign returns two slices: one slice containing all negative elements of a, and one slice
// containing all positive elements of a.
func splitSign(a []int) (negative, positive []int) {
	for _, v := range a {
		if v < 0 {
			negative = append(negative, v)
		} else {
			positive = append(positive, v)
		}
	}
	return
}

// buckets returns a slice of b buckets, where the kth bucket contains all the elements of a whose
// nth digit in base-b representation is k.
func buckets(a []int, b, n int) [][]int {
	buckets := make([][]int, b)
	for _, v := range a {
		d := digit(v, b, n)
		buckets[d] = append(buckets[d], v)
	}
	return buckets
}

// concat returns the concatenation of all buckets.
func concat(buckets [][]int) []int {
	a := []int{}
	for _, bucket := range buckets {
		a = append(a, bucket...)
	}
	return a
}

// maxDigits returns the maximum number of digits of any element in a, in base-b representation.
func maxDigits(a []int, b int) int {
	max := 0
	for _, v := range a {
		if av := abs(v); av > max {
			max = av
		}
	}
	return digits(max, b)
}

// digits returns the number of digits of a, in base-b representation.
func digits(a, b int) int {
	return int(log(abs(a), b)) + 1
}

// digit returns the nth digit of a, in base-b representation.
func digit(a, b, n int) int {
	return int(abs(a) / pow(b, n) % b)
}

// log returns the logarithm of a in base b.
func log(a, b int) float64 {
	return math.Log(float64(a)) / math.Log(float64(b))
}

// pow returns the base-b exponential of n (often written as b**n or b^n).
func pow(b, n int) int {
	return int(math.Pow(float64(b), float64(n)))
}

// abs returns the absolute value of a.
func abs(a int) int {
	if a < 0 {
		return -a
	}
	return a
}
<|endoftext|>


<commit_before>package palitrans

import (
	"testing"
)

func TestRomanToThai(t *testing.T) {
	var mapping = map[string]string{
		"ปา":   "pā",
		"ลิ":   "li",
		"ลี":   "lī",
		"ปาลิ": "pāli",
		"สาธุ": "sādhu",
		"ก":    "ka",
		"กิ":   "ki",
		"กุ":   "ku",
		"กา":   "kā",
		"กี":   "kī",
		"กู":   "kū",
		//"เก":   "ke",
		//"โก":   "ko",
		"กจ":      "kaca",
		"อิติ":    "iti",
		"เอว":     "eva",
		"อปิ":     "api",
		"อาชิ":    "āji",
		"อุป":     "upa",
		"กํ":      "kaṃ",
		"นรํ":     "naraṃ",
		"ภิกฺขุ":  "bhikkhu",
		"ทุกฺข":   "dukkha",
		"พุทฺเธน": "buddhena",
		"อหํ":     "ahaṃ",
		"พุทฺธํ":  "buddhaṃ",
		//"สรณํ":    "saranaṃ",
		"คจฺฉามิ": "gacchāmi",
		//"นโม":     "namo",
		"ทสฺส": "dassa",
		//"ภควโต":   "bhagavato",
		"ธมฺมานิ":   "dhammāni",
		"คนฺตฺวา":   "gantvā",
		"มฺหิ":      "mhi",
		"ยฺห":       "yha",
		"มยฺหํ":     "mayhaṃ",
		"อคฺคิมฺหิ": "aggimhi",
		"กึ":        "kiṃ",
		"":          "",
	}

	for k, v := range mapping {
		if k != RomanToThai(v) {
			t.Error(k, v)
			return
		}
	}
}

func TestCharAt(t *testing.T) {
	s := CharAt("abc", -1)
	if s != "" {
		t.Error(s)
		return
	}

	s = CharAt("I am 字串", 5)
	if s != "字" {
		t.Error(s)
		return
	}

	s = CharAt("ādā", 0)
	if s != "ā" {
		t.Error(s)
		return
	}

	s = CharAt("ādā", 1)
	if s != "d" {
		t.Error(s)
		return
	}

	s = CharAt("ādā", 2)
	if s != "ā" {
		t.Error(s)
		return
	}

	s = CharAt("ādā", 3)
	if s != "" {
		t.Error(s)
		return
	}
}

func TestLength(t *testing.T) {
	if length("I am 字串") != 7 {
		t.Error("I am 字串")
		return
	}

	if length("ādā") != 3 {
		t.Error("ādā")
		return
	}

	if length("abc") != 3 {
		t.Error("abc")
		return
	}
}
<commit_msg>add test case<commit_after>package palitrans

import (
	"testing"
)

func TestRomanToThai(t *testing.T) {
	var mapping = map[string]string{
		"ปา":   "pā",
		"ลิ":   "li",
		"ลี":   "lī",
		"ปาลิ": "pāli",
		"สาธุ": "sādhu",
		"ก":    "ka",
		"กิ":   "ki",
		"กุ":   "ku",
		"กา":   "kā",
		"กี":   "kī",
		"กู":   "kū",
		//"เก":   "ke",
		//"โก":   "ko",
		"กจ":      "kaca",
		"อิติ":    "iti",
		"เอว":     "eva",
		"อปิ":     "api",
		"อาชิ":    "āji",
		"อุป":     "upa",
		"กํ":      "kaṃ",
		"นรํ":     "naraṃ",
		"ภิกฺขุ":  "bhikkhu",
		"ทุกฺข":   "dukkha",
		"พุทฺเธน": "buddhena",
		"อหํ":     "ahaṃ",
		"พุทฺธํ":  "buddhaṃ",
		"สรณํ":    "saraṇaṃ",
		"คจฺฉามิ": "gacchāmi",
		//"นโม":     "namo",
		"ทสฺส": "dassa",
		//"ภควโต":   "bhagavato",
		"ธมฺมานิ":   "dhammāni",
		"คนฺตฺวา":   "gantvā",
		"มฺหิ":      "mhi",
		"ยฺห":       "yha",
		"มยฺหํ":     "mayhaṃ",
		"อคฺคิมฺหิ": "aggimhi",
		"กึ":        "kiṃ",
		"":          "",
	}

	for k, v := range mapping {
		if k != RomanToThai(v) {
			t.Error(k, v)
			return
		}
	}
}

func TestCharAt(t *testing.T) {
	s := CharAt("abc", -1)
	if s != "" {
		t.Error(s)
		return
	}

	s = CharAt("I am 字串", 5)
	if s != "字" {
		t.Error(s)
		return
	}

	s = CharAt("ādā", 0)
	if s != "ā" {
		t.Error(s)
		return
	}

	s = CharAt("ādā", 1)
	if s != "d" {
		t.Error(s)
		return
	}

	s = CharAt("ādā", 2)
	if s != "ā" {
		t.Error(s)
		return
	}

	s = CharAt("ādā", 3)
	if s != "" {
		t.Error(s)
		return
	}
}

func TestLength(t *testing.T) {
	if length("I am 字串") != 7 {
		t.Error("I am 字串")
		return
	}

	if length("ādā") != 3 {
		t.Error("ādā")
		return
	}

	if length("abc") != 3 {
		t.Error("abc")
		return
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Uber Technologies, Inc.

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package trace

import (
	"net"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/mock"
	"github.com/stretchr/testify/require"
	"github.com/uber/tchannel/golang"
	"github.com/uber/tchannel/golang/thrift"
	gen "github.com/uber/tchannel/golang/trace/thrift/gen-go/tcollector"
	"github.com/uber/tchannel/golang/trace/thrift/mocks"
)

func TestZipkinTraceReporterFactory(t *testing.T) {
	_, err := tchannel.NewChannel("client", &tchannel.ChannelOptions{
		Logger:               tchannel.SimpleLogger,
		TraceReporterFactory: ZipkinTraceReporterFactory,
	})

	assert.NoError(t, err)
}

func TestBuildZipkinSpan(t *testing.T) {
	endpoint := tchannel.TargetEndpoint{
		HostPort:    "127.0.0.1:8888",
		ServiceName: "testServer",
		Operation:   "test",
	}
	span := *tchannel.NewRootSpan()
	annotations := RandomAnnotations()
	thriftSpan := buildZipkinSpan(span, annotations, nil, endpoint)

	expectedSpan := &gen.Span{
		TraceId: uint64ToBytes(span.TraceID()),
		Host: &gen.Endpoint{
			Ipv4:        (int32)(inetAton("127.0.0.1")),
			Port:        8888,
			ServiceName: "testServer",
		},
		Name:        "test",
		Id:          uint64ToBytes(span.SpanID()),
		ParentId:    uint64ToBytes(span.ParentID()),
		Annotations: buildZipkinAnnotations(annotations),
		Debug:       false,
	}

	assert.Equal(t, thriftSpan, expectedSpan, "Span mismatch")
}

func TestInetAton(t *testing.T) {
	assert.Equal(t, inetAton("1.2.3.4"), uint32(16909060))
}

func TestUInt64ToBytes(t *testing.T) {
	assert.Equal(t, uint64ToBytes(54613478251749257), []byte("\x00\xc2\x06\xabK$\xdf\x89"))
}

func TestBase64Encode(t *testing.T) {
	assert.Equal(t, base64Encode(12711515087145684), "AC0pDj1TitQ=")
}

func RandomAnnotations() []tchannel.Annotation {
	baseTime := time.Date(2015, 1, 2, 3, 4, 5, 6, time.UTC)
	return []tchannel.Annotation{
		{
			Key:       tchannel.AnnotationKeyClientReceive,
			Timestamp: baseTime.Add(time.Second),
		},
		{
			Key:       tchannel.AnnotationKeyClientSend,
			Timestamp: baseTime.Add(2 * time.Second),
		},
		{
			Key:       tchannel.AnnotationKeyServerReceive,
			Timestamp: baseTime.Add(3 * time.Second),
		},
		{
			Key:       tchannel.AnnotationKeyServerSend,
			Timestamp: baseTime.Add(4 * time.Second),
		},
	}
}

type testArgs struct {
	s *mocks.TChanTCollector
	c tchannel.TraceReporter
}

func ctxArg() mock.AnythingOfTypeArgument {
	return mock.AnythingOfType("*tchannel.headerCtx")
}

func TestSubmit(t *testing.T) {
	withSetup(t, func(ctx thrift.Context, args testArgs) {
		endpoint := tchannel.TargetEndpoint{
			HostPort:    "127.0.0.1:8888",
			ServiceName: "testServer",
			Operation:   "test",
		}
		span := *tchannel.NewRootSpan()
		annotations := RandomAnnotations()
		thriftSpan := buildZipkinSpan(span, annotations, nil, endpoint)
		thriftSpan.BinaryAnnotations = []*gen.BinaryAnnotation{}
		ret := &gen.Response{Ok: true}

		called := make(chan struct{})
		args.s.On("Submit", ctxArg(), thriftSpan).Return(ret, nil).Run(func(_ mock.Arguments) {
			close(called)
		})
		args.c.Report(span, annotations, nil, endpoint)

		// wait for the server's Submit to get called
		select {
		case <-time.After(time.Second):
			t.Fatal("Submit not called")
		case <-called:
		}
	})
}

func withSetup(t *testing.T, f func(ctx thrift.Context, args testArgs)) {
	args := testArgs{
		s: new(mocks.TChanTCollector),
	}

	ctx, cancel := thrift.NewContext(time.Second * 10)
	defer cancel()

	// Start server
	tchan, listener, err := setupServer(args.s)
	require.NoError(t, err)
	defer tchan.Close()

	// Get client1
	args.c, err = getClient(listener.Addr().String())
	require.NoError(t, err)

	f(ctx, args)

	args.s.AssertExpectations(t)
}

func setupServer(h *mocks.TChanTCollector) (*tchannel.Channel, net.Listener, error) {
	tchan, err := tchannel.NewChannel(tcollectorServiceName, &tchannel.ChannelOptions{
		Logger: tchannel.SimpleLogger,
	})
	if err != nil {
		return nil, nil, err
	}

	listener, err := net.Listen("tcp", ":0")
	if err != nil {
		return nil, nil, err
	}

	server := thrift.NewServer(tchan)
	server.Register(gen.NewTChanTCollectorServer(h))

	tchan.Serve(listener)
	return tchan, listener, nil
}

func getClient(dst string) (tchannel.TraceReporter, error) {
	tchan, err := tchannel.NewChannel("client", &tchannel.ChannelOptions{
		Logger: tchannel.SimpleLogger,
	})
	if err != nil {
		return nil, err
	}

	tchan.Peers().Add(dst)
	return NewZipkinTraceReporter(tchan), nil
}

func BenchmarkBuildThrift(b *testing.B) {
	endpoint := tchannel.TargetEndpoint{
		HostPort:    "127.0.0.1:8888",
		ServiceName: "testServer",
		Operation:   "test",
	}
	span := *tchannel.NewRootSpan()
	annotations := RandomAnnotations()

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		buildZipkinSpan(span, annotations, nil, endpoint)
	}
}
<commit_msg>Use testutils to create channels<commit_after>// Copyright (c) 2015 Uber Technologies, Inc.

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package trace

import (
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/mock"
	"github.com/stretchr/testify/require"
	"github.com/uber/tchannel/golang"
	"github.com/uber/tchannel/golang/testutils"
	"github.com/uber/tchannel/golang/thrift"
	gen "github.com/uber/tchannel/golang/trace/thrift/gen-go/tcollector"
	"github.com/uber/tchannel/golang/trace/thrift/mocks"
)

func TestZipkinTraceReporterFactory(t *testing.T) {
	_, err := tchannel.NewChannel("client", &tchannel.ChannelOptions{
		Logger:               tchannel.SimpleLogger,
		TraceReporterFactory: ZipkinTraceReporterFactory,
	})

	assert.NoError(t, err)
}

func TestBuildZipkinSpan(t *testing.T) {
	endpoint := tchannel.TargetEndpoint{
		HostPort:    "127.0.0.1:8888",
		ServiceName: "testServer",
		Operation:   "test",
	}
	span := *tchannel.NewRootSpan()
	annotations := RandomAnnotations()
	thriftSpan := buildZipkinSpan(span, annotations, nil, endpoint)

	expectedSpan := &gen.Span{
		TraceId: uint64ToBytes(span.TraceID()),
		Host: &gen.Endpoint{
			Ipv4:        (int32)(inetAton("127.0.0.1")),
			Port:        8888,
			ServiceName: "testServer",
		},
		Name:        "test",
		Id:          uint64ToBytes(span.SpanID()),
		ParentId:    uint64ToBytes(span.ParentID()),
		Annotations: buildZipkinAnnotations(annotations),
		Debug:       false,
	}

	assert.Equal(t, thriftSpan, expectedSpan, "Span mismatch")
}

func TestInetAton(t *testing.T) {
	assert.Equal(t, inetAton("1.2.3.4"), uint32(16909060))
}

func TestUInt64ToBytes(t *testing.T) {
	assert.Equal(t, uint64ToBytes(54613478251749257), []byte("\x00\xc2\x06\xabK$\xdf\x89"))
}

func TestBase64Encode(t *testing.T) {
	assert.Equal(t, base64Encode(12711515087145684), "AC0pDj1TitQ=")
}

func RandomAnnotations() []tchannel.Annotation {
	baseTime := time.Date(2015, 1, 2, 3, 4, 5, 6, time.UTC)
	return []tchannel.Annotation{
		{
			Key:       tchannel.AnnotationKeyClientReceive,
			Timestamp: baseTime.Add(time.Second),
		},
		{
			Key:       tchannel.AnnotationKeyClientSend,
			Timestamp: baseTime.Add(2 * time.Second),
		},
		{
			Key:       tchannel.AnnotationKeyServerReceive,
			Timestamp: baseTime.Add(3 * time.Second),
		},
		{
			Key:       tchannel.AnnotationKeyServerSend,
			Timestamp: baseTime.Add(4 * time.Second),
		},
	}
}

type testArgs struct {
	s *mocks.TChanTCollector
	c tchannel.TraceReporter
}

func ctxArg() mock.AnythingOfTypeArgument {
	return mock.AnythingOfType("*tchannel.headerCtx")
}

func TestSubmit(t *testing.T) {
	withSetup(t, func(ctx thrift.Context, args testArgs) {
		endpoint := tchannel.TargetEndpoint{
			HostPort:    "127.0.0.1:8888",
			ServiceName: "testServer",
			Operation:   "test",
		}
		span := *tchannel.NewRootSpan()
		annotations := RandomAnnotations()
		thriftSpan := buildZipkinSpan(span, annotations, nil, endpoint)
		thriftSpan.BinaryAnnotations = []*gen.BinaryAnnotation{}
		ret := &gen.Response{Ok: true}

		called := make(chan struct{})
		args.s.On("Submit", ctxArg(), thriftSpan).Return(ret, nil).Run(func(_ mock.Arguments) {
			close(called)
		})
		args.c.Report(span, annotations, nil, endpoint)

		// wait for the server's Submit to get called
		select {
		case <-time.After(time.Second):
			t.Fatal("Submit not called")
		case <-called:
		}
	})
}

func withSetup(t *testing.T, f func(ctx thrift.Context, args testArgs)) {
	args := testArgs{
		s: new(mocks.TChanTCollector),
	}

	ctx, cancel := thrift.NewContext(time.Second * 10)
	defer cancel()

	// Start server
	tchan, err := setupServer(args.s)
	require.NoError(t, err)
	defer tchan.Close()

	// Get client1
	args.c, err = getClient(tchan.PeerInfo().HostPort)
	require.NoError(t, err)

	f(ctx, args)

	args.s.AssertExpectations(t)
}

func setupServer(h *mocks.TChanTCollector) (*tchannel.Channel, error) {
	tchan, err := testutils.NewServer(&testutils.ChannelOpts{
		ServiceName: tcollectorServiceName,
	})
	if err != nil {
		return nil, err
	}

	server := thrift.NewServer(tchan)
	server.Register(gen.NewTChanTCollectorServer(h))
	return tchan, nil
}

func getClient(dst string) (tchannel.TraceReporter, error) {
	tchan, err := testutils.NewClient(nil)
	if err != nil {
		return nil, err
	}

	tchan.Peers().Add(dst)
	return NewZipkinTraceReporter(tchan), nil
}

func BenchmarkBuildThrift(b *testing.B) {
	endpoint := tchannel.TargetEndpoint{
		HostPort:    "127.0.0.1:8888",
		ServiceName: "testServer",
		Operation:   "test",
	}
	span := *tchannel.NewRootSpan()
	annotations := RandomAnnotations()

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		buildZipkinSpan(span, annotations, nil, endpoint)
	}
}
<|endoftext|>


<commit_before>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package resize

import (
	"image"
	"image/ycbcr"
)

// Resize returns a scaled copy of the image slice r of m.
// The returned image has width w and height h.
func Resize(m image.Image, r image.Rectangle, w, h int) image.Image {
	if w < 0 || h < 0 {
		return nil
	}
	if w == 0 || h == 0 || r.Dx() <= 0 || r.Dy() <= 0 {
		return image.NewRGBA64(w, h)
	}
	switch m := m.(type) {
	case *image.RGBA:
		return resizeRGBA(m, r, w, h)
	case *ycbcr.YCbCr:
		if m, ok := resizeYCbCr(m, r, w, h); ok {
			return m
		}
	}
	ww, hh := uint64(w), uint64(h)
	dx, dy := uint64(r.Dx()), uint64(r.Dy())
	// The scaling algorithm is to nearest-neighbor magnify the dx * dy source
	// to a (ww*dx) * (hh*dy) intermediate image and then minify the intermediate
	// image back down to a ww * hh destination with a simple box filter.
	// The intermediate image is implied, we do not physically allocate a slice
	// of length ww*dx*hh*dy.
	// For example, consider a 4*3 source image. Label its pixels from a-l:
	//	abcd
	//	efgh
	//	ijkl
	// To resize this to a 3*2 destination image, the intermediate is 12*6.
	// Whitespace has been added to delineate the destination pixels:
	//	aaab bbcc cddd
	//	aaab bbcc cddd
	//	eeef ffgg ghhh
	//
	//	eeef ffgg ghhh
	//	iiij jjkk klll
	//	iiij jjkk klll
	// Thus, the 'b' source pixel contributes one third of its value to the
	// (0, 0) destination pixel and two thirds to (1, 0).
	// The implementation is a two-step process. First, the source pixels are
	// iterated over and each source pixel's contribution to 1 or more
	// destination pixels are summed. Second, the sums are divided by a scaling
	// factor to yield the destination pixels.
	// TODO: By interleaving the two steps, instead of doing all of
	// step 1 first and all of step 2 second, we could allocate a smaller sum
	// slice of length 4*w*2 instead of 4*w*h, although the resultant code
	// would become more complicated.
	n, sum := dx*dy, make([]uint64, 4*w*h)
	for y := r.Min.Y; y < r.Max.Y; y++ {
		for x := r.Min.X; x < r.Max.X; x++ {
			// Get the source pixel.
			r32, g32, b32, a32 := m.At(x, y).RGBA()
			r64 := uint64(r32)
			g64 := uint64(g32)
			b64 := uint64(b32)
			a64 := uint64(a32)
			// Spread the source pixel over 1 or more destination rows.
			py := uint64(y) * hh
			for remy := hh; remy > 0; {
				qy := dy - (py % dy)
				if qy > remy {
					qy = remy
				}
				// Spread the source pixel over 1 or more destination columns.
				px := uint64(x) * ww
				index := 4 * ((py/dy)*ww + (px / dx))
				for remx := ww; remx > 0; {
					qx := dx - (px % dx)
					if qx > remx {
						qx = remx
					}
					sum[index+0] += r64 * qx * qy
					sum[index+1] += g64 * qx * qy
					sum[index+2] += b64 * qx * qy
					sum[index+3] += a64 * qx * qy
					index += 4
					px += qx
					remx -= qx
				}
				py += qy
				remy -= qy
			}
		}
	}
	return average(sum, w, h, n*0x0101)
}

// average convert the sums to averages and returns the result.
func average(sum []uint64, w, h int, n uint64) image.Image {
	ret := image.NewRGBA(w, h)
	for y := 0; y < h; y++ {
		for x := 0; x < w; x++ {
			index := 4 * (y*w + x)
			ret.Pix[y*ret.Stride+x] = image.RGBAColor{
				uint8(sum[index+0] / n),
				uint8(sum[index+1] / n),
				uint8(sum[index+2] / n),
				uint8(sum[index+3] / n),
			}
		}
	}
	return ret
}

// resizeYCbCr returns a scaled copy of the YCbCr image slice r of m.
// The returned image has width w and height h.
func resizeYCbCr(m *ycbcr.YCbCr, r image.Rectangle, w, h int) (image.Image, bool) {
	var verticalRes int
	switch m.SubsampleRatio {
	case ycbcr.SubsampleRatio420:
		verticalRes = 2
	case ycbcr.SubsampleRatio422:
		verticalRes = 1
	default:
		return nil, false
	}
	ww, hh := uint64(w), uint64(h)
	dx, dy := uint64(r.Dx()), uint64(r.Dy())
	// See comment in Resize.
	n, sum := dx*dy, make([]uint64, 4*w*h)
	for y := r.Min.Y; y < r.Max.Y; y++ {
		Y := m.Y[y*m.YStride:]
		Cb := m.Cb[y/verticalRes*m.CStride:]
		Cr := m.Cr[y/verticalRes*m.CStride:]
		for x := r.Min.X; x < r.Max.X; x++ {
			// Get the source pixel.
			r8, g8, b8 := ycbcr.YCbCrToRGB(Y[x], Cb[x/2], Cr[x/2])
			r64 := uint64(r8)
			g64 := uint64(g8)
			b64 := uint64(b8)
			// Spread the source pixel over 1 or more destination rows.
			py := uint64(y) * hh
			for remy := hh; remy > 0; {
				qy := dy - (py % dy)
				if qy > remy {
					qy = remy
				}
				// Spread the source pixel over 1 or more destination columns.
				px := uint64(x) * ww
				index := 4 * ((py/dy)*ww + (px / dx))
				for remx := ww; remx > 0; {
					qx := dx - (px % dx)
					if qx > remx {
						qx = remx
					}
					qxy := qx * qy
					sum[index+0] += r64 * qxy
					sum[index+1] += g64 * qxy
					sum[index+2] += b64 * qxy
					sum[index+3] += 0xFFFF * qxy
					index += 4
					px += qx
					remx -= qx
				}
				py += qy
				remy -= qy
			}
		}
	}
	return average(sum, w, h, n), true
}

// resizeRGBA returns a scaled copy of the RGBA image slice r of m.
// The returned image has width w and height h.
func resizeRGBA(m *image.RGBA, r image.Rectangle, w, h int) image.Image {
	ww, hh := uint64(w), uint64(h)
	dx, dy := uint64(r.Dx()), uint64(r.Dy())
	// See comment in Resize.
	n, sum := dx*dy, make([]uint64, 4*w*h)
	for y := r.Min.Y; y < r.Max.Y; y++ {
		pix := m.Pix[y*m.Stride:]
		for x := r.Min.X; x < r.Max.X; x++ {
			// Get the source pixel.
			p := pix[x]
			r64 := uint64(p.R)
			g64 := uint64(p.G)
			b64 := uint64(p.B)
			a64 := uint64(p.A)
			// Spread the source pixel over 1 or more destination rows.
			py := uint64(y) * hh
			for remy := hh; remy > 0; {
				qy := dy - (py % dy)
				if qy > remy {
					qy = remy
				}
				// Spread the source pixel over 1 or more destination columns.
				px := uint64(x) * ww
				index := 4 * ((py/dy)*ww + (px / dx))
				for remx := ww; remx > 0; {
					qx := dx - (px % dx)
					if qx > remx {
						qx = remx
					}
					qxy := qx * qy
					sum[index+0] += r64 * qxy
					sum[index+1] += g64 * qxy
					sum[index+2] += b64 * qxy
					sum[index+3] += a64 * qxy
					index += 4
					px += qx
					remx -= qx
				}
				py += qy
				remy -= qy
			}
		}
	}
	return average(sum, w, h, n)
}

// Resample returns a resampled copy of the image slice r of m.
// The returned image has width w and height h.
func Resample(m image.Image, r image.Rectangle, w, h int) image.Image {
	if w < 0 || h < 0 {
		return nil
	}
	if w == 0 || h == 0 || r.Dx() <= 0 || r.Dy() <= 0 {
		return image.NewRGBA64(w, h)
	}
	curw, curh := r.Dx(), r.Dy()
	img := image.NewRGBA(w, h)
	for y := 0; y < h; y++ {
		for x := 0; x < w; x++ {
			// Get a source pixel.
			subx := x * curw / w
			suby := y * curh / h
			r32, g32, b32, a32 := m.At(subx, suby).RGBA()
			r := uint8(r32 >> 8)
			g := uint8(g32 >> 8)
			b := uint8(b32 >> 8)
			a := uint8(a32 >> 8)
			img.SetRGBA(x, y, image.RGBAColor{r, g, b, a})
		}
	}
	return img
}
<commit_msg>Update image resizing code for Go change 9031:5c33eaa24213<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package resize

import (
	"image"
	"image/ycbcr"
)

// Resize returns a scaled copy of the image slice r of m.
// The returned image has width w and height h.
func Resize(m image.Image, r image.Rectangle, w, h int) image.Image {
	if w < 0 || h < 0 {
		return nil
	}
	if w == 0 || h == 0 || r.Dx() <= 0 || r.Dy() <= 0 {
		return image.NewRGBA64(w, h)
	}
	switch m := m.(type) {
	case *image.RGBA:
		return resizeRGBA(m, r, w, h)
	case *ycbcr.YCbCr:
		if m, ok := resizeYCbCr(m, r, w, h); ok {
			return m
		}
	}
	ww, hh := uint64(w), uint64(h)
	dx, dy := uint64(r.Dx()), uint64(r.Dy())
	// The scaling algorithm is to nearest-neighbor magnify the dx * dy source
	// to a (ww*dx) * (hh*dy) intermediate image and then minify the intermediate
	// image back down to a ww * hh destination with a simple box filter.
	// The intermediate image is implied, we do not physically allocate a slice
	// of length ww*dx*hh*dy.
	// For example, consider a 4*3 source image. Label its pixels from a-l:
	//	abcd
	//	efgh
	//	ijkl
	// To resize this to a 3*2 destination image, the intermediate is 12*6.
	// Whitespace has been added to delineate the destination pixels:
	//	aaab bbcc cddd
	//	aaab bbcc cddd
	//	eeef ffgg ghhh
	//
	//	eeef ffgg ghhh
	//	iiij jjkk klll
	//	iiij jjkk klll
	// Thus, the 'b' source pixel contributes one third of its value to the
	// (0, 0) destination pixel and two thirds to (1, 0).
	// The implementation is a two-step process. First, the source pixels are
	// iterated over and each source pixel's contribution to 1 or more
	// destination pixels are summed. Second, the sums are divided by a scaling
	// factor to yield the destination pixels.
	// TODO: By interleaving the two steps, instead of doing all of
	// step 1 first and all of step 2 second, we could allocate a smaller sum
	// slice of length 4*w*2 instead of 4*w*h, although the resultant code
	// would become more complicated.
	n, sum := dx*dy, make([]uint64, 4*w*h)
	for y := r.Min.Y; y < r.Max.Y; y++ {
		for x := r.Min.X; x < r.Max.X; x++ {
			// Get the source pixel.
			r32, g32, b32, a32 := m.At(x, y).RGBA()
			r64 := uint64(r32)
			g64 := uint64(g32)
			b64 := uint64(b32)
			a64 := uint64(a32)
			// Spread the source pixel over 1 or more destination rows.
			py := uint64(y-r.Min.Y) * hh
			for remy := hh; remy > 0; {
				qy := dy - (py % dy)
				if qy > remy {
					qy = remy
				}
				// Spread the source pixel over 1 or more destination columns.
				px := uint64(x-r.Min.X) * ww
				index := 4 * ((py/dy)*ww + (px / dx))
				for remx := ww; remx > 0; {
					qx := dx - (px % dx)
					if qx > remx {
						qx = remx
					}
					sum[index+0] += r64 * qx * qy
					sum[index+1] += g64 * qx * qy
					sum[index+2] += b64 * qx * qy
					sum[index+3] += a64 * qx * qy
					index += 4
					px += qx
					remx -= qx
				}
				py += qy
				remy -= qy
			}
		}
	}
	return average(sum, w, h, n*0x0101)
}

// average convert the sums to averages and returns the result.
func average(sum []uint64, w, h int, n uint64) image.Image {
	ret := image.NewRGBA(w, h)
	for y := 0; y < h; y++ {
		for x := 0; x < w; x++ {
			index := 4 * (y*w + x)
			ret.Pix[y*ret.Stride+x] = image.RGBAColor{
				uint8(sum[index+0] / n),
				uint8(sum[index+1] / n),
				uint8(sum[index+2] / n),
				uint8(sum[index+3] / n),
			}
		}
	}
	return ret
}

// resizeYCbCr returns a scaled copy of the YCbCr image slice r of m.
// The returned image has width w and height h.
func resizeYCbCr(m *ycbcr.YCbCr, r image.Rectangle, w, h int) (image.Image, bool) {
	var verticalRes int
	switch m.SubsampleRatio {
	case ycbcr.SubsampleRatio420:
		verticalRes = 2
	case ycbcr.SubsampleRatio422:
		verticalRes = 1
	default:
		return nil, false
	}
	ww, hh := uint64(w), uint64(h)
	dx, dy := uint64(r.Dx()), uint64(r.Dy())
	// See comment in Resize.
	n, sum := dx*dy, make([]uint64, 4*w*h)
	for y := r.Min.Y; y < r.Max.Y; y++ {
		Y := m.Y[y*m.YStride:]
		Cb := m.Cb[y/verticalRes*m.CStride:]
		Cr := m.Cr[y/verticalRes*m.CStride:]
		for x := r.Min.X; x < r.Max.X; x++ {
			// Get the source pixel.
			r8, g8, b8 := ycbcr.YCbCrToRGB(Y[x], Cb[x/2], Cr[x/2])
			r64 := uint64(r8)
			g64 := uint64(g8)
			b64 := uint64(b8)
			// Spread the source pixel over 1 or more destination rows.
			py := uint64(y-r.Min.Y) * hh
			for remy := hh; remy > 0; {
				qy := dy - (py % dy)
				if qy > remy {
					qy = remy
				}
				// Spread the source pixel over 1 or more destination columns.
				px := uint64(x-r.Min.X) * ww
				index := 4 * ((py/dy)*ww + (px / dx))
				for remx := ww; remx > 0; {
					qx := dx - (px % dx)
					if qx > remx {
						qx = remx
					}
					qxy := qx * qy
					sum[index+0] += r64 * qxy
					sum[index+1] += g64 * qxy
					sum[index+2] += b64 * qxy
					sum[index+3] += 0xFFFF * qxy
					index += 4
					px += qx
					remx -= qx
				}
				py += qy
				remy -= qy
			}
		}
	}
	return average(sum, w, h, n), true
}

// resizeRGBA returns a scaled copy of the RGBA image slice r of m.
// The returned image has width w and height h.
func resizeRGBA(m *image.RGBA, r image.Rectangle, w, h int) image.Image {
	ww, hh := uint64(w), uint64(h)
	dx, dy := uint64(r.Dx()), uint64(r.Dy())
	// See comment in Resize.
	n, sum := dx*dy, make([]uint64, 4*w*h)
	for y := r.Min.Y; y < r.Max.Y; y++ {
		pix := m.Pix[(y-m.Rect.Min.Y)*m.Stride:]
		for x := r.Min.X; x < r.Max.X; x++ {
			// Get the source pixel.
			p := pix[x-m.Rect.Min.X]
			r64 := uint64(p.R)
			g64 := uint64(p.G)
			b64 := uint64(p.B)
			a64 := uint64(p.A)
			// Spread the source pixel over 1 or more destination rows.
			py := uint64(y-r.Min.Y) * hh
			for remy := hh; remy > 0; {
				qy := dy - (py % dy)
				if qy > remy {
					qy = remy
				}
				// Spread the source pixel over 1 or more destination columns.
				px := uint64(x-r.Min.X) * ww
				index := 4 * ((py/dy)*ww + (px / dx))
				for remx := ww; remx > 0; {
					qx := dx - (px % dx)
					if qx > remx {
						qx = remx
					}
					qxy := qx * qy
					sum[index+0] += r64 * qxy
					sum[index+1] += g64 * qxy
					sum[index+2] += b64 * qxy
					sum[index+3] += a64 * qxy
					index += 4
					px += qx
					remx -= qx
				}
				py += qy
				remy -= qy
			}
		}
	}
	return average(sum, w, h, n)
}

// Resample returns a resampled copy of the image slice r of m.
// The returned image has width w and height h.
func Resample(m image.Image, r image.Rectangle, w, h int) image.Image {
	if w < 0 || h < 0 {
		return nil
	}
	if w == 0 || h == 0 || r.Dx() <= 0 || r.Dy() <= 0 {
		return image.NewRGBA64(w, h)
	}
	curw, curh := r.Dx(), r.Dy()
	img := image.NewRGBA(w, h)
	for y := 0; y < h; y++ {
		for x := 0; x < w; x++ {
			// Get a source pixel.
			subx := x * curw / w
			suby := y * curh / h
			r32, g32, b32, a32 := m.At(subx, suby).RGBA()
			r := uint8(r32 >> 8)
			g := uint8(g32 >> 8)
			b := uint8(b32 >> 8)
			a := uint8(a32 >> 8)
			img.SetRGBA(x, y, image.RGBAColor{r, g, b, a})
		}
	}
	return img
}
<|endoftext|>


<commit_before>// Copyright (c) 2016, Janoš Guljaš <janos@resenje.org>
// All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package fileServer

import (
	"net/http"
	"os"
	"path"
	"path/filepath"
	"strings"
)

func redirect(w http.ResponseWriter, r *http.Request, location string) {
	if q := r.URL.RawQuery; q != "" {
		location += "?" + q
	}
	w.Header().Set("Location", location)
	w.Header().Set("Cache-Control", "no-cache")
	w.WriteHeader(http.StatusFound)
}

func open(root, name string) (http.File, error) {
	if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 ||
		strings.Contains(name, "\x00") {
		return nil, errNotFound // invalid character in file path
	}
	if root == "" {
		root = "."
	}
	f, err := os.Open(filepath.Join(root, filepath.FromSlash(path.Clean("/"+name))))
	if err != nil {
		return nil, err
	}
	return f, nil
}
<commit_msg>Simplify open function for file server<commit_after>// Copyright (c) 2016, Janoš Guljaš <janos@resenje.org>
// All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package fileServer

import (
	"net/http"
	"os"
	"path"
	"path/filepath"
)

func redirect(w http.ResponseWriter, r *http.Request, location string) {
	if q := r.URL.RawQuery; q != "" {
		location += "?" + q
	}
	w.Header().Set("Location", location)
	w.Header().Set("Cache-Control", "no-cache")
	w.WriteHeader(http.StatusFound)
}

func open(root, name string) (http.File, error) {
	if root == "" {
		root = "."
	}
	return os.Open(filepath.Join(root, filepath.FromSlash(path.Clean("/"+name))))
}
<|endoftext|>


<commit_before>// This program implements "fizz/buzz" solution in a rather overrengineered sort of way.
// Running example can be found here:
//
//     https://play.golang.org/p/budLggnTMXH
//
// This example studies the way to implement functional style programming in Go.
package main

import (
	"fmt"
	"log"
	"strconv"
	"strings"
)

// Start of the program
func main() {
	// Create filtering pipeline and display resuluts
	makePipeline().
		AddFilter(makeLimitFilter(45)).        // Limit number of generated values in a stream.
		AddFilter(makeValueFilter(3, "fizz")). // Add tag "fizz" to all values devisible by 3.
		AddFilter(makeValueFilter(5, "buzz")). // Add tag "buzz" to all values devisible by 5.
		AddFilter(makeValueFilter(7, "zang")). // Add tag "boom" to all values devisible by 7.
		AddFilter(makeValueFilter(9, "bang")). // Add tag "bang" to all values devisible by 9.
		Run(func(v Val) { fmt.Println(v) })    // Collect and display filtered values.
}

// Val is a supporting type to hold and represent enumerated value
type Val struct {
	i int
	s []string
}

// String pretty printer for Val type. It outputs either space-joined V.s,
// or V.i in string form.
func (v Val) String() string {
	s := strconv.Itoa(v.i)
	if len(v.s) > 0 {
		s = strings.Join(v.s, " ")
	}
	return s
}

type Processor func(Val)

type Sink chan<- Val

type Pipeline <-chan Val

// Pipeline factory
func makePipeline() Pipeline {
	ch := make(chan Val)
	go func() {
		for i := 1; ; i++ {
			ch <- Val{i, make([]string, 0, 1)}
		}
	}()
	return ch
}

func (p Pipeline) Run(proc Processor) {
	for v := range p {
		proc(v)
	}
}

func (p Pipeline) AddFilter(filter Filter) Pipeline {
	return filter(p)
}

// Filter is connecting pipelines
type Filter func(in Pipeline) Pipeline

// FilterFn is a function that does the actual filtering
type FilterFn func(out Sink, in Pipeline)

// apply creates Filter by applying provided FilterFn. It takes care of resources by closing
// channels at the appropriate time. It also handles panics in filtering funcitons.
func apply(filterFn FilterFn) Filter {
	return func(in Pipeline) Pipeline {
		out := make(chan Val)
		go func() {
			defer func() {
				if err := recover(); err != nil {
					log.Printf("pipeline paniced: %v", err)
				}
				close(out) // Always close channel, even if filterFn() panics
			}()
			filterFn(out, in)
		}()
		return out
	}
}

// Limiting filter generator implemented as closure to capture provided parameter.
func makeLimitFilter(limit int) Filter {
	return apply(func(limit int) FilterFn {
		return func(out Sink, in Pipeline) {
			for i := 0; i < limit; i++ {
				v, ok := <-in
				if !ok {
					break
				}
				// passthrough
				out <- v
			}
		}
	}(limit))
}

// Value filter generator implemented as closure to capture provided parameter.
func makeValueFilter(num int, tag string) Filter {
	return apply(func(div int, tag string) FilterFn {
		return func(out Sink, in Pipeline) {
			for {
				v, ok := <-in
				if !ok {
					break
				}
				// Check if number if divisible by our divizor
				if v.i%div == 0 {
					v.s = append(v.s, tag)
				}
				out <- v
			}
		}
	}(num, tag))
}
<commit_msg>Reorganized code and provided documenting comments.<commit_after>// This program implements "fizz/buzz" solution in a rather overrengineered sort of way.
// Running example can be found here:
//
//     https://play.golang.org/p/budLggnTMXH
//
// This example studies the way to implement functional style programming in Go.
package main

import (
	"fmt"
	"log"
	"strconv"
	"strings"
)

// Start of the program
func main() {
	// Create filtering pipeline and display resuluts
	makePipeline().
		AddFilter(makeLimitFilter(45)).        // Limit number of generated values in a stream.
		AddFilter(makeValueFilter(3, "fizz")). // Add tag "fizz" to all values devisible by 3.
		AddFilter(makeValueFilter(5, "buzz")). // Add tag "buzz" to all values devisible by 5.
		AddFilter(makeValueFilter(7, "zang")). // Add tag "boom" to all values devisible by 7.
		AddFilter(makeValueFilter(9, "bang")). // Add tag "bang" to all values devisible by 9.
		Run(func(v Val) { fmt.Println(v) })    // Collect and display filtered values.
}

// Val is a supporting type to hold and represent enumerated value
type Val struct {
	i int
	s []string
}

// String pretty printer for Val type. It outputs either space-joined V.s or V.i in string form.
func (v Val) String() string {
	s := strconv.Itoa(v.i)
	if len(v.s) > 0 {
		s = strings.Join(v.s, " ")
	}
	return s
}

// Pipeline helper types

// Processor is a functor object used to process each value in a filtered pipeline.
type Processor func(Val)

// Sink is a helper type to denote collector in the pipeline chain.
type Sink chan<- Val

// Pipeline is a helper object to represent generator int he pipeline chain.
type Pipeline <-chan Val

// makePipeline is a Pipeline factory function. It creates generator responsible for
// creating initial stream of Val values.
func makePipeline() Pipeline {
	ch := make(chan Val)
	go func() {
		for i := 1; ; i++ {
			ch <- Val{i, make([]string, 0, 1)}
		}
	}()
	return ch
}

// Run method wraps final collector.
func (p Pipeline) Run(proc Processor) {
	for v := range p {
		proc(v)
	}
}

// AddFilter method inserts new Filter node into a Pipeline.
func (p Pipeline) AddFilter(filter Filter) Pipeline {
	return filter(p)
}

// Filter is a helper type that create new generator, based on the processed stream from `in` Pipeline, effectively
// creating a new node in the chain of connected Pipeline objects.
type Filter func(in Pipeline) Pipeline

// FilterFn is a function that does the actual filtering by recieving a Val object from `in`, processing it, and
// optionally passing it out to `out` Sink.
type FilterFn func(out Sink, in Pipeline)

// Limiting filter generator implemented as closure to capture provided parameter.
func makeLimitFilter(limit int) Filter {
	return apply(func(limit int) FilterFn {
		return func(out Sink, in Pipeline) {
			for i := 0; i < limit; i++ {
				v, ok := <-in
				if !ok {
					break
				}
				// passthrough
				out <- v
			}
		}
	}(limit))
}

// Value filter generator implemented as closure to capture provided parameter.
func makeValueFilter(num int, tag string) Filter {
	return apply(func(div int, tag string) FilterFn {
		return func(out Sink, in Pipeline) {
			for {
				v, ok := <-in
				if !ok {
					break
				}
				// Check if number if divisible by our divizor
				if v.i%div == 0 {
					v.s = append(v.s, tag)
				}
				out <- v
			}
		}
	}(num, tag))
}

// apply constructs a new Filter by applying provided FilterFn. It takes care of resources by closing
// `out` channels at the appropriate time. It also handles panics in filtering funcitons.
func apply(filterFn FilterFn) Filter {
	return func(in Pipeline) Pipeline {
		out := make(chan Val)
		go func() {
			defer func() {
				if err := recover(); err != nil {
					log.Printf("pipeline paniced: %v", err)
				}
				close(out) // Always close channel, even if filterFn() panics
			}()
			filterFn(out, in)
		}()
		return out
	}
}
<|endoftext|>


<commit_before>package toolbox

import (
	"fmt"
	"strings"
)

//Matcher represents a matcher, that matches input from offset position, it returns number of characters matched.
type Matcher interface {
	//Match matches input starting from offset, it return number of characters matched
	Match(input string, offset int) (matched int)
}

//Token a matchable input
type Token struct {
	Token   int
	Matched string
}

//Tokenizer represents a token scanner.
type Tokenizer struct {
	matchers       map[int]Matcher
	Input          string
	Index          int
	InvalidToken   int
	EndOfFileToken int
}

//Nexts matches the first of the candidates
func (t *Tokenizer) Nexts(candidates ...int) *Token {
	for _, candidate := range candidates {
		result := t.Next(candidate)
		if result.Token != t.InvalidToken {
			return result

		}
	}
	return &Token{t.InvalidToken, ""}
}

//Next tries to match a candidate, it returns token if imatching is successful.
func (t *Tokenizer) Next(candidate int) *Token {
	offset := t.Index
	if !(offset < len(t.Input)) {
		return &Token{t.EndOfFileToken, ""}
	}
	if matcher, ok := t.matchers[candidate]; ok {
		matchedSize := matcher.Match(t.Input, offset)
		if matchedSize > 0 {
			t.Index = t.Index + matchedSize
			return &Token{candidate, t.Input[offset : offset+matchedSize]}
		}

	} else {
		panic(fmt.Sprintf("Failed to lookup matcher for %v", candidate))
	}
	return &Token{t.InvalidToken, ""}
}

//NewTokenizer creates a new NewTokenizer, it takes input, invalidToken, endOfFileToeken, and matchers.
func NewTokenizer(input string, invalidToken int, endOfFileToken int, matcher map[int]Matcher) *Tokenizer {
	return &Tokenizer{
		matchers:       matcher,
		Input:          input,
		Index:          0,
		InvalidToken:   invalidToken,
		EndOfFileToken: endOfFileToken,
	}
}

//CharactersMatcher represents a matcher, that matches any of Chars.
type CharactersMatcher struct {
	Chars string //characters to be matched
}

//Match matches any characters defined in Chars in the input, returns 1 if character has been matched
func (m CharactersMatcher) Match(input string, offset int) (matched int) {
	var result = 0
outer:
	for i := 0; i < len(input)-offset; i++ {
		aChar := input[offset+i : offset+i+1]
		for j := 0; j < len(m.Chars); j++ {
			if aChar == m.Chars[j:j+1] {
				result++
				continue outer
			}
		}
		break
	}
	return result
}

func isLetter(aChar string) bool {
	return (aChar >= "a" && aChar <= "z") || (aChar >= "A" && aChar <= "Z")
}

func isDigit(aChar string) bool {
	return (aChar >= "0" && aChar <= "9")
}

//EOFMatcher represents end of input matcher
type EOFMatcher struct {
}

//Match returns 1 if end of input has been reached otherwise 0
func (m EOFMatcher) Match(input string, offset int) (matched int) {
	if offset+1 == len(input) {
		return 1
	}
	return 0
}

//IntMatcher represents a matcher that finds any int in the input
type IntMatcher struct{}

//Match matches a literal in the input, it returns number of character matched.
func (m IntMatcher) Match(input string, offset int) (matched int) {
	if !isDigit(input[offset : offset+1]) {
		return 0
	}
	var i = 1
	for ; i < len(input)-offset; i++ {
		aChar := input[offset+i : offset+i+1]
		if !isDigit(aChar) {
			break
		}
	}
	return i
}

//LiteralMatcher represents a matcher that finds any literals in the input
type LiteralMatcher struct{}

//Match matches a literal in the input, it returns number of character matched.
func (m LiteralMatcher) Match(input string, offset int) (matched int) {
	if !isLetter(input[offset : offset+1]) {
		return 0
	}
	var i = 1
	for ; i < len(input)-offset; i++ {
		aChar := input[offset+i : offset+i+1]
		if !((isLetter(aChar)) || isDigit(aChar) || aChar == "_" || aChar == ".") {
			break
		}
	}
	return i
}

//LiteralMatcher represents a matcher that finds any literals in the input
type BodyMatcher struct {
	Begin string
	End   string
}

//Match matches a literal in the input, it returns number of character matched.
func (m BodyMatcher) Match(input string, offset int) (matched int) {
	if input[offset:offset+1] != m.Begin {
		return 0
	}
	var depth = 1
	var i = 1
	for ; i < len(input)-offset; i++ {
		aChar := input[offset+i : offset+i+1]
		switch aChar {
		case m.Begin:
			depth++
			break
		case m.End:
			depth--

		}
		if depth == 0 {
			i++
			break
		}
	}
	return i
}

//KeywordMatcher represents a keyword matcher
type KeywordMatcher struct {
	Keyword       string
	CaseSensitive bool
}

//Match matches keyword in the input,  it returns number of character matched.
func (m KeywordMatcher) Match(input string, offset int) (matched int) {
	if !(offset+len(m.Keyword)-1 < len(input)) {
		return 0
	}

	if m.CaseSensitive {
		if input[offset:offset+len(m.Keyword)] == m.Keyword {
			return len(m.Keyword)
		}
	} else {
		if strings.ToLower(input[offset:offset+len(m.Keyword)]) == strings.ToLower(m.Keyword) {
			return len(m.Keyword)
		}
	}
	return 0
}

//KeywordsMatcher represents a matcher that finds any of specified keywords in the input
type KeywordsMatcher struct {
	Keywords      []string
	CaseSensitive bool
}

//Match matches any specified keyword,  it returns number of character matched.
func (m KeywordsMatcher) Match(input string, offset int) (matched int) {
	for _, keyword := range m.Keywords {
		if len(input)-offset < len(keyword) {
			continue
		}
		if m.CaseSensitive {
			if input[offset:offset+len(keyword)] == keyword {
				return len(keyword)
			}
		} else {
			if strings.ToLower(input[offset:offset+len(keyword)]) == strings.ToLower(keyword) {
				return len(keyword)
			}
		}
	}
	return 0
}
<commit_msg>added IdMathcer<commit_after>package toolbox

import (
	"fmt"
	"strings"
)

//Matcher represents a matcher, that matches input from offset position, it returns number of characters matched.
type Matcher interface {
	//Match matches input starting from offset, it return number of characters matched
	Match(input string, offset int) (matched int)
}

//Token a matchable input
type Token struct {
	Token   int
	Matched string
}

//Tokenizer represents a token scanner.
type Tokenizer struct {
	matchers       map[int]Matcher
	Input          string
	Index          int
	InvalidToken   int
	EndOfFileToken int
}

//Nexts matches the first of the candidates
func (t *Tokenizer) Nexts(candidates ...int) *Token {
	for _, candidate := range candidates {
		result := t.Next(candidate)
		if result.Token != t.InvalidToken {
			return result

		}
	}
	return &Token{t.InvalidToken, ""}
}

//Next tries to match a candidate, it returns token if imatching is successful.
func (t *Tokenizer) Next(candidate int) *Token {
	offset := t.Index
	if !(offset < len(t.Input)) {
		return &Token{t.EndOfFileToken, ""}
	}
	if matcher, ok := t.matchers[candidate]; ok {
		matchedSize := matcher.Match(t.Input, offset)
		if matchedSize > 0 {
			t.Index = t.Index + matchedSize
			return &Token{candidate, t.Input[offset : offset+matchedSize]}
		}

	} else {
		panic(fmt.Sprintf("Failed to lookup matcher for %v", candidate))
	}
	return &Token{t.InvalidToken, ""}
}

//NewTokenizer creates a new NewTokenizer, it takes input, invalidToken, endOfFileToeken, and matchers.
func NewTokenizer(input string, invalidToken int, endOfFileToken int, matcher map[int]Matcher) *Tokenizer {
	return &Tokenizer{
		matchers:       matcher,
		Input:          input,
		Index:          0,
		InvalidToken:   invalidToken,
		EndOfFileToken: endOfFileToken,
	}
}

//CharactersMatcher represents a matcher, that matches any of Chars.
type CharactersMatcher struct {
	Chars string //characters to be matched
}

//Match matches any characters defined in Chars in the input, returns 1 if character has been matched
func (m CharactersMatcher) Match(input string, offset int) (matched int) {
	var result = 0
outer:
	for i := 0; i < len(input)-offset; i++ {
		aChar := input[offset+i : offset+i+1]
		for j := 0; j < len(m.Chars); j++ {
			if aChar == m.Chars[j:j+1] {
				result++
				continue outer
			}
		}
		break
	}
	return result
}

func isLetter(aChar string) bool {
	return (aChar >= "a" && aChar <= "z") || (aChar >= "A" && aChar <= "Z")
}

func isDigit(aChar string) bool {
	return (aChar >= "0" && aChar <= "9")
}

//EOFMatcher represents end of input matcher
type EOFMatcher struct {
}

//Match returns 1 if end of input has been reached otherwise 0
func (m EOFMatcher) Match(input string, offset int) (matched int) {
	if offset+1 == len(input) {
		return 1
	}
	return 0
}

//IntMatcher represents a matcher that finds any int in the input
type IntMatcher struct{}

//Match matches a literal in the input, it returns number of character matched.
func (m IntMatcher) Match(input string, offset int) (matched int) {
	if !isDigit(input[offset : offset+1]) {
		return 0
	}
	var i = 1
	for ; i < len(input)-offset; i++ {
		aChar := input[offset+i : offset+i+1]
		if !isDigit(aChar) {
			break
		}
	}
	return i
}

//LiteralMatcher represents a matcher that finds any literals in the input
type LiteralMatcher struct{}

//Match matches a literal in the input, it returns number of character matched.
func (m LiteralMatcher) Match(input string, offset int) (matched int) {
	if !isLetter(input[offset : offset+1]) {
		return 0
	}
	var i = 1
	for ; i < len(input)-offset; i++ {
		aChar := input[offset+i : offset+i+1]
		if !((isLetter(aChar)) || isDigit(aChar) || aChar == "_" || aChar == ".") {
			break
		}
	}
	return i
}

//LiteralMatcher represents a matcher that finds any literals in the input
type IdMatcher struct{}

//Match matches a literal in the input, it returns number of character matched.
func (m IdMatcher) Match(input string, offset int) (matched int) {
	if !isLetter(input[offset : offset+1]) && !isDigit(input[offset : offset+1])  {
		return 0
	}
	var i = 1
	for ; i < len(input)-offset; i++ {
		aChar := input[offset+i : offset+i+1]
		if !((isLetter(aChar)) || isDigit(aChar) || aChar == "_" || aChar == ".") {
			break
		}
	}
	return i
}

//LiteralMatcher represents a matcher that finds any literals in the input
type BodyMatcher struct {
	Begin string
	End   string
}

//Match matches a literal in the input, it returns number of character matched.
func (m BodyMatcher) Match(input string, offset int) (matched int) {
	if input[offset:offset+1] != m.Begin {
		return 0
	}
	var depth = 1
	var i = 1
	for ; i < len(input)-offset; i++ {
		aChar := input[offset+i : offset+i+1]
		switch aChar {
		case m.Begin:
			depth++
			break
		case m.End:
			depth--

		}
		if depth == 0 {
			i++
			break
		}
	}
	return i
}

//KeywordMatcher represents a keyword matcher
type KeywordMatcher struct {
	Keyword       string
	CaseSensitive bool
}

//Match matches keyword in the input,  it returns number of character matched.
func (m KeywordMatcher) Match(input string, offset int) (matched int) {
	if !(offset+len(m.Keyword)-1 < len(input)) {
		return 0
	}

	if m.CaseSensitive {
		if input[offset:offset+len(m.Keyword)] == m.Keyword {
			return len(m.Keyword)
		}
	} else {
		if strings.ToLower(input[offset:offset+len(m.Keyword)]) == strings.ToLower(m.Keyword) {
			return len(m.Keyword)
		}
	}
	return 0
}

//KeywordsMatcher represents a matcher that finds any of specified keywords in the input
type KeywordsMatcher struct {
	Keywords      []string
	CaseSensitive bool
}

//Match matches any specified keyword,  it returns number of character matched.
func (m KeywordsMatcher) Match(input string, offset int) (matched int) {
	for _, keyword := range m.Keywords {
		if len(input)-offset < len(keyword) {
			continue
		}
		if m.CaseSensitive {
			if input[offset:offset+len(keyword)] == keyword {
				return len(keyword)
			}
		} else {
			if strings.ToLower(input[offset:offset+len(keyword)]) == strings.ToLower(keyword) {
				return len(keyword)
			}
		}
	}
	return 0
}
<|endoftext|>


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

// This package implements a basic LISP interpretor for embedding in a go program for scripting.
// This file implements the tokenizer.

package golisp

import (
	"fmt"
	"unicode"
)

const (
	ILLEGAL = iota
	SYMBOL
	NUMBER
	HEXNUMBER
	BINARYNUMBER
	FLOAT
	STRING
	QUOTE
	BACKQUOTE
	COMMA
	COMMAAT
	LPAREN
	RPAREN
	LBRACKET
	RBRACKET
	LBRACE
	RBRACE
	PERIOD
	TRUE
	FALSE
	COMMENT
	EOF
)

type Tokenizer struct {
	LookaheadToken int
	LookaheadLit   string
	Source         string
	Position       int
}

func NewTokenizer(src string) *Tokenizer {
	t := &Tokenizer{Source: src}
	t.ConsumeToken()
	return t
}

func (self *Tokenizer) NextToken() (token int, lit string) {
	return self.LookaheadToken, self.LookaheadLit
}

func (self *Tokenizer) isSymbolCharacter(ch rune) bool {
	return unicode.IsLetter(ch) || unicode.IsNumber(ch) || ch == '*' || ch == '-' || ch == '?' || ch == '!' || ch == '_' || ch == '>' || ch == ':' || ch == '^'
}

func (self *Tokenizer) readSymbol() (token int, lit string) {
	start := self.Position
	for !self.isEof() && self.isSymbolCharacter(rune(self.Source[self.Position])) {
		self.Position++
	}
	return SYMBOL, self.Source[start:self.Position]
}

func isHexChar(ch rune) bool {
	switch ch {
	case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
		return true
	case 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F':
		return true
	default:
		return false
	}
}

func isBinaryChar(ch rune) bool {
	switch ch {
	case '0', '1':
		return true
	default:
		return false
	}
}

func (self *Tokenizer) readHexNumber() (token int, lit string) {
	start := self.Position
	for !self.isEof() {
		ch := rune(self.Source[self.Position])
		if isHexChar(ch) {
			self.Position++
		} else {
			break
		}
	}

	lit = self.Source[start:self.Position]
	token = HEXNUMBER
	return
}

func (self *Tokenizer) readBinaryNumber() (token int, lit string) {
	start := self.Position
	for !self.isEof() {
		ch := rune(self.Source[self.Position])
		if isBinaryChar(ch) {
			self.Position++
		} else {
			break
		}
	}

	lit = self.Source[start:self.Position]
	token = BINARYNUMBER
	return
}

func (self *Tokenizer) readNumber() (token int, lit string) {
	start := self.Position
	isFloat := false
	sawDecimal := false
	for !self.isEof() {
		ch := rune(self.Source[self.Position])
		if ch == '.' && !sawDecimal {
			isFloat = true
			sawDecimal = true
			self.Position++
		} else if (start == self.Position) && ch == '-' {
			self.Position++
		} else if unicode.IsNumber(ch) {
			self.Position++
		} else {
			break
		}
	}

	lit = self.Source[start:self.Position]
	if isFloat {
		token = FLOAT
	} else {
		token = NUMBER
	}
	return
}

func (self *Tokenizer) readString() (token int, lit string) {
	buffer := make([]rune, 0, 10)
	self.Position++
	for !self.isEof() && rune(self.Source[self.Position]) != '"' {
		if rune(self.Source[self.Position]) == '\\' {
			self.Position++
		}
		buffer = append(buffer, rune(self.Source[self.Position]))
		self.Position++
	}
	if self.isEof() {
		return EOF, ""
	}
	self.Position++
	return STRING, string(buffer)
}

func (self *Tokenizer) isEof() bool {
	return self.Position >= len(self.Source)
}

func (self *Tokenizer) isAlmostEof() bool {
	return self.Position == len(self.Source)-1
}

func (self *Tokenizer) readNextToken() (token int, lit string) {
	if self.isEof() {
		return EOF, ""
	}
	for unicode.IsSpace(rune(self.Source[self.Position])) {
		self.Position++
		if self.isEof() {
			return EOF, ""
		}
	}
	currentChar := rune(self.Source[self.Position])
	var nextChar rune
	if !self.isAlmostEof() {
		nextChar = rune(self.Source[self.Position+1])
	}
	if unicode.IsLetter(currentChar) || currentChar == '_' {
		return self.readSymbol()
	} else if currentChar == '0' && nextChar == 'x' {
		self.Position += 2
		return self.readHexNumber()
	} else if unicode.IsNumber(currentChar) {
		return self.readNumber()
	} else if currentChar == '-' && unicode.IsNumber(nextChar) {
		return self.readNumber()
	} else if currentChar == '"' {
		return self.readString()
	} else if currentChar == '\'' {
		self.Position++
		return QUOTE, "'"
	} else if currentChar == '`' {
		self.Position++
		return BACKQUOTE, "`"
	} else if currentChar == ',' && nextChar == '@' {
		self.Position += 2
		return COMMAAT, ",@"
	} else if currentChar == ',' {
		self.Position++
		return COMMA, ","
	} else if currentChar == '(' {
		self.Position++
		return LPAREN, "("
	} else if currentChar == ')' {
		self.Position++
		return RPAREN, ")"
	} else if currentChar == '[' {
		self.Position++
		return LBRACKET, "["
	} else if currentChar == ']' {
		self.Position++
		return RBRACKET, "]"
	} else if currentChar == '{' {
		self.Position++
		return LBRACE, "{"
	} else if currentChar == '}' {
		self.Position++
		return RBRACE, "}"
	} else if currentChar == '.' {
		self.Position++
		return PERIOD, "."
	} else if currentChar == '-' && nextChar == '>' {
		self.Position += 2
		return SYMBOL, "->"
	} else if currentChar == '=' && nextChar == '>' {
		self.Position += 2
		return SYMBOL, "=>"
	} else if currentChar == '+' {
		self.Position++
		return SYMBOL, "+"
	} else if currentChar == '-' {
		self.Position++
		return SYMBOL, "-"
	} else if currentChar == '*' {
		self.Position++
		return SYMBOL, "*"
	} else if currentChar == '/' {
		self.Position++
		return SYMBOL, "/"
	} else if currentChar == '%' {
		self.Position++
		return SYMBOL, "%"
	} else if currentChar == '<' && nextChar == '=' {
		self.Position += 2
		return SYMBOL, "<="
	} else if currentChar == '<' {
		self.Position++
		return SYMBOL, "<"
	} else if currentChar == '>' && nextChar == '=' {
		self.Position += 2
		return SYMBOL, ">="
	} else if currentChar == '>' {
		self.Position++
		return SYMBOL, ">"
	} else if currentChar == '=' && nextChar == '=' {
		self.Position += 2
		return SYMBOL, "=="
	} else if currentChar == '=' {
		self.Position++
		return SYMBOL, "="
	} else if currentChar == '!' && nextChar == '=' {
		self.Position += 2
		return SYMBOL, "!="
	} else if currentChar == '!' {
		self.Position++
		return SYMBOL, "!"
	} else if currentChar == '#' {
		self.Position += 2
		if nextChar == 't' {
			return TRUE, "#t"
		} else if nextChar == 'f' {
			return FALSE, "#f"
		} else if nextChar == 'x' {
			return self.readHexNumber()
		} else if nextChar == 'b' {
			return self.readBinaryNumber()
		} else {
			return ILLEGAL, fmt.Sprintf("#%c", nextChar)
		}
	} else if currentChar == ';' {
		start := self.Position
		for {
			if self.isEof() {
				return COMMENT, self.Source[start:]
			} else if self.Source[self.Position] == '\n' {
				return COMMENT, self.Source[start:self.Position]
			}
			self.Position++
		}
	} else {
		return ILLEGAL, fmt.Sprintf("%c", currentChar)
	}
}

func (self *Tokenizer) ConsumeToken() {
	self.LookaheadToken, self.LookaheadLit = self.readNextToken()
	if self.LookaheadToken == COMMENT { // skip comments
		self.ConsumeToken()
	}
}
<commit_msg>Make identifiers conform to GNU/MIT Scheme.  This greatly simplifies the tokenizer as well as allowing user defined operators.<commit_after>// Copyright 2014 SteelSeries ApS.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This package implements a basic LISP interpretor for embedding in a go program for scripting.
// This file implements the tokenizer.

package golisp

import (
	"fmt"
	"strings"
	"unicode"
)

const (
	ILLEGAL = iota
	SYMBOL
	NUMBER
	HEXNUMBER
	BINARYNUMBER
	FLOAT
	STRING
	QUOTE
	BACKQUOTE
	COMMA
	COMMAAT
	LPAREN
	RPAREN
	LBRACKET
	RBRACKET
	LBRACE
	RBRACE
	PERIOD
	TRUE
	FALSE
	COMMENT
	EOF
)

type Tokenizer struct {
	LookaheadToken int
	LookaheadLit   string
	Source         string
	Position       int
}

func NewTokenizer(src string) *Tokenizer {
	t := &Tokenizer{Source: src}
	t.ConsumeToken()
	return t
}

func (self *Tokenizer) NextToken() (token int, lit string) {
	return self.LookaheadToken, self.LookaheadLit
}

func (self *Tokenizer) isSymbolCharacter(ch rune) bool {
	return unicode.IsGraphic(ch) && !unicode.IsSpace(ch) && !strings.ContainsRune("();\"'`|[]{}#,", ch)
}

func (self *Tokenizer) readSymbol() (token int, lit string) {
	start := self.Position
	for !self.isEof() && self.isSymbolCharacter(rune(self.Source[self.Position])) {
		self.Position++
	}
	return SYMBOL, self.Source[start:self.Position]
}

func isHexChar(ch rune) bool {
	switch ch {
	case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
		return true
	case 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F':
		return true
	default:
		return false
	}
}

func isBinaryChar(ch rune) bool {
	switch ch {
	case '0', '1':
		return true
	default:
		return false
	}
}

func (self *Tokenizer) readHexNumber() (token int, lit string) {
	start := self.Position
	for !self.isEof() {
		ch := rune(self.Source[self.Position])
		if isHexChar(ch) {
			self.Position++
		} else {
			break
		}
	}

	lit = self.Source[start:self.Position]
	token = HEXNUMBER
	return
}

func (self *Tokenizer) readBinaryNumber() (token int, lit string) {
	start := self.Position
	for !self.isEof() {
		ch := rune(self.Source[self.Position])
		if isBinaryChar(ch) {
			self.Position++
		} else {
			break
		}
	}

	lit = self.Source[start:self.Position]
	token = BINARYNUMBER
	return
}

func (self *Tokenizer) readNumber() (token int, lit string) {
	start := self.Position
	isFloat := false
	sawDecimal := false
	for !self.isEof() {
		ch := rune(self.Source[self.Position])
		if ch == '.' && !sawDecimal {
			isFloat = true
			sawDecimal = true
			self.Position++
		} else if (start == self.Position) && ch == '-' {
			self.Position++
		} else if unicode.IsNumber(ch) {
			self.Position++
		} else {
			break
		}
	}

	lit = self.Source[start:self.Position]
	if isFloat {
		token = FLOAT
	} else {
		token = NUMBER
	}
	return
}

func (self *Tokenizer) readString() (token int, lit string) {
	buffer := make([]rune, 0, 10)
	self.Position++
	for !self.isEof() && rune(self.Source[self.Position]) != '"' {
		if rune(self.Source[self.Position]) == '\\' {
			self.Position++
		}
		buffer = append(buffer, rune(self.Source[self.Position]))
		self.Position++
	}
	if self.isEof() {
		return EOF, ""
	}
	self.Position++
	return STRING, string(buffer)
}

func (self *Tokenizer) isEof() bool {
	return self.Position >= len(self.Source)
}

func (self *Tokenizer) isAlmostEof() bool {
	return self.Position == len(self.Source)-1
}

func (self *Tokenizer) readNextToken() (token int, lit string) {
	if self.isEof() {
		return EOF, ""
	}
	for unicode.IsSpace(rune(self.Source[self.Position])) {
		self.Position++
		if self.isEof() {
			return EOF, ""
		}
	}
	currentChar := rune(self.Source[self.Position])
	var nextChar rune
	if !self.isAlmostEof() {
		nextChar = rune(self.Source[self.Position+1])
	}
	if currentChar == '0' && nextChar == 'x' {
		self.Position += 2
		return self.readHexNumber()
	} else if unicode.IsNumber(currentChar) {
		return self.readNumber()
	} else if currentChar == '-' && unicode.IsNumber(nextChar) {
		return self.readNumber()
	} else if currentChar == '"' {
		return self.readString()
	} else if currentChar == '\'' {
		self.Position++
		return QUOTE, "'"
	} else if currentChar == '`' {
		self.Position++
		return BACKQUOTE, "`"
	} else if currentChar == ',' && nextChar == '@' {
		self.Position += 2
		return COMMAAT, ",@"
	} else if currentChar == ',' {
		self.Position++
		return COMMA, ","
	} else if currentChar == '(' {
		self.Position++
		return LPAREN, "("
	} else if currentChar == ')' {
		self.Position++
		return RPAREN, ")"
	} else if currentChar == '[' {
		self.Position++
		return LBRACKET, "["
	} else if currentChar == ']' {
		self.Position++
		return RBRACKET, "]"
	} else if currentChar == '{' {
		self.Position++
		return LBRACE, "{"
	} else if currentChar == '}' {
		self.Position++
		return RBRACE, "}"
	} else if currentChar == '.' && nextChar == ' ' {
		self.Position++
		return PERIOD, "."
	} else if self.isSymbolCharacter(currentChar) {
		return self.readSymbol()
	} else if currentChar == '#' {
		self.Position += 2
		if nextChar == 't' {
			return TRUE, "#t"
		} else if nextChar == 'f' {
			return FALSE, "#f"
		} else if nextChar == 'x' {
			return self.readHexNumber()
		} else if nextChar == 'b' {
			return self.readBinaryNumber()
		} else {
			return ILLEGAL, fmt.Sprintf("#%c", nextChar)
		}
	} else if currentChar == ';' {
		start := self.Position
		for {
			if self.isEof() {
				return COMMENT, self.Source[start:]
			} else if self.Source[self.Position] == '\n' {
				return COMMENT, self.Source[start:self.Position]
			}
			self.Position++
		}
	} else {
		return ILLEGAL, fmt.Sprintf("%c", currentChar)
	}
}

func (self *Tokenizer) ConsumeToken() {
	self.LookaheadToken, self.LookaheadLit = self.readNextToken()
	if self.LookaheadToken == COMMENT { // skip comments
		self.ConsumeToken()
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 Martin Hebnes Pedersen (LA5NTA). All rights reserved.
// Use of this source code is governed by the MIT-license that can be
// found in the LICENSE file.

package wl2k

import (
	"bufio"
	"fmt"
	"net"
	"strings"
	"testing"
)

//[WL2K-2.8.4.8-B2FWIHJM$]
//Brentwood CMS >
//	;FW: LA5NTA
//	[RMS Express-1.2.35.0-B2FHM$]
//	; WL2K DE LA5NTA (JO39EQ)
//	FF
//FQ

func TestSessionP2P(t *testing.T) {
	client, master := net.Pipe()

	clientErr := make(chan error)
	go func() {
		s := NewSession("LA5NTA", "N0CALL", "JO39EQ", nil)
		clientErr <- s.Exchange(client)
	}()

	masterErr := make(chan error)
	go func() {
		s := NewSession("N0CALL", "LA5NTA", "JO39EQ", nil)
		s.IsMaster(true)
		masterErr <- s.Exchange(master)
	}()

	if err := <-masterErr; err != nil {
		t.Errorf("Master returned with error: %s", err)
	}
	if err := <-clientErr; err != nil {
		t.Errorf("Client returned with error: %s", err)
	}
}

func TestSessionCMS(t *testing.T) {
	client, srv := net.Pipe()

	cerrs := make(chan error)
	go func() {
		s := NewSession("LA5NTA", "LA1B-10", "JO39EQ", nil)
		cerrs <- s.Exchange(client)
	}()

	fmt.Fprint(srv, "[WL2K-2.8.4.8-B2FWIHJM$]\r")
	fmt.Fprint(srv, "Test CMS >\r")

	expectLines := []string{
		";FW: LA5NTA\r",
		"[wl2kgo-0.1a-B2FHM$]\r",
		"; LA1B-10 DE LA5NTA (JO39EQ)\r",
		"FF\r",
	}

	// Read until FF
	rd := bufio.NewReader(srv)
	for i, expected := range expectLines {
		line, _ := rd.ReadString('\r')
		if line != expected {
			line, expected = strings.TrimSpace(line), strings.TrimSpace(expected)
			t.Fatalf("Unexpected line [%d]: Got '%s', expected '%s'.", i, line, expected)
		}
	}

	fmt.Fprint(srv, "FQ\r")
	srv.Close()

	if err := <-cerrs; err != nil {
		t.Errorf("Session exchange returned error: %s")
	}
}

func TestSessionCMDWithMessage(t *testing.T) {
	client, srv := net.Pipe()

	cerrs := make(chan error)
	go func() {
		s := NewSession("LA5NTA", "LA1B-10", "JO39EQ", nil)
		cerrs <- s.Exchange(client)
	}()

	fmt.Fprint(srv, "[WL2K-2.8.4.8-B2FWIHJM$]\r")
	fmt.Fprint(srv, "Test CMS >\r")

	expectLines := []string{
		";FW: LA5NTA\r",
		"[wl2kgo-0.1a-B2FHM$]\r",
		"; LA1B-10 DE LA5NTA (JO39EQ)\r",
		"FF\r",
	}

	// Read until FF
	rd := bufio.NewReader(srv)
	for i, expected := range expectLines {
		line, _ := rd.ReadString('\r')
		if line != expected {
			line, expected = strings.TrimSpace(line), strings.TrimSpace(expected)
			t.Fatalf("Unexpected line [%d]: Got '%s', expected '%s'.", i, line, expected)
		}
	}

	// Send one proposal
	fmt.Fprintf(srv, "FC EM TJKYEIMMHSRB 527 123 0\r")
	fmt.Fprintf(srv, "F> 3b\r") // No more proposals + checksum

	propAnswer, _ := rd.ReadString('\r')
	if propAnswer != "FS =\r" {
		t.Errorf("Expected 'FS =', got '%s'", propAnswer)
	}
	fmt.Fprintf(srv, "FF\r") // No more messages

	if line, _ := rd.ReadString('\r'); line != "FQ\r" {
		t.Errorf("Expected 'FQ', got '%s'", line)
	}

	if err := <-cerrs; err != nil {
		t.Errorf("Session exchange returned error: %s")
	}
}
<commit_msg>wl2k: Fix tests after API change.<commit_after>// Copyright 2015 Martin Hebnes Pedersen (LA5NTA). All rights reserved.
// Use of this source code is governed by the MIT-license that can be
// found in the LICENSE file.

package wl2k

import (
	"bufio"
	"fmt"
	"net"
	"strings"
	"testing"
)

//[WL2K-2.8.4.8-B2FWIHJM$]
//Brentwood CMS >
//	;FW: LA5NTA
//	[RMS Express-1.2.35.0-B2FHM$]
//	; WL2K DE LA5NTA (JO39EQ)
//	FF
//FQ

func TestSessionP2P(t *testing.T) {
	client, master := net.Pipe()

	clientErr := make(chan error)
	go func() {
		s := NewSession("LA5NTA", "N0CALL", "JO39EQ", nil)
		_, err := s.Exchange(client)
		clientErr <- err
	}()

	masterErr := make(chan error)
	go func() {
		s := NewSession("N0CALL", "LA5NTA", "JO39EQ", nil)
		s.IsMaster(true)
		_, err := s.Exchange(master)
		masterErr <- err
	}()

	if err := <-masterErr; err != nil {
		t.Errorf("Master returned with error: %s", err)
	}
	if err := <-clientErr; err != nil {
		t.Errorf("Client returned with error: %s", err)
	}
}

func TestSessionCMS(t *testing.T) {
	client, srv := net.Pipe()

	cerrs := make(chan error)
	go func() {
		s := NewSession("LA5NTA", "LA1B-10", "JO39EQ", nil)
		_, err := s.Exchange(client)
		cerrs <- err
	}()

	fmt.Fprint(srv, "[WL2K-2.8.4.8-B2FWIHJM$]\r")
	fmt.Fprint(srv, "Test CMS >\r")

	expectLines := []string{
		";FW: LA5NTA\r",
		"[wl2kgo-0.1a-B2FHM$]\r",
		"; LA1B-10 DE LA5NTA (JO39EQ)\r",
		"FF\r",
	}

	// Read until FF
	rd := bufio.NewReader(srv)
	for i, expected := range expectLines {
		line, _ := rd.ReadString('\r')
		if line != expected {
			line, expected = strings.TrimSpace(line), strings.TrimSpace(expected)
			t.Fatalf("Unexpected line [%d]: Got '%s', expected '%s'.", i, line, expected)
		}
	}

	fmt.Fprint(srv, "FQ\r")
	srv.Close()

	if err := <-cerrs; err != nil {
		t.Errorf("Session exchange returned error: %s")
	}
}

func TestSessionCMDWithMessage(t *testing.T) {
	client, srv := net.Pipe()

	cerrs := make(chan error)
	go func() {
		s := NewSession("LA5NTA", "LA1B-10", "JO39EQ", nil)
		_, err := s.Exchange(client)
		cerrs <- err
	}()

	fmt.Fprint(srv, "[WL2K-2.8.4.8-B2FWIHJM$]\r")
	fmt.Fprint(srv, "Test CMS >\r")

	expectLines := []string{
		";FW: LA5NTA\r",
		"[wl2kgo-0.1a-B2FHM$]\r",
		"; LA1B-10 DE LA5NTA (JO39EQ)\r",
		"FF\r",
	}

	// Read until FF
	rd := bufio.NewReader(srv)
	for i, expected := range expectLines {
		line, _ := rd.ReadString('\r')
		if line != expected {
			line, expected = strings.TrimSpace(line), strings.TrimSpace(expected)
			t.Fatalf("Unexpected line [%d]: Got '%s', expected '%s'.", i, line, expected)
		}
	}

	// Send one proposal
	fmt.Fprintf(srv, "FC EM TJKYEIMMHSRB 527 123 0\r")
	fmt.Fprintf(srv, "F> 3b\r") // No more proposals + checksum

	propAnswer, _ := rd.ReadString('\r')
	if propAnswer != "FS =\r" {
		t.Errorf("Expected 'FS =', got '%s'", propAnswer)
	}
	fmt.Fprintf(srv, "FF\r") // No more messages

	if line, _ := rd.ReadString('\r'); line != "FQ\r" {
		t.Errorf("Expected 'FQ', got '%s'", line)
	}

	if err := <-cerrs; err != nil {
		t.Errorf("Session exchange returned error: %s")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"cred-alert/inflator"
	"cred-alert/kolsch"
	"cred-alert/mimetype"
	"cred-alert/scanners"
	"cred-alert/scanners/diffscanner"
	"cred-alert/scanners/dirscanner"
	"cred-alert/scanners/filescanner"
	"cred-alert/sniff"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
	"time"

	"code.cloudfoundry.org/lager"

	"github.com/jessevdk/go-flags"
	"github.com/mgutz/ansi"
)

type Opts struct {
	File string `short:"f" long:"file" description:"the file to scan" value-name:"FILE"`
	Diff bool   `long:"diff" description:"content to be scanned is a git diff"`
}

var red = ansi.ColorFunc("red+b")
var green = ansi.ColorFunc("green+b")

func main() {
	var opts Opts

	_, err := flags.ParseArgs(&opts, os.Args)
	if err != nil {
		os.Exit(1)
	}

	logger := kolsch.NewLogger()
	sniffer := sniff.NewDefaultSniffer()
	inflate := inflator.New()
	defer inflate.Close()

	var credsFound int
	handler := func(logger lager.Logger, line scanners.Line) error {
		credsFound++
		fmt.Printf("%s %s:%d\n", red("[CRED]"), line.Path, line.LineNumber)

		return nil
	}

	if opts.File != "" {
		fh, err := os.Open(opts.File)
		if err != nil {
			log.Fatalln(err.Error())
		}

		br := bufio.NewReader(fh)
		mime, isArchive := mimetype.IsArchive(logger, br)
		if isArchive {
			inflateDir, err := ioutil.TempDir("", "cred-alert-cli")
			if err != nil {
				log.Fatalln(err.Error())
			}
			defer os.RemoveAll(inflateDir)

			violationsDir, err := ioutil.TempDir("", "cred-alert-cli-violations")
			if err != nil {
				log.Fatalln(err.Error())
			}

			archiveViolationHandler := func(logger lager.Logger, line scanners.Line) error {
				credsFound++
				relPath, err := filepath.Rel(inflateDir, line.Path)
				if err != nil {
					return err
				}

				destPath := filepath.Join(violationsDir, relPath)
				err = os.MkdirAll(filepath.Dir(destPath), os.ModePerm)
				if err != nil {
					return err
				}

				err = persistFile(line.Path, destPath)
				if err != nil {
					return err
				}

				fmt.Printf("%s %s:%d\n", red("[CRED]"), destPath, line.LineNumber)

				return nil
			}

			inflateStart := time.Now()
			fmt.Printf("Inflating archive into %s\n", inflateDir)
			err = inflate.Inflate(logger, opts.File, inflateDir)
			if err != nil {
				fmt.Printf("%s\n", red("FAILED"))
				log.Fatalln(err.Error())
			}
			fmt.Printf("%s (%s)\n", green("DONE"), time.Since(inflateStart))

			scanStart := time.Now()
			dirScanner := dirscanner.New(archiveViolationHandler, sniffer)
			err = dirScanner.Scan(logger, inflateDir)
			if err != nil {
				log.Fatalln(err.Error())
			}

			fmt.Println()
			fmt.Println("Scan complete!")
			fmt.Println()
			fmt.Println("Time taken:", time.Since(scanStart))
			fmt.Println("Credentials found:", credsFound)
			fmt.Println()
			fmt.Println("Any archive inflation errors can be found in: ", inflate.LogPath())
		} else {
			if strings.HasPrefix(mime, "text") {
				scanFile(logger, handler, sniffer, br, opts.File)
			}
		}
	} else if opts.Diff {
		handleDiff(logger, handler, opts)

	} else {
		scanFile(logger, handler, sniffer, os.Stdin, "STDIN")
	}

	if credsFound > 0 {
		os.Exit(3)
	}
}

func persistFile(srcPath, destPath string) error {
	destFile, err := os.Create(destPath)
	if err != nil {
		return err
	}
	defer destFile.Close()

	srcFile, err := os.Open(srcPath)
	if err != nil {
		return err
	}
	defer srcFile.Close()

	_, err = io.Copy(destFile, srcFile)
	return err
}

func scanFile(
	logger lager.Logger,
	handler sniff.ViolationHandlerFunc,
	sniffer sniff.Sniffer,
	f io.Reader,
	name string,
) {
	scanner := filescanner.New(f, name)
	sniffer.Sniff(logger, scanner, handler)
}

func handleDiff(logger lager.Logger, handler sniff.ViolationHandlerFunc, opts Opts) {
	logger.Session("handle-diff")
	scanner := diffscanner.NewDiffScanner(os.Stdin)
	sniffer := sniff.NewDefaultSniffer()

	sniffer.Sniff(logger, scanner, handler)
}
<commit_msg>Do not show inflating dir<commit_after>package main

import (
	"bufio"
	"cred-alert/inflator"
	"cred-alert/kolsch"
	"cred-alert/mimetype"
	"cred-alert/scanners"
	"cred-alert/scanners/diffscanner"
	"cred-alert/scanners/dirscanner"
	"cred-alert/scanners/filescanner"
	"cred-alert/sniff"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
	"time"

	"code.cloudfoundry.org/lager"

	"github.com/jessevdk/go-flags"
	"github.com/mgutz/ansi"
)

type Opts struct {
	File string `short:"f" long:"file" description:"the file to scan" value-name:"FILE"`
	Diff bool   `long:"diff" description:"content to be scanned is a git diff"`
}

var red = ansi.ColorFunc("red+b")
var green = ansi.ColorFunc("green+b")

func main() {
	var opts Opts

	_, err := flags.ParseArgs(&opts, os.Args)
	if err != nil {
		os.Exit(1)
	}

	logger := kolsch.NewLogger()
	sniffer := sniff.NewDefaultSniffer()
	inflate := inflator.New()
	defer inflate.Close()

	var credsFound int
	handler := func(logger lager.Logger, line scanners.Line) error {
		credsFound++
		fmt.Printf("%s %s:%d\n", red("[CRED]"), line.Path, line.LineNumber)

		return nil
	}

	if opts.File != "" {
		fh, err := os.Open(opts.File)
		if err != nil {
			log.Fatalln(err.Error())
		}

		br := bufio.NewReader(fh)
		mime, isArchive := mimetype.IsArchive(logger, br)
		if isArchive {
			inflateDir, err := ioutil.TempDir("", "cred-alert-cli")
			if err != nil {
				log.Fatalln(err.Error())
			}
			defer os.RemoveAll(inflateDir)

			violationsDir, err := ioutil.TempDir("", "cred-alert-cli-violations")
			if err != nil {
				log.Fatalln(err.Error())
			}

			archiveViolationHandler := func(logger lager.Logger, line scanners.Line) error {
				credsFound++
				relPath, err := filepath.Rel(inflateDir, line.Path)
				if err != nil {
					return err
				}

				destPath := filepath.Join(violationsDir, relPath)
				err = os.MkdirAll(filepath.Dir(destPath), os.ModePerm)
				if err != nil {
					return err
				}

				err = persistFile(line.Path, destPath)
				if err != nil {
					return err
				}

				fmt.Printf("%s %s:%d\n", red("[CRED]"), destPath, line.LineNumber)

				return nil
			}

			inflateStart := time.Now()
			fmt.Printf("Inflating archive... ")
			err = inflate.Inflate(logger, opts.File, inflateDir)
			if err != nil {
				fmt.Printf("%s\n", red("FAILED"))
				log.Fatalln(err.Error())
			}
			fmt.Printf("%s (%s)\n", green("DONE"), time.Since(inflateStart))

			scanStart := time.Now()
			dirScanner := dirscanner.New(archiveViolationHandler, sniffer)
			err = dirScanner.Scan(logger, inflateDir)
			if err != nil {
				log.Fatalln(err.Error())
			}

			fmt.Println()
			fmt.Println("Scan complete!")
			fmt.Println()
			fmt.Println("Time taken:", time.Since(scanStart))
			fmt.Println("Credentials found:", credsFound)
			fmt.Println()
			fmt.Println("Any archive inflation errors can be found in: ", inflate.LogPath())
		} else {
			if strings.HasPrefix(mime, "text") {
				scanFile(logger, handler, sniffer, br, opts.File)
			}
		}
	} else if opts.Diff {
		handleDiff(logger, handler, opts)

	} else {
		scanFile(logger, handler, sniffer, os.Stdin, "STDIN")
	}

	if credsFound > 0 {
		os.Exit(3)
	}
}

func persistFile(srcPath, destPath string) error {
	destFile, err := os.Create(destPath)
	if err != nil {
		return err
	}
	defer destFile.Close()

	srcFile, err := os.Open(srcPath)
	if err != nil {
		return err
	}
	defer srcFile.Close()

	_, err = io.Copy(destFile, srcFile)
	return err
}

func scanFile(
	logger lager.Logger,
	handler sniff.ViolationHandlerFunc,
	sniffer sniff.Sniffer,
	f io.Reader,
	name string,
) {
	scanner := filescanner.New(f, name)
	sniffer.Sniff(logger, scanner, handler)
}

func handleDiff(logger lager.Logger, handler sniff.ViolationHandlerFunc, opts Opts) {
	logger.Session("handle-diff")
	scanner := diffscanner.NewDiffScanner(os.Stdin)
	sniffer := sniff.NewDefaultSniffer()

	sniffer.Sniff(logger, scanner, handler)
}
<|endoftext|>