<commit_before>package hashids

import (
	"math"
	"reflect"
	"testing"
)

func TestEncodeDecode(t *testing.T) {
	hdata := NewData()
	hdata.MinLength = 30
	hdata.Salt = "this is my salt"

	hid, _ := NewWithData(hdata)

	numbers := []int{45, 434, 1313, 99}
	hash, err := hid.Encode(numbers)
	if err != nil {
		t.Fatal(err)
	}
	dec := hid.Decode(hash)

	t.Logf("%v -> %v -> %v", numbers, hash, dec)

	if !reflect.DeepEqual(dec, numbers) {
		t.Errorf("Decoded numbers `%v` did not match with original `%v`", dec, numbers)
	}
}

func TestEncodeDecodeInt64(t *testing.T) {
	hdata := NewData()
	hdata.MinLength = 30
	hdata.Salt = "this is my salt"

	hid, _ := NewWithData(hdata)

	numbers := []int64{45, 434, 1313, 99, math.MaxInt64}
	hash, err := hid.EncodeInt64(numbers)
	if err != nil {
		t.Fatal(err)
	}
	dec := hid.DecodeInt64(hash)

	t.Logf("%v -> %v -> %v", numbers, hash, dec)

	if !reflect.DeepEqual(dec, numbers) {
		t.Errorf("Decoded numbers `%v` did not match with original `%v`", dec, numbers)
	}
}

func TestEncodeWithKnownHash(t *testing.T) {
	hdata := NewData()
	hdata.MinLength = 0
	hdata.Salt = "this is my salt"

	hid, _ := NewWithData(hdata)

	numbers := []int{45, 434, 1313, 99}
	hash, err := hid.Encode(numbers)
	if err != nil {
		t.Fatal(err)
	}

	t.Logf("%v -> %v", numbers, hash)

	if hash != "7nnhzEsDkiYa" {
		t.Error("hash does not match expected one")
	}
}

func TestDecodeWithKnownHash(t *testing.T) {
	hdata := NewData()
	hdata.MinLength = 0
	hdata.Salt = "this is my salt"

	hid, _ := NewWithData(hdata)

	hash := "7nnhzEsDkiYa"
	numbers := hid.Decode(hash)

	t.Logf("%v -> %v", hash, numbers)

	expected := []int{45, 434, 1313, 99}
	if !reflect.DeepEqual(numbers, expected) {
		t.Errorf("Decoded numbers `%v` did not match with expected `%v`", numbers, expected)
	}
}

func TestDefaultLength(t *testing.T) {
	hdata := NewData()
	hdata.Salt = "this is my salt"

	hid, _ := NewWithData(hdata)

	numbers := []int{45, 434, 1313, 99}
	hash, err := hid.Encode(numbers)
	if err != nil {
		t.Fatal(err)
	}
	dec := hid.Decode(hash)

	t.Logf("%v -> %v -> %v", numbers, hash, dec)

	if !reflect.DeepEqual(dec, numbers) {
		t.Errorf("Decoded numbers `%v` did not match with original `%v`", dec, numbers)
	}
}

func TestMinLength(t *testing.T) {
	hdata := NewData()
	hdata.Salt = "salt1"
	hdata.MinLength = 10
	hid, _ := NewWithData(hdata)
	hid.Encode([]int{0})
}

func TestCustomAlphabet(t *testing.T) {
	hdata := NewData()
	hdata.Alphabet = "PleasAkMEFoThStx"
	hdata.Salt = "this is my salt"

	hid, _ := NewWithData(hdata)

	numbers := []int{45, 434, 1313, 99}
	hash, err := hid.Encode(numbers)
	if err != nil {
		t.Fatal(err)
	}
	dec := hid.Decode(hash)

	t.Logf("%v -> %v -> %v", numbers, hash, dec)

	if !reflect.DeepEqual(dec, numbers) {
		t.Errorf("Decoded numbers `%v` did not match with original `%v`", dec, numbers)
	}
}

func TestDecodeWithError(t *testing.T) {
	hdata := NewData()
	hdata.Alphabet = "PleasAkMEFoThStx"
	hdata.Salt = "this is my salt"

	hid, _ := NewWithData(hdata)
	// hash now contains a letter not in the alphabet
	dec, err := hid.DecodeWithError("MAkhkloFAxAoskaZ")

	if dec != nil {
		t.Error("Expected `nil` but got `%v`", dec)
	}
	expected := "alphabet used for hash was different"
	if err == nil || err.Error() != expected {
		t.Errorf("Expected error `%s` but got `%s`", expected, err)
	}
}

// tests issue #28
func TestDecodeWithWrongSalt(t *testing.T) {
	hdata := NewData()
	hdata.Alphabet = "PleasAkMEFoThStx"
	hdata.Salt = "temp"

	hidEncode, _ := NewWithData(hdata)

	numbers := []int{45, 434, 1313, 99}
	hash, _ := hidEncode.Encode(numbers)

	hdata.Salt = "test"
	hidDecode, _ := NewWithData(hdata)
	dec, err := hidDecode.DecodeWithError(hash)

	t.Logf("%v -> %v -> %v", numbers, hash, dec)

	expected := "mismatch between encode and decode"
	if err == nil || err.Error() != expected {
		t.Errorf("Expected error `%s` but got `%s`", expected, err)
	}
}
<commit_msg>Add a test for allocations per encoding<commit_after>package hashids

import (
	"math"
	"reflect"
	"testing"
)

func TestEncodeDecode(t *testing.T) {
	hdata := NewData()
	hdata.MinLength = 30
	hdata.Salt = "this is my salt"

	hid, _ := NewWithData(hdata)

	numbers := []int{45, 434, 1313, 99}
	hash, err := hid.Encode(numbers)
	if err != nil {
		t.Fatal(err)
	}
	dec := hid.Decode(hash)

	t.Logf("%v -> %v -> %v", numbers, hash, dec)

	if !reflect.DeepEqual(dec, numbers) {
		t.Errorf("Decoded numbers `%v` did not match with original `%v`", dec, numbers)
	}
}

func TestEncodeDecodeInt64(t *testing.T) {
	hdata := NewData()
	hdata.MinLength = 30
	hdata.Salt = "this is my salt"

	hid, _ := NewWithData(hdata)

	numbers := []int64{45, 434, 1313, 99, math.MaxInt64}
	hash, err := hid.EncodeInt64(numbers)
	if err != nil {
		t.Fatal(err)
	}
	dec := hid.DecodeInt64(hash)

	t.Logf("%v -> %v -> %v", numbers, hash, dec)

	if !reflect.DeepEqual(dec, numbers) {
		t.Errorf("Decoded numbers `%v` did not match with original `%v`", dec, numbers)
	}
}

func TestEncodeWithKnownHash(t *testing.T) {
	hdata := NewData()
	hdata.MinLength = 0
	hdata.Salt = "this is my salt"

	hid, _ := NewWithData(hdata)

	numbers := []int{45, 434, 1313, 99}
	hash, err := hid.Encode(numbers)
	if err != nil {
		t.Fatal(err)
	}

	t.Logf("%v -> %v", numbers, hash)

	if hash != "7nnhzEsDkiYa" {
		t.Error("hash does not match expected one")
	}
}

func TestDecodeWithKnownHash(t *testing.T) {
	hdata := NewData()
	hdata.MinLength = 0
	hdata.Salt = "this is my salt"

	hid, _ := NewWithData(hdata)

	hash := "7nnhzEsDkiYa"
	numbers := hid.Decode(hash)

	t.Logf("%v -> %v", hash, numbers)

	expected := []int{45, 434, 1313, 99}
	if !reflect.DeepEqual(numbers, expected) {
		t.Errorf("Decoded numbers `%v` did not match with expected `%v`", numbers, expected)
	}
}

func TestDefaultLength(t *testing.T) {
	hdata := NewData()
	hdata.Salt = "this is my salt"

	hid, _ := NewWithData(hdata)

	numbers := []int{45, 434, 1313, 99}
	hash, err := hid.Encode(numbers)
	if err != nil {
		t.Fatal(err)
	}
	dec := hid.Decode(hash)

	t.Logf("%v -> %v -> %v", numbers, hash, dec)

	if !reflect.DeepEqual(dec, numbers) {
		t.Errorf("Decoded numbers `%v` did not match with original `%v`", dec, numbers)
	}
}

func TestMinLength(t *testing.T) {
	hdata := NewData()
	hdata.Salt = "salt1"
	hdata.MinLength = 10
	hid, _ := NewWithData(hdata)
	hid.Encode([]int{0})
}

func TestCustomAlphabet(t *testing.T) {
	hdata := NewData()
	hdata.Alphabet = "PleasAkMEFoThStx"
	hdata.Salt = "this is my salt"

	hid, _ := NewWithData(hdata)

	numbers := []int{45, 434, 1313, 99}
	hash, err := hid.Encode(numbers)
	if err != nil {
		t.Fatal(err)
	}
	dec := hid.Decode(hash)

	t.Logf("%v -> %v -> %v", numbers, hash, dec)

	if !reflect.DeepEqual(dec, numbers) {
		t.Errorf("Decoded numbers `%v` did not match with original `%v`", dec, numbers)
	}
}

func TestDecodeWithError(t *testing.T) {
	hdata := NewData()
	hdata.Alphabet = "PleasAkMEFoThStx"
	hdata.Salt = "this is my salt"

	hid, _ := NewWithData(hdata)
	// hash now contains a letter not in the alphabet
	dec, err := hid.DecodeWithError("MAkhkloFAxAoskaZ")

	if dec != nil {
		t.Error("Expected `nil` but got `%v`", dec)
	}
	expected := "alphabet used for hash was different"
	if err == nil || err.Error() != expected {
		t.Errorf("Expected error `%s` but got `%s`", expected, err)
	}
}

// tests issue #28
func TestDecodeWithWrongSalt(t *testing.T) {
	hdata := NewData()
	hdata.Alphabet = "PleasAkMEFoThStx"
	hdata.Salt = "temp"

	hidEncode, _ := NewWithData(hdata)

	numbers := []int{45, 434, 1313, 99}
	hash, _ := hidEncode.Encode(numbers)

	hdata.Salt = "test"
	hidDecode, _ := NewWithData(hdata)
	dec, err := hidDecode.DecodeWithError(hash)

	t.Logf("%v -> %v -> %v", numbers, hash, dec)

	expected := "mismatch between encode and decode"
	if err == nil || err.Error() != expected {
		t.Errorf("Expected error `%s` but got `%s`", expected, err)
	}
}

func TestAllocationsPerEncode(t *testing.T) {
	hdata := NewData()
	hdata.Salt = "temp"
	hdata.MinLength = 0
	hid, _ := NewWithData(hdata)

	numbers := []int64{math.MaxInt64, 0, 1024, math.MaxInt64 / 2}
	allocsPerRun := testing.AllocsPerRun(100, func() {
		_, err := hid.EncodeInt64(numbers)
		if err != nil {
			t.Errorf("Unexpected error encoding test data: %s, %v", err, numbers)
		}
	})
	if allocsPerRun != 31 {
		t.Errorf("Expected 31 allocations, got %v ", allocsPerRun)
	}
}
<|endoftext|>


<commit_before>package ghost

import (
	"fmt"
	"io/ioutil"
	"math/rand"
	"strings"
	"testing"
	"time"
)

const MAXSIZE = 82

var (
	empty     *hashMap
	one       *hashMap
	several   *hashMap
	many      *hashMap
	wordsHash *hashMap
	nativeMap map[string]string
	words     []string
	result    string
)

func init() {
	empty = NewHashMap()
	one = NewHashMap()
	several = NewHashMap()
	many = NewHashMap()
	wordsHash = NewHashMap()

	one.Set("One", "one")

	several.Set("One", "one")
	several.Set("Two", "two")

	for i := 0; i < MAXSIZE; i++ {
		many.Set(fmt.Sprintf("%d", i), fmt.Sprintf("%d", i))
	}

	raw, err := ioutil.ReadFile("/usr/share/dict/cracklib-small")

	if err == nil {
		data := string(raw)
		words = strings.Split(data, "\n")
	}

	for _, w := range words {
		wordsHash.Set(string(w), string(w))
	}

	nativeMap = make(map[string]string)

	for _, w := range words {
		nativeMap[string(w)] = string(w)
	}
}

func TestHashGet(t *testing.T) {
	if i, _ := one.Get("One"); i != "one" {
		t.Errorf("One hash Get failed")
	}

	first, _ := several.Get("One")
	second, _ := several.Get("Two")
	if first != "one" || second != "two" {
		t.Errorf("Several hash Get failed")
	}

	for i := 0; i < MAXSIZE; i++ {
		if j, _ := many.Get(fmt.Sprintf("%d", i)); fmt.Sprintf("%d", i) != j {
			t.Errorf("Many hash Get failed. Expected: %d, Got: %d", i, j)
		}
	}
}

func TestHashGetNotInTable(t *testing.T) {
	if _, err := empty.Get("One"); err == nil {
		t.Errorf("Wrong behavior")
	}

	if _, err := one.Get("Two"); err == nil {
		t.Errorf("Wrong behavior")
	}

	if _, err := several.Get("three"); err == nil {
		t.Errorf("Wrong behavior")
	}
}

func TestHashSetChangeValue(t *testing.T) {
	one.Set("One", "ten")

	if val, _ := one.Get("One"); val != "ten" {
		t.Errorf("Wrong update behavior")
	}

	several.Set("Two", "ten")

	if val, _ := several.Get("Two"); val != "ten" {
		t.Errorf("Wrong update behavior")
	}
}

func TestHashSetValue(t *testing.T) {
	one.Set("Two", "ten")

	if val, _ := one.Get("Two"); val != "ten" {
		t.Errorf("Wrong update behavior")
	}

	several.Set("Ten", "ten")

	if val, _ := several.Get("Ten"); val != "ten" {
		t.Errorf("Wrong update behavior")
	}
}

func TestHashDelete(t *testing.T) {
	one.Del("One")

	if res, err := one.Get("One"); err == nil {
		t.Errorf("Wrong delete behavior. Got: %s", res)
	}

	several.Del("Two")

	if _, err := several.Get("Two"); err == nil {
		t.Errorf("Wrong delete behavior")
	}
}

func BenchmarkSet(b *testing.B) {
	h := NewHashMap()

	for i := 0; i < b.N; i++ {
		for _, w := range words {
			h.Set(string(w), string(w))
		}
	}
}

func BenchmarkGet(b *testing.B) {
	for i := 0; i < b.N; i++ {
		for _, w := range words {
			wordsHash.Get(string(w))
		}
	}
}

func BenchmarkDel(b *testing.B) {
	for i := 0; i < b.N; i++ {
		for _, w := range words {
			wordsHash.Del(string(w))
		}
	}
}

func BenchmarkMixed(b *testing.B) {
	r := rand.New(rand.NewSource(time.Now().UnixNano()))

	for i := 0; i < b.N; i++ {
		for j := 0; j < 10000; j++ {
			op := r.Intn(100)

			switch {
			case op <= 75:
				wordsHash.Get(words[r.Intn(2500)])
			case op <= 90:
				wordsHash.Set(words[r.Intn(2500)], words[r.Intn(2500)])
			default:
				wordsHash.Del(words[r.Intn(2500)])
			}
		}
	}
}

func BenchmarkNativeSet(b *testing.B) {
	h := make(map[string]string)

	for i := 0; i < b.N; i++ {
		for _, w := range words {
			h[string(w)] = string(w)
		}
	}
}

func BenchmarkNativeGet(b *testing.B) {
	var r string

	for i := 0; i < b.N; i++ {
		for _, w := range words {
			r = nativeMap[string(w)]
		}
	}

	result = r
}

func BenchmarkNativeDel(b *testing.B) {
	for i := 0; i < b.N; i++ {
		for _, w := range words {
			delete(nativeMap, string(w))
		}
	}
}

func BenchmarkNativeMixed(b *testing.B) {
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	var res string

	for i := 0; i < b.N; i++ {
		for j := 0; j < 10000; j++ {
			op := r.Intn(100)

			switch {
			case op < 75:
				res = nativeMap[words[r.Intn(2500)]]
			case op < 90:
				nativeMap[words[r.Intn(2500)]] = words[r.Intn(2500)]
			default:
				delete(nativeMap, words[r.Intn(2500)])
			}
		}
	}

	result = res
}
<commit_msg>Improve benchmarks<commit_after>package ghost

import (
	"fmt"
	"testing"
)

const MAXSIZE = 82

var (
	empty   *hashMap
	one     *hashMap
	several *hashMap
	many    *hashMap
	result  string
)

func init() {
	empty = NewHashMap()
	one = NewHashMap()
	several = NewHashMap()
	many = NewHashMap()

	one.Set("One", "one")

	several.Set("One", "one")
	several.Set("Two", "two")

	for i := 0; i < MAXSIZE; i++ {
		many.Set(fmt.Sprintf("%d", i), fmt.Sprintf("%d", i))
	}
}

func TestHashGet(t *testing.T) {
	if i, _ := one.Get("One"); i != "one" {
		t.Errorf("One hash Get failed")
	}

	first, _ := several.Get("One")
	second, _ := several.Get("Two")
	if first != "one" || second != "two" {
		t.Errorf("Several hash Get failed")
	}

	for i := 0; i < MAXSIZE; i++ {
		if j, _ := many.Get(fmt.Sprintf("%d", i)); fmt.Sprintf("%d", i) != j {
			t.Errorf("Many hash Get failed. Expected: %d, Got: %d", i, j)
		}
	}
}

func TestHashGetNotInTable(t *testing.T) {
	if _, err := empty.Get("One"); err == nil {
		t.Errorf("Wrong behavior")
	}

	if _, err := one.Get("Two"); err == nil {
		t.Errorf("Wrong behavior")
	}

	if _, err := several.Get("three"); err == nil {
		t.Errorf("Wrong behavior")
	}
}

func TestHashSetChangeValue(t *testing.T) {
	one.Set("One", "ten")

	if val, _ := one.Get("One"); val != "ten" {
		t.Errorf("Wrong update behavior")
	}

	several.Set("Two", "ten")

	if val, _ := several.Get("Two"); val != "ten" {
		t.Errorf("Wrong update behavior")
	}
}

func TestHashSetValue(t *testing.T) {
	one.Set("Two", "ten")

	if val, _ := one.Get("Two"); val != "ten" {
		t.Errorf("Wrong update behavior")
	}

	several.Set("Ten", "ten")

	if val, _ := several.Get("Ten"); val != "ten" {
		t.Errorf("Wrong update behavior")
	}
}

func TestHashDelete(t *testing.T) {
	one.Del("One")

	if res, err := one.Get("One"); err == nil {
		t.Errorf("Wrong delete behavior. Got: %s", res)
	}

	several.Del("Two")

	if _, err := several.Get("Two"); err == nil {
		t.Errorf("Wrong delete behavior")
	}
}

func BenchmarkSet(b *testing.B) {
	b.StopTimer()
	h := NewHashMap()
	b.StartTimer()

	for i := 0; i < b.N; i++ {
		h.Set(string(i), "Yarrr")
	}
}

func BenchmarkGet(b *testing.B) {
	b.StopTimer()
	h := NewHashMap()

	for i := 0; i < b.N; i++ {
		h.Set(string(i), "Yarrr")
	}

	b.StartTimer()

	for i := 0; i < b.N; i++ {
		h.Get(string(i))
	}
}

func BenchmarkDel(b *testing.B) {
	b.StopTimer()
	h := NewHashMap()

	for i := 0; i < b.N; i++ {
		h.Set(string(i), "Yarrr")
	}

	b.StartTimer()

	for i := 0; i < b.N; i++ {
		h.Del(string(i))
	}
}

func BenchmarkNativeSet(b *testing.B) {
	b.StopTimer()
	h := make(map[string]string)
	b.StartTimer()

	for i := 0; i < b.N; i++ {
		h[string(i)] = "Yarrr"
	}
}

func BenchmarkNativeGet(b *testing.B) {
	b.StopTimer()
	var r string
	h := make(map[string]string)

	for i := 0; i < b.N; i++ {
		h[string(i)] = "Yarrr"
	}

	b.StartTimer()

	for i := 0; i < b.N; i++ {
		r = h[string(i)]
	}

	result = r
}

func BenchmarkNativeDel(b *testing.B) {
	b.StopTimer()
	h := make(map[string]string)

	for i := 0; i < b.N; i++ {
		h[string(i)] = "Yarrr"
	}

	b.StartTimer()

	for i := 0; i < b.N; i++ {
		delete(h, string(i))
	}
}
<|endoftext|>


<commit_before>/*
* Copyright (c) 2013 Santiago Arias | Remy Jourde | Carlos Bernal
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

package helpers

import (
	"encoding/json"
)

type JsonResponse map[string]interface{}

// converts a json response to json string by marshaling it
func (r JsonResponse) String() (s string) {
	b, err := json.Marshal(r)
	if err != nil {
			s = ""
			return
	}
	s = string(b)
	return
}
<commit_msg>remove unused json.go file<commit_after><|endoftext|>


<commit_before>package xlsx

import (
	"fmt"
	"os"
	"testing"
)

// Test we can correctly open a XSLX file and return a xlsx.File
// struct.
func TestOpenFile(t *testing.T) {
	var xlsxFile *File
	var error os.Error
	xlsxFile, error = OpenFile("testfile.xlsx")
	if error != nil {
		t.Error(error.String())
		return
	}
	if xlsxFile == nil {
		t.Error("OpenFile returned nil FileInterface without generating an os.Error")
		return
	}

}

// Test that when we open a real XLSX file we create xlsx.Sheet
// objects for the sheets inside the file and that these sheets are
// themselves correct.
func TestCreateSheet(t *testing.T) {
	var xlsxFile *File
	var error os.Error
	var sheet *Sheet
	xlsxFile, error = OpenFile("testfile.xlsx")
	if error != nil {
		t.Error(error.String())
		return
	}
	if xlsxFile == nil {
		t.Error("OpenFile returned a nil File pointer but did not generate an error.")
		return
	}
	if len(xlsxFile.Sheets) == 0 {
		t.Error("Expected len(xlsxFile.Sheets) > 0")
		return
	}
	sheet = xlsxFile.Sheets[0]
	if len(sheet.Cells) == 0 {
		t.Error("Expected len(sheet.Cells) == 4")
	}
}

<commit_msg>* lib_test.go: Removed unused import<commit_after>package xlsx

import (
	"os"
	"testing"
)

// Test we can correctly open a XSLX file and return a xlsx.File
// struct.
func TestOpenFile(t *testing.T) {
	var xlsxFile *File
	var error os.Error
	xlsxFile, error = OpenFile("testfile.xlsx")
	if error != nil {
		t.Error(error.String())
		return
	}
	if xlsxFile == nil {
		t.Error("OpenFile returned nil FileInterface without generating an os.Error")
		return
	}

}

// Test that when we open a real XLSX file we create xlsx.Sheet
// objects for the sheets inside the file and that these sheets are
// themselves correct.
func TestCreateSheet(t *testing.T) {
	var xlsxFile *File
	var error os.Error
	var sheet *Sheet
	xlsxFile, error = OpenFile("testfile.xlsx")
	if error != nil {
		t.Error(error.String())
		return
	}
	if xlsxFile == nil {
		t.Error("OpenFile returned a nil File pointer but did not generate an error.")
		return
	}
	if len(xlsxFile.Sheets) == 0 {
		t.Error("Expected len(xlsxFile.Sheets) > 0")
		return
	}
	sheet = xlsxFile.Sheets[0]
	if len(sheet.Cells) == 0 {
		t.Error("Expected len(sheet.Cells) == 4")
	}
}

<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"time"

	"net/url"

	"code.cloudfoundry.org/cli/cf/api/resources"
	"code.cloudfoundry.org/cli/cf/configuration/coreconfig"
	"code.cloudfoundry.org/cli/cf/models"
	"code.cloudfoundry.org/cli/cf/net"
)

type EventRepo struct {
	config  coreconfig.Reader
	gateway net.Gateway
}

func NewEventRepo(config coreconfig.Repository, gateway net.Gateway) (repo EventRepo) {
	repo.config = config
	repo.gateway = gateway
	return
}

func (r EventRepo) GetAppEvents(app models.Application, since time.Time, callback func(models.EventFields) bool) error {
	return r.gateway.ListPaginatedResources(
		r.config.APIEndpoint(),
		fmt.Sprintf("/v2/events?q=actee:%s&q=timestamp%3E%s", app.GUID, url.QueryEscape(since.Format(time.RFC3339))),
		resources.EventResourceNewV2{},
		func(resource interface{}) bool {
			return callback(resource.(resources.EventResourceNewV2).ToFields())
		})
}
<commit_msg>Fix string formatting in URL path<commit_after>package main

import (
	"fmt"
	"time"

	"net/url"

	"code.cloudfoundry.org/cli/cf/api/resources"
	"code.cloudfoundry.org/cli/cf/configuration/coreconfig"
	"code.cloudfoundry.org/cli/cf/models"
	"code.cloudfoundry.org/cli/cf/net"
)

type EventRepo struct {
	config  coreconfig.Reader
	gateway net.Gateway
}

func NewEventRepo(config coreconfig.Repository, gateway net.Gateway) (repo EventRepo) {
	repo.config = config
	repo.gateway = gateway
	return
}

func (r EventRepo) GetAppEvents(app models.Application, since time.Time, callback func(models.EventFields) bool) error {
	return r.gateway.ListPaginatedResources(
		r.config.APIEndpoint(),
		fmt.Sprintf("/v2/events?q=actee:%s&q=timestamp%s", app.GUID, url.QueryEscape(">"+since.Format(time.RFC3339))),
		resources.EventResourceNewV2{},
		func(resource interface{}) bool {
			return callback(resource.(resources.EventResourceNewV2).ToFields())
		})
}
<|endoftext|>


<commit_before>package chartserver

import (
	"encoding/json"
	"errors"
	"time"

	beego_cache "github.com/astaxie/beego/cache"
	hlog "github.com/goharbor/harbor/src/common/utils/log"

	// Enable redis cache adaptor
	_ "github.com/astaxie/beego/cache/redis"
)

const (
	standardExpireTime  = 3600 * time.Second
	redisENVKey         = "_REDIS_URL"
	cacheDriverENVKey   = "CHART_CACHE_DRIVER" // "memory" or "redis"
	cacheDriverMem      = "memory"
	cacheDriverRedis    = "redis"
	cacheCollectionName = "helm_chart_cache"
)

// ChartCache is designed to cache some processed data for repeated accessing
// to improve the performance
type ChartCache struct {
	// Cache driver
	cache beego_cache.Cache

	// Keep the driver type
	driverType string

	// To indicate if the chart cache is enabled
	isEnabled bool
}

// ChartCacheConfig keeps the configurations of ChartCache
type ChartCacheConfig struct {
	// Only support 'in-memory' and 'redis' now
	DriverType string

	// Align with config
	Config string
}

// NewChartCache is constructor of ChartCache
// If return nil, that means no cache is enabled for chart repository server
func NewChartCache(config *ChartCacheConfig) *ChartCache {
	// Never return nil object
	chartCache := &ChartCache{
		isEnabled: false,
	}

	// Double check the configurations are what we want
	if config == nil {
		return chartCache
	}

	if config.DriverType != cacheDriverMem && config.DriverType != cacheDriverRedis {
		return chartCache
	}

	if config.DriverType == cacheDriverRedis {
		if len(config.Config) == 0 {
			return chartCache
		}
	}

	// Try to create the upstream cache
	cache := initCacheDriver(config)
	if cache == nil {
		return chartCache
	}

	// Cache enabled
	chartCache.isEnabled = true
	chartCache.driverType = config.DriverType
	chartCache.cache = cache

	return chartCache
}

// IsEnabled to indicate if the chart cache is successfully enabled
// The cache may be disabled if
//  user does not set
//  wrong configurations
func (chc *ChartCache) IsEnabled() bool {
	return chc.isEnabled
}

// PutChart caches the detailed data of chart version
func (chc *ChartCache) PutChart(chart *ChartVersionDetails) {
	// If cache is not enabled, do nothing
	if !chc.IsEnabled() {
		return
	}

	// As it's a valid json data anymore when retrieving back from redis cache,
	// here we use separate methods to handle the data according to the driver type
	if chart != nil {
		var err error

		switch chc.driverType {
		case cacheDriverMem:
			// Directly put object in
			err = chc.cache.Put(chart.Metadata.Digest, chart, standardExpireTime)
		case cacheDriverRedis:
			// Marshal to json data before saving
			var jsonData []byte
			if jsonData, err = json.Marshal(chart); err == nil {
				err = chc.cache.Put(chart.Metadata.Digest, jsonData, standardExpireTime)
			}
		default:
			// Should not reach here, but still put guard code here
			err = errors.New("Meet invalid cache driver")
		}

		if err != nil {
			// Just logged
			hlog.Errorf("Failed to cache chart object with error: %s\n", err)
			hlog.Warningf("If cache driver is using 'redis', please check the related configurations or the network connection")
		}
	}
}

// GetChart trys to retrieve it from the cache
// If hit, return the cached item;
// otherwise, nil object is returned
func (chc *ChartCache) GetChart(chartDigest string) *ChartVersionDetails {
	// If cache is not enabled, do nothing
	if !chc.IsEnabled() {
		return nil
	}

	object := chc.cache.Get(chartDigest)
	if object != nil {
		// Try to convert data
		// First try the normal way
		if chartDetails, ok := object.(*ChartVersionDetails); ok {
			return chartDetails
		}

		// Maybe json bytes
		if bytes, yes := object.([]byte); yes {
			chartDetails := &ChartVersionDetails{}
			err := json.Unmarshal(bytes, chartDetails)
			if err == nil {
				return chartDetails
			}
			// Just logged the error
			hlog.Errorf("Failed to retrieve chart from cache with error: %s", err)
		}
	}

	return nil
}

// Initialize the cache driver based on the config
func initCacheDriver(cacheConfig *ChartCacheConfig) beego_cache.Cache {
	switch cacheConfig.DriverType {
	case cacheDriverMem:
		hlog.Info("Enable memory cache for chart caching")
		return beego_cache.NewMemoryCache()
	case cacheDriverRedis:
		redisCache, err := beego_cache.NewCache(cacheDriverRedis, cacheConfig.Config)
		if err != nil {
			// Just logged
			hlog.Errorf("Failed to initialize redis cache: %s", err)
			return nil
		}

		hlog.Info("Enable redis cache for chart caching")
		return redisCache
	default:
		break
	}

	// Any other cases
	hlog.Info("No cache is enabled for chart caching")
	return nil
}
<commit_msg>Add retry with backoff when creating redis cache for chart server<commit_after>package chartserver

import (
	"encoding/json"
	"errors"
	"math"
	"time"

	beego_cache "github.com/astaxie/beego/cache"
	hlog "github.com/goharbor/harbor/src/common/utils/log"

	// Enable redis cache adaptor
	_ "github.com/astaxie/beego/cache/redis"
)

const (
	standardExpireTime  = 3600 * time.Second
	redisENVKey         = "_REDIS_URL"
	cacheDriverENVKey   = "CHART_CACHE_DRIVER" // "memory" or "redis"
	cacheDriverMem      = "memory"
	cacheDriverRedis    = "redis"
	cacheCollectionName = "helm_chart_cache"
	maxTry              = 10
)

// ChartCache is designed to cache some processed data for repeated accessing
// to improve the performance
type ChartCache struct {
	// Cache driver
	cache beego_cache.Cache

	// Keep the driver type
	driverType string

	// To indicate if the chart cache is enabled
	isEnabled bool
}

// ChartCacheConfig keeps the configurations of ChartCache
type ChartCacheConfig struct {
	// Only support 'in-memory' and 'redis' now
	DriverType string

	// Align with config
	Config string
}

// NewChartCache is constructor of ChartCache
// If return nil, that means no cache is enabled for chart repository server
func NewChartCache(config *ChartCacheConfig) *ChartCache {
	// Never return nil object
	chartCache := &ChartCache{
		isEnabled: false,
	}

	// Double check the configurations are what we want
	if config == nil {
		return chartCache
	}

	if config.DriverType != cacheDriverMem && config.DriverType != cacheDriverRedis {
		return chartCache
	}

	if config.DriverType == cacheDriverRedis {
		if len(config.Config) == 0 {
			return chartCache
		}
	}

	// Try to create the upstream cache
	cache := initCacheDriver(config)
	if cache == nil {
		return chartCache
	}

	// Cache enabled
	chartCache.isEnabled = true
	chartCache.driverType = config.DriverType
	chartCache.cache = cache

	return chartCache
}

// IsEnabled to indicate if the chart cache is successfully enabled
// The cache may be disabled if
//  user does not set
//  wrong configurations
func (chc *ChartCache) IsEnabled() bool {
	return chc.isEnabled
}

// PutChart caches the detailed data of chart version
func (chc *ChartCache) PutChart(chart *ChartVersionDetails) {
	// If cache is not enabled, do nothing
	if !chc.IsEnabled() {
		return
	}

	// As it's a valid json data anymore when retrieving back from redis cache,
	// here we use separate methods to handle the data according to the driver type
	if chart != nil {
		var err error

		switch chc.driverType {
		case cacheDriverMem:
			// Directly put object in
			err = chc.cache.Put(chart.Metadata.Digest, chart, standardExpireTime)
		case cacheDriverRedis:
			// Marshal to json data before saving
			var jsonData []byte
			if jsonData, err = json.Marshal(chart); err == nil {
				err = chc.cache.Put(chart.Metadata.Digest, jsonData, standardExpireTime)
			}
		default:
			// Should not reach here, but still put guard code here
			err = errors.New("Meet invalid cache driver")
		}

		if err != nil {
			// Just logged
			hlog.Errorf("Failed to cache chart object with error: %s\n", err)
			hlog.Warningf("If cache driver is using 'redis', please check the related configurations or the network connection")
		}
	}
}

// GetChart trys to retrieve it from the cache
// If hit, return the cached item;
// otherwise, nil object is returned
func (chc *ChartCache) GetChart(chartDigest string) *ChartVersionDetails {
	// If cache is not enabled, do nothing
	if !chc.IsEnabled() {
		return nil
	}

	object := chc.cache.Get(chartDigest)
	if object != nil {
		// Try to convert data
		// First try the normal way
		if chartDetails, ok := object.(*ChartVersionDetails); ok {
			return chartDetails
		}

		// Maybe json bytes
		if bytes, yes := object.([]byte); yes {
			chartDetails := &ChartVersionDetails{}
			err := json.Unmarshal(bytes, chartDetails)
			if err == nil {
				return chartDetails
			}
			// Just logged the error
			hlog.Errorf("Failed to retrieve chart from cache with error: %s", err)
		}
	}

	return nil
}

// Initialize the cache driver based on the config
func initCacheDriver(cacheConfig *ChartCacheConfig) beego_cache.Cache {
	switch cacheConfig.DriverType {
	case cacheDriverMem:
		hlog.Info("Enable memory cache for chart caching")
		return beego_cache.NewMemoryCache()
	case cacheDriverRedis:
		// New with retry
		count := 0
		for {
			count++
			redisCache, err := beego_cache.NewCache(cacheDriverRedis, cacheConfig.Config)
			if err != nil {
				// Just logged
				hlog.Errorf("Failed to initialize redis cache: %s", err)

				if count < maxTry {
					<-time.After(time.Duration(backoff(count)) * time.Second)
					continue
				}

				return nil
			}

			hlog.Info("Enable redis cache for chart caching")
			return redisCache
		}
	default:
		break
	}

	// Any other cases
	hlog.Info("No cache is enabled for chart caching")
	return nil
}

// backoff: fast->slow->fast
func backoff(count int) int {
	f := 5 - math.Abs((float64)(count)-5)
	return (int)(math.Pow(2, f))
}
<|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 main

import (
	"bufio"
	"exec"
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"time"
	"unicode"
	"utf8"
)

// Environment for commands.
var (
	XGC       []string // 6g -I _test -o _xtest_.6
	GC        []string // 6g -I _test _testmain.go
	GL        []string // 6l -L _test _testmain.6
	GOARCH    string
	GOROOT    string
	GORUN     string
	O         string
	args      []string // arguments passed to gotest; also passed to the binary
	fileNames []string
	env       = os.Environ()
)

// These strings are created by getTestNames.
var (
	insideFileNames  []string // list of *.go files inside the package.
	outsideFileNames []string // list of *.go files outside the package (in package foo_test).
)

var (
	files      []*File
	importPath string
)

// Flags for our own purposes. We do our own flag processing.
var (
	cFlag bool
	xFlag bool
)

// elapsed returns  time elapsed since gotest started.
func elapsed() float64 {
	return float64(time.Nanoseconds()-start) / 1e9
}

var start = time.Nanoseconds()

// File represents a file that contains tests.
type File struct {
	name       string
	pkg        string
	file       *os.File
	astFile    *ast.File
	tests      []string // The names of the TestXXXs.
	benchmarks []string // The names of the BenchmarkXXXs.
}

func main() {
	flags()
	needMakefile()
	setEnvironment()
	getTestFileNames()
	parseFiles()
	getTestNames()
	run("gomake", "testpackage-clean")
	run("gomake", "testpackage", fmt.Sprintf("GOTESTFILES=%s", strings.Join(insideFileNames, " ")))
	if len(outsideFileNames) > 0 {
		run(append(XGC, outsideFileNames...)...)
	}
	importPath = runWithStdout("gomake", "-s", "importpath")
	writeTestmainGo()
	run(GC...)
	run(GL...)
	if !cFlag {
		runTestWithArgs("./" + O + ".out")
	}
	if xFlag {
		fmt.Printf("gotest %.2fs: done\n", elapsed())
	}
}

// needMakefile tests that we have a Makefile in this directory.
func needMakefile() {
	if _, err := os.Stat("Makefile"); err != nil {
		Fatalf("please create a Makefile for gotest; see http://golang.org/doc/code.html for details")
	}
}

// Fatalf formats its arguments, prints the message with a final newline, and exits.
func Fatalf(s string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, "gotest: "+s+"\n", args...)
	os.Exit(2)
}

// theChar is the map from architecture to object character.
var theChar = map[string]string{
	"arm":   "5",
	"amd64": "6",
	"386":   "8",
}

// addEnv adds a name=value pair to the environment passed to subcommands.
// If the item is already in the environment, addEnv replaces the value.
func addEnv(name, value string) {
	for i := 0; i < len(env); i++ {
		if strings.HasPrefix(env[i], name+"=") {
			env[i] = name + "=" + value
			return
		}
	}
	env = append(env, name+"="+value)
}

// setEnvironment assembles the configuration for gotest and its subcommands.
func setEnvironment() {
	// Basic environment.
	GOROOT = runtime.GOROOT()
	addEnv("GOROOT", GOROOT)
	GOARCH = os.Getenv("GOARCH")
	if GOARCH == "" {
		GOARCH = runtime.GOARCH
	}
	addEnv("GOARCH", GOARCH)
	O = theChar[GOARCH]
	if O == "" {
		Fatalf("unknown architecture %s", GOARCH)
	}

	// Commands and their flags.
	gc := os.Getenv("GC")
	if gc == "" {
		gc = O + "g"
	}
	XGC = []string{gc, "-I", "_test", "-o", "_xtest_." + O}
	GC = []string{gc, "-I", "_test", "_testmain.go"}
	gl := os.Getenv("GL")
	if gl == "" {
		gl = O + "l"
	}
	GL = []string{gl, "-L", "_test", "_testmain." + O}

	// Silence make on Linux
	addEnv("MAKEFLAGS", "")
	addEnv("MAKELEVEL", "")
}

// getTestFileNames gets the set of files we're looking at.
// If gotest has no arguments, it scans for file names matching "[^.]*_test.go".
func getTestFileNames() {
	names := fileNames
	if len(names) == 0 {
		var err os.Error
		names, err = filepath.Glob("[^.]*_test.go")
		if err != nil {
			Fatalf("Glob pattern error: %s", err)
		}
		if len(names) == 0 {
			Fatalf(`no test files found: no match for "[^.]*_test.go"`)
		}
	}
	for _, n := range names {
		fd, err := os.Open(n)
		if err != nil {
			Fatalf("%s: %s", n, err)
		}
		f := &File{name: n, file: fd}
		files = append(files, f)
	}
}

// parseFiles parses the files and remembers the packages we find.
func parseFiles() {
	fileSet := token.NewFileSet()
	for _, f := range files {
		// Report declaration errors so we can abort if the files are incorrect Go.
		file, err := parser.ParseFile(fileSet, f.name, nil, parser.DeclarationErrors)
		if err != nil {
			Fatalf("parse error: %s", err)
		}
		f.astFile = file
		f.pkg = file.Name.String()
		if f.pkg == "" {
			Fatalf("cannot happen: no package name in %s", f.name)
		}
	}
}

// getTestNames extracts the names of tests and benchmarks.  They are all
// top-level functions that are not methods.
func getTestNames() {
	for _, f := range files {
		for _, d := range f.astFile.Decls {
			n, ok := d.(*ast.FuncDecl)
			if !ok {
				continue
			}
			if n.Recv != nil { // a method, not a function.
				continue
			}
			name := n.Name.String()
			if isTest(name, "Test") {
				f.tests = append(f.tests, name)
			} else if isTest(name, "Benchmark") {
				f.benchmarks = append(f.benchmarks, name)
			}
			// TODO: worth checking the signature? Probably not.
		}
		if strings.HasSuffix(f.pkg, "_test") {
			outsideFileNames = append(outsideFileNames, f.name)
		} else {
			insideFileNames = append(insideFileNames, f.name)
		}
	}
}

// isTest tells whether name looks like a test (or benchmark, according to prefix).
// It is a Test (say) if there is a character after Test that is not a lower-case letter.
// We don't want TesticularCancer.
func isTest(name, prefix string) bool {
	if !strings.HasPrefix(name, prefix) {
		return false
	}
	if len(name) == len(prefix) { // "Test" is ok
		return true
	}
	rune, _ := utf8.DecodeRuneInString(name[len(prefix):])
	return !unicode.IsLower(rune)
}

func run(args ...string) {
	doRun(args, false)
}

// runWithStdout is like run, but returns the text of standard output with the last newline dropped.
func runWithStdout(argv ...string) string {
	s := doRun(argv, true)
	if strings.HasSuffix(s, "\r\n") {
		s = s[:len(s)-2]
	} else if strings.HasSuffix(s, "\n") {
		s = s[:len(s)-1]
	}
	if len(s) == 0 {
		Fatalf("no output from command %s", strings.Join(argv, " "))
	}
	return s
}

// runTestWithArgs appends gotest's runs the provided binary with the args passed on the command line.
func runTestWithArgs(binary string) {
	doRun(append([]string{binary}, args...), false)
}

// doRun is the general command runner.  The flag says whether we want to
// retrieve standard output.
func doRun(argv []string, returnStdout bool) string {
	if xFlag {
		fmt.Printf("gotest %.2fs: %s\n", elapsed(), strings.Join(argv, " "))
		t := -time.Nanoseconds()
		defer func() {
			t += time.Nanoseconds()
			fmt.Printf(" [+%.2fs]\n", float64(t)/1e9)
		}()
	}
	command := argv[0]
	if runtime.GOOS == "windows" && command == "gomake" {
		// gomake is a shell script and it cannot be executed directly on Windows.
		cmd := ""
		for i, v := range argv {
			if i > 0 {
				cmd += " "
			}
			cmd += `"` + v + `"`
		}
		argv = []string{"sh", "-c", cmd}
	}
	var err os.Error
	argv[0], err = exec.LookPath(argv[0])
	if err != nil {
		Fatalf("can't find %s: %s", command, err)
	}
	procAttr := &os.ProcAttr{
		Env: env,
		Files: []*os.File{
			os.Stdin,
			os.Stdout,
			os.Stderr,
		},
	}
	var r, w *os.File
	if returnStdout {
		r, w, err = os.Pipe()
		if err != nil {
			Fatalf("can't create pipe: %s", err)
		}
		procAttr.Files[1] = w
	}
	proc, err := os.StartProcess(argv[0], argv, procAttr)
	if err != nil {
		Fatalf("%s failed to start: %s", command, err)
	}
	if returnStdout {
		defer r.Close()
		w.Close()
	}
	waitMsg, err := proc.Wait(0)
	if err != nil || waitMsg == nil {
		Fatalf("%s failed: %s", command, err)
	}
	if !waitMsg.Exited() || waitMsg.ExitStatus() != 0 {
		Fatalf("%q failed: %s", strings.Join(argv, " "), waitMsg)
	}
	if returnStdout {
		b, err := ioutil.ReadAll(r)
		if err != nil {
			Fatalf("can't read output from command: %s", err)
		}
		return string(b)
	}
	return ""
}

// writeTestmainGo generates the test program to be compiled, "./_testmain.go".
func writeTestmainGo() {
	f, err := os.Create("_testmain.go")
	if err != nil {
		Fatalf("can't create _testmain.go: %s", err)
	}
	defer f.Close()
	b := bufio.NewWriter(f)
	defer b.Flush()

	// Package and imports.
	fmt.Fprint(b, "package main\n\n")
	// Are there tests from a package other than the one we're testing?
	// We can't just use file names because some of the things we compiled
	// contain no tests.
	outsideTests := false
	insideTests := false
	for _, f := range files {
		//println(f.name, f.pkg)
		if len(f.tests) == 0 && len(f.benchmarks) == 0 {
			continue
		}
		if strings.HasSuffix(f.pkg, "_test") {
			outsideTests = true
		} else {
			insideTests = true
		}
	}
	if insideTests {
		switch importPath {
		case "testing":
		case "main":
			// Import path main is reserved, so import with
			// explicit reference to ./_test/main instead.
			// Also, the file we are writing defines a function named main,
			// so rename this import to __main__ to avoid name conflict.
			fmt.Fprintf(b, "import __main__ %q\n", "./_test/main")
		default:
			fmt.Fprintf(b, "import %q\n", importPath)
		}
	}
	if outsideTests {
		fmt.Fprintf(b, "import %q\n", "./_xtest_")
	}
	fmt.Fprintf(b, "import %q\n", "testing")
	fmt.Fprintf(b, "import __os__ %q\n", "os")         // rename in case tested package is called os
	fmt.Fprintf(b, "import __regexp__ %q\n", "regexp") // rename in case tested package is called regexp
	fmt.Fprintln(b)                                    // for gofmt

	// Tests.
	fmt.Fprintln(b, "var tests = []testing.InternalTest{")
	for _, f := range files {
		for _, t := range f.tests {
			fmt.Fprintf(b, "\t{\"%s.%s\", %s.%s},\n", f.pkg, t, notMain(f.pkg), t)
		}
	}
	fmt.Fprintln(b, "}")
	fmt.Fprintln(b)

	// Benchmarks.
	fmt.Fprintf(b, "var benchmarks = []testing.InternalBenchmark{")
	for _, f := range files {
		for _, bm := range f.benchmarks {
			fmt.Fprintf(b, "\t{\"%s.%s\", %s.%s},\n", f.pkg, bm, notMain(f.pkg), bm)
		}
	}
	fmt.Fprintln(b, "}")

	// Body.
	fmt.Fprintln(b, testBody)
}

// notMain returns the package, renaming as appropriate if it's "main".
func notMain(pkg string) string {
	if pkg == "main" {
		return "__main__"
	}
	return pkg
}

// testBody is just copied to the output. It's the code that runs the tests.
var testBody = `
var matchPat string
var matchRe *__regexp__.Regexp

func matchString(pat, str string) (result bool, err __os__.Error) {
	if matchRe == nil || matchPat != pat {
		matchPat = pat
		matchRe, err = __regexp__.Compile(matchPat)
		if err != nil {
			return
		}
	}
	return matchRe.MatchString(str), nil
}

func main() {
	testing.Main(matchString, tests, benchmarks)
}`
<commit_msg>windows: reset command var to sh for correct error output messages<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 main

import (
	"bufio"
	"exec"
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"time"
	"unicode"
	"utf8"
)

// Environment for commands.
var (
	XGC       []string // 6g -I _test -o _xtest_.6
	GC        []string // 6g -I _test _testmain.go
	GL        []string // 6l -L _test _testmain.6
	GOARCH    string
	GOROOT    string
	GORUN     string
	O         string
	args      []string // arguments passed to gotest; also passed to the binary
	fileNames []string
	env       = os.Environ()
)

// These strings are created by getTestNames.
var (
	insideFileNames  []string // list of *.go files inside the package.
	outsideFileNames []string // list of *.go files outside the package (in package foo_test).
)

var (
	files      []*File
	importPath string
)

// Flags for our own purposes. We do our own flag processing.
var (
	cFlag bool
	xFlag bool
)

// elapsed returns  time elapsed since gotest started.
func elapsed() float64 {
	return float64(time.Nanoseconds()-start) / 1e9
}

var start = time.Nanoseconds()

// File represents a file that contains tests.
type File struct {
	name       string
	pkg        string
	file       *os.File
	astFile    *ast.File
	tests      []string // The names of the TestXXXs.
	benchmarks []string // The names of the BenchmarkXXXs.
}

func main() {
	flags()
	needMakefile()
	setEnvironment()
	getTestFileNames()
	parseFiles()
	getTestNames()
	run("gomake", "testpackage-clean")
	run("gomake", "testpackage", fmt.Sprintf("GOTESTFILES=%s", strings.Join(insideFileNames, " ")))
	if len(outsideFileNames) > 0 {
		run(append(XGC, outsideFileNames...)...)
	}
	importPath = runWithStdout("gomake", "-s", "importpath")
	writeTestmainGo()
	run(GC...)
	run(GL...)
	if !cFlag {
		runTestWithArgs("./" + O + ".out")
	}
	if xFlag {
		fmt.Printf("gotest %.2fs: done\n", elapsed())
	}
}

// needMakefile tests that we have a Makefile in this directory.
func needMakefile() {
	if _, err := os.Stat("Makefile"); err != nil {
		Fatalf("please create a Makefile for gotest; see http://golang.org/doc/code.html for details")
	}
}

// Fatalf formats its arguments, prints the message with a final newline, and exits.
func Fatalf(s string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, "gotest: "+s+"\n", args...)
	os.Exit(2)
}

// theChar is the map from architecture to object character.
var theChar = map[string]string{
	"arm":   "5",
	"amd64": "6",
	"386":   "8",
}

// addEnv adds a name=value pair to the environment passed to subcommands.
// If the item is already in the environment, addEnv replaces the value.
func addEnv(name, value string) {
	for i := 0; i < len(env); i++ {
		if strings.HasPrefix(env[i], name+"=") {
			env[i] = name + "=" + value
			return
		}
	}
	env = append(env, name+"="+value)
}

// setEnvironment assembles the configuration for gotest and its subcommands.
func setEnvironment() {
	// Basic environment.
	GOROOT = runtime.GOROOT()
	addEnv("GOROOT", GOROOT)
	GOARCH = os.Getenv("GOARCH")
	if GOARCH == "" {
		GOARCH = runtime.GOARCH
	}
	addEnv("GOARCH", GOARCH)
	O = theChar[GOARCH]
	if O == "" {
		Fatalf("unknown architecture %s", GOARCH)
	}

	// Commands and their flags.
	gc := os.Getenv("GC")
	if gc == "" {
		gc = O + "g"
	}
	XGC = []string{gc, "-I", "_test", "-o", "_xtest_." + O}
	GC = []string{gc, "-I", "_test", "_testmain.go"}
	gl := os.Getenv("GL")
	if gl == "" {
		gl = O + "l"
	}
	GL = []string{gl, "-L", "_test", "_testmain." + O}

	// Silence make on Linux
	addEnv("MAKEFLAGS", "")
	addEnv("MAKELEVEL", "")
}

// getTestFileNames gets the set of files we're looking at.
// If gotest has no arguments, it scans for file names matching "[^.]*_test.go".
func getTestFileNames() {
	names := fileNames
	if len(names) == 0 {
		var err os.Error
		names, err = filepath.Glob("[^.]*_test.go")
		if err != nil {
			Fatalf("Glob pattern error: %s", err)
		}
		if len(names) == 0 {
			Fatalf(`no test files found: no match for "[^.]*_test.go"`)
		}
	}
	for _, n := range names {
		fd, err := os.Open(n)
		if err != nil {
			Fatalf("%s: %s", n, err)
		}
		f := &File{name: n, file: fd}
		files = append(files, f)
	}
}

// parseFiles parses the files and remembers the packages we find.
func parseFiles() {
	fileSet := token.NewFileSet()
	for _, f := range files {
		// Report declaration errors so we can abort if the files are incorrect Go.
		file, err := parser.ParseFile(fileSet, f.name, nil, parser.DeclarationErrors)
		if err != nil {
			Fatalf("parse error: %s", err)
		}
		f.astFile = file
		f.pkg = file.Name.String()
		if f.pkg == "" {
			Fatalf("cannot happen: no package name in %s", f.name)
		}
	}
}

// getTestNames extracts the names of tests and benchmarks.  They are all
// top-level functions that are not methods.
func getTestNames() {
	for _, f := range files {
		for _, d := range f.astFile.Decls {
			n, ok := d.(*ast.FuncDecl)
			if !ok {
				continue
			}
			if n.Recv != nil { // a method, not a function.
				continue
			}
			name := n.Name.String()
			if isTest(name, "Test") {
				f.tests = append(f.tests, name)
			} else if isTest(name, "Benchmark") {
				f.benchmarks = append(f.benchmarks, name)
			}
			// TODO: worth checking the signature? Probably not.
		}
		if strings.HasSuffix(f.pkg, "_test") {
			outsideFileNames = append(outsideFileNames, f.name)
		} else {
			insideFileNames = append(insideFileNames, f.name)
		}
	}
}

// isTest tells whether name looks like a test (or benchmark, according to prefix).
// It is a Test (say) if there is a character after Test that is not a lower-case letter.
// We don't want TesticularCancer.
func isTest(name, prefix string) bool {
	if !strings.HasPrefix(name, prefix) {
		return false
	}
	if len(name) == len(prefix) { // "Test" is ok
		return true
	}
	rune, _ := utf8.DecodeRuneInString(name[len(prefix):])
	return !unicode.IsLower(rune)
}

func run(args ...string) {
	doRun(args, false)
}

// runWithStdout is like run, but returns the text of standard output with the last newline dropped.
func runWithStdout(argv ...string) string {
	s := doRun(argv, true)
	if strings.HasSuffix(s, "\r\n") {
		s = s[:len(s)-2]
	} else if strings.HasSuffix(s, "\n") {
		s = s[:len(s)-1]
	}
	if len(s) == 0 {
		Fatalf("no output from command %s", strings.Join(argv, " "))
	}
	return s
}

// runTestWithArgs appends gotest's runs the provided binary with the args passed on the command line.
func runTestWithArgs(binary string) {
	doRun(append([]string{binary}, args...), false)
}

// doRun is the general command runner.  The flag says whether we want to
// retrieve standard output.
func doRun(argv []string, returnStdout bool) string {
	if xFlag {
		fmt.Printf("gotest %.2fs: %s\n", elapsed(), strings.Join(argv, " "))
		t := -time.Nanoseconds()
		defer func() {
			t += time.Nanoseconds()
			fmt.Printf(" [+%.2fs]\n", float64(t)/1e9)
		}()
	}
	command := argv[0]
	if runtime.GOOS == "windows" && command == "gomake" {
		// gomake is a shell script and it cannot be executed directly on Windows.
		cmd := ""
		for i, v := range argv {
			if i > 0 {
				cmd += " "
			}
			cmd += `"` + v + `"`
		}
		command = "sh"
		argv = []string{"sh", "-c", cmd}
	}
	var err os.Error
	argv[0], err = exec.LookPath(argv[0])
	if err != nil {
		Fatalf("can't find %s: %s", command, err)
	}
	procAttr := &os.ProcAttr{
		Env: env,
		Files: []*os.File{
			os.Stdin,
			os.Stdout,
			os.Stderr,
		},
	}
	var r, w *os.File
	if returnStdout {
		r, w, err = os.Pipe()
		if err != nil {
			Fatalf("can't create pipe: %s", err)
		}
		procAttr.Files[1] = w
	}
	proc, err := os.StartProcess(argv[0], argv, procAttr)
	if err != nil {
		Fatalf("%s failed to start: %s", command, err)
	}
	if returnStdout {
		defer r.Close()
		w.Close()
	}
	waitMsg, err := proc.Wait(0)
	if err != nil || waitMsg == nil {
		Fatalf("%s failed: %s", command, err)
	}
	if !waitMsg.Exited() || waitMsg.ExitStatus() != 0 {
		Fatalf("%q failed: %s", strings.Join(argv, " "), waitMsg)
	}
	if returnStdout {
		b, err := ioutil.ReadAll(r)
		if err != nil {
			Fatalf("can't read output from command: %s", err)
		}
		return string(b)
	}
	return ""
}

// writeTestmainGo generates the test program to be compiled, "./_testmain.go".
func writeTestmainGo() {
	f, err := os.Create("_testmain.go")
	if err != nil {
		Fatalf("can't create _testmain.go: %s", err)
	}
	defer f.Close()
	b := bufio.NewWriter(f)
	defer b.Flush()

	// Package and imports.
	fmt.Fprint(b, "package main\n\n")
	// Are there tests from a package other than the one we're testing?
	// We can't just use file names because some of the things we compiled
	// contain no tests.
	outsideTests := false
	insideTests := false
	for _, f := range files {
		//println(f.name, f.pkg)
		if len(f.tests) == 0 && len(f.benchmarks) == 0 {
			continue
		}
		if strings.HasSuffix(f.pkg, "_test") {
			outsideTests = true
		} else {
			insideTests = true
		}
	}
	if insideTests {
		switch importPath {
		case "testing":
		case "main":
			// Import path main is reserved, so import with
			// explicit reference to ./_test/main instead.
			// Also, the file we are writing defines a function named main,
			// so rename this import to __main__ to avoid name conflict.
			fmt.Fprintf(b, "import __main__ %q\n", "./_test/main")
		default:
			fmt.Fprintf(b, "import %q\n", importPath)
		}
	}
	if outsideTests {
		fmt.Fprintf(b, "import %q\n", "./_xtest_")
	}
	fmt.Fprintf(b, "import %q\n", "testing")
	fmt.Fprintf(b, "import __os__ %q\n", "os")         // rename in case tested package is called os
	fmt.Fprintf(b, "import __regexp__ %q\n", "regexp") // rename in case tested package is called regexp
	fmt.Fprintln(b)                                    // for gofmt

	// Tests.
	fmt.Fprintln(b, "var tests = []testing.InternalTest{")
	for _, f := range files {
		for _, t := range f.tests {
			fmt.Fprintf(b, "\t{\"%s.%s\", %s.%s},\n", f.pkg, t, notMain(f.pkg), t)
		}
	}
	fmt.Fprintln(b, "}")
	fmt.Fprintln(b)

	// Benchmarks.
	fmt.Fprintf(b, "var benchmarks = []testing.InternalBenchmark{")
	for _, f := range files {
		for _, bm := range f.benchmarks {
			fmt.Fprintf(b, "\t{\"%s.%s\", %s.%s},\n", f.pkg, bm, notMain(f.pkg), bm)
		}
	}
	fmt.Fprintln(b, "}")

	// Body.
	fmt.Fprintln(b, testBody)
}

// notMain returns the package, renaming as appropriate if it's "main".
func notMain(pkg string) string {
	if pkg == "main" {
		return "__main__"
	}
	return pkg
}

// testBody is just copied to the output. It's the code that runs the tests.
var testBody = `
var matchPat string
var matchRe *__regexp__.Regexp

func matchString(pat, str string) (result bool, err __os__.Error) {
	if matchRe == nil || matchPat != pat {
		matchPat = pat
		matchRe, err = __regexp__.Compile(matchPat)
		if err != nil {
			return
		}
	}
	return matchRe.MatchString(str), nil
}

func main() {
	testing.Main(matchString, tests, benchmarks)
}`
<|endoftext|>


<commit_before>package main

import (
	"model"
	"runner"
	"runner/sshrunner"

	"fmt"

	"util"

	"github.com/codegangsta/cli"
)

var (
	// ErrCmdRequired require cmd option
	ErrCmdRequired = fmt.Errorf("option -c/--cmd is required")
	// ErrNoNodeToExec no more node to execute
	ErrNoNodeToExec = fmt.Errorf("found no node to execute")
)

type execParams struct {
	GroupName string
	NodeName  string
	User      string
	Cmd       string
	Yes       bool
}

func initExecSubCmd(app *cli.App) {
	execSubCmd := cli.Command{
		Name:        "exec",
		Usage:       "exec <options>",
		Description: "exec command on groups or nodes",
		Flags: []cli.Flag{
			cli.StringFlag{
				Name:  "g,group",
				Value: "*",
				Usage: "exec command on group",
			},
			cli.StringFlag{
				Name:  "n,node",
				Value: "",
				Usage: "exec command on node",
			},
			cli.StringFlag{
				Name:  "u,user",
				Value: "root",
				Usage: "user who exec the command",
			},
			cli.StringFlag{
				Name:  "c,cmd",
				Value: "",
				Usage: "command for exec",
			},
			cli.BoolFlag{
				Name:  "y,yes",
				Usage: "excute command without confirm",
			},
		},
		Action: func(c *cli.Context) {
			var ep, err = checkExecParams(c)
			if err != nil {
				fmt.Println(util.FgRed(err))
				cli.ShowCommandHelp(c, "exec")
				return
			}
			if err = execCmd(ep); err != nil {
				fmt.Println(util.FgRed(err))
			}
		},
	}

	if app.Commands == nil {
		app.Commands = cli.Commands{execSubCmd}
	} else {
		app.Commands = append(app.Commands, execSubCmd)
	}
}

func checkExecParams(c *cli.Context) (execParams, error) {
	var ep = execParams{
		GroupName: c.String("group"),
		NodeName:  c.String("node"),
		User:      c.String("user"),
		Cmd:       c.String("cmd"),
		Yes:       c.Bool("yes"),
	}

	if ep.Cmd == "" {
		return ep, ErrCmdRequired
	}

	return ep, nil
}

func execCmd(ep execParams) error {
	// TODO should use sshrunner from config

	// get node info for exec
	repo := GetRepo()
	var nodes, err = repo.FilterNodes(ep.GroupName, ep.NodeName)
	if err != nil {
		return err
	}

	if len(nodes) == 0 {
		return ErrNoNodeToExec
	}

	if !ep.Yes && !confirmExec(nodes, ep.User, ep.Cmd) {
		return nil
	}

	// exec cmd on node
	for _, n := range nodes {
		fmt.Printf("Start to excute \"%s\" on %s(%s):\n", util.FgBoldGreen(ep.Cmd), util.FgBoldGreen(n.Name), util.FgBoldGreen(n.Host))
		var runCmd = sshrunner.New(n.User, n.Password, n.KeyPath, n.Host, n.Port)
		var input = runner.Input{
			ExecHost: n.Host,
			ExecUser: ep.User,
			Command:  ep.Cmd,
		}

		// display result
		output, err := runCmd.SyncExec(input)
		displayExecResult(output, err)
	}
	return nil
}

func displayExecResult(output *runner.Output, err error) {
	if err != nil {
		fmt.Printf("Command exec failed: %s\n", util.FgRed(err))
	}

	if output == nil {
		return
	}

	fmt.Printf(">>>>>>>>>>>>>>>>>>>> STDOUT >>>>>>>>>>>>>>>>>>>>\n%s\n", output.StdOutput)
	if output.StdError != "" {
		fmt.Printf(">>>>>>>>>>>>>>>>>>>> STDERR >>>>>>>>>>>>>>>>>>>>\n%s\n", output.StdError)
	}
	fmt.Printf("time costs: %v\n", output.ExecEnd.Sub(output.ExecStart))
	fmt.Println(util.FgBoldBlue("==========================================================\n"))
}

func confirmExec(nodes []model.Node, user, cmd string) bool {
	fmt.Printf("%-3s\t%-10s\t%-10s\n", "No.", "Name", "IP")
	fmt.Println("----------------------------------------------------------------------")
	for index, n := range nodes {
		fmt.Printf("%-3d\t%-10s\t%-10s\n", index+1, n.Name, n.Host)
	}

	fmt.Println()
	return util.Confirm(fmt.Sprintf("You want to exec COMMAND(%s) by UESR(%s) at the above nodes, yes/no(y/n) ?",
		util.FgBoldRed(cmd), util.FgBoldRed(user)))
}
<commit_msg>distinct error output from successful output<commit_after>package main

import (
	"model"
	"runner"
	"runner/sshrunner"

	"fmt"

	"util"

	"github.com/codegangsta/cli"
)

var (
	// ErrCmdRequired require cmd option
	ErrCmdRequired = fmt.Errorf("option -c/--cmd is required")
	// ErrNoNodeToExec no more node to execute
	ErrNoNodeToExec = fmt.Errorf("found no node to execute")
)

type execParams struct {
	GroupName string
	NodeName  string
	User      string
	Cmd       string
	Yes       bool
}

func initExecSubCmd(app *cli.App) {
	execSubCmd := cli.Command{
		Name:        "exec",
		Usage:       "exec <options>",
		Description: "exec command on groups or nodes",
		Flags: []cli.Flag{
			cli.StringFlag{
				Name:  "g,group",
				Value: "*",
				Usage: "exec command on group",
			},
			cli.StringFlag{
				Name:  "n,node",
				Value: "",
				Usage: "exec command on node",
			},
			cli.StringFlag{
				Name:  "u,user",
				Value: "root",
				Usage: "user who exec the command",
			},
			cli.StringFlag{
				Name:  "c,cmd",
				Value: "",
				Usage: "command for exec",
			},
			cli.BoolFlag{
				Name:  "y,yes",
				Usage: "excute command without confirm",
			},
		},
		Action: func(c *cli.Context) {
			var ep, err = checkExecParams(c)
			if err != nil {
				fmt.Println(util.FgRed(err))
				cli.ShowCommandHelp(c, "exec")
				return
			}
			if err = execCmd(ep); err != nil {
				fmt.Println(util.FgRed(err))
			}
		},
	}

	if app.Commands == nil {
		app.Commands = cli.Commands{execSubCmd}
	} else {
		app.Commands = append(app.Commands, execSubCmd)
	}
}

func checkExecParams(c *cli.Context) (execParams, error) {
	var ep = execParams{
		GroupName: c.String("group"),
		NodeName:  c.String("node"),
		User:      c.String("user"),
		Cmd:       c.String("cmd"),
		Yes:       c.Bool("yes"),
	}

	if ep.Cmd == "" {
		return ep, ErrCmdRequired
	}

	return ep, nil
}

func execCmd(ep execParams) error {
	// TODO should use sshrunner from config

	// get node info for exec
	repo := GetRepo()
	var nodes, err = repo.FilterNodes(ep.GroupName, ep.NodeName)
	if err != nil {
		return err
	}

	if len(nodes) == 0 {
		return ErrNoNodeToExec
	}

	if !ep.Yes && !confirmExec(nodes, ep.User, ep.Cmd) {
		return nil
	}

	// exec cmd on node
	for _, n := range nodes {
		fmt.Printf("Start to excute \"%s\" on %s(%s):\n", util.FgBoldGreen(ep.Cmd), util.FgBoldGreen(n.Name), util.FgBoldGreen(n.Host))
		var runCmd = sshrunner.New(n.User, n.Password, n.KeyPath, n.Host, n.Port)
		var input = runner.Input{
			ExecHost: n.Host,
			ExecUser: ep.User,
			Command:  ep.Cmd,
		}

		// display result
		output, err := runCmd.SyncExec(input)
		displayExecResult(output, err)
	}
	return nil
}

func displayExecResult(output *runner.Output, err error) {
	if err != nil {
		fmt.Printf("Command exec failed: %s\n", util.FgRed(err))
	}

	if output != nil {
		fmt.Printf(">>>>>>>>>>>>>>>>>>>> STDOUT >>>>>>>>>>>>>>>>>>>>\n%s\n", output.StdOutput)
		if output.StdError != "" {
			fmt.Printf(">>>>>>>>>>>>>>>>>>>> STDERR >>>>>>>>>>>>>>>>>>>>\n%s\n", output.StdError)
		}
		fmt.Printf("time costs: %v\n", output.ExecEnd.Sub(output.ExecStart))
	}
	fmt.Println(util.FgBoldBlue("==========================================================\n"))
}

func confirmExec(nodes []model.Node, user, cmd string) bool {
	fmt.Printf("%-3s\t%-10s\t%-10s\n", "No.", "Name", "IP")
	fmt.Println("----------------------------------------------------------------------")
	for index, n := range nodes {
		fmt.Printf("%-3d\t%-10s\t%-10s\n", index+1, n.Name, n.Host)
	}

	fmt.Println()
	return util.Confirm(fmt.Sprintf("You want to exec COMMAND(%s) by UESR(%s) at the above nodes, yes/no(y/n) ?",
		util.FgBoldRed(cmd), util.FgBoldRed(user)))
}
<|endoftext|>


<commit_before>package user

import (
	"database/sql"
	"fmt"
	"os"
	"strings"

	"db"

	"github.com/cjey/slog"
)

func Ifconfig(username, dev string, configs ...string) {
	name, device := StdUsername(username)
	if len(name) == 0 {
		slog.Emergf("Invalid username format: %s", username)
		os.Exit(1)
	}
	var alldev bool
	if len(device) == 0 {
		device = "default"
		alldev = true
	}

	DB := db.Get()

	var fexists int
	if len(dev) > 0 {
		err := DB.QueryRow(`
            select count(1) from ovpn
            where dev=?
        `, dev).Scan(&fexists)
		if err != nil {
			slog.Emerg(err.Error())
			os.Exit(1)
		}
		if fexists == 0 {
			slog.Emergf("Dev[%s] not served\n", dev)
			os.Exit(1)
		}
	}

	err := DB.QueryRow(`
        select count(1) from device
        where username=? and device=?
    `, name, device).Scan(&fexists)
	if err != nil {
		slog.Emergf(err.Error())
		os.Exit(1)
	}
	if fexists == 0 {
		slog.Warningf("Device[%s] of user[%s] not exists", device, name)
		return
	}

	valid := map[string]string{}
	for _, config := range configs {
		tmp := strings.SplitN(config, "=", 2)
		key := strings.ToLower(tmp[0])
		switch key {
		case "ip", "dns":
		default:
			slog.Emergf("Unsupported config field[%s]", key)
			os.Exit(1)
		}
		if len(tmp) > 1 {
			valid[key] = tmp[1]
		} else {
			valid[key] = ""
		}
	}

	if len(valid) > 0 {
		var ip, dns string
		err := DB.QueryRow(`
            select ip,dns from ifconfig
            where username=? and device=? and ovpn_dev=?
        `, name, device, dev).Scan(&ip, &dns)
		if err != nil && err != sql.ErrNoRows {
			slog.Emerg(err.Error())
			os.Exit(1)
		}
		if v, ok := valid["ip"]; ok {
			ip = v
		}
		if v, ok := valid["dns"]; ok {
			dns = v
		}

		_, err = DB.Exec(`
            insert or replace into ifconfig
                (username,device,ovpn_dev,ip,dns)
            values
                (?,?,?,?,?)
        `, name, device, dev, ip, dns)
		if err != nil {
			slog.Emerg(err.Error())
			os.Exit(1)
		}
	}

	if alldev {
		ifconfigShow(name, "")
	} else {
		ifconfigShow(name, device)
	}
}

func ifconfigShow(name, device string) {
	DB := db.Get()
	rows, err := DB.Query(`
        select ovpn_dev,device,ip,dns from ifconfig
        where username=?
    `, name)
	if err != nil {
		slog.Emergf(err.Error())
		os.Exit(1)
	}

	var fmore bool
	err = db.RangeRows(rows, func() error {
		var dev, dvc, ip, dns string
		err := rows.Scan(&dev, &dvc, &ip, &dns)
		if err != nil {
			return err
		}
		if len(device) > 0 && device != dvc {
			return nil
		}
		if fmore {
			fmt.Printf("\n")
		}
		fmt.Printf("Device: %s%%%s\n", name, dvc)
		fmt.Printf("Interface: %s\n", dev)
		if len(ip) == 0 {
			ip = "dhcp"
		}
		fmt.Printf("IP: %s\n", ip)
		if len(dns) == 0 {
			dns = "dhcp"
		}
		fmt.Printf("DNS: %s\n", dns)
		fmore = true
		return nil
	})
	if err != nil {
		slog.Emergf(err.Error())
		os.Exit(1)
	}
}
<commit_msg>style<commit_after>package user

import (
	"database/sql"
	"fmt"
	"os"
	"strings"

	"db"

	"github.com/cjey/slog"
)

func Ifconfig(username, dev string, configs ...string) {
	name, device := StdUsername(username)
	if len(name) == 0 {
		slog.Emergf("Invalid username format: %s", username)
		os.Exit(1)
	}
	var alldev bool
	if len(device) == 0 {
		device = "default"
		alldev = true
	}

	DB := db.Get()

	var fexists int
	if len(dev) > 0 {
		err := DB.QueryRow(`
            select count(1) from ovpn
            where dev=?
        `, dev).Scan(&fexists)
		if err != nil {
			slog.Emerg(err.Error())
			os.Exit(1)
		}
		if fexists == 0 {
			slog.Emergf("Dev[%s] not served\n", dev)
			os.Exit(1)
		}
	}

	err := DB.QueryRow(`
        select count(1) from device
        where username=? and device=?
    `, name, device).Scan(&fexists)
	if err != nil {
		slog.Emergf(err.Error())
		os.Exit(1)
	}
	if fexists == 0 {
		slog.Warningf("Device[%s] of user[%s] not exists", device, name)
		return
	}

	valid := map[string]string{}
	for _, config := range configs {
		tmp := strings.SplitN(config, "=", 2)
		key := strings.ToLower(tmp[0])
		switch key {
		case "ip", "dns":
		default:
			slog.Emergf("Unsupported config field[%s]", key)
			os.Exit(1)
		}
		if len(tmp) > 1 {
			valid[key] = tmp[1]
		} else {
			valid[key] = ""
		}
	}

	if len(valid) > 0 {
		var ip, dns string
		err := DB.QueryRow(`
            select ip,dns from ifconfig
            where username=? and device=? and ovpn_dev=?
        `, name, device, dev).Scan(&ip, &dns)
		if err != nil && err != sql.ErrNoRows {
			slog.Emerg(err.Error())
			os.Exit(1)
		}
		if v, ok := valid["ip"]; ok {
			ip = v
		}
		if v, ok := valid["dns"]; ok {
			dns = v
		}

		_, err = DB.Exec(`
            insert or replace into ifconfig
                (username,device,ovpn_dev,ip,dns)
            values
                (?,?,?,?,?)
        `, name, device, dev, ip, dns)
		if err != nil {
			slog.Emerg(err.Error())
			os.Exit(1)
		}
	}

	if alldev {
		ifconfigShow(name, "")
	} else {
		ifconfigShow(name, device)
	}
}

func ifconfigShow(name, device string) {
	DB := db.Get()
	rows, err := DB.Query(`
        select ovpn_dev,device,ip,dns from ifconfig
        where username=?
    `, name)
	if err != nil {
		slog.Emergf(err.Error())
		os.Exit(1)
	}

	var fmore bool
	err = db.RangeRows(rows, func() error {
		var dev, dvc, ip, dns string
		err := rows.Scan(&dev, &dvc, &ip, &dns)
		if err != nil {
			return err
		}
		if len(device) > 0 && device != dvc {
			return nil
		}
		if fmore {
			fmt.Printf("\n")
		}
		fmt.Printf("Device: %s%%%s\n", name, dvc)
		fmt.Printf("----\n")
		fmt.Printf("Interface: %s\n", dev)
		if len(ip) == 0 {
			ip = "dhcp"
		}
		fmt.Printf("IP: %s\n", ip)
		if len(dns) == 0 {
			dns = "dhcp"
		}
		fmt.Printf("DNS: %s\n", dns)
		fmore = true
		return nil
	})
	if err != nil {
		slog.Emergf(err.Error())
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package raftgorums

import (
	"encoding/binary"
	"errors"
	"os"

	"github.com/boltdb/bolt"
	"github.com/relab/raft/commonpb"
)

var (
	stateBucket    = []byte("state")
	logBucket      = []byte("log")
	snapshotBucket = []byte("snapshot")
)

// ErrKeyNotFound means that the given key could not be found in the storage.
var ErrKeyNotFound = errors.New("key not found")

// FileStorage is an implementation of the Storage interface for file based
// storage.
type FileStorage struct {
	*bolt.DB
}

// NewFileStorage returns a new FileStorage using the file given with the path
// argument. Overwrite decides whether to use the database if it already exists
// or overwrite it.
func NewFileStorage(path string, overwrite bool) (*FileStorage, error) {
	// Check if file already exists.
	if _, err := os.Stat(path); err != nil {
		if os.IsNotExist(err) {
			// We don't need to overwrite a file that doesn't exist.
			overwrite = false
		} else {
			// If we are unable to verify the existence of the file,
			// there is probably a permission problem.
			return nil, err
		}
	}

	// If overwrite is still true, the file must exist. Thus failing to
	// remove it is an error.
	if overwrite {
		if err := os.Remove(path); err != nil {
			return nil, err
		}
	}

	db, err := bolt.Open(path, 0600, nil)

	if err != nil {
		return nil, err
	}

	tx, err := db.Begin(true)

	if err != nil {
		return nil, err
	}

	defer tx.Rollback()

	if _, err := tx.CreateBucketIfNotExists(stateBucket); err != nil {
		return nil, err
	}

	if _, err := tx.CreateBucketIfNotExists(logBucket); err != nil {
		return nil, err
	}

	firstIndex := get(tx.Bucket(stateBucket), KeyFirstIndex)
	nextIndex := get(tx.Bucket(stateBucket), KeyNextIndex)

	if firstIndex == 0 {
		err := set(tx.Bucket(stateBucket), KeyFirstIndex, 1)
		if err != nil {
			return nil, err
		}
	}

	if nextIndex == 0 {
		err := set(tx.Bucket(stateBucket), KeyNextIndex, 1)
		if err != nil {
			return nil, err
		}
	}

	if err := tx.Commit(); err != nil {
		return nil, err
	}

	return &FileStorage{
		DB: db,
	}, nil
}

// Set implements the Storage interface.
func (fs *FileStorage) Set(key uint64, value uint64) error {
	tx, err := fs.Begin(true)

	if err != nil {
		return err
	}

	defer tx.Rollback()

	if err := set(tx.Bucket(stateBucket), key, value); err != nil {
		return err
	}

	return tx.Commit()
}

func set(bucket *bolt.Bucket, key uint64, value uint64) error {
	k := make([]byte, 8)
	v := make([]byte, 8)
	binary.BigEndian.PutUint64(k, key)
	binary.BigEndian.PutUint64(v, value)

	return bucket.Put(k, v)
}

// Get implements the Storage interface.
func (fs *FileStorage) Get(key uint64) (uint64, error) {
	tx, err := fs.Begin(false)

	if err != nil {
		return 0, err
	}

	defer tx.Rollback()

	return get(tx.Bucket(stateBucket), key), nil
}

func get(bucket *bolt.Bucket, key uint64) uint64 {
	k := make([]byte, 8)
	binary.BigEndian.PutUint64(k, key)

	val := bucket.Get(k)

	if val == nil {
		// Default to 0. This lets us get values not yet set.
		return 0
	}

	return binary.BigEndian.Uint64(val)
}

// StoreEntries implements the Storage interface.
func (fs *FileStorage) StoreEntries(entries []*commonpb.Entry) error {
	tx, err := fs.Begin(true)

	if err != nil {
		return err
	}

	defer tx.Rollback()

	k := make([]byte, 8)
	bucket := tx.Bucket(logBucket)

	for _, entry := range entries {
		binary.BigEndian.PutUint64(k, entry.Index)

		val, err := entry.Marshal()

		if err != nil {
			return err
		}

		if err := bucket.Put(k, val); err != nil {
			return err
		}
	}

	nextIndex := entries[len(entries)-1].Index + 1
	if err := set(tx.Bucket(stateBucket), KeyNextIndex, nextIndex); err != nil {
		return err
	}

	return tx.Commit()
}

// GetEntry implements the Storage interface.
func (fs *FileStorage) GetEntry(index uint64) (*commonpb.Entry, error) {
	tx, err := fs.Begin(false)

	if err != nil {
		return nil, err
	}

	defer tx.Rollback()

	bucket := tx.Bucket(logBucket)

	k := make([]byte, 8)
	binary.BigEndian.PutUint64(k, index)

	if val := bucket.Get(k); val != nil {
		var entry commonpb.Entry
		err := entry.Unmarshal(val)

		if err != nil {
			return nil, err
		}

		return &entry, nil
	}

	return nil, ErrKeyNotFound
}

// GetEntries implements the Storage interface.
func (fs *FileStorage) GetEntries(first, last uint64) ([]*commonpb.Entry, error) {
	tx, err := fs.Begin(false)

	if err != nil {
		return nil, err
	}

	defer tx.Rollback()

	bucket := tx.Bucket(logBucket)

	entries := make([]*commonpb.Entry, last-first+1)
	k := make([]byte, 8)

	i := first
	for j := range entries {
		binary.BigEndian.PutUint64(k, i)

		val := bucket.Get(k)

		if val == nil {
			return nil, ErrKeyNotFound
		}

		var entry commonpb.Entry
		err := entry.Unmarshal(val)

		if err != nil {
			return nil, err
		}

		entries[j] = &entry
		i++

	}

	return entries, nil
}

// RemoveEntries implements the Storage interface.
func (fs *FileStorage) RemoveEntries(first, last uint64) error {
	tx, err := fs.Begin(true)

	if err != nil {
		return err
	}

	defer tx.Rollback()

	c := tx.Bucket(logBucket).Cursor()
	k := make([]byte, 8)
	binary.BigEndian.PutUint64(k, first)
	c.Seek(k)

	for i := first; i <= last; i++ {
		if err := c.Delete(); err != nil {
			return err
		}

		c.Next()
	}

	if err := set(tx.Bucket(stateBucket), KeyNextIndex, first); err != nil {
		return err
	}

	return tx.Commit()
}

// FirstIndex implements the Storage interface.
func (fs *FileStorage) FirstIndex() (uint64, error) {
	return fs.Get(KeyFirstIndex)
}

// NextIndex implements the Storage interface.
func (fs *FileStorage) NextIndex() (uint64, error) {
	return fs.Get(KeyNextIndex)
}

// SetSnapshot implements the Storage interface.
func (fs *FileStorage) SetSnapshot(snapshot *commonpb.Snapshot) error {
	tx, err := fs.Begin(true)

	if err != nil {
		return err
	}

	defer tx.Rollback()

	k := make([]byte, 8)
	binary.BigEndian.PutUint64(k, KeySnapshot)

	v, err := snapshot.Marshal()

	if err != nil {
		return err
	}

	if err := tx.Bucket(stateBucket).Put(k, v); err != nil {
		return err
	}

	firstIndex := snapshot.LastIncludedIndex
	if err := set(tx.Bucket(stateBucket), KeyFirstIndex, firstIndex); err != nil {
		return err
	}
	nextIndex := firstIndex + 1
	if err := set(tx.Bucket(stateBucket), KeyNextIndex, nextIndex); err != nil {
		return err
	}

	return tx.Commit()
}

// GetSnapshot implements the Storage interface.
func (fs *FileStorage) GetSnapshot() (*commonpb.Snapshot, error) {
	tx, err := fs.Begin(false)

	if err != nil {
		return nil, err
	}

	defer tx.Rollback()

	k := make([]byte, 8)
	binary.BigEndian.PutUint64(k, KeySnapshot)

	val := tx.Bucket(stateBucket).Get(k)

	if val != nil {
		var snapshot commonpb.Snapshot
		err := snapshot.Unmarshal(val)

		if err != nil {
			return nil, err
		}

		return &snapshot, nil
	}

	return nil, ErrKeyNotFound
}
<commit_msg>raftgorums/filestorage.go: Add TODO<commit_after>package raftgorums

import (
	"encoding/binary"
	"errors"
	"os"

	"github.com/boltdb/bolt"
	"github.com/relab/raft/commonpb"
)

var (
	stateBucket    = []byte("state")
	logBucket      = []byte("log")
	snapshotBucket = []byte("snapshot")
)

// ErrKeyNotFound means that the given key could not be found in the storage.
var ErrKeyNotFound = errors.New("key not found")

// FileStorage is an implementation of the Storage interface for file based
// storage.
type FileStorage struct {
	*bolt.DB
}

// NewFileStorage returns a new FileStorage using the file given with the path
// argument. Overwrite decides whether to use the database if it already exists
// or overwrite it.
func NewFileStorage(path string, overwrite bool) (*FileStorage, error) {
	// Check if file already exists.
	if _, err := os.Stat(path); err != nil {
		if os.IsNotExist(err) {
			// We don't need to overwrite a file that doesn't exist.
			overwrite = false
		} else {
			// If we are unable to verify the existence of the file,
			// there is probably a permission problem.
			return nil, err
		}
	}

	// If overwrite is still true, the file must exist. Thus failing to
	// remove it is an error.
	if overwrite {
		if err := os.Remove(path); err != nil {
			return nil, err
		}
	}

	db, err := bolt.Open(path, 0600, nil)

	if err != nil {
		return nil, err
	}

	tx, err := db.Begin(true)

	if err != nil {
		return nil, err
	}

	defer tx.Rollback()

	if _, err := tx.CreateBucketIfNotExists(stateBucket); err != nil {
		return nil, err
	}

	if _, err := tx.CreateBucketIfNotExists(logBucket); err != nil {
		return nil, err
	}

	firstIndex := get(tx.Bucket(stateBucket), KeyFirstIndex)
	nextIndex := get(tx.Bucket(stateBucket), KeyNextIndex)

	if firstIndex == 0 {
		err := set(tx.Bucket(stateBucket), KeyFirstIndex, 1)
		if err != nil {
			return nil, err
		}
	}

	if nextIndex == 0 {
		err := set(tx.Bucket(stateBucket), KeyNextIndex, 1)
		if err != nil {
			return nil, err
		}
	}

	if err := tx.Commit(); err != nil {
		return nil, err
	}

	return &FileStorage{
		DB: db,
	}, nil
}

// Set implements the Storage interface.
func (fs *FileStorage) Set(key uint64, value uint64) error {
	tx, err := fs.Begin(true)

	if err != nil {
		return err
	}

	defer tx.Rollback()

	if err := set(tx.Bucket(stateBucket), key, value); err != nil {
		return err
	}

	return tx.Commit()
}

func set(bucket *bolt.Bucket, key uint64, value uint64) error {
	k := make([]byte, 8)
	v := make([]byte, 8)
	binary.BigEndian.PutUint64(k, key)
	binary.BigEndian.PutUint64(v, value)

	return bucket.Put(k, v)
}

// Get implements the Storage interface.
func (fs *FileStorage) Get(key uint64) (uint64, error) {
	tx, err := fs.Begin(false)

	if err != nil {
		return 0, err
	}

	defer tx.Rollback()

	return get(tx.Bucket(stateBucket), key), nil
}

func get(bucket *bolt.Bucket, key uint64) uint64 {
	k := make([]byte, 8)
	binary.BigEndian.PutUint64(k, key)

	val := bucket.Get(k)

	if val == nil {
		// Default to 0. This lets us get values not yet set.
		return 0
	}

	return binary.BigEndian.Uint64(val)
}

// StoreEntries implements the Storage interface.
func (fs *FileStorage) StoreEntries(entries []*commonpb.Entry) error {
	tx, err := fs.Begin(true)

	if err != nil {
		return err
	}

	defer tx.Rollback()

	k := make([]byte, 8)
	bucket := tx.Bucket(logBucket)

	for _, entry := range entries {
		binary.BigEndian.PutUint64(k, entry.Index)

		val, err := entry.Marshal()

		if err != nil {
			return err
		}

		if err := bucket.Put(k, val); err != nil {
			return err
		}
	}

	nextIndex := entries[len(entries)-1].Index + 1
	if err := set(tx.Bucket(stateBucket), KeyNextIndex, nextIndex); err != nil {
		return err
	}

	return tx.Commit()
}

// GetEntry implements the Storage interface.
func (fs *FileStorage) GetEntry(index uint64) (*commonpb.Entry, error) {
	tx, err := fs.Begin(false)

	if err != nil {
		return nil, err
	}

	defer tx.Rollback()

	bucket := tx.Bucket(logBucket)

	k := make([]byte, 8)
	binary.BigEndian.PutUint64(k, index)

	if val := bucket.Get(k); val != nil {
		var entry commonpb.Entry
		err := entry.Unmarshal(val)

		if err != nil {
			return nil, err
		}

		return &entry, nil
	}

	return nil, ErrKeyNotFound
}

// GetEntries implements the Storage interface.
// TODO We can reduce allocation by passing the slice to fill.
func (fs *FileStorage) GetEntries(first, last uint64) ([]*commonpb.Entry, error) {
	tx, err := fs.Begin(false)

	if err != nil {
		return nil, err
	}

	defer tx.Rollback()

	bucket := tx.Bucket(logBucket)

	entries := make([]*commonpb.Entry, last-first+1)
	k := make([]byte, 8)

	i := first
	for j := range entries {
		binary.BigEndian.PutUint64(k, i)

		val := bucket.Get(k)

		if val == nil {
			return nil, ErrKeyNotFound
		}

		var entry commonpb.Entry
		err := entry.Unmarshal(val)

		if err != nil {
			return nil, err
		}

		entries[j] = &entry
		i++

	}

	return entries, nil
}

// RemoveEntries implements the Storage interface.
func (fs *FileStorage) RemoveEntries(first, last uint64) error {
	tx, err := fs.Begin(true)

	if err != nil {
		return err
	}

	defer tx.Rollback()

	c := tx.Bucket(logBucket).Cursor()
	k := make([]byte, 8)
	binary.BigEndian.PutUint64(k, first)
	c.Seek(k)

	for i := first; i <= last; i++ {
		if err := c.Delete(); err != nil {
			return err
		}

		c.Next()
	}

	if err := set(tx.Bucket(stateBucket), KeyNextIndex, first); err != nil {
		return err
	}

	return tx.Commit()
}

// FirstIndex implements the Storage interface.
func (fs *FileStorage) FirstIndex() (uint64, error) {
	return fs.Get(KeyFirstIndex)
}

// NextIndex implements the Storage interface.
func (fs *FileStorage) NextIndex() (uint64, error) {
	return fs.Get(KeyNextIndex)
}

// SetSnapshot implements the Storage interface.
func (fs *FileStorage) SetSnapshot(snapshot *commonpb.Snapshot) error {
	tx, err := fs.Begin(true)

	if err != nil {
		return err
	}

	defer tx.Rollback()

	k := make([]byte, 8)
	binary.BigEndian.PutUint64(k, KeySnapshot)

	v, err := snapshot.Marshal()

	if err != nil {
		return err
	}

	if err := tx.Bucket(stateBucket).Put(k, v); err != nil {
		return err
	}

	firstIndex := snapshot.LastIncludedIndex
	if err := set(tx.Bucket(stateBucket), KeyFirstIndex, firstIndex); err != nil {
		return err
	}
	nextIndex := firstIndex + 1
	if err := set(tx.Bucket(stateBucket), KeyNextIndex, nextIndex); err != nil {
		return err
	}

	return tx.Commit()
}

// GetSnapshot implements the Storage interface.
func (fs *FileStorage) GetSnapshot() (*commonpb.Snapshot, error) {
	tx, err := fs.Begin(false)

	if err != nil {
		return nil, err
	}

	defer tx.Rollback()

	k := make([]byte, 8)
	binary.BigEndian.PutUint64(k, KeySnapshot)

	val := tx.Bucket(stateBucket).Get(k)

	if val != nil {
		var snapshot commonpb.Snapshot
		err := snapshot.Unmarshal(val)

		if err != nil {
			return nil, err
		}

		return &snapshot, nil
	}

	return nil, ErrKeyNotFound
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"flag"
	"log"

	"github.com/google/trillian"
	"google.golang.org/grpc"
)

var (
	trillianLog = flag.String("trillian_log", "localhost:8090", "address of the Trillian Log RPC server.")
	logID       = flag.Int64("log_id", 0, "Trillian LogID to populate.")
)

const CHUNK = 10

func main() {
	flag.Parse()

	g, err := grpc.Dial(*trillianLog, grpc.WithInsecure())
	if err != nil {
		log.Fatalf("Failed to dial Trillian Log: %v", err)
	}
	defer g.Close()

	tc := trillian.NewTrillianLogClient(g)
	ctx := context.Background()

	rr := &trillian.GetLatestSignedLogRootRequest{LogId: *logID}
	lr, err := tc.GetLatestSignedLogRoot(ctx, rr)
	if err != nil {
		log.Fatalf("Can't get log root: %v", err)
	}

	ts := lr.SignedLogRoot.TreeSize
	for n := int64(0); n < ts; {
		g := &trillian.GetLeavesByRangeRequest{LogId: *logID, StartIndex: n, Count: CHUNK}
		r, err := tc.GetLeavesByRange(ctx, g)
		if err != nil {
			log.Fatalf("Can't get leaf %d: %v", n, err)
		}

		// deal with server skew
		if r.Skew.GetTreeSizeSet() {
			ts = r.Skew.GetTreeSize()
			log.Printf("Skew")
		}

		if n < ts && len(r.Leaves) == 0 {
			log.Fatalf("No progress at leaf %d", n)
		}

		for m := 0; m < len(r.Leaves) && n < ts; n++ {
			if r.Leaves[m] == nil {
				log.Fatalf("Can't get leaf %d (no error)", n)
			}
			log.Printf("leaf %d: %v", n, r.Leaves[m])
			m++
		}
	}
}
<commit_msg>Update skew handling to new API.<commit_after>package main

import (
	"context"
	"flag"
	"log"

	"github.com/google/trillian"
	"google.golang.org/grpc"
)

var (
	trillianLog = flag.String("trillian_log", "localhost:8090", "address of the Trillian Log RPC server.")
	logID       = flag.Int64("log_id", 0, "Trillian LogID to populate.")
)

const CHUNK = 10

func main() {
	flag.Parse()

	g, err := grpc.Dial(*trillianLog, grpc.WithInsecure())
	if err != nil {
		log.Fatalf("Failed to dial Trillian Log: %v", err)
	}
	defer g.Close()

	tc := trillian.NewTrillianLogClient(g)
	ctx := context.Background()

	rr := &trillian.GetLatestSignedLogRootRequest{LogId: *logID}
	lr, err := tc.GetLatestSignedLogRoot(ctx, rr)
	if err != nil {
		log.Fatalf("Can't get log root: %v", err)
	}

	ts := lr.SignedLogRoot.TreeSize
	for n := int64(0); n < ts; {
		g := &trillian.GetLeavesByRangeRequest{LogId: *logID, StartIndex: n, Count: CHUNK}
		r, err := tc.GetLeavesByRange(ctx, g)
		if err != nil {
			log.Fatalf("Can't get leaf %d: %v", n, err)
		}

		// deal with server skew
		if r.SignedLogRoot.TreeSize < ts {
			ts = r.SignedLogRoot.TreeSize
			log.Printf("Skew")
		}

		if n < ts && len(r.Leaves) == 0 {
			log.Fatalf("No progress at leaf %d", n)
		}

		for m := 0; m < len(r.Leaves) && n < ts; n++ {
			if r.Leaves[m] == nil {
				log.Fatalf("Can't get leaf %d (no error)", n)
			}
			log.Printf("leaf %d: %v", n, r.Leaves[m])
			m++
		}
	}
}
<|endoftext|>


<commit_before>package registry

import (
	"testing"
)

func TestTypeConversion(t *testing.T) {
	// TODO: Are there some real-world examples we want to validate here?
	tests := map[string]Type{
		"foo":                   NewTypeOrDie("", "foo", ""),
		"foo:v1":                NewTypeOrDie("", "foo", "v1"),
		"github.com/foo":        NewTypeOrDie("github.com", "foo", ""),
		"github.com/foo:v1.2.3": NewTypeOrDie("github.com", "foo", "v1.2.3"),
	}

	for in, expect := range tests {
		out, err := ParseType(in)
		if err != nil {
			t.Errorf("Error parsing type string %s: $s", in, err)
		}

		if out.Name != expect.Name {
			t.Errorf("Expected name to be %q, got %q", expect.Name, out.Name)
		}

		if out.GetVersion() != expect.GetVersion() {
			t.Errorf("Expected version to be %q, got %q", expect.GetVersion(), out.GetVersion())
		}

		if out.Collection != expect.Collection {
			t.Errorf("Expected collection to be %q, got %q", expect.Collection, out.Collection)
		}

		svalue := out.String()
		if svalue != in {
			t.Errorf("Expected string value to be %q, got %q", in, svalue)
		}
	}
}
<commit_msg>fix string formatting typo<commit_after>package registry

import (
	"testing"
)

func TestTypeConversion(t *testing.T) {
	// TODO: Are there some real-world examples we want to validate here?
	tests := map[string]Type{
		"foo":                   NewTypeOrDie("", "foo", ""),
		"foo:v1":                NewTypeOrDie("", "foo", "v1"),
		"github.com/foo":        NewTypeOrDie("github.com", "foo", ""),
		"github.com/foo:v1.2.3": NewTypeOrDie("github.com", "foo", "v1.2.3"),
	}

	for in, expect := range tests {
		out, err := ParseType(in)
		if err != nil {
			t.Errorf("Error parsing type string %s: %s", in, err)
		}

		if out.Name != expect.Name {
			t.Errorf("Expected name to be %q, got %q", expect.Name, out.Name)
		}

		if out.GetVersion() != expect.GetVersion() {
			t.Errorf("Expected version to be %q, got %q", expect.GetVersion(), out.GetVersion())
		}

		if out.Collection != expect.Collection {
			t.Errorf("Expected collection to be %q, got %q", expect.Collection, out.Collection)
		}

		svalue := out.String()
		if svalue != in {
			t.Errorf("Expected string value to be %q, got %q", in, svalue)
		}
	}
}
<|endoftext|>


<commit_before>package report

import (
	"crypto/x509"
	"encoding/json"
	"io/ioutil"
	"time"
)

type PGPKey struct {
	ArmoredKey  string `json:"armoredKey"`
	Identity    string `json:"identity"`
	FingerPrint string `json:"fingerprint"`
}

type BitcoinService struct {
	Detected        bool     `json:"detected"`
	UserAgent       string   `json:"userAgent"`
	ProtocolVersion int      `json:"prototocolVersion"`
	OnionPeers      []string `json:"onionPeers"`
}

type OnionScanReport struct {
	HiddenService  string    `json:"hiddenService"`
	DateScanned    time.Time `json:"dateScanned"`
	Online         bool      `json:"online"`
	PerformedScans []string  `json:"performedScans"`

	// Summary
	WebDetected      bool `json:"webDetected"`
	TLSDetected      bool `json:"tlsDetected"`
	SSHDetected      bool `json:"sshDetected"`
	RicochetDetected bool `json:"ricochetDetected"`
	IRCDetected      bool `json:"ircDetected"`
	FTPDetected      bool `json:"ftpDetected"`
	SMTPDetected     bool `json:"smtpDetected"`
	BitcoinDetected  bool `json:"bitcoinDetected"`
	MongoDBDetected  bool `json:"mongodbDetected"`
	VNCDetected      bool `json:"vncDetected"`
	XMPPDetected     bool `json:"xmppDetected"`
	SkynetDetected   bool `json:"skynetDetected"`

	// Site Specific
	Crawls map[string]int `json:"crawls"`

	// Page Content
	PGPKeys []PGPKey `json:"pgpKeys"`

	// TLS
	Certificates []x509.Certificate `json:"certificates"`

	// Bitcoin
	BitcoinAddresses []string                   `json:"bitcoinAddresses"`
	BitcoinServices  map[string]*BitcoinService `json:"bitcoinServices"`

	// SSH
	SSHKey    string `json:"sshKey"`
	SSHBanner string `json:"sshBanner"`

	// FTP
	FTPFingerprint string `json:"ftpFingerprint"`
	FTPBanner      string `json:"ftpBanner"`

	// SMTP
	SMTPFingerprint string `json:"smtpFingerprint"`
	SMTPBanner      string `json:"smtpBanner"`

	NextAction string `json:"lastAction"`
	TimedOut   bool
}

func LoadReportFromFile(filename string) (OnionScanReport, error) {
	dat, err := ioutil.ReadFile(filename)
	if err != nil {
		return OnionScanReport{}, err
	}
	res := OnionScanReport{}
	err = json.Unmarshal(dat, &res)
	return res, err
}

func NewOnionScanReport(hiddenService string) *OnionScanReport {
	report := new(OnionScanReport)
	report.HiddenService = hiddenService
	report.DateScanned = time.Now()
	report.Crawls = make(map[string]int)
	report.PerformedScans = []string{}
	report.BitcoinServices = make(map[string]*BitcoinService)
	return report
}

func (osr *OnionScanReport) AddPGPKey(armoredKey, identity, fingerprint string) {
	osr.PGPKeys = append(osr.PGPKeys, PGPKey{armoredKey, identity, fingerprint})
	//TODO map of fingerprint:PGPKeys? and  utils.RemoveDuplicates(&osr.PGPKeys)
}

func (osr *OnionScanReport) AddBitcoinService(name string) *BitcoinService {
	var s = new(BitcoinService)
	osr.BitcoinServices[name] = s
	return s
}

func (osr *OnionScanReport) Serialize() (string, error) {
	report, err := json.Marshal(osr)
	if err != nil {
		return "", err
	}
	return string(report), nil
}
<commit_msg>Remove unused field OnionScanReport.BitcoinAddresses<commit_after>package report

import (
	"crypto/x509"
	"encoding/json"
	"io/ioutil"
	"time"
)

type PGPKey struct {
	ArmoredKey  string `json:"armoredKey"`
	Identity    string `json:"identity"`
	FingerPrint string `json:"fingerprint"`
}

type BitcoinService struct {
	Detected        bool     `json:"detected"`
	UserAgent       string   `json:"userAgent"`
	ProtocolVersion int      `json:"prototocolVersion"`
	OnionPeers      []string `json:"onionPeers"`
}

type OnionScanReport struct {
	HiddenService  string    `json:"hiddenService"`
	DateScanned    time.Time `json:"dateScanned"`
	Online         bool      `json:"online"`
	PerformedScans []string  `json:"performedScans"`

	// Summary
	WebDetected      bool `json:"webDetected"`
	TLSDetected      bool `json:"tlsDetected"`
	SSHDetected      bool `json:"sshDetected"`
	RicochetDetected bool `json:"ricochetDetected"`
	IRCDetected      bool `json:"ircDetected"`
	FTPDetected      bool `json:"ftpDetected"`
	SMTPDetected     bool `json:"smtpDetected"`
	BitcoinDetected  bool `json:"bitcoinDetected"`
	MongoDBDetected  bool `json:"mongodbDetected"`
	VNCDetected      bool `json:"vncDetected"`
	XMPPDetected     bool `json:"xmppDetected"`
	SkynetDetected   bool `json:"skynetDetected"`

	// Site Specific
	Crawls map[string]int `json:"crawls"`

	// Page Content
	PGPKeys []PGPKey `json:"pgpKeys"`

	// TLS
	Certificates []x509.Certificate `json:"certificates"`

	// Bitcoin
	BitcoinServices map[string]*BitcoinService `json:"bitcoinServices"`

	// SSH
	SSHKey    string `json:"sshKey"`
	SSHBanner string `json:"sshBanner"`

	// FTP
	FTPFingerprint string `json:"ftpFingerprint"`
	FTPBanner      string `json:"ftpBanner"`

	// SMTP
	SMTPFingerprint string `json:"smtpFingerprint"`
	SMTPBanner      string `json:"smtpBanner"`

	NextAction string `json:"lastAction"`
	TimedOut   bool
}

func LoadReportFromFile(filename string) (OnionScanReport, error) {
	dat, err := ioutil.ReadFile(filename)
	if err != nil {
		return OnionScanReport{}, err
	}
	res := OnionScanReport{}
	err = json.Unmarshal(dat, &res)
	return res, err
}

func NewOnionScanReport(hiddenService string) *OnionScanReport {
	report := new(OnionScanReport)
	report.HiddenService = hiddenService
	report.DateScanned = time.Now()
	report.Crawls = make(map[string]int)
	report.PerformedScans = []string{}
	report.BitcoinServices = make(map[string]*BitcoinService)
	return report
}

func (osr *OnionScanReport) AddPGPKey(armoredKey, identity, fingerprint string) {
	osr.PGPKeys = append(osr.PGPKeys, PGPKey{armoredKey, identity, fingerprint})
	//TODO map of fingerprint:PGPKeys? and  utils.RemoveDuplicates(&osr.PGPKeys)
}

func (osr *OnionScanReport) AddBitcoinService(name string) *BitcoinService {
	var s = new(BitcoinService)
	osr.BitcoinServices[name] = s
	return s
}

func (osr *OnionScanReport) Serialize() (string, error) {
	report, err := json.Marshal(osr)
	if err != nil {
		return "", err
	}
	return string(report), nil
}
<|endoftext|>


<commit_before>package core

import (
	// "github.com/boltdb/bolt"
	"bufio"
	"errors"
	// "log"
	"os/exec"
	"strconv"
	"strings"
	"time"
)

const (
	CAny       = "*"
	CDash      = "-"
	CBackslash = "/"
	CComma     = ","
)

var badTime = errors.New("bad crontab syntax")

//reading and create tasks from linux crontab
//crontab -l command
func fromCrontab(c int) (tasks []Task, err error) {
	tasks = make([]Task, 0, c)
	cmd := exec.Command("crontab", "-l")
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return nil, err
	}

	if err := cmd.Start(); err != nil {
		return nil, err
	}
	scanner := bufio.NewScanner(stdout)
	for scanner.Scan() {
		s := scanner.Text()
		//ignore comments
		if strings.HasPrefix(s, "#") {
			continue
		}
		task := ResolveTask(s)
		tasks = append(tasks, *task)
	}
	if err := scanner.Err(); err != nil {
		return nil, err
	}

	return
}

//checking times contains by crontab times
//some crontab usage follow
//min   hour    day     mon week
//30    21      *       *   *
//45    4       1,10,22 *   *
//0,30  18-23   *       *   *
//*     */2     *       *   *
//*     23-7/1  *       *   *
//0     4       1       jan *
func checkInCrontabTime(s_times []string, t_times []int, tm time.Time) (ok bool, err error) {
	for i, t := range s_times {
		ok, err = resolveCrontabTimeAtom(TDate(i), t_times[i], t, tm)
		if err != nil {
			return false, err
		}
		if !ok {
			return false, nil
		}
	}
	return ok, nil
}

