Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

M0022 cancellation #408

Merged
merged 3 commits into from
Aug 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading