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