rspec-openhab-scripting 0.0.10-java → 0.0.11-java
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.
- checksums.yaml +4 -4
- data/lib/rspec/openhab/dsl/imports.rb +136 -10
- data/lib/rspec/openhab/dsl/timers/timer.rb +85 -0
- data/lib/rspec/openhab/helpers.rb +42 -0
- data/lib/rspec/openhab/hooks.rb +18 -0
- data/lib/rspec/openhab/items.rb +0 -24
- data/lib/rspec/openhab/suspend_rules.rb +56 -0
- data/lib/rspec/openhab/version.rb +1 -1
- data/lib/rspec-openhab-scripting.rb +14 -6
- metadata +20 -6
- data/lib/rspec/openhab/state.rb +0 -20
- data/lib/rspec/openhab/timer.rb +0 -12
- data/lib/rspec/openhab/trigger.rb +0 -17
- data/lib/rspec/openhab/wait.rb +0 -82
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3ef6a42e87b4466cf53972b65523d3a810060cbeac84497796ab4514b377d445
|
4
|
+
data.tar.gz: 0b3be611dddf1a4e5643cdb48fd3f8a05d35eda32e50e9b4062a063f49f6ad17
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0ffaf54c3e64d9a4f1be5ff0ecec757976db0e5ebbddec2d916d254fb9f9f730f3e1e1245fc478a970e8e42509613877ac535f9983aa94288cbb9c1f7abfa826
|
7
|
+
data.tar.gz: 3333117270aa1e6b2de597ad9570df51a9f829d0c5da345cdbb1aed5f50d5bf841cdd1b9a140a94cf06695982acce024280ec814f4cbe5b46ab94dce88566b40
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "singleton"
|
4
|
+
|
3
5
|
require "openhab/core/osgi"
|
4
6
|
|
5
7
|
module OpenHAB
|
@@ -20,6 +22,7 @@ module OpenHAB
|
|
20
22
|
|
21
23
|
def initialize(event_manager)
|
22
24
|
@event_manager = event_manager
|
25
|
+
@pending_events = nil
|
23
26
|
end
|
24
27
|
|
25
28
|
def post_event(event)
|
@@ -27,7 +30,17 @@ module OpenHAB
|
|
27
30
|
end
|
28
31
|
|
29
32
|
def send_event(event)
|
33
|
+
if @pending_events
|
34
|
+
@pending_events << event
|
35
|
+
return
|
36
|
+
end
|
37
|
+
|
38
|
+
@pending_events = []
|
30
39
|
@event_manager.handle_event(event)
|
40
|
+
|
41
|
+
@event_manager.handle_event(@pending_events.shift) until @pending_events.empty?
|
42
|
+
|
43
|
+
@pending_events = nil
|
31
44
|
end
|
32
45
|
end
|
33
46
|
|
@@ -123,6 +136,119 @@ module OpenHAB
|
|
123
136
|
field_reader :typedEventFactories, :typedEventSubscribers
|
124
137
|
end
|
125
138
|
|
139
|
+
# reimplement to not use a thread
|
140
|
+
class EventHandler
|
141
|
+
def initialize(typed_event_subscribers, typed_event_factories)
|
142
|
+
@typed_event_subscribers = typed_event_subscribers
|
143
|
+
@typed_event_factories = typed_event_factories
|
144
|
+
end
|
145
|
+
|
146
|
+
def handle_event(osgi_event)
|
147
|
+
type = osgi_event.get_property("type")
|
148
|
+
payload = osgi_event.get_property("payload")
|
149
|
+
topic = osgi_event.get_property("topic")
|
150
|
+
source = osgi_event.get_property("source")
|
151
|
+
|
152
|
+
if type.is_a?(String) && payload.is_a?(String) && topic.is_a?(String)
|
153
|
+
handle_event_internal(type, payload, topic, source) unless type.empty? || payload.empty? || topic.empty?
|
154
|
+
else
|
155
|
+
logger.error("The handled OSGi event is invalid. " \
|
156
|
+
"Expect properties as string named 'type', 'payload', and 'topic'. " \
|
157
|
+
"Received event properties are: #{properties.keys.inspect}")
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
private
|
162
|
+
|
163
|
+
def handle_event_internal(type, payload, topic, source)
|
164
|
+
event_factory = @typed_event_factories[type]
|
165
|
+
unless event_factory
|
166
|
+
logger.debug("Could not find an Event Factory for the event type '#{type}'.")
|
167
|
+
return
|
168
|
+
end
|
169
|
+
|
170
|
+
event_subscribers = event_subscribers(type)
|
171
|
+
return if event_subscribers.empty?
|
172
|
+
|
173
|
+
event = create_event(event_factory, type, payload, topic, source)
|
174
|
+
return unless event
|
175
|
+
|
176
|
+
dispatch_event(event_subscribers, event)
|
177
|
+
end
|
178
|
+
|
179
|
+
def event_subscribers(event_type)
|
180
|
+
event_type_subscribers = @typed_event_subscribers[event_type]
|
181
|
+
all_event_type_subscribers = @typed_event_subscribers["ALL"]
|
182
|
+
|
183
|
+
subscribers = java.util.HashSet.new
|
184
|
+
subscribers.add_all(event_type_subscribers) if event_type_subscribers
|
185
|
+
subscribers.add_all(all_event_type_subscribers) if all_event_type_subscribers
|
186
|
+
subscribers
|
187
|
+
end
|
188
|
+
|
189
|
+
def create_event(event_factory, type, payload, topic, source)
|
190
|
+
event_factory.create_event(type, topic, payload, source)
|
191
|
+
rescue Exception => e
|
192
|
+
logger.warn("Creation of event failed, because one of the " \
|
193
|
+
"registered event factories has thrown an exception: #{e}")
|
194
|
+
nil
|
195
|
+
end
|
196
|
+
|
197
|
+
def dispatch_event(event_subscribers, event)
|
198
|
+
event_subscribers.each do |event_subscriber|
|
199
|
+
filter = event_subscriber.event_filter
|
200
|
+
if filter.nil? || filter.apply(event)
|
201
|
+
begin
|
202
|
+
event_subscriber.receive(event)
|
203
|
+
rescue Exception => e
|
204
|
+
logger.warn("Dispatching/filtering event for subscriber '#{event_subscriber.class}' failed: #{e}")
|
205
|
+
end
|
206
|
+
else
|
207
|
+
logger.trace("Skip event subscriber (#{event_subscriber.class}) because of its filter.")
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
org.openhab.core.automation.internal.TriggerHandlerCallbackImpl.field_accessor :executor
|
214
|
+
org.openhab.core.automation.internal.TriggerHandlerCallbackImpl.field_reader :ruleUID
|
215
|
+
class SynchronousExecutor
|
216
|
+
include java.util.concurrent.ScheduledExecutorService
|
217
|
+
include Singleton
|
218
|
+
|
219
|
+
def submit(runnable)
|
220
|
+
runnable.run
|
221
|
+
|
222
|
+
java.util.concurrent.CompletableFuture.completed_future(nil)
|
223
|
+
end
|
224
|
+
|
225
|
+
def execute(runnable)
|
226
|
+
runnable.run
|
227
|
+
end
|
228
|
+
|
229
|
+
def shutdown_now; end
|
230
|
+
|
231
|
+
def shutdown?
|
232
|
+
false
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
class CallbacksMap < java.util.HashMap
|
237
|
+
def put(_rule_uid, trigger_handler)
|
238
|
+
trigger_handler.executor.shutdown_now
|
239
|
+
trigger_handler.executor = SynchronousExecutor.instance
|
240
|
+
super
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
class SynchronousExecutorMap
|
245
|
+
include java.util.Map
|
246
|
+
|
247
|
+
def get(_key)
|
248
|
+
SynchronousExecutor.instance
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
126
252
|
@imported = false
|
127
253
|
|
128
254
|
class << self
|
@@ -133,18 +259,13 @@ module OpenHAB
|
|
133
259
|
|
134
260
|
@imported = true
|
135
261
|
|
136
|
-
|
137
|
-
|
138
|
-
status = 0
|
139
|
-
status = $!.status if $!.is_a?(SystemExit)
|
140
|
-
exit!(status)
|
141
|
-
end
|
262
|
+
org.openhab.core.common.ThreadPoolManager.field_accessor :pools
|
263
|
+
org.openhab.core.common.ThreadPoolManager.pools = SynchronousExecutorMap.new
|
142
264
|
|
143
265
|
# OSGiEventManager will create a ThreadedEventHandler on OSGi activation;
|
144
266
|
# we're skipping that, and directly sending to a non-threaded event handler.
|
145
267
|
em = EventManager.new
|
146
|
-
eh =
|
147
|
-
at_exit { eh.close }
|
268
|
+
eh = EventHandler.new(em.typedEventSubscribers, em.typedEventFactories)
|
148
269
|
ea = EventAdmin.new(eh)
|
149
270
|
ep = org.openhab.core.internal.events.OSGiEventPublisher.new(ea)
|
150
271
|
bc = BundleContext.new(em)
|
@@ -234,8 +355,7 @@ module OpenHAB
|
|
234
355
|
$se = $scriptExtension = sew
|
235
356
|
|
236
357
|
# need to create some singletons referencing registries
|
237
|
-
|
238
|
-
org.openhab.core.model.script.ScriptServiceUtil.new(ir, tr, ep, nil, scheduler)
|
358
|
+
org.openhab.core.model.script.ScriptServiceUtil.new(ir, tr, ep, nil, nil)
|
239
359
|
org.openhab.core.model.script.internal.engine.action.SemanticsActionService.new(ir)
|
240
360
|
|
241
361
|
# link up event bus infrastructure
|
@@ -265,6 +385,12 @@ module OpenHAB
|
|
265
385
|
|
266
386
|
rs = org.openhab.core.internal.service.ReadyServiceImpl.new
|
267
387
|
re = org.openhab.core.automation.internal.RuleEngineImpl.new(mtr, rr, ss, rs)
|
388
|
+
# overwrite thCallbacks to one that will spy to remove threading
|
389
|
+
field = re.class.java_class.declared_field("thCallbacks")
|
390
|
+
field.accessible = true
|
391
|
+
field.set(re, CallbacksMap.new)
|
392
|
+
re.class.field_accessor :executor
|
393
|
+
re.executor = SynchronousExecutor.instance
|
268
394
|
re.add_module_handler_factory(cmhf)
|
269
395
|
re.add_module_handler_factory(scmhf)
|
270
396
|
re.add_module_handler_factory(spmhf)
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OpenHAB
|
4
|
+
module DSL
|
5
|
+
class Timer
|
6
|
+
module MockedZonedDateTime
|
7
|
+
def now
|
8
|
+
mocked_time_stack_item = Timecop.top_stack_item
|
9
|
+
return super unless mocked_time_stack_item
|
10
|
+
|
11
|
+
instant = java.time.Instant.of_epoch_milli((Time.now.to_f * 1000).to_i)
|
12
|
+
ZonedDateTime.of_instant(instant, java.time.ZoneId.system_default)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
ZonedDateTime.singleton_class.prepend(MockedZonedDateTime)
|
16
|
+
|
17
|
+
# extend Timecop to support java time classes
|
18
|
+
module TimeCopStackItem
|
19
|
+
def parse_time(*args)
|
20
|
+
if args.length == 1 && args.first.is_a?(Duration)
|
21
|
+
return time_klass.at(ZonedDateTime.now.plus(args.first).to_instant.to_epoch_milli / 1000.0)
|
22
|
+
end
|
23
|
+
|
24
|
+
super
|
25
|
+
end
|
26
|
+
end
|
27
|
+
Timecop::TimeStackItem.prepend(TimeCopStackItem)
|
28
|
+
|
29
|
+
attr_reader :execution_time
|
30
|
+
|
31
|
+
def initialize(duration:, thread_locals: {}, &block) # rubocop:disable Lint/UnusedMethodArgument
|
32
|
+
@block = block
|
33
|
+
reschedule(duration)
|
34
|
+
end
|
35
|
+
|
36
|
+
def reschedule(duration = nil)
|
37
|
+
@duration = duration || @duration
|
38
|
+
@execution_time = ZonedDateTime.now.plus(@duration)
|
39
|
+
@executed = @cancelled = false
|
40
|
+
|
41
|
+
Timers.timer_manager.add(self)
|
42
|
+
end
|
43
|
+
|
44
|
+
def execute
|
45
|
+
raise "Timer already cancelled" if cancelled?
|
46
|
+
raise "Timer already executed" if terminated?
|
47
|
+
|
48
|
+
@block.call
|
49
|
+
Timers.timer_manager.delete(self)
|
50
|
+
@executed = true
|
51
|
+
end
|
52
|
+
|
53
|
+
def cancel
|
54
|
+
Timers.timer_manager.delete(self)
|
55
|
+
@executed = false
|
56
|
+
@cancelled = true
|
57
|
+
true
|
58
|
+
end
|
59
|
+
|
60
|
+
def cancelled?
|
61
|
+
@cancelled
|
62
|
+
end
|
63
|
+
|
64
|
+
def terminated?
|
65
|
+
@executed || @cancelled
|
66
|
+
end
|
67
|
+
|
68
|
+
def running?
|
69
|
+
active? && @execution_time > ZonedDateTime.now
|
70
|
+
end
|
71
|
+
|
72
|
+
def active?
|
73
|
+
!terminated?
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
module Support
|
78
|
+
class TimerManager
|
79
|
+
def execute_timers
|
80
|
+
@timers.each { |t| t.execute if t.active? && t.execution_time < ZonedDateTime.now }
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module OpenHAB
|
5
|
+
module Helpers
|
6
|
+
def autoupdate_all_items
|
7
|
+
@autoupdated_items ||= {}
|
8
|
+
$ir.for_each do |_provider, item|
|
9
|
+
@autoupdated_items[item] = item.meta.delete("autoupdate") if item.meta.key?("autoupdate")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def execute_timers
|
14
|
+
OpenHAB::DSL::Timers.timer_manager.execute_timers
|
15
|
+
end
|
16
|
+
|
17
|
+
def suspend_rules(&block)
|
18
|
+
SuspendRules.suspend_rules(&block)
|
19
|
+
end
|
20
|
+
|
21
|
+
def trigger_rule(rule_name, event = nil)
|
22
|
+
@rules ||= ::OpenHAB::DSL::Rules::Rule.script_rules.each_with_object({}) { |r, obj| obj[r.name] = r }
|
23
|
+
|
24
|
+
@rules.fetch(rule_name).execute(nil, { "event" => event })
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def restore_autoupdate_items
|
30
|
+
return unless instance_variable_defined?(:@autoupdated_items)
|
31
|
+
|
32
|
+
@autoupdated_items.each do |(item, meta)|
|
33
|
+
item.meta["autoupdate"] = meta
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
RSpec.configure do |config|
|
39
|
+
config.include Helpers
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.configure do |config|
|
4
|
+
config.before(:all) { OpenHAB::DSL::Timers.timer_manager.cancel_all }
|
5
|
+
|
6
|
+
config.before do
|
7
|
+
suspend_rules do
|
8
|
+
$ir.for_each do |_provider, item|
|
9
|
+
item.state = NULL unless item.raw_state == NULL
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
config.after do
|
14
|
+
OpenHAB::DSL::Timers.timer_manager.cancel_all
|
15
|
+
Timecop.return
|
16
|
+
restore_autoupdate_items
|
17
|
+
end
|
18
|
+
end
|
data/lib/rspec/openhab/items.rb
CHANGED
@@ -49,30 +49,6 @@ module RSpec
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
end
|
52
|
-
|
53
|
-
def autoupdate_all_items
|
54
|
-
@autoupdated_items ||= {}
|
55
|
-
$ir.for_each do |_provider, item|
|
56
|
-
@autoupdated_items[item] = item.meta.delete("autoupdate") if item.meta.key?("autoupdate")
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
private
|
61
|
-
|
62
|
-
def restore_autoupdate_items
|
63
|
-
return unless instance_variable_defined?(:@autoupdated_items)
|
64
|
-
|
65
|
-
@autoupdated_items.each do |(item, meta)|
|
66
|
-
item.meta["autoupdate"] = meta
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
::RSpec.configure do |config|
|
71
|
-
config.include(self)
|
72
|
-
config.after do
|
73
|
-
restore_autoupdate_items
|
74
|
-
end
|
75
|
-
end
|
76
52
|
end
|
77
53
|
end
|
78
54
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module OpenHAB
|
5
|
+
module SuspendRules
|
6
|
+
# I'd prefer to prepend a module, but I can't because of
|
7
|
+
# https://github.com/jruby/jruby/issues/6966#issuecomment-1172983776
|
8
|
+
class ::OpenHAB::DSL::Rules::AutomationRule # rubocop:disable Style/ClassAndModuleChildren
|
9
|
+
def execute(mod = nil, inputs = nil)
|
10
|
+
if SuspendRules.suspended?
|
11
|
+
logger.debug("Skipping execution of #{name} because rules are suspended.")
|
12
|
+
return
|
13
|
+
end
|
14
|
+
|
15
|
+
# super
|
16
|
+
::OpenHAB::DSL.import_presets
|
17
|
+
thread_local(RULE_NAME: name) do
|
18
|
+
logger.trace { "Execute called with mod (#{mod&.to_string}) and inputs (#{inputs.inspect})" }
|
19
|
+
logger.trace { "Event details #{inputs["event"].inspect}" } if inputs&.key?("event")
|
20
|
+
trigger_conditions(inputs).process(mod: mod, inputs: inputs) do
|
21
|
+
process_queue(create_queue(inputs), mod, inputs)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
# private_constant :AutomationRule
|
27
|
+
# ::OpenHAB::DSL::Rules::AutomationRule.prepend(AutomationRule)
|
28
|
+
|
29
|
+
module Timers
|
30
|
+
def after(*)
|
31
|
+
return if SuspendRules.suspended?
|
32
|
+
|
33
|
+
super
|
34
|
+
end
|
35
|
+
end
|
36
|
+
private_constant :Timers
|
37
|
+
::Object.prepend(Timers)
|
38
|
+
|
39
|
+
@suspended = false
|
40
|
+
|
41
|
+
class << self
|
42
|
+
def suspend_rules
|
43
|
+
old_suspended = @suspended
|
44
|
+
@suspended = true
|
45
|
+
yield
|
46
|
+
ensure
|
47
|
+
@suspended = old_suspended
|
48
|
+
end
|
49
|
+
|
50
|
+
def suspended?
|
51
|
+
@suspended
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -57,10 +57,13 @@ def oh.config_folder
|
|
57
57
|
end
|
58
58
|
|
59
59
|
# global variables need to be set up before openhab-scripting loads
|
60
|
+
require "timecop"
|
60
61
|
require "openhab/log/logger"
|
61
62
|
require "rspec/openhab/core/logger"
|
63
|
+
|
62
64
|
# during testing, we don't want "regular" output from rules
|
63
65
|
OpenHAB::Log.logger("org.openhab.automation.jruby.runtime").level = :warn
|
66
|
+
OpenHAB::Log.logger("org.openhab.automation.jruby.logger").level = :warn
|
64
67
|
require "openhab/dsl/imports"
|
65
68
|
OpenHAB::DSL::Imports.api = api
|
66
69
|
OpenHAB::DSL::Imports.import_presets
|
@@ -70,19 +73,24 @@ require "openhab"
|
|
70
73
|
require "rspec/openhab/actions"
|
71
74
|
require "rspec/openhab/core/cron_scheduler"
|
72
75
|
|
76
|
+
# override several timer methods
|
77
|
+
require_relative "rspec/openhab/dsl/timers/timer"
|
78
|
+
|
73
79
|
# RSpec additions
|
74
80
|
require "rspec/core"
|
75
81
|
require "rspec/openhab/dsl/rules/rspec"
|
76
82
|
require "rspec/openhab/items"
|
77
|
-
require "rspec/openhab/
|
78
|
-
require "rspec/openhab/
|
79
|
-
require "rspec/openhab/
|
80
|
-
|
83
|
+
require "rspec/openhab/helpers"
|
84
|
+
require "rspec/openhab/hooks"
|
85
|
+
require "rspec/openhab/suspend_rules"
|
86
|
+
|
81
87
|
RSpec.configure do |config|
|
82
88
|
config.include OpenHAB::Core::EntityLookup
|
83
89
|
end
|
84
90
|
|
85
|
-
RSpec::OpenHAB::
|
91
|
+
RSpec::OpenHAB::SuspendRules.suspend_rules do
|
92
|
+
RSpec::OpenHAB::Items.populate_items_from_api(api)
|
93
|
+
end
|
86
94
|
|
87
95
|
# make bundler/inline _not_ destroy the already existing load path
|
88
96
|
module Bundler
|
@@ -96,7 +104,7 @@ OPENHAB_AUTOMATION_PATH = "#{org.openhab.core.OpenHAB.config_folder}/automation/
|
|
96
104
|
|
97
105
|
Dir["#{OPENHAB_AUTOMATION_PATH}/*.rb"].each do |f|
|
98
106
|
load f
|
99
|
-
rescue Exception => e
|
107
|
+
rescue Exception => e
|
100
108
|
warn "Failed loading #{f}: #{e.inspect}"
|
101
109
|
warn e.backtrace
|
102
110
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-openhab-scripting
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.11
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Cody Cutrer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-07-
|
11
|
+
date: 2022-07-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -94,6 +94,20 @@ dependencies:
|
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '3.3'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0.9'
|
103
|
+
name: timecop
|
104
|
+
prerelease: false
|
105
|
+
type: :runtime
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0.9'
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
requirement: !ruby/object:Gem::Requirement
|
99
113
|
requirements:
|
@@ -182,12 +196,12 @@ files:
|
|
182
196
|
- lib/rspec/openhab/core/script_handling.rb
|
183
197
|
- lib/rspec/openhab/dsl/imports.rb
|
184
198
|
- lib/rspec/openhab/dsl/rules/rspec.rb
|
199
|
+
- lib/rspec/openhab/dsl/timers/timer.rb
|
200
|
+
- lib/rspec/openhab/helpers.rb
|
201
|
+
- lib/rspec/openhab/hooks.rb
|
185
202
|
- lib/rspec/openhab/items.rb
|
186
|
-
- lib/rspec/openhab/
|
187
|
-
- lib/rspec/openhab/timer.rb
|
188
|
-
- lib/rspec/openhab/trigger.rb
|
203
|
+
- lib/rspec/openhab/suspend_rules.rb
|
189
204
|
- lib/rspec/openhab/version.rb
|
190
|
-
- lib/rspec/openhab/wait.rb
|
191
205
|
- vendor/gems/jar-dependencies-1.0.0/lib/jar-dependencies.rb
|
192
206
|
- vendor/gems/jar-dependencies-1.0.0/lib/jar_dependencies.rb
|
193
207
|
- vendor/gems/jar-dependencies-1.0.0/lib/jar_install_post_install_hook.rb
|
data/lib/rspec/openhab/state.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.configure do |config|
|
4
|
-
config.before(:each) do
|
5
|
-
ep = $ir.event_publisher
|
6
|
-
|
7
|
-
# stash event publishers to avoid triggering any rules
|
8
|
-
$ir.for_each do |_provider, item|
|
9
|
-
item.event_publisher = nil
|
10
|
-
end
|
11
|
-
|
12
|
-
$ir.for_each do |_provider, item| # rubocop:disable Style/CombinableLoops
|
13
|
-
item.state = NULL # don't use update, to avoid triggering any rules
|
14
|
-
end
|
15
|
-
ensure
|
16
|
-
$ir.for_each do |_provider, item|
|
17
|
-
item.event_publisher = ep
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
data/lib/rspec/openhab/timer.rb
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.configure do |config|
|
4
|
-
config.before(:each) do
|
5
|
-
OpenHAB::DSL::Timers.timer_manager.cancel_all
|
6
|
-
wait_for_background_tasks
|
7
|
-
end
|
8
|
-
config.after(:each) do
|
9
|
-
OpenHAB::DSL::Timers.timer_manager.cancel_all
|
10
|
-
wait_for_background_tasks
|
11
|
-
end
|
12
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module RSpec
|
4
|
-
module OpenHAB
|
5
|
-
module Trigger
|
6
|
-
def trigger_rule(rule_name, event = nil)
|
7
|
-
@rules ||= ::OpenHAB::DSL::Rules::Rule.script_rules.each_with_object({}) { |r, obj| obj[r.name] = r }
|
8
|
-
|
9
|
-
@rules.fetch(rule_name).execute(nil, { "event" => event })
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
RSpec.configure do |config|
|
16
|
-
config.include RSpec::OpenHAB::Trigger
|
17
|
-
end
|
data/lib/rspec/openhab/wait.rb
DELETED
@@ -1,82 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module RSpec
|
4
|
-
module OpenHAB
|
5
|
-
module Wait
|
6
|
-
def wait_for_rules
|
7
|
-
wait_for_background_tasks(timers: false)
|
8
|
-
end
|
9
|
-
|
10
|
-
def wait_for_timers
|
11
|
-
wait_for_background_tasks(rules: false)
|
12
|
-
end
|
13
|
-
|
14
|
-
def wait_for_background_tasks(rules: true, timers: true)
|
15
|
-
loop do
|
16
|
-
sleep 0.1
|
17
|
-
next if java.lang.Thread.all_stack_traces.any? do |(t, stack)|
|
18
|
-
# this is just an estimate. I see 9 when it's parked waiting
|
19
|
-
# for an event, but once it hits ruby it gets real big real quick
|
20
|
-
min_frames = 15
|
21
|
-
|
22
|
-
case t.name
|
23
|
-
when /^OH-scheduler-/
|
24
|
-
# timer thread; born and die for each timer
|
25
|
-
if thread_running?(t) || stack.length > min_frames
|
26
|
-
logger.debug "thread #{t.name} is running (#{stack.length})"
|
27
|
-
stack.each do |frame|
|
28
|
-
logger.trace " #{frame}"
|
29
|
-
end
|
30
|
-
next timers
|
31
|
-
end
|
32
|
-
when /^OH-rule-/
|
33
|
-
|
34
|
-
if thread_running?(t) || stack.length > min_frames
|
35
|
-
logger.debug "thread #{t.name} is running (#{stack.length})"
|
36
|
-
stack.each do |frame|
|
37
|
-
logger.trace " #{frame}"
|
38
|
-
end
|
39
|
-
|
40
|
-
next rules
|
41
|
-
end
|
42
|
-
when /^OH-(?:eventwatcher|eventexecutor)-/
|
43
|
-
# an event is making its way through the system
|
44
|
-
if thread_running?(t)
|
45
|
-
logger.debug "thread #{t.name} is running"
|
46
|
-
next rules
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
# no need to retry if there were no timers
|
52
|
-
break unless timers && wait_for_next_timer
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
private
|
57
|
-
|
58
|
-
def thread_running?(thread)
|
59
|
-
![java.lang.Thread::State::WAITING,
|
60
|
-
java.lang.Thread::State::TIMED_WAITING].include?(thread.state)
|
61
|
-
end
|
62
|
-
|
63
|
-
def wait_for_next_timer
|
64
|
-
latest = ::OpenHAB::DSL::Timers.timer_manager.instance_variable_get(:@timers).min_by(&:execution_time)
|
65
|
-
return false unless latest
|
66
|
-
|
67
|
-
delta = (latest.execution_time.to_instant.to_epoch_milli - java.time.Instant.now.to_epoch_milli) / 1000.0
|
68
|
-
# in the past? it's probably executing
|
69
|
-
return true if delta.negative?
|
70
|
-
|
71
|
-
logger.info("Waiting #{delta}s for next timer") if delta > 5
|
72
|
-
|
73
|
-
sleep(delta)
|
74
|
-
true
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
RSpec.configure do |config|
|
81
|
-
config.include RSpec::OpenHAB::Wait
|
82
|
-
end
|