123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- /*
- Copyright 2015 The Kubernetes 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 dbus
- import (
- "fmt"
- "os"
- "testing"
- godbus "github.com/godbus/dbus"
- )
- const (
- DBusNameFlagDoNotQueue uint32 = 1 << (iota + 1)
- )
- const (
- DBusRequestNameReplyPrimaryOwner uint32 = iota + 1
- DBusRequestNameReplyAlreadyOwner
- )
- const (
- DBusReleaseNameReplyReleased uint32 = iota + 1
- DBusReleaseNameReplyNotOwner
- )
- func doDBusTest(t *testing.T, dbus Interface, real bool) {
- bus, err := dbus.SystemBus()
- if err != nil {
- if !real {
- t.Errorf("dbus.SystemBus() failed with fake Interface")
- }
- t.Skipf("D-Bus is not running: %v", err)
- }
- busObj := bus.BusObject()
- id := ""
- err = busObj.Call("org.freedesktop.DBus.GetId", 0).Store(&id)
- if err != nil {
- t.Errorf("expected success, got %v", err)
- }
- if len(id) == 0 {
- t.Errorf("expected non-empty Id, got \"\"")
- }
- // Switch to the session bus for the rest, since the system bus is more
- // locked down (and thus harder to trick into emitting signals).
- bus, err = dbus.SessionBus()
- if err != nil {
- if !real {
- t.Errorf("dbus.SystemBus() failed with fake Interface")
- }
- t.Skipf("D-Bus session bus is not available: %v", err)
- }
- busObj = bus.BusObject()
- name := fmt.Sprintf("io.kubernetes.dbus_test_%d", os.Getpid())
- owner := ""
- err = busObj.Call("org.freedesktop.DBus.GetNameOwner", 0, name).Store(&owner)
- if err == nil {
- t.Errorf("expected '%s' to be un-owned, but found owner %s", name, owner)
- }
- dbuserr, ok := err.(godbus.Error)
- if !ok {
- t.Errorf("expected godbus.Error, but got %#v", err)
- }
- if dbuserr.Name != "org.freedesktop.DBus.Error.NameHasNoOwner" {
- t.Errorf("expected NameHasNoOwner error but got %v", err)
- }
- sigchan := make(chan *godbus.Signal, 10)
- bus.Signal(sigchan)
- rule := fmt.Sprintf("type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged',path='/org/freedesktop/DBus',sender='org.freedesktop.DBus',arg0='%s'", name)
- err = busObj.Call("org.freedesktop.DBus.AddMatch", 0, rule).Store()
- if err != nil {
- t.Errorf("expected success, got %v", err)
- }
- var ret uint32
- err = busObj.Call("org.freedesktop.DBus.RequestName", 0, name, DBusNameFlagDoNotQueue).Store(&ret)
- if err != nil {
- t.Errorf("expected success, got %v", err)
- }
- if ret != DBusRequestNameReplyPrimaryOwner {
- t.Errorf("expected %v, got %v", DBusRequestNameReplyPrimaryOwner, ret)
- }
- err = busObj.Call("org.freedesktop.DBus.GetNameOwner", 0, name).Store(&owner)
- if err != nil {
- t.Errorf("expected success, got %v", err)
- }
- var changedSignal, acquiredSignal, lostSignal *godbus.Signal
- sig1 := <-sigchan
- sig2 := <-sigchan
- // We get two signals, but the order isn't guaranteed
- if sig1.Name == "org.freedesktop.DBus.NameOwnerChanged" {
- changedSignal = sig1
- acquiredSignal = sig2
- } else {
- acquiredSignal = sig1
- changedSignal = sig2
- }
- if acquiredSignal.Sender != "org.freedesktop.DBus" || acquiredSignal.Name != "org.freedesktop.DBus.NameAcquired" {
- t.Errorf("expected NameAcquired signal, got %v", acquiredSignal)
- }
- acquiredName := acquiredSignal.Body[0].(string)
- if acquiredName != name {
- t.Errorf("unexpected NameAcquired arguments: %v", acquiredSignal)
- }
- if changedSignal.Sender != "org.freedesktop.DBus" || changedSignal.Name != "org.freedesktop.DBus.NameOwnerChanged" {
- t.Errorf("expected NameOwnerChanged signal, got %v", changedSignal)
- }
- changedName := changedSignal.Body[0].(string)
- oldOwner := changedSignal.Body[1].(string)
- newOwner := changedSignal.Body[2].(string)
- if changedName != name || oldOwner != "" || newOwner != owner {
- t.Errorf("unexpected NameOwnerChanged arguments: %v", changedSignal)
- }
- err = busObj.Call("org.freedesktop.DBus.ReleaseName", 0, name).Store(&ret)
- if err != nil {
- t.Errorf("expected success, got %v", err)
- }
- if ret != DBusReleaseNameReplyReleased {
- t.Errorf("expected %v, got %v", DBusReleaseNameReplyReleased, ret)
- }
- sig1 = <-sigchan
- sig2 = <-sigchan
- if sig1.Name == "org.freedesktop.DBus.NameOwnerChanged" {
- changedSignal = sig1
- lostSignal = sig2
- } else {
- lostSignal = sig1
- changedSignal = sig2
- }
- if lostSignal.Sender != "org.freedesktop.DBus" || lostSignal.Name != "org.freedesktop.DBus.NameLost" {
- t.Errorf("expected NameLost signal, got %v", lostSignal)
- }
- lostName := lostSignal.Body[0].(string)
- if lostName != name {
- t.Errorf("unexpected NameLost arguments: %v", lostSignal)
- }
- if changedSignal.Sender != "org.freedesktop.DBus" || changedSignal.Name != "org.freedesktop.DBus.NameOwnerChanged" {
- t.Errorf("expected NameOwnerChanged signal, got %v", changedSignal)
- }
- changedName = changedSignal.Body[0].(string)
- oldOwner = changedSignal.Body[1].(string)
- newOwner = changedSignal.Body[2].(string)
- if changedName != name || oldOwner != owner || newOwner != "" {
- t.Errorf("unexpected NameOwnerChanged arguments: %v", changedSignal)
- }
- if len(sigchan) != 0 {
- t.Errorf("unexpected extra signals (%d)", len(sigchan))
- }
- // Unregister sigchan
- bus.Signal(sigchan)
- }
- func TestRealDBus(t *testing.T) {
- dbus := New()
- doDBusTest(t, dbus, true)
- }
- func TestFakeDBus(t *testing.T) {
- uniqueName := ":1.1"
- ownedName := ""
- fakeSystem := NewFakeConnection()
- fakeSystem.SetBusObject(
- func(method string, args ...interface{}) ([]interface{}, error) {
- if method == "org.freedesktop.DBus.GetId" {
- return []interface{}{"foo"}, nil
- }
- return nil, fmt.Errorf("unexpected method call '%s'", method)
- },
- )
- fakeSession := NewFakeConnection()
- fakeSession.SetBusObject(
- func(method string, args ...interface{}) ([]interface{}, error) {
- if method == "org.freedesktop.DBus.GetNameOwner" {
- checkName := args[0].(string)
- if checkName != ownedName {
- return nil, godbus.Error{Name: "org.freedesktop.DBus.Error.NameHasNoOwner", Body: nil}
- }
- return []interface{}{uniqueName}, nil
- } else if method == "org.freedesktop.DBus.RequestName" {
- reqName := args[0].(string)
- _ = args[1].(uint32)
- if ownedName != "" {
- return []interface{}{DBusRequestNameReplyAlreadyOwner}, nil
- }
- ownedName = reqName
- fakeSession.EmitSignal("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "NameAcquired", reqName)
- fakeSession.EmitSignal("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "NameOwnerChanged", reqName, "", uniqueName)
- return []interface{}{DBusRequestNameReplyPrimaryOwner}, nil
- } else if method == "org.freedesktop.DBus.ReleaseName" {
- reqName := args[0].(string)
- if reqName != ownedName {
- return []interface{}{DBusReleaseNameReplyNotOwner}, nil
- }
- ownedName = ""
- fakeSession.EmitSignal("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "NameOwnerChanged", reqName, uniqueName, "")
- fakeSession.EmitSignal("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "NameLost", reqName)
- return []interface{}{DBusReleaseNameReplyReleased}, nil
- } else if method == "org.freedesktop.DBus.AddMatch" {
- return nil, nil
- } else {
- return nil, fmt.Errorf("unexpected method call '%s'", method)
- }
- },
- )
- dbus := NewFake(fakeSystem, fakeSession)
- doDBusTest(t, dbus, false)
- }
|