em-ruby-dbus 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. checksums.yaml +7 -0
  2. data/COPYING +504 -0
  3. data/NEWS +253 -0
  4. data/README.md +93 -0
  5. data/Rakefile +58 -0
  6. data/VERSION +1 -0
  7. data/doc/Reference.md +207 -0
  8. data/doc/Tutorial.md +480 -0
  9. data/doc/ex-calling-methods.body.rb +8 -0
  10. data/doc/ex-calling-methods.rb +3 -0
  11. data/doc/ex-properties.body.rb +9 -0
  12. data/doc/ex-properties.rb +3 -0
  13. data/doc/ex-setup.rb +7 -0
  14. data/doc/ex-signal.body.rb +20 -0
  15. data/doc/ex-signal.rb +3 -0
  16. data/doc/example-helper.rb +6 -0
  17. data/em-ruby-dbus.gemspec +20 -0
  18. data/examples/gdbus/gdbus +255 -0
  19. data/examples/gdbus/gdbus.glade +184 -0
  20. data/examples/gdbus/launch.sh +4 -0
  21. data/examples/no-introspect/nm-test.rb +21 -0
  22. data/examples/no-introspect/tracker-test.rb +16 -0
  23. data/examples/rhythmbox/playpause.rb +25 -0
  24. data/examples/service/call_service.rb +25 -0
  25. data/examples/service/service_newapi.rb +51 -0
  26. data/examples/simple/call_introspect.rb +34 -0
  27. data/examples/simple/properties.rb +19 -0
  28. data/examples/utils/listnames.rb +11 -0
  29. data/examples/utils/notify.rb +19 -0
  30. data/lib/dbus.rb +82 -0
  31. data/lib/dbus/auth.rb +269 -0
  32. data/lib/dbus/bus.rb +739 -0
  33. data/lib/dbus/core_ext/array/extract_options.rb +31 -0
  34. data/lib/dbus/core_ext/class/attribute.rb +129 -0
  35. data/lib/dbus/core_ext/kernel/singleton_class.rb +8 -0
  36. data/lib/dbus/core_ext/module/remove_method.rb +14 -0
  37. data/lib/dbus/error.rb +46 -0
  38. data/lib/dbus/export.rb +128 -0
  39. data/lib/dbus/introspect.rb +219 -0
  40. data/lib/dbus/logger.rb +31 -0
  41. data/lib/dbus/loop-em.rb +19 -0
  42. data/lib/dbus/marshall.rb +434 -0
  43. data/lib/dbus/matchrule.rb +101 -0
  44. data/lib/dbus/message.rb +276 -0
  45. data/lib/dbus/message_queue.rb +166 -0
  46. data/lib/dbus/proxy_object.rb +149 -0
  47. data/lib/dbus/proxy_object_factory.rb +41 -0
  48. data/lib/dbus/proxy_object_interface.rb +128 -0
  49. data/lib/dbus/type.rb +193 -0
  50. data/lib/dbus/xml.rb +161 -0
  51. data/test/async_spec.rb +47 -0
  52. data/test/binding_spec.rb +74 -0
  53. data/test/bus_and_xml_backend_spec.rb +39 -0
  54. data/test/bus_driver_spec.rb +20 -0
  55. data/test/bus_spec.rb +20 -0
  56. data/test/byte_array_spec.rb +38 -0
  57. data/test/err_msg_spec.rb +42 -0
  58. data/test/introspect_xml_parser_spec.rb +26 -0
  59. data/test/introspection_spec.rb +32 -0
  60. data/test/main_loop_spec.rb +82 -0
  61. data/test/property_spec.rb +53 -0
  62. data/test/server_robustness_spec.rb +66 -0
  63. data/test/server_spec.rb +53 -0
  64. data/test/service_newapi.rb +217 -0
  65. data/test/session_bus_spec_manual.rb +15 -0
  66. data/test/signal_spec.rb +90 -0
  67. data/test/spec_helper.rb +33 -0
  68. data/test/thread_safety_spec.rb +31 -0
  69. data/test/tools/dbus-launch-simple +35 -0
  70. data/test/tools/dbus-limited-session.conf +28 -0
  71. data/test/tools/test_env +13 -0
  72. data/test/tools/test_server +39 -0
  73. data/test/type_spec.rb +19 -0
  74. data/test/value_spec.rb +81 -0
  75. data/test/variant_spec.rb +66 -0
  76. metadata +145 -0
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env rspec
2
+ require_relative "spec_helper"
3
+ require "dbus"
4
+
5
+ describe DBus::ASessionBus do
6
+ context "when DBUS_SESSION_BUS_ADDRESS is unset in ENV (Issue#4)" do
7
+ ENV.delete "DBUS_SESSION_BUS_ADDRESS"
8
+
9
+ it "can connect" do
10
+ bus = DBus::ASessionBus.new
11
+ svc = bus.service("org.freedesktop.DBus")
12
+ expect(svc.exists?).to be_true
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env rspec
2
+ # Test the signal handlers
3
+ require_relative "spec_helper"
4
+ require "dbus"
5
+
6
+ describe "SignalHandlerTest" do
7
+ before(:each) do
8
+ @session_bus = DBus::ASessionBus.new
9
+ svc = @session_bus.service("org.ruby.service")
10
+ @obj = svc.object("/org/ruby/MyInstance")
11
+ @obj.introspect # necessary
12
+ @obj.default_iface = "org.ruby.Loop"
13
+ @intf = @obj["org.ruby.Loop"]
14
+
15
+ @loop = DBus::Main.new
16
+ @loop << @session_bus
17
+ end
18
+
19
+ # testing for commit 017c83 (kkaempf)
20
+ it "tests overriding a handler" do
21
+ DBus.logger.debug "Inside test_overriding_a_handler"
22
+ counter = 0
23
+
24
+ @obj.on_signal "LongTaskEnd" do
25
+ DBus.logger.debug "+10"
26
+ counter += 10
27
+ end
28
+ @obj.on_signal "LongTaskEnd" do
29
+ DBus.logger.debug "+1"
30
+ counter += 1
31
+ end
32
+
33
+ DBus.logger.debug "will begin"
34
+ @obj.LongTaskBegin 3
35
+
36
+ quitter = Thread.new do
37
+ DBus.logger.debug "sleep before quit"
38
+ # FIXME if we sleep for too long
39
+ # the socket will be drained and we deadlock in a select.
40
+ # It could be worked around by sending ourselves a Unix signal
41
+ # (with a dummy handler) to interrupt the select
42
+ sleep 1
43
+ DBus.logger.debug "will quit"
44
+ @loop.quit
45
+ end
46
+ @loop.run
47
+ quitter.join
48
+
49
+ expect(counter).to eq(1)
50
+ end
51
+
52
+ it "tests on signal overload" do
53
+ DBus.logger.debug "Inside test_on_signal_overload"
54
+ counter = 0
55
+ started = false
56
+ @intf.on_signal "LongTaskStart" do
57
+ started = true
58
+ end
59
+ # Same as intf.on_signal("LongTaskEnd"), just the old way
60
+ @intf.on_signal @obj.bus, "LongTaskEnd" do
61
+ counter += 1
62
+ end
63
+ @obj.LongTaskBegin 3
64
+ quitter = Thread.new do
65
+ DBus.logger.debug "sleep before quit"
66
+ sleep 1
67
+ DBus.logger.debug "will quit"
68
+ @loop.quit
69
+ end
70
+ @loop.run
71
+ quitter.join
72
+
73
+ expect(started).to eq(true)
74
+ expect(counter).to eq(1)
75
+ expect { @intf.on_signal }.to raise_error(ArgumentError) # not enough
76
+ expect { @intf.on_signal 'to', 'many', 'yarrrrr!' }.to raise_error(ArgumentError)
77
+ end
78
+
79
+ it "tests too many rules" do
80
+ 100.times do
81
+ @obj.on_signal "Whichever" do
82
+ puts "not called"
83
+ end
84
+ end
85
+ end
86
+
87
+ it "tests removing a nonexistent rule" do
88
+ @obj.on_signal "DoesNotExist"
89
+ end
90
+ end
@@ -0,0 +1,33 @@
1
+ if ENV["COVERAGE"]
2
+ coverage = ENV["COVERAGE"] == "true"
3
+ else
4
+ # heuristics: enable for interactive builds (but not in OBS) or in Travis
5
+ coverage = !!ENV["DISPLAY"] || ENV["TRAVIS"]
6
+ end
7
+
8
+ if coverage
9
+ require "simplecov"
10
+ SimpleCov.root File.expand_path("../..", __FILE__)
11
+
12
+ # do not cover specs
13
+ SimpleCov.add_filter "_spec.rb"
14
+ # do not cover the activesupport helpers
15
+ SimpleCov.add_filter "/core_ext/"
16
+
17
+ # use coveralls for on-line code coverage reporting at Travis CI
18
+ if ENV["TRAVIS"]
19
+ require "coveralls"
20
+ end
21
+ SimpleCov.start
22
+ end
23
+
24
+ $:.unshift File.expand_path("../../lib", __FILE__)
25
+
26
+ if Object.const_defined? "RSpec"
27
+ # http://betterspecs.org/#expect
28
+ RSpec.configure do |config|
29
+ config.expect_with :rspec do |c|
30
+ c.syntax = :expect
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env rspec
2
+ # Test thread safety
3
+ require_relative "spec_helper"
4
+ require "dbus"
5
+
6
+ describe "ThreadSafetyTest" do
7
+ it "tests thread competition" do
8
+ print "Thread competition: "
9
+ jobs = []
10
+ 5.times do
11
+ jobs << Thread.new do
12
+ Thread.current.abort_on_exception = true
13
+
14
+ # use separate connections to avoid races
15
+ bus = DBus::ASessionBus.new
16
+ svc = bus.service("org.ruby.service")
17
+ obj = svc.object("/org/ruby/MyInstance")
18
+ obj.introspect
19
+ obj.default_iface = "org.ruby.SampleInterface"
20
+
21
+ 10.times do |i|
22
+ print "#{i} "
23
+ $stdout.flush
24
+ expect(obj.the_answer[0]).to eq(42)
25
+ sleep 0.1 * rand
26
+ end
27
+ end
28
+ end
29
+ jobs.each do |thread| thread.join end
30
+ end
31
+ end
@@ -0,0 +1,35 @@
1
+ #! /bin/sh
2
+ # A wrapper for DBus tests
3
+ # Reimplementing dbus-launch because it is in dbus-1-x11.rpm
4
+ # Sets up a private session bus and call the specified program
5
+ set -o errexit
6
+
7
+ # This launches the bus daemon,
8
+ # exports DBUS_SESSION_BUS_ADDRESS and sets DBUS_SESSION_BUS_PID
9
+ my_dbus_launch () {
10
+ # reimplementing dbus-launch because it is in dbus-1-x11.rpm
11
+ PF=`mktemp dbus.pid.XXXXXX` || exit
12
+ AF=`mktemp dbus.addr.XXXXXX` || exit
13
+ RM_FILES="$RM_FILES $PF $AF"
14
+
15
+ dbus-daemon --config-file=dbus-limited-session.conf --print-address=3 3>$AF --print-pid=4 4>$PF &
16
+ # wait for the daemon to print the info
17
+ TRIES=0
18
+ while [ ! -s $AF -o ! -s $PF ]; do
19
+ sleep 0.1
20
+ TRIES=`expr $TRIES + 1`
21
+ if [ $TRIES -gt 100 ]; then echo "dbus-daemon failed?"; exit 1; fi
22
+ done
23
+ DBUS_SESSION_BUS_PID=$(cat $PF)
24
+ export DBUS_SESSION_BUS_ADDRESS=$(cat $AF)
25
+ KILLS="$KILLS $DBUS_SESSION_BUS_PID"
26
+ # dbus-monitor &
27
+ }
28
+
29
+ my_dbus_launch
30
+
31
+ # Clean up at exit.
32
+ trap "kill \$KILLS; rm -rf \$RM_FILES" EXIT TERM INT
33
+
34
+ # run the payload; the return value is passed on
35
+ "$@"
@@ -0,0 +1,28 @@
1
+ <!-- This configuration file controls the testing message bus.
2
+ It is based on a session bus config. -->
3
+
4
+ <!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
5
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
6
+ <busconfig>
7
+ <!-- Our well-known bus type, don't change this -->
8
+ <type>session</type>
9
+
10
+ <listen>unix:tmpdir=/tmp</listen>
11
+ <listen>tcp:host=127.0.0.1</listen>
12
+
13
+ <standard_session_servicedirs />
14
+
15
+ <policy context="default">
16
+ <!-- Allow everything to be sent -->
17
+ <allow send_destination="*" eavesdrop="true"/>
18
+ <!-- Allow everything to be received -->
19
+ <allow eavesdrop="true"/>
20
+ <!-- Allow anyone to own anything -->
21
+ <allow own="*"/>
22
+ </policy>
23
+
24
+ <!-- Do not increase the limits.
25
+ Instead, lower some so that we can test resource leaks. -->
26
+ <limit name="max_match_rules_per_connection">50</limit><!-- was 512 -->
27
+
28
+ </busconfig>
@@ -0,0 +1,13 @@
1
+ #! /bin/bash
2
+ # test_env: set up the environment needed to run tests:
3
+ # - set up a private bus
4
+ # - run a test server on it
5
+
6
+ #export DBUS_VERBOSE=1
7
+ #export RUBYOPT="-d"
8
+ export RUBYOPT="$RUBYOPT -w"
9
+ ./test_server \
10
+ ../service_newapi.rb \
11
+ -- \
12
+ ./dbus-launch-simple \
13
+ "$@"
@@ -0,0 +1,39 @@
1
+ #! /bin/sh
2
+ # A wrapper for DBus tests
3
+ # Run a server (directly or by dbus activation) and then the test
4
+ # $0 server [args...] -- test [args...]
5
+ set -o errexit
6
+
7
+ while [ "$1" != "--" ]; do
8
+ SERVER="$SERVER $1"
9
+ shift
10
+ done
11
+ shift # --
12
+
13
+ setup_activation () {
14
+ SDIR=$XDG_DATA_DIRS/dbus-1/services
15
+ mkdir -p $SDIR
16
+ # FIXME Name is hardcoded
17
+ cat <<EOF > $SDIR/test.service
18
+ [D-BUS Service]
19
+ Name=org.ruby.service
20
+ Exec=$SERVER
21
+ EOF
22
+ }
23
+
24
+ run_server () {
25
+ echo -n "Hey, server, get on da bus... "
26
+ # start the server
27
+ $SERVER & sleep 3
28
+ echo "off we go!"
29
+ }
30
+
31
+ export XDG_DATA_DIRS=`mktemp -d dbus.activation.XXXXXX`
32
+ RM_FILES="$RM_FILES $XDG_DATA_DIRS"
33
+ setup_activation
34
+ #run_server
35
+
36
+ # Clean up at exit.
37
+ trap "rm -rf \$RM_FILES" EXIT TERM INT
38
+
39
+ "$@"
data/test/type_spec.rb ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env rspec
2
+ require_relative "spec_helper"
3
+ require "dbus"
4
+
5
+ describe DBus do
6
+ describe ".type" do
7
+ %w{i ai a(ii) aai}.each do |s|
8
+ it "parses some type #{s}" do
9
+ expect(DBus::type(s).to_s).to be_eql s
10
+ end
11
+ end
12
+
13
+ %w{aa (ii ii) hrmp}.each do |s|
14
+ it "raises exception for invalid type #{s}" do
15
+ expect {DBus::type(s).to_s}.to raise_error DBus::Type::SignatureException
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env rspec
2
+ # -*- coding: utf-8 -*-
3
+ require_relative "spec_helper"
4
+ require "dbus"
5
+
6
+ describe "ValueTest" do
7
+ before(:each) do
8
+ session_bus = DBus::ASessionBus.new
9
+ svc = session_bus.service("org.ruby.service")
10
+ @obj = svc.object("/org/ruby/MyInstance")
11
+ @obj.introspect # necessary
12
+ @obj.default_iface = "org.ruby.SampleInterface"
13
+ end
14
+
15
+ it "tests passing an array of structs through a variant" do
16
+ triple = ['a(uuu)', []]
17
+ @obj.test_variant(triple)
18
+ quadruple = ['a(uuuu)', []] # a(uuu) works fine
19
+ # The bus disconnects us because of malformed message,
20
+ # code 12: DBUS_INVALID_TOO_MUCH_DATA
21
+ @obj.test_variant(quadruple)
22
+ end
23
+
24
+ it "tests passing an array through a variant" do
25
+ # old explicit typing
26
+ @obj.test_variant(["as", ["coucou", "kuku"]])
27
+ # automatic typing
28
+ @obj.test_variant(["coucou", "kuku"])
29
+ @obj.test_variant(["saint", "was that a word or a signature?"])
30
+ end
31
+
32
+ it "tests bouncing a variant" do
33
+ expect(@obj.bounce_variant("cuckoo")[0]).to eq("cuckoo")
34
+ expect(@obj.bounce_variant(["coucou", "kuku"])[0]).to eq(["coucou", "kuku"])
35
+ expect(@obj.bounce_variant([])[0]).to eq([])
36
+ empty_hash = {}
37
+ expect(@obj.bounce_variant(empty_hash)[0]).to eq(empty_hash)
38
+ end
39
+
40
+ # these are ambiguous
41
+ it "tests pairs with a string" do
42
+
43
+ # deprecated
44
+ expect(@obj.bounce_variant(["s", "foo"])[0]).to eq("foo")
45
+
46
+ expect(@obj.bounce_variant(DBus.variant("s", "foo"))[0]).to eq("foo")
47
+ expect(@obj.bounce_variant([DBus.type("s"), "foo"])[0]).to eq("foo")
48
+
49
+ # does not work, because the server side forgets the explicit typing
50
+ # assert_equal ["s", "foo"], @obj.bounce_variant(["av", ["s", "foo"]])[0]
51
+ # assert_equal ["s", "foo"], @obj.bounce_variant(["as", ["s", "foo"]])[0]
52
+
53
+ # instead, use this to demonstrate that the variant is passed as expected
54
+ expect(@obj.variant_size(["s", "four"])[0]).to eq(4)
55
+ # "av" is the simplest thing that will work,
56
+ # shifting the heuristic from a pair to the individual items
57
+ expect(@obj.variant_size(["av", ["s", "four"]])[0]).to eq(2)
58
+ end
59
+
60
+ it "tests marshalling an array of variants" do
61
+ # https://trac.luon.net/ruby-dbus/ticket/30
62
+ @obj.default_iface = "org.ruby.Ticket30"
63
+ choices = []
64
+ choices << ['s', 'Plan A']
65
+ choices << ['s', 'Plan B']
66
+ # old explicit typing
67
+ expect(@obj.Sybilla(choices)[0]).to eq("Do Plan A")
68
+ # automatic typing
69
+ expect(@obj.Sybilla(["Plan A", "Plan B"])[0]).to eq("Do Plan A")
70
+ end
71
+
72
+ it "tests service returning nonarray" do
73
+ # "warning: default `to_a' will be obsolete"
74
+ @obj.the_answer
75
+ end
76
+
77
+ it "tests multibyte string" do
78
+ str = @obj.multibyte_string[0]
79
+ expect(str).to eq("あいうえお")
80
+ end
81
+ end
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env rspec
2
+ # Test marshalling variants according to ruby types
3
+ require_relative "spec_helper"
4
+ require "dbus"
5
+
6
+ describe "VariantTest" do
7
+ before(:each) do
8
+ @bus = DBus::ASessionBus.new
9
+ @svc = @bus.service("org.ruby.service")
10
+ end
11
+
12
+ def make_variant(a)
13
+ DBus::PacketMarshaller.make_variant(a)
14
+ end
15
+
16
+ it "tests make variant scalar" do
17
+ # special case: do not fail immediately, marshaller will do that
18
+ expect(make_variant(nil)).to eq(["b", nil])
19
+
20
+ expect(make_variant(true)).to eq(["b", true])
21
+ # Integers
22
+ # no byte
23
+ expect(make_variant(42)).to eq(["i", 42])
24
+ # 3_000_000_000 can be u or x.
25
+ # less specific test: just run it thru a loopback
26
+ expect(make_variant(3_000_000_000)).to eq(["x", 3_000_000_000])
27
+ expect(make_variant(5_000_000_000)).to eq(["x", 5_000_000_000])
28
+
29
+ expect(make_variant(3.14)).to eq(["d", 3.14])
30
+
31
+ expect(make_variant("foo")).to eq(["s", "foo"])
32
+ expect(make_variant(:bar)).to eq(["s", "bar"])
33
+
34
+ # left: strruct, array, dict
35
+ # object path: detect exported objects?, signature
36
+
37
+ # # by Ruby types
38
+ # class Foo
39
+ # end
40
+ # make_variant(Foo.new)
41
+ # if we don;t understand a class, the error should be informative -> new exception
42
+ end
43
+
44
+ it "tests make variant array" do
45
+ ai = [1, 2, 3]
46
+ # as = ["one", "two", "three"]
47
+ # which?
48
+ # expect(make_variant(ai)).to eq(["ai", [1, 2, 3]])
49
+ expect(make_variant(ai)).to eq(["av", [["i", 1],
50
+ ["i", 2],
51
+ ["i", 3]]])
52
+ a0 = []
53
+ expect(make_variant(a0)).to eq(["av", []])
54
+
55
+ end
56
+
57
+ it "tests make variant hash" do
58
+ h = {"k1" => "v1", "k2" => "v2"}
59
+ expect(make_variant(h)).to eq(["a{sv}", {
60
+ "k1" => ["s", "v1"],
61
+ "k2" => ["s", "v2"],
62
+ }])
63
+ h0 = {}
64
+ expect(make_variant(h0)).to eq(["a{sv}", {}])
65
+ end
66
+ end