//resolve ',' '-','/'
func resolveCrontabTimeAtom(dt TDate, dst int, atom_desc string, t time.Time) (ok bool, err error) {
	if atom_desc == CAny {
		return true, nil
	}

	//month word
	if dt == TMonth {
		atom_desc = strings.ToLower(atom_desc)
		for i, wm := range Months {
			atom_desc = strings.Replace(atom_desc, wm, strconv.Itoa(i+1), -1)
		}
	}

	//backslash
	if strings.Contains(atom_desc, CBackslash) {
		re_times := strings.Split(atom_desc, CBackslash)
		if len(re_times) != 2 {
			return false, badTime
		}
		//*/n (n>1) not support  yet
		return resolveCrontabTimeAtom(dt, dst, re_times[0], t)
	}

	//comma
	if strings.Contains(atom_desc, CComma) {
		dstr := strconv.Itoa(dst)
		for _, v := range strings.Split(atom_desc, CComma) {
			if dstr == v {
				return true, nil
			}
		}
		return false, nil
	}

	//dash
	if strings.Contains(atom_desc, CDash) {
		re_times, err := asTois(strings.Split(atom_desc, CDash))
		if err != nil {
			return false, err
		}
		if len(re_times) != 2 {
			return false, badTime
		}
		if re_times[0] < re_times[1] {
			return re_times[0] <= dst && dst <= re_times[1], nil
		}
		tmax := TDateMax(dt, t)
		return (re_times[0] <= dst && dst <= tmax) || (0 <= dst && dst <= re_times[1]), nil
	}

	return strconv.Itoa(dst) == atom_desc, nil
}

