running dep prune

This commit is contained in:
Cory Bennett
2017-09-11 00:11:56 -07:00
parent 608e586d1c
commit c3c008e53d
407 changed files with 0 additions and 69344 deletions
-2
View File
@@ -1,2 +0,0 @@
{{define "x"}}TEXT{{end}}
{{define "dotV"}}{{.V}}{{end}}
-2
View File
@@ -1,2 +0,0 @@
{{define "dot"}}{{.}}{{end}}
{{define "nested"}}{{template "dot" .}}{{end}}
-3
View File
@@ -1,3 +0,0 @@
template1
{{define "x"}}x{{end}}
{{template "y"}}
-3
View File
@@ -1,3 +0,0 @@
template2
{{define "y"}}y{{end}}
{{template "x"}}
-12
View File
@@ -1,12 +0,0 @@
package math
import "github.com/cheekybits/genny/generic"
type ThisNumberType generic.Number
func ThisNumberTypeMax(fn func(a, b ThisNumberType) bool, a, b ThisNumberType) ThisNumberType {
if fn(a, b) {
return a
}
return b
}
-3
View File
@@ -1,3 +0,0 @@
#!/bin/bash
cat ./generic_max.go | ../../genny gen "NumberType=NUMBERS" > numbers_max_get.go
cat ./func_thing.go | ../../genny gen "ThisNumberType=NUMBERS" > numbers_func_thing.go
-14
View File
@@ -1,14 +0,0 @@
package math
import "github.com/cheekybits/genny/generic"
type NumberType generic.Number
// NumberTypeMax gets the maximum number from the
// two specified.
func NumberTypeMax(a, b NumberType) NumberType {
if a > b {
return a
}
return b
}
-27
View File
@@ -1,27 +0,0 @@
package math_test
import (
"testing"
"github.com/cheekybits/genny/examples/davechaney"
)
func TestNumberTypeMax(t *testing.T) {
var v math.NumberType
v = math.NumberTypeMax(10, 20)
if v != 20 {
t.Errorf("Max of 10 and 20 is 20")
}
v = math.NumberTypeMax(20, 20)
if v != 20 {
t.Errorf("Max of 20 and 20 is 20")
}
v = math.NumberTypeMax(25, 20)
if v != 25 {
t.Errorf("Max of 25 and 20 is 25")
}
}
@@ -1,89 +0,0 @@
// This file was automatically generated by genny.
// Any changes will be lost if this file is regenerated.
// see https://github.com/cheekybits/genny
package math
func Float32Max(fn func(a, b float32) bool, a, b float32) float32 {
if fn(a, b) {
return a
}
return b
}
func Float64Max(fn func(a, b float64) bool, a, b float64) float64 {
if fn(a, b) {
return a
}
return b
}
func IntMax(fn func(a, b int) bool, a, b int) int {
if fn(a, b) {
return a
}
return b
}
func Int16Max(fn func(a, b int16) bool, a, b int16) int16 {
if fn(a, b) {
return a
}
return b
}
func Int32Max(fn func(a, b int32) bool, a, b int32) int32 {
if fn(a, b) {
return a
}
return b
}
func Int64Max(fn func(a, b int64) bool, a, b int64) int64 {
if fn(a, b) {
return a
}
return b
}
func Int8Max(fn func(a, b int8) bool, a, b int8) int8 {
if fn(a, b) {
return a
}
return b
}
func UintMax(fn func(a, b uint) bool, a, b uint) uint {
if fn(a, b) {
return a
}
return b
}
func Uint16Max(fn func(a, b uint16) bool, a, b uint16) uint16 {
if fn(a, b) {
return a
}
return b
}
func Uint32Max(fn func(a, b uint32) bool, a, b uint32) uint32 {
if fn(a, b) {
return a
}
return b
}
func Uint64Max(fn func(a, b uint64) bool, a, b uint64) uint64 {
if fn(a, b) {
return a
}
return b
}
func Uint8Max(fn func(a, b uint8) bool, a, b uint8) uint8 {
if fn(a, b) {
return a
}
return b
}
@@ -1,29 +0,0 @@
// This file was automatically generated by genny.
// Any changes will be lost if this file is regenerated.
// see https://github.com/cheekybits/genny
package gogenerate
type StringStringMap map[string]string
func NewStringStringMap() map[string]string {
return make(map[string]string)
}
type StringIntMap map[string]int
func NewStringIntMap() map[string]int {
return make(map[string]int)
}
type IntStringMap map[int]string
func NewIntStringMap() map[int]string {
return make(map[int]string)
}
type IntIntMap map[int]int
func NewIntIntMap() map[int]int {
return make(map[int]int)
}
-14
View File
@@ -1,14 +0,0 @@
package gogenerate
import "github.com/cheekybits/genny/generic"
//go:generate genny -in=$GOFILE -out=gen-$GOFILE gen "KeyType=string,int ValueType=string,int"
type KeyType generic.Type
type ValueType generic.Type
type KeyTypeValueTypeMap map[KeyType]ValueType
func NewKeyTypeValueTypeMap() map[KeyType]ValueType {
return make(map[KeyType]ValueType)
}
-2
View File
@@ -1,2 +0,0 @@
#!/bin/bash
cat ./queue_generic.go | ../../genny gen "Generic=string,int" > queue_generic_gen.go
-33
View File
@@ -1,33 +0,0 @@
package example
import "github.com/cheekybits/genny/generic"
type Generic generic.Type
// GenericQueue represents a queue of Generic types.
type GenericQueue struct {
items []Generic
}
// NewGenericQueue makes a new empty Generic queue.
func NewGenericQueue() *GenericQueue {
return &GenericQueue{items: make([]Generic, 0)}
}
// Enq adds an item to the queue.
func (q *GenericQueue) Enq(obj Generic) *GenericQueue {
q.items = append(q.items, obj)
return q
}
// Deq removes and returns the next item in the queue.
func (q *GenericQueue) Deq() Generic {
obj := q.items[0]
q.items = q.items[1:]
return obj
}
// Len gets the current number of Generic items in the queue.
func (q *GenericQueue) Len() int {
return len(q.items)
}
@@ -1,32 +0,0 @@
package example
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNew(t *testing.T) {
q := NewGenericQueue()
assert.NotNil(t, q)
}
func TestEnqueueAndDequeue(t *testing.T) {
item1 := new(Generic)
item2 := new(Generic)
q := NewGenericQueue()
assert.Equal(t, q, q.Enq(item1), "Enq should return the queue")
assert.Equal(t, 1, q.Len())
assert.Equal(t, q, q.Enq(item2), "Enq should return the queue")
assert.Equal(t, 2, q.Len())
assert.Equal(t, item1, q.Deq())
assert.Equal(t, 1, q.Len())
assert.Equal(t, item2, q.Deq())
assert.Equal(t, 0, q.Len())
}
-41
View File
@@ -1,41 +0,0 @@
package parse
// Builtins contains a slice of all built-in Go types.
var Builtins = []string{
"bool",
"byte",
"complex128",
"complex64",
"error",
"float32",
"float64",
"int",
"int16",
"int32",
"int64",
"int8",
"rune",
"string",
"uint",
"uint16",
"uint32",
"uint64",
"uint8",
"uintptr",
}
// Numbers contains a slice of all built-in number types.
var Numbers = []string{
"float32",
"float64",
"int",
"int16",
"int32",
"int64",
"int8",
"uint",
"uint16",
"uint32",
"uint64",
"uint8",
}
-14
View File
@@ -1,14 +0,0 @@
// Package parse contains the generic code generation capabilities
// that power genny.
//
// genny gen "{types}"
//
// gen - generates type specific code (to stdout) from generic code (via stdin)
//
// {types} - (required) Specific types for each generic type in the source
// {types} format: {generic}={specific}[,another][ {generic2}={specific2}]
// Examples:
// Generic=Specific
// Generic1=Specific1 Generic2=Specific2
// Generic1=Specific1,Specific2 Generic2=Specific3,Specific4
package parse
-47
View File
@@ -1,47 +0,0 @@
package parse
import (
"errors"
)
// errMissingSpecificType represents an error when a generic type is not
// satisfied by a specific type.
type errMissingSpecificType struct {
GenericType string
}
// Error gets a human readable string describing this error.
func (e errMissingSpecificType) Error() string {
return "Missing specific type for '" + e.GenericType + "' generic type"
}
// errImports represents an error from goimports.
type errImports struct {
Err error
}
// Error gets a human readable string describing this error.
func (e errImports) Error() string {
return "Failed to goimports the generated code: " + e.Err.Error()
}
// errSource represents an error with the source file.
type errSource struct {
Err error
}
// Error gets a human readable string describing this error.
func (e errSource) Error() string {
return "Failed to parse source file: " + e.Err.Error()
}
type errBadTypeArgs struct {
Message string
Arg string
}
func (e errBadTypeArgs) Error() string {
return "\"" + e.Arg + "\" is bad: " + e.Message
}
var errMissingTypeInformation = errors.New("No type arguments were specified and no \"// +gogen\" tag was found in the source.")
-271
View File
@@ -1,271 +0,0 @@
package parse
import (
"bufio"
"bytes"
"fmt"
"go/ast"
"go/parser"
"go/token"
"io"
"os"
"strings"
"unicode"
"golang.org/x/tools/imports"
)
type isExported bool
var header = []byte(`
// This file was automatically generated by genny.
// Any changes will be lost if this file is regenerated.
// see https://github.com/cheekybits/genny
`)
var (
packageKeyword = []byte("package")
importKeyword = []byte("import")
openBrace = []byte("(")
closeBrace = []byte(")")
space = " "
genericPackage = "generic"
genericType = "generic.Type"
genericNumber = "generic.Number"
linefeed = "\r\n"
)
var unwantedLinePrefixes = [][]byte{
[]byte("//go:generate genny "),
}
func generateSpecific(filename string, in io.ReadSeeker, typeSet map[string]string) ([]byte, error) {
// ensure we are at the beginning of the file
in.Seek(0, os.SEEK_SET)
// parse the source file
fs := token.NewFileSet()
file, err := parser.ParseFile(fs, filename, in, 0)
if err != nil {
return nil, &errSource{Err: err}
}
// make sure every generic.Type is represented in the types
// argument.
for _, decl := range file.Decls {
switch it := decl.(type) {
case *ast.GenDecl:
for _, spec := range it.Specs {
ts, ok := spec.(*ast.TypeSpec)
if !ok {
continue
}
switch tt := ts.Type.(type) {
case *ast.SelectorExpr:
if name, ok := tt.X.(*ast.Ident); ok {
if name.Name == genericPackage {
if _, ok := typeSet[ts.Name.Name]; !ok {
return nil, &errMissingSpecificType{GenericType: ts.Name.Name}
}
}
}
}
}
}
}
// go back to the start of the file
in.Seek(0, os.SEEK_SET)
var buf bytes.Buffer
comment := ""
scanner := bufio.NewScanner(in)
for scanner.Scan() {
l := scanner.Text()
// does this line contain generic.Type?
if strings.Contains(l, genericType) || strings.Contains(l, genericNumber) {
comment = ""
continue
}
for t, specificType := range typeSet {
// does the line contain our type
if strings.Contains(l, t) {
var newLine string
// check each word
for _, word := range strings.Fields(l) {
i := 0
for {
i = strings.Index(word[i:], t) // find out where
if i > -1 {
// if this isn't an exact match
if i > 0 && isAlphaNumeric(rune(word[i-1])) || i < len(word)-len(t) && isAlphaNumeric(rune(word[i+len(t)])) {
// replace the word with a capitolized version
word = strings.Replace(word, t, wordify(specificType, unicode.IsUpper(rune(strings.TrimLeft(word, "*&")[0]))), 1)
} else {
// replace the word as is
word = strings.Replace(word, t, specificType, 1)
}
} else {
newLine = newLine + word + space
break
}
}
}
l = newLine
}
}
if comment != "" {
buf.WriteString(line(comment))
comment = ""
}
// is this line a comment?
// TODO: should we handle /* */ comments?
if strings.HasPrefix(l, "//") {
// record this line to print later
comment = l
continue
}
// write the line
buf.WriteString(line(l))
}
// write it out
return buf.Bytes(), nil
}
// Generics parses the source file and generates the bytes replacing the
// generic types for the keys map with the specific types (its value).
func Generics(filename, pkgName string, in io.ReadSeeker, typeSets []map[string]string) ([]byte, error) {
totalOutput := header
for _, typeSet := range typeSets {
// generate the specifics
parsed, err := generateSpecific(filename, in, typeSet)
if err != nil {
return nil, err
}
totalOutput = append(totalOutput, parsed...)
}
// clean up the code line by line
packageFound := false
insideImportBlock := false
var cleanOutputLines []string
scanner := bufio.NewScanner(bytes.NewReader(totalOutput))
for scanner.Scan() {
// end of imports block?
if insideImportBlock {
if bytes.HasSuffix(scanner.Bytes(), closeBrace) {
insideImportBlock = false
}
continue
}
if bytes.HasPrefix(scanner.Bytes(), packageKeyword) {
if packageFound {
continue
} else {
packageFound = true
}
} else if bytes.HasPrefix(scanner.Bytes(), importKeyword) {
if bytes.HasSuffix(scanner.Bytes(), openBrace) {
insideImportBlock = true
}
continue
}
// check all unwantedLinePrefixes - and skip them
skipline := false
for _, prefix := range unwantedLinePrefixes {
if bytes.HasPrefix(scanner.Bytes(), prefix) {
skipline = true
continue
}
}
if skipline {
continue
}
cleanOutputLines = append(cleanOutputLines, line(scanner.Text()))
}
cleanOutput := strings.Join(cleanOutputLines, "")
output := []byte(cleanOutput)
var err error
// change package name
if pkgName != "" {
output = changePackage(bytes.NewReader([]byte(output)), pkgName)
}
// fix the imports
output, err = imports.Process(filename, output, nil)
if err != nil {
return nil, &errImports{Err: err}
}
return output, nil
}
func line(s string) string {
return fmt.Sprintln(strings.TrimRight(s, linefeed))
}
// isAlphaNumeric gets whether the rune is alphanumeric or _.
func isAlphaNumeric(r rune) bool {
return r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r)
}
// wordify turns a type into a nice word for function and type
// names etc.
func wordify(s string, exported bool) string {
s = strings.TrimRight(s, "{}")
s = strings.TrimLeft(s, "*&")
s = strings.Replace(s, ".", "", -1)
if !exported {
return s
}
return strings.ToUpper(string(s[0])) + s[1:]
}
func changePackage(r io.Reader, pkgName string) []byte {
var out bytes.Buffer
sc := bufio.NewScanner(r)
done := false
for sc.Scan() {
s := sc.Text()
if !done && strings.HasPrefix(s, "package") {
parts := strings.Split(s, " ")
parts[1] = pkgName
s = strings.Join(parts, " ")
done = true
}
fmt.Fprintln(&out, s)
}
return out.Bytes()
}
-35
View File
@@ -1,35 +0,0 @@
package parse
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestIsAlphaNumeric(t *testing.T) {
for _, r := range []rune{'a', '1', '_', 'A', 'Z'} {
assert.True(t, isAlphaNumeric(r))
}
for _, r := range []rune{' ', '[', ']', '!', '"'} {
assert.False(t, isAlphaNumeric(r))
}
}
func TestWordify(t *testing.T) {
for word, wordified := range map[string]string{
"int": "Int",
"*int": "Int",
"string": "String",
"*MyType": "MyType",
"*myType": "MyType",
"interface{}": "Interface",
"pack.type": "Packtype",
"*pack.type": "Packtype",
} {
assert.Equal(t, wordified, wordify(word, true))
}
}
-126
View File
@@ -1,126 +0,0 @@
package parse_test
import (
"io/ioutil"
"log"
"strings"
"testing"
"github.com/cheekybits/genny/parse"
"github.com/stretchr/testify/assert"
)
var tests = []struct {
// input
filename string
pkgName string
in string
types []map[string]string
// expectations
expectedOut string
expectedErr error
}{
{
filename: "generic_queue.go",
in: `test/queue/generic_queue.go`,
types: []map[string]string{{"Something": "int"}},
expectedOut: `test/queue/int_queue.go`,
},
{
filename: "generic_queue.go",
pkgName: "changed",
in: `test/queue/generic_queue.go`,
types: []map[string]string{{"Something": "int"}},
expectedOut: `test/queue/changed/int_queue.go`,
},
{
filename: "generic_queue.go",
in: `test/queue/generic_queue.go`,
types: []map[string]string{{"Something": "float32"}},
expectedOut: `test/queue/float32_queue.go`,
},
{
filename: "generic_simplemap.go",
in: `test/multipletypes/generic_simplemap.go`,
types: []map[string]string{{"KeyType": "string", "ValueType": "int"}},
expectedOut: `test/multipletypes/string_int_simplemap.go`,
},
{
filename: "generic_simplemap.go",
in: `test/multipletypes/generic_simplemap.go`,
types: []map[string]string{{"KeyType": "interface{}", "ValueType": "int"}},
expectedOut: `test/multipletypes/interface_int_simplemap.go`,
},
{
filename: "generic_simplemap.go",
in: `test/multipletypes/generic_simplemap.go`,
types: []map[string]string{{"KeyType": "*MyType1", "ValueType": "*MyOtherType"}},
expectedOut: `test/multipletypes/custom_types_simplemap.go`,
},
{
filename: "generic_internal.go",
in: `test/unexported/generic_internal.go`,
types: []map[string]string{{"secret": "*myType"}},
expectedOut: `test/unexported/mytype_internal.go`,
},
{
filename: "generic_simplemap.go",
in: `test/multipletypesets/generic_simplemap.go`,
types: []map[string]string{
{"KeyType": "int", "ValueType": "string"},
{"KeyType": "float64", "ValueType": "bool"},
},
expectedOut: `test/multipletypesets/many_simplemaps.go`,
},
{
filename: "generic_number.go",
in: `test/numbers/generic_number.go`,
types: []map[string]string{{"NumberType": "int"}},
expectedOut: `test/numbers/int_number.go`,
},
{
filename: "generic_digraph.go",
in: `test/bugreports/generic_digraph.go`,
types: []map[string]string{{"Node": "int"}},
expectedOut: `test/bugreports/int_digraph.go`,
},
}
func TestParse(t *testing.T) {
for _, test := range tests {
test.in = contents(test.in)
test.expectedOut = contents(test.expectedOut)
bytes, err := parse.Generics(test.filename, test.pkgName, strings.NewReader(test.in), test.types)
// check the error
if test.expectedErr == nil {
assert.NoError(t, err, "(%s) No error was expected but got: %s", test.filename, err)
} else {
assert.NotNil(t, err, "(%s) No error was returned by one was expected: %s", test.filename, test.expectedErr)
assert.IsType(t, test.expectedErr, err, "(%s) Generate should return object of type %v", test.filename, test.expectedErr)
}
// assert the response
if !assert.Equal(t, string(bytes), test.expectedOut, "Parse didn't generate the expected output.") {
log.Println("EXPECTED: " + test.expectedOut)
log.Println("ACTUAL: " + string(bytes))
}
}
}
func contents(s string) string {
if strings.HasSuffix(s, "go") {
file, err := ioutil.ReadFile(s)
if err != nil {
panic(err)
}
return string(file)
}
return s
}
@@ -1,30 +0,0 @@
package bugreports
import "github.com/cheekybits/genny/generic"
type Node generic.Type
type DigraphNode struct {
nodes map[Node][]Node
}
func NewDigraphNode() *DigraphNode {
return &DigraphNode{
nodes: make(map[Node][]Node),
}
}
func (dig *DigraphNode) Add(n Node) {
if _, exists := dig.nodes[n]; exists {
return
}
dig.nodes[n] = nil
}
func (dig *DigraphNode) Connect(a, b Node) {
dig.Add(a)
dig.Add(b)
dig.nodes[a] = append(dig.nodes[a], b)
}
@@ -1,30 +0,0 @@
// This file was automatically generated by genny.
// Any changes will be lost if this file is regenerated.
// see https://github.com/cheekybits/genny
package bugreports
type DigraphInt struct {
nodes map[int][]int
}
func NewDigraphInt() *DigraphInt {
return &DigraphInt{
nodes: make(map[int][]int),
}
}
func (dig *DigraphInt) Add(n int) {
if _, exists := dig.nodes[n]; exists {
return
}
dig.nodes[n] = nil
}
func (dig *DigraphInt) Connect(a, b int) {
dig.Add(a)
dig.Add(b)
dig.nodes[a] = append(dig.nodes[a], b)
}
@@ -1,5 +0,0 @@
package multipletypes
type MyType1 struct{}
type MyOtherType struct{}
@@ -1,21 +0,0 @@
// This file was automatically generated by genny.
// Any changes will be lost if this file is regenerated.
// see https://github.com/cheekybits/genny
package multipletypes
type MyType1MyOtherTypeMap map[*MyType1]*MyOtherType
func (m MyType1MyOtherTypeMap) Has(key *MyType1) bool {
_, ok := m[key]
return ok
}
func (m MyType1MyOtherTypeMap) Get(key *MyType1) *MyOtherType {
return m[key]
}
func (m MyType1MyOtherTypeMap) Set(key *MyType1, value *MyOtherType) MyType1MyOtherTypeMap {
m[key] = value
return m
}
@@ -1,22 +0,0 @@
package multipletypes
import "github.com/cheekybits/genny/generic"
type KeyType generic.Type
type ValueType generic.Type
type KeyTypeValueTypeMap map[KeyType]ValueType
func (m KeyTypeValueTypeMap) Has(key KeyType) bool {
_, ok := m[key]
return ok
}
func (m KeyTypeValueTypeMap) Get(key KeyType) ValueType {
return m[key]
}
func (m KeyTypeValueTypeMap) Set(key KeyType, value ValueType) KeyTypeValueTypeMap {
m[key] = value
return m
}
@@ -1,35 +0,0 @@
package multipletypes
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestSimpleMap(t *testing.T) {
key1 := new(KeyType)
key2 := new(KeyType)
value1 := new(ValueType)
m := make(KeyTypeValueTypeMap)
assert.Equal(t, m, m.Set(key1, value1))
assert.True(t, m.Has(key1))
assert.False(t, m.Has(key2))
assert.Equal(t, value1, m.Get(key1))
}
func TestCustomTypesMap(t *testing.T) {
key1 := new(MyType1)
key2 := new(MyType1)
value1 := new(MyOtherType)
m := make(MyType1MyOtherTypeMap)
assert.Equal(t, m, m.Set(key1, value1))
assert.True(t, m.Has(key1))
assert.False(t, m.Has(key2))
assert.Equal(t, value1, m.Get(key1))
}
@@ -1,21 +0,0 @@
// This file was automatically generated by genny.
// Any changes will be lost if this file is regenerated.
// see https://github.com/cheekybits/genny
package multipletypes
type InterfaceIntMap map[interface{}]int
func (m InterfaceIntMap) Has(key interface{}) bool {
_, ok := m[key]
return ok
}
func (m InterfaceIntMap) Get(key interface{}) int {
return m[key]
}
func (m InterfaceIntMap) Set(key interface{}, value int) InterfaceIntMap {
m[key] = value
return m
}
@@ -1,21 +0,0 @@
// This file was automatically generated by genny.
// Any changes will be lost if this file is regenerated.
// see https://github.com/cheekybits/genny
package multipletypes
type StringIntMap map[string]int
func (m StringIntMap) Has(key string) bool {
_, ok := m[key]
return ok
}
func (m StringIntMap) Get(key string) int {
return m[key]
}
func (m StringIntMap) Set(key string, value int) StringIntMap {
m[key] = value
return m
}
@@ -1,27 +0,0 @@
package multipletypesets
import (
"log"
"github.com/cheekybits/genny/generic"
)
type KeyType generic.Type
type ValueType generic.Type
type KeyTypeValueTypeMap map[KeyType]ValueType
func (m KeyTypeValueTypeMap) Has(key KeyType) bool {
_, ok := m[key]
return ok
}
func (m KeyTypeValueTypeMap) Get(key KeyType) ValueType {
return m[key]
}
func (m KeyTypeValueTypeMap) Set(key KeyType, value ValueType) KeyTypeValueTypeMap {
log.Println(value)
m[key] = value
return m
}
@@ -1,21 +0,0 @@
package multipletypesets
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestSimpleMap(t *testing.T) {
key1 := new(KeyType)
key2 := new(KeyType)
value1 := new(ValueType)
m := make(KeyTypeValueTypeMap)
assert.Equal(t, m, m.Set(key1, value1))
assert.True(t, m.Has(key1))
assert.False(t, m.Has(key2))
assert.Equal(t, value1, m.Get(key1))
}
@@ -1,41 +0,0 @@
// This file was automatically generated by genny.
// Any changes will be lost if this file is regenerated.
// see https://github.com/cheekybits/genny
package multipletypesets
import "log"
type IntStringMap map[int]string
func (m IntStringMap) Has(key int) bool {
_, ok := m[key]
return ok
}
func (m IntStringMap) Get(key int) string {
return m[key]
}
func (m IntStringMap) Set(key int, value string) IntStringMap {
log.Println(value)
m[key] = value
return m
}
type Float64BoolMap map[float64]bool
func (m Float64BoolMap) Has(key float64) bool {
_, ok := m[key]
return ok
}
func (m Float64BoolMap) Get(key float64) bool {
return m[key]
}
func (m Float64BoolMap) Set(key float64, value bool) Float64BoolMap {
log.Println(value)
m[key] = value
return m
}
@@ -1,12 +0,0 @@
package numbers
import "github.com/cheekybits/genny/generic"
type NumberType generic.Number
func NumberTypeMax(a, b NumberType) NumberType {
if a > b {
return a
}
return b
}
-12
View File
@@ -1,12 +0,0 @@
// This file was automatically generated by genny.
// Any changes will be lost if this file is regenerated.
// see https://github.com/cheekybits/genny
package numbers
func IntMax(a, b int) int {
if a > b {
return a
}
return b
}
@@ -1,22 +0,0 @@
// This file was automatically generated by genny.
// Any changes will be lost if this file is regenerated.
// see https://github.com/cheekybits/genny
package changed
// IntQueue is a queue of Ints.
type IntQueue struct {
items []int
}
func NewIntQueue() *IntQueue {
return &IntQueue{items: make([]int, 0)}
}
func (q *IntQueue) Push(item int) {
q.items = append(q.items, item)
}
func (q *IntQueue) Pop() int {
item := q.items[0]
q.items = q.items[1:]
return item
}
-22
View File
@@ -1,22 +0,0 @@
// This file was automatically generated by genny.
// Any changes will be lost if this file is regenerated.
// see https://github.com/cheekybits/genny
package queue
// Float32Queue is a queue of Float32s.
type Float32Queue struct {
items []float32
}
func NewFloat32Queue() *Float32Queue {
return &Float32Queue{items: make([]float32, 0)}
}
func (q *Float32Queue) Push(item float32) {
q.items = append(q.items, item)
}
func (q *Float32Queue) Pop() float32 {
item := q.items[0]
q.items = q.items[1:]
return item
}
-23
View File
@@ -1,23 +0,0 @@
package queue
import "github.com/cheekybits/genny/generic"
// Something is a type that does something
type Something generic.Type
// SomethingQueue is a queue of Somethings.
type SomethingQueue struct {
items []Something
}
func NewSomethingQueue() *SomethingQueue {
return &SomethingQueue{items: make([]Something, 0)}
}
func (q *SomethingQueue) Push(item Something) {
q.items = append(q.items, item)
}
func (q *SomethingQueue) Pop() Something {
item := q.items[0]
q.items = q.items[1:]
return item
}
@@ -1,87 +0,0 @@
package queue
import "testing"
func TestSomethingQueue(t *testing.T) {
var item1 *Something = new(Something)
var item2 *Something = new(Something)
var item3 *Something = new(Something)
q := NewSomethingQueue()
q.Push(item1)
if len(q.items) != 1 {
t.Error("Push should add the item")
}
q.Push(item2)
if len(q.items) != 2 {
t.Error("Push should add the item")
}
q.Push(item3)
if len(q.items) != 3 {
t.Error("Push should add the item")
}
if q.Pop() != item1 {
t.Error("Pop should return items in the order in which they were added")
}
if len(q.items) != 2 {
t.Error("Pop should remove the item")
}
if q.Pop() != item2 {
t.Error("Pop should return items in the order in which they were added")
}
if len(q.items) != 1 {
t.Error("Pop should remove the item")
}
if q.Pop() != item3 {
t.Error("Pop should return items in the order in which they were added")
}
if len(q.items) != 0 {
t.Error("Pop should remove the item")
}
}
func TestIntQueue(t *testing.T) {
var item1 int = 1
var item2 int = 2
var item3 int = 3
q := NewIntQueue()
q.Push(item1)
if len(q.items) != 1 {
t.Error("Push should add the item")
}
q.Push(item2)
if len(q.items) != 2 {
t.Error("Push should add the item")
}
q.Push(item3)
if len(q.items) != 3 {
t.Error("Push should add the item")
}
if q.Pop() != item1 {
t.Error("Pop should return items in the order in which they were added")
}
if len(q.items) != 2 {
t.Error("Pop should remove the item")
}
if q.Pop() != item2 {
t.Error("Pop should return items in the order in which they were added")
}
if len(q.items) != 1 {
t.Error("Pop should remove the item")
}
if q.Pop() != item3 {
t.Error("Pop should return items in the order in which they were added")
}
if len(q.items) != 0 {
t.Error("Pop should remove the item")
}
}
-22
View File
@@ -1,22 +0,0 @@
// This file was automatically generated by genny.
// Any changes will be lost if this file is regenerated.
// see https://github.com/cheekybits/genny
package queue
// IntQueue is a queue of Ints.
type IntQueue struct {
items []int
}
func NewIntQueue() *IntQueue {
return &IntQueue{items: make([]int, 0)}
}
func (q *IntQueue) Push(item int) {
q.items = append(q.items, item)
}
func (q *IntQueue) Pop() int {
item := q.items[0]
q.items = q.items[1:]
return item
}
-24
View File
@@ -1,24 +0,0 @@
package slice
import (
"log"
"reflect"
"github.com/cheekybits/genny/generic"
)
type MyType generic.Type
func EnsureSlice(objectOrSlice interface{}) []MyType {
log.Printf("%v", reflect.TypeOf(objectOrSlice))
switch obj := objectOrSlice.(type) {
case []MyType:
log.Println(" returning it untouched")
return obj
case MyType, *MyType:
log.Println(" wrapping in slice")
return []MyType{obj}
default:
panic("ensure slice needs MyType or []MyType")
}
}
@@ -1,24 +0,0 @@
package slice
import (
"log"
"testing"
"github.com/stretchr/testify/assert"
)
func TestEnsureSlice(t *testing.T) {
myType := new(MyType)
slice := EnsureSlice(myType)
if assert.NotNil(t, slice) {
assert.Equal(t, slice[0], myType)
}
slice = EnsureSlice(slice)
log.Printf("%#v", slice[0])
if assert.NotNil(t, slice) {
assert.Equal(t, slice[0], myType)
}
}
@@ -1,3 +0,0 @@
package unexported
type myType struct{}
@@ -1,13 +0,0 @@
package unexported
import (
"fmt"
"github.com/cheekybits/genny/generic"
)
type secret generic.Type
func secretInspect(s secret) string {
return fmt.Sprintf("%#v", s)
}
@@ -1,11 +0,0 @@
// This file was automatically generated by genny.
// Any changes will be lost if this file is regenerated.
// see https://github.com/cheekybits/genny
package unexported
import "fmt"
func myTypeInspect(s *myType) string {
return fmt.Sprintf("%#v", s)
}
-89
View File
@@ -1,89 +0,0 @@
package parse
import "strings"
const (
typeSep = " "
keyValueSep = "="
valuesSep = ","
builtins = "BUILTINS"
numbers = "NUMBERS"
)
// TypeSet turns a type string into a []map[string]string
// that can be given to parse.Generics for it to do its magic.
//
// Acceptable args are:
//
// Person=man
// Person=man Animal=dog
// Person=man Animal=dog Animal2=cat
// Person=man,woman Animal=dog,cat
// Person=man,woman,child Animal=dog,cat Place=london,paris
func TypeSet(arg string) ([]map[string]string, error) {
types := make(map[string][]string)
var keys []string
for _, pair := range strings.Split(arg, typeSep) {
segs := strings.Split(pair, keyValueSep)
if len(segs) != 2 {
return nil, &errBadTypeArgs{Arg: arg, Message: "Generic=Specific expected"}
}
key := segs[0]
keys = append(keys, key)
types[key] = make([]string, 0)
for _, t := range strings.Split(segs[1], valuesSep) {
if t == builtins {
types[key] = append(types[key], Builtins...)
} else if t == numbers {
types[key] = append(types[key], Numbers...)
} else {
types[key] = append(types[key], t)
}
}
}
cursors := make(map[string]int)
for _, key := range keys {
cursors[key] = 0
}
outChan := make(chan map[string]string)
go func() {
buildTypeSet(keys, 0, cursors, types, outChan)
close(outChan)
}()
var typeSets []map[string]string
for typeSet := range outChan {
typeSets = append(typeSets, typeSet)
}
return typeSets, nil
}
func buildTypeSet(keys []string, keyI int, cursors map[string]int, types map[string][]string, out chan<- map[string]string) {
key := keys[keyI]
for cursors[key] < len(types[key]) {
if keyI < len(keys)-1 {
buildTypeSet(keys, keyI+1, copycursors(cursors), types, out)
} else {
// build the typeset for this combination
ts := make(map[string]string)
for k, vals := range types {
ts[k] = vals[cursors[k]]
}
out <- ts
}
cursors[key]++
}
}
func copycursors(source map[string]int) map[string]int {
copy := make(map[string]int)
for k, v := range source {
copy[k] = v
}
return copy
}
-74
View File
@@ -1,74 +0,0 @@
package parse_test
import (
"testing"
"github.com/cheekybits/genny/parse"
"github.com/stretchr/testify/assert"
)
func TestArgsToTypeset(t *testing.T) {
args := "Person=man,woman Animal=dog,cat Place=london,paris"
ts, err := parse.TypeSet(args)
if assert.NoError(t, err) {
if assert.Equal(t, 8, len(ts)) {
assert.Equal(t, ts[0]["Person"], "man")
assert.Equal(t, ts[0]["Animal"], "dog")
assert.Equal(t, ts[0]["Place"], "london")
assert.Equal(t, ts[1]["Person"], "man")
assert.Equal(t, ts[1]["Animal"], "dog")
assert.Equal(t, ts[1]["Place"], "paris")
assert.Equal(t, ts[2]["Person"], "man")
assert.Equal(t, ts[2]["Animal"], "cat")
assert.Equal(t, ts[2]["Place"], "london")
assert.Equal(t, ts[3]["Person"], "man")
assert.Equal(t, ts[3]["Animal"], "cat")
assert.Equal(t, ts[3]["Place"], "paris")
assert.Equal(t, ts[4]["Person"], "woman")
assert.Equal(t, ts[4]["Animal"], "dog")
assert.Equal(t, ts[4]["Place"], "london")
assert.Equal(t, ts[5]["Person"], "woman")
assert.Equal(t, ts[5]["Animal"], "dog")
assert.Equal(t, ts[5]["Place"], "paris")
assert.Equal(t, ts[6]["Person"], "woman")
assert.Equal(t, ts[6]["Animal"], "cat")
assert.Equal(t, ts[6]["Place"], "london")
assert.Equal(t, ts[7]["Person"], "woman")
assert.Equal(t, ts[7]["Animal"], "cat")
assert.Equal(t, ts[7]["Place"], "paris")
}
}
ts, err = parse.TypeSet("Person=man Animal=dog Place=london")
if assert.NoError(t, err) {
assert.Equal(t, 1, len(ts))
}
ts, err = parse.TypeSet("Person=1,2,3,4,5 Animal=1,2,3,4,5 Place=1,2,3,4,5")
if assert.NoError(t, err) {
assert.Equal(t, 125, len(ts))
}
ts, err = parse.TypeSet("Person=1 Animal=1,2,3,4,5 Place=1,2")
if assert.NoError(t, err) {
assert.Equal(t, 10, len(ts))
}
ts, err = parse.TypeSet("Person=interface{} Animal=interface{} Place=interface{}")
if assert.NoError(t, err) {
assert.Equal(t, 1, len(ts))
assert.Equal(t, ts[0]["Animal"], "interface{}")
assert.Equal(t, ts[0]["Person"], "interface{}")
assert.Equal(t, ts[0]["Place"], "interface{}")
}
}
-9
View File
@@ -1,9 +0,0 @@
str1:
foo: bar
arr1: strval1
map1:
- abc
- def
int1: true
float1: "strval2"
bool1: 123.45
-13
View File
@@ -1,13 +0,0 @@
#!/bin/sh
cat <<EOM
str1: d3str1val1
arr1:
- d3arr1val1
- d3arr1val2
map1:
key2: d3map1val2
key3: d3map1val3
int1: 333
float1: 3.33
bool1: true
EOM
-12
View File
@@ -1,12 +0,0 @@
str1: d3str1val1
arr1:
- d3arr1val1
- d3arr1val2
- dupval
map1:
key2: d3map1val2
key3: d3map1val3
dup: d3dupval
int1: 333
float1: 3.33
bool1: true
-10
View File
@@ -1,10 +0,0 @@
str1: d3str1val1
arr1:
- d3arr1val1
- d3arr1val2
map1:
key2: d3map1val2
key3: d3map1val3
int1: 333
float1: 3.33
bool1: true
-10
View File
@@ -1,10 +0,0 @@
str1: d3str1val1
arr1:
- d3arr1val1
- d3arr1val2
map1:
key2: d3map1val2
key3: d3map1val3
int1: 333
float1: 3.33
bool1: true
-13
View File
@@ -1,13 +0,0 @@
#!/bin/sh
cat <<EOM
str1: d2str1val1
arr1:
- d2arr1val1
- d2arr1val2
map1:
key1: d2map1val1
key2: d2map1val2
int1: 222
float1: 2.22
bool1: false
EOM
-12
View File
@@ -1,12 +0,0 @@
str1: d2str1val1
arr1:
- d2arr1val1
- d2arr1val2
- dupval
map1:
key1: d2map1val1
key2: d2map1val2
dup: d2dupval
int1: 222
float1: 2.22
bool1: false
-15
View File
@@ -1,15 +0,0 @@
config:
overwrite:
- str1
- arr1
- bool1
str1: d2str1val1
arr1:
- d2arr1val1
- d2arr1val2
map1:
key1: d2map1val1
key2: d2map1val2
int1: 222
float1: 2.22
bool1: false
-12
View File
@@ -1,12 +0,0 @@
config:
stop: true
str1: d2str1val1
arr1:
- d2arr1val1
- d2arr1val2
map1:
key1: d2map1val1
key2: d2map1val2
int1: 222
float1: 2.22
bool1: false
-13
View File
@@ -1,13 +0,0 @@
#!/bin/bash
cat <<EOM
str1: d1str1val1
arr1:
- d1arr1val1
- d1arr1val2
map1:
key0: d1map1val0
key1: d1map1val1
int1: 111
float1: 1.11
bool1: true
EOM
-12
View File
@@ -1,12 +0,0 @@
str1: d1str1val1
arr1:
- d1arr1val1
- d1arr1val2
- dupval
map1:
key0: d1map1val0
key1: d1map1val1
dup: d1dupval
int1: 111
float1: 1.11
bool1: true
-15
View File
@@ -1,15 +0,0 @@
config:
overwrite:
- map1
- int1
- float1
str1: d1str1val1
arr1:
- d1arr1val1
- d1arr1val2
map1:
key0: d1map1val0
key1: d1map1val1
int1: 111
float1: 1.11
bool1: true
-10
View File
@@ -1,10 +0,0 @@
str1: d1str1val1
arr1:
- d1arr1val1
- d1arr1val2
map1:
key0: d1map1val0
key1: d1map1val1
int1: 111
float1: 1.11
bool1: true
-30
View File
@@ -1,30 +0,0 @@
package main
import (
"fmt"
"github.com/guelfey/go.dbus"
"os"
)
func main() {
conn, err := dbus.SessionBus()
if err != nil {
fmt.Fprintln(os.Stderr, "Failed to connect to session bus:", err)
os.Exit(1)
}
for _, v := range []string{"method_call", "method_return", "error", "signal"} {
call := conn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0,
"eavesdrop='true',type='"+v+"'")
if call.Err != nil {
fmt.Fprintln(os.Stderr, "Failed to add match:", call.Err)
os.Exit(1)
}
}
c := make(chan *dbus.Message, 10)
conn.Eavesdrop(c)
fmt.Println("Listening for everything")
for v := range c {
fmt.Println(v)
}
}
-21
View File
@@ -1,21 +0,0 @@
package main
import (
"encoding/json"
"github.com/guelfey/go.dbus"
"github.com/guelfey/go.dbus/introspect"
"os"
)
func main() {
conn, err := dbus.SessionBus()
if err != nil {
panic(err)
}
node, err := introspect.Call(conn.Object("org.freedesktop.DBus", "/org/freedesktop/DBus"))
if err != nil {
panic(err)
}
data, _ := json.MarshalIndent(node, "", " ")
os.Stdout.Write(data)
}
-27
View File
@@ -1,27 +0,0 @@
package main
import (
"fmt"
"github.com/guelfey/go.dbus"
"os"
)
func main() {
conn, err := dbus.SessionBus()
if err != nil {
fmt.Fprintln(os.Stderr, "Failed to connect to session bus:", err)
os.Exit(1)
}
var s []string
err = conn.BusObject().Call("org.freedesktop.DBus.ListNames", 0).Store(&s)
if err != nil {
fmt.Fprintln(os.Stderr, "Failed to get list of owned names:", err)
os.Exit(1)
}
fmt.Println("Currently owned names on the session bus:")
for _, v := range s {
fmt.Println(v)
}
}
-17
View File
@@ -1,17 +0,0 @@
package main
import "github.com/guelfey/go.dbus"
func main() {
conn, err := dbus.SessionBus()
if err != nil {
panic(err)
}
obj := conn.Object("org.freedesktop.Notifications", "/org/freedesktop/Notifications")
call := obj.Call("org.freedesktop.Notifications.Notify", 0, "", uint32(0),
"", "Test", "This is a test of the DBus bindings for go.", []string{},
map[string]dbus.Variant{}, int32(5000))
if call.Err != nil {
panic(call.Err)
}
}
-68
View File
@@ -1,68 +0,0 @@
package main
import (
"fmt"
"github.com/guelfey/go.dbus"
"github.com/guelfey/go.dbus/introspect"
"github.com/guelfey/go.dbus/prop"
"os"
)
type foo string
func (f foo) Foo() (string, *dbus.Error) {
fmt.Println(f)
return string(f), nil
}
func main() {
conn, err := dbus.SessionBus()
if err != nil {
panic(err)
}
reply, err := conn.RequestName("com.github.guelfey.Demo",
dbus.NameFlagDoNotQueue)
if err != nil {
panic(err)
}
if reply != dbus.RequestNameReplyPrimaryOwner {
fmt.Fprintln(os.Stderr, "name already taken")
os.Exit(1)
}
propsSpec := map[string]map[string]*prop.Prop{
"com.github.guelfey.Demo": {
"SomeInt": {
int32(0),
true,
prop.EmitTrue,
func(c *prop.Change) *dbus.Error {
fmt.Println(c.Name, "changed to", c.Value)
return nil
},
},
},
}
f := foo("Bar")
conn.Export(f, "/com/github/guelfey/Demo", "com.github.guelfey.Demo")
props := prop.New(conn, "/com/github/guelfey/Demo", propsSpec)
n := &introspect.Node{
Name: "/com/github/guelfey/Demo",
Interfaces: []introspect.Interface{
introspect.IntrospectData,
prop.IntrospectData,
{
Name: "com.github.guelfey.Demo",
Methods: introspect.Methods(f),
Properties: props.Introspection("com.github.guelfey.Demo"),
},
},
}
conn.Export(introspect.NewIntrospectable(n), "/com/github/guelfey/Demo",
"org.freedesktop.DBus.Introspectable")
fmt.Println("Listening on com.github.guelfey.Demo / /com/github/guelfey/Demo ...")
c := make(chan *dbus.Signal)
conn.Signal(c)
for _ = range c {
}
}
-45
View File
@@ -1,45 +0,0 @@
package main
import (
"fmt"
"github.com/guelfey/go.dbus"
"github.com/guelfey/go.dbus/introspect"
"os"
)
const intro = `
<node>
<interface name="com.github.guelfey.Demo">
<method name="Foo">
<arg direction="out" type="s"/>
</method>
</interface>` + introspect.IntrospectDataString + `</node> `
type foo string
func (f foo) Foo() (string, *dbus.Error) {
fmt.Println(f)
return string(f), nil
}
func main() {
conn, err := dbus.SessionBus()
if err != nil {
panic(err)
}
reply, err := conn.RequestName("com.github.guelfey.Demo",
dbus.NameFlagDoNotQueue)
if err != nil {
panic(err)
}
if reply != dbus.RequestNameReplyPrimaryOwner {
fmt.Fprintln(os.Stderr, "name already taken")
os.Exit(1)
}
f := foo("Bar!")
conn.Export(f, "/com/github/guelfey/Demo", "com.github.guelfey.Demo")
conn.Export(introspect.Introspectable(intro), "/com/github/guelfey/Demo",
"org.freedesktop.DBus.Introspectable")
fmt.Println("Listening on com.github.guelfey.Demo / /com/github/guelfey/Demo ...")
select {}
}
-24
View File
@@ -1,24 +0,0 @@
package main
import (
"fmt"
"github.com/guelfey/go.dbus"
"os"
)
func main() {
conn, err := dbus.SessionBus()
if err != nil {
fmt.Fprintln(os.Stderr, "Failed to connect to session bus:", err)
os.Exit(1)
}
conn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0,
"type='signal',path='/org/freedesktop/DBus',interface='org.freedesktop.DBus',sender='org.freedesktop.DBus'")
c := make(chan *dbus.Signal, 10)
conn.Signal(c)
for v := range c {
fmt.Println(v)
}
}
-27
View File
@@ -1,27 +0,0 @@
package introspect
import (
"encoding/xml"
"github.com/guelfey/go.dbus"
"strings"
)
// Call calls org.freedesktop.Introspectable.Introspect on a remote object
// and returns the introspection data.
func Call(o *dbus.Object) (*Node, error) {
var xmldata string
var node Node
err := o.Call("org.freedesktop.DBus.Introspectable.Introspect", 0).Store(&xmldata)
if err != nil {
return nil, err
}
err = xml.NewDecoder(strings.NewReader(xmldata)).Decode(&node)
if err != nil {
return nil, err
}
if node.Name == "" {
node.Name = string(o.Path())
}
return &node, nil
}
-80
View File
@@ -1,80 +0,0 @@
// Package introspect provides some utilities for dealing with the DBus
// introspection format.
package introspect
import "encoding/xml"
// The introspection data for the org.freedesktop.DBus.Introspectable interface.
var IntrospectData = Interface{
Name: "org.freedesktop.DBus.Introspectable",
Methods: []Method{
{
Name: "Introspect",
Args: []Arg{
{"out", "s", "out"},
},
},
},
}
// The introspection data for the org.freedesktop.DBus.Introspectable interface,
// as a string.
const IntrospectDataString = `
<interface name="org.freedesktop.DBus.Introspectable">
<method name="Introspect">
<arg name="out" direction="out" type="s"/>
</method>
</interface>
`
// Node is the root element of an introspection.
type Node struct {
XMLName xml.Name `xml:"node"`
Name string `xml:"name,attr,omitempty"`
Interfaces []Interface `xml:"interface"`
Children []Node `xml:"node,omitempty"`
}
// Interface describes a DBus interface that is available on the message bus.
type Interface struct {
Name string `xml:"name,attr"`
Methods []Method `xml:"method"`
Signals []Signal `xml:"signal"`
Properties []Property `xml:"property"`
Annotations []Annotation `xml:"annotation"`
}
// Method describes a Method on an Interface as retured by an introspection.
type Method struct {
Name string `xml:"name,attr"`
Args []Arg `xml:"arg"`
Annotations []Annotation `xml:"annotation"`
}
// Signal describes a Signal emitted on an Interface.
type Signal struct {
Name string `xml:"name,attr"`
Args []Arg `xml:"arg"`
Annotations []Annotation `xml:"annotation"`
}
// Property describes a property of an Interface.
type Property struct {
Name string `xml:"name,attr"`
Type string `xml:"type,attr"`
Access string `xml:"access,attr"`
Annotations []Annotation `xml:"annotation"`
}
// Arg represents an argument of a method or a signal.
type Arg struct {
Name string `xml:"name,attr,omitempty"`
Type string `xml:"type,attr"`
Direction string `xml:"direction,attr,omitempty"`
}
// Annotation is an annotation in the introspection format.
type Annotation struct {
Name string `xml:"name,attr"`
Value string `xml:"value,attr"`
}
-74
View File
@@ -1,74 +0,0 @@
package introspect
import (
"encoding/xml"
"github.com/guelfey/go.dbus"
"reflect"
)
// Introspectable implements org.freedesktop.Introspectable.
//
// You can create it by converting the XML-formatted introspection data from a
// string to an Introspectable or call NewIntrospectable with a Node. Then,
// export it as org.freedesktop.Introspectable on you object.
type Introspectable string
// NewIntrospectable returns an Introspectable that returns the introspection
// data that corresponds to the given Node. If n.Interfaces doesn't contain the
// data for org.freedesktop.DBus.Introspectable, it is added automatically.
func NewIntrospectable(n *Node) Introspectable {
found := false
for _, v := range n.Interfaces {
if v.Name == "org.freedesktop.DBus.Introspectable" {
found = true
break
}
}
if !found {
n.Interfaces = append(n.Interfaces, IntrospectData)
}
b, err := xml.Marshal(n)
if err != nil {
panic(err)
}
return Introspectable(b)
}
// Introspect implements org.freedesktop.Introspectable.Introspect.
func (i Introspectable) Introspect() (string, *dbus.Error) {
return string(i), nil
}
// Methods returns the description of the methods of v. This can be used to
// create a Node which can be passed to NewIntrospectable.
func Methods(v interface{}) []Method {
t := reflect.TypeOf(v)
ms := make([]Method, 0, t.NumMethod())
for i := 0; i < t.NumMethod(); i++ {
if t.Method(i).PkgPath != "" {
continue
}
mt := t.Method(i).Type
if mt.NumOut() == 0 ||
mt.Out(mt.NumOut()-1) != reflect.TypeOf(&dbus.Error{"", nil}) {
continue
}
var m Method
m.Name = t.Method(i).Name
m.Args = make([]Arg, 0, mt.NumIn()+mt.NumOut()-2)
for j := 1; j < mt.NumIn(); j++ {
if mt.In(j) != reflect.TypeOf((*dbus.Sender)(nil)).Elem() {
arg := Arg{"", dbus.SignatureOfType(mt.In(j)).String(), "in"}
m.Args = append(m.Args, arg)
}
}
for j := 0; j < mt.NumOut()-1; j++ {
arg := Arg{"", dbus.SignatureOfType(mt.Out(j)).String(), "out"}
m.Args = append(m.Args, arg)
}
m.Annotations = make([]Annotation, 0)
ms = append(ms, m)
}
return ms
}
-264
View File
@@ -1,264 +0,0 @@
// Package prop provides the Properties struct which can be used to implement
// org.freedesktop.DBus.Properties.
package prop
import (
"github.com/guelfey/go.dbus"
"github.com/guelfey/go.dbus/introspect"
"sync"
)
// EmitType controls how org.freedesktop.DBus.Properties.PropertiesChanged is
// emitted for a property. If it is EmitTrue, the signal is emitted. If it is
// EmitInvalidates, the signal is also emitted, but the new value of the property
// is not disclosed.
type EmitType byte
const (
EmitFalse EmitType = iota
EmitTrue
EmitInvalidates
)
// ErrIfaceNotFound is the error returned to peers who try to access properties
// on interfaces that aren't found.
var ErrIfaceNotFound = &dbus.Error{"org.freedesktop.DBus.Properties.Error.InterfaceNotFound", nil}
// ErrPropNotFound is the error returned to peers trying to access properties
// that aren't found.
var ErrPropNotFound = &dbus.Error{"org.freedesktop.DBus.Properties.Error.PropertyNotFound", nil}
// ErrReadOnly is the error returned to peers trying to set a read-only
// property.
var ErrReadOnly = &dbus.Error{"org.freedesktop.DBus.Properties.Error.ReadOnly", nil}
// ErrInvalidArg is returned to peers if the type of the property that is being
// changed and the argument don't match.
var ErrInvalidArg = &dbus.Error{"org.freedesktop.DBus.Properties.Error.InvalidArg", nil}
// The introspection data for the org.freedesktop.DBus.Properties interface.
var IntrospectData = introspect.Interface{
Name: "org.freedesktop.DBus.Properties",
Methods: []introspect.Method{
{
Name: "Get",
Args: []introspect.Arg{
{"interface", "s", "in"},
{"property", "s", "in"},
{"value", "v", "out"},
},
},
{
Name: "GetAll",
Args: []introspect.Arg{
{"interface", "s", "in"},
{"props", "a{sv}", "out"},
},
},
{
Name: "Set",
Args: []introspect.Arg{
{"interface", "s", "in"},
{"property", "s", "in"},
{"value", "v", "in"},
},
},
},
Signals: []introspect.Signal{
{
Name: "PropertiesChanged",
Args: []introspect.Arg{
{"interface", "s", "out"},
{"changed_properties", "a{sv}", "out"},
{"invalidates_properties", "as", "out"},
},
},
},
}
// The introspection data for the org.freedesktop.DBus.Properties interface, as
// a string.
const IntrospectDataString = `
<interface name="org.freedesktop.DBus.Introspectable">
<method name="Get">
<arg name="interface" direction="in" type="s"/>
<arg name="property" direction="in" type="s"/>
<arg name="value" direction="out" type="v"/>
</method>
<method name="GetAll">
<arg name="interface" direction="in" type="s"/>
<arg name="props" direction="out" type="a{sv}"/>
</method>
<method name="Set">
<arg name="interface" direction="in" type="s"/>
<arg name="property" direction="in" type="s"/>
<arg name="value" direction="in" type="v"/>
</method>
<signal name="PropertiesChanged">
<arg name="interface" type="s"/>
<arg name="changed_properties" type="a{sv}"/>
<arg name="invalidates_properties" type="as"/>
</signal>
</interface>
`
// Prop represents a single property. It is used for creating a Properties
// value.
type Prop struct {
// Initial value. Must be a DBus-representable type.
Value interface{}
// If true, the value can be modified by calls to Set.
Writable bool
// Controls how org.freedesktop.DBus.Properties.PropertiesChanged is
// emitted if this property changes.
Emit EmitType
// If not nil, anytime this property is changed by Set, this function is
// called with an appropiate Change as its argument. If the returned error
// is not nil, it is sent back to the caller of Set and the property is not
// changed.
Callback func(*Change) *dbus.Error
}
// Change represents a change of a property by a call to Set.
type Change struct {
Props *Properties
Iface string
Name string
Value interface{}
}
// Properties is a set of values that can be made available to the message bus
// using the org.freedesktop.DBus.Properties interface. It is safe for
// concurrent use by multiple goroutines.
type Properties struct {
m map[string]map[string]*Prop
mut sync.RWMutex
conn *dbus.Conn
path dbus.ObjectPath
}
// New returns a new Properties structure that manages the given properties.
// The key for the first-level map of props is the name of the interface; the
// second-level key is the name of the property. The returned structure will be
// exported as org.freedesktop.DBus.Properties on path.
func New(conn *dbus.Conn, path dbus.ObjectPath, props map[string]map[string]*Prop) *Properties {
p := &Properties{m: props, conn: conn, path: path}
conn.Export(p, path, "org.freedesktop.DBus.Properties")
return p
}
// Get implements org.freedesktop.DBus.Properties.Get.
func (p *Properties) Get(iface, property string) (dbus.Variant, *dbus.Error) {
p.mut.RLock()
defer p.mut.RUnlock()
m, ok := p.m[iface]
if !ok {
return dbus.Variant{}, ErrIfaceNotFound
}
prop, ok := m[property]
if !ok {
return dbus.Variant{}, ErrPropNotFound
}
return dbus.MakeVariant(prop.Value), nil
}
// GetAll implements org.freedesktop.DBus.Properties.GetAll.
func (p *Properties) GetAll(iface string) (map[string]dbus.Variant, *dbus.Error) {
p.mut.RLock()
defer p.mut.RUnlock()
m, ok := p.m[iface]
if !ok {
return nil, ErrIfaceNotFound
}
rm := make(map[string]dbus.Variant, len(m))
for k, v := range m {
rm[k] = dbus.MakeVariant(v.Value)
}
return rm, nil
}
// GetMust returns the value of the given property and panics if either the
// interface or the property name are invalid.
func (p *Properties) GetMust(iface, property string) interface{} {
p.mut.RLock()
defer p.mut.RUnlock()
return p.m[iface][property].Value
}
// Introspection returns the introspection data that represents the properties
// of iface.
func (p *Properties) Introspection(iface string) []introspect.Property {
p.mut.RLock()
defer p.mut.RUnlock()
m := p.m[iface]
s := make([]introspect.Property, 0, len(m))
for k, v := range m {
p := introspect.Property{Name: k, Type: dbus.SignatureOf(v.Value).String()}
if v.Writable {
p.Access = "readwrite"
} else {
p.Access = "read"
}
s = append(s, p)
}
return s
}
// set sets the given property and emits PropertyChanged if appropiate. p.mut
// must already be locked.
func (p *Properties) set(iface, property string, v interface{}) {
prop := p.m[iface][property]
prop.Value = v
switch prop.Emit {
case EmitFalse:
// do nothing
case EmitInvalidates:
p.conn.Emit(p.path, "org.freedesktop.DBus.Properties.PropertiesChanged",
iface, map[string]dbus.Variant{}, []string{property})
case EmitTrue:
p.conn.Emit(p.path, "org.freedesktop.DBus.Properties.PropertiesChanged",
iface, map[string]dbus.Variant{property: dbus.MakeVariant(v)},
[]string{})
default:
panic("invalid value for EmitType")
}
}
// Set implements org.freedesktop.Properties.Set.
func (p *Properties) Set(iface, property string, newv dbus.Variant) *dbus.Error {
p.mut.Lock()
defer p.mut.Unlock()
m, ok := p.m[iface]
if !ok {
return ErrIfaceNotFound
}
prop, ok := m[property]
if !ok {
return ErrPropNotFound
}
if !prop.Writable {
return ErrReadOnly
}
if newv.Signature() != dbus.SignatureOf(prop.Value) {
return ErrInvalidArg
}
if prop.Callback != nil {
err := prop.Callback(&Change{p, iface, property, newv.Value()})
if err != nil {
return err
}
}
p.set(iface, property, newv.Value())
return nil
}
// SetMust sets the value of the given property and panics if the interface or
// the property name are invalid.
func (p *Properties) SetMust(iface, property string, v interface{}) {
p.mut.Lock()
p.set(iface, property, v)
p.mut.Unlock()
}
-16
View File
@@ -1,16 +0,0 @@
package main
import (
"bufio"
"fmt"
"github.com/mattn/go-colorable"
)
func main() {
stdOut := bufio.NewWriter(colorable.NewColorableStdout())
fmt.Fprint(stdOut, "\x1B[3GMove to 3rd Column\n")
fmt.Fprint(stdOut, "\x1B[1;2HMove to 2nd Column on 1st Line\n")
stdOut.Flush()
}
-16
View File
@@ -1,16 +0,0 @@
package main
import (
"github.com/mattn/go-colorable"
"github.com/sirupsen/logrus"
)
func main() {
logrus.SetFormatter(&logrus.TextFormatter{ForceColors: true})
logrus.SetOutput(colorable.NewColorableStdout())
logrus.Info("succeeded")
logrus.Warn("not correct")
logrus.Error("something error")
logrus.Fatal("panic")
}
-14
View File
@@ -1,14 +0,0 @@
package main
import (
"fmt"
"os"
. "github.com/mattn/go-colorable"
)
func main() {
out := NewColorableStdout()
fmt.Fprint(out, "\x1B]0;TITLE Changed\007(See title and hit any key)")
var c [1]byte
os.Stdin.Read(c[:])
}
-12
View File
@@ -1,12 +0,0 @@
package main
import (
"io"
"os"
"github.com/mattn/go-colorable"
)
func main() {
io.Copy(colorable.NewColorableStdout(), os.Stdin)
}
-135
View File
@@ -1,135 +0,0 @@
package main
import (
"fmt"
"sort"
"strconv"
"github.com/mattn/go-colorable"
"github.com/mgutz/ansi"
)
func main() {
printColors()
print256Colors()
printConstants()
}
func pad(s string, length int) string {
for len(s) < length {
s += " "
}
return s
}
func padColor(s string, styles []string) string {
buffer := ""
for _, style := range styles {
buffer += ansi.Color(pad(s+style, 20), s+style)
}
return buffer
}
func printPlain() {
ansi.DisableColors(true)
bgColors := []string{
"",
":black",
":red",
":green",
":yellow",
":blue",
":magenta",
":cyan",
":white",
}
for fg := range ansi.Colors {
for _, bg := range bgColors {
println(padColor(fg, []string{"" + bg, "+b" + bg, "+bh" + bg, "+u" + bg}))
println(padColor(fg, []string{"+uh" + bg, "+B" + bg, "+Bb" + bg /* backgrounds */, "" + bg + "+h"}))
println(padColor(fg, []string{"+b" + bg + "+h", "+bh" + bg + "+h", "+u" + bg + "+h", "+uh" + bg + "+h"}))
}
}
}
func printColors() {
ansi.DisableColors(false)
stdout := colorable.NewColorableStdout()
bgColors := []string{
"",
":black",
":red",
":green",
":yellow",
":blue",
":magenta",
":cyan",
":white",
}
keys := []string{}
for fg := range ansi.Colors {
_, err := strconv.Atoi(fg)
if err != nil {
keys = append(keys, fg)
}
}
sort.Strings(keys)
for _, fg := range keys {
for _, bg := range bgColors {
fmt.Fprintln(stdout, padColor(fg, []string{"" + bg, "+b" + bg, "+bh" + bg, "+u" + bg}))
fmt.Fprintln(stdout, padColor(fg, []string{"+uh" + bg, "+B" + bg, "+Bb" + bg /* backgrounds */, "" + bg + "+h", "+s" + bg}))
fmt.Fprintln(stdout, padColor(fg, []string{"+b" + bg + "+h", "+bh" + bg + "+h", "+u" + bg + "+h", "+uh" + bg + "+h"}))
}
}
}
func print256Colors() {
ansi.DisableColors(false)
stdout := colorable.NewColorableStdout()
bgColors := []string{""}
for i := 0; i < 256; i++ {
key := fmt.Sprintf(":%d", i)
bgColors = append(bgColors, key)
}
keys := []string{}
for fg := range ansi.Colors {
n, err := strconv.Atoi(fg)
if err == nil {
keys = append(keys, fmt.Sprintf("%3d", n))
}
}
sort.Strings(keys)
for _, fg := range keys {
for _, bg := range bgColors {
fmt.Fprintln(stdout, padColor(fg, []string{"" + bg, "+b" + bg, "+u" + bg}))
fmt.Fprintln(stdout, padColor(fg, []string{"+B" + bg, "+Bb" + bg, "+s" + bg}))
}
}
}
func printConstants() {
stdout := colorable.NewColorableStdout()
fmt.Fprintln(stdout, ansi.DefaultFG, "ansi.DefaultFG", ansi.Reset)
fmt.Fprintln(stdout, ansi.Black, "ansi.Black", ansi.Reset)
fmt.Fprintln(stdout, ansi.Red, "ansi.Red", ansi.Reset)
fmt.Fprintln(stdout, ansi.Green, "ansi.Green", ansi.Reset)
fmt.Fprintln(stdout, ansi.Yellow, "ansi.Yellow", ansi.Reset)
fmt.Fprintln(stdout, ansi.Blue, "ansi.Blue", ansi.Reset)
fmt.Fprintln(stdout, ansi.Magenta, "ansi.Magenta", ansi.Reset)
fmt.Fprintln(stdout, ansi.Cyan, "ansi.Cyan", ansi.Reset)
fmt.Fprintln(stdout, ansi.White, "ansi.White", ansi.Reset)
fmt.Fprintln(stdout, ansi.LightBlack, "ansi.LightBlack", ansi.Reset)
fmt.Fprintln(stdout, ansi.LightRed, "ansi.LightRed", ansi.Reset)
fmt.Fprintln(stdout, ansi.LightGreen, "ansi.LightGreen", ansi.Reset)
fmt.Fprintln(stdout, ansi.LightYellow, "ansi.LightYellow", ansi.Reset)
fmt.Fprintln(stdout, ansi.LightBlue, "ansi.LightBlue", ansi.Reset)
fmt.Fprintln(stdout, ansi.LightMagenta, "ansi.LightMagenta", ansi.Reset)
fmt.Fprintln(stdout, ansi.LightCyan, "ansi.LightCyan", ansi.Reset)
fmt.Fprintln(stdout, ansi.LightWhite, "ansi.LightWhite", ansi.Reset)
}
-50
View File
@@ -1,50 +0,0 @@
// Open is a simple example of the github.com/pkg/browser package.
//
// Usage:
//
// # Open a file in a browser window
// Open $FILE
//
// # Open a URL in a browser window
// Open $URL
//
// # Open the contents of stdin in a browser window
// cat $SOMEFILE | Open
package main
import (
"flag"
"fmt"
"log"
"os"
"github.com/pkg/browser"
)
func usage() {
fmt.Fprintf(os.Stderr, "Usage:\n %s [file]\n", os.Args[0])
flag.PrintDefaults()
}
func init() {
flag.Usage = usage
flag.Parse()
}
func check(err error) {
if err != nil {
log.Fatal(err)
}
}
func main() {
args := flag.Args()
switch len(args) {
case 0:
check(browser.OpenReader(os.Stdin))
case 1:
check(browser.OpenFile(args[0]))
default:
usage()
}
}
-27
View File
@@ -1,27 +0,0 @@
# Timing Tests
It was noted in [issue #2](github.com/sethgrid/pester/issue/2) that Pester may be slower than the standard library (along with bug that was fixed).
I put together a quick test to see how Pester fairs against the stand library. Here are the results:
```
$ go test
Standard Library Get 675178 ns Avg.
Pester, Default 690157 ns Avg.
Pester, Retries 1, Conc 1 671322 ns Avg.
Pester, Retries 2, Conc 2 764386 ns Avg.
Pester, Retries 3, Conc 3 893899 ns Avg.
Pester, Retries 0, Conc 1 730407 ns Avg.
Pester, Retries 0, Conc 2 1077721 ns Avg.
Pester, Retries 0, Conc 3 1889403 ns Avg.
Pester, Retries 0, Conc 1 1758464 ns Avg.
Pester, Retries 2, Conc 1 1249081 ns Avg.
Pester, Retries 3, Conc 1 1824322 ns Avg.
PASS
```
Running the test locally multiple times shows some variance, but this is a typical result. In raw time, these average times are not far off from each other (about 1ms from the best to worst case). In comparisons between percents, we see a drift of up to 3x.
The up to 3x drift between the near identical default Pester implementation and the Standard Library http.Get call compared to the last test case of 'Retries 3, Conc 1' makes little sense in that the default Pester uses 'Retries 3, Conc 1' as its settings.
I think that it is safe to say that there is no material difference in speed between the Standard Library and Pester.
-164
View File
@@ -1,164 +0,0 @@
package main
/*
Can't use testing.B Tests because it eats up file descriptors
*/
import (
"fmt"
"log"
"net"
"net/http"
"strconv"
"strings"
"testing"
"time"
"github.com/sethgrid/pester"
)
type getter func(string) (*http.Response, error)
func TestWarmup(t *testing.T) {
// The first request/test takes more time.
// Does not matter if we use http.Get or pester.Get
// nor if we use the default client or initialize one.
// I don't know why yet.
c := pester.New()
_ = runner("Warm Up", c.Get)
}
func TestStdLibGet(t *testing.T) {
// base case - get a url with std lib
fmt.Println(runner("Standard Library Get ", http.Get))
}
func TestPesterGetDefaults(t *testing.T) {
fmt.Println(runner("Pester, Default", pester.Get))
}
func TestPesterRetry1Conc1(t *testing.T) {
c := pester.New()
c.MaxRetries = 1
c.Concurrency = 1
fmt.Println(runner("Pester, Retries 1, Conc 1", c.Get))
}
func TestPesterRetry2Conc2(t *testing.T) {
c := pester.New()
c.MaxRetries = 2
c.Concurrency = 2
fmt.Println(runner("Pester, Retries 2, Conc 2", c.Get))
}
func TestPesterRetry3Conc3(t *testing.T) {
c := pester.New()
c.MaxRetries = 3
c.Concurrency = 3
fmt.Println(runner("Pester, Retries 3, Conc 3", c.Get))
}
func TestPesterGetRetry0Conc1(t *testing.T) {
c := pester.New()
c.MaxRetries = 0
c.Concurrency = 1
fmt.Println(runner("Pester, Retries 0, Conc 1", c.Get))
}
func TestPesterGetRetry0Conc2(t *testing.T) {
c := pester.New()
c.MaxRetries = 0
c.Concurrency = 2
fmt.Println(runner("Pester, Retries 0, Conc 2", c.Get))
}
func TestPesterGetRetry0Conc3(t *testing.T) {
c := pester.New()
c.MaxRetries = 0
c.Concurrency = 3
fmt.Println(runner("Pester, Retries 0, Conc 3", c.Get))
}
func TestPesterGetRetry1Conc1(t *testing.T) {
c := pester.New()
c.MaxRetries = 0
c.Concurrency = 1
fmt.Println(runner("Pester, Retries 0, Conc 1", c.Get))
}
func TestPesterGetRetries2Conc1(t *testing.T) {
c := pester.New()
c.Concurrency = 2
c.MaxRetries = 1
fmt.Println(runner("Pester, Retries 2, Conc 1", c.Get))
}
func TestPesterGetRetries3Conc1(t *testing.T) {
c := pester.New()
c.Concurrency = 3
c.MaxRetries = 1
fmt.Println(runner("Pester, Retries 3, Conc 1", c.Get))
}
func reportTimings(name string, timings []int64) string {
var sum int64
for _, t := range timings {
sum += t
}
average := sum / int64(len(timings))
return fmt.Sprintf(" %-29s %7d ns Avg.", name, average)
}
func runServer() int {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("OK"))
})
l, err := net.Listen("tcp", ":0")
if err != nil {
log.Fatal("unable to secure listener", err)
}
go func() {
if err := http.Serve(l, mux); err != nil {
log.Fatal("stable server error", err)
}
}()
port, err := strconv.Atoi(strings.Replace(l.Addr().String(), "[::]:", "", 1))
if err != nil {
log.Fatal("unable to determine port", err)
}
return port
}
func runner(name string, Do getter) string {
var timings []int64
for n := 0; n < 7; n++ {
stableServerPort := runServer()
start := time.Now().UnixNano()
r, err := Do(fmt.Sprintf("http://localhost:%d/%d", stableServerPort, time.Now().UnixNano()))
if err != nil {
log.Fatal("Error came back and it should not have", err)
}
if r == nil {
log.Fatal("No response!")
}
if r.Body == nil {
log.Fatal("No response body!")
}
r.Body.Close()
end := time.Now().UnixNano()
timings = append(timings, end-start)
}
return reportTimings(name, timings)
}
-184
View File
@@ -1,184 +0,0 @@
package main
/*
We start up a rando response server that will give different response codes
and different response times to simulate poor network / service conditions.
The main function is cut into blocks to perserve variable scope and examples
of each pester function can be seen in action.
The server logs incoming requests while the main blocks log what they intend
to do and what they get back.
*/
import (
"flag"
"fmt"
"log"
"math/rand"
"net/http"
"net/url"
"strings"
"time"
"github.com/sethgrid/pester"
)
func init() {
rand.Seed(time.Now().Unix())
}
func main() {
// set everything up
var port int
flag.IntVar(&port, "port", 9000, "set the port for the rando response server")
flag.Parse()
log.Printf("Starting a rando response server on :%d ...\n\n", port)
go func() {
http.HandleFunc("/", randoHandler)
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", port), nil))
}()
//////////////////////////////////////////////////////
// begin running through each of the pestor methods //
//////////////////////////////////////////////////////
log.Println("> pester.Get default")
{ // drop in replacement for http.Get and other client methods
resp, err := pester.Get(fmt.Sprintf("http://localhost:%d", port))
if err != nil {
log.Fatalf("error GETing default", err)
}
defer resp.Body.Close()
log.Printf("GET :%d %s \n\n", port, resp.Status)
}
log.Println("> pester.Get with set backoff stategy, concurrency and retries increased")
{ // control the resiliency
client := pester.New()
client.Concurrency = 3
client.MaxRetries = 5
client.Backoff = pester.ExponentialJitterBackoff
client.KeepLog = true
resp, err := client.Get(fmt.Sprintf("http://localhost:%d", port))
if err != nil {
log.Fatalf("error GETing with all options, %s\n\n", client.LogString())
}
defer resp.Body.Close()
log.Printf("Exponential Jitter Backoff :%d %s [request %d, retry %d]\n\n", port, resp.Status, client.SuccessReqNum, client.SuccessRetryNum)
}
log.Println("> pester.Get with custom backoff strategy")
{ // set a custom backoff strategy
client := pester.New()
client.Backoff = func(retry int) time.Duration {
return time.Duration(retry*200) * time.Millisecond
}
client.Timeout = 5 * time.Second
client.KeepLog = true
resp, err := client.Get(fmt.Sprintf("http://localhost:%d", port))
if err != nil {
log.Fatalf("error GETing custom backoff\n\n", client.LogString())
}
defer resp.Body.Close()
log.Printf("Custom backoff :%d %s [request %d, retry %d]\n\n", port, resp.Status, client.SuccessReqNum, client.SuccessRetryNum)
}
log.Println("> pester.Post with defaults")
{ // use the pester.Post drop in replacement
resp, err := pester.Post(fmt.Sprintf("http://localhost:%d", port), "text/plain", strings.NewReader("data"))
if err != nil {
log.Fatalf("error POSTing with defaults - %v\n\n", err)
}
defer resp.Body.Close()
log.Printf("POST :%d %s\n\n", port, resp.Status)
}
log.Println("> pester.Post with retries to non-existant url")
{
client := pester.New()
client.MaxRetries = 3
client.KeepLog = true
_, err := client.Post("http://localhost:9001", "application/json", strings.NewReader(`{"json":true}`))
if err == nil {
log.Printf("expected to error after max retries of 3")
}
if len(client.ErrLog) != 3 {
log.Fatalf("expected 3 error logs, got %d: %v", len(client.ErrLog), client.ErrLog)
}
log.Printf("POST: %v\n\n", err)
}
log.Println("> pester.Head with defaults")
{ // use the pester.Head drop in replacement
resp, err := pester.Head(fmt.Sprintf("http://localhost:%d", port))
if err != nil {
log.Fatalf("error HEADing with defaults - %v\n\n", err)
}
defer resp.Body.Close()
log.Printf("HEAD :%d %s\n\n", port, resp.Status)
}
log.Println("> pester.PostForm with defaults")
{ // use the pester.Head drop in replacement
resp, err := pester.PostForm(fmt.Sprintf("http://localhost:%d", port), url.Values{"param1": []string{"val1a", "val1b"}, "param2": []string{"val2"}})
if err != nil {
log.Fatalf("error POSTing a form with defaults - %v\n\n", err)
}
defer resp.Body.Close()
log.Printf("POST (form) :%d %s\n\n", port, resp.Status)
}
log.Println("> pester Do with POST")
{ // use the pester version of http.Client.Do
req, err := http.NewRequest("POST", fmt.Sprintf("http://localhost:%d", port), strings.NewReader("data"))
if err != nil {
log.Fatal("Unable to create a new http request", err)
}
resp, err := pester.Do(req)
if err != nil {
log.Fatalf("error POSTing with Do() - %v\n\n", err)
}
defer resp.Body.Close()
log.Printf("Do() POST :%d %s\n\n", port, resp.Status)
}
}
// randoHandler will cause random delays and give random status responses
func randoHandler(w http.ResponseWriter, r *http.Request) {
delay := rand.Intn(5000)
var code int
switch rand.Intn(10) {
case 0:
code = 404
case 1:
code = 400
case 2:
code = 501
case 3:
code = 500
default:
code = 200
}
log.Printf("incoming request on :9000 - will return %d in %d ms", code, delay)
<-time.Tick(time.Duration(delay) * time.Millisecond)
w.WriteHeader(code)
w.Write([]byte(http.StatusText(code)))
}
-45
View File
@@ -1,45 +0,0 @@
// Shows example use of the keyring package
//
// May need to be built with a platform-specific build flag to specify a
// provider. See keyring documentation for details.
//
package main
import (
"fmt"
"os"
"syscall"
"github.com/tmc/keyring"
"golang.org/x/crypto/ssh/terminal"
)
func main() {
if pw, err := keyring.Get("keyring_example", "jack"); err == nil {
fmt.Println("current stored password:", pw)
} else if err == keyring.ErrNotFound {
fmt.Println("no password stored yet")
} else {
fmt.Println("got unexpected error:", err)
os.Exit(1)
}
fmt.Printf("enter new password: ")
pw, err := terminal.ReadPassword(int(syscall.Stdin))
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println("setting keyring_example/jack to..", pw)
err = keyring.Set("keyring_example", "jack", string(pw))
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println("fetching keyring_example/jack..")
if pw, err := keyring.Get("keyring_example", "jack"); err == nil {
fmt.Println("got", pw)
} else {
fmt.Println("error:", err)
}
}