Switch to new vendor style (#1747)
* Switch to new vendor style. * Fix metrics generate command. * Fix miekg/dns types_generate. * Use generated copies of files. * Update miekg to latest. Fixes a problem with `go generate`. * Set GO15VENDOREXPERIMENT. * Build in letsencrypt/boulder. * fix travis more. * Exclude vendor instead of godeps. * Replace some ... * Fix unformatted cmd * Fix errcheck for vendorexp * Add GO15VENDOREXPERIMENT to Makefile. * Temp disable errcheck. * Restore master fetch. * Restore errcheck. * Build with 1.6 also. * Match statsd.*" * Skip errcheck unles Go1.6. * Add other ignorepkg. * Fix errcheck. * move errcheck * Remove go1.6 requirement. * Put godep-restore with errcheck. * Remove go1.6 dep. * Revert master fetch revert. * Remove -r flag from godep save. * Set GO15VENDOREXPERIMENT in Dockerfile and remove _worskpace. * Fix Godep version.
This commit is contained in:
parent
9cb9f82516
commit
e6c17e1717
|
@ -45,6 +45,7 @@ branches:
|
|||
|
||||
before_install:
|
||||
- travis_retry test/travis-before-install.sh
|
||||
- cd $GOPATH/src/github.com/letsencrypt/boulder
|
||||
|
||||
# Override default Travis install command to prevent it from adding
|
||||
# Godeps/_workspace to GOPATH. When that happens, it hides failures that should
|
||||
|
@ -55,13 +56,13 @@ install:
|
|||
env:
|
||||
global:
|
||||
- LETSENCRYPT_PATH=$HOME/letsencrypt
|
||||
- GO15VENDOREXPERIMENT=1
|
||||
matrix:
|
||||
- RUN="integration vet lint fmt errcheck migrations"
|
||||
- RUN="vet fmt migrations integration godep-restore errcheck"
|
||||
# Config changes that have landed in master but not yet been applied to
|
||||
# production can be made in boulder-config-next.json.
|
||||
- RUN="integration" BOULDER_CONFIG="test/boulder-config-next.json"
|
||||
- RUN="unit"
|
||||
- RUN="godep-restore"
|
||||
|
||||
script:
|
||||
- bash test.sh
|
||||
|
|
|
@ -22,7 +22,7 @@ RUN go get -v \
|
|||
# Boulder exposes its web application at port TCP 4000
|
||||
EXPOSE 4000 4002 4003 8053 8055
|
||||
|
||||
ENV GOPATH /go/src/github.com/letsencrypt/boulder/Godeps/_workspace:$GOPATH
|
||||
ENV GO15VENDOREXPERIMENT 1
|
||||
|
||||
WORKDIR /go/src/github.com/letsencrypt/boulder
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"ImportPath": "github.com/letsencrypt/boulder",
|
||||
"GoVersion": "go1.5",
|
||||
"GodepVersion": "v60",
|
||||
"GodepVersion": "v62",
|
||||
"Packages": [
|
||||
"./..."
|
||||
],
|
||||
|
@ -123,8 +123,8 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "github.com/letsencrypt/go-safe-browsing-api",
|
||||
"Comment": "2.0.0-9-gf1b4fa4",
|
||||
"Rev": "f1b4fa409d9efcee2ceee9047549413861603033"
|
||||
"Comment": "2.0.0-10-ga109a23",
|
||||
"Rev": "a109a231e10a089285a0aac0fd03c8a083975758"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/letsencrypt/net/publicsuffix",
|
||||
|
@ -136,7 +136,7 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "github.com/miekg/dns",
|
||||
"Rev": "d27455715200c7d3e321a1e5cadb27c9ee0b0f02"
|
||||
"Rev": "031fad65fea12748347cbb2a30f190b6257fc844"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/miekg/pkcs11",
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
/pkg
|
||||
/bin
|
196
Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd/buffered_test.go
generated
vendored
196
Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd/buffered_test.go
generated
vendored
|
@ -1,196 +0,0 @@
|
|||
package statsd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestBufferedClientFlushSize(t *testing.T) {
|
||||
l, err := newUDPListener("127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer l.Close()
|
||||
|
||||
for _, tt := range statsdPacketTests {
|
||||
// set flush length to the size of the expected output packet
|
||||
// so we can ensure a flush happens right away.
|
||||
// set flush time sufficiently high so that it never matters for this
|
||||
// test
|
||||
c, err := NewBufferedClient(l.LocalAddr().String(), tt.Prefix, 10*time.Second, len(tt.Expected)+1)
|
||||
if err != nil {
|
||||
c.Close()
|
||||
t.Fatal(err)
|
||||
}
|
||||
method := reflect.ValueOf(c).MethodByName(tt.Method)
|
||||
e := method.Call([]reflect.Value{
|
||||
reflect.ValueOf(tt.Stat),
|
||||
reflect.ValueOf(tt.Value),
|
||||
reflect.ValueOf(tt.Rate)})[0]
|
||||
errInter := e.Interface()
|
||||
if errInter != nil {
|
||||
c.Close()
|
||||
t.Fatal(errInter.(error))
|
||||
}
|
||||
|
||||
data := make([]byte, len(tt.Expected)+16)
|
||||
_, _, err = l.ReadFrom(data)
|
||||
if err != nil {
|
||||
c.Close()
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
data = bytes.TrimRight(data, "\x00\n")
|
||||
if bytes.Equal(data, []byte(tt.Expected)) != true {
|
||||
t.Fatalf("%s got '%s' expected '%s'", tt.Method, data, tt.Expected)
|
||||
}
|
||||
c.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func TestBufferedClientFlushTime(t *testing.T) {
|
||||
l, err := newUDPListener("127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer l.Close()
|
||||
|
||||
for _, tt := range statsdPacketTests {
|
||||
// set flush length to the size of the expected output packet
|
||||
// so we can ensure a flush happens right away.
|
||||
// set flush time sufficiently high so that it never matters for this
|
||||
// test
|
||||
c, err := NewBufferedClient(l.LocalAddr().String(), tt.Prefix, 1*time.Microsecond, 1024)
|
||||
if err != nil {
|
||||
c.Close()
|
||||
t.Fatal(err)
|
||||
}
|
||||
method := reflect.ValueOf(c).MethodByName(tt.Method)
|
||||
e := method.Call([]reflect.Value{
|
||||
reflect.ValueOf(tt.Stat),
|
||||
reflect.ValueOf(tt.Value),
|
||||
reflect.ValueOf(tt.Rate)})[0]
|
||||
errInter := e.Interface()
|
||||
if errInter != nil {
|
||||
c.Close()
|
||||
t.Fatal(errInter.(error))
|
||||
}
|
||||
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
|
||||
data := make([]byte, len(tt.Expected)+16)
|
||||
_, _, err = l.ReadFrom(data)
|
||||
if err != nil {
|
||||
c.Close()
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
data = bytes.TrimRight(data, "\x00\n")
|
||||
if bytes.Equal(data, []byte(tt.Expected)) != true {
|
||||
t.Fatalf("%s got '%s' expected '%s'", tt.Method, data, tt.Expected)
|
||||
}
|
||||
c.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func TestBufferedClientBigPacket(t *testing.T) {
|
||||
l, err := newUDPListener("127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer l.Close()
|
||||
|
||||
c, err := NewBufferedClient(l.LocalAddr().String(), "test", 10*time.Millisecond, 1024)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
for _, tt := range statsdPacketTests {
|
||||
if tt.Prefix != "test" {
|
||||
continue
|
||||
}
|
||||
method := reflect.ValueOf(c).MethodByName(tt.Method)
|
||||
e := method.Call([]reflect.Value{
|
||||
reflect.ValueOf(tt.Stat),
|
||||
reflect.ValueOf(tt.Value),
|
||||
reflect.ValueOf(tt.Rate)})[0]
|
||||
errInter := e.Interface()
|
||||
if errInter != nil {
|
||||
t.Fatal(errInter.(error))
|
||||
}
|
||||
}
|
||||
|
||||
expected := ""
|
||||
for _, tt := range statsdPacketTests {
|
||||
if tt.Prefix != "test" {
|
||||
continue
|
||||
}
|
||||
expected = expected + tt.Expected + "\n"
|
||||
}
|
||||
|
||||
time.Sleep(12 * time.Millisecond)
|
||||
data := make([]byte, 1024)
|
||||
_, _, err = l.ReadFrom(data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
data = bytes.TrimRight(data, "\x00")
|
||||
if bytes.Equal(data, []byte(expected)) != true {
|
||||
t.Fatalf("got '%s' expected '%s'", data, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFlushOnClose(t *testing.T) {
|
||||
l, err := newUDPListener("127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer l.Close()
|
||||
|
||||
c, err := NewBufferedClient(l.LocalAddr().String(), "test", 1*time.Second, 1024)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
c.Inc("count", int64(1), 1.0)
|
||||
c.Close()
|
||||
|
||||
expected := "test.count:1|c\n"
|
||||
|
||||
data := make([]byte, 1024)
|
||||
_, _, err = l.ReadFrom(data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
data = bytes.TrimRight(data, "\x00")
|
||||
if bytes.Equal(data, []byte(expected)) != true {
|
||||
fmt.Println(data)
|
||||
fmt.Println([]byte(expected))
|
||||
t.Fatalf("got '%s' expected '%s'", data, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleClient_buffered() {
|
||||
// first create a client
|
||||
client, err := NewBufferedClient("127.0.0.1:8125", "test-client", 10*time.Millisecond, 0)
|
||||
// handle any errors
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// make sure to clean up
|
||||
defer client.Close()
|
||||
|
||||
// Send a stat
|
||||
err = client.Inc("stat1", 42, 1.0)
|
||||
// handle any errors
|
||||
if err != nil {
|
||||
log.Printf("Error sending metric: %+v", err)
|
||||
}
|
||||
}
|
|
@ -1,285 +0,0 @@
|
|||
package statsd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"log"
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var statsdPacketTests = []struct {
|
||||
Prefix string
|
||||
Method string
|
||||
Stat string
|
||||
Value interface{}
|
||||
Rate float32
|
||||
Expected string
|
||||
}{
|
||||
{"test", "Gauge", "gauge", int64(1), 1.0, "test.gauge:1|g"},
|
||||
{"test", "Inc", "count", int64(1), 0.999999, "test.count:1|c|@0.999999"},
|
||||
{"test", "Inc", "count", int64(1), 1.0, "test.count:1|c"},
|
||||
{"test", "Dec", "count", int64(1), 1.0, "test.count:-1|c"},
|
||||
{"test", "Timing", "timing", int64(1), 1.0, "test.timing:1|ms"},
|
||||
{"test", "TimingDuration", "timing", 1500 * time.Microsecond, 1.0, "test.timing:1.5|ms"},
|
||||
{"test", "TimingDuration", "timing", 3 * time.Microsecond, 1.0, "test.timing:0.003|ms"},
|
||||
{"test", "Set", "strset", "pickle", 1.0, "test.strset:pickle|s"},
|
||||
{"test", "SetInt", "intset", int64(1), 1.0, "test.intset:1|s"},
|
||||
{"test", "GaugeDelta", "gauge", int64(1), 1.0, "test.gauge:+1|g"},
|
||||
{"test", "GaugeDelta", "gauge", int64(-1), 1.0, "test.gauge:-1|g"},
|
||||
|
||||
{"", "Gauge", "gauge", int64(1), 1.0, "gauge:1|g"},
|
||||
{"", "Inc", "count", int64(1), 0.999999, "count:1|c|@0.999999"},
|
||||
{"", "Inc", "count", int64(1), 1.0, "count:1|c"},
|
||||
{"", "Dec", "count", int64(1), 1.0, "count:-1|c"},
|
||||
{"", "Timing", "timing", int64(1), 1.0, "timing:1|ms"},
|
||||
{"", "TimingDuration", "timing", 1500 * time.Microsecond, 1.0, "timing:1.5|ms"},
|
||||
{"", "Set", "strset", "pickle", 1.0, "strset:pickle|s"},
|
||||
{"", "SetInt", "intset", int64(1), 1.0, "intset:1|s"},
|
||||
{"", "GaugeDelta", "gauge", int64(1), 1.0, "gauge:+1|g"},
|
||||
{"", "GaugeDelta", "gauge", int64(-1), 1.0, "gauge:-1|g"},
|
||||
}
|
||||
|
||||
func TestClient(t *testing.T) {
|
||||
l, err := newUDPListener("127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer l.Close()
|
||||
for _, tt := range statsdPacketTests {
|
||||
c, err := NewClient(l.LocalAddr().String(), tt.Prefix)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
method := reflect.ValueOf(c).MethodByName(tt.Method)
|
||||
e := method.Call([]reflect.Value{
|
||||
reflect.ValueOf(tt.Stat),
|
||||
reflect.ValueOf(tt.Value),
|
||||
reflect.ValueOf(tt.Rate)})[0]
|
||||
errInter := e.Interface()
|
||||
if errInter != nil {
|
||||
t.Fatal(errInter.(error))
|
||||
}
|
||||
|
||||
data := make([]byte, 128)
|
||||
_, _, err = l.ReadFrom(data)
|
||||
if err != nil {
|
||||
c.Close()
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
data = bytes.TrimRight(data, "\x00")
|
||||
if bytes.Equal(data, []byte(tt.Expected)) != true {
|
||||
c.Close()
|
||||
t.Fatalf("%s got '%s' expected '%s'", tt.Method, data, tt.Expected)
|
||||
}
|
||||
c.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkClientInc(b *testing.B) {
|
||||
l, err := newUDPListener("127.0.0.1:0")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
defer l.Close()
|
||||
c, err := NewClient(l.LocalAddr().String(), "test")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
b.ResetTimer()
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
//i := 0; i < b.N; i++ {
|
||||
c.Inc("benchinc", 1, 1)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkClientIncSample(b *testing.B) {
|
||||
l, err := newUDPListener("127.0.0.1:0")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
defer l.Close()
|
||||
c, err := NewClient(l.LocalAddr().String(), "test")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
b.ResetTimer()
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
//i := 0; i < b.N; i++ {
|
||||
c.Inc("benchinc", 1, 0.3)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkClientSetInt(b *testing.B) {
|
||||
l, err := newUDPListener("127.0.0.1:0")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
defer l.Close()
|
||||
c, err := NewClient(l.LocalAddr().String(), "test")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
b.ResetTimer()
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
//i := 0; i < b.N; i++ {
|
||||
c.SetInt("setint", 1, 1)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkClientSetIntSample(b *testing.B) {
|
||||
l, err := newUDPListener("127.0.0.1:0")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
defer l.Close()
|
||||
c, err := NewClient(l.LocalAddr().String(), "test")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
b.ResetTimer()
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
//i := 0; i < b.N; i++ {
|
||||
c.SetInt("setint", 1, 0.3)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestNilClient(t *testing.T) {
|
||||
l, err := newUDPListener("127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer l.Close()
|
||||
for _, tt := range statsdPacketTests {
|
||||
var c *Client
|
||||
|
||||
method := reflect.ValueOf(c).MethodByName(tt.Method)
|
||||
e := method.Call([]reflect.Value{
|
||||
reflect.ValueOf(tt.Stat),
|
||||
reflect.ValueOf(tt.Value),
|
||||
reflect.ValueOf(tt.Rate)})[0]
|
||||
errInter := e.Interface()
|
||||
if errInter != nil {
|
||||
t.Fatal(errInter.(error))
|
||||
}
|
||||
|
||||
data := make([]byte, 128)
|
||||
n, _, err := l.ReadFrom(data)
|
||||
// this is expected to error, since there should
|
||||
// be no udp data sent, so the read will time out
|
||||
if err == nil || n != 0 {
|
||||
c.Close()
|
||||
t.Fatal(err)
|
||||
}
|
||||
c.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoopClient(t *testing.T) {
|
||||
l, err := newUDPListener("127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer l.Close()
|
||||
for _, tt := range statsdPacketTests {
|
||||
c, err := NewNoopClient(l.LocalAddr().String(), tt.Prefix)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
method := reflect.ValueOf(c).MethodByName(tt.Method)
|
||||
e := method.Call([]reflect.Value{
|
||||
reflect.ValueOf(tt.Stat),
|
||||
reflect.ValueOf(tt.Value),
|
||||
reflect.ValueOf(tt.Rate)})[0]
|
||||
errInter := e.Interface()
|
||||
if errInter != nil {
|
||||
t.Fatal(errInter.(error))
|
||||
}
|
||||
|
||||
data := make([]byte, 128)
|
||||
n, _, err := l.ReadFrom(data)
|
||||
// this is expected to error, since there should
|
||||
// be no udp data sent, so the read will time out
|
||||
if err == nil || n != 0 {
|
||||
c.Close()
|
||||
t.Fatal(err)
|
||||
}
|
||||
c.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func newUDPListener(addr string) (*net.UDPConn, error) {
|
||||
l, err := net.ListenPacket("udp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
l.SetDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
l.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
l.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))
|
||||
return l.(*net.UDPConn), nil
|
||||
}
|
||||
|
||||
func ExampleClient() {
|
||||
// first create a client
|
||||
client, err := NewClient("127.0.0.1:8125", "test-client")
|
||||
// handle any errors
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// make sure to clean up
|
||||
defer client.Close()
|
||||
|
||||
// Send a stat
|
||||
err = client.Inc("stat1", 42, 1.0)
|
||||
// handle any errors
|
||||
if err != nil {
|
||||
log.Printf("Error sending metric: %+v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleClient_noop() {
|
||||
// use interface so we can sub noop client if needed
|
||||
var client Statter
|
||||
var err error
|
||||
|
||||
// first try to create a real client
|
||||
client, err = NewClient("not-resolvable:8125", "test-client")
|
||||
// Let us say real client creation fails, but you don't care enough about
|
||||
// stats that you don't want your program to run. Just log an error and
|
||||
// make a NoopClient instead
|
||||
if err != nil {
|
||||
log.Println("Remote endpoint did not resolve. Disabling stats", err)
|
||||
client, err = NewNoopClient()
|
||||
}
|
||||
// make sure to clean up
|
||||
defer client.Close()
|
||||
|
||||
// Send a stat
|
||||
err = client.Inc("stat1", 42, 1.0)
|
||||
// handle any errors
|
||||
if err != nil {
|
||||
log.Printf("Error sending metric: %+v", err)
|
||||
}
|
||||
}
|
99
Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd/test-client/main.go
generated
vendored
99
Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd/test-client/main.go
generated
vendored
|
@ -1,99 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
flags "github.com/jessevdk/go-flags"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
// command line flags
|
||||
var opts struct {
|
||||
HostPort string `long:"host" default:"127.0.0.1:8125" description:"host:port of statsd server"`
|
||||
Prefix string `long:"prefix" default:"test-client" description:"Statsd prefix"`
|
||||
StatType string `long:"type" default:"count" description:"stat type to send. Can be timing, count, guage"`
|
||||
StatValue int64 `long:"value" default:"1" description:"Value to send"`
|
||||
Name string `short:"n" long:"name" default:"counter" description:"stat name"`
|
||||
Rate float32 `short:"r" long:"rate" default:"1.0" description:"sample rate"`
|
||||
Volume int `short:"c" long:"count" default:"1000" description:"Number of stats to send. Volume."`
|
||||
Nil bool `long:"nil" default:"false" description:"Use nil client"`
|
||||
Buffered bool `long:"buffered" default:"false" description:"Use a buffered client"`
|
||||
Duration time.Duration `short:"d" long:"duration" default:"10s" description:"How long to spread the volume across. Each second of duration volume/seconds events will be sent."`
|
||||
}
|
||||
|
||||
// parse said flags
|
||||
_, err := flags.Parse(&opts)
|
||||
if err != nil {
|
||||
if e, ok := err.(*flags.Error); ok {
|
||||
if e.Type == flags.ErrHelp {
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
fmt.Printf("Error: %+v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if opts.Nil && opts.Buffered {
|
||||
fmt.Printf("Specifying both nil and buffered together is invalid.")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var client statsd.Statter
|
||||
if !opts.Nil {
|
||||
if !opts.Buffered {
|
||||
client, err = statsd.NewClient(opts.HostPort, opts.Prefix)
|
||||
} else {
|
||||
client, err = statsd.NewBufferedClient(opts.HostPort, opts.Prefix, opts.Duration/time.Duration(4), 0)
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer client.Close()
|
||||
}
|
||||
|
||||
var stat func(stat string, value int64, rate float32) error
|
||||
switch opts.StatType {
|
||||
case "count":
|
||||
stat = func(stat string, value int64, rate float32) error {
|
||||
return client.Inc(stat, value, rate)
|
||||
}
|
||||
case "gauge":
|
||||
stat = func(stat string, value int64, rate float32) error {
|
||||
return client.Gauge(stat, value, rate)
|
||||
}
|
||||
case "timing":
|
||||
stat = func(stat string, value int64, rate float32) error {
|
||||
return client.Timing(stat, value, rate)
|
||||
}
|
||||
default:
|
||||
log.Fatal("Unsupported state type")
|
||||
}
|
||||
|
||||
pertick := opts.Volume / int(opts.Duration.Seconds()) / 10
|
||||
// add some extra tiem, because the first tick takes a while
|
||||
ender := time.After(opts.Duration + 100*time.Millisecond)
|
||||
c := time.Tick(time.Second / 10)
|
||||
count := 0
|
||||
for {
|
||||
select {
|
||||
case <-c:
|
||||
for x := 0; x < pertick; x++ {
|
||||
err := stat(opts.Name, opts.StatValue, opts.Rate)
|
||||
if err != nil {
|
||||
log.Printf("Got Error: %+v", err)
|
||||
break
|
||||
}
|
||||
count += 1
|
||||
}
|
||||
case <-ender:
|
||||
log.Printf("%d events called", count)
|
||||
os.Exit(0)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
Copyright (c) 2014 Kyle Isom <kyle@gokyle.org>
|
||||
|
||||
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.
|
|
@ -1,554 +0,0 @@
|
|||
package cli_test
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/codegangsta/cli"
|
||||
)
|
||||
|
||||
func ExampleApp() {
|
||||
// set args for examples sake
|
||||
os.Args = []string{"greet", "--name", "Jeremy"}
|
||||
|
||||
app := cli.NewApp()
|
||||
app.Name = "greet"
|
||||
app.Flags = []cli.Flag{
|
||||
cli.StringFlag{Name: "name", Value: "bob", Usage: "a name to say"},
|
||||
}
|
||||
app.Action = func(c *cli.Context) {
|
||||
fmt.Printf("Hello %v\n", c.String("name"))
|
||||
}
|
||||
app.Run(os.Args)
|
||||
// Output:
|
||||
// Hello Jeremy
|
||||
}
|
||||
|
||||
func ExampleAppSubcommand() {
|
||||
// set args for examples sake
|
||||
os.Args = []string{"say", "hi", "english", "--name", "Jeremy"}
|
||||
app := cli.NewApp()
|
||||
app.Name = "say"
|
||||
app.Commands = []cli.Command{
|
||||
{
|
||||
Name: "hello",
|
||||
ShortName: "hi",
|
||||
Usage: "use it to see a description",
|
||||
Description: "This is how we describe hello the function",
|
||||
Subcommands: []cli.Command{
|
||||
{
|
||||
Name: "english",
|
||||
ShortName: "en",
|
||||
Usage: "sends a greeting in english",
|
||||
Description: "greets someone in english",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "name",
|
||||
Value: "Bob",
|
||||
Usage: "Name of the person to greet",
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) {
|
||||
fmt.Println("Hello,", c.String("name"))
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
app.Run(os.Args)
|
||||
// Output:
|
||||
// Hello, Jeremy
|
||||
}
|
||||
|
||||
func ExampleAppHelp() {
|
||||
// set args for examples sake
|
||||
os.Args = []string{"greet", "h", "describeit"}
|
||||
|
||||
app := cli.NewApp()
|
||||
app.Name = "greet"
|
||||
app.Flags = []cli.Flag{
|
||||
cli.StringFlag{Name: "name", Value: "bob", Usage: "a name to say"},
|
||||
}
|
||||
app.Commands = []cli.Command{
|
||||
{
|
||||
Name: "describeit",
|
||||
ShortName: "d",
|
||||
Usage: "use it to see a description",
|
||||
Description: "This is how we describe describeit the function",
|
||||
Action: func(c *cli.Context) {
|
||||
fmt.Printf("i like to describe things")
|
||||
},
|
||||
},
|
||||
}
|
||||
app.Run(os.Args)
|
||||
// Output:
|
||||
// NAME:
|
||||
// describeit - use it to see a description
|
||||
//
|
||||
// USAGE:
|
||||
// command describeit [arguments...]
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// This is how we describe describeit the function
|
||||
}
|
||||
|
||||
func ExampleAppBashComplete() {
|
||||
// set args for examples sake
|
||||
os.Args = []string{"greet", "--generate-bash-completion"}
|
||||
|
||||
app := cli.NewApp()
|
||||
app.Name = "greet"
|
||||
app.EnableBashCompletion = true
|
||||
app.Commands = []cli.Command{
|
||||
{
|
||||
Name: "describeit",
|
||||
ShortName: "d",
|
||||
Usage: "use it to see a description",
|
||||
Description: "This is how we describe describeit the function",
|
||||
Action: func(c *cli.Context) {
|
||||
fmt.Printf("i like to describe things")
|
||||
},
|
||||
}, {
|
||||
Name: "next",
|
||||
Usage: "next example",
|
||||
Description: "more stuff to see when generating bash completion",
|
||||
Action: func(c *cli.Context) {
|
||||
fmt.Printf("the next example")
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
app.Run(os.Args)
|
||||
// Output:
|
||||
// describeit
|
||||
// d
|
||||
// next
|
||||
// help
|
||||
// h
|
||||
}
|
||||
|
||||
func TestApp_Run(t *testing.T) {
|
||||
s := ""
|
||||
|
||||
app := cli.NewApp()
|
||||
app.Action = func(c *cli.Context) {
|
||||
s = s + c.Args().First()
|
||||
}
|
||||
|
||||
err := app.Run([]string{"command", "foo"})
|
||||
expect(t, err, nil)
|
||||
err = app.Run([]string{"command", "bar"})
|
||||
expect(t, err, nil)
|
||||
expect(t, s, "foobar")
|
||||
}
|
||||
|
||||
var commandAppTests = []struct {
|
||||
name string
|
||||
expected bool
|
||||
}{
|
||||
{"foobar", true},
|
||||
{"batbaz", true},
|
||||
{"b", true},
|
||||
{"f", true},
|
||||
{"bat", false},
|
||||
{"nothing", false},
|
||||
}
|
||||
|
||||
func TestApp_Command(t *testing.T) {
|
||||
app := cli.NewApp()
|
||||
fooCommand := cli.Command{Name: "foobar", ShortName: "f"}
|
||||
batCommand := cli.Command{Name: "batbaz", ShortName: "b"}
|
||||
app.Commands = []cli.Command{
|
||||
fooCommand,
|
||||
batCommand,
|
||||
}
|
||||
|
||||
for _, test := range commandAppTests {
|
||||
expect(t, app.Command(test.name) != nil, test.expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestApp_CommandWithArgBeforeFlags(t *testing.T) {
|
||||
var parsedOption, firstArg string
|
||||
|
||||
app := cli.NewApp()
|
||||
command := cli.Command{
|
||||
Name: "cmd",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{Name: "option", Value: "", Usage: "some option"},
|
||||
},
|
||||
Action: func(c *cli.Context) {
|
||||
parsedOption = c.String("option")
|
||||
firstArg = c.Args().First()
|
||||
},
|
||||
}
|
||||
app.Commands = []cli.Command{command}
|
||||
|
||||
app.Run([]string{"", "cmd", "my-arg", "--option", "my-option"})
|
||||
|
||||
expect(t, parsedOption, "my-option")
|
||||
expect(t, firstArg, "my-arg")
|
||||
}
|
||||
|
||||
func TestApp_RunAsSubcommandParseFlags(t *testing.T) {
|
||||
var context *cli.Context
|
||||
|
||||
a := cli.NewApp()
|
||||
a.Commands = []cli.Command{
|
||||
{
|
||||
Name: "foo",
|
||||
Action: func(c *cli.Context) {
|
||||
context = c
|
||||
},
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "lang",
|
||||
Value: "english",
|
||||
Usage: "language for the greeting",
|
||||
},
|
||||
},
|
||||
Before: func(_ *cli.Context) error { return nil },
|
||||
},
|
||||
}
|
||||
a.Run([]string{"", "foo", "--lang", "spanish", "abcd"})
|
||||
|
||||
expect(t, context.Args().Get(0), "abcd")
|
||||
expect(t, context.String("lang"), "spanish")
|
||||
}
|
||||
|
||||
func TestApp_CommandWithFlagBeforeTerminator(t *testing.T) {
|
||||
var parsedOption string
|
||||
var args []string
|
||||
|
||||
app := cli.NewApp()
|
||||
command := cli.Command{
|
||||
Name: "cmd",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{Name: "option", Value: "", Usage: "some option"},
|
||||
},
|
||||
Action: func(c *cli.Context) {
|
||||
parsedOption = c.String("option")
|
||||
args = c.Args()
|
||||
},
|
||||
}
|
||||
app.Commands = []cli.Command{command}
|
||||
|
||||
app.Run([]string{"", "cmd", "my-arg", "--option", "my-option", "--", "--notARealFlag"})
|
||||
|
||||
expect(t, parsedOption, "my-option")
|
||||
expect(t, args[0], "my-arg")
|
||||
expect(t, args[1], "--")
|
||||
expect(t, args[2], "--notARealFlag")
|
||||
}
|
||||
|
||||
func TestApp_CommandWithNoFlagBeforeTerminator(t *testing.T) {
|
||||
var args []string
|
||||
|
||||
app := cli.NewApp()
|
||||
command := cli.Command{
|
||||
Name: "cmd",
|
||||
Action: func(c *cli.Context) {
|
||||
args = c.Args()
|
||||
},
|
||||
}
|
||||
app.Commands = []cli.Command{command}
|
||||
|
||||
app.Run([]string{"", "cmd", "my-arg", "--", "notAFlagAtAll"})
|
||||
|
||||
expect(t, args[0], "my-arg")
|
||||
expect(t, args[1], "--")
|
||||
expect(t, args[2], "notAFlagAtAll")
|
||||
}
|
||||
|
||||
func TestApp_Float64Flag(t *testing.T) {
|
||||
var meters float64
|
||||
|
||||
app := cli.NewApp()
|
||||
app.Flags = []cli.Flag{
|
||||
cli.Float64Flag{Name: "height", Value: 1.5, Usage: "Set the height, in meters"},
|
||||
}
|
||||
app.Action = func(c *cli.Context) {
|
||||
meters = c.Float64("height")
|
||||
}
|
||||
|
||||
app.Run([]string{"", "--height", "1.93"})
|
||||
expect(t, meters, 1.93)
|
||||
}
|
||||
|
||||
func TestApp_ParseSliceFlags(t *testing.T) {
|
||||
var parsedOption, firstArg string
|
||||
var parsedIntSlice []int
|
||||
var parsedStringSlice []string
|
||||
|
||||
app := cli.NewApp()
|
||||
command := cli.Command{
|
||||
Name: "cmd",
|
||||
Flags: []cli.Flag{
|
||||
cli.IntSliceFlag{Name: "p", Value: &cli.IntSlice{}, Usage: "set one or more ip addr"},
|
||||
cli.StringSliceFlag{Name: "ip", Value: &cli.StringSlice{}, Usage: "set one or more ports to open"},
|
||||
},
|
||||
Action: func(c *cli.Context) {
|
||||
parsedIntSlice = c.IntSlice("p")
|
||||
parsedStringSlice = c.StringSlice("ip")
|
||||
parsedOption = c.String("option")
|
||||
firstArg = c.Args().First()
|
||||
},
|
||||
}
|
||||
app.Commands = []cli.Command{command}
|
||||
|
||||
app.Run([]string{"", "cmd", "my-arg", "-p", "22", "-p", "80", "-ip", "8.8.8.8", "-ip", "8.8.4.4"})
|
||||
|
||||
IntsEquals := func(a, b []int) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
for i, v := range a {
|
||||
if v != b[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
StrsEquals := func(a, b []string) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
for i, v := range a {
|
||||
if v != b[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
var expectedIntSlice = []int{22, 80}
|
||||
var expectedStringSlice = []string{"8.8.8.8", "8.8.4.4"}
|
||||
|
||||
if !IntsEquals(parsedIntSlice, expectedIntSlice) {
|
||||
t.Errorf("%v does not match %v", parsedIntSlice, expectedIntSlice)
|
||||
}
|
||||
|
||||
if !StrsEquals(parsedStringSlice, expectedStringSlice) {
|
||||
t.Errorf("%v does not match %v", parsedStringSlice, expectedStringSlice)
|
||||
}
|
||||
}
|
||||
|
||||
func TestApp_DefaultStdout(t *testing.T) {
|
||||
app := cli.NewApp()
|
||||
|
||||
if app.Writer != os.Stdout {
|
||||
t.Error("Default output writer not set.")
|
||||
}
|
||||
}
|
||||
|
||||
type mockWriter struct {
|
||||
written []byte
|
||||
}
|
||||
|
||||
func (fw *mockWriter) Write(p []byte) (n int, err error) {
|
||||
if fw.written == nil {
|
||||
fw.written = p
|
||||
} else {
|
||||
fw.written = append(fw.written, p...)
|
||||
}
|
||||
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func (fw *mockWriter) GetWritten() (b []byte) {
|
||||
return fw.written
|
||||
}
|
||||
|
||||
func TestApp_SetStdout(t *testing.T) {
|
||||
w := &mockWriter{}
|
||||
|
||||
app := cli.NewApp()
|
||||
app.Name = "test"
|
||||
app.Writer = w
|
||||
|
||||
err := app.Run([]string{"help"})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Run error: %s", err)
|
||||
}
|
||||
|
||||
if len(w.written) == 0 {
|
||||
t.Error("App did not write output to desired writer.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestApp_BeforeFunc(t *testing.T) {
|
||||
beforeRun, subcommandRun := false, false
|
||||
beforeError := fmt.Errorf("fail")
|
||||
var err error
|
||||
|
||||
app := cli.NewApp()
|
||||
|
||||
app.Before = func(c *cli.Context) error {
|
||||
beforeRun = true
|
||||
s := c.String("opt")
|
||||
if s == "fail" {
|
||||
return beforeError
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
app.Commands = []cli.Command{
|
||||
cli.Command{
|
||||
Name: "sub",
|
||||
Action: func(c *cli.Context) {
|
||||
subcommandRun = true
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
app.Flags = []cli.Flag{
|
||||
cli.StringFlag{Name: "opt"},
|
||||
}
|
||||
|
||||
// run with the Before() func succeeding
|
||||
err = app.Run([]string{"command", "--opt", "succeed", "sub"})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Run error: %s", err)
|
||||
}
|
||||
|
||||
if beforeRun == false {
|
||||
t.Errorf("Before() not executed when expected")
|
||||
}
|
||||
|
||||
if subcommandRun == false {
|
||||
t.Errorf("Subcommand not executed when expected")
|
||||
}
|
||||
|
||||
// reset
|
||||
beforeRun, subcommandRun = false, false
|
||||
|
||||
// run with the Before() func failing
|
||||
err = app.Run([]string{"command", "--opt", "fail", "sub"})
|
||||
|
||||
// should be the same error produced by the Before func
|
||||
if err != beforeError {
|
||||
t.Errorf("Run error expected, but not received")
|
||||
}
|
||||
|
||||
if beforeRun == false {
|
||||
t.Errorf("Before() not executed when expected")
|
||||
}
|
||||
|
||||
if subcommandRun == true {
|
||||
t.Errorf("Subcommand executed when NOT expected")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestAppNoHelpFlag(t *testing.T) {
|
||||
oldFlag := cli.HelpFlag
|
||||
defer func() {
|
||||
cli.HelpFlag = oldFlag
|
||||
}()
|
||||
|
||||
cli.HelpFlag = cli.BoolFlag{}
|
||||
|
||||
app := cli.NewApp()
|
||||
err := app.Run([]string{"test", "-h"})
|
||||
|
||||
if err != flag.ErrHelp {
|
||||
t.Errorf("expected error about missing help flag, but got: %s (%T)", err, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppHelpPrinter(t *testing.T) {
|
||||
oldPrinter := cli.HelpPrinter
|
||||
defer func() {
|
||||
cli.HelpPrinter = oldPrinter
|
||||
}()
|
||||
|
||||
var wasCalled = false
|
||||
cli.HelpPrinter = func(template string, data interface{}) {
|
||||
wasCalled = true
|
||||
}
|
||||
|
||||
app := cli.NewApp()
|
||||
app.Run([]string{"-h"})
|
||||
|
||||
if wasCalled == false {
|
||||
t.Errorf("Help printer expected to be called, but was not")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppVersionPrinter(t *testing.T) {
|
||||
oldPrinter := cli.VersionPrinter
|
||||
defer func() {
|
||||
cli.VersionPrinter = oldPrinter
|
||||
}()
|
||||
|
||||
var wasCalled = false
|
||||
cli.VersionPrinter = func(c *cli.Context) {
|
||||
wasCalled = true
|
||||
}
|
||||
|
||||
app := cli.NewApp()
|
||||
ctx := cli.NewContext(app, nil, nil)
|
||||
cli.ShowVersion(ctx)
|
||||
|
||||
if wasCalled == false {
|
||||
t.Errorf("Version printer expected to be called, but was not")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppCommandNotFound(t *testing.T) {
|
||||
beforeRun, subcommandRun := false, false
|
||||
app := cli.NewApp()
|
||||
|
||||
app.CommandNotFound = func(c *cli.Context, command string) {
|
||||
beforeRun = true
|
||||
}
|
||||
|
||||
app.Commands = []cli.Command{
|
||||
cli.Command{
|
||||
Name: "bar",
|
||||
Action: func(c *cli.Context) {
|
||||
subcommandRun = true
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
app.Run([]string{"command", "foo"})
|
||||
|
||||
expect(t, beforeRun, true)
|
||||
expect(t, subcommandRun, false)
|
||||
}
|
||||
|
||||
func TestGlobalFlagsInSubcommands(t *testing.T) {
|
||||
subcommandRun := false
|
||||
app := cli.NewApp()
|
||||
|
||||
app.Flags = []cli.Flag{
|
||||
cli.BoolFlag{Name: "debug, d", Usage: "Enable debugging"},
|
||||
}
|
||||
|
||||
app.Commands = []cli.Command{
|
||||
cli.Command{
|
||||
Name: "foo",
|
||||
Subcommands: []cli.Command{
|
||||
{
|
||||
Name: "bar",
|
||||
Action: func(c *cli.Context) {
|
||||
if c.GlobalBool("debug") {
|
||||
subcommandRun = true
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
app.Run([]string{"command", "-d", "foo", "bar"})
|
||||
|
||||
expect(t, subcommandRun, true)
|
||||
}
|
13
Godeps/_workspace/src/github.com/codegangsta/cli/autocomplete/bash_autocomplete
generated
vendored
13
Godeps/_workspace/src/github.com/codegangsta/cli/autocomplete/bash_autocomplete
generated
vendored
|
@ -1,13 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
_cli_bash_autocomplete() {
|
||||
local cur prev opts base
|
||||
COMPREPLY=()
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --generate-bash-completion )
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||
return 0
|
||||
}
|
||||
|
||||
complete -F _cli_bash_autocomplete $PROG
|
|
@ -1,5 +0,0 @@
|
|||
autoload -U compinit && compinit
|
||||
autoload -U bashcompinit && bashcompinit
|
||||
|
||||
script_dir=$(dirname $0)
|
||||
source ${script_dir}/bash_autocomplete
|
|
@ -1,100 +0,0 @@
|
|||
package cli_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/codegangsta/cli"
|
||||
)
|
||||
|
||||
func Example() {
|
||||
app := cli.NewApp()
|
||||
app.Name = "todo"
|
||||
app.Usage = "task list on the command line"
|
||||
app.Commands = []cli.Command{
|
||||
{
|
||||
Name: "add",
|
||||
ShortName: "a",
|
||||
Usage: "add a task to the list",
|
||||
Action: func(c *cli.Context) {
|
||||
println("added task: ", c.Args().First())
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "complete",
|
||||
ShortName: "c",
|
||||
Usage: "complete a task on the list",
|
||||
Action: func(c *cli.Context) {
|
||||
println("completed task: ", c.Args().First())
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
app.Run(os.Args)
|
||||
}
|
||||
|
||||
func ExampleSubcommand() {
|
||||
app := cli.NewApp()
|
||||
app.Name = "say"
|
||||
app.Commands = []cli.Command{
|
||||
{
|
||||
Name: "hello",
|
||||
ShortName: "hi",
|
||||
Usage: "use it to see a description",
|
||||
Description: "This is how we describe hello the function",
|
||||
Subcommands: []cli.Command{
|
||||
{
|
||||
Name: "english",
|
||||
ShortName: "en",
|
||||
Usage: "sends a greeting in english",
|
||||
Description: "greets someone in english",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "name",
|
||||
Value: "Bob",
|
||||
Usage: "Name of the person to greet",
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) {
|
||||
println("Hello, ", c.String("name"))
|
||||
},
|
||||
}, {
|
||||
Name: "spanish",
|
||||
ShortName: "sp",
|
||||
Usage: "sends a greeting in spanish",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "surname",
|
||||
Value: "Jones",
|
||||
Usage: "Surname of the person to greet",
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) {
|
||||
println("Hola, ", c.String("surname"))
|
||||
},
|
||||
}, {
|
||||
Name: "french",
|
||||
ShortName: "fr",
|
||||
Usage: "sends a greeting in french",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "nickname",
|
||||
Value: "Stevie",
|
||||
Usage: "Nickname of the person to greet",
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) {
|
||||
println("Bonjour, ", c.String("nickname"))
|
||||
},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
Name: "bye",
|
||||
Usage: "says goodbye",
|
||||
Action: func(c *cli.Context) {
|
||||
println("bye")
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
app.Run(os.Args)
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
package cli_test
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"testing"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/codegangsta/cli"
|
||||
)
|
||||
|
||||
func TestCommandDoNotIgnoreFlags(t *testing.T) {
|
||||
app := cli.NewApp()
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
test := []string{"blah", "blah", "-break"}
|
||||
set.Parse(test)
|
||||
|
||||
c := cli.NewContext(app, set, set)
|
||||
|
||||
command := cli.Command{
|
||||
Name: "test-cmd",
|
||||
ShortName: "tc",
|
||||
Usage: "this is for testing",
|
||||
Description: "testing",
|
||||
Action: func(_ *cli.Context) {},
|
||||
}
|
||||
err := command.Run(c)
|
||||
|
||||
expect(t, err.Error(), "flag provided but not defined: -break")
|
||||
}
|
||||
|
||||
func TestCommandIgnoreFlags(t *testing.T) {
|
||||
app := cli.NewApp()
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
test := []string{"blah", "blah"}
|
||||
set.Parse(test)
|
||||
|
||||
c := cli.NewContext(app, set, set)
|
||||
|
||||
command := cli.Command{
|
||||
Name: "test-cmd",
|
||||
ShortName: "tc",
|
||||
Usage: "this is for testing",
|
||||
Description: "testing",
|
||||
Action: func(_ *cli.Context) {},
|
||||
SkipFlagParsing: true,
|
||||
}
|
||||
err := command.Run(c)
|
||||
|
||||
expect(t, err, nil)
|
||||
}
|
|
@ -1,99 +0,0 @@
|
|||
package cli_test
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/codegangsta/cli"
|
||||
)
|
||||
|
||||
func TestNewContext(t *testing.T) {
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Int("myflag", 12, "doc")
|
||||
globalSet := flag.NewFlagSet("test", 0)
|
||||
globalSet.Int("myflag", 42, "doc")
|
||||
command := cli.Command{Name: "mycommand"}
|
||||
c := cli.NewContext(nil, set, globalSet)
|
||||
c.Command = command
|
||||
expect(t, c.Int("myflag"), 12)
|
||||
expect(t, c.GlobalInt("myflag"), 42)
|
||||
expect(t, c.Command.Name, "mycommand")
|
||||
}
|
||||
|
||||
func TestContext_Int(t *testing.T) {
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Int("myflag", 12, "doc")
|
||||
c := cli.NewContext(nil, set, set)
|
||||
expect(t, c.Int("myflag"), 12)
|
||||
}
|
||||
|
||||
func TestContext_Duration(t *testing.T) {
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Duration("myflag", time.Duration(12*time.Second), "doc")
|
||||
c := cli.NewContext(nil, set, set)
|
||||
expect(t, c.Duration("myflag"), time.Duration(12*time.Second))
|
||||
}
|
||||
|
||||
func TestContext_String(t *testing.T) {
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.String("myflag", "hello world", "doc")
|
||||
c := cli.NewContext(nil, set, set)
|
||||
expect(t, c.String("myflag"), "hello world")
|
||||
}
|
||||
|
||||
func TestContext_Bool(t *testing.T) {
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Bool("myflag", false, "doc")
|
||||
c := cli.NewContext(nil, set, set)
|
||||
expect(t, c.Bool("myflag"), false)
|
||||
}
|
||||
|
||||
func TestContext_BoolT(t *testing.T) {
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Bool("myflag", true, "doc")
|
||||
c := cli.NewContext(nil, set, set)
|
||||
expect(t, c.BoolT("myflag"), true)
|
||||
}
|
||||
|
||||
func TestContext_Args(t *testing.T) {
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Bool("myflag", false, "doc")
|
||||
c := cli.NewContext(nil, set, set)
|
||||
set.Parse([]string{"--myflag", "bat", "baz"})
|
||||
expect(t, len(c.Args()), 2)
|
||||
expect(t, c.Bool("myflag"), true)
|
||||
}
|
||||
|
||||
func TestContext_IsSet(t *testing.T) {
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Bool("myflag", false, "doc")
|
||||
set.String("otherflag", "hello world", "doc")
|
||||
globalSet := flag.NewFlagSet("test", 0)
|
||||
globalSet.Bool("myflagGlobal", true, "doc")
|
||||
c := cli.NewContext(nil, set, globalSet)
|
||||
set.Parse([]string{"--myflag", "bat", "baz"})
|
||||
globalSet.Parse([]string{"--myflagGlobal", "bat", "baz"})
|
||||
expect(t, c.IsSet("myflag"), true)
|
||||
expect(t, c.IsSet("otherflag"), false)
|
||||
expect(t, c.IsSet("bogusflag"), false)
|
||||
expect(t, c.IsSet("myflagGlobal"), false)
|
||||
}
|
||||
|
||||
func TestContext_GlobalIsSet(t *testing.T) {
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Bool("myflag", false, "doc")
|
||||
set.String("otherflag", "hello world", "doc")
|
||||
globalSet := flag.NewFlagSet("test", 0)
|
||||
globalSet.Bool("myflagGlobal", true, "doc")
|
||||
globalSet.Bool("myflagGlobalUnset", true, "doc")
|
||||
c := cli.NewContext(nil, set, globalSet)
|
||||
set.Parse([]string{"--myflag", "bat", "baz"})
|
||||
globalSet.Parse([]string{"--myflagGlobal", "bat", "baz"})
|
||||
expect(t, c.GlobalIsSet("myflag"), false)
|
||||
expect(t, c.GlobalIsSet("otherflag"), false)
|
||||
expect(t, c.GlobalIsSet("bogusflag"), false)
|
||||
expect(t, c.GlobalIsSet("myflagGlobal"), true)
|
||||
expect(t, c.GlobalIsSet("myflagGlobalUnset"), false)
|
||||
expect(t, c.GlobalIsSet("bogusGlobal"), false)
|
||||
}
|
|
@ -1,742 +0,0 @@
|
|||
package cli_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/codegangsta/cli"
|
||||
)
|
||||
|
||||
var boolFlagTests = []struct {
|
||||
name string
|
||||
expected string
|
||||
}{
|
||||
{"help", "--help\t"},
|
||||
{"h", "-h\t"},
|
||||
}
|
||||
|
||||
func TestBoolFlagHelpOutput(t *testing.T) {
|
||||
|
||||
for _, test := range boolFlagTests {
|
||||
flag := cli.BoolFlag{Name: test.name}
|
||||
output := flag.String()
|
||||
|
||||
if output != test.expected {
|
||||
t.Errorf("%s does not match %s", output, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var stringFlagTests = []struct {
|
||||
name string
|
||||
value string
|
||||
expected string
|
||||
}{
|
||||
{"help", "", "--help \t"},
|
||||
{"h", "", "-h \t"},
|
||||
{"h", "", "-h \t"},
|
||||
{"test", "Something", "--test \"Something\"\t"},
|
||||
}
|
||||
|
||||
func TestStringFlagHelpOutput(t *testing.T) {
|
||||
|
||||
for _, test := range stringFlagTests {
|
||||
flag := cli.StringFlag{Name: test.name, Value: test.value}
|
||||
output := flag.String()
|
||||
|
||||
if output != test.expected {
|
||||
t.Errorf("%s does not match %s", output, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringFlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_FOO", "derp")
|
||||
for _, test := range stringFlagTests {
|
||||
flag := cli.StringFlag{Name: test.name, Value: test.value, EnvVar: "APP_FOO"}
|
||||
output := flag.String()
|
||||
|
||||
if !strings.HasSuffix(output, " [$APP_FOO]") {
|
||||
t.Errorf("%s does not end with [$APP_FOO]", output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var stringSliceFlagTests = []struct {
|
||||
name string
|
||||
value *cli.StringSlice
|
||||
expected string
|
||||
}{
|
||||
{"help", func() *cli.StringSlice {
|
||||
s := &cli.StringSlice{}
|
||||
s.Set("")
|
||||
return s
|
||||
}(), "--help [--help option --help option]\t"},
|
||||
{"h", func() *cli.StringSlice {
|
||||
s := &cli.StringSlice{}
|
||||
s.Set("")
|
||||
return s
|
||||
}(), "-h [-h option -h option]\t"},
|
||||
{"h", func() *cli.StringSlice {
|
||||
s := &cli.StringSlice{}
|
||||
s.Set("")
|
||||
return s
|
||||
}(), "-h [-h option -h option]\t"},
|
||||
{"test", func() *cli.StringSlice {
|
||||
s := &cli.StringSlice{}
|
||||
s.Set("Something")
|
||||
return s
|
||||
}(), "--test [--test option --test option]\t"},
|
||||
}
|
||||
|
||||
func TestStringSliceFlagHelpOutput(t *testing.T) {
|
||||
|
||||
for _, test := range stringSliceFlagTests {
|
||||
flag := cli.StringSliceFlag{Name: test.name, Value: test.value}
|
||||
output := flag.String()
|
||||
|
||||
if output != test.expected {
|
||||
t.Errorf("%q does not match %q", output, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringSliceFlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_QWWX", "11,4")
|
||||
for _, test := range stringSliceFlagTests {
|
||||
flag := cli.StringSliceFlag{Name: test.name, Value: test.value, EnvVar: "APP_QWWX"}
|
||||
output := flag.String()
|
||||
|
||||
if !strings.HasSuffix(output, " [$APP_QWWX]") {
|
||||
t.Errorf("%q does not end with [$APP_QWWX]", output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var intFlagTests = []struct {
|
||||
name string
|
||||
expected string
|
||||
}{
|
||||
{"help", "--help \"0\"\t"},
|
||||
{"h", "-h \"0\"\t"},
|
||||
}
|
||||
|
||||
func TestIntFlagHelpOutput(t *testing.T) {
|
||||
|
||||
for _, test := range intFlagTests {
|
||||
flag := cli.IntFlag{Name: test.name}
|
||||
output := flag.String()
|
||||
|
||||
if output != test.expected {
|
||||
t.Errorf("%s does not match %s", output, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntFlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_BAR", "2")
|
||||
for _, test := range intFlagTests {
|
||||
flag := cli.IntFlag{Name: test.name, EnvVar: "APP_BAR"}
|
||||
output := flag.String()
|
||||
|
||||
if !strings.HasSuffix(output, " [$APP_BAR]") {
|
||||
t.Errorf("%s does not end with [$APP_BAR]", output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var durationFlagTests = []struct {
|
||||
name string
|
||||
expected string
|
||||
}{
|
||||
{"help", "--help \"0\"\t"},
|
||||
{"h", "-h \"0\"\t"},
|
||||
}
|
||||
|
||||
func TestDurationFlagHelpOutput(t *testing.T) {
|
||||
|
||||
for _, test := range durationFlagTests {
|
||||
flag := cli.DurationFlag{Name: test.name}
|
||||
output := flag.String()
|
||||
|
||||
if output != test.expected {
|
||||
t.Errorf("%s does not match %s", output, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDurationFlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_BAR", "2h3m6s")
|
||||
for _, test := range durationFlagTests {
|
||||
flag := cli.DurationFlag{Name: test.name, EnvVar: "APP_BAR"}
|
||||
output := flag.String()
|
||||
|
||||
if !strings.HasSuffix(output, " [$APP_BAR]") {
|
||||
t.Errorf("%s does not end with [$APP_BAR]", output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var intSliceFlagTests = []struct {
|
||||
name string
|
||||
value *cli.IntSlice
|
||||
expected string
|
||||
}{
|
||||
{"help", &cli.IntSlice{}, "--help [--help option --help option]\t"},
|
||||
{"h", &cli.IntSlice{}, "-h [-h option -h option]\t"},
|
||||
{"h", &cli.IntSlice{}, "-h [-h option -h option]\t"},
|
||||
{"test", func() *cli.IntSlice {
|
||||
i := &cli.IntSlice{}
|
||||
i.Set("9")
|
||||
return i
|
||||
}(), "--test [--test option --test option]\t"},
|
||||
}
|
||||
|
||||
func TestIntSliceFlagHelpOutput(t *testing.T) {
|
||||
|
||||
for _, test := range intSliceFlagTests {
|
||||
flag := cli.IntSliceFlag{Name: test.name, Value: test.value}
|
||||
output := flag.String()
|
||||
|
||||
if output != test.expected {
|
||||
t.Errorf("%q does not match %q", output, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntSliceFlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_SMURF", "42,3")
|
||||
for _, test := range intSliceFlagTests {
|
||||
flag := cli.IntSliceFlag{Name: test.name, Value: test.value, EnvVar: "APP_SMURF"}
|
||||
output := flag.String()
|
||||
|
||||
if !strings.HasSuffix(output, " [$APP_SMURF]") {
|
||||
t.Errorf("%q does not end with [$APP_SMURF]", output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var float64FlagTests = []struct {
|
||||
name string
|
||||
expected string
|
||||
}{
|
||||
{"help", "--help \"0\"\t"},
|
||||
{"h", "-h \"0\"\t"},
|
||||
}
|
||||
|
||||
func TestFloat64FlagHelpOutput(t *testing.T) {
|
||||
|
||||
for _, test := range float64FlagTests {
|
||||
flag := cli.Float64Flag{Name: test.name}
|
||||
output := flag.String()
|
||||
|
||||
if output != test.expected {
|
||||
t.Errorf("%s does not match %s", output, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFloat64FlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_BAZ", "99.4")
|
||||
for _, test := range float64FlagTests {
|
||||
flag := cli.Float64Flag{Name: test.name, EnvVar: "APP_BAZ"}
|
||||
output := flag.String()
|
||||
|
||||
if !strings.HasSuffix(output, " [$APP_BAZ]") {
|
||||
t.Errorf("%s does not end with [$APP_BAZ]", output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var genericFlagTests = []struct {
|
||||
name string
|
||||
value cli.Generic
|
||||
expected string
|
||||
}{
|
||||
{"test", &Parser{"abc", "def"}, "--test \"abc,def\"\ttest flag"},
|
||||
{"t", &Parser{"abc", "def"}, "-t \"abc,def\"\ttest flag"},
|
||||
}
|
||||
|
||||
func TestGenericFlagHelpOutput(t *testing.T) {
|
||||
|
||||
for _, test := range genericFlagTests {
|
||||
flag := cli.GenericFlag{Name: test.name, Value: test.value, Usage: "test flag"}
|
||||
output := flag.String()
|
||||
|
||||
if output != test.expected {
|
||||
t.Errorf("%q does not match %q", output, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenericFlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_ZAP", "3")
|
||||
for _, test := range genericFlagTests {
|
||||
flag := cli.GenericFlag{Name: test.name, EnvVar: "APP_ZAP"}
|
||||
output := flag.String()
|
||||
|
||||
if !strings.HasSuffix(output, " [$APP_ZAP]") {
|
||||
t.Errorf("%s does not end with [$APP_ZAP]", output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseMultiString(t *testing.T) {
|
||||
(&cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{Name: "serve, s"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.String("serve") != "10" {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if ctx.String("s") != "10" {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
},
|
||||
}).Run([]string{"run", "-s", "10"})
|
||||
}
|
||||
|
||||
func TestParseMultiStringFromEnv(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_COUNT", "20")
|
||||
(&cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{Name: "count, c", EnvVar: "APP_COUNT"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.String("count") != "20" {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if ctx.String("c") != "20" {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
},
|
||||
}).Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiStringFromEnvCascade(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_COUNT", "20")
|
||||
(&cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{Name: "count, c", EnvVar: "COMPAT_COUNT,APP_COUNT"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.String("count") != "20" {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if ctx.String("c") != "20" {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
},
|
||||
}).Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiStringSlice(t *testing.T) {
|
||||
(&cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.StringSliceFlag{Name: "serve, s", Value: &cli.StringSlice{}},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if !reflect.DeepEqual(ctx.StringSlice("serve"), []string{"10", "20"}) {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if !reflect.DeepEqual(ctx.StringSlice("s"), []string{"10", "20"}) {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
},
|
||||
}).Run([]string{"run", "-s", "10", "-s", "20"})
|
||||
}
|
||||
|
||||
func TestParseMultiStringSliceFromEnv(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_INTERVALS", "20,30,40")
|
||||
|
||||
(&cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.StringSliceFlag{Name: "intervals, i", Value: &cli.StringSlice{}, EnvVar: "APP_INTERVALS"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if !reflect.DeepEqual(ctx.StringSlice("intervals"), []string{"20", "30", "40"}) {
|
||||
t.Errorf("main name not set from env")
|
||||
}
|
||||
if !reflect.DeepEqual(ctx.StringSlice("i"), []string{"20", "30", "40"}) {
|
||||
t.Errorf("short name not set from env")
|
||||
}
|
||||
},
|
||||
}).Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiStringSliceFromEnvCascade(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_INTERVALS", "20,30,40")
|
||||
|
||||
(&cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.StringSliceFlag{Name: "intervals, i", Value: &cli.StringSlice{}, EnvVar: "COMPAT_INTERVALS,APP_INTERVALS"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if !reflect.DeepEqual(ctx.StringSlice("intervals"), []string{"20", "30", "40"}) {
|
||||
t.Errorf("main name not set from env")
|
||||
}
|
||||
if !reflect.DeepEqual(ctx.StringSlice("i"), []string{"20", "30", "40"}) {
|
||||
t.Errorf("short name not set from env")
|
||||
}
|
||||
},
|
||||
}).Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiInt(t *testing.T) {
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.IntFlag{Name: "serve, s"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.Int("serve") != 10 {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if ctx.Int("s") != 10 {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run", "-s", "10"})
|
||||
}
|
||||
|
||||
func TestParseMultiIntFromEnv(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_TIMEOUT_SECONDS", "10")
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.IntFlag{Name: "timeout, t", EnvVar: "APP_TIMEOUT_SECONDS"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.Int("timeout") != 10 {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if ctx.Int("t") != 10 {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiIntFromEnvCascade(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_TIMEOUT_SECONDS", "10")
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.IntFlag{Name: "timeout, t", EnvVar: "COMPAT_TIMEOUT_SECONDS,APP_TIMEOUT_SECONDS"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.Int("timeout") != 10 {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if ctx.Int("t") != 10 {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiIntSlice(t *testing.T) {
|
||||
(&cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.IntSliceFlag{Name: "serve, s", Value: &cli.IntSlice{}},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if !reflect.DeepEqual(ctx.IntSlice("serve"), []int{10, 20}) {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if !reflect.DeepEqual(ctx.IntSlice("s"), []int{10, 20}) {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
},
|
||||
}).Run([]string{"run", "-s", "10", "-s", "20"})
|
||||
}
|
||||
|
||||
func TestParseMultiIntSliceFromEnv(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_INTERVALS", "20,30,40")
|
||||
|
||||
(&cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.IntSliceFlag{Name: "intervals, i", Value: &cli.IntSlice{}, EnvVar: "APP_INTERVALS"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if !reflect.DeepEqual(ctx.IntSlice("intervals"), []int{20, 30, 40}) {
|
||||
t.Errorf("main name not set from env")
|
||||
}
|
||||
if !reflect.DeepEqual(ctx.IntSlice("i"), []int{20, 30, 40}) {
|
||||
t.Errorf("short name not set from env")
|
||||
}
|
||||
},
|
||||
}).Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiIntSliceFromEnvCascade(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_INTERVALS", "20,30,40")
|
||||
|
||||
(&cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.IntSliceFlag{Name: "intervals, i", Value: &cli.IntSlice{}, EnvVar: "COMPAT_INTERVALS,APP_INTERVALS"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if !reflect.DeepEqual(ctx.IntSlice("intervals"), []int{20, 30, 40}) {
|
||||
t.Errorf("main name not set from env")
|
||||
}
|
||||
if !reflect.DeepEqual(ctx.IntSlice("i"), []int{20, 30, 40}) {
|
||||
t.Errorf("short name not set from env")
|
||||
}
|
||||
},
|
||||
}).Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiFloat64(t *testing.T) {
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.Float64Flag{Name: "serve, s"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.Float64("serve") != 10.2 {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if ctx.Float64("s") != 10.2 {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run", "-s", "10.2"})
|
||||
}
|
||||
|
||||
func TestParseMultiFloat64FromEnv(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_TIMEOUT_SECONDS", "15.5")
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.Float64Flag{Name: "timeout, t", EnvVar: "APP_TIMEOUT_SECONDS"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.Float64("timeout") != 15.5 {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if ctx.Float64("t") != 15.5 {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiFloat64FromEnvCascade(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_TIMEOUT_SECONDS", "15.5")
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.Float64Flag{Name: "timeout, t", EnvVar: "COMPAT_TIMEOUT_SECONDS,APP_TIMEOUT_SECONDS"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.Float64("timeout") != 15.5 {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if ctx.Float64("t") != 15.5 {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiBool(t *testing.T) {
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{Name: "serve, s"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.Bool("serve") != true {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if ctx.Bool("s") != true {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run", "--serve"})
|
||||
}
|
||||
|
||||
func TestParseMultiBoolFromEnv(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_DEBUG", "1")
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{Name: "debug, d", EnvVar: "APP_DEBUG"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.Bool("debug") != true {
|
||||
t.Errorf("main name not set from env")
|
||||
}
|
||||
if ctx.Bool("d") != true {
|
||||
t.Errorf("short name not set from env")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiBoolFromEnvCascade(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_DEBUG", "1")
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{Name: "debug, d", EnvVar: "COMPAT_DEBUG,APP_DEBUG"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.Bool("debug") != true {
|
||||
t.Errorf("main name not set from env")
|
||||
}
|
||||
if ctx.Bool("d") != true {
|
||||
t.Errorf("short name not set from env")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiBoolT(t *testing.T) {
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolTFlag{Name: "serve, s"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.BoolT("serve") != true {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if ctx.BoolT("s") != true {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run", "--serve"})
|
||||
}
|
||||
|
||||
func TestParseMultiBoolTFromEnv(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_DEBUG", "0")
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolTFlag{Name: "debug, d", EnvVar: "APP_DEBUG"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.BoolT("debug") != false {
|
||||
t.Errorf("main name not set from env")
|
||||
}
|
||||
if ctx.BoolT("d") != false {
|
||||
t.Errorf("short name not set from env")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiBoolTFromEnvCascade(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_DEBUG", "0")
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolTFlag{Name: "debug, d", EnvVar: "COMPAT_DEBUG,APP_DEBUG"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.BoolT("debug") != false {
|
||||
t.Errorf("main name not set from env")
|
||||
}
|
||||
if ctx.BoolT("d") != false {
|
||||
t.Errorf("short name not set from env")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run"})
|
||||
}
|
||||
|
||||
type Parser [2]string
|
||||
|
||||
func (p *Parser) Set(value string) error {
|
||||
parts := strings.Split(value, ",")
|
||||
if len(parts) != 2 {
|
||||
return fmt.Errorf("invalid format")
|
||||
}
|
||||
|
||||
(*p)[0] = parts[0]
|
||||
(*p)[1] = parts[1]
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) String() string {
|
||||
return fmt.Sprintf("%s,%s", p[0], p[1])
|
||||
}
|
||||
|
||||
func TestParseGeneric(t *testing.T) {
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.GenericFlag{Name: "serve, s", Value: &Parser{}},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if !reflect.DeepEqual(ctx.Generic("serve"), &Parser{"10", "20"}) {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if !reflect.DeepEqual(ctx.Generic("s"), &Parser{"10", "20"}) {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run", "-s", "10,20"})
|
||||
}
|
||||
|
||||
func TestParseGenericFromEnv(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_SERVE", "20,30")
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.GenericFlag{Name: "serve, s", Value: &Parser{}, EnvVar: "APP_SERVE"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if !reflect.DeepEqual(ctx.Generic("serve"), &Parser{"20", "30"}) {
|
||||
t.Errorf("main name not set from env")
|
||||
}
|
||||
if !reflect.DeepEqual(ctx.Generic("s"), &Parser{"20", "30"}) {
|
||||
t.Errorf("short name not set from env")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseGenericFromEnvCascade(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_FOO", "99,2000")
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.GenericFlag{Name: "foos", Value: &Parser{}, EnvVar: "COMPAT_FOO,APP_FOO"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if !reflect.DeepEqual(ctx.Generic("foos"), &Parser{"99", "2000"}) {
|
||||
t.Errorf("value not set from env")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run"})
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
package cli_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
/* Test Helpers */
|
||||
func expect(t *testing.T, a interface{}, b interface{}) {
|
||||
if a != b {
|
||||
t.Errorf("Expected %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a))
|
||||
}
|
||||
}
|
||||
|
||||
func refute(t *testing.T, a interface{}, b interface{}) {
|
||||
if a == b {
|
||||
t.Errorf("Did not expect %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a))
|
||||
}
|
||||
}
|
|
@ -1,536 +0,0 @@
|
|||
package clock_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/facebookgo/clock"
|
||||
)
|
||||
|
||||
// Ensure that the clock's After channel sends at the correct time.
|
||||
func TestClock_After(t *testing.T) {
|
||||
var ok bool
|
||||
go func() {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
ok = true
|
||||
}()
|
||||
go func() {
|
||||
time.Sleep(30 * time.Millisecond)
|
||||
t.Fatal("too late")
|
||||
}()
|
||||
gosched()
|
||||
|
||||
<-clock.New().After(20 * time.Millisecond)
|
||||
if !ok {
|
||||
t.Fatal("too early")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the clock's AfterFunc executes at the correct time.
|
||||
func TestClock_AfterFunc(t *testing.T) {
|
||||
var ok bool
|
||||
go func() {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
ok = true
|
||||
}()
|
||||
go func() {
|
||||
time.Sleep(30 * time.Millisecond)
|
||||
t.Fatal("too late")
|
||||
}()
|
||||
gosched()
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
clock.New().AfterFunc(20*time.Millisecond, func() {
|
||||
wg.Done()
|
||||
})
|
||||
wg.Wait()
|
||||
if !ok {
|
||||
t.Fatal("too early")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the clock's time matches the standary library.
|
||||
func TestClock_Now(t *testing.T) {
|
||||
a := time.Now().Round(time.Second)
|
||||
b := clock.New().Now().Round(time.Second)
|
||||
if !a.Equal(b) {
|
||||
t.Errorf("not equal: %s != %s", a, b)
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the clock sleeps for the appropriate amount of time.
|
||||
func TestClock_Sleep(t *testing.T) {
|
||||
var ok bool
|
||||
go func() {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
ok = true
|
||||
}()
|
||||
go func() {
|
||||
time.Sleep(30 * time.Millisecond)
|
||||
t.Fatal("too late")
|
||||
}()
|
||||
gosched()
|
||||
|
||||
clock.New().Sleep(20 * time.Millisecond)
|
||||
if !ok {
|
||||
t.Fatal("too early")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the clock ticks correctly.
|
||||
func TestClock_Tick(t *testing.T) {
|
||||
var ok bool
|
||||
go func() {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
ok = true
|
||||
}()
|
||||
go func() {
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
t.Fatal("too late")
|
||||
}()
|
||||
gosched()
|
||||
|
||||
c := clock.New().Tick(20 * time.Millisecond)
|
||||
<-c
|
||||
<-c
|
||||
if !ok {
|
||||
t.Fatal("too early")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the clock's ticker ticks correctly.
|
||||
func TestClock_Ticker(t *testing.T) {
|
||||
var ok bool
|
||||
go func() {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
ok = true
|
||||
}()
|
||||
go func() {
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
t.Fatal("too late")
|
||||
}()
|
||||
gosched()
|
||||
|
||||
ticker := clock.New().Ticker(50 * time.Millisecond)
|
||||
<-ticker.C
|
||||
<-ticker.C
|
||||
if !ok {
|
||||
t.Fatal("too early")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the clock's ticker can stop correctly.
|
||||
func TestClock_Ticker_Stp(t *testing.T) {
|
||||
var ok bool
|
||||
go func() {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
ok = true
|
||||
}()
|
||||
gosched()
|
||||
|
||||
ticker := clock.New().Ticker(20 * time.Millisecond)
|
||||
<-ticker.C
|
||||
ticker.Stop()
|
||||
select {
|
||||
case <-ticker.C:
|
||||
t.Fatal("unexpected send")
|
||||
case <-time.After(30 * time.Millisecond):
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the clock's timer waits correctly.
|
||||
func TestClock_Timer(t *testing.T) {
|
||||
var ok bool
|
||||
go func() {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
ok = true
|
||||
}()
|
||||
go func() {
|
||||
time.Sleep(30 * time.Millisecond)
|
||||
t.Fatal("too late")
|
||||
}()
|
||||
gosched()
|
||||
|
||||
timer := clock.New().Timer(20 * time.Millisecond)
|
||||
<-timer.C
|
||||
if !ok {
|
||||
t.Fatal("too early")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the clock's timer can be stopped.
|
||||
func TestClock_Timer_Stop(t *testing.T) {
|
||||
var ok bool
|
||||
go func() {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
ok = true
|
||||
}()
|
||||
|
||||
timer := clock.New().Timer(20 * time.Millisecond)
|
||||
timer.Stop()
|
||||
select {
|
||||
case <-timer.C:
|
||||
t.Fatal("unexpected send")
|
||||
case <-time.After(30 * time.Millisecond):
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the mock's After channel sends at the correct time.
|
||||
func TestMock_After(t *testing.T) {
|
||||
var ok int32
|
||||
clock := clock.NewMock()
|
||||
|
||||
// Create a channel to execute after 10 mock seconds.
|
||||
ch := clock.After(10 * time.Second)
|
||||
go func(ch <-chan time.Time) {
|
||||
<-ch
|
||||
atomic.StoreInt32(&ok, 1)
|
||||
}(ch)
|
||||
|
||||
// Move clock forward to just before the time.
|
||||
clock.Add(9 * time.Second)
|
||||
if atomic.LoadInt32(&ok) == 1 {
|
||||
t.Fatal("too early")
|
||||
}
|
||||
|
||||
// Move clock forward to the after channel's time.
|
||||
clock.Add(1 * time.Second)
|
||||
if atomic.LoadInt32(&ok) == 0 {
|
||||
t.Fatal("too late")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the mock's AfterFunc executes at the correct time.
|
||||
func TestMock_AfterFunc(t *testing.T) {
|
||||
var ok int32
|
||||
clock := clock.NewMock()
|
||||
|
||||
// Execute function after duration.
|
||||
clock.AfterFunc(10*time.Second, func() {
|
||||
atomic.StoreInt32(&ok, 1)
|
||||
})
|
||||
|
||||
// Move clock forward to just before the time.
|
||||
clock.Add(9 * time.Second)
|
||||
if atomic.LoadInt32(&ok) == 1 {
|
||||
t.Fatal("too early")
|
||||
}
|
||||
|
||||
// Move clock forward to the after channel's time.
|
||||
clock.Add(1 * time.Second)
|
||||
if atomic.LoadInt32(&ok) == 0 {
|
||||
t.Fatal("too late")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the mock's AfterFunc doesn't execute if stopped.
|
||||
func TestMock_AfterFunc_Stop(t *testing.T) {
|
||||
// Execute function after duration.
|
||||
clock := clock.NewMock()
|
||||
timer := clock.AfterFunc(10*time.Second, func() {
|
||||
t.Fatal("unexpected function execution")
|
||||
})
|
||||
gosched()
|
||||
|
||||
// Stop timer & move clock forward.
|
||||
timer.Stop()
|
||||
clock.Add(10 * time.Second)
|
||||
gosched()
|
||||
}
|
||||
|
||||
// Ensure that the mock's current time can be changed.
|
||||
func TestMock_Now(t *testing.T) {
|
||||
clock := clock.NewMock()
|
||||
if now := clock.Now(); !now.Equal(time.Unix(0, 0)) {
|
||||
t.Fatalf("expected epoch, got: ", now)
|
||||
}
|
||||
|
||||
// Add 10 seconds and check the time.
|
||||
clock.Add(10 * time.Second)
|
||||
if now := clock.Now(); !now.Equal(time.Unix(10, 0)) {
|
||||
t.Fatalf("expected epoch, got: ", now)
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the mock can sleep for the correct time.
|
||||
func TestMock_Sleep(t *testing.T) {
|
||||
var ok int32
|
||||
clock := clock.NewMock()
|
||||
|
||||
// Create a channel to execute after 10 mock seconds.
|
||||
go func() {
|
||||
clock.Sleep(10 * time.Second)
|
||||
atomic.StoreInt32(&ok, 1)
|
||||
}()
|
||||
gosched()
|
||||
|
||||
// Move clock forward to just before the sleep duration.
|
||||
clock.Add(9 * time.Second)
|
||||
if atomic.LoadInt32(&ok) == 1 {
|
||||
t.Fatal("too early")
|
||||
}
|
||||
|
||||
// Move clock forward to the after the sleep duration.
|
||||
clock.Add(1 * time.Second)
|
||||
if atomic.LoadInt32(&ok) == 0 {
|
||||
t.Fatal("too late")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the mock's Tick channel sends at the correct time.
|
||||
func TestMock_Tick(t *testing.T) {
|
||||
var n int32
|
||||
clock := clock.NewMock()
|
||||
|
||||
// Create a channel to increment every 10 seconds.
|
||||
go func() {
|
||||
tick := clock.Tick(10 * time.Second)
|
||||
for {
|
||||
<-tick
|
||||
atomic.AddInt32(&n, 1)
|
||||
}
|
||||
}()
|
||||
gosched()
|
||||
|
||||
// Move clock forward to just before the first tick.
|
||||
clock.Add(9 * time.Second)
|
||||
if atomic.LoadInt32(&n) != 0 {
|
||||
t.Fatalf("expected 0, got %d", n)
|
||||
}
|
||||
|
||||
// Move clock forward to the start of the first tick.
|
||||
clock.Add(1 * time.Second)
|
||||
if atomic.LoadInt32(&n) != 1 {
|
||||
t.Fatalf("expected 1, got %d", n)
|
||||
}
|
||||
|
||||
// Move clock forward over several ticks.
|
||||
clock.Add(30 * time.Second)
|
||||
if atomic.LoadInt32(&n) != 4 {
|
||||
t.Fatalf("expected 4, got %d", n)
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the mock's Ticker channel sends at the correct time.
|
||||
func TestMock_Ticker(t *testing.T) {
|
||||
var n int32
|
||||
clock := clock.NewMock()
|
||||
|
||||
// Create a channel to increment every microsecond.
|
||||
go func() {
|
||||
ticker := clock.Ticker(1 * time.Microsecond)
|
||||
for {
|
||||
<-ticker.C
|
||||
atomic.AddInt32(&n, 1)
|
||||
}
|
||||
}()
|
||||
gosched()
|
||||
|
||||
// Move clock forward.
|
||||
clock.Add(10 * time.Microsecond)
|
||||
if atomic.LoadInt32(&n) != 10 {
|
||||
t.Fatalf("unexpected: %d", n)
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the mock's Ticker channel won't block if not read from.
|
||||
func TestMock_Ticker_Overflow(t *testing.T) {
|
||||
clock := clock.NewMock()
|
||||
ticker := clock.Ticker(1 * time.Microsecond)
|
||||
clock.Add(10 * time.Microsecond)
|
||||
ticker.Stop()
|
||||
}
|
||||
|
||||
// Ensure that the mock's Ticker can be stopped.
|
||||
func TestMock_Ticker_Stop(t *testing.T) {
|
||||
var n int32
|
||||
clock := clock.NewMock()
|
||||
|
||||
// Create a channel to increment every second.
|
||||
ticker := clock.Ticker(1 * time.Second)
|
||||
go func() {
|
||||
for {
|
||||
<-ticker.C
|
||||
atomic.AddInt32(&n, 1)
|
||||
}
|
||||
}()
|
||||
gosched()
|
||||
|
||||
// Move clock forward.
|
||||
clock.Add(5 * time.Second)
|
||||
if atomic.LoadInt32(&n) != 5 {
|
||||
t.Fatalf("expected 5, got: %d", n)
|
||||
}
|
||||
|
||||
ticker.Stop()
|
||||
|
||||
// Move clock forward again.
|
||||
clock.Add(5 * time.Second)
|
||||
if atomic.LoadInt32(&n) != 5 {
|
||||
t.Fatalf("still expected 5, got: %d", n)
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that multiple tickers can be used together.
|
||||
func TestMock_Ticker_Multi(t *testing.T) {
|
||||
var n int32
|
||||
clock := clock.NewMock()
|
||||
|
||||
go func() {
|
||||
a := clock.Ticker(1 * time.Microsecond)
|
||||
b := clock.Ticker(3 * time.Microsecond)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-a.C:
|
||||
atomic.AddInt32(&n, 1)
|
||||
case <-b.C:
|
||||
atomic.AddInt32(&n, 100)
|
||||
}
|
||||
}
|
||||
}()
|
||||
gosched()
|
||||
|
||||
// Move clock forward.
|
||||
clock.Add(10 * time.Microsecond)
|
||||
gosched()
|
||||
if atomic.LoadInt32(&n) != 310 {
|
||||
t.Fatalf("unexpected: %d", n)
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleMock_After() {
|
||||
// Create a new mock clock.
|
||||
clock := clock.NewMock()
|
||||
count := 0
|
||||
|
||||
// Create a channel to execute after 10 mock seconds.
|
||||
go func() {
|
||||
<-clock.After(10 * time.Second)
|
||||
count = 100
|
||||
}()
|
||||
runtime.Gosched()
|
||||
|
||||
// Print the starting value.
|
||||
fmt.Printf("%s: %d\n", clock.Now().UTC(), count)
|
||||
|
||||
// Move the clock forward 5 seconds and print the value again.
|
||||
clock.Add(5 * time.Second)
|
||||
fmt.Printf("%s: %d\n", clock.Now().UTC(), count)
|
||||
|
||||
// Move the clock forward 5 seconds to the tick time and check the value.
|
||||
clock.Add(5 * time.Second)
|
||||
fmt.Printf("%s: %d\n", clock.Now().UTC(), count)
|
||||
|
||||
// Output:
|
||||
// 1970-01-01 00:00:00 +0000 UTC: 0
|
||||
// 1970-01-01 00:00:05 +0000 UTC: 0
|
||||
// 1970-01-01 00:00:10 +0000 UTC: 100
|
||||
}
|
||||
|
||||
func ExampleMock_AfterFunc() {
|
||||
// Create a new mock clock.
|
||||
clock := clock.NewMock()
|
||||
count := 0
|
||||
|
||||
// Execute a function after 10 mock seconds.
|
||||
clock.AfterFunc(10*time.Second, func() {
|
||||
count = 100
|
||||
})
|
||||
runtime.Gosched()
|
||||
|
||||
// Print the starting value.
|
||||
fmt.Printf("%s: %d\n", clock.Now().UTC(), count)
|
||||
|
||||
// Move the clock forward 10 seconds and print the new value.
|
||||
clock.Add(10 * time.Second)
|
||||
fmt.Printf("%s: %d\n", clock.Now().UTC(), count)
|
||||
|
||||
// Output:
|
||||
// 1970-01-01 00:00:00 +0000 UTC: 0
|
||||
// 1970-01-01 00:00:10 +0000 UTC: 100
|
||||
}
|
||||
|
||||
func ExampleMock_Sleep() {
|
||||
// Create a new mock clock.
|
||||
clock := clock.NewMock()
|
||||
count := 0
|
||||
|
||||
// Execute a function after 10 mock seconds.
|
||||
go func() {
|
||||
clock.Sleep(10 * time.Second)
|
||||
count = 100
|
||||
}()
|
||||
runtime.Gosched()
|
||||
|
||||
// Print the starting value.
|
||||
fmt.Printf("%s: %d\n", clock.Now().UTC(), count)
|
||||
|
||||
// Move the clock forward 10 seconds and print the new value.
|
||||
clock.Add(10 * time.Second)
|
||||
fmt.Printf("%s: %d\n", clock.Now().UTC(), count)
|
||||
|
||||
// Output:
|
||||
// 1970-01-01 00:00:00 +0000 UTC: 0
|
||||
// 1970-01-01 00:00:10 +0000 UTC: 100
|
||||
}
|
||||
|
||||
func ExampleMock_Ticker() {
|
||||
// Create a new mock clock.
|
||||
clock := clock.NewMock()
|
||||
count := 0
|
||||
|
||||
// Increment count every mock second.
|
||||
go func() {
|
||||
ticker := clock.Ticker(1 * time.Second)
|
||||
for {
|
||||
<-ticker.C
|
||||
count++
|
||||
}
|
||||
}()
|
||||
runtime.Gosched()
|
||||
|
||||
// Move the clock forward 10 seconds and print the new value.
|
||||
clock.Add(10 * time.Second)
|
||||
fmt.Printf("Count is %d after 10 seconds\n", count)
|
||||
|
||||
// Move the clock forward 5 more seconds and print the new value.
|
||||
clock.Add(5 * time.Second)
|
||||
fmt.Printf("Count is %d after 15 seconds\n", count)
|
||||
|
||||
// Output:
|
||||
// Count is 10 after 10 seconds
|
||||
// Count is 15 after 15 seconds
|
||||
}
|
||||
|
||||
func ExampleMock_Timer() {
|
||||
// Create a new mock clock.
|
||||
clock := clock.NewMock()
|
||||
count := 0
|
||||
|
||||
// Increment count after a mock second.
|
||||
go func() {
|
||||
timer := clock.Timer(1 * time.Second)
|
||||
<-timer.C
|
||||
count++
|
||||
}()
|
||||
runtime.Gosched()
|
||||
|
||||
// Move the clock forward 10 seconds and print the new value.
|
||||
clock.Add(10 * time.Second)
|
||||
fmt.Printf("Count is %d after 10 seconds\n", count)
|
||||
|
||||
// Output:
|
||||
// Count is 1 after 10 seconds
|
||||
}
|
||||
|
||||
func warn(v ...interface{}) { fmt.Fprintln(os.Stderr, v...) }
|
||||
func warnf(msg string, v ...interface{}) { fmt.Fprintf(os.Stderr, msg+"\n", v...) }
|
||||
|
||||
func gosched() { time.Sleep(1 * time.Millisecond) }
|
|
@ -1,77 +0,0 @@
|
|||
package stats_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/facebookgo/ensure"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/facebookgo/stats"
|
||||
)
|
||||
|
||||
// Ensure calling End works even when a BumpTimeHook isn't provided.
|
||||
func TestHookClientBumpTime(t *testing.T) {
|
||||
(&stats.HookClient{}).BumpTime("foo").End()
|
||||
}
|
||||
|
||||
func TestPrefixClient(t *testing.T) {
|
||||
const (
|
||||
prefix1 = "prefix1"
|
||||
prefix2 = "prefix2"
|
||||
avgKey = "avg"
|
||||
avgVal = float64(1)
|
||||
sumKey = "sum"
|
||||
sumVal = float64(2)
|
||||
histogramKey = "histogram"
|
||||
histogramVal = float64(3)
|
||||
timeKey = "time"
|
||||
)
|
||||
|
||||
var keys []string
|
||||
hc := &stats.HookClient{
|
||||
BumpAvgHook: func(key string, val float64) {
|
||||
keys = append(keys, key)
|
||||
ensure.DeepEqual(t, val, avgVal)
|
||||
},
|
||||
BumpSumHook: func(key string, val float64) {
|
||||
keys = append(keys, key)
|
||||
ensure.DeepEqual(t, val, sumVal)
|
||||
},
|
||||
BumpHistogramHook: func(key string, val float64) {
|
||||
keys = append(keys, key)
|
||||
ensure.DeepEqual(t, val, histogramVal)
|
||||
},
|
||||
BumpTimeHook: func(key string) interface {
|
||||
End()
|
||||
} {
|
||||
return multiEnderTest{
|
||||
EndHook: func() {
|
||||
keys = append(keys, key)
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
pc := stats.PrefixClient([]string{prefix1, prefix2}, hc)
|
||||
pc.BumpAvg(avgKey, avgVal)
|
||||
pc.BumpSum(sumKey, sumVal)
|
||||
pc.BumpHistogram(histogramKey, histogramVal)
|
||||
pc.BumpTime(timeKey).End()
|
||||
|
||||
ensure.SameElements(t, keys, []string{
|
||||
prefix1 + avgKey,
|
||||
prefix1 + sumKey,
|
||||
prefix1 + histogramKey,
|
||||
prefix1 + timeKey,
|
||||
prefix2 + avgKey,
|
||||
prefix2 + sumKey,
|
||||
prefix2 + histogramKey,
|
||||
prefix2 + timeKey,
|
||||
})
|
||||
}
|
||||
|
||||
type multiEnderTest struct {
|
||||
EndHook func()
|
||||
}
|
||||
|
||||
func (e multiEnderTest) End() {
|
||||
e.EndHook()
|
||||
}
|
49
Godeps/_workspace/src/github.com/golang/mock/gomock/mock_matcher/mock_matcher.go
generated
vendored
49
Godeps/_workspace/src/github.com/golang/mock/gomock/mock_matcher/mock_matcher.go
generated
vendored
|
@ -1,49 +0,0 @@
|
|||
// Automatically generated by MockGen. DO NOT EDIT!
|
||||
// Source: github.com/golang/mock/gomock (interfaces: Matcher)
|
||||
|
||||
package mock_gomock
|
||||
|
||||
import (
|
||||
gomock "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
// Mock of Matcher interface
|
||||
type MockMatcher struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *_MockMatcherRecorder
|
||||
}
|
||||
|
||||
// Recorder for MockMatcher (not exported)
|
||||
type _MockMatcherRecorder struct {
|
||||
mock *MockMatcher
|
||||
}
|
||||
|
||||
func NewMockMatcher(ctrl *gomock.Controller) *MockMatcher {
|
||||
mock := &MockMatcher{ctrl: ctrl}
|
||||
mock.recorder = &_MockMatcherRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
func (_m *MockMatcher) EXPECT() *_MockMatcherRecorder {
|
||||
return _m.recorder
|
||||
}
|
||||
|
||||
func (_m *MockMatcher) Matches(_param0 interface{}) bool {
|
||||
ret := _m.ctrl.Call(_m, "Matches", _param0)
|
||||
ret0, _ := ret[0].(bool)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (_mr *_MockMatcherRecorder) Matches(arg0 interface{}) *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "Matches", arg0)
|
||||
}
|
||||
|
||||
func (_m *MockMatcher) String() string {
|
||||
ret := _m.ctrl.Call(_m, "String")
|
||||
ret0, _ := ret[0].(string)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (_mr *_MockMatcherRecorder) String() *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "String")
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
package clock
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestFakeClockGoldenPath(t *testing.T) {
|
||||
clk := NewFake()
|
||||
second := NewFake()
|
||||
oldT := clk.Now()
|
||||
|
||||
if !clk.Now().Equal(second.Now()) {
|
||||
t.Errorf("clocks must start out at the same time but didn't: %#v vs %#v", clk.Now(), second.Now())
|
||||
}
|
||||
clk.Add(3 * time.Second)
|
||||
if clk.Now().Equal(second.Now()) {
|
||||
t.Errorf("clocks different must differ: %#v vs %#v", clk.Now(), second.Now())
|
||||
}
|
||||
|
||||
clk.Set(oldT)
|
||||
if !clk.Now().Equal(second.Now()) {
|
||||
t.Errorf("clk should have been been set backwards: %#v vs %#v", clk.Now(), second.Now())
|
||||
}
|
||||
|
||||
clk.Sleep(time.Second)
|
||||
if clk.Now().Equal(second.Now()) {
|
||||
t.Errorf("clk should have been set forwards (by sleeping): %#v vs %#v", clk.Now(), second.Now())
|
||||
}
|
||||
}
|
||||
|
||||
func TestNegativeSleep(t *testing.T) {
|
||||
clk := NewFake()
|
||||
clk.Add(1 * time.Hour)
|
||||
first := clk.Now()
|
||||
clk.Sleep(-10 * time.Second)
|
||||
if !clk.Now().Equal(first) {
|
||||
t.Errorf("clk should not move in time on a negative sleep")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func ExampleClock() {
|
||||
c := Default()
|
||||
now := c.Now()
|
||||
fmt.Println(now.UTC().Zone())
|
||||
// Output:
|
||||
// UTC 0
|
||||
}
|
||||
|
||||
func ExampleFakeClock() {
|
||||
c := Default()
|
||||
fc := NewFake()
|
||||
fc.Add(20 * time.Hour)
|
||||
fc.Add(-5 * time.Minute) // negatives work, as well
|
||||
|
||||
if fc.Now().Equal(fc.Now()) {
|
||||
fmt.Println("FakeClocks' Times always equal themselves.")
|
||||
}
|
||||
if !c.Now().Equal(fc.Now()) {
|
||||
fmt.Println("Clock and FakeClock can be set to different times.")
|
||||
}
|
||||
if !fc.Now().Equal(NewFake().Now()) {
|
||||
fmt.Println("FakeClocks work independently, too.")
|
||||
}
|
||||
// Output:
|
||||
// FakeClocks' Times always equal themselves.
|
||||
// Clock and FakeClock can be set to different times.
|
||||
// FakeClocks work independently, too.
|
||||
}
|
19
Godeps/_workspace/src/github.com/letsencrypt/go-safe-browsing-api/hat-trie/COPYING
generated
vendored
19
Godeps/_workspace/src/github.com/letsencrypt/go-safe-browsing-api/hat-trie/COPYING
generated
vendored
|
@ -1,19 +0,0 @@
|
|||
Copyright (C) 2011 by Daniel C. Jones <dcjones@cs.washington.edu>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
|
||||
SUBDIRS = src test
|
||||
|
||||
EXTRA_DIST = README.md COPYING
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = hat-trie-0.1.pc
|
||||
|
||||
|
47
Godeps/_workspace/src/github.com/letsencrypt/go-safe-browsing-api/hat-trie/README.md
generated
vendored
47
Godeps/_workspace/src/github.com/letsencrypt/go-safe-browsing-api/hat-trie/README.md
generated
vendored
|
@ -1,47 +0,0 @@
|
|||
|
||||
Hat-Trie
|
||||
========
|
||||
|
||||
[](https://travis-ci.org/dcjones/hat-trie)
|
||||
|
||||
This a ANSI C99 implementation of the HAT-trie data structure of Askitis and
|
||||
Sinha, an extremely efficient (space and time) modern variant of tries.
|
||||
|
||||
The version implemented here maps arrays of bytes to words (i.e., unsigned
|
||||
longs), which can be used to store counts, pointers, etc, or not used at all if
|
||||
you simply want to maintain a set of unique strings.
|
||||
|
||||
For details see,
|
||||
|
||||
1. Askitis, N., & Sinha, R. (2007). HAT-trie: a cache-conscious trie-based data
|
||||
structure for strings. Proceedings of the thirtieth Australasian conference on
|
||||
Computer science-Volume 62 (pp. 97–105). Australian Computer Society, Inc.
|
||||
|
||||
2. Askitis, N., & Zobel, J. (2005). Cache-conscious collision resolution in
|
||||
string hash tables. String Processing and Information Retrieval (pp.
|
||||
91–102). Springer.
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
git clone git@github.com:dcjones/hat-trie.git
|
||||
cd hat-trie
|
||||
autoreconf -i
|
||||
./configure
|
||||
make install
|
||||
|
||||
To use the library, include `hat-trie.h` and link using `-lhat-trie`.
|
||||
|
||||
|
||||
Tests
|
||||
-----
|
||||
|
||||
Build and run the tests:
|
||||
|
||||
make check
|
||||
|
||||
Other Language Bindings
|
||||
-----------------------
|
||||
* Ruby - https://github.com/luikore/triez
|
||||
* Python - https://github.com/kmike/hat-trie
|
6
Godeps/_workspace/src/github.com/letsencrypt/go-safe-browsing-api/hat-trie/TODO
generated
vendored
6
Godeps/_workspace/src/github.com/letsencrypt/go-safe-browsing-api/hat-trie/TODO
generated
vendored
|
@ -1,6 +0,0 @@
|
|||
|
||||
todo:
|
||||
* Deletion in ahtable.
|
||||
* Deletion in hattrie.
|
||||
|
||||
|
34
Godeps/_workspace/src/github.com/letsencrypt/go-safe-browsing-api/hat-trie/configure.ac
generated
vendored
34
Godeps/_workspace/src/github.com/letsencrypt/go-safe-browsing-api/hat-trie/configure.ac
generated
vendored
|
@ -1,34 +0,0 @@
|
|||
|
||||
AC_INIT([hat-trie], [0.1.0], [dcjones@cs.washington.edu])
|
||||
AM_INIT_AUTOMAKE([foreign])
|
||||
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
base_CFLAGS="-std=c99 -Wall -Wextra -pedantic"
|
||||
opt_CFLAGS="${base_CFLAGS} -O3"
|
||||
dbg_CFLAGS="${base_CFLAGS} -g -O0"
|
||||
|
||||
AC_ARG_ENABLE([debugging],
|
||||
[AS_HELP_STRING([--enable-debugging],
|
||||
[enable debugging info (default is no)])],
|
||||
[], [enable_debugging=no])
|
||||
|
||||
AS_IF([test "x$enable_debugging" = xyes],
|
||||
[CFLAGS="$dbg_CFLAGS"],
|
||||
[CFLAGS="$opt_CFLAGS"])
|
||||
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_CPP
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_LN_S
|
||||
AC_PROG_MAKE_SET
|
||||
AC_DISABLE_SHARED
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
AC_C_BIGENDIAN([AC_MSG_ERROR([Big-endian systems are not currently supported.])])
|
||||
AC_HEADER_STDBOOL
|
||||
|
||||
AC_CONFIG_FILES([hat-trie-0.1.pc Makefile src/Makefile test/Makefile])
|
||||
AC_OUTPUT
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: @PACKAGE_NAME@
|
||||
Description: An efficient trie implementation.
|
||||
Version: @PACKAGE_VERSION@
|
||||
Cflags: -I{includedir}
|
||||
Libs: -L${libdir}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
|
||||
lib_LTLIBRARIES = libhat-trie.la
|
||||
|
||||
libhat_trie_la_SOURCES = common.h \
|
||||
ahtable.h ahtable.c \
|
||||
hat-trie.h hat-trie.c \
|
||||
misc.h misc.c \
|
||||
murmurhash3.h murmurhash3.c
|
||||
|
||||
pkginclude_HEADERS = hat-trie.h ahtable.h common.h pstdint.h
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
|
||||
TESTS = check_ahtable check_hattrie
|
||||
check_PROGRAMS = check_ahtable check_hattrie bench_sorted_iter
|
||||
|
||||
check_ahtable_SOURCES = check_ahtable.c str_map.c
|
||||
check_ahtable_LDADD = $(top_builddir)/src/libhat-trie.la
|
||||
check_ahtable_CPPFLAGS = -I$(top_builddir)/src
|
||||
|
||||
check_hattrie_SOURCES = check_hattrie.c str_map.c
|
||||
check_hattrie_LDADD = $(top_builddir)/src/libhat-trie.la
|
||||
check_hattrie_CPPFLAGS = -I$(top_builddir)/src
|
||||
|
||||
bench_sorted_iter_SOURCES = bench_sorted_iter.c
|
||||
bench_sorted_iter_LDADD = $(top_builddir)/src/libhat-trie.la
|
||||
bench_sorted_iter_CPPFLAGS = -I$(top_builddir)/src
|
|
@ -1,69 +0,0 @@
|
|||
|
||||
/* A quick test of the degree to which ordered iteration is slower than unordered. */
|
||||
|
||||
#include "../src/hat-trie.h"
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
/* Simple random string generation. */
|
||||
void randstr(char* x, size_t len)
|
||||
{
|
||||
x[len] = '\0';
|
||||
while (len > 0) {
|
||||
x[--len] = '\x20' + (rand() % ('\x7e' - '\x20' + 1));
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
hattrie_t* T = hattrie_create();
|
||||
const size_t n = 1000000; // how many strings
|
||||
const size_t m_low = 50; // minimum length of each string
|
||||
const size_t m_high = 500; // maximum length of each string
|
||||
char x[501];
|
||||
|
||||
size_t i, m;
|
||||
for (i = 0; i < n; ++i) {
|
||||
m = m_low + rand() % (m_high - m_low);
|
||||
randstr(x, m);
|
||||
*hattrie_get(T, x, m) = 1;
|
||||
}
|
||||
|
||||
hattrie_iter_t* it;
|
||||
clock_t t0, t;
|
||||
const size_t repetitions = 100;
|
||||
size_t r;
|
||||
|
||||
/* iterate in unsorted order */
|
||||
fprintf(stderr, "iterating out of order ... ");
|
||||
t0 = clock();
|
||||
for (r = 0; r < repetitions; ++r) {
|
||||
it = hattrie_iter_begin(T, false);
|
||||
while (!hattrie_iter_finished(it)) {
|
||||
hattrie_iter_next(it);
|
||||
}
|
||||
hattrie_iter_free(it);
|
||||
}
|
||||
t = clock();
|
||||
fprintf(stderr, "finished. (%0.2f seconds)\n", (double) (t - t0) / (double) CLOCKS_PER_SEC);
|
||||
|
||||
|
||||
/* iterate in sorted order */
|
||||
fprintf(stderr, "iterating in order ... ");
|
||||
t0 = clock();
|
||||
for (r = 0; r < repetitions; ++r) {
|
||||
it = hattrie_iter_begin(T, true);
|
||||
while (!hattrie_iter_finished(it)) {
|
||||
hattrie_iter_next(it);
|
||||
}
|
||||
hattrie_iter_free(it);
|
||||
}
|
||||
t = clock();
|
||||
fprintf(stderr, "finished. (%0.2f seconds)\n", (double) (t - t0) / (double) CLOCKS_PER_SEC);
|
||||
|
||||
|
||||
hattrie_free(T);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,220 +0,0 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "str_map.h"
|
||||
#include "../src/ahtable.h"
|
||||
|
||||
/* Simple random string generation. */
|
||||
void randstr(char* x, size_t len)
|
||||
{
|
||||
x[len] = '\0';
|
||||
while (len > 0) {
|
||||
x[--len] = '\x20' + (rand() % ('\x7e' - '\x20' + 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const size_t n = 100000; // how many unique strings
|
||||
const size_t m_low = 50; // minimum length of each string
|
||||
const size_t m_high = 500; // maximum length of each string
|
||||
const size_t k = 200000; // number of insertions
|
||||
char** xs;
|
||||
|
||||
ahtable_t* T;
|
||||
str_map* M;
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
fprintf(stderr, "generating %zu keys ... ", n);
|
||||
xs = malloc(n * sizeof(char*));
|
||||
size_t i;
|
||||
size_t m;
|
||||
for (i = 0; i < n; ++i) {
|
||||
m = m_low + rand() % (m_high - m_low);
|
||||
xs[i] = malloc(m + 1);
|
||||
randstr(xs[i], m);
|
||||
}
|
||||
|
||||
T = ahtable_create();
|
||||
M = str_map_create();
|
||||
fprintf(stderr, "done.\n");
|
||||
}
|
||||
|
||||
|
||||
void teardown()
|
||||
{
|
||||
ahtable_free(T);
|
||||
str_map_destroy(M);
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < n; ++i) {
|
||||
free(xs[i]);
|
||||
}
|
||||
free(xs);
|
||||
}
|
||||
|
||||
|
||||
void test_ahtable_insert()
|
||||
{
|
||||
fprintf(stderr, "inserting %zu keys ... \n", k);
|
||||
|
||||
size_t i, j;
|
||||
value_t* u;
|
||||
value_t v;
|
||||
|
||||
for (j = 0; j < k; ++j) {
|
||||
i = rand() % n;
|
||||
|
||||
|
||||
v = 1 + str_map_get(M, xs[i], strlen(xs[i]));
|
||||
str_map_set(M, xs[i], strlen(xs[i]), v);
|
||||
|
||||
|
||||
u = ahtable_get(T, xs[i], strlen(xs[i]));
|
||||
*u += 1;
|
||||
|
||||
|
||||
if (*u != v) {
|
||||
fprintf(stderr, "[error] tally mismatch (reported: %lu, correct: %lu)\n",
|
||||
*u, v);
|
||||
}
|
||||
}
|
||||
|
||||
/* delete some keys */
|
||||
for (j = 0; i < k/100; ++j) {
|
||||
i = rand() % n;
|
||||
ahtable_del(T, xs[i], strlen(xs[i]));
|
||||
str_map_del(M, xs[i], strlen(xs[i]));
|
||||
u = ahtable_tryget(T, xs[i], strlen(xs[i]));
|
||||
if (u) {
|
||||
fprintf(stderr, "[error] deleted node found in ahtable\n");
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "done.\n");
|
||||
}
|
||||
|
||||
|
||||
void test_ahtable_iteration()
|
||||
{
|
||||
fprintf(stderr, "iterating through %zu keys ... \n", k);
|
||||
|
||||
ahtable_iter_t* i = ahtable_iter_begin(T, false);
|
||||
|
||||
size_t count = 0;
|
||||
value_t* u;
|
||||
value_t v;
|
||||
|
||||
size_t len;
|
||||
const char* key;
|
||||
|
||||
while (!ahtable_iter_finished(i)) {
|
||||
++count;
|
||||
|
||||
key = ahtable_iter_key(i, &len);
|
||||
u = ahtable_iter_val(i);
|
||||
v = str_map_get(M, key, len);
|
||||
|
||||
if (*u != v) {
|
||||
if (v == 0) {
|
||||
fprintf(stderr, "[error] incorrect iteration (%lu, %lu)\n", *u, v);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "[error] incorrect iteration tally (%lu, %lu)\n", *u, v);
|
||||
}
|
||||
}
|
||||
|
||||
// this way we will see an error if the same key is iterated through
|
||||
// twice
|
||||
str_map_set(M, key, len, 0);
|
||||
|
||||
ahtable_iter_next(i);
|
||||
}
|
||||
|
||||
if (count != M->m) {
|
||||
fprintf(stderr, "[error] iterated through %zu element, expected %zu\n",
|
||||
count, M->m);
|
||||
}
|
||||
|
||||
ahtable_iter_free(i);
|
||||
|
||||
fprintf(stderr, "done.\n");
|
||||
}
|
||||
|
||||
|
||||
int cmpkey(const char* a, size_t ka, const char* b, size_t kb)
|
||||
{
|
||||
int c = memcmp(a, b, ka < kb ? ka : kb);
|
||||
return c == 0 ? (int) ka - (int) kb : c;
|
||||
}
|
||||
|
||||
|
||||
void test_ahtable_sorted_iteration()
|
||||
{
|
||||
fprintf(stderr, "iterating in order through %zu keys ... \n", k);
|
||||
|
||||
ahtable_iter_t* i = ahtable_iter_begin(T, true);
|
||||
|
||||
size_t count = 0;
|
||||
value_t* u;
|
||||
value_t v;
|
||||
|
||||
char* prev_key = malloc(m_high + 1);
|
||||
size_t prev_len = 0;
|
||||
|
||||
const char *key = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
while (!ahtable_iter_finished(i)) {
|
||||
memcpy(prev_key, key, len);
|
||||
prev_len = len;
|
||||
++count;
|
||||
|
||||
key = ahtable_iter_key(i, &len);
|
||||
if (prev_key != NULL && cmpkey(prev_key, prev_len, key, len) > 0) {
|
||||
fprintf(stderr, "[error] iteration is not correctly ordered.\n");
|
||||
}
|
||||
|
||||
u = ahtable_iter_val(i);
|
||||
v = str_map_get(M, key, len);
|
||||
|
||||
if (*u != v) {
|
||||
if (v == 0) {
|
||||
fprintf(stderr, "[error] incorrect iteration (%lu, %lu)\n", *u, v);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "[error] incorrect iteration tally (%lu, %lu)\n", *u, v);
|
||||
}
|
||||
}
|
||||
|
||||
// this way we will see an error if the same key is iterated through
|
||||
// twice
|
||||
str_map_set(M, key, len, 0);
|
||||
|
||||
ahtable_iter_next(i);
|
||||
}
|
||||
|
||||
ahtable_iter_free(i);
|
||||
free(prev_key);
|
||||
|
||||
fprintf(stderr, "done.\n");
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
setup();
|
||||
test_ahtable_insert();
|
||||
test_ahtable_iteration();
|
||||
teardown();
|
||||
|
||||
setup();
|
||||
test_ahtable_insert();
|
||||
test_ahtable_sorted_iteration();
|
||||
teardown();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,268 +0,0 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "str_map.h"
|
||||
#include "../src/hat-trie.h"
|
||||
|
||||
/* Simple random string generation. */
|
||||
void randstr(char* x, size_t len)
|
||||
{
|
||||
x[len] = '\0';
|
||||
while (len > 0) {
|
||||
x[--len] = '\x20' + (rand() % ('\x7e' - '\x20' + 1));
|
||||
}
|
||||
}
|
||||
|
||||
const size_t n = 100000; // how many unique strings
|
||||
const size_t m_low = 50; // minimum length of each string
|
||||
const size_t m_high = 500; // maximum length of each string
|
||||
const size_t k = 200000; // number of insertions
|
||||
const size_t d = 50000;
|
||||
|
||||
char** xs;
|
||||
char** ds;
|
||||
|
||||
hattrie_t* T;
|
||||
str_map* M;
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
fprintf(stderr, "generating %zu keys ... ", n);
|
||||
xs = malloc(n * sizeof(char*));
|
||||
ds = malloc(d * sizeof(char*));
|
||||
size_t i;
|
||||
size_t m;
|
||||
for (i = 0; i < n; ++i) {
|
||||
m = m_low + rand() % (m_high - m_low);
|
||||
xs[i] = malloc(m + 1);
|
||||
randstr(xs[i], m);
|
||||
}
|
||||
for (i = 0; i < d; ++i) {
|
||||
m = rand()%n;
|
||||
ds[i] = xs[m];
|
||||
}
|
||||
|
||||
T = hattrie_create();
|
||||
M = str_map_create();
|
||||
fprintf(stderr, "done.\n");
|
||||
}
|
||||
|
||||
|
||||
void teardown()
|
||||
{
|
||||
hattrie_free(T);
|
||||
str_map_destroy(M);
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < n; ++i) {
|
||||
free(xs[i]);
|
||||
}
|
||||
free(xs);
|
||||
free(ds);
|
||||
}
|
||||
|
||||
|
||||
void test_hattrie_insert()
|
||||
{
|
||||
fprintf(stderr, "inserting %zu keys ... \n", k);
|
||||
|
||||
size_t i, j;
|
||||
value_t* u;
|
||||
value_t v;
|
||||
|
||||
for (j = 0; j < k; ++j) {
|
||||
i = rand() % n;
|
||||
|
||||
|
||||
v = 1 + str_map_get(M, xs[i], strlen(xs[i]));
|
||||
str_map_set(M, xs[i], strlen(xs[i]), v);
|
||||
|
||||
|
||||
u = hattrie_get(T, xs[i], strlen(xs[i]));
|
||||
*u += 1;
|
||||
|
||||
|
||||
if (*u != v) {
|
||||
fprintf(stderr, "[error] tally mismatch (reported: %lu, correct: %lu)\n",
|
||||
*u, v);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "deleting %zu keys ... \n", d);
|
||||
for (j = 0; j < d; ++j) {
|
||||
str_map_del(M, ds[j], strlen(ds[j]));
|
||||
hattrie_del(T, ds[j], strlen(ds[j]));
|
||||
u = hattrie_tryget(T, ds[j], strlen(ds[j]));
|
||||
if (u) {
|
||||
fprintf(stderr, "[error] item %zu still found in trie after delete\n",
|
||||
j);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "done.\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void test_hattrie_iteration()
|
||||
{
|
||||
fprintf(stderr, "iterating through %zu keys ... \n", k);
|
||||
|
||||
hattrie_iter_t* i = hattrie_iter_begin(T, false);
|
||||
|
||||
size_t count = 0;
|
||||
value_t* u;
|
||||
value_t v;
|
||||
|
||||
size_t len;
|
||||
const char* key;
|
||||
|
||||
while (!hattrie_iter_finished(i)) {
|
||||
++count;
|
||||
|
||||
key = hattrie_iter_key(i, &len);
|
||||
u = hattrie_iter_val(i);
|
||||
|
||||
v = str_map_get(M, key, len);
|
||||
|
||||
if (*u != v) {
|
||||
if (v == 0) {
|
||||
fprintf(stderr, "[error] incorrect iteration (%lu, %lu)\n", *u, v);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "[error] incorrect iteration tally (%lu, %lu)\n", *u, v);
|
||||
}
|
||||
}
|
||||
|
||||
// this way we will see an error if the same key is iterated through
|
||||
// twice
|
||||
str_map_set(M, key, len, 0);
|
||||
|
||||
hattrie_iter_next(i);
|
||||
}
|
||||
|
||||
if (count != M->m) {
|
||||
fprintf(stderr, "[error] iterated through %zu element, expected %zu\n",
|
||||
count, M->m);
|
||||
}
|
||||
|
||||
hattrie_iter_free(i);
|
||||
|
||||
fprintf(stderr, "done.\n");
|
||||
}
|
||||
|
||||
|
||||
int cmpkey(const char* a, size_t ka, const char* b, size_t kb)
|
||||
{
|
||||
int c = memcmp(a, b, ka < kb ? ka : kb);
|
||||
return c == 0 ? (int) ka - (int) kb : c;
|
||||
}
|
||||
|
||||
|
||||
void test_hattrie_sorted_iteration()
|
||||
{
|
||||
fprintf(stderr, "iterating in order through %zu keys ... \n", k);
|
||||
|
||||
hattrie_iter_t* i = hattrie_iter_begin(T, true);
|
||||
|
||||
size_t count = 0;
|
||||
value_t* u;
|
||||
value_t v;
|
||||
|
||||
char* key_copy = malloc(m_high + 1);
|
||||
char* prev_key = malloc(m_high + 1);
|
||||
memset(prev_key, 0, m_high + 1);
|
||||
size_t prev_len = 0;
|
||||
|
||||
const char *key = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
while (!hattrie_iter_finished(i)) {
|
||||
memcpy(prev_key, key_copy, len);
|
||||
prev_key[len] = '\0';
|
||||
prev_len = len;
|
||||
++count;
|
||||
|
||||
key = hattrie_iter_key(i, &len);
|
||||
|
||||
/* memory for key may be changed on iter, copy it */
|
||||
strncpy(key_copy, key, len);
|
||||
|
||||
if (prev_key != NULL && cmpkey(prev_key, prev_len, key, len) > 0) {
|
||||
fprintf(stderr, "[error] iteration is not correctly ordered.\n");
|
||||
}
|
||||
|
||||
u = hattrie_iter_val(i);
|
||||
v = str_map_get(M, key, len);
|
||||
|
||||
if (*u != v) {
|
||||
if (v == 0) {
|
||||
fprintf(stderr, "[error] incorrect iteration (%lu, %lu)\n", *u, v);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "[error] incorrect iteration tally (%lu, %lu)\n", *u, v);
|
||||
}
|
||||
}
|
||||
|
||||
// this way we will see an error if the same key is iterated through
|
||||
// twice
|
||||
str_map_set(M, key, len, 0);
|
||||
|
||||
hattrie_iter_next(i);
|
||||
}
|
||||
|
||||
if (count != M->m) {
|
||||
fprintf(stderr, "[error] iterated through %zu element, expected %zu\n",
|
||||
count, M->m);
|
||||
}
|
||||
|
||||
hattrie_iter_free(i);
|
||||
free(prev_key);
|
||||
free(key_copy);
|
||||
|
||||
fprintf(stderr, "done.\n");
|
||||
}
|
||||
|
||||
|
||||
void test_trie_non_ascii()
|
||||
{
|
||||
fprintf(stderr, "checking non-ascii... \n");
|
||||
|
||||
value_t* u;
|
||||
hattrie_t* T = hattrie_create();
|
||||
char* txt = "\x81\x70";
|
||||
|
||||
u = hattrie_get(T, txt, strlen(txt));
|
||||
*u = 10;
|
||||
|
||||
u = hattrie_tryget(T, txt, strlen(txt));
|
||||
if (*u != 10){
|
||||
fprintf(stderr, "can't store non-ascii strings\n");
|
||||
}
|
||||
hattrie_free(T);
|
||||
|
||||
fprintf(stderr, "done.\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
test_trie_non_ascii();
|
||||
|
||||
setup();
|
||||
test_hattrie_insert();
|
||||
test_hattrie_iteration();
|
||||
teardown();
|
||||
|
||||
setup();
|
||||
test_hattrie_insert();
|
||||
test_hattrie_sorted_iteration();
|
||||
teardown();
|
||||
|
||||
return 0;
|
||||
}
|
241
Godeps/_workspace/src/github.com/letsencrypt/go-safe-browsing-api/hat-trie/test/str_map.c
generated
vendored
241
Godeps/_workspace/src/github.com/letsencrypt/go-safe-browsing-api/hat-trie/test/str_map.c
generated
vendored
|
@ -1,241 +0,0 @@
|
|||
|
||||
/*
|
||||
* This file is part of fastq-tools.
|
||||
*
|
||||
* Copyright (c) 2011 by Daniel C. Jones <dcjones@cs.washington.edu>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "str_map.h"
|
||||
#include "misc.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static const size_t INITIAL_TABLE_SIZE = 16;
|
||||
static const double MAX_LOAD = 0.77;
|
||||
|
||||
|
||||
/*
|
||||
* Paul Hsieh's SuperFastHash
|
||||
* http://www.azillionmonkeys.com/qed/hash.html
|
||||
*/
|
||||
|
||||
|
||||
#undef get16bits
|
||||
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
|
||||
|| defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
|
||||
#define get16bits(d) (*((const uint16_t *) (d)))
|
||||
#endif
|
||||
|
||||
#if !defined (get16bits)
|
||||
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
|
||||
+(uint32_t)(((const uint8_t *)(d))[0]) )
|
||||
#endif
|
||||
|
||||
static uint32_t hash(const char * data, size_t len) {
|
||||
uint32_t hash = len, tmp;
|
||||
int rem;
|
||||
|
||||
if (len <= 0 || data == NULL) return 0;
|
||||
|
||||
rem = len & 3;
|
||||
len >>= 2;
|
||||
|
||||
/* Main loop */
|
||||
for (;len > 0; len--) {
|
||||
hash += get16bits (data);
|
||||
tmp = (get16bits (data+2) << 11) ^ hash;
|
||||
hash = (hash << 16) ^ tmp;
|
||||
data += 2*sizeof (uint16_t);
|
||||
hash += hash >> 11;
|
||||
}
|
||||
|
||||
/* Handle end cases */
|
||||
switch (rem) {
|
||||
case 3: hash += get16bits (data);
|
||||
hash ^= hash << 16;
|
||||
hash ^= data[sizeof (uint16_t)] << 18;
|
||||
hash += hash >> 11;
|
||||
break;
|
||||
case 2: hash += get16bits (data);
|
||||
hash ^= hash << 11;
|
||||
hash += hash >> 17;
|
||||
break;
|
||||
case 1: hash += *data;
|
||||
hash ^= hash << 10;
|
||||
hash += hash >> 1;
|
||||
}
|
||||
|
||||
/* Force "avalanching" of final 127 bits */
|
||||
hash ^= hash << 3;
|
||||
hash += hash >> 5;
|
||||
hash ^= hash << 4;
|
||||
hash += hash >> 17;
|
||||
hash ^= hash << 25;
|
||||
hash += hash >> 6;
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void rehash(str_map* T, size_t new_n);
|
||||
static void clear(str_map*);
|
||||
|
||||
|
||||
|
||||
str_map* str_map_create()
|
||||
{
|
||||
str_map* T = malloc_or_die(sizeof(str_map));
|
||||
T->A = malloc_or_die(INITIAL_TABLE_SIZE * sizeof(str_map_pair*));
|
||||
memset(T->A, 0, INITIAL_TABLE_SIZE * sizeof(str_map_pair*));
|
||||
T->n = INITIAL_TABLE_SIZE;
|
||||
T->m = 0;
|
||||
T->max_m = T->n * MAX_LOAD;
|
||||
|
||||
return T;
|
||||
}
|
||||
|
||||
|
||||
void str_map_destroy(str_map* T)
|
||||
{
|
||||
if (T != NULL) {
|
||||
clear(T);
|
||||
free(T->A);
|
||||
free(T);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void clear(str_map* T)
|
||||
{
|
||||
str_map_pair* u;
|
||||
size_t i;
|
||||
for (i = 0; i < T->n; i++) {
|
||||
while (T->A[i]) {
|
||||
u = T->A[i]->next;
|
||||
free(T->A[i]->key);
|
||||
free(T->A[i]);
|
||||
T->A[i] = u;
|
||||
}
|
||||
}
|
||||
|
||||
T->m = 0;
|
||||
}
|
||||
|
||||
|
||||
static void insert_without_copy(str_map* T, str_map_pair* V)
|
||||
{
|
||||
uint32_t h = hash(V->key, V->keylen) % T->n;
|
||||
V->next = T->A[h];
|
||||
T->A[h] = V;
|
||||
T->m++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void rehash(str_map* T, size_t new_n)
|
||||
{
|
||||
str_map U;
|
||||
U.n = new_n;
|
||||
U.m = 0;
|
||||
U.max_m = U.n * MAX_LOAD;
|
||||
U.A = malloc_or_die(U.n * sizeof(str_map_pair*));
|
||||
memset(U.A, 0, U.n * sizeof(str_map_pair*));
|
||||
|
||||
str_map_pair *j, *k;
|
||||
size_t i;
|
||||
for (i = 0; i < T->n; i++) {
|
||||
j = T->A[i];
|
||||
while (j) {
|
||||
k = j->next;
|
||||
insert_without_copy(&U, j);
|
||||
j = k;
|
||||
}
|
||||
T->A[i] = NULL;
|
||||
}
|
||||
|
||||
free(T->A);
|
||||
T->A = U.A;
|
||||
T->n = U.n;
|
||||
T->max_m = U.max_m;
|
||||
}
|
||||
|
||||
|
||||
void str_map_set(str_map* T, const char* key, size_t keylen, value_t value)
|
||||
{
|
||||
if (T->m >= T->max_m) rehash(T, T->n * 2);
|
||||
|
||||
uint32_t h = hash(key, keylen) % T->n;
|
||||
|
||||
str_map_pair* u = T->A[h];
|
||||
|
||||
while (u) {
|
||||
if (u->keylen == keylen && memcmp(u->key, key, keylen) == 0) {
|
||||
u->value = value;
|
||||
return;
|
||||
}
|
||||
|
||||
u = u->next;
|
||||
}
|
||||
|
||||
u = malloc_or_die(sizeof(str_map_pair));
|
||||
u->key = malloc_or_die(keylen);
|
||||
memcpy(u->key, key, keylen);
|
||||
u->keylen = keylen;
|
||||
u->value = value;
|
||||
|
||||
u->next = T->A[h];
|
||||
T->A[h] = u;
|
||||
|
||||
T->m++;
|
||||
}
|
||||
|
||||
|
||||
value_t str_map_get(const str_map* T, const char* key, size_t keylen)
|
||||
{
|
||||
uint32_t h = hash(key, keylen) % T->n;
|
||||
|
||||
str_map_pair* u = T->A[h];
|
||||
|
||||
while (u) {
|
||||
if (u->keylen == keylen && memcmp(u->key, key, keylen) == 0) {
|
||||
return u->value;
|
||||
}
|
||||
|
||||
u = u->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void str_map_del(str_map* T, const char* key, size_t keylen)
|
||||
{
|
||||
uint32_t h = hash(key, keylen) % T->n;
|
||||
|
||||
str_map_pair* u = T->A[h];
|
||||
str_map_pair* p = NULL;
|
||||
while (u) {
|
||||
|
||||
if (u->keylen == keylen && memcmp(u->key, key, keylen) == 0) {
|
||||
if (p) {
|
||||
p->next = u->next;
|
||||
} else {
|
||||
T->A[h] = u->next;
|
||||
}
|
||||
free(u->key);
|
||||
free(u);
|
||||
--T->m;
|
||||
return;
|
||||
}
|
||||
|
||||
p = u;
|
||||
u = u->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2011 by Daniel C. Jones <dcjones@cs.washington.edu>
|
||||
*
|
||||
* hash :
|
||||
* A quick and simple hash table mapping strings to things.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ISOLATOR_STR_MAP_H
|
||||
#define ISOLATOR_STR_MAP_H
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
typedef struct str_map_pair_
|
||||
{
|
||||
char* key;
|
||||
size_t keylen;
|
||||
value_t value;
|
||||
|
||||
struct str_map_pair_* next;
|
||||
} str_map_pair;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
str_map_pair** A; /* table proper */
|
||||
size_t n; /* table size */
|
||||
size_t m; /* hashed items */
|
||||
size_t max_m; /* max hashed items before rehash */
|
||||
} str_map;
|
||||
|
||||
|
||||
|
||||
str_map* str_map_create(void);
|
||||
void str_map_destroy(str_map*);
|
||||
void str_map_set(str_map*, const char* key, size_t keylen, value_t value);
|
||||
value_t str_map_get(const str_map*, const char* key, size_t keylen);
|
||||
void str_map_del(str_map* T, const char* key, size_t keylen);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
config.toml
|
||||
data
|
||||
data.old
|
||||
webserver
|
|
@ -1,6 +0,0 @@
|
|||
# example config file for safe browsing server
|
||||
address = "0.0.0.0:8080"
|
||||
googleApiKey = ""
|
||||
dataDir = "/tmp/safe-browsing-data"
|
||||
# enable example usage page at /form
|
||||
enableFormPage = true
|
225
Godeps/_workspace/src/github.com/letsencrypt/go-safe-browsing-api/webserver/webserver.go
generated
vendored
225
Godeps/_workspace/src/github.com/letsencrypt/go-safe-browsing-api/webserver/webserver.go
generated
vendored
|
@ -1,225 +0,0 @@
|
|||
/*
|
||||
Copyright (c) 2014, Richard Johnson
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
toml "github.com/BurntSushi/toml"
|
||||
safebrowsing "github.com/rjohnsondev/go-safe-browsing-api"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Address string
|
||||
GoogleApiKey string
|
||||
DataDir string
|
||||
EnableFormPage bool
|
||||
}
|
||||
|
||||
var sb *safebrowsing.SafeBrowsing
|
||||
|
||||
func main() {
|
||||
|
||||
flag.Parse()
|
||||
if len(flag.Args()) < 1 {
|
||||
fmt.Printf("Usage: webserver config-file.toml")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var conf Config
|
||||
if _, err := toml.DecodeFile(flag.Arg(0), &conf); err != nil {
|
||||
fmt.Printf(
|
||||
"Error reading config file %s: %s",
|
||||
flag.Arg(0),
|
||||
err,
|
||||
)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var err error
|
||||
sb, err = safebrowsing.NewSafeBrowsing(
|
||||
conf.GoogleApiKey,
|
||||
conf.DataDir,
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if conf.EnableFormPage {
|
||||
http.HandleFunc("/form", handleHtml)
|
||||
}
|
||||
http.HandleFunc("/", handler)
|
||||
http.ListenAndServe(conf.Address, nil)
|
||||
}
|
||||
|
||||
type UrlResponse struct {
|
||||
IsListed bool `json:"isListed"`
|
||||
List string `json:"list,omitempty"`
|
||||
Error string `json:"error,omitempty"`
|
||||
WarningTitle string `json:"warningTitle,omitempty"`
|
||||
WarningText string `json:"warningText,omitempty"`
|
||||
FullHashRequested bool `json:"fullHashRequested,omitempty"`
|
||||
}
|
||||
|
||||
var warnings map[string]map[string]string = map[string]map[string]string{
|
||||
"goog-malware-shavar": map[string]string{
|
||||
"title": "Warning - Visiting this web site may harm your computer.",
|
||||
"text": "This page may be a forgery or imitation of another website, " +
|
||||
"designed to trick users into sharing personal or financial " +
|
||||
"information. Entering any personal information on this page " +
|
||||
"may result in identity theft or other abuse. You can find " +
|
||||
"out more about phishing from http://www.antiphishing.org/",
|
||||
},
|
||||
"googpub-phish-shavar": map[string]string{
|
||||
"title": "Warning - Suspected phishing page.",
|
||||
"text": "This page appears to contain malicious code that could be " +
|
||||
"downloaded to your computer without your consent. You can " +
|
||||
"learn more about harmful web content including viruses and " +
|
||||
"other malicious code and how to protect your computer at " +
|
||||
"http://StopBadware.org/",
|
||||
},
|
||||
}
|
||||
|
||||
func handleHtml(w http.ResponseWriter, r *http.Request) {
|
||||
html := `<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<div style="margin: auto; width: 800px; font-family: sans-serif;">
|
||||
<h2>Example JSON usage:</h2>
|
||||
Request Object:<br />
|
||||
<textarea id="txtJson" rows="6" style="width: 100%;">[
|
||||
"http://www.google.com/",
|
||||
"http://www.ianfette.org/",
|
||||
"http://www.evil.com/"
|
||||
]
|
||||
</textarea><br />
|
||||
<br />
|
||||
<label><input type="checkbox" id="blocking" /> Have server block to confirm suspect URLs*</label><br />
|
||||
<small>
|
||||
* As the server contains only partial hash matches for URLs, the first time a URL
|
||||
matches a bad hash the server needs to consult Google's Safe Browsing service
|
||||
to fetch the full hash before it is able to confirm it is indeed a bad URL.<br />
|
||||
<br />
|
||||
By default, the server returns immediately and spawns a goroutine to fetch the
|
||||
full hash in the background, meaning the first query on a bad URL will return:
|
||||
<code>{ isListed: false, fullHashRequested: true }</code>. If however you wish
|
||||
to wait for this request for full hashes to happen and not miss the first query
|
||||
about a bad URL, check this box to pass through the blocking=1 parameter.
|
||||
</small><br />
|
||||
<br />
|
||||
<input type="button" value="Submit" onclick="fireRequest();" /><br />
|
||||
<br />
|
||||
Output:<br />
|
||||
<pre id="output" style="border: 1px solid #CCC; padding: 5px; overflow: auto;"></pre><br/>
|
||||
<br />
|
||||
JS code:<br />
|
||||
<pre style="padding: 5px; border: 1px solid #CCC;">
|
||||
var obj = {"urls": $("#txtJson").val(), "block": $("#blocking").prop("checked")};
|
||||
$.post("/", obj, function(data, textStatus, jqXHR) {
|
||||
$("#output").text(data);
|
||||
});
|
||||
</pre>
|
||||
<script>
|
||||
fireRequest = function() {
|
||||
var obj = {"urls": $("#txtJson").val(), "block": $("#blocking").prop("checked")};
|
||||
$.post("/", obj, function(data, textStatus, jqXHR) {
|
||||
$("#output").text(data);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
fmt.Fprint(w, html)
|
||||
}
|
||||
|
||||
func queryUrl(url string, isBlocking bool) (response *UrlResponse) {
|
||||
response = new(UrlResponse)
|
||||
|
||||
list := ""
|
||||
var err error
|
||||
fullHashMatch := false
|
||||
|
||||
if isBlocking {
|
||||
list, err = sb.IsListed(url)
|
||||
fullHashMatch = true
|
||||
} else {
|
||||
list, fullHashMatch, err = sb.MightBeListed(url)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
fmt.Sprintf(response.Error, "Error looking up url: %s", err.Error())
|
||||
}
|
||||
if list != "" {
|
||||
if fullHashMatch && sb.IsUpToDate() {
|
||||
response.IsListed = true
|
||||
response.List = list
|
||||
response.WarningTitle = warnings[list]["title"]
|
||||
response.WarningText = warnings[list]["text"]
|
||||
} else {
|
||||
response.IsListed = false
|
||||
response.List = list
|
||||
response.FullHashRequested = true
|
||||
// Requesting full hash in background...
|
||||
go sb.IsListed(url)
|
||||
}
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
func handler(w http.ResponseWriter, r *http.Request) {
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
fmt.Fprintf(w, "Error loading form: %s", err.Error())
|
||||
return
|
||||
}
|
||||
isBlocking := (r.FormValue("block") != "" &&
|
||||
r.FormValue("block") != "false" &&
|
||||
r.FormValue("block") != "0")
|
||||
|
||||
urls := make([]string, 0)
|
||||
err = json.Unmarshal([]byte(r.FormValue("urls")), &urls)
|
||||
if err != nil {
|
||||
fmt.Fprintf(w, "Error reading json: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
output := make(map[string]*UrlResponse, 0)
|
||||
for _, url := range urls {
|
||||
output[url] = queryUrl(url, isBlocking)
|
||||
}
|
||||
txtOutput, err := json.MarshalIndent(output, "", " ")
|
||||
if err != nil {
|
||||
fmt.Fprintf(w, "Error marshalling response: %s", err.Error())
|
||||
return
|
||||
}
|
||||
fmt.Fprint(w, string(txtOutput))
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,373 +0,0 @@
|
|||
// Package idn implements encoding from and to punycode as speficied by RFC 3492.
|
||||
package idn
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/miekg/dns"
|
||||
)
|
||||
|
||||
// Implementation idea from RFC itself and from from IDNA::Punycode created by
|
||||
// Tatsuhiko Miyagawa <miyagawa@bulknews.net> and released under Perl Artistic
|
||||
// License in 2002.
|
||||
|
||||
const (
|
||||
_MIN rune = 1
|
||||
_MAX rune = 26
|
||||
_SKEW rune = 38
|
||||
_BASE rune = 36
|
||||
_BIAS rune = 72
|
||||
_N rune = 128
|
||||
_DAMP rune = 700
|
||||
|
||||
_DELIMITER = '-'
|
||||
_PREFIX = "xn--"
|
||||
)
|
||||
|
||||
// ToPunycode converts unicode domain names to DNS-appropriate punycode names.
|
||||
// This function will return an empty string result for domain names with
|
||||
// invalid unicode strings. This function expects domain names in lowercase.
|
||||
func ToPunycode(s string) string {
|
||||
// Early check to see if encoding is needed.
|
||||
// This will prevent making heap allocations when not needed.
|
||||
if !needToPunycode(s) {
|
||||
return s
|
||||
}
|
||||
|
||||
tokens := dns.SplitDomainName(s)
|
||||
switch {
|
||||
case s == "":
|
||||
return ""
|
||||
case tokens == nil: // s == .
|
||||
return "."
|
||||
case s[len(s)-1] == '.':
|
||||
tokens = append(tokens, "")
|
||||
}
|
||||
|
||||
for i := range tokens {
|
||||
t := encode([]byte(tokens[i]))
|
||||
if t == nil {
|
||||
return ""
|
||||
}
|
||||
tokens[i] = string(t)
|
||||
}
|
||||
return strings.Join(tokens, ".")
|
||||
}
|
||||
|
||||
// FromPunycode returns unicode domain name from provided punycode string.
|
||||
// This function expects punycode strings in lowercase.
|
||||
func FromPunycode(s string) string {
|
||||
// Early check to see if decoding is needed.
|
||||
// This will prevent making heap allocations when not needed.
|
||||
if !needFromPunycode(s) {
|
||||
return s
|
||||
}
|
||||
|
||||
tokens := dns.SplitDomainName(s)
|
||||
switch {
|
||||
case s == "":
|
||||
return ""
|
||||
case tokens == nil: // s == .
|
||||
return "."
|
||||
case s[len(s)-1] == '.':
|
||||
tokens = append(tokens, "")
|
||||
}
|
||||
for i := range tokens {
|
||||
tokens[i] = string(decode([]byte(tokens[i])))
|
||||
}
|
||||
return strings.Join(tokens, ".")
|
||||
}
|
||||
|
||||
// digitval converts single byte into meaningful value that's used to calculate decoded unicode character.
|
||||
const errdigit = 0xffff
|
||||
|
||||
func digitval(code rune) rune {
|
||||
switch {
|
||||
case code >= 'A' && code <= 'Z':
|
||||
return code - 'A'
|
||||
case code >= 'a' && code <= 'z':
|
||||
return code - 'a'
|
||||
case code >= '0' && code <= '9':
|
||||
return code - '0' + 26
|
||||
}
|
||||
return errdigit
|
||||
}
|
||||
|
||||
// lettercode finds BASE36 byte (a-z0-9) based on calculated number.
|
||||
func lettercode(digit rune) rune {
|
||||
switch {
|
||||
case digit >= 0 && digit <= 25:
|
||||
return digit + 'a'
|
||||
case digit >= 26 && digit <= 36:
|
||||
return digit - 26 + '0'
|
||||
}
|
||||
panic("dns: not reached")
|
||||
}
|
||||
|
||||
// adapt calculates next bias to be used for next iteration delta.
|
||||
func adapt(delta rune, numpoints int, firsttime bool) rune {
|
||||
if firsttime {
|
||||
delta /= _DAMP
|
||||
} else {
|
||||
delta /= 2
|
||||
}
|
||||
|
||||
var k rune
|
||||
for delta = delta + delta/rune(numpoints); delta > (_BASE-_MIN)*_MAX/2; k += _BASE {
|
||||
delta /= _BASE - _MIN
|
||||
}
|
||||
|
||||
return k + ((_BASE-_MIN+1)*delta)/(delta+_SKEW)
|
||||
}
|
||||
|
||||
// next finds minimal rune (one with lowest codepoint value) that should be equal or above boundary.
|
||||
func next(b []rune, boundary rune) rune {
|
||||
if len(b) == 0 {
|
||||
panic("dns: invalid set of runes to determine next one")
|
||||
}
|
||||
m := b[0]
|
||||
for _, x := range b[1:] {
|
||||
if x >= boundary && (m < boundary || x < m) {
|
||||
m = x
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// preprune converts unicode rune to lower case. At this time it's not
|
||||
// supporting all things described in RFCs.
|
||||
func preprune(r rune) rune {
|
||||
if unicode.IsUpper(r) {
|
||||
r = unicode.ToLower(r)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// tfunc is a function that helps calculate each character weight.
|
||||
func tfunc(k, bias rune) rune {
|
||||
switch {
|
||||
case k <= bias:
|
||||
return _MIN
|
||||
case k >= bias+_MAX:
|
||||
return _MAX
|
||||
}
|
||||
return k - bias
|
||||
}
|
||||
|
||||
// needToPunycode returns true for strings that require punycode encoding
|
||||
// (contain unicode characters).
|
||||
func needToPunycode(s string) bool {
|
||||
// This function is very similar to bytes.Runes. We don't use bytes.Runes
|
||||
// because it makes a heap allocation that's not needed here.
|
||||
for i := 0; len(s) > 0; i++ {
|
||||
r, l := utf8.DecodeRuneInString(s)
|
||||
if r > 0x7f {
|
||||
return true
|
||||
}
|
||||
s = s[l:]
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// needFromPunycode returns true for strings that require punycode decoding.
|
||||
func needFromPunycode(s string) bool {
|
||||
if s == "." {
|
||||
return false
|
||||
}
|
||||
|
||||
off := 0
|
||||
end := false
|
||||
pl := len(_PREFIX)
|
||||
sl := len(s)
|
||||
|
||||
// If s starts with _PREFIX.
|
||||
if sl > pl && s[off:off+pl] == _PREFIX {
|
||||
return true
|
||||
}
|
||||
|
||||
for {
|
||||
// Find the part after the next ".".
|
||||
off, end = dns.NextLabel(s, off)
|
||||
if end {
|
||||
return false
|
||||
}
|
||||
// If this parts starts with _PREFIX.
|
||||
if sl-off > pl && s[off:off+pl] == _PREFIX {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// encode transforms Unicode input bytes (that represent DNS label) into
|
||||
// punycode bytestream. This function would return nil if there's an invalid
|
||||
// character in the label.
|
||||
func encode(input []byte) []byte {
|
||||
n, bias := _N, _BIAS
|
||||
|
||||
b := bytes.Runes(input)
|
||||
for i := range b {
|
||||
if !isValidRune(b[i]) {
|
||||
return nil
|
||||
}
|
||||
|
||||
b[i] = preprune(b[i])
|
||||
}
|
||||
|
||||
basic := make([]byte, 0, len(b))
|
||||
for _, ltr := range b {
|
||||
if ltr <= 0x7f {
|
||||
basic = append(basic, byte(ltr))
|
||||
}
|
||||
}
|
||||
basiclen := len(basic)
|
||||
fulllen := len(b)
|
||||
if basiclen == fulllen {
|
||||
return basic
|
||||
}
|
||||
|
||||
var out bytes.Buffer
|
||||
|
||||
out.WriteString(_PREFIX)
|
||||
if basiclen > 0 {
|
||||
out.Write(basic)
|
||||
out.WriteByte(_DELIMITER)
|
||||
}
|
||||
|
||||
var (
|
||||
ltr, nextltr rune
|
||||
delta, q rune // delta calculation (see rfc)
|
||||
t, k, cp rune // weight and codepoint calculation
|
||||
)
|
||||
|
||||
s := &bytes.Buffer{}
|
||||
for h := basiclen; h < fulllen; n, delta = n+1, delta+1 {
|
||||
nextltr = next(b, n)
|
||||
s.Truncate(0)
|
||||
s.WriteRune(nextltr)
|
||||
delta, n = delta+(nextltr-n)*rune(h+1), nextltr
|
||||
|
||||
for _, ltr = range b {
|
||||
if ltr < n {
|
||||
delta++
|
||||
}
|
||||
if ltr == n {
|
||||
q = delta
|
||||
for k = _BASE; ; k += _BASE {
|
||||
t = tfunc(k, bias)
|
||||
if q < t {
|
||||
break
|
||||
}
|
||||
cp = t + ((q - t) % (_BASE - t))
|
||||
out.WriteRune(lettercode(cp))
|
||||
q = (q - t) / (_BASE - t)
|
||||
}
|
||||
|
||||
out.WriteRune(lettercode(q))
|
||||
|
||||
bias = adapt(delta, h+1, h == basiclen)
|
||||
h, delta = h+1, 0
|
||||
}
|
||||
}
|
||||
}
|
||||
return out.Bytes()
|
||||
}
|
||||
|
||||
// decode transforms punycode input bytes (that represent DNS label) into Unicode bytestream.
|
||||
func decode(b []byte) []byte {
|
||||
src := b // b would move and we need to keep it
|
||||
|
||||
n, bias := _N, _BIAS
|
||||
if !bytes.HasPrefix(b, []byte(_PREFIX)) {
|
||||
return b
|
||||
}
|
||||
out := make([]rune, 0, len(b))
|
||||
b = b[len(_PREFIX):]
|
||||
for pos := len(b) - 1; pos >= 0; pos-- {
|
||||
// only last delimiter is our interest
|
||||
if b[pos] == _DELIMITER {
|
||||
out = append(out, bytes.Runes(b[:pos])...)
|
||||
b = b[pos+1:] // trim source string
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(b) == 0 {
|
||||
return src
|
||||
}
|
||||
var (
|
||||
i, oldi, w rune
|
||||
ch byte
|
||||
t, digit rune
|
||||
ln int
|
||||
)
|
||||
|
||||
for i = 0; len(b) > 0; i++ {
|
||||
oldi, w = i, 1
|
||||
for k := _BASE; len(b) > 0; k += _BASE {
|
||||
ch, b = b[0], b[1:]
|
||||
digit = digitval(rune(ch))
|
||||
if digit == errdigit {
|
||||
return src
|
||||
}
|
||||
i += digit * w
|
||||
if i < 0 {
|
||||
// safety check for rune overflow
|
||||
return src
|
||||
}
|
||||
|
||||
t = tfunc(k, bias)
|
||||
if digit < t {
|
||||
break
|
||||
}
|
||||
|
||||
w *= _BASE - t
|
||||
}
|
||||
ln = len(out) + 1
|
||||
bias = adapt(i-oldi, ln, oldi == 0)
|
||||
n += i / rune(ln)
|
||||
i = i % rune(ln)
|
||||
// insert
|
||||
out = append(out, 0)
|
||||
copy(out[i+1:], out[i:])
|
||||
out[i] = n
|
||||
}
|
||||
|
||||
var ret bytes.Buffer
|
||||
for _, r := range out {
|
||||
ret.WriteRune(r)
|
||||
}
|
||||
return ret.Bytes()
|
||||
}
|
||||
|
||||
// isValidRune checks if the character is valid. We will look for the
|
||||
// character property in the code points list. For now we aren't checking special
|
||||
// rules in case of contextual property
|
||||
func isValidRune(r rune) bool {
|
||||
return findProperty(r) == propertyPVALID
|
||||
}
|
||||
|
||||
// findProperty will try to check the code point property of the given
|
||||
// character. It will use a binary search algorithm as we have a slice of
|
||||
// ordered ranges (average case performance O(log n))
|
||||
func findProperty(r rune) property {
|
||||
imin, imax := 0, len(codePoints)
|
||||
|
||||
for imax >= imin {
|
||||
imid := (imin + imax) / 2
|
||||
|
||||
codePoint := codePoints[imid]
|
||||
if (codePoint.start == r && codePoint.end == 0) || (codePoint.start <= r && codePoint.end >= r) {
|
||||
return codePoint.state
|
||||
}
|
||||
|
||||
if (codePoint.end > 0 && codePoint.end < r) || (codePoint.end == 0 && codePoint.start < r) {
|
||||
imin = imid + 1
|
||||
} else {
|
||||
imax = imid - 1
|
||||
}
|
||||
}
|
||||
|
||||
return propertyUnknown
|
||||
}
|
|
@ -1,94 +0,0 @@
|
|||
package dns
|
||||
|
||||
// NameUsed sets the RRs in the prereq section to
|
||||
// "Name is in use" RRs. RFC 2136 section 2.4.4.
|
||||
func (u *Msg) NameUsed(rr []RR) {
|
||||
u.Answer = make([]RR, len(rr))
|
||||
for i, r := range rr {
|
||||
u.Answer[i] = &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassANY}}
|
||||
}
|
||||
}
|
||||
|
||||
// NameNotUsed sets the RRs in the prereq section to
|
||||
// "Name is in not use" RRs. RFC 2136 section 2.4.5.
|
||||
func (u *Msg) NameNotUsed(rr []RR) {
|
||||
u.Answer = make([]RR, len(rr))
|
||||
for i, r := range rr {
|
||||
u.Answer[i] = &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassNONE}}
|
||||
}
|
||||
}
|
||||
|
||||
// Used sets the RRs in the prereq section to
|
||||
// "RRset exists (value dependent -- with rdata)" RRs. RFC 2136 section 2.4.2.
|
||||
func (u *Msg) Used(rr []RR) {
|
||||
if len(u.Question) == 0 {
|
||||
panic("dns: empty question section")
|
||||
}
|
||||
u.Answer = make([]RR, len(rr))
|
||||
for i, r := range rr {
|
||||
u.Answer[i] = r
|
||||
u.Answer[i].Header().Class = u.Question[0].Qclass
|
||||
}
|
||||
}
|
||||
|
||||
// RRsetUsed sets the RRs in the prereq section to
|
||||
// "RRset exists (value independent -- no rdata)" RRs. RFC 2136 section 2.4.1.
|
||||
func (u *Msg) RRsetUsed(rr []RR) {
|
||||
u.Answer = make([]RR, len(rr))
|
||||
for i, r := range rr {
|
||||
u.Answer[i] = r
|
||||
u.Answer[i].Header().Class = ClassANY
|
||||
u.Answer[i].Header().Ttl = 0
|
||||
u.Answer[i].Header().Rdlength = 0
|
||||
}
|
||||
}
|
||||
|
||||
// RRsetNotUsed sets the RRs in the prereq section to
|
||||
// "RRset does not exist" RRs. RFC 2136 section 2.4.3.
|
||||
func (u *Msg) RRsetNotUsed(rr []RR) {
|
||||
u.Answer = make([]RR, len(rr))
|
||||
for i, r := range rr {
|
||||
u.Answer[i] = r
|
||||
u.Answer[i].Header().Class = ClassNONE
|
||||
u.Answer[i].Header().Rdlength = 0
|
||||
u.Answer[i].Header().Ttl = 0
|
||||
}
|
||||
}
|
||||
|
||||
// Insert creates a dynamic update packet that adds an complete RRset, see RFC 2136 section 2.5.1.
|
||||
func (u *Msg) Insert(rr []RR) {
|
||||
if len(u.Question) == 0 {
|
||||
panic("dns: empty question section")
|
||||
}
|
||||
u.Ns = make([]RR, len(rr))
|
||||
for i, r := range rr {
|
||||
u.Ns[i] = r
|
||||
u.Ns[i].Header().Class = u.Question[0].Qclass
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveRRset creates a dynamic update packet that deletes an RRset, see RFC 2136 section 2.5.2.
|
||||
func (u *Msg) RemoveRRset(rr []RR) {
|
||||
u.Ns = make([]RR, len(rr))
|
||||
for i, r := range rr {
|
||||
u.Ns[i] = &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: r.Header().Rrtype, Class: ClassANY}}
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveName creates a dynamic update packet that deletes all RRsets of a name, see RFC 2136 section 2.5.3
|
||||
func (u *Msg) RemoveName(rr []RR) {
|
||||
u.Ns = make([]RR, len(rr))
|
||||
for i, r := range rr {
|
||||
u.Ns[i] = &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassANY}}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove creates a dynamic update packet deletes RR from the RRSset, see RFC 2136 section 2.5.4
|
||||
func (u *Msg) Remove(rr []RR) {
|
||||
u.Ns = make([]RR, len(rr))
|
||||
for i, r := range rr {
|
||||
u.Ns[i] = r
|
||||
u.Ns[i].Header().Class = ClassNONE
|
||||
u.Ns[i].Header().Ttl = 0
|
||||
}
|
||||
}
|
|
@ -1,90 +0,0 @@
|
|||
package amqp
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAllocatorFirstShouldBeTheLow(t *testing.T) {
|
||||
n, ok := newAllocator(1, 2).next()
|
||||
if !ok {
|
||||
t.Fatalf("expected to allocate between 1 and 2")
|
||||
}
|
||||
|
||||
if want, got := 1, n; want != got {
|
||||
t.Fatalf("expected to first allocation to be 1")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAllocatorShouldBeBoundByHigh(t *testing.T) {
|
||||
a := newAllocator(1, 2)
|
||||
|
||||
if n, ok := a.next(); n != 1 || !ok {
|
||||
t.Fatalf("expected to allocate between 1 and 2, got %d, %v", n, ok)
|
||||
}
|
||||
if n, ok := a.next(); n != 2 || !ok {
|
||||
t.Fatalf("expected to allocate between 1 and 2, got %d, %v", n, ok)
|
||||
}
|
||||
if _, ok := a.next(); ok {
|
||||
t.Fatalf("expected not to allocate outside of 1 and 2")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAllocatorStringShouldIncludeAllocatedRanges(t *testing.T) {
|
||||
a := newAllocator(1, 10)
|
||||
a.reserve(1)
|
||||
a.reserve(2)
|
||||
a.reserve(3)
|
||||
a.reserve(5)
|
||||
a.reserve(6)
|
||||
a.reserve(8)
|
||||
a.reserve(10)
|
||||
|
||||
if want, got := "allocator[1..10] 1..3 5..6 8 10", a.String(); want != got {
|
||||
t.Fatalf("expected String of %q, got %q", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAllocatorShouldReuseReleased(t *testing.T) {
|
||||
a := newAllocator(1, 2)
|
||||
|
||||
first, _ := a.next()
|
||||
if want, got := 1, first; want != got {
|
||||
t.Fatalf("expected allocation to be %d, got: %d", want, got)
|
||||
}
|
||||
|
||||
second, _ := a.next()
|
||||
if want, got := 2, second; want != got {
|
||||
t.Fatalf("expected allocation to be %d, got: %d", want, got)
|
||||
}
|
||||
|
||||
a.release(first)
|
||||
|
||||
third, _ := a.next()
|
||||
if want, got := first, third; want != got {
|
||||
t.Fatalf("expected third allocation to be %d, got: %d", want, got)
|
||||
}
|
||||
|
||||
_, ok := a.next()
|
||||
if want, got := false, ok; want != got {
|
||||
t.Fatalf("expected fourth allocation to saturate the pool")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAllocatorReleasesKeepUpWithAllocationsForAllSizes(t *testing.T) {
|
||||
const runs = 5
|
||||
const max = 13
|
||||
|
||||
for lim := 1; lim < 2<<max; lim <<= 1 {
|
||||
a := newAllocator(0, lim)
|
||||
|
||||
for i := 0; i < runs*lim; i++ {
|
||||
if i >= lim { // fills the allocator
|
||||
a.release(int(rand.Int63n(int64(lim))))
|
||||
}
|
||||
if _, ok := a.next(); !ok {
|
||||
t.Fatalf("expected %d runs of random release of size %d not to fail on allocation %d", runs, lim, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,559 +0,0 @@
|
|||
// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
// Source code and contact info at http://github.com/streadway/amqp
|
||||
|
||||
package amqp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
type server struct {
|
||||
*testing.T
|
||||
r reader // framer <- client
|
||||
w writer // framer -> client
|
||||
S io.ReadWriteCloser // Server IO
|
||||
C io.ReadWriteCloser // Client IO
|
||||
|
||||
// captured client frames
|
||||
start connectionStartOk
|
||||
tune connectionTuneOk
|
||||
}
|
||||
|
||||
func defaultConfig() Config {
|
||||
return Config{SASL: []Authentication{&PlainAuth{"guest", "guest"}}, Vhost: "/"}
|
||||
}
|
||||
|
||||
func newSession(t *testing.T) (io.ReadWriteCloser, *server) {
|
||||
rs, wc := io.Pipe()
|
||||
rc, ws := io.Pipe()
|
||||
|
||||
rws := &logIO{t, "server", pipe{rs, ws}}
|
||||
rwc := &logIO{t, "client", pipe{rc, wc}}
|
||||
|
||||
server := server{
|
||||
T: t,
|
||||
r: reader{rws},
|
||||
w: writer{rws},
|
||||
S: rws,
|
||||
C: rwc,
|
||||
}
|
||||
|
||||
return rwc, &server
|
||||
}
|
||||
|
||||
func (t *server) expectBytes(b []byte) {
|
||||
in := make([]byte, len(b))
|
||||
if _, err := io.ReadFull(t.S, in); err != nil {
|
||||
t.Fatalf("io error expecting bytes: %v", err)
|
||||
}
|
||||
|
||||
if bytes.Compare(b, in) != 0 {
|
||||
t.Fatalf("failed bytes: expected: %s got: %s", string(b), string(in))
|
||||
}
|
||||
}
|
||||
|
||||
func (t *server) send(channel int, m message) {
|
||||
defer time.AfterFunc(time.Second, func() { panic("send deadlock") }).Stop()
|
||||
|
||||
if err := t.w.WriteFrame(&methodFrame{
|
||||
ChannelId: uint16(channel),
|
||||
Method: m,
|
||||
}); err != nil {
|
||||
t.Fatalf("frame err, write: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
// drops all but method frames expected on the given channel
|
||||
func (t *server) recv(channel int, m message) message {
|
||||
defer time.AfterFunc(time.Second, func() { panic("recv deadlock") }).Stop()
|
||||
|
||||
var remaining int
|
||||
var header *headerFrame
|
||||
var body []byte
|
||||
|
||||
for {
|
||||
frame, err := t.r.ReadFrame()
|
||||
if err != nil {
|
||||
t.Fatalf("frame err, read: %s", err)
|
||||
}
|
||||
|
||||
if frame.channel() != uint16(channel) {
|
||||
t.Fatalf("expected frame on channel %d, got channel %d", channel, frame.channel())
|
||||
}
|
||||
|
||||
switch f := frame.(type) {
|
||||
case *heartbeatFrame:
|
||||
// drop
|
||||
|
||||
case *headerFrame:
|
||||
// start content state
|
||||
header = f
|
||||
remaining = int(header.Size)
|
||||
if remaining == 0 {
|
||||
m.(messageWithContent).setContent(header.Properties, nil)
|
||||
return m
|
||||
}
|
||||
|
||||
case *bodyFrame:
|
||||
// continue until terminated
|
||||
body = append(body, f.Body...)
|
||||
remaining -= len(f.Body)
|
||||
if remaining <= 0 {
|
||||
m.(messageWithContent).setContent(header.Properties, body)
|
||||
return m
|
||||
}
|
||||
|
||||
case *methodFrame:
|
||||
if reflect.TypeOf(m) == reflect.TypeOf(f.Method) {
|
||||
wantv := reflect.ValueOf(m).Elem()
|
||||
havev := reflect.ValueOf(f.Method).Elem()
|
||||
wantv.Set(havev)
|
||||
if _, ok := m.(messageWithContent); !ok {
|
||||
return m
|
||||
}
|
||||
} else {
|
||||
t.Fatalf("expected method type: %T, got: %T", m, f.Method)
|
||||
}
|
||||
|
||||
default:
|
||||
t.Fatalf("unexpected frame: %+v", f)
|
||||
}
|
||||
}
|
||||
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
func (t *server) expectAMQP() {
|
||||
t.expectBytes([]byte{'A', 'M', 'Q', 'P', 0, 0, 9, 1})
|
||||
}
|
||||
|
||||
func (t *server) connectionStart() {
|
||||
t.send(0, &connectionStart{
|
||||
VersionMajor: 0,
|
||||
VersionMinor: 9,
|
||||
Mechanisms: "PLAIN",
|
||||
Locales: "en-us",
|
||||
})
|
||||
|
||||
t.recv(0, &t.start)
|
||||
}
|
||||
|
||||
func (t *server) connectionTune() {
|
||||
t.send(0, &connectionTune{
|
||||
ChannelMax: 11,
|
||||
FrameMax: 20000,
|
||||
Heartbeat: 10,
|
||||
})
|
||||
|
||||
t.recv(0, &t.tune)
|
||||
}
|
||||
|
||||
func (t *server) connectionOpen() {
|
||||
t.expectAMQP()
|
||||
t.connectionStart()
|
||||
t.connectionTune()
|
||||
|
||||
t.recv(0, &connectionOpen{})
|
||||
t.send(0, &connectionOpenOk{})
|
||||
}
|
||||
|
||||
func (t *server) connectionClose() {
|
||||
t.recv(0, &connectionClose{})
|
||||
t.send(0, &connectionCloseOk{})
|
||||
}
|
||||
|
||||
func (t *server) channelOpen(id int) {
|
||||
t.recv(id, &channelOpen{})
|
||||
t.send(id, &channelOpenOk{})
|
||||
}
|
||||
|
||||
func TestDefaultClientProperties(t *testing.T) {
|
||||
rwc, srv := newSession(t)
|
||||
|
||||
go func() {
|
||||
srv.connectionOpen()
|
||||
rwc.Close()
|
||||
}()
|
||||
|
||||
if c, err := Open(rwc, defaultConfig()); err != nil {
|
||||
t.Fatalf("could not create connection: %v (%s)", c, err)
|
||||
}
|
||||
|
||||
if want, got := defaultProduct, srv.start.ClientProperties["product"]; want != got {
|
||||
t.Errorf("expected product %s got: %s", want, got)
|
||||
}
|
||||
|
||||
if want, got := defaultVersion, srv.start.ClientProperties["version"]; want != got {
|
||||
t.Errorf("expected version %s got: %s", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCustomClientProperties(t *testing.T) {
|
||||
rwc, srv := newSession(t)
|
||||
|
||||
config := defaultConfig()
|
||||
config.Properties = Table{
|
||||
"product": "foo",
|
||||
"version": "1.0",
|
||||
}
|
||||
|
||||
go func() {
|
||||
srv.connectionOpen()
|
||||
rwc.Close()
|
||||
}()
|
||||
|
||||
if c, err := Open(rwc, config); err != nil {
|
||||
t.Fatalf("could not create connection: %v (%s)", c, err)
|
||||
}
|
||||
|
||||
if want, got := config.Properties["product"], srv.start.ClientProperties["product"]; want != got {
|
||||
t.Errorf("expected product %s got: %s", want, got)
|
||||
}
|
||||
|
||||
if want, got := config.Properties["version"], srv.start.ClientProperties["version"]; want != got {
|
||||
t.Errorf("expected version %s got: %s", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpen(t *testing.T) {
|
||||
rwc, srv := newSession(t)
|
||||
go func() {
|
||||
srv.connectionOpen()
|
||||
rwc.Close()
|
||||
}()
|
||||
|
||||
if c, err := Open(rwc, defaultConfig()); err != nil {
|
||||
t.Fatalf("could not create connection: %v (%s)", c, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestChannelOpen(t *testing.T) {
|
||||
rwc, srv := newSession(t)
|
||||
|
||||
go func() {
|
||||
srv.connectionOpen()
|
||||
srv.channelOpen(1)
|
||||
|
||||
rwc.Close()
|
||||
}()
|
||||
|
||||
c, err := Open(rwc, defaultConfig())
|
||||
if err != nil {
|
||||
t.Fatalf("could not create connection: %v (%s)", c, err)
|
||||
}
|
||||
|
||||
ch, err := c.Channel()
|
||||
if err != nil {
|
||||
t.Fatalf("could not open channel: %v (%s)", ch, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpenFailedSASLUnsupportedMechanisms(t *testing.T) {
|
||||
rwc, srv := newSession(t)
|
||||
|
||||
go func() {
|
||||
srv.expectAMQP()
|
||||
srv.send(0, &connectionStart{
|
||||
VersionMajor: 0,
|
||||
VersionMinor: 9,
|
||||
Mechanisms: "KERBEROS NTLM",
|
||||
Locales: "en-us",
|
||||
})
|
||||
}()
|
||||
|
||||
c, err := Open(rwc, defaultConfig())
|
||||
if err != ErrSASL {
|
||||
t.Fatalf("expected ErrSASL got: %+v on %+v", err, c)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpenFailedCredentials(t *testing.T) {
|
||||
rwc, srv := newSession(t)
|
||||
|
||||
go func() {
|
||||
srv.expectAMQP()
|
||||
srv.connectionStart()
|
||||
// Now kill/timeout the connection indicating bad auth
|
||||
rwc.Close()
|
||||
}()
|
||||
|
||||
c, err := Open(rwc, defaultConfig())
|
||||
if err != ErrCredentials {
|
||||
t.Fatalf("expected ErrCredentials got: %+v on %+v", err, c)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpenFailedVhost(t *testing.T) {
|
||||
rwc, srv := newSession(t)
|
||||
|
||||
go func() {
|
||||
srv.expectAMQP()
|
||||
srv.connectionStart()
|
||||
srv.connectionTune()
|
||||
srv.recv(0, &connectionOpen{})
|
||||
|
||||
// Now kill/timeout the connection on bad Vhost
|
||||
rwc.Close()
|
||||
}()
|
||||
|
||||
c, err := Open(rwc, defaultConfig())
|
||||
if err != ErrVhost {
|
||||
t.Fatalf("expected ErrVhost got: %+v on %+v", err, c)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfirmMultipleOrdersDeliveryTags(t *testing.T) {
|
||||
rwc, srv := newSession(t)
|
||||
defer rwc.Close()
|
||||
|
||||
go func() {
|
||||
srv.connectionOpen()
|
||||
srv.channelOpen(1)
|
||||
|
||||
srv.recv(1, &confirmSelect{})
|
||||
srv.send(1, &confirmSelectOk{})
|
||||
|
||||
srv.recv(1, &basicPublish{})
|
||||
srv.recv(1, &basicPublish{})
|
||||
srv.recv(1, &basicPublish{})
|
||||
srv.recv(1, &basicPublish{})
|
||||
|
||||
// Single tag, plus multiple, should produce
|
||||
// 2, 1, 3, 4
|
||||
srv.send(1, &basicAck{DeliveryTag: 2})
|
||||
srv.send(1, &basicAck{DeliveryTag: 4, Multiple: true})
|
||||
|
||||
srv.recv(1, &basicPublish{})
|
||||
srv.recv(1, &basicPublish{})
|
||||
srv.recv(1, &basicPublish{})
|
||||
srv.recv(1, &basicPublish{})
|
||||
|
||||
// And some more, but in reverse order, multiple then one
|
||||
// 5, 6, 7, 8
|
||||
srv.send(1, &basicAck{DeliveryTag: 6, Multiple: true})
|
||||
srv.send(1, &basicAck{DeliveryTag: 8})
|
||||
srv.send(1, &basicAck{DeliveryTag: 7})
|
||||
}()
|
||||
|
||||
c, err := Open(rwc, defaultConfig())
|
||||
if err != nil {
|
||||
t.Fatalf("could not create connection: %v (%s)", c, err)
|
||||
}
|
||||
|
||||
ch, err := c.Channel()
|
||||
if err != nil {
|
||||
t.Fatalf("could not open channel: %v (%s)", ch, err)
|
||||
}
|
||||
|
||||
acks, _ := ch.NotifyConfirm(make(chan uint64), make(chan uint64))
|
||||
|
||||
ch.Confirm(false)
|
||||
|
||||
ch.Publish("", "q", false, false, Publishing{Body: []byte("pub 1")})
|
||||
ch.Publish("", "q", false, false, Publishing{Body: []byte("pub 2")})
|
||||
ch.Publish("", "q", false, false, Publishing{Body: []byte("pub 3")})
|
||||
ch.Publish("", "q", false, false, Publishing{Body: []byte("pub 4")})
|
||||
|
||||
for i, tag := range []uint64{2, 1, 3, 4} {
|
||||
if ack := <-acks; tag != ack {
|
||||
t.Fatalf("failed ack, expected ack#%d to be %d, got %d", i, tag, ack)
|
||||
}
|
||||
}
|
||||
|
||||
ch.Publish("", "q", false, false, Publishing{Body: []byte("pub 5")})
|
||||
ch.Publish("", "q", false, false, Publishing{Body: []byte("pub 6")})
|
||||
ch.Publish("", "q", false, false, Publishing{Body: []byte("pub 7")})
|
||||
ch.Publish("", "q", false, false, Publishing{Body: []byte("pub 8")})
|
||||
|
||||
for i, tag := range []uint64{5, 6, 8, 7} {
|
||||
if ack := <-acks; tag != ack {
|
||||
t.Fatalf("failed ack, expected ack#%d to be %d, got %d", i, tag, ack)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestNotifyClosesReusedPublisherConfirmChan(t *testing.T) {
|
||||
rwc, srv := newSession(t)
|
||||
|
||||
go func() {
|
||||
srv.connectionOpen()
|
||||
srv.channelOpen(1)
|
||||
|
||||
srv.recv(1, &confirmSelect{})
|
||||
srv.send(1, &confirmSelectOk{})
|
||||
|
||||
srv.recv(0, &connectionClose{})
|
||||
srv.send(0, &connectionCloseOk{})
|
||||
}()
|
||||
|
||||
c, err := Open(rwc, defaultConfig())
|
||||
if err != nil {
|
||||
t.Fatalf("could not create connection: %v (%s)", c, err)
|
||||
}
|
||||
|
||||
ch, err := c.Channel()
|
||||
if err != nil {
|
||||
t.Fatalf("could not open channel: %v (%s)", ch, err)
|
||||
}
|
||||
|
||||
ackAndNack := make(chan uint64)
|
||||
ch.NotifyConfirm(ackAndNack, ackAndNack)
|
||||
|
||||
if err := ch.Confirm(false); err != nil {
|
||||
t.Fatalf("expected to enter confirm mode: %v", err)
|
||||
}
|
||||
|
||||
if err := c.Close(); err != nil {
|
||||
t.Fatalf("could not close connection: %v (%s)", c, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNotifyClosesAllChansAfterConnectionClose(t *testing.T) {
|
||||
rwc, srv := newSession(t)
|
||||
|
||||
go func() {
|
||||
srv.connectionOpen()
|
||||
srv.channelOpen(1)
|
||||
|
||||
srv.recv(0, &connectionClose{})
|
||||
srv.send(0, &connectionCloseOk{})
|
||||
}()
|
||||
|
||||
c, err := Open(rwc, defaultConfig())
|
||||
if err != nil {
|
||||
t.Fatalf("could not create connection: %v (%s)", c, err)
|
||||
}
|
||||
|
||||
ch, err := c.Channel()
|
||||
if err != nil {
|
||||
t.Fatalf("could not open channel: %v (%s)", ch, err)
|
||||
}
|
||||
|
||||
if err := c.Close(); err != nil {
|
||||
t.Fatalf("could not close connection: %v (%s)", c, err)
|
||||
}
|
||||
|
||||
select {
|
||||
case <-c.NotifyClose(make(chan *Error)):
|
||||
case <-time.After(time.Millisecond):
|
||||
t.Errorf("expected to close NotifyClose chan after Connection.Close")
|
||||
}
|
||||
|
||||
select {
|
||||
case <-ch.NotifyClose(make(chan *Error)):
|
||||
case <-time.After(time.Millisecond):
|
||||
t.Errorf("expected to close Connection.NotifyClose chan after Connection.Close")
|
||||
}
|
||||
|
||||
select {
|
||||
case <-ch.NotifyFlow(make(chan bool)):
|
||||
case <-time.After(time.Millisecond):
|
||||
t.Errorf("expected to close Channel.NotifyFlow chan after Connection.Close")
|
||||
}
|
||||
|
||||
select {
|
||||
case <-ch.NotifyCancel(make(chan string)):
|
||||
case <-time.After(time.Millisecond):
|
||||
t.Errorf("expected to close Channel.NofityCancel chan after Connection.Close")
|
||||
}
|
||||
|
||||
select {
|
||||
case <-ch.NotifyReturn(make(chan Return)):
|
||||
case <-time.After(time.Millisecond):
|
||||
t.Errorf("expected to close Channel.NotifyReturn chan after Connection.Close")
|
||||
}
|
||||
|
||||
ack, nack := ch.NotifyConfirm(make(chan uint64), make(chan uint64))
|
||||
|
||||
select {
|
||||
case <-ack:
|
||||
case <-time.After(time.Millisecond):
|
||||
t.Errorf("expected to close acks on Channel.NotifyConfirm chan after Connection.Close")
|
||||
}
|
||||
|
||||
select {
|
||||
case <-nack:
|
||||
case <-time.After(time.Millisecond):
|
||||
t.Errorf("expected to close nacks Channel.NotifyConfirm chan after Connection.Close")
|
||||
}
|
||||
}
|
||||
|
||||
// Should not panic when sending bodies split at differnet boundaries
|
||||
func TestPublishBodySliceIssue74(t *testing.T) {
|
||||
rwc, srv := newSession(t)
|
||||
defer rwc.Close()
|
||||
|
||||
const frameSize = 100
|
||||
const publishings = frameSize * 3
|
||||
|
||||
done := make(chan bool)
|
||||
base := make([]byte, publishings)
|
||||
|
||||
go func() {
|
||||
srv.connectionOpen()
|
||||
srv.channelOpen(1)
|
||||
|
||||
for i := 0; i < publishings; i++ {
|
||||
srv.recv(1, &basicPublish{})
|
||||
}
|
||||
|
||||
done <- true
|
||||
}()
|
||||
|
||||
cfg := defaultConfig()
|
||||
cfg.FrameSize = frameSize
|
||||
|
||||
c, err := Open(rwc, cfg)
|
||||
if err != nil {
|
||||
t.Fatalf("could not create connection: %v (%s)", c, err)
|
||||
}
|
||||
|
||||
ch, err := c.Channel()
|
||||
if err != nil {
|
||||
t.Fatalf("could not open channel: %v (%s)", ch, err)
|
||||
}
|
||||
|
||||
for i := 0; i < publishings; i++ {
|
||||
go ch.Publish("", "q", false, false, Publishing{Body: base[0:i]})
|
||||
}
|
||||
|
||||
<-done
|
||||
}
|
||||
|
||||
func TestPublishAndShutdownDeadlockIssue84(t *testing.T) {
|
||||
rwc, srv := newSession(t)
|
||||
defer rwc.Close()
|
||||
|
||||
go func() {
|
||||
srv.connectionOpen()
|
||||
srv.channelOpen(1)
|
||||
srv.recv(1, &basicPublish{})
|
||||
// Mimic a broken io pipe so that Publish catches the error and goes into shutdown
|
||||
srv.S.Close()
|
||||
}()
|
||||
|
||||
c, err := Open(rwc, defaultConfig())
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't create connection: %v (%s)", c, err)
|
||||
}
|
||||
|
||||
ch, err := c.Channel()
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't open channel: %v (%s)", ch, err)
|
||||
}
|
||||
|
||||
defer time.AfterFunc(500*time.Millisecond, func() { panic("Publish deadlock") }).Stop()
|
||||
for {
|
||||
if err := ch.Publish("exchange", "q", false, false, Publishing{Body: []byte("test")}); err != nil {
|
||||
t.Log("successfully caught disconnect error", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
package amqp
|
||||
|
||||
import "testing"
|
||||
|
||||
func shouldNotPanic(t *testing.T) {
|
||||
if err := recover(); err != nil {
|
||||
t.Fatalf("should not panic, got: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
// A closed delivery chan could produce zero value. Ack/Nack/Reject on these
|
||||
// deliveries can produce a nil pointer panic. Instead return an error when
|
||||
// the method can never be successful.
|
||||
func TestAckZeroValueAcknowledgerDoesNotPanic(t *testing.T) {
|
||||
defer shouldNotPanic(t)
|
||||
if err := (Delivery{}).Ack(false); err == nil {
|
||||
t.Errorf("expected Delivery{}.Ack to error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNackZeroValueAcknowledgerDoesNotPanic(t *testing.T) {
|
||||
defer shouldNotPanic(t)
|
||||
if err := (Delivery{}).Nack(false, false); err == nil {
|
||||
t.Errorf("expected Delivery{}.Ack to error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRejectZeroValueAcknowledgerDoesNotPanic(t *testing.T) {
|
||||
defer shouldNotPanic(t)
|
||||
if err := (Delivery{}).Reject(false); err == nil {
|
||||
t.Errorf("expected Delivery{}.Ack to error")
|
||||
}
|
||||
}
|
|
@ -1,395 +0,0 @@
|
|||
package amqp_test
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/streadway/amqp"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"runtime"
|
||||
"time"
|
||||
)
|
||||
|
||||
func ExampleConfig_timeout() {
|
||||
// Provide your own anonymous Dial function that delgates to net.DialTimout
|
||||
// for custom timeouts
|
||||
|
||||
conn, err := amqp.DialConfig("amqp:///", amqp.Config{
|
||||
Dial: func(network, addr string) (net.Conn, error) {
|
||||
return net.DialTimeout(network, addr, 2*time.Second)
|
||||
},
|
||||
})
|
||||
|
||||
log.Printf("conn: %v, err: %v", conn, err)
|
||||
}
|
||||
|
||||
func ExampleDialTLS() {
|
||||
// To get started with SSL/TLS follow the instructions for adding SSL/TLS
|
||||
// support in RabbitMQ with a private certificate authority here:
|
||||
//
|
||||
// http://www.rabbitmq.com/ssl.html
|
||||
//
|
||||
// Then in your rabbitmq.config, disable the plain AMQP port, verify clients
|
||||
// and fail if no certificate is presented with the following:
|
||||
//
|
||||
// [
|
||||
// {rabbit, [
|
||||
// {tcp_listeners, []}, % listens on 127.0.0.1:5672
|
||||
// {ssl_listeners, [5671]}, % listens on 0.0.0.0:5671
|
||||
// {ssl_options, [{cacertfile,"/path/to/your/testca/cacert.pem"},
|
||||
// {certfile,"/path/to/your/server/cert.pem"},
|
||||
// {keyfile,"/path/to/your/server/key.pem"},
|
||||
// {verify,verify_peer},
|
||||
// {fail_if_no_peer_cert,true}]}
|
||||
// ]}
|
||||
// ].
|
||||
|
||||
cfg := new(tls.Config)
|
||||
|
||||
// The self-signing certificate authority's certificate must be included in
|
||||
// the RootCAs to be trusted so that the server certificate can be verified.
|
||||
//
|
||||
// Alternatively to adding it to the tls.Config you can add the CA's cert to
|
||||
// your system's root CAs. The tls package will use the system roots
|
||||
// specific to each support OS. Under OS X, add (drag/drop) your cacert.pem
|
||||
// file to the 'Certificates' section of KeyChain.app to add and always
|
||||
// trust.
|
||||
//
|
||||
// Or with the command line add and trust the DER encoded certificate:
|
||||
//
|
||||
// security add-certificate testca/cacert.cer
|
||||
// security add-trusted-cert testca/cacert.cer
|
||||
//
|
||||
// If you depend on the system root CAs, then use nil for the RootCAs field
|
||||
// so the system roots will be loaded.
|
||||
|
||||
cfg.RootCAs = x509.NewCertPool()
|
||||
|
||||
if ca, err := ioutil.ReadFile("testca/cacert.pem"); err == nil {
|
||||
cfg.RootCAs.AppendCertsFromPEM(ca)
|
||||
}
|
||||
|
||||
// Move the client cert and key to a location specific to your application
|
||||
// and load them here.
|
||||
|
||||
if cert, err := tls.LoadX509KeyPair("client/cert.pem", "client/key.pem"); err == nil {
|
||||
cfg.Certificates = append(cfg.Certificates, cert)
|
||||
}
|
||||
|
||||
// Server names are validated by the crypto/tls package, so the server
|
||||
// certificate must be made for the hostname in the URL. Find the commonName
|
||||
// (CN) and make sure the hostname in the URL matches this common name. Per
|
||||
// the RabbitMQ instructions for a self-signed cert, this defautls to the
|
||||
// current hostname.
|
||||
//
|
||||
// openssl x509 -noout -in server/cert.pem -subject
|
||||
//
|
||||
// If your server name in your certificate is different than the host you are
|
||||
// connecting to, set the hostname used for verification in
|
||||
// ServerName field of the tls.Config struct.
|
||||
|
||||
conn, err := amqp.DialTLS("amqps://server-name-from-certificate/", cfg)
|
||||
|
||||
log.Printf("conn: %v, err: %v", conn, err)
|
||||
}
|
||||
|
||||
func ExampleChannel_Confirm_bridge() {
|
||||
// This example acts as a bridge, shoveling all messages sent from the source
|
||||
// exchange "log" to destination exchange "log".
|
||||
|
||||
// Confirming publishes can help from overproduction and ensure every message
|
||||
// is delivered.
|
||||
|
||||
// Setup the source of the store and forward
|
||||
source, err := amqp.Dial("amqp://source/")
|
||||
if err != nil {
|
||||
log.Fatalf("connection.open source: %s", err)
|
||||
}
|
||||
defer source.Close()
|
||||
|
||||
chs, err := source.Channel()
|
||||
if err != nil {
|
||||
log.Fatalf("channel.open source: %s", err)
|
||||
}
|
||||
|
||||
if err := chs.ExchangeDeclare("log", "topic", true, false, false, false, nil); err != nil {
|
||||
log.Fatalf("exchange.declare destination: %s", err)
|
||||
}
|
||||
|
||||
if _, err := chs.QueueDeclare("remote-tee", true, true, false, false, nil); err != nil {
|
||||
log.Fatalf("queue.declare source: %s", err)
|
||||
}
|
||||
|
||||
if err := chs.QueueBind("remote-tee", "#", "logs", false, nil); err != nil {
|
||||
log.Fatalf("queue.bind source: %s", err)
|
||||
}
|
||||
|
||||
shovel, err := chs.Consume("remote-tee", "shovel", false, false, false, false, nil)
|
||||
if err != nil {
|
||||
log.Fatalf("basic.consume source: %s", err)
|
||||
}
|
||||
|
||||
// Setup the destination of the store and forward
|
||||
destination, err := amqp.Dial("amqp://destination/")
|
||||
if err != nil {
|
||||
log.Fatalf("connection.open destination: %s", err)
|
||||
}
|
||||
defer destination.Close()
|
||||
|
||||
chd, err := destination.Channel()
|
||||
if err != nil {
|
||||
log.Fatalf("channel.open destination: %s", err)
|
||||
}
|
||||
|
||||
if err := chd.ExchangeDeclare("log", "topic", true, false, false, false, nil); err != nil {
|
||||
log.Fatalf("exchange.declare destination: %s", err)
|
||||
}
|
||||
|
||||
// Buffer of 1 for our single outstanding publishing
|
||||
pubAcks, pubNacks := chd.NotifyConfirm(make(chan uint64, 1), make(chan uint64, 1))
|
||||
|
||||
if err := chd.Confirm(false); err != nil {
|
||||
log.Fatalf("confirm.select destination: %s", err)
|
||||
}
|
||||
|
||||
// Now pump the messages, one by one, a smarter implementation
|
||||
// would batch the deliveries and use multiple ack/nacks
|
||||
for {
|
||||
msg, ok := <-shovel
|
||||
if !ok {
|
||||
log.Fatalf("source channel closed, see the reconnect example for handling this")
|
||||
}
|
||||
|
||||
err = chd.Publish("logs", msg.RoutingKey, false, false, amqp.Publishing{
|
||||
// Copy all the properties
|
||||
ContentType: msg.ContentType,
|
||||
ContentEncoding: msg.ContentEncoding,
|
||||
DeliveryMode: msg.DeliveryMode,
|
||||
Priority: msg.Priority,
|
||||
CorrelationId: msg.CorrelationId,
|
||||
ReplyTo: msg.ReplyTo,
|
||||
Expiration: msg.Expiration,
|
||||
MessageId: msg.MessageId,
|
||||
Timestamp: msg.Timestamp,
|
||||
Type: msg.Type,
|
||||
UserId: msg.UserId,
|
||||
AppId: msg.AppId,
|
||||
|
||||
// Custom headers
|
||||
Headers: msg.Headers,
|
||||
|
||||
// And the body
|
||||
Body: msg.Body,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
msg.Nack(false, false)
|
||||
log.Fatalf("basic.publish destination: %s", msg)
|
||||
}
|
||||
|
||||
// only ack the source delivery when the destination acks the publishing
|
||||
// here you could check for delivery order by keeping a local state of
|
||||
// expected delivery tags
|
||||
select {
|
||||
case <-pubAcks:
|
||||
msg.Ack(false)
|
||||
case <-pubNacks:
|
||||
msg.Nack(false, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleChannel_Consume() {
|
||||
// Connects opens an AMQP connection from the credentials in the URL.
|
||||
conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
|
||||
if err != nil {
|
||||
log.Fatalf("connection.open: %s", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
c, err := conn.Channel()
|
||||
if err != nil {
|
||||
log.Fatalf("channel.open: %s", err)
|
||||
}
|
||||
|
||||
// We declare our topology on both the publisher and consumer to ensure they
|
||||
// are the same. This is part of AMQP being a programmable messaging model.
|
||||
//
|
||||
// See the Channel.Publish example for the complimentary declare.
|
||||
err = c.ExchangeDeclare("logs", "topic", true, false, false, false, nil)
|
||||
if err != nil {
|
||||
log.Fatalf("exchange.declare: %s", err)
|
||||
}
|
||||
|
||||
// Establish our queue topologies that we are responsible for
|
||||
type bind struct {
|
||||
queue string
|
||||
key string
|
||||
}
|
||||
|
||||
bindings := []bind{
|
||||
bind{"page", "alert"},
|
||||
bind{"email", "info"},
|
||||
bind{"firehose", "#"},
|
||||
}
|
||||
|
||||
for _, b := range bindings {
|
||||
_, err = c.QueueDeclare(b.queue, true, false, false, false, nil)
|
||||
if err != nil {
|
||||
log.Fatalf("queue.declare: %v", err)
|
||||
}
|
||||
|
||||
err = c.QueueBind(b.queue, b.key, "logs", false, nil)
|
||||
if err != nil {
|
||||
log.Fatalf("queue.bind: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Set our quality of service. Since we're sharing 3 consumers on the same
|
||||
// channel, we want at least 3 messages in flight.
|
||||
err = c.Qos(3, 0, false)
|
||||
if err != nil {
|
||||
log.Fatalf("basic.qos: %v", err)
|
||||
}
|
||||
|
||||
// Establish our consumers that have different responsibilities. Our first
|
||||
// two queues do not ack the messages on the server, so require to be acked
|
||||
// on the client.
|
||||
|
||||
pages, err := c.Consume("page", "pager", false, false, false, false, nil)
|
||||
if err != nil {
|
||||
log.Fatalf("basic.consume: %v", err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
for log := range pages {
|
||||
// ... this consumer is responsible for sending pages per log
|
||||
log.Ack(false)
|
||||
}
|
||||
}()
|
||||
|
||||
// Notice how the concern for which messages arrive here are in the AMQP
|
||||
// topology and not in the queue. We let the server pick a consumer tag this
|
||||
// time.
|
||||
|
||||
emails, err := c.Consume("email", "", false, false, false, false, nil)
|
||||
if err != nil {
|
||||
log.Fatalf("basic.consume: %v", err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
for log := range emails {
|
||||
// ... this consumer is responsible for sending emails per log
|
||||
log.Ack(false)
|
||||
}
|
||||
}()
|
||||
|
||||
// This consumer requests that every message is acknowledged as soon as it's
|
||||
// delivered.
|
||||
|
||||
firehose, err := c.Consume("firehose", "", true, false, false, false, nil)
|
||||
if err != nil {
|
||||
log.Fatalf("basic.consume: %v", err)
|
||||
}
|
||||
|
||||
// To show how to process the items in parallel, we'll use a work pool.
|
||||
for i := 0; i < runtime.NumCPU(); i++ {
|
||||
go func(work <-chan amqp.Delivery) {
|
||||
for _ = range work {
|
||||
// ... this consumer pulls from the firehose and doesn't need to acknowledge
|
||||
}
|
||||
}(firehose)
|
||||
}
|
||||
|
||||
// Wait until you're ready to finish, could be a signal handler here.
|
||||
time.Sleep(10 * time.Second)
|
||||
|
||||
// Cancelling a consumer by name will finish the range and gracefully end the
|
||||
// goroutine
|
||||
err = c.Cancel("pager", false)
|
||||
if err != nil {
|
||||
log.Fatalf("basic.cancel: %v", err)
|
||||
}
|
||||
|
||||
// deferred closing the Connection will also finish the consumer's ranges of
|
||||
// their delivery chans. If you need every delivery to be processed, make
|
||||
// sure to wait for all consumers goroutines to finish before exiting your
|
||||
// process.
|
||||
}
|
||||
|
||||
func ExampleChannel_Publish() {
|
||||
// Connects opens an AMQP connection from the credentials in the URL.
|
||||
conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
|
||||
if err != nil {
|
||||
log.Fatalf("connection.open: %s", err)
|
||||
}
|
||||
|
||||
// This waits for a server acknowledgment which means the sockets will have
|
||||
// flushed all outbound publishings prior to returning. It's important to
|
||||
// block on Close to not lose any publishings.
|
||||
defer conn.Close()
|
||||
|
||||
c, err := conn.Channel()
|
||||
if err != nil {
|
||||
log.Fatalf("channel.open: %s", err)
|
||||
}
|
||||
|
||||
// We declare our topology on both the publisher and consumer to ensure they
|
||||
// are the same. This is part of AMQP being a programmable messaging model.
|
||||
//
|
||||
// See the Channel.Consume example for the complimentary declare.
|
||||
err = c.ExchangeDeclare("logs", "topic", true, false, false, false, nil)
|
||||
if err != nil {
|
||||
log.Fatalf("exchange.declare: %v", err)
|
||||
}
|
||||
|
||||
// Prepare this message to be persistent. Your publishing requirements may
|
||||
// be different.
|
||||
msg := amqp.Publishing{
|
||||
DeliveryMode: amqp.Persistent,
|
||||
Timestamp: time.Now(),
|
||||
ContentType: "text/plain",
|
||||
Body: []byte("Go Go AMQP!"),
|
||||
}
|
||||
|
||||
// This is not a mandatory delivery, so it will be dropped if there are no
|
||||
// queues bound to the logs exchange.
|
||||
err = c.Publish("logs", "info", false, false, msg)
|
||||
if err != nil {
|
||||
// Since publish is asynchronous this can happen if the network connection
|
||||
// is reset or if the server has run out of resources.
|
||||
log.Fatalf("basic.publish: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func publishAllTheThings(conn *amqp.Connection) {
|
||||
// ... snarf snarf, barf barf
|
||||
}
|
||||
|
||||
func ExampleConnection_NotifyBlocked() {
|
||||
// Simply logs when the server throttles the TCP connection for publishers
|
||||
|
||||
// Test this by tuning your server to have a low memory watermark:
|
||||
// rabbitmqctl set_vm_memory_high_watermark 0.00000001
|
||||
|
||||
conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
|
||||
if err != nil {
|
||||
log.Fatalf("connection.open: %s", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
blockings := conn.NotifyBlocked(make(chan amqp.Blocking))
|
||||
go func() {
|
||||
for b := range blockings {
|
||||
if b.Active {
|
||||
log.Printf("TCP blocked: %q", b.Reason)
|
||||
} else {
|
||||
log.Printf("TCP unblocked")
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Your application domain channel setup publishings
|
||||
publishAllTheThings(conn)
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,113 +0,0 @@
|
|||
package amqp_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/streadway/amqp"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Every connection should declare the topology they expect
|
||||
func setup(url, queue string) (*amqp.Connection, *amqp.Channel, error) {
|
||||
conn, err := amqp.Dial(url)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
ch, err := conn.Channel()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if _, err := ch.QueueDeclare(queue, false, true, false, false, nil); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return conn, ch, nil
|
||||
}
|
||||
|
||||
func consume(url, queue string) (*amqp.Connection, <-chan amqp.Delivery, error) {
|
||||
conn, ch, err := setup(url, queue)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Indicate we only want 1 message to acknowledge at a time.
|
||||
if err := ch.Qos(1, 0, false); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Exclusive consumer
|
||||
deliveries, err := ch.Consume(queue, "", false, true, false, false, nil)
|
||||
|
||||
return conn, deliveries, err
|
||||
}
|
||||
|
||||
func ExampleConnection_reconnect() {
|
||||
if url := os.Getenv("AMQP_URL"); url != "" {
|
||||
queue := "example.reconnect"
|
||||
|
||||
// The connection/channel for publishing to interleave the ingress messages
|
||||
// between reconnects, shares the same topology as the consumer. If we rather
|
||||
// sent all messages up front, the first consumer would receive every message.
|
||||
// We would rather show how the messages are not lost between reconnects.
|
||||
_, pub, err := setup(url, queue)
|
||||
if err != nil {
|
||||
fmt.Println("err publisher setup:", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Purge the queue from the publisher side to establish initial state
|
||||
if _, err := pub.QueuePurge(queue, false); err != nil {
|
||||
fmt.Println("err purge:", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Reconnect simulation, should be for { ... } in production
|
||||
for i := 1; i <= 3; i++ {
|
||||
fmt.Println("connect")
|
||||
|
||||
conn, deliveries, err := consume(url, queue)
|
||||
if err != nil {
|
||||
fmt.Println("err consume:", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Simulate a producer on a different connection showing that consumers
|
||||
// continue where they were left off after each reconnect.
|
||||
if err := pub.Publish("", queue, false, false, amqp.Publishing{
|
||||
Body: []byte(fmt.Sprintf("%d", i)),
|
||||
}); err != nil {
|
||||
fmt.Println("err publish:", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Simulates a consumer that when the range finishes, will setup a new
|
||||
// session and begin ranging over the deliveries again.
|
||||
for msg := range deliveries {
|
||||
fmt.Println(string(msg.Body))
|
||||
msg.Ack(false)
|
||||
|
||||
// Simulate an error like a server restart, loss of route or operator
|
||||
// intervention that results in the connection terminating
|
||||
go conn.Close()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// pass with expected output when not running in an integration
|
||||
// environment.
|
||||
fmt.Println("connect")
|
||||
fmt.Println("1")
|
||||
fmt.Println("connect")
|
||||
fmt.Println("2")
|
||||
fmt.Println("connect")
|
||||
fmt.Println("3")
|
||||
}
|
||||
|
||||
// Output:
|
||||
// connect
|
||||
// 1
|
||||
// connect
|
||||
// 2
|
||||
// connect
|
||||
// 3
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
// Source code and contact info at http://github.com/streadway/amqp
|
||||
|
||||
package amqp
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"io"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type pipe struct {
|
||||
r *io.PipeReader
|
||||
w *io.PipeWriter
|
||||
}
|
||||
|
||||
func (p pipe) Read(b []byte) (int, error) {
|
||||
return p.r.Read(b)
|
||||
}
|
||||
|
||||
func (p pipe) Write(b []byte) (int, error) {
|
||||
return p.w.Write(b)
|
||||
}
|
||||
|
||||
func (p pipe) Close() error {
|
||||
p.r.Close()
|
||||
p.w.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
type logIO struct {
|
||||
t *testing.T
|
||||
prefix string
|
||||
proxy io.ReadWriteCloser
|
||||
}
|
||||
|
||||
func (me *logIO) Read(p []byte) (n int, err error) {
|
||||
me.t.Logf("%s reading %d\n", me.prefix, len(p))
|
||||
n, err = me.proxy.Read(p)
|
||||
if err != nil {
|
||||
me.t.Logf("%s read %x: %v\n", me.prefix, p[0:n], err)
|
||||
} else {
|
||||
me.t.Logf("%s read:\n%s\n", me.prefix, hex.Dump(p[0:n]))
|
||||
//fmt.Printf("%s read:\n%s\n", me.prefix, hex.Dump(p[0:n]))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (me *logIO) Write(p []byte) (n int, err error) {
|
||||
me.t.Logf("%s writing %d\n", me.prefix, len(p))
|
||||
n, err = me.proxy.Write(p)
|
||||
if err != nil {
|
||||
me.t.Logf("%s write %d, %x: %v\n", me.prefix, len(p), p[0:n], err)
|
||||
} else {
|
||||
me.t.Logf("%s write %d:\n%s", me.prefix, len(p), hex.Dump(p[0:n]))
|
||||
//fmt.Printf("%s write %d:\n%s", me.prefix, len(p), hex.Dump(p[0:n]))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (me *logIO) Close() (err error) {
|
||||
err = me.proxy.Close()
|
||||
if err != nil {
|
||||
me.t.Logf("%s close : %v\n", me.prefix, err)
|
||||
} else {
|
||||
me.t.Logf("%s close\n", me.prefix, err)
|
||||
}
|
||||
return
|
||||
}
|
537
Godeps/_workspace/src/github.com/streadway/amqp/spec/amqp0-9-1.stripped.extended.xml
generated
vendored
537
Godeps/_workspace/src/github.com/streadway/amqp/spec/amqp0-9-1.stripped.extended.xml
generated
vendored
|
@ -1,537 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<!--
|
||||
WARNING: Modified from the official 0-9-1 specification XML by
|
||||
the addition of:
|
||||
confirm.select and confirm.select-ok,
|
||||
exchange.bind and exchange.bind-ok,
|
||||
exchange.unbind and exchange.unbind-ok,
|
||||
basic.nack,
|
||||
the ability for the Server to send basic.ack, basic.nack and
|
||||
basic.cancel to the client, and
|
||||
the un-deprecation of exchange.declare{auto-delete} and exchange.declare{internal}
|
||||
|
||||
Modifications are (c) 2010-2013 VMware, Inc. and may be distributed
|
||||
under the same BSD license as below.
|
||||
-->
|
||||
|
||||
<!--
|
||||
Copyright (c) 2009 AMQP Working Group.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-->
|
||||
<amqp major="0" minor="9" revision="1" port="5672">
|
||||
<constant name="frame-method" value="1"/>
|
||||
<constant name="frame-header" value="2"/>
|
||||
<constant name="frame-body" value="3"/>
|
||||
<constant name="frame-heartbeat" value="8"/>
|
||||
<constant name="frame-min-size" value="4096"/>
|
||||
<constant name="frame-end" value="206"/>
|
||||
<constant name="reply-success" value="200"/>
|
||||
<constant name="content-too-large" value="311" class="soft-error"/>
|
||||
<constant name="no-route" value="312" class = "soft-error">
|
||||
<doc>
|
||||
Errata: Section 1.2 ought to define an exception 312 "No route", which used to
|
||||
exist in 0-9 and is what RabbitMQ sends back with 'basic.return' when a
|
||||
'mandatory' message cannot be delivered to any queue.
|
||||
</doc>
|
||||
</constant>
|
||||
<constant name="no-consumers" value="313" class="soft-error"/>
|
||||
<constant name="connection-forced" value="320" class="hard-error"/>
|
||||
<constant name="invalid-path" value="402" class="hard-error"/>
|
||||
<constant name="access-refused" value="403" class="soft-error"/>
|
||||
<constant name="not-found" value="404" class="soft-error"/>
|
||||
<constant name="resource-locked" value="405" class="soft-error"/>
|
||||
<constant name="precondition-failed" value="406" class="soft-error"/>
|
||||
<constant name="frame-error" value="501" class="hard-error"/>
|
||||
<constant name="syntax-error" value="502" class="hard-error"/>
|
||||
<constant name="command-invalid" value="503" class="hard-error"/>
|
||||
<constant name="channel-error" value="504" class="hard-error"/>
|
||||
<constant name="unexpected-frame" value="505" class="hard-error"/>
|
||||
<constant name="resource-error" value="506" class="hard-error"/>
|
||||
<constant name="not-allowed" value="530" class="hard-error"/>
|
||||
<constant name="not-implemented" value="540" class="hard-error"/>
|
||||
<constant name="internal-error" value="541" class="hard-error"/>
|
||||
<domain name="class-id" type="short"/>
|
||||
<domain name="consumer-tag" type="shortstr"/>
|
||||
<domain name="delivery-tag" type="longlong"/>
|
||||
<domain name="exchange-name" type="shortstr">
|
||||
<assert check="length" value="127"/>
|
||||
<assert check="regexp" value="^[a-zA-Z0-9-_.:]*$"/>
|
||||
</domain>
|
||||
<domain name="method-id" type="short"/>
|
||||
<domain name="no-ack" type="bit"/>
|
||||
<domain name="no-local" type="bit"/>
|
||||
<domain name="no-wait" type="bit"/>
|
||||
<domain name="path" type="shortstr">
|
||||
<assert check="notnull"/>
|
||||
<assert check="length" value="127"/>
|
||||
</domain>
|
||||
<domain name="peer-properties" type="table"/>
|
||||
<domain name="queue-name" type="shortstr">
|
||||
<assert check="length" value="127"/>
|
||||
<assert check="regexp" value="^[a-zA-Z0-9-_.:]*$"/>
|
||||
</domain>
|
||||
<domain name="redelivered" type="bit"/>
|
||||
<domain name="message-count" type="long"/>
|
||||
<domain name="reply-code" type="short">
|
||||
<assert check="notnull"/>
|
||||
</domain>
|
||||
<domain name="reply-text" type="shortstr">
|
||||
<assert check="notnull"/>
|
||||
</domain>
|
||||
<domain name="bit" type="bit"/>
|
||||
<domain name="octet" type="octet"/>
|
||||
<domain name="short" type="short"/>
|
||||
<domain name="long" type="long"/>
|
||||
<domain name="longlong" type="longlong"/>
|
||||
<domain name="shortstr" type="shortstr"/>
|
||||
<domain name="longstr" type="longstr"/>
|
||||
<domain name="timestamp" type="timestamp"/>
|
||||
<domain name="table" type="table"/>
|
||||
<class name="connection" handler="connection" index="10">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<chassis name="client" implement="MUST"/>
|
||||
<method name="start" synchronous="1" index="10">
|
||||
<chassis name="client" implement="MUST"/>
|
||||
<response name="start-ok"/>
|
||||
<field name="version-major" domain="octet"/>
|
||||
<field name="version-minor" domain="octet"/>
|
||||
<field name="server-properties" domain="peer-properties"/>
|
||||
<field name="mechanisms" domain="longstr">
|
||||
<assert check="notnull"/>
|
||||
</field>
|
||||
<field name="locales" domain="longstr">
|
||||
<assert check="notnull"/>
|
||||
</field>
|
||||
</method>
|
||||
<method name="start-ok" synchronous="1" index="11">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<field name="client-properties" domain="peer-properties"/>
|
||||
<field name="mechanism" domain="shortstr">
|
||||
<assert check="notnull"/>
|
||||
</field>
|
||||
<field name="response" domain="longstr">
|
||||
<assert check="notnull"/>
|
||||
</field>
|
||||
<field name="locale" domain="shortstr">
|
||||
<assert check="notnull"/>
|
||||
</field>
|
||||
</method>
|
||||
<method name="secure" synchronous="1" index="20">
|
||||
<chassis name="client" implement="MUST"/>
|
||||
<response name="secure-ok"/>
|
||||
<field name="challenge" domain="longstr"/>
|
||||
</method>
|
||||
<method name="secure-ok" synchronous="1" index="21">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<field name="response" domain="longstr">
|
||||
<assert check="notnull"/>
|
||||
</field>
|
||||
</method>
|
||||
<method name="tune" synchronous="1" index="30">
|
||||
<chassis name="client" implement="MUST"/>
|
||||
<response name="tune-ok"/>
|
||||
<field name="channel-max" domain="short"/>
|
||||
<field name="frame-max" domain="long"/>
|
||||
<field name="heartbeat" domain="short"/>
|
||||
</method>
|
||||
<method name="tune-ok" synchronous="1" index="31">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<field name="channel-max" domain="short">
|
||||
<assert check="notnull"/>
|
||||
<assert check="le" method="tune" field="channel-max"/>
|
||||
</field>
|
||||
<field name="frame-max" domain="long"/>
|
||||
<field name="heartbeat" domain="short"/>
|
||||
</method>
|
||||
<method name="open" synchronous="1" index="40">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<response name="open-ok"/>
|
||||
<field name="virtual-host" domain="path"/>
|
||||
<field name="reserved-1" type="shortstr" reserved="1"/>
|
||||
<field name="reserved-2" type="bit" reserved="1"/>
|
||||
</method>
|
||||
<method name="open-ok" synchronous="1" index="41">
|
||||
<chassis name="client" implement="MUST"/>
|
||||
<field name="reserved-1" type="shortstr" reserved="1"/>
|
||||
</method>
|
||||
<method name="close" synchronous="1" index="50">
|
||||
<chassis name="client" implement="MUST"/>
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<response name="close-ok"/>
|
||||
<field name="reply-code" domain="reply-code"/>
|
||||
<field name="reply-text" domain="reply-text"/>
|
||||
<field name="class-id" domain="class-id"/>
|
||||
<field name="method-id" domain="method-id"/>
|
||||
</method>
|
||||
<method name="close-ok" synchronous="1" index="51">
|
||||
<chassis name="client" implement="MUST"/>
|
||||
<chassis name="server" implement="MUST"/>
|
||||
</method>
|
||||
<method name="blocked" index="60">
|
||||
<chassis name="server" implement="MAY"/>
|
||||
<field name="reason" type="shortstr"/>
|
||||
</method>
|
||||
<method name="unblocked" index="61">
|
||||
<chassis name="server" implement="MAY"/>
|
||||
</method>
|
||||
</class>
|
||||
<class name="channel" handler="channel" index="20">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<chassis name="client" implement="MUST"/>
|
||||
<method name="open" synchronous="1" index="10">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<response name="open-ok"/>
|
||||
<field name="reserved-1" type="shortstr" reserved="1"/>
|
||||
</method>
|
||||
<method name="open-ok" synchronous="1" index="11">
|
||||
<chassis name="client" implement="MUST"/>
|
||||
<field name="reserved-1" type="longstr" reserved="1"/>
|
||||
</method>
|
||||
<method name="flow" synchronous="1" index="20">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<chassis name="client" implement="MUST"/>
|
||||
<response name="flow-ok"/>
|
||||
<field name="active" domain="bit"/>
|
||||
</method>
|
||||
<method name="flow-ok" index="21">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<chassis name="client" implement="MUST"/>
|
||||
<field name="active" domain="bit"/>
|
||||
</method>
|
||||
<method name="close" synchronous="1" index="40">
|
||||
<chassis name="client" implement="MUST"/>
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<response name="close-ok"/>
|
||||
<field name="reply-code" domain="reply-code"/>
|
||||
<field name="reply-text" domain="reply-text"/>
|
||||
<field name="class-id" domain="class-id"/>
|
||||
<field name="method-id" domain="method-id"/>
|
||||
</method>
|
||||
<method name="close-ok" synchronous="1" index="41">
|
||||
<chassis name="client" implement="MUST"/>
|
||||
<chassis name="server" implement="MUST"/>
|
||||
</method>
|
||||
</class>
|
||||
<class name="exchange" handler="channel" index="40">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<chassis name="client" implement="MUST"/>
|
||||
<method name="declare" synchronous="1" index="10">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<response name="declare-ok"/>
|
||||
<field name="reserved-1" type="short" reserved="1"/>
|
||||
<field name="exchange" domain="exchange-name">
|
||||
<assert check="notnull"/>
|
||||
</field>
|
||||
<field name="type" domain="shortstr"/>
|
||||
<field name="passive" domain="bit"/>
|
||||
<field name="durable" domain="bit"/>
|
||||
<field name="auto-delete" domain="bit"/>
|
||||
<field name="internal" domain="bit"/>
|
||||
<field name="no-wait" domain="no-wait"/>
|
||||
<field name="arguments" domain="table"/>
|
||||
</method>
|
||||
<method name="declare-ok" synchronous="1" index="11">
|
||||
<chassis name="client" implement="MUST"/>
|
||||
</method>
|
||||
<method name="delete" synchronous="1" index="20">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<response name="delete-ok"/>
|
||||
<field name="reserved-1" type="short" reserved="1"/>
|
||||
<field name="exchange" domain="exchange-name">
|
||||
<assert check="notnull"/>
|
||||
</field>
|
||||
<field name="if-unused" domain="bit"/>
|
||||
<field name="no-wait" domain="no-wait"/>
|
||||
</method>
|
||||
<method name="delete-ok" synchronous="1" index="21">
|
||||
<chassis name="client" implement="MUST"/>
|
||||
</method>
|
||||
<method name="bind" synchronous="1" index="30">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<response name="bind-ok"/>
|
||||
<field name="reserved-1" type="short" reserved="1"/>
|
||||
<field name="destination" domain="exchange-name"/>
|
||||
<field name="source" domain="exchange-name"/>
|
||||
<field name="routing-key" domain="shortstr"/>
|
||||
<field name="no-wait" domain="no-wait"/>
|
||||
<field name="arguments" domain="table"/>
|
||||
</method>
|
||||
<method name="bind-ok" synchronous="1" index="31">
|
||||
<chassis name="client" implement="MUST"/>
|
||||
</method>
|
||||
<method name="unbind" synchronous="1" index="40">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<response name="unbind-ok"/>
|
||||
<field name="reserved-1" type="short" reserved="1"/>
|
||||
<field name="destination" domain="exchange-name"/>
|
||||
<field name="source" domain="exchange-name"/>
|
||||
<field name="routing-key" domain="shortstr"/>
|
||||
<field name="no-wait" domain="no-wait"/>
|
||||
<field name="arguments" domain="table"/>
|
||||
</method>
|
||||
<method name="unbind-ok" synchronous="1" index="51">
|
||||
<chassis name="client" implement="MUST"/>
|
||||
</method>
|
||||
</class>
|
||||
<class name="queue" handler="channel" index="50">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<chassis name="client" implement="MUST"/>
|
||||
<method name="declare" synchronous="1" index="10">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<response name="declare-ok"/>
|
||||
<field name="reserved-1" type="short" reserved="1"/>
|
||||
<field name="queue" domain="queue-name"/>
|
||||
<field name="passive" domain="bit"/>
|
||||
<field name="durable" domain="bit"/>
|
||||
<field name="exclusive" domain="bit"/>
|
||||
<field name="auto-delete" domain="bit"/>
|
||||
<field name="no-wait" domain="no-wait"/>
|
||||
<field name="arguments" domain="table"/>
|
||||
</method>
|
||||
<method name="declare-ok" synchronous="1" index="11">
|
||||
<chassis name="client" implement="MUST"/>
|
||||
<field name="queue" domain="queue-name">
|
||||
<assert check="notnull"/>
|
||||
</field>
|
||||
<field name="message-count" domain="message-count"/>
|
||||
<field name="consumer-count" domain="long"/>
|
||||
</method>
|
||||
<method name="bind" synchronous="1" index="20">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<response name="bind-ok"/>
|
||||
<field name="reserved-1" type="short" reserved="1"/>
|
||||
<field name="queue" domain="queue-name"/>
|
||||
<field name="exchange" domain="exchange-name"/>
|
||||
<field name="routing-key" domain="shortstr"/>
|
||||
<field name="no-wait" domain="no-wait"/>
|
||||
<field name="arguments" domain="table"/>
|
||||
</method>
|
||||
<method name="bind-ok" synchronous="1" index="21">
|
||||
<chassis name="client" implement="MUST"/>
|
||||
</method>
|
||||
<method name="unbind" synchronous="1" index="50">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<response name="unbind-ok"/>
|
||||
<field name="reserved-1" type="short" reserved="1"/>
|
||||
<field name="queue" domain="queue-name"/>
|
||||
<field name="exchange" domain="exchange-name"/>
|
||||
<field name="routing-key" domain="shortstr"/>
|
||||
<field name="arguments" domain="table"/>
|
||||
</method>
|
||||
<method name="unbind-ok" synchronous="1" index="51">
|
||||
<chassis name="client" implement="MUST"/>
|
||||
</method>
|
||||
<method name="purge" synchronous="1" index="30">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<response name="purge-ok"/>
|
||||
<field name="reserved-1" type="short" reserved="1"/>
|
||||
<field name="queue" domain="queue-name"/>
|
||||
<field name="no-wait" domain="no-wait"/>
|
||||
</method>
|
||||
<method name="purge-ok" synchronous="1" index="31">
|
||||
<chassis name="client" implement="MUST"/>
|
||||
<field name="message-count" domain="message-count"/>
|
||||
</method>
|
||||
<method name="delete" synchronous="1" index="40">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<response name="delete-ok"/>
|
||||
<field name="reserved-1" type="short" reserved="1"/>
|
||||
<field name="queue" domain="queue-name"/>
|
||||
<field name="if-unused" domain="bit"/>
|
||||
<field name="if-empty" domain="bit"/>
|
||||
<field name="no-wait" domain="no-wait"/>
|
||||
</method>
|
||||
<method name="delete-ok" synchronous="1" index="41">
|
||||
<chassis name="client" implement="MUST"/>
|
||||
<field name="message-count" domain="message-count"/>
|
||||
</method>
|
||||
</class>
|
||||
<class name="basic" handler="channel" index="60">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<chassis name="client" implement="MAY"/>
|
||||
<field name="content-type" domain="shortstr"/>
|
||||
<field name="content-encoding" domain="shortstr"/>
|
||||
<field name="headers" domain="table"/>
|
||||
<field name="delivery-mode" domain="octet"/>
|
||||
<field name="priority" domain="octet"/>
|
||||
<field name="correlation-id" domain="shortstr"/>
|
||||
<field name="reply-to" domain="shortstr"/>
|
||||
<field name="expiration" domain="shortstr"/>
|
||||
<field name="message-id" domain="shortstr"/>
|
||||
<field name="timestamp" domain="timestamp"/>
|
||||
<field name="type" domain="shortstr"/>
|
||||
<field name="user-id" domain="shortstr"/>
|
||||
<field name="app-id" domain="shortstr"/>
|
||||
<field name="reserved" domain="shortstr"/>
|
||||
<method name="qos" synchronous="1" index="10">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<response name="qos-ok"/>
|
||||
<field name="prefetch-size" domain="long"/>
|
||||
<field name="prefetch-count" domain="short"/>
|
||||
<field name="global" domain="bit"/>
|
||||
</method>
|
||||
<method name="qos-ok" synchronous="1" index="11">
|
||||
<chassis name="client" implement="MUST"/>
|
||||
</method>
|
||||
<method name="consume" synchronous="1" index="20">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<response name="consume-ok"/>
|
||||
<field name="reserved-1" type="short" reserved="1"/>
|
||||
<field name="queue" domain="queue-name"/>
|
||||
<field name="consumer-tag" domain="consumer-tag"/>
|
||||
<field name="no-local" domain="no-local"/>
|
||||
<field name="no-ack" domain="no-ack"/>
|
||||
<field name="exclusive" domain="bit"/>
|
||||
<field name="no-wait" domain="no-wait"/>
|
||||
<field name="arguments" domain="table"/>
|
||||
</method>
|
||||
<method name="consume-ok" synchronous="1" index="21">
|
||||
<chassis name="client" implement="MUST"/>
|
||||
<field name="consumer-tag" domain="consumer-tag"/>
|
||||
</method>
|
||||
<method name="cancel" synchronous="1" index="30">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<chassis name="client" implement="SHOULD"/>
|
||||
<response name="cancel-ok"/>
|
||||
<field name="consumer-tag" domain="consumer-tag"/>
|
||||
<field name="no-wait" domain="no-wait"/>
|
||||
</method>
|
||||
<method name="cancel-ok" synchronous="1" index="31">
|
||||
<chassis name="client" implement="MUST"/>
|
||||
<chassis name="server" implement="MAY"/>
|
||||
<field name="consumer-tag" domain="consumer-tag"/>
|
||||
</method>
|
||||
<method name="publish" content="1" index="40">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<field name="reserved-1" type="short" reserved="1"/>
|
||||
<field name="exchange" domain="exchange-name"/>
|
||||
<field name="routing-key" domain="shortstr"/>
|
||||
<field name="mandatory" domain="bit"/>
|
||||
<field name="immediate" domain="bit"/>
|
||||
</method>
|
||||
<method name="return" content="1" index="50">
|
||||
<chassis name="client" implement="MUST"/>
|
||||
<field name="reply-code" domain="reply-code"/>
|
||||
<field name="reply-text" domain="reply-text"/>
|
||||
<field name="exchange" domain="exchange-name"/>
|
||||
<field name="routing-key" domain="shortstr"/>
|
||||
</method>
|
||||
<method name="deliver" content="1" index="60">
|
||||
<chassis name="client" implement="MUST"/>
|
||||
<field name="consumer-tag" domain="consumer-tag"/>
|
||||
<field name="delivery-tag" domain="delivery-tag"/>
|
||||
<field name="redelivered" domain="redelivered"/>
|
||||
<field name="exchange" domain="exchange-name"/>
|
||||
<field name="routing-key" domain="shortstr"/>
|
||||
</method>
|
||||
<method name="get" synchronous="1" index="70">
|
||||
<response name="get-ok"/>
|
||||
<response name="get-empty"/>
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<field name="reserved-1" type="short" reserved="1"/>
|
||||
<field name="queue" domain="queue-name"/>
|
||||
<field name="no-ack" domain="no-ack"/>
|
||||
</method>
|
||||
<method name="get-ok" synchronous="1" content="1" index="71">
|
||||
<chassis name="client" implement="MAY"/>
|
||||
<field name="delivery-tag" domain="delivery-tag"/>
|
||||
<field name="redelivered" domain="redelivered"/>
|
||||
<field name="exchange" domain="exchange-name"/>
|
||||
<field name="routing-key" domain="shortstr"/>
|
||||
<field name="message-count" domain="message-count"/>
|
||||
</method>
|
||||
<method name="get-empty" synchronous="1" index="72">
|
||||
<chassis name="client" implement="MAY"/>
|
||||
<field name="reserved-1" type="shortstr" reserved="1"/>
|
||||
</method>
|
||||
<method name="ack" index="80">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<chassis name="client" implement="MUST"/>
|
||||
<field name="delivery-tag" domain="delivery-tag"/>
|
||||
<field name="multiple" domain="bit"/>
|
||||
</method>
|
||||
<method name="reject" index="90">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<field name="delivery-tag" domain="delivery-tag"/>
|
||||
<field name="requeue" domain="bit"/>
|
||||
</method>
|
||||
<method name="recover-async" index="100" deprecated="1">
|
||||
<chassis name="server" implement="MAY"/>
|
||||
<field name="requeue" domain="bit"/>
|
||||
</method>
|
||||
<method name="recover" synchronous="1" index="110">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<field name="requeue" domain="bit"/>
|
||||
</method>
|
||||
<method name="recover-ok" synchronous="1" index="111">
|
||||
<chassis name="client" implement="MUST"/>
|
||||
</method>
|
||||
<method name="nack" index="120">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<chassis name="client" implement="MUST"/>
|
||||
<field name="delivery-tag" domain="delivery-tag"/>
|
||||
<field name="multiple" domain="bit"/>
|
||||
<field name="requeue" domain="bit"/>
|
||||
</method>
|
||||
</class>
|
||||
<class name="tx" handler="channel" index="90">
|
||||
<chassis name="server" implement="SHOULD"/>
|
||||
<chassis name="client" implement="MAY"/>
|
||||
<method name="select" synchronous="1" index="10">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<response name="select-ok"/>
|
||||
</method>
|
||||
<method name="select-ok" synchronous="1" index="11">
|
||||
<chassis name="client" implement="MUST"/>
|
||||
</method>
|
||||
<method name="commit" synchronous="1" index="20">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<response name="commit-ok"/>
|
||||
</method>
|
||||
<method name="commit-ok" synchronous="1" index="21">
|
||||
<chassis name="client" implement="MUST"/>
|
||||
</method>
|
||||
<method name="rollback" synchronous="1" index="30">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<response name="rollback-ok"/>
|
||||
</method>
|
||||
<method name="rollback-ok" synchronous="1" index="31">
|
||||
<chassis name="client" implement="MUST"/>
|
||||
</method>
|
||||
</class>
|
||||
<class name="confirm" handler="channel" index="85">
|
||||
<chassis name="server" implement="SHOULD"/>
|
||||
<chassis name="client" implement="MAY"/>
|
||||
<method name="select" synchronous="1" index="10">
|
||||
<chassis name="server" implement="MUST"/>
|
||||
<response name="select-ok"/>
|
||||
<field name="nowait" type="bit"/>
|
||||
</method>
|
||||
<method name="select-ok" synchronous="1" index="11">
|
||||
<chassis name="client" implement="MUST"/>
|
||||
</method>
|
||||
</class>
|
||||
</amqp>
|
|
@ -1,536 +0,0 @@
|
|||
// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
// Source code and contact info at http://github.com/streadway/amqp
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrUnknownType = errors.New("Unknown field type in gen")
|
||||
ErrUnknownDomain = errors.New("Unknown domain type in gen")
|
||||
)
|
||||
|
||||
var amqpTypeToNative = map[string]string{
|
||||
"bit": "bool",
|
||||
"octet": "byte",
|
||||
"shortshort": "uint8",
|
||||
"short": "uint16",
|
||||
"long": "uint32",
|
||||
"longlong": "uint64",
|
||||
"timestamp": "time.Time",
|
||||
"table": "Table",
|
||||
"shortstr": "string",
|
||||
"longstr": "string",
|
||||
}
|
||||
|
||||
type Rule struct {
|
||||
Name string `xml:"name,attr"`
|
||||
Docs []string `xml:"doc"`
|
||||
}
|
||||
|
||||
type Doc struct {
|
||||
Type string `xml:"type,attr"`
|
||||
Body string `xml:",innerxml"`
|
||||
}
|
||||
|
||||
type Chassis struct {
|
||||
Name string `xml:"name,attr"`
|
||||
Implement string `xml:"implement,attr"`
|
||||
}
|
||||
|
||||
type Assert struct {
|
||||
Check string `xml:"check,attr"`
|
||||
Value string `xml:"value,attr"`
|
||||
Method string `xml:"method,attr"`
|
||||
}
|
||||
|
||||
type Field struct {
|
||||
Name string `xml:"name,attr"`
|
||||
Domain string `xml:"domain,attr"`
|
||||
Type string `xml:"type,attr"`
|
||||
Label string `xml:"label,attr"`
|
||||
Reserved bool `xml:"reserved,attr"`
|
||||
Docs []Doc `xml:"doc"`
|
||||
Asserts []Assert `xml:"assert"`
|
||||
}
|
||||
|
||||
type Response struct {
|
||||
Name string `xml:"name,attr"`
|
||||
}
|
||||
|
||||
type Method struct {
|
||||
Name string `xml:"name,attr"`
|
||||
Response Response `xml:"response"`
|
||||
Synchronous bool `xml:"synchronous,attr"`
|
||||
Content bool `xml:"content,attr"`
|
||||
Index string `xml:"index,attr"`
|
||||
Label string `xml:"label,attr"`
|
||||
Docs []Doc `xml:"doc"`
|
||||
Rules []Rule `xml:"rule"`
|
||||
Fields []Field `xml:"field"`
|
||||
Chassis []Chassis `xml:"chassis"`
|
||||
}
|
||||
|
||||
type Class struct {
|
||||
Name string `xml:"name,attr"`
|
||||
Handler string `xml:"handler,attr"`
|
||||
Index string `xml:"index,attr"`
|
||||
Label string `xml:"label,attr"`
|
||||
Docs []Doc `xml:"doc"`
|
||||
Methods []Method `xml:"method"`
|
||||
Chassis []Chassis `xml:"chassis"`
|
||||
}
|
||||
|
||||
type Domain struct {
|
||||
Name string `xml:"name,attr"`
|
||||
Type string `xml:"type,attr"`
|
||||
Label string `xml:"label,attr"`
|
||||
Rules []Rule `xml:"rule"`
|
||||
Docs []Doc `xml:"doc"`
|
||||
}
|
||||
|
||||
type Constant struct {
|
||||
Name string `xml:"name,attr"`
|
||||
Value int `xml:"value,attr"`
|
||||
Class string `xml:"class,attr"`
|
||||
Doc string `xml:"doc"`
|
||||
}
|
||||
|
||||
type Amqp struct {
|
||||
Major int `xml:"major,attr"`
|
||||
Minor int `xml:"minor,attr"`
|
||||
Port int `xml:"port,attr"`
|
||||
Comment string `xml:"comment,attr"`
|
||||
|
||||
Constants []Constant `xml:"constant"`
|
||||
Domains []Domain `xml:"domain"`
|
||||
Classes []Class `xml:"class"`
|
||||
}
|
||||
|
||||
type renderer struct {
|
||||
Root Amqp
|
||||
bitcounter int
|
||||
}
|
||||
|
||||
type fieldset struct {
|
||||
AmqpType string
|
||||
NativeType string
|
||||
Fields []Field
|
||||
*renderer
|
||||
}
|
||||
|
||||
var (
|
||||
helpers = template.FuncMap{
|
||||
"public": public,
|
||||
"private": private,
|
||||
"clean": clean,
|
||||
}
|
||||
|
||||
packageTemplate = template.Must(template.New("package").Funcs(helpers).Parse(`
|
||||
// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
// Source code and contact info at http://github.com/streadway/amqp
|
||||
|
||||
/* GENERATED FILE - DO NOT EDIT */
|
||||
/* Rebuild from the spec/gen.go tool */
|
||||
|
||||
{{with .Root}}
|
||||
package amqp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Error codes that can be sent from the server during a connection or
|
||||
// channel exception or used by the client to indicate a class of error like
|
||||
// ErrCredentials. The text of the error is likely more interesting than
|
||||
// these constants.
|
||||
const (
|
||||
{{range $c := .Constants}}
|
||||
{{if $c.IsError}}{{.Name | public}}{{else}}{{.Name | private}}{{end}} = {{.Value}}{{end}}
|
||||
)
|
||||
|
||||
func isSoftExceptionCode(code int) bool {
|
||||
switch code {
|
||||
{{range $c := .Constants}} {{if $c.IsSoftError}} case {{$c.Value}}:
|
||||
return true
|
||||
{{end}}{{end}}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
{{range .Classes}}
|
||||
{{$class := .}}
|
||||
{{range .Methods}}
|
||||
{{$method := .}}
|
||||
{{$struct := $.StructName $class.Name $method.Name}}
|
||||
{{if .Docs}}/* {{range .Docs}} {{.Body | clean}} {{end}} */{{end}}
|
||||
type {{$struct}} struct {
|
||||
{{range .Fields}}
|
||||
{{$.FieldName .}} {{$.FieldType . | $.NativeType}} {{if .Label}}// {{.Label}}{{end}}{{end}}
|
||||
{{if .Content}}Properties properties
|
||||
Body []byte{{end}}
|
||||
}
|
||||
|
||||
func (me *{{$struct}}) id() (uint16, uint16) {
|
||||
return {{$class.Index}}, {{$method.Index}}
|
||||
}
|
||||
|
||||
func (me *{{$struct}}) wait() (bool) {
|
||||
return {{.Synchronous}}{{if $.HasField "NoWait" .}} && !me.NoWait{{end}}
|
||||
}
|
||||
|
||||
{{if .Content}}
|
||||
func (me *{{$struct}}) getContent() (properties, []byte) {
|
||||
return me.Properties, me.Body
|
||||
}
|
||||
|
||||
func (me *{{$struct}}) setContent(props properties, body []byte) {
|
||||
me.Properties, me.Body = props, body
|
||||
}
|
||||
{{end}}
|
||||
func (me *{{$struct}}) write(w io.Writer) (err error) {
|
||||
{{if $.HasType "bit" $method}}var bits byte{{end}}
|
||||
{{.Fields | $.Fieldsets | $.Partial "enc-"}}
|
||||
return
|
||||
}
|
||||
|
||||
func (me *{{$struct}}) read(r io.Reader) (err error) {
|
||||
{{if $.HasType "bit" $method}}var bits byte{{end}}
|
||||
{{.Fields | $.Fieldsets | $.Partial "dec-"}}
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
func (me *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err error) {
|
||||
mf := &methodFrame {
|
||||
ChannelId: channel,
|
||||
}
|
||||
|
||||
if err = binary.Read(me.r, binary.BigEndian, &mf.ClassId); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = binary.Read(me.r, binary.BigEndian, &mf.MethodId); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
switch mf.ClassId {
|
||||
{{range .Classes}}
|
||||
{{$class := .}}
|
||||
case {{.Index}}: // {{.Name}}
|
||||
switch mf.MethodId {
|
||||
{{range .Methods}}
|
||||
case {{.Index}}: // {{$class.Name}} {{.Name}}
|
||||
//fmt.Println("NextMethod: class:{{$class.Index}} method:{{.Index}}")
|
||||
method := &{{$.StructName $class.Name .Name}}{}
|
||||
if err = method.read(me.r); err != nil {
|
||||
return
|
||||
}
|
||||
mf.Method = method
|
||||
{{end}}
|
||||
default:
|
||||
return nil, fmt.Errorf("Bad method frame, unknown method %d for class %d", mf.MethodId, mf.ClassId)
|
||||
}
|
||||
{{end}}
|
||||
default:
|
||||
return nil, fmt.Errorf("Bad method frame, unknown class %d", mf.ClassId)
|
||||
}
|
||||
|
||||
return mf, nil
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{define "enc-bit"}}
|
||||
{{range $off, $field := .Fields}}
|
||||
if me.{{$field | $.FieldName}} { bits |= 1 << {{$off}} }
|
||||
{{end}}
|
||||
if err = binary.Write(w, binary.BigEndian, bits); err != nil { return }
|
||||
{{end}}
|
||||
{{define "enc-octet"}}
|
||||
{{range .Fields}} if err = binary.Write(w, binary.BigEndian, me.{{. | $.FieldName}}); err != nil { return }
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{define "enc-shortshort"}}
|
||||
{{range .Fields}} if err = binary.Write(w, binary.BigEndian, me.{{. | $.FieldName}}); err != nil { return }
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{define "enc-short"}}
|
||||
{{range .Fields}} if err = binary.Write(w, binary.BigEndian, me.{{. | $.FieldName}}); err != nil { return }
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{define "enc-long"}}
|
||||
{{range .Fields}} if err = binary.Write(w, binary.BigEndian, me.{{. | $.FieldName}}); err != nil { return }
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{define "enc-longlong"}}
|
||||
{{range .Fields}} if err = binary.Write(w, binary.BigEndian, me.{{. | $.FieldName}}); err != nil { return }
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{define "enc-timestamp"}}
|
||||
{{range .Fields}} if err = writeTimestamp(w, me.{{. | $.FieldName}}); err != nil { return }
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{define "enc-shortstr"}}
|
||||
{{range .Fields}} if err = writeShortstr(w, me.{{. | $.FieldName}}); err != nil { return }
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{define "enc-longstr"}}
|
||||
{{range .Fields}} if err = writeLongstr(w, me.{{. | $.FieldName}}); err != nil { return }
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{define "enc-table"}}
|
||||
{{range .Fields}} if err = writeTable(w, me.{{. | $.FieldName}}); err != nil { return }
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{define "dec-bit"}}
|
||||
if err = binary.Read(r, binary.BigEndian, &bits); err != nil {
|
||||
return
|
||||
}
|
||||
{{range $off, $field := .Fields}} me.{{$field | $.FieldName}} = (bits & (1 << {{$off}}) > 0)
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{define "dec-octet"}}
|
||||
{{range .Fields}} if err = binary.Read(r, binary.BigEndian, &me.{{. | $.FieldName}}); err != nil { return }
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{define "dec-shortshort"}}
|
||||
{{range .Fields}} if err = binary.Read(r, binary.BigEndian, &me.{{. | $.FieldName}}); err != nil { return }
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{define "dec-short"}}
|
||||
{{range .Fields}} if err = binary.Read(r, binary.BigEndian, &me.{{. | $.FieldName}}); err != nil { return }
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{define "dec-long"}}
|
||||
{{range .Fields}} if err = binary.Read(r, binary.BigEndian, &me.{{. | $.FieldName}}); err != nil { return }
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{define "dec-longlong"}}
|
||||
{{range .Fields}} if err = binary.Read(r, binary.BigEndian, &me.{{. | $.FieldName}}); err != nil { return }
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{define "dec-timestamp"}}
|
||||
{{range .Fields}} if me.{{. | $.FieldName}}, err = readTimestamp(r); err != nil { return }
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{define "dec-shortstr"}}
|
||||
{{range .Fields}} if me.{{. | $.FieldName}}, err = readShortstr(r); err != nil { return }
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{define "dec-longstr"}}
|
||||
{{range .Fields}} if me.{{. | $.FieldName}}, err = readLongstr(r); err != nil { return }
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{define "dec-table"}}
|
||||
{{range .Fields}} if me.{{. | $.FieldName}}, err = readTable(r); err != nil { return }
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
`))
|
||||
)
|
||||
|
||||
func (me *Constant) IsError() bool {
|
||||
return strings.Contains(me.Class, "error")
|
||||
}
|
||||
|
||||
func (me *Constant) IsSoftError() bool {
|
||||
return me.Class == "soft-error"
|
||||
}
|
||||
|
||||
func (me *renderer) Partial(prefix string, fields []fieldset) (s string, err error) {
|
||||
var buf bytes.Buffer
|
||||
for _, set := range fields {
|
||||
name := prefix + set.AmqpType
|
||||
t := packageTemplate.Lookup(name)
|
||||
if t == nil {
|
||||
return "", errors.New(fmt.Sprintf("Missing template: %s", name))
|
||||
}
|
||||
if err = t.Execute(&buf, set); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return string(buf.Bytes()), nil
|
||||
}
|
||||
|
||||
// Groups the fields so that the right encoder/decoder can be called
|
||||
func (me *renderer) Fieldsets(fields []Field) (f []fieldset, err error) {
|
||||
if len(fields) > 0 {
|
||||
for _, field := range fields {
|
||||
cur := fieldset{}
|
||||
cur.AmqpType, err = me.FieldType(field)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
cur.NativeType, err = me.NativeType(cur.AmqpType)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
cur.Fields = append(cur.Fields, field)
|
||||
f = append(f, cur)
|
||||
}
|
||||
|
||||
i, j := 0, 1
|
||||
for j < len(f) {
|
||||
if f[i].AmqpType == f[j].AmqpType {
|
||||
f[i].Fields = append(f[i].Fields, f[j].Fields...)
|
||||
} else {
|
||||
i++
|
||||
f[i] = f[j]
|
||||
}
|
||||
j++
|
||||
}
|
||||
return f[:i+1], nil
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (me *renderer) HasType(typ string, method Method) bool {
|
||||
for _, f := range method.Fields {
|
||||
name, _ := me.FieldType(f)
|
||||
if name == typ {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (me *renderer) HasField(field string, method Method) bool {
|
||||
for _, f := range method.Fields {
|
||||
name := me.FieldName(f)
|
||||
if name == field {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (me *renderer) Domain(field Field) (domain Domain, err error) {
|
||||
for _, domain = range me.Root.Domains {
|
||||
if field.Domain == domain.Name {
|
||||
return
|
||||
}
|
||||
}
|
||||
return domain, nil
|
||||
//return domain, ErrUnknownDomain
|
||||
}
|
||||
|
||||
func (me *renderer) FieldName(field Field) (t string) {
|
||||
t = public(field.Name)
|
||||
|
||||
if field.Reserved {
|
||||
t = strings.ToLower(t)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (me *renderer) FieldType(field Field) (t string, err error) {
|
||||
t = field.Type
|
||||
|
||||
if t == "" {
|
||||
var domain Domain
|
||||
domain, err = me.Domain(field)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
t = domain.Type
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (me *renderer) NativeType(amqpType string) (t string, err error) {
|
||||
if t, ok := amqpTypeToNative[amqpType]; ok {
|
||||
return t, nil
|
||||
}
|
||||
return "", ErrUnknownType
|
||||
}
|
||||
|
||||
func (me *renderer) Tag(d Domain) string {
|
||||
label := "`"
|
||||
|
||||
label += `domain:"` + d.Name + `"`
|
||||
|
||||
if len(d.Type) > 0 {
|
||||
label += `,type:"` + d.Type + `"`
|
||||
}
|
||||
|
||||
label += "`"
|
||||
|
||||
return label
|
||||
}
|
||||
|
||||
func (me *renderer) StructName(parts ...string) string {
|
||||
return parts[0] + public(parts[1:]...)
|
||||
}
|
||||
|
||||
func clean(body string) (res string) {
|
||||
return strings.Replace(body, "\r", "", -1)
|
||||
}
|
||||
|
||||
func private(parts ...string) string {
|
||||
return export(regexp.MustCompile(`[-_]\w`), parts...)
|
||||
}
|
||||
|
||||
func public(parts ...string) string {
|
||||
return export(regexp.MustCompile(`^\w|[-_]\w`), parts...)
|
||||
}
|
||||
|
||||
func export(delim *regexp.Regexp, parts ...string) (res string) {
|
||||
for _, in := range parts {
|
||||
|
||||
res += delim.ReplaceAllStringFunc(in, func(match string) string {
|
||||
switch len(match) {
|
||||
case 1:
|
||||
return strings.ToUpper(match)
|
||||
case 2:
|
||||
return strings.ToUpper(match[1:])
|
||||
}
|
||||
panic("unreachable")
|
||||
})
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func main() {
|
||||
var r renderer
|
||||
|
||||
spec, err := ioutil.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
log.Fatalln("Please pass spec on stdin", err)
|
||||
}
|
||||
|
||||
err = xml.Unmarshal(spec, &r.Root)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalln("Could not parse XML:", err)
|
||||
}
|
||||
|
||||
if err = packageTemplate.Execute(os.Stdout, &r); err != nil {
|
||||
log.Fatalln("Generate error: ", err)
|
||||
}
|
||||
}
|
|
@ -1,218 +0,0 @@
|
|||
package amqp_test
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/streadway/amqp"
|
||||
"io"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
type tlsServer struct {
|
||||
net.Listener
|
||||
URL string
|
||||
Config *tls.Config
|
||||
Header chan []byte
|
||||
}
|
||||
|
||||
// Captures the header for each accepted connection
|
||||
func (s *tlsServer) Serve() {
|
||||
for {
|
||||
c, err := s.Accept()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
header := make([]byte, 4)
|
||||
io.ReadFull(c, header)
|
||||
s.Header <- header
|
||||
c.Write([]byte{'A', 'M', 'Q', 'P', 0, 0, 0, 0})
|
||||
c.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func tlsConfig() *tls.Config {
|
||||
cfg := new(tls.Config)
|
||||
|
||||
cfg.ClientCAs = x509.NewCertPool()
|
||||
cfg.ClientCAs.AppendCertsFromPEM([]byte(caCert))
|
||||
|
||||
cert, err := tls.X509KeyPair([]byte(serverCert), []byte(serverKey))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
cfg.Certificates = append(cfg.Certificates, cert)
|
||||
cfg.ClientAuth = tls.RequireAndVerifyClientCert
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
func startTlsServer() tlsServer {
|
||||
cfg := tlsConfig()
|
||||
|
||||
l, err := tls.Listen("tcp", "127.0.0.1:0", cfg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
s := tlsServer{
|
||||
Listener: l,
|
||||
Config: cfg,
|
||||
URL: fmt.Sprintf("amqps://%s/", l.Addr().String()),
|
||||
Header: make(chan []byte, 1),
|
||||
}
|
||||
|
||||
go s.Serve()
|
||||
return s
|
||||
}
|
||||
|
||||
// Tests that the server has handshaked the connection and seen the client
|
||||
// protocol announcement. Does not nest that the connection.open is successful.
|
||||
func TestTLSHandshake(t *testing.T) {
|
||||
srv := startTlsServer()
|
||||
defer srv.Close()
|
||||
|
||||
cfg := new(tls.Config)
|
||||
cfg.RootCAs = x509.NewCertPool()
|
||||
cfg.RootCAs.AppendCertsFromPEM([]byte(caCert))
|
||||
|
||||
cert, _ := tls.X509KeyPair([]byte(clientCert), []byte(clientKey))
|
||||
cfg.Certificates = append(cfg.Certificates, cert)
|
||||
|
||||
_, err := amqp.DialTLS(srv.URL, cfg)
|
||||
|
||||
select {
|
||||
case <-time.After(10 * time.Millisecond):
|
||||
t.Fatalf("did not succeed to handshake the TLS connection after 10ms")
|
||||
case header := <-srv.Header:
|
||||
if string(header) != "AMQP" {
|
||||
t.Fatalf("expected to handshake a TLS connection, got err: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const caCert = `
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICxjCCAa6gAwIBAgIJANWuMWMQSxvdMA0GCSqGSIb3DQEBBQUAMBMxETAPBgNV
|
||||
BAMTCE15VGVzdENBMB4XDTE0MDEyNzE5NTIyMloXDTI0MDEyNTE5NTIyMlowEzER
|
||||
MA8GA1UEAxMITXlUZXN0Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
|
||||
AQDBsIrkW4ob9Z/gzR2/Maa2stbutry6/vvz8eiJwIKIbaHGwqtFOUGiWeKw7H76
|
||||
IH3SjTAhNQY2hoKPyH41D36sDJkYBRyHFJTK/6ffvOhpyLnuXJAnoS62eKPSNUAx
|
||||
5i/lkHj42ESutYAH9qbHCI/gBm9G4WmhGAyA16xzC1n07JObl6KFoY1PqHKl823z
|
||||
mvF47I24DzemEfjdwC9nAAX/pGYOg9FA9nQv7NnhlsJMxueCx55RNU1ADRoqsbfE
|
||||
T0CQTOT4ryugGrUp9J4Cwen6YbXZrS6+Kff5SQCAns0Qu8/bwj0DKkuBGLF+Mnwe
|
||||
mq9bMzyZPUrPM3Gu48ao8YAfAgMBAAGjHTAbMAwGA1UdEwQFMAMBAf8wCwYDVR0P
|
||||
BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQCBwXGblRxIEOlEP6ANZ1C8AHWyG8lR
|
||||
CQduFclc0tmyCCz5fnyLK0aGu9LhXXe6/HSKqgs4mJqeqYOojdjkfOme/YdwDzjK
|
||||
WIf0kRYQHcB6NeyEZwW8C7subTP1Xw6zbAmjvQrtCGvRM+fi3/cs1sSSkd/EoRk4
|
||||
7GM9qQl/JIIoCOGncninf2NQm5YSpbit6/mOQD7EhqXsw+bX+IRh3DHC1Apv/PoA
|
||||
HlDNeM4vjWaBxsmvRSndrIvew1czboFM18oRSSIqAkU7dKZ0SbC11grzmNxMG2aD
|
||||
f9y8FIG6RK/SEaOZuc+uBGXx7tj7dczpE/2puqYcaVGwcv4kkrC/ZuRm
|
||||
-----END CERTIFICATE-----
|
||||
`
|
||||
|
||||
const serverCert = `
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIC8zCCAdugAwIBAgIBATANBgkqhkiG9w0BAQUFADATMREwDwYDVQQDEwhNeVRl
|
||||
c3RDQTAeFw0xNDAxMjcxOTUyMjNaFw0yNDAxMjUxOTUyMjNaMCUxEjAQBgNVBAMT
|
||||
CTEyNy4wLjAuMTEPMA0GA1UEChMGc2VydmVyMIIBIjANBgkqhkiG9w0BAQEFAAOC
|
||||
AQ8AMIIBCgKCAQEAxYAKbeGyg0gP0xwVsZsufzk/SUCtD44Gp3lQYQ9QumQ1IVZu
|
||||
PmZWwPWrzI93a1Abruz6ZhXaB3jcL5QPAy1N44IiFgVN45CZXBsqkpJe/abzRFOV
|
||||
DRnHxattPDHdgwML5d3nURKGUM/7+ACj5E4pZEDlM3RIjIKVd+doJsL7n6myO8FE
|
||||
tIpt4vTz1MFp3F+ntPnHU3BZ/VZ1UjSlFWnCjT0CR0tnXsPmlIaC98HThS8x5zNB
|
||||
fvvSN+Zln8RWdNLnEVHVdqYtOQ828QbCx8s1HfClGgaVoSDrzz+qQgtZFO4wW264
|
||||
2CWkNd8DSJUJ/HlPNXmbXsrRMgvGaL7YUz2yRQIDAQABo0AwPjAJBgNVHRMEAjAA
|
||||
MAsGA1UdDwQEAwIFIDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHREECDAGhwR/
|
||||
AAABMA0GCSqGSIb3DQEBBQUAA4IBAQAE2g+wAFf9Xg5svcnb7+mfseYV16k9l5WG
|
||||
onrmR3FLsbTxfbr4PZJMHrswPbi2NRk0+ETPUpcv1RP7pUB7wSEvuS1NPGcU92iP
|
||||
58ycP3dYtLzmuu6BkgToZqwsCU8fC2zM0wt3+ifzPpDMffWWOioVuA3zdM9WPQYz
|
||||
+Ofajd0XaZwFZS8uTI5WXgObz7Xqfmln4tF3Sq1CTyuJ44qK4p83XOKFq+L04aD0
|
||||
d0c8w3YQNUENny/vMP9mDu3FQ3SnDz2GKl1LSjGe2TUnkoMkDfdk4wSzndTz/ecb
|
||||
QiCPKijwVPWNOWV3NDE2edMxDPxDoKoEm5F4UGfGjxSRnYCIoZLh
|
||||
-----END CERTIFICATE-----
|
||||
`
|
||||
|
||||
const serverKey = `
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAxYAKbeGyg0gP0xwVsZsufzk/SUCtD44Gp3lQYQ9QumQ1IVZu
|
||||
PmZWwPWrzI93a1Abruz6ZhXaB3jcL5QPAy1N44IiFgVN45CZXBsqkpJe/abzRFOV
|
||||
DRnHxattPDHdgwML5d3nURKGUM/7+ACj5E4pZEDlM3RIjIKVd+doJsL7n6myO8FE
|
||||
tIpt4vTz1MFp3F+ntPnHU3BZ/VZ1UjSlFWnCjT0CR0tnXsPmlIaC98HThS8x5zNB
|
||||
fvvSN+Zln8RWdNLnEVHVdqYtOQ828QbCx8s1HfClGgaVoSDrzz+qQgtZFO4wW264
|
||||
2CWkNd8DSJUJ/HlPNXmbXsrRMgvGaL7YUz2yRQIDAQABAoIBAGsyEvcPAGg3DbfE
|
||||
z5WFp9gPx2TIAOanbL8rnlAAEw4H47qDgfTGcSHsdeHioKuTYGMyZrpP8/YISGJe
|
||||
l0NfLJ5mfH+9Q0hXrJWMfS/u2DYOjo0wXH8u1fpZEEISwqsgVS3fonSjfFmSea1j
|
||||
E5GQRvEONBkYbWQuYFgjNqmLPS2r5lKbWCQvc1MB/vvVBwOTiO0ON7m/EkM5RKt9
|
||||
cDT5ZhhVjBpdmd9HpVbKTdBj8Q0l5/ZHZUEgZA6FDZEwYxTd9l87Z4YT+5SR0z9t
|
||||
k8/Z0CHd3x3Rv891t7m66ZJkaOda8NC65/432MQEQwJltmrKnc22dS8yI26rrmpp
|
||||
g3tcbSUCgYEA5nMXdQKS4vF+Kp10l/HqvGz2sU8qQaWYZQIg7Th3QJPo6N52po/s
|
||||
nn3UF0P5mT1laeZ5ZQJKx4gnmuPnIZ2ZtJQDyFhIbRPcZ+2hSNSuLYVcrumOC3EP
|
||||
3OZyFtFE1THO73aFe5e1jEdtoOne3Bds/Hq6NF45fkVdL+M9e8pfXIsCgYEA22W8
|
||||
zGjbWyrFOYvKknMQVtHnMx8BJEtsvWRknP6CWAv/8WyeZpE128Pve1m441AQnopS
|
||||
CuOF5wFK0iUXBFbS3Pe1/1j3em6yfVznuUHqJ7Qc+dNzxVvkTK8jGB6x+vm+M9Hg
|
||||
muHUM726IUxckoSNXbPNAVPIZab1NdSxam7F9m8CgYEAx55QZmIJXJ41XLKxqWC7
|
||||
peZ5NpPNlbncrTpPzUzJN94ntXfmrVckbxGt401VayEctMQYyZ9XqUlOjUP3FU5Q
|
||||
M3S3Zhba/eljVX8o406fZf0MkNLs4QpZ5E6V6x/xEP+pMhKng6yhbVb+JpIPIvUD
|
||||
yhyBKRWplbB+DRo5Sv685gsCgYA7l5m9h+m1DJv/cnn2Z2yTuHXtC8namuYRV1iA
|
||||
0ByFX9UINXGc+GpBpCnDPm6ax5+MAJQiQwSW52H0TIDA+/hQbrQvhHHL/o9av8Zt
|
||||
Kns4h5KrRQUYIUqUjamhnozHV9iS6LnyN87Usv8AlmY6oehoADN53dD702qdUYVT
|
||||
HH2G3wKBgCdvqyw78FR/n8cUWesTPnxx5HCeWJ1J+2BESnUnPmKZ71CV1H7uweja
|
||||
vPUxuuuGLKfNx84OKCfRDbtOgMOeyh9T1RmXry6Srz/7/udjlF0qmFiRXfBNAgoR
|
||||
tNb0+Ri/vY0AHrQ7UnCbl12qPVaqhEXLr+kCGNEPFqpMJPPEeMK0
|
||||
-----END RSA PRIVATE KEY-----
|
||||
`
|
||||
|
||||
const clientCert = `
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIC4jCCAcqgAwIBAgIBAjANBgkqhkiG9w0BAQUFADATMREwDwYDVQQDEwhNeVRl
|
||||
c3RDQTAeFw0xNDAxMjcxOTUyMjNaFw0yNDAxMjUxOTUyMjNaMCUxEjAQBgNVBAMT
|
||||
CTEyNy4wLjAuMTEPMA0GA1UEChMGY2xpZW50MIIBIjANBgkqhkiG9w0BAQEFAAOC
|
||||
AQ8AMIIBCgKCAQEAu7LMqd+agoH168Bsi0WJ36ulYqDypq+GZPF7uWOo2pE0raKH
|
||||
B++31/hjnkt6yC5kLKVZZ0EfolBa9q4Cy6swfGaEMafy44ZCRneLnt1azL1N6Kfz
|
||||
+U0KsOqyQDoMxYJG1gVTEZN19/U/ew2eazcxKyERI3oGCQ4SbpkxBTbfxtAFk49e
|
||||
xIB3obsuMVUrmtXE4FkUkvG7NgpPUgrhp0yxYpj9zruZGzGGT1zNhcarbQ/4i7It
|
||||
ZMbnv6pqQWtYDgnGX2TDRcEiXGeO+KrzhfpTRLfO3K4np8e8cmTyXM+4lMlWUgma
|
||||
KrRdu1QXozGqRs47u2prGKGdSQWITpqNVCY8fQIDAQABoy8wLTAJBgNVHRMEAjAA
|
||||
MAsGA1UdDwQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAjANBgkqhkiG9w0BAQUF
|
||||
AAOCAQEAhCuBCLznPc4O96hT3P8Fx19L3ltrWbc/pWrx8JjxUaGk8kNmjMjY+/Mt
|
||||
JBbjUBx2kJwaY0EHMAfw7D1f1wcCeNycx/0dyb0E6xzhmPw5fY15GGNg8rzWwqSY
|
||||
+i/1iqU0IRkmRHV7XCF+trd2H0Ec+V1Fd/61E2ccJfOL5aSAyWbMCUtWxS3QMnqH
|
||||
FBfKdVEiY9WNht5hnvsXQBRaNhowJ6Cwa7/1/LZjmhcXiJ0xrc1Hggj3cvS+4vll
|
||||
Ew+20a0tPKjD/v/2oSQL+qkeYKV4fhCGkaBHCpPlSJrqorb7B6NmPy3nS26ETKE/
|
||||
o2UCfZc5g2MU1ENa31kT1iuhKZapsA==
|
||||
-----END CERTIFICATE-----
|
||||
`
|
||||
|
||||
const clientKey = `
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAu7LMqd+agoH168Bsi0WJ36ulYqDypq+GZPF7uWOo2pE0raKH
|
||||
B++31/hjnkt6yC5kLKVZZ0EfolBa9q4Cy6swfGaEMafy44ZCRneLnt1azL1N6Kfz
|
||||
+U0KsOqyQDoMxYJG1gVTEZN19/U/ew2eazcxKyERI3oGCQ4SbpkxBTbfxtAFk49e
|
||||
xIB3obsuMVUrmtXE4FkUkvG7NgpPUgrhp0yxYpj9zruZGzGGT1zNhcarbQ/4i7It
|
||||
ZMbnv6pqQWtYDgnGX2TDRcEiXGeO+KrzhfpTRLfO3K4np8e8cmTyXM+4lMlWUgma
|
||||
KrRdu1QXozGqRs47u2prGKGdSQWITpqNVCY8fQIDAQABAoIBAGSEn3hFyEAmCyYi
|
||||
2b5IEksXaC2GlgxQKb/7Vs/0oCPU6YonZPsKFMFzQx4tu+ZiecEzF8rlJGTPdbdv
|
||||
fw3FcuTcHeVd1QSmDO4h7UK5tnu40XVMJKsY6CXQun8M13QajYbmORNLjjypOULU
|
||||
C0fNueYoAj6mhX7p61MRdSAev/5+0+bVQQG/tSVDQzdngvKpaCunOphiB2VW2Aa0
|
||||
7aYPOFCoPB2uo0DwUmBB0yfx9x4hXX9ovQI0YFou7bq6iYJ0vlZBvYQ9YrVdxjKL
|
||||
avcz1N5xM3WFAkZJSVT/Ho5+uTbZx4RrJ8b5T+t2spOKmXyAjwS2rL/XMAh8YRZ1
|
||||
u44duoECgYEA4jpK2qshgQ0t49rjVHEDKX5x7ElEZefl0rHZ/2X/uHUDKpKj2fTq
|
||||
3TQzHquiQ4Aof7OEB9UE3DGrtpvo/j/PYxL5Luu5VR4AIEJm+CA8GYuE96+uIL0Z
|
||||
M2r3Lux6Bp30Z47Eit2KiY4fhrWs59WB3NHHoFxgzHSVbnuA02gcX2ECgYEA1GZw
|
||||
iXIVYaK07ED+q/0ObyS5hD1cMhJ7ifSN9BxuG0qUpSigbkTGj09fUDS4Fqsz9dvz
|
||||
F0P93fZvyia242TIfDUwJEsDQCgHk7SGa4Rx/p/3x/obIEERk7K76Hdg93U5NXhV
|
||||
NvczvgL0HYxnb+qtumwMgGPzncB4lGcTnRyOfp0CgYBTIsDnYwRI/KLknUf1fCKB
|
||||
WSpcfwBXwsS+jQVjygQTsUyclI8KResZp1kx6DkVPT+kzj+y8SF8GfTUgq844BJC
|
||||
gnJ4P8A3+3JoaH6WqKHtcUxICZOgDF36e1CjOdwOGnX6qIipz4hdzJDhXFpSSDAV
|
||||
CjKmR8x61k0j8NcC2buzgQKBgFr7eo9VwBTvpoJhIPY5UvqHB7S+uAR26FZi3H/J
|
||||
wdyM6PmKWpaBfXCb9l8cBhMnyP0y94FqzY9L5fz48nSbkkmqWvHg9AaCXySFOuNJ
|
||||
e68vhOszlnUNimLzOAzPPkkh/JyL7Cy8XXyyNTGHGDPXmg12BTDmH8/eR4iCUuOE
|
||||
/QD9AoGBALQ/SkvfO3D5+k9e/aTHRuMJ0+PWdLUMTZ39oJQxUx+qj7/xpjDvWTBn
|
||||
eDmF/wjnIAg+020oXyBYo6plEZfDz3EYJQZ+3kLLEU+O/A7VxCakPYPwCr7N/InL
|
||||
Ccg/TVSIXxw/6uJnojoAjMIEU45NoP6RMp0mWYYb2OlteEv08Ovp
|
||||
-----END RSA PRIVATE KEY-----
|
||||
`
|
|
@ -1,328 +0,0 @@
|
|||
package amqp
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Test matrix defined on http://www.rabbitmq.com/uri-spec.html
|
||||
type testURI struct {
|
||||
url string
|
||||
username string
|
||||
password string
|
||||
host string
|
||||
port int
|
||||
vhost string
|
||||
canon string
|
||||
}
|
||||
|
||||
var uriTests = []testURI{
|
||||
{
|
||||
url: "amqp://user:pass@host:10000/vhost",
|
||||
username: "user",
|
||||
password: "pass",
|
||||
host: "host",
|
||||
port: 10000,
|
||||
vhost: "vhost",
|
||||
canon: "amqp://user:pass@host:10000/vhost",
|
||||
},
|
||||
|
||||
// this fails due to net/url not parsing pct-encoding in host
|
||||
// testURI{url: "amqp://user%61:%61pass@ho%61st:10000/v%2Fhost",
|
||||
// username: "usera",
|
||||
// password: "apass",
|
||||
// host: "hoast",
|
||||
// port: 10000,
|
||||
// vhost: "v/host",
|
||||
// },
|
||||
|
||||
{
|
||||
url: "amqp://",
|
||||
username: defaultURI.Username,
|
||||
password: defaultURI.Password,
|
||||
host: defaultURI.Host,
|
||||
port: defaultURI.Port,
|
||||
vhost: defaultURI.Vhost,
|
||||
canon: "amqp://localhost/",
|
||||
},
|
||||
|
||||
{
|
||||
url: "amqp://:@/",
|
||||
username: "",
|
||||
password: "",
|
||||
host: defaultURI.Host,
|
||||
port: defaultURI.Port,
|
||||
vhost: defaultURI.Vhost,
|
||||
canon: "amqp://:@localhost/",
|
||||
},
|
||||
|
||||
{
|
||||
url: "amqp://user@",
|
||||
username: "user",
|
||||
password: defaultURI.Password,
|
||||
host: defaultURI.Host,
|
||||
port: defaultURI.Port,
|
||||
vhost: defaultURI.Vhost,
|
||||
canon: "amqp://user@localhost/",
|
||||
},
|
||||
|
||||
{
|
||||
url: "amqp://user:pass@",
|
||||
username: "user",
|
||||
password: "pass",
|
||||
host: defaultURI.Host,
|
||||
port: defaultURI.Port,
|
||||
vhost: defaultURI.Vhost,
|
||||
canon: "amqp://user:pass@localhost/",
|
||||
},
|
||||
|
||||
{
|
||||
url: "amqp://guest:pass@",
|
||||
username: "guest",
|
||||
password: "pass",
|
||||
host: defaultURI.Host,
|
||||
port: defaultURI.Port,
|
||||
vhost: defaultURI.Vhost,
|
||||
canon: "amqp://guest:pass@localhost/",
|
||||
},
|
||||
|
||||
{
|
||||
url: "amqp://host",
|
||||
username: defaultURI.Username,
|
||||
password: defaultURI.Password,
|
||||
host: "host",
|
||||
port: defaultURI.Port,
|
||||
vhost: defaultURI.Vhost,
|
||||
canon: "amqp://host/",
|
||||
},
|
||||
|
||||
{
|
||||
url: "amqp://:10000",
|
||||
username: defaultURI.Username,
|
||||
password: defaultURI.Password,
|
||||
host: defaultURI.Host,
|
||||
port: 10000,
|
||||
vhost: defaultURI.Vhost,
|
||||
canon: "amqp://localhost:10000/",
|
||||
},
|
||||
|
||||
{
|
||||
url: "amqp:///vhost",
|
||||
username: defaultURI.Username,
|
||||
password: defaultURI.Password,
|
||||
host: defaultURI.Host,
|
||||
port: defaultURI.Port,
|
||||
vhost: "vhost",
|
||||
canon: "amqp://localhost/vhost",
|
||||
},
|
||||
|
||||
{
|
||||
url: "amqp://host/",
|
||||
username: defaultURI.Username,
|
||||
password: defaultURI.Password,
|
||||
host: "host",
|
||||
port: defaultURI.Port,
|
||||
vhost: defaultURI.Vhost,
|
||||
canon: "amqp://host/",
|
||||
},
|
||||
|
||||
{
|
||||
url: "amqp://host/%2F",
|
||||
username: defaultURI.Username,
|
||||
password: defaultURI.Password,
|
||||
host: "host",
|
||||
port: defaultURI.Port,
|
||||
vhost: "/",
|
||||
canon: "amqp://host/",
|
||||
},
|
||||
|
||||
{
|
||||
url: "amqp://host/%2F%2F",
|
||||
username: defaultURI.Username,
|
||||
password: defaultURI.Password,
|
||||
host: "host",
|
||||
port: defaultURI.Port,
|
||||
vhost: "//",
|
||||
canon: "amqp://host/%2F%2F",
|
||||
},
|
||||
|
||||
{
|
||||
url: "amqp://host/%2Fslash%2F",
|
||||
username: defaultURI.Username,
|
||||
password: defaultURI.Password,
|
||||
host: "host",
|
||||
port: defaultURI.Port,
|
||||
vhost: "/slash/",
|
||||
canon: "amqp://host/%2Fslash%2F",
|
||||
},
|
||||
|
||||
{
|
||||
url: "amqp://192.168.1.1:1000/",
|
||||
username: defaultURI.Username,
|
||||
password: defaultURI.Password,
|
||||
host: "192.168.1.1",
|
||||
port: 1000,
|
||||
vhost: defaultURI.Vhost,
|
||||
canon: "amqp://192.168.1.1:1000/",
|
||||
},
|
||||
|
||||
{
|
||||
url: "amqp://[::1]",
|
||||
username: defaultURI.Username,
|
||||
password: defaultURI.Password,
|
||||
host: "[::1]",
|
||||
port: defaultURI.Port,
|
||||
vhost: defaultURI.Vhost,
|
||||
canon: "amqp://[::1]/",
|
||||
},
|
||||
|
||||
{
|
||||
url: "amqp://[::1]:1000",
|
||||
username: defaultURI.Username,
|
||||
password: defaultURI.Password,
|
||||
host: "[::1]",
|
||||
port: 1000,
|
||||
vhost: defaultURI.Vhost,
|
||||
canon: "amqp://[::1]:1000/",
|
||||
},
|
||||
|
||||
{
|
||||
url: "amqps:///",
|
||||
username: defaultURI.Username,
|
||||
password: defaultURI.Password,
|
||||
host: defaultURI.Host,
|
||||
port: schemePorts["amqps"],
|
||||
vhost: defaultURI.Vhost,
|
||||
canon: "amqps://localhost/",
|
||||
},
|
||||
|
||||
{
|
||||
url: "amqps://host:1000/",
|
||||
username: defaultURI.Username,
|
||||
password: defaultURI.Password,
|
||||
host: "host",
|
||||
port: 1000,
|
||||
vhost: defaultURI.Vhost,
|
||||
canon: "amqps://host:1000/",
|
||||
},
|
||||
}
|
||||
|
||||
func TestURISpec(t *testing.T) {
|
||||
for _, test := range uriTests {
|
||||
u, err := ParseURI(test.url)
|
||||
if err != nil {
|
||||
t.Fatal("Could not parse spec URI: ", test.url, " err: ", err)
|
||||
}
|
||||
|
||||
if test.username != u.Username {
|
||||
t.Error("For: ", test.url, " usernames do not match. want: ", test.username, " got: ", u.Username)
|
||||
}
|
||||
|
||||
if test.password != u.Password {
|
||||
t.Error("For: ", test.url, " passwords do not match. want: ", test.password, " got: ", u.Password)
|
||||
}
|
||||
|
||||
if test.host != u.Host {
|
||||
t.Error("For: ", test.url, " hosts do not match. want: ", test.host, " got: ", u.Host)
|
||||
}
|
||||
|
||||
if test.port != u.Port {
|
||||
t.Error("For: ", test.url, " ports do not match. want: ", test.port, " got: ", u.Port)
|
||||
}
|
||||
|
||||
if test.vhost != u.Vhost {
|
||||
t.Error("For: ", test.url, " vhosts do not match. want: ", test.vhost, " got: ", u.Vhost)
|
||||
}
|
||||
|
||||
if test.canon != u.String() {
|
||||
t.Error("For: ", test.url, " canonical string does not match. want: ", test.canon, " got: ", u.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestURIUnknownScheme(t *testing.T) {
|
||||
if _, err := ParseURI("http://example.com/"); err == nil {
|
||||
t.Fatal("Expected error when parsing non-amqp scheme")
|
||||
}
|
||||
}
|
||||
|
||||
func TestURIScheme(t *testing.T) {
|
||||
if _, err := ParseURI("amqp://example.com/"); err != nil {
|
||||
t.Fatalf("Expected to parse amqp scheme, got %v", err)
|
||||
}
|
||||
|
||||
if _, err := ParseURI("amqps://example.com/"); err != nil {
|
||||
t.Fatalf("Expected to parse amqps scheme, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestURIDefaults(t *testing.T) {
|
||||
url := "amqp://"
|
||||
uri, err := ParseURI(url)
|
||||
if err != nil {
|
||||
t.Fatal("Could not parse")
|
||||
}
|
||||
|
||||
if uri.String() != "amqp://localhost/" {
|
||||
t.Fatal("Defaults not encoded properly got:", uri.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestURIComplete(t *testing.T) {
|
||||
url := "amqp://bob:dobbs@foo.bar:5678/private"
|
||||
uri, err := ParseURI(url)
|
||||
if err != nil {
|
||||
t.Fatal("Could not parse")
|
||||
}
|
||||
|
||||
if uri.String() != url {
|
||||
t.Fatal("Defaults not encoded properly want:", url, " got:", uri.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestURIDefaultPortAmqpNotIncluded(t *testing.T) {
|
||||
url := "amqp://foo.bar:5672/"
|
||||
uri, err := ParseURI(url)
|
||||
if err != nil {
|
||||
t.Fatal("Could not parse")
|
||||
}
|
||||
|
||||
if uri.String() != "amqp://foo.bar/" {
|
||||
t.Fatal("Defaults not encoded properly got:", uri.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestURIDefaultPortAmqp(t *testing.T) {
|
||||
url := "amqp://foo.bar/"
|
||||
uri, err := ParseURI(url)
|
||||
if err != nil {
|
||||
t.Fatal("Could not parse")
|
||||
}
|
||||
|
||||
if uri.Port != 5672 {
|
||||
t.Fatal("Default port not correct for amqp, got:", uri.Port)
|
||||
}
|
||||
}
|
||||
|
||||
func TestURIDefaultPortAmqpsNotIncludedInString(t *testing.T) {
|
||||
url := "amqps://foo.bar:5671/"
|
||||
uri, err := ParseURI(url)
|
||||
if err != nil {
|
||||
t.Fatal("Could not parse")
|
||||
}
|
||||
|
||||
if uri.String() != "amqps://foo.bar/" {
|
||||
t.Fatal("Defaults not encoded properly got:", uri.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestURIDefaultPortAmqps(t *testing.T) {
|
||||
url := "amqps://foo.bar/"
|
||||
uri, err := ParseURI(url)
|
||||
if err != nil {
|
||||
t.Fatal("Could not parse")
|
||||
}
|
||||
|
||||
if uri.Port != 5671 {
|
||||
t.Fatal("Default port not correct for amqps, got:", uri.Port)
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,966 +0,0 @@
|
|||
package yaml_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/gopkg.in/yaml.v2"
|
||||
. "gopkg.in/check.v1"
|
||||
"math"
|
||||
"net"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var unmarshalIntTest = 123
|
||||
|
||||
var unmarshalTests = []struct {
|
||||
data string
|
||||
value interface{}
|
||||
}{
|
||||
{
|
||||
"",
|
||||
&struct{}{},
|
||||
}, {
|
||||
"{}", &struct{}{},
|
||||
}, {
|
||||
"v: hi",
|
||||
map[string]string{"v": "hi"},
|
||||
}, {
|
||||
"v: hi", map[string]interface{}{"v": "hi"},
|
||||
}, {
|
||||
"v: true",
|
||||
map[string]string{"v": "true"},
|
||||
}, {
|
||||
"v: true",
|
||||
map[string]interface{}{"v": true},
|
||||
}, {
|
||||
"v: 10",
|
||||
map[string]interface{}{"v": 10},
|
||||
}, {
|
||||
"v: 0b10",
|
||||
map[string]interface{}{"v": 2},
|
||||
}, {
|
||||
"v: 0xA",
|
||||
map[string]interface{}{"v": 10},
|
||||
}, {
|
||||
"v: 4294967296",
|
||||
map[string]int64{"v": 4294967296},
|
||||
}, {
|
||||
"v: 0.1",
|
||||
map[string]interface{}{"v": 0.1},
|
||||
}, {
|
||||
"v: .1",
|
||||
map[string]interface{}{"v": 0.1},
|
||||
}, {
|
||||
"v: .Inf",
|
||||
map[string]interface{}{"v": math.Inf(+1)},
|
||||
}, {
|
||||
"v: -.Inf",
|
||||
map[string]interface{}{"v": math.Inf(-1)},
|
||||
}, {
|
||||
"v: -10",
|
||||
map[string]interface{}{"v": -10},
|
||||
}, {
|
||||
"v: -.1",
|
||||
map[string]interface{}{"v": -0.1},
|
||||
},
|
||||
|
||||
// Simple values.
|
||||
{
|
||||
"123",
|
||||
&unmarshalIntTest,
|
||||
},
|
||||
|
||||
// Floats from spec
|
||||
{
|
||||
"canonical: 6.8523e+5",
|
||||
map[string]interface{}{"canonical": 6.8523e+5},
|
||||
}, {
|
||||
"expo: 685.230_15e+03",
|
||||
map[string]interface{}{"expo": 685.23015e+03},
|
||||
}, {
|
||||
"fixed: 685_230.15",
|
||||
map[string]interface{}{"fixed": 685230.15},
|
||||
}, {
|
||||
"neginf: -.inf",
|
||||
map[string]interface{}{"neginf": math.Inf(-1)},
|
||||
}, {
|
||||
"fixed: 685_230.15",
|
||||
map[string]float64{"fixed": 685230.15},
|
||||
},
|
||||
//{"sexa: 190:20:30.15", map[string]interface{}{"sexa": 0}}, // Unsupported
|
||||
//{"notanum: .NaN", map[string]interface{}{"notanum": math.NaN()}}, // Equality of NaN fails.
|
||||
|
||||
// Bools from spec
|
||||
{
|
||||
"canonical: y",
|
||||
map[string]interface{}{"canonical": true},
|
||||
}, {
|
||||
"answer: NO",
|
||||
map[string]interface{}{"answer": false},
|
||||
}, {
|
||||
"logical: True",
|
||||
map[string]interface{}{"logical": true},
|
||||
}, {
|
||||
"option: on",
|
||||
map[string]interface{}{"option": true},
|
||||
}, {
|
||||
"option: on",
|
||||
map[string]bool{"option": true},
|
||||
},
|
||||
// Ints from spec
|
||||
{
|
||||
"canonical: 685230",
|
||||
map[string]interface{}{"canonical": 685230},
|
||||
}, {
|
||||
"decimal: +685_230",
|
||||
map[string]interface{}{"decimal": 685230},
|
||||
}, {
|
||||
"octal: 02472256",
|
||||
map[string]interface{}{"octal": 685230},
|
||||
}, {
|
||||
"hexa: 0x_0A_74_AE",
|
||||
map[string]interface{}{"hexa": 685230},
|
||||
}, {
|
||||
"bin: 0b1010_0111_0100_1010_1110",
|
||||
map[string]interface{}{"bin": 685230},
|
||||
}, {
|
||||
"bin: -0b101010",
|
||||
map[string]interface{}{"bin": -42},
|
||||
}, {
|
||||
"decimal: +685_230",
|
||||
map[string]int{"decimal": 685230},
|
||||
},
|
||||
|
||||
//{"sexa: 190:20:30", map[string]interface{}{"sexa": 0}}, // Unsupported
|
||||
|
||||
// Nulls from spec
|
||||
{
|
||||
"empty:",
|
||||
map[string]interface{}{"empty": nil},
|
||||
}, {
|
||||
"canonical: ~",
|
||||
map[string]interface{}{"canonical": nil},
|
||||
}, {
|
||||
"english: null",
|
||||
map[string]interface{}{"english": nil},
|
||||
}, {
|
||||
"~: null key",
|
||||
map[interface{}]string{nil: "null key"},
|
||||
}, {
|
||||
"empty:",
|
||||
map[string]*bool{"empty": nil},
|
||||
},
|
||||
|
||||
// Flow sequence
|
||||
{
|
||||
"seq: [A,B]",
|
||||
map[string]interface{}{"seq": []interface{}{"A", "B"}},
|
||||
}, {
|
||||
"seq: [A,B,C,]",
|
||||
map[string][]string{"seq": []string{"A", "B", "C"}},
|
||||
}, {
|
||||
"seq: [A,1,C]",
|
||||
map[string][]string{"seq": []string{"A", "1", "C"}},
|
||||
}, {
|
||||
"seq: [A,1,C]",
|
||||
map[string][]int{"seq": []int{1}},
|
||||
}, {
|
||||
"seq: [A,1,C]",
|
||||
map[string]interface{}{"seq": []interface{}{"A", 1, "C"}},
|
||||
},
|
||||
// Block sequence
|
||||
{
|
||||
"seq:\n - A\n - B",
|
||||
map[string]interface{}{"seq": []interface{}{"A", "B"}},
|
||||
}, {
|
||||
"seq:\n - A\n - B\n - C",
|
||||
map[string][]string{"seq": []string{"A", "B", "C"}},
|
||||
}, {
|
||||
"seq:\n - A\n - 1\n - C",
|
||||
map[string][]string{"seq": []string{"A", "1", "C"}},
|
||||
}, {
|
||||
"seq:\n - A\n - 1\n - C",
|
||||
map[string][]int{"seq": []int{1}},
|
||||
}, {
|
||||
"seq:\n - A\n - 1\n - C",
|
||||
map[string]interface{}{"seq": []interface{}{"A", 1, "C"}},
|
||||
},
|
||||
|
||||
// Literal block scalar
|
||||
{
|
||||
"scalar: | # Comment\n\n literal\n\n \ttext\n\n",
|
||||
map[string]string{"scalar": "\nliteral\n\n\ttext\n"},
|
||||
},
|
||||
|
||||
// Folded block scalar
|
||||
{
|
||||
"scalar: > # Comment\n\n folded\n line\n \n next\n line\n * one\n * two\n\n last\n line\n\n",
|
||||
map[string]string{"scalar": "\nfolded line\nnext line\n * one\n * two\n\nlast line\n"},
|
||||
},
|
||||
|
||||
// Map inside interface with no type hints.
|
||||
{
|
||||
"a: {b: c}",
|
||||
map[interface{}]interface{}{"a": map[interface{}]interface{}{"b": "c"}},
|
||||
},
|
||||
|
||||
// Structs and type conversions.
|
||||
{
|
||||
"hello: world",
|
||||
&struct{ Hello string }{"world"},
|
||||
}, {
|
||||
"a: {b: c}",
|
||||
&struct{ A struct{ B string } }{struct{ B string }{"c"}},
|
||||
}, {
|
||||
"a: {b: c}",
|
||||
&struct{ A *struct{ B string } }{&struct{ B string }{"c"}},
|
||||
}, {
|
||||
"a: {b: c}",
|
||||
&struct{ A map[string]string }{map[string]string{"b": "c"}},
|
||||
}, {
|
||||
"a: {b: c}",
|
||||
&struct{ A *map[string]string }{&map[string]string{"b": "c"}},
|
||||
}, {
|
||||
"a:",
|
||||
&struct{ A map[string]string }{},
|
||||
}, {
|
||||
"a: 1",
|
||||
&struct{ A int }{1},
|
||||
}, {
|
||||
"a: 1",
|
||||
&struct{ A float64 }{1},
|
||||
}, {
|
||||
"a: 1.0",
|
||||
&struct{ A int }{1},
|
||||
}, {
|
||||
"a: 1.0",
|
||||
&struct{ A uint }{1},
|
||||
}, {
|
||||
"a: [1, 2]",
|
||||
&struct{ A []int }{[]int{1, 2}},
|
||||
}, {
|
||||
"a: 1",
|
||||
&struct{ B int }{0},
|
||||
}, {
|
||||
"a: 1",
|
||||
&struct {
|
||||
B int "a"
|
||||
}{1},
|
||||
}, {
|
||||
"a: y",
|
||||
&struct{ A bool }{true},
|
||||
},
|
||||
|
||||
// Some cross type conversions
|
||||
{
|
||||
"v: 42",
|
||||
map[string]uint{"v": 42},
|
||||
}, {
|
||||
"v: -42",
|
||||
map[string]uint{},
|
||||
}, {
|
||||
"v: 4294967296",
|
||||
map[string]uint64{"v": 4294967296},
|
||||
}, {
|
||||
"v: -4294967296",
|
||||
map[string]uint64{},
|
||||
},
|
||||
|
||||
// int
|
||||
{
|
||||
"int_max: 2147483647",
|
||||
map[string]int{"int_max": math.MaxInt32},
|
||||
},
|
||||
{
|
||||
"int_min: -2147483648",
|
||||
map[string]int{"int_min": math.MinInt32},
|
||||
},
|
||||
{
|
||||
"int_overflow: 9223372036854775808", // math.MaxInt64 + 1
|
||||
map[string]int{},
|
||||
},
|
||||
|
||||
// int64
|
||||
{
|
||||
"int64_max: 9223372036854775807",
|
||||
map[string]int64{"int64_max": math.MaxInt64},
|
||||
},
|
||||
{
|
||||
"int64_max_base2: 0b111111111111111111111111111111111111111111111111111111111111111",
|
||||
map[string]int64{"int64_max_base2": math.MaxInt64},
|
||||
},
|
||||
{
|
||||
"int64_min: -9223372036854775808",
|
||||
map[string]int64{"int64_min": math.MinInt64},
|
||||
},
|
||||
{
|
||||
"int64_neg_base2: -0b111111111111111111111111111111111111111111111111111111111111111",
|
||||
map[string]int64{"int64_neg_base2": -math.MaxInt64},
|
||||
},
|
||||
{
|
||||
"int64_overflow: 9223372036854775808", // math.MaxInt64 + 1
|
||||
map[string]int64{},
|
||||
},
|
||||
|
||||
// uint
|
||||
{
|
||||
"uint_min: 0",
|
||||
map[string]uint{"uint_min": 0},
|
||||
},
|
||||
{
|
||||
"uint_max: 4294967295",
|
||||
map[string]uint{"uint_max": math.MaxUint32},
|
||||
},
|
||||
{
|
||||
"uint_underflow: -1",
|
||||
map[string]uint{},
|
||||
},
|
||||
|
||||
// uint64
|
||||
{
|
||||
"uint64_min: 0",
|
||||
map[string]uint{"uint64_min": 0},
|
||||
},
|
||||
{
|
||||
"uint64_max: 18446744073709551615",
|
||||
map[string]uint64{"uint64_max": math.MaxUint64},
|
||||
},
|
||||
{
|
||||
"uint64_max_base2: 0b1111111111111111111111111111111111111111111111111111111111111111",
|
||||
map[string]uint64{"uint64_max_base2": math.MaxUint64},
|
||||
},
|
||||
{
|
||||
"uint64_maxint64: 9223372036854775807",
|
||||
map[string]uint64{"uint64_maxint64": math.MaxInt64},
|
||||
},
|
||||
{
|
||||
"uint64_underflow: -1",
|
||||
map[string]uint64{},
|
||||
},
|
||||
|
||||
// float32
|
||||
{
|
||||
"float32_max: 3.40282346638528859811704183484516925440e+38",
|
||||
map[string]float32{"float32_max": math.MaxFloat32},
|
||||
},
|
||||
{
|
||||
"float32_nonzero: 1.401298464324817070923729583289916131280e-45",
|
||||
map[string]float32{"float32_nonzero": math.SmallestNonzeroFloat32},
|
||||
},
|
||||
{
|
||||
"float32_maxuint64: 18446744073709551615",
|
||||
map[string]float32{"float32_maxuint64": float32(math.MaxUint64)},
|
||||
},
|
||||
{
|
||||
"float32_maxuint64+1: 18446744073709551616",
|
||||
map[string]float32{"float32_maxuint64+1": float32(math.MaxUint64 + 1)},
|
||||
},
|
||||
|
||||
// float64
|
||||
{
|
||||
"float64_max: 1.797693134862315708145274237317043567981e+308",
|
||||
map[string]float64{"float64_max": math.MaxFloat64},
|
||||
},
|
||||
{
|
||||
"float64_nonzero: 4.940656458412465441765687928682213723651e-324",
|
||||
map[string]float64{"float64_nonzero": math.SmallestNonzeroFloat64},
|
||||
},
|
||||
{
|
||||
"float64_maxuint64: 18446744073709551615",
|
||||
map[string]float64{"float64_maxuint64": float64(math.MaxUint64)},
|
||||
},
|
||||
{
|
||||
"float64_maxuint64+1: 18446744073709551616",
|
||||
map[string]float64{"float64_maxuint64+1": float64(math.MaxUint64 + 1)},
|
||||
},
|
||||
|
||||
// Overflow cases.
|
||||
{
|
||||
"v: 4294967297",
|
||||
map[string]int32{},
|
||||
}, {
|
||||
"v: 128",
|
||||
map[string]int8{},
|
||||
},
|
||||
|
||||
// Quoted values.
|
||||
{
|
||||
"'1': '\"2\"'",
|
||||
map[interface{}]interface{}{"1": "\"2\""},
|
||||
}, {
|
||||
"v:\n- A\n- 'B\n\n C'\n",
|
||||
map[string][]string{"v": []string{"A", "B\nC"}},
|
||||
},
|
||||
|
||||
// Explicit tags.
|
||||
{
|
||||
"v: !!float '1.1'",
|
||||
map[string]interface{}{"v": 1.1},
|
||||
}, {
|
||||
"v: !!null ''",
|
||||
map[string]interface{}{"v": nil},
|
||||
}, {
|
||||
"%TAG !y! tag:yaml.org,2002:\n---\nv: !y!int '1'",
|
||||
map[string]interface{}{"v": 1},
|
||||
},
|
||||
|
||||
// Anchors and aliases.
|
||||
{
|
||||
"a: &x 1\nb: &y 2\nc: *x\nd: *y\n",
|
||||
&struct{ A, B, C, D int }{1, 2, 1, 2},
|
||||
}, {
|
||||
"a: &a {c: 1}\nb: *a",
|
||||
&struct {
|
||||
A, B struct {
|
||||
C int
|
||||
}
|
||||
}{struct{ C int }{1}, struct{ C int }{1}},
|
||||
}, {
|
||||
"a: &a [1, 2]\nb: *a",
|
||||
&struct{ B []int }{[]int{1, 2}},
|
||||
}, {
|
||||
"b: *a\na: &a {c: 1}",
|
||||
&struct {
|
||||
A, B struct {
|
||||
C int
|
||||
}
|
||||
}{struct{ C int }{1}, struct{ C int }{1}},
|
||||
},
|
||||
|
||||
// Bug #1133337
|
||||
{
|
||||
"foo: ''",
|
||||
map[string]*string{"foo": new(string)},
|
||||
}, {
|
||||
"foo: null",
|
||||
map[string]string{"foo": ""},
|
||||
}, {
|
||||
"foo: null",
|
||||
map[string]interface{}{"foo": nil},
|
||||
},
|
||||
|
||||
// Ignored field
|
||||
{
|
||||
"a: 1\nb: 2\n",
|
||||
&struct {
|
||||
A int
|
||||
B int "-"
|
||||
}{1, 0},
|
||||
},
|
||||
|
||||
// Bug #1191981
|
||||
{
|
||||
"" +
|
||||
"%YAML 1.1\n" +
|
||||
"--- !!str\n" +
|
||||
`"Generic line break (no glyph)\n\` + "\n" +
|
||||
` Generic line break (glyphed)\n\` + "\n" +
|
||||
` Line separator\u2028\` + "\n" +
|
||||
` Paragraph separator\u2029"` + "\n",
|
||||
"" +
|
||||
"Generic line break (no glyph)\n" +
|
||||
"Generic line break (glyphed)\n" +
|
||||
"Line separator\u2028Paragraph separator\u2029",
|
||||
},
|
||||
|
||||
// Struct inlining
|
||||
{
|
||||
"a: 1\nb: 2\nc: 3\n",
|
||||
&struct {
|
||||
A int
|
||||
C inlineB `yaml:",inline"`
|
||||
}{1, inlineB{2, inlineC{3}}},
|
||||
},
|
||||
|
||||
// Map inlining
|
||||
{
|
||||
"a: 1\nb: 2\nc: 3\n",
|
||||
&struct {
|
||||
A int
|
||||
C map[string]int `yaml:",inline"`
|
||||
}{1, map[string]int{"b": 2, "c": 3}},
|
||||
},
|
||||
|
||||
// bug 1243827
|
||||
{
|
||||
"a: -b_c",
|
||||
map[string]interface{}{"a": "-b_c"},
|
||||
},
|
||||
{
|
||||
"a: +b_c",
|
||||
map[string]interface{}{"a": "+b_c"},
|
||||
},
|
||||
{
|
||||
"a: 50cent_of_dollar",
|
||||
map[string]interface{}{"a": "50cent_of_dollar"},
|
||||
},
|
||||
|
||||
// Duration
|
||||
{
|
||||
"a: 3s",
|
||||
map[string]time.Duration{"a": 3 * time.Second},
|
||||
},
|
||||
|
||||
// Issue #24.
|
||||
{
|
||||
"a: <foo>",
|
||||
map[string]string{"a": "<foo>"},
|
||||
},
|
||||
|
||||
// Base 60 floats are obsolete and unsupported.
|
||||
{
|
||||
"a: 1:1\n",
|
||||
map[string]string{"a": "1:1"},
|
||||
},
|
||||
|
||||
// Binary data.
|
||||
{
|
||||
"a: !!binary gIGC\n",
|
||||
map[string]string{"a": "\x80\x81\x82"},
|
||||
}, {
|
||||
"a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n",
|
||||
map[string]string{"a": strings.Repeat("\x90", 54)},
|
||||
}, {
|
||||
"a: !!binary |\n " + strings.Repeat("A", 70) + "\n ==\n",
|
||||
map[string]string{"a": strings.Repeat("\x00", 52)},
|
||||
},
|
||||
|
||||
// Ordered maps.
|
||||
{
|
||||
"{b: 2, a: 1, d: 4, c: 3, sub: {e: 5}}",
|
||||
&yaml.MapSlice{{"b", 2}, {"a", 1}, {"d", 4}, {"c", 3}, {"sub", yaml.MapSlice{{"e", 5}}}},
|
||||
},
|
||||
|
||||
// Issue #39.
|
||||
{
|
||||
"a:\n b:\n c: d\n",
|
||||
map[string]struct{ B interface{} }{"a": {map[interface{}]interface{}{"c": "d"}}},
|
||||
},
|
||||
|
||||
// Custom map type.
|
||||
{
|
||||
"a: {b: c}",
|
||||
M{"a": M{"b": "c"}},
|
||||
},
|
||||
|
||||
// Support encoding.TextUnmarshaler.
|
||||
{
|
||||
"a: 1.2.3.4\n",
|
||||
map[string]net.IP{"a": net.IPv4(1, 2, 3, 4)},
|
||||
},
|
||||
{
|
||||
"a: 2015-02-24T18:19:39Z\n",
|
||||
map[string]time.Time{"a": time.Unix(1424801979, 0)},
|
||||
},
|
||||
|
||||
// Encode empty lists as zero-length slices.
|
||||
{
|
||||
"a: []",
|
||||
&struct{ A []int }{[]int{}},
|
||||
},
|
||||
}
|
||||
|
||||
type M map[interface{}]interface{}
|
||||
|
||||
type inlineB struct {
|
||||
B int
|
||||
inlineC `yaml:",inline"`
|
||||
}
|
||||
|
||||
type inlineC struct {
|
||||
C int
|
||||
}
|
||||
|
||||
func (s *S) TestUnmarshal(c *C) {
|
||||
for _, item := range unmarshalTests {
|
||||
t := reflect.ValueOf(item.value).Type()
|
||||
var value interface{}
|
||||
switch t.Kind() {
|
||||
case reflect.Map:
|
||||
value = reflect.MakeMap(t).Interface()
|
||||
case reflect.String:
|
||||
value = reflect.New(t).Interface()
|
||||
case reflect.Ptr:
|
||||
value = reflect.New(t.Elem()).Interface()
|
||||
default:
|
||||
c.Fatalf("missing case for %s", t)
|
||||
}
|
||||
err := yaml.Unmarshal([]byte(item.data), value)
|
||||
if _, ok := err.(*yaml.TypeError); !ok {
|
||||
c.Assert(err, IsNil)
|
||||
}
|
||||
if t.Kind() == reflect.String {
|
||||
c.Assert(*value.(*string), Equals, item.value)
|
||||
} else {
|
||||
c.Assert(value, DeepEquals, item.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *S) TestUnmarshalNaN(c *C) {
|
||||
value := map[string]interface{}{}
|
||||
err := yaml.Unmarshal([]byte("notanum: .NaN"), &value)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(math.IsNaN(value["notanum"].(float64)), Equals, true)
|
||||
}
|
||||
|
||||
var unmarshalErrorTests = []struct {
|
||||
data, error string
|
||||
}{
|
||||
{"v: !!float 'error'", "yaml: cannot decode !!str `error` as a !!float"},
|
||||
{"v: [A,", "yaml: line 1: did not find expected node content"},
|
||||
{"v:\n- [A,", "yaml: line 2: did not find expected node content"},
|
||||
{"a: *b\n", "yaml: unknown anchor 'b' referenced"},
|
||||
{"a: &a\n b: *a\n", "yaml: anchor 'a' value contains itself"},
|
||||
{"value: -", "yaml: block sequence entries are not allowed in this context"},
|
||||
{"a: !!binary ==", "yaml: !!binary value contains invalid base64 data"},
|
||||
{"{[.]}", `yaml: invalid map key: \[\]interface \{\}\{"\."\}`},
|
||||
{"{{.}}", `yaml: invalid map key: map\[interface\ \{\}\]interface \{\}\{".":interface \{\}\(nil\)\}`},
|
||||
}
|
||||
|
||||
func (s *S) TestUnmarshalErrors(c *C) {
|
||||
for _, item := range unmarshalErrorTests {
|
||||
var value interface{}
|
||||
err := yaml.Unmarshal([]byte(item.data), &value)
|
||||
c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value))
|
||||
}
|
||||
}
|
||||
|
||||
var unmarshalerTests = []struct {
|
||||
data, tag string
|
||||
value interface{}
|
||||
}{
|
||||
{"_: {hi: there}", "!!map", map[interface{}]interface{}{"hi": "there"}},
|
||||
{"_: [1,A]", "!!seq", []interface{}{1, "A"}},
|
||||
{"_: 10", "!!int", 10},
|
||||
{"_: null", "!!null", nil},
|
||||
{`_: BAR!`, "!!str", "BAR!"},
|
||||
{`_: "BAR!"`, "!!str", "BAR!"},
|
||||
{"_: !!foo 'BAR!'", "!!foo", "BAR!"},
|
||||
}
|
||||
|
||||
var unmarshalerResult = map[int]error{}
|
||||
|
||||
type unmarshalerType struct {
|
||||
value interface{}
|
||||
}
|
||||
|
||||
func (o *unmarshalerType) UnmarshalYAML(unmarshal func(v interface{}) error) error {
|
||||
if err := unmarshal(&o.value); err != nil {
|
||||
return err
|
||||
}
|
||||
if i, ok := o.value.(int); ok {
|
||||
if result, ok := unmarshalerResult[i]; ok {
|
||||
return result
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type unmarshalerPointer struct {
|
||||
Field *unmarshalerType "_"
|
||||
}
|
||||
|
||||
type unmarshalerValue struct {
|
||||
Field unmarshalerType "_"
|
||||
}
|
||||
|
||||
func (s *S) TestUnmarshalerPointerField(c *C) {
|
||||
for _, item := range unmarshalerTests {
|
||||
obj := &unmarshalerPointer{}
|
||||
err := yaml.Unmarshal([]byte(item.data), obj)
|
||||
c.Assert(err, IsNil)
|
||||
if item.value == nil {
|
||||
c.Assert(obj.Field, IsNil)
|
||||
} else {
|
||||
c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value))
|
||||
c.Assert(obj.Field.value, DeepEquals, item.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *S) TestUnmarshalerValueField(c *C) {
|
||||
for _, item := range unmarshalerTests {
|
||||
obj := &unmarshalerValue{}
|
||||
err := yaml.Unmarshal([]byte(item.data), obj)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value))
|
||||
c.Assert(obj.Field.value, DeepEquals, item.value)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *S) TestUnmarshalerWholeDocument(c *C) {
|
||||
obj := &unmarshalerType{}
|
||||
err := yaml.Unmarshal([]byte(unmarshalerTests[0].data), obj)
|
||||
c.Assert(err, IsNil)
|
||||
value, ok := obj.value.(map[interface{}]interface{})
|
||||
c.Assert(ok, Equals, true, Commentf("value: %#v", obj.value))
|
||||
c.Assert(value["_"], DeepEquals, unmarshalerTests[0].value)
|
||||
}
|
||||
|
||||
func (s *S) TestUnmarshalerTypeError(c *C) {
|
||||
unmarshalerResult[2] = &yaml.TypeError{[]string{"foo"}}
|
||||
unmarshalerResult[4] = &yaml.TypeError{[]string{"bar"}}
|
||||
defer func() {
|
||||
delete(unmarshalerResult, 2)
|
||||
delete(unmarshalerResult, 4)
|
||||
}()
|
||||
|
||||
type T struct {
|
||||
Before int
|
||||
After int
|
||||
M map[string]*unmarshalerType
|
||||
}
|
||||
var v T
|
||||
data := `{before: A, m: {abc: 1, def: 2, ghi: 3, jkl: 4}, after: B}`
|
||||
err := yaml.Unmarshal([]byte(data), &v)
|
||||
c.Assert(err, ErrorMatches, ""+
|
||||
"yaml: unmarshal errors:\n"+
|
||||
" line 1: cannot unmarshal !!str `A` into int\n"+
|
||||
" foo\n"+
|
||||
" bar\n"+
|
||||
" line 1: cannot unmarshal !!str `B` into int")
|
||||
c.Assert(v.M["abc"], NotNil)
|
||||
c.Assert(v.M["def"], IsNil)
|
||||
c.Assert(v.M["ghi"], NotNil)
|
||||
c.Assert(v.M["jkl"], IsNil)
|
||||
|
||||
c.Assert(v.M["abc"].value, Equals, 1)
|
||||
c.Assert(v.M["ghi"].value, Equals, 3)
|
||||
}
|
||||
|
||||
type proxyTypeError struct{}
|
||||
|
||||
func (v *proxyTypeError) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
var s string
|
||||
var a int32
|
||||
var b int64
|
||||
if err := unmarshal(&s); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if s == "a" {
|
||||
if err := unmarshal(&b); err == nil {
|
||||
panic("should have failed")
|
||||
}
|
||||
return unmarshal(&a)
|
||||
}
|
||||
if err := unmarshal(&a); err == nil {
|
||||
panic("should have failed")
|
||||
}
|
||||
return unmarshal(&b)
|
||||
}
|
||||
|
||||
func (s *S) TestUnmarshalerTypeErrorProxying(c *C) {
|
||||
type T struct {
|
||||
Before int
|
||||
After int
|
||||
M map[string]*proxyTypeError
|
||||
}
|
||||
var v T
|
||||
data := `{before: A, m: {abc: a, def: b}, after: B}`
|
||||
err := yaml.Unmarshal([]byte(data), &v)
|
||||
c.Assert(err, ErrorMatches, ""+
|
||||
"yaml: unmarshal errors:\n"+
|
||||
" line 1: cannot unmarshal !!str `A` into int\n"+
|
||||
" line 1: cannot unmarshal !!str `a` into int32\n"+
|
||||
" line 1: cannot unmarshal !!str `b` into int64\n"+
|
||||
" line 1: cannot unmarshal !!str `B` into int")
|
||||
}
|
||||
|
||||
type failingUnmarshaler struct{}
|
||||
|
||||
var failingErr = errors.New("failingErr")
|
||||
|
||||
func (ft *failingUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
return failingErr
|
||||
}
|
||||
|
||||
func (s *S) TestUnmarshalerError(c *C) {
|
||||
err := yaml.Unmarshal([]byte("a: b"), &failingUnmarshaler{})
|
||||
c.Assert(err, Equals, failingErr)
|
||||
}
|
||||
|
||||
type sliceUnmarshaler []int
|
||||
|
||||
func (su *sliceUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
var slice []int
|
||||
err := unmarshal(&slice)
|
||||
if err == nil {
|
||||
*su = slice
|
||||
return nil
|
||||
}
|
||||
|
||||
var intVal int
|
||||
err = unmarshal(&intVal)
|
||||
if err == nil {
|
||||
*su = []int{intVal}
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *S) TestUnmarshalerRetry(c *C) {
|
||||
var su sliceUnmarshaler
|
||||
err := yaml.Unmarshal([]byte("[1, 2, 3]"), &su)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1, 2, 3}))
|
||||
|
||||
err = yaml.Unmarshal([]byte("1"), &su)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1}))
|
||||
}
|
||||
|
||||
// From http://yaml.org/type/merge.html
|
||||
var mergeTests = `
|
||||
anchors:
|
||||
list:
|
||||
- &CENTER { "x": 1, "y": 2 }
|
||||
- &LEFT { "x": 0, "y": 2 }
|
||||
- &BIG { "r": 10 }
|
||||
- &SMALL { "r": 1 }
|
||||
|
||||
# All the following maps are equal:
|
||||
|
||||
plain:
|
||||
# Explicit keys
|
||||
"x": 1
|
||||
"y": 2
|
||||
"r": 10
|
||||
label: center/big
|
||||
|
||||
mergeOne:
|
||||
# Merge one map
|
||||
<< : *CENTER
|
||||
"r": 10
|
||||
label: center/big
|
||||
|
||||
mergeMultiple:
|
||||
# Merge multiple maps
|
||||
<< : [ *CENTER, *BIG ]
|
||||
label: center/big
|
||||
|
||||
override:
|
||||
# Override
|
||||
<< : [ *BIG, *LEFT, *SMALL ]
|
||||
"x": 1
|
||||
label: center/big
|
||||
|
||||
shortTag:
|
||||
# Explicit short merge tag
|
||||
!!merge "<<" : [ *CENTER, *BIG ]
|
||||
label: center/big
|
||||
|
||||
longTag:
|
||||
# Explicit merge long tag
|
||||
!<tag:yaml.org,2002:merge> "<<" : [ *CENTER, *BIG ]
|
||||
label: center/big
|
||||
|
||||
inlineMap:
|
||||
# Inlined map
|
||||
<< : {"x": 1, "y": 2, "r": 10}
|
||||
label: center/big
|
||||
|
||||
inlineSequenceMap:
|
||||
# Inlined map in sequence
|
||||
<< : [ *CENTER, {"r": 10} ]
|
||||
label: center/big
|
||||
`
|
||||
|
||||
func (s *S) TestMerge(c *C) {
|
||||
var want = map[interface{}]interface{}{
|
||||
"x": 1,
|
||||
"y": 2,
|
||||
"r": 10,
|
||||
"label": "center/big",
|
||||
}
|
||||
|
||||
var m map[interface{}]interface{}
|
||||
err := yaml.Unmarshal([]byte(mergeTests), &m)
|
||||
c.Assert(err, IsNil)
|
||||
for name, test := range m {
|
||||
if name == "anchors" {
|
||||
continue
|
||||
}
|
||||
c.Assert(test, DeepEquals, want, Commentf("test %q failed", name))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *S) TestMergeStruct(c *C) {
|
||||
type Data struct {
|
||||
X, Y, R int
|
||||
Label string
|
||||
}
|
||||
want := Data{1, 2, 10, "center/big"}
|
||||
|
||||
var m map[string]Data
|
||||
err := yaml.Unmarshal([]byte(mergeTests), &m)
|
||||
c.Assert(err, IsNil)
|
||||
for name, test := range m {
|
||||
if name == "anchors" {
|
||||
continue
|
||||
}
|
||||
c.Assert(test, Equals, want, Commentf("test %q failed", name))
|
||||
}
|
||||
}
|
||||
|
||||
var unmarshalNullTests = []func() interface{}{
|
||||
func() interface{} { var v interface{}; v = "v"; return &v },
|
||||
func() interface{} { var s = "s"; return &s },
|
||||
func() interface{} { var s = "s"; sptr := &s; return &sptr },
|
||||
func() interface{} { var i = 1; return &i },
|
||||
func() interface{} { var i = 1; iptr := &i; return &iptr },
|
||||
func() interface{} { m := map[string]int{"s": 1}; return &m },
|
||||
func() interface{} { m := map[string]int{"s": 1}; return m },
|
||||
}
|
||||
|
||||
func (s *S) TestUnmarshalNull(c *C) {
|
||||
for _, test := range unmarshalNullTests {
|
||||
item := test()
|
||||
zero := reflect.Zero(reflect.TypeOf(item).Elem()).Interface()
|
||||
err := yaml.Unmarshal([]byte("null"), item)
|
||||
c.Assert(err, IsNil)
|
||||
if reflect.TypeOf(item).Kind() == reflect.Map {
|
||||
c.Assert(reflect.ValueOf(item).Interface(), DeepEquals, reflect.MakeMap(reflect.TypeOf(item)).Interface())
|
||||
} else {
|
||||
c.Assert(reflect.ValueOf(item).Elem().Interface(), DeepEquals, zero)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *S) TestUnmarshalSliceOnPreset(c *C) {
|
||||
// Issue #48.
|
||||
v := struct{ A []int }{[]int{1}}
|
||||
yaml.Unmarshal([]byte("a: [2]"), &v)
|
||||
c.Assert(v.A, DeepEquals, []int{2})
|
||||
}
|
||||
|
||||
//var data []byte
|
||||
//func init() {
|
||||
// var err error
|
||||
// data, err = ioutil.ReadFile("/tmp/file.yaml")
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//func (s *S) BenchmarkUnmarshal(c *C) {
|
||||
// var err error
|
||||
// for i := 0; i < c.N; i++ {
|
||||
// var v map[string]interface{}
|
||||
// err = yaml.Unmarshal(data, &v)
|
||||
// }
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//func (s *S) BenchmarkMarshal(c *C) {
|
||||
// var v map[string]interface{}
|
||||
// yaml.Unmarshal(data, &v)
|
||||
// c.ResetTimer()
|
||||
// for i := 0; i < c.N; i++ {
|
||||
// yaml.Marshal(&v)
|
||||
// }
|
||||
//}
|
|
@ -1,501 +0,0 @@
|
|||
package yaml_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/gopkg.in/yaml.v2"
|
||||
. "gopkg.in/check.v1"
|
||||
"net"
|
||||
"os"
|
||||
)
|
||||
|
||||
var marshalIntTest = 123
|
||||
|
||||
var marshalTests = []struct {
|
||||
value interface{}
|
||||
data string
|
||||
}{
|
||||
{
|
||||
nil,
|
||||
"null\n",
|
||||
}, {
|
||||
&struct{}{},
|
||||
"{}\n",
|
||||
}, {
|
||||
map[string]string{"v": "hi"},
|
||||
"v: hi\n",
|
||||
}, {
|
||||
map[string]interface{}{"v": "hi"},
|
||||
"v: hi\n",
|
||||
}, {
|
||||
map[string]string{"v": "true"},
|
||||
"v: \"true\"\n",
|
||||
}, {
|
||||
map[string]string{"v": "false"},
|
||||
"v: \"false\"\n",
|
||||
}, {
|
||||
map[string]interface{}{"v": true},
|
||||
"v: true\n",
|
||||
}, {
|
||||
map[string]interface{}{"v": false},
|
||||
"v: false\n",
|
||||
}, {
|
||||
map[string]interface{}{"v": 10},
|
||||
"v: 10\n",
|
||||
}, {
|
||||
map[string]interface{}{"v": -10},
|
||||
"v: -10\n",
|
||||
}, {
|
||||
map[string]uint{"v": 42},
|
||||
"v: 42\n",
|
||||
}, {
|
||||
map[string]interface{}{"v": int64(4294967296)},
|
||||
"v: 4294967296\n",
|
||||
}, {
|
||||
map[string]int64{"v": int64(4294967296)},
|
||||
"v: 4294967296\n",
|
||||
}, {
|
||||
map[string]uint64{"v": 4294967296},
|
||||
"v: 4294967296\n",
|
||||
}, {
|
||||
map[string]interface{}{"v": "10"},
|
||||
"v: \"10\"\n",
|
||||
}, {
|
||||
map[string]interface{}{"v": 0.1},
|
||||
"v: 0.1\n",
|
||||
}, {
|
||||
map[string]interface{}{"v": float64(0.1)},
|
||||
"v: 0.1\n",
|
||||
}, {
|
||||
map[string]interface{}{"v": -0.1},
|
||||
"v: -0.1\n",
|
||||
}, {
|
||||
map[string]interface{}{"v": math.Inf(+1)},
|
||||
"v: .inf\n",
|
||||
}, {
|
||||
map[string]interface{}{"v": math.Inf(-1)},
|
||||
"v: -.inf\n",
|
||||
}, {
|
||||
map[string]interface{}{"v": math.NaN()},
|
||||
"v: .nan\n",
|
||||
}, {
|
||||
map[string]interface{}{"v": nil},
|
||||
"v: null\n",
|
||||
}, {
|
||||
map[string]interface{}{"v": ""},
|
||||
"v: \"\"\n",
|
||||
}, {
|
||||
map[string][]string{"v": []string{"A", "B"}},
|
||||
"v:\n- A\n- B\n",
|
||||
}, {
|
||||
map[string][]string{"v": []string{"A", "B\nC"}},
|
||||
"v:\n- A\n- |-\n B\n C\n",
|
||||
}, {
|
||||
map[string][]interface{}{"v": []interface{}{"A", 1, map[string][]int{"B": []int{2, 3}}}},
|
||||
"v:\n- A\n- 1\n- B:\n - 2\n - 3\n",
|
||||
}, {
|
||||
map[string]interface{}{"a": map[interface{}]interface{}{"b": "c"}},
|
||||
"a:\n b: c\n",
|
||||
}, {
|
||||
map[string]interface{}{"a": "-"},
|
||||
"a: '-'\n",
|
||||
},
|
||||
|
||||
// Simple values.
|
||||
{
|
||||
&marshalIntTest,
|
||||
"123\n",
|
||||
},
|
||||
|
||||
// Structures
|
||||
{
|
||||
&struct{ Hello string }{"world"},
|
||||
"hello: world\n",
|
||||
}, {
|
||||
&struct {
|
||||
A struct {
|
||||
B string
|
||||
}
|
||||
}{struct{ B string }{"c"}},
|
||||
"a:\n b: c\n",
|
||||
}, {
|
||||
&struct {
|
||||
A *struct {
|
||||
B string
|
||||
}
|
||||
}{&struct{ B string }{"c"}},
|
||||
"a:\n b: c\n",
|
||||
}, {
|
||||
&struct {
|
||||
A *struct {
|
||||
B string
|
||||
}
|
||||
}{},
|
||||
"a: null\n",
|
||||
}, {
|
||||
&struct{ A int }{1},
|
||||
"a: 1\n",
|
||||
}, {
|
||||
&struct{ A []int }{[]int{1, 2}},
|
||||
"a:\n- 1\n- 2\n",
|
||||
}, {
|
||||
&struct {
|
||||
B int "a"
|
||||
}{1},
|
||||
"a: 1\n",
|
||||
}, {
|
||||
&struct{ A bool }{true},
|
||||
"a: true\n",
|
||||
},
|
||||
|
||||
// Conditional flag
|
||||
{
|
||||
&struct {
|
||||
A int "a,omitempty"
|
||||
B int "b,omitempty"
|
||||
}{1, 0},
|
||||
"a: 1\n",
|
||||
}, {
|
||||
&struct {
|
||||
A int "a,omitempty"
|
||||
B int "b,omitempty"
|
||||
}{0, 0},
|
||||
"{}\n",
|
||||
}, {
|
||||
&struct {
|
||||
A *struct{ X, y int } "a,omitempty,flow"
|
||||
}{&struct{ X, y int }{1, 2}},
|
||||
"a: {x: 1}\n",
|
||||
}, {
|
||||
&struct {
|
||||
A *struct{ X, y int } "a,omitempty,flow"
|
||||
}{nil},
|
||||
"{}\n",
|
||||
}, {
|
||||
&struct {
|
||||
A *struct{ X, y int } "a,omitempty,flow"
|
||||
}{&struct{ X, y int }{}},
|
||||
"a: {x: 0}\n",
|
||||
}, {
|
||||
&struct {
|
||||
A struct{ X, y int } "a,omitempty,flow"
|
||||
}{struct{ X, y int }{1, 2}},
|
||||
"a: {x: 1}\n",
|
||||
}, {
|
||||
&struct {
|
||||
A struct{ X, y int } "a,omitempty,flow"
|
||||
}{struct{ X, y int }{0, 1}},
|
||||
"{}\n",
|
||||
}, {
|
||||
&struct {
|
||||
A float64 "a,omitempty"
|
||||
B float64 "b,omitempty"
|
||||
}{1, 0},
|
||||
"a: 1\n",
|
||||
},
|
||||
|
||||
// Flow flag
|
||||
{
|
||||
&struct {
|
||||
A []int "a,flow"
|
||||
}{[]int{1, 2}},
|
||||
"a: [1, 2]\n",
|
||||
}, {
|
||||
&struct {
|
||||
A map[string]string "a,flow"
|
||||
}{map[string]string{"b": "c", "d": "e"}},
|
||||
"a: {b: c, d: e}\n",
|
||||
}, {
|
||||
&struct {
|
||||
A struct {
|
||||
B, D string
|
||||
} "a,flow"
|
||||
}{struct{ B, D string }{"c", "e"}},
|
||||
"a: {b: c, d: e}\n",
|
||||
},
|
||||
|
||||
// Unexported field
|
||||
{
|
||||
&struct {
|
||||
u int
|
||||
A int
|
||||
}{0, 1},
|
||||
"a: 1\n",
|
||||
},
|
||||
|
||||
// Ignored field
|
||||
{
|
||||
&struct {
|
||||
A int
|
||||
B int "-"
|
||||
}{1, 2},
|
||||
"a: 1\n",
|
||||
},
|
||||
|
||||
// Struct inlining
|
||||
{
|
||||
&struct {
|
||||
A int
|
||||
C inlineB `yaml:",inline"`
|
||||
}{1, inlineB{2, inlineC{3}}},
|
||||
"a: 1\nb: 2\nc: 3\n",
|
||||
},
|
||||
|
||||
// Map inlining
|
||||
{
|
||||
&struct {
|
||||
A int
|
||||
C map[string]int `yaml:",inline"`
|
||||
}{1, map[string]int{"b": 2, "c": 3}},
|
||||
"a: 1\nb: 2\nc: 3\n",
|
||||
},
|
||||
|
||||
// Duration
|
||||
{
|
||||
map[string]time.Duration{"a": 3 * time.Second},
|
||||
"a: 3s\n",
|
||||
},
|
||||
|
||||
// Issue #24: bug in map merging logic.
|
||||
{
|
||||
map[string]string{"a": "<foo>"},
|
||||
"a: <foo>\n",
|
||||
},
|
||||
|
||||
// Issue #34: marshal unsupported base 60 floats quoted for compatibility
|
||||
// with old YAML 1.1 parsers.
|
||||
{
|
||||
map[string]string{"a": "1:1"},
|
||||
"a: \"1:1\"\n",
|
||||
},
|
||||
|
||||
// Binary data.
|
||||
{
|
||||
map[string]string{"a": "\x00"},
|
||||
"a: \"\\0\"\n",
|
||||
}, {
|
||||
map[string]string{"a": "\x80\x81\x82"},
|
||||
"a: !!binary gIGC\n",
|
||||
}, {
|
||||
map[string]string{"a": strings.Repeat("\x90", 54)},
|
||||
"a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n",
|
||||
},
|
||||
|
||||
// Ordered maps.
|
||||
{
|
||||
&yaml.MapSlice{{"b", 2}, {"a", 1}, {"d", 4}, {"c", 3}, {"sub", yaml.MapSlice{{"e", 5}}}},
|
||||
"b: 2\na: 1\nd: 4\nc: 3\nsub:\n e: 5\n",
|
||||
},
|
||||
|
||||
// Encode unicode as utf-8 rather than in escaped form.
|
||||
{
|
||||
map[string]string{"a": "你好"},
|
||||
"a: 你好\n",
|
||||
},
|
||||
|
||||
// Support encoding.TextMarshaler.
|
||||
{
|
||||
map[string]net.IP{"a": net.IPv4(1, 2, 3, 4)},
|
||||
"a: 1.2.3.4\n",
|
||||
},
|
||||
{
|
||||
map[string]time.Time{"a": time.Unix(1424801979, 0)},
|
||||
"a: 2015-02-24T18:19:39Z\n",
|
||||
},
|
||||
|
||||
// Ensure strings containing ": " are quoted (reported as PR #43, but not reproducible).
|
||||
{
|
||||
map[string]string{"a": "b: c"},
|
||||
"a: 'b: c'\n",
|
||||
},
|
||||
|
||||
// Containing hash mark ('#') in string should be quoted
|
||||
{
|
||||
map[string]string{"a": "Hello #comment"},
|
||||
"a: 'Hello #comment'\n",
|
||||
},
|
||||
{
|
||||
map[string]string{"a": "你好 #comment"},
|
||||
"a: '你好 #comment'\n",
|
||||
},
|
||||
}
|
||||
|
||||
func (s *S) TestMarshal(c *C) {
|
||||
defer os.Setenv("TZ", os.Getenv("TZ"))
|
||||
os.Setenv("TZ", "UTC")
|
||||
for _, item := range marshalTests {
|
||||
data, err := yaml.Marshal(item.value)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(string(data), Equals, item.data)
|
||||
}
|
||||
}
|
||||
|
||||
var marshalErrorTests = []struct {
|
||||
value interface{}
|
||||
error string
|
||||
panic string
|
||||
}{{
|
||||
value: &struct {
|
||||
B int
|
||||
inlineB ",inline"
|
||||
}{1, inlineB{2, inlineC{3}}},
|
||||
panic: `Duplicated key 'b' in struct struct \{ B int; .*`,
|
||||
}, {
|
||||
value: &struct {
|
||||
A int
|
||||
B map[string]int ",inline"
|
||||
}{1, map[string]int{"a": 2}},
|
||||
panic: `Can't have key "a" in inlined map; conflicts with struct field`,
|
||||
}}
|
||||
|
||||
func (s *S) TestMarshalErrors(c *C) {
|
||||
for _, item := range marshalErrorTests {
|
||||
if item.panic != "" {
|
||||
c.Assert(func() { yaml.Marshal(item.value) }, PanicMatches, item.panic)
|
||||
} else {
|
||||
_, err := yaml.Marshal(item.value)
|
||||
c.Assert(err, ErrorMatches, item.error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *S) TestMarshalTypeCache(c *C) {
|
||||
var data []byte
|
||||
var err error
|
||||
func() {
|
||||
type T struct{ A int }
|
||||
data, err = yaml.Marshal(&T{})
|
||||
c.Assert(err, IsNil)
|
||||
}()
|
||||
func() {
|
||||
type T struct{ B int }
|
||||
data, err = yaml.Marshal(&T{})
|
||||
c.Assert(err, IsNil)
|
||||
}()
|
||||
c.Assert(string(data), Equals, "b: 0\n")
|
||||
}
|
||||
|
||||
var marshalerTests = []struct {
|
||||
data string
|
||||
value interface{}
|
||||
}{
|
||||
{"_:\n hi: there\n", map[interface{}]interface{}{"hi": "there"}},
|
||||
{"_:\n- 1\n- A\n", []interface{}{1, "A"}},
|
||||
{"_: 10\n", 10},
|
||||
{"_: null\n", nil},
|
||||
{"_: BAR!\n", "BAR!"},
|
||||
}
|
||||
|
||||
type marshalerType struct {
|
||||
value interface{}
|
||||
}
|
||||
|
||||
func (o marshalerType) MarshalText() ([]byte, error) {
|
||||
panic("MarshalText called on type with MarshalYAML")
|
||||
}
|
||||
|
||||
func (o marshalerType) MarshalYAML() (interface{}, error) {
|
||||
return o.value, nil
|
||||
}
|
||||
|
||||
type marshalerValue struct {
|
||||
Field marshalerType "_"
|
||||
}
|
||||
|
||||
func (s *S) TestMarshaler(c *C) {
|
||||
for _, item := range marshalerTests {
|
||||
obj := &marshalerValue{}
|
||||
obj.Field.value = item.value
|
||||
data, err := yaml.Marshal(obj)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(string(data), Equals, string(item.data))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *S) TestMarshalerWholeDocument(c *C) {
|
||||
obj := &marshalerType{}
|
||||
obj.value = map[string]string{"hello": "world!"}
|
||||
data, err := yaml.Marshal(obj)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(string(data), Equals, "hello: world!\n")
|
||||
}
|
||||
|
||||
type failingMarshaler struct{}
|
||||
|
||||
func (ft *failingMarshaler) MarshalYAML() (interface{}, error) {
|
||||
return nil, failingErr
|
||||
}
|
||||
|
||||
func (s *S) TestMarshalerError(c *C) {
|
||||
_, err := yaml.Marshal(&failingMarshaler{})
|
||||
c.Assert(err, Equals, failingErr)
|
||||
}
|
||||
|
||||
func (s *S) TestSortedOutput(c *C) {
|
||||
order := []interface{}{
|
||||
false,
|
||||
true,
|
||||
1,
|
||||
uint(1),
|
||||
1.0,
|
||||
1.1,
|
||||
1.2,
|
||||
2,
|
||||
uint(2),
|
||||
2.0,
|
||||
2.1,
|
||||
"",
|
||||
".1",
|
||||
".2",
|
||||
".a",
|
||||
"1",
|
||||
"2",
|
||||
"a!10",
|
||||
"a/2",
|
||||
"a/10",
|
||||
"a~10",
|
||||
"ab/1",
|
||||
"b/1",
|
||||
"b/01",
|
||||
"b/2",
|
||||
"b/02",
|
||||
"b/3",
|
||||
"b/03",
|
||||
"b1",
|
||||
"b01",
|
||||
"b3",
|
||||
"c2.10",
|
||||
"c10.2",
|
||||
"d1",
|
||||
"d12",
|
||||
"d12a",
|
||||
}
|
||||
m := make(map[interface{}]int)
|
||||
for _, k := range order {
|
||||
m[k] = 1
|
||||
}
|
||||
data, err := yaml.Marshal(m)
|
||||
c.Assert(err, IsNil)
|
||||
out := "\n" + string(data)
|
||||
last := 0
|
||||
for i, k := range order {
|
||||
repr := fmt.Sprint(k)
|
||||
if s, ok := k.(string); ok {
|
||||
if _, err = strconv.ParseFloat(repr, 32); s == "" || err == nil {
|
||||
repr = `"` + repr + `"`
|
||||
}
|
||||
}
|
||||
index := strings.Index(out, "\n"+repr+":")
|
||||
if index == -1 {
|
||||
c.Fatalf("%#v is not in the output: %#v", k, out)
|
||||
}
|
||||
if index < last {
|
||||
c.Fatalf("%#v was generated before %#v: %q", k, order[i-1], out)
|
||||
}
|
||||
last = index
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
package yaml_test
|
||||
|
||||
import (
|
||||
. "gopkg.in/check.v1"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) { TestingT(t) }
|
||||
|
||||
type S struct{}
|
||||
|
||||
var _ = Suite(&S{})
|
1
Makefile
1
Makefile
|
@ -39,6 +39,7 @@ $(OBJDIR):
|
|||
$(CMD_BINS): build_cmds
|
||||
|
||||
build_cmds: | $(OBJDIR)
|
||||
export GO15VENDOREXPERIMENT=1
|
||||
GOBIN=$(OBJDIR) go install $(GO_BUILD_FLAGS) ./...
|
||||
|
||||
clean:
|
||||
|
|
|
@ -14,8 +14,8 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/jmhodges/clock"
|
||||
"github.com/cactus/go-statsd-client/statsd"
|
||||
"github.com/jmhodges/clock"
|
||||
"github.com/letsencrypt/boulder/core"
|
||||
|
||||
blog "github.com/letsencrypt/boulder/log"
|
||||
|
|
|
@ -7,8 +7,8 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/jmhodges/clock"
|
||||
"github.com/cactus/go-statsd-client/statsd"
|
||||
"github.com/jmhodges/clock"
|
||||
|
||||
"github.com/letsencrypt/boulder/test"
|
||||
)
|
||||
|
|
|
@ -12,10 +12,10 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/jmhodges/clock"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/miekg/dns"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/golang.org/x/net/context"
|
||||
"github.com/jmhodges/clock"
|
||||
"github.com/letsencrypt/boulder/metrics"
|
||||
"github.com/miekg/dns"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
|
@ -15,13 +15,13 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/golang.org/x/net/context"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/jmhodges/clock"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/miekg/dns"
|
||||
"github.com/cactus/go-statsd-client/statsd"
|
||||
"github.com/jmhodges/clock"
|
||||
"github.com/letsencrypt/boulder/metrics"
|
||||
"github.com/letsencrypt/boulder/test"
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
const dnsLoopbackAddr = "127.0.0.1:4053"
|
||||
|
|
|
@ -7,8 +7,8 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/miekg/dns"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/golang.org/x/net/context"
|
||||
"github.com/miekg/dns"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// MockDNSResolver is a mock
|
||||
|
|
|
@ -9,9 +9,9 @@ import (
|
|||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/miekg/dns"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/golang.org/x/net/context"
|
||||
"github.com/letsencrypt/boulder/probs"
|
||||
"github.com/miekg/dns"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// DNSError wraps a DNS error with various relevant information
|
||||
|
|
|
@ -10,8 +10,8 @@ import (
|
|||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/miekg/dns"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/golang.org/x/net/context"
|
||||
"github.com/miekg/dns"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/letsencrypt/boulder/probs"
|
||||
)
|
||||
|
|
|
@ -23,14 +23,14 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd"
|
||||
cfsslConfig "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/config"
|
||||
cferr "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/errors"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/local"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/jmhodges/clock"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/miekg/pkcs11"
|
||||
"github.com/cactus/go-statsd-client/statsd"
|
||||
cfsslConfig "github.com/cloudflare/cfssl/config"
|
||||
cferr "github.com/cloudflare/cfssl/errors"
|
||||
"github.com/cloudflare/cfssl/ocsp"
|
||||
"github.com/cloudflare/cfssl/signer"
|
||||
"github.com/cloudflare/cfssl/signer/local"
|
||||
"github.com/jmhodges/clock"
|
||||
"github.com/miekg/pkcs11"
|
||||
|
||||
"github.com/letsencrypt/boulder/cmd"
|
||||
"github.com/letsencrypt/boulder/core"
|
||||
|
|
|
@ -16,10 +16,10 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
cfsslConfig "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/config"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/jmhodges/clock"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/golang.org/x/crypto/ocsp"
|
||||
cfsslConfig "github.com/cloudflare/cfssl/config"
|
||||
"github.com/cloudflare/cfssl/helpers"
|
||||
"github.com/jmhodges/clock"
|
||||
"golang.org/x/crypto/ocsp"
|
||||
|
||||
"github.com/letsencrypt/boulder/cmd"
|
||||
"github.com/letsencrypt/boulder/core"
|
||||
|
|
|
@ -16,9 +16,9 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/codegangsta/cli"
|
||||
gorp "github.com/letsencrypt/boulder/Godeps/_workspace/src/gopkg.in/gorp.v1"
|
||||
"github.com/cactus/go-statsd-client/statsd"
|
||||
"github.com/codegangsta/cli"
|
||||
gorp "gopkg.in/gorp.v1"
|
||||
|
||||
"github.com/letsencrypt/boulder/cmd"
|
||||
"github.com/letsencrypt/boulder/core"
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/codegangsta/cli"
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/letsencrypt/boulder/akamai"
|
||||
|
||||
"github.com/letsencrypt/boulder/cmd"
|
||||
|
|
|
@ -12,10 +12,10 @@ import (
|
|||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/helpers"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/jmhodges/clock"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/letsencrypt/pkcs11key"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/gopkg.in/gorp.v1"
|
||||
"github.com/cloudflare/cfssl/helpers"
|
||||
"github.com/jmhodges/clock"
|
||||
"github.com/letsencrypt/pkcs11key"
|
||||
"gopkg.in/gorp.v1"
|
||||
|
||||
"github.com/letsencrypt/boulder/ca"
|
||||
"github.com/letsencrypt/boulder/cmd"
|
||||
|
|
|
@ -8,7 +8,7 @@ package main
|
|||
import (
|
||||
"os"
|
||||
|
||||
ct "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/google/certificate-transparency/go"
|
||||
ct "github.com/google/certificate-transparency/go"
|
||||
|
||||
"github.com/letsencrypt/boulder/cmd"
|
||||
"github.com/letsencrypt/boulder/core"
|
||||
|
|
|
@ -8,12 +8,12 @@ package main
|
|||
import (
|
||||
"time"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/jmhodges/clock"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/gopkg.in/gorp.v1"
|
||||
"github.com/jmhodges/clock"
|
||||
"github.com/letsencrypt/boulder/bdns"
|
||||
"github.com/letsencrypt/boulder/metrics"
|
||||
"github.com/letsencrypt/boulder/policy"
|
||||
"github.com/letsencrypt/boulder/sa"
|
||||
"gopkg.in/gorp.v1"
|
||||
|
||||
"github.com/letsencrypt/boulder/cmd"
|
||||
blog "github.com/letsencrypt/boulder/log"
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/jmhodges/clock"
|
||||
"github.com/jmhodges/clock"
|
||||
|
||||
"github.com/letsencrypt/boulder/cmd"
|
||||
blog "github.com/letsencrypt/boulder/log"
|
||||
|
|
|
@ -10,9 +10,9 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
safebrowsing "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/letsencrypt/go-safe-browsing-api"
|
||||
"github.com/letsencrypt/boulder/cmd"
|
||||
"github.com/letsencrypt/boulder/va"
|
||||
safebrowsing "github.com/letsencrypt/go-safe-browsing-api"
|
||||
)
|
||||
|
||||
// newGoogleSafeBrowsing returns nil if the GoogleSafeBrowsing struct given is
|
||||
|
|
|
@ -8,7 +8,7 @@ package main
|
|||
import (
|
||||
"time"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/jmhodges/clock"
|
||||
"github.com/jmhodges/clock"
|
||||
|
||||
"github.com/letsencrypt/boulder/bdns"
|
||||
"github.com/letsencrypt/boulder/cmd"
|
||||
|
|
|
@ -10,9 +10,9 @@ import (
|
|||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/codegangsta/cli"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/facebookgo/httpdown"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/jmhodges/clock"
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/facebookgo/httpdown"
|
||||
"github.com/jmhodges/clock"
|
||||
|
||||
"github.com/letsencrypt/boulder/cmd"
|
||||
blog "github.com/letsencrypt/boulder/log"
|
||||
|
|
|
@ -14,13 +14,13 @@ It has these top-level messages:
|
|||
*/
|
||||
package caaChecker
|
||||
|
||||
import proto "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/golang/protobuf/proto"
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
import (
|
||||
context "github.com/letsencrypt/boulder/Godeps/_workspace/src/golang.org/x/net/context"
|
||||
grpc "github.com/letsencrypt/boulder/Godeps/_workspace/src/google.golang.org/grpc"
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
@ -153,16 +153,15 @@ var _CAAChecker_serviceDesc = grpc.ServiceDesc{
|
|||
}
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 167 bytes of a gzipped FileDescriptorProto
|
||||
// 156 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x12, 0x48, 0x4e, 0x4c, 0x74,
|
||||
0xce, 0x48, 0x4d, 0xce, 0x4e, 0x2d, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x57, 0xb2, 0xe7, 0x62,
|
||||
0x05, 0x0b, 0x08, 0x09, 0x71, 0xb1, 0xe4, 0x25, 0xe6, 0xa6, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0x70,
|
||||
0x06, 0x81, 0xd9, 0x42, 0x4a, 0x5c, 0x3c, 0x99, 0xc5, 0xc5, 0xa5, 0xa9, 0x45, 0x2e, 0xf9, 0xb9,
|
||||
0x89, 0x99, 0x79, 0x12, 0x4c, 0x60, 0x39, 0x14, 0x31, 0x25, 0x0b, 0x2e, 0xb6, 0xa0, 0xd4, 0xe2,
|
||||
0xd2, 0x9c, 0x12, 0x21, 0x09, 0x2e, 0xf6, 0x82, 0xa2, 0xd4, 0xe2, 0xd4, 0xbc, 0x12, 0xb0, 0x21,
|
||||
0x1c, 0x41, 0x30, 0xae, 0x90, 0x08, 0x17, 0x6b, 0x59, 0x62, 0x4e, 0x66, 0x0a, 0xd8, 0x00, 0x8e,
|
||||
0x20, 0x08, 0xc7, 0xc8, 0x98, 0x8b, 0xcb, 0xd9, 0xd1, 0x11, 0xea, 0x1c, 0x21, 0x55, 0x2e, 0x81,
|
||||
0x30, 0x90, 0xb0, 0x5b, 0x7e, 0x91, 0x27, 0xd0, 0xfc, 0xc4, 0xbc, 0xe4, 0x54, 0x21, 0x36, 0x3d,
|
||||
0xb0, 0xac, 0x14, 0xbb, 0x1e, 0xc4, 0x0a, 0x25, 0x06, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x17,
|
||||
0xdb, 0xa7, 0x3b, 0xc2, 0x00, 0x00, 0x00,
|
||||
0xce, 0x48, 0x4d, 0xce, 0x4e, 0x2d, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x57, 0xd2, 0xe6, 0x62,
|
||||
0x05, 0x0b, 0x08, 0xf1, 0x70, 0xb1, 0xe4, 0x25, 0xe6, 0xa6, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0x70,
|
||||
0x0a, 0x89, 0x70, 0xf1, 0x64, 0x16, 0x17, 0x97, 0xa6, 0x16, 0xb9, 0xe4, 0xe7, 0x26, 0x66, 0xe6,
|
||||
0x49, 0x30, 0x81, 0x44, 0x95, 0x34, 0xb8, 0xd8, 0x82, 0x52, 0x8b, 0x4b, 0x73, 0x4a, 0x84, 0xf8,
|
||||
0xb9, 0xd8, 0x0b, 0x8a, 0x52, 0x8b, 0x53, 0xf3, 0x4a, 0xc0, 0x1a, 0x38, 0x84, 0x78, 0xb9, 0x58,
|
||||
0xcb, 0x12, 0x73, 0x32, 0x53, 0xc0, 0x2a, 0x39, 0x8c, 0x8c, 0xb9, 0xb8, 0x9c, 0x1d, 0x1d, 0xa1,
|
||||
0x56, 0x09, 0xa9, 0x72, 0x09, 0x84, 0x81, 0x24, 0xdd, 0xf2, 0x8b, 0x3c, 0x81, 0xa6, 0x26, 0xe6,
|
||||
0x25, 0xa7, 0x0a, 0xb1, 0xe9, 0x81, 0x65, 0xa5, 0xd8, 0xf5, 0x20, 0x46, 0x2a, 0x31, 0x00, 0x02,
|
||||
0x00, 0x00, 0xff, 0xff, 0xa4, 0xed, 0x44, 0x02, 0x9e, 0x00, 0x00, 0x00,
|
||||
}
|
||||
|
|
|
@ -7,12 +7,12 @@ import (
|
|||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/jmhodges/clock"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/miekg/dns"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/golang.org/x/net/context"
|
||||
grpcCodes "github.com/letsencrypt/boulder/Godeps/_workspace/src/google.golang.org/grpc/codes"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/gopkg.in/yaml.v2"
|
||||
"github.com/cactus/go-statsd-client/statsd"
|
||||
"github.com/jmhodges/clock"
|
||||
"github.com/miekg/dns"
|
||||
"golang.org/x/net/context"
|
||||
grpcCodes "google.golang.org/grpc/codes"
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/letsencrypt/boulder/bdns"
|
||||
"github.com/letsencrypt/boulder/cmd"
|
||||
|
|
|
@ -3,8 +3,8 @@ package main
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/golang.org/x/net/context"
|
||||
"github.com/cactus/go-statsd-client/statsd"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/letsencrypt/boulder/bdns"
|
||||
pb "github.com/letsencrypt/boulder/cmd/caa-checker/proto"
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/golang.org/x/net/context"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/letsencrypt/boulder/cmd"
|
||||
pb "github.com/letsencrypt/boulder/cmd/caa-checker/proto"
|
||||
|
|
|
@ -18,9 +18,9 @@ import (
|
|||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/codegangsta/cli"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/jmhodges/clock"
|
||||
gorp "github.com/letsencrypt/boulder/Godeps/_workspace/src/gopkg.in/gorp.v1"
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/jmhodges/clock"
|
||||
gorp "gopkg.in/gorp.v1"
|
||||
|
||||
"github.com/letsencrypt/boulder/cmd"
|
||||
"github.com/letsencrypt/boulder/core"
|
||||
|
|
|
@ -17,7 +17,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/jmhodges/clock"
|
||||
"github.com/jmhodges/clock"
|
||||
|
||||
"github.com/letsencrypt/boulder/core"
|
||||
blog "github.com/letsencrypt/boulder/log"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
package cmd
|
||||
|
||||
import "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/jmhodges/clock"
|
||||
import "github.com/jmhodges/clock"
|
||||
|
||||
// Clock functions similarly to clock.Default(), but the returned value can be
|
||||
// changed using the FAKECLOCK environment variable if the 'integration' build
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/jmhodges/clock"
|
||||
"github.com/jmhodges/clock"
|
||||
blog "github.com/letsencrypt/boulder/log"
|
||||
)
|
||||
|
||||
|
|
|
@ -13,9 +13,9 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
cfsslConfig "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/config"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/letsencrypt/pkcs11key"
|
||||
cfsslConfig "github.com/cloudflare/cfssl/config"
|
||||
"github.com/letsencrypt/boulder/core"
|
||||
"github.com/letsencrypt/pkcs11key"
|
||||
)
|
||||
|
||||
// Config stores configuration parameters that applications
|
||||
|
|
|
@ -18,10 +18,10 @@ import (
|
|||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/codegangsta/cli"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/jmhodges/clock"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/gopkg.in/gorp.v1"
|
||||
"github.com/cactus/go-statsd-client/statsd"
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/jmhodges/clock"
|
||||
"gopkg.in/gorp.v1"
|
||||
|
||||
"github.com/letsencrypt/boulder/cmd"
|
||||
"github.com/letsencrypt/boulder/core"
|
||||
|
|
|
@ -20,10 +20,10 @@ import (
|
|||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/jmhodges/clock"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/square/go-jose"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/gopkg.in/gorp.v1"
|
||||
"github.com/cactus/go-statsd-client/statsd"
|
||||
"github.com/jmhodges/clock"
|
||||
"github.com/square/go-jose"
|
||||
"gopkg.in/gorp.v1"
|
||||
|
||||
"github.com/letsencrypt/boulder/core"
|
||||
blog "github.com/letsencrypt/boulder/log"
|
||||
|
|
|
@ -14,8 +14,8 @@ import (
|
|||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/codegangsta/cli"
|
||||
gorp "github.com/letsencrypt/boulder/Godeps/_workspace/src/gopkg.in/gorp.v1"
|
||||
"github.com/codegangsta/cli"
|
||||
gorp "gopkg.in/gorp.v1"
|
||||
|
||||
"github.com/letsencrypt/boulder/cmd"
|
||||
"github.com/letsencrypt/boulder/core"
|
||||
|
|
|
@ -16,11 +16,11 @@ import (
|
|||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd"
|
||||
cfocsp "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/facebookgo/httpdown"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/jmhodges/clock"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/golang.org/x/crypto/ocsp"
|
||||
"github.com/cactus/go-statsd-client/statsd"
|
||||
cfocsp "github.com/cloudflare/cfssl/ocsp"
|
||||
"github.com/facebookgo/httpdown"
|
||||
"github.com/jmhodges/clock"
|
||||
"golang.org/x/crypto/ocsp"
|
||||
|
||||
"github.com/letsencrypt/boulder/cmd"
|
||||
"github.com/letsencrypt/boulder/core"
|
||||
|
|
|
@ -9,11 +9,11 @@ import (
|
|||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd"
|
||||
cfocsp "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/golang.org/x/crypto/ocsp"
|
||||
"github.com/cactus/go-statsd-client/statsd"
|
||||
cfocsp "github.com/cloudflare/cfssl/ocsp"
|
||||
blog "github.com/letsencrypt/boulder/log"
|
||||
"github.com/letsencrypt/boulder/test"
|
||||
"golang.org/x/crypto/ocsp"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
|
@ -14,10 +14,10 @@ import (
|
|||
"path"
|
||||
"time"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/jmhodges/clock"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/golang.org/x/crypto/ocsp"
|
||||
gorp "github.com/letsencrypt/boulder/Godeps/_workspace/src/gopkg.in/gorp.v1"
|
||||
"github.com/cactus/go-statsd-client/statsd"
|
||||
"github.com/jmhodges/clock"
|
||||
"golang.org/x/crypto/ocsp"
|
||||
gorp "gopkg.in/gorp.v1"
|
||||
|
||||
"github.com/letsencrypt/boulder/akamai"
|
||||
"github.com/letsencrypt/boulder/cmd"
|
||||
|
|
|
@ -6,9 +6,9 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/jmhodges/clock"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/gopkg.in/gorp.v1"
|
||||
"github.com/cactus/go-statsd-client/statsd"
|
||||
"github.com/jmhodges/clock"
|
||||
"gopkg.in/gorp.v1"
|
||||
|
||||
"github.com/letsencrypt/boulder/cmd"
|
||||
"github.com/letsencrypt/boulder/core"
|
||||
|
|
|
@ -11,8 +11,8 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/codegangsta/cli"
|
||||
"github.com/cactus/go-statsd-client/statsd"
|
||||
"github.com/codegangsta/cli"
|
||||
|
||||
"github.com/letsencrypt/boulder/cmd"
|
||||
"github.com/letsencrypt/boulder/core"
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/jmhodges/clock"
|
||||
"github.com/jmhodges/clock"
|
||||
"github.com/letsencrypt/boulder/core"
|
||||
|
||||
blog "github.com/letsencrypt/boulder/log"
|
||||
|
|
|
@ -12,8 +12,8 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/codegangsta/cli"
|
||||
_ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/go-sql-driver/mysql"
|
||||
"github.com/codegangsta/cli"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/letsencrypt/boulder/sa"
|
||||
|
||||
"github.com/letsencrypt/boulder/cmd"
|
||||
|
|
|
@ -11,7 +11,7 @@ package main
|
|||
import (
|
||||
"flag"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/streadway/amqp"
|
||||
"github.com/streadway/amqp"
|
||||
|
||||
"github.com/letsencrypt/boulder/cmd"
|
||||
)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/gopkg.in/yaml.v2"
|
||||
"gopkg.in/yaml.v2"
|
||||
"io/ioutil"
|
||||
"time"
|
||||
)
|
||||
|
|
|
@ -38,10 +38,10 @@ import (
|
|||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/go-sql-driver/mysql"
|
||||
"github.com/go-sql-driver/mysql"
|
||||
|
||||
cfsslLog "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/log"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/codegangsta/cli"
|
||||
cfsslLog "github.com/cloudflare/cfssl/log"
|
||||
"github.com/codegangsta/cli"
|
||||
|
||||
"github.com/letsencrypt/boulder/core"
|
||||
blog "github.com/letsencrypt/boulder/log"
|
||||
|
|
|
@ -14,9 +14,9 @@ import (
|
|||
|
||||
"github.com/letsencrypt/boulder/cmd"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/codegangsta/cli"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/letsencrypt/pkcs11key"
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/golang.org/x/crypto/ocsp"
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/letsencrypt/pkcs11key"
|
||||
"golang.org/x/crypto/ocsp"
|
||||
)
|
||||
|
||||
// PKCS11Config defines how to load a module for an HSM.
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/letsencrypt/pkcs11key"
|
||||
"github.com/letsencrypt/pkcs11key"
|
||||
)
|
||||
|
||||
const pkcs11FileName = "pkcs11.json"
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/square/go-jose"
|
||||
"github.com/square/go-jose"
|
||||
)
|
||||
|
||||
func newChallenge(challengeType string, accountKey *jose.JsonWebKey) Challenge {
|
||||
|
|
|
@ -11,8 +11,8 @@ import (
|
|||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/square/go-jose"
|
||||
"github.com/letsencrypt/boulder/test"
|
||||
"github.com/square/go-jose"
|
||||
)
|
||||
|
||||
// challenges.go
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
"net/http"
|
||||
"time"
|
||||
|
||||
jose "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/square/go-jose"
|
||||
jose "github.com/square/go-jose"
|
||||
)
|
||||
|
||||
// A WebFrontEnd object supplies methods that can be hooked into
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue