mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-11-04 07:49:35 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			250 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			250 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
/*
 | 
						|
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 (
 | 
						|
	DBusNameFlagAllowReplacement uint32 = 1 << (iota + 1)
 | 
						|
	DBusNameFlagReplaceExisting
 | 
						|
	DBusNameFlagDoNotQueue
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	DBusRequestNameReplyPrimaryOwner uint32 = iota + 1
 | 
						|
	DBusRequestNameReplyInQueue
 | 
						|
	DBusRequestNameReplyExists
 | 
						|
	DBusRequestNameReplyAlreadyOwner
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	DBusReleaseNameReplyReleased uint32 = iota + 1
 | 
						|
	DBusReleaseNameReplyNonExistent
 | 
						|
	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}
 | 
						|
				} else {
 | 
						|
					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)
 | 
						|
}
 |