Skip to content

Commit

Permalink
Merge pull request #408 from rsmp-nordic/m0022_cancellation
Browse files Browse the repository at this point in the history
M0022 cancellation
  • Loading branch information
emiltin authored Aug 23, 2024
2 parents a6acb48 + 477ac30 commit 88e9933
Show file tree
Hide file tree
Showing 10 changed files with 311 additions and 99 deletions.
12 changes: 6 additions & 6 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,18 @@ GEM
minitest (>= 5.1)
mutex_m
tzinfo (~> 2.0)
async (2.12.0)
async (2.12.1)
console (~> 1.25, >= 1.25.2)
fiber-annotation
io-event (~> 1.6)
io-event (~> 1.6, >= 1.6.5)
async-io (1.43.2)
async
base64 (0.2.0)
bigdecimal (3.1.8)
colorize (1.1.0)
concurrent-ruby (1.3.3)
connection_pool (2.4.1)
console (1.25.2)
console (1.27.0)
fiber-annotation
fiber-local (~> 1.1)
json
Expand All @@ -31,11 +31,11 @@ GEM
fiber-annotation (0.2.0)
fiber-local (1.1.0)
fiber-storage
fiber-storage (0.1.2)
fiber-storage (1.0.0)
hana (1.3.7)
i18n (1.14.5)
concurrent-ruby (~> 1.0)
io-event (1.6.4)
io-event (1.6.5)
json (2.7.2)
json_schemer (2.3.0)
bigdecimal
Expand All @@ -46,7 +46,7 @@ GEM
mutex_m (0.2.0)
rake (13.2.1)
regexp_parser (2.9.2)
rsmp (0.29.0)
rsmp (0.31.0)
async (~> 2.12.0)
async-io (~> 1.43.0)
colorize (~> 1.1)
Expand Down
3 changes: 3 additions & 0 deletions config/gem_tlc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,6 @@ alarms:
restrict_testing:
sxl_version: 1.2.1
core_version: 3.2.2
log:
watchdogs: false
acknowledgements: false
2 changes: 1 addition & 1 deletion spec/site/tlc/alarm_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def verify_timestamp alarm, duration=1.minute
collect_task = task.async do
RSMP::AlarmCollector.new(site,
num: 1,
query: {
matcher: {
'aCId' => alarm_code_id,
'aSp' => /Acknowledge/i,
'ack' => /Acknowledged/i,
Expand Down
12 changes: 6 additions & 6 deletions spec/site/tlc/clock_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,12 @@
status = status_list.keys.first.to_s

received = Time.new(
collector.query_result( {"sCI" => status, "n" => "year"} )['s'],
collector.query_result( {"sCI" => status, "n" => "month"} )['s'],
collector.query_result( {"sCI" => status, "n" => "day"} )['s'],
collector.query_result( {"sCI" => status, "n" => "hour"} )['s'],
collector.query_result( {"sCI" => status, "n" => "minute"} )['s'],
collector.query_result( {"sCI" => status, "n" => "second"} )['s'],
collector.matcher_result( {"sCI" => status, "n" => "year"} )['s'],
collector.matcher_result( {"sCI" => status, "n" => "month"} )['s'],
collector.matcher_result( {"sCI" => status, "n" => "day"} )['s'],
collector.matcher_result( {"sCI" => status, "n" => "hour"} )['s'],
collector.matcher_result( {"sCI" => status, "n" => "minute"} )['s'],
collector.matcher_result( {"sCI" => status, "n" => "second"} )['s'],
'UTC'
)

Expand Down
161 changes: 84 additions & 77 deletions spec/site/tlc/signal_priority_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,92 +52,99 @@
end
end

# Validate that signal priority status are send when priorty is requested
# Validate that a signal priority completes when we cancel it.
#
# 1. Given the site is connected
# 2. And we subscribe to signal priority status
# 2. When we send a signal priority request
# 3. Then we should receive status updates
it 'state goes through received, activated, completed', sxl: '>=1.1' do |example|
# 3. When we send a signal priority request
# 4. Then the request state should become 'received'
# 5. Then the request state should become 'activated'
# 6. When we cancel the request
# 7. Then the state should become 'completed'

it 'becomes completed when cancelled', sxl: '>=1.1' do |example|
Validator::Site.connected do |task,supervisor,site|
sequence = ['received','activated','completed']
# subscribe
timeout = Validator.get_config('timeouts','priority_completion')
component = Validator.get_config('main_component')
log "Subscribing to signal priority request status updates"
status_list = [{'sCI'=>'S0033','n'=>'status','uRt'=>'0'}]
status_list.map! { |item| item.merge!('sOc' => true) } if use_sOc?(site)
site.subscribe_to_status component, status_list

# start collector
request_id = SecureRandom.uuid()[0..3] # make a message id
num = sequence.length
states = []
result = nil
collector = nil
collect_task = task.async do
collector = RSMP::Collector.new(
site,
type: "StatusUpdate",
num: num,
timeout: Validator.get_config('timeouts','priority_completion'),
component: component
)

def search_for_request_state request_id, message, states
message.attribute('sS').each do |status|
return nil unless status['sCI'] == 'S0033' && status['n'] == 'status'
status['s'].each do |priority|
next unless priority['r'] == request_id # is this our request
state = priority['s']
next unless state != states.last # did the state change?
log "Priority request reached state '#{state}'"
return state
end
end
nil
end

result = collector.collect do |message|
state = search_for_request_state request_id, message, states
next unless state
states << state
:keep
end
end
signal_group_id = Validator.get_config('components','signal_group').keys.first
prio = Validator::StatusHelpers::SignalPriorityRequestHelper.new(
site,
component: component,
signal_group_id: signal_group_id,
timeout: timeout,
task: task
)

prio.run do
log "Before: Send unrelated signal priority request."
prio.request_unrelated

log "Send signal priority request, wait for reception."
prio.request

def send_priority_request log, id:nil, site:, component:
# send an unrelated request before our request, to check that it does not interfere
log log
signal_group = Validator.get_config('components','signal_group').keys.first
command_list = build_command_list :M0022, :requestPriority, {
requestId: (id || SecureRandom.uuid()[0..3]),
signalGroupId: signal_group,
type: 'new',
level: 7,
eta: 2,
vehicleType: 'car'
}
site.send_command component, command_list
log "After: Send unrelated signal priority request."
prio.request_unrelated

prio.expect :received
log "Signal priority request was received, wait for activation."

prio.expect :activated
log "Signal priority request was activated, now cancel it and wait for completion."


prio.cancel
prio.expect :completed
log "Signal priority request was completed."
end
end
end

# Validate that a signal priority times out if not cancelled.
#
# 1. Given the site is connected
# 2. And we subscribe to signal priority status
# 3. When we send a signal priority request
# 4. Then the request state should become 'received'
# 5. Then the request state should become 'activated'
# 6. When we do not cancel the request
# 7. Then the state should become 'stale'

it 'becomes stale if not cancelled', sxl: '>=1.1' do |example|
Validator::Site.connected do |task,supervisor,site|
timeout = Validator.get_config('timeouts','priority_completion')
component = Validator.get_config('main_component')
signal_group_id = Validator.get_config('components','signal_group').keys.first
prio = Validator::StatusHelpers::SignalPriorityRequestHelper.new(
site,
component: component,
signal_group_id: signal_group_id,
timeout: timeout,
task: task
)

prio.run do
log "Before: Send unrelated signal priority request."
prio.request_unrelated

send_priority_request "Send an unrelated signal priority request before",
site: site, component: component
send_priority_request "Send our signal priority request",
site: site, component: component, id: request_id
send_priority_request "Send an unrelated signal priority request after",
site: site, component: component

# wait for collector to complete and check result
collect_task.wait
expect(result).to eq(:ok)
expect(collector.messages).to be_an(Array)
expect(collector.messages.size).to eq(num)
expect(states).to eq(sequence), "Expected state sequence #{sequence}, got #{states}"
ensure
# unsubcribe
unsubscribe_list = status_list.map { |item| item.slice('sCI','n') }
site.unsubscribe_to_status component, unsubscribe_list
log "Send signal priority request, wait for reception."
prio.request

log "After: Send unrelated signal priority request."
prio.request_unrelated

prio.expect :received
log "Signal priority request was received, wait for activation."

prio.expect :activated
log "Signal priority request was activated, wait for it to become stale."


# don't cancel request, it should then become stale by itself
prio.expect :stale
log "Signal priority request became stale."
end
end
end

end
end
4 changes: 3 additions & 1 deletion spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@
require_relative 'support/test_supervisor'
require_relative 'support/command_helpers'
require_relative 'support/status_helpers'
require_relative 'support/sequence_helper'
require_relative 'support/signal_group_sequence_helper'
require_relative 'support/signal_priority_request_helper'
require_relative 'support/log_helpers'
require_relative 'support/handshake_helper'
require_relative 'support/formatters/report_stream.rb'
require_relative 'support/formatters/formatter_base.rb'
require_relative 'support/formatters/brief.rb'
require_relative 'support/formatters/details.rb'
require_relative 'support/formatters/list.rb'
require_relative 'support/formatters/steps.rb'

include RSpec
include Validator::Log
Expand Down
14 changes: 7 additions & 7 deletions spec/support/command_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ def set_functional_position status, timeout_minutes:0
securityCode: Validator.get_config('secrets','security_codes',2),
status: status,
timeout: timeout_minutes,
intersection: 0
intersection: 0,
}
send_command_and_confirm @task, command_list, "Switch to functional position #{status}"
end
Expand Down Expand Up @@ -216,7 +216,7 @@ def get_dynamic_bands plan, band
timeout: Validator.get_config('timeouts','status_update', default: 0)
}
collector = result[:collector]
collector.queries.first.got['s'].split(',').each do |item|
collector.matchers.first.got['s'].split(',').each do |item|
some_plan, some_band, value = *item.split('-')
return value.to_i if some_plan.to_i == plan.to_i && some_band.to_i == band.to_i
end
Expand Down Expand Up @@ -368,7 +368,7 @@ def with_alarm_activated task, site, alarm_code_id, initial_deactivation: true
collect_task = task.async do # run the collector in an async task
collector = RSMP::AlarmCollector.new( site,
num: 1,
query: {
matcher: {
'cId' => component_id,
'aCId' => alarm_code_id,
'aSp' => alarm_specialization,
Expand All @@ -386,7 +386,7 @@ def with_alarm_activated task, site, alarm_code_id, initial_deactivation: true
collect_task = task.async do # run the collector in an async task
collector = RSMP::AlarmCollector.new( site,
num: 1,
query: {
matcher: {
'cId' => component_id,
'aCId' => alarm_code_id,
'aSp' => /Issue/i,
Expand Down Expand Up @@ -493,7 +493,7 @@ def verify_startup_sequence &block
component = Validator.get_config('main_component')
timeout = Validator.get_config('timeouts','startup_sequence')
collector = RSMP::StatusCollector.new @site, status_list, timeout: timeout
sequencer = Validator::StatusHelpers::SequenceHelper.new Validator.get_config('startup_sequence')
sequencer = Validator::StatusHelpers::SignalGroupSequenceHelper.new Validator.get_config('startup_sequence')
states = nil

collector_task = @task.async do
Expand Down Expand Up @@ -575,7 +575,7 @@ def suspend_alarm site, task, cId:, aCId:, collect:
RSMP::AlarmCollector.new(site,
m_id: suspend.m_id,
num: 1,
query: {
matcher: {
'cId' => cId,
'aCI' => aCId,
'aSp' => 'Suspend',
Expand Down Expand Up @@ -603,7 +603,7 @@ def resume_alarm site, task, cId:, aCId:, collect:
RSMP::AlarmCollector.new(site,
m_id: resume.m_id,
num: 1,
query: {
matcher: {
'cId' => cId,
'aCI'=>aCId,
'aSp'=>'Suspend',
Expand Down
59 changes: 59 additions & 0 deletions spec/support/formatters/steps.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
require 'rspec/core/formatters/console_codes'

module Validator
class Steps < FormatterBase
RSpec::Core::Formatters.register self, :start, :dump_pending, :dump_failures, :close,
:dump_summary, :example_started, :example_passed, :example_failed, :example_pending,
:message, :warning, :step, :example_group_started, :example_group_finished

def start notification
@output << "\n"
end

def warning notification
@output << colorize(" Warning: #{notification.message}\n",:yellow)
end

def step notification
@output << colorize(" #{notification.message}\n",:cyan)
end

def message notification
@output << " #{notification.message}\n"
end

def example_pending notification
@output << colorize(" Pending\n\n", :pending)
end

def example_started notification
@output << colorize("\n#{notification.example.full_description}\n",:bold)
end

def example_passed notification # ExampleNotification
@output << colorize(" Passed\n\n",:success)
end

def example_failed notification
# RSpec::Core::Formatters::ExceptionPresenter is a private class which
# should not really be used by us, but the snippet extraction and backtrace
# processing seems rather cumbersome to reimplement
presenter = RSpec::Core::Formatters::ExceptionPresenter.new(notification.example.execution_result.exception, notification.example, :indentation => 0)

error = presenter.message_lines.map do |line|
colorize(" #{line}\n",:failure)
end.join
@output << error << "\n"

backtrace = presenter.formatted_backtrace.map do |line|
colorize(" # #{line}\n",:light_blue)
end.join
@output << backtrace << "\n"
end

def dump_pending notification
dump_sentinel_warnings
super notification
end
end
end
Loading

0 comments on commit 88e9933

Please sign in to comment.