//convert []string to []int
func asTois(strs []string) (re_ints []int, err error) {
	re_ints = make([]int, len(strs))
	for i, v := range strs {
		re_ints[i], err = strconv.Atoi(v)
		if err != nil {
			return nil, err
		}
	}
	return re_ints, nil
}
<commit_msg>add not support error<commit_after>package core

import (
	// "github.com/boltdb/bolt"
	"bufio"
	"errors"
	// "log"
	"os/exec"
	"strconv"
	"strings"
	"time"
)

const (
	CAny       = "*"
	CDash      = "-"
	CBackslash = "/"
	CComma     = ","
)

var badTime = errors.New("bad crontab syntax")

//reading and create tasks from linux crontab
//crontab -l command
func fromCrontab(c int) (tasks []Task, err error) {
	tasks = make([]Task, 0, c)
	cmd := exec.Command("crontab", "-l")
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return nil, err
	}

	if err := cmd.Start(); err != nil {
		return nil, err
	}
	scanner := bufio.NewScanner(stdout)
	for scanner.Scan() {
		s := scanner.Text()
		//ignore comments
		if strings.HasPrefix(s, "#") {
			continue
		}
		task := ResolveTask(s)
		tasks = append(tasks, *task)
	}
	if err := scanner.Err(); err != nil {
		return nil, err
	}

	return
}

