*: migrate Godeps to vendor/
parent
e9b9b228e7
commit
bd832e5b0a
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"ImportPath": "github.com/coreos/etcd",
|
||||
"GoVersion": "go1.5.1",
|
||||
"GoVersion": "go1.6",
|
||||
"GodepVersion": "v60",
|
||||
"Packages": [
|
||||
"./..."
|
||||
],
|
||||
|
@ -8,7 +9,7 @@
|
|||
{
|
||||
"ImportPath": "bitbucket.org/ww/goautoneg",
|
||||
"Comment": "null-5",
|
||||
"Rev": "75cd24fc2f2c2a2088577d12123ddee5f54e0675"
|
||||
"Rev": "'75cd24fc2f2c2a2088577d12123ddee5f54e0675'"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/akrennmair/gopcap",
|
||||
|
@ -186,6 +187,10 @@
|
|||
"ImportPath": "golang.org/x/net/http2",
|
||||
"Rev": "6acef71eb69611914f7a30939ea9f6e194c78172"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/net/http2/hpack",
|
||||
"Rev": "6acef71eb69611914f7a30939ea9f6e194c78172"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/net/internal/timeseries",
|
||||
"Rev": "6acef71eb69611914f7a30939ea9f6e194c78172"
|
||||
|
@ -202,6 +207,34 @@
|
|||
"ImportPath": "google.golang.org/grpc",
|
||||
"Rev": "b88c12e7caf74af3928de99a864aaa9916fa5aad"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/grpc/codes",
|
||||
"Rev": "b88c12e7caf74af3928de99a864aaa9916fa5aad"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/grpc/credentials",
|
||||
"Rev": "b88c12e7caf74af3928de99a864aaa9916fa5aad"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/grpc/grpclog",
|
||||
"Rev": "b88c12e7caf74af3928de99a864aaa9916fa5aad"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/grpc/metadata",
|
||||
"Rev": "b88c12e7caf74af3928de99a864aaa9916fa5aad"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/grpc/naming",
|
||||
"Rev": "b88c12e7caf74af3928de99a864aaa9916fa5aad"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/grpc/peer",
|
||||
"Rev": "b88c12e7caf74af3928de99a864aaa9916fa5aad"
|
||||
},
|
||||
{
|
||||
"ImportPath": "google.golang.org/grpc/transport",
|
||||
"Rev": "b88c12e7caf74af3928de99a864aaa9916fa5aad"
|
||||
},
|
||||
{
|
||||
"ImportPath": "gopkg.in/cheggaaa/pb.v1",
|
||||
"Comment": "v1.0.1",
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
/pkg
|
||||
/bin
|
|
@ -1,33 +0,0 @@
|
|||
package goautoneg
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var chrome = "application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"
|
||||
|
||||
func TestParseAccept(t *testing.T) {
|
||||
alternatives := []string{"text/html", "image/png"}
|
||||
content_type := Negotiate(chrome, alternatives)
|
||||
if content_type != "image/png" {
|
||||
t.Errorf("got %s expected image/png", content_type)
|
||||
}
|
||||
|
||||
alternatives = []string{"text/html", "text/plain", "text/n3"}
|
||||
content_type = Negotiate(chrome, alternatives)
|
||||
if content_type != "text/html" {
|
||||
t.Errorf("got %s expected text/html", content_type)
|
||||
}
|
||||
|
||||
alternatives = []string{"text/n3", "text/plain"}
|
||||
content_type = Negotiate(chrome, alternatives)
|
||||
if content_type != "text/plain" {
|
||||
t.Errorf("got %s expected text/plain", content_type)
|
||||
}
|
||||
|
||||
alternatives = []string{"text/n3", "application/rdf+xml"}
|
||||
content_type = Negotiate(chrome, alternatives)
|
||||
if content_type != "text/n3" {
|
||||
t.Errorf("got %s expected text/n3", content_type)
|
||||
}
|
||||
}
|
|
@ -1,247 +0,0 @@
|
|||
package pcap
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var testSimpleTcpPacket *Packet = &Packet{
|
||||
Data: []byte{
|
||||
0x00, 0x00, 0x0c, 0x9f, 0xf0, 0x20, 0xbc, 0x30, 0x5b, 0xe8, 0xd3, 0x49,
|
||||
0x08, 0x00, 0x45, 0x00, 0x01, 0xa4, 0x39, 0xdf, 0x40, 0x00, 0x40, 0x06,
|
||||
0x55, 0x5a, 0xac, 0x11, 0x51, 0x49, 0xad, 0xde, 0xfe, 0xe1, 0xc5, 0xf7,
|
||||
0x00, 0x50, 0xc5, 0x7e, 0x0e, 0x48, 0x49, 0x07, 0x42, 0x32, 0x80, 0x18,
|
||||
0x00, 0x73, 0xab, 0xb1, 0x00, 0x00, 0x01, 0x01, 0x08, 0x0a, 0x03, 0x77,
|
||||
0x37, 0x9c, 0x42, 0x77, 0x5e, 0x3a, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x20,
|
||||
0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f,
|
||||
0x73, 0x74, 0x3a, 0x20, 0x77, 0x77, 0x77, 0x2e, 0x66, 0x69, 0x73, 0x68,
|
||||
0x2e, 0x63, 0x6f, 0x6d, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x6b, 0x65, 0x65, 0x70, 0x2d, 0x61,
|
||||
0x6c, 0x69, 0x76, 0x65, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d, 0x41,
|
||||
0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c,
|
||||
0x61, 0x2f, 0x35, 0x2e, 0x30, 0x20, 0x28, 0x58, 0x31, 0x31, 0x3b, 0x20,
|
||||
0x4c, 0x69, 0x6e, 0x75, 0x78, 0x20, 0x78, 0x38, 0x36, 0x5f, 0x36, 0x34,
|
||||
0x29, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x57, 0x65, 0x62, 0x4b, 0x69,
|
||||
0x74, 0x2f, 0x35, 0x33, 0x35, 0x2e, 0x32, 0x20, 0x28, 0x4b, 0x48, 0x54,
|
||||
0x4d, 0x4c, 0x2c, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x47, 0x65, 0x63,
|
||||
0x6b, 0x6f, 0x29, 0x20, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x2f, 0x31,
|
||||
0x35, 0x2e, 0x30, 0x2e, 0x38, 0x37, 0x34, 0x2e, 0x31, 0x32, 0x31, 0x20,
|
||||
0x53, 0x61, 0x66, 0x61, 0x72, 0x69, 0x2f, 0x35, 0x33, 0x35, 0x2e, 0x32,
|
||||
0x0d, 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20, 0x74, 0x65,
|
||||
0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c,
|
||||
0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x68, 0x74, 0x6d,
|
||||
0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x6d, 0x6c, 0x3b, 0x71, 0x3d,
|
||||
0x30, 0x2e, 0x39, 0x2c, 0x2a, 0x2f, 0x2a, 0x3b, 0x71, 0x3d, 0x30, 0x2e,
|
||||
0x38, 0x0d, 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x45, 0x6e,
|
||||
0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x67, 0x7a, 0x69, 0x70,
|
||||
0x2c, 0x64, 0x65, 0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64, 0x63,
|
||||
0x68, 0x0d, 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x4c, 0x61,
|
||||
0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x3a, 0x20, 0x65, 0x6e, 0x2d, 0x55,
|
||||
0x53, 0x2c, 0x65, 0x6e, 0x3b, 0x71, 0x3d, 0x30, 0x2e, 0x38, 0x0d, 0x0a,
|
||||
0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x43, 0x68, 0x61, 0x72, 0x73,
|
||||
0x65, 0x74, 0x3a, 0x20, 0x49, 0x53, 0x4f, 0x2d, 0x38, 0x38, 0x35, 0x39,
|
||||
0x2d, 0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x3b, 0x71, 0x3d, 0x30,
|
||||
0x2e, 0x37, 0x2c, 0x2a, 0x3b, 0x71, 0x3d, 0x30, 0x2e, 0x33, 0x0d, 0x0a,
|
||||
0x0d, 0x0a,
|
||||
}}
|
||||
|
||||
func BenchmarkDecodeSimpleTcpPacket(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
testSimpleTcpPacket.Decode()
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeSimpleTcpPacket(t *testing.T) {
|
||||
p := testSimpleTcpPacket
|
||||
p.Decode()
|
||||
if p.DestMac != 0x00000c9ff020 {
|
||||
t.Error("Dest mac", p.DestMac)
|
||||
}
|
||||
if p.SrcMac != 0xbc305be8d349 {
|
||||
t.Error("Src mac", p.SrcMac)
|
||||
}
|
||||
if len(p.Headers) != 2 {
|
||||
t.Error("Incorrect number of headers", len(p.Headers))
|
||||
return
|
||||
}
|
||||
if ip, ipOk := p.Headers[0].(*Iphdr); ipOk {
|
||||
if ip.Version != 4 {
|
||||
t.Error("ip Version", ip.Version)
|
||||
}
|
||||
if ip.Ihl != 5 {
|
||||
t.Error("ip header length", ip.Ihl)
|
||||
}
|
||||
if ip.Tos != 0 {
|
||||
t.Error("ip TOS", ip.Tos)
|
||||
}
|
||||
if ip.Length != 420 {
|
||||
t.Error("ip Length", ip.Length)
|
||||
}
|
||||
if ip.Id != 14815 {
|
||||
t.Error("ip ID", ip.Id)
|
||||
}
|
||||
if ip.Flags != 0x02 {
|
||||
t.Error("ip Flags", ip.Flags)
|
||||
}
|
||||
if ip.FragOffset != 0 {
|
||||
t.Error("ip Fragoffset", ip.FragOffset)
|
||||
}
|
||||
if ip.Ttl != 64 {
|
||||
t.Error("ip TTL", ip.Ttl)
|
||||
}
|
||||
if ip.Protocol != 6 {
|
||||
t.Error("ip Protocol", ip.Protocol)
|
||||
}
|
||||
if ip.Checksum != 0x555A {
|
||||
t.Error("ip Checksum", ip.Checksum)
|
||||
}
|
||||
if !bytes.Equal(ip.SrcIp, []byte{172, 17, 81, 73}) {
|
||||
t.Error("ip Src", ip.SrcIp)
|
||||
}
|
||||
if !bytes.Equal(ip.DestIp, []byte{173, 222, 254, 225}) {
|
||||
t.Error("ip Dest", ip.DestIp)
|
||||
}
|
||||
if tcp, tcpOk := p.Headers[1].(*Tcphdr); tcpOk {
|
||||
if tcp.SrcPort != 50679 {
|
||||
t.Error("tcp srcport", tcp.SrcPort)
|
||||
}
|
||||
if tcp.DestPort != 80 {
|
||||
t.Error("tcp destport", tcp.DestPort)
|
||||
}
|
||||
if tcp.Seq != 0xc57e0e48 {
|
||||
t.Error("tcp seq", tcp.Seq)
|
||||
}
|
||||
if tcp.Ack != 0x49074232 {
|
||||
t.Error("tcp ack", tcp.Ack)
|
||||
}
|
||||
if tcp.DataOffset != 8 {
|
||||
t.Error("tcp dataoffset", tcp.DataOffset)
|
||||
}
|
||||
if tcp.Flags != 0x18 {
|
||||
t.Error("tcp flags", tcp.Flags)
|
||||
}
|
||||
if tcp.Window != 0x73 {
|
||||
t.Error("tcp window", tcp.Window)
|
||||
}
|
||||
if tcp.Checksum != 0xabb1 {
|
||||
t.Error("tcp checksum", tcp.Checksum)
|
||||
}
|
||||
if tcp.Urgent != 0 {
|
||||
t.Error("tcp urgent", tcp.Urgent)
|
||||
}
|
||||
} else {
|
||||
t.Error("Second header is not TCP header")
|
||||
}
|
||||
} else {
|
||||
t.Error("First header is not IP header")
|
||||
}
|
||||
if string(p.Payload) != "GET / HTTP/1.1\r\nHost: www.fish.com\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Encoding: gzip,deflate,sdch\r\nAccept-Language: en-US,en;q=0.8\r\nAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3\r\n\r\n" {
|
||||
t.Error("--- PAYLOAD STRING ---\n", string(p.Payload), "\n--- PAYLOAD BYTES ---\n", p.Payload)
|
||||
}
|
||||
}
|
||||
|
||||
// Makes sure packet payload doesn't display the 6 trailing null of this packet
|
||||
// as part of the payload. They're actually the ethernet trailer.
|
||||
func TestDecodeSmallTcpPacketHasEmptyPayload(t *testing.T) {
|
||||
p := &Packet{
|
||||
// This packet is only 54 bits (an empty TCP RST), thus 6 trailing null
|
||||
// bytes are added by the ethernet layer to make it the minimum packet size.
|
||||
Data: []byte{
|
||||
0xbc, 0x30, 0x5b, 0xe8, 0xd3, 0x49, 0xb8, 0xac, 0x6f, 0x92, 0xd5, 0xbf,
|
||||
0x08, 0x00, 0x45, 0x00, 0x00, 0x28, 0x00, 0x00, 0x40, 0x00, 0x40, 0x06,
|
||||
0x3f, 0x9f, 0xac, 0x11, 0x51, 0xc5, 0xac, 0x11, 0x51, 0x49, 0x00, 0x63,
|
||||
0x9a, 0xef, 0x00, 0x00, 0x00, 0x00, 0x2e, 0xc1, 0x27, 0x83, 0x50, 0x14,
|
||||
0x00, 0x00, 0xc3, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
}}
|
||||
p.Decode()
|
||||
if p.Payload == nil {
|
||||
t.Error("Nil payload")
|
||||
}
|
||||
if len(p.Payload) != 0 {
|
||||
t.Error("Non-empty payload:", p.Payload)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeVlanPacket(t *testing.T) {
|
||||
p := &Packet{
|
||||
Data: []byte{
|
||||
0x00, 0x10, 0xdb, 0xff, 0x10, 0x00, 0x00, 0x15, 0x2c, 0x9d, 0xcc, 0x00, 0x81, 0x00, 0x01, 0xf7,
|
||||
0x08, 0x00, 0x45, 0x00, 0x00, 0x28, 0x29, 0x8d, 0x40, 0x00, 0x7d, 0x06, 0x83, 0xa0, 0xac, 0x1b,
|
||||
0xca, 0x8e, 0x45, 0x16, 0x94, 0xe2, 0xd4, 0x0a, 0x00, 0x50, 0xdf, 0xab, 0x9c, 0xc6, 0xcd, 0x1e,
|
||||
0xe5, 0xd1, 0x50, 0x10, 0x01, 0x00, 0x5a, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
}}
|
||||
p.Decode()
|
||||
if p.Type != TYPE_VLAN {
|
||||
t.Error("Didn't detect vlan")
|
||||
}
|
||||
if len(p.Headers) != 3 {
|
||||
t.Error("Incorrect number of headers:", len(p.Headers))
|
||||
for i, h := range p.Headers {
|
||||
t.Errorf("Header %d: %#v", i, h)
|
||||
}
|
||||
t.FailNow()
|
||||
}
|
||||
if _, ok := p.Headers[0].(*Vlanhdr); !ok {
|
||||
t.Errorf("First header isn't vlan: %q", p.Headers[0])
|
||||
}
|
||||
if _, ok := p.Headers[1].(*Iphdr); !ok {
|
||||
t.Errorf("Second header isn't IP: %q", p.Headers[1])
|
||||
}
|
||||
if _, ok := p.Headers[2].(*Tcphdr); !ok {
|
||||
t.Errorf("Third header isn't TCP: %q", p.Headers[2])
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeFuzzFallout(t *testing.T) {
|
||||
testData := []struct {
|
||||
Data []byte
|
||||
}{
|
||||
{[]byte("000000000000\x81\x000")},
|
||||
{[]byte("000000000000\x81\x00000")},
|
||||
{[]byte("000000000000\x86\xdd0")},
|
||||
{[]byte("000000000000\b\x000")},
|
||||
{[]byte("000000000000\b\x060")},
|
||||
{[]byte{}},
|
||||
{[]byte("000000000000\b\x0600000000")},
|
||||
{[]byte("000000000000\x86\xdd000000\x01000000000000000000000000000000000")},
|
||||
{[]byte("000000000000\x81\x0000\b\x0600000000")},
|
||||
{[]byte("000000000000\b\x00n0000000000000000000")},
|
||||
{[]byte("000000000000\x86\xdd000000\x0100000000000000000000000000000000000")},
|
||||
{[]byte("000000000000\x81\x0000\b\x00g0000000000000000000")},
|
||||
//{[]byte()},
|
||||
{[]byte("000000000000\b\x00400000000\x110000000000")},
|
||||
{[]byte("0nMء\xfe\x13\x13\x81\x00gr\b\x00&x\xc9\xe5b'\x1e0\x00\x04\x00\x0020596224")},
|
||||
{[]byte("000000000000\x81\x0000\b\x00400000000\x110000000000")},
|
||||
{[]byte("000000000000\b\x00000000000\x0600\xff0000000")},
|
||||
{[]byte("000000000000\x86\xdd000000\x06000000000000000000000000000000000")},
|
||||
{[]byte("000000000000\x81\x0000\b\x00000000000\x0600b0000000")},
|
||||
{[]byte("000000000000\x81\x0000\b\x00400000000\x060000000000")},
|
||||
{[]byte("000000000000\x86\xdd000000\x11000000000000000000000000000000000")},
|
||||
{[]byte("000000000000\x86\xdd000000\x0600000000000000000000000000000000000000000000M")},
|
||||
{[]byte("000000000000\b\x00500000000\x0600000000000")},
|
||||
{[]byte("0nM\xd80\xfe\x13\x13\x81\x00gr\b\x00&x\xc9\xe5b'\x1e0\x00\x04\x00\x0020596224")},
|
||||
}
|
||||
|
||||
for _, entry := range testData {
|
||||
pkt := &Packet{
|
||||
Time: time.Now(),
|
||||
Caplen: uint32(len(entry.Data)),
|
||||
Len: uint32(len(entry.Data)),
|
||||
Data: entry.Data,
|
||||
}
|
||||
|
||||
pkt.Decode()
|
||||
/*
|
||||
func() {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
t.Fatalf("%d. %q failed: %v", idx, string(entry.Data), err)
|
||||
}
|
||||
}()
|
||||
pkt.Decode()
|
||||
}()
|
||||
*/
|
||||
}
|
||||
}
|
49
Godeps/_workspace/src/github.com/akrennmair/gopcap/tools/benchmark/benchmark.go
generated
vendored
49
Godeps/_workspace/src/github.com/akrennmair/gopcap/tools/benchmark/benchmark.go
generated
vendored
|
@ -1,49 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime/pprof"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/akrennmair/gopcap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var filename *string = flag.String("file", "", "filename")
|
||||
var decode *bool = flag.Bool("d", false, "If true, decode each packet")
|
||||
var cpuprofile *string = flag.String("cpuprofile", "", "filename")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
h, err := pcap.Openoffline(*filename)
|
||||
if err != nil {
|
||||
fmt.Printf("Couldn't create pcap reader: %v", err)
|
||||
}
|
||||
|
||||
if *cpuprofile != "" {
|
||||
if out, err := os.Create(*cpuprofile); err == nil {
|
||||
pprof.StartCPUProfile(out)
|
||||
defer func() {
|
||||
pprof.StopCPUProfile()
|
||||
out.Close()
|
||||
}()
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
i, nilPackets := 0, 0
|
||||
start := time.Now()
|
||||
for pkt, code := h.NextEx(); code != -2; pkt, code = h.NextEx() {
|
||||
if pkt == nil {
|
||||
nilPackets++
|
||||
} else if *decode {
|
||||
pkt.Decode()
|
||||
}
|
||||
i++
|
||||
}
|
||||
duration := time.Since(start)
|
||||
fmt.Printf("Took %v to process %v packets, %v per packet, %d nil packets\n", duration, i, duration/time.Duration(i), nilPackets)
|
||||
}
|
|
@ -1,96 +0,0 @@
|
|||
package main
|
||||
|
||||
// Parses a pcap file, writes it back to disk, then verifies the files
|
||||
// are the same.
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/akrennmair/gopcap"
|
||||
)
|
||||
|
||||
var input *string = flag.String("input", "", "input file")
|
||||
var output *string = flag.String("output", "", "output file")
|
||||
var decode *bool = flag.Bool("decode", false, "print decoded packets")
|
||||
|
||||
func copyPcap(dest, src string) {
|
||||
f, err := os.Open(src)
|
||||
if err != nil {
|
||||
fmt.Printf("couldn't open %q: %v\n", src, err)
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
reader, err := pcap.NewReader(bufio.NewReader(f))
|
||||
if err != nil {
|
||||
fmt.Printf("couldn't create reader: %v\n", err)
|
||||
return
|
||||
}
|
||||
w, err := os.Create(dest)
|
||||
if err != nil {
|
||||
fmt.Printf("couldn't open %q: %v\n", dest, err)
|
||||
return
|
||||
}
|
||||
defer w.Close()
|
||||
buf := bufio.NewWriter(w)
|
||||
writer, err := pcap.NewWriter(buf, &reader.Header)
|
||||
if err != nil {
|
||||
fmt.Printf("couldn't create writer: %v\n", err)
|
||||
return
|
||||
}
|
||||
for {
|
||||
pkt := reader.Next()
|
||||
if pkt == nil {
|
||||
break
|
||||
}
|
||||
if *decode {
|
||||
pkt.Decode()
|
||||
fmt.Println(pkt.String())
|
||||
}
|
||||
writer.Write(pkt)
|
||||
}
|
||||
buf.Flush()
|
||||
}
|
||||
|
||||
func check(dest, src string) {
|
||||
f, err := os.Open(src)
|
||||
if err != nil {
|
||||
fmt.Printf("couldn't open %q: %v\n", src, err)
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
freader := bufio.NewReader(f)
|
||||
|
||||
g, err := os.Open(dest)
|
||||
if err != nil {
|
||||
fmt.Printf("couldn't open %q: %v\n", src, err)
|
||||
return
|
||||
}
|
||||
defer g.Close()
|
||||
greader := bufio.NewReader(g)
|
||||
|
||||
for {
|
||||
fb, ferr := freader.ReadByte()
|
||||
gb, gerr := greader.ReadByte()
|
||||
|
||||
if ferr == io.EOF && gerr == io.EOF {
|
||||
break
|
||||
}
|
||||
if fb == gb {
|
||||
continue
|
||||
}
|
||||
fmt.Println("FAIL")
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("PASS")
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
copyPcap(*output, *input)
|
||||
check(*output, *input)
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/akrennmair/gopcap"
|
||||
)
|
||||
|
||||
func min(x uint32, y uint32) uint32 {
|
||||
if x < y {
|
||||
return x
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
||||
func main() {
|
||||
var device *string = flag.String("d", "", "device")
|
||||
var file *string = flag.String("r", "", "file")
|
||||
var expr *string = flag.String("e", "", "filter expression")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
var h *pcap.Pcap
|
||||
var err error
|
||||
|
||||
ifs, err := pcap.Findalldevs()
|
||||
if len(ifs) == 0 {
|
||||
fmt.Printf("Warning: no devices found : %s\n", err)
|
||||
} else {
|
||||
for i := 0; i < len(ifs); i++ {
|
||||
fmt.Printf("dev %d: %s (%s)\n", i+1, ifs[i].Name, ifs[i].Description)
|
||||
}
|
||||
}
|
||||
|
||||
if *device != "" {
|
||||
h, err = pcap.Openlive(*device, 65535, true, 0)
|
||||
if h == nil {
|
||||
fmt.Printf("Openlive(%s) failed: %s\n", *device, err)
|
||||
return
|
||||
}
|
||||
} else if *file != "" {
|
||||
h, err = pcap.Openoffline(*file)
|
||||
if h == nil {
|
||||
fmt.Printf("Openoffline(%s) failed: %s\n", *file, err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("usage: pcaptest [-d <device> | -r <file>]\n")
|
||||
return
|
||||
}
|
||||
defer h.Close()
|
||||
|
||||
fmt.Printf("pcap version: %s\n", pcap.Version())
|
||||
|
||||
if *expr != "" {
|
||||
fmt.Printf("Setting filter: %s\n", *expr)
|
||||
err := h.Setfilter(*expr)
|
||||
if err != nil {
|
||||
fmt.Printf("Warning: setting filter failed: %s\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
for pkt := h.Next(); pkt != nil; pkt = h.Next() {
|
||||
fmt.Printf("time: %d.%06d (%s) caplen: %d len: %d\nData:",
|
||||
int64(pkt.Time.Second()), int64(pkt.Time.Nanosecond()),
|
||||
time.Unix(int64(pkt.Time.Second()), 0).String(), int64(pkt.Caplen), int64(pkt.Len))
|
||||
for i := uint32(0); i < pkt.Caplen; i++ {
|
||||
if i%32 == 0 {
|
||||
fmt.Printf("\n")
|
||||
}
|
||||
if 32 <= pkt.Data[i] && pkt.Data[i] <= 126 {
|
||||
fmt.Printf("%c", pkt.Data[i])
|
||||
} else {
|
||||
fmt.Printf(".")
|
||||
}
|
||||
}
|
||||
fmt.Printf("\n\n")
|
||||
}
|
||||
|
||||
}
|
|
@ -1,121 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/akrennmair/gopcap"
|
||||
)
|
||||
|
||||
const (
|
||||
TYPE_IP = 0x0800
|
||||
TYPE_ARP = 0x0806
|
||||
TYPE_IP6 = 0x86DD
|
||||
|
||||
IP_ICMP = 1
|
||||
IP_INIP = 4
|
||||
IP_TCP = 6
|
||||
IP_UDP = 17
|
||||
)
|
||||
|
||||
var out *bufio.Writer
|
||||
var errout *bufio.Writer
|
||||
|
||||
func main() {
|
||||
var device *string = flag.String("i", "", "interface")
|
||||
var snaplen *int = flag.Int("s", 65535, "snaplen")
|
||||
var hexdump *bool = flag.Bool("X", false, "hexdump")
|
||||
expr := ""
|
||||
|
||||
out = bufio.NewWriter(os.Stdout)
|
||||
errout = bufio.NewWriter(os.Stderr)
|
||||
|
||||
flag.Usage = func() {
|
||||
fmt.Fprintf(errout, "usage: %s [ -i interface ] [ -s snaplen ] [ -X ] [ expression ]\n", os.Args[0])
|
||||
errout.Flush()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
flag.Parse()
|
||||
|
||||
if len(flag.Args()) > 0 {
|
||||
expr = flag.Arg(0)
|
||||
}
|
||||
|
||||
if *device == "" {
|
||||
devs, err := pcap.Findalldevs()
|
||||
if err != nil {
|
||||
fmt.Fprintf(errout, "tcpdump: couldn't find any devices: %s\n", err)
|
||||
}
|
||||
if 0 == len(devs) {
|
||||
flag.Usage()
|
||||
}
|
||||
*device = devs[0].Name
|
||||
}
|
||||
|
||||
h, err := pcap.Openlive(*device, int32(*snaplen), true, 0)
|
||||
if h == nil {
|
||||
fmt.Fprintf(errout, "tcpdump: %s\n", err)
|
||||
errout.Flush()
|
||||
return
|
||||
}
|
||||
defer h.Close()
|
||||
|
||||
if expr != "" {
|
||||
ferr := h.Setfilter(expr)
|
||||
if ferr != nil {
|
||||
fmt.Fprintf(out, "tcpdump: %s\n", ferr)
|
||||
out.Flush()
|
||||
}
|
||||
}
|
||||
|
||||
for pkt := h.Next(); pkt != nil; pkt = h.Next() {
|
||||
pkt.Decode()
|
||||
fmt.Fprintf(out, "%s\n", pkt.String())
|
||||
if *hexdump {
|
||||
Hexdump(pkt)
|
||||
}
|
||||
out.Flush()
|
||||
}
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func Hexdump(pkt *pcap.Packet) {
|
||||
for i := 0; i < len(pkt.Data); i += 16 {
|
||||
Dumpline(uint32(i), pkt.Data[i:min(i+16, len(pkt.Data))])
|
||||
}
|
||||
}
|
||||
|
||||
func Dumpline(addr uint32, line []byte) {
|
||||
fmt.Fprintf(out, "\t0x%04x: ", int32(addr))
|
||||
var i uint16
|
||||
for i = 0; i < 16 && i < uint16(len(line)); i++ {
|
||||
if i%2 == 0 {
|
||||
out.WriteString(" ")
|
||||
}
|
||||
fmt.Fprintf(out, "%02x", line[i])
|
||||
}
|
||||
for j := i; j <= 16; j++ {
|
||||
if j%2 == 0 {
|
||||
out.WriteString(" ")
|
||||
}
|
||||
out.WriteString(" ")
|
||||
}
|
||||
out.WriteString(" ")
|
||||
for i = 0; i < 16 && i < uint16(len(line)); i++ {
|
||||
if line[i] >= 32 && line[i] <= 126 {
|
||||
fmt.Fprintf(out, "%c", line[i])
|
||||
} else {
|
||||
out.WriteString(".")
|
||||
}
|
||||
}
|
||||
out.WriteString("\n")
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
package quantile
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkInsertTargeted(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
|
||||
s := NewTargeted(Targets)
|
||||
b.ResetTimer()
|
||||
for i := float64(0); i < float64(b.N); i++ {
|
||||
s.Insert(i)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInsertTargetedSmallEpsilon(b *testing.B) {
|
||||
s := NewTargeted(TargetsSmallEpsilon)
|
||||
b.ResetTimer()
|
||||
for i := float64(0); i < float64(b.N); i++ {
|
||||
s.Insert(i)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInsertBiased(b *testing.B) {
|
||||
s := NewLowBiased(0.01)
|
||||
b.ResetTimer()
|
||||
for i := float64(0); i < float64(b.N); i++ {
|
||||
s.Insert(i)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInsertBiasedSmallEpsilon(b *testing.B) {
|
||||
s := NewLowBiased(0.0001)
|
||||
b.ResetTimer()
|
||||
for i := float64(0); i < float64(b.N); i++ {
|
||||
s.Insert(i)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkQuery(b *testing.B) {
|
||||
s := NewTargeted(Targets)
|
||||
for i := float64(0); i < 1e6; i++ {
|
||||
s.Insert(i)
|
||||
}
|
||||
b.ResetTimer()
|
||||
n := float64(b.N)
|
||||
for i := float64(0); i < n; i++ {
|
||||
s.Query(i / n)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkQuerySmallEpsilon(b *testing.B) {
|
||||
s := NewTargeted(TargetsSmallEpsilon)
|
||||
for i := float64(0); i < 1e6; i++ {
|
||||
s.Insert(i)
|
||||
}
|
||||
b.ResetTimer()
|
||||
n := float64(b.N)
|
||||
for i := float64(0); i < n; i++ {
|
||||
s.Query(i / n)
|
||||
}
|
||||
}
|
|
@ -1,121 +0,0 @@
|
|||
// +build go1.1
|
||||
|
||||
package quantile_test
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/beorn7/perks/quantile"
|
||||
)
|
||||
|
||||
func Example_simple() {
|
||||
ch := make(chan float64)
|
||||
go sendFloats(ch)
|
||||
|
||||
// Compute the 50th, 90th, and 99th percentile.
|
||||
q := quantile.NewTargeted(map[float64]float64{
|
||||
0.50: 0.005,
|
||||
0.90: 0.001,
|
||||
0.99: 0.0001,
|
||||
})
|
||||
for v := range ch {
|
||||
q.Insert(v)
|
||||
}
|
||||
|
||||
fmt.Println("perc50:", q.Query(0.50))
|
||||
fmt.Println("perc90:", q.Query(0.90))
|
||||
fmt.Println("perc99:", q.Query(0.99))
|
||||
fmt.Println("count:", q.Count())
|
||||
// Output:
|
||||
// perc50: 5
|
||||
// perc90: 16
|
||||
// perc99: 223
|
||||
// count: 2388
|
||||
}
|
||||
|
||||
func Example_mergeMultipleStreams() {
|
||||
// Scenario:
|
||||
// We have multiple database shards. On each shard, there is a process
|
||||
// collecting query response times from the database logs and inserting
|
||||
// them into a Stream (created via NewTargeted(0.90)), much like the
|
||||
// Simple example. These processes expose a network interface for us to
|
||||
// ask them to serialize and send us the results of their
|
||||
// Stream.Samples so we may Merge and Query them.
|
||||
//
|
||||
// NOTES:
|
||||
// * These sample sets are small, allowing us to get them
|
||||
// across the network much faster than sending the entire list of data
|
||||
// points.
|
||||
//
|
||||
// * For this to work correctly, we must supply the same quantiles
|
||||
// a priori the process collecting the samples supplied to NewTargeted,
|
||||
// even if we do not plan to query them all here.
|
||||
ch := make(chan quantile.Samples)
|
||||
getDBQuerySamples(ch)
|
||||
q := quantile.NewTargeted(map[float64]float64{0.90: 0.001})
|
||||
for samples := range ch {
|
||||
q.Merge(samples)
|
||||
}
|
||||
fmt.Println("perc90:", q.Query(0.90))
|
||||
}
|
||||
|
||||
func Example_window() {
|
||||
// Scenario: We want the 90th, 95th, and 99th percentiles for each
|
||||
// minute.
|
||||
|
||||
ch := make(chan float64)
|
||||
go sendStreamValues(ch)
|
||||
|
||||
tick := time.NewTicker(1 * time.Minute)
|
||||
q := quantile.NewTargeted(map[float64]float64{
|
||||
0.90: 0.001,
|
||||
0.95: 0.0005,
|
||||
0.99: 0.0001,
|
||||
})
|
||||
for {
|
||||
select {
|
||||
case t := <-tick.C:
|
||||
flushToDB(t, q.Samples())
|
||||
q.Reset()
|
||||
case v := <-ch:
|
||||
q.Insert(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func sendStreamValues(ch chan float64) {
|
||||
// Use your imagination
|
||||
}
|
||||
|
||||
func flushToDB(t time.Time, samples quantile.Samples) {
|
||||
// Use your imagination
|
||||
}
|
||||
|
||||
// This is a stub for the above example. In reality this would hit the remote
|
||||
// servers via http or something like it.
|
||||
func getDBQuerySamples(ch chan quantile.Samples) {}
|
||||
|
||||
func sendFloats(ch chan<- float64) {
|
||||
f, err := os.Open("exampledata.txt")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
sc := bufio.NewScanner(f)
|
||||
for sc.Scan() {
|
||||
b := sc.Bytes()
|
||||
v, err := strconv.ParseFloat(string(b), 64)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
ch <- v
|
||||
}
|
||||
if sc.Err() != nil {
|
||||
log.Fatal(sc.Err())
|
||||
}
|
||||
close(ch)
|
||||
}
|
|
@ -1,188 +0,0 @@
|
|||
package quantile
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/rand"
|
||||
"sort"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
Targets = map[float64]float64{
|
||||
0.01: 0.001,
|
||||
0.10: 0.01,
|
||||
0.50: 0.05,
|
||||
0.90: 0.01,
|
||||
0.99: 0.001,
|
||||
}
|
||||
TargetsSmallEpsilon = map[float64]float64{
|
||||
0.01: 0.0001,
|
||||
0.10: 0.001,
|
||||
0.50: 0.005,
|
||||
0.90: 0.001,
|
||||
0.99: 0.0001,
|
||||
}
|
||||
LowQuantiles = []float64{0.01, 0.1, 0.5}
|
||||
HighQuantiles = []float64{0.99, 0.9, 0.5}
|
||||
)
|
||||
|
||||
const RelativeEpsilon = 0.01
|
||||
|
||||
func verifyPercsWithAbsoluteEpsilon(t *testing.T, a []float64, s *Stream) {
|
||||
sort.Float64s(a)
|
||||
for quantile, epsilon := range Targets {
|
||||
n := float64(len(a))
|
||||
k := int(quantile * n)
|
||||
lower := int((quantile - epsilon) * n)
|
||||
if lower < 1 {
|
||||
lower = 1
|
||||
}
|
||||
upper := int(math.Ceil((quantile + epsilon) * n))
|
||||
if upper > len(a) {
|
||||
upper = len(a)
|
||||
}
|
||||
w, min, max := a[k-1], a[lower-1], a[upper-1]
|
||||
if g := s.Query(quantile); g < min || g > max {
|
||||
t.Errorf("q=%f: want %v [%f,%f], got %v", quantile, w, min, max, g)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func verifyLowPercsWithRelativeEpsilon(t *testing.T, a []float64, s *Stream) {
|
||||
sort.Float64s(a)
|
||||
for _, qu := range LowQuantiles {
|
||||
n := float64(len(a))
|
||||
k := int(qu * n)
|
||||
|
||||
lowerRank := int((1 - RelativeEpsilon) * qu * n)
|
||||
upperRank := int(math.Ceil((1 + RelativeEpsilon) * qu * n))
|
||||
w, min, max := a[k-1], a[lowerRank-1], a[upperRank-1]
|
||||
if g := s.Query(qu); g < min || g > max {
|
||||
t.Errorf("q=%f: want %v [%f,%f], got %v", qu, w, min, max, g)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func verifyHighPercsWithRelativeEpsilon(t *testing.T, a []float64, s *Stream) {
|
||||
sort.Float64s(a)
|
||||
for _, qu := range HighQuantiles {
|
||||
n := float64(len(a))
|
||||
k := int(qu * n)
|
||||
|
||||
lowerRank := int((1 - (1+RelativeEpsilon)*(1-qu)) * n)
|
||||
upperRank := int(math.Ceil((1 - (1-RelativeEpsilon)*(1-qu)) * n))
|
||||
w, min, max := a[k-1], a[lowerRank-1], a[upperRank-1]
|
||||
if g := s.Query(qu); g < min || g > max {
|
||||
t.Errorf("q=%f: want %v [%f,%f], got %v", qu, w, min, max, g)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func populateStream(s *Stream) []float64 {
|
||||
a := make([]float64, 0, 1e5+100)
|
||||
for i := 0; i < cap(a); i++ {
|
||||
v := rand.NormFloat64()
|
||||
// Add 5% asymmetric outliers.
|
||||
if i%20 == 0 {
|
||||
v = v*v + 1
|
||||
}
|
||||
s.Insert(v)
|
||||
a = append(a, v)
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
func TestTargetedQuery(t *testing.T) {
|
||||
rand.Seed(42)
|
||||
s := NewTargeted(Targets)
|
||||
a := populateStream(s)
|
||||
verifyPercsWithAbsoluteEpsilon(t, a, s)
|
||||
}
|
||||
|
||||
func TestLowBiasedQuery(t *testing.T) {
|
||||
rand.Seed(42)
|
||||
s := NewLowBiased(RelativeEpsilon)
|
||||
a := populateStream(s)
|
||||
verifyLowPercsWithRelativeEpsilon(t, a, s)
|
||||
}
|
||||
|
||||
func TestHighBiasedQuery(t *testing.T) {
|
||||
rand.Seed(42)
|
||||
s := NewHighBiased(RelativeEpsilon)
|
||||
a := populateStream(s)
|
||||
verifyHighPercsWithRelativeEpsilon(t, a, s)
|
||||
}
|
||||
|
||||
// BrokenTestTargetedMerge is broken, see Merge doc comment.
|
||||
func BrokenTestTargetedMerge(t *testing.T) {
|
||||
rand.Seed(42)
|
||||
s1 := NewTargeted(Targets)
|
||||
s2 := NewTargeted(Targets)
|
||||
a := populateStream(s1)
|
||||
a = append(a, populateStream(s2)...)
|
||||
s1.Merge(s2.Samples())
|
||||
verifyPercsWithAbsoluteEpsilon(t, a, s1)
|
||||
}
|
||||
|
||||
// BrokenTestLowBiasedMerge is broken, see Merge doc comment.
|
||||
func BrokenTestLowBiasedMerge(t *testing.T) {
|
||||
rand.Seed(42)
|
||||
s1 := NewLowBiased(RelativeEpsilon)
|
||||
s2 := NewLowBiased(RelativeEpsilon)
|
||||
a := populateStream(s1)
|
||||
a = append(a, populateStream(s2)...)
|
||||
s1.Merge(s2.Samples())
|
||||
verifyLowPercsWithRelativeEpsilon(t, a, s2)
|
||||
}
|
||||
|
||||
// BrokenTestHighBiasedMerge is broken, see Merge doc comment.
|
||||
func BrokenTestHighBiasedMerge(t *testing.T) {
|
||||
rand.Seed(42)
|
||||
s1 := NewHighBiased(RelativeEpsilon)
|
||||
s2 := NewHighBiased(RelativeEpsilon)
|
||||
a := populateStream(s1)
|
||||
a = append(a, populateStream(s2)...)
|
||||
s1.Merge(s2.Samples())
|
||||
verifyHighPercsWithRelativeEpsilon(t, a, s2)
|
||||
}
|
||||
|
||||
func TestUncompressed(t *testing.T) {
|
||||
q := NewTargeted(Targets)
|
||||
for i := 100; i > 0; i-- {
|
||||
q.Insert(float64(i))
|
||||
}
|
||||
if g := q.Count(); g != 100 {
|
||||
t.Errorf("want count 100, got %d", g)
|
||||
}
|
||||
// Before compression, Query should have 100% accuracy.
|
||||
for quantile := range Targets {
|
||||
w := quantile * 100
|
||||
if g := q.Query(quantile); g != w {
|
||||
t.Errorf("want %f, got %f", w, g)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUncompressedSamples(t *testing.T) {
|
||||
q := NewTargeted(map[float64]float64{0.99: 0.001})
|
||||
for i := 1; i <= 100; i++ {
|
||||
q.Insert(float64(i))
|
||||
}
|
||||
if g := q.Samples().Len(); g != 100 {
|
||||
t.Errorf("want count 100, got %d", g)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUncompressedOne(t *testing.T) {
|
||||
q := NewTargeted(map[float64]float64{0.99: 0.01})
|
||||
q.Insert(3.14)
|
||||
if g := q.Query(0.90); g != 3.14 {
|
||||
t.Error("want PI, got", g)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefaults(t *testing.T) {
|
||||
if g := NewTargeted(map[float64]float64{0.99: 0.001}).Query(0.99); g != 0 {
|
||||
t.Errorf("want 0, got %f", g)
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/bgentry/speakeasy"
|
||||
)
|
||||
|
||||
func main() {
|
||||
password, err := speakeasy.Ask("Please enter a password: ")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("Password result: %q\n", password)
|
||||
fmt.Printf("Password len: %d\n", len(password))
|
||||
}
|
File diff suppressed because it is too large
Load Diff
14
Godeps/_workspace/src/github.com/codegangsta/cli/autocomplete/bash_autocomplete
generated
vendored
14
Godeps/_workspace/src/github.com/codegangsta/cli/autocomplete/bash_autocomplete
generated
vendored
|
@ -1,14 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
: ${PROG:=$(basename ${BASH_SOURCE})}
|
||||
|
||||
_cli_bash_autocomplete() {
|
||||
local cur opts base
|
||||
COMPREPLY=()
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
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,27 +0,0 @@
|
|||
package main
|
||||
|
||||
import gexpect "github.com/coreos/etcd/Godeps/_workspace/src/github.com/coreos/gexpect"
|
||||
import "log"
|
||||
|
||||
func main() {
|
||||
log.Printf("Testing Ftp... ")
|
||||
|
||||
child, err := gexpect.Spawn("ftp ftp.openbsd.org")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
child.Expect("Name")
|
||||
child.SendLine("anonymous")
|
||||
child.Expect("Password")
|
||||
child.SendLine("pexpect@sourceforge.net")
|
||||
child.Expect("ftp> ")
|
||||
child.SendLine("cd /pub/OpenBSD/3.7/packages/i386")
|
||||
child.Expect("ftp> ")
|
||||
child.SendLine("bin")
|
||||
child.Expect("ftp> ")
|
||||
child.SendLine("prompt")
|
||||
child.Expect("ftp> ")
|
||||
child.SendLine("pwd")
|
||||
child.Expect("ftp> ")
|
||||
log.Printf("Success\n")
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package main
|
||||
|
||||
import gexpect "github.com/coreos/etcd/Godeps/_workspace/src/github.com/coreos/gexpect"
|
||||
import "log"
|
||||
|
||||
func main() {
|
||||
log.Printf("Testing Ping interact... \n")
|
||||
|
||||
child, err := gexpect.Spawn("ping -c8 127.0.0.1")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
child.Interact()
|
||||
log.Printf("Success\n")
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package main
|
||||
|
||||
import "github.com/coreos/etcd/Godeps/_workspace/src/github.com/coreos/gexpect"
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Printf("Starting python.. \n")
|
||||
child, err := gexpect.Spawn("python")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Printf("Expecting >>>.. \n")
|
||||
child.Expect(">>>")
|
||||
fmt.Printf("print 'Hello World'..\n")
|
||||
child.SendLine("print 'Hello World'")
|
||||
child.Expect(">>>")
|
||||
|
||||
fmt.Printf("Interacting.. \n")
|
||||
child.Interact()
|
||||
fmt.Printf("Done \n")
|
||||
child.Close()
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
package main
|
||||
|
||||
import "github.com/coreos/etcd/Godeps/_workspace/src/github.com/coreos/gexpect"
|
||||
import "fmt"
|
||||
import "strings"
|
||||
|
||||
func main() {
|
||||
waitChan := make(chan string)
|
||||
|
||||
fmt.Printf("Starting screen.. \n")
|
||||
|
||||
child, err := gexpect.Spawn("screen")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
sender, reciever := child.AsyncInteractChannels()
|
||||
go func() {
|
||||
waitString := ""
|
||||
count := 0
|
||||
for {
|
||||
select {
|
||||
case waitString = <-waitChan:
|
||||
count++
|
||||
case msg, open := <-reciever:
|
||||
if !open {
|
||||
return
|
||||
}
|
||||
fmt.Printf("Recieved: %s\n", msg)
|
||||
|
||||
if strings.Contains(msg, waitString) {
|
||||
if count >= 1 {
|
||||
waitChan <- msg
|
||||
count -= 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
wait := func(str string) {
|
||||
waitChan <- str
|
||||
<-waitChan
|
||||
}
|
||||
fmt.Printf("Waiting until started.. \n")
|
||||
wait(" ")
|
||||
fmt.Printf("Sending Enter.. \n")
|
||||
sender <- "\n"
|
||||
wait("$")
|
||||
fmt.Printf("Sending echo.. \n")
|
||||
sender <- "echo Hello World\n"
|
||||
wait("Hello World")
|
||||
fmt.Printf("Received echo. \n")
|
||||
}
|
|
@ -1,223 +0,0 @@
|
|||
package semver
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
type fixture struct {
|
||||
greaterVersion string
|
||||
lesserVersion string
|
||||
}
|
||||
|
||||
var fixtures = []fixture{
|
||||
fixture{"0.0.0", "0.0.0-foo"},
|
||||
fixture{"0.0.1", "0.0.0"},
|
||||
fixture{"1.0.0", "0.9.9"},
|
||||
fixture{"0.10.0", "0.9.0"},
|
||||
fixture{"0.99.0", "0.10.0"},
|
||||
fixture{"2.0.0", "1.2.3"},
|
||||
fixture{"0.0.0", "0.0.0-foo"},
|
||||
fixture{"0.0.1", "0.0.0"},
|
||||
fixture{"1.0.0", "0.9.9"},
|
||||
fixture{"0.10.0", "0.9.0"},
|
||||
fixture{"0.99.0", "0.10.0"},
|
||||
fixture{"2.0.0", "1.2.3"},
|
||||
fixture{"0.0.0", "0.0.0-foo"},
|
||||
fixture{"0.0.1", "0.0.0"},
|
||||
fixture{"1.0.0", "0.9.9"},
|
||||
fixture{"0.10.0", "0.9.0"},
|
||||
fixture{"0.99.0", "0.10.0"},
|
||||
fixture{"2.0.0", "1.2.3"},
|
||||
fixture{"1.2.3", "1.2.3-asdf"},
|
||||
fixture{"1.2.3", "1.2.3-4"},
|
||||
fixture{"1.2.3", "1.2.3-4-foo"},
|
||||
fixture{"1.2.3-5-foo", "1.2.3-5"},
|
||||
fixture{"1.2.3-5", "1.2.3-4"},
|
||||
fixture{"1.2.3-5-foo", "1.2.3-5-Foo"},
|
||||
fixture{"3.0.0", "2.7.2+asdf"},
|
||||
fixture{"3.0.0+foobar", "2.7.2"},
|
||||
fixture{"1.2.3-a.10", "1.2.3-a.5"},
|
||||
fixture{"1.2.3-a.b", "1.2.3-a.5"},
|
||||
fixture{"1.2.3-a.b", "1.2.3-a"},
|
||||
fixture{"1.2.3-a.b.c.10.d.5", "1.2.3-a.b.c.5.d.100"},
|
||||
fixture{"1.0.0", "1.0.0-rc.1"},
|
||||
fixture{"1.0.0-rc.2", "1.0.0-rc.1"},
|
||||
fixture{"1.0.0-rc.1", "1.0.0-beta.11"},
|
||||
fixture{"1.0.0-beta.11", "1.0.0-beta.2"},
|
||||
fixture{"1.0.0-beta.2", "1.0.0-beta"},
|
||||
fixture{"1.0.0-beta", "1.0.0-alpha.beta"},
|
||||
fixture{"1.0.0-alpha.beta", "1.0.0-alpha.1"},
|
||||
fixture{"1.0.0-alpha.1", "1.0.0-alpha"},
|
||||
}
|
||||
|
||||
func TestCompare(t *testing.T) {
|
||||
for _, v := range fixtures {
|
||||
gt, err := NewVersion(v.greaterVersion)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
lt, err := NewVersion(v.lesserVersion)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if gt.LessThan(*lt) == true {
|
||||
t.Errorf("%s should not be less than %s", gt, lt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testString(t *testing.T, orig string, version *Version) {
|
||||
if orig != version.String() {
|
||||
t.Errorf("%s != %s", orig, version)
|
||||
}
|
||||
}
|
||||
|
||||
func TestString(t *testing.T) {
|
||||
for _, v := range fixtures {
|
||||
gt, err := NewVersion(v.greaterVersion)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
testString(t, v.greaterVersion, gt)
|
||||
|
||||
lt, err := NewVersion(v.lesserVersion)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
testString(t, v.lesserVersion, lt)
|
||||
}
|
||||
}
|
||||
|
||||
func shuffleStringSlice(src []string) []string {
|
||||
dest := make([]string, len(src))
|
||||
rand.Seed(time.Now().Unix())
|
||||
perm := rand.Perm(len(src))
|
||||
for i, v := range perm {
|
||||
dest[v] = src[i]
|
||||
}
|
||||
return dest
|
||||
}
|
||||
|
||||
func TestSort(t *testing.T) {
|
||||
sortedVersions := []string{"1.0.0", "1.0.2", "1.2.0", "3.1.1"}
|
||||
unsortedVersions := shuffleStringSlice(sortedVersions)
|
||||
|
||||
semvers := []*Version{}
|
||||
for _, v := range unsortedVersions {
|
||||
sv, err := NewVersion(v)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
semvers = append(semvers, sv)
|
||||
}
|
||||
|
||||
Sort(semvers)
|
||||
|
||||
for idx, sv := range semvers {
|
||||
if sv.String() != sortedVersions[idx] {
|
||||
t.Fatalf("incorrect sort at index %v", idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBumpMajor(t *testing.T) {
|
||||
version, _ := NewVersion("1.0.0")
|
||||
version.BumpMajor()
|
||||
if version.Major != 2 {
|
||||
t.Fatalf("bumping major on 1.0.0 resulted in %v", version)
|
||||
}
|
||||
|
||||
version, _ = NewVersion("1.5.2")
|
||||
version.BumpMajor()
|
||||
if version.Minor != 0 && version.Patch != 0 {
|
||||
t.Fatalf("bumping major on 1.5.2 resulted in %v", version)
|
||||
}
|
||||
|
||||
version, _ = NewVersion("1.0.0+build.1-alpha.1")
|
||||
version.BumpMajor()
|
||||
if version.PreRelease != "" && version.PreRelease != "" {
|
||||
t.Fatalf("bumping major on 1.0.0+build.1-alpha.1 resulted in %v", version)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBumpMinor(t *testing.T) {
|
||||
version, _ := NewVersion("1.0.0")
|
||||
version.BumpMinor()
|
||||
|
||||
if version.Major != 1 {
|
||||
t.Fatalf("bumping minor on 1.0.0 resulted in %v", version)
|
||||
}
|
||||
|
||||
if version.Minor != 1 {
|
||||
t.Fatalf("bumping major on 1.0.0 resulted in %v", version)
|
||||
}
|
||||
|
||||
version, _ = NewVersion("1.0.0+build.1-alpha.1")
|
||||
version.BumpMinor()
|
||||
if version.PreRelease != "" && version.PreRelease != "" {
|
||||
t.Fatalf("bumping major on 1.0.0+build.1-alpha.1 resulted in %v", version)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBumpPatch(t *testing.T) {
|
||||
version, _ := NewVersion("1.0.0")
|
||||
version.BumpPatch()
|
||||
|
||||
if version.Major != 1 {
|
||||
t.Fatalf("bumping minor on 1.0.0 resulted in %v", version)
|
||||
}
|
||||
|
||||
if version.Minor != 0 {
|
||||
t.Fatalf("bumping major on 1.0.0 resulted in %v", version)
|
||||
}
|
||||
|
||||
if version.Patch != 1 {
|
||||
t.Fatalf("bumping major on 1.0.0 resulted in %v", version)
|
||||
}
|
||||
|
||||
version, _ = NewVersion("1.0.0+build.1-alpha.1")
|
||||
version.BumpPatch()
|
||||
if version.PreRelease != "" && version.PreRelease != "" {
|
||||
t.Fatalf("bumping major on 1.0.0+build.1-alpha.1 resulted in %v", version)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMust(t *testing.T) {
|
||||
tests := []struct {
|
||||
versionStr string
|
||||
|
||||
version *Version
|
||||
recov interface{}
|
||||
}{
|
||||
{
|
||||
versionStr: "1.0.0",
|
||||
version: &Version{Major: 1},
|
||||
},
|
||||
{
|
||||
versionStr: "version number",
|
||||
recov: errors.New("version number is not in dotted-tri format"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
func() {
|
||||
defer func() {
|
||||
recov := recover()
|
||||
if !reflect.DeepEqual(tt.recov, recov) {
|
||||
t.Fatalf("incorrect panic for %q: want %v, got %v", tt.versionStr, tt.recov, recov)
|
||||
}
|
||||
}()
|
||||
|
||||
version := Must(NewVersion(tt.versionStr))
|
||||
if !reflect.DeepEqual(tt.version, version) {
|
||||
t.Fatalf("incorrect version for %q: want %+v, got %+v", tt.versionStr, tt.version, version)
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
oldlog "log"
|
||||
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/coreos/pkg/capnslog"
|
||||
)
|
||||
|
||||
var logLevel = capnslog.INFO
|
||||
var log = capnslog.NewPackageLogger("github.com/coreos/pkg/capnslog/cmd", "main")
|
||||
var dlog = capnslog.NewPackageLogger("github.com/coreos/pkg/capnslog/cmd", "dolly")
|
||||
|
||||
func init() {
|
||||
flag.Var(&logLevel, "log-level", "Global log level.")
|
||||
}
|
||||
|
||||
func main() {
|
||||
rl := capnslog.MustRepoLogger("github.com/coreos/pkg/capnslog/cmd")
|
||||
|
||||
// We can parse the log level configs from the command line
|
||||
flag.Parse()
|
||||
if flag.NArg() > 1 {
|
||||
cfg, err := rl.ParseLogLevelConfig(flag.Arg(1))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
rl.SetLogLevel(cfg)
|
||||
log.Infof("Setting output to %s", flag.Arg(1))
|
||||
}
|
||||
|
||||
// Send some messages at different levels to the different packages
|
||||
dlog.Infof("Hello Dolly")
|
||||
dlog.Warningf("Well hello, Dolly")
|
||||
log.Errorf("It's so nice to have you back where you belong")
|
||||
dlog.Debugf("You're looking swell, Dolly")
|
||||
dlog.Tracef("I can tell, Dolly")
|
||||
|
||||
// We also have control over the built-in "log" package.
|
||||
capnslog.SetGlobalLogLevel(logLevel)
|
||||
oldlog.Println("You're still glowin', you're still crowin', you're still lookin' strong")
|
||||
log.Fatalf("Dolly'll never go away again")
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,267 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package proto_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto"
|
||||
|
||||
proto3pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto/proto3_proto"
|
||||
pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata"
|
||||
)
|
||||
|
||||
var cloneTestMessage = &pb.MyMessage{
|
||||
Count: proto.Int32(42),
|
||||
Name: proto.String("Dave"),
|
||||
Pet: []string{"bunny", "kitty", "horsey"},
|
||||
Inner: &pb.InnerMessage{
|
||||
Host: proto.String("niles"),
|
||||
Port: proto.Int32(9099),
|
||||
Connected: proto.Bool(true),
|
||||
},
|
||||
Others: []*pb.OtherMessage{
|
||||
{
|
||||
Value: []byte("some bytes"),
|
||||
},
|
||||
},
|
||||
Somegroup: &pb.MyMessage_SomeGroup{
|
||||
GroupField: proto.Int32(6),
|
||||
},
|
||||
RepBytes: [][]byte{[]byte("sham"), []byte("wow")},
|
||||
}
|
||||
|
||||
func init() {
|
||||
ext := &pb.Ext{
|
||||
Data: proto.String("extension"),
|
||||
}
|
||||
if err := proto.SetExtension(cloneTestMessage, pb.E_Ext_More, ext); err != nil {
|
||||
panic("SetExtension: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestClone(t *testing.T) {
|
||||
m := proto.Clone(cloneTestMessage).(*pb.MyMessage)
|
||||
if !proto.Equal(m, cloneTestMessage) {
|
||||
t.Errorf("Clone(%v) = %v", cloneTestMessage, m)
|
||||
}
|
||||
|
||||
// Verify it was a deep copy.
|
||||
*m.Inner.Port++
|
||||
if proto.Equal(m, cloneTestMessage) {
|
||||
t.Error("Mutating clone changed the original")
|
||||
}
|
||||
// Byte fields and repeated fields should be copied.
|
||||
if &m.Pet[0] == &cloneTestMessage.Pet[0] {
|
||||
t.Error("Pet: repeated field not copied")
|
||||
}
|
||||
if &m.Others[0] == &cloneTestMessage.Others[0] {
|
||||
t.Error("Others: repeated field not copied")
|
||||
}
|
||||
if &m.Others[0].Value[0] == &cloneTestMessage.Others[0].Value[0] {
|
||||
t.Error("Others[0].Value: bytes field not copied")
|
||||
}
|
||||
if &m.RepBytes[0] == &cloneTestMessage.RepBytes[0] {
|
||||
t.Error("RepBytes: repeated field not copied")
|
||||
}
|
||||
if &m.RepBytes[0][0] == &cloneTestMessage.RepBytes[0][0] {
|
||||
t.Error("RepBytes[0]: bytes field not copied")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCloneNil(t *testing.T) {
|
||||
var m *pb.MyMessage
|
||||
if c := proto.Clone(m); !proto.Equal(m, c) {
|
||||
t.Errorf("Clone(%v) = %v", m, c)
|
||||
}
|
||||
}
|
||||
|
||||
var mergeTests = []struct {
|
||||
src, dst, want proto.Message
|
||||
}{
|
||||
{
|
||||
src: &pb.MyMessage{
|
||||
Count: proto.Int32(42),
|
||||
},
|
||||
dst: &pb.MyMessage{
|
||||
Name: proto.String("Dave"),
|
||||
},
|
||||
want: &pb.MyMessage{
|
||||
Count: proto.Int32(42),
|
||||
Name: proto.String("Dave"),
|
||||
},
|
||||
},
|
||||
{
|
||||
src: &pb.MyMessage{
|
||||
Inner: &pb.InnerMessage{
|
||||
Host: proto.String("hey"),
|
||||
Connected: proto.Bool(true),
|
||||
},
|
||||
Pet: []string{"horsey"},
|
||||
Others: []*pb.OtherMessage{
|
||||
{
|
||||
Value: []byte("some bytes"),
|
||||
},
|
||||
},
|
||||
},
|
||||
dst: &pb.MyMessage{
|
||||
Inner: &pb.InnerMessage{
|
||||
Host: proto.String("niles"),
|
||||
Port: proto.Int32(9099),
|
||||
},
|
||||
Pet: []string{"bunny", "kitty"},
|
||||
Others: []*pb.OtherMessage{
|
||||
{
|
||||
Key: proto.Int64(31415926535),
|
||||
},
|
||||
{
|
||||
// Explicitly test a src=nil field
|
||||
Inner: nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &pb.MyMessage{
|
||||
Inner: &pb.InnerMessage{
|
||||
Host: proto.String("hey"),
|
||||
Connected: proto.Bool(true),
|
||||
Port: proto.Int32(9099),
|
||||
},
|
||||
Pet: []string{"bunny", "kitty", "horsey"},
|
||||
Others: []*pb.OtherMessage{
|
||||
{
|
||||
Key: proto.Int64(31415926535),
|
||||
},
|
||||
{},
|
||||
{
|
||||
Value: []byte("some bytes"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
src: &pb.MyMessage{
|
||||
RepBytes: [][]byte{[]byte("wow")},
|
||||
},
|
||||
dst: &pb.MyMessage{
|
||||
Somegroup: &pb.MyMessage_SomeGroup{
|
||||
GroupField: proto.Int32(6),
|
||||
},
|
||||
RepBytes: [][]byte{[]byte("sham")},
|
||||
},
|
||||
want: &pb.MyMessage{
|
||||
Somegroup: &pb.MyMessage_SomeGroup{
|
||||
GroupField: proto.Int32(6),
|
||||
},
|
||||
RepBytes: [][]byte{[]byte("sham"), []byte("wow")},
|
||||
},
|
||||
},
|
||||
// Check that a scalar bytes field replaces rather than appends.
|
||||
{
|
||||
src: &pb.OtherMessage{Value: []byte("foo")},
|
||||
dst: &pb.OtherMessage{Value: []byte("bar")},
|
||||
want: &pb.OtherMessage{Value: []byte("foo")},
|
||||
},
|
||||
{
|
||||
src: &pb.MessageWithMap{
|
||||
NameMapping: map[int32]string{6: "Nigel"},
|
||||
MsgMapping: map[int64]*pb.FloatingPoint{
|
||||
0x4001: {F: proto.Float64(2.0)},
|
||||
},
|
||||
ByteMapping: map[bool][]byte{true: []byte("wowsa")},
|
||||
},
|
||||
dst: &pb.MessageWithMap{
|
||||
NameMapping: map[int32]string{
|
||||
6: "Bruce", // should be overwritten
|
||||
7: "Andrew",
|
||||
},
|
||||
},
|
||||
want: &pb.MessageWithMap{
|
||||
NameMapping: map[int32]string{
|
||||
6: "Nigel",
|
||||
7: "Andrew",
|
||||
},
|
||||
MsgMapping: map[int64]*pb.FloatingPoint{
|
||||
0x4001: {F: proto.Float64(2.0)},
|
||||
},
|
||||
ByteMapping: map[bool][]byte{true: []byte("wowsa")},
|
||||
},
|
||||
},
|
||||
// proto3 shouldn't merge zero values,
|
||||
// in the same way that proto2 shouldn't merge nils.
|
||||
{
|
||||
src: &proto3pb.Message{
|
||||
Name: "Aaron",
|
||||
Data: []byte(""), // zero value, but not nil
|
||||
},
|
||||
dst: &proto3pb.Message{
|
||||
HeightInCm: 176,
|
||||
Data: []byte("texas!"),
|
||||
},
|
||||
want: &proto3pb.Message{
|
||||
Name: "Aaron",
|
||||
HeightInCm: 176,
|
||||
Data: []byte("texas!"),
|
||||
},
|
||||
},
|
||||
// Oneof fields should merge by assignment.
|
||||
{
|
||||
src: &pb.Communique{
|
||||
Union: &pb.Communique_Number{Number: 41},
|
||||
},
|
||||
dst: &pb.Communique{
|
||||
Union: &pb.Communique_Name{Name: "Bobby Tables"},
|
||||
},
|
||||
want: &pb.Communique{
|
||||
Union: &pb.Communique_Number{Number: 41},
|
||||
},
|
||||
},
|
||||
// Oneof nil is the same as not set.
|
||||
{
|
||||
src: &pb.Communique{},
|
||||
dst: &pb.Communique{
|
||||
Union: &pb.Communique_Name{Name: "Bobby Tables"},
|
||||
},
|
||||
want: &pb.Communique{
|
||||
Union: &pb.Communique_Name{Name: "Bobby Tables"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestMerge(t *testing.T) {
|
||||
for _, m := range mergeTests {
|
||||
got := proto.Clone(m.dst)
|
||||
proto.Merge(got, m.src)
|
||||
if !proto.Equal(got, m.want) {
|
||||
t.Errorf("Merge(%v, %v)\n got %v\nwant %v\n", m.dst, m.src, got, m.want)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,209 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package proto_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto"
|
||||
pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata"
|
||||
)
|
||||
|
||||
// Four identical base messages.
|
||||
// The init function adds extensions to some of them.
|
||||
var messageWithoutExtension = &pb.MyMessage{Count: Int32(7)}
|
||||
var messageWithExtension1a = &pb.MyMessage{Count: Int32(7)}
|
||||
var messageWithExtension1b = &pb.MyMessage{Count: Int32(7)}
|
||||
var messageWithExtension2 = &pb.MyMessage{Count: Int32(7)}
|
||||
|
||||
// Two messages with non-message extensions.
|
||||
var messageWithInt32Extension1 = &pb.MyMessage{Count: Int32(8)}
|
||||
var messageWithInt32Extension2 = &pb.MyMessage{Count: Int32(8)}
|
||||
|
||||
func init() {
|
||||
ext1 := &pb.Ext{Data: String("Kirk")}
|
||||
ext2 := &pb.Ext{Data: String("Picard")}
|
||||
|
||||
// messageWithExtension1a has ext1, but never marshals it.
|
||||
if err := SetExtension(messageWithExtension1a, pb.E_Ext_More, ext1); err != nil {
|
||||
panic("SetExtension on 1a failed: " + err.Error())
|
||||
}
|
||||
|
||||
// messageWithExtension1b is the unmarshaled form of messageWithExtension1a.
|
||||
if err := SetExtension(messageWithExtension1b, pb.E_Ext_More, ext1); err != nil {
|
||||
panic("SetExtension on 1b failed: " + err.Error())
|
||||
}
|
||||
buf, err := Marshal(messageWithExtension1b)
|
||||
if err != nil {
|
||||
panic("Marshal of 1b failed: " + err.Error())
|
||||
}
|
||||
messageWithExtension1b.Reset()
|
||||
if err := Unmarshal(buf, messageWithExtension1b); err != nil {
|
||||
panic("Unmarshal of 1b failed: " + err.Error())
|
||||
}
|
||||
|
||||
// messageWithExtension2 has ext2.
|
||||
if err := SetExtension(messageWithExtension2, pb.E_Ext_More, ext2); err != nil {
|
||||
panic("SetExtension on 2 failed: " + err.Error())
|
||||
}
|
||||
|
||||
if err := SetExtension(messageWithInt32Extension1, pb.E_Ext_Number, Int32(23)); err != nil {
|
||||
panic("SetExtension on Int32-1 failed: " + err.Error())
|
||||
}
|
||||
if err := SetExtension(messageWithInt32Extension1, pb.E_Ext_Number, Int32(24)); err != nil {
|
||||
panic("SetExtension on Int32-2 failed: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
var EqualTests = []struct {
|
||||
desc string
|
||||
a, b Message
|
||||
exp bool
|
||||
}{
|
||||
{"different types", &pb.GoEnum{}, &pb.GoTestField{}, false},
|
||||
{"equal empty", &pb.GoEnum{}, &pb.GoEnum{}, true},
|
||||
{"nil vs nil", nil, nil, true},
|
||||
{"typed nil vs typed nil", (*pb.GoEnum)(nil), (*pb.GoEnum)(nil), true},
|
||||
{"typed nil vs empty", (*pb.GoEnum)(nil), &pb.GoEnum{}, false},
|
||||
{"different typed nil", (*pb.GoEnum)(nil), (*pb.GoTestField)(nil), false},
|
||||
|
||||
{"one set field, one unset field", &pb.GoTestField{Label: String("foo")}, &pb.GoTestField{}, false},
|
||||
{"one set field zero, one unset field", &pb.GoTest{Param: Int32(0)}, &pb.GoTest{}, false},
|
||||
{"different set fields", &pb.GoTestField{Label: String("foo")}, &pb.GoTestField{Label: String("bar")}, false},
|
||||
{"equal set", &pb.GoTestField{Label: String("foo")}, &pb.GoTestField{Label: String("foo")}, true},
|
||||
|
||||
{"repeated, one set", &pb.GoTest{F_Int32Repeated: []int32{2, 3}}, &pb.GoTest{}, false},
|
||||
{"repeated, different length", &pb.GoTest{F_Int32Repeated: []int32{2, 3}}, &pb.GoTest{F_Int32Repeated: []int32{2}}, false},
|
||||
{"repeated, different value", &pb.GoTest{F_Int32Repeated: []int32{2}}, &pb.GoTest{F_Int32Repeated: []int32{3}}, false},
|
||||
{"repeated, equal", &pb.GoTest{F_Int32Repeated: []int32{2, 4}}, &pb.GoTest{F_Int32Repeated: []int32{2, 4}}, true},
|
||||
{"repeated, nil equal nil", &pb.GoTest{F_Int32Repeated: nil}, &pb.GoTest{F_Int32Repeated: nil}, true},
|
||||
{"repeated, nil equal empty", &pb.GoTest{F_Int32Repeated: nil}, &pb.GoTest{F_Int32Repeated: []int32{}}, true},
|
||||
{"repeated, empty equal nil", &pb.GoTest{F_Int32Repeated: []int32{}}, &pb.GoTest{F_Int32Repeated: nil}, true},
|
||||
|
||||
{
|
||||
"nested, different",
|
||||
&pb.GoTest{RequiredField: &pb.GoTestField{Label: String("foo")}},
|
||||
&pb.GoTest{RequiredField: &pb.GoTestField{Label: String("bar")}},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"nested, equal",
|
||||
&pb.GoTest{RequiredField: &pb.GoTestField{Label: String("wow")}},
|
||||
&pb.GoTest{RequiredField: &pb.GoTestField{Label: String("wow")}},
|
||||
true,
|
||||
},
|
||||
|
||||
{"bytes", &pb.OtherMessage{Value: []byte("foo")}, &pb.OtherMessage{Value: []byte("foo")}, true},
|
||||
{"bytes, empty", &pb.OtherMessage{Value: []byte{}}, &pb.OtherMessage{Value: []byte{}}, true},
|
||||
{"bytes, empty vs nil", &pb.OtherMessage{Value: []byte{}}, &pb.OtherMessage{Value: nil}, false},
|
||||
{
|
||||
"repeated bytes",
|
||||
&pb.MyMessage{RepBytes: [][]byte{[]byte("sham"), []byte("wow")}},
|
||||
&pb.MyMessage{RepBytes: [][]byte{[]byte("sham"), []byte("wow")}},
|
||||
true,
|
||||
},
|
||||
|
||||
{"extension vs. no extension", messageWithoutExtension, messageWithExtension1a, false},
|
||||
{"extension vs. same extension", messageWithExtension1a, messageWithExtension1b, true},
|
||||
{"extension vs. different extension", messageWithExtension1a, messageWithExtension2, false},
|
||||
|
||||
{"int32 extension vs. itself", messageWithInt32Extension1, messageWithInt32Extension1, true},
|
||||
{"int32 extension vs. a different int32", messageWithInt32Extension1, messageWithInt32Extension2, false},
|
||||
|
||||
{
|
||||
"message with group",
|
||||
&pb.MyMessage{
|
||||
Count: Int32(1),
|
||||
Somegroup: &pb.MyMessage_SomeGroup{
|
||||
GroupField: Int32(5),
|
||||
},
|
||||
},
|
||||
&pb.MyMessage{
|
||||
Count: Int32(1),
|
||||
Somegroup: &pb.MyMessage_SomeGroup{
|
||||
GroupField: Int32(5),
|
||||
},
|
||||
},
|
||||
true,
|
||||
},
|
||||
|
||||
{
|
||||
"map same",
|
||||
&pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}},
|
||||
&pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"map different entry",
|
||||
&pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}},
|
||||
&pb.MessageWithMap{NameMapping: map[int32]string{2: "Rob"}},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"map different key only",
|
||||
&pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}},
|
||||
&pb.MessageWithMap{NameMapping: map[int32]string{2: "Ken"}},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"map different value only",
|
||||
&pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}},
|
||||
&pb.MessageWithMap{NameMapping: map[int32]string{1: "Rob"}},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"oneof same",
|
||||
&pb.Communique{Union: &pb.Communique_Number{Number: 41}},
|
||||
&pb.Communique{Union: &pb.Communique_Number{Number: 41}},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"oneof one nil",
|
||||
&pb.Communique{Union: &pb.Communique_Number{Number: 41}},
|
||||
&pb.Communique{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"oneof different",
|
||||
&pb.Communique{Union: &pb.Communique_Number{Number: 41}},
|
||||
&pb.Communique{Union: &pb.Communique_Name{Name: "Bobby Tables"}},
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
func TestEqual(t *testing.T) {
|
||||
for _, tc := range EqualTests {
|
||||
if res := Equal(tc.a, tc.b); res != tc.exp {
|
||||
t.Errorf("%v: Equal(%v, %v) = %v, want %v", tc.desc, tc.a, tc.b, res, tc.exp)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,292 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package proto_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto"
|
||||
pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata"
|
||||
)
|
||||
|
||||
func TestGetExtensionsWithMissingExtensions(t *testing.T) {
|
||||
msg := &pb.MyMessage{}
|
||||
ext1 := &pb.Ext{}
|
||||
if err := proto.SetExtension(msg, pb.E_Ext_More, ext1); err != nil {
|
||||
t.Fatalf("Could not set ext1: %s", ext1)
|
||||
}
|
||||
exts, err := proto.GetExtensions(msg, []*proto.ExtensionDesc{
|
||||
pb.E_Ext_More,
|
||||
pb.E_Ext_Text,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("GetExtensions() failed: %s", err)
|
||||
}
|
||||
if exts[0] != ext1 {
|
||||
t.Errorf("ext1 not in returned extensions: %T %v", exts[0], exts[0])
|
||||
}
|
||||
if exts[1] != nil {
|
||||
t.Errorf("ext2 in returned extensions: %T %v", exts[1], exts[1])
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetExtensionStability(t *testing.T) {
|
||||
check := func(m *pb.MyMessage) bool {
|
||||
ext1, err := proto.GetExtension(m, pb.E_Ext_More)
|
||||
if err != nil {
|
||||
t.Fatalf("GetExtension() failed: %s", err)
|
||||
}
|
||||
ext2, err := proto.GetExtension(m, pb.E_Ext_More)
|
||||
if err != nil {
|
||||
t.Fatalf("GetExtension() failed: %s", err)
|
||||
}
|
||||
return ext1 == ext2
|
||||
}
|
||||
msg := &pb.MyMessage{Count: proto.Int32(4)}
|
||||
ext0 := &pb.Ext{}
|
||||
if err := proto.SetExtension(msg, pb.E_Ext_More, ext0); err != nil {
|
||||
t.Fatalf("Could not set ext1: %s", ext0)
|
||||
}
|
||||
if !check(msg) {
|
||||
t.Errorf("GetExtension() not stable before marshaling")
|
||||
}
|
||||
bb, err := proto.Marshal(msg)
|
||||
if err != nil {
|
||||
t.Fatalf("Marshal() failed: %s", err)
|
||||
}
|
||||
msg1 := &pb.MyMessage{}
|
||||
err = proto.Unmarshal(bb, msg1)
|
||||
if err != nil {
|
||||
t.Fatalf("Unmarshal() failed: %s", err)
|
||||
}
|
||||
if !check(msg1) {
|
||||
t.Errorf("GetExtension() not stable after unmarshaling")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetExtensionDefaults(t *testing.T) {
|
||||
var setFloat64 float64 = 1
|
||||
var setFloat32 float32 = 2
|
||||
var setInt32 int32 = 3
|
||||
var setInt64 int64 = 4
|
||||
var setUint32 uint32 = 5
|
||||
var setUint64 uint64 = 6
|
||||
var setBool = true
|
||||
var setBool2 = false
|
||||
var setString = "Goodnight string"
|
||||
var setBytes = []byte("Goodnight bytes")
|
||||
var setEnum = pb.DefaultsMessage_TWO
|
||||
|
||||
type testcase struct {
|
||||
ext *proto.ExtensionDesc // Extension we are testing.
|
||||
want interface{} // Expected value of extension, or nil (meaning that GetExtension will fail).
|
||||
def interface{} // Expected value of extension after ClearExtension().
|
||||
}
|
||||
tests := []testcase{
|
||||
{pb.E_NoDefaultDouble, setFloat64, nil},
|
||||
{pb.E_NoDefaultFloat, setFloat32, nil},
|
||||
{pb.E_NoDefaultInt32, setInt32, nil},
|
||||
{pb.E_NoDefaultInt64, setInt64, nil},
|
||||
{pb.E_NoDefaultUint32, setUint32, nil},
|
||||
{pb.E_NoDefaultUint64, setUint64, nil},
|
||||
{pb.E_NoDefaultSint32, setInt32, nil},
|
||||
{pb.E_NoDefaultSint64, setInt64, nil},
|
||||
{pb.E_NoDefaultFixed32, setUint32, nil},
|
||||
{pb.E_NoDefaultFixed64, setUint64, nil},
|
||||
{pb.E_NoDefaultSfixed32, setInt32, nil},
|
||||
{pb.E_NoDefaultSfixed64, setInt64, nil},
|
||||
{pb.E_NoDefaultBool, setBool, nil},
|
||||
{pb.E_NoDefaultBool, setBool2, nil},
|
||||
{pb.E_NoDefaultString, setString, nil},
|
||||
{pb.E_NoDefaultBytes, setBytes, nil},
|
||||
{pb.E_NoDefaultEnum, setEnum, nil},
|
||||
{pb.E_DefaultDouble, setFloat64, float64(3.1415)},
|
||||
{pb.E_DefaultFloat, setFloat32, float32(3.14)},
|
||||
{pb.E_DefaultInt32, setInt32, int32(42)},
|
||||
{pb.E_DefaultInt64, setInt64, int64(43)},
|
||||
{pb.E_DefaultUint32, setUint32, uint32(44)},
|
||||
{pb.E_DefaultUint64, setUint64, uint64(45)},
|
||||
{pb.E_DefaultSint32, setInt32, int32(46)},
|
||||
{pb.E_DefaultSint64, setInt64, int64(47)},
|
||||
{pb.E_DefaultFixed32, setUint32, uint32(48)},
|
||||
{pb.E_DefaultFixed64, setUint64, uint64(49)},
|
||||
{pb.E_DefaultSfixed32, setInt32, int32(50)},
|
||||
{pb.E_DefaultSfixed64, setInt64, int64(51)},
|
||||
{pb.E_DefaultBool, setBool, true},
|
||||
{pb.E_DefaultBool, setBool2, true},
|
||||
{pb.E_DefaultString, setString, "Hello, string"},
|
||||
{pb.E_DefaultBytes, setBytes, []byte("Hello, bytes")},
|
||||
{pb.E_DefaultEnum, setEnum, pb.DefaultsMessage_ONE},
|
||||
}
|
||||
|
||||
checkVal := func(test testcase, msg *pb.DefaultsMessage, valWant interface{}) error {
|
||||
val, err := proto.GetExtension(msg, test.ext)
|
||||
if err != nil {
|
||||
if valWant != nil {
|
||||
return fmt.Errorf("GetExtension(): %s", err)
|
||||
}
|
||||
if want := proto.ErrMissingExtension; err != want {
|
||||
return fmt.Errorf("Unexpected error: got %v, want %v", err, want)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// All proto2 extension values are either a pointer to a value or a slice of values.
|
||||
ty := reflect.TypeOf(val)
|
||||
tyWant := reflect.TypeOf(test.ext.ExtensionType)
|
||||
if got, want := ty, tyWant; got != want {
|
||||
return fmt.Errorf("unexpected reflect.TypeOf(): got %v want %v", got, want)
|
||||
}
|
||||
tye := ty.Elem()
|
||||
tyeWant := tyWant.Elem()
|
||||
if got, want := tye, tyeWant; got != want {
|
||||
return fmt.Errorf("unexpected reflect.TypeOf().Elem(): got %v want %v", got, want)
|
||||
}
|
||||
|
||||
// Check the name of the type of the value.
|
||||
// If it is an enum it will be type int32 with the name of the enum.
|
||||
if got, want := tye.Name(), tye.Name(); got != want {
|
||||
return fmt.Errorf("unexpected reflect.TypeOf().Elem().Name(): got %v want %v", got, want)
|
||||
}
|
||||
|
||||
// Check that value is what we expect.
|
||||
// If we have a pointer in val, get the value it points to.
|
||||
valExp := val
|
||||
if ty.Kind() == reflect.Ptr {
|
||||
valExp = reflect.ValueOf(val).Elem().Interface()
|
||||
}
|
||||
if got, want := valExp, valWant; !reflect.DeepEqual(got, want) {
|
||||
return fmt.Errorf("unexpected reflect.DeepEqual(): got %v want %v", got, want)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
setTo := func(test testcase) interface{} {
|
||||
setTo := reflect.ValueOf(test.want)
|
||||
if typ := reflect.TypeOf(test.ext.ExtensionType); typ.Kind() == reflect.Ptr {
|
||||
setTo = reflect.New(typ).Elem()
|
||||
setTo.Set(reflect.New(setTo.Type().Elem()))
|
||||
setTo.Elem().Set(reflect.ValueOf(test.want))
|
||||
}
|
||||
return setTo.Interface()
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
msg := &pb.DefaultsMessage{}
|
||||
name := test.ext.Name
|
||||
|
||||
// Check the initial value.
|
||||
if err := checkVal(test, msg, test.def); err != nil {
|
||||
t.Errorf("%s: %v", name, err)
|
||||
}
|
||||
|
||||
// Set the per-type value and check value.
|
||||
name = fmt.Sprintf("%s (set to %T %v)", name, test.want, test.want)
|
||||
if err := proto.SetExtension(msg, test.ext, setTo(test)); err != nil {
|
||||
t.Errorf("%s: SetExtension(): %v", name, err)
|
||||
continue
|
||||
}
|
||||
if err := checkVal(test, msg, test.want); err != nil {
|
||||
t.Errorf("%s: %v", name, err)
|
||||
continue
|
||||
}
|
||||
|
||||
// Set and check the value.
|
||||
name += " (cleared)"
|
||||
proto.ClearExtension(msg, test.ext)
|
||||
if err := checkVal(test, msg, test.def); err != nil {
|
||||
t.Errorf("%s: %v", name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtensionsRoundTrip(t *testing.T) {
|
||||
msg := &pb.MyMessage{}
|
||||
ext1 := &pb.Ext{
|
||||
Data: proto.String("hi"),
|
||||
}
|
||||
ext2 := &pb.Ext{
|
||||
Data: proto.String("there"),
|
||||
}
|
||||
exists := proto.HasExtension(msg, pb.E_Ext_More)
|
||||
if exists {
|
||||
t.Error("Extension More present unexpectedly")
|
||||
}
|
||||
if err := proto.SetExtension(msg, pb.E_Ext_More, ext1); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := proto.SetExtension(msg, pb.E_Ext_More, ext2); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
e, err := proto.GetExtension(msg, pb.E_Ext_More)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
x, ok := e.(*pb.Ext)
|
||||
if !ok {
|
||||
t.Errorf("e has type %T, expected testdata.Ext", e)
|
||||
} else if *x.Data != "there" {
|
||||
t.Errorf("SetExtension failed to overwrite, got %+v, not 'there'", x)
|
||||
}
|
||||
proto.ClearExtension(msg, pb.E_Ext_More)
|
||||
if _, err = proto.GetExtension(msg, pb.E_Ext_More); err != proto.ErrMissingExtension {
|
||||
t.Errorf("got %v, expected ErrMissingExtension", e)
|
||||
}
|
||||
if _, err := proto.GetExtension(msg, pb.E_X215); err == nil {
|
||||
t.Error("expected bad extension error, got nil")
|
||||
}
|
||||
if err := proto.SetExtension(msg, pb.E_X215, 12); err == nil {
|
||||
t.Error("expected extension err")
|
||||
}
|
||||
if err := proto.SetExtension(msg, pb.E_Ext_More, 12); err == nil {
|
||||
t.Error("expected some sort of type mismatch error, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNilExtension(t *testing.T) {
|
||||
msg := &pb.MyMessage{
|
||||
Count: proto.Int32(1),
|
||||
}
|
||||
if err := proto.SetExtension(msg, pb.E_Ext_Text, proto.String("hello")); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := proto.SetExtension(msg, pb.E_Ext_More, (*pb.Ext)(nil)); err == nil {
|
||||
t.Error("expected SetExtension to fail due to a nil extension")
|
||||
} else if want := "proto: SetExtension called with nil value of type *testdata.Ext"; err.Error() != want {
|
||||
t.Errorf("expected error %v, got %v", want, err)
|
||||
}
|
||||
// Note: if the behavior of Marshal is ever changed to ignore nil extensions, update
|
||||
// this test to verify that E_Ext_Text is properly propagated through marshal->unmarshal.
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package proto
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestUnmarshalMessageSetWithDuplicate(t *testing.T) {
|
||||
// Check that a repeated message set entry will be concatenated.
|
||||
in := &messageSet{
|
||||
Item: []*_MessageSet_Item{
|
||||
{TypeId: Int32(12345), Message: []byte("hoo")},
|
||||
{TypeId: Int32(12345), Message: []byte("hah")},
|
||||
},
|
||||
}
|
||||
b, err := Marshal(in)
|
||||
if err != nil {
|
||||
t.Fatalf("Marshal: %v", err)
|
||||
}
|
||||
t.Logf("Marshaled bytes: %q", b)
|
||||
|
||||
m := make(map[int32]Extension)
|
||||
if err := UnmarshalMessageSet(b, m); err != nil {
|
||||
t.Fatalf("UnmarshalMessageSet: %v", err)
|
||||
}
|
||||
ext, ok := m[12345]
|
||||
if !ok {
|
||||
t.Fatalf("Didn't retrieve extension 12345; map is %v", m)
|
||||
}
|
||||
// Skip wire type/field number and length varints.
|
||||
got := skipVarint(skipVarint(ext.enc))
|
||||
if want := []byte("hoohah"); !bytes.Equal(got, want) {
|
||||
t.Errorf("Combined extension is %q, want %q", got, want)
|
||||
}
|
||||
}
|
129
Godeps/_workspace/src/github.com/gogo/protobuf/proto/proto3_proto/proto3.pb.go
generated
vendored
129
Godeps/_workspace/src/github.com/gogo/protobuf/proto/proto3_proto/proto3.pb.go
generated
vendored
|
@ -1,129 +0,0 @@
|
|||
// Code generated by protoc-gen-gogo.
|
||||
// source: proto3_proto/proto3.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package proto3_proto is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
proto3_proto/proto3.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Message
|
||||
Nested
|
||||
MessageWithMap
|
||||
*/
|
||||
package proto3_proto
|
||||
|
||||
import proto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import testdata "github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
type Message_Humour int32
|
||||
|
||||
const (
|
||||
Message_UNKNOWN Message_Humour = 0
|
||||
Message_PUNS Message_Humour = 1
|
||||
Message_SLAPSTICK Message_Humour = 2
|
||||
Message_BILL_BAILEY Message_Humour = 3
|
||||
)
|
||||
|
||||
var Message_Humour_name = map[int32]string{
|
||||
0: "UNKNOWN",
|
||||
1: "PUNS",
|
||||
2: "SLAPSTICK",
|
||||
3: "BILL_BAILEY",
|
||||
}
|
||||
var Message_Humour_value = map[string]int32{
|
||||
"UNKNOWN": 0,
|
||||
"PUNS": 1,
|
||||
"SLAPSTICK": 2,
|
||||
"BILL_BAILEY": 3,
|
||||
}
|
||||
|
||||
func (x Message_Humour) String() string {
|
||||
return proto.EnumName(Message_Humour_name, int32(x))
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Hilarity Message_Humour `protobuf:"varint,2,opt,name=hilarity,proto3,enum=proto3_proto.Message_Humour" json:"hilarity,omitempty"`
|
||||
HeightInCm uint32 `protobuf:"varint,3,opt,name=height_in_cm,proto3" json:"height_in_cm,omitempty"`
|
||||
Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"`
|
||||
ResultCount int64 `protobuf:"varint,7,opt,name=result_count,proto3" json:"result_count,omitempty"`
|
||||
TrueScotsman bool `protobuf:"varint,8,opt,name=true_scotsman,proto3" json:"true_scotsman,omitempty"`
|
||||
Score float32 `protobuf:"fixed32,9,opt,name=score,proto3" json:"score,omitempty"`
|
||||
Key []uint64 `protobuf:"varint,5,rep,name=key" json:"key,omitempty"`
|
||||
Nested *Nested `protobuf:"bytes,6,opt,name=nested" json:"nested,omitempty"`
|
||||
Terrain map[string]*Nested `protobuf:"bytes,10,rep,name=terrain" json:"terrain,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value"`
|
||||
Proto2Field *testdata.SubDefaults `protobuf:"bytes,11,opt,name=proto2_field" json:"proto2_field,omitempty"`
|
||||
Proto2Value map[string]*testdata.SubDefaults `protobuf:"bytes,13,rep,name=proto2_value" json:"proto2_value,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value"`
|
||||
}
|
||||
|
||||
func (m *Message) Reset() { *m = Message{} }
|
||||
func (m *Message) String() string { return proto.CompactTextString(m) }
|
||||
func (*Message) ProtoMessage() {}
|
||||
|
||||
func (m *Message) GetNested() *Nested {
|
||||
if m != nil {
|
||||
return m.Nested
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Message) GetTerrain() map[string]*Nested {
|
||||
if m != nil {
|
||||
return m.Terrain
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Message) GetProto2Field() *testdata.SubDefaults {
|
||||
if m != nil {
|
||||
return m.Proto2Field
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Message) GetProto2Value() map[string]*testdata.SubDefaults {
|
||||
if m != nil {
|
||||
return m.Proto2Value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Nested struct {
|
||||
Bunny string `protobuf:"bytes,1,opt,name=bunny,proto3" json:"bunny,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Nested) Reset() { *m = Nested{} }
|
||||
func (m *Nested) String() string { return proto.CompactTextString(m) }
|
||||
func (*Nested) ProtoMessage() {}
|
||||
|
||||
type MessageWithMap struct {
|
||||
ByteMapping map[bool][]byte `protobuf:"bytes,1,rep,name=byte_mapping" json:"byte_mapping,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||
}
|
||||
|
||||
func (m *MessageWithMap) Reset() { *m = MessageWithMap{} }
|
||||
func (m *MessageWithMap) String() string { return proto.CompactTextString(m) }
|
||||
func (*MessageWithMap) ProtoMessage() {}
|
||||
|
||||
func (m *MessageWithMap) GetByteMapping() map[bool][]byte {
|
||||
if m != nil {
|
||||
return m.ByteMapping
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Message)(nil), "proto3_proto.Message")
|
||||
proto.RegisterType((*Nested)(nil), "proto3_proto.Nested")
|
||||
proto.RegisterType((*MessageWithMap)(nil), "proto3_proto.MessageWithMap")
|
||||
proto.RegisterEnum("proto3_proto.Message_Humour", Message_Humour_name, Message_Humour_value)
|
||||
}
|
68
Godeps/_workspace/src/github.com/gogo/protobuf/proto/proto3_proto/proto3.proto
generated
vendored
68
Godeps/_workspace/src/github.com/gogo/protobuf/proto/proto3_proto/proto3.proto
generated
vendored
|
@ -1,68 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package proto3_proto;
|
||||
|
||||
import "github.com/gogo/protobuf/proto/testdata/test.proto";
|
||||
|
||||
message Message {
|
||||
enum Humour {
|
||||
UNKNOWN = 0;
|
||||
PUNS = 1;
|
||||
SLAPSTICK = 2;
|
||||
BILL_BAILEY = 3;
|
||||
}
|
||||
|
||||
string name = 1;
|
||||
Humour hilarity = 2;
|
||||
uint32 height_in_cm = 3;
|
||||
bytes data = 4;
|
||||
int64 result_count = 7;
|
||||
bool true_scotsman = 8;
|
||||
float score = 9;
|
||||
|
||||
repeated uint64 key = 5;
|
||||
Nested nested = 6;
|
||||
|
||||
map<string, Nested> terrain = 10;
|
||||
testdata.SubDefaults proto2_field = 11;
|
||||
map<string, testdata.SubDefaults> proto2_value = 13;
|
||||
}
|
||||
|
||||
message Nested {
|
||||
string bunny = 1;
|
||||
}
|
||||
|
||||
message MessageWithMap {
|
||||
map<bool, bytes> byte_mapping = 1;
|
||||
}
|
|
@ -1,125 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package proto_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto"
|
||||
pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto/proto3_proto"
|
||||
tpb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata"
|
||||
)
|
||||
|
||||
func TestProto3ZeroValues(t *testing.T) {
|
||||
tests := []struct {
|
||||
desc string
|
||||
m proto.Message
|
||||
}{
|
||||
{"zero message", &pb.Message{}},
|
||||
{"empty bytes field", &pb.Message{Data: []byte{}}},
|
||||
}
|
||||
for _, test := range tests {
|
||||
b, err := proto.Marshal(test.m)
|
||||
if err != nil {
|
||||
t.Errorf("%s: proto.Marshal: %v", test.desc, err)
|
||||
continue
|
||||
}
|
||||
if len(b) > 0 {
|
||||
t.Errorf("%s: Encoding is non-empty: %q", test.desc, b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRoundTripProto3(t *testing.T) {
|
||||
m := &pb.Message{
|
||||
Name: "David", // (2 | 1<<3): 0x0a 0x05 "David"
|
||||
Hilarity: pb.Message_PUNS, // (0 | 2<<3): 0x10 0x01
|
||||
HeightInCm: 178, // (0 | 3<<3): 0x18 0xb2 0x01
|
||||
Data: []byte("roboto"), // (2 | 4<<3): 0x20 0x06 "roboto"
|
||||
ResultCount: 47, // (0 | 7<<3): 0x38 0x2f
|
||||
TrueScotsman: true, // (0 | 8<<3): 0x40 0x01
|
||||
Score: 8.1, // (5 | 9<<3): 0x4d <8.1>
|
||||
|
||||
Key: []uint64{1, 0xdeadbeef},
|
||||
Nested: &pb.Nested{
|
||||
Bunny: "Monty",
|
||||
},
|
||||
}
|
||||
t.Logf(" m: %v", m)
|
||||
|
||||
b, err := proto.Marshal(m)
|
||||
if err != nil {
|
||||
t.Fatalf("proto.Marshal: %v", err)
|
||||
}
|
||||
t.Logf(" b: %q", b)
|
||||
|
||||
m2 := new(pb.Message)
|
||||
if err := proto.Unmarshal(b, m2); err != nil {
|
||||
t.Fatalf("proto.Unmarshal: %v", err)
|
||||
}
|
||||
t.Logf("m2: %v", m2)
|
||||
|
||||
if !proto.Equal(m, m2) {
|
||||
t.Errorf("proto.Equal returned false:\n m: %v\nm2: %v", m, m2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProto3SetDefaults(t *testing.T) {
|
||||
in := &pb.Message{
|
||||
Terrain: map[string]*pb.Nested{
|
||||
"meadow": new(pb.Nested),
|
||||
},
|
||||
Proto2Field: new(tpb.SubDefaults),
|
||||
Proto2Value: map[string]*tpb.SubDefaults{
|
||||
"badlands": new(tpb.SubDefaults),
|
||||
},
|
||||
}
|
||||
|
||||
got := proto.Clone(in).(*pb.Message)
|
||||
proto.SetDefaults(got)
|
||||
|
||||
// There are no defaults in proto3. Everything should be the zero value, but
|
||||
// we need to remember to set defaults for nested proto2 messages.
|
||||
want := &pb.Message{
|
||||
Terrain: map[string]*pb.Nested{
|
||||
"meadow": new(pb.Nested),
|
||||
},
|
||||
Proto2Field: &tpb.SubDefaults{N: proto.Int64(7)},
|
||||
Proto2Value: map[string]*tpb.SubDefaults{
|
||||
"badlands": {N: proto.Int64(7)},
|
||||
},
|
||||
}
|
||||
|
||||
if !proto.Equal(got, want) {
|
||||
t.Errorf("with in = %v\nproto.SetDefaults(in) =>\ngot %v\nwant %v", in, got, want)
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package proto
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// This is a separate file and package from size_test.go because that one uses
|
||||
// generated messages and thus may not be in package proto without having a circular
|
||||
// dependency, whereas this file tests unexported details of size.go.
|
||||
|
||||
func TestVarintSize(t *testing.T) {
|
||||
// Check the edge cases carefully.
|
||||
testCases := []struct {
|
||||
n uint64
|
||||
size int
|
||||
}{
|
||||
{0, 1},
|
||||
{1, 1},
|
||||
{127, 1},
|
||||
{128, 2},
|
||||
{16383, 2},
|
||||
{16384, 3},
|
||||
{1<<63 - 1, 9},
|
||||
{1 << 63, 10},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
size := sizeVarint(tc.n)
|
||||
if size != tc.size {
|
||||
t.Errorf("sizeVarint(%d) = %d, want %d", tc.n, size, tc.size)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,147 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package proto_test
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
. "github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto"
|
||||
proto3pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto/proto3_proto"
|
||||
pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata"
|
||||
)
|
||||
|
||||
var messageWithExtension1 = &pb.MyMessage{Count: Int32(7)}
|
||||
|
||||
// messageWithExtension2 is in equal_test.go.
|
||||
var messageWithExtension3 = &pb.MyMessage{Count: Int32(8)}
|
||||
|
||||
func init() {
|
||||
if err := SetExtension(messageWithExtension1, pb.E_Ext_More, &pb.Ext{Data: String("Abbott")}); err != nil {
|
||||
log.Panicf("SetExtension: %v", err)
|
||||
}
|
||||
if err := SetExtension(messageWithExtension3, pb.E_Ext_More, &pb.Ext{Data: String("Costello")}); err != nil {
|
||||
log.Panicf("SetExtension: %v", err)
|
||||
}
|
||||
|
||||
// Force messageWithExtension3 to have the extension encoded.
|
||||
Marshal(messageWithExtension3)
|
||||
|
||||
}
|
||||
|
||||
var SizeTests = []struct {
|
||||
desc string
|
||||
pb Message
|
||||
}{
|
||||
{"empty", &pb.OtherMessage{}},
|
||||
// Basic types.
|
||||
{"bool", &pb.Defaults{F_Bool: Bool(true)}},
|
||||
{"int32", &pb.Defaults{F_Int32: Int32(12)}},
|
||||
{"negative int32", &pb.Defaults{F_Int32: Int32(-1)}},
|
||||
{"small int64", &pb.Defaults{F_Int64: Int64(1)}},
|
||||
{"big int64", &pb.Defaults{F_Int64: Int64(1 << 20)}},
|
||||
{"negative int64", &pb.Defaults{F_Int64: Int64(-1)}},
|
||||
{"fixed32", &pb.Defaults{F_Fixed32: Uint32(71)}},
|
||||
{"fixed64", &pb.Defaults{F_Fixed64: Uint64(72)}},
|
||||
{"uint32", &pb.Defaults{F_Uint32: Uint32(123)}},
|
||||
{"uint64", &pb.Defaults{F_Uint64: Uint64(124)}},
|
||||
{"float", &pb.Defaults{F_Float: Float32(12.6)}},
|
||||
{"double", &pb.Defaults{F_Double: Float64(13.9)}},
|
||||
{"string", &pb.Defaults{F_String: String("niles")}},
|
||||
{"bytes", &pb.Defaults{F_Bytes: []byte("wowsa")}},
|
||||
{"bytes, empty", &pb.Defaults{F_Bytes: []byte{}}},
|
||||
{"sint32", &pb.Defaults{F_Sint32: Int32(65)}},
|
||||
{"sint64", &pb.Defaults{F_Sint64: Int64(67)}},
|
||||
{"enum", &pb.Defaults{F_Enum: pb.Defaults_BLUE.Enum()}},
|
||||
// Repeated.
|
||||
{"empty repeated bool", &pb.MoreRepeated{Bools: []bool{}}},
|
||||
{"repeated bool", &pb.MoreRepeated{Bools: []bool{false, true, true, false}}},
|
||||
{"packed repeated bool", &pb.MoreRepeated{BoolsPacked: []bool{false, true, true, false, true, true, true}}},
|
||||
{"repeated int32", &pb.MoreRepeated{Ints: []int32{1, 12203, 1729, -1}}},
|
||||
{"repeated int32 packed", &pb.MoreRepeated{IntsPacked: []int32{1, 12203, 1729}}},
|
||||
{"repeated int64 packed", &pb.MoreRepeated{Int64SPacked: []int64{
|
||||
// Need enough large numbers to verify that the header is counting the number of bytes
|
||||
// for the field, not the number of elements.
|
||||
1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62,
|
||||
1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62,
|
||||
}}},
|
||||
{"repeated string", &pb.MoreRepeated{Strings: []string{"r", "ken", "gri"}}},
|
||||
{"repeated fixed", &pb.MoreRepeated{Fixeds: []uint32{1, 2, 3, 4}}},
|
||||
// Nested.
|
||||
{"nested", &pb.OldMessage{Nested: &pb.OldMessage_Nested{Name: String("whatever")}}},
|
||||
{"group", &pb.GroupOld{G: &pb.GroupOld_G{X: Int32(12345)}}},
|
||||
// Other things.
|
||||
{"unrecognized", &pb.MoreRepeated{XXX_unrecognized: []byte{13<<3 | 0, 4}}},
|
||||
{"extension (unencoded)", messageWithExtension1},
|
||||
{"extension (encoded)", messageWithExtension3},
|
||||
// proto3 message
|
||||
{"proto3 empty", &proto3pb.Message{}},
|
||||
{"proto3 bool", &proto3pb.Message{TrueScotsman: true}},
|
||||
{"proto3 int64", &proto3pb.Message{ResultCount: 1}},
|
||||
{"proto3 uint32", &proto3pb.Message{HeightInCm: 123}},
|
||||
{"proto3 float", &proto3pb.Message{Score: 12.6}},
|
||||
{"proto3 string", &proto3pb.Message{Name: "Snezana"}},
|
||||
{"proto3 bytes", &proto3pb.Message{Data: []byte("wowsa")}},
|
||||
{"proto3 bytes, empty", &proto3pb.Message{Data: []byte{}}},
|
||||
{"proto3 enum", &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}},
|
||||
{"proto3 map field with empty bytes", &proto3pb.MessageWithMap{ByteMapping: map[bool][]byte{false: {}}}},
|
||||
|
||||
{"map field", &pb.MessageWithMap{NameMapping: map[int32]string{1: "Rob", 7: "Andrew"}}},
|
||||
{"map field with message", &pb.MessageWithMap{MsgMapping: map[int64]*pb.FloatingPoint{0x7001: {F: Float64(2.0)}}}},
|
||||
{"map field with bytes", &pb.MessageWithMap{ByteMapping: map[bool][]byte{true: []byte("this time for sure")}}},
|
||||
{"map field with empty bytes", &pb.MessageWithMap{ByteMapping: map[bool][]byte{true: {}}}},
|
||||
|
||||
{"map field with big entry", &pb.MessageWithMap{NameMapping: map[int32]string{8: strings.Repeat("x", 125)}}},
|
||||
{"map field with big key and val", &pb.MessageWithMap{StrToStr: map[string]string{strings.Repeat("x", 70): strings.Repeat("y", 70)}}},
|
||||
{"map field with big numeric key", &pb.MessageWithMap{NameMapping: map[int32]string{0xf00d: "om nom nom"}}},
|
||||
|
||||
{"oneof not set", &pb.Communique{}},
|
||||
{"oneof zero int32", &pb.Communique{Union: &pb.Communique_Number{Number: 0}}},
|
||||
{"oneof int32", &pb.Communique{Union: &pb.Communique_Number{Number: 3}}},
|
||||
{"oneof string", &pb.Communique{Union: &pb.Communique_Name{Name: "Rhythmic Fman"}}},
|
||||
}
|
||||
|
||||
func TestSize(t *testing.T) {
|
||||
for _, tc := range SizeTests {
|
||||
size := Size(tc.pb)
|
||||
b, err := Marshal(tc.pb)
|
||||
if err != nil {
|
||||
t.Errorf("%v: Marshal failed: %v", tc.desc, err)
|
||||
continue
|
||||
}
|
||||
if size != len(b) {
|
||||
t.Errorf("%v: Size(%v) = %d, want %d", tc.desc, tc.pb, size, len(b))
|
||||
t.Logf("%v: bytes: %#v", tc.desc, b)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
# Go support for Protocol Buffers - Google's data interchange format
|
||||
#
|
||||
# Copyright 2010 The Go Authors. All rights reserved.
|
||||
# https://github.com/golang/protobuf
|
||||
#
|
||||
# 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.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
all: regenerate
|
||||
|
||||
regenerate:
|
||||
go install github.com/gogo/protobuf/protoc-min-version
|
||||
protoc-min-version --version="3.0.0" --gogo_out=. test.proto
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Verify that the compiler output for test.proto is unchanged.
|
||||
|
||||
package testdata
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// sum returns in string form (for easy comparison) the SHA-1 hash of the named file.
|
||||
func sum(t *testing.T, name string) string {
|
||||
data, err := ioutil.ReadFile(name)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Logf("sum(%q): length is %d", name, len(data))
|
||||
hash := sha1.New()
|
||||
_, err = hash.Write(data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return fmt.Sprintf("% x", hash.Sum(nil))
|
||||
}
|
||||
|
||||
func run(t *testing.T, name string, args ...string) {
|
||||
cmd := exec.Command(name, args...)
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGolden(t *testing.T) {
|
||||
// Compute the original checksum.
|
||||
goldenSum := sum(t, "test.pb.go")
|
||||
// Run the proto compiler.
|
||||
run(t, "protoc", "--gogo_out="+os.TempDir(), "test.proto")
|
||||
newFile := filepath.Join(os.TempDir(), "test.pb.go")
|
||||
defer os.Remove(newFile)
|
||||
// Compute the new checksum.
|
||||
newSum := sum(t, newFile)
|
||||
// Verify
|
||||
if newSum != goldenSum {
|
||||
run(t, "diff", "-u", "test.pb.go", newFile)
|
||||
t.Fatal("Code generated by protoc-gen-go has changed; update test.pb.go")
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
1737
Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata/test.pb.go.golden
generated
vendored
1737
Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata/test.pb.go.golden
generated
vendored
File diff suppressed because it is too large
Load Diff
|
@ -1,494 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// A feature-rich test file for the protocol compiler and libraries.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package testdata;
|
||||
|
||||
enum FOO { FOO1 = 1; };
|
||||
|
||||
message GoEnum {
|
||||
required FOO foo = 1;
|
||||
}
|
||||
|
||||
message GoTestField {
|
||||
required string Label = 1;
|
||||
required string Type = 2;
|
||||
}
|
||||
|
||||
message GoTest {
|
||||
// An enum, for completeness.
|
||||
enum KIND {
|
||||
VOID = 0;
|
||||
|
||||
// Basic types
|
||||
BOOL = 1;
|
||||
BYTES = 2;
|
||||
FINGERPRINT = 3;
|
||||
FLOAT = 4;
|
||||
INT = 5;
|
||||
STRING = 6;
|
||||
TIME = 7;
|
||||
|
||||
// Groupings
|
||||
TUPLE = 8;
|
||||
ARRAY = 9;
|
||||
MAP = 10;
|
||||
|
||||
// Table types
|
||||
TABLE = 11;
|
||||
|
||||
// Functions
|
||||
FUNCTION = 12; // last tag
|
||||
};
|
||||
|
||||
// Some typical parameters
|
||||
required KIND Kind = 1;
|
||||
optional string Table = 2;
|
||||
optional int32 Param = 3;
|
||||
|
||||
// Required, repeated and optional foreign fields.
|
||||
required GoTestField RequiredField = 4;
|
||||
repeated GoTestField RepeatedField = 5;
|
||||
optional GoTestField OptionalField = 6;
|
||||
|
||||
// Required fields of all basic types
|
||||
required bool F_Bool_required = 10;
|
||||
required int32 F_Int32_required = 11;
|
||||
required int64 F_Int64_required = 12;
|
||||
required fixed32 F_Fixed32_required = 13;
|
||||
required fixed64 F_Fixed64_required = 14;
|
||||
required uint32 F_Uint32_required = 15;
|
||||
required uint64 F_Uint64_required = 16;
|
||||
required float F_Float_required = 17;
|
||||
required double F_Double_required = 18;
|
||||
required string F_String_required = 19;
|
||||
required bytes F_Bytes_required = 101;
|
||||
required sint32 F_Sint32_required = 102;
|
||||
required sint64 F_Sint64_required = 103;
|
||||
|
||||
// Repeated fields of all basic types
|
||||
repeated bool F_Bool_repeated = 20;
|
||||
repeated int32 F_Int32_repeated = 21;
|
||||
repeated int64 F_Int64_repeated = 22;
|
||||
repeated fixed32 F_Fixed32_repeated = 23;
|
||||
repeated fixed64 F_Fixed64_repeated = 24;
|
||||
repeated uint32 F_Uint32_repeated = 25;
|
||||
repeated uint64 F_Uint64_repeated = 26;
|
||||
repeated float F_Float_repeated = 27;
|
||||
repeated double F_Double_repeated = 28;
|
||||
repeated string F_String_repeated = 29;
|
||||
repeated bytes F_Bytes_repeated = 201;
|
||||
repeated sint32 F_Sint32_repeated = 202;
|
||||
repeated sint64 F_Sint64_repeated = 203;
|
||||
|
||||
// Optional fields of all basic types
|
||||
optional bool F_Bool_optional = 30;
|
||||
optional int32 F_Int32_optional = 31;
|
||||
optional int64 F_Int64_optional = 32;
|
||||
optional fixed32 F_Fixed32_optional = 33;
|
||||
optional fixed64 F_Fixed64_optional = 34;
|
||||
optional uint32 F_Uint32_optional = 35;
|
||||
optional uint64 F_Uint64_optional = 36;
|
||||
optional float F_Float_optional = 37;
|
||||
optional double F_Double_optional = 38;
|
||||
optional string F_String_optional = 39;
|
||||
optional bytes F_Bytes_optional = 301;
|
||||
optional sint32 F_Sint32_optional = 302;
|
||||
optional sint64 F_Sint64_optional = 303;
|
||||
|
||||
// Default-valued fields of all basic types
|
||||
optional bool F_Bool_defaulted = 40 [default=true];
|
||||
optional int32 F_Int32_defaulted = 41 [default=32];
|
||||
optional int64 F_Int64_defaulted = 42 [default=64];
|
||||
optional fixed32 F_Fixed32_defaulted = 43 [default=320];
|
||||
optional fixed64 F_Fixed64_defaulted = 44 [default=640];
|
||||
optional uint32 F_Uint32_defaulted = 45 [default=3200];
|
||||
optional uint64 F_Uint64_defaulted = 46 [default=6400];
|
||||
optional float F_Float_defaulted = 47 [default=314159.];
|
||||
optional double F_Double_defaulted = 48 [default=271828.];
|
||||
optional string F_String_defaulted = 49 [default="hello, \"world!\"\n"];
|
||||
optional bytes F_Bytes_defaulted = 401 [default="Bignose"];
|
||||
optional sint32 F_Sint32_defaulted = 402 [default = -32];
|
||||
optional sint64 F_Sint64_defaulted = 403 [default = -64];
|
||||
|
||||
// Packed repeated fields (no string or bytes).
|
||||
repeated bool F_Bool_repeated_packed = 50 [packed=true];
|
||||
repeated int32 F_Int32_repeated_packed = 51 [packed=true];
|
||||
repeated int64 F_Int64_repeated_packed = 52 [packed=true];
|
||||
repeated fixed32 F_Fixed32_repeated_packed = 53 [packed=true];
|
||||
repeated fixed64 F_Fixed64_repeated_packed = 54 [packed=true];
|
||||
repeated uint32 F_Uint32_repeated_packed = 55 [packed=true];
|
||||
repeated uint64 F_Uint64_repeated_packed = 56 [packed=true];
|
||||
repeated float F_Float_repeated_packed = 57 [packed=true];
|
||||
repeated double F_Double_repeated_packed = 58 [packed=true];
|
||||
repeated sint32 F_Sint32_repeated_packed = 502 [packed=true];
|
||||
repeated sint64 F_Sint64_repeated_packed = 503 [packed=true];
|
||||
|
||||
// Required, repeated, and optional groups.
|
||||
required group RequiredGroup = 70 {
|
||||
required string RequiredField = 71;
|
||||
};
|
||||
|
||||
repeated group RepeatedGroup = 80 {
|
||||
required string RequiredField = 81;
|
||||
};
|
||||
|
||||
optional group OptionalGroup = 90 {
|
||||
required string RequiredField = 91;
|
||||
};
|
||||
}
|
||||
|
||||
// For testing skipping of unrecognized fields.
|
||||
// Numbers are all big, larger than tag numbers in GoTestField,
|
||||
// the message used in the corresponding test.
|
||||
message GoSkipTest {
|
||||
required int32 skip_int32 = 11;
|
||||
required fixed32 skip_fixed32 = 12;
|
||||
required fixed64 skip_fixed64 = 13;
|
||||
required string skip_string = 14;
|
||||
required group SkipGroup = 15 {
|
||||
required int32 group_int32 = 16;
|
||||
required string group_string = 17;
|
||||
}
|
||||
}
|
||||
|
||||
// For testing packed/non-packed decoder switching.
|
||||
// A serialized instance of one should be deserializable as the other.
|
||||
message NonPackedTest {
|
||||
repeated int32 a = 1;
|
||||
}
|
||||
|
||||
message PackedTest {
|
||||
repeated int32 b = 1 [packed=true];
|
||||
}
|
||||
|
||||
message MaxTag {
|
||||
// Maximum possible tag number.
|
||||
optional string last_field = 536870911;
|
||||
}
|
||||
|
||||
message OldMessage {
|
||||
message Nested {
|
||||
optional string name = 1;
|
||||
}
|
||||
optional Nested nested = 1;
|
||||
|
||||
optional int32 num = 2;
|
||||
}
|
||||
|
||||
// NewMessage is wire compatible with OldMessage;
|
||||
// imagine it as a future version.
|
||||
message NewMessage {
|
||||
message Nested {
|
||||
optional string name = 1;
|
||||
optional string food_group = 2;
|
||||
}
|
||||
optional Nested nested = 1;
|
||||
|
||||
// This is an int32 in OldMessage.
|
||||
optional int64 num = 2;
|
||||
}
|
||||
|
||||
// Smaller tests for ASCII formatting.
|
||||
|
||||
message InnerMessage {
|
||||
required string host = 1;
|
||||
optional int32 port = 2 [default=4000];
|
||||
optional bool connected = 3;
|
||||
}
|
||||
|
||||
message OtherMessage {
|
||||
optional int64 key = 1;
|
||||
optional bytes value = 2;
|
||||
optional float weight = 3;
|
||||
optional InnerMessage inner = 4;
|
||||
}
|
||||
|
||||
message MyMessage {
|
||||
required int32 count = 1;
|
||||
optional string name = 2;
|
||||
optional string quote = 3;
|
||||
repeated string pet = 4;
|
||||
optional InnerMessage inner = 5;
|
||||
repeated OtherMessage others = 6;
|
||||
repeated InnerMessage rep_inner = 12;
|
||||
|
||||
enum Color {
|
||||
RED = 0;
|
||||
GREEN = 1;
|
||||
BLUE = 2;
|
||||
};
|
||||
optional Color bikeshed = 7;
|
||||
|
||||
optional group SomeGroup = 8 {
|
||||
optional int32 group_field = 9;
|
||||
}
|
||||
|
||||
// This field becomes [][]byte in the generated code.
|
||||
repeated bytes rep_bytes = 10;
|
||||
|
||||
optional double bigfloat = 11;
|
||||
|
||||
extensions 100 to max;
|
||||
}
|
||||
|
||||
message Ext {
|
||||
extend MyMessage {
|
||||
optional Ext more = 103;
|
||||
optional string text = 104;
|
||||
optional int32 number = 105;
|
||||
}
|
||||
|
||||
optional string data = 1;
|
||||
}
|
||||
|
||||
extend MyMessage {
|
||||
repeated string greeting = 106;
|
||||
}
|
||||
|
||||
message DefaultsMessage {
|
||||
enum DefaultsEnum {
|
||||
ZERO = 0;
|
||||
ONE = 1;
|
||||
TWO = 2;
|
||||
};
|
||||
extensions 100 to max;
|
||||
}
|
||||
|
||||
extend DefaultsMessage {
|
||||
optional double no_default_double = 101;
|
||||
optional float no_default_float = 102;
|
||||
optional int32 no_default_int32 = 103;
|
||||
optional int64 no_default_int64 = 104;
|
||||
optional uint32 no_default_uint32 = 105;
|
||||
optional uint64 no_default_uint64 = 106;
|
||||
optional sint32 no_default_sint32 = 107;
|
||||
optional sint64 no_default_sint64 = 108;
|
||||
optional fixed32 no_default_fixed32 = 109;
|
||||
optional fixed64 no_default_fixed64 = 110;
|
||||
optional sfixed32 no_default_sfixed32 = 111;
|
||||
optional sfixed64 no_default_sfixed64 = 112;
|
||||
optional bool no_default_bool = 113;
|
||||
optional string no_default_string = 114;
|
||||
optional bytes no_default_bytes = 115;
|
||||
optional DefaultsMessage.DefaultsEnum no_default_enum = 116;
|
||||
|
||||
optional double default_double = 201 [default = 3.1415];
|
||||
optional float default_float = 202 [default = 3.14];
|
||||
optional int32 default_int32 = 203 [default = 42];
|
||||
optional int64 default_int64 = 204 [default = 43];
|
||||
optional uint32 default_uint32 = 205 [default = 44];
|
||||
optional uint64 default_uint64 = 206 [default = 45];
|
||||
optional sint32 default_sint32 = 207 [default = 46];
|
||||
optional sint64 default_sint64 = 208 [default = 47];
|
||||
optional fixed32 default_fixed32 = 209 [default = 48];
|
||||
optional fixed64 default_fixed64 = 210 [default = 49];
|
||||
optional sfixed32 default_sfixed32 = 211 [default = 50];
|
||||
optional sfixed64 default_sfixed64 = 212 [default = 51];
|
||||
optional bool default_bool = 213 [default = true];
|
||||
optional string default_string = 214 [default = "Hello, string"];
|
||||
optional bytes default_bytes = 215 [default = "Hello, bytes"];
|
||||
optional DefaultsMessage.DefaultsEnum default_enum = 216 [default = ONE];
|
||||
}
|
||||
|
||||
message MyMessageSet {
|
||||
option message_set_wire_format = true;
|
||||
extensions 100 to max;
|
||||
}
|
||||
|
||||
message Empty {
|
||||
}
|
||||
|
||||
extend MyMessageSet {
|
||||
optional Empty x201 = 201;
|
||||
optional Empty x202 = 202;
|
||||
optional Empty x203 = 203;
|
||||
optional Empty x204 = 204;
|
||||
optional Empty x205 = 205;
|
||||
optional Empty x206 = 206;
|
||||
optional Empty x207 = 207;
|
||||
optional Empty x208 = 208;
|
||||
optional Empty x209 = 209;
|
||||
optional Empty x210 = 210;
|
||||
optional Empty x211 = 211;
|
||||
optional Empty x212 = 212;
|
||||
optional Empty x213 = 213;
|
||||
optional Empty x214 = 214;
|
||||
optional Empty x215 = 215;
|
||||
optional Empty x216 = 216;
|
||||
optional Empty x217 = 217;
|
||||
optional Empty x218 = 218;
|
||||
optional Empty x219 = 219;
|
||||
optional Empty x220 = 220;
|
||||
optional Empty x221 = 221;
|
||||
optional Empty x222 = 222;
|
||||
optional Empty x223 = 223;
|
||||
optional Empty x224 = 224;
|
||||
optional Empty x225 = 225;
|
||||
optional Empty x226 = 226;
|
||||
optional Empty x227 = 227;
|
||||
optional Empty x228 = 228;
|
||||
optional Empty x229 = 229;
|
||||
optional Empty x230 = 230;
|
||||
optional Empty x231 = 231;
|
||||
optional Empty x232 = 232;
|
||||
optional Empty x233 = 233;
|
||||
optional Empty x234 = 234;
|
||||
optional Empty x235 = 235;
|
||||
optional Empty x236 = 236;
|
||||
optional Empty x237 = 237;
|
||||
optional Empty x238 = 238;
|
||||
optional Empty x239 = 239;
|
||||
optional Empty x240 = 240;
|
||||
optional Empty x241 = 241;
|
||||
optional Empty x242 = 242;
|
||||
optional Empty x243 = 243;
|
||||
optional Empty x244 = 244;
|
||||
optional Empty x245 = 245;
|
||||
optional Empty x246 = 246;
|
||||
optional Empty x247 = 247;
|
||||
optional Empty x248 = 248;
|
||||
optional Empty x249 = 249;
|
||||
optional Empty x250 = 250;
|
||||
}
|
||||
|
||||
message MessageList {
|
||||
repeated group Message = 1 {
|
||||
required string name = 2;
|
||||
required int32 count = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message Strings {
|
||||
optional string string_field = 1;
|
||||
optional bytes bytes_field = 2;
|
||||
}
|
||||
|
||||
message Defaults {
|
||||
enum Color {
|
||||
RED = 0;
|
||||
GREEN = 1;
|
||||
BLUE = 2;
|
||||
}
|
||||
|
||||
// Default-valued fields of all basic types.
|
||||
// Same as GoTest, but copied here to make testing easier.
|
||||
optional bool F_Bool = 1 [default=true];
|
||||
optional int32 F_Int32 = 2 [default=32];
|
||||
optional int64 F_Int64 = 3 [default=64];
|
||||
optional fixed32 F_Fixed32 = 4 [default=320];
|
||||
optional fixed64 F_Fixed64 = 5 [default=640];
|
||||
optional uint32 F_Uint32 = 6 [default=3200];
|
||||
optional uint64 F_Uint64 = 7 [default=6400];
|
||||
optional float F_Float = 8 [default=314159.];
|
||||
optional double F_Double = 9 [default=271828.];
|
||||
optional string F_String = 10 [default="hello, \"world!\"\n"];
|
||||
optional bytes F_Bytes = 11 [default="Bignose"];
|
||||
optional sint32 F_Sint32 = 12 [default=-32];
|
||||
optional sint64 F_Sint64 = 13 [default=-64];
|
||||
optional Color F_Enum = 14 [default=GREEN];
|
||||
|
||||
// More fields with crazy defaults.
|
||||
optional float F_Pinf = 15 [default=inf];
|
||||
optional float F_Ninf = 16 [default=-inf];
|
||||
optional float F_Nan = 17 [default=nan];
|
||||
|
||||
// Sub-message.
|
||||
optional SubDefaults sub = 18;
|
||||
|
||||
// Redundant but explicit defaults.
|
||||
optional string str_zero = 19 [default=""];
|
||||
}
|
||||
|
||||
message SubDefaults {
|
||||
optional int64 n = 1 [default=7];
|
||||
}
|
||||
|
||||
message RepeatedEnum {
|
||||
enum Color {
|
||||
RED = 1;
|
||||
}
|
||||
repeated Color color = 1;
|
||||
}
|
||||
|
||||
message MoreRepeated {
|
||||
repeated bool bools = 1;
|
||||
repeated bool bools_packed = 2 [packed=true];
|
||||
repeated int32 ints = 3;
|
||||
repeated int32 ints_packed = 4 [packed=true];
|
||||
repeated int64 int64s_packed = 7 [packed=true];
|
||||
repeated string strings = 5;
|
||||
repeated fixed32 fixeds = 6;
|
||||
}
|
||||
|
||||
// GroupOld and GroupNew have the same wire format.
|
||||
// GroupNew has a new field inside a group.
|
||||
|
||||
message GroupOld {
|
||||
optional group G = 101 {
|
||||
optional int32 x = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message GroupNew {
|
||||
optional group G = 101 {
|
||||
optional int32 x = 2;
|
||||
optional int32 y = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message FloatingPoint {
|
||||
required double f = 1;
|
||||
}
|
||||
|
||||
message MessageWithMap {
|
||||
map<int32, string> name_mapping = 1;
|
||||
map<sint64, FloatingPoint> msg_mapping = 2;
|
||||
map<bool, bytes> byte_mapping = 3;
|
||||
map<string, string> str_to_str = 4;
|
||||
}
|
||||
|
||||
message Communique {
|
||||
optional bool make_me_cry = 1;
|
||||
|
||||
// This is a oneof, called "union".
|
||||
oneof union {
|
||||
int32 number = 5;
|
||||
string name = 6;
|
||||
bytes data = 7;
|
||||
double temp_c = 8;
|
||||
MyMessage.Color col = 9;
|
||||
Strings msg = 10;
|
||||
}
|
||||
}
|
|
@ -1,532 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package proto_test
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
. "github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto"
|
||||
proto3pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto/proto3_proto"
|
||||
. "github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata"
|
||||
)
|
||||
|
||||
type UnmarshalTextTest struct {
|
||||
in string
|
||||
err string // if "", no error expected
|
||||
out *MyMessage
|
||||
}
|
||||
|
||||
func buildExtStructTest(text string) UnmarshalTextTest {
|
||||
msg := &MyMessage{
|
||||
Count: Int32(42),
|
||||
}
|
||||
SetExtension(msg, E_Ext_More, &Ext{
|
||||
Data: String("Hello, world!"),
|
||||
})
|
||||
return UnmarshalTextTest{in: text, out: msg}
|
||||
}
|
||||
|
||||
func buildExtDataTest(text string) UnmarshalTextTest {
|
||||
msg := &MyMessage{
|
||||
Count: Int32(42),
|
||||
}
|
||||
SetExtension(msg, E_Ext_Text, String("Hello, world!"))
|
||||
SetExtension(msg, E_Ext_Number, Int32(1729))
|
||||
return UnmarshalTextTest{in: text, out: msg}
|
||||
}
|
||||
|
||||
func buildExtRepStringTest(text string) UnmarshalTextTest {
|
||||
msg := &MyMessage{
|
||||
Count: Int32(42),
|
||||
}
|
||||
if err := SetExtension(msg, E_Greeting, []string{"bula", "hola"}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return UnmarshalTextTest{in: text, out: msg}
|
||||
}
|
||||
|
||||
var unMarshalTextTests = []UnmarshalTextTest{
|
||||
// Basic
|
||||
{
|
||||
in: " count:42\n name:\"Dave\" ",
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Name: String("Dave"),
|
||||
},
|
||||
},
|
||||
|
||||
// Empty quoted string
|
||||
{
|
||||
in: `count:42 name:""`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Name: String(""),
|
||||
},
|
||||
},
|
||||
|
||||
// Quoted string concatenation
|
||||
{
|
||||
in: `count:42 name: "My name is "` + "\n" + `"elsewhere"`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Name: String("My name is elsewhere"),
|
||||
},
|
||||
},
|
||||
|
||||
// Quoted string with escaped apostrophe
|
||||
{
|
||||
in: `count:42 name: "HOLIDAY - New Year\'s Day"`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Name: String("HOLIDAY - New Year's Day"),
|
||||
},
|
||||
},
|
||||
|
||||
// Quoted string with single quote
|
||||
{
|
||||
in: `count:42 name: 'Roger "The Ramster" Ramjet'`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Name: String(`Roger "The Ramster" Ramjet`),
|
||||
},
|
||||
},
|
||||
|
||||
// Quoted string with all the accepted special characters from the C++ test
|
||||
{
|
||||
in: `count:42 name: ` + "\"\\\"A string with \\' characters \\n and \\r newlines and \\t tabs and \\001 slashes \\\\ and multiple spaces\"",
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Name: String("\"A string with ' characters \n and \r newlines and \t tabs and \001 slashes \\ and multiple spaces"),
|
||||
},
|
||||
},
|
||||
|
||||
// Quoted string with quoted backslash
|
||||
{
|
||||
in: `count:42 name: "\\'xyz"`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Name: String(`\'xyz`),
|
||||
},
|
||||
},
|
||||
|
||||
// Quoted string with UTF-8 bytes.
|
||||
{
|
||||
in: "count:42 name: '\303\277\302\201\xAB'",
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Name: String("\303\277\302\201\xAB"),
|
||||
},
|
||||
},
|
||||
|
||||
// Bad quoted string
|
||||
{
|
||||
in: `inner: < host: "\0" >` + "\n",
|
||||
err: `line 1.15: invalid quoted string "\0": \0 requires 2 following digits`,
|
||||
},
|
||||
|
||||
// Number too large for int64
|
||||
{
|
||||
in: "count: 1 others { key: 123456789012345678901 }",
|
||||
err: "line 1.23: invalid int64: 123456789012345678901",
|
||||
},
|
||||
|
||||
// Number too large for int32
|
||||
{
|
||||
in: "count: 1234567890123",
|
||||
err: "line 1.7: invalid int32: 1234567890123",
|
||||
},
|
||||
|
||||
// Number in hexadecimal
|
||||
{
|
||||
in: "count: 0x2beef",
|
||||
out: &MyMessage{
|
||||
Count: Int32(0x2beef),
|
||||
},
|
||||
},
|
||||
|
||||
// Number in octal
|
||||
{
|
||||
in: "count: 024601",
|
||||
out: &MyMessage{
|
||||
Count: Int32(024601),
|
||||
},
|
||||
},
|
||||
|
||||
// Floating point number with "f" suffix
|
||||
{
|
||||
in: "count: 4 others:< weight: 17.0f >",
|
||||
out: &MyMessage{
|
||||
Count: Int32(4),
|
||||
Others: []*OtherMessage{
|
||||
{
|
||||
Weight: Float32(17),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Floating point positive infinity
|
||||
{
|
||||
in: "count: 4 bigfloat: inf",
|
||||
out: &MyMessage{
|
||||
Count: Int32(4),
|
||||
Bigfloat: Float64(math.Inf(1)),
|
||||
},
|
||||
},
|
||||
|
||||
// Floating point negative infinity
|
||||
{
|
||||
in: "count: 4 bigfloat: -inf",
|
||||
out: &MyMessage{
|
||||
Count: Int32(4),
|
||||
Bigfloat: Float64(math.Inf(-1)),
|
||||
},
|
||||
},
|
||||
|
||||
// Number too large for float32
|
||||
{
|
||||
in: "others:< weight: 12345678901234567890123456789012345678901234567890 >",
|
||||
err: "line 1.17: invalid float32: 12345678901234567890123456789012345678901234567890",
|
||||
},
|
||||
|
||||
// Number posing as a quoted string
|
||||
{
|
||||
in: `inner: < host: 12 >` + "\n",
|
||||
err: `line 1.15: invalid string: 12`,
|
||||
},
|
||||
|
||||
// Quoted string posing as int32
|
||||
{
|
||||
in: `count: "12"`,
|
||||
err: `line 1.7: invalid int32: "12"`,
|
||||
},
|
||||
|
||||
// Quoted string posing a float32
|
||||
{
|
||||
in: `others:< weight: "17.4" >`,
|
||||
err: `line 1.17: invalid float32: "17.4"`,
|
||||
},
|
||||
|
||||
// Enum
|
||||
{
|
||||
in: `count:42 bikeshed: BLUE`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Bikeshed: MyMessage_BLUE.Enum(),
|
||||
},
|
||||
},
|
||||
|
||||
// Repeated field
|
||||
{
|
||||
in: `count:42 pet: "horsey" pet:"bunny"`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Pet: []string{"horsey", "bunny"},
|
||||
},
|
||||
},
|
||||
|
||||
// Repeated field with list notation
|
||||
{
|
||||
in: `count:42 pet: ["horsey", "bunny"]`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Pet: []string{"horsey", "bunny"},
|
||||
},
|
||||
},
|
||||
|
||||
// Repeated message with/without colon and <>/{}
|
||||
{
|
||||
in: `count:42 others:{} others{} others:<> others:{}`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Others: []*OtherMessage{
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Missing colon for inner message
|
||||
{
|
||||
in: `count:42 inner < host: "cauchy.syd" >`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Inner: &InnerMessage{
|
||||
Host: String("cauchy.syd"),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Missing colon for string field
|
||||
{
|
||||
in: `name "Dave"`,
|
||||
err: `line 1.5: expected ':', found "\"Dave\""`,
|
||||
},
|
||||
|
||||
// Missing colon for int32 field
|
||||
{
|
||||
in: `count 42`,
|
||||
err: `line 1.6: expected ':', found "42"`,
|
||||
},
|
||||
|
||||
// Missing required field
|
||||
{
|
||||
in: `name: "Pawel"`,
|
||||
err: `proto: required field "testdata.MyMessage.count" not set`,
|
||||
out: &MyMessage{
|
||||
Name: String("Pawel"),
|
||||
},
|
||||
},
|
||||
|
||||
// Repeated non-repeated field
|
||||
{
|
||||
in: `name: "Rob" name: "Russ"`,
|
||||
err: `line 1.12: non-repeated field "name" was repeated`,
|
||||
},
|
||||
|
||||
// Group
|
||||
{
|
||||
in: `count: 17 SomeGroup { group_field: 12 }`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(17),
|
||||
Somegroup: &MyMessage_SomeGroup{
|
||||
GroupField: Int32(12),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Semicolon between fields
|
||||
{
|
||||
in: `count:3;name:"Calvin"`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(3),
|
||||
Name: String("Calvin"),
|
||||
},
|
||||
},
|
||||
// Comma between fields
|
||||
{
|
||||
in: `count:4,name:"Ezekiel"`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(4),
|
||||
Name: String("Ezekiel"),
|
||||
},
|
||||
},
|
||||
|
||||
// Extension
|
||||
buildExtStructTest(`count: 42 [testdata.Ext.more]:<data:"Hello, world!" >`),
|
||||
buildExtStructTest(`count: 42 [testdata.Ext.more] {data:"Hello, world!"}`),
|
||||
buildExtDataTest(`count: 42 [testdata.Ext.text]:"Hello, world!" [testdata.Ext.number]:1729`),
|
||||
buildExtRepStringTest(`count: 42 [testdata.greeting]:"bula" [testdata.greeting]:"hola"`),
|
||||
|
||||
// Big all-in-one
|
||||
{
|
||||
in: "count:42 # Meaning\n" +
|
||||
`name:"Dave" ` +
|
||||
`quote:"\"I didn't want to go.\"" ` +
|
||||
`pet:"bunny" ` +
|
||||
`pet:"kitty" ` +
|
||||
`pet:"horsey" ` +
|
||||
`inner:<` +
|
||||
` host:"footrest.syd" ` +
|
||||
` port:7001 ` +
|
||||
` connected:true ` +
|
||||
`> ` +
|
||||
`others:<` +
|
||||
` key:3735928559 ` +
|
||||
` value:"\x01A\a\f" ` +
|
||||
`> ` +
|
||||
`others:<` +
|
||||
" weight:58.9 # Atomic weight of Co\n" +
|
||||
` inner:<` +
|
||||
` host:"lesha.mtv" ` +
|
||||
` port:8002 ` +
|
||||
` >` +
|
||||
`>`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Name: String("Dave"),
|
||||
Quote: String(`"I didn't want to go."`),
|
||||
Pet: []string{"bunny", "kitty", "horsey"},
|
||||
Inner: &InnerMessage{
|
||||
Host: String("footrest.syd"),
|
||||
Port: Int32(7001),
|
||||
Connected: Bool(true),
|
||||
},
|
||||
Others: []*OtherMessage{
|
||||
{
|
||||
Key: Int64(3735928559),
|
||||
Value: []byte{0x1, 'A', '\a', '\f'},
|
||||
},
|
||||
{
|
||||
Weight: Float32(58.9),
|
||||
Inner: &InnerMessage{
|
||||
Host: String("lesha.mtv"),
|
||||
Port: Int32(8002),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestUnmarshalText(t *testing.T) {
|
||||
for i, test := range unMarshalTextTests {
|
||||
pb := new(MyMessage)
|
||||
err := UnmarshalText(test.in, pb)
|
||||
if test.err == "" {
|
||||
// We don't expect failure.
|
||||
if err != nil {
|
||||
t.Errorf("Test %d: Unexpected error: %v", i, err)
|
||||
} else if !reflect.DeepEqual(pb, test.out) {
|
||||
t.Errorf("Test %d: Incorrect populated \nHave: %v\nWant: %v",
|
||||
i, pb, test.out)
|
||||
}
|
||||
} else {
|
||||
// We do expect failure.
|
||||
if err == nil {
|
||||
t.Errorf("Test %d: Didn't get expected error: %v", i, test.err)
|
||||
} else if err.Error() != test.err {
|
||||
t.Errorf("Test %d: Incorrect error.\nHave: %v\nWant: %v",
|
||||
i, err.Error(), test.err)
|
||||
} else if _, ok := err.(*RequiredNotSetError); ok && test.out != nil && !reflect.DeepEqual(pb, test.out) {
|
||||
t.Errorf("Test %d: Incorrect populated \nHave: %v\nWant: %v",
|
||||
i, pb, test.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalTextCustomMessage(t *testing.T) {
|
||||
msg := &textMessage{}
|
||||
if err := UnmarshalText("custom", msg); err != nil {
|
||||
t.Errorf("Unexpected error from custom unmarshal: %v", err)
|
||||
}
|
||||
if UnmarshalText("not custom", msg) == nil {
|
||||
t.Errorf("Didn't get expected error from custom unmarshal")
|
||||
}
|
||||
}
|
||||
|
||||
// Regression test; this caused a panic.
|
||||
func TestRepeatedEnum(t *testing.T) {
|
||||
pb := new(RepeatedEnum)
|
||||
if err := UnmarshalText("color: RED", pb); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
exp := &RepeatedEnum{
|
||||
Color: []RepeatedEnum_Color{RepeatedEnum_RED},
|
||||
}
|
||||
if !Equal(pb, exp) {
|
||||
t.Errorf("Incorrect populated \nHave: %v\nWant: %v", pb, exp)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProto3TextParsing(t *testing.T) {
|
||||
m := new(proto3pb.Message)
|
||||
const in = `name: "Wallace" true_scotsman: true`
|
||||
want := &proto3pb.Message{
|
||||
Name: "Wallace",
|
||||
TrueScotsman: true,
|
||||
}
|
||||
if err := UnmarshalText(in, m); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !Equal(m, want) {
|
||||
t.Errorf("\n got %v\nwant %v", m, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMapParsing(t *testing.T) {
|
||||
m := new(MessageWithMap)
|
||||
const in = `name_mapping:<key:1234 value:"Feist"> name_mapping:<key:1 value:"Beatles">` +
|
||||
`msg_mapping:<key:-4, value:<f: 2.0>,>` + // separating commas are okay
|
||||
`msg_mapping<key:-2 value<f: 4.0>>` + // no colon after "value"
|
||||
`byte_mapping:<key:true value:"so be it">`
|
||||
want := &MessageWithMap{
|
||||
NameMapping: map[int32]string{
|
||||
1: "Beatles",
|
||||
1234: "Feist",
|
||||
},
|
||||
MsgMapping: map[int64]*FloatingPoint{
|
||||
-4: {F: Float64(2.0)},
|
||||
-2: {F: Float64(4.0)},
|
||||
},
|
||||
ByteMapping: map[bool][]byte{
|
||||
true: []byte("so be it"),
|
||||
},
|
||||
}
|
||||
if err := UnmarshalText(in, m); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !Equal(m, want) {
|
||||
t.Errorf("\n got %v\nwant %v", m, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOneofParsing(t *testing.T) {
|
||||
const in = `name:"Shrek"`
|
||||
m := new(Communique)
|
||||
want := &Communique{Union: &Communique_Name{"Shrek"}}
|
||||
if err := UnmarshalText(in, m); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !Equal(m, want) {
|
||||
t.Errorf("\n got %v\nwant %v", m, want)
|
||||
}
|
||||
}
|
||||
|
||||
var benchInput string
|
||||
|
||||
func init() {
|
||||
benchInput = "count: 4\n"
|
||||
for i := 0; i < 1000; i++ {
|
||||
benchInput += "pet: \"fido\"\n"
|
||||
}
|
||||
|
||||
// Check it is valid input.
|
||||
pb := new(MyMessage)
|
||||
err := UnmarshalText(benchInput, pb)
|
||||
if err != nil {
|
||||
panic("Bad benchmark input: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnmarshalText(b *testing.B) {
|
||||
pb := new(MyMessage)
|
||||
for i := 0; i < b.N; i++ {
|
||||
UnmarshalText(benchInput, pb)
|
||||
}
|
||||
b.SetBytes(int64(len(benchInput)))
|
||||
}
|
|
@ -1,474 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package proto_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto"
|
||||
|
||||
proto3pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto/proto3_proto"
|
||||
pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata"
|
||||
)
|
||||
|
||||
// textMessage implements the methods that allow it to marshal and unmarshal
|
||||
// itself as text.
|
||||
type textMessage struct {
|
||||
}
|
||||
|
||||
func (*textMessage) MarshalText() ([]byte, error) {
|
||||
return []byte("custom"), nil
|
||||
}
|
||||
|
||||
func (*textMessage) UnmarshalText(bytes []byte) error {
|
||||
if string(bytes) != "custom" {
|
||||
return errors.New("expected 'custom'")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*textMessage) Reset() {}
|
||||
func (*textMessage) String() string { return "" }
|
||||
func (*textMessage) ProtoMessage() {}
|
||||
|
||||
func newTestMessage() *pb.MyMessage {
|
||||
msg := &pb.MyMessage{
|
||||
Count: proto.Int32(42),
|
||||
Name: proto.String("Dave"),
|
||||
Quote: proto.String(`"I didn't want to go."`),
|
||||
Pet: []string{"bunny", "kitty", "horsey"},
|
||||
Inner: &pb.InnerMessage{
|
||||
Host: proto.String("footrest.syd"),
|
||||
Port: proto.Int32(7001),
|
||||
Connected: proto.Bool(true),
|
||||
},
|
||||
Others: []*pb.OtherMessage{
|
||||
{
|
||||
Key: proto.Int64(0xdeadbeef),
|
||||
Value: []byte{1, 65, 7, 12},
|
||||
},
|
||||
{
|
||||
Weight: proto.Float32(6.022),
|
||||
Inner: &pb.InnerMessage{
|
||||
Host: proto.String("lesha.mtv"),
|
||||
Port: proto.Int32(8002),
|
||||
},
|
||||
},
|
||||
},
|
||||
Bikeshed: pb.MyMessage_BLUE.Enum(),
|
||||
Somegroup: &pb.MyMessage_SomeGroup{
|
||||
GroupField: proto.Int32(8),
|
||||
},
|
||||
// One normally wouldn't do this.
|
||||
// This is an undeclared tag 13, as a varint (wire type 0) with value 4.
|
||||
XXX_unrecognized: []byte{13<<3 | 0, 4},
|
||||
}
|
||||
ext := &pb.Ext{
|
||||
Data: proto.String("Big gobs for big rats"),
|
||||
}
|
||||
if err := proto.SetExtension(msg, pb.E_Ext_More, ext); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
greetings := []string{"adg", "easy", "cow"}
|
||||
if err := proto.SetExtension(msg, pb.E_Greeting, greetings); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Add an unknown extension. We marshal a pb.Ext, and fake the ID.
|
||||
b, err := proto.Marshal(&pb.Ext{Data: proto.String("3G skiing")})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
b = append(proto.EncodeVarint(201<<3|proto.WireBytes), b...)
|
||||
proto.SetRawExtension(msg, 201, b)
|
||||
|
||||
// Extensions can be plain fields, too, so let's test that.
|
||||
b = append(proto.EncodeVarint(202<<3|proto.WireVarint), 19)
|
||||
proto.SetRawExtension(msg, 202, b)
|
||||
|
||||
return msg
|
||||
}
|
||||
|
||||
const text = `count: 42
|
||||
name: "Dave"
|
||||
quote: "\"I didn't want to go.\""
|
||||
pet: "bunny"
|
||||
pet: "kitty"
|
||||
pet: "horsey"
|
||||
inner: <
|
||||
host: "footrest.syd"
|
||||
port: 7001
|
||||
connected: true
|
||||
>
|
||||
others: <
|
||||
key: 3735928559
|
||||
value: "\001A\007\014"
|
||||
>
|
||||
others: <
|
||||
weight: 6.022
|
||||
inner: <
|
||||
host: "lesha.mtv"
|
||||
port: 8002
|
||||
>
|
||||
>
|
||||
bikeshed: BLUE
|
||||
SomeGroup {
|
||||
group_field: 8
|
||||
}
|
||||
/* 2 unknown bytes */
|
||||
13: 4
|
||||
[testdata.Ext.more]: <
|
||||
data: "Big gobs for big rats"
|
||||
>
|
||||
[testdata.greeting]: "adg"
|
||||
[testdata.greeting]: "easy"
|
||||
[testdata.greeting]: "cow"
|
||||
/* 13 unknown bytes */
|
||||
201: "\t3G skiing"
|
||||
/* 3 unknown bytes */
|
||||
202: 19
|
||||
`
|
||||
|
||||
func TestMarshalText(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
if err := proto.MarshalText(buf, newTestMessage()); err != nil {
|
||||
t.Fatalf("proto.MarshalText: %v", err)
|
||||
}
|
||||
s := buf.String()
|
||||
if s != text {
|
||||
t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", s, text)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalTextCustomMessage(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
if err := proto.MarshalText(buf, &textMessage{}); err != nil {
|
||||
t.Fatalf("proto.MarshalText: %v", err)
|
||||
}
|
||||
s := buf.String()
|
||||
if s != "custom" {
|
||||
t.Errorf("Got %q, expected %q", s, "custom")
|
||||
}
|
||||
}
|
||||
func TestMarshalTextNil(t *testing.T) {
|
||||
want := "<nil>"
|
||||
tests := []proto.Message{nil, (*pb.MyMessage)(nil)}
|
||||
for i, test := range tests {
|
||||
buf := new(bytes.Buffer)
|
||||
if err := proto.MarshalText(buf, test); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := buf.String(); got != want {
|
||||
t.Errorf("%d: got %q want %q", i, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalTextUnknownEnum(t *testing.T) {
|
||||
// The Color enum only specifies values 0-2.
|
||||
m := &pb.MyMessage{Bikeshed: pb.MyMessage_Color(3).Enum()}
|
||||
got := m.String()
|
||||
const want = `bikeshed:3 `
|
||||
if got != want {
|
||||
t.Errorf("\n got %q\nwant %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTextOneof(t *testing.T) {
|
||||
tests := []struct {
|
||||
m proto.Message
|
||||
want string
|
||||
}{
|
||||
// zero message
|
||||
{&pb.Communique{}, ``},
|
||||
// scalar field
|
||||
{&pb.Communique{Union: &pb.Communique_Number{Number: 4}}, `number:4`},
|
||||
// message field
|
||||
{&pb.Communique{Union: &pb.Communique_Msg{
|
||||
Msg: &pb.Strings{StringField: proto.String("why hello!")},
|
||||
}}, `msg:<string_field:"why hello!" >`},
|
||||
// bad oneof (should not panic)
|
||||
{&pb.Communique{Union: &pb.Communique_Msg{Msg: nil}}, `msg:/* nil */`},
|
||||
}
|
||||
for _, test := range tests {
|
||||
got := strings.TrimSpace(test.m.String())
|
||||
if got != test.want {
|
||||
t.Errorf("\n got %s\nwant %s", got, test.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarshalTextBuffered(b *testing.B) {
|
||||
buf := new(bytes.Buffer)
|
||||
m := newTestMessage()
|
||||
for i := 0; i < b.N; i++ {
|
||||
buf.Reset()
|
||||
proto.MarshalText(buf, m)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarshalTextUnbuffered(b *testing.B) {
|
||||
w := ioutil.Discard
|
||||
m := newTestMessage()
|
||||
for i := 0; i < b.N; i++ {
|
||||
proto.MarshalText(w, m)
|
||||
}
|
||||
}
|
||||
|
||||
func compact(src string) string {
|
||||
// s/[ \n]+/ /g; s/ $//;
|
||||
dst := make([]byte, len(src))
|
||||
space, comment := false, false
|
||||
j := 0
|
||||
for i := 0; i < len(src); i++ {
|
||||
if strings.HasPrefix(src[i:], "/*") {
|
||||
comment = true
|
||||
i++
|
||||
continue
|
||||
}
|
||||
if comment && strings.HasPrefix(src[i:], "*/") {
|
||||
comment = false
|
||||
i++
|
||||
continue
|
||||
}
|
||||
if comment {
|
||||
continue
|
||||
}
|
||||
c := src[i]
|
||||
if c == ' ' || c == '\n' {
|
||||
space = true
|
||||
continue
|
||||
}
|
||||
if j > 0 && (dst[j-1] == ':' || dst[j-1] == '<' || dst[j-1] == '{') {
|
||||
space = false
|
||||
}
|
||||
if c == '{' {
|
||||
space = false
|
||||
}
|
||||
if space {
|
||||
dst[j] = ' '
|
||||
j++
|
||||
space = false
|
||||
}
|
||||
dst[j] = c
|
||||
j++
|
||||
}
|
||||
if space {
|
||||
dst[j] = ' '
|
||||
j++
|
||||
}
|
||||
return string(dst[0:j])
|
||||
}
|
||||
|
||||
var compactText = compact(text)
|
||||
|
||||
func TestCompactText(t *testing.T) {
|
||||
s := proto.CompactTextString(newTestMessage())
|
||||
if s != compactText {
|
||||
t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v\n===\n", s, compactText)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringEscaping(t *testing.T) {
|
||||
testCases := []struct {
|
||||
in *pb.Strings
|
||||
out string
|
||||
}{
|
||||
{
|
||||
// Test data from C++ test (TextFormatTest.StringEscape).
|
||||
// Single divergence: we don't escape apostrophes.
|
||||
&pb.Strings{StringField: proto.String("\"A string with ' characters \n and \r newlines and \t tabs and \001 slashes \\ and multiple spaces")},
|
||||
"string_field: \"\\\"A string with ' characters \\n and \\r newlines and \\t tabs and \\001 slashes \\\\ and multiple spaces\"\n",
|
||||
},
|
||||
{
|
||||
// Test data from the same C++ test.
|
||||
&pb.Strings{StringField: proto.String("\350\260\267\346\255\214")},
|
||||
"string_field: \"\\350\\260\\267\\346\\255\\214\"\n",
|
||||
},
|
||||
{
|
||||
// Some UTF-8.
|
||||
&pb.Strings{StringField: proto.String("\x00\x01\xff\x81")},
|
||||
`string_field: "\000\001\377\201"` + "\n",
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
var buf bytes.Buffer
|
||||
if err := proto.MarshalText(&buf, tc.in); err != nil {
|
||||
t.Errorf("proto.MarsalText: %v", err)
|
||||
continue
|
||||
}
|
||||
s := buf.String()
|
||||
if s != tc.out {
|
||||
t.Errorf("#%d: Got:\n%s\nExpected:\n%s\n", i, s, tc.out)
|
||||
continue
|
||||
}
|
||||
|
||||
// Check round-trip.
|
||||
pb := new(pb.Strings)
|
||||
if err := proto.UnmarshalText(s, pb); err != nil {
|
||||
t.Errorf("#%d: UnmarshalText: %v", i, err)
|
||||
continue
|
||||
}
|
||||
if !proto.Equal(pb, tc.in) {
|
||||
t.Errorf("#%d: Round-trip failed:\nstart: %v\n end: %v", i, tc.in, pb)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A limitedWriter accepts some output before it fails.
|
||||
// This is a proxy for something like a nearly-full or imminently-failing disk,
|
||||
// or a network connection that is about to die.
|
||||
type limitedWriter struct {
|
||||
b bytes.Buffer
|
||||
limit int
|
||||
}
|
||||
|
||||
var outOfSpace = errors.New("proto: insufficient space")
|
||||
|
||||
func (w *limitedWriter) Write(p []byte) (n int, err error) {
|
||||
var avail = w.limit - w.b.Len()
|
||||
if avail <= 0 {
|
||||
return 0, outOfSpace
|
||||
}
|
||||
if len(p) <= avail {
|
||||
return w.b.Write(p)
|
||||
}
|
||||
n, _ = w.b.Write(p[:avail])
|
||||
return n, outOfSpace
|
||||
}
|
||||
|
||||
func TestMarshalTextFailing(t *testing.T) {
|
||||
// Try lots of different sizes to exercise more error code-paths.
|
||||
for lim := 0; lim < len(text); lim++ {
|
||||
buf := new(limitedWriter)
|
||||
buf.limit = lim
|
||||
err := proto.MarshalText(buf, newTestMessage())
|
||||
// We expect a certain error, but also some partial results in the buffer.
|
||||
if err != outOfSpace {
|
||||
t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", err, outOfSpace)
|
||||
}
|
||||
s := buf.b.String()
|
||||
x := text[:buf.limit]
|
||||
if s != x {
|
||||
t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", s, x)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFloats(t *testing.T) {
|
||||
tests := []struct {
|
||||
f float64
|
||||
want string
|
||||
}{
|
||||
{0, "0"},
|
||||
{4.7, "4.7"},
|
||||
{math.Inf(1), "inf"},
|
||||
{math.Inf(-1), "-inf"},
|
||||
{math.NaN(), "nan"},
|
||||
}
|
||||
for _, test := range tests {
|
||||
msg := &pb.FloatingPoint{F: &test.f}
|
||||
got := strings.TrimSpace(msg.String())
|
||||
want := `f:` + test.want
|
||||
if got != want {
|
||||
t.Errorf("f=%f: got %q, want %q", test.f, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepeatedNilText(t *testing.T) {
|
||||
m := &pb.MessageList{
|
||||
Message: []*pb.MessageList_Message{
|
||||
nil,
|
||||
{
|
||||
Name: proto.String("Horse"),
|
||||
},
|
||||
nil,
|
||||
},
|
||||
}
|
||||
want := `Message <nil>
|
||||
Message {
|
||||
name: "Horse"
|
||||
}
|
||||
Message <nil>
|
||||
`
|
||||
if s := proto.MarshalTextString(m); s != want {
|
||||
t.Errorf(" got: %s\nwant: %s", s, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProto3Text(t *testing.T) {
|
||||
tests := []struct {
|
||||
m proto.Message
|
||||
want string
|
||||
}{
|
||||
// zero message
|
||||
{&proto3pb.Message{}, ``},
|
||||
// zero message except for an empty byte slice
|
||||
{&proto3pb.Message{Data: []byte{}}, ``},
|
||||
// trivial case
|
||||
{&proto3pb.Message{Name: "Rob", HeightInCm: 175}, `name:"Rob" height_in_cm:175`},
|
||||
// empty map
|
||||
{&pb.MessageWithMap{}, ``},
|
||||
// non-empty map; map format is the same as a repeated struct,
|
||||
// and they are sorted by key (numerically for numeric keys).
|
||||
{
|
||||
&pb.MessageWithMap{NameMapping: map[int32]string{
|
||||
-1: "Negatory",
|
||||
7: "Lucky",
|
||||
1234: "Feist",
|
||||
6345789: "Otis",
|
||||
}},
|
||||
`name_mapping:<key:-1 value:"Negatory" > ` +
|
||||
`name_mapping:<key:7 value:"Lucky" > ` +
|
||||
`name_mapping:<key:1234 value:"Feist" > ` +
|
||||
`name_mapping:<key:6345789 value:"Otis" >`,
|
||||
},
|
||||
// map with nil value; not well-defined, but we shouldn't crash
|
||||
{
|
||||
&pb.MessageWithMap{MsgMapping: map[int64]*pb.FloatingPoint{7: nil}},
|
||||
`msg_mapping:<key:7 >`,
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
got := strings.TrimSpace(test.m.String())
|
||||
if got != test.want {
|
||||
t.Errorf("\n got %s\nwant %s", got, test.want)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,415 +0,0 @@
|
|||
// Go support for leveled logs, analogous to https://code.google.com/p/google-glog/
|
||||
//
|
||||
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package glog
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
stdLog "log"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Test that shortHostname works as advertised.
|
||||
func TestShortHostname(t *testing.T) {
|
||||
for hostname, expect := range map[string]string{
|
||||
"": "",
|
||||
"host": "host",
|
||||
"host.google.com": "host",
|
||||
} {
|
||||
if got := shortHostname(hostname); expect != got {
|
||||
t.Errorf("shortHostname(%q): expected %q, got %q", hostname, expect, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// flushBuffer wraps a bytes.Buffer to satisfy flushSyncWriter.
|
||||
type flushBuffer struct {
|
||||
bytes.Buffer
|
||||
}
|
||||
|
||||
func (f *flushBuffer) Flush() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *flushBuffer) Sync() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// swap sets the log writers and returns the old array.
|
||||
func (l *loggingT) swap(writers [numSeverity]flushSyncWriter) (old [numSeverity]flushSyncWriter) {
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
old = l.file
|
||||
for i, w := range writers {
|
||||
logging.file[i] = w
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// newBuffers sets the log writers to all new byte buffers and returns the old array.
|
||||
func (l *loggingT) newBuffers() [numSeverity]flushSyncWriter {
|
||||
return l.swap([numSeverity]flushSyncWriter{new(flushBuffer), new(flushBuffer), new(flushBuffer), new(flushBuffer)})
|
||||
}
|
||||
|
||||
// contents returns the specified log value as a string.
|
||||
func contents(s severity) string {
|
||||
return logging.file[s].(*flushBuffer).String()
|
||||
}
|
||||
|
||||
// contains reports whether the string is contained in the log.
|
||||
func contains(s severity, str string, t *testing.T) bool {
|
||||
return strings.Contains(contents(s), str)
|
||||
}
|
||||
|
||||
// setFlags configures the logging flags how the test expects them.
|
||||
func setFlags() {
|
||||
logging.toStderr = false
|
||||
}
|
||||
|
||||
// Test that Info works as advertised.
|
||||
func TestInfo(t *testing.T) {
|
||||
setFlags()
|
||||
defer logging.swap(logging.newBuffers())
|
||||
Info("test")
|
||||
if !contains(infoLog, "I", t) {
|
||||
t.Errorf("Info has wrong character: %q", contents(infoLog))
|
||||
}
|
||||
if !contains(infoLog, "test", t) {
|
||||
t.Error("Info failed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestInfoDepth(t *testing.T) {
|
||||
setFlags()
|
||||
defer logging.swap(logging.newBuffers())
|
||||
|
||||
f := func() { InfoDepth(1, "depth-test1") }
|
||||
|
||||
// The next three lines must stay together
|
||||
_, _, wantLine, _ := runtime.Caller(0)
|
||||
InfoDepth(0, "depth-test0")
|
||||
f()
|
||||
|
||||
msgs := strings.Split(strings.TrimSuffix(contents(infoLog), "\n"), "\n")
|
||||
if len(msgs) != 2 {
|
||||
t.Fatalf("Got %d lines, expected 2", len(msgs))
|
||||
}
|
||||
|
||||
for i, m := range msgs {
|
||||
if !strings.HasPrefix(m, "I") {
|
||||
t.Errorf("InfoDepth[%d] has wrong character: %q", i, m)
|
||||
}
|
||||
w := fmt.Sprintf("depth-test%d", i)
|
||||
if !strings.Contains(m, w) {
|
||||
t.Errorf("InfoDepth[%d] missing %q: %q", i, w, m)
|
||||
}
|
||||
|
||||
// pull out the line number (between : and ])
|
||||
msg := m[strings.LastIndex(m, ":")+1:]
|
||||
x := strings.Index(msg, "]")
|
||||
if x < 0 {
|
||||
t.Errorf("InfoDepth[%d]: missing ']': %q", i, m)
|
||||
continue
|
||||
}
|
||||
line, err := strconv.Atoi(msg[:x])
|
||||
if err != nil {
|
||||
t.Errorf("InfoDepth[%d]: bad line number: %q", i, m)
|
||||
continue
|
||||
}
|
||||
wantLine++
|
||||
if wantLine != line {
|
||||
t.Errorf("InfoDepth[%d]: got line %d, want %d", i, line, wantLine)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
CopyStandardLogTo("INFO")
|
||||
}
|
||||
|
||||
// Test that CopyStandardLogTo panics on bad input.
|
||||
func TestCopyStandardLogToPanic(t *testing.T) {
|
||||
defer func() {
|
||||
if s, ok := recover().(string); !ok || !strings.Contains(s, "LOG") {
|
||||
t.Errorf(`CopyStandardLogTo("LOG") should have panicked: %v`, s)
|
||||
}
|
||||
}()
|
||||
CopyStandardLogTo("LOG")
|
||||
}
|
||||
|
||||
// Test that using the standard log package logs to INFO.
|
||||
func TestStandardLog(t *testing.T) {
|
||||
setFlags()
|
||||
defer logging.swap(logging.newBuffers())
|
||||
stdLog.Print("test")
|
||||
if !contains(infoLog, "I", t) {
|
||||
t.Errorf("Info has wrong character: %q", contents(infoLog))
|
||||
}
|
||||
if !contains(infoLog, "test", t) {
|
||||
t.Error("Info failed")
|
||||
}
|
||||
}
|
||||
|
||||
// Test that the header has the correct format.
|
||||
func TestHeader(t *testing.T) {
|
||||
setFlags()
|
||||
defer logging.swap(logging.newBuffers())
|
||||
defer func(previous func() time.Time) { timeNow = previous }(timeNow)
|
||||
timeNow = func() time.Time {
|
||||
return time.Date(2006, 1, 2, 15, 4, 5, .067890e9, time.Local)
|
||||
}
|
||||
pid = 1234
|
||||
Info("test")
|
||||
var line int
|
||||
format := "I0102 15:04:05.067890 1234 glog_test.go:%d] test\n"
|
||||
n, err := fmt.Sscanf(contents(infoLog), format, &line)
|
||||
if n != 1 || err != nil {
|
||||
t.Errorf("log format error: %d elements, error %s:\n%s", n, err, contents(infoLog))
|
||||
}
|
||||
// Scanf treats multiple spaces as equivalent to a single space,
|
||||
// so check for correct space-padding also.
|
||||
want := fmt.Sprintf(format, line)
|
||||
if contents(infoLog) != want {
|
||||
t.Errorf("log format error: got:\n\t%q\nwant:\t%q", contents(infoLog), want)
|
||||
}
|
||||
}
|
||||
|
||||
// Test that an Error log goes to Warning and Info.
|
||||
// Even in the Info log, the source character will be E, so the data should
|
||||
// all be identical.
|
||||
func TestError(t *testing.T) {
|
||||
setFlags()
|
||||
defer logging.swap(logging.newBuffers())
|
||||
Error("test")
|
||||
if !contains(errorLog, "E", t) {
|
||||
t.Errorf("Error has wrong character: %q", contents(errorLog))
|
||||
}
|
||||
if !contains(errorLog, "test", t) {
|
||||
t.Error("Error failed")
|
||||
}
|
||||
str := contents(errorLog)
|
||||
if !contains(warningLog, str, t) {
|
||||
t.Error("Warning failed")
|
||||
}
|
||||
if !contains(infoLog, str, t) {
|
||||
t.Error("Info failed")
|
||||
}
|
||||
}
|
||||
|
||||
// Test that a Warning log goes to Info.
|
||||
// Even in the Info log, the source character will be W, so the data should
|
||||
// all be identical.
|
||||
func TestWarning(t *testing.T) {
|
||||
setFlags()
|
||||
defer logging.swap(logging.newBuffers())
|
||||
Warning("test")
|
||||
if !contains(warningLog, "W", t) {
|
||||
t.Errorf("Warning has wrong character: %q", contents(warningLog))
|
||||
}
|
||||
if !contains(warningLog, "test", t) {
|
||||
t.Error("Warning failed")
|
||||
}
|
||||
str := contents(warningLog)
|
||||
if !contains(infoLog, str, t) {
|
||||
t.Error("Info failed")
|
||||
}
|
||||
}
|
||||
|
||||
// Test that a V log goes to Info.
|
||||
func TestV(t *testing.T) {
|
||||
setFlags()
|
||||
defer logging.swap(logging.newBuffers())
|
||||
logging.verbosity.Set("2")
|
||||
defer logging.verbosity.Set("0")
|
||||
V(2).Info("test")
|
||||
if !contains(infoLog, "I", t) {
|
||||
t.Errorf("Info has wrong character: %q", contents(infoLog))
|
||||
}
|
||||
if !contains(infoLog, "test", t) {
|
||||
t.Error("Info failed")
|
||||
}
|
||||
}
|
||||
|
||||
// Test that a vmodule enables a log in this file.
|
||||
func TestVmoduleOn(t *testing.T) {
|
||||
setFlags()
|
||||
defer logging.swap(logging.newBuffers())
|
||||
logging.vmodule.Set("glog_test=2")
|
||||
defer logging.vmodule.Set("")
|
||||
if !V(1) {
|
||||
t.Error("V not enabled for 1")
|
||||
}
|
||||
if !V(2) {
|
||||
t.Error("V not enabled for 2")
|
||||
}
|
||||
if V(3) {
|
||||
t.Error("V enabled for 3")
|
||||
}
|
||||
V(2).Info("test")
|
||||
if !contains(infoLog, "I", t) {
|
||||
t.Errorf("Info has wrong character: %q", contents(infoLog))
|
||||
}
|
||||
if !contains(infoLog, "test", t) {
|
||||
t.Error("Info failed")
|
||||
}
|
||||
}
|
||||
|
||||
// Test that a vmodule of another file does not enable a log in this file.
|
||||
func TestVmoduleOff(t *testing.T) {
|
||||
setFlags()
|
||||
defer logging.swap(logging.newBuffers())
|
||||
logging.vmodule.Set("notthisfile=2")
|
||||
defer logging.vmodule.Set("")
|
||||
for i := 1; i <= 3; i++ {
|
||||
if V(Level(i)) {
|
||||
t.Errorf("V enabled for %d", i)
|
||||
}
|
||||
}
|
||||
V(2).Info("test")
|
||||
if contents(infoLog) != "" {
|
||||
t.Error("V logged incorrectly")
|
||||
}
|
||||
}
|
||||
|
||||
// vGlobs are patterns that match/don't match this file at V=2.
|
||||
var vGlobs = map[string]bool{
|
||||
// Easy to test the numeric match here.
|
||||
"glog_test=1": false, // If -vmodule sets V to 1, V(2) will fail.
|
||||
"glog_test=2": true,
|
||||
"glog_test=3": true, // If -vmodule sets V to 1, V(3) will succeed.
|
||||
// These all use 2 and check the patterns. All are true.
|
||||
"*=2": true,
|
||||
"?l*=2": true,
|
||||
"????_*=2": true,
|
||||
"??[mno]?_*t=2": true,
|
||||
// These all use 2 and check the patterns. All are false.
|
||||
"*x=2": false,
|
||||
"m*=2": false,
|
||||
"??_*=2": false,
|
||||
"?[abc]?_*t=2": false,
|
||||
}
|
||||
|
||||
// Test that vmodule globbing works as advertised.
|
||||
func testVmoduleGlob(pat string, match bool, t *testing.T) {
|
||||
setFlags()
|
||||
defer logging.swap(logging.newBuffers())
|
||||
defer logging.vmodule.Set("")
|
||||
logging.vmodule.Set(pat)
|
||||
if V(2) != Verbose(match) {
|
||||
t.Errorf("incorrect match for %q: got %t expected %t", pat, V(2), match)
|
||||
}
|
||||
}
|
||||
|
||||
// Test that a vmodule globbing works as advertised.
|
||||
func TestVmoduleGlob(t *testing.T) {
|
||||
for glob, match := range vGlobs {
|
||||
testVmoduleGlob(glob, match, t)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRollover(t *testing.T) {
|
||||
setFlags()
|
||||
var err error
|
||||
defer func(previous func(error)) { logExitFunc = previous }(logExitFunc)
|
||||
logExitFunc = func(e error) {
|
||||
err = e
|
||||
}
|
||||
defer func(previous uint64) { MaxSize = previous }(MaxSize)
|
||||
MaxSize = 512
|
||||
|
||||
Info("x") // Be sure we have a file.
|
||||
info, ok := logging.file[infoLog].(*syncBuffer)
|
||||
if !ok {
|
||||
t.Fatal("info wasn't created")
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("info has initial error: %v", err)
|
||||
}
|
||||
fname0 := info.file.Name()
|
||||
Info(strings.Repeat("x", int(MaxSize))) // force a rollover
|
||||
if err != nil {
|
||||
t.Fatalf("info has error after big write: %v", err)
|
||||
}
|
||||
|
||||
// Make sure the next log file gets a file name with a different
|
||||
// time stamp.
|
||||
//
|
||||
// TODO: determine whether we need to support subsecond log
|
||||
// rotation. C++ does not appear to handle this case (nor does it
|
||||
// handle Daylight Savings Time properly).
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
Info("x") // create a new file
|
||||
if err != nil {
|
||||
t.Fatalf("error after rotation: %v", err)
|
||||
}
|
||||
fname1 := info.file.Name()
|
||||
if fname0 == fname1 {
|
||||
t.Errorf("info.f.Name did not change: %v", fname0)
|
||||
}
|
||||
if info.nbytes >= MaxSize {
|
||||
t.Errorf("file size was not reset: %d", info.nbytes)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLogBacktraceAt(t *testing.T) {
|
||||
setFlags()
|
||||
defer logging.swap(logging.newBuffers())
|
||||
// The peculiar style of this code simplifies line counting and maintenance of the
|
||||
// tracing block below.
|
||||
var infoLine string
|
||||
setTraceLocation := func(file string, line int, ok bool, delta int) {
|
||||
if !ok {
|
||||
t.Fatal("could not get file:line")
|
||||
}
|
||||
_, file = filepath.Split(file)
|
||||
infoLine = fmt.Sprintf("%s:%d", file, line+delta)
|
||||
err := logging.traceLocation.Set(infoLine)
|
||||
if err != nil {
|
||||
t.Fatal("error setting log_backtrace_at: ", err)
|
||||
}
|
||||
}
|
||||
{
|
||||
// Start of tracing block. These lines know about each other's relative position.
|
||||
_, file, line, ok := runtime.Caller(0)
|
||||
setTraceLocation(file, line, ok, +2) // Two lines between Caller and Info calls.
|
||||
Info("we want a stack trace here")
|
||||
}
|
||||
numAppearances := strings.Count(contents(infoLog), infoLine)
|
||||
if numAppearances < 2 {
|
||||
// Need 2 appearances, one in the log header and one in the trace:
|
||||
// log_test.go:281: I0511 16:36:06.952398 02238 log_test.go:280] we want a stack trace here
|
||||
// ...
|
||||
// github.com/glog/glog_test.go:280 (0x41ba91)
|
||||
// ...
|
||||
// We could be more precise but that would require knowing the details
|
||||
// of the traceback format, which may not be dependable.
|
||||
t.Fatal("got no trace back; log is ", contents(infoLog))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkHeader(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
buf, _, _ := logging.header(infoLog, 0)
|
||||
logging.putBuffer(buf)
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,267 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package proto_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
|
||||
|
||||
proto3pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto"
|
||||
pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata"
|
||||
)
|
||||
|
||||
var cloneTestMessage = &pb.MyMessage{
|
||||
Count: proto.Int32(42),
|
||||
Name: proto.String("Dave"),
|
||||
Pet: []string{"bunny", "kitty", "horsey"},
|
||||
Inner: &pb.InnerMessage{
|
||||
Host: proto.String("niles"),
|
||||
Port: proto.Int32(9099),
|
||||
Connected: proto.Bool(true),
|
||||
},
|
||||
Others: []*pb.OtherMessage{
|
||||
{
|
||||
Value: []byte("some bytes"),
|
||||
},
|
||||
},
|
||||
Somegroup: &pb.MyMessage_SomeGroup{
|
||||
GroupField: proto.Int32(6),
|
||||
},
|
||||
RepBytes: [][]byte{[]byte("sham"), []byte("wow")},
|
||||
}
|
||||
|
||||
func init() {
|
||||
ext := &pb.Ext{
|
||||
Data: proto.String("extension"),
|
||||
}
|
||||
if err := proto.SetExtension(cloneTestMessage, pb.E_Ext_More, ext); err != nil {
|
||||
panic("SetExtension: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestClone(t *testing.T) {
|
||||
m := proto.Clone(cloneTestMessage).(*pb.MyMessage)
|
||||
if !proto.Equal(m, cloneTestMessage) {
|
||||
t.Errorf("Clone(%v) = %v", cloneTestMessage, m)
|
||||
}
|
||||
|
||||
// Verify it was a deep copy.
|
||||
*m.Inner.Port++
|
||||
if proto.Equal(m, cloneTestMessage) {
|
||||
t.Error("Mutating clone changed the original")
|
||||
}
|
||||
// Byte fields and repeated fields should be copied.
|
||||
if &m.Pet[0] == &cloneTestMessage.Pet[0] {
|
||||
t.Error("Pet: repeated field not copied")
|
||||
}
|
||||
if &m.Others[0] == &cloneTestMessage.Others[0] {
|
||||
t.Error("Others: repeated field not copied")
|
||||
}
|
||||
if &m.Others[0].Value[0] == &cloneTestMessage.Others[0].Value[0] {
|
||||
t.Error("Others[0].Value: bytes field not copied")
|
||||
}
|
||||
if &m.RepBytes[0] == &cloneTestMessage.RepBytes[0] {
|
||||
t.Error("RepBytes: repeated field not copied")
|
||||
}
|
||||
if &m.RepBytes[0][0] == &cloneTestMessage.RepBytes[0][0] {
|
||||
t.Error("RepBytes[0]: bytes field not copied")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCloneNil(t *testing.T) {
|
||||
var m *pb.MyMessage
|
||||
if c := proto.Clone(m); !proto.Equal(m, c) {
|
||||
t.Errorf("Clone(%v) = %v", m, c)
|
||||
}
|
||||
}
|
||||
|
||||
var mergeTests = []struct {
|
||||
src, dst, want proto.Message
|
||||
}{
|
||||
{
|
||||
src: &pb.MyMessage{
|
||||
Count: proto.Int32(42),
|
||||
},
|
||||
dst: &pb.MyMessage{
|
||||
Name: proto.String("Dave"),
|
||||
},
|
||||
want: &pb.MyMessage{
|
||||
Count: proto.Int32(42),
|
||||
Name: proto.String("Dave"),
|
||||
},
|
||||
},
|
||||
{
|
||||
src: &pb.MyMessage{
|
||||
Inner: &pb.InnerMessage{
|
||||
Host: proto.String("hey"),
|
||||
Connected: proto.Bool(true),
|
||||
},
|
||||
Pet: []string{"horsey"},
|
||||
Others: []*pb.OtherMessage{
|
||||
{
|
||||
Value: []byte("some bytes"),
|
||||
},
|
||||
},
|
||||
},
|
||||
dst: &pb.MyMessage{
|
||||
Inner: &pb.InnerMessage{
|
||||
Host: proto.String("niles"),
|
||||
Port: proto.Int32(9099),
|
||||
},
|
||||
Pet: []string{"bunny", "kitty"},
|
||||
Others: []*pb.OtherMessage{
|
||||
{
|
||||
Key: proto.Int64(31415926535),
|
||||
},
|
||||
{
|
||||
// Explicitly test a src=nil field
|
||||
Inner: nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &pb.MyMessage{
|
||||
Inner: &pb.InnerMessage{
|
||||
Host: proto.String("hey"),
|
||||
Connected: proto.Bool(true),
|
||||
Port: proto.Int32(9099),
|
||||
},
|
||||
Pet: []string{"bunny", "kitty", "horsey"},
|
||||
Others: []*pb.OtherMessage{
|
||||
{
|
||||
Key: proto.Int64(31415926535),
|
||||
},
|
||||
{},
|
||||
{
|
||||
Value: []byte("some bytes"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
src: &pb.MyMessage{
|
||||
RepBytes: [][]byte{[]byte("wow")},
|
||||
},
|
||||
dst: &pb.MyMessage{
|
||||
Somegroup: &pb.MyMessage_SomeGroup{
|
||||
GroupField: proto.Int32(6),
|
||||
},
|
||||
RepBytes: [][]byte{[]byte("sham")},
|
||||
},
|
||||
want: &pb.MyMessage{
|
||||
Somegroup: &pb.MyMessage_SomeGroup{
|
||||
GroupField: proto.Int32(6),
|
||||
},
|
||||
RepBytes: [][]byte{[]byte("sham"), []byte("wow")},
|
||||
},
|
||||
},
|
||||
// Check that a scalar bytes field replaces rather than appends.
|
||||
{
|
||||
src: &pb.OtherMessage{Value: []byte("foo")},
|
||||
dst: &pb.OtherMessage{Value: []byte("bar")},
|
||||
want: &pb.OtherMessage{Value: []byte("foo")},
|
||||
},
|
||||
{
|
||||
src: &pb.MessageWithMap{
|
||||
NameMapping: map[int32]string{6: "Nigel"},
|
||||
MsgMapping: map[int64]*pb.FloatingPoint{
|
||||
0x4001: &pb.FloatingPoint{F: proto.Float64(2.0)},
|
||||
},
|
||||
ByteMapping: map[bool][]byte{true: []byte("wowsa")},
|
||||
},
|
||||
dst: &pb.MessageWithMap{
|
||||
NameMapping: map[int32]string{
|
||||
6: "Bruce", // should be overwritten
|
||||
7: "Andrew",
|
||||
},
|
||||
},
|
||||
want: &pb.MessageWithMap{
|
||||
NameMapping: map[int32]string{
|
||||
6: "Nigel",
|
||||
7: "Andrew",
|
||||
},
|
||||
MsgMapping: map[int64]*pb.FloatingPoint{
|
||||
0x4001: &pb.FloatingPoint{F: proto.Float64(2.0)},
|
||||
},
|
||||
ByteMapping: map[bool][]byte{true: []byte("wowsa")},
|
||||
},
|
||||
},
|
||||
// proto3 shouldn't merge zero values,
|
||||
// in the same way that proto2 shouldn't merge nils.
|
||||
{
|
||||
src: &proto3pb.Message{
|
||||
Name: "Aaron",
|
||||
Data: []byte(""), // zero value, but not nil
|
||||
},
|
||||
dst: &proto3pb.Message{
|
||||
HeightInCm: 176,
|
||||
Data: []byte("texas!"),
|
||||
},
|
||||
want: &proto3pb.Message{
|
||||
Name: "Aaron",
|
||||
HeightInCm: 176,
|
||||
Data: []byte("texas!"),
|
||||
},
|
||||
},
|
||||
// Oneof fields should merge by assignment.
|
||||
{
|
||||
src: &pb.Communique{
|
||||
Union: &pb.Communique_Number{41},
|
||||
},
|
||||
dst: &pb.Communique{
|
||||
Union: &pb.Communique_Name{"Bobby Tables"},
|
||||
},
|
||||
want: &pb.Communique{
|
||||
Union: &pb.Communique_Number{41},
|
||||
},
|
||||
},
|
||||
// Oneof nil is the same as not set.
|
||||
{
|
||||
src: &pb.Communique{},
|
||||
dst: &pb.Communique{
|
||||
Union: &pb.Communique_Name{"Bobby Tables"},
|
||||
},
|
||||
want: &pb.Communique{
|
||||
Union: &pb.Communique_Name{"Bobby Tables"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestMerge(t *testing.T) {
|
||||
for _, m := range mergeTests {
|
||||
got := proto.Clone(m.dst)
|
||||
proto.Merge(got, m.src)
|
||||
if !proto.Equal(got, m.want) {
|
||||
t.Errorf("Merge(%v, %v)\n got %v\nwant %v\n", m.dst, m.src, got, m.want)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,212 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package proto_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
|
||||
proto3pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto"
|
||||
pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata"
|
||||
)
|
||||
|
||||
// Four identical base messages.
|
||||
// The init function adds extensions to some of them.
|
||||
var messageWithoutExtension = &pb.MyMessage{Count: Int32(7)}
|
||||
var messageWithExtension1a = &pb.MyMessage{Count: Int32(7)}
|
||||
var messageWithExtension1b = &pb.MyMessage{Count: Int32(7)}
|
||||
var messageWithExtension2 = &pb.MyMessage{Count: Int32(7)}
|
||||
|
||||
// Two messages with non-message extensions.
|
||||
var messageWithInt32Extension1 = &pb.MyMessage{Count: Int32(8)}
|
||||
var messageWithInt32Extension2 = &pb.MyMessage{Count: Int32(8)}
|
||||
|
||||
func init() {
|
||||
ext1 := &pb.Ext{Data: String("Kirk")}
|
||||
ext2 := &pb.Ext{Data: String("Picard")}
|
||||
|
||||
// messageWithExtension1a has ext1, but never marshals it.
|
||||
if err := SetExtension(messageWithExtension1a, pb.E_Ext_More, ext1); err != nil {
|
||||
panic("SetExtension on 1a failed: " + err.Error())
|
||||
}
|
||||
|
||||
// messageWithExtension1b is the unmarshaled form of messageWithExtension1a.
|
||||
if err := SetExtension(messageWithExtension1b, pb.E_Ext_More, ext1); err != nil {
|
||||
panic("SetExtension on 1b failed: " + err.Error())
|
||||
}
|
||||
buf, err := Marshal(messageWithExtension1b)
|
||||
if err != nil {
|
||||
panic("Marshal of 1b failed: " + err.Error())
|
||||
}
|
||||
messageWithExtension1b.Reset()
|
||||
if err := Unmarshal(buf, messageWithExtension1b); err != nil {
|
||||
panic("Unmarshal of 1b failed: " + err.Error())
|
||||
}
|
||||
|
||||
// messageWithExtension2 has ext2.
|
||||
if err := SetExtension(messageWithExtension2, pb.E_Ext_More, ext2); err != nil {
|
||||
panic("SetExtension on 2 failed: " + err.Error())
|
||||
}
|
||||
|
||||
if err := SetExtension(messageWithInt32Extension1, pb.E_Ext_Number, Int32(23)); err != nil {
|
||||
panic("SetExtension on Int32-1 failed: " + err.Error())
|
||||
}
|
||||
if err := SetExtension(messageWithInt32Extension1, pb.E_Ext_Number, Int32(24)); err != nil {
|
||||
panic("SetExtension on Int32-2 failed: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
var EqualTests = []struct {
|
||||
desc string
|
||||
a, b Message
|
||||
exp bool
|
||||
}{
|
||||
{"different types", &pb.GoEnum{}, &pb.GoTestField{}, false},
|
||||
{"equal empty", &pb.GoEnum{}, &pb.GoEnum{}, true},
|
||||
{"nil vs nil", nil, nil, true},
|
||||
{"typed nil vs typed nil", (*pb.GoEnum)(nil), (*pb.GoEnum)(nil), true},
|
||||
{"typed nil vs empty", (*pb.GoEnum)(nil), &pb.GoEnum{}, false},
|
||||
{"different typed nil", (*pb.GoEnum)(nil), (*pb.GoTestField)(nil), false},
|
||||
|
||||
{"one set field, one unset field", &pb.GoTestField{Label: String("foo")}, &pb.GoTestField{}, false},
|
||||
{"one set field zero, one unset field", &pb.GoTest{Param: Int32(0)}, &pb.GoTest{}, false},
|
||||
{"different set fields", &pb.GoTestField{Label: String("foo")}, &pb.GoTestField{Label: String("bar")}, false},
|
||||
{"equal set", &pb.GoTestField{Label: String("foo")}, &pb.GoTestField{Label: String("foo")}, true},
|
||||
|
||||
{"repeated, one set", &pb.GoTest{F_Int32Repeated: []int32{2, 3}}, &pb.GoTest{}, false},
|
||||
{"repeated, different length", &pb.GoTest{F_Int32Repeated: []int32{2, 3}}, &pb.GoTest{F_Int32Repeated: []int32{2}}, false},
|
||||
{"repeated, different value", &pb.GoTest{F_Int32Repeated: []int32{2}}, &pb.GoTest{F_Int32Repeated: []int32{3}}, false},
|
||||
{"repeated, equal", &pb.GoTest{F_Int32Repeated: []int32{2, 4}}, &pb.GoTest{F_Int32Repeated: []int32{2, 4}}, true},
|
||||
{"repeated, nil equal nil", &pb.GoTest{F_Int32Repeated: nil}, &pb.GoTest{F_Int32Repeated: nil}, true},
|
||||
{"repeated, nil equal empty", &pb.GoTest{F_Int32Repeated: nil}, &pb.GoTest{F_Int32Repeated: []int32{}}, true},
|
||||
{"repeated, empty equal nil", &pb.GoTest{F_Int32Repeated: []int32{}}, &pb.GoTest{F_Int32Repeated: nil}, true},
|
||||
|
||||
{
|
||||
"nested, different",
|
||||
&pb.GoTest{RequiredField: &pb.GoTestField{Label: String("foo")}},
|
||||
&pb.GoTest{RequiredField: &pb.GoTestField{Label: String("bar")}},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"nested, equal",
|
||||
&pb.GoTest{RequiredField: &pb.GoTestField{Label: String("wow")}},
|
||||
&pb.GoTest{RequiredField: &pb.GoTestField{Label: String("wow")}},
|
||||
true,
|
||||
},
|
||||
|
||||
{"bytes", &pb.OtherMessage{Value: []byte("foo")}, &pb.OtherMessage{Value: []byte("foo")}, true},
|
||||
{"bytes, empty", &pb.OtherMessage{Value: []byte{}}, &pb.OtherMessage{Value: []byte{}}, true},
|
||||
{"bytes, empty vs nil", &pb.OtherMessage{Value: []byte{}}, &pb.OtherMessage{Value: nil}, false},
|
||||
{
|
||||
"repeated bytes",
|
||||
&pb.MyMessage{RepBytes: [][]byte{[]byte("sham"), []byte("wow")}},
|
||||
&pb.MyMessage{RepBytes: [][]byte{[]byte("sham"), []byte("wow")}},
|
||||
true,
|
||||
},
|
||||
// In proto3, []byte{} and []byte(nil) are equal.
|
||||
{"proto3 bytes, empty vs nil", &proto3pb.Message{Data: []byte{}}, &proto3pb.Message{Data: nil}, true},
|
||||
|
||||
{"extension vs. no extension", messageWithoutExtension, messageWithExtension1a, false},
|
||||
{"extension vs. same extension", messageWithExtension1a, messageWithExtension1b, true},
|
||||
{"extension vs. different extension", messageWithExtension1a, messageWithExtension2, false},
|
||||
|
||||
{"int32 extension vs. itself", messageWithInt32Extension1, messageWithInt32Extension1, true},
|
||||
{"int32 extension vs. a different int32", messageWithInt32Extension1, messageWithInt32Extension2, false},
|
||||
|
||||
{
|
||||
"message with group",
|
||||
&pb.MyMessage{
|
||||
Count: Int32(1),
|
||||
Somegroup: &pb.MyMessage_SomeGroup{
|
||||
GroupField: Int32(5),
|
||||
},
|
||||
},
|
||||
&pb.MyMessage{
|
||||
Count: Int32(1),
|
||||
Somegroup: &pb.MyMessage_SomeGroup{
|
||||
GroupField: Int32(5),
|
||||
},
|
||||
},
|
||||
true,
|
||||
},
|
||||
|
||||
{
|
||||
"map same",
|
||||
&pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}},
|
||||
&pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"map different entry",
|
||||
&pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}},
|
||||
&pb.MessageWithMap{NameMapping: map[int32]string{2: "Rob"}},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"map different key only",
|
||||
&pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}},
|
||||
&pb.MessageWithMap{NameMapping: map[int32]string{2: "Ken"}},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"map different value only",
|
||||
&pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}},
|
||||
&pb.MessageWithMap{NameMapping: map[int32]string{1: "Rob"}},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"oneof same",
|
||||
&pb.Communique{Union: &pb.Communique_Number{41}},
|
||||
&pb.Communique{Union: &pb.Communique_Number{41}},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"oneof one nil",
|
||||
&pb.Communique{Union: &pb.Communique_Number{41}},
|
||||
&pb.Communique{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"oneof different",
|
||||
&pb.Communique{Union: &pb.Communique_Number{41}},
|
||||
&pb.Communique{Union: &pb.Communique_Name{"Bobby Tables"}},
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
func TestEqual(t *testing.T) {
|
||||
for _, tc := range EqualTests {
|
||||
if res := Equal(tc.a, tc.b); res != tc.exp {
|
||||
t.Errorf("%v: Equal(%v, %v) = %v, want %v", tc.desc, tc.a, tc.b, res, tc.exp)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,430 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package proto_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
|
||||
pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata"
|
||||
)
|
||||
|
||||
func TestGetExtensionsWithMissingExtensions(t *testing.T) {
|
||||
msg := &pb.MyMessage{}
|
||||
ext1 := &pb.Ext{}
|
||||
if err := proto.SetExtension(msg, pb.E_Ext_More, ext1); err != nil {
|
||||
t.Fatalf("Could not set ext1: %s", ext1)
|
||||
}
|
||||
exts, err := proto.GetExtensions(msg, []*proto.ExtensionDesc{
|
||||
pb.E_Ext_More,
|
||||
pb.E_Ext_Text,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("GetExtensions() failed: %s", err)
|
||||
}
|
||||
if exts[0] != ext1 {
|
||||
t.Errorf("ext1 not in returned extensions: %T %v", exts[0], exts[0])
|
||||
}
|
||||
if exts[1] != nil {
|
||||
t.Errorf("ext2 in returned extensions: %T %v", exts[1], exts[1])
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetExtensionStability(t *testing.T) {
|
||||
check := func(m *pb.MyMessage) bool {
|
||||
ext1, err := proto.GetExtension(m, pb.E_Ext_More)
|
||||
if err != nil {
|
||||
t.Fatalf("GetExtension() failed: %s", err)
|
||||
}
|
||||
ext2, err := proto.GetExtension(m, pb.E_Ext_More)
|
||||
if err != nil {
|
||||
t.Fatalf("GetExtension() failed: %s", err)
|
||||
}
|
||||
return ext1 == ext2
|
||||
}
|
||||
msg := &pb.MyMessage{Count: proto.Int32(4)}
|
||||
ext0 := &pb.Ext{}
|
||||
if err := proto.SetExtension(msg, pb.E_Ext_More, ext0); err != nil {
|
||||
t.Fatalf("Could not set ext1: %s", ext0)
|
||||
}
|
||||
if !check(msg) {
|
||||
t.Errorf("GetExtension() not stable before marshaling")
|
||||
}
|
||||
bb, err := proto.Marshal(msg)
|
||||
if err != nil {
|
||||
t.Fatalf("Marshal() failed: %s", err)
|
||||
}
|
||||
msg1 := &pb.MyMessage{}
|
||||
err = proto.Unmarshal(bb, msg1)
|
||||
if err != nil {
|
||||
t.Fatalf("Unmarshal() failed: %s", err)
|
||||
}
|
||||
if !check(msg1) {
|
||||
t.Errorf("GetExtension() not stable after unmarshaling")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetExtensionDefaults(t *testing.T) {
|
||||
var setFloat64 float64 = 1
|
||||
var setFloat32 float32 = 2
|
||||
var setInt32 int32 = 3
|
||||
var setInt64 int64 = 4
|
||||
var setUint32 uint32 = 5
|
||||
var setUint64 uint64 = 6
|
||||
var setBool = true
|
||||
var setBool2 = false
|
||||
var setString = "Goodnight string"
|
||||
var setBytes = []byte("Goodnight bytes")
|
||||
var setEnum = pb.DefaultsMessage_TWO
|
||||
|
||||
type testcase struct {
|
||||
ext *proto.ExtensionDesc // Extension we are testing.
|
||||
want interface{} // Expected value of extension, or nil (meaning that GetExtension will fail).
|
||||
def interface{} // Expected value of extension after ClearExtension().
|
||||
}
|
||||
tests := []testcase{
|
||||
{pb.E_NoDefaultDouble, setFloat64, nil},
|
||||
{pb.E_NoDefaultFloat, setFloat32, nil},
|
||||
{pb.E_NoDefaultInt32, setInt32, nil},
|
||||
{pb.E_NoDefaultInt64, setInt64, nil},
|
||||
{pb.E_NoDefaultUint32, setUint32, nil},
|
||||
{pb.E_NoDefaultUint64, setUint64, nil},
|
||||
{pb.E_NoDefaultSint32, setInt32, nil},
|
||||
{pb.E_NoDefaultSint64, setInt64, nil},
|
||||
{pb.E_NoDefaultFixed32, setUint32, nil},
|
||||
{pb.E_NoDefaultFixed64, setUint64, nil},
|
||||
{pb.E_NoDefaultSfixed32, setInt32, nil},
|
||||
{pb.E_NoDefaultSfixed64, setInt64, nil},
|
||||
{pb.E_NoDefaultBool, setBool, nil},
|
||||
{pb.E_NoDefaultBool, setBool2, nil},
|
||||
{pb.E_NoDefaultString, setString, nil},
|
||||
{pb.E_NoDefaultBytes, setBytes, nil},
|
||||
{pb.E_NoDefaultEnum, setEnum, nil},
|
||||
{pb.E_DefaultDouble, setFloat64, float64(3.1415)},
|
||||
{pb.E_DefaultFloat, setFloat32, float32(3.14)},
|
||||
{pb.E_DefaultInt32, setInt32, int32(42)},
|
||||
{pb.E_DefaultInt64, setInt64, int64(43)},
|
||||
{pb.E_DefaultUint32, setUint32, uint32(44)},
|
||||
{pb.E_DefaultUint64, setUint64, uint64(45)},
|
||||
{pb.E_DefaultSint32, setInt32, int32(46)},
|
||||
{pb.E_DefaultSint64, setInt64, int64(47)},
|
||||
{pb.E_DefaultFixed32, setUint32, uint32(48)},
|
||||
{pb.E_DefaultFixed64, setUint64, uint64(49)},
|
||||
{pb.E_DefaultSfixed32, setInt32, int32(50)},
|
||||
{pb.E_DefaultSfixed64, setInt64, int64(51)},
|
||||
{pb.E_DefaultBool, setBool, true},
|
||||
{pb.E_DefaultBool, setBool2, true},
|
||||
{pb.E_DefaultString, setString, "Hello, string"},
|
||||
{pb.E_DefaultBytes, setBytes, []byte("Hello, bytes")},
|
||||
{pb.E_DefaultEnum, setEnum, pb.DefaultsMessage_ONE},
|
||||
}
|
||||
|
||||
checkVal := func(test testcase, msg *pb.DefaultsMessage, valWant interface{}) error {
|
||||
val, err := proto.GetExtension(msg, test.ext)
|
||||
if err != nil {
|
||||
if valWant != nil {
|
||||
return fmt.Errorf("GetExtension(): %s", err)
|
||||
}
|
||||
if want := proto.ErrMissingExtension; err != want {
|
||||
return fmt.Errorf("Unexpected error: got %v, want %v", err, want)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// All proto2 extension values are either a pointer to a value or a slice of values.
|
||||
ty := reflect.TypeOf(val)
|
||||
tyWant := reflect.TypeOf(test.ext.ExtensionType)
|
||||
if got, want := ty, tyWant; got != want {
|
||||
return fmt.Errorf("unexpected reflect.TypeOf(): got %v want %v", got, want)
|
||||
}
|
||||
tye := ty.Elem()
|
||||
tyeWant := tyWant.Elem()
|
||||
if got, want := tye, tyeWant; got != want {
|
||||
return fmt.Errorf("unexpected reflect.TypeOf().Elem(): got %v want %v", got, want)
|
||||
}
|
||||
|
||||
// Check the name of the type of the value.
|
||||
// If it is an enum it will be type int32 with the name of the enum.
|
||||
if got, want := tye.Name(), tye.Name(); got != want {
|
||||
return fmt.Errorf("unexpected reflect.TypeOf().Elem().Name(): got %v want %v", got, want)
|
||||
}
|
||||
|
||||
// Check that value is what we expect.
|
||||
// If we have a pointer in val, get the value it points to.
|
||||
valExp := val
|
||||
if ty.Kind() == reflect.Ptr {
|
||||
valExp = reflect.ValueOf(val).Elem().Interface()
|
||||
}
|
||||
if got, want := valExp, valWant; !reflect.DeepEqual(got, want) {
|
||||
return fmt.Errorf("unexpected reflect.DeepEqual(): got %v want %v", got, want)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
setTo := func(test testcase) interface{} {
|
||||
setTo := reflect.ValueOf(test.want)
|
||||
if typ := reflect.TypeOf(test.ext.ExtensionType); typ.Kind() == reflect.Ptr {
|
||||
setTo = reflect.New(typ).Elem()
|
||||
setTo.Set(reflect.New(setTo.Type().Elem()))
|
||||
setTo.Elem().Set(reflect.ValueOf(test.want))
|
||||
}
|
||||
return setTo.Interface()
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
msg := &pb.DefaultsMessage{}
|
||||
name := test.ext.Name
|
||||
|
||||
// Check the initial value.
|
||||
if err := checkVal(test, msg, test.def); err != nil {
|
||||
t.Errorf("%s: %v", name, err)
|
||||
}
|
||||
|
||||
// Set the per-type value and check value.
|
||||
name = fmt.Sprintf("%s (set to %T %v)", name, test.want, test.want)
|
||||
if err := proto.SetExtension(msg, test.ext, setTo(test)); err != nil {
|
||||
t.Errorf("%s: SetExtension(): %v", name, err)
|
||||
continue
|
||||
}
|
||||
if err := checkVal(test, msg, test.want); err != nil {
|
||||
t.Errorf("%s: %v", name, err)
|
||||
continue
|
||||
}
|
||||
|
||||
// Set and check the value.
|
||||
name += " (cleared)"
|
||||
proto.ClearExtension(msg, test.ext)
|
||||
if err := checkVal(test, msg, test.def); err != nil {
|
||||
t.Errorf("%s: %v", name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtensionsRoundTrip(t *testing.T) {
|
||||
msg := &pb.MyMessage{}
|
||||
ext1 := &pb.Ext{
|
||||
Data: proto.String("hi"),
|
||||
}
|
||||
ext2 := &pb.Ext{
|
||||
Data: proto.String("there"),
|
||||
}
|
||||
exists := proto.HasExtension(msg, pb.E_Ext_More)
|
||||
if exists {
|
||||
t.Error("Extension More present unexpectedly")
|
||||
}
|
||||
if err := proto.SetExtension(msg, pb.E_Ext_More, ext1); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := proto.SetExtension(msg, pb.E_Ext_More, ext2); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
e, err := proto.GetExtension(msg, pb.E_Ext_More)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
x, ok := e.(*pb.Ext)
|
||||
if !ok {
|
||||
t.Errorf("e has type %T, expected testdata.Ext", e)
|
||||
} else if *x.Data != "there" {
|
||||
t.Errorf("SetExtension failed to overwrite, got %+v, not 'there'", x)
|
||||
}
|
||||
proto.ClearExtension(msg, pb.E_Ext_More)
|
||||
if _, err = proto.GetExtension(msg, pb.E_Ext_More); err != proto.ErrMissingExtension {
|
||||
t.Errorf("got %v, expected ErrMissingExtension", e)
|
||||
}
|
||||
if _, err := proto.GetExtension(msg, pb.E_X215); err == nil {
|
||||
t.Error("expected bad extension error, got nil")
|
||||
}
|
||||
if err := proto.SetExtension(msg, pb.E_X215, 12); err == nil {
|
||||
t.Error("expected extension err")
|
||||
}
|
||||
if err := proto.SetExtension(msg, pb.E_Ext_More, 12); err == nil {
|
||||
t.Error("expected some sort of type mismatch error, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNilExtension(t *testing.T) {
|
||||
msg := &pb.MyMessage{
|
||||
Count: proto.Int32(1),
|
||||
}
|
||||
if err := proto.SetExtension(msg, pb.E_Ext_Text, proto.String("hello")); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := proto.SetExtension(msg, pb.E_Ext_More, (*pb.Ext)(nil)); err == nil {
|
||||
t.Error("expected SetExtension to fail due to a nil extension")
|
||||
} else if want := "proto: SetExtension called with nil value of type *testdata.Ext"; err.Error() != want {
|
||||
t.Errorf("expected error %v, got %v", want, err)
|
||||
}
|
||||
// Note: if the behavior of Marshal is ever changed to ignore nil extensions, update
|
||||
// this test to verify that E_Ext_Text is properly propagated through marshal->unmarshal.
|
||||
}
|
||||
|
||||
func TestMarshalUnmarshalRepeatedExtension(t *testing.T) {
|
||||
// Add a repeated extension to the result.
|
||||
tests := []struct {
|
||||
name string
|
||||
ext []*pb.ComplexExtension
|
||||
}{
|
||||
{
|
||||
"two fields",
|
||||
[]*pb.ComplexExtension{
|
||||
{First: proto.Int32(7)},
|
||||
{Second: proto.Int32(11)},
|
||||
},
|
||||
},
|
||||
{
|
||||
"repeated field",
|
||||
[]*pb.ComplexExtension{
|
||||
{Third: []int32{1000}},
|
||||
{Third: []int32{2000}},
|
||||
},
|
||||
},
|
||||
{
|
||||
"two fields and repeated field",
|
||||
[]*pb.ComplexExtension{
|
||||
{Third: []int32{1000}},
|
||||
{First: proto.Int32(9)},
|
||||
{Second: proto.Int32(21)},
|
||||
{Third: []int32{2000}},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
// Marshal message with a repeated extension.
|
||||
msg1 := new(pb.OtherMessage)
|
||||
err := proto.SetExtension(msg1, pb.E_RComplex, test.ext)
|
||||
if err != nil {
|
||||
t.Fatalf("[%s] Error setting extension: %v", test.name, err)
|
||||
}
|
||||
b, err := proto.Marshal(msg1)
|
||||
if err != nil {
|
||||
t.Fatalf("[%s] Error marshaling message: %v", test.name, err)
|
||||
}
|
||||
|
||||
// Unmarshal and read the merged proto.
|
||||
msg2 := new(pb.OtherMessage)
|
||||
err = proto.Unmarshal(b, msg2)
|
||||
if err != nil {
|
||||
t.Fatalf("[%s] Error unmarshaling message: %v", test.name, err)
|
||||
}
|
||||
e, err := proto.GetExtension(msg2, pb.E_RComplex)
|
||||
if err != nil {
|
||||
t.Fatalf("[%s] Error getting extension: %v", test.name, err)
|
||||
}
|
||||
ext := e.([]*pb.ComplexExtension)
|
||||
if ext == nil {
|
||||
t.Fatalf("[%s] Invalid extension", test.name)
|
||||
}
|
||||
if !reflect.DeepEqual(ext, test.ext) {
|
||||
t.Errorf("[%s] Wrong value for ComplexExtension: got: %v want: %v\n", test.name, ext, test.ext)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalRepeatingNonRepeatedExtension(t *testing.T) {
|
||||
// We may see multiple instances of the same extension in the wire
|
||||
// format. For example, the proto compiler may encode custom options in
|
||||
// this way. Here, we verify that we merge the extensions together.
|
||||
tests := []struct {
|
||||
name string
|
||||
ext []*pb.ComplexExtension
|
||||
}{
|
||||
{
|
||||
"two fields",
|
||||
[]*pb.ComplexExtension{
|
||||
{First: proto.Int32(7)},
|
||||
{Second: proto.Int32(11)},
|
||||
},
|
||||
},
|
||||
{
|
||||
"repeated field",
|
||||
[]*pb.ComplexExtension{
|
||||
{Third: []int32{1000}},
|
||||
{Third: []int32{2000}},
|
||||
},
|
||||
},
|
||||
{
|
||||
"two fields and repeated field",
|
||||
[]*pb.ComplexExtension{
|
||||
{Third: []int32{1000}},
|
||||
{First: proto.Int32(9)},
|
||||
{Second: proto.Int32(21)},
|
||||
{Third: []int32{2000}},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
var buf bytes.Buffer
|
||||
var want pb.ComplexExtension
|
||||
|
||||
// Generate a serialized representation of a repeated extension
|
||||
// by catenating bytes together.
|
||||
for i, e := range test.ext {
|
||||
// Merge to create the wanted proto.
|
||||
proto.Merge(&want, e)
|
||||
|
||||
// serialize the message
|
||||
msg := new(pb.OtherMessage)
|
||||
err := proto.SetExtension(msg, pb.E_Complex, e)
|
||||
if err != nil {
|
||||
t.Fatalf("[%s] Error setting extension %d: %v", test.name, i, err)
|
||||
}
|
||||
b, err := proto.Marshal(msg)
|
||||
if err != nil {
|
||||
t.Fatalf("[%s] Error marshaling message %d: %v", test.name, i, err)
|
||||
}
|
||||
buf.Write(b)
|
||||
}
|
||||
|
||||
// Unmarshal and read the merged proto.
|
||||
msg2 := new(pb.OtherMessage)
|
||||
err := proto.Unmarshal(buf.Bytes(), msg2)
|
||||
if err != nil {
|
||||
t.Fatalf("[%s] Error unmarshaling message: %v", test.name, err)
|
||||
}
|
||||
e, err := proto.GetExtension(msg2, pb.E_Complex)
|
||||
if err != nil {
|
||||
t.Fatalf("[%s] Error getting extension: %v", test.name, err)
|
||||
}
|
||||
ext := e.(*pb.ComplexExtension)
|
||||
if ext == nil {
|
||||
t.Fatalf("[%s] Invalid extension", test.name)
|
||||
}
|
||||
if !reflect.DeepEqual(*ext, want) {
|
||||
t.Errorf("[%s] Wrong value for ComplexExtension: got: %s want: %s\n", test.name, ext, want)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package proto
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestUnmarshalMessageSetWithDuplicate(t *testing.T) {
|
||||
// Check that a repeated message set entry will be concatenated.
|
||||
in := &messageSet{
|
||||
Item: []*_MessageSet_Item{
|
||||
{TypeId: Int32(12345), Message: []byte("hoo")},
|
||||
{TypeId: Int32(12345), Message: []byte("hah")},
|
||||
},
|
||||
}
|
||||
b, err := Marshal(in)
|
||||
if err != nil {
|
||||
t.Fatalf("Marshal: %v", err)
|
||||
}
|
||||
t.Logf("Marshaled bytes: %q", b)
|
||||
|
||||
m := make(map[int32]Extension)
|
||||
if err := UnmarshalMessageSet(b, m); err != nil {
|
||||
t.Fatalf("UnmarshalMessageSet: %v", err)
|
||||
}
|
||||
ext, ok := m[12345]
|
||||
if !ok {
|
||||
t.Fatalf("Didn't retrieve extension 12345; map is %v", m)
|
||||
}
|
||||
// Skip wire type/field number and length varints.
|
||||
got := skipVarint(skipVarint(ext.enc))
|
||||
if want := []byte("hoohah"); !bytes.Equal(got, want) {
|
||||
t.Errorf("Combined extension is %q, want %q", got, want)
|
||||
}
|
||||
}
|
122
Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go
generated
vendored
122
Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go
generated
vendored
|
@ -1,122 +0,0 @@
|
|||
// Code generated by protoc-gen-go.
|
||||
// source: proto3_proto/proto3.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package proto3_proto is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
proto3_proto/proto3.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Message
|
||||
Nested
|
||||
MessageWithMap
|
||||
*/
|
||||
package proto3_proto
|
||||
|
||||
import proto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
|
||||
import testdata "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
|
||||
type Message_Humour int32
|
||||
|
||||
const (
|
||||
Message_UNKNOWN Message_Humour = 0
|
||||
Message_PUNS Message_Humour = 1
|
||||
Message_SLAPSTICK Message_Humour = 2
|
||||
Message_BILL_BAILEY Message_Humour = 3
|
||||
)
|
||||
|
||||
var Message_Humour_name = map[int32]string{
|
||||
0: "UNKNOWN",
|
||||
1: "PUNS",
|
||||
2: "SLAPSTICK",
|
||||
3: "BILL_BAILEY",
|
||||
}
|
||||
var Message_Humour_value = map[string]int32{
|
||||
"UNKNOWN": 0,
|
||||
"PUNS": 1,
|
||||
"SLAPSTICK": 2,
|
||||
"BILL_BAILEY": 3,
|
||||
}
|
||||
|
||||
func (x Message_Humour) String() string {
|
||||
return proto.EnumName(Message_Humour_name, int32(x))
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||
Hilarity Message_Humour `protobuf:"varint,2,opt,name=hilarity,enum=proto3_proto.Message_Humour" json:"hilarity,omitempty"`
|
||||
HeightInCm uint32 `protobuf:"varint,3,opt,name=height_in_cm" json:"height_in_cm,omitempty"`
|
||||
Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"`
|
||||
ResultCount int64 `protobuf:"varint,7,opt,name=result_count" json:"result_count,omitempty"`
|
||||
TrueScotsman bool `protobuf:"varint,8,opt,name=true_scotsman" json:"true_scotsman,omitempty"`
|
||||
Score float32 `protobuf:"fixed32,9,opt,name=score" json:"score,omitempty"`
|
||||
Key []uint64 `protobuf:"varint,5,rep,name=key" json:"key,omitempty"`
|
||||
Nested *Nested `protobuf:"bytes,6,opt,name=nested" json:"nested,omitempty"`
|
||||
Terrain map[string]*Nested `protobuf:"bytes,10,rep,name=terrain" json:"terrain,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
|
||||
Proto2Field *testdata.SubDefaults `protobuf:"bytes,11,opt,name=proto2_field" json:"proto2_field,omitempty"`
|
||||
Proto2Value map[string]*testdata.SubDefaults `protobuf:"bytes,13,rep,name=proto2_value" json:"proto2_value,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
|
||||
}
|
||||
|
||||
func (m *Message) Reset() { *m = Message{} }
|
||||
func (m *Message) String() string { return proto.CompactTextString(m) }
|
||||
func (*Message) ProtoMessage() {}
|
||||
|
||||
func (m *Message) GetNested() *Nested {
|
||||
if m != nil {
|
||||
return m.Nested
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Message) GetTerrain() map[string]*Nested {
|
||||
if m != nil {
|
||||
return m.Terrain
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Message) GetProto2Field() *testdata.SubDefaults {
|
||||
if m != nil {
|
||||
return m.Proto2Field
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Message) GetProto2Value() map[string]*testdata.SubDefaults {
|
||||
if m != nil {
|
||||
return m.Proto2Value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Nested struct {
|
||||
Bunny string `protobuf:"bytes,1,opt,name=bunny" json:"bunny,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Nested) Reset() { *m = Nested{} }
|
||||
func (m *Nested) String() string { return proto.CompactTextString(m) }
|
||||
func (*Nested) ProtoMessage() {}
|
||||
|
||||
type MessageWithMap struct {
|
||||
ByteMapping map[bool][]byte `protobuf:"bytes,1,rep,name=byte_mapping" json:"byte_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||
}
|
||||
|
||||
func (m *MessageWithMap) Reset() { *m = MessageWithMap{} }
|
||||
func (m *MessageWithMap) String() string { return proto.CompactTextString(m) }
|
||||
func (*MessageWithMap) ProtoMessage() {}
|
||||
|
||||
func (m *MessageWithMap) GetByteMapping() map[bool][]byte {
|
||||
if m != nil {
|
||||
return m.ByteMapping
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterEnum("proto3_proto.Message_Humour", Message_Humour_name, Message_Humour_value)
|
||||
}
|
68
Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto/proto3.proto
generated
vendored
68
Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto/proto3.proto
generated
vendored
|
@ -1,68 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
import "testdata/test.proto";
|
||||
|
||||
package proto3_proto;
|
||||
|
||||
message Message {
|
||||
enum Humour {
|
||||
UNKNOWN = 0;
|
||||
PUNS = 1;
|
||||
SLAPSTICK = 2;
|
||||
BILL_BAILEY = 3;
|
||||
}
|
||||
|
||||
string name = 1;
|
||||
Humour hilarity = 2;
|
||||
uint32 height_in_cm = 3;
|
||||
bytes data = 4;
|
||||
int64 result_count = 7;
|
||||
bool true_scotsman = 8;
|
||||
float score = 9;
|
||||
|
||||
repeated uint64 key = 5;
|
||||
Nested nested = 6;
|
||||
|
||||
map<string, Nested> terrain = 10;
|
||||
testdata.SubDefaults proto2_field = 11;
|
||||
map<string, testdata.SubDefaults> proto2_value = 13;
|
||||
}
|
||||
|
||||
message Nested {
|
||||
string bunny = 1;
|
||||
}
|
||||
|
||||
message MessageWithMap {
|
||||
map<bool, bytes> byte_mapping = 1;
|
||||
}
|
|
@ -1,125 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package proto_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
|
||||
pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto"
|
||||
tpb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata"
|
||||
)
|
||||
|
||||
func TestProto3ZeroValues(t *testing.T) {
|
||||
tests := []struct {
|
||||
desc string
|
||||
m proto.Message
|
||||
}{
|
||||
{"zero message", &pb.Message{}},
|
||||
{"empty bytes field", &pb.Message{Data: []byte{}}},
|
||||
}
|
||||
for _, test := range tests {
|
||||
b, err := proto.Marshal(test.m)
|
||||
if err != nil {
|
||||
t.Errorf("%s: proto.Marshal: %v", test.desc, err)
|
||||
continue
|
||||
}
|
||||
if len(b) > 0 {
|
||||
t.Errorf("%s: Encoding is non-empty: %q", test.desc, b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRoundTripProto3(t *testing.T) {
|
||||
m := &pb.Message{
|
||||
Name: "David", // (2 | 1<<3): 0x0a 0x05 "David"
|
||||
Hilarity: pb.Message_PUNS, // (0 | 2<<3): 0x10 0x01
|
||||
HeightInCm: 178, // (0 | 3<<3): 0x18 0xb2 0x01
|
||||
Data: []byte("roboto"), // (2 | 4<<3): 0x20 0x06 "roboto"
|
||||
ResultCount: 47, // (0 | 7<<3): 0x38 0x2f
|
||||
TrueScotsman: true, // (0 | 8<<3): 0x40 0x01
|
||||
Score: 8.1, // (5 | 9<<3): 0x4d <8.1>
|
||||
|
||||
Key: []uint64{1, 0xdeadbeef},
|
||||
Nested: &pb.Nested{
|
||||
Bunny: "Monty",
|
||||
},
|
||||
}
|
||||
t.Logf(" m: %v", m)
|
||||
|
||||
b, err := proto.Marshal(m)
|
||||
if err != nil {
|
||||
t.Fatalf("proto.Marshal: %v", err)
|
||||
}
|
||||
t.Logf(" b: %q", b)
|
||||
|
||||
m2 := new(pb.Message)
|
||||
if err := proto.Unmarshal(b, m2); err != nil {
|
||||
t.Fatalf("proto.Unmarshal: %v", err)
|
||||
}
|
||||
t.Logf("m2: %v", m2)
|
||||
|
||||
if !proto.Equal(m, m2) {
|
||||
t.Errorf("proto.Equal returned false:\n m: %v\nm2: %v", m, m2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProto3SetDefaults(t *testing.T) {
|
||||
in := &pb.Message{
|
||||
Terrain: map[string]*pb.Nested{
|
||||
"meadow": new(pb.Nested),
|
||||
},
|
||||
Proto2Field: new(tpb.SubDefaults),
|
||||
Proto2Value: map[string]*tpb.SubDefaults{
|
||||
"badlands": new(tpb.SubDefaults),
|
||||
},
|
||||
}
|
||||
|
||||
got := proto.Clone(in).(*pb.Message)
|
||||
proto.SetDefaults(got)
|
||||
|
||||
// There are no defaults in proto3. Everything should be the zero value, but
|
||||
// we need to remember to set defaults for nested proto2 messages.
|
||||
want := &pb.Message{
|
||||
Terrain: map[string]*pb.Nested{
|
||||
"meadow": new(pb.Nested),
|
||||
},
|
||||
Proto2Field: &tpb.SubDefaults{N: proto.Int64(7)},
|
||||
Proto2Value: map[string]*tpb.SubDefaults{
|
||||
"badlands": &tpb.SubDefaults{N: proto.Int64(7)},
|
||||
},
|
||||
}
|
||||
|
||||
if !proto.Equal(got, want) {
|
||||
t.Errorf("with in = %v\nproto.SetDefaults(in) =>\ngot %v\nwant %v", in, got, want)
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package proto
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// This is a separate file and package from size_test.go because that one uses
|
||||
// generated messages and thus may not be in package proto without having a circular
|
||||
// dependency, whereas this file tests unexported details of size.go.
|
||||
|
||||
func TestVarintSize(t *testing.T) {
|
||||
// Check the edge cases carefully.
|
||||
testCases := []struct {
|
||||
n uint64
|
||||
size int
|
||||
}{
|
||||
{0, 1},
|
||||
{1, 1},
|
||||
{127, 1},
|
||||
{128, 2},
|
||||
{16383, 2},
|
||||
{16384, 3},
|
||||
{1<<63 - 1, 9},
|
||||
{1 << 63, 10},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
size := sizeVarint(tc.n)
|
||||
if size != tc.size {
|
||||
t.Errorf("sizeVarint(%d) = %d, want %d", tc.n, size, tc.size)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,164 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package proto_test
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
. "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
|
||||
proto3pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto"
|
||||
pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata"
|
||||
)
|
||||
|
||||
var messageWithExtension1 = &pb.MyMessage{Count: Int32(7)}
|
||||
|
||||
// messageWithExtension2 is in equal_test.go.
|
||||
var messageWithExtension3 = &pb.MyMessage{Count: Int32(8)}
|
||||
|
||||
func init() {
|
||||
if err := SetExtension(messageWithExtension1, pb.E_Ext_More, &pb.Ext{Data: String("Abbott")}); err != nil {
|
||||
log.Panicf("SetExtension: %v", err)
|
||||
}
|
||||
if err := SetExtension(messageWithExtension3, pb.E_Ext_More, &pb.Ext{Data: String("Costello")}); err != nil {
|
||||
log.Panicf("SetExtension: %v", err)
|
||||
}
|
||||
|
||||
// Force messageWithExtension3 to have the extension encoded.
|
||||
Marshal(messageWithExtension3)
|
||||
|
||||
}
|
||||
|
||||
var SizeTests = []struct {
|
||||
desc string
|
||||
pb Message
|
||||
}{
|
||||
{"empty", &pb.OtherMessage{}},
|
||||
// Basic types.
|
||||
{"bool", &pb.Defaults{F_Bool: Bool(true)}},
|
||||
{"int32", &pb.Defaults{F_Int32: Int32(12)}},
|
||||
{"negative int32", &pb.Defaults{F_Int32: Int32(-1)}},
|
||||
{"small int64", &pb.Defaults{F_Int64: Int64(1)}},
|
||||
{"big int64", &pb.Defaults{F_Int64: Int64(1 << 20)}},
|
||||
{"negative int64", &pb.Defaults{F_Int64: Int64(-1)}},
|
||||
{"fixed32", &pb.Defaults{F_Fixed32: Uint32(71)}},
|
||||
{"fixed64", &pb.Defaults{F_Fixed64: Uint64(72)}},
|
||||
{"uint32", &pb.Defaults{F_Uint32: Uint32(123)}},
|
||||
{"uint64", &pb.Defaults{F_Uint64: Uint64(124)}},
|
||||
{"float", &pb.Defaults{F_Float: Float32(12.6)}},
|
||||
{"double", &pb.Defaults{F_Double: Float64(13.9)}},
|
||||
{"string", &pb.Defaults{F_String: String("niles")}},
|
||||
{"bytes", &pb.Defaults{F_Bytes: []byte("wowsa")}},
|
||||
{"bytes, empty", &pb.Defaults{F_Bytes: []byte{}}},
|
||||
{"sint32", &pb.Defaults{F_Sint32: Int32(65)}},
|
||||
{"sint64", &pb.Defaults{F_Sint64: Int64(67)}},
|
||||
{"enum", &pb.Defaults{F_Enum: pb.Defaults_BLUE.Enum()}},
|
||||
// Repeated.
|
||||
{"empty repeated bool", &pb.MoreRepeated{Bools: []bool{}}},
|
||||
{"repeated bool", &pb.MoreRepeated{Bools: []bool{false, true, true, false}}},
|
||||
{"packed repeated bool", &pb.MoreRepeated{BoolsPacked: []bool{false, true, true, false, true, true, true}}},
|
||||
{"repeated int32", &pb.MoreRepeated{Ints: []int32{1, 12203, 1729, -1}}},
|
||||
{"repeated int32 packed", &pb.MoreRepeated{IntsPacked: []int32{1, 12203, 1729}}},
|
||||
{"repeated int64 packed", &pb.MoreRepeated{Int64SPacked: []int64{
|
||||
// Need enough large numbers to verify that the header is counting the number of bytes
|
||||
// for the field, not the number of elements.
|
||||
1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62,
|
||||
1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62,
|
||||
}}},
|
||||
{"repeated string", &pb.MoreRepeated{Strings: []string{"r", "ken", "gri"}}},
|
||||
{"repeated fixed", &pb.MoreRepeated{Fixeds: []uint32{1, 2, 3, 4}}},
|
||||
// Nested.
|
||||
{"nested", &pb.OldMessage{Nested: &pb.OldMessage_Nested{Name: String("whatever")}}},
|
||||
{"group", &pb.GroupOld{G: &pb.GroupOld_G{X: Int32(12345)}}},
|
||||
// Other things.
|
||||
{"unrecognized", &pb.MoreRepeated{XXX_unrecognized: []byte{13<<3 | 0, 4}}},
|
||||
{"extension (unencoded)", messageWithExtension1},
|
||||
{"extension (encoded)", messageWithExtension3},
|
||||
// proto3 message
|
||||
{"proto3 empty", &proto3pb.Message{}},
|
||||
{"proto3 bool", &proto3pb.Message{TrueScotsman: true}},
|
||||
{"proto3 int64", &proto3pb.Message{ResultCount: 1}},
|
||||
{"proto3 uint32", &proto3pb.Message{HeightInCm: 123}},
|
||||
{"proto3 float", &proto3pb.Message{Score: 12.6}},
|
||||
{"proto3 string", &proto3pb.Message{Name: "Snezana"}},
|
||||
{"proto3 bytes", &proto3pb.Message{Data: []byte("wowsa")}},
|
||||
{"proto3 bytes, empty", &proto3pb.Message{Data: []byte{}}},
|
||||
{"proto3 enum", &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}},
|
||||
{"proto3 map field with empty bytes", &proto3pb.MessageWithMap{ByteMapping: map[bool][]byte{false: []byte{}}}},
|
||||
|
||||
{"map field", &pb.MessageWithMap{NameMapping: map[int32]string{1: "Rob", 7: "Andrew"}}},
|
||||
{"map field with message", &pb.MessageWithMap{MsgMapping: map[int64]*pb.FloatingPoint{0x7001: &pb.FloatingPoint{F: Float64(2.0)}}}},
|
||||
{"map field with bytes", &pb.MessageWithMap{ByteMapping: map[bool][]byte{true: []byte("this time for sure")}}},
|
||||
{"map field with empty bytes", &pb.MessageWithMap{ByteMapping: map[bool][]byte{true: []byte{}}}},
|
||||
|
||||
{"map field with big entry", &pb.MessageWithMap{NameMapping: map[int32]string{8: strings.Repeat("x", 125)}}},
|
||||
{"map field with big key and val", &pb.MessageWithMap{StrToStr: map[string]string{strings.Repeat("x", 70): strings.Repeat("y", 70)}}},
|
||||
{"map field with big numeric key", &pb.MessageWithMap{NameMapping: map[int32]string{0xf00d: "om nom nom"}}},
|
||||
|
||||
{"oneof not set", &pb.Oneof{}},
|
||||
{"oneof bool", &pb.Oneof{Union: &pb.Oneof_F_Bool{true}}},
|
||||
{"oneof zero int32", &pb.Oneof{Union: &pb.Oneof_F_Int32{0}}},
|
||||
{"oneof big int32", &pb.Oneof{Union: &pb.Oneof_F_Int32{1 << 20}}},
|
||||
{"oneof int64", &pb.Oneof{Union: &pb.Oneof_F_Int64{42}}},
|
||||
{"oneof fixed32", &pb.Oneof{Union: &pb.Oneof_F_Fixed32{43}}},
|
||||
{"oneof fixed64", &pb.Oneof{Union: &pb.Oneof_F_Fixed64{44}}},
|
||||
{"oneof uint32", &pb.Oneof{Union: &pb.Oneof_F_Uint32{45}}},
|
||||
{"oneof uint64", &pb.Oneof{Union: &pb.Oneof_F_Uint64{46}}},
|
||||
{"oneof float", &pb.Oneof{Union: &pb.Oneof_F_Float{47.1}}},
|
||||
{"oneof double", &pb.Oneof{Union: &pb.Oneof_F_Double{48.9}}},
|
||||
{"oneof string", &pb.Oneof{Union: &pb.Oneof_F_String{"Rhythmic Fman"}}},
|
||||
{"oneof bytes", &pb.Oneof{Union: &pb.Oneof_F_Bytes{[]byte("let go")}}},
|
||||
{"oneof sint32", &pb.Oneof{Union: &pb.Oneof_F_Sint32{50}}},
|
||||
{"oneof sint64", &pb.Oneof{Union: &pb.Oneof_F_Sint64{51}}},
|
||||
{"oneof enum", &pb.Oneof{Union: &pb.Oneof_F_Enum{pb.MyMessage_BLUE}}},
|
||||
{"message for oneof", &pb.GoTestField{Label: String("k"), Type: String("v")}},
|
||||
{"oneof message", &pb.Oneof{Union: &pb.Oneof_F_Message{&pb.GoTestField{Label: String("k"), Type: String("v")}}}},
|
||||
{"oneof group", &pb.Oneof{Union: &pb.Oneof_FGroup{&pb.Oneof_F_Group{X: Int32(52)}}}},
|
||||
{"oneof largest tag", &pb.Oneof{Union: &pb.Oneof_F_Largest_Tag{1}}},
|
||||
{"multiple oneofs", &pb.Oneof{Union: &pb.Oneof_F_Int32{1}, Tormato: &pb.Oneof_Value{2}}},
|
||||
}
|
||||
|
||||
func TestSize(t *testing.T) {
|
||||
for _, tc := range SizeTests {
|
||||
size := Size(tc.pb)
|
||||
b, err := Marshal(tc.pb)
|
||||
if err != nil {
|
||||
t.Errorf("%v: Marshal failed: %v", tc.desc, err)
|
||||
continue
|
||||
}
|
||||
if size != len(b) {
|
||||
t.Errorf("%v: Size(%v) = %d, want %d", tc.desc, tc.pb, size, len(b))
|
||||
t.Logf("%v: bytes: %#v", tc.desc, b)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
# Go support for Protocol Buffers - Google's data interchange format
|
||||
#
|
||||
# Copyright 2010 The Go Authors. All rights reserved.
|
||||
# https://github.com/golang/protobuf
|
||||
#
|
||||
# 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.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
include ../../Make.protobuf
|
||||
|
||||
all: regenerate
|
||||
|
||||
regenerate:
|
||||
rm -f test.pb.go
|
||||
make test.pb.go
|
||||
|
||||
# The following rules are just aids to development. Not needed for typical testing.
|
||||
|
||||
diff: regenerate
|
||||
git diff test.pb.go
|
||||
|
||||
restore:
|
||||
cp test.pb.go.golden test.pb.go
|
||||
|
||||
preserve:
|
||||
cp test.pb.go test.pb.go.golden
|
86
Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/golden_test.go
generated
vendored
86
Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/golden_test.go
generated
vendored
|
@ -1,86 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Verify that the compiler output for test.proto is unchanged.
|
||||
|
||||
package testdata
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// sum returns in string form (for easy comparison) the SHA-1 hash of the named file.
|
||||
func sum(t *testing.T, name string) string {
|
||||
data, err := ioutil.ReadFile(name)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Logf("sum(%q): length is %d", name, len(data))
|
||||
hash := sha1.New()
|
||||
_, err = hash.Write(data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return fmt.Sprintf("% x", hash.Sum(nil))
|
||||
}
|
||||
|
||||
func run(t *testing.T, name string, args ...string) {
|
||||
cmd := exec.Command(name, args...)
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGolden(t *testing.T) {
|
||||
// Compute the original checksum.
|
||||
goldenSum := sum(t, "test.pb.go")
|
||||
// Run the proto compiler.
|
||||
run(t, "protoc", "--go_out="+os.TempDir(), "test.proto")
|
||||
newFile := filepath.Join(os.TempDir(), "test.pb.go")
|
||||
defer os.Remove(newFile)
|
||||
// Compute the new checksum.
|
||||
newSum := sum(t, newFile)
|
||||
// Verify
|
||||
if newSum != goldenSum {
|
||||
run(t, "diff", "-u", "test.pb.go", newFile)
|
||||
t.Fatal("Code generated by protoc-gen-go has changed; update test.pb.go")
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,535 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// A feature-rich test file for the protocol compiler and libraries.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package testdata;
|
||||
|
||||
enum FOO { FOO1 = 1; };
|
||||
|
||||
message GoEnum {
|
||||
required FOO foo = 1;
|
||||
}
|
||||
|
||||
message GoTestField {
|
||||
required string Label = 1;
|
||||
required string Type = 2;
|
||||
}
|
||||
|
||||
message GoTest {
|
||||
// An enum, for completeness.
|
||||
enum KIND {
|
||||
VOID = 0;
|
||||
|
||||
// Basic types
|
||||
BOOL = 1;
|
||||
BYTES = 2;
|
||||
FINGERPRINT = 3;
|
||||
FLOAT = 4;
|
||||
INT = 5;
|
||||
STRING = 6;
|
||||
TIME = 7;
|
||||
|
||||
// Groupings
|
||||
TUPLE = 8;
|
||||
ARRAY = 9;
|
||||
MAP = 10;
|
||||
|
||||
// Table types
|
||||
TABLE = 11;
|
||||
|
||||
// Functions
|
||||
FUNCTION = 12; // last tag
|
||||
};
|
||||
|
||||
// Some typical parameters
|
||||
required KIND Kind = 1;
|
||||
optional string Table = 2;
|
||||
optional int32 Param = 3;
|
||||
|
||||
// Required, repeated and optional foreign fields.
|
||||
required GoTestField RequiredField = 4;
|
||||
repeated GoTestField RepeatedField = 5;
|
||||
optional GoTestField OptionalField = 6;
|
||||
|
||||
// Required fields of all basic types
|
||||
required bool F_Bool_required = 10;
|
||||
required int32 F_Int32_required = 11;
|
||||
required int64 F_Int64_required = 12;
|
||||
required fixed32 F_Fixed32_required = 13;
|
||||
required fixed64 F_Fixed64_required = 14;
|
||||
required uint32 F_Uint32_required = 15;
|
||||
required uint64 F_Uint64_required = 16;
|
||||
required float F_Float_required = 17;
|
||||
required double F_Double_required = 18;
|
||||
required string F_String_required = 19;
|
||||
required bytes F_Bytes_required = 101;
|
||||
required sint32 F_Sint32_required = 102;
|
||||
required sint64 F_Sint64_required = 103;
|
||||
|
||||
// Repeated fields of all basic types
|
||||
repeated bool F_Bool_repeated = 20;
|
||||
repeated int32 F_Int32_repeated = 21;
|
||||
repeated int64 F_Int64_repeated = 22;
|
||||
repeated fixed32 F_Fixed32_repeated = 23;
|
||||
repeated fixed64 F_Fixed64_repeated = 24;
|
||||
repeated uint32 F_Uint32_repeated = 25;
|
||||
repeated uint64 F_Uint64_repeated = 26;
|
||||
repeated float F_Float_repeated = 27;
|
||||
repeated double F_Double_repeated = 28;
|
||||
repeated string F_String_repeated = 29;
|
||||
repeated bytes F_Bytes_repeated = 201;
|
||||
repeated sint32 F_Sint32_repeated = 202;
|
||||
repeated sint64 F_Sint64_repeated = 203;
|
||||
|
||||
// Optional fields of all basic types
|
||||
optional bool F_Bool_optional = 30;
|
||||
optional int32 F_Int32_optional = 31;
|
||||
optional int64 F_Int64_optional = 32;
|
||||
optional fixed32 F_Fixed32_optional = 33;
|
||||
optional fixed64 F_Fixed64_optional = 34;
|
||||
optional uint32 F_Uint32_optional = 35;
|
||||
optional uint64 F_Uint64_optional = 36;
|
||||
optional float F_Float_optional = 37;
|
||||
optional double F_Double_optional = 38;
|
||||
optional string F_String_optional = 39;
|
||||
optional bytes F_Bytes_optional = 301;
|
||||
optional sint32 F_Sint32_optional = 302;
|
||||
optional sint64 F_Sint64_optional = 303;
|
||||
|
||||
// Default-valued fields of all basic types
|
||||
optional bool F_Bool_defaulted = 40 [default=true];
|
||||
optional int32 F_Int32_defaulted = 41 [default=32];
|
||||
optional int64 F_Int64_defaulted = 42 [default=64];
|
||||
optional fixed32 F_Fixed32_defaulted = 43 [default=320];
|
||||
optional fixed64 F_Fixed64_defaulted = 44 [default=640];
|
||||
optional uint32 F_Uint32_defaulted = 45 [default=3200];
|
||||
optional uint64 F_Uint64_defaulted = 46 [default=6400];
|
||||
optional float F_Float_defaulted = 47 [default=314159.];
|
||||
optional double F_Double_defaulted = 48 [default=271828.];
|
||||
optional string F_String_defaulted = 49 [default="hello, \"world!\"\n"];
|
||||
optional bytes F_Bytes_defaulted = 401 [default="Bignose"];
|
||||
optional sint32 F_Sint32_defaulted = 402 [default = -32];
|
||||
optional sint64 F_Sint64_defaulted = 403 [default = -64];
|
||||
|
||||
// Packed repeated fields (no string or bytes).
|
||||
repeated bool F_Bool_repeated_packed = 50 [packed=true];
|
||||
repeated int32 F_Int32_repeated_packed = 51 [packed=true];
|
||||
repeated int64 F_Int64_repeated_packed = 52 [packed=true];
|
||||
repeated fixed32 F_Fixed32_repeated_packed = 53 [packed=true];
|
||||
repeated fixed64 F_Fixed64_repeated_packed = 54 [packed=true];
|
||||
repeated uint32 F_Uint32_repeated_packed = 55 [packed=true];
|
||||
repeated uint64 F_Uint64_repeated_packed = 56 [packed=true];
|
||||
repeated float F_Float_repeated_packed = 57 [packed=true];
|
||||
repeated double F_Double_repeated_packed = 58 [packed=true];
|
||||
repeated sint32 F_Sint32_repeated_packed = 502 [packed=true];
|
||||
repeated sint64 F_Sint64_repeated_packed = 503 [packed=true];
|
||||
|
||||
// Required, repeated, and optional groups.
|
||||
required group RequiredGroup = 70 {
|
||||
required string RequiredField = 71;
|
||||
};
|
||||
|
||||
repeated group RepeatedGroup = 80 {
|
||||
required string RequiredField = 81;
|
||||
};
|
||||
|
||||
optional group OptionalGroup = 90 {
|
||||
required string RequiredField = 91;
|
||||
};
|
||||
}
|
||||
|
||||
// For testing skipping of unrecognized fields.
|
||||
// Numbers are all big, larger than tag numbers in GoTestField,
|
||||
// the message used in the corresponding test.
|
||||
message GoSkipTest {
|
||||
required int32 skip_int32 = 11;
|
||||
required fixed32 skip_fixed32 = 12;
|
||||
required fixed64 skip_fixed64 = 13;
|
||||
required string skip_string = 14;
|
||||
required group SkipGroup = 15 {
|
||||
required int32 group_int32 = 16;
|
||||
required string group_string = 17;
|
||||
}
|
||||
}
|
||||
|
||||
// For testing packed/non-packed decoder switching.
|
||||
// A serialized instance of one should be deserializable as the other.
|
||||
message NonPackedTest {
|
||||
repeated int32 a = 1;
|
||||
}
|
||||
|
||||
message PackedTest {
|
||||
repeated int32 b = 1 [packed=true];
|
||||
}
|
||||
|
||||
message MaxTag {
|
||||
// Maximum possible tag number.
|
||||
optional string last_field = 536870911;
|
||||
}
|
||||
|
||||
message OldMessage {
|
||||
message Nested {
|
||||
optional string name = 1;
|
||||
}
|
||||
optional Nested nested = 1;
|
||||
|
||||
optional int32 num = 2;
|
||||
}
|
||||
|
||||
// NewMessage is wire compatible with OldMessage;
|
||||
// imagine it as a future version.
|
||||
message NewMessage {
|
||||
message Nested {
|
||||
optional string name = 1;
|
||||
optional string food_group = 2;
|
||||
}
|
||||
optional Nested nested = 1;
|
||||
|
||||
// This is an int32 in OldMessage.
|
||||
optional int64 num = 2;
|
||||
}
|
||||
|
||||
// Smaller tests for ASCII formatting.
|
||||
|
||||
message InnerMessage {
|
||||
required string host = 1;
|
||||
optional int32 port = 2 [default=4000];
|
||||
optional bool connected = 3;
|
||||
}
|
||||
|
||||
message OtherMessage {
|
||||
optional int64 key = 1;
|
||||
optional bytes value = 2;
|
||||
optional float weight = 3;
|
||||
optional InnerMessage inner = 4;
|
||||
|
||||
extensions 100 to max;
|
||||
}
|
||||
|
||||
message MyMessage {
|
||||
required int32 count = 1;
|
||||
optional string name = 2;
|
||||
optional string quote = 3;
|
||||
repeated string pet = 4;
|
||||
optional InnerMessage inner = 5;
|
||||
repeated OtherMessage others = 6;
|
||||
repeated InnerMessage rep_inner = 12;
|
||||
|
||||
enum Color {
|
||||
RED = 0;
|
||||
GREEN = 1;
|
||||
BLUE = 2;
|
||||
};
|
||||
optional Color bikeshed = 7;
|
||||
|
||||
optional group SomeGroup = 8 {
|
||||
optional int32 group_field = 9;
|
||||
}
|
||||
|
||||
// This field becomes [][]byte in the generated code.
|
||||
repeated bytes rep_bytes = 10;
|
||||
|
||||
optional double bigfloat = 11;
|
||||
|
||||
extensions 100 to max;
|
||||
}
|
||||
|
||||
message Ext {
|
||||
extend MyMessage {
|
||||
optional Ext more = 103;
|
||||
optional string text = 104;
|
||||
optional int32 number = 105;
|
||||
}
|
||||
|
||||
optional string data = 1;
|
||||
}
|
||||
|
||||
extend MyMessage {
|
||||
repeated string greeting = 106;
|
||||
}
|
||||
|
||||
message ComplexExtension {
|
||||
optional int32 first = 1;
|
||||
optional int32 second = 2;
|
||||
repeated int32 third = 3;
|
||||
}
|
||||
|
||||
extend OtherMessage {
|
||||
optional ComplexExtension complex = 200;
|
||||
repeated ComplexExtension r_complex = 201;
|
||||
}
|
||||
|
||||
message DefaultsMessage {
|
||||
enum DefaultsEnum {
|
||||
ZERO = 0;
|
||||
ONE = 1;
|
||||
TWO = 2;
|
||||
};
|
||||
extensions 100 to max;
|
||||
}
|
||||
|
||||
extend DefaultsMessage {
|
||||
optional double no_default_double = 101;
|
||||
optional float no_default_float = 102;
|
||||
optional int32 no_default_int32 = 103;
|
||||
optional int64 no_default_int64 = 104;
|
||||
optional uint32 no_default_uint32 = 105;
|
||||
optional uint64 no_default_uint64 = 106;
|
||||
optional sint32 no_default_sint32 = 107;
|
||||
optional sint64 no_default_sint64 = 108;
|
||||
optional fixed32 no_default_fixed32 = 109;
|
||||
optional fixed64 no_default_fixed64 = 110;
|
||||
optional sfixed32 no_default_sfixed32 = 111;
|
||||
optional sfixed64 no_default_sfixed64 = 112;
|
||||
optional bool no_default_bool = 113;
|
||||
optional string no_default_string = 114;
|
||||
optional bytes no_default_bytes = 115;
|
||||
optional DefaultsMessage.DefaultsEnum no_default_enum = 116;
|
||||
|
||||
optional double default_double = 201 [default = 3.1415];
|
||||
optional float default_float = 202 [default = 3.14];
|
||||
optional int32 default_int32 = 203 [default = 42];
|
||||
optional int64 default_int64 = 204 [default = 43];
|
||||
optional uint32 default_uint32 = 205 [default = 44];
|
||||
optional uint64 default_uint64 = 206 [default = 45];
|
||||
optional sint32 default_sint32 = 207 [default = 46];
|
||||
optional sint64 default_sint64 = 208 [default = 47];
|
||||
optional fixed32 default_fixed32 = 209 [default = 48];
|
||||
optional fixed64 default_fixed64 = 210 [default = 49];
|
||||
optional sfixed32 default_sfixed32 = 211 [default = 50];
|
||||
optional sfixed64 default_sfixed64 = 212 [default = 51];
|
||||
optional bool default_bool = 213 [default = true];
|
||||
optional string default_string = 214 [default = "Hello, string"];
|
||||
optional bytes default_bytes = 215 [default = "Hello, bytes"];
|
||||
optional DefaultsMessage.DefaultsEnum default_enum = 216 [default = ONE];
|
||||
}
|
||||
|
||||
message MyMessageSet {
|
||||
option message_set_wire_format = true;
|
||||
extensions 100 to max;
|
||||
}
|
||||
|
||||
message Empty {
|
||||
}
|
||||
|
||||
extend MyMessageSet {
|
||||
optional Empty x201 = 201;
|
||||
optional Empty x202 = 202;
|
||||
optional Empty x203 = 203;
|
||||
optional Empty x204 = 204;
|
||||
optional Empty x205 = 205;
|
||||
optional Empty x206 = 206;
|
||||
optional Empty x207 = 207;
|
||||
optional Empty x208 = 208;
|
||||
optional Empty x209 = 209;
|
||||
optional Empty x210 = 210;
|
||||
optional Empty x211 = 211;
|
||||
optional Empty x212 = 212;
|
||||
optional Empty x213 = 213;
|
||||
optional Empty x214 = 214;
|
||||
optional Empty x215 = 215;
|
||||
optional Empty x216 = 216;
|
||||
optional Empty x217 = 217;
|
||||
optional Empty x218 = 218;
|
||||
optional Empty x219 = 219;
|
||||
optional Empty x220 = 220;
|
||||
optional Empty x221 = 221;
|
||||
optional Empty x222 = 222;
|
||||
optional Empty x223 = 223;
|
||||
optional Empty x224 = 224;
|
||||
optional Empty x225 = 225;
|
||||
optional Empty x226 = 226;
|
||||
optional Empty x227 = 227;
|
||||
optional Empty x228 = 228;
|
||||
optional Empty x229 = 229;
|
||||
optional Empty x230 = 230;
|
||||
optional Empty x231 = 231;
|
||||
optional Empty x232 = 232;
|
||||
optional Empty x233 = 233;
|
||||
optional Empty x234 = 234;
|
||||
optional Empty x235 = 235;
|
||||
optional Empty x236 = 236;
|
||||
optional Empty x237 = 237;
|
||||
optional Empty x238 = 238;
|
||||
optional Empty x239 = 239;
|
||||
optional Empty x240 = 240;
|
||||
optional Empty x241 = 241;
|
||||
optional Empty x242 = 242;
|
||||
optional Empty x243 = 243;
|
||||
optional Empty x244 = 244;
|
||||
optional Empty x245 = 245;
|
||||
optional Empty x246 = 246;
|
||||
optional Empty x247 = 247;
|
||||
optional Empty x248 = 248;
|
||||
optional Empty x249 = 249;
|
||||
optional Empty x250 = 250;
|
||||
}
|
||||
|
||||
message MessageList {
|
||||
repeated group Message = 1 {
|
||||
required string name = 2;
|
||||
required int32 count = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message Strings {
|
||||
optional string string_field = 1;
|
||||
optional bytes bytes_field = 2;
|
||||
}
|
||||
|
||||
message Defaults {
|
||||
enum Color {
|
||||
RED = 0;
|
||||
GREEN = 1;
|
||||
BLUE = 2;
|
||||
}
|
||||
|
||||
// Default-valued fields of all basic types.
|
||||
// Same as GoTest, but copied here to make testing easier.
|
||||
optional bool F_Bool = 1 [default=true];
|
||||
optional int32 F_Int32 = 2 [default=32];
|
||||
optional int64 F_Int64 = 3 [default=64];
|
||||
optional fixed32 F_Fixed32 = 4 [default=320];
|
||||
optional fixed64 F_Fixed64 = 5 [default=640];
|
||||
optional uint32 F_Uint32 = 6 [default=3200];
|
||||
optional uint64 F_Uint64 = 7 [default=6400];
|
||||
optional float F_Float = 8 [default=314159.];
|
||||
optional double F_Double = 9 [default=271828.];
|
||||
optional string F_String = 10 [default="hello, \"world!\"\n"];
|
||||
optional bytes F_Bytes = 11 [default="Bignose"];
|
||||
optional sint32 F_Sint32 = 12 [default=-32];
|
||||
optional sint64 F_Sint64 = 13 [default=-64];
|
||||
optional Color F_Enum = 14 [default=GREEN];
|
||||
|
||||
// More fields with crazy defaults.
|
||||
optional float F_Pinf = 15 [default=inf];
|
||||
optional float F_Ninf = 16 [default=-inf];
|
||||
optional float F_Nan = 17 [default=nan];
|
||||
|
||||
// Sub-message.
|
||||
optional SubDefaults sub = 18;
|
||||
|
||||
// Redundant but explicit defaults.
|
||||
optional string str_zero = 19 [default=""];
|
||||
}
|
||||
|
||||
message SubDefaults {
|
||||
optional int64 n = 1 [default=7];
|
||||
}
|
||||
|
||||
message RepeatedEnum {
|
||||
enum Color {
|
||||
RED = 1;
|
||||
}
|
||||
repeated Color color = 1;
|
||||
}
|
||||
|
||||
message MoreRepeated {
|
||||
repeated bool bools = 1;
|
||||
repeated bool bools_packed = 2 [packed=true];
|
||||
repeated int32 ints = 3;
|
||||
repeated int32 ints_packed = 4 [packed=true];
|
||||
repeated int64 int64s_packed = 7 [packed=true];
|
||||
repeated string strings = 5;
|
||||
repeated fixed32 fixeds = 6;
|
||||
}
|
||||
|
||||
// GroupOld and GroupNew have the same wire format.
|
||||
// GroupNew has a new field inside a group.
|
||||
|
||||
message GroupOld {
|
||||
optional group G = 101 {
|
||||
optional int32 x = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message GroupNew {
|
||||
optional group G = 101 {
|
||||
optional int32 x = 2;
|
||||
optional int32 y = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message FloatingPoint {
|
||||
required double f = 1;
|
||||
}
|
||||
|
||||
message MessageWithMap {
|
||||
map<int32, string> name_mapping = 1;
|
||||
map<sint64, FloatingPoint> msg_mapping = 2;
|
||||
map<bool, bytes> byte_mapping = 3;
|
||||
map<string, string> str_to_str = 4;
|
||||
}
|
||||
|
||||
message Oneof {
|
||||
oneof union {
|
||||
bool F_Bool = 1;
|
||||
int32 F_Int32 = 2;
|
||||
int64 F_Int64 = 3;
|
||||
fixed32 F_Fixed32 = 4;
|
||||
fixed64 F_Fixed64 = 5;
|
||||
uint32 F_Uint32 = 6;
|
||||
uint64 F_Uint64 = 7;
|
||||
float F_Float = 8;
|
||||
double F_Double = 9;
|
||||
string F_String = 10;
|
||||
bytes F_Bytes = 11;
|
||||
sint32 F_Sint32 = 12;
|
||||
sint64 F_Sint64 = 13;
|
||||
MyMessage.Color F_Enum = 14;
|
||||
GoTestField F_Message = 15;
|
||||
group F_Group = 16 {
|
||||
optional int32 x = 17;
|
||||
}
|
||||
int32 F_Largest_Tag = 536870911;
|
||||
}
|
||||
|
||||
oneof tormato {
|
||||
int32 value = 100;
|
||||
}
|
||||
}
|
||||
|
||||
message Communique {
|
||||
optional bool make_me_cry = 1;
|
||||
|
||||
// This is a oneof, called "union".
|
||||
oneof union {
|
||||
int32 number = 5;
|
||||
string name = 6;
|
||||
bytes data = 7;
|
||||
double temp_c = 8;
|
||||
MyMessage.Color col = 9;
|
||||
Strings msg = 10;
|
||||
}
|
||||
}
|
|
@ -1,532 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package proto_test
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
. "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
|
||||
proto3pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto"
|
||||
. "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata"
|
||||
)
|
||||
|
||||
type UnmarshalTextTest struct {
|
||||
in string
|
||||
err string // if "", no error expected
|
||||
out *MyMessage
|
||||
}
|
||||
|
||||
func buildExtStructTest(text string) UnmarshalTextTest {
|
||||
msg := &MyMessage{
|
||||
Count: Int32(42),
|
||||
}
|
||||
SetExtension(msg, E_Ext_More, &Ext{
|
||||
Data: String("Hello, world!"),
|
||||
})
|
||||
return UnmarshalTextTest{in: text, out: msg}
|
||||
}
|
||||
|
||||
func buildExtDataTest(text string) UnmarshalTextTest {
|
||||
msg := &MyMessage{
|
||||
Count: Int32(42),
|
||||
}
|
||||
SetExtension(msg, E_Ext_Text, String("Hello, world!"))
|
||||
SetExtension(msg, E_Ext_Number, Int32(1729))
|
||||
return UnmarshalTextTest{in: text, out: msg}
|
||||
}
|
||||
|
||||
func buildExtRepStringTest(text string) UnmarshalTextTest {
|
||||
msg := &MyMessage{
|
||||
Count: Int32(42),
|
||||
}
|
||||
if err := SetExtension(msg, E_Greeting, []string{"bula", "hola"}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return UnmarshalTextTest{in: text, out: msg}
|
||||
}
|
||||
|
||||
var unMarshalTextTests = []UnmarshalTextTest{
|
||||
// Basic
|
||||
{
|
||||
in: " count:42\n name:\"Dave\" ",
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Name: String("Dave"),
|
||||
},
|
||||
},
|
||||
|
||||
// Empty quoted string
|
||||
{
|
||||
in: `count:42 name:""`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Name: String(""),
|
||||
},
|
||||
},
|
||||
|
||||
// Quoted string concatenation
|
||||
{
|
||||
in: `count:42 name: "My name is "` + "\n" + `"elsewhere"`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Name: String("My name is elsewhere"),
|
||||
},
|
||||
},
|
||||
|
||||
// Quoted string with escaped apostrophe
|
||||
{
|
||||
in: `count:42 name: "HOLIDAY - New Year\'s Day"`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Name: String("HOLIDAY - New Year's Day"),
|
||||
},
|
||||
},
|
||||
|
||||
// Quoted string with single quote
|
||||
{
|
||||
in: `count:42 name: 'Roger "The Ramster" Ramjet'`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Name: String(`Roger "The Ramster" Ramjet`),
|
||||
},
|
||||
},
|
||||
|
||||
// Quoted string with all the accepted special characters from the C++ test
|
||||
{
|
||||
in: `count:42 name: ` + "\"\\\"A string with \\' characters \\n and \\r newlines and \\t tabs and \\001 slashes \\\\ and multiple spaces\"",
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Name: String("\"A string with ' characters \n and \r newlines and \t tabs and \001 slashes \\ and multiple spaces"),
|
||||
},
|
||||
},
|
||||
|
||||
// Quoted string with quoted backslash
|
||||
{
|
||||
in: `count:42 name: "\\'xyz"`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Name: String(`\'xyz`),
|
||||
},
|
||||
},
|
||||
|
||||
// Quoted string with UTF-8 bytes.
|
||||
{
|
||||
in: "count:42 name: '\303\277\302\201\xAB'",
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Name: String("\303\277\302\201\xAB"),
|
||||
},
|
||||
},
|
||||
|
||||
// Bad quoted string
|
||||
{
|
||||
in: `inner: < host: "\0" >` + "\n",
|
||||
err: `line 1.15: invalid quoted string "\0": \0 requires 2 following digits`,
|
||||
},
|
||||
|
||||
// Number too large for int64
|
||||
{
|
||||
in: "count: 1 others { key: 123456789012345678901 }",
|
||||
err: "line 1.23: invalid int64: 123456789012345678901",
|
||||
},
|
||||
|
||||
// Number too large for int32
|
||||
{
|
||||
in: "count: 1234567890123",
|
||||
err: "line 1.7: invalid int32: 1234567890123",
|
||||
},
|
||||
|
||||
// Number in hexadecimal
|
||||
{
|
||||
in: "count: 0x2beef",
|
||||
out: &MyMessage{
|
||||
Count: Int32(0x2beef),
|
||||
},
|
||||
},
|
||||
|
||||
// Number in octal
|
||||
{
|
||||
in: "count: 024601",
|
||||
out: &MyMessage{
|
||||
Count: Int32(024601),
|
||||
},
|
||||
},
|
||||
|
||||
// Floating point number with "f" suffix
|
||||
{
|
||||
in: "count: 4 others:< weight: 17.0f >",
|
||||
out: &MyMessage{
|
||||
Count: Int32(4),
|
||||
Others: []*OtherMessage{
|
||||
{
|
||||
Weight: Float32(17),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Floating point positive infinity
|
||||
{
|
||||
in: "count: 4 bigfloat: inf",
|
||||
out: &MyMessage{
|
||||
Count: Int32(4),
|
||||
Bigfloat: Float64(math.Inf(1)),
|
||||
},
|
||||
},
|
||||
|
||||
// Floating point negative infinity
|
||||
{
|
||||
in: "count: 4 bigfloat: -inf",
|
||||
out: &MyMessage{
|
||||
Count: Int32(4),
|
||||
Bigfloat: Float64(math.Inf(-1)),
|
||||
},
|
||||
},
|
||||
|
||||
// Number too large for float32
|
||||
{
|
||||
in: "others:< weight: 12345678901234567890123456789012345678901234567890 >",
|
||||
err: "line 1.17: invalid float32: 12345678901234567890123456789012345678901234567890",
|
||||
},
|
||||
|
||||
// Number posing as a quoted string
|
||||
{
|
||||
in: `inner: < host: 12 >` + "\n",
|
||||
err: `line 1.15: invalid string: 12`,
|
||||
},
|
||||
|
||||
// Quoted string posing as int32
|
||||
{
|
||||
in: `count: "12"`,
|
||||
err: `line 1.7: invalid int32: "12"`,
|
||||
},
|
||||
|
||||
// Quoted string posing a float32
|
||||
{
|
||||
in: `others:< weight: "17.4" >`,
|
||||
err: `line 1.17: invalid float32: "17.4"`,
|
||||
},
|
||||
|
||||
// Enum
|
||||
{
|
||||
in: `count:42 bikeshed: BLUE`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Bikeshed: MyMessage_BLUE.Enum(),
|
||||
},
|
||||
},
|
||||
|
||||
// Repeated field
|
||||
{
|
||||
in: `count:42 pet: "horsey" pet:"bunny"`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Pet: []string{"horsey", "bunny"},
|
||||
},
|
||||
},
|
||||
|
||||
// Repeated field with list notation
|
||||
{
|
||||
in: `count:42 pet: ["horsey", "bunny"]`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Pet: []string{"horsey", "bunny"},
|
||||
},
|
||||
},
|
||||
|
||||
// Repeated message with/without colon and <>/{}
|
||||
{
|
||||
in: `count:42 others:{} others{} others:<> others:{}`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Others: []*OtherMessage{
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Missing colon for inner message
|
||||
{
|
||||
in: `count:42 inner < host: "cauchy.syd" >`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Inner: &InnerMessage{
|
||||
Host: String("cauchy.syd"),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Missing colon for string field
|
||||
{
|
||||
in: `name "Dave"`,
|
||||
err: `line 1.5: expected ':', found "\"Dave\""`,
|
||||
},
|
||||
|
||||
// Missing colon for int32 field
|
||||
{
|
||||
in: `count 42`,
|
||||
err: `line 1.6: expected ':', found "42"`,
|
||||
},
|
||||
|
||||
// Missing required field
|
||||
{
|
||||
in: `name: "Pawel"`,
|
||||
err: `proto: required field "testdata.MyMessage.count" not set`,
|
||||
out: &MyMessage{
|
||||
Name: String("Pawel"),
|
||||
},
|
||||
},
|
||||
|
||||
// Repeated non-repeated field
|
||||
{
|
||||
in: `name: "Rob" name: "Russ"`,
|
||||
err: `line 1.12: non-repeated field "name" was repeated`,
|
||||
},
|
||||
|
||||
// Group
|
||||
{
|
||||
in: `count: 17 SomeGroup { group_field: 12 }`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(17),
|
||||
Somegroup: &MyMessage_SomeGroup{
|
||||
GroupField: Int32(12),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Semicolon between fields
|
||||
{
|
||||
in: `count:3;name:"Calvin"`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(3),
|
||||
Name: String("Calvin"),
|
||||
},
|
||||
},
|
||||
// Comma between fields
|
||||
{
|
||||
in: `count:4,name:"Ezekiel"`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(4),
|
||||
Name: String("Ezekiel"),
|
||||
},
|
||||
},
|
||||
|
||||
// Extension
|
||||
buildExtStructTest(`count: 42 [testdata.Ext.more]:<data:"Hello, world!" >`),
|
||||
buildExtStructTest(`count: 42 [testdata.Ext.more] {data:"Hello, world!"}`),
|
||||
buildExtDataTest(`count: 42 [testdata.Ext.text]:"Hello, world!" [testdata.Ext.number]:1729`),
|
||||
buildExtRepStringTest(`count: 42 [testdata.greeting]:"bula" [testdata.greeting]:"hola"`),
|
||||
|
||||
// Big all-in-one
|
||||
{
|
||||
in: "count:42 # Meaning\n" +
|
||||
`name:"Dave" ` +
|
||||
`quote:"\"I didn't want to go.\"" ` +
|
||||
`pet:"bunny" ` +
|
||||
`pet:"kitty" ` +
|
||||
`pet:"horsey" ` +
|
||||
`inner:<` +
|
||||
` host:"footrest.syd" ` +
|
||||
` port:7001 ` +
|
||||
` connected:true ` +
|
||||
`> ` +
|
||||
`others:<` +
|
||||
` key:3735928559 ` +
|
||||
` value:"\x01A\a\f" ` +
|
||||
`> ` +
|
||||
`others:<` +
|
||||
" weight:58.9 # Atomic weight of Co\n" +
|
||||
` inner:<` +
|
||||
` host:"lesha.mtv" ` +
|
||||
` port:8002 ` +
|
||||
` >` +
|
||||
`>`,
|
||||
out: &MyMessage{
|
||||
Count: Int32(42),
|
||||
Name: String("Dave"),
|
||||
Quote: String(`"I didn't want to go."`),
|
||||
Pet: []string{"bunny", "kitty", "horsey"},
|
||||
Inner: &InnerMessage{
|
||||
Host: String("footrest.syd"),
|
||||
Port: Int32(7001),
|
||||
Connected: Bool(true),
|
||||
},
|
||||
Others: []*OtherMessage{
|
||||
{
|
||||
Key: Int64(3735928559),
|
||||
Value: []byte{0x1, 'A', '\a', '\f'},
|
||||
},
|
||||
{
|
||||
Weight: Float32(58.9),
|
||||
Inner: &InnerMessage{
|
||||
Host: String("lesha.mtv"),
|
||||
Port: Int32(8002),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestUnmarshalText(t *testing.T) {
|
||||
for i, test := range unMarshalTextTests {
|
||||
pb := new(MyMessage)
|
||||
err := UnmarshalText(test.in, pb)
|
||||
if test.err == "" {
|
||||
// We don't expect failure.
|
||||
if err != nil {
|
||||
t.Errorf("Test %d: Unexpected error: %v", i, err)
|
||||
} else if !reflect.DeepEqual(pb, test.out) {
|
||||
t.Errorf("Test %d: Incorrect populated \nHave: %v\nWant: %v",
|
||||
i, pb, test.out)
|
||||
}
|
||||
} else {
|
||||
// We do expect failure.
|
||||
if err == nil {
|
||||
t.Errorf("Test %d: Didn't get expected error: %v", i, test.err)
|
||||
} else if err.Error() != test.err {
|
||||
t.Errorf("Test %d: Incorrect error.\nHave: %v\nWant: %v",
|
||||
i, err.Error(), test.err)
|
||||
} else if _, ok := err.(*RequiredNotSetError); ok && test.out != nil && !reflect.DeepEqual(pb, test.out) {
|
||||
t.Errorf("Test %d: Incorrect populated \nHave: %v\nWant: %v",
|
||||
i, pb, test.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalTextCustomMessage(t *testing.T) {
|
||||
msg := &textMessage{}
|
||||
if err := UnmarshalText("custom", msg); err != nil {
|
||||
t.Errorf("Unexpected error from custom unmarshal: %v", err)
|
||||
}
|
||||
if UnmarshalText("not custom", msg) == nil {
|
||||
t.Errorf("Didn't get expected error from custom unmarshal")
|
||||
}
|
||||
}
|
||||
|
||||
// Regression test; this caused a panic.
|
||||
func TestRepeatedEnum(t *testing.T) {
|
||||
pb := new(RepeatedEnum)
|
||||
if err := UnmarshalText("color: RED", pb); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
exp := &RepeatedEnum{
|
||||
Color: []RepeatedEnum_Color{RepeatedEnum_RED},
|
||||
}
|
||||
if !Equal(pb, exp) {
|
||||
t.Errorf("Incorrect populated \nHave: %v\nWant: %v", pb, exp)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProto3TextParsing(t *testing.T) {
|
||||
m := new(proto3pb.Message)
|
||||
const in = `name: "Wallace" true_scotsman: true`
|
||||
want := &proto3pb.Message{
|
||||
Name: "Wallace",
|
||||
TrueScotsman: true,
|
||||
}
|
||||
if err := UnmarshalText(in, m); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !Equal(m, want) {
|
||||
t.Errorf("\n got %v\nwant %v", m, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMapParsing(t *testing.T) {
|
||||
m := new(MessageWithMap)
|
||||
const in = `name_mapping:<key:1234 value:"Feist"> name_mapping:<key:1 value:"Beatles">` +
|
||||
`msg_mapping:<key:-4, value:<f: 2.0>,>` + // separating commas are okay
|
||||
`msg_mapping<key:-2 value<f: 4.0>>` + // no colon after "value"
|
||||
`byte_mapping:<key:true value:"so be it">`
|
||||
want := &MessageWithMap{
|
||||
NameMapping: map[int32]string{
|
||||
1: "Beatles",
|
||||
1234: "Feist",
|
||||
},
|
||||
MsgMapping: map[int64]*FloatingPoint{
|
||||
-4: {F: Float64(2.0)},
|
||||
-2: {F: Float64(4.0)},
|
||||
},
|
||||
ByteMapping: map[bool][]byte{
|
||||
true: []byte("so be it"),
|
||||
},
|
||||
}
|
||||
if err := UnmarshalText(in, m); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !Equal(m, want) {
|
||||
t.Errorf("\n got %v\nwant %v", m, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOneofParsing(t *testing.T) {
|
||||
const in = `name:"Shrek"`
|
||||
m := new(Communique)
|
||||
want := &Communique{Union: &Communique_Name{"Shrek"}}
|
||||
if err := UnmarshalText(in, m); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !Equal(m, want) {
|
||||
t.Errorf("\n got %v\nwant %v", m, want)
|
||||
}
|
||||
}
|
||||
|
||||
var benchInput string
|
||||
|
||||
func init() {
|
||||
benchInput = "count: 4\n"
|
||||
for i := 0; i < 1000; i++ {
|
||||
benchInput += "pet: \"fido\"\n"
|
||||
}
|
||||
|
||||
// Check it is valid input.
|
||||
pb := new(MyMessage)
|
||||
err := UnmarshalText(benchInput, pb)
|
||||
if err != nil {
|
||||
panic("Bad benchmark input: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnmarshalText(b *testing.B) {
|
||||
pb := new(MyMessage)
|
||||
for i := 0; i < b.N; i++ {
|
||||
UnmarshalText(benchInput, pb)
|
||||
}
|
||||
b.SetBytes(int64(len(benchInput)))
|
||||
}
|
|
@ -1,474 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package proto_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
|
||||
|
||||
proto3pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto"
|
||||
pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata"
|
||||
)
|
||||
|
||||
// textMessage implements the methods that allow it to marshal and unmarshal
|
||||
// itself as text.
|
||||
type textMessage struct {
|
||||
}
|
||||
|
||||
func (*textMessage) MarshalText() ([]byte, error) {
|
||||
return []byte("custom"), nil
|
||||
}
|
||||
|
||||
func (*textMessage) UnmarshalText(bytes []byte) error {
|
||||
if string(bytes) != "custom" {
|
||||
return errors.New("expected 'custom'")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*textMessage) Reset() {}
|
||||
func (*textMessage) String() string { return "" }
|
||||
func (*textMessage) ProtoMessage() {}
|
||||
|
||||
func newTestMessage() *pb.MyMessage {
|
||||
msg := &pb.MyMessage{
|
||||
Count: proto.Int32(42),
|
||||
Name: proto.String("Dave"),
|
||||
Quote: proto.String(`"I didn't want to go."`),
|
||||
Pet: []string{"bunny", "kitty", "horsey"},
|
||||
Inner: &pb.InnerMessage{
|
||||
Host: proto.String("footrest.syd"),
|
||||
Port: proto.Int32(7001),
|
||||
Connected: proto.Bool(true),
|
||||
},
|
||||
Others: []*pb.OtherMessage{
|
||||
{
|
||||
Key: proto.Int64(0xdeadbeef),
|
||||
Value: []byte{1, 65, 7, 12},
|
||||
},
|
||||
{
|
||||
Weight: proto.Float32(6.022),
|
||||
Inner: &pb.InnerMessage{
|
||||
Host: proto.String("lesha.mtv"),
|
||||
Port: proto.Int32(8002),
|
||||
},
|
||||
},
|
||||
},
|
||||
Bikeshed: pb.MyMessage_BLUE.Enum(),
|
||||
Somegroup: &pb.MyMessage_SomeGroup{
|
||||
GroupField: proto.Int32(8),
|
||||
},
|
||||
// One normally wouldn't do this.
|
||||
// This is an undeclared tag 13, as a varint (wire type 0) with value 4.
|
||||
XXX_unrecognized: []byte{13<<3 | 0, 4},
|
||||
}
|
||||
ext := &pb.Ext{
|
||||
Data: proto.String("Big gobs for big rats"),
|
||||
}
|
||||
if err := proto.SetExtension(msg, pb.E_Ext_More, ext); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
greetings := []string{"adg", "easy", "cow"}
|
||||
if err := proto.SetExtension(msg, pb.E_Greeting, greetings); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Add an unknown extension. We marshal a pb.Ext, and fake the ID.
|
||||
b, err := proto.Marshal(&pb.Ext{Data: proto.String("3G skiing")})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
b = append(proto.EncodeVarint(201<<3|proto.WireBytes), b...)
|
||||
proto.SetRawExtension(msg, 201, b)
|
||||
|
||||
// Extensions can be plain fields, too, so let's test that.
|
||||
b = append(proto.EncodeVarint(202<<3|proto.WireVarint), 19)
|
||||
proto.SetRawExtension(msg, 202, b)
|
||||
|
||||
return msg
|
||||
}
|
||||
|
||||
const text = `count: 42
|
||||
name: "Dave"
|
||||
quote: "\"I didn't want to go.\""
|
||||
pet: "bunny"
|
||||
pet: "kitty"
|
||||
pet: "horsey"
|
||||
inner: <
|
||||
host: "footrest.syd"
|
||||
port: 7001
|
||||
connected: true
|
||||
>
|
||||
others: <
|
||||
key: 3735928559
|
||||
value: "\001A\007\014"
|
||||
>
|
||||
others: <
|
||||
weight: 6.022
|
||||
inner: <
|
||||
host: "lesha.mtv"
|
||||
port: 8002
|
||||
>
|
||||
>
|
||||
bikeshed: BLUE
|
||||
SomeGroup {
|
||||
group_field: 8
|
||||
}
|
||||
/* 2 unknown bytes */
|
||||
13: 4
|
||||
[testdata.Ext.more]: <
|
||||
data: "Big gobs for big rats"
|
||||
>
|
||||
[testdata.greeting]: "adg"
|
||||
[testdata.greeting]: "easy"
|
||||
[testdata.greeting]: "cow"
|
||||
/* 13 unknown bytes */
|
||||
201: "\t3G skiing"
|
||||
/* 3 unknown bytes */
|
||||
202: 19
|
||||
`
|
||||
|
||||
func TestMarshalText(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
if err := proto.MarshalText(buf, newTestMessage()); err != nil {
|
||||
t.Fatalf("proto.MarshalText: %v", err)
|
||||
}
|
||||
s := buf.String()
|
||||
if s != text {
|
||||
t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", s, text)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalTextCustomMessage(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
if err := proto.MarshalText(buf, &textMessage{}); err != nil {
|
||||
t.Fatalf("proto.MarshalText: %v", err)
|
||||
}
|
||||
s := buf.String()
|
||||
if s != "custom" {
|
||||
t.Errorf("Got %q, expected %q", s, "custom")
|
||||
}
|
||||
}
|
||||
func TestMarshalTextNil(t *testing.T) {
|
||||
want := "<nil>"
|
||||
tests := []proto.Message{nil, (*pb.MyMessage)(nil)}
|
||||
for i, test := range tests {
|
||||
buf := new(bytes.Buffer)
|
||||
if err := proto.MarshalText(buf, test); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := buf.String(); got != want {
|
||||
t.Errorf("%d: got %q want %q", i, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalTextUnknownEnum(t *testing.T) {
|
||||
// The Color enum only specifies values 0-2.
|
||||
m := &pb.MyMessage{Bikeshed: pb.MyMessage_Color(3).Enum()}
|
||||
got := m.String()
|
||||
const want = `bikeshed:3 `
|
||||
if got != want {
|
||||
t.Errorf("\n got %q\nwant %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTextOneof(t *testing.T) {
|
||||
tests := []struct {
|
||||
m proto.Message
|
||||
want string
|
||||
}{
|
||||
// zero message
|
||||
{&pb.Communique{}, ``},
|
||||
// scalar field
|
||||
{&pb.Communique{Union: &pb.Communique_Number{4}}, `number:4`},
|
||||
// message field
|
||||
{&pb.Communique{Union: &pb.Communique_Msg{
|
||||
&pb.Strings{StringField: proto.String("why hello!")},
|
||||
}}, `msg:<string_field:"why hello!" >`},
|
||||
// bad oneof (should not panic)
|
||||
{&pb.Communique{Union: &pb.Communique_Msg{nil}}, `msg:/* nil */`},
|
||||
}
|
||||
for _, test := range tests {
|
||||
got := strings.TrimSpace(test.m.String())
|
||||
if got != test.want {
|
||||
t.Errorf("\n got %s\nwant %s", got, test.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarshalTextBuffered(b *testing.B) {
|
||||
buf := new(bytes.Buffer)
|
||||
m := newTestMessage()
|
||||
for i := 0; i < b.N; i++ {
|
||||
buf.Reset()
|
||||
proto.MarshalText(buf, m)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarshalTextUnbuffered(b *testing.B) {
|
||||
w := ioutil.Discard
|
||||
m := newTestMessage()
|
||||
for i := 0; i < b.N; i++ {
|
||||
proto.MarshalText(w, m)
|
||||
}
|
||||
}
|
||||
|
||||
func compact(src string) string {
|
||||
// s/[ \n]+/ /g; s/ $//;
|
||||
dst := make([]byte, len(src))
|
||||
space, comment := false, false
|
||||
j := 0
|
||||
for i := 0; i < len(src); i++ {
|
||||
if strings.HasPrefix(src[i:], "/*") {
|
||||
comment = true
|
||||
i++
|
||||
continue
|
||||
}
|
||||
if comment && strings.HasPrefix(src[i:], "*/") {
|
||||
comment = false
|
||||
i++
|
||||
continue
|
||||
}
|
||||
if comment {
|
||||
continue
|
||||
}
|
||||
c := src[i]
|
||||
if c == ' ' || c == '\n' {
|
||||
space = true
|
||||
continue
|
||||
}
|
||||
if j > 0 && (dst[j-1] == ':' || dst[j-1] == '<' || dst[j-1] == '{') {
|
||||
space = false
|
||||
}
|
||||
if c == '{' {
|
||||
space = false
|
||||
}
|
||||
if space {
|
||||
dst[j] = ' '
|
||||
j++
|
||||
space = false
|
||||
}
|
||||
dst[j] = c
|
||||
j++
|
||||
}
|
||||
if space {
|
||||
dst[j] = ' '
|
||||
j++
|
||||
}
|
||||
return string(dst[0:j])
|
||||
}
|
||||
|
||||
var compactText = compact(text)
|
||||
|
||||
func TestCompactText(t *testing.T) {
|
||||
s := proto.CompactTextString(newTestMessage())
|
||||
if s != compactText {
|
||||
t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v\n===\n", s, compactText)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringEscaping(t *testing.T) {
|
||||
testCases := []struct {
|
||||
in *pb.Strings
|
||||
out string
|
||||
}{
|
||||
{
|
||||
// Test data from C++ test (TextFormatTest.StringEscape).
|
||||
// Single divergence: we don't escape apostrophes.
|
||||
&pb.Strings{StringField: proto.String("\"A string with ' characters \n and \r newlines and \t tabs and \001 slashes \\ and multiple spaces")},
|
||||
"string_field: \"\\\"A string with ' characters \\n and \\r newlines and \\t tabs and \\001 slashes \\\\ and multiple spaces\"\n",
|
||||
},
|
||||
{
|
||||
// Test data from the same C++ test.
|
||||
&pb.Strings{StringField: proto.String("\350\260\267\346\255\214")},
|
||||
"string_field: \"\\350\\260\\267\\346\\255\\214\"\n",
|
||||
},
|
||||
{
|
||||
// Some UTF-8.
|
||||
&pb.Strings{StringField: proto.String("\x00\x01\xff\x81")},
|
||||
`string_field: "\000\001\377\201"` + "\n",
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
var buf bytes.Buffer
|
||||
if err := proto.MarshalText(&buf, tc.in); err != nil {
|
||||
t.Errorf("proto.MarsalText: %v", err)
|
||||
continue
|
||||
}
|
||||
s := buf.String()
|
||||
if s != tc.out {
|
||||
t.Errorf("#%d: Got:\n%s\nExpected:\n%s\n", i, s, tc.out)
|
||||
continue
|
||||
}
|
||||
|
||||
// Check round-trip.
|
||||
pb := new(pb.Strings)
|
||||
if err := proto.UnmarshalText(s, pb); err != nil {
|
||||
t.Errorf("#%d: UnmarshalText: %v", i, err)
|
||||
continue
|
||||
}
|
||||
if !proto.Equal(pb, tc.in) {
|
||||
t.Errorf("#%d: Round-trip failed:\nstart: %v\n end: %v", i, tc.in, pb)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A limitedWriter accepts some output before it fails.
|
||||
// This is a proxy for something like a nearly-full or imminently-failing disk,
|
||||
// or a network connection that is about to die.
|
||||
type limitedWriter struct {
|
||||
b bytes.Buffer
|
||||
limit int
|
||||
}
|
||||
|
||||
var outOfSpace = errors.New("proto: insufficient space")
|
||||
|
||||
func (w *limitedWriter) Write(p []byte) (n int, err error) {
|
||||
var avail = w.limit - w.b.Len()
|
||||
if avail <= 0 {
|
||||
return 0, outOfSpace
|
||||
}
|
||||
if len(p) <= avail {
|
||||
return w.b.Write(p)
|
||||
}
|
||||
n, _ = w.b.Write(p[:avail])
|
||||
return n, outOfSpace
|
||||
}
|
||||
|
||||
func TestMarshalTextFailing(t *testing.T) {
|
||||
// Try lots of different sizes to exercise more error code-paths.
|
||||
for lim := 0; lim < len(text); lim++ {
|
||||
buf := new(limitedWriter)
|
||||
buf.limit = lim
|
||||
err := proto.MarshalText(buf, newTestMessage())
|
||||
// We expect a certain error, but also some partial results in the buffer.
|
||||
if err != outOfSpace {
|
||||
t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", err, outOfSpace)
|
||||
}
|
||||
s := buf.b.String()
|
||||
x := text[:buf.limit]
|
||||
if s != x {
|
||||
t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", s, x)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFloats(t *testing.T) {
|
||||
tests := []struct {
|
||||
f float64
|
||||
want string
|
||||
}{
|
||||
{0, "0"},
|
||||
{4.7, "4.7"},
|
||||
{math.Inf(1), "inf"},
|
||||
{math.Inf(-1), "-inf"},
|
||||
{math.NaN(), "nan"},
|
||||
}
|
||||
for _, test := range tests {
|
||||
msg := &pb.FloatingPoint{F: &test.f}
|
||||
got := strings.TrimSpace(msg.String())
|
||||
want := `f:` + test.want
|
||||
if got != want {
|
||||
t.Errorf("f=%f: got %q, want %q", test.f, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepeatedNilText(t *testing.T) {
|
||||
m := &pb.MessageList{
|
||||
Message: []*pb.MessageList_Message{
|
||||
nil,
|
||||
&pb.MessageList_Message{
|
||||
Name: proto.String("Horse"),
|
||||
},
|
||||
nil,
|
||||
},
|
||||
}
|
||||
want := `Message <nil>
|
||||
Message {
|
||||
name: "Horse"
|
||||
}
|
||||
Message <nil>
|
||||
`
|
||||
if s := proto.MarshalTextString(m); s != want {
|
||||
t.Errorf(" got: %s\nwant: %s", s, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProto3Text(t *testing.T) {
|
||||
tests := []struct {
|
||||
m proto.Message
|
||||
want string
|
||||
}{
|
||||
// zero message
|
||||
{&proto3pb.Message{}, ``},
|
||||
// zero message except for an empty byte slice
|
||||
{&proto3pb.Message{Data: []byte{}}, ``},
|
||||
// trivial case
|
||||
{&proto3pb.Message{Name: "Rob", HeightInCm: 175}, `name:"Rob" height_in_cm:175`},
|
||||
// empty map
|
||||
{&pb.MessageWithMap{}, ``},
|
||||
// non-empty map; map format is the same as a repeated struct,
|
||||
// and they are sorted by key (numerically for numeric keys).
|
||||
{
|
||||
&pb.MessageWithMap{NameMapping: map[int32]string{
|
||||
-1: "Negatory",
|
||||
7: "Lucky",
|
||||
1234: "Feist",
|
||||
6345789: "Otis",
|
||||
}},
|
||||
`name_mapping:<key:-1 value:"Negatory" > ` +
|
||||
`name_mapping:<key:7 value:"Lucky" > ` +
|
||||
`name_mapping:<key:1234 value:"Feist" > ` +
|
||||
`name_mapping:<key:6345789 value:"Otis" >`,
|
||||
},
|
||||
// map with nil value; not well-defined, but we shouldn't crash
|
||||
{
|
||||
&pb.MessageWithMap{MsgMapping: map[int64]*pb.FloatingPoint{7: nil}},
|
||||
`msg_mapping:<key:7 >`,
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
got := strings.TrimSpace(test.m.String())
|
||||
if got != test.want {
|
||||
t.Errorf("\n got %s\nwant %s", got, test.want)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,293 +0,0 @@
|
|||
// Copyright 2014 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package btree
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
seed := time.Now().Unix()
|
||||
fmt.Println(seed)
|
||||
rand.Seed(seed)
|
||||
}
|
||||
|
||||
// perm returns a random permutation of n Int items in the range [0, n).
|
||||
func perm(n int) (out []Item) {
|
||||
for _, v := range rand.Perm(n) {
|
||||
out = append(out, Int(v))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// rang returns an ordered list of Int items in the range [0, n).
|
||||
func rang(n int) (out []Item) {
|
||||
for i := 0; i < n; i++ {
|
||||
out = append(out, Int(i))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// all extracts all items from a tree in order as a slice.
|
||||
func all(t *BTree) (out []Item) {
|
||||
t.Ascend(func(a Item) bool {
|
||||
out = append(out, a)
|
||||
return true
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var btreeDegree = flag.Int("degree", 32, "B-Tree degree")
|
||||
|
||||
func TestBTree(t *testing.T) {
|
||||
tr := New(*btreeDegree)
|
||||
const treeSize = 10000
|
||||
for i := 0; i < 10; i++ {
|
||||
for _, item := range perm(treeSize) {
|
||||
if x := tr.ReplaceOrInsert(item); x != nil {
|
||||
t.Fatal("insert found item", item)
|
||||
}
|
||||
}
|
||||
for _, item := range perm(treeSize) {
|
||||
if x := tr.ReplaceOrInsert(item); x == nil {
|
||||
t.Fatal("insert didn't find item", item)
|
||||
}
|
||||
}
|
||||
got := all(tr)
|
||||
want := rang(treeSize)
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("mismatch:\n got: %v\nwant: %v", got, want)
|
||||
}
|
||||
for _, item := range perm(treeSize) {
|
||||
if x := tr.Delete(item); x == nil {
|
||||
t.Fatalf("didn't find %v", item)
|
||||
}
|
||||
}
|
||||
if got = all(tr); len(got) > 0 {
|
||||
t.Fatalf("some left!: %v", got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleBTree() {
|
||||
tr := New(*btreeDegree)
|
||||
for i := Int(0); i < 10; i++ {
|
||||
tr.ReplaceOrInsert(i)
|
||||
}
|
||||
fmt.Println("len: ", tr.Len())
|
||||
fmt.Println("get3: ", tr.Get(Int(3)))
|
||||
fmt.Println("get100: ", tr.Get(Int(100)))
|
||||
fmt.Println("del4: ", tr.Delete(Int(4)))
|
||||
fmt.Println("del100: ", tr.Delete(Int(100)))
|
||||
fmt.Println("replace5: ", tr.ReplaceOrInsert(Int(5)))
|
||||
fmt.Println("replace100:", tr.ReplaceOrInsert(Int(100)))
|
||||
fmt.Println("delmin: ", tr.DeleteMin())
|
||||
fmt.Println("delmax: ", tr.DeleteMax())
|
||||
fmt.Println("len: ", tr.Len())
|
||||
// Output:
|
||||
// len: 10
|
||||
// get3: 3
|
||||
// get100: <nil>
|
||||
// del4: 4
|
||||
// del100: <nil>
|
||||
// replace5: 5
|
||||
// replace100: <nil>
|
||||
// delmin: 0
|
||||
// delmax: 100
|
||||
// len: 8
|
||||
}
|
||||
|
||||
func TestDeleteMin(t *testing.T) {
|
||||
tr := New(3)
|
||||
for _, v := range perm(100) {
|
||||
tr.ReplaceOrInsert(v)
|
||||
}
|
||||
var got []Item
|
||||
for v := tr.DeleteMin(); v != nil; v = tr.DeleteMin() {
|
||||
got = append(got, v)
|
||||
}
|
||||
if want := rang(100); !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteMax(t *testing.T) {
|
||||
tr := New(3)
|
||||
for _, v := range perm(100) {
|
||||
tr.ReplaceOrInsert(v)
|
||||
}
|
||||
var got []Item
|
||||
for v := tr.DeleteMax(); v != nil; v = tr.DeleteMax() {
|
||||
got = append(got, v)
|
||||
}
|
||||
// Reverse our list.
|
||||
for i := 0; i < len(got)/2; i++ {
|
||||
got[i], got[len(got)-i-1] = got[len(got)-i-1], got[i]
|
||||
}
|
||||
if want := rang(100); !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAscendRange(t *testing.T) {
|
||||
tr := New(2)
|
||||
for _, v := range perm(100) {
|
||||
tr.ReplaceOrInsert(v)
|
||||
}
|
||||
var got []Item
|
||||
tr.AscendRange(Int(40), Int(60), func(a Item) bool {
|
||||
got = append(got, a)
|
||||
return true
|
||||
})
|
||||
if want := rang(100)[40:60]; !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want)
|
||||
}
|
||||
got = got[:0]
|
||||
tr.AscendRange(Int(40), Int(60), func(a Item) bool {
|
||||
if a.(Int) > 50 {
|
||||
return false
|
||||
}
|
||||
got = append(got, a)
|
||||
return true
|
||||
})
|
||||
if want := rang(100)[40:51]; !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAscendLessThan(t *testing.T) {
|
||||
tr := New(*btreeDegree)
|
||||
for _, v := range perm(100) {
|
||||
tr.ReplaceOrInsert(v)
|
||||
}
|
||||
var got []Item
|
||||
tr.AscendLessThan(Int(60), func(a Item) bool {
|
||||
got = append(got, a)
|
||||
return true
|
||||
})
|
||||
if want := rang(100)[:60]; !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want)
|
||||
}
|
||||
got = got[:0]
|
||||
tr.AscendLessThan(Int(60), func(a Item) bool {
|
||||
if a.(Int) > 50 {
|
||||
return false
|
||||
}
|
||||
got = append(got, a)
|
||||
return true
|
||||
})
|
||||
if want := rang(100)[:51]; !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAscendGreaterOrEqual(t *testing.T) {
|
||||
tr := New(*btreeDegree)
|
||||
for _, v := range perm(100) {
|
||||
tr.ReplaceOrInsert(v)
|
||||
}
|
||||
var got []Item
|
||||
tr.AscendGreaterOrEqual(Int(40), func(a Item) bool {
|
||||
got = append(got, a)
|
||||
return true
|
||||
})
|
||||
if want := rang(100)[40:]; !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want)
|
||||
}
|
||||
got = got[:0]
|
||||
tr.AscendGreaterOrEqual(Int(40), func(a Item) bool {
|
||||
if a.(Int) > 50 {
|
||||
return false
|
||||
}
|
||||
got = append(got, a)
|
||||
return true
|
||||
})
|
||||
if want := rang(100)[40:51]; !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
const benchmarkTreeSize = 10000
|
||||
|
||||
func BenchmarkInsert(b *testing.B) {
|
||||
b.StopTimer()
|
||||
insertP := perm(benchmarkTreeSize)
|
||||
b.StartTimer()
|
||||
i := 0
|
||||
for i < b.N {
|
||||
tr := New(*btreeDegree)
|
||||
for _, item := range insertP {
|
||||
tr.ReplaceOrInsert(item)
|
||||
i++
|
||||
if i >= b.N {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkDelete(b *testing.B) {
|
||||
b.StopTimer()
|
||||
insertP := perm(benchmarkTreeSize)
|
||||
removeP := perm(benchmarkTreeSize)
|
||||
b.StartTimer()
|
||||
i := 0
|
||||
for i < b.N {
|
||||
b.StopTimer()
|
||||
tr := New(*btreeDegree)
|
||||
for _, v := range insertP {
|
||||
tr.ReplaceOrInsert(v)
|
||||
}
|
||||
b.StartTimer()
|
||||
for _, item := range removeP {
|
||||
tr.Delete(item)
|
||||
i++
|
||||
if i >= b.N {
|
||||
return
|
||||
}
|
||||
}
|
||||
if tr.Len() > 0 {
|
||||
panic(tr.Len())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkGet(b *testing.B) {
|
||||
b.StopTimer()
|
||||
insertP := perm(benchmarkTreeSize)
|
||||
removeP := perm(benchmarkTreeSize)
|
||||
b.StartTimer()
|
||||
i := 0
|
||||
for i < b.N {
|
||||
b.StopTimer()
|
||||
tr := New(*btreeDegree)
|
||||
for _, v := range insertP {
|
||||
tr.ReplaceOrInsert(v)
|
||||
}
|
||||
b.StartTimer()
|
||||
for _, item := range removeP {
|
||||
tr.Get(item)
|
||||
i++
|
||||
if i >= b.N {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,106 +0,0 @@
|
|||
package clockwork
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestFakeClockAfter(t *testing.T) {
|
||||
fc := &fakeClock{}
|
||||
|
||||
zero := fc.After(0)
|
||||
select {
|
||||
case <-zero:
|
||||
default:
|
||||
t.Errorf("zero did not return!")
|
||||
}
|
||||
one := fc.After(1)
|
||||
two := fc.After(2)
|
||||
six := fc.After(6)
|
||||
ten := fc.After(10)
|
||||
fc.Advance(1)
|
||||
select {
|
||||
case <-one:
|
||||
default:
|
||||
t.Errorf("one did not return!")
|
||||
}
|
||||
select {
|
||||
case <-two:
|
||||
t.Errorf("two returned prematurely!")
|
||||
case <-six:
|
||||
t.Errorf("six returned prematurely!")
|
||||
case <-ten:
|
||||
t.Errorf("ten returned prematurely!")
|
||||
default:
|
||||
}
|
||||
fc.Advance(1)
|
||||
select {
|
||||
case <-two:
|
||||
default:
|
||||
t.Errorf("two did not return!")
|
||||
}
|
||||
select {
|
||||
case <-six:
|
||||
t.Errorf("six returned prematurely!")
|
||||
case <-ten:
|
||||
t.Errorf("ten returned prematurely!")
|
||||
default:
|
||||
}
|
||||
fc.Advance(1)
|
||||
select {
|
||||
case <-six:
|
||||
t.Errorf("six returned prematurely!")
|
||||
case <-ten:
|
||||
t.Errorf("ten returned prematurely!")
|
||||
default:
|
||||
}
|
||||
fc.Advance(3)
|
||||
select {
|
||||
case <-six:
|
||||
default:
|
||||
t.Errorf("six did not return!")
|
||||
}
|
||||
select {
|
||||
case <-ten:
|
||||
t.Errorf("ten returned prematurely!")
|
||||
default:
|
||||
}
|
||||
fc.Advance(100)
|
||||
select {
|
||||
case <-ten:
|
||||
default:
|
||||
t.Errorf("ten did not return!")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNotifyBlockers(t *testing.T) {
|
||||
b1 := &blocker{1, make(chan struct{})}
|
||||
b2 := &blocker{2, make(chan struct{})}
|
||||
b3 := &blocker{5, make(chan struct{})}
|
||||
b4 := &blocker{10, make(chan struct{})}
|
||||
b5 := &blocker{10, make(chan struct{})}
|
||||
bs := []*blocker{b1, b2, b3, b4, b5}
|
||||
bs1 := notifyBlockers(bs, 2)
|
||||
if n := len(bs1); n != 4 {
|
||||
t.Fatalf("got %d blockers, want %d", n, 4)
|
||||
}
|
||||
select {
|
||||
case <-b2.ch:
|
||||
case <-time.After(time.Second):
|
||||
t.Fatalf("timed out waiting for channel close!")
|
||||
}
|
||||
bs2 := notifyBlockers(bs1, 10)
|
||||
if n := len(bs2); n != 2 {
|
||||
t.Fatalf("got %d blockers, want %d", n, 2)
|
||||
}
|
||||
select {
|
||||
case <-b4.ch:
|
||||
case <-time.After(time.Second):
|
||||
t.Fatalf("timed out waiting for channel close!")
|
||||
}
|
||||
select {
|
||||
case <-b5.ch:
|
||||
case <-time.After(time.Second):
|
||||
t.Fatalf("timed out waiting for channel close!")
|
||||
}
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
package clockwork
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// my_func is an example of a time-dependent function, using an
|
||||
// injected clock
|
||||
func my_func(clock Clock, i *int) {
|
||||
clock.Sleep(3 * time.Second)
|
||||
*i += 1
|
||||
}
|
||||
|
||||
// assert_state is an example of a state assertion in a test
|
||||
func assert_state(t *testing.T, i, j int) {
|
||||
if i != j {
|
||||
t.Fatalf("i %d, j %d", i, j)
|
||||
}
|
||||
}
|
||||
|
||||
// TestMyFunc tests my_func's behaviour with a FakeClock
|
||||
func TestMyFunc(t *testing.T) {
|
||||
var i int
|
||||
c := NewFakeClock()
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
my_func(c, &i)
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
// Wait until my_func is actually sleeping on the clock
|
||||
c.BlockUntil(1)
|
||||
|
||||
// Assert the initial state
|
||||
assert_state(t, i, 0)
|
||||
|
||||
// Now advance the clock forward in time
|
||||
c.Advance(1 * time.Hour)
|
||||
|
||||
// Wait until the function completes
|
||||
wg.Wait()
|
||||
|
||||
// Assert the final state
|
||||
assert_state(t, i, 1)
|
||||
}
|
320
Godeps/_workspace/src/github.com/matttproud/golang_protobuf_extensions/pbutil/all_test.go
generated
vendored
320
Godeps/_workspace/src/github.com/matttproud/golang_protobuf_extensions/pbutil/all_test.go
generated
vendored
|
@ -1,320 +0,0 @@
|
|||
// Copyright 2013 Matt T. Proud
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package pbutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"testing"
|
||||
"testing/quick"
|
||||
|
||||
"github.com/matttproud/golang_protobuf_extensions/pbtest"
|
||||
|
||||
. "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
|
||||
. "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata"
|
||||
)
|
||||
|
||||
func TestWriteDelimited(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
msg Message
|
||||
buf []byte
|
||||
n int
|
||||
err error
|
||||
}{
|
||||
{
|
||||
msg: &Empty{},
|
||||
n: 1,
|
||||
buf: []byte{0},
|
||||
},
|
||||
{
|
||||
msg: &GoEnum{Foo: FOO_FOO1.Enum()},
|
||||
n: 3,
|
||||
buf: []byte{2, 8, 1},
|
||||
},
|
||||
{
|
||||
msg: &Strings{
|
||||
StringField: String(`This is my gigantic, unhappy string. It exceeds
|
||||
the encoding size of a single byte varint. We are using it to fuzz test the
|
||||
correctness of the header decoding mechanisms, which may prove problematic.
|
||||
I expect it may. Let's hope you enjoy testing as much as we do.`),
|
||||
},
|
||||
n: 271,
|
||||
buf: []byte{141, 2, 10, 138, 2, 84, 104, 105, 115, 32, 105, 115, 32, 109,
|
||||
121, 32, 103, 105, 103, 97, 110, 116, 105, 99, 44, 32, 117, 110, 104,
|
||||
97, 112, 112, 121, 32, 115, 116, 114, 105, 110, 103, 46, 32, 32, 73,
|
||||
116, 32, 101, 120, 99, 101, 101, 100, 115, 10, 116, 104, 101, 32, 101,
|
||||
110, 99, 111, 100, 105, 110, 103, 32, 115, 105, 122, 101, 32, 111, 102,
|
||||
32, 97, 32, 115, 105, 110, 103, 108, 101, 32, 98, 121, 116, 101, 32,
|
||||
118, 97, 114, 105, 110, 116, 46, 32, 32, 87, 101, 32, 97, 114, 101, 32,
|
||||
117, 115, 105, 110, 103, 32, 105, 116, 32, 116, 111, 32, 102, 117, 122,
|
||||
122, 32, 116, 101, 115, 116, 32, 116, 104, 101, 10, 99, 111, 114, 114,
|
||||
101, 99, 116, 110, 101, 115, 115, 32, 111, 102, 32, 116, 104, 101, 32,
|
||||
104, 101, 97, 100, 101, 114, 32, 100, 101, 99, 111, 100, 105, 110, 103,
|
||||
32, 109, 101, 99, 104, 97, 110, 105, 115, 109, 115, 44, 32, 119, 104,
|
||||
105, 99, 104, 32, 109, 97, 121, 32, 112, 114, 111, 118, 101, 32, 112,
|
||||
114, 111, 98, 108, 101, 109, 97, 116, 105, 99, 46, 10, 73, 32, 101, 120,
|
||||
112, 101, 99, 116, 32, 105, 116, 32, 109, 97, 121, 46, 32, 32, 76, 101,
|
||||
116, 39, 115, 32, 104, 111, 112, 101, 32, 121, 111, 117, 32, 101, 110,
|
||||
106, 111, 121, 32, 116, 101, 115, 116, 105, 110, 103, 32, 97, 115, 32,
|
||||
109, 117, 99, 104, 32, 97, 115, 32, 119, 101, 32, 100, 111, 46},
|
||||
},
|
||||
} {
|
||||
var buf bytes.Buffer
|
||||
if n, err := WriteDelimited(&buf, test.msg); n != test.n || err != test.err {
|
||||
t.Fatalf("WriteDelimited(buf, %#v) = %v, %v; want %v, %v", test.msg, n, err, test.n, test.err)
|
||||
}
|
||||
if out := buf.Bytes(); !bytes.Equal(out, test.buf) {
|
||||
t.Fatalf("WriteDelimited(buf, %#v); buf = %v; want %v", test.msg, out, test.buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadDelimited(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
buf []byte
|
||||
msg Message
|
||||
n int
|
||||
err error
|
||||
}{
|
||||
{
|
||||
buf: []byte{0},
|
||||
msg: &Empty{},
|
||||
n: 1,
|
||||
},
|
||||
{
|
||||
n: 3,
|
||||
buf: []byte{2, 8, 1},
|
||||
msg: &GoEnum{Foo: FOO_FOO1.Enum()},
|
||||
},
|
||||
{
|
||||
buf: []byte{141, 2, 10, 138, 2, 84, 104, 105, 115, 32, 105, 115, 32, 109,
|
||||
121, 32, 103, 105, 103, 97, 110, 116, 105, 99, 44, 32, 117, 110, 104,
|
||||
97, 112, 112, 121, 32, 115, 116, 114, 105, 110, 103, 46, 32, 32, 73,
|
||||
116, 32, 101, 120, 99, 101, 101, 100, 115, 10, 116, 104, 101, 32, 101,
|
||||
110, 99, 111, 100, 105, 110, 103, 32, 115, 105, 122, 101, 32, 111, 102,
|
||||
32, 97, 32, 115, 105, 110, 103, 108, 101, 32, 98, 121, 116, 101, 32,
|
||||
118, 97, 114, 105, 110, 116, 46, 32, 32, 87, 101, 32, 97, 114, 101, 32,
|
||||
117, 115, 105, 110, 103, 32, 105, 116, 32, 116, 111, 32, 102, 117, 122,
|
||||
122, 32, 116, 101, 115, 116, 32, 116, 104, 101, 10, 99, 111, 114, 114,
|
||||
101, 99, 116, 110, 101, 115, 115, 32, 111, 102, 32, 116, 104, 101, 32,
|
||||
104, 101, 97, 100, 101, 114, 32, 100, 101, 99, 111, 100, 105, 110, 103,
|
||||
32, 109, 101, 99, 104, 97, 110, 105, 115, 109, 115, 44, 32, 119, 104,
|
||||
105, 99, 104, 32, 109, 97, 121, 32, 112, 114, 111, 118, 101, 32, 112,
|
||||
114, 111, 98, 108, 101, 109, 97, 116, 105, 99, 46, 10, 73, 32, 101, 120,
|
||||
112, 101, 99, 116, 32, 105, 116, 32, 109, 97, 121, 46, 32, 32, 76, 101,
|
||||
116, 39, 115, 32, 104, 111, 112, 101, 32, 121, 111, 117, 32, 101, 110,
|
||||
106, 111, 121, 32, 116, 101, 115, 116, 105, 110, 103, 32, 97, 115, 32,
|
||||
109, 117, 99, 104, 32, 97, 115, 32, 119, 101, 32, 100, 111, 46},
|
||||
msg: &Strings{
|
||||
StringField: String(`This is my gigantic, unhappy string. It exceeds
|
||||
the encoding size of a single byte varint. We are using it to fuzz test the
|
||||
correctness of the header decoding mechanisms, which may prove problematic.
|
||||
I expect it may. Let's hope you enjoy testing as much as we do.`),
|
||||
},
|
||||
n: 271,
|
||||
},
|
||||
} {
|
||||
msg := Clone(test.msg)
|
||||
msg.Reset()
|
||||
if n, err := ReadDelimited(bytes.NewBuffer(test.buf), msg); n != test.n || err != test.err {
|
||||
t.Fatalf("ReadDelimited(%v, msg) = %v, %v; want %v, %v", test.buf, n, err, test.n, test.err)
|
||||
}
|
||||
if !Equal(msg, test.msg) {
|
||||
t.Fatalf("ReadDelimited(%v, msg); msg = %v; want %v", test.buf, msg, test.msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEndToEndValid(t *testing.T) {
|
||||
for _, test := range [][]Message{
|
||||
{&Empty{}},
|
||||
{&GoEnum{Foo: FOO_FOO1.Enum()}, &Empty{}, &GoEnum{Foo: FOO_FOO1.Enum()}},
|
||||
{&GoEnum{Foo: FOO_FOO1.Enum()}},
|
||||
{&Strings{
|
||||
StringField: String(`This is my gigantic, unhappy string. It exceeds
|
||||
the encoding size of a single byte varint. We are using it to fuzz test the
|
||||
correctness of the header decoding mechanisms, which may prove problematic.
|
||||
I expect it may. Let's hope you enjoy testing as much as we do.`),
|
||||
}},
|
||||
} {
|
||||
var buf bytes.Buffer
|
||||
var written int
|
||||
for i, msg := range test {
|
||||
n, err := WriteDelimited(&buf, msg)
|
||||
if err != nil {
|
||||
// Assumption: TestReadDelimited and TestWriteDelimited are sufficient
|
||||
// and inputs for this test are explicitly exercised there.
|
||||
t.Fatalf("WriteDelimited(buf, %v[%d]) = ?, %v; wanted ?, nil", test, i, err)
|
||||
}
|
||||
written += n
|
||||
}
|
||||
var read int
|
||||
for i, msg := range test {
|
||||
out := Clone(msg)
|
||||
out.Reset()
|
||||
n, _ := ReadDelimited(&buf, out)
|
||||
// Decide to do EOF checking?
|
||||
read += n
|
||||
if !Equal(out, msg) {
|
||||
t.Fatalf("out = %v; want %v[%d] = %#v", out, test, i, msg)
|
||||
}
|
||||
}
|
||||
if read != written {
|
||||
t.Fatalf("%v read = %d; want %d", test, read, written)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rndMessage generates a random valid Protocol Buffer message.
|
||||
func rndMessage(r *rand.Rand) Message {
|
||||
var t reflect.Type
|
||||
switch v := rand.Intn(23); v {
|
||||
// TODO(br): Uncomment the elements below once fix is incorporated, except
|
||||
// for the elements marked as patently incompatible.
|
||||
// case 0:
|
||||
// t = reflect.TypeOf(&GoEnum{})
|
||||
// break
|
||||
// case 1:
|
||||
// t = reflect.TypeOf(&GoTestField{})
|
||||
// break
|
||||
case 2:
|
||||
t = reflect.TypeOf(&GoTest{})
|
||||
break
|
||||
// case 3:
|
||||
// t = reflect.TypeOf(&GoSkipTest{})
|
||||
// break
|
||||
// case 4:
|
||||
// t = reflect.TypeOf(&NonPackedTest{})
|
||||
// break
|
||||
// case 5:
|
||||
// t = reflect.TypeOf(&PackedTest{})
|
||||
// break
|
||||
case 6:
|
||||
t = reflect.TypeOf(&MaxTag{})
|
||||
break
|
||||
case 7:
|
||||
t = reflect.TypeOf(&OldMessage{})
|
||||
break
|
||||
case 8:
|
||||
t = reflect.TypeOf(&NewMessage{})
|
||||
break
|
||||
case 9:
|
||||
t = reflect.TypeOf(&InnerMessage{})
|
||||
break
|
||||
case 10:
|
||||
t = reflect.TypeOf(&OtherMessage{})
|
||||
break
|
||||
case 11:
|
||||
// PATENTLY INVALID FOR FUZZ GENERATION
|
||||
// t = reflect.TypeOf(&MyMessage{})
|
||||
break
|
||||
// case 12:
|
||||
// t = reflect.TypeOf(&Ext{})
|
||||
// break
|
||||
case 13:
|
||||
// PATENTLY INVALID FOR FUZZ GENERATION
|
||||
// t = reflect.TypeOf(&MyMessageSet{})
|
||||
break
|
||||
// case 14:
|
||||
// t = reflect.TypeOf(&Empty{})
|
||||
// break
|
||||
// case 15:
|
||||
// t = reflect.TypeOf(&MessageList{})
|
||||
// break
|
||||
// case 16:
|
||||
// t = reflect.TypeOf(&Strings{})
|
||||
// break
|
||||
// case 17:
|
||||
// t = reflect.TypeOf(&Defaults{})
|
||||
// break
|
||||
// case 17:
|
||||
// t = reflect.TypeOf(&SubDefaults{})
|
||||
// break
|
||||
// case 18:
|
||||
// t = reflect.TypeOf(&RepeatedEnum{})
|
||||
// break
|
||||
case 19:
|
||||
t = reflect.TypeOf(&MoreRepeated{})
|
||||
break
|
||||
// case 20:
|
||||
// t = reflect.TypeOf(&GroupOld{})
|
||||
// break
|
||||
// case 21:
|
||||
// t = reflect.TypeOf(&GroupNew{})
|
||||
// break
|
||||
case 22:
|
||||
t = reflect.TypeOf(&FloatingPoint{})
|
||||
break
|
||||
default:
|
||||
// TODO(br): Replace with an unreachable once fixed.
|
||||
t = reflect.TypeOf(&GoTest{})
|
||||
break
|
||||
}
|
||||
if t == nil {
|
||||
t = reflect.TypeOf(&GoTest{})
|
||||
}
|
||||
v, ok := quick.Value(t, r)
|
||||
if !ok {
|
||||
panic("attempt to generate illegal item; consult item 11")
|
||||
}
|
||||
if err := pbtest.SanitizeGenerated(v.Interface().(Message)); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v.Interface().(Message)
|
||||
}
|
||||
|
||||
// rndMessages generates several random Protocol Buffer messages.
|
||||
func rndMessages(r *rand.Rand) []Message {
|
||||
n := r.Intn(128)
|
||||
out := make([]Message, 0, n)
|
||||
for i := 0; i < n; i++ {
|
||||
out = append(out, rndMessage(r))
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func TestFuzz(t *testing.T) {
|
||||
rnd := rand.New(rand.NewSource(42))
|
||||
check := func() bool {
|
||||
messages := rndMessages(rnd)
|
||||
var buf bytes.Buffer
|
||||
var written int
|
||||
for i, msg := range messages {
|
||||
n, err := WriteDelimited(&buf, msg)
|
||||
if err != nil {
|
||||
t.Fatalf("WriteDelimited(buf, %v[%d]) = ?, %v; wanted ?, nil", messages, i, err)
|
||||
}
|
||||
written += n
|
||||
}
|
||||
var read int
|
||||
for i, msg := range messages {
|
||||
out := Clone(msg)
|
||||
out.Reset()
|
||||
n, _ := ReadDelimited(&buf, out)
|
||||
read += n
|
||||
if !Equal(out, msg) {
|
||||
t.Fatalf("out = %v; want %v[%d] = %#v", out, messages, i, msg)
|
||||
}
|
||||
}
|
||||
if read != written {
|
||||
t.Fatalf("%v read = %d; want %d", messages, read, written)
|
||||
}
|
||||
return true
|
||||
}
|
||||
if err := quick.Check(check, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
|
@ -1,103 +0,0 @@
|
|||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// http://github.com/golang/protobuf/
|
||||
//
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package pbutil
|
||||
|
||||
import (
|
||||
. "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
|
||||
. "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata"
|
||||
)
|
||||
|
||||
// FROM https://github.com/golang/protobuf/blob/master/proto/all_test.go.
|
||||
|
||||
func initGoTestField() *GoTestField {
|
||||
f := new(GoTestField)
|
||||
f.Label = String("label")
|
||||
f.Type = String("type")
|
||||
return f
|
||||
}
|
||||
|
||||
// These are all structurally equivalent but the tag numbers differ.
|
||||
// (It's remarkable that required, optional, and repeated all have
|
||||
// 8 letters.)
|
||||
func initGoTest_RequiredGroup() *GoTest_RequiredGroup {
|
||||
return &GoTest_RequiredGroup{
|
||||
RequiredField: String("required"),
|
||||
}
|
||||
}
|
||||
|
||||
func initGoTest_OptionalGroup() *GoTest_OptionalGroup {
|
||||
return &GoTest_OptionalGroup{
|
||||
RequiredField: String("optional"),
|
||||
}
|
||||
}
|
||||
|
||||
func initGoTest_RepeatedGroup() *GoTest_RepeatedGroup {
|
||||
return &GoTest_RepeatedGroup{
|
||||
RequiredField: String("repeated"),
|
||||
}
|
||||
}
|
||||
|
||||
func initGoTest(setdefaults bool) *GoTest {
|
||||
pb := new(GoTest)
|
||||
if setdefaults {
|
||||
pb.F_BoolDefaulted = Bool(Default_GoTest_F_BoolDefaulted)
|
||||
pb.F_Int32Defaulted = Int32(Default_GoTest_F_Int32Defaulted)
|
||||
pb.F_Int64Defaulted = Int64(Default_GoTest_F_Int64Defaulted)
|
||||
pb.F_Fixed32Defaulted = Uint32(Default_GoTest_F_Fixed32Defaulted)
|
||||
pb.F_Fixed64Defaulted = Uint64(Default_GoTest_F_Fixed64Defaulted)
|
||||
pb.F_Uint32Defaulted = Uint32(Default_GoTest_F_Uint32Defaulted)
|
||||
pb.F_Uint64Defaulted = Uint64(Default_GoTest_F_Uint64Defaulted)
|
||||
pb.F_FloatDefaulted = Float32(Default_GoTest_F_FloatDefaulted)
|
||||
pb.F_DoubleDefaulted = Float64(Default_GoTest_F_DoubleDefaulted)
|
||||
pb.F_StringDefaulted = String(Default_GoTest_F_StringDefaulted)
|
||||
pb.F_BytesDefaulted = Default_GoTest_F_BytesDefaulted
|
||||
pb.F_Sint32Defaulted = Int32(Default_GoTest_F_Sint32Defaulted)
|
||||
pb.F_Sint64Defaulted = Int64(Default_GoTest_F_Sint64Defaulted)
|
||||
}
|
||||
|
||||
pb.Kind = GoTest_TIME.Enum()
|
||||
pb.RequiredField = initGoTestField()
|
||||
pb.F_BoolRequired = Bool(true)
|
||||
pb.F_Int32Required = Int32(3)
|
||||
pb.F_Int64Required = Int64(6)
|
||||
pb.F_Fixed32Required = Uint32(32)
|
||||
pb.F_Fixed64Required = Uint64(64)
|
||||
pb.F_Uint32Required = Uint32(3232)
|
||||
pb.F_Uint64Required = Uint64(6464)
|
||||
pb.F_FloatRequired = Float32(3232)
|
||||
pb.F_DoubleRequired = Float64(6464)
|
||||
pb.F_StringRequired = String("string")
|
||||
pb.F_BytesRequired = []byte("bytes")
|
||||
pb.F_Sint32Required = Int32(-32)
|
||||
pb.F_Sint64Required = Int64(-64)
|
||||
pb.Requiredgroup = initGoTest_RequiredGroup()
|
||||
|
||||
return pb
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
ASCII Table Writer Tool
|
||||
=========
|
||||
|
||||
Generate ASCII table on the fly via command line ... Installation is simple as
|
||||
|
||||
#### Get Tool
|
||||
|
||||
go get github.com/olekukonko/tablewriter/csv2table
|
||||
|
||||
#### Install Tool
|
||||
|
||||
go install github.com/olekukonko/tablewriter/csv2table
|
||||
|
||||
|
||||
#### Usage
|
||||
|
||||
csv2table -f test.csv
|
||||
|
||||
#### Support for Piping
|
||||
|
||||
cat test.csv | csv2table -p=true
|
||||
|
||||
#### Output
|
||||
|
||||
```
|
||||
+------------+-----------+---------+
|
||||
| FIRST NAME | LAST NAME | SSN |
|
||||
+------------+-----------+---------+
|
||||
| John | Barry | 123456 |
|
||||
| Kathy | Smith | 687987 |
|
||||
| Bob | McCornick | 3979870 |
|
||||
+------------+-----------+---------+
|
||||
```
|
||||
|
||||
#### Another Piping with Header set to `false`
|
||||
|
||||
echo dance,with,me | csv2table -p=true -h=false
|
||||
|
||||
#### Output
|
||||
|
||||
+-------+------+-----+
|
||||
| dance | with | me |
|
||||
+-------+------+-----+
|
84
Godeps/_workspace/src/github.com/olekukonko/tablewriter/csv2table/csv2table.go
generated
vendored
84
Godeps/_workspace/src/github.com/olekukonko/tablewriter/csv2table/csv2table.go
generated
vendored
|
@ -1,84 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/csv"
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/olekukonko/tablewriter"
|
||||
"io"
|
||||
"os"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
var (
|
||||
fileName = flag.String("f", "", "Set file with eg. sample.csv")
|
||||
delimiter = flag.String("d", ",", "Set CSV File delimiter eg. ,|;|\t ")
|
||||
header = flag.Bool("h", true, "Set header options eg. true|false ")
|
||||
align = flag.String("a", "none", "Set aligmement with eg. none|left|right|centre")
|
||||
pipe = flag.Bool("p", false, "Suport for Piping from STDIN")
|
||||
border = flag.Bool("b", true, "Enable / disable table border")
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
fmt.Println()
|
||||
if *pipe || hasArg("-p") {
|
||||
process(os.Stdin)
|
||||
} else {
|
||||
if *fileName == "" {
|
||||
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
|
||||
flag.PrintDefaults()
|
||||
fmt.Println()
|
||||
os.Exit(1)
|
||||
}
|
||||
processFile()
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func hasArg(name string) bool {
|
||||
for _, v := range os.Args {
|
||||
if name == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
func processFile() {
|
||||
r, err := os.Open(*fileName)
|
||||
if err != nil {
|
||||
exit(err)
|
||||
}
|
||||
defer r.Close()
|
||||
process(r)
|
||||
}
|
||||
func process(r io.Reader) {
|
||||
csvReader := csv.NewReader(r)
|
||||
rune, size := utf8.DecodeRuneInString(*delimiter)
|
||||
if size == 0 {
|
||||
rune = ','
|
||||
}
|
||||
csvReader.Comma = rune
|
||||
|
||||
table, err := tablewriter.NewCSVReader(os.Stdout, csvReader, *header)
|
||||
|
||||
if err != nil {
|
||||
exit(err)
|
||||
}
|
||||
|
||||
switch *align {
|
||||
case "left":
|
||||
table.SetAlignment(tablewriter.ALIGN_LEFT)
|
||||
case "right":
|
||||
table.SetAlignment(tablewriter.ALIGN_RIGHT)
|
||||
case "center":
|
||||
table.SetAlignment(tablewriter.ALIGN_CENTRE)
|
||||
}
|
||||
table.SetBorder(*border)
|
||||
table.Render()
|
||||
}
|
||||
|
||||
func exit(err error) {
|
||||
fmt.Fprintf(os.Stderr, "#Error : %s", err)
|
||||
os.Exit(1)
|
||||
}
|
159
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/benchmark_test.go
generated
vendored
159
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/benchmark_test.go
generated
vendored
|
@ -1,159 +0,0 @@
|
|||
// Copyright 2014 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkCounterWithLabelValues(b *testing.B) {
|
||||
m := NewCounterVec(
|
||||
CounterOpts{
|
||||
Name: "benchmark_counter",
|
||||
Help: "A counter to benchmark it.",
|
||||
},
|
||||
[]string{"one", "two", "three"},
|
||||
)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
m.WithLabelValues("eins", "zwei", "drei").Inc()
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCounterWithMappedLabels(b *testing.B) {
|
||||
m := NewCounterVec(
|
||||
CounterOpts{
|
||||
Name: "benchmark_counter",
|
||||
Help: "A counter to benchmark it.",
|
||||
},
|
||||
[]string{"one", "two", "three"},
|
||||
)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
m.With(Labels{"two": "zwei", "one": "eins", "three": "drei"}).Inc()
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCounterWithPreparedMappedLabels(b *testing.B) {
|
||||
m := NewCounterVec(
|
||||
CounterOpts{
|
||||
Name: "benchmark_counter",
|
||||
Help: "A counter to benchmark it.",
|
||||
},
|
||||
[]string{"one", "two", "three"},
|
||||
)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
labels := Labels{"two": "zwei", "one": "eins", "three": "drei"}
|
||||
for i := 0; i < b.N; i++ {
|
||||
m.With(labels).Inc()
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCounterNoLabels(b *testing.B) {
|
||||
m := NewCounter(CounterOpts{
|
||||
Name: "benchmark_counter",
|
||||
Help: "A counter to benchmark it.",
|
||||
})
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
m.Inc()
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkGaugeWithLabelValues(b *testing.B) {
|
||||
m := NewGaugeVec(
|
||||
GaugeOpts{
|
||||
Name: "benchmark_gauge",
|
||||
Help: "A gauge to benchmark it.",
|
||||
},
|
||||
[]string{"one", "two", "three"},
|
||||
)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
m.WithLabelValues("eins", "zwei", "drei").Set(3.1415)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkGaugeNoLabels(b *testing.B) {
|
||||
m := NewGauge(GaugeOpts{
|
||||
Name: "benchmark_gauge",
|
||||
Help: "A gauge to benchmark it.",
|
||||
})
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
m.Set(3.1415)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSummaryWithLabelValues(b *testing.B) {
|
||||
m := NewSummaryVec(
|
||||
SummaryOpts{
|
||||
Name: "benchmark_summary",
|
||||
Help: "A summary to benchmark it.",
|
||||
},
|
||||
[]string{"one", "two", "three"},
|
||||
)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
m.WithLabelValues("eins", "zwei", "drei").Observe(3.1415)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSummaryNoLabels(b *testing.B) {
|
||||
m := NewSummary(SummaryOpts{
|
||||
Name: "benchmark_summary",
|
||||
Help: "A summary to benchmark it.",
|
||||
},
|
||||
)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
m.Observe(3.1415)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkHistogramWithLabelValues(b *testing.B) {
|
||||
m := NewHistogramVec(
|
||||
HistogramOpts{
|
||||
Name: "benchmark_histogram",
|
||||
Help: "A histogram to benchmark it.",
|
||||
},
|
||||
[]string{"one", "two", "three"},
|
||||
)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
m.WithLabelValues("eins", "zwei", "drei").Observe(3.1415)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkHistogramNoLabels(b *testing.B) {
|
||||
m := NewHistogram(HistogramOpts{
|
||||
Name: "benchmark_histogram",
|
||||
Help: "A histogram to benchmark it.",
|
||||
},
|
||||
)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
m.Observe(3.1415)
|
||||
}
|
||||
}
|
58
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/counter_test.go
generated
vendored
58
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/counter_test.go
generated
vendored
|
@ -1,58 +0,0 @@
|
|||
// Copyright 2014 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
|
||||
)
|
||||
|
||||
func TestCounterAdd(t *testing.T) {
|
||||
counter := NewCounter(CounterOpts{
|
||||
Name: "test",
|
||||
Help: "test help",
|
||||
ConstLabels: Labels{"a": "1", "b": "2"},
|
||||
}).(*counter)
|
||||
counter.Inc()
|
||||
if expected, got := 1., math.Float64frombits(counter.valBits); expected != got {
|
||||
t.Errorf("Expected %f, got %f.", expected, got)
|
||||
}
|
||||
counter.Add(42)
|
||||
if expected, got := 43., math.Float64frombits(counter.valBits); expected != got {
|
||||
t.Errorf("Expected %f, got %f.", expected, got)
|
||||
}
|
||||
|
||||
if expected, got := "counter cannot decrease in value", decreaseCounter(counter).Error(); expected != got {
|
||||
t.Errorf("Expected error %q, got %q.", expected, got)
|
||||
}
|
||||
|
||||
m := &dto.Metric{}
|
||||
counter.Write(m)
|
||||
|
||||
if expected, got := `label:<name:"a" value:"1" > label:<name:"b" value:"2" > counter:<value:43 > `, m.String(); expected != got {
|
||||
t.Errorf("expected %q, got %q", expected, got)
|
||||
}
|
||||
}
|
||||
|
||||
func decreaseCounter(c *counter) (err error) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
err = e.(error)
|
||||
}
|
||||
}()
|
||||
c.Add(-1)
|
||||
return nil
|
||||
}
|
|
@ -1,130 +0,0 @@
|
|||
// Copyright 2014 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package prometheus_test
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
// ClusterManager is an example for a system that might have been built without
|
||||
// Prometheus in mind. It models a central manager of jobs running in a
|
||||
// cluster. To turn it into something that collects Prometheus metrics, we
|
||||
// simply add the two methods required for the Collector interface.
|
||||
//
|
||||
// An additional challenge is that multiple instances of the ClusterManager are
|
||||
// run within the same binary, each in charge of a different zone. We need to
|
||||
// make use of ConstLabels to be able to register each ClusterManager instance
|
||||
// with Prometheus.
|
||||
type ClusterManager struct {
|
||||
Zone string
|
||||
OOMCount *prometheus.CounterVec
|
||||
RAMUsage *prometheus.GaugeVec
|
||||
mtx sync.Mutex // Protects OOMCount and RAMUsage.
|
||||
// ... many more fields
|
||||
}
|
||||
|
||||
// ReallyExpensiveAssessmentOfTheSystemState is a mock for the data gathering a
|
||||
// real cluster manager would have to do. Since it may actually be really
|
||||
// expensive, it must only be called once per collection. This implementation,
|
||||
// obviously, only returns some made-up data.
|
||||
func (c *ClusterManager) ReallyExpensiveAssessmentOfTheSystemState() (
|
||||
oomCountByHost map[string]int, ramUsageByHost map[string]float64,
|
||||
) {
|
||||
// Just example fake data.
|
||||
oomCountByHost = map[string]int{
|
||||
"foo.example.org": 42,
|
||||
"bar.example.org": 2001,
|
||||
}
|
||||
ramUsageByHost = map[string]float64{
|
||||
"foo.example.org": 6.023e23,
|
||||
"bar.example.org": 3.14,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Describe faces the interesting challenge that the two metric vectors that are
|
||||
// used in this example are already Collectors themselves. However, thanks to
|
||||
// the use of channels, it is really easy to "chain" Collectors. Here we simply
|
||||
// call the Describe methods of the two metric vectors.
|
||||
func (c *ClusterManager) Describe(ch chan<- *prometheus.Desc) {
|
||||
c.OOMCount.Describe(ch)
|
||||
c.RAMUsage.Describe(ch)
|
||||
}
|
||||
|
||||
// Collect first triggers the ReallyExpensiveAssessmentOfTheSystemState. Then it
|
||||
// sets the retrieved values in the two metric vectors and then sends all their
|
||||
// metrics to the channel (again using a chaining technique as in the Describe
|
||||
// method). Since Collect could be called multiple times concurrently, that part
|
||||
// is protected by a mutex.
|
||||
func (c *ClusterManager) Collect(ch chan<- prometheus.Metric) {
|
||||
oomCountByHost, ramUsageByHost := c.ReallyExpensiveAssessmentOfTheSystemState()
|
||||
c.mtx.Lock()
|
||||
defer c.mtx.Unlock()
|
||||
for host, oomCount := range oomCountByHost {
|
||||
c.OOMCount.WithLabelValues(host).Set(float64(oomCount))
|
||||
}
|
||||
for host, ramUsage := range ramUsageByHost {
|
||||
c.RAMUsage.WithLabelValues(host).Set(ramUsage)
|
||||
}
|
||||
c.OOMCount.Collect(ch)
|
||||
c.RAMUsage.Collect(ch)
|
||||
// All metrics in OOMCount and RAMUsage are sent to the channel now. We
|
||||
// can safely reset the two metric vectors now, so that we can start
|
||||
// fresh in the next Collect cycle. (Imagine a host disappears from the
|
||||
// cluster. If we did not reset here, its Metric would stay in the
|
||||
// metric vectors forever.)
|
||||
c.OOMCount.Reset()
|
||||
c.RAMUsage.Reset()
|
||||
}
|
||||
|
||||
// NewClusterManager creates the two metric vectors OOMCount and RAMUsage. Note
|
||||
// that the zone is set as a ConstLabel. (It's different in each instance of the
|
||||
// ClusterManager, but constant over the lifetime of an instance.) The reported
|
||||
// values are partitioned by host, which is therefore a variable label.
|
||||
func NewClusterManager(zone string) *ClusterManager {
|
||||
return &ClusterManager{
|
||||
Zone: zone,
|
||||
OOMCount: prometheus.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Subsystem: "clustermanager",
|
||||
Name: "oom_count",
|
||||
Help: "number of OOM crashes",
|
||||
ConstLabels: prometheus.Labels{"zone": zone},
|
||||
},
|
||||
[]string{"host"},
|
||||
),
|
||||
RAMUsage: prometheus.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Subsystem: "clustermanager",
|
||||
Name: "ram_usage_bytes",
|
||||
Help: "RAM usage as reported to the cluster manager",
|
||||
ConstLabels: prometheus.Labels{"zone": zone},
|
||||
},
|
||||
[]string{"host"},
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleCollector_clustermanager() {
|
||||
workerDB := NewClusterManager("db")
|
||||
workerCA := NewClusterManager("ca")
|
||||
prometheus.MustRegister(workerDB)
|
||||
prometheus.MustRegister(workerCA)
|
||||
|
||||
// Since we are dealing with custom Collector implementations, it might
|
||||
// be a good idea to enable the collect checks in the registry.
|
||||
prometheus.EnableCollectChecks(true)
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
// Copyright 2014 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package prometheus_test
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
var (
|
||||
allocDesc = prometheus.NewDesc(
|
||||
prometheus.BuildFQName("", "memstats", "alloc_bytes"),
|
||||
"bytes allocated and still in use",
|
||||
nil, nil,
|
||||
)
|
||||
totalAllocDesc = prometheus.NewDesc(
|
||||
prometheus.BuildFQName("", "memstats", "total_alloc_bytes"),
|
||||
"bytes allocated (even if freed)",
|
||||
nil, nil,
|
||||
)
|
||||
numGCDesc = prometheus.NewDesc(
|
||||
prometheus.BuildFQName("", "memstats", "num_gc_total"),
|
||||
"number of GCs run",
|
||||
nil, nil,
|
||||
)
|
||||
)
|
||||
|
||||
// MemStatsCollector is an example for a custom Collector that solves the
|
||||
// problem of feeding into multiple metrics at the same time. The
|
||||
// runtime.ReadMemStats should happen only once, and then the results need to be
|
||||
// fed into a number of separate Metrics. In this example, only a few of the
|
||||
// values reported by ReadMemStats are used. For each, there is a Desc provided
|
||||
// as a var, so the MemStatsCollector itself needs nothing else in the
|
||||
// struct. Only the methods need to be implemented.
|
||||
type MemStatsCollector struct{}
|
||||
|
||||
// Describe just sends the three Desc objects for the Metrics we intend to
|
||||
// collect.
|
||||
func (_ MemStatsCollector) Describe(ch chan<- *prometheus.Desc) {
|
||||
ch <- allocDesc
|
||||
ch <- totalAllocDesc
|
||||
ch <- numGCDesc
|
||||
}
|
||||
|
||||
// Collect does the trick by calling ReadMemStats once and then constructing
|
||||
// three different Metrics on the fly.
|
||||
func (_ MemStatsCollector) Collect(ch chan<- prometheus.Metric) {
|
||||
var ms runtime.MemStats
|
||||
runtime.ReadMemStats(&ms)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
allocDesc,
|
||||
prometheus.GaugeValue,
|
||||
float64(ms.Alloc),
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
totalAllocDesc,
|
||||
prometheus.GaugeValue,
|
||||
float64(ms.TotalAlloc),
|
||||
)
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
numGCDesc,
|
||||
prometheus.CounterValue,
|
||||
float64(ms.NumGC),
|
||||
)
|
||||
// To avoid new allocations on each collection, you could also keep
|
||||
// metric objects around and return the same objects each time, just
|
||||
// with new values set.
|
||||
}
|
||||
|
||||
func ExampleCollector_memstats() {
|
||||
prometheus.MustRegister(&MemStatsCollector{})
|
||||
// Since we are dealing with custom Collector implementations, it might
|
||||
// be a good idea to enable the collect checks in the registry.
|
||||
prometheus.EnableCollectChecks(true)
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
// Copyright 2014 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package prometheus_test
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus"
|
||||
dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
|
||||
)
|
||||
|
||||
func NewCallbackMetric(desc *prometheus.Desc, callback func() float64) *CallbackMetric {
|
||||
result := &CallbackMetric{desc: desc, callback: callback}
|
||||
result.Init(result) // Initialize the SelfCollector.
|
||||
return result
|
||||
}
|
||||
|
||||
// TODO: Come up with a better example.
|
||||
|
||||
// CallbackMetric is an example for a user-defined Metric that exports the
|
||||
// result of a function call as a metric of type "untyped" without any
|
||||
// labels. It uses SelfCollector to turn the Metric into a Collector so that it
|
||||
// can be registered with Prometheus.
|
||||
//
|
||||
// Note that this example is pretty much academic as the prometheus package
|
||||
// already provides an UntypedFunc type.
|
||||
type CallbackMetric struct {
|
||||
prometheus.SelfCollector
|
||||
|
||||
desc *prometheus.Desc
|
||||
callback func() float64
|
||||
}
|
||||
|
||||
func (cm *CallbackMetric) Desc() *prometheus.Desc {
|
||||
return cm.desc
|
||||
}
|
||||
|
||||
func (cm *CallbackMetric) Write(m *dto.Metric) error {
|
||||
m.Untyped = &dto.Untyped{Value: proto.Float64(cm.callback())}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ExampleSelfCollector() {
|
||||
m := NewCallbackMetric(
|
||||
prometheus.NewDesc(
|
||||
"runtime_goroutines_count",
|
||||
"Total number of goroutines that currently exist.",
|
||||
nil, nil, // No labels, these must be nil.
|
||||
),
|
||||
func() float64 {
|
||||
return float64(runtime.NumGoroutine())
|
||||
},
|
||||
)
|
||||
prometheus.MustRegister(m)
|
||||
}
|
647
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/examples_test.go
generated
vendored
647
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/examples_test.go
generated
vendored
|
@ -1,647 +0,0 @@
|
|||
// Copyright 2014 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package prometheus_test
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"math"
|
||||
"net/http"
|
||||
"os"
|
||||
"runtime"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus"
|
||||
dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
|
||||
)
|
||||
|
||||
func ExampleGauge() {
|
||||
opsQueued := prometheus.NewGauge(prometheus.GaugeOpts{
|
||||
Namespace: "our_company",
|
||||
Subsystem: "blob_storage",
|
||||
Name: "ops_queued",
|
||||
Help: "Number of blob storage operations waiting to be processed.",
|
||||
})
|
||||
prometheus.MustRegister(opsQueued)
|
||||
|
||||
// 10 operations queued by the goroutine managing incoming requests.
|
||||
opsQueued.Add(10)
|
||||
// A worker goroutine has picked up a waiting operation.
|
||||
opsQueued.Dec()
|
||||
// And once more...
|
||||
opsQueued.Dec()
|
||||
}
|
||||
|
||||
func ExampleGaugeVec() {
|
||||
binaryVersion := flag.String("binary_version", "debug", "Version of the binary: debug, canary, production.")
|
||||
flag.Parse()
|
||||
|
||||
opsQueued := prometheus.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Namespace: "our_company",
|
||||
Subsystem: "blob_storage",
|
||||
Name: "ops_queued",
|
||||
Help: "Number of blob storage operations waiting to be processed, partitioned by user and type.",
|
||||
ConstLabels: prometheus.Labels{"binary_version": *binaryVersion},
|
||||
},
|
||||
[]string{
|
||||
// Which user has requested the operation?
|
||||
"user",
|
||||
// Of what type is the operation?
|
||||
"type",
|
||||
},
|
||||
)
|
||||
prometheus.MustRegister(opsQueued)
|
||||
|
||||
// Increase a value using compact (but order-sensitive!) WithLabelValues().
|
||||
opsQueued.WithLabelValues("bob", "put").Add(4)
|
||||
// Increase a value with a map using WithLabels. More verbose, but order
|
||||
// doesn't matter anymore.
|
||||
opsQueued.With(prometheus.Labels{"type": "delete", "user": "alice"}).Inc()
|
||||
}
|
||||
|
||||
func ExampleGaugeFunc() {
|
||||
if err := prometheus.Register(prometheus.NewGaugeFunc(
|
||||
prometheus.GaugeOpts{
|
||||
Subsystem: "runtime",
|
||||
Name: "goroutines_count",
|
||||
Help: "Number of goroutines that currently exist.",
|
||||
},
|
||||
func() float64 { return float64(runtime.NumGoroutine()) },
|
||||
)); err == nil {
|
||||
fmt.Println("GaugeFunc 'goroutines_count' registered.")
|
||||
}
|
||||
// Note that the count of goroutines is a gauge (and not a counter) as
|
||||
// it can go up and down.
|
||||
|
||||
// Output:
|
||||
// GaugeFunc 'goroutines_count' registered.
|
||||
}
|
||||
|
||||
func ExampleCounter() {
|
||||
pushCounter := prometheus.NewCounter(prometheus.CounterOpts{
|
||||
Name: "repository_pushes", // Note: No help string...
|
||||
})
|
||||
err := prometheus.Register(pushCounter) // ... so this will return an error.
|
||||
if err != nil {
|
||||
fmt.Println("Push counter couldn't be registered, no counting will happen:", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Try it once more, this time with a help string.
|
||||
pushCounter = prometheus.NewCounter(prometheus.CounterOpts{
|
||||
Name: "repository_pushes",
|
||||
Help: "Number of pushes to external repository.",
|
||||
})
|
||||
err = prometheus.Register(pushCounter)
|
||||
if err != nil {
|
||||
fmt.Println("Push counter couldn't be registered AGAIN, no counting will happen:", err)
|
||||
return
|
||||
}
|
||||
|
||||
pushComplete := make(chan struct{})
|
||||
// TODO: Start a goroutine that performs repository pushes and reports
|
||||
// each completion via the channel.
|
||||
for _ = range pushComplete {
|
||||
pushCounter.Inc()
|
||||
}
|
||||
// Output:
|
||||
// Push counter couldn't be registered, no counting will happen: descriptor Desc{fqName: "repository_pushes", help: "", constLabels: {}, variableLabels: []} is invalid: empty help string
|
||||
}
|
||||
|
||||
func ExampleCounterVec() {
|
||||
binaryVersion := flag.String("environment", "test", "Execution environment: test, staging, production.")
|
||||
flag.Parse()
|
||||
|
||||
httpReqs := prometheus.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: "http_requests_total",
|
||||
Help: "How many HTTP requests processed, partitioned by status code and HTTP method.",
|
||||
ConstLabels: prometheus.Labels{"env": *binaryVersion},
|
||||
},
|
||||
[]string{"code", "method"},
|
||||
)
|
||||
prometheus.MustRegister(httpReqs)
|
||||
|
||||
httpReqs.WithLabelValues("404", "POST").Add(42)
|
||||
|
||||
// If you have to access the same set of labels very frequently, it
|
||||
// might be good to retrieve the metric only once and keep a handle to
|
||||
// it. But beware of deletion of that metric, see below!
|
||||
m := httpReqs.WithLabelValues("200", "GET")
|
||||
for i := 0; i < 1000000; i++ {
|
||||
m.Inc()
|
||||
}
|
||||
// Delete a metric from the vector. If you have previously kept a handle
|
||||
// to that metric (as above), future updates via that handle will go
|
||||
// unseen (even if you re-create a metric with the same label set
|
||||
// later).
|
||||
httpReqs.DeleteLabelValues("200", "GET")
|
||||
// Same thing with the more verbose Labels syntax.
|
||||
httpReqs.Delete(prometheus.Labels{"method": "GET", "code": "200"})
|
||||
}
|
||||
|
||||
func ExampleInstrumentHandler() {
|
||||
// Handle the "/doc" endpoint with the standard http.FileServer handler.
|
||||
// By wrapping the handler with InstrumentHandler, request count,
|
||||
// request and response sizes, and request latency are automatically
|
||||
// exported to Prometheus, partitioned by HTTP status code and method
|
||||
// and by the handler name (here "fileserver").
|
||||
http.Handle("/doc", prometheus.InstrumentHandler(
|
||||
"fileserver", http.FileServer(http.Dir("/usr/share/doc")),
|
||||
))
|
||||
// The Prometheus handler still has to be registered to handle the
|
||||
// "/metrics" endpoint. The handler returned by prometheus.Handler() is
|
||||
// already instrumented - with "prometheus" as the handler name. In this
|
||||
// example, we want the handler name to be "metrics", so we instrument
|
||||
// the uninstrumented Prometheus handler ourselves.
|
||||
http.Handle("/metrics", prometheus.InstrumentHandler(
|
||||
"metrics", prometheus.UninstrumentedHandler(),
|
||||
))
|
||||
}
|
||||
|
||||
func ExampleLabelPairSorter() {
|
||||
labelPairs := []*dto.LabelPair{
|
||||
&dto.LabelPair{Name: proto.String("status"), Value: proto.String("404")},
|
||||
&dto.LabelPair{Name: proto.String("method"), Value: proto.String("get")},
|
||||
}
|
||||
|
||||
sort.Sort(prometheus.LabelPairSorter(labelPairs))
|
||||
|
||||
fmt.Println(labelPairs)
|
||||
// Output:
|
||||
// [name:"method" value:"get" name:"status" value:"404" ]
|
||||
}
|
||||
|
||||
func ExampleRegister() {
|
||||
// Imagine you have a worker pool and want to count the tasks completed.
|
||||
taskCounter := prometheus.NewCounter(prometheus.CounterOpts{
|
||||
Subsystem: "worker_pool",
|
||||
Name: "completed_tasks_total",
|
||||
Help: "Total number of tasks completed.",
|
||||
})
|
||||
// This will register fine.
|
||||
if err := prometheus.Register(taskCounter); err != nil {
|
||||
fmt.Println(err)
|
||||
} else {
|
||||
fmt.Println("taskCounter registered.")
|
||||
}
|
||||
// Don't forget to tell the HTTP server about the Prometheus handler.
|
||||
// (In a real program, you still need to start the HTTP server...)
|
||||
http.Handle("/metrics", prometheus.Handler())
|
||||
|
||||
// Now you can start workers and give every one of them a pointer to
|
||||
// taskCounter and let it increment it whenever it completes a task.
|
||||
taskCounter.Inc() // This has to happen somewhere in the worker code.
|
||||
|
||||
// But wait, you want to see how individual workers perform. So you need
|
||||
// a vector of counters, with one element for each worker.
|
||||
taskCounterVec := prometheus.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Subsystem: "worker_pool",
|
||||
Name: "completed_tasks_total",
|
||||
Help: "Total number of tasks completed.",
|
||||
},
|
||||
[]string{"worker_id"},
|
||||
)
|
||||
|
||||
// Registering will fail because we already have a metric of that name.
|
||||
if err := prometheus.Register(taskCounterVec); err != nil {
|
||||
fmt.Println("taskCounterVec not registered:", err)
|
||||
} else {
|
||||
fmt.Println("taskCounterVec registered.")
|
||||
}
|
||||
|
||||
// To fix, first unregister the old taskCounter.
|
||||
if prometheus.Unregister(taskCounter) {
|
||||
fmt.Println("taskCounter unregistered.")
|
||||
}
|
||||
|
||||
// Try registering taskCounterVec again.
|
||||
if err := prometheus.Register(taskCounterVec); err != nil {
|
||||
fmt.Println("taskCounterVec not registered:", err)
|
||||
} else {
|
||||
fmt.Println("taskCounterVec registered.")
|
||||
}
|
||||
// Bummer! Still doesn't work.
|
||||
|
||||
// Prometheus will not allow you to ever export metrics with
|
||||
// inconsistent help strings or label names. After unregistering, the
|
||||
// unregistered metrics will cease to show up in the /metrics HTTP
|
||||
// response, but the registry still remembers that those metrics had
|
||||
// been exported before. For this example, we will now choose a
|
||||
// different name. (In a real program, you would obviously not export
|
||||
// the obsolete metric in the first place.)
|
||||
taskCounterVec = prometheus.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Subsystem: "worker_pool",
|
||||
Name: "completed_tasks_by_id",
|
||||
Help: "Total number of tasks completed.",
|
||||
},
|
||||
[]string{"worker_id"},
|
||||
)
|
||||
if err := prometheus.Register(taskCounterVec); err != nil {
|
||||
fmt.Println("taskCounterVec not registered:", err)
|
||||
} else {
|
||||
fmt.Println("taskCounterVec registered.")
|
||||
}
|
||||
// Finally it worked!
|
||||
|
||||
// The workers have to tell taskCounterVec their id to increment the
|
||||
// right element in the metric vector.
|
||||
taskCounterVec.WithLabelValues("42").Inc() // Code from worker 42.
|
||||
|
||||
// Each worker could also keep a reference to their own counter element
|
||||
// around. Pick the counter at initialization time of the worker.
|
||||
myCounter := taskCounterVec.WithLabelValues("42") // From worker 42 initialization code.
|
||||
myCounter.Inc() // Somewhere in the code of that worker.
|
||||
|
||||
// Note that something like WithLabelValues("42", "spurious arg") would
|
||||
// panic (because you have provided too many label values). If you want
|
||||
// to get an error instead, use GetMetricWithLabelValues(...) instead.
|
||||
notMyCounter, err := taskCounterVec.GetMetricWithLabelValues("42", "spurious arg")
|
||||
if err != nil {
|
||||
fmt.Println("Worker initialization failed:", err)
|
||||
}
|
||||
if notMyCounter == nil {
|
||||
fmt.Println("notMyCounter is nil.")
|
||||
}
|
||||
|
||||
// A different (and somewhat tricky) approach is to use
|
||||
// ConstLabels. ConstLabels are pairs of label names and label values
|
||||
// that never change. You might ask what those labels are good for (and
|
||||
// rightfully so - if they never change, they could as well be part of
|
||||
// the metric name). There are essentially two use-cases: The first is
|
||||
// if labels are constant throughout the lifetime of a binary execution,
|
||||
// but they vary over time or between different instances of a running
|
||||
// binary. The second is what we have here: Each worker creates and
|
||||
// registers an own Counter instance where the only difference is in the
|
||||
// value of the ConstLabels. Those Counters can all be registered
|
||||
// because the different ConstLabel values guarantee that each worker
|
||||
// will increment a different Counter metric.
|
||||
counterOpts := prometheus.CounterOpts{
|
||||
Subsystem: "worker_pool",
|
||||
Name: "completed_tasks",
|
||||
Help: "Total number of tasks completed.",
|
||||
ConstLabels: prometheus.Labels{"worker_id": "42"},
|
||||
}
|
||||
taskCounterForWorker42 := prometheus.NewCounter(counterOpts)
|
||||
if err := prometheus.Register(taskCounterForWorker42); err != nil {
|
||||
fmt.Println("taskCounterVForWorker42 not registered:", err)
|
||||
} else {
|
||||
fmt.Println("taskCounterForWorker42 registered.")
|
||||
}
|
||||
// Obviously, in real code, taskCounterForWorker42 would be a member
|
||||
// variable of a worker struct, and the "42" would be retrieved with a
|
||||
// GetId() method or something. The Counter would be created and
|
||||
// registered in the initialization code of the worker.
|
||||
|
||||
// For the creation of the next Counter, we can recycle
|
||||
// counterOpts. Just change the ConstLabels.
|
||||
counterOpts.ConstLabels = prometheus.Labels{"worker_id": "2001"}
|
||||
taskCounterForWorker2001 := prometheus.NewCounter(counterOpts)
|
||||
if err := prometheus.Register(taskCounterForWorker2001); err != nil {
|
||||
fmt.Println("taskCounterVForWorker2001 not registered:", err)
|
||||
} else {
|
||||
fmt.Println("taskCounterForWorker2001 registered.")
|
||||
}
|
||||
|
||||
taskCounterForWorker2001.Inc()
|
||||
taskCounterForWorker42.Inc()
|
||||
taskCounterForWorker2001.Inc()
|
||||
|
||||
// Yet another approach would be to turn the workers themselves into
|
||||
// Collectors and register them. See the Collector example for details.
|
||||
|
||||
// Output:
|
||||
// taskCounter registered.
|
||||
// taskCounterVec not registered: a previously registered descriptor with the same fully-qualified name as Desc{fqName: "worker_pool_completed_tasks_total", help: "Total number of tasks completed.", constLabels: {}, variableLabels: [worker_id]} has different label names or a different help string
|
||||
// taskCounter unregistered.
|
||||
// taskCounterVec not registered: a previously registered descriptor with the same fully-qualified name as Desc{fqName: "worker_pool_completed_tasks_total", help: "Total number of tasks completed.", constLabels: {}, variableLabels: [worker_id]} has different label names or a different help string
|
||||
// taskCounterVec registered.
|
||||
// Worker initialization failed: inconsistent label cardinality
|
||||
// notMyCounter is nil.
|
||||
// taskCounterForWorker42 registered.
|
||||
// taskCounterForWorker2001 registered.
|
||||
}
|
||||
|
||||
func ExampleSummary() {
|
||||
temps := prometheus.NewSummary(prometheus.SummaryOpts{
|
||||
Name: "pond_temperature_celsius",
|
||||
Help: "The temperature of the frog pond.", // Sorry, we can't measure how badly it smells.
|
||||
})
|
||||
|
||||
// Simulate some observations.
|
||||
for i := 0; i < 1000; i++ {
|
||||
temps.Observe(30 + math.Floor(120*math.Sin(float64(i)*0.1))/10)
|
||||
}
|
||||
|
||||
// Just for demonstration, let's check the state of the summary by
|
||||
// (ab)using its Write method (which is usually only used by Prometheus
|
||||
// internally).
|
||||
metric := &dto.Metric{}
|
||||
temps.Write(metric)
|
||||
fmt.Println(proto.MarshalTextString(metric))
|
||||
|
||||
// Output:
|
||||
// summary: <
|
||||
// sample_count: 1000
|
||||
// sample_sum: 29969.50000000001
|
||||
// quantile: <
|
||||
// quantile: 0.5
|
||||
// value: 31.1
|
||||
// >
|
||||
// quantile: <
|
||||
// quantile: 0.9
|
||||
// value: 41.3
|
||||
// >
|
||||
// quantile: <
|
||||
// quantile: 0.99
|
||||
// value: 41.9
|
||||
// >
|
||||
// >
|
||||
}
|
||||
|
||||
func ExampleSummaryVec() {
|
||||
temps := prometheus.NewSummaryVec(
|
||||
prometheus.SummaryOpts{
|
||||
Name: "pond_temperature_celsius",
|
||||
Help: "The temperature of the frog pond.", // Sorry, we can't measure how badly it smells.
|
||||
},
|
||||
[]string{"species"},
|
||||
)
|
||||
|
||||
// Simulate some observations.
|
||||
for i := 0; i < 1000; i++ {
|
||||
temps.WithLabelValues("litoria-caerulea").Observe(30 + math.Floor(120*math.Sin(float64(i)*0.1))/10)
|
||||
temps.WithLabelValues("lithobates-catesbeianus").Observe(32 + math.Floor(100*math.Cos(float64(i)*0.11))/10)
|
||||
}
|
||||
|
||||
// Create a Summary without any observations.
|
||||
temps.WithLabelValues("leiopelma-hochstetteri")
|
||||
|
||||
// Just for demonstration, let's check the state of the summary vector
|
||||
// by (ab)using its Collect method and the Write method of its elements
|
||||
// (which is usually only used by Prometheus internally - code like the
|
||||
// following will never appear in your own code).
|
||||
metricChan := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
defer close(metricChan)
|
||||
temps.Collect(metricChan)
|
||||
}()
|
||||
|
||||
metricStrings := []string{}
|
||||
for metric := range metricChan {
|
||||
dtoMetric := &dto.Metric{}
|
||||
metric.Write(dtoMetric)
|
||||
metricStrings = append(metricStrings, proto.MarshalTextString(dtoMetric))
|
||||
}
|
||||
sort.Strings(metricStrings) // For reproducible print order.
|
||||
fmt.Println(metricStrings)
|
||||
|
||||
// Output:
|
||||
// [label: <
|
||||
// name: "species"
|
||||
// value: "leiopelma-hochstetteri"
|
||||
// >
|
||||
// summary: <
|
||||
// sample_count: 0
|
||||
// sample_sum: 0
|
||||
// quantile: <
|
||||
// quantile: 0.5
|
||||
// value: nan
|
||||
// >
|
||||
// quantile: <
|
||||
// quantile: 0.9
|
||||
// value: nan
|
||||
// >
|
||||
// quantile: <
|
||||
// quantile: 0.99
|
||||
// value: nan
|
||||
// >
|
||||
// >
|
||||
// label: <
|
||||
// name: "species"
|
||||
// value: "lithobates-catesbeianus"
|
||||
// >
|
||||
// summary: <
|
||||
// sample_count: 1000
|
||||
// sample_sum: 31956.100000000017
|
||||
// quantile: <
|
||||
// quantile: 0.5
|
||||
// value: 32.4
|
||||
// >
|
||||
// quantile: <
|
||||
// quantile: 0.9
|
||||
// value: 41.4
|
||||
// >
|
||||
// quantile: <
|
||||
// quantile: 0.99
|
||||
// value: 41.9
|
||||
// >
|
||||
// >
|
||||
// label: <
|
||||
// name: "species"
|
||||
// value: "litoria-caerulea"
|
||||
// >
|
||||
// summary: <
|
||||
// sample_count: 1000
|
||||
// sample_sum: 29969.50000000001
|
||||
// quantile: <
|
||||
// quantile: 0.5
|
||||
// value: 31.1
|
||||
// >
|
||||
// quantile: <
|
||||
// quantile: 0.9
|
||||
// value: 41.3
|
||||
// >
|
||||
// quantile: <
|
||||
// quantile: 0.99
|
||||
// value: 41.9
|
||||
// >
|
||||
// >
|
||||
// ]
|
||||
}
|
||||
|
||||
func ExampleConstSummary() {
|
||||
desc := prometheus.NewDesc(
|
||||
"http_request_duration_seconds",
|
||||
"A summary of the HTTP request durations.",
|
||||
[]string{"code", "method"},
|
||||
prometheus.Labels{"owner": "example"},
|
||||
)
|
||||
|
||||
// Create a constant summary from values we got from a 3rd party telemetry system.
|
||||
s := prometheus.MustNewConstSummary(
|
||||
desc,
|
||||
4711, 403.34,
|
||||
map[float64]float64{0.5: 42.3, 0.9: 323.3},
|
||||
"200", "get",
|
||||
)
|
||||
|
||||
// Just for demonstration, let's check the state of the summary by
|
||||
// (ab)using its Write method (which is usually only used by Prometheus
|
||||
// internally).
|
||||
metric := &dto.Metric{}
|
||||
s.Write(metric)
|
||||
fmt.Println(proto.MarshalTextString(metric))
|
||||
|
||||
// Output:
|
||||
// label: <
|
||||
// name: "code"
|
||||
// value: "200"
|
||||
// >
|
||||
// label: <
|
||||
// name: "method"
|
||||
// value: "get"
|
||||
// >
|
||||
// label: <
|
||||
// name: "owner"
|
||||
// value: "example"
|
||||
// >
|
||||
// summary: <
|
||||
// sample_count: 4711
|
||||
// sample_sum: 403.34
|
||||
// quantile: <
|
||||
// quantile: 0.5
|
||||
// value: 42.3
|
||||
// >
|
||||
// quantile: <
|
||||
// quantile: 0.9
|
||||
// value: 323.3
|
||||
// >
|
||||
// >
|
||||
}
|
||||
|
||||
func ExampleHistogram() {
|
||||
temps := prometheus.NewHistogram(prometheus.HistogramOpts{
|
||||
Name: "pond_temperature_celsius",
|
||||
Help: "The temperature of the frog pond.", // Sorry, we can't measure how badly it smells.
|
||||
Buckets: prometheus.LinearBuckets(20, 5, 5), // 5 buckets, each 5 centigrade wide.
|
||||
})
|
||||
|
||||
// Simulate some observations.
|
||||
for i := 0; i < 1000; i++ {
|
||||
temps.Observe(30 + math.Floor(120*math.Sin(float64(i)*0.1))/10)
|
||||
}
|
||||
|
||||
// Just for demonstration, let's check the state of the histogram by
|
||||
// (ab)using its Write method (which is usually only used by Prometheus
|
||||
// internally).
|
||||
metric := &dto.Metric{}
|
||||
temps.Write(metric)
|
||||
fmt.Println(proto.MarshalTextString(metric))
|
||||
|
||||
// Output:
|
||||
// histogram: <
|
||||
// sample_count: 1000
|
||||
// sample_sum: 29969.50000000001
|
||||
// bucket: <
|
||||
// cumulative_count: 192
|
||||
// upper_bound: 20
|
||||
// >
|
||||
// bucket: <
|
||||
// cumulative_count: 366
|
||||
// upper_bound: 25
|
||||
// >
|
||||
// bucket: <
|
||||
// cumulative_count: 501
|
||||
// upper_bound: 30
|
||||
// >
|
||||
// bucket: <
|
||||
// cumulative_count: 638
|
||||
// upper_bound: 35
|
||||
// >
|
||||
// bucket: <
|
||||
// cumulative_count: 816
|
||||
// upper_bound: 40
|
||||
// >
|
||||
// >
|
||||
}
|
||||
|
||||
func ExampleConstHistogram() {
|
||||
desc := prometheus.NewDesc(
|
||||
"http_request_duration_seconds",
|
||||
"A histogram of the HTTP request durations.",
|
||||
[]string{"code", "method"},
|
||||
prometheus.Labels{"owner": "example"},
|
||||
)
|
||||
|
||||
// Create a constant histogram from values we got from a 3rd party telemetry system.
|
||||
h := prometheus.MustNewConstHistogram(
|
||||
desc,
|
||||
4711, 403.34,
|
||||
map[float64]uint64{25: 121, 50: 2403, 100: 3221, 200: 4233},
|
||||
"200", "get",
|
||||
)
|
||||
|
||||
// Just for demonstration, let's check the state of the histogram by
|
||||
// (ab)using its Write method (which is usually only used by Prometheus
|
||||
// internally).
|
||||
metric := &dto.Metric{}
|
||||
h.Write(metric)
|
||||
fmt.Println(proto.MarshalTextString(metric))
|
||||
|
||||
// Output:
|
||||
// label: <
|
||||
// name: "code"
|
||||
// value: "200"
|
||||
// >
|
||||
// label: <
|
||||
// name: "method"
|
||||
// value: "get"
|
||||
// >
|
||||
// label: <
|
||||
// name: "owner"
|
||||
// value: "example"
|
||||
// >
|
||||
// histogram: <
|
||||
// sample_count: 4711
|
||||
// sample_sum: 403.34
|
||||
// bucket: <
|
||||
// cumulative_count: 121
|
||||
// upper_bound: 25
|
||||
// >
|
||||
// bucket: <
|
||||
// cumulative_count: 2403
|
||||
// upper_bound: 50
|
||||
// >
|
||||
// bucket: <
|
||||
// cumulative_count: 3221
|
||||
// upper_bound: 100
|
||||
// >
|
||||
// bucket: <
|
||||
// cumulative_count: 4233
|
||||
// upper_bound: 200
|
||||
// >
|
||||
// >
|
||||
}
|
||||
|
||||
func ExamplePushCollectors() {
|
||||
hostname, _ := os.Hostname()
|
||||
completionTime := prometheus.NewGauge(prometheus.GaugeOpts{
|
||||
Name: "db_backup_last_completion_time",
|
||||
Help: "The timestamp of the last succesful completion of a DB backup.",
|
||||
})
|
||||
completionTime.Set(float64(time.Now().Unix()))
|
||||
if err := prometheus.PushCollectors(
|
||||
"db_backup", hostname,
|
||||
"http://pushgateway:9091",
|
||||
completionTime,
|
||||
); err != nil {
|
||||
fmt.Println("Could not push completion time to Pushgateway:", err)
|
||||
}
|
||||
}
|
96
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/expvar_test.go
generated
vendored
96
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/expvar_test.go
generated
vendored
|
@ -1,96 +0,0 @@
|
|||
// Copyright 2014 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package prometheus_test
|
||||
|
||||
import (
|
||||
"expvar"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus"
|
||||
dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
|
||||
)
|
||||
|
||||
func ExampleExpvarCollector() {
|
||||
expvarCollector := prometheus.NewExpvarCollector(map[string]*prometheus.Desc{
|
||||
"memstats": prometheus.NewDesc(
|
||||
"expvar_memstats",
|
||||
"All numeric memstats as one metric family. Not a good role-model, actually... ;-)",
|
||||
[]string{"type"}, nil,
|
||||
),
|
||||
"lone-int": prometheus.NewDesc(
|
||||
"expvar_lone_int",
|
||||
"Just an expvar int as an example.",
|
||||
nil, nil,
|
||||
),
|
||||
"http-request-map": prometheus.NewDesc(
|
||||
"expvar_http_request_total",
|
||||
"How many http requests processed, partitioned by status code and http method.",
|
||||
[]string{"code", "method"}, nil,
|
||||
),
|
||||
})
|
||||
prometheus.MustRegister(expvarCollector)
|
||||
|
||||
// The Prometheus part is done here. But to show that this example is
|
||||
// doing anything, we have to manually export something via expvar. In
|
||||
// real-life use-cases, some library would already have exported via
|
||||
// expvar what we want to re-export as Prometheus metrics.
|
||||
expvar.NewInt("lone-int").Set(42)
|
||||
expvarMap := expvar.NewMap("http-request-map")
|
||||
var (
|
||||
expvarMap1, expvarMap2 expvar.Map
|
||||
expvarInt11, expvarInt12, expvarInt21, expvarInt22 expvar.Int
|
||||
)
|
||||
expvarMap1.Init()
|
||||
expvarMap2.Init()
|
||||
expvarInt11.Set(3)
|
||||
expvarInt12.Set(13)
|
||||
expvarInt21.Set(11)
|
||||
expvarInt22.Set(212)
|
||||
expvarMap1.Set("POST", &expvarInt11)
|
||||
expvarMap1.Set("GET", &expvarInt12)
|
||||
expvarMap2.Set("POST", &expvarInt21)
|
||||
expvarMap2.Set("GET", &expvarInt22)
|
||||
expvarMap.Set("404", &expvarMap1)
|
||||
expvarMap.Set("200", &expvarMap2)
|
||||
// Results in the following expvar map:
|
||||
// "http-request-count": {"200": {"POST": 11, "GET": 212}, "404": {"POST": 3, "GET": 13}}
|
||||
|
||||
// Let's see what the scrape would yield, but exclude the memstats metrics.
|
||||
metricStrings := []string{}
|
||||
metric := dto.Metric{}
|
||||
metricChan := make(chan prometheus.Metric)
|
||||
go func() {
|
||||
expvarCollector.Collect(metricChan)
|
||||
close(metricChan)
|
||||
}()
|
||||
for m := range metricChan {
|
||||
if strings.Index(m.Desc().String(), "expvar_memstats") == -1 {
|
||||
metric.Reset()
|
||||
m.Write(&metric)
|
||||
metricStrings = append(metricStrings, metric.String())
|
||||
}
|
||||
}
|
||||
sort.Strings(metricStrings)
|
||||
for _, s := range metricStrings {
|
||||
fmt.Println(strings.TrimRight(s, " "))
|
||||
}
|
||||
// Output:
|
||||
// label:<name:"code" value:"200" > label:<name:"method" value:"GET" > untyped:<value:212 >
|
||||
// label:<name:"code" value:"200" > label:<name:"method" value:"POST" > untyped:<value:11 >
|
||||
// label:<name:"code" value:"404" > label:<name:"method" value:"GET" > untyped:<value:13 >
|
||||
// label:<name:"code" value:"404" > label:<name:"method" value:"POST" > untyped:<value:3 >
|
||||
// untyped:<value:42 >
|
||||
}
|
182
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/gauge_test.go
generated
vendored
182
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/gauge_test.go
generated
vendored
|
@ -1,182 +0,0 @@
|
|||
// Copyright 2014 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/rand"
|
||||
"sync"
|
||||
"testing"
|
||||
"testing/quick"
|
||||
|
||||
dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
|
||||
)
|
||||
|
||||
func listenGaugeStream(vals, result chan float64, done chan struct{}) {
|
||||
var sum float64
|
||||
outer:
|
||||
for {
|
||||
select {
|
||||
case <-done:
|
||||
close(vals)
|
||||
for v := range vals {
|
||||
sum += v
|
||||
}
|
||||
break outer
|
||||
case v := <-vals:
|
||||
sum += v
|
||||
}
|
||||
}
|
||||
result <- sum
|
||||
close(result)
|
||||
}
|
||||
|
||||
func TestGaugeConcurrency(t *testing.T) {
|
||||
it := func(n uint32) bool {
|
||||
mutations := int(n % 10000)
|
||||
concLevel := int(n%15 + 1)
|
||||
|
||||
var start, end sync.WaitGroup
|
||||
start.Add(1)
|
||||
end.Add(concLevel)
|
||||
|
||||
sStream := make(chan float64, mutations*concLevel)
|
||||
result := make(chan float64)
|
||||
done := make(chan struct{})
|
||||
|
||||
go listenGaugeStream(sStream, result, done)
|
||||
go func() {
|
||||
end.Wait()
|
||||
close(done)
|
||||
}()
|
||||
|
||||
gge := NewGauge(GaugeOpts{
|
||||
Name: "test_gauge",
|
||||
Help: "no help can be found here",
|
||||
})
|
||||
for i := 0; i < concLevel; i++ {
|
||||
vals := make([]float64, mutations)
|
||||
for j := 0; j < mutations; j++ {
|
||||
vals[j] = rand.Float64() - 0.5
|
||||
}
|
||||
|
||||
go func(vals []float64) {
|
||||
start.Wait()
|
||||
for _, v := range vals {
|
||||
sStream <- v
|
||||
gge.Add(v)
|
||||
}
|
||||
end.Done()
|
||||
}(vals)
|
||||
}
|
||||
start.Done()
|
||||
|
||||
if expected, got := <-result, math.Float64frombits(gge.(*value).valBits); math.Abs(expected-got) > 0.000001 {
|
||||
t.Fatalf("expected approx. %f, got %f", expected, got)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
if err := quick.Check(it, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGaugeVecConcurrency(t *testing.T) {
|
||||
it := func(n uint32) bool {
|
||||
mutations := int(n % 10000)
|
||||
concLevel := int(n%15 + 1)
|
||||
vecLength := int(n%5 + 1)
|
||||
|
||||
var start, end sync.WaitGroup
|
||||
start.Add(1)
|
||||
end.Add(concLevel)
|
||||
|
||||
sStreams := make([]chan float64, vecLength)
|
||||
results := make([]chan float64, vecLength)
|
||||
done := make(chan struct{})
|
||||
|
||||
for i := 0; i < vecLength; i++ {
|
||||
sStreams[i] = make(chan float64, mutations*concLevel)
|
||||
results[i] = make(chan float64)
|
||||
go listenGaugeStream(sStreams[i], results[i], done)
|
||||
}
|
||||
|
||||
go func() {
|
||||
end.Wait()
|
||||
close(done)
|
||||
}()
|
||||
|
||||
gge := NewGaugeVec(
|
||||
GaugeOpts{
|
||||
Name: "test_gauge",
|
||||
Help: "no help can be found here",
|
||||
},
|
||||
[]string{"label"},
|
||||
)
|
||||
for i := 0; i < concLevel; i++ {
|
||||
vals := make([]float64, mutations)
|
||||
pick := make([]int, mutations)
|
||||
for j := 0; j < mutations; j++ {
|
||||
vals[j] = rand.Float64() - 0.5
|
||||
pick[j] = rand.Intn(vecLength)
|
||||
}
|
||||
|
||||
go func(vals []float64) {
|
||||
start.Wait()
|
||||
for i, v := range vals {
|
||||
sStreams[pick[i]] <- v
|
||||
gge.WithLabelValues(string('A' + pick[i])).Add(v)
|
||||
}
|
||||
end.Done()
|
||||
}(vals)
|
||||
}
|
||||
start.Done()
|
||||
|
||||
for i := range sStreams {
|
||||
if expected, got := <-results[i], math.Float64frombits(gge.WithLabelValues(string('A'+i)).(*value).valBits); math.Abs(expected-got) > 0.000001 {
|
||||
t.Fatalf("expected approx. %f, got %f", expected, got)
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
if err := quick.Check(it, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGaugeFunc(t *testing.T) {
|
||||
gf := NewGaugeFunc(
|
||||
GaugeOpts{
|
||||
Name: "test_name",
|
||||
Help: "test help",
|
||||
ConstLabels: Labels{"a": "1", "b": "2"},
|
||||
},
|
||||
func() float64 { return 3.1415 },
|
||||
)
|
||||
|
||||
if expected, got := `Desc{fqName: "test_name", help: "test help", constLabels: {a="1",b="2"}, variableLabels: []}`, gf.Desc().String(); expected != got {
|
||||
t.Errorf("expected %q, got %q", expected, got)
|
||||
}
|
||||
|
||||
m := &dto.Metric{}
|
||||
gf.Write(m)
|
||||
|
||||
if expected, got := `label:<name:"a" value:"1" > label:<name:"b" value:"2" > gauge:<value:3.1415 > `, m.String(); expected != got {
|
||||
t.Errorf("expected %q, got %q", expected, got)
|
||||
}
|
||||
}
|
123
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/go_collector_test.go
generated
vendored
123
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/go_collector_test.go
generated
vendored
|
@ -1,123 +0,0 @@
|
|||
package prometheus
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
|
||||
)
|
||||
|
||||
func TestGoCollector(t *testing.T) {
|
||||
var (
|
||||
c = NewGoCollector()
|
||||
ch = make(chan Metric)
|
||||
waitc = make(chan struct{})
|
||||
closec = make(chan struct{})
|
||||
old = -1
|
||||
)
|
||||
defer close(closec)
|
||||
|
||||
go func() {
|
||||
c.Collect(ch)
|
||||
go func(c <-chan struct{}) {
|
||||
<-c
|
||||
}(closec)
|
||||
<-waitc
|
||||
c.Collect(ch)
|
||||
}()
|
||||
|
||||
for {
|
||||
select {
|
||||
case metric := <-ch:
|
||||
switch m := metric.(type) {
|
||||
// Attention, this also catches Counter...
|
||||
case Gauge:
|
||||
pb := &dto.Metric{}
|
||||
m.Write(pb)
|
||||
if pb.GetGauge() == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if old == -1 {
|
||||
old = int(pb.GetGauge().GetValue())
|
||||
close(waitc)
|
||||
continue
|
||||
}
|
||||
|
||||
if diff := int(pb.GetGauge().GetValue()) - old; diff != 1 {
|
||||
// TODO: This is flaky in highly concurrent situations.
|
||||
t.Errorf("want 1 new goroutine, got %d", diff)
|
||||
}
|
||||
|
||||
// GoCollector performs two sends per call.
|
||||
// On line 27 we need to receive the second send
|
||||
// to shut down cleanly.
|
||||
<-ch
|
||||
return
|
||||
}
|
||||
case <-time.After(1 * time.Second):
|
||||
t.Fatalf("expected collect timed out")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGCCollector(t *testing.T) {
|
||||
var (
|
||||
c = NewGoCollector()
|
||||
ch = make(chan Metric)
|
||||
waitc = make(chan struct{})
|
||||
closec = make(chan struct{})
|
||||
oldGC uint64
|
||||
oldPause float64
|
||||
)
|
||||
defer close(closec)
|
||||
|
||||
go func() {
|
||||
c.Collect(ch)
|
||||
// force GC
|
||||
runtime.GC()
|
||||
<-waitc
|
||||
c.Collect(ch)
|
||||
}()
|
||||
|
||||
first := true
|
||||
for {
|
||||
select {
|
||||
case metric := <-ch:
|
||||
switch m := metric.(type) {
|
||||
case *constSummary, *value:
|
||||
pb := &dto.Metric{}
|
||||
m.Write(pb)
|
||||
if pb.GetSummary() == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if len(pb.GetSummary().Quantile) != 5 {
|
||||
t.Errorf("expected 4 buckets, got %d", len(pb.GetSummary().Quantile))
|
||||
}
|
||||
for idx, want := range []float64{0.0, 0.25, 0.5, 0.75, 1.0} {
|
||||
if *pb.GetSummary().Quantile[idx].Quantile != want {
|
||||
t.Errorf("bucket #%d is off, got %f, want %f", idx, *pb.GetSummary().Quantile[idx].Quantile, want)
|
||||
}
|
||||
}
|
||||
if first {
|
||||
first = false
|
||||
oldGC = *pb.GetSummary().SampleCount
|
||||
oldPause = *pb.GetSummary().SampleSum
|
||||
close(waitc)
|
||||
continue
|
||||
}
|
||||
if diff := *pb.GetSummary().SampleCount - oldGC; diff != 1 {
|
||||
t.Errorf("want 1 new garbage collection run, got %d", diff)
|
||||
}
|
||||
if diff := *pb.GetSummary().SampleSum - oldPause; diff <= 0 {
|
||||
t.Errorf("want moar pause, got %f", diff)
|
||||
}
|
||||
return
|
||||
}
|
||||
case <-time.After(1 * time.Second):
|
||||
t.Fatalf("expected collect timed out")
|
||||
}
|
||||
}
|
||||
}
|
326
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/histogram_test.go
generated
vendored
326
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/histogram_test.go
generated
vendored
|
@ -1,326 +0,0 @@
|
|||
// Copyright 2015 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"sort"
|
||||
"sync"
|
||||
"testing"
|
||||
"testing/quick"
|
||||
|
||||
dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
|
||||
)
|
||||
|
||||
func benchmarkHistogramObserve(w int, b *testing.B) {
|
||||
b.StopTimer()
|
||||
|
||||
wg := new(sync.WaitGroup)
|
||||
wg.Add(w)
|
||||
|
||||
g := new(sync.WaitGroup)
|
||||
g.Add(1)
|
||||
|
||||
s := NewHistogram(HistogramOpts{})
|
||||
|
||||
for i := 0; i < w; i++ {
|
||||
go func() {
|
||||
g.Wait()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
s.Observe(float64(i))
|
||||
}
|
||||
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
b.StartTimer()
|
||||
g.Done()
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func BenchmarkHistogramObserve1(b *testing.B) {
|
||||
benchmarkHistogramObserve(1, b)
|
||||
}
|
||||
|
||||
func BenchmarkHistogramObserve2(b *testing.B) {
|
||||
benchmarkHistogramObserve(2, b)
|
||||
}
|
||||
|
||||
func BenchmarkHistogramObserve4(b *testing.B) {
|
||||
benchmarkHistogramObserve(4, b)
|
||||
}
|
||||
|
||||
func BenchmarkHistogramObserve8(b *testing.B) {
|
||||
benchmarkHistogramObserve(8, b)
|
||||
}
|
||||
|
||||
func benchmarkHistogramWrite(w int, b *testing.B) {
|
||||
b.StopTimer()
|
||||
|
||||
wg := new(sync.WaitGroup)
|
||||
wg.Add(w)
|
||||
|
||||
g := new(sync.WaitGroup)
|
||||
g.Add(1)
|
||||
|
||||
s := NewHistogram(HistogramOpts{})
|
||||
|
||||
for i := 0; i < 1000000; i++ {
|
||||
s.Observe(float64(i))
|
||||
}
|
||||
|
||||
for j := 0; j < w; j++ {
|
||||
outs := make([]dto.Metric, b.N)
|
||||
|
||||
go func(o []dto.Metric) {
|
||||
g.Wait()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
s.Write(&o[i])
|
||||
}
|
||||
|
||||
wg.Done()
|
||||
}(outs)
|
||||
}
|
||||
|
||||
b.StartTimer()
|
||||
g.Done()
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func BenchmarkHistogramWrite1(b *testing.B) {
|
||||
benchmarkHistogramWrite(1, b)
|
||||
}
|
||||
|
||||
func BenchmarkHistogramWrite2(b *testing.B) {
|
||||
benchmarkHistogramWrite(2, b)
|
||||
}
|
||||
|
||||
func BenchmarkHistogramWrite4(b *testing.B) {
|
||||
benchmarkHistogramWrite(4, b)
|
||||
}
|
||||
|
||||
func BenchmarkHistogramWrite8(b *testing.B) {
|
||||
benchmarkHistogramWrite(8, b)
|
||||
}
|
||||
|
||||
// Intentionally adding +Inf here to test if that case is handled correctly.
|
||||
// Also, getCumulativeCounts depends on it.
|
||||
var testBuckets = []float64{-2, -1, -0.5, 0, 0.5, 1, 2, math.Inf(+1)}
|
||||
|
||||
func TestHistogramConcurrency(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping test in short mode.")
|
||||
}
|
||||
|
||||
rand.Seed(42)
|
||||
|
||||
it := func(n uint32) bool {
|
||||
mutations := int(n%1e4 + 1e4)
|
||||
concLevel := int(n%5 + 1)
|
||||
total := mutations * concLevel
|
||||
|
||||
var start, end sync.WaitGroup
|
||||
start.Add(1)
|
||||
end.Add(concLevel)
|
||||
|
||||
sum := NewHistogram(HistogramOpts{
|
||||
Name: "test_histogram",
|
||||
Help: "helpless",
|
||||
Buckets: testBuckets,
|
||||
})
|
||||
|
||||
allVars := make([]float64, total)
|
||||
var sampleSum float64
|
||||
for i := 0; i < concLevel; i++ {
|
||||
vals := make([]float64, mutations)
|
||||
for j := 0; j < mutations; j++ {
|
||||
v := rand.NormFloat64()
|
||||
vals[j] = v
|
||||
allVars[i*mutations+j] = v
|
||||
sampleSum += v
|
||||
}
|
||||
|
||||
go func(vals []float64) {
|
||||
start.Wait()
|
||||
for _, v := range vals {
|
||||
sum.Observe(v)
|
||||
}
|
||||
end.Done()
|
||||
}(vals)
|
||||
}
|
||||
sort.Float64s(allVars)
|
||||
start.Done()
|
||||
end.Wait()
|
||||
|
||||
m := &dto.Metric{}
|
||||
sum.Write(m)
|
||||
if got, want := int(*m.Histogram.SampleCount), total; got != want {
|
||||
t.Errorf("got sample count %d, want %d", got, want)
|
||||
}
|
||||
if got, want := *m.Histogram.SampleSum, sampleSum; math.Abs((got-want)/want) > 0.001 {
|
||||
t.Errorf("got sample sum %f, want %f", got, want)
|
||||
}
|
||||
|
||||
wantCounts := getCumulativeCounts(allVars)
|
||||
|
||||
if got, want := len(m.Histogram.Bucket), len(testBuckets)-1; got != want {
|
||||
t.Errorf("got %d buckets in protobuf, want %d", got, want)
|
||||
}
|
||||
for i, wantBound := range testBuckets {
|
||||
if i == len(testBuckets)-1 {
|
||||
break // No +Inf bucket in protobuf.
|
||||
}
|
||||
if gotBound := *m.Histogram.Bucket[i].UpperBound; gotBound != wantBound {
|
||||
t.Errorf("got bound %f, want %f", gotBound, wantBound)
|
||||
}
|
||||
if gotCount, wantCount := *m.Histogram.Bucket[i].CumulativeCount, wantCounts[i]; gotCount != wantCount {
|
||||
t.Errorf("got count %d, want %d", gotCount, wantCount)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
if err := quick.Check(it, nil); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHistogramVecConcurrency(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping test in short mode.")
|
||||
}
|
||||
|
||||
rand.Seed(42)
|
||||
|
||||
objectives := make([]float64, 0, len(DefObjectives))
|
||||
for qu := range DefObjectives {
|
||||
|
||||
objectives = append(objectives, qu)
|
||||
}
|
||||
sort.Float64s(objectives)
|
||||
|
||||
it := func(n uint32) bool {
|
||||
mutations := int(n%1e4 + 1e4)
|
||||
concLevel := int(n%7 + 1)
|
||||
vecLength := int(n%3 + 1)
|
||||
|
||||
var start, end sync.WaitGroup
|
||||
start.Add(1)
|
||||
end.Add(concLevel)
|
||||
|
||||
his := NewHistogramVec(
|
||||
HistogramOpts{
|
||||
Name: "test_histogram",
|
||||
Help: "helpless",
|
||||
Buckets: []float64{-2, -1, -0.5, 0, 0.5, 1, 2, math.Inf(+1)},
|
||||
},
|
||||
[]string{"label"},
|
||||
)
|
||||
|
||||
allVars := make([][]float64, vecLength)
|
||||
sampleSums := make([]float64, vecLength)
|
||||
for i := 0; i < concLevel; i++ {
|
||||
vals := make([]float64, mutations)
|
||||
picks := make([]int, mutations)
|
||||
for j := 0; j < mutations; j++ {
|
||||
v := rand.NormFloat64()
|
||||
vals[j] = v
|
||||
pick := rand.Intn(vecLength)
|
||||
picks[j] = pick
|
||||
allVars[pick] = append(allVars[pick], v)
|
||||
sampleSums[pick] += v
|
||||
}
|
||||
|
||||
go func(vals []float64) {
|
||||
start.Wait()
|
||||
for i, v := range vals {
|
||||
his.WithLabelValues(string('A' + picks[i])).Observe(v)
|
||||
}
|
||||
end.Done()
|
||||
}(vals)
|
||||
}
|
||||
for _, vars := range allVars {
|
||||
sort.Float64s(vars)
|
||||
}
|
||||
start.Done()
|
||||
end.Wait()
|
||||
|
||||
for i := 0; i < vecLength; i++ {
|
||||
m := &dto.Metric{}
|
||||
s := his.WithLabelValues(string('A' + i))
|
||||
s.Write(m)
|
||||
|
||||
if got, want := len(m.Histogram.Bucket), len(testBuckets)-1; got != want {
|
||||
t.Errorf("got %d buckets in protobuf, want %d", got, want)
|
||||
}
|
||||
if got, want := int(*m.Histogram.SampleCount), len(allVars[i]); got != want {
|
||||
t.Errorf("got sample count %d, want %d", got, want)
|
||||
}
|
||||
if got, want := *m.Histogram.SampleSum, sampleSums[i]; math.Abs((got-want)/want) > 0.001 {
|
||||
t.Errorf("got sample sum %f, want %f", got, want)
|
||||
}
|
||||
|
||||
wantCounts := getCumulativeCounts(allVars[i])
|
||||
|
||||
for j, wantBound := range testBuckets {
|
||||
if j == len(testBuckets)-1 {
|
||||
break // No +Inf bucket in protobuf.
|
||||
}
|
||||
if gotBound := *m.Histogram.Bucket[j].UpperBound; gotBound != wantBound {
|
||||
t.Errorf("got bound %f, want %f", gotBound, wantBound)
|
||||
}
|
||||
if gotCount, wantCount := *m.Histogram.Bucket[j].CumulativeCount, wantCounts[j]; gotCount != wantCount {
|
||||
t.Errorf("got count %d, want %d", gotCount, wantCount)
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
if err := quick.Check(it, nil); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func getCumulativeCounts(vars []float64) []uint64 {
|
||||
counts := make([]uint64, len(testBuckets))
|
||||
for _, v := range vars {
|
||||
for i := len(testBuckets) - 1; i >= 0; i-- {
|
||||
if v > testBuckets[i] {
|
||||
break
|
||||
}
|
||||
counts[i]++
|
||||
}
|
||||
}
|
||||
return counts
|
||||
}
|
||||
|
||||
func TestBuckets(t *testing.T) {
|
||||
got := LinearBuckets(-15, 5, 6)
|
||||
want := []float64{-15, -10, -5, 0, 5, 10}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("linear buckets: got %v, want %v", got, want)
|
||||
}
|
||||
|
||||
got = ExponentialBuckets(100, 1.2, 3)
|
||||
want = []float64{100, 120, 144}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("linear buckets: got %v, want %v", got, want)
|
||||
}
|
||||
}
|
121
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/http_test.go
generated
vendored
121
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/http_test.go
generated
vendored
|
@ -1,121 +0,0 @@
|
|||
// Copyright 2014 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
|
||||
)
|
||||
|
||||
type respBody string
|
||||
|
||||
func (b respBody) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusTeapot)
|
||||
w.Write([]byte(b))
|
||||
}
|
||||
|
||||
func TestInstrumentHandler(t *testing.T) {
|
||||
defer func(n nower) {
|
||||
now = n.(nower)
|
||||
}(now)
|
||||
|
||||
instant := time.Now()
|
||||
end := instant.Add(30 * time.Second)
|
||||
now = nowSeries(instant, end)
|
||||
respBody := respBody("Howdy there!")
|
||||
|
||||
hndlr := InstrumentHandler("test-handler", respBody)
|
||||
|
||||
opts := SummaryOpts{
|
||||
Subsystem: "http",
|
||||
ConstLabels: Labels{"handler": "test-handler"},
|
||||
}
|
||||
|
||||
reqCnt := MustRegisterOrGet(NewCounterVec(
|
||||
CounterOpts{
|
||||
Namespace: opts.Namespace,
|
||||
Subsystem: opts.Subsystem,
|
||||
Name: "requests_total",
|
||||
Help: "Total number of HTTP requests made.",
|
||||
ConstLabels: opts.ConstLabels,
|
||||
},
|
||||
instLabels,
|
||||
)).(*CounterVec)
|
||||
|
||||
opts.Name = "request_duration_microseconds"
|
||||
opts.Help = "The HTTP request latencies in microseconds."
|
||||
reqDur := MustRegisterOrGet(NewSummary(opts)).(Summary)
|
||||
|
||||
opts.Name = "request_size_bytes"
|
||||
opts.Help = "The HTTP request sizes in bytes."
|
||||
MustRegisterOrGet(NewSummary(opts))
|
||||
|
||||
opts.Name = "response_size_bytes"
|
||||
opts.Help = "The HTTP response sizes in bytes."
|
||||
MustRegisterOrGet(NewSummary(opts))
|
||||
|
||||
reqCnt.Reset()
|
||||
|
||||
resp := httptest.NewRecorder()
|
||||
req := &http.Request{
|
||||
Method: "GET",
|
||||
}
|
||||
|
||||
hndlr.ServeHTTP(resp, req)
|
||||
|
||||
if resp.Code != http.StatusTeapot {
|
||||
t.Fatalf("expected status %d, got %d", http.StatusTeapot, resp.Code)
|
||||
}
|
||||
if string(resp.Body.Bytes()) != "Howdy there!" {
|
||||
t.Fatalf("expected body %s, got %s", "Howdy there!", string(resp.Body.Bytes()))
|
||||
}
|
||||
|
||||
out := &dto.Metric{}
|
||||
reqDur.Write(out)
|
||||
if want, got := "test-handler", out.Label[0].GetValue(); want != got {
|
||||
t.Errorf("want label value %q in reqDur, got %q", want, got)
|
||||
}
|
||||
if want, got := uint64(1), out.Summary.GetSampleCount(); want != got {
|
||||
t.Errorf("want sample count %d in reqDur, got %d", want, got)
|
||||
}
|
||||
|
||||
out.Reset()
|
||||
if want, got := 1, len(reqCnt.children); want != got {
|
||||
t.Errorf("want %d children in reqCnt, got %d", want, got)
|
||||
}
|
||||
cnt, err := reqCnt.GetMetricWithLabelValues("get", "418")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cnt.Write(out)
|
||||
if want, got := "418", out.Label[0].GetValue(); want != got {
|
||||
t.Errorf("want label value %q in reqCnt, got %q", want, got)
|
||||
}
|
||||
if want, got := "test-handler", out.Label[1].GetValue(); want != got {
|
||||
t.Errorf("want label value %q in reqCnt, got %q", want, got)
|
||||
}
|
||||
if want, got := "get", out.Label[2].GetValue(); want != got {
|
||||
t.Errorf("want label value %q in reqCnt, got %q", want, got)
|
||||
}
|
||||
if out.Counter == nil {
|
||||
t.Fatal("expected non-nil counter in reqCnt")
|
||||
}
|
||||
if want, got := 1., out.Counter.GetValue(); want != got {
|
||||
t.Errorf("want reqCnt of %f, got %f", want, got)
|
||||
}
|
||||
}
|
35
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/metric_test.go
generated
vendored
35
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/metric_test.go
generated
vendored
|
@ -1,35 +0,0 @@
|
|||
// Copyright 2014 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package prometheus
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestBuildFQName(t *testing.T) {
|
||||
scenarios := []struct{ namespace, subsystem, name, result string }{
|
||||
{"a", "b", "c", "a_b_c"},
|
||||
{"", "b", "c", "b_c"},
|
||||
{"a", "", "c", "a_c"},
|
||||
{"", "", "c", "c"},
|
||||
{"a", "b", "", ""},
|
||||
{"a", "", "", ""},
|
||||
{"", "b", "", ""},
|
||||
{" ", "", "", ""},
|
||||
}
|
||||
|
||||
for i, s := range scenarios {
|
||||
if want, got := s.result, BuildFQName(s.namespace, s.subsystem, s.name); want != got {
|
||||
t.Errorf("%d. want %s, got %s", i, want, got)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
package prometheus
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/procfs"
|
||||
)
|
||||
|
||||
func TestProcessCollector(t *testing.T) {
|
||||
if _, err := procfs.Self(); err != nil {
|
||||
t.Skipf("skipping TestProcessCollector, procfs not available: %s", err)
|
||||
}
|
||||
|
||||
registry := newRegistry()
|
||||
registry.Register(NewProcessCollector(os.Getpid(), ""))
|
||||
registry.Register(NewProcessCollectorPIDFn(
|
||||
func() (int, error) { return os.Getpid(), nil }, "foobar"))
|
||||
|
||||
s := httptest.NewServer(InstrumentHandler("prometheus", registry))
|
||||
defer s.Close()
|
||||
r, err := http.Get(s.URL)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer r.Body.Close()
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for _, re := range []*regexp.Regexp{
|
||||
regexp.MustCompile("process_cpu_seconds_total [0-9]"),
|
||||
regexp.MustCompile("process_max_fds [0-9]{2,}"),
|
||||
regexp.MustCompile("process_open_fds [1-9]"),
|
||||
regexp.MustCompile("process_virtual_memory_bytes [1-9]"),
|
||||
regexp.MustCompile("process_resident_memory_bytes [1-9]"),
|
||||
regexp.MustCompile("process_start_time_seconds [0-9.]{10,}"),
|
||||
regexp.MustCompile("foobar_process_cpu_seconds_total [0-9]"),
|
||||
regexp.MustCompile("foobar_process_max_fds [0-9]{2,}"),
|
||||
regexp.MustCompile("foobar_process_open_fds [1-9]"),
|
||||
regexp.MustCompile("foobar_process_virtual_memory_bytes [1-9]"),
|
||||
regexp.MustCompile("foobar_process_resident_memory_bytes [1-9]"),
|
||||
regexp.MustCompile("foobar_process_start_time_seconds [0-9.]{10,}"),
|
||||
} {
|
||||
if !re.Match(body) {
|
||||
t.Errorf("want body to match %s\n%s", re, body)
|
||||
}
|
||||
}
|
||||
}
|
535
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/registry_test.go
generated
vendored
535
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/registry_test.go
generated
vendored
|
@ -1,535 +0,0 @@
|
|||
// Copyright 2014 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Copyright (c) 2013, The Prometheus Authors
|
||||
// All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license that can be found
|
||||
// in the LICENSE file.
|
||||
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
|
||||
dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
|
||||
)
|
||||
|
||||
type fakeResponseWriter struct {
|
||||
header http.Header
|
||||
body bytes.Buffer
|
||||
}
|
||||
|
||||
func (r *fakeResponseWriter) Header() http.Header {
|
||||
return r.header
|
||||
}
|
||||
|
||||
func (r *fakeResponseWriter) Write(d []byte) (l int, err error) {
|
||||
return r.body.Write(d)
|
||||
}
|
||||
|
||||
func (r *fakeResponseWriter) WriteHeader(c int) {
|
||||
}
|
||||
|
||||
func testHandler(t testing.TB) {
|
||||
|
||||
metricVec := NewCounterVec(
|
||||
CounterOpts{
|
||||
Name: "name",
|
||||
Help: "docstring",
|
||||
ConstLabels: Labels{"constname": "constvalue"},
|
||||
},
|
||||
[]string{"labelname"},
|
||||
)
|
||||
|
||||
metricVec.WithLabelValues("val1").Inc()
|
||||
metricVec.WithLabelValues("val2").Inc()
|
||||
|
||||
varintBuf := make([]byte, binary.MaxVarintLen32)
|
||||
|
||||
externalMetricFamily := &dto.MetricFamily{
|
||||
Name: proto.String("externalname"),
|
||||
Help: proto.String("externaldocstring"),
|
||||
Type: dto.MetricType_COUNTER.Enum(),
|
||||
Metric: []*dto.Metric{
|
||||
{
|
||||
Label: []*dto.LabelPair{
|
||||
{
|
||||
Name: proto.String("externalconstname"),
|
||||
Value: proto.String("externalconstvalue"),
|
||||
},
|
||||
{
|
||||
Name: proto.String("externallabelname"),
|
||||
Value: proto.String("externalval1"),
|
||||
},
|
||||
},
|
||||
Counter: &dto.Counter{
|
||||
Value: proto.Float64(1),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
marshaledExternalMetricFamily, err := proto.Marshal(externalMetricFamily)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var externalBuf bytes.Buffer
|
||||
l := binary.PutUvarint(varintBuf, uint64(len(marshaledExternalMetricFamily)))
|
||||
_, err = externalBuf.Write(varintBuf[:l])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = externalBuf.Write(marshaledExternalMetricFamily)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
externalMetricFamilyAsBytes := externalBuf.Bytes()
|
||||
externalMetricFamilyAsText := []byte(`# HELP externalname externaldocstring
|
||||
# TYPE externalname counter
|
||||
externalname{externalconstname="externalconstvalue",externallabelname="externalval1"} 1
|
||||
`)
|
||||
externalMetricFamilyAsProtoText := []byte(`name: "externalname"
|
||||
help: "externaldocstring"
|
||||
type: COUNTER
|
||||
metric: <
|
||||
label: <
|
||||
name: "externalconstname"
|
||||
value: "externalconstvalue"
|
||||
>
|
||||
label: <
|
||||
name: "externallabelname"
|
||||
value: "externalval1"
|
||||
>
|
||||
counter: <
|
||||
value: 1
|
||||
>
|
||||
>
|
||||
|
||||
`)
|
||||
externalMetricFamilyAsProtoCompactText := []byte(`name:"externalname" help:"externaldocstring" type:COUNTER metric:<label:<name:"externalconstname" value:"externalconstvalue" > label:<name:"externallabelname" value:"externalval1" > counter:<value:1 > >
|
||||
`)
|
||||
|
||||
expectedMetricFamily := &dto.MetricFamily{
|
||||
Name: proto.String("name"),
|
||||
Help: proto.String("docstring"),
|
||||
Type: dto.MetricType_COUNTER.Enum(),
|
||||
Metric: []*dto.Metric{
|
||||
{
|
||||
Label: []*dto.LabelPair{
|
||||
{
|
||||
Name: proto.String("constname"),
|
||||
Value: proto.String("constvalue"),
|
||||
},
|
||||
{
|
||||
Name: proto.String("labelname"),
|
||||
Value: proto.String("val1"),
|
||||
},
|
||||
},
|
||||
Counter: &dto.Counter{
|
||||
Value: proto.Float64(1),
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: []*dto.LabelPair{
|
||||
{
|
||||
Name: proto.String("constname"),
|
||||
Value: proto.String("constvalue"),
|
||||
},
|
||||
{
|
||||
Name: proto.String("labelname"),
|
||||
Value: proto.String("val2"),
|
||||
},
|
||||
},
|
||||
Counter: &dto.Counter{
|
||||
Value: proto.Float64(1),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
marshaledExpectedMetricFamily, err := proto.Marshal(expectedMetricFamily)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
l = binary.PutUvarint(varintBuf, uint64(len(marshaledExpectedMetricFamily)))
|
||||
_, err = buf.Write(varintBuf[:l])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = buf.Write(marshaledExpectedMetricFamily)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expectedMetricFamilyAsBytes := buf.Bytes()
|
||||
expectedMetricFamilyAsText := []byte(`# HELP name docstring
|
||||
# TYPE name counter
|
||||
name{constname="constvalue",labelname="val1"} 1
|
||||
name{constname="constvalue",labelname="val2"} 1
|
||||
`)
|
||||
expectedMetricFamilyAsProtoText := []byte(`name: "name"
|
||||
help: "docstring"
|
||||
type: COUNTER
|
||||
metric: <
|
||||
label: <
|
||||
name: "constname"
|
||||
value: "constvalue"
|
||||
>
|
||||
label: <
|
||||
name: "labelname"
|
||||
value: "val1"
|
||||
>
|
||||
counter: <
|
||||
value: 1
|
||||
>
|
||||
>
|
||||
metric: <
|
||||
label: <
|
||||
name: "constname"
|
||||
value: "constvalue"
|
||||
>
|
||||
label: <
|
||||
name: "labelname"
|
||||
value: "val2"
|
||||
>
|
||||
counter: <
|
||||
value: 1
|
||||
>
|
||||
>
|
||||
|
||||
`)
|
||||
expectedMetricFamilyAsProtoCompactText := []byte(`name:"name" help:"docstring" type:COUNTER metric:<label:<name:"constname" value:"constvalue" > label:<name:"labelname" value:"val1" > counter:<value:1 > > metric:<label:<name:"constname" value:"constvalue" > label:<name:"labelname" value:"val2" > counter:<value:1 > >
|
||||
`)
|
||||
|
||||
externalMetricFamilyWithSameName := &dto.MetricFamily{
|
||||
Name: proto.String("name"),
|
||||
Help: proto.String("inconsistent help string does not matter here"),
|
||||
Type: dto.MetricType_COUNTER.Enum(),
|
||||
Metric: []*dto.Metric{
|
||||
{
|
||||
Label: []*dto.LabelPair{
|
||||
{
|
||||
Name: proto.String("constname"),
|
||||
Value: proto.String("constvalue"),
|
||||
},
|
||||
{
|
||||
Name: proto.String("labelname"),
|
||||
Value: proto.String("different_val"),
|
||||
},
|
||||
},
|
||||
Counter: &dto.Counter{
|
||||
Value: proto.Float64(42),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expectedMetricFamilyMergedWithExternalAsProtoCompactText := []byte(`name:"name" help:"docstring" type:COUNTER metric:<label:<name:"constname" value:"constvalue" > label:<name:"labelname" value:"different_val" > counter:<value:42 > > metric:<label:<name:"constname" value:"constvalue" > label:<name:"labelname" value:"val1" > counter:<value:1 > > metric:<label:<name:"constname" value:"constvalue" > label:<name:"labelname" value:"val2" > counter:<value:1 > >
|
||||
`)
|
||||
|
||||
type output struct {
|
||||
headers map[string]string
|
||||
body []byte
|
||||
}
|
||||
|
||||
var scenarios = []struct {
|
||||
headers map[string]string
|
||||
out output
|
||||
collector Collector
|
||||
externalMF []*dto.MetricFamily
|
||||
}{
|
||||
{ // 0
|
||||
headers: map[string]string{
|
||||
"Accept": "foo/bar;q=0.2, dings/bums;q=0.8",
|
||||
},
|
||||
out: output{
|
||||
headers: map[string]string{
|
||||
"Content-Type": `text/plain; version=0.0.4`,
|
||||
},
|
||||
body: []byte{},
|
||||
},
|
||||
},
|
||||
{ // 1
|
||||
headers: map[string]string{
|
||||
"Accept": "foo/bar;q=0.2, application/quark;q=0.8",
|
||||
},
|
||||
out: output{
|
||||
headers: map[string]string{
|
||||
"Content-Type": `text/plain; version=0.0.4`,
|
||||
},
|
||||
body: []byte{},
|
||||
},
|
||||
},
|
||||
{ // 2
|
||||
headers: map[string]string{
|
||||
"Accept": "foo/bar;q=0.2, application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=bla;q=0.8",
|
||||
},
|
||||
out: output{
|
||||
headers: map[string]string{
|
||||
"Content-Type": `text/plain; version=0.0.4`,
|
||||
},
|
||||
body: []byte{},
|
||||
},
|
||||
},
|
||||
{ // 3
|
||||
headers: map[string]string{
|
||||
"Accept": "text/plain;q=0.2, application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=delimited;q=0.8",
|
||||
},
|
||||
out: output{
|
||||
headers: map[string]string{
|
||||
"Content-Type": `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=delimited`,
|
||||
},
|
||||
body: []byte{},
|
||||
},
|
||||
},
|
||||
{ // 4
|
||||
headers: map[string]string{
|
||||
"Accept": "application/json",
|
||||
},
|
||||
out: output{
|
||||
headers: map[string]string{
|
||||
"Content-Type": `text/plain; version=0.0.4`,
|
||||
},
|
||||
body: expectedMetricFamilyAsText,
|
||||
},
|
||||
collector: metricVec,
|
||||
},
|
||||
{ // 5
|
||||
headers: map[string]string{
|
||||
"Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=delimited",
|
||||
},
|
||||
out: output{
|
||||
headers: map[string]string{
|
||||
"Content-Type": `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=delimited`,
|
||||
},
|
||||
body: expectedMetricFamilyAsBytes,
|
||||
},
|
||||
collector: metricVec,
|
||||
},
|
||||
{ // 6
|
||||
headers: map[string]string{
|
||||
"Accept": "application/json",
|
||||
},
|
||||
out: output{
|
||||
headers: map[string]string{
|
||||
"Content-Type": `text/plain; version=0.0.4`,
|
||||
},
|
||||
body: externalMetricFamilyAsText,
|
||||
},
|
||||
externalMF: []*dto.MetricFamily{externalMetricFamily},
|
||||
},
|
||||
{ // 7
|
||||
headers: map[string]string{
|
||||
"Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=delimited",
|
||||
},
|
||||
out: output{
|
||||
headers: map[string]string{
|
||||
"Content-Type": `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=delimited`,
|
||||
},
|
||||
body: externalMetricFamilyAsBytes,
|
||||
},
|
||||
externalMF: []*dto.MetricFamily{externalMetricFamily},
|
||||
},
|
||||
{ // 8
|
||||
headers: map[string]string{
|
||||
"Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=delimited",
|
||||
},
|
||||
out: output{
|
||||
headers: map[string]string{
|
||||
"Content-Type": `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=delimited`,
|
||||
},
|
||||
body: bytes.Join(
|
||||
[][]byte{
|
||||
externalMetricFamilyAsBytes,
|
||||
expectedMetricFamilyAsBytes,
|
||||
},
|
||||
[]byte{},
|
||||
),
|
||||
},
|
||||
collector: metricVec,
|
||||
externalMF: []*dto.MetricFamily{externalMetricFamily},
|
||||
},
|
||||
{ // 9
|
||||
headers: map[string]string{
|
||||
"Accept": "text/plain",
|
||||
},
|
||||
out: output{
|
||||
headers: map[string]string{
|
||||
"Content-Type": `text/plain; version=0.0.4`,
|
||||
},
|
||||
body: []byte{},
|
||||
},
|
||||
},
|
||||
{ // 10
|
||||
headers: map[string]string{
|
||||
"Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=bla;q=0.2, text/plain;q=0.5",
|
||||
},
|
||||
out: output{
|
||||
headers: map[string]string{
|
||||
"Content-Type": `text/plain; version=0.0.4`,
|
||||
},
|
||||
body: expectedMetricFamilyAsText,
|
||||
},
|
||||
collector: metricVec,
|
||||
},
|
||||
{ // 11
|
||||
headers: map[string]string{
|
||||
"Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=bla;q=0.2, text/plain;q=0.5;version=0.0.4",
|
||||
},
|
||||
out: output{
|
||||
headers: map[string]string{
|
||||
"Content-Type": `text/plain; version=0.0.4`,
|
||||
},
|
||||
body: bytes.Join(
|
||||
[][]byte{
|
||||
externalMetricFamilyAsText,
|
||||
expectedMetricFamilyAsText,
|
||||
},
|
||||
[]byte{},
|
||||
),
|
||||
},
|
||||
collector: metricVec,
|
||||
externalMF: []*dto.MetricFamily{externalMetricFamily},
|
||||
},
|
||||
{ // 12
|
||||
headers: map[string]string{
|
||||
"Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=delimited;q=0.2, text/plain;q=0.5;version=0.0.2",
|
||||
},
|
||||
out: output{
|
||||
headers: map[string]string{
|
||||
"Content-Type": `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=delimited`,
|
||||
},
|
||||
body: bytes.Join(
|
||||
[][]byte{
|
||||
externalMetricFamilyAsBytes,
|
||||
expectedMetricFamilyAsBytes,
|
||||
},
|
||||
[]byte{},
|
||||
),
|
||||
},
|
||||
collector: metricVec,
|
||||
externalMF: []*dto.MetricFamily{externalMetricFamily},
|
||||
},
|
||||
{ // 13
|
||||
headers: map[string]string{
|
||||
"Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=text;q=0.5, application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=delimited;q=0.4",
|
||||
},
|
||||
out: output{
|
||||
headers: map[string]string{
|
||||
"Content-Type": `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=text`,
|
||||
},
|
||||
body: bytes.Join(
|
||||
[][]byte{
|
||||
externalMetricFamilyAsProtoText,
|
||||
expectedMetricFamilyAsProtoText,
|
||||
},
|
||||
[]byte{},
|
||||
),
|
||||
},
|
||||
collector: metricVec,
|
||||
externalMF: []*dto.MetricFamily{externalMetricFamily},
|
||||
},
|
||||
{ // 14
|
||||
headers: map[string]string{
|
||||
"Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=compact-text",
|
||||
},
|
||||
out: output{
|
||||
headers: map[string]string{
|
||||
"Content-Type": `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=compact-text`,
|
||||
},
|
||||
body: bytes.Join(
|
||||
[][]byte{
|
||||
externalMetricFamilyAsProtoCompactText,
|
||||
expectedMetricFamilyAsProtoCompactText,
|
||||
},
|
||||
[]byte{},
|
||||
),
|
||||
},
|
||||
collector: metricVec,
|
||||
externalMF: []*dto.MetricFamily{externalMetricFamily},
|
||||
},
|
||||
{ // 15
|
||||
headers: map[string]string{
|
||||
"Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=compact-text",
|
||||
},
|
||||
out: output{
|
||||
headers: map[string]string{
|
||||
"Content-Type": `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=compact-text`,
|
||||
},
|
||||
body: bytes.Join(
|
||||
[][]byte{
|
||||
externalMetricFamilyAsProtoCompactText,
|
||||
expectedMetricFamilyMergedWithExternalAsProtoCompactText,
|
||||
},
|
||||
[]byte{},
|
||||
),
|
||||
},
|
||||
collector: metricVec,
|
||||
externalMF: []*dto.MetricFamily{
|
||||
externalMetricFamily,
|
||||
externalMetricFamilyWithSameName,
|
||||
},
|
||||
},
|
||||
}
|
||||
for i, scenario := range scenarios {
|
||||
registry := newRegistry()
|
||||
registry.collectChecksEnabled = true
|
||||
|
||||
if scenario.collector != nil {
|
||||
registry.Register(scenario.collector)
|
||||
}
|
||||
if scenario.externalMF != nil {
|
||||
registry.metricFamilyInjectionHook = func() []*dto.MetricFamily {
|
||||
return scenario.externalMF
|
||||
}
|
||||
}
|
||||
writer := &fakeResponseWriter{
|
||||
header: http.Header{},
|
||||
}
|
||||
handler := InstrumentHandler("prometheus", registry)
|
||||
request, _ := http.NewRequest("GET", "/", nil)
|
||||
for key, value := range scenario.headers {
|
||||
request.Header.Add(key, value)
|
||||
}
|
||||
handler(writer, request)
|
||||
|
||||
for key, value := range scenario.out.headers {
|
||||
if writer.Header().Get(key) != value {
|
||||
t.Errorf(
|
||||
"%d. expected %q for header %q, got %q",
|
||||
i, value, key, writer.Header().Get(key),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if !bytes.Equal(scenario.out.body, writer.body.Bytes()) {
|
||||
t.Errorf(
|
||||
"%d. expected %q for body, got %q",
|
||||
i, scenario.out.body, writer.body.Bytes(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandler(t *testing.T) {
|
||||
testHandler(t)
|
||||
}
|
||||
|
||||
func BenchmarkHandler(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
testHandler(b)
|
||||
}
|
||||
}
|
347
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/summary_test.go
generated
vendored
347
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/summary_test.go
generated
vendored
|
@ -1,347 +0,0 @@
|
|||
// Copyright 2014 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/rand"
|
||||
"sort"
|
||||
"sync"
|
||||
"testing"
|
||||
"testing/quick"
|
||||
"time"
|
||||
|
||||
dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
|
||||
)
|
||||
|
||||
func benchmarkSummaryObserve(w int, b *testing.B) {
|
||||
b.StopTimer()
|
||||
|
||||
wg := new(sync.WaitGroup)
|
||||
wg.Add(w)
|
||||
|
||||
g := new(sync.WaitGroup)
|
||||
g.Add(1)
|
||||
|
||||
s := NewSummary(SummaryOpts{})
|
||||
|
||||
for i := 0; i < w; i++ {
|
||||
go func() {
|
||||
g.Wait()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
s.Observe(float64(i))
|
||||
}
|
||||
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
b.StartTimer()
|
||||
g.Done()
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func BenchmarkSummaryObserve1(b *testing.B) {
|
||||
benchmarkSummaryObserve(1, b)
|
||||
}
|
||||
|
||||
func BenchmarkSummaryObserve2(b *testing.B) {
|
||||
benchmarkSummaryObserve(2, b)
|
||||
}
|
||||
|
||||
func BenchmarkSummaryObserve4(b *testing.B) {
|
||||
benchmarkSummaryObserve(4, b)
|
||||
}
|
||||
|
||||
func BenchmarkSummaryObserve8(b *testing.B) {
|
||||
benchmarkSummaryObserve(8, b)
|
||||
}
|
||||
|
||||
func benchmarkSummaryWrite(w int, b *testing.B) {
|
||||
b.StopTimer()
|
||||
|
||||
wg := new(sync.WaitGroup)
|
||||
wg.Add(w)
|
||||
|
||||
g := new(sync.WaitGroup)
|
||||
g.Add(1)
|
||||
|
||||
s := NewSummary(SummaryOpts{})
|
||||
|
||||
for i := 0; i < 1000000; i++ {
|
||||
s.Observe(float64(i))
|
||||
}
|
||||
|
||||
for j := 0; j < w; j++ {
|
||||
outs := make([]dto.Metric, b.N)
|
||||
|
||||
go func(o []dto.Metric) {
|
||||
g.Wait()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
s.Write(&o[i])
|
||||
}
|
||||
|
||||
wg.Done()
|
||||
}(outs)
|
||||
}
|
||||
|
||||
b.StartTimer()
|
||||
g.Done()
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func BenchmarkSummaryWrite1(b *testing.B) {
|
||||
benchmarkSummaryWrite(1, b)
|
||||
}
|
||||
|
||||
func BenchmarkSummaryWrite2(b *testing.B) {
|
||||
benchmarkSummaryWrite(2, b)
|
||||
}
|
||||
|
||||
func BenchmarkSummaryWrite4(b *testing.B) {
|
||||
benchmarkSummaryWrite(4, b)
|
||||
}
|
||||
|
||||
func BenchmarkSummaryWrite8(b *testing.B) {
|
||||
benchmarkSummaryWrite(8, b)
|
||||
}
|
||||
|
||||
func TestSummaryConcurrency(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping test in short mode.")
|
||||
}
|
||||
|
||||
rand.Seed(42)
|
||||
|
||||
it := func(n uint32) bool {
|
||||
mutations := int(n%1e4 + 1e4)
|
||||
concLevel := int(n%5 + 1)
|
||||
total := mutations * concLevel
|
||||
|
||||
var start, end sync.WaitGroup
|
||||
start.Add(1)
|
||||
end.Add(concLevel)
|
||||
|
||||
sum := NewSummary(SummaryOpts{
|
||||
Name: "test_summary",
|
||||
Help: "helpless",
|
||||
})
|
||||
|
||||
allVars := make([]float64, total)
|
||||
var sampleSum float64
|
||||
for i := 0; i < concLevel; i++ {
|
||||
vals := make([]float64, mutations)
|
||||
for j := 0; j < mutations; j++ {
|
||||
v := rand.NormFloat64()
|
||||
vals[j] = v
|
||||
allVars[i*mutations+j] = v
|
||||
sampleSum += v
|
||||
}
|
||||
|
||||
go func(vals []float64) {
|
||||
start.Wait()
|
||||
for _, v := range vals {
|
||||
sum.Observe(v)
|
||||
}
|
||||
end.Done()
|
||||
}(vals)
|
||||
}
|
||||
sort.Float64s(allVars)
|
||||
start.Done()
|
||||
end.Wait()
|
||||
|
||||
m := &dto.Metric{}
|
||||
sum.Write(m)
|
||||
if got, want := int(*m.Summary.SampleCount), total; got != want {
|
||||
t.Errorf("got sample count %d, want %d", got, want)
|
||||
}
|
||||
if got, want := *m.Summary.SampleSum, sampleSum; math.Abs((got-want)/want) > 0.001 {
|
||||
t.Errorf("got sample sum %f, want %f", got, want)
|
||||
}
|
||||
|
||||
objectives := make([]float64, 0, len(DefObjectives))
|
||||
for qu := range DefObjectives {
|
||||
objectives = append(objectives, qu)
|
||||
}
|
||||
sort.Float64s(objectives)
|
||||
|
||||
for i, wantQ := range objectives {
|
||||
ε := DefObjectives[wantQ]
|
||||
gotQ := *m.Summary.Quantile[i].Quantile
|
||||
gotV := *m.Summary.Quantile[i].Value
|
||||
min, max := getBounds(allVars, wantQ, ε)
|
||||
if gotQ != wantQ {
|
||||
t.Errorf("got quantile %f, want %f", gotQ, wantQ)
|
||||
}
|
||||
if gotV < min || gotV > max {
|
||||
t.Errorf("got %f for quantile %f, want [%f,%f]", gotV, gotQ, min, max)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
if err := quick.Check(it, nil); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSummaryVecConcurrency(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping test in short mode.")
|
||||
}
|
||||
|
||||
rand.Seed(42)
|
||||
|
||||
objectives := make([]float64, 0, len(DefObjectives))
|
||||
for qu := range DefObjectives {
|
||||
|
||||
objectives = append(objectives, qu)
|
||||
}
|
||||
sort.Float64s(objectives)
|
||||
|
||||
it := func(n uint32) bool {
|
||||
mutations := int(n%1e4 + 1e4)
|
||||
concLevel := int(n%7 + 1)
|
||||
vecLength := int(n%3 + 1)
|
||||
|
||||
var start, end sync.WaitGroup
|
||||
start.Add(1)
|
||||
end.Add(concLevel)
|
||||
|
||||
sum := NewSummaryVec(
|
||||
SummaryOpts{
|
||||
Name: "test_summary",
|
||||
Help: "helpless",
|
||||
},
|
||||
[]string{"label"},
|
||||
)
|
||||
|
||||
allVars := make([][]float64, vecLength)
|
||||
sampleSums := make([]float64, vecLength)
|
||||
for i := 0; i < concLevel; i++ {
|
||||
vals := make([]float64, mutations)
|
||||
picks := make([]int, mutations)
|
||||
for j := 0; j < mutations; j++ {
|
||||
v := rand.NormFloat64()
|
||||
vals[j] = v
|
||||
pick := rand.Intn(vecLength)
|
||||
picks[j] = pick
|
||||
allVars[pick] = append(allVars[pick], v)
|
||||
sampleSums[pick] += v
|
||||
}
|
||||
|
||||
go func(vals []float64) {
|
||||
start.Wait()
|
||||
for i, v := range vals {
|
||||
sum.WithLabelValues(string('A' + picks[i])).Observe(v)
|
||||
}
|
||||
end.Done()
|
||||
}(vals)
|
||||
}
|
||||
for _, vars := range allVars {
|
||||
sort.Float64s(vars)
|
||||
}
|
||||
start.Done()
|
||||
end.Wait()
|
||||
|
||||
for i := 0; i < vecLength; i++ {
|
||||
m := &dto.Metric{}
|
||||
s := sum.WithLabelValues(string('A' + i))
|
||||
s.Write(m)
|
||||
if got, want := int(*m.Summary.SampleCount), len(allVars[i]); got != want {
|
||||
t.Errorf("got sample count %d for label %c, want %d", got, 'A'+i, want)
|
||||
}
|
||||
if got, want := *m.Summary.SampleSum, sampleSums[i]; math.Abs((got-want)/want) > 0.001 {
|
||||
t.Errorf("got sample sum %f for label %c, want %f", got, 'A'+i, want)
|
||||
}
|
||||
for j, wantQ := range objectives {
|
||||
ε := DefObjectives[wantQ]
|
||||
gotQ := *m.Summary.Quantile[j].Quantile
|
||||
gotV := *m.Summary.Quantile[j].Value
|
||||
min, max := getBounds(allVars[i], wantQ, ε)
|
||||
if gotQ != wantQ {
|
||||
t.Errorf("got quantile %f for label %c, want %f", gotQ, 'A'+i, wantQ)
|
||||
}
|
||||
if gotV < min || gotV > max {
|
||||
t.Errorf("got %f for quantile %f for label %c, want [%f,%f]", gotV, gotQ, 'A'+i, min, max)
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
if err := quick.Check(it, nil); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSummaryDecay(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping test in short mode.")
|
||||
// More because it depends on timing than because it is particularly long...
|
||||
}
|
||||
|
||||
sum := NewSummary(SummaryOpts{
|
||||
Name: "test_summary",
|
||||
Help: "helpless",
|
||||
MaxAge: 100 * time.Millisecond,
|
||||
Objectives: map[float64]float64{0.1: 0.001},
|
||||
AgeBuckets: 10,
|
||||
})
|
||||
|
||||
m := &dto.Metric{}
|
||||
i := 0
|
||||
tick := time.NewTicker(time.Millisecond)
|
||||
for _ = range tick.C {
|
||||
i++
|
||||
sum.Observe(float64(i))
|
||||
if i%10 == 0 {
|
||||
sum.Write(m)
|
||||
if got, want := *m.Summary.Quantile[0].Value, math.Max(float64(i)/10, float64(i-90)); math.Abs(got-want) > 20 {
|
||||
t.Errorf("%d. got %f, want %f", i, got, want)
|
||||
}
|
||||
m.Reset()
|
||||
}
|
||||
if i >= 1000 {
|
||||
break
|
||||
}
|
||||
}
|
||||
tick.Stop()
|
||||
// Wait for MaxAge without observations and make sure quantiles are NaN.
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
sum.Write(m)
|
||||
if got := *m.Summary.Quantile[0].Value; !math.IsNaN(got) {
|
||||
t.Errorf("got %f, want NaN after expiration", got)
|
||||
}
|
||||
}
|
||||
|
||||
func getBounds(vars []float64, q, ε float64) (min, max float64) {
|
||||
// TODO: This currently tolerates an error of up to 2*ε. The error must
|
||||
// be at most ε, but for some reason, it's sometimes slightly
|
||||
// higher. That's a bug.
|
||||
n := float64(len(vars))
|
||||
lower := int((q - 2*ε) * n)
|
||||
upper := int(math.Ceil((q + 2*ε) * n))
|
||||
min = vars[0]
|
||||
if lower > 1 {
|
||||
min = vars[lower-1]
|
||||
}
|
||||
max = vars[len(vars)-1]
|
||||
if upper < len(vars) {
|
||||
max = vars[upper-1]
|
||||
}
|
||||
return
|
||||
}
|
91
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/vec_test.go
generated
vendored
91
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/vec_test.go
generated
vendored
|
@ -1,91 +0,0 @@
|
|||
// Copyright 2014 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
"hash/fnv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDelete(t *testing.T) {
|
||||
desc := NewDesc("test", "helpless", []string{"l1", "l2"}, nil)
|
||||
vec := MetricVec{
|
||||
children: map[uint64]Metric{},
|
||||
desc: desc,
|
||||
hash: fnv.New64a(),
|
||||
newMetric: func(lvs ...string) Metric {
|
||||
return newValue(desc, UntypedValue, 0, lvs...)
|
||||
},
|
||||
}
|
||||
|
||||
if got, want := vec.Delete(Labels{"l1": "v1", "l2": "v2"}), false; got != want {
|
||||
t.Errorf("got %v, want %v", got, want)
|
||||
}
|
||||
|
||||
vec.With(Labels{"l1": "v1", "l2": "v2"}).(Untyped).Set(42)
|
||||
if got, want := vec.Delete(Labels{"l1": "v1", "l2": "v2"}), true; got != want {
|
||||
t.Errorf("got %v, want %v", got, want)
|
||||
}
|
||||
if got, want := vec.Delete(Labels{"l1": "v1", "l2": "v2"}), false; got != want {
|
||||
t.Errorf("got %v, want %v", got, want)
|
||||
}
|
||||
|
||||
vec.With(Labels{"l1": "v1", "l2": "v2"}).(Untyped).Set(42)
|
||||
if got, want := vec.Delete(Labels{"l2": "v2", "l1": "v1"}), true; got != want {
|
||||
t.Errorf("got %v, want %v", got, want)
|
||||
}
|
||||
if got, want := vec.Delete(Labels{"l2": "v2", "l1": "v1"}), false; got != want {
|
||||
t.Errorf("got %v, want %v", got, want)
|
||||
}
|
||||
|
||||
vec.With(Labels{"l1": "v1", "l2": "v2"}).(Untyped).Set(42)
|
||||
if got, want := vec.Delete(Labels{"l2": "v1", "l1": "v2"}), false; got != want {
|
||||
t.Errorf("got %v, want %v", got, want)
|
||||
}
|
||||
if got, want := vec.Delete(Labels{"l1": "v1"}), false; got != want {
|
||||
t.Errorf("got %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteLabelValues(t *testing.T) {
|
||||
desc := NewDesc("test", "helpless", []string{"l1", "l2"}, nil)
|
||||
vec := MetricVec{
|
||||
children: map[uint64]Metric{},
|
||||
desc: desc,
|
||||
hash: fnv.New64a(),
|
||||
newMetric: func(lvs ...string) Metric {
|
||||
return newValue(desc, UntypedValue, 0, lvs...)
|
||||
},
|
||||
}
|
||||
|
||||
if got, want := vec.DeleteLabelValues("v1", "v2"), false; got != want {
|
||||
t.Errorf("got %v, want %v", got, want)
|
||||
}
|
||||
|
||||
vec.With(Labels{"l1": "v1", "l2": "v2"}).(Untyped).Set(42)
|
||||
if got, want := vec.DeleteLabelValues("v1", "v2"), true; got != want {
|
||||
t.Errorf("got %v, want %v", got, want)
|
||||
}
|
||||
if got, want := vec.DeleteLabelValues("v1", "v2"), false; got != want {
|
||||
t.Errorf("got %v, want %v", got, want)
|
||||
}
|
||||
|
||||
vec.With(Labels{"l1": "v1", "l2": "v2"}).(Untyped).Set(42)
|
||||
if got, want := vec.DeleteLabelValues("v2", "v1"), false; got != want {
|
||||
t.Errorf("got %v, want %v", got, want)
|
||||
}
|
||||
if got, want := vec.DeleteLabelValues("v1"), false; got != want {
|
||||
t.Errorf("got %v, want %v", got, want)
|
||||
}
|
||||
}
|
|
@ -1,170 +0,0 @@
|
|||
// Copyright 2015 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expfmt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/matttproud/golang_protobuf_extensions/pbutil"
|
||||
dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
|
||||
)
|
||||
|
||||
var parser TextParser
|
||||
|
||||
// Benchmarks to show how much penalty text format parsing actually inflicts.
|
||||
//
|
||||
// Example results on Linux 3.13.0, Intel(R) Core(TM) i7-4700MQ CPU @ 2.40GHz, go1.4.
|
||||
//
|
||||
// BenchmarkParseText 1000 1188535 ns/op 205085 B/op 6135 allocs/op
|
||||
// BenchmarkParseTextGzip 1000 1376567 ns/op 246224 B/op 6151 allocs/op
|
||||
// BenchmarkParseProto 10000 172790 ns/op 52258 B/op 1160 allocs/op
|
||||
// BenchmarkParseProtoGzip 5000 324021 ns/op 94931 B/op 1211 allocs/op
|
||||
// BenchmarkParseProtoMap 10000 187946 ns/op 58714 B/op 1203 allocs/op
|
||||
//
|
||||
// CONCLUSION: The overhead for the map is negligible. Text format needs ~5x more allocations.
|
||||
// Without compression, it needs ~7x longer, but with compression (the more relevant scenario),
|
||||
// the difference becomes less relevant, only ~4x.
|
||||
//
|
||||
// The test data contains 248 samples.
|
||||
//
|
||||
// BenchmarkProcessor002ParseOnly in the extraction package is not quite
|
||||
// comparable to the benchmarks here, but it gives an idea: JSON parsing is even
|
||||
// slower than text parsing and needs a comparable amount of allocs.
|
||||
|
||||
// BenchmarkParseText benchmarks the parsing of a text-format scrape into metric
|
||||
// family DTOs.
|
||||
func BenchmarkParseText(b *testing.B) {
|
||||
b.StopTimer()
|
||||
data, err := ioutil.ReadFile("testdata/text")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
b.StartTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := parser.TextToMetricFamilies(bytes.NewReader(data)); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// BenchmarkParseTextGzip benchmarks the parsing of a gzipped text-format scrape
|
||||
// into metric family DTOs.
|
||||
func BenchmarkParseTextGzip(b *testing.B) {
|
||||
b.StopTimer()
|
||||
data, err := ioutil.ReadFile("testdata/text.gz")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
b.StartTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
in, err := gzip.NewReader(bytes.NewReader(data))
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
if _, err := parser.TextToMetricFamilies(in); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// BenchmarkParseProto benchmarks the parsing of a protobuf-format scrape into
|
||||
// metric family DTOs. Note that this does not build a map of metric families
|
||||
// (as the text version does), because it is not required for Prometheus
|
||||
// ingestion either. (However, it is required for the text-format parsing, as
|
||||
// the metric family might be sprinkled all over the text, while the
|
||||
// protobuf-format guarantees bundling at one place.)
|
||||
func BenchmarkParseProto(b *testing.B) {
|
||||
b.StopTimer()
|
||||
data, err := ioutil.ReadFile("testdata/protobuf")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
b.StartTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
family := &dto.MetricFamily{}
|
||||
in := bytes.NewReader(data)
|
||||
for {
|
||||
family.Reset()
|
||||
if _, err := pbutil.ReadDelimited(in, family); err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// BenchmarkParseProtoGzip is like BenchmarkParseProto above, but parses gzipped
|
||||
// protobuf format.
|
||||
func BenchmarkParseProtoGzip(b *testing.B) {
|
||||
b.StopTimer()
|
||||
data, err := ioutil.ReadFile("testdata/protobuf.gz")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
b.StartTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
family := &dto.MetricFamily{}
|
||||
in, err := gzip.NewReader(bytes.NewReader(data))
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
for {
|
||||
family.Reset()
|
||||
if _, err := pbutil.ReadDelimited(in, family); err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// BenchmarkParseProtoMap is like BenchmarkParseProto but DOES put the parsed
|
||||
// metric family DTOs into a map. This is not happening during Prometheus
|
||||
// ingestion. It is just here to measure the overhead of that map creation and
|
||||
// separate it from the overhead of the text format parsing.
|
||||
func BenchmarkParseProtoMap(b *testing.B) {
|
||||
b.StopTimer()
|
||||
data, err := ioutil.ReadFile("testdata/protobuf")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
b.StartTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
families := map[string]*dto.MetricFamily{}
|
||||
in := bytes.NewReader(data)
|
||||
for {
|
||||
family := &dto.MetricFamily{}
|
||||
if _, err := pbutil.ReadDelimited(in, family); err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
b.Fatal(err)
|
||||
}
|
||||
families[family.GetName()] = family
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,356 +0,0 @@
|
|||
// Copyright 2015 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package expfmt
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/common/model"
|
||||
)
|
||||
|
||||
func TestTextDecoder(t *testing.T) {
|
||||
var (
|
||||
ts = model.Now()
|
||||
in = `
|
||||
# Only a quite simple scenario with two metric families.
|
||||
# More complicated tests of the parser itself can be found in the text package.
|
||||
# TYPE mf2 counter
|
||||
mf2 3
|
||||
mf1{label="value1"} -3.14 123456
|
||||
mf1{label="value2"} 42
|
||||
mf2 4
|
||||
`
|
||||
out = model.Vector{
|
||||
&model.Sample{
|
||||
Metric: model.Metric{
|
||||
model.MetricNameLabel: "mf1",
|
||||
"label": "value1",
|
||||
},
|
||||
Value: -3.14,
|
||||
Timestamp: 123456,
|
||||
},
|
||||
&model.Sample{
|
||||
Metric: model.Metric{
|
||||
model.MetricNameLabel: "mf1",
|
||||
"label": "value2",
|
||||
},
|
||||
Value: 42,
|
||||
Timestamp: ts,
|
||||
},
|
||||
&model.Sample{
|
||||
Metric: model.Metric{
|
||||
model.MetricNameLabel: "mf2",
|
||||
},
|
||||
Value: 3,
|
||||
Timestamp: ts,
|
||||
},
|
||||
&model.Sample{
|
||||
Metric: model.Metric{
|
||||
model.MetricNameLabel: "mf2",
|
||||
},
|
||||
Value: 4,
|
||||
Timestamp: ts,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
dec := &SampleDecoder{
|
||||
Dec: &textDecoder{r: strings.NewReader(in)},
|
||||
Opts: &DecodeOptions{
|
||||
Timestamp: ts,
|
||||
},
|
||||
}
|
||||
var all model.Vector
|
||||
for {
|
||||
var smpls model.Vector
|
||||
err := dec.Decode(&smpls)
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
all = append(all, smpls...)
|
||||
}
|
||||
sort.Sort(all)
|
||||
sort.Sort(out)
|
||||
if !reflect.DeepEqual(all, out) {
|
||||
t.Fatalf("output does not match")
|
||||
}
|
||||
}
|
||||
|
||||
func TestProtoDecoder(t *testing.T) {
|
||||
|
||||
var testTime = model.Now()
|
||||
|
||||
scenarios := []struct {
|
||||
in string
|
||||
expected model.Vector
|
||||
}{
|
||||
{
|
||||
in: "",
|
||||
},
|
||||
{
|
||||
in: "\x8f\x01\n\rrequest_count\x12\x12Number of requests\x18\x00\"0\n#\n\x0fsome_label_name\x12\x10some_label_value\x1a\t\t\x00\x00\x00\x00\x00\x00E\xc0\"6\n)\n\x12another_label_name\x12\x13another_label_value\x1a\t\t\x00\x00\x00\x00\x00\x00U@",
|
||||
expected: model.Vector{
|
||||
&model.Sample{
|
||||
Metric: model.Metric{
|
||||
model.MetricNameLabel: "request_count",
|
||||
"some_label_name": "some_label_value",
|
||||
},
|
||||
Value: -42,
|
||||
Timestamp: testTime,
|
||||
},
|
||||
&model.Sample{
|
||||
Metric: model.Metric{
|
||||
model.MetricNameLabel: "request_count",
|
||||
"another_label_name": "another_label_value",
|
||||
},
|
||||
Value: 84,
|
||||
Timestamp: testTime,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
in: "\xb9\x01\n\rrequest_count\x12\x12Number of requests\x18\x02\"O\n#\n\x0fsome_label_name\x12\x10some_label_value\"(\x1a\x12\t\xaeG\xe1z\x14\xae\xef?\x11\x00\x00\x00\x00\x00\x00E\xc0\x1a\x12\t+\x87\x16\xd9\xce\xf7\xef?\x11\x00\x00\x00\x00\x00\x00U\xc0\"A\n)\n\x12another_label_name\x12\x13another_label_value\"\x14\x1a\x12\t\x00\x00\x00\x00\x00\x00\xe0?\x11\x00\x00\x00\x00\x00\x00$@",
|
||||
expected: model.Vector{
|
||||
&model.Sample{
|
||||
Metric: model.Metric{
|
||||
model.MetricNameLabel: "request_count_count",
|
||||
"some_label_name": "some_label_value",
|
||||
},
|
||||
Value: 0,
|
||||
Timestamp: testTime,
|
||||
},
|
||||
&model.Sample{
|
||||
Metric: model.Metric{
|
||||
model.MetricNameLabel: "request_count_sum",
|
||||
"some_label_name": "some_label_value",
|
||||
},
|
||||
Value: 0,
|
||||
Timestamp: testTime,
|
||||
},
|
||||
&model.Sample{
|
||||
Metric: model.Metric{
|
||||
model.MetricNameLabel: "request_count",
|
||||
"some_label_name": "some_label_value",
|
||||
"quantile": "0.99",
|
||||
},
|
||||
Value: -42,
|
||||
Timestamp: testTime,
|
||||
},
|
||||
&model.Sample{
|
||||
Metric: model.Metric{
|
||||
model.MetricNameLabel: "request_count",
|
||||
"some_label_name": "some_label_value",
|
||||
"quantile": "0.999",
|
||||
},
|
||||
Value: -84,
|
||||
Timestamp: testTime,
|
||||
},
|
||||
&model.Sample{
|
||||
Metric: model.Metric{
|
||||
model.MetricNameLabel: "request_count_count",
|
||||
"another_label_name": "another_label_value",
|
||||
},
|
||||
Value: 0,
|
||||
Timestamp: testTime,
|
||||
},
|
||||
&model.Sample{
|
||||
Metric: model.Metric{
|
||||
model.MetricNameLabel: "request_count_sum",
|
||||
"another_label_name": "another_label_value",
|
||||
},
|
||||
Value: 0,
|
||||
Timestamp: testTime,
|
||||
},
|
||||
&model.Sample{
|
||||
Metric: model.Metric{
|
||||
model.MetricNameLabel: "request_count",
|
||||
"another_label_name": "another_label_value",
|
||||
"quantile": "0.5",
|
||||
},
|
||||
Value: 10,
|
||||
Timestamp: testTime,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
in: "\x8d\x01\n\x1drequest_duration_microseconds\x12\x15The response latency.\x18\x04\"S:Q\b\x85\x15\x11\xcd\xcc\xccL\x8f\xcb:A\x1a\v\b{\x11\x00\x00\x00\x00\x00\x00Y@\x1a\f\b\x9c\x03\x11\x00\x00\x00\x00\x00\x00^@\x1a\f\b\xd0\x04\x11\x00\x00\x00\x00\x00\x00b@\x1a\f\b\xf4\v\x11\x9a\x99\x99\x99\x99\x99e@\x1a\f\b\x85\x15\x11\x00\x00\x00\x00\x00\x00\xf0\u007f",
|
||||
expected: model.Vector{
|
||||
&model.Sample{
|
||||
Metric: model.Metric{
|
||||
model.MetricNameLabel: "request_duration_microseconds_bucket",
|
||||
"le": "100",
|
||||
},
|
||||
Value: 123,
|
||||
Timestamp: testTime,
|
||||
},
|
||||
&model.Sample{
|
||||
Metric: model.Metric{
|
||||
model.MetricNameLabel: "request_duration_microseconds_bucket",
|
||||
"le": "120",
|
||||
},
|
||||
Value: 412,
|
||||
Timestamp: testTime,
|
||||
},
|
||||
&model.Sample{
|
||||
Metric: model.Metric{
|
||||
model.MetricNameLabel: "request_duration_microseconds_bucket",
|
||||
"le": "144",
|
||||
},
|
||||
Value: 592,
|
||||
Timestamp: testTime,
|
||||
},
|
||||
&model.Sample{
|
||||
Metric: model.Metric{
|
||||
model.MetricNameLabel: "request_duration_microseconds_bucket",
|
||||
"le": "172.8",
|
||||
},
|
||||
Value: 1524,
|
||||
Timestamp: testTime,
|
||||
},
|
||||
&model.Sample{
|
||||
Metric: model.Metric{
|
||||
model.MetricNameLabel: "request_duration_microseconds_bucket",
|
||||
"le": "+Inf",
|
||||
},
|
||||
Value: 2693,
|
||||
Timestamp: testTime,
|
||||
},
|
||||
&model.Sample{
|
||||
Metric: model.Metric{
|
||||
model.MetricNameLabel: "request_duration_microseconds_sum",
|
||||
},
|
||||
Value: 1756047.3,
|
||||
Timestamp: testTime,
|
||||
},
|
||||
&model.Sample{
|
||||
Metric: model.Metric{
|
||||
model.MetricNameLabel: "request_duration_microseconds_count",
|
||||
},
|
||||
Value: 2693,
|
||||
Timestamp: testTime,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
// The metric type is unset in this protobuf, which needs to be handled
|
||||
// correctly by the decoder.
|
||||
in: "\x1c\n\rrequest_count\"\v\x1a\t\t\x00\x00\x00\x00\x00\x00\xf0?",
|
||||
expected: model.Vector{
|
||||
&model.Sample{
|
||||
Metric: model.Metric{
|
||||
model.MetricNameLabel: "request_count",
|
||||
},
|
||||
Value: 1,
|
||||
Timestamp: testTime,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, scenario := range scenarios {
|
||||
dec := &SampleDecoder{
|
||||
Dec: &protoDecoder{r: strings.NewReader(scenario.in)},
|
||||
Opts: &DecodeOptions{
|
||||
Timestamp: testTime,
|
||||
},
|
||||
}
|
||||
|
||||
var all model.Vector
|
||||
for {
|
||||
var smpls model.Vector
|
||||
err := dec.Decode(&smpls)
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
all = append(all, smpls...)
|
||||
}
|
||||
sort.Sort(all)
|
||||
sort.Sort(scenario.expected)
|
||||
if !reflect.DeepEqual(all, scenario.expected) {
|
||||
t.Fatalf("%d. output does not match, want: %#v, got %#v", i, scenario.expected, all)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testDiscriminatorHTTPHeader(t testing.TB) {
|
||||
var scenarios = []struct {
|
||||
input map[string]string
|
||||
output Format
|
||||
err error
|
||||
}{
|
||||
{
|
||||
input: map[string]string{"Content-Type": `application/vnd.google.protobuf; proto="io.prometheus.client.MetricFamily"; encoding="delimited"`},
|
||||
output: FmtProtoDelim,
|
||||
},
|
||||
{
|
||||
input: map[string]string{"Content-Type": `application/vnd.google.protobuf; proto="illegal"; encoding="delimited"`},
|
||||
output: FmtUnknown,
|
||||
},
|
||||
{
|
||||
input: map[string]string{"Content-Type": `application/vnd.google.protobuf; proto="io.prometheus.client.MetricFamily"; encoding="illegal"`},
|
||||
output: FmtUnknown,
|
||||
},
|
||||
{
|
||||
input: map[string]string{"Content-Type": `text/plain; version=0.0.4`},
|
||||
output: FmtText,
|
||||
},
|
||||
{
|
||||
input: map[string]string{"Content-Type": `text/plain`},
|
||||
output: FmtText,
|
||||
},
|
||||
{
|
||||
input: map[string]string{"Content-Type": `text/plain; version=0.0.3`},
|
||||
output: FmtUnknown,
|
||||
},
|
||||
}
|
||||
|
||||
for i, scenario := range scenarios {
|
||||
var header http.Header
|
||||
|
||||
if len(scenario.input) > 0 {
|
||||
header = http.Header{}
|
||||
}
|
||||
|
||||
for key, value := range scenario.input {
|
||||
header.Add(key, value)
|
||||
}
|
||||
|
||||
actual := ResponseFormat(header)
|
||||
|
||||
if scenario.output != actual {
|
||||
t.Errorf("%d. expected %s, got %s", i, scenario.output, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDiscriminatorHTTPHeader(t *testing.T) {
|
||||
testDiscriminatorHTTPHeader(t)
|
||||
}
|
||||
|
||||
func BenchmarkDiscriminatorHTTPHeader(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
testDiscriminatorHTTPHeader(b)
|
||||
}
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
|
||||
minimal_metric 1.234
|
||||
another_metric -3e3 103948
|
||||
# Even that:
|
||||
no_labels{} 3
|
||||
# HELP line for non-existing metric will be ignored.
|
12
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_2
generated
vendored
12
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_2
generated
vendored
|
@ -1,12 +0,0 @@
|
|||
|
||||
# A normal comment.
|
||||
#
|
||||
# TYPE name counter
|
||||
name{labelname="val1",basename="basevalue"} NaN
|
||||
name {labelname="val2",basename="base\"v\\al\nue"} 0.23 1234567890
|
||||
# HELP name two-line\n doc str\\ing
|
||||
|
||||
# HELP name2 doc str"ing 2
|
||||
# TYPE name2 gauge
|
||||
name2{labelname="val2" ,basename = "basevalue2" } +Inf 54321
|
||||
name2{ labelname = "val1" , }-Inf
|
22
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_3
generated
vendored
22
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_3
generated
vendored
|
@ -1,22 +0,0 @@
|
|||
|
||||
# TYPE my_summary summary
|
||||
my_summary{n1="val1",quantile="0.5"} 110
|
||||
decoy -1 -2
|
||||
my_summary{n1="val1",quantile="0.9"} 140 1
|
||||
my_summary_count{n1="val1"} 42
|
||||
# Latest timestamp wins in case of a summary.
|
||||
my_summary_sum{n1="val1"} 4711 2
|
||||
fake_sum{n1="val1"} 2001
|
||||
# TYPE another_summary summary
|
||||
another_summary_count{n2="val2",n1="val1"} 20
|
||||
my_summary_count{n2="val2",n1="val1"} 5 5
|
||||
another_summary{n1="val1",n2="val2",quantile=".3"} -1.2
|
||||
my_summary_sum{n1="val2"} 08 15
|
||||
my_summary{n1="val3", quantile="0.2"} 4711
|
||||
my_summary{n1="val1",n2="val2",quantile="-12.34",} NaN
|
||||
# some
|
||||
# funny comments
|
||||
# HELP
|
||||
# HELP
|
||||
# HELP my_summary
|
||||
# HELP my_summary
|
10
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_4
generated
vendored
10
Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_4
generated
vendored
|
@ -1,10 +0,0 @@
|
|||
|
||||
# HELP request_duration_microseconds The response latency.
|
||||
# TYPE request_duration_microseconds histogram
|
||||
request_duration_microseconds_bucket{le="100"} 123
|
||||
request_duration_microseconds_bucket{le="120"} 412
|
||||
request_duration_microseconds_bucket{le="144"} 592
|
||||
request_duration_microseconds_bucket{le="172.8"} 1524
|
||||
request_duration_microseconds_bucket{le="+Inf"} 2693
|
||||
request_duration_microseconds_sum 1.7560473e+06
|
||||
request_duration_microseconds_count 2693
|
|
@ -1 +0,0 @@
|
|||
bla 3.14
|
|
@ -1 +0,0 @@
|
|||
metric{label="\t"} 3.14
|
|
@ -1 +0,0 @@
|
|||
metric{label="bla"} 3.14 2 3
|
|
@ -1 +0,0 @@
|
|||
metric{label="bla"} blubb
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
# HELP metric one
|
||||
# HELP metric two
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
# TYPE metric counter
|
||||
# TYPE metric untyped
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
metric 4.12
|
||||
# TYPE metric counter
|
|
@ -1,2 +0,0 @@
|
|||
|
||||
# TYPE metric bla
|
|
@ -1,2 +0,0 @@
|
|||
|
||||
# TYPE met-ric
|
|
@ -1 +0,0 @@
|
|||
@invalidmetric{label="bla"} 3.14 2
|
|
@ -1 +0,0 @@
|
|||
{label="bla"} 3.14 2
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
# TYPE metric histogram
|
||||
metric_bucket{le="bla"} 3.14
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
metric{label="new
|
||||
line"} 3.14
|
|
@ -1 +0,0 @@
|
|||
metric{@="bla"} 3.14
|
|
@ -1 +0,0 @@
|
|||
metric{__name__="bla"} 3.14
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue