vendor: remove dep and use vndr

Signed-off-by: Antonio Murdaca <runcom@redhat.com>
This commit is contained in:
Antonio Murdaca 2017-06-06 09:19:04 +02:00
parent 16f44674a4
commit 148e72d81e
No known key found for this signature in database
GPG key ID: B2BEAD150DE936B9
16131 changed files with 73815 additions and 4235138 deletions

View file

@ -1,50 +0,0 @@
# How to Contribute
## Getting Started
- Fork the repository on GitHub
- Read the [README](README.markdown) for build and test instructions
- Play with the project, submit bugs, submit patches!
## Contribution Flow
This is a rough outline of what a contributor's workflow looks like:
- Create a topic branch from where you want to base your work (usually master).
- Make commits of logical units.
- Make sure your commit messages are in the proper format (see below).
- Push your changes to a topic branch in your fork of the repository.
- Make sure the tests pass, and add any new tests as appropriate.
- Submit a pull request to the original repository.
Thanks for your contributions!
### Format of the Commit Message
We follow a rough convention for commit messages that is designed to answer two
questions: what changed and why. The subject line should feature the what and
the body of the commit should describe the why.
```
scripts: add the test-cluster command
this uses tmux to setup a test cluster that you can easily kill and
start for debugging.
Fixes #38
```
The format can be described more formally as follows:
```
<subsystem>: <what changed>
<BLANK LINE>
<why this change was made>
<BLANK LINE>
<footer>
```
The first line is the subject and should be no longer than 70 characters, the
second line is always blank, and other lines should be wrapped at 80 characters.
This allows the message to be easier to read on GitHub as well as in various
git tools.

View file

@ -1,2 +0,0 @@
Brandon Philips <brandon@ifup.org> (@philips)
Brian Waldon <brian@waldon.cc> (@bcwaldon)

View file

@ -1,30 +0,0 @@
package main
import (
"fmt"
"github.com/godbus/dbus"
"os"
)
func main() {
conn, err := dbus.SessionBus()
if err != nil {
fmt.Fprintln(os.Stderr, "Failed to connect to session bus:", err)
os.Exit(1)
}
for _, v := range []string{"method_call", "method_return", "error", "signal"} {
call := conn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0,
"eavesdrop='true',type='"+v+"'")
if call.Err != nil {
fmt.Fprintln(os.Stderr, "Failed to add match:", call.Err)
os.Exit(1)
}
}
c := make(chan *dbus.Message, 10)
conn.Eavesdrop(c)
fmt.Println("Listening for everything")
for v := range c {
fmt.Println(v)
}
}

View file

@ -1,21 +0,0 @@
package main
import (
"encoding/json"
"github.com/godbus/dbus"
"github.com/godbus/dbus/introspect"
"os"
)
func main() {
conn, err := dbus.SessionBus()
if err != nil {
panic(err)
}
node, err := introspect.Call(conn.Object("org.freedesktop.DBus", "/org/freedesktop/DBus"))
if err != nil {
panic(err)
}
data, _ := json.MarshalIndent(node, "", " ")
os.Stdout.Write(data)
}

View file

@ -1,27 +0,0 @@
package main
import (
"fmt"
"github.com/godbus/dbus"
"os"
)
func main() {
conn, err := dbus.SessionBus()
if err != nil {
fmt.Fprintln(os.Stderr, "Failed to connect to session bus:", err)
os.Exit(1)
}
var s []string
err = conn.BusObject().Call("org.freedesktop.DBus.ListNames", 0).Store(&s)
if err != nil {
fmt.Fprintln(os.Stderr, "Failed to get list of owned names:", err)
os.Exit(1)
}
fmt.Println("Currently owned names on the session bus:")
for _, v := range s {
fmt.Println(v)
}
}

View file

@ -1,17 +0,0 @@
package main
import "github.com/godbus/dbus"
func main() {
conn, err := dbus.SessionBus()
if err != nil {
panic(err)
}
obj := conn.Object("org.freedesktop.Notifications", "/org/freedesktop/Notifications")
call := obj.Call("org.freedesktop.Notifications.Notify", 0, "", uint32(0),
"", "Test", "This is a test of the DBus bindings for go.", []string{},
map[string]dbus.Variant{}, int32(5000))
if call.Err != nil {
panic(call.Err)
}
}

View file

@ -1,68 +0,0 @@
package main
import (
"fmt"
"github.com/godbus/dbus"
"github.com/godbus/dbus/introspect"
"github.com/godbus/dbus/prop"
"os"
)
type foo string
func (f foo) Foo() (string, *dbus.Error) {
fmt.Println(f)
return string(f), nil
}
func main() {
conn, err := dbus.SessionBus()
if err != nil {
panic(err)
}
reply, err := conn.RequestName("com.github.guelfey.Demo",
dbus.NameFlagDoNotQueue)
if err != nil {
panic(err)
}
if reply != dbus.RequestNameReplyPrimaryOwner {
fmt.Fprintln(os.Stderr, "name already taken")
os.Exit(1)
}
propsSpec := map[string]map[string]*prop.Prop{
"com.github.guelfey.Demo": {
"SomeInt": {
int32(0),
true,
prop.EmitTrue,
func(c *prop.Change) *dbus.Error {
fmt.Println(c.Name, "changed to", c.Value)
return nil
},
},
},
}
f := foo("Bar")
conn.Export(f, "/com/github/guelfey/Demo", "com.github.guelfey.Demo")
props := prop.New(conn, "/com/github/guelfey/Demo", propsSpec)
n := &introspect.Node{
Name: "/com/github/guelfey/Demo",
Interfaces: []introspect.Interface{
introspect.IntrospectData,
prop.IntrospectData,
{
Name: "com.github.guelfey.Demo",
Methods: introspect.Methods(f),
Properties: props.Introspection("com.github.guelfey.Demo"),
},
},
}
conn.Export(introspect.NewIntrospectable(n), "/com/github/guelfey/Demo",
"org.freedesktop.DBus.Introspectable")
fmt.Println("Listening on com.github.guelfey.Demo / /com/github/guelfey/Demo ...")
c := make(chan *dbus.Signal)
conn.Signal(c)
for _ = range c {
}
}

View file

@ -1,45 +0,0 @@
package main
import (
"fmt"
"github.com/godbus/dbus"
"github.com/godbus/dbus/introspect"
"os"
)
const intro = `
<node>
<interface name="com.github.guelfey.Demo">
<method name="Foo">
<arg direction="out" type="s"/>
</method>
</interface>` + introspect.IntrospectDataString + `</node> `
type foo string
func (f foo) Foo() (string, *dbus.Error) {
fmt.Println(f)
return string(f), nil
}
func main() {
conn, err := dbus.SessionBus()
if err != nil {
panic(err)
}
reply, err := conn.RequestName("com.github.guelfey.Demo",
dbus.NameFlagDoNotQueue)
if err != nil {
panic(err)
}
if reply != dbus.RequestNameReplyPrimaryOwner {
fmt.Fprintln(os.Stderr, "name already taken")
os.Exit(1)
}
f := foo("Bar!")
conn.Export(f, "/com/github/guelfey/Demo", "com.github.guelfey.Demo")
conn.Export(introspect.Introspectable(intro), "/com/github/guelfey/Demo",
"org.freedesktop.DBus.Introspectable")
fmt.Println("Listening on com.github.guelfey.Demo / /com/github/guelfey/Demo ...")
select {}
}

View file

@ -1,24 +0,0 @@
package main
import (
"fmt"
"github.com/godbus/dbus"
"os"
)
func main() {
conn, err := dbus.SessionBus()
if err != nil {
fmt.Fprintln(os.Stderr, "Failed to connect to session bus:", err)
os.Exit(1)
}
conn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0,
"type='signal',path='/org/freedesktop/DBus',interface='org.freedesktop.DBus',sender='org.freedesktop.DBus'")
c := make(chan *dbus.Signal, 10)
conn.Signal(c)
for v := range c {
fmt.Println(v)
}
}

View file

@ -1,236 +0,0 @@
package dbus
import "testing"
func TestSessionBus(t *testing.T) {
_, err := SessionBus()
if err != nil {
t.Error(err)
}
}
func TestSystemBus(t *testing.T) {
_, err := SystemBus()
if err != nil {
t.Error(err)
}
}
func TestSend(t *testing.T) {
bus, err := SessionBus()
if err != nil {
t.Fatal(err)
}
ch := make(chan *Call, 1)
msg := &Message{
Type: TypeMethodCall,
Flags: 0,
Headers: map[HeaderField]Variant{
FieldDestination: MakeVariant(bus.Names()[0]),
FieldPath: MakeVariant(ObjectPath("/org/freedesktop/DBus")),
FieldInterface: MakeVariant("org.freedesktop.DBus.Peer"),
FieldMember: MakeVariant("Ping"),
},
}
call := bus.Send(msg, ch)
<-ch
if call.Err != nil {
t.Error(call.Err)
}
}
func TestRemoveSignal(t *testing.T) {
bus, err := NewConn(nil)
if err != nil {
t.Error(err)
}
ch := make(chan *Signal)
ch2 := make(chan *Signal)
for _, ch := range []chan *Signal{ch, ch2, ch, ch2, ch2, ch} {
bus.Signal(ch)
}
if len(bus.signals) != 6 {
t.Errorf("remove signal: signals length not equal: got '%d', want '6'", len(bus.signals))
}
bus.RemoveSignal(ch)
if len(bus.signals) != 3 {
t.Errorf("remove signal: signals length not equal: got '%d', want '3'", len(bus.signals))
}
for _, bch := range bus.signals {
if bch != ch2 {
t.Errorf("remove signal: removed signal present: got '%v', want '%v'", bch, ch2)
}
}
}
type server struct{}
func (server) Double(i int64) (int64, *Error) {
return 2 * i, nil
}
func BenchmarkCall(b *testing.B) {
b.StopTimer()
var s string
bus, err := SessionBus()
if err != nil {
b.Fatal(err)
}
name := bus.Names()[0]
obj := bus.BusObject()
b.StartTimer()
for i := 0; i < b.N; i++ {
err := obj.Call("org.freedesktop.DBus.GetNameOwner", 0, name).Store(&s)
if err != nil {
b.Fatal(err)
}
if s != name {
b.Errorf("got %s, wanted %s", s, name)
}
}
}
func BenchmarkCallAsync(b *testing.B) {
b.StopTimer()
bus, err := SessionBus()
if err != nil {
b.Fatal(err)
}
name := bus.Names()[0]
obj := bus.BusObject()
c := make(chan *Call, 50)
done := make(chan struct{})
go func() {
for i := 0; i < b.N; i++ {
v := <-c
if v.Err != nil {
b.Error(v.Err)
}
s := v.Body[0].(string)
if s != name {
b.Errorf("got %s, wanted %s", s, name)
}
}
close(done)
}()
b.StartTimer()
for i := 0; i < b.N; i++ {
obj.Go("org.freedesktop.DBus.GetNameOwner", 0, c, name)
}
<-done
}
func BenchmarkServe(b *testing.B) {
b.StopTimer()
srv, err := SessionBus()
if err != nil {
b.Fatal(err)
}
cli, err := SessionBusPrivate()
if err != nil {
b.Fatal(err)
}
if err = cli.Auth(nil); err != nil {
b.Fatal(err)
}
if err = cli.Hello(); err != nil {
b.Fatal(err)
}
benchmarkServe(b, srv, cli)
}
func BenchmarkServeAsync(b *testing.B) {
b.StopTimer()
srv, err := SessionBus()
if err != nil {
b.Fatal(err)
}
cli, err := SessionBusPrivate()
if err != nil {
b.Fatal(err)
}
if err = cli.Auth(nil); err != nil {
b.Fatal(err)
}
if err = cli.Hello(); err != nil {
b.Fatal(err)
}
benchmarkServeAsync(b, srv, cli)
}
func BenchmarkServeSameConn(b *testing.B) {
b.StopTimer()
bus, err := SessionBus()
if err != nil {
b.Fatal(err)
}
benchmarkServe(b, bus, bus)
}
func BenchmarkServeSameConnAsync(b *testing.B) {
b.StopTimer()
bus, err := SessionBus()
if err != nil {
b.Fatal(err)
}
benchmarkServeAsync(b, bus, bus)
}
func benchmarkServe(b *testing.B, srv, cli *Conn) {
var r int64
var err error
dest := srv.Names()[0]
srv.Export(server{}, "/org/guelfey/DBus/Test", "org.guelfey.DBus.Test")
obj := cli.Object(dest, "/org/guelfey/DBus/Test")
b.StartTimer()
for i := 0; i < b.N; i++ {
err = obj.Call("org.guelfey.DBus.Test.Double", 0, int64(i)).Store(&r)
if err != nil {
b.Fatal(err)
}
if r != 2*int64(i) {
b.Errorf("got %d, wanted %d", r, 2*int64(i))
}
}
}
func benchmarkServeAsync(b *testing.B, srv, cli *Conn) {
dest := srv.Names()[0]
srv.Export(server{}, "/org/guelfey/DBus/Test", "org.guelfey.DBus.Test")
obj := cli.Object(dest, "/org/guelfey/DBus/Test")
c := make(chan *Call, 50)
done := make(chan struct{})
go func() {
for i := 0; i < b.N; i++ {
v := <-c
if v.Err != nil {
b.Fatal(v.Err)
}
i, r := v.Args[0].(int64), v.Body[0].(int64)
if 2*i != r {
b.Errorf("got %d, wanted %d", r, 2*i)
}
}
close(done)
}()
b.StartTimer()
for i := 0; i < b.N; i++ {
obj.Go("org.guelfey.DBus.Test.Double", 0, c, int64(i))
}
<-done
}
func TestGetKey(t *testing.T) {
keys := "host=1.2.3.4,port=5678,family=ipv4"
if host := getKey(keys, "host"); host != "1.2.3.4" {
t.Error(`Expected "1.2.3.4", got`, host)
}
if port := getKey(keys, "port"); port != "5678" {
t.Error(`Expected "5678", got`, port)
}
if family := getKey(keys, "family"); family != "ipv4" {
t.Error(`Expected "ipv4", got`, family)
}
}

View file

@ -1,58 +0,0 @@
package dbus
import (
"bytes"
"encoding/binary"
"reflect"
"testing"
)
func TestEncodeArrayOfMaps(t *testing.T) {
tests := []struct {
name string
vs []interface{}
}{
{
"aligned at 8 at start of array",
[]interface{}{
"12345",
[]map[string]Variant{
{
"abcdefg": MakeVariant("foo"),
"cdef": MakeVariant(uint32(2)),
},
},
},
},
{
"not aligned at 8 for start of array",
[]interface{}{
"1234567890",
[]map[string]Variant{
{
"abcdefg": MakeVariant("foo"),
"cdef": MakeVariant(uint32(2)),
},
},
},
},
}
for _, order := range []binary.ByteOrder{binary.LittleEndian, binary.BigEndian} {
for _, tt := range tests {
buf := new(bytes.Buffer)
enc := newEncoder(buf, order)
enc.Encode(tt.vs...)
dec := newDecoder(buf, order)
v, err := dec.Decode(SignatureOf(tt.vs...))
if err != nil {
t.Errorf("%q: decode (%v) failed: %v", tt.name, order, err)
continue
}
if !reflect.DeepEqual(v, tt.vs) {
t.Errorf("%q: (%v) not equal: got '%v', want '%v'", tt.name, order, v, tt.vs)
continue
}
}
}
}

View file

@ -1,50 +0,0 @@
package dbus
import "fmt"
func ExampleConn_Emit() {
conn, err := SessionBus()
if err != nil {
panic(err)
}
conn.Emit("/foo/bar", "foo.bar.Baz", uint32(0xDAEDBEEF))
}
func ExampleObject_Call() {
var list []string
conn, err := SessionBus()
if err != nil {
panic(err)
}
err = conn.BusObject().Call("org.freedesktop.DBus.ListNames", 0).Store(&list)
if err != nil {
panic(err)
}
for _, v := range list {
fmt.Println(v)
}
}
func ExampleObject_Go() {
conn, err := SessionBus()
if err != nil {
panic(err)
}
ch := make(chan *Call, 10)
conn.BusObject().Go("org.freedesktop.DBus.ListActivatableNames", 0, ch)
select {
case call := <-ch:
if call.Err != nil {
panic(err)
}
list := call.Body[0].([]string)
for _, v := range list {
fmt.Println(v)
}
// put some other cases here
}
}

View file

@ -1,635 +0,0 @@
package dbus
import (
"fmt"
"regexp"
"strings"
"testing"
)
type lowerCaseExport struct{}
func (export lowerCaseExport) foo() (string, *Error) {
return "bar", nil
}
type fooExport struct {
message Message
}
func (export *fooExport) Foo(message Message, param string) (string, *Error) {
export.message = message
return "foo", nil
}
type barExport struct{}
func (export barExport) Foo(param string) (string, *Error) {
return "bar", nil
}
type badExport struct{}
func (export badExport) Foo(param string) string {
return "bar"
}
// Test typical Export usage.
func TestExport(t *testing.T) {
connection, err := SessionBus()
if err != nil {
t.Fatalf("Unexpected error connecting to session bus: %s", err)
}
name := connection.Names()[0]
connection.Export(server{}, "/org/guelfey/DBus/Test", "org.guelfey.DBus.Test")
object := connection.Object(name, "/org/guelfey/DBus/Test")
subtreeObject := connection.Object(name, "/org/guelfey/DBus/Test/Foo")
var response int64
err = object.Call("org.guelfey.DBus.Test.Double", 0, int64(2)).Store(&response)
if err != nil {
t.Errorf("Unexpected error calling Double: %s", err)
}
if response != 4 {
t.Errorf("Response was %d, expected 4", response)
}
// Verify that calling a subtree of a regular export does not result in a
// valid method call.
err = subtreeObject.Call("org.guelfey.DBus.Test.Double", 0, int64(2)).Store(&response)
if err == nil {
t.Error("Expected error due to no object being exported on that path")
}
// Now remove export
connection.Export(nil, "/org/guelfey/DBus/Test", "org.guelfey.DBus.Test")
err = object.Call("org.guelfey.DBus.Test.Double", 0, int64(2)).Store(&response)
if err == nil {
t.Error("Expected an error since the export was removed")
}
}
// Test that Exported handlers can obtain raw message.
func TestExport_message(t *testing.T) {
connection, err := SessionBus()
if err != nil {
t.Fatalf("Unexpected error connecting to session bus: %s", err)
}
name := connection.Names()[0]
export := &fooExport{}
connection.Export(export, "/org/guelfey/DBus/Test", "org.guelfey.DBus.Test")
object := connection.Object(name, "/org/guelfey/DBus/Test")
var response string
err = object.Call("org.guelfey.DBus.Test.Foo", 0, "qux").Store(&response)
if err != nil {
t.Errorf("Unexpected error calling Foo: %s", err)
}
if response != "foo" {
t.Errorf(`Response was %s, expected "foo"`, response)
}
if export.message.serial == 0 {
t.Error("Expected a valid message to be given to handler")
}
}
// Test Export with an invalid path.
func TestExport_invalidPath(t *testing.T) {
connection, err := SessionBus()
if err != nil {
t.Fatalf("Unexpected error connecting to session bus: %s", err)
}
err = connection.Export(nil, "foo", "bar")
if err == nil {
t.Error("Expected an error due to exporting with an invalid path")
}
}
// Test Export with an un-exported method. This should not panic, but rather
// result in an invalid method call.
func TestExport_unexportedMethod(t *testing.T) {
connection, err := SessionBus()
if err != nil {
t.Fatalf("Unexpected error connecting to session bus: %s", err)
}
name := connection.Names()[0]
connection.Export(lowerCaseExport{}, "/org/guelfey/DBus/Test", "org.guelfey.DBus.Test")
object := connection.Object(name, "/org/guelfey/DBus/Test")
var response string
call := object.Call("org.guelfey.DBus.Test.foo", 0)
err = call.Store(&response)
if err == nil {
t.Errorf("Expected an error due to calling unexported method")
}
}
// Test Export with a method lacking the correct return signature. This should
// result in an invalid method call.
func TestExport_badSignature(t *testing.T) {
connection, err := SessionBus()
if err != nil {
t.Fatalf("Unexpected error connecting to session bus: %s", err)
}
name := connection.Names()[0]
connection.Export(badExport{}, "/org/guelfey/DBus/Test", "org.guelfey.DBus.Test")
object := connection.Object(name, "/org/guelfey/DBus/Test")
var response string
call := object.Call("org.guelfey.DBus.Test.Foo", 0)
err = call.Store(&response)
if err == nil {
t.Errorf("Expected an error due to the method lacking the right signature")
}
}
// Test typical ExportWithMap usage.
func TestExportWithMap(t *testing.T) {
connection, err := SessionBus()
if err != nil {
t.Fatalf("Unexpected error connecting to session bus: %s", err)
}
name := connection.Names()[0]
mapping := make(map[string]string)
mapping["Double"] = "double" // Export this method as lower-case
connection.ExportWithMap(server{}, mapping, "/org/guelfey/DBus/Test", "org.guelfey.DBus.Test")
object := connection.Object(name, "/org/guelfey/DBus/Test")
var response int64
err = object.Call("org.guelfey.DBus.Test.double", 0, int64(2)).Store(&response)
if err != nil {
t.Errorf("Unexpected error calling double: %s", err)
}
if response != 4 {
t.Errorf("Response was %d, expected 4", response)
}
}
// Test that ExportWithMap does not export both method alias and method.
func TestExportWithMap_bypassAlias(t *testing.T) {
connection, err := SessionBus()
if err != nil {
t.Fatalf("Unexpected error connecting to session bus: %s", err)
}
name := connection.Names()[0]
mapping := make(map[string]string)
mapping["Double"] = "double" // Export this method as lower-case
connection.ExportWithMap(server{}, mapping, "/org/guelfey/DBus/Test", "org.guelfey.DBus.Test")
object := connection.Object(name, "/org/guelfey/DBus/Test")
var response int64
// Call upper-case Double (i.e. the real method, not the alias)
err = object.Call("org.guelfey.DBus.Test.Double", 0, int64(2)).Store(&response)
if err == nil {
t.Error("Expected an error due to calling actual method, not alias")
}
}
// Test typical ExportSubtree usage.
func TestExportSubtree(t *testing.T) {
connection, err := SessionBus()
if err != nil {
t.Fatalf("Unexpected error connecting to session bus: %s", err)
}
name := connection.Names()[0]
export := &fooExport{}
connection.ExportSubtree(export, "/org/guelfey/DBus/Test", "org.guelfey.DBus.Test")
// Call a subpath of the exported path
object := connection.Object(name, "/org/guelfey/DBus/Test/Foo")
var response string
err = object.Call("org.guelfey.DBus.Test.Foo", 0, "qux").Store(&response)
if err != nil {
t.Errorf("Unexpected error calling Foo: %s", err)
}
if response != "foo" {
t.Errorf(`Response was %s, expected "foo"`, response)
}
if export.message.serial == 0 {
t.Error("Expected the raw message, got an invalid one")
}
// Now remove export
connection.Export(nil, "/org/guelfey/DBus/Test", "org.guelfey.DBus.Test")
err = object.Call("org.guelfey.DBus.Test.Foo", 0, "qux").Store(&response)
if err == nil {
t.Error("Expected an error since the export was removed")
}
}
// Test that using ExportSubtree with exported methods that don't contain a
// Message still work, they just don't get the message.
func TestExportSubtree_noMessage(t *testing.T) {
connection, err := SessionBus()
if err != nil {
t.Fatalf("Unexpected error connecting to session bus: %s", err)
}
name := connection.Names()[0]
connection.ExportSubtree(server{}, "/org/guelfey/DBus/Test", "org.guelfey.DBus.Test")
// Call a subpath of the exported path
object := connection.Object(name, "/org/guelfey/DBus/Test/Foo")
var response int64
err = object.Call("org.guelfey.DBus.Test.Double", 0, int64(2)).Store(&response)
if err != nil {
t.Errorf("Unexpected error calling Double: %s", err)
}
if response != 4 {
t.Errorf("Response was %d, expected 4", response)
}
// Now remove export
connection.Export(nil, "/org/guelfey/DBus/Test", "org.guelfey.DBus.Test")
err = object.Call("org.guelfey.DBus.Test.Double", 0, int64(2)).Store(&response)
if err == nil {
t.Error("Expected an error since the export was removed")
}
}
// Test that a regular Export takes precedence over ExportSubtree.
func TestExportSubtree_exportPrecedence(t *testing.T) {
connection, err := SessionBus()
if err != nil {
t.Fatalf("Unexpected error connecting to session bus: %s", err)
}
name := connection.Names()[0]
// Register for the entire subtree of /org/guelfey/DBus/Test
connection.ExportSubtree(&fooExport{},
"/org/guelfey/DBus/Test", "org.guelfey.DBus.Test")
// Explicitly register for /org/guelfey/DBus/Test/Foo, a subpath of above
connection.Export(&barExport{}, "/org/guelfey/DBus/Test/Foo",
"org.guelfey.DBus.Test")
// Call the explicitly exported path
object := connection.Object(name, "/org/guelfey/DBus/Test/Foo")
var response string
err = object.Call("org.guelfey.DBus.Test.Foo", 0, "qux").Store(&response)
if err != nil {
t.Errorf("Unexpected error calling Foo: %s", err)
}
if response != "bar" {
t.Errorf(`Response was %s, expected "bar"`, response)
}
response = "" // Reset response so errors aren't confusing
// Now remove explicit export
connection.Export(nil, "/org/guelfey/DBus/Test/Foo", "org.guelfey.DBus.Test")
err = object.Call("org.guelfey.DBus.Test.Foo", 0, "qux").Store(&response)
if err != nil {
t.Errorf("Unexpected error calling Foo: %s", err)
}
// Now the subtree export should handle the call
if response != "foo" {
t.Errorf(`Response was %s, expected "foo"`, response)
}
}
// Test typical ExportSubtreeWithMap usage.
func TestExportSubtreeWithMap(t *testing.T) {
connection, err := SessionBus()
if err != nil {
t.Fatalf("Unexpected error connecting to session bus: %s", err)
}
name := connection.Names()[0]
mapping := make(map[string]string)
mapping["Foo"] = "foo" // Export this method as lower-case
connection.ExportSubtreeWithMap(&fooExport{}, mapping, "/org/guelfey/DBus/Test", "org.guelfey.DBus.Test")
// Call a subpath of the exported path
object := connection.Object(name, "/org/guelfey/DBus/Test/Foo")
var response string
// Call the lower-case method
err = object.Call("org.guelfey.DBus.Test.foo", 0, "qux").Store(&response)
if err != nil {
t.Errorf("Unexpected error calling Foo: %s", err)
}
if response != "foo" {
t.Errorf(`Response was %s, expected "foo"`, response)
}
// Now remove export
connection.Export(nil, "/org/guelfey/DBus/Test", "org.guelfey.DBus.Test")
err = object.Call("org.guelfey.DBus.Test.foo", 0, "qux").Store(&response)
if err == nil {
t.Error("Expected an error since the export was removed")
}
}
// Test that ExportSubtreeWithMap does not export both method alias and method.
func TestExportSubtreeWithMap_bypassAlias(t *testing.T) {
connection, err := SessionBus()
if err != nil {
t.Fatalf("Unexpected error connecting to session bus: %s", err)
}
name := connection.Names()[0]
mapping := make(map[string]string)
mapping["Foo"] = "foo" // Export this method as lower-case
connection.ExportSubtreeWithMap(&fooExport{}, mapping, "/org/guelfey/DBus/Test", "org.guelfey.DBus.Test")
object := connection.Object(name, "/org/guelfey/DBus/Test/Foo")
var response string
// Call upper-case Foo (i.e. the real method, not the alias)
err = object.Call("org.guelfey.DBus.Test.Foo", 0, "qux").Store(&response)
if err == nil {
t.Error("Expected an error due to calling actual method, not alias")
}
}
func TestExportMethodTable(t *testing.T) {
connection, err := SessionBus()
if err != nil {
t.Fatalf("Unexpected error connecting to session bus: %s", err)
}
name := connection.Names()[0]
export := &fooExport{}
tbl := make(map[string]interface{})
tbl["Foo"] = func(message Message, param string) (string, *Error) {
return export.Foo(message, param)
}
tbl["Foo2"] = export.Foo
connection.ExportMethodTable(tbl, "/org/guelfey/DBus/Test", "org.guelfey.DBus.Test")
object := connection.Object(name, "/org/guelfey/DBus/Test")
var response string
err = object.Call("org.guelfey.DBus.Test.Foo", 0, "qux").Store(&response)
if err != nil {
t.Errorf("Unexpected error calling Foo: %s", err)
}
if response != "foo" {
t.Errorf(`Response was %s, expected "foo"`, response)
}
if export.message.serial == 0 {
t.Error("Expected the raw message, got an invalid one")
}
err = object.Call("org.guelfey.DBus.Test.Foo2", 0, "qux").Store(&response)
if err != nil {
t.Errorf("Unexpected error calling Foo: %s", err)
}
if response != "foo" {
t.Errorf(`Response was %s, expected "foo"`, response)
}
if export.message.serial == 0 {
t.Error("Expected the raw message, got an invalid one")
}
// Now remove export
connection.Export(nil, "/org/guelfey/DBus/Test", "org.guelfey.DBus.Test")
err = object.Call("org.guelfey.DBus.Test.Foo", 0, "qux").Store(&response)
if err == nil {
t.Error("Expected an error since the export was removed")
}
}
func TestExportSubtreeMethodTable(t *testing.T) {
connection, err := SessionBus()
if err != nil {
t.Fatalf("Unexpected error connecting to session bus: %s", err)
}
name := connection.Names()[0]
export := &fooExport{}
tbl := make(map[string]interface{})
tbl["Foo"] = func(message Message, param string) (string, *Error) {
return export.Foo(message, param)
}
tbl["Foo2"] = export.Foo
connection.ExportSubtreeMethodTable(tbl, "/org/guelfey/DBus/Test", "org.guelfey.DBus.Test")
// Call a subpath of the exported path
object := connection.Object(name, "/org/guelfey/DBus/Test/Foo")
var response string
err = object.Call("org.guelfey.DBus.Test.Foo", 0, "qux").Store(&response)
if err != nil {
t.Errorf("Unexpected error calling Foo: %s", err)
}
if response != "foo" {
t.Errorf(`Response was %s, expected "foo"`, response)
}
if export.message.serial == 0 {
t.Error("Expected the raw message, got an invalid one")
}
err = object.Call("org.guelfey.DBus.Test.Foo2", 0, "qux").Store(&response)
if err != nil {
t.Errorf("Unexpected error calling Foo: %s", err)
}
if response != "foo" {
t.Errorf(`Response was %s, expected "foo"`, response)
}
if export.message.serial == 0 {
t.Error("Expected the raw message, got an invalid one")
}
// Now remove export
connection.Export(nil, "/org/guelfey/DBus/Test", "org.guelfey.DBus.Test")
err = object.Call("org.guelfey.DBus.Test.Foo", 0, "qux").Store(&response)
if err == nil {
t.Error("Expected an error since the export was removed")
}
}
func TestExportMethodTable_NotFunc(t *testing.T) {
connection, err := SessionBus()
if err != nil {
t.Fatalf("Unexpected error connecting to session bus: %s", err)
}
name := connection.Names()[0]
export := &fooExport{}
tbl := make(map[string]interface{})
tbl["Foo"] = func(message Message, param string) (string, *Error) {
return export.Foo(message, param)
}
tbl["Foo2"] = "foobar"
connection.ExportMethodTable(tbl, "/org/guelfey/DBus/Test", "org.guelfey.DBus.Test")
object := connection.Object(name, "/org/guelfey/DBus/Test")
var response string
err = object.Call("org.guelfey.DBus.Test.Foo", 0, "qux").Store(&response)
if err != nil {
t.Errorf("Unexpected error calling Foo: %s", err)
}
if response != "foo" {
t.Errorf(`Response was %s, expected "foo"`, response)
}
if export.message.serial == 0 {
t.Error("Expected the raw message, got an invalid one")
}
err = object.Call("org.guelfey.DBus.Test.Foo2", 0, "qux").Store(&response)
if err == nil {
t.Errorf("Expected an error since the Foo2 was not a function")
}
}
func TestExportMethodTable_ReturnNotError(t *testing.T) {
connection, err := SessionBus()
if err != nil {
t.Fatalf("Unexpected error connecting to session bus: %s", err)
}
name := connection.Names()[0]
export := &fooExport{}
tbl := make(map[string]interface{})
tbl["Foo"] = func(message Message, param string) (string, string) {
out, _ := export.Foo(message, param)
return out, out
}
connection.ExportMethodTable(tbl, "/org/guelfey/DBus/Test", "org.guelfey.DBus.Test")
object := connection.Object(name, "/org/guelfey/DBus/Test")
var response string
err = object.Call("org.guelfey.DBus.Test.Foo", 0, "qux").Store(&response)
if err == nil {
t.Errorf("Expected an error since the Foo did not have a final return as *dbus.Error")
}
}
// Test that introspection works on sub path of every exported object
func TestExportSubPathIntrospection(t *testing.T) {
const (
introIntf = "org.freedesktop.DBus.Introspectable"
respTmpl = `^<node>\s*<node\s+name="%s"\s*/>\s*</node>$`
pathstr = "/org/guelfey/DBus/Test"
foopathstr = pathstr + "/Foo"
barpathstr = pathstr + "/Bar"
test1intfstr = "org.guelfey.DBus.Test1"
test2intfstr = "org.guelfey.DBus.Test2"
intro = `
<node>
<interface name="` + test1intfstr + `">
<method name="Foo">
<arg direction="out" type="s"/>
</method>
</interface>
<interface name="` + test2intfstr + `">
<method name="Foo">
<arg direction="out" type="s"/>
</method>
<method name="Bar">
<arg direction="out" type="s"/>
</method>
</interface>
<interface name="` + introIntf + `">
<method name="Introspect">
<arg name="out" direction="out" type="s"/>
</method>
</interface>
</node>`
)
connection, err := SessionBus()
if err != nil {
t.Fatalf("Unexpected error connecting to session bus: %s", err)
}
name := connection.Names()[0]
foo := &fooExport{}
bar := &barExport{}
connection.Export(foo, foopathstr, test1intfstr)
connection.Export(foo, foopathstr, test2intfstr)
connection.Export(bar, barpathstr, test2intfstr)
connection.Export(intro, pathstr, introIntf)
var response string
var match bool
path := strings.Split(pathstr, "/")
for i := 0; i < len(path)-1; i++ {
var subpath string
if i == 0 {
subpath = "/"
} else {
subpath = strings.Join(path[:i+1], "/")
}
object := connection.Object(name, ObjectPath(subpath))
err = object.Call(introIntf+".Introspect", 0).Store(&response)
if err != nil {
t.Errorf("Unexpected error calling Introspect on %s: %s", subpath, err)
}
exp := fmt.Sprintf(respTmpl, path[i+1])
match, err = regexp.MatchString(exp, response)
if err != nil {
t.Fatalf("Error calling MatchString: %s", err)
}
if !match {
t.Errorf("Unexpected introspection response for %s: %s", subpath, response)
}
}
// Test invalid subpath
invalSubpath := "/org/guelfey/DBus/Test/Nonexistent"
object := connection.Object(name, ObjectPath(invalSubpath))
err = object.Call(introIntf+".Introspect", 0).Store(&response)
if err != nil {
t.Errorf("Unexpected error calling Introspect on %s: %s", invalSubpath, err)
}
match, err = regexp.MatchString(`^<node>\s*</node>$`, response)
if err != nil {
t.Fatalf("Error calling MatchString: %s", err)
}
if !match {
t.Errorf("Unexpected introspection response for %s: %s", invalSubpath, response)
}
}

View file

@ -1,27 +0,0 @@
package introspect
import (
"encoding/xml"
"github.com/godbus/dbus"
"strings"
)
// Call calls org.freedesktop.Introspectable.Introspect on a remote object
// and returns the introspection data.
func Call(o dbus.BusObject) (*Node, error) {
var xmldata string
var node Node
err := o.Call("org.freedesktop.DBus.Introspectable.Introspect", 0).Store(&xmldata)
if err != nil {
return nil, err
}
err = xml.NewDecoder(strings.NewReader(xmldata)).Decode(&node)
if err != nil {
return nil, err
}
if node.Name == "" {
node.Name = string(o.Path())
}
return &node, nil
}

View file

@ -1,86 +0,0 @@
// Package introspect provides some utilities for dealing with the DBus
// introspection format.
package introspect
import "encoding/xml"
// The introspection data for the org.freedesktop.DBus.Introspectable interface.
var IntrospectData = Interface{
Name: "org.freedesktop.DBus.Introspectable",
Methods: []Method{
{
Name: "Introspect",
Args: []Arg{
{"out", "s", "out"},
},
},
},
}
// XML document type declaration of the introspection format version 1.0
const IntrospectDeclarationString = `
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
`
// The introspection data for the org.freedesktop.DBus.Introspectable interface,
// as a string.
const IntrospectDataString = `
<interface name="org.freedesktop.DBus.Introspectable">
<method name="Introspect">
<arg name="out" direction="out" type="s"/>
</method>
</interface>
`
// Node is the root element of an introspection.
type Node struct {
XMLName xml.Name `xml:"node"`
Name string `xml:"name,attr,omitempty"`
Interfaces []Interface `xml:"interface"`
Children []Node `xml:"node,omitempty"`
}
// Interface describes a DBus interface that is available on the message bus.
type Interface struct {
Name string `xml:"name,attr"`
Methods []Method `xml:"method"`
Signals []Signal `xml:"signal"`
Properties []Property `xml:"property"`
Annotations []Annotation `xml:"annotation"`
}
// Method describes a Method on an Interface as retured by an introspection.
type Method struct {
Name string `xml:"name,attr"`
Args []Arg `xml:"arg"`
Annotations []Annotation `xml:"annotation"`
}
// Signal describes a Signal emitted on an Interface.
type Signal struct {
Name string `xml:"name,attr"`
Args []Arg `xml:"arg"`
Annotations []Annotation `xml:"annotation"`
}
// Property describes a property of an Interface.
type Property struct {
Name string `xml:"name,attr"`
Type string `xml:"type,attr"`
Access string `xml:"access,attr"`
Annotations []Annotation `xml:"annotation"`
}
// Arg represents an argument of a method or a signal.
type Arg struct {
Name string `xml:"name,attr,omitempty"`
Type string `xml:"type,attr"`
Direction string `xml:"direction,attr,omitempty"`
}
// Annotation is an annotation in the introspection format.
type Annotation struct {
Name string `xml:"name,attr"`
Value string `xml:"value,attr"`
}

View file

@ -1,76 +0,0 @@
package introspect
import (
"encoding/xml"
"github.com/godbus/dbus"
"reflect"
"strings"
)
// Introspectable implements org.freedesktop.Introspectable.
//
// You can create it by converting the XML-formatted introspection data from a
// string to an Introspectable or call NewIntrospectable with a Node. Then,
// export it as org.freedesktop.Introspectable on you object.
type Introspectable string
// NewIntrospectable returns an Introspectable that returns the introspection
// data that corresponds to the given Node. If n.Interfaces doesn't contain the
// data for org.freedesktop.DBus.Introspectable, it is added automatically.
func NewIntrospectable(n *Node) Introspectable {
found := false
for _, v := range n.Interfaces {
if v.Name == "org.freedesktop.DBus.Introspectable" {
found = true
break
}
}
if !found {
n.Interfaces = append(n.Interfaces, IntrospectData)
}
b, err := xml.Marshal(n)
if err != nil {
panic(err)
}
return Introspectable(strings.TrimSpace(IntrospectDeclarationString) + string(b))
}
// Introspect implements org.freedesktop.Introspectable.Introspect.
func (i Introspectable) Introspect() (string, *dbus.Error) {
return string(i), nil
}
// Methods returns the description of the methods of v. This can be used to
// create a Node which can be passed to NewIntrospectable.
func Methods(v interface{}) []Method {
t := reflect.TypeOf(v)
ms := make([]Method, 0, t.NumMethod())
for i := 0; i < t.NumMethod(); i++ {
if t.Method(i).PkgPath != "" {
continue
}
mt := t.Method(i).Type
if mt.NumOut() == 0 ||
mt.Out(mt.NumOut()-1) != reflect.TypeOf(&dbus.Error{}) {
continue
}
var m Method
m.Name = t.Method(i).Name
m.Args = make([]Arg, 0, mt.NumIn()+mt.NumOut()-2)
for j := 1; j < mt.NumIn(); j++ {
if mt.In(j) != reflect.TypeOf((*dbus.Sender)(nil)).Elem() &&
mt.In(j) != reflect.TypeOf((*dbus.Message)(nil)).Elem() {
arg := Arg{"", dbus.SignatureOfType(mt.In(j)).String(), "in"}
m.Args = append(m.Args, arg)
}
}
for j := 0; j < mt.NumOut()-1; j++ {
arg := Arg{"", dbus.SignatureOfType(mt.Out(j)).String(), "out"}
m.Args = append(m.Args, arg)
}
m.Annotations = make([]Annotation, 0)
ms = append(ms, m)
}
return ms
}

View file

@ -1,264 +0,0 @@
// Package prop provides the Properties struct which can be used to implement
// org.freedesktop.DBus.Properties.
package prop
import (
"github.com/godbus/dbus"
"github.com/godbus/dbus/introspect"
"sync"
)
// EmitType controls how org.freedesktop.DBus.Properties.PropertiesChanged is
// emitted for a property. If it is EmitTrue, the signal is emitted. If it is
// EmitInvalidates, the signal is also emitted, but the new value of the property
// is not disclosed.
type EmitType byte
const (
EmitFalse EmitType = iota
EmitTrue
EmitInvalidates
)
// ErrIfaceNotFound is the error returned to peers who try to access properties
// on interfaces that aren't found.
var ErrIfaceNotFound = dbus.NewError("org.freedesktop.DBus.Properties.Error.InterfaceNotFound", nil)
// ErrPropNotFound is the error returned to peers trying to access properties
// that aren't found.
var ErrPropNotFound = dbus.NewError("org.freedesktop.DBus.Properties.Error.PropertyNotFound", nil)
// ErrReadOnly is the error returned to peers trying to set a read-only
// property.
var ErrReadOnly = dbus.NewError("org.freedesktop.DBus.Properties.Error.ReadOnly", nil)
// ErrInvalidArg is returned to peers if the type of the property that is being
// changed and the argument don't match.
var ErrInvalidArg = dbus.NewError("org.freedesktop.DBus.Properties.Error.InvalidArg", nil)
// The introspection data for the org.freedesktop.DBus.Properties interface.
var IntrospectData = introspect.Interface{
Name: "org.freedesktop.DBus.Properties",
Methods: []introspect.Method{
{
Name: "Get",
Args: []introspect.Arg{
{"interface", "s", "in"},
{"property", "s", "in"},
{"value", "v", "out"},
},
},
{
Name: "GetAll",
Args: []introspect.Arg{
{"interface", "s", "in"},
{"props", "a{sv}", "out"},
},
},
{
Name: "Set",
Args: []introspect.Arg{
{"interface", "s", "in"},
{"property", "s", "in"},
{"value", "v", "in"},
},
},
},
Signals: []introspect.Signal{
{
Name: "PropertiesChanged",
Args: []introspect.Arg{
{"interface", "s", "out"},
{"changed_properties", "a{sv}", "out"},
{"invalidates_properties", "as", "out"},
},
},
},
}
// The introspection data for the org.freedesktop.DBus.Properties interface, as
// a string.
const IntrospectDataString = `
<interface name="org.freedesktop.DBus.Properties">
<method name="Get">
<arg name="interface" direction="in" type="s"/>
<arg name="property" direction="in" type="s"/>
<arg name="value" direction="out" type="v"/>
</method>
<method name="GetAll">
<arg name="interface" direction="in" type="s"/>
<arg name="props" direction="out" type="a{sv}"/>
</method>
<method name="Set">
<arg name="interface" direction="in" type="s"/>
<arg name="property" direction="in" type="s"/>
<arg name="value" direction="in" type="v"/>
</method>
<signal name="PropertiesChanged">
<arg name="interface" type="s"/>
<arg name="changed_properties" type="a{sv}"/>
<arg name="invalidates_properties" type="as"/>
</signal>
</interface>
`
// Prop represents a single property. It is used for creating a Properties
// value.
type Prop struct {
// Initial value. Must be a DBus-representable type.
Value interface{}
// If true, the value can be modified by calls to Set.
Writable bool
// Controls how org.freedesktop.DBus.Properties.PropertiesChanged is
// emitted if this property changes.
Emit EmitType
// If not nil, anytime this property is changed by Set, this function is
// called with an appropiate Change as its argument. If the returned error
// is not nil, it is sent back to the caller of Set and the property is not
// changed.
Callback func(*Change) *dbus.Error
}
// Change represents a change of a property by a call to Set.
type Change struct {
Props *Properties
Iface string
Name string
Value interface{}
}
// Properties is a set of values that can be made available to the message bus
// using the org.freedesktop.DBus.Properties interface. It is safe for
// concurrent use by multiple goroutines.
type Properties struct {
m map[string]map[string]*Prop
mut sync.RWMutex
conn *dbus.Conn
path dbus.ObjectPath
}
// New returns a new Properties structure that manages the given properties.
// The key for the first-level map of props is the name of the interface; the
// second-level key is the name of the property. The returned structure will be
// exported as org.freedesktop.DBus.Properties on path.
func New(conn *dbus.Conn, path dbus.ObjectPath, props map[string]map[string]*Prop) *Properties {
p := &Properties{m: props, conn: conn, path: path}
conn.Export(p, path, "org.freedesktop.DBus.Properties")
return p
}
// Get implements org.freedesktop.DBus.Properties.Get.
func (p *Properties) Get(iface, property string) (dbus.Variant, *dbus.Error) {
p.mut.RLock()
defer p.mut.RUnlock()
m, ok := p.m[iface]
if !ok {
return dbus.Variant{}, ErrIfaceNotFound
}
prop, ok := m[property]
if !ok {
return dbus.Variant{}, ErrPropNotFound
}
return dbus.MakeVariant(prop.Value), nil
}
// GetAll implements org.freedesktop.DBus.Properties.GetAll.
func (p *Properties) GetAll(iface string) (map[string]dbus.Variant, *dbus.Error) {
p.mut.RLock()
defer p.mut.RUnlock()
m, ok := p.m[iface]
if !ok {
return nil, ErrIfaceNotFound
}
rm := make(map[string]dbus.Variant, len(m))
for k, v := range m {
rm[k] = dbus.MakeVariant(v.Value)
}
return rm, nil
}
// GetMust returns the value of the given property and panics if either the
// interface or the property name are invalid.
func (p *Properties) GetMust(iface, property string) interface{} {
p.mut.RLock()
defer p.mut.RUnlock()
return p.m[iface][property].Value
}
// Introspection returns the introspection data that represents the properties
// of iface.
func (p *Properties) Introspection(iface string) []introspect.Property {
p.mut.RLock()
defer p.mut.RUnlock()
m := p.m[iface]
s := make([]introspect.Property, 0, len(m))
for k, v := range m {
p := introspect.Property{Name: k, Type: dbus.SignatureOf(v.Value).String()}
if v.Writable {
p.Access = "readwrite"
} else {
p.Access = "read"
}
s = append(s, p)
}
return s
}
// set sets the given property and emits PropertyChanged if appropiate. p.mut
// must already be locked.
func (p *Properties) set(iface, property string, v interface{}) {
prop := p.m[iface][property]
prop.Value = v
switch prop.Emit {
case EmitFalse:
// do nothing
case EmitInvalidates:
p.conn.Emit(p.path, "org.freedesktop.DBus.Properties.PropertiesChanged",
iface, map[string]dbus.Variant{}, []string{property})
case EmitTrue:
p.conn.Emit(p.path, "org.freedesktop.DBus.Properties.PropertiesChanged",
iface, map[string]dbus.Variant{property: dbus.MakeVariant(v)},
[]string{})
default:
panic("invalid value for EmitType")
}
}
// Set implements org.freedesktop.Properties.Set.
func (p *Properties) Set(iface, property string, newv dbus.Variant) *dbus.Error {
p.mut.Lock()
defer p.mut.Unlock()
m, ok := p.m[iface]
if !ok {
return ErrIfaceNotFound
}
prop, ok := m[property]
if !ok {
return ErrPropNotFound
}
if !prop.Writable {
return ErrReadOnly
}
if newv.Signature() != dbus.SignatureOf(prop.Value) {
return ErrInvalidArg
}
if prop.Callback != nil {
err := prop.Callback(&Change{p, iface, property, newv.Value()})
if err != nil {
return err
}
}
p.set(iface, property, newv.Value())
return nil
}
// SetMust sets the value of the given property and panics if the interface or
// the property name are invalid.
func (p *Properties) SetMust(iface, property string, v interface{}) {
p.mut.Lock()
p.set(iface, property, v)
p.mut.Unlock()
}

View file

@ -1,369 +0,0 @@
package dbus
import (
"bytes"
"encoding/binary"
"io/ioutil"
"math"
"reflect"
"testing"
)
var protoTests = []struct {
vs []interface{}
bigEndian []byte
littleEndian []byte
}{
{
[]interface{}{int32(0)},
[]byte{0, 0, 0, 0},
[]byte{0, 0, 0, 0},
},
{
[]interface{}{true, false},
[]byte{0, 0, 0, 1, 0, 0, 0, 0},
[]byte{1, 0, 0, 0, 0, 0, 0, 0},
},
{
[]interface{}{byte(0), uint16(12), int16(32), uint32(43)},
[]byte{0, 0, 0, 12, 0, 32, 0, 0, 0, 0, 0, 43},
[]byte{0, 0, 12, 0, 32, 0, 0, 0, 43, 0, 0, 0},
},
{
[]interface{}{int64(-1), uint64(1<<64 - 1)},
bytes.Repeat([]byte{255}, 16),
bytes.Repeat([]byte{255}, 16),
},
{
[]interface{}{math.Inf(+1)},
[]byte{0x7f, 0xf0, 0, 0, 0, 0, 0, 0},
[]byte{0, 0, 0, 0, 0, 0, 0xf0, 0x7f},
},
{
[]interface{}{"foo"},
[]byte{0, 0, 0, 3, 'f', 'o', 'o', 0},
[]byte{3, 0, 0, 0, 'f', 'o', 'o', 0},
},
{
[]interface{}{Signature{"ai"}},
[]byte{2, 'a', 'i', 0},
[]byte{2, 'a', 'i', 0},
},
{
[]interface{}{[]int16{42, 256}},
[]byte{0, 0, 0, 4, 0, 42, 1, 0},
[]byte{4, 0, 0, 0, 42, 0, 0, 1},
},
{
[]interface{}{MakeVariant("foo")},
[]byte{1, 's', 0, 0, 0, 0, 0, 3, 'f', 'o', 'o', 0},
[]byte{1, 's', 0, 0, 3, 0, 0, 0, 'f', 'o', 'o', 0},
},
{
[]interface{}{MakeVariant(MakeVariant(Signature{"v"}))},
[]byte{1, 'v', 0, 1, 'g', 0, 1, 'v', 0},
[]byte{1, 'v', 0, 1, 'g', 0, 1, 'v', 0},
},
{
[]interface{}{map[int32]bool{42: true}},
[]byte{0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 1},
[]byte{8, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 1, 0, 0, 0},
},
{
[]interface{}{map[string]Variant{}, byte(42)},
[]byte{0, 0, 0, 0, 0, 0, 0, 0, 42},
[]byte{0, 0, 0, 0, 0, 0, 0, 0, 42},
},
{
[]interface{}{[]uint64{}, byte(42)},
[]byte{0, 0, 0, 0, 0, 0, 0, 0, 42},
[]byte{0, 0, 0, 0, 0, 0, 0, 0, 42},
},
}
func TestProto(t *testing.T) {
for i, v := range protoTests {
buf := new(bytes.Buffer)
bigEnc := newEncoder(buf, binary.BigEndian)
bigEnc.Encode(v.vs...)
marshalled := buf.Bytes()
if bytes.Compare(marshalled, v.bigEndian) != 0 {
t.Errorf("test %d (marshal be): got '%v', but expected '%v'\n", i+1, marshalled,
v.bigEndian)
}
buf.Reset()
litEnc := newEncoder(buf, binary.LittleEndian)
litEnc.Encode(v.vs...)
marshalled = buf.Bytes()
if bytes.Compare(marshalled, v.littleEndian) != 0 {
t.Errorf("test %d (marshal le): got '%v', but expected '%v'\n", i+1, marshalled,
v.littleEndian)
}
unmarshalled := reflect.MakeSlice(reflect.TypeOf(v.vs),
0, 0)
for i := range v.vs {
unmarshalled = reflect.Append(unmarshalled,
reflect.New(reflect.TypeOf(v.vs[i])))
}
bigDec := newDecoder(bytes.NewReader(v.bigEndian), binary.BigEndian)
vs, err := bigDec.Decode(SignatureOf(v.vs...))
if err != nil {
t.Errorf("test %d (unmarshal be): %s\n", i+1, err)
continue
}
if !reflect.DeepEqual(vs, v.vs) {
t.Errorf("test %d (unmarshal be): got %#v, but expected %#v\n", i+1, vs, v.vs)
}
litDec := newDecoder(bytes.NewReader(v.littleEndian), binary.LittleEndian)
vs, err = litDec.Decode(SignatureOf(v.vs...))
if err != nil {
t.Errorf("test %d (unmarshal le): %s\n", i+1, err)
continue
}
if !reflect.DeepEqual(vs, v.vs) {
t.Errorf("test %d (unmarshal le): got %#v, but expected %#v\n", i+1, vs, v.vs)
}
}
}
func TestProtoMap(t *testing.T) {
m := map[string]uint8{
"foo": 23,
"bar": 2,
}
var n map[string]uint8
buf := new(bytes.Buffer)
enc := newEncoder(buf, binary.LittleEndian)
enc.Encode(m)
dec := newDecoder(buf, binary.LittleEndian)
vs, err := dec.Decode(Signature{"a{sy}"})
if err != nil {
t.Fatal(err)
}
if err = Store(vs, &n); err != nil {
t.Fatal(err)
}
if len(n) != 2 || n["foo"] != 23 || n["bar"] != 2 {
t.Error("got", n)
}
}
func TestProtoVariantStruct(t *testing.T) {
var variant Variant
v := MakeVariant(struct {
A int32
B int16
}{1, 2})
buf := new(bytes.Buffer)
enc := newEncoder(buf, binary.LittleEndian)
enc.Encode(v)
dec := newDecoder(buf, binary.LittleEndian)
vs, err := dec.Decode(Signature{"v"})
if err != nil {
t.Fatal(err)
}
if err = Store(vs, &variant); err != nil {
t.Fatal(err)
}
sl := variant.Value().([]interface{})
v1, v2 := sl[0].(int32), sl[1].(int16)
if v1 != int32(1) {
t.Error("got", v1, "as first int")
}
if v2 != int16(2) {
t.Error("got", v2, "as second int")
}
}
func TestProtoStructTag(t *testing.T) {
type Bar struct {
A int32
B chan interface{} `dbus:"-"`
C int32
}
var bar1, bar2 Bar
bar1.A = 234
bar2.C = 345
buf := new(bytes.Buffer)
enc := newEncoder(buf, binary.LittleEndian)
enc.Encode(bar1)
dec := newDecoder(buf, binary.LittleEndian)
vs, err := dec.Decode(Signature{"(ii)"})
if err != nil {
t.Fatal(err)
}
if err = Store(vs, &bar2); err != nil {
t.Fatal(err)
}
if bar1 != bar2 {
t.Error("struct tag test: got", bar2)
}
}
func TestProtoStoreStruct(t *testing.T) {
var foo struct {
A int32
B string
c chan interface{}
D interface{} `dbus:"-"`
}
src := []interface{}{[]interface{}{int32(42), "foo"}}
err := Store(src, &foo)
if err != nil {
t.Fatal(err)
}
}
func TestProtoStoreNestedStruct(t *testing.T) {
var foo struct {
A int32
B struct {
C string
D float64
}
}
src := []interface{}{
[]interface{}{
int32(42),
[]interface{}{
"foo",
3.14,
},
},
}
err := Store(src, &foo)
if err != nil {
t.Fatal(err)
}
}
func TestMessage(t *testing.T) {
buf := new(bytes.Buffer)
message := new(Message)
message.Type = TypeMethodCall
message.serial = 32
message.Headers = map[HeaderField]Variant{
FieldPath: MakeVariant(ObjectPath("/org/foo/bar")),
FieldMember: MakeVariant("baz"),
}
message.Body = make([]interface{}, 0)
err := message.EncodeTo(buf, binary.LittleEndian)
if err != nil {
t.Error(err)
}
_, err = DecodeMessage(buf)
if err != nil {
t.Error(err)
}
}
func TestProtoStructInterfaces(t *testing.T) {
b := []byte{42}
vs, err := newDecoder(bytes.NewReader(b), binary.LittleEndian).Decode(Signature{"(y)"})
if err != nil {
t.Fatal(err)
}
if vs[0].([]interface{})[0].(byte) != 42 {
t.Errorf("wrongs results (got %v)", vs)
}
}
// ordinary org.freedesktop.DBus.Hello call
var smallMessage = &Message{
Type: TypeMethodCall,
serial: 1,
Headers: map[HeaderField]Variant{
FieldDestination: MakeVariant("org.freedesktop.DBus"),
FieldPath: MakeVariant(ObjectPath("/org/freedesktop/DBus")),
FieldInterface: MakeVariant("org.freedesktop.DBus"),
FieldMember: MakeVariant("Hello"),
},
}
// org.freedesktop.Notifications.Notify
var bigMessage = &Message{
Type: TypeMethodCall,
serial: 2,
Headers: map[HeaderField]Variant{
FieldDestination: MakeVariant("org.freedesktop.Notifications"),
FieldPath: MakeVariant(ObjectPath("/org/freedesktop/Notifications")),
FieldInterface: MakeVariant("org.freedesktop.Notifications"),
FieldMember: MakeVariant("Notify"),
FieldSignature: MakeVariant(Signature{"susssasa{sv}i"}),
},
Body: []interface{}{
"app_name",
uint32(0),
"dialog-information",
"Notification",
"This is the body of a notification",
[]string{"ok", "Ok"},
map[string]Variant{
"sound-name": MakeVariant("dialog-information"),
},
int32(-1),
},
}
func BenchmarkDecodeMessageSmall(b *testing.B) {
var err error
var rd *bytes.Reader
b.StopTimer()
buf := new(bytes.Buffer)
err = smallMessage.EncodeTo(buf, binary.LittleEndian)
if err != nil {
b.Fatal(err)
}
decoded := buf.Bytes()
b.StartTimer()
for i := 0; i < b.N; i++ {
rd = bytes.NewReader(decoded)
_, err = DecodeMessage(rd)
if err != nil {
b.Fatal(err)
}
}
}
func BenchmarkDecodeMessageBig(b *testing.B) {
var err error
var rd *bytes.Reader
b.StopTimer()
buf := new(bytes.Buffer)
err = bigMessage.EncodeTo(buf, binary.LittleEndian)
if err != nil {
b.Fatal(err)
}
decoded := buf.Bytes()
b.StartTimer()
for i := 0; i < b.N; i++ {
rd = bytes.NewReader(decoded)
_, err = DecodeMessage(rd)
if err != nil {
b.Fatal(err)
}
}
}
func BenchmarkEncodeMessageSmall(b *testing.B) {
var err error
for i := 0; i < b.N; i++ {
err = smallMessage.EncodeTo(ioutil.Discard, binary.LittleEndian)
if err != nil {
b.Fatal(err)
}
}
}
func BenchmarkEncodeMessageBig(b *testing.B) {
var err error
for i := 0; i < b.N; i++ {
err = bigMessage.EncodeTo(ioutil.Discard, binary.LittleEndian)
if err != nil {
b.Fatal(err)
}
}
}

View file

@ -1,70 +0,0 @@
package dbus
import (
"testing"
)
var sigTests = []struct {
vs []interface{}
sig Signature
}{
{
[]interface{}{new(int32)},
Signature{"i"},
},
{
[]interface{}{new(string)},
Signature{"s"},
},
{
[]interface{}{new(Signature)},
Signature{"g"},
},
{
[]interface{}{new([]int16)},
Signature{"an"},
},
{
[]interface{}{new(int16), new(uint32)},
Signature{"nu"},
},
{
[]interface{}{new(map[byte]Variant)},
Signature{"a{yv}"},
},
{
[]interface{}{new(Variant), new([]map[int32]string)},
Signature{"vaa{is}"},
},
}
func TestSig(t *testing.T) {
for i, v := range sigTests {
sig := SignatureOf(v.vs...)
if sig != v.sig {
t.Errorf("test %d: got %q, expected %q", i+1, sig.str, v.sig.str)
}
}
}
var getSigTest = []interface{}{
[]struct {
b byte
i int32
t uint64
s string
}{},
map[string]Variant{},
}
func BenchmarkGetSignatureSimple(b *testing.B) {
for i := 0; i < b.N; i++ {
SignatureOf("", int32(0))
}
}
func BenchmarkGetSignatureLong(b *testing.B) {
for i := 0; i < b.N; i++ {
SignatureOf(getSigTest...)
}
}

View file

@ -1,26 +0,0 @@
package dbus
import (
"fmt"
"net"
"testing"
)
func TestTcpConnection(t *testing.T) {
listener, err := net.Listen("tcp", ":0")
if err != nil {
t.Fatal("Failed to create listener")
}
host, port, err := net.SplitHostPort(listener.Addr().String())
if err != nil {
t.Fatal("Failed to parse host/port")
}
conn, err := Dial(fmt.Sprintf("tcp:host=%s,port=%s", host, port))
if err != nil {
t.Error("Expected no error, got", err)
}
if conn == nil {
t.Error("Expected connection, got nil")
}
}

View file

@ -1,49 +0,0 @@
package dbus
import (
"os"
"testing"
)
const testString = `This is a test!
This text should be read from the file that is created by this test.`
type unixFDTest struct{}
func (t unixFDTest) Test(fd UnixFD) (string, *Error) {
var b [4096]byte
file := os.NewFile(uintptr(fd), "testfile")
defer file.Close()
n, err := file.Read(b[:])
if err != nil {
return "", &Error{"com.github.guelfey.test.Error", nil}
}
return string(b[:n]), nil
}
func TestUnixFDs(t *testing.T) {
conn, err := SessionBus()
if err != nil {
t.Fatal(err)
}
r, w, err := os.Pipe()
if err != nil {
t.Fatal(err)
}
defer w.Close()
if _, err := w.Write([]byte(testString)); err != nil {
t.Fatal(err)
}
name := conn.Names()[0]
test := unixFDTest{}
conn.Export(test, "/com/github/guelfey/test", "com.github.guelfey.test")
var s string
obj := conn.Object(name, "/com/github/guelfey/test")
err = obj.Call("com.github.guelfey.test.Test", 0, UnixFD(r.Fd())).Store(&s)
if err != nil {
t.Fatal(err)
}
if s != testString {
t.Fatal("got", s, "wanted", testString)
}
}

View file

@ -1,78 +0,0 @@
package dbus
import "reflect"
import "testing"
var variantFormatTests = []struct {
v interface{}
s string
}{
{int32(1), `1`},
{"foo", `"foo"`},
{ObjectPath("/org/foo"), `@o "/org/foo"`},
{Signature{"i"}, `@g "i"`},
{[]byte{}, `@ay []`},
{[]int32{1, 2}, `[1, 2]`},
{[]int64{1, 2}, `@ax [1, 2]`},
{[][]int32{{3, 4}, {5, 6}}, `[[3, 4], [5, 6]]`},
{[]Variant{MakeVariant(int32(1)), MakeVariant(1.0)}, `[<1>, <@d 1>]`},
{map[string]int32{"one": 1, "two": 2}, `{"one": 1, "two": 2}`},
{map[int32]ObjectPath{1: "/org/foo"}, `@a{io} {1: "/org/foo"}`},
{map[string]Variant{}, `@a{sv} {}`},
}
func TestFormatVariant(t *testing.T) {
for i, v := range variantFormatTests {
if s := MakeVariant(v.v).String(); s != v.s {
t.Errorf("test %d: got %q, wanted %q", i+1, s, v.s)
}
}
}
var variantParseTests = []struct {
s string
v interface{}
}{
{"1", int32(1)},
{"true", true},
{"false", false},
{"1.0", float64(1.0)},
{"0x10", int32(16)},
{"1e1", float64(10)},
{`"foo"`, "foo"},
{`"\a\b\f\n\r\t"`, "\x07\x08\x0c\n\r\t"},
{`"\u00e4\U0001f603"`, "\u00e4\U0001f603"},
{"[1]", []int32{1}},
{"[1, 2, 3]", []int32{1, 2, 3}},
{"@ai []", []int32{}},
{"[1, 5.0]", []float64{1, 5.0}},
{"[[1, 2], [3, 4.0]]", [][]float64{{1, 2}, {3, 4}}},
{`[@o "/org/foo", "/org/bar"]`, []ObjectPath{"/org/foo", "/org/bar"}},
{"<1>", MakeVariant(int32(1))},
{"[<1>, <2.0>]", []Variant{MakeVariant(int32(1)), MakeVariant(2.0)}},
{`[[], [""]]`, [][]string{{}, {""}}},
{`@a{ss} {}`, map[string]string{}},
{`{"foo": 1}`, map[string]int32{"foo": 1}},
{`[{}, {"foo": "bar"}]`, []map[string]string{{}, {"foo": "bar"}}},
{`{"a": <1>, "b": <"foo">}`,
map[string]Variant{"a": MakeVariant(int32(1)), "b": MakeVariant("foo")}},
{`b''`, []byte{0}},
{`b"abc"`, []byte{'a', 'b', 'c', 0}},
{`b"\x01\0002\a\b\f\n\r\t"`, []byte{1, 2, 0x7, 0x8, 0xc, '\n', '\r', '\t', 0}},
{`[[0], b""]`, [][]byte{{0}, {0}}},
{"int16 0", int16(0)},
{"byte 0", byte(0)},
}
func TestParseVariant(t *testing.T) {
for i, v := range variantParseTests {
nv, err := ParseVariant(v.s, Signature{})
if err != nil {
t.Errorf("test %d: parsing failed: %s", i+1, err)
continue
}
if !reflect.DeepEqual(nv.value, v.v) {
t.Errorf("test %d: got %q, wanted %q", i+1, nv, v.v)
}
}
}