//checking times contains by crontab times
//some crontab usage follow
//min   hour    day     mon week
//30    21      *       *   *
//45    4       1,10,22 *   *
//0,30  18-23   *       *   *
//*     */2     *       *   *
//*     23-7/1  *       *   *
//0     4       1       jan *
func checkInCrontabTime(s_times []string, t_times []int, tm time.Time) (ok bool, err error) {
	for i, t := range s_times {
		ok, err = resolveCrontabTimeAtom(TDate(i), t_times[i], t, tm)
		if err != nil {
			return false, err
		}
		if !ok {
			return false, nil
		}
	}
	return ok, nil
}

//resolve ',' '-','/'
func resolveCrontabTimeAtom(dt TDate, dst int, atom_desc string, t time.Time) (ok bool, err error) {
	if atom_desc == CAny {
		return true, nil
	}

	//month word
	if dt == TMonth {
		atom_desc = strings.ToLower(atom_desc)
		for i, wm := range Months {
			atom_desc = strings.Replace(atom_desc, wm, strconv.Itoa(i+1), -1)
		}
	}

	//backslash
	if strings.Contains(atom_desc, CBackslash) {
		re_times := strings.Split(atom_desc, CBackslash)
		if len(re_times) != 2 {
			return false, badTime
		}
		//*/n (n>1) not support  yet
		if re_times[1] != "1" {
			return false, errors.New("*/n (n>1) not support yet")
		}
		return resolveCrontabTimeAtom(dt, dst, re_times[0], t)
	}

	//comma
	if strings.Contains(atom_desc, CComma) {
		dstr := strconv.Itoa(dst)
		for _, v := range strings.Split(atom_desc, CComma) {
			if dstr == v {
				return true, nil
			}
		}
		return false, nil
	}

	//dash
	if strings.Contains(atom_desc, CDash) {
		re_times, err := asTois(strings.Split(atom_desc, CDash))
		if err != nil {
			return false, err
		}
		if len(re_times) != 2 {
			return false, badTime
		}
		if re_times[0] < re_times[1] {
			return re_times[0] <= dst && dst <= re_times[1], nil
		}
		tmax := TDateMax(dt, t)
		return (re_times[0] <= dst && dst <= tmax) || (0 <= dst && dst <= re_times[1]), nil
	}

	return strconv.Itoa(dst) == atom_desc, nil
}

//convert []string to []int
func asTois(strs []string) (re_ints []int, err error) {
	re_ints = make([]int, len(strs))
	for i, v := range strs {
		re_ints[i], err = strconv.Atoi(v)
		if err != nil {
			return nil, err
		}
	}
	return re_ints, nil
}
<|endoftext|>