ruby-dbus 0.22.1 → 0.23.0.beta1

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.
@@ -0,0 +1,180 @@
1
+ <node>
2
+ <!--
3
+ This file is part of Cockpit.
4
+
5
+ Copyright (C) 2013 Red Hat, Inc.
6
+
7
+ Cockpit is free software; you can redistribute it and/or modify it
8
+ under the terms of the GNU Lesser General Public License as published by
9
+ the Free Software Foundation; either version 2.1 of the License, or
10
+ (at your option) any later version.
11
+
12
+ Cockpit is distributed in the hope that it will be useful, but
13
+ WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ Lesser General Public License for more details.
16
+
17
+ You should have received a copy of the GNU Lesser General Public License
18
+ along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
19
+ -->
20
+
21
+ <interface name="com.redhat.Cockpit.DBusTests.Alpha">
22
+ </interface>
23
+
24
+ <interface name="com.redhat.Cockpit.DBusTests.Frobber">
25
+ <method name="HelloWorld">
26
+ <arg name="greeting" direction="in" type="s"/>
27
+ <arg name="response" direction="out" type="s"/>
28
+ </method>
29
+
30
+ <method name="NeverReturn">
31
+ </method>
32
+
33
+ <method name="TestPrimitiveTypes">
34
+ <arg direction="in" type="y" name="val_byte" />
35
+ <arg direction="in" type="b" name="val_boolean" />
36
+ <arg direction="in" type="n" name="val_int16" />
37
+ <arg direction="in" type="q" name="val_uint16" />
38
+ <arg direction="in" type="i" name="val_int32" />
39
+ <arg direction="in" type="u" name="val_uint32" />
40
+ <arg direction="in" type="x" name="val_int64" />
41
+ <arg direction="in" type="t" name="val_uint64" />
42
+ <arg direction="in" type="d" name="val_double" />
43
+ <arg direction="in" type="s" name="val_string" />
44
+ <arg direction="in" type="o" name="val_objpath" />
45
+ <arg direction="in" type="g" name="val_signature" />
46
+ <arg direction="in" type="ay" name="val_bytestring" />
47
+ <arg direction="out" type="y" name="ret_byte" />
48
+ <arg direction="out" type="b" name="ret_boolean" />
49
+ <arg direction="out" type="n" name="ret_int16" />
50
+ <arg direction="out" type="q" name="ret_uint16" />
51
+ <arg direction="out" type="i" name="ret_int32" />
52
+ <arg direction="out" type="u" name="ret_uint32" />
53
+ <arg direction="out" type="x" name="ret_int64" />
54
+ <arg direction="out" type="t" name="ret_uint64" />
55
+ <arg direction="out" type="d" name="ret_double" />
56
+ <arg direction="out" type="s" name="ret_string" />
57
+ <arg direction="out" type="o" name="ret_objpath" />
58
+ <arg direction="out" type="g" name="ret_signature" />
59
+ <arg direction="out" type="ay" name="ret_bytestring" />
60
+ </method>
61
+
62
+ <method name="TestNonPrimitiveTypes">
63
+ <arg direction="in" type="a{ss}" name="dict_s_to_s" />
64
+ <arg direction="in" type="a{s(ii)}" name="dict_s_to_pairs" />
65
+ <arg direction="in" type="(iss)" name="a_struct" />
66
+ <arg direction="in" type="as" name="array_of_strings" />
67
+ <arg direction="in" type="ao" name="array_of_objpaths" />
68
+ <arg direction="in" type="ag" name="array_of_signatures" />
69
+ <arg direction="in" type="aay" name="array_of_bytestrings" />
70
+ <arg direction="out" type="s" name="result" />
71
+ </method>
72
+
73
+ <method name="TestAsv">
74
+ <arg direction="in" type="a{sv}" name="asv" />
75
+ <arg direction="out" type="s" name="result" />
76
+ </method>
77
+
78
+ <method name="TestVariant">
79
+ <arg direction="in" type="v" name="v" />
80
+ </method>
81
+
82
+ <method name="RequestSignalEmission">
83
+ <arg direction="in" type="i" name="which_one" />
84
+ </method>
85
+
86
+ <method name="RequestPropertyMods"/>
87
+
88
+ <method name="RequestMultiPropertyMods"/>
89
+
90
+ <method name="UnimplementedMethod"/>
91
+
92
+ <method name="PropertyCancellation"/>
93
+
94
+ <signal name="TestSignal">
95
+ <arg type="i" name="val_int32"/>
96
+ <arg type="as" name="array_of_strings" />
97
+ <arg type="ao" name="array_of_objpaths" />
98
+ <arg type="a{s(ii)}" name="dict_s_to_pairs" />
99
+ </signal>
100
+
101
+ <signal name="AnotherSignal">
102
+ <arg type="s" name="word" />
103
+ </signal>
104
+
105
+ <method name="DeleteAllObjects"/>
106
+
107
+ <method name="CreateObject">
108
+ <arg direction="in" type="o" name="at_path" />
109
+ </method>
110
+
111
+ <method name="DeleteObject">
112
+ <arg direction="in" type="o" name="path" />
113
+ </method>
114
+
115
+ <method name="AddAlpha"/>
116
+ <method name="RemoveAlpha"/>
117
+
118
+ <method name="CreateClique">
119
+ <arg direction="in" type="s" name="name" />
120
+ <arg direction="out" type="o" name="member" />
121
+ </method>
122
+
123
+ <method name="EmitHidden">
124
+ <arg direction="in" type="s" name="name" />
125
+ </method>
126
+
127
+ <method name="ClaimOtherName">
128
+ <arg name="name" direction="in" type="s"/>
129
+ </method>
130
+
131
+ <method name="ReleaseOtherName">
132
+ <arg name="name" direction="in" type="s"/>
133
+ </method>
134
+
135
+ <method name="TellMeYourName">
136
+ <arg direction="out" name="name" type="s"/>
137
+ </method>
138
+
139
+ <method name="MakeTestFd">
140
+ <arg direction="in" name="type" type="s"/>
141
+ <arg direction="out" name="fd" type="h"/>
142
+ </method>
143
+
144
+ <property name="y" type="y" access="readwrite"/>
145
+ <property name="b" type="b" access="readwrite"/>
146
+ <property name="n" type="n" access="readwrite"/>
147
+ <property name="q" type="q" access="readwrite"/>
148
+ <property name="i" type="i" access="readwrite"/>
149
+ <property name="u" type="u" access="readwrite"/>
150
+ <property name="x" type="x" access="readwrite"/>
151
+ <property name="t" type="t" access="readwrite"/>
152
+ <property name="d" type="d" access="readwrite"/>
153
+ <property name="s" type="s" access="readwrite"/>
154
+ <property name="o" type="o" access="readwrite"/>
155
+ <property name="g" type="g" access="readwrite"/>
156
+ <property name="ay" type="ay" access="readwrite"/>
157
+ <property name="as" type="as" access="readwrite"/>
158
+ <property name="aay" type="aay" access="readwrite"/>
159
+ <property name="ao" type="ao" access="readwrite"/>
160
+ <property name="ag" type="ag" access="readwrite"/>
161
+ <property name="FinallyNormalName" type="s" access="readwrite"/>
162
+ <property name="ReadonlyProperty" type="s" access="read"/>
163
+ <property name="WriteonlyProperty" type="s" access="write"/>
164
+ </interface>
165
+
166
+ <interface name="com.redhat.Cockpit.DBusTests.Clique">
167
+ <property name="Friend" type="o" access="read"/>
168
+ </interface>
169
+
170
+ <interface name="com.redhat.Cockpit.DBusTests.Hidden">
171
+ <property name="Name" type="s" access="read"/>
172
+ </interface>
173
+
174
+ </node>
175
+
176
+ <!--
177
+ Local Variables:
178
+ indent-tabs-mode: nil
179
+ End:
180
+ -->
@@ -0,0 +1,4 @@
1
+ [D-BUS Service]
2
+ Name=org.ruby.service
3
+ # ... will replace the directory with the current one
4
+ Exec=/usr/bin/spaghetti-monster.rb
@@ -0,0 +1,4 @@
1
+ [D-BUS Service]
2
+ Name=org.rubygems.ruby_dbus.DBusTests
3
+ # ... will replace the directory with the current one
4
+ Exec=/usr/bin/cockpit-dbustests.rb
@@ -1,14 +1,20 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require_relative "spec_helper"
5
- SimpleCov.command_name "Service Tests" if Object.const_defined? "SimpleCov"
4
+ # This file was formerly named spec/service_newapi.rb, after the example
5
+ # which it mutated from.
6
+ # Spaghetti monster is a better name,
7
+ # reflecting on its evolution and current nature :'-)
8
+
9
+ require_relative "../coverage_helper"
10
+ SimpleCov.command_name "Service Tests (#{Process.pid})" if Object.const_defined? "SimpleCov"
11
+
6
12
  # find the library without external help
7
- $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
13
+ $LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
8
14
 
9
15
  require "dbus"
10
16
 
11
- PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties"
17
+ SERVICE_NAME = "org.ruby.service"
12
18
 
13
19
  class TestChild < DBus::Object
14
20
  def initialize(opath)
@@ -177,15 +183,16 @@ class Test < DBus::Object
177
183
  dbus_interface "org.ruby.TestParent" do
178
184
  dbus_method :New, "in name:s, out opath:o" do |name|
179
185
  child = TestChild.new("#{path}/#{name}")
180
- @service.export(child)
186
+ connection.object_server.export(child)
181
187
  [child.path]
182
188
  end
183
189
 
184
190
  dbus_method :Delete, "in opath:o" do |opath|
185
191
  raise ArgumentError unless opath.start_with?(path)
186
192
 
187
- obj = @service.get_node(opath)&.object
188
- @service.unexport(obj)
193
+ svr = connection.object_server
194
+ obj = svr.get_node(opath)&.object
195
+ svr.unexport(obj)
189
196
  end
190
197
  end
191
198
 
@@ -194,6 +201,9 @@ class Test < DBus::Object
194
201
  [0]
195
202
  end
196
203
  dbus_method :interfaces, "out answer:i" do
204
+ # 'Shadowed' from the Ruby side, meaning ProxyObject#interfaces
205
+ # will return the list of interfaces rather than calling this method.
206
+ # Calling it with busctl will work just fine.
197
207
  raise "This DBus method is currently shadowed by ProxyObject#interfaces"
198
208
  end
199
209
  end
@@ -231,13 +241,14 @@ class Test2 < DBus::Object
231
241
  end
232
242
 
233
243
  bus = DBus::SessionBus.instance
234
- service = bus.request_service("org.ruby.service")
244
+ service = bus.object_server
235
245
  myobj = Test.new("/org/ruby/MyInstance")
236
246
  service.export(myobj)
237
247
  derived = Derived.new "/org/ruby/MyDerivedInstance"
238
248
  service.export derived
239
249
  test2 = Test2.new "/org/ruby/MyInstance2"
240
250
  service.export test2
251
+ bus.request_name(SERVICE_NAME)
241
252
 
242
253
  # introspect every other connection, Ticket #34
243
254
  # (except the one that activates us - it has already emitted
@@ -254,12 +265,13 @@ bus.add_match(mr) do |msg|
254
265
  end
255
266
  end
256
267
 
257
- puts "listening, with ruby-#{RUBY_VERSION}"
268
+ DBus.logger.info "Service #{SERVICE_NAME} listening, with ruby-#{RUBY_VERSION}"
258
269
  main = DBus::Main.new
259
270
  main << bus
260
271
  myobj.main_loop = main
261
272
  begin
262
273
  main.run
263
- rescue SystemCallError
274
+ rescue SystemCallError, SignalException => e
275
+ DBus.logger.info "Service #{SERVICE_NAME} got #{e.inspect}, exiting"
264
276
  # the test driver will kill the bus, that's OK
265
277
  end
data/spec/node_spec.rb CHANGED
@@ -44,11 +44,7 @@ describe DBus::Node do
44
44
 
45
45
  context "on the bus" do
46
46
  let(:bus) { DBus::ASessionBus.new }
47
- let(:service) do
48
- # if we used org.ruby.service it would be a name collision
49
- # ... which would not break the test for lucky reasons
50
- bus.request_service("org.ruby.service.scratch")
51
- end
47
+ let(:service) { bus.object_server }
52
48
 
53
49
  before do
54
50
  service.export(DBus::Object.new(manager_path))
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env rspec
2
+ # frozen_string_literal: true
3
+
4
+ require_relative "spec_helper"
5
+ require "dbus"
6
+
7
+ describe DBus::ObjectServer do
8
+ let(:bus) { DBus::ASessionBus.new }
9
+ let(:server) { bus.object_server }
10
+
11
+ describe "#descendants_for" do
12
+ it "raises for not existing path" do
13
+ expect { server.descendants_for("/notthere") }.to raise_error(ArgumentError, /notthere doesn't exist/)
14
+ end
15
+ end
16
+
17
+ # tag_bus MEANS that the test needs a session bus
18
+ # tag_service MEANS that it needs a session bus with our testing services
19
+
20
+ describe "#export, #object, #[]", tag_bus: true do
21
+ it "object and [] return the object if it was exported" do
22
+ path = "/org/ruby/Foo"
23
+ obj = DBus::Object.new(path)
24
+ server.export(obj)
25
+ expect(server.object(path)).to be_equal(obj)
26
+ expect(server[path]).to be_equal(obj)
27
+ end
28
+
29
+ it "object and [] return nil if the path was not found or has no object" do
30
+ path = "/org/ruby/Bar"
31
+ obj = DBus::Object.new(path)
32
+ server.export(obj)
33
+
34
+ path2 = "/org/ruby/nosuch"
35
+ expect(server.object(path2)).to be_nil
36
+ expect(server[path2]).to be_nil
37
+
38
+ path3 = "/org"
39
+ expect(server.object(path3)).to be_nil
40
+ expect(server[path3]).to be_nil
41
+ end
42
+ end
43
+
44
+ describe "#export", tag_bus: true do
45
+ context "when exporting at a path where an object exists already" do
46
+ let(:path) { "/org/ruby/Same" }
47
+ let(:obj1) do
48
+ o = DBus::Object.new(path)
49
+ o.define_singleton_method(:which) { 1 }
50
+ o
51
+ end
52
+ let(:obj2) do
53
+ o = DBus::Object.new(path)
54
+ o.define_singleton_method(:which) { 2 }
55
+ o
56
+ end
57
+
58
+ # which is right?
59
+ # current behavior
60
+ it "a) silently uses the new object" do
61
+ server.export(obj1)
62
+ server.export(obj2)
63
+
64
+ expect(server).to_not receive(:unexport).with(obj1)
65
+ expect(server[path].which).to eq 2
66
+ end
67
+
68
+ xit "b) unexports the other object first" do
69
+ server.export(obj1)
70
+
71
+ expect(server).to receive(:unexport).with(obj1)
72
+ server.export(obj2)
73
+ end
74
+
75
+ xit "c) raises an error" do
76
+ server.export(obj1)
77
+ expect { server.export(obj2) }.to raise_error(RuntimeError)
78
+ end
79
+ end
80
+ end
81
+
82
+ describe "#unexport", tag_bus: true do
83
+ before(:each) do
84
+ bus = DBus::ASessionBus.new
85
+ @svc = bus.object_server
86
+ end
87
+
88
+ it "returns the unexported object" do
89
+ obj = DBus::Object.new "/org/ruby/Foo"
90
+ @svc.export obj
91
+ expect(@svc.unexport(obj)).to be_a DBus::Object
92
+ end
93
+
94
+ it "returns false if the object was never exported" do
95
+ obj = DBus::Object.new "/org/ruby/Foo"
96
+ expect(@svc.unexport(obj)).to be false
97
+ end
98
+
99
+ it "raises when argument is not a DBus::Object" do
100
+ path = "/org/ruby/Foo"
101
+ expect { @svc.unexport(path) }.to raise_error(ArgumentError)
102
+ end
103
+ end
104
+ end
data/spec/object_spec.rb CHANGED
@@ -118,6 +118,27 @@ describe DBus::Object do
118
118
  end
119
119
  end
120
120
 
121
+ describe ".dbus_signal" do
122
+ it "can only be used within a dbus_interface" do
123
+ expect do
124
+ ObjectTest.instance_exec do
125
+ dbus_signal :signal_without_interface
126
+ end
127
+ end.to raise_error(DBus::Object::UndefinedInterface)
128
+ end
129
+
130
+ it "cannot be named with a bang" do
131
+ expect do
132
+ ObjectTest.instance_exec do
133
+ dbus_interface "org.ruby.ServerTest" do
134
+ # a valid Ruby symbol but an invalid DBus name; Ticket#38
135
+ dbus_signal :signal_with_a_bang!
136
+ end
137
+ end
138
+ end.to raise_error(DBus::InvalidMethodName)
139
+ end
140
+ end
141
+
121
142
  describe ".emits_changed_signal" do
122
143
  it "raises UndefinedInterface when so" do
123
144
  expect { ObjectTest.emits_changed_signal = false }
@@ -145,4 +166,13 @@ describe DBus::Object do
145
166
  end.to raise_error(RuntimeError, /assigned more than once/)
146
167
  end
147
168
  end
169
+
170
+ # coverage obsession
171
+ describe "#dispatch" do
172
+ it "survives being called with a non-METHOD_CALL, doing nothing" do
173
+ obj = ObjectTest.new("/test")
174
+ msg = DBus::MethodReturnMessage.new
175
+ expect { obj.dispatch(msg) }.to_not raise_error
176
+ end
177
+ end
148
178
  end
@@ -4,7 +4,7 @@
4
4
  require_relative "spec_helper"
5
5
  require "dbus"
6
6
 
7
- describe DBus::Service do
7
+ describe DBus::ProxyService do
8
8
  context "when a private bus is set up" do
9
9
  around(:each) do |example|
10
10
  with_private_bus do
data/spec/spec_helper.rb CHANGED
@@ -1,51 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- coverage = if ENV["COVERAGE"]
4
- ENV["COVERAGE"] == "true"
5
- else
6
- # heuristics: enable for interactive builds (but not in OBS)
7
- ENV["DISPLAY"]
8
- end
9
-
10
- if coverage
11
- require "simplecov"
12
- SimpleCov.root File.expand_path("..", __dir__)
13
-
14
- # do not cover specs
15
- SimpleCov.add_filter "_spec.rb"
16
- # do not cover the activesupport helpers
17
- SimpleCov.add_filter "/core_ext/"
18
- # measure all if/else branches on a line
19
- SimpleCov.enable_coverage :branch
20
-
21
- SimpleCov.start
22
-
23
- # additionally use the LCOV format for on-line code coverage reporting at CI
24
- if ENV["COVERAGE_LCOV"] == "true"
25
- require "simplecov-lcov"
26
-
27
- SimpleCov::Formatter::LcovFormatter.config do |c|
28
- c.report_with_single_file = true
29
- # this is the default Coveralls GitHub Action location
30
- # https://github.com/marketplace/actions/coveralls-github-action
31
- c.single_report_path = "coverage/lcov.info"
32
- end
33
-
34
- SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new [
35
- SimpleCov::Formatter::HTMLFormatter,
36
- SimpleCov::Formatter::LcovFormatter
37
- ]
38
- end
39
- end
3
+ require_relative "coverage_helper"
40
4
 
41
5
  $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
42
6
 
43
- if Object.const_defined? "RSpec"
44
- # http://betterspecs.org/#expect
45
- RSpec.configure do |config|
46
- config.expect_with :rspec do |c|
47
- c.syntax = :expect
48
- end
7
+ # http://betterspecs.org/#expect
8
+ RSpec.configure do |config|
9
+ config.expect_with :rspec do |c|
10
+ c.syntax = :expect
49
11
  end
50
12
  end
51
13
 
@@ -102,7 +64,7 @@ end
102
64
 
103
65
  def with_service_by_activation(&block)
104
66
  name = "org.ruby.service"
105
- exec = "#{TOPDIR}/spec/service_newapi.rb"
67
+ exec = "#{TOPDIR}/spec/mock-service/spaghetti-monster.rb"
106
68
 
107
69
  service_dir = "#{ENV["XDG_DATA_DIRS"]}/dbus-1/services"
108
70
  FileUtils.mkdir_p service_dir
@@ -118,7 +80,9 @@ def with_service_by_activation(&block)
118
80
 
119
81
  block.call
120
82
 
121
- system "pkill -f #{exec}"
83
+ # This would kill also other instances,
84
+ # namely on the bus set up by test_env.
85
+ ## system "pkill -f #{exec}"
122
86
  end
123
87
 
124
88
  # Make a binary string from readable YAML pieces; see data/marshall.yaml
@@ -53,22 +53,20 @@ describe "thread safety" do
53
53
  end
54
54
 
55
55
  context "W/O: when the threads only send signals" do
56
- it "it works with a shared separate bus connection" do
57
- race_threads(5) do |j|
58
- # shared connection
59
- bus = DBus::SessionBus.instance
60
- # hackish: we do not actually request the name
61
- svc = DBus::Service.new("org.ruby.server-test#{j}", bus)
62
-
63
- obj = TestSignalRace.new "/org/ruby/Foo"
64
- svc.export obj
56
+ it "it works with a shared bus connection" do
57
+ # shared connection
58
+ bus = DBus::SessionBus.instance
59
+ svc = bus.object_server
60
+ obj = TestSignalRace.new "/org/ruby/Foo"
61
+ svc.export obj
65
62
 
63
+ race_threads(5) do |_j|
66
64
  repeat_with_jitter(10) do
67
65
  obj.signal_without_arguments
68
66
  end
69
-
70
- svc.unexport(obj)
71
67
  end
68
+
69
+ svc.unexport(obj)
72
70
  puts
73
71
  end
74
72
  end
@@ -12,7 +12,10 @@ my_dbus_launch () {
12
12
  AF=`mktemp dbus.addr.XXXXXX` || exit
13
13
  RM_FILES="$RM_FILES $PF $AF"
14
14
 
15
- dbus-daemon --config-file=$(dirname $0)/dbus-limited-session.conf --print-address=3 3>$AF --print-pid=4 4>$PF &
15
+ # For debugging:
16
+ # DBUS_DAEMON=~/svn/dbus/bus/dbus-daemon DBUS_VERBOSE=1 ./spec/tools/test_env env PS1="TEST $PS1" bash
17
+ : ${DBUS_DAEMON=dbus-daemon}
18
+ $DBUS_DAEMON --config-file=$(dirname $0)/dbus-limited-session.conf --print-address=3 3>$AF --print-pid=4 4>$PF &
16
19
  # wait for the daemon to print the info
17
20
  TRIES=0
18
21
  while [ ! -s $AF -o ! -s $PF ]; do
data/spec/tools/test_env CHANGED
@@ -2,13 +2,33 @@
2
2
  # test_env: set up the environment needed to run tests:
3
3
  # - set up a private bus
4
4
  # - run a test server on it
5
+ set -o errexit
5
6
 
6
7
  #export DBUS_VERBOSE=1
7
8
  #export RUBYOPT="-d"
8
9
  export RUBYOPT="$RUBYOPT -w"
9
- DIR=$(dirname $0)
10
- $DIR/test_server \
11
- $DIR/../service_newapi.rb \
12
- -- \
13
- $DIR/dbus-launch-simple \
14
- "$@"
10
+ MYDIR=$(dirname $0)
11
+ TOPDIR=$(realpath $MYDIR/../..)
12
+
13
+
14
+ # Clean up at exit.
15
+ trap "rm -rf \$RM_FILES" EXIT TERM INT
16
+
17
+ export XDG_DATA_DIRS=`mktemp -d dbus.activation.XXXXXX`
18
+ RM_FILES="$RM_FILES $XDG_DATA_DIRS"
19
+
20
+ SVCDIR=$XDG_DATA_DIRS/dbus-1/services
21
+ mkdir -p $SVCDIR
22
+ for SVC in $TOPDIR/spec/mock-service/*.service; do
23
+ SVCBASE=${SVC##*/}
24
+ sed -e "s@\(Exec\)=/usr/bin/@\1=$TOPDIR/spec/mock-service/@" $SVC > $SVCDIR/$SVCBASE
25
+ done
26
+
27
+
28
+ # no command given -> run an interactive shell
29
+ if [ $# = 0 ]; then
30
+ set -- env PS1="TEST_ENV \w> " bash
31
+ fi
32
+
33
+ $MYDIR/dbus-launch-simple \
34
+ "$@"