Repository: godbus/dbus
Pull request #185 (2019-12-03 13:39:49)

Add Connect* functions
Hi there.

This partially solves problems described in #179 giving a shortcuts to establish connection with the system/session bus without calling `Auth` and `Hello` explicitly.

There's still number of `SystemBus` and `SessionBus` calls in examples and tests we need to decide connecting which way will be recommended to users.

P.S. I'd still recommend to get rid of the conception of shared/private connections.

jsouthworth: I like the new API here, it makes things generally easier. I'd rather not break compatibility with existing clients again. Leaving the shared vs. private connection doesn't hurt anything. If you wish, you can add documentation to the old bus access methods to say they are deprecated in favor of the new Connect functions to make it clear the new functions are preferred for new clients.
jsouthworth: To address another comment in your description; I will support having these new functions be the recommended mechanism for new clients and updating the examples accordingly.
amenzhinsky: @jsouthworth updated tests and examples, please have a look
jsouthworth: Looks great! Thanks for following through on this.

Patch:
diff --git a/_examples/bluetooth_introspect.go b/_examples/bluetooth_introspect.go
index e128917..c8a68ed 100644
--- a/_examples/bluetooth_introspect.go
+++ b/_examples/bluetooth_introspect.go
@@ -8,11 +8,12 @@ import (
 )
 
 func main() {
-	conn, err := dbus.SystemBus()
+	conn, err := dbus.ConnectSystemBus()
 	if err != nil {
 		fmt.Fprintln(os.Stderr, "Failed to connect to SystemBus bus:", err)
 		os.Exit(1)
 	}
+	defer conn.Close()
 
 	var s string
 	err = conn.Object("org.bluez", "/").Call("org.freedesktop.DBus.Introspectable.Introspect", 0).Store(&s)
diff --git a/_examples/eavesdrop.go b/_examples/eavesdrop.go
index df49e23..86306f0 100644
--- a/_examples/eavesdrop.go
+++ b/_examples/eavesdrop.go
@@ -8,11 +8,12 @@ import (
 )
 
 func main() {
-	conn, err := dbus.SessionBus()
+	conn, err := dbus.ConnectSessionBus()
 	if err != nil {
 		fmt.Fprintln(os.Stderr, "Failed to connect to session bus:", err)
 		os.Exit(1)
 	}
+	defer conn.Close()
 
 	for _, v := range []string{"method_call", "method_return", "error", "signal"} {
 		call := conn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0,
diff --git a/_examples/introspect.go b/_examples/introspect.go
index 2d12383..44b33c8 100644
--- a/_examples/introspect.go
+++ b/_examples/introspect.go
@@ -9,10 +9,12 @@ import (
 )
 
 func main() {
-	conn, err := dbus.SessionBus()
+	conn, err := dbus.ConnectSessionBus()
 	if err != nil {
 		panic(err)
 	}
+	defer conn.Close()
+
 	node, err := introspect.Call(conn.Object("org.freedesktop.DBus", "/org/freedesktop/DBus"))
 	if err != nil {
 		panic(err)
diff --git a/_examples/list-names.go b/_examples/list-names.go
index 17ed640..6f91dce 100644
--- a/_examples/list-names.go
+++ b/_examples/list-names.go
@@ -8,11 +8,12 @@ import (
 )
 
 func main() {
-	conn, err := dbus.SessionBus()
+	conn, err := dbus.ConnectSessionBus()
 	if err != nil {
 		fmt.Fprintln(os.Stderr, "Failed to connect to session bus:", err)
 		os.Exit(1)
 	}
+	defer conn.Close()
 
 	var s []string
 	err = conn.BusObject().Call("org.freedesktop.DBus.ListNames", 0).Store(&s)
diff --git a/_examples/monitor.go b/_examples/monitor.go
index 87cf4b6..0750da8 100644
--- a/_examples/monitor.go
+++ b/_examples/monitor.go
@@ -8,11 +8,12 @@ import (
 )
 
 func main() {
-	conn, err := dbus.SessionBus()
+	conn, err := dbus.ConnectSessionBus()
 	if err != nil {
 		fmt.Fprintln(os.Stderr, "Failed to connect to session bus:", err)
 		os.Exit(1)
 	}
+	defer conn.Close()
 
 	var rules = []string{
 		"type='signal',member='Notify',path='/org/freedesktop/Notifications',interface='org.freedesktop.Notifications'",
diff --git a/_examples/notification.go b/_examples/notification.go
index 6956a20..22991d7 100644
--- a/_examples/notification.go
+++ b/_examples/notification.go
@@ -3,10 +3,12 @@ package main
 import "github.com/godbus/dbus/v5"
 
 func main() {
-	conn, err := dbus.SessionBus()
+	conn, err := dbus.ConnectSessionBus()
 	if err != nil {
 		panic(err)
 	}
+	defer conn.Close()
+
 	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{},
diff --git a/_examples/prop.go b/_examples/prop.go
index 3128a92..7053e2a 100644
--- a/_examples/prop.go
+++ b/_examples/prop.go
@@ -17,10 +17,12 @@ func (f foo) Foo() (string, *dbus.Error) {
 }
 
 func main() {
-	conn, err := dbus.SessionBus()
+	conn, err := dbus.ConnectSessionBus()
 	if err != nil {
 		panic(err)
 	}
+	defer conn.Close()
+
 	reply, err := conn.RequestName("com.github.guelfey.Demo",
 		dbus.NameFlagDoNotQueue)
 	if err != nil {
diff --git a/_examples/server.go b/_examples/server.go
index 0f4ee32..f5464d9 100644
--- a/_examples/server.go
+++ b/_examples/server.go
@@ -24,10 +24,11 @@ func (f foo) Foo() (string, *dbus.Error) {
 }
 
 func main() {
-	conn, err := dbus.SessionBus()
+	conn, err := dbus.ConnectSessionBus()
 	if err != nil {
 		panic(err)
 	}
+	defer conn.Close()
 
 	f := foo("Bar!")
 	conn.Export(f, "/com/github/guelfey/Demo", "com.github.guelfey.Demo")
diff --git a/_examples/signal.go b/_examples/signal.go
index 02f16e5..df4732a 100644
--- a/_examples/signal.go
+++ b/_examples/signal.go
@@ -8,14 +8,20 @@ import (
 )
 
 func main() {
-	conn, err := dbus.SessionBus()
+	conn, err := dbus.ConnectSessionBus()
 	if err != nil {
 		fmt.Fprintln(os.Stderr, "Failed to connect to session bus:", err)
 		os.Exit(1)
 	}
+	defer conn.Close()
 
-	conn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0,
-		"type='signal',path='/org/freedesktop/DBus',interface='org.freedesktop.DBus',sender='org.freedesktop.DBus'")
+	if err = conn.AddMatchSignal(
+		dbus.WithMatchObjectPath("/org/freedesktop/DBus"),
+		dbus.WithMatchInterface("org.freedesktop.DBus"),
+		dbus.WithMatchSender("org.freedesktop.DBus"),
+	); err != nil {
+		panic(err)
+	}
 
 	c := make(chan *dbus.Signal, 10)
 	conn.Signal(c)
diff --git a/_examples/tcp_conn.go b/_examples/tcp_conn.go
index 7940ba6..8e4b2bf 100644
--- a/_examples/tcp_conn.go
+++ b/_examples/tcp_conn.go
@@ -47,12 +47,11 @@ func run(addr string) error {
 	if err != nil {
 		return err
 	}
-	conn, err := dbus.Dial("tcp:host=" + host + ",port=" + port)
+	conn, err := dbus.Connect("tcp:host="+host+",port="+port, dbus.WithAuth(dbus.AuthAnonymous()))
 	if err != nil {
 		return err
 	}
-	if err = conn.Auth([]dbus.Auth{dbus.AuthAnonymous()}); err != nil {
-		return err
-	}
-	return conn.Hello()
+	defer conn.Close()
+	fmt.Println("connected to D-Bus over TCP")
+	return nil
 }
diff --git a/conn.go b/conn.go
index b55bc99..ad00ccb 100644
--- a/conn.go
+++ b/conn.go
@@ -45,6 +45,7 @@ type Conn struct {
 	serialGen     SerialGenerator
 	inInt         Interceptor
 	outInt        Interceptor
+	auth          []Auth
 
 	names      *nameTracker
 	calls      *callTracker
@@ -67,19 +68,7 @@ func SessionBus() (conn *Conn, err error) {
 			sessionBus = conn
 		}
 	}()
-	conn, err = SessionBusPrivate()
-	if err != nil {
-		return
-	}
-	if err = conn.Auth(nil); err != nil {
-		conn.Close()
-		conn = nil
-		return
-	}
-	if err = conn.Hello(); err != nil {
-		conn.Close()
-		conn = nil
-	}
+	conn, err = ConnectSessionBus()
 	return
 }
 
@@ -124,20 +113,42 @@ func SystemBus() (conn *Conn, err error) {
 			systemBus = conn
 		}
 	}()
-	conn, err = SystemBusPrivate()
+	conn, err = ConnectSystemBus()
+	return
+}
+
+// ConnectSessionBus connects to the session bus.
+func ConnectSessionBus(opts ...ConnOption) (*Conn, error) {
+	address, err := getSessionBusAddress()
 	if err != nil {
-		return
+		return nil, err
 	}
-	if err = conn.Auth(nil); err != nil {
-		conn.Close()
-		conn = nil
-		return
+	return Connect(address, opts...)
+}
+
+// ConnectSystemBus connects to the system bus.
+func ConnectSystemBus(opts ...ConnOption) (*Conn, error) {
+	return Connect(getSystemBusPlatformAddress(), opts...)
+}
+
+// Connect connects to the given address.
+//
+// Returned connection is ready to use and doesn't require calling
+// Auth and Hello methods to make it usable.
+func Connect(address string, opts ...ConnOption) (*Conn, error) {
+	conn, err := Dial(address, opts...)
+	if err != nil {
+		return nil, err
+	}
+	if err = conn.Auth(conn.auth); err != nil {
+		_ = conn.Close()
+		return nil, err
 	}
 	if err = conn.Hello(); err != nil {
-		conn.Close()
-		conn = nil
+		_ = conn.Close()
+		return nil, err
 	}
-	return
+	return conn, nil
 }
 
 // SystemBusPrivate returns a new private connection to the system bus.
@@ -197,6 +208,14 @@ func WithSerialGenerator(gen SerialGenerator) ConnOption {
 	}
 }
 
+// WithAuth sets authentication methods for the auth conversation.
+func WithAuth(methods ...Auth) ConnOption {
+	return func(conn *Conn) error {
+		conn.auth = methods
+		return nil
+	}
+}
+
 // Interceptor intercepts incoming and outgoing messages.
 type Interceptor func(msg *Message)
 


Test patch:
diff --git a/conn_test.go b/conn_test.go
index ef3b8d9..9360131 100644
--- a/conn_test.go
+++ b/conn_test.go
@@ -24,31 +24,33 @@ func TestSystemBus(t *testing.T) {
 	}
 }
 
-func ExampleSystemBusPrivate() {
-	setupPrivateSystemBus := func() (conn *Conn, err error) {
-		conn, err = SystemBusPrivate()
-		if err != nil {
-			return nil, err
-		}
-		if err = conn.Auth(nil); err != nil {
-			conn.Close()
-			conn = nil
-			return
-		}
-		if err = conn.Hello(); err != nil {
-			conn.Close()
-			conn = nil
-		}
-		return conn, nil // success
+func TestConnectSessionBus(t *testing.T) {
+	conn, err := ConnectSessionBus()
+	if err != nil {
+		t.Fatal(err)
+	}
+	if err = conn.Close(); err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestConnectSystemBus(t *testing.T) {
+	conn, err := ConnectSystemBus()
+	if err != nil {
+		t.Fatal(err)
+	}
+	if err = conn.Close(); err != nil {
+		t.Fatal(err)
 	}
-	_, _ = setupPrivateSystemBus()
 }
 
 func TestSend(t *testing.T) {
-	bus, err := SessionBus()
+	bus, err := ConnectSessionBus()
 	if err != nil {
 		t.Fatal(err)
 	}
+	defer bus.Close()
+
 	ch := make(chan *Call, 1)
 	msg := &Message{
 		Type:  TypeMethodCall,
@@ -68,10 +70,12 @@ func TestSend(t *testing.T) {
 }
 
 func TestFlagNoReplyExpectedSend(t *testing.T) {
-	bus, err := SessionBus()
+	bus, err := ConnectSessionBus()
 	if err != nil {
 		t.Fatal(err)
 	}
+	defer bus.Close()
+
 	done := make(chan struct{})
 	go func() {
 		bus.BusObject().Call("org.freedesktop.DBus.ListNames", FlagNoReplyExpected)
@@ -201,19 +205,12 @@ func TestCloseChannelAfterRemoveSignal(t *testing.T) {
 }
 
 func TestAddAndRemoveMatchSignal(t *testing.T) {
-	conn, err := SessionBusPrivate()
+	conn, err := ConnectSessionBus()
 	if err != nil {
 		t.Fatal(err)
 	}
 	defer conn.Close()
 
-	if err = conn.Auth(nil); err != nil {
-		t.Fatal(err)
-	}
-	if err = conn.Hello(); err != nil {
-		t.Fatal(err)
-	}
-
 	sigc := make(chan *Signal, 1)
 	conn.Signal(sigc)
 
@@ -269,10 +266,12 @@ func BenchmarkCall(b *testing.B) {
 	b.StopTimer()
 	b.ReportAllocs()
 	var s string
-	bus, err := SessionBus()
+	bus, err := ConnectSessionBus()
 	if err != nil {
 		b.Fatal(err)
 	}
+	defer bus.Close()
+
 	name := bus.Names()[0]
 	obj := bus.BusObject()
 	b.StartTimer()
@@ -290,10 +289,12 @@ func BenchmarkCall(b *testing.B) {
 func BenchmarkCallAsync(b *testing.B) {
 	b.StopTimer()
 	b.ReportAllocs()
-	bus, err := SessionBus()
+	bus, err := ConnectSessionBus()
 	if err != nil {
 		b.Fatal(err)
 	}
+	defer bus.Close()
+
 	name := bus.Names()[0]
 	obj := bus.BusObject()
 	c := make(chan *Call, 50)
@@ -320,58 +321,56 @@ func BenchmarkCallAsync(b *testing.B) {
 
 func BenchmarkServe(b *testing.B) {
 	b.StopTimer()
-	srv, err := SessionBus()
+	srv, err := ConnectSessionBus()
 	if err != nil {
 		b.Fatal(err)
 	}
-	cli, err := SessionBusPrivate()
+	defer srv.Close()
+
+	cli, err := ConnectSessionBus()
 	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)
-	}
+	defer cli.Close()
+
 	benchmarkServe(b, srv, cli)
 }
 
 func BenchmarkServeAsync(b *testing.B) {
 	b.StopTimer()
-	srv, err := SessionBus()
+	srv, err := ConnectSessionBus()
 	if err != nil {
 		b.Fatal(err)
 	}
-	cli, err := SessionBusPrivate()
+	defer srv.Close()
+
+	cli, err := ConnectSessionBus()
 	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)
-	}
+	defer cli.Close()
+
 	benchmarkServeAsync(b, srv, cli)
 }
 
 func BenchmarkServeSameConn(b *testing.B) {
 	b.StopTimer()
-	bus, err := SessionBus()
+	bus, err := ConnectSessionBus()
 	if err != nil {
 		b.Fatal(err)
 	}
+	defer bus.Close()
 
 	benchmarkServe(b, bus, bus)
 }
 
 func BenchmarkServeSameConnAsync(b *testing.B) {
 	b.StopTimer()
-	bus, err := SessionBus()
+	bus, err := ConnectSessionBus()
 	if err != nil {
 		b.Fatal(err)
 	}
+	defer bus.Close()
 
 	benchmarkServeAsync(b, bus, bus)
 }
@@ -434,7 +433,7 @@ func TestGetKey(t *testing.T) {
 }
 
 func TestInterceptors(t *testing.T) {
-	conn, err := SessionBusPrivate(
+	conn, err := ConnectSessionBus(
 		WithIncomingInterceptor(func(msg *Message) {
 			log.Println("<", msg)
 		}),
@@ -446,32 +445,15 @@ func TestInterceptors(t *testing.T) {
 		t.Fatal(err)
 	}
 	defer conn.Close()
-
-	if err = conn.Auth(nil); err != nil {
-		t.Fatal(err)
-	}
-	if err = conn.Hello(); err != nil {
-		t.Fatal(err)
-	}
 }
 
 func TestCloseCancelsConnectionContext(t *testing.T) {
-	bus, err := SessionBusPrivate()
+	bus, err := ConnectSessionBus()
 	if err != nil {
 		t.Fatal(err)
 	}
 	defer bus.Close()
 
-	if err = bus.Auth(nil); err != nil {
-		t.Fatal(err)
-	}
-	if err = bus.Hello(); err != nil {
-		t.Fatal(err)
-	}
-	if err != nil {
-		t.Fatal(err)
-	}
-
 	// The context is not done at this point
 	ctx := bus.Context()
 	select {
diff --git a/examples_test.go b/examples_test.go
index 0218ac5..7b11dea 100644
--- a/examples_test.go
+++ b/examples_test.go
@@ -3,21 +3,25 @@ package dbus
 import "fmt"
 
 func ExampleConn_Emit() {
-	conn, err := SessionBus()
+	conn, err := ConnectSystemBus()
 	if err != nil {
 		panic(err)
 	}
+	defer conn.Close()
 
-	conn.Emit("/foo/bar", "foo.bar.Baz", uint32(0xDAEDBEEF))
+	if err := conn.Emit("/foo/bar", "foo.bar.Baz", uint32(0xDAEDBEEF)); err != nil {
+		panic(err)
+	}
 }
 
 func ExampleObject_Call() {
 	var list []string
 
-	conn, err := SessionBus()
+	conn, err := ConnectSessionBus()
 	if err != nil {
 		panic(err)
 	}
+	defer conn.Close()
 
 	err = conn.BusObject().Call("org.freedesktop.DBus.ListNames", 0).Store(&list)
 	if err != nil {
@@ -29,10 +33,11 @@ func ExampleObject_Call() {
 }
 
 func ExampleObject_Go() {
-	conn, err := SessionBus()
+	conn, err := ConnectSessionBus()
 	if err != nil {
 		panic(err)
 	}
+	defer conn.Close()
 
 	ch := make(chan *Call, 10)
 	conn.BusObject().Go("org.freedesktop.DBus.ListActivatableNames", 0, ch)
diff --git a/export_test.go b/export_test.go
index 30f5f5e..ce13a8d 100644
--- a/export_test.go
+++ b/export_test.go
@@ -36,10 +36,11 @@ func (export badExport) Foo(param string) string {
 
 // Test typical Export usage.
 func TestExport(t *testing.T) {
-	connection, err := SessionBus()
+	connection, err := ConnectSessionBus()
 	if err != nil {
 		t.Fatalf("Unexpected error connecting to session bus: %s", err)
 	}
+	defer connection.Close()
 
 	name := connection.Names()[0]
 
@@ -74,10 +75,11 @@ func TestExport(t *testing.T) {
 
 // Test that Exported handlers can obtain raw message.
 func TestExport_message(t *testing.T) {
-	connection, err := SessionBus()
+	connection, err := ConnectSessionBus()
 	if err != nil {
 		t.Fatalf("Unexpected error connecting to session bus: %s", err)
 	}
+	defer connection.Close()
 
 	name := connection.Names()[0]
 
@@ -102,10 +104,11 @@ func TestExport_message(t *testing.T) {
 
 // Test Export with an invalid path.
 func TestExport_invalidPath(t *testing.T) {
-	connection, err := SessionBus()
+	connection, err := ConnectSessionBus()
 	if err != nil {
 		t.Fatalf("Unexpected error connecting to session bus: %s", err)
 	}
+	defer connection.Close()
 
 	err = connection.Export(nil, "foo", "bar")
 	if err == nil {
@@ -116,10 +119,11 @@ func TestExport_invalidPath(t *testing.T) {
 // 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()
+	connection, err := ConnectSessionBus()
 	if err != nil {
 		t.Fatalf("Unexpected error connecting to session bus: %s", err)
 	}
+	defer connection.Close()
 
 	name := connection.Names()[0]
 
@@ -137,10 +141,11 @@ func TestExport_unexportedMethod(t *testing.T) {
 // 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()
+	connection, err := ConnectSessionBus()
 	if err != nil {
 		t.Fatalf("Unexpected error connecting to session bus: %s", err)
 	}
+	defer connection.Close()
 
 	name := connection.Names()[0]
 
@@ -157,10 +162,11 @@ func TestExport_badSignature(t *testing.T) {
 
 // Test typical ExportWithMap usage.
 func TestExportWithMap(t *testing.T) {
-	connection, err := SessionBus()
+	connection, err := ConnectSessionBus()
 	if err != nil {
 		t.Fatalf("Unexpected error connecting to session bus: %s", err)
 	}
+	defer connection.Close()
 
 	name := connection.Names()[0]
 
@@ -183,10 +189,11 @@ func TestExportWithMap(t *testing.T) {
 
 // Test that ExportWithMap does not export both method alias and method.
 func TestExportWithMap_bypassAlias(t *testing.T) {
-	connection, err := SessionBus()
+	connection, err := ConnectSessionBus()
 	if err != nil {
 		t.Fatalf("Unexpected error connecting to session bus: %s", err)
 	}
+	defer connection.Close()
 
 	name := connection.Names()[0]
 
@@ -206,10 +213,11 @@ func TestExportWithMap_bypassAlias(t *testing.T) {
 
 // Test typical ExportSubtree usage.
 func TestExportSubtree(t *testing.T) {
-	connection, err := SessionBus()
+	connection, err := ConnectSessionBus()
 	if err != nil {
 		t.Fatalf("Unexpected error connecting to session bus: %s", err)
 	}
+	defer connection.Close()
 
 	name := connection.Names()[0]
 
@@ -244,10 +252,11 @@ func TestExportSubtree(t *testing.T) {
 // 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()
+	connection, err := ConnectSessionBus()
 	if err != nil {
 		t.Fatalf("Unexpected error connecting to session bus: %s", err)
 	}
+	defer connection.Close()
 
 	name := connection.Names()[0]
 
@@ -276,10 +285,11 @@ func TestExportSubtree_noMessage(t *testing.T) {
 
 // Test that a regular Export takes precedence over ExportSubtree.
 func TestExportSubtree_exportPrecedence(t *testing.T) {
-	connection, err := SessionBus()
+	connection, err := ConnectSessionBus()
 	if err != nil {
 		t.Fatalf("Unexpected error connecting to session bus: %s", err)
 	}
+	defer connection.Close()
 
 	name := connection.Names()[0]
 
@@ -321,10 +331,11 @@ func TestExportSubtree_exportPrecedence(t *testing.T) {
 
 // Test typical ExportSubtreeWithMap usage.
 func TestExportSubtreeWithMap(t *testing.T) {
-	connection, err := SessionBus()
+	connection, err := ConnectSessionBus()
 	if err != nil {
 		t.Fatalf("Unexpected error connecting to session bus: %s", err)
 	}
+	defer connection.Close()
 
 	name := connection.Names()[0]
 
@@ -357,10 +368,11 @@ func TestExportSubtreeWithMap(t *testing.T) {
 
 // Test that ExportSubtreeWithMap does not export both method alias and method.
 func TestExportSubtreeWithMap_bypassAlias(t *testing.T) {
-	connection, err := SessionBus()
+	connection, err := ConnectSessionBus()
 	if err != nil {
 		t.Fatalf("Unexpected error connecting to session bus: %s", err)
 	}
+	defer connection.Close()
 
 	name := connection.Names()[0]
 
@@ -379,10 +391,11 @@ func TestExportSubtreeWithMap_bypassAlias(t *testing.T) {
 }
 
 func TestExportMethodTable(t *testing.T) {
-	connection, err := SessionBus()
+	connection, err := ConnectSessionBus()
 	if err != nil {
 		t.Fatalf("Unexpected error connecting to session bus: %s", err)
 	}
+	defer connection.Close()
 
 	name := connection.Names()[0]
 	export := &fooExport{}
@@ -431,10 +444,11 @@ func TestExportMethodTable(t *testing.T) {
 }
 
 func TestExportSubtreeMethodTable(t *testing.T) {
-	connection, err := SessionBus()
+	connection, err := ConnectSessionBus()
 	if err != nil {
 		t.Fatalf("Unexpected error connecting to session bus: %s", err)
 	}
+	defer connection.Close()
 
 	name := connection.Names()[0]
 
@@ -485,10 +499,11 @@ func TestExportSubtreeMethodTable(t *testing.T) {
 }
 
 func TestExportMethodTable_NotFunc(t *testing.T) {
-	connection, err := SessionBus()
+	connection, err := ConnectSessionBus()
 	if err != nil {
 		t.Fatalf("Unexpected error connecting to session bus: %s", err)
 	}
+	defer connection.Close()
 
 	name := connection.Names()[0]
 	export := &fooExport{}
@@ -522,10 +537,11 @@ func TestExportMethodTable_NotFunc(t *testing.T) {
 }
 
 func TestExportMethodTable_ReturnNotError(t *testing.T) {
-	connection, err := SessionBus()
+	connection, err := ConnectSessionBus()
 	if err != nil {
 		t.Fatalf("Unexpected error connecting to session bus: %s", err)
 	}
+	defer connection.Close()
 
 	name := connection.Names()[0]
 	export := &fooExport{}
@@ -577,10 +593,11 @@ func TestExportSubPathIntrospection(t *testing.T) {
 			</interface>
 			</node>`
 	)
-	connection, err := SessionBus()
+	connection, err := ConnectSessionBus()
 	if err != nil {
 		t.Fatalf("Unexpected error connecting to session bus: %s", err)
 	}
+	defer connection.Close()
 
 	name := connection.Names()[0]
 
diff --git a/object_test.go b/object_test.go
index b821e7b..f1753c9 100644
--- a/object_test.go
+++ b/object_test.go
@@ -19,10 +19,11 @@ func (o objectGoContextServer) Sleep() *Error {
 }
 
 func TestObjectGoWithContextTimeout(t *testing.T) {
-	bus, err := SessionBus()
+	bus, err := ConnectSessionBus()
 	if err != nil {
 		t.Fatalf("Unexpected error connecting to session bus: %s", err)
 	}
+	defer bus.Close()
 
 	name := bus.Names()[0]
 	bus.Export(objectGoContextServer{t, time.Second}, "/org/dannin/DBus/Test", "org.dannin.DBus.Test")
@@ -39,10 +40,11 @@ func TestObjectGoWithContextTimeout(t *testing.T) {
 }
 
 func TestObjectGoWithContext(t *testing.T) {
-	bus, err := SessionBus()
+	bus, err := ConnectSessionBus()
 	if err != nil {
 		t.Fatalf("Unexpected error connecting to session bus: %s", err)
 	}
+	defer bus.Close()
 
 	name := bus.Names()[0]
 	bus.Export(objectGoContextServer{t, time.Millisecond}, "/org/dannin/DBus/Test", "org.dannin.DBus.Test")
@@ -75,10 +77,11 @@ func fetchSignal(t *testing.T, ch chan *Signal, timeout time.Duration) *Signal {
 }
 
 func TestObjectSignalHandling(t *testing.T) {
-	bus, err := SessionBus()
+	bus, err := ConnectSessionBus()
 	if err != nil {
 		t.Fatalf("Unexpected error connecting to session bus: %s", err)
 	}
+	defer bus.Close()
 
 	name := bus.Names()[0]
 	path := ObjectPath("/org/godbus/DBus/TestSignals")
diff --git a/server_interfaces_test.go b/server_interfaces_test.go
index 0f9a26e..1c4f21b 100644
--- a/server_interfaces_test.go
+++ b/server_interfaces_test.go
@@ -219,7 +219,7 @@ func newTester() (*tester, error) {
 		sigs:    make(chan *Signal),
 		subSigs: make(map[string]map[string]struct{}),
 	}
-	conn, err := SessionBusPrivate(
+	conn, err := ConnectSessionBus(
 		WithHandler(tester),
 		WithSignalHandler(tester),
 		WithSerialGenerator(tester),
@@ -227,16 +227,6 @@ func newTester() (*tester, error) {
 	if err != nil {
 		return nil, err
 	}
-	err = conn.Auth(nil)
-	if err != nil {
-		conn.Close()
-		return nil, err
-	}
-	err = conn.Hello()
-	if err != nil {
-		conn.Close()
-		return nil, err
-	}
 	tester.conn = conn
 	return tester, nil
 }
@@ -246,10 +236,11 @@ func TestHandlerCall(t *testing.T) {
 	if err != nil {
 		t.Errorf("Unexpected error: %s", err)
 	}
-	conn, err := SessionBus()
+	conn, err := ConnectSessionBus()
 	if err != nil {
 		t.Errorf("Unexpected error: %s", err)
 	}
+	defer conn.Close()
 	obj := conn.Object(tester.Name(), "/com/github/godbus/tester")
 	var out string
 	in := "foo"
@@ -268,10 +259,11 @@ func TestHandlerCallGenericError(t *testing.T) {
 	if err != nil {
 		t.Errorf("Unexpected error: %s", err)
 	}
-	conn, err := SessionBus()
+	conn, err := ConnectSessionBus()
 	if err != nil {
 		t.Errorf("Unexpected error: %s", err)
 	}
+	defer conn.Close()
 	obj := conn.Object(tester.Name(), "/com/github/godbus/tester")
 	var out string
 	in := "foo"
@@ -288,10 +280,11 @@ func TestHandlerCallNonExistent(t *testing.T) {
 	if err != nil {
 		t.Errorf("Unexpected error: %s", err)
 	}
-	conn, err := SessionBus()
+	conn, err := ConnectSessionBus()
 	if err != nil {
 		t.Errorf("Unexpected error: %s", err)
 	}
+	defer conn.Close()
 	obj := conn.Object(tester.Name(), "/com/github/godbus/tester/nonexist")
 	var out string
 	in := "foo"
@@ -309,10 +302,11 @@ func TestHandlerInvalidFunc(t *testing.T) {
 	if err != nil {
 		t.Errorf("Unexpected error: %s", err)
 	}
-	conn, err := SessionBus()
+	conn, err := ConnectSessionBus()
 	if err != nil {
 		t.Errorf("Unexpected error: %s", err)
 	}
+	defer conn.Close()
 	obj := conn.Object(tester.Name(), "/com/github/godbus/tester")
 	var out string
 	in := "foo"
@@ -328,10 +322,11 @@ func TestHandlerInvalidNumArg(t *testing.T) {
 	if err != nil {
 		t.Errorf("Unexpected error: %s", err)
 	}
-	conn, err := SessionBus()
+	conn, err := ConnectSessionBus()
 	if err != nil {
 		t.Errorf("Unexpected error: %s", err)
 	}
+	defer conn.Close()
 	obj := conn.Object(tester.Name(), "/com/github/godbus/tester")
 	var out string
 	err = obj.Call("com.github.godbus.dbus.Tester.Test", 0).Store(&out)
@@ -346,10 +341,11 @@ func TestHandlerInvalidArgType(t *testing.T) {
 	if err != nil {
 		t.Errorf("Unexpected error: %s", err)
 	}
-	conn, err := SessionBus()
+	conn, err := ConnectSessionBus()
 	if err != nil {
 		t.Errorf("Unexpected error: %s", err)
 	}
+	defer conn.Close()
 	obj := conn.Object(tester.Name(), "/com/github/godbus/tester")
 	var out string
 	err = obj.Call("com.github.godbus.dbus.Tester.Test", 0, 2.10).Store(&out)
@@ -364,10 +360,11 @@ func TestHandlerIntrospect(t *testing.T) {
 	if err != nil {
 		t.Errorf("Unexpected error: %s", err)
 	}
-	conn, err := SessionBus()
+	conn, err := ConnectSessionBus()
 	if err != nil {
 		t.Errorf("Unexpected error: %s", err)
 	}
+	defer conn.Close()
 	obj := conn.Object(tester.Name(), "/com/github/godbus/tester")
 	var out string
 	err = obj.Call("org.freedesktop.DBus.Introspectable.Introspect", 0).Store(&out)
@@ -401,10 +398,11 @@ func TestHandlerIntrospectPath(t *testing.T) {
 	if err != nil {
 		t.Errorf("Unexpected error: %s", err)
 	}
-	conn, err := SessionBus()
+	conn, err := ConnectSessionBus()
 	if err != nil {
 		t.Errorf("Unexpected error: %s", err)
 	}
+	defer conn.Close()
 	obj := conn.Object(tester.Name(), "/com/github/godbus")
 	var out string
 	err = obj.Call("org.freedesktop.DBus.Introspectable.Introspect", 0).Store(&out)
@@ -423,10 +421,11 @@ func TestHandlerSignal(t *testing.T) {
 	if err != nil {
 		t.Errorf("Unexpected error: %s", err)
 	}
-	conn, err := SessionBus()
+	conn, err := ConnectSessionBus()
 	if err != nil {
 		t.Errorf("Unexpected error: %s", err)
 	}
+	defer conn.Close()
 	if err = tester.AddSignal("com.github.godbus.dbus.Tester", "sig1"); err != nil {
 		t.Fatal(err)
 	}
@@ -461,10 +460,11 @@ func TestRaceInExport(t *testing.T) {
 		dbusInterface = "org.example.godbus.test1"
 	)
 
-	bus, err := SessionBus()
+	bus, err := ConnectSessionBus()
 	if err != nil {
 		t.Fatal(err)
 	}
+	defer bus.Close()
 
 	var x X
 
diff --git a/transport_nonce_tcp_test.go b/transport_nonce_tcp_test.go
index d5a0f5d..cd7577c 100644
--- a/transport_nonce_tcp_test.go
+++ b/transport_nonce_tcp_test.go
@@ -26,14 +26,11 @@ func TestTcpNonceConnection(t *testing.T) {
 `)
 	defer process.Kill()
 
-	c, err := Dial(addr)
+	conn, err := Connect(addr, WithAuth(AuthAnonymous()))
 	if err != nil {
 		t.Fatal(err)
 	}
-	if err = c.Auth([]Auth{AuthAnonymous()}); err != nil {
-		t.Fatal(err)
-	}
-	if err = c.Hello(); err != nil {
+	if err = conn.Close(); err != nil {
 		t.Fatal(err)
 	}
 }
diff --git a/transport_unix_test.go b/transport_unix_test.go
index 302233f..b1d7bdf 100644
--- a/transport_unix_test.go
+++ b/transport_unix_test.go
@@ -22,10 +22,11 @@ func (t unixFDTest) Test(fd UnixFD) (string, *Error) {
 }
 
 func TestUnixFDs(t *testing.T) {
-	conn, err := SessionBus()
+	conn, err := ConnectSessionBus()
 	if err != nil {
 		t.Fatal(err)
 	}
+	defer conn.Close()
 	r, w, err := os.Pipe()
 	if err != nil {
 		t.Fatal(err)