em-ruby-dbus 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
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