1package dbus 2 3import ( 4 "encoding/binary" 5 "io" 6 "io/ioutil" 7 "testing" 8 "time" 9) 10 11func TestSessionBus(t *testing.T) { 12 _, err := SessionBus() 13 if err != nil { 14 t.Error(err) 15 } 16} 17 18func TestSystemBus(t *testing.T) { 19 _, err := SystemBus() 20 if err != nil { 21 t.Error(err) 22 } 23} 24 25func ExampleSystemBusPrivate() { 26 setupPrivateSystemBus := func() (conn *Conn, err error) { 27 conn, err = SystemBusPrivate() 28 if err != nil { 29 return nil, err 30 } 31 if err = conn.Auth(nil); err != nil { 32 conn.Close() 33 conn = nil 34 return 35 } 36 if err = conn.Hello(); err != nil { 37 conn.Close() 38 conn = nil 39 } 40 return conn, nil // success 41 } 42 _, _ = setupPrivateSystemBus() 43} 44 45func TestSend(t *testing.T) { 46 bus, err := SessionBus() 47 if err != nil { 48 t.Fatal(err) 49 } 50 ch := make(chan *Call, 1) 51 msg := &Message{ 52 Type: TypeMethodCall, 53 Flags: 0, 54 Headers: map[HeaderField]Variant{ 55 FieldDestination: MakeVariant(bus.Names()[0]), 56 FieldPath: MakeVariant(ObjectPath("/org/freedesktop/DBus")), 57 FieldInterface: MakeVariant("org.freedesktop.DBus.Peer"), 58 FieldMember: MakeVariant("Ping"), 59 }, 60 } 61 call := bus.Send(msg, ch) 62 <-ch 63 if call.Err != nil { 64 t.Error(call.Err) 65 } 66} 67 68func TestFlagNoReplyExpectedSend(t *testing.T) { 69 bus, err := SessionBus() 70 if err != nil { 71 t.Fatal(err) 72 } 73 done := make(chan struct{}) 74 go func() { 75 bus.BusObject().Call("org.freedesktop.DBus.ListNames", FlagNoReplyExpected) 76 close(done) 77 }() 78 select { 79 case <-done: 80 case <-time.After(1 * time.Second): 81 t.Error("Failed to announce that the call was done") 82 } 83} 84 85func TestRemoveSignal(t *testing.T) { 86 bus, err := NewConn(nil) 87 if err != nil { 88 t.Error(err) 89 } 90 signals := bus.signalHandler.(*defaultSignalHandler).signals 91 ch := make(chan *Signal) 92 ch2 := make(chan *Signal) 93 for _, ch := range []chan *Signal{ch, ch2, ch, ch2, ch2, ch} { 94 bus.Signal(ch) 95 } 96 signals = bus.signalHandler.(*defaultSignalHandler).signals 97 if len(signals) != 6 { 98 t.Errorf("remove signal: signals length not equal: got '%d', want '6'", len(signals)) 99 } 100 bus.RemoveSignal(ch) 101 signals = bus.signalHandler.(*defaultSignalHandler).signals 102 if len(signals) != 3 { 103 t.Errorf("remove signal: signals length not equal: got '%d', want '3'", len(signals)) 104 } 105 signals = bus.signalHandler.(*defaultSignalHandler).signals 106 for _, bch := range signals { 107 if bch != ch2 { 108 t.Errorf("remove signal: removed signal present: got '%v', want '%v'", bch, ch2) 109 } 110 } 111} 112 113type rwc struct { 114 io.Reader 115 io.Writer 116} 117 118func (rwc) Close() error { return nil } 119 120type fakeAuth struct { 121} 122 123func (fakeAuth) FirstData() (name, resp []byte, status AuthStatus) { 124 return []byte("name"), []byte("resp"), AuthOk 125} 126 127func (fakeAuth) HandleData(data []byte) (resp []byte, status AuthStatus) { 128 return nil, AuthOk 129} 130 131func TestCloseBeforeSignal(t *testing.T) { 132 reader, pipewriter := io.Pipe() 133 defer pipewriter.Close() 134 defer reader.Close() 135 136 bus, err := NewConn(rwc{Reader: reader, Writer: ioutil.Discard}) 137 if err != nil { 138 t.Fatal(err) 139 } 140 // give ch a buffer so sends won't block 141 ch := make(chan *Signal, 1) 142 bus.Signal(ch) 143 144 go func() { 145 _, err := pipewriter.Write([]byte("REJECTED name\r\nOK myuuid\r\n")) 146 if err != nil { 147 t.Errorf("error writing to pipe: %v", err) 148 } 149 }() 150 151 err = bus.Auth([]Auth{fakeAuth{}}) 152 if err != nil { 153 t.Fatal(err) 154 } 155 156 err = bus.Close() 157 if err != nil { 158 t.Fatal(err) 159 } 160 161 msg := &Message{ 162 Type: TypeSignal, 163 Headers: map[HeaderField]Variant{ 164 FieldInterface: MakeVariant("foo.bar"), 165 FieldMember: MakeVariant("bar"), 166 FieldPath: MakeVariant(ObjectPath("/baz")), 167 }, 168 } 169 err = msg.EncodeTo(pipewriter, binary.LittleEndian) 170 if err != nil { 171 t.Fatal(err) 172 } 173} 174 175type server struct{} 176 177func (server) Double(i int64) (int64, *Error) { 178 return 2 * i, nil 179} 180 181func BenchmarkCall(b *testing.B) { 182 b.StopTimer() 183 b.ReportAllocs() 184 var s string 185 bus, err := SessionBus() 186 if err != nil { 187 b.Fatal(err) 188 } 189 name := bus.Names()[0] 190 obj := bus.BusObject() 191 b.StartTimer() 192 for i := 0; i < b.N; i++ { 193 err := obj.Call("org.freedesktop.DBus.GetNameOwner", 0, name).Store(&s) 194 if err != nil { 195 b.Fatal(err) 196 } 197 if s != name { 198 b.Errorf("got %s, wanted %s", s, name) 199 } 200 } 201} 202 203func BenchmarkCallAsync(b *testing.B) { 204 b.StopTimer() 205 b.ReportAllocs() 206 bus, err := SessionBus() 207 if err != nil { 208 b.Fatal(err) 209 } 210 name := bus.Names()[0] 211 obj := bus.BusObject() 212 c := make(chan *Call, 50) 213 done := make(chan struct{}) 214 go func() { 215 for i := 0; i < b.N; i++ { 216 v := <-c 217 if v.Err != nil { 218 b.Error(v.Err) 219 } 220 s := v.Body[0].(string) 221 if s != name { 222 b.Errorf("got %s, wanted %s", s, name) 223 } 224 } 225 close(done) 226 }() 227 b.StartTimer() 228 for i := 0; i < b.N; i++ { 229 obj.Go("org.freedesktop.DBus.GetNameOwner", 0, c, name) 230 } 231 <-done 232} 233 234func BenchmarkServe(b *testing.B) { 235 b.StopTimer() 236 srv, err := SessionBus() 237 if err != nil { 238 b.Fatal(err) 239 } 240 cli, err := SessionBusPrivate() 241 if err != nil { 242 b.Fatal(err) 243 } 244 if err = cli.Auth(nil); err != nil { 245 b.Fatal(err) 246 } 247 if err = cli.Hello(); err != nil { 248 b.Fatal(err) 249 } 250 benchmarkServe(b, srv, cli) 251} 252 253func BenchmarkServeAsync(b *testing.B) { 254 b.StopTimer() 255 srv, err := SessionBus() 256 if err != nil { 257 b.Fatal(err) 258 } 259 cli, err := SessionBusPrivate() 260 if err != nil { 261 b.Fatal(err) 262 } 263 if err = cli.Auth(nil); err != nil { 264 b.Fatal(err) 265 } 266 if err = cli.Hello(); err != nil { 267 b.Fatal(err) 268 } 269 benchmarkServeAsync(b, srv, cli) 270} 271 272func BenchmarkServeSameConn(b *testing.B) { 273 b.StopTimer() 274 bus, err := SessionBus() 275 if err != nil { 276 b.Fatal(err) 277 } 278 279 benchmarkServe(b, bus, bus) 280} 281 282func BenchmarkServeSameConnAsync(b *testing.B) { 283 b.StopTimer() 284 bus, err := SessionBus() 285 if err != nil { 286 b.Fatal(err) 287 } 288 289 benchmarkServeAsync(b, bus, bus) 290} 291 292func benchmarkServe(b *testing.B, srv, cli *Conn) { 293 var r int64 294 var err error 295 dest := srv.Names()[0] 296 srv.Export(server{}, "/org/guelfey/DBus/Test", "org.guelfey.DBus.Test") 297 obj := cli.Object(dest, "/org/guelfey/DBus/Test") 298 b.StartTimer() 299 for i := 0; i < b.N; i++ { 300 err = obj.Call("org.guelfey.DBus.Test.Double", 0, int64(i)).Store(&r) 301 if err != nil { 302 b.Fatal(err) 303 } 304 if r != 2*int64(i) { 305 b.Errorf("got %d, wanted %d", r, 2*int64(i)) 306 } 307 } 308} 309 310func benchmarkServeAsync(b *testing.B, srv, cli *Conn) { 311 dest := srv.Names()[0] 312 srv.Export(server{}, "/org/guelfey/DBus/Test", "org.guelfey.DBus.Test") 313 obj := cli.Object(dest, "/org/guelfey/DBus/Test") 314 c := make(chan *Call, 50) 315 done := make(chan struct{}) 316 go func() { 317 for i := 0; i < b.N; i++ { 318 v := <-c 319 if v.Err != nil { 320 b.Fatal(v.Err) 321 } 322 i, r := v.Args[0].(int64), v.Body[0].(int64) 323 if 2*i != r { 324 b.Errorf("got %d, wanted %d", r, 2*i) 325 } 326 } 327 close(done) 328 }() 329 b.StartTimer() 330 for i := 0; i < b.N; i++ { 331 obj.Go("org.guelfey.DBus.Test.Double", 0, c, int64(i)) 332 } 333 <-done 334} 335 336func TestGetKey(t *testing.T) { 337 keys := "host=1.2.3.4,port=5678,family=ipv4" 338 if host := getKey(keys, "host"); host != "1.2.3.4" { 339 t.Error(`Expected "1.2.3.4", got`, host) 340 } 341 if port := getKey(keys, "port"); port != "5678" { 342 t.Error(`Expected "5678", got`, port) 343 } 344 if family := getKey(keys, "family"); family != "ipv4" { 345 t.Error(`Expected "ipv4", got`, family) 346 } 347} 348