Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
emiltin committed Aug 9, 2024
1 parent 225259f commit 99a3422
Show file tree
Hide file tree
Showing 2 changed files with 256 additions and 77 deletions.
170 changes: 93 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,108 @@
end
end

# Validate that signal priority status are send when priorty is requested
# Validate that a signal priority becomes completed 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 'state reaches completed', sxl: '>=1.1' do |example|
Validator::Site.connected do |task,supervisor,site|

sequence = ['received','activated','completed']
# subscribe
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
timeout = Validator.get_config('timeouts','priority_completion'),

prio = Validator::StatusHelpers::PriorityHelper.new(site: site, component: component)

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
prio_options = {
signalGroupId: signal_group,
level: 7,
eta: 2,
vehicleType: 'car'
}

prio.validate_sequence do |state|
case state
when nil:
log "Send an unrelated signal priority request before"
prio.request_unrelated prio_options
log "Send signal priority request, wait for reception."
prio.request prio_options
log "Send an unrelated signal priority request after"
prio.request_unrelated prio_options
prio.next 'received', timeout: timeout

when 'received':
log "Signal priority request was received, wait for activation."
prio.next 'activated', timeout: timeout

when 'acticated':
log "Signal priority request was activated, now cancel it and wait for completion."
prio.cancel
prio.next 'completed', timeout: timeout

when 'completed':
log "Signal priority request was completed."
prio.done
end
end
end

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
# Validate that a signal priority became stale if we do not cancel it.
#
# 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. And the request state should become 'activated'
# 7. Then the state should become 'stale'

it 'state becomes stale', sxl: '>=1.1' do |example|
Validator::Site.connected do |task,supervisor,site|
sequence = ['received','activated','completed']
timeout = Validator.get_config('timeouts','priority_completion'),
component = Validator.get_config('main_component')
signal_group = Validator.get_config('components','signal_group').keys.first

prio = Validator::StatusHelpers::PriorityHelper.new(site: site, component: component)

prio_options = {
signalGroupId: signal_group,
level: 7,
eta: 2,
vehicleType: 'car'
}

prio.validate_sequence do |state|
case state
when nil:
log "Send an unrelated signal priority request before"
prio.request_unrelated prio_options
log "Send signal priority request, wait for reception."
prio.request prio_options
log "Send an unrelated signal priority request after"
prio.request_unrelated prio_options
prio.next 'received', timeout: timeout

when 'received':
log "Signal priority request was received, wait for activation."
prio.next 'activated', timeout: timeout

when 'acticated':
log "Signal priority request was activated, wait for it to become stale."
prio.next 'completed', timeout: timeout

when 'stale':
log "Signal priority request became stale."
prio.done
end
end
end

end
end
163 changes: 163 additions & 0 deletions spec/support/priority_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@

module RSMP
class Sequencer < Listener

def initialize notifier:, component:, filter:, task:, timeout:
@notifier = notifier
@filter = filter
@task = task || notifier.task
@condition = Async::Notification.new
@timeout = timeout
@state = nil
reset
end

def reset
@next = nil
@messages = []
@done = false
end

# Waits for message and passes each message accept by the filter
# to the block.
# The block can do any validation of the
#
#
def validate &block
reset
@notifier.add_listener self
until @done
yield wait_for_message
end
ensure
@notifier.remove_listener self
end

def wait_for_message
if @messages.empty?
@task.with_timeout(@timeout) { @condition.wait }
end
@messages.shift
rescue Async::TimeoutError
@error = RSMP::TimeoutError
end

def notify message
if @filter.accept? messages
@messages.push messages
@condition.notifify
end
end
end

def done
@done = true
end
end


module Validator::StatusHelpers
class SignalPriorityHelper < RSMP::Listener

def request
end

def request_unrelated
end

def next state
@next = state
end

def done
@done = true
end

private

def send_priority_request id: nil, type: 'new'
command_list = build_command_list :M0022, :requestPriority, {
requestId: (id || SecureRandom.uuid()[0..3]),
signalGroupId: signal_group,
type: type,
level: 7,
eta: 2,
vehicleType: 'car'
}
site.send_command component, command_list
end

# look through a status message to find state
# updates for a specific priority request
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
end
end




# @request_id = SecureRandom.uuid()[0..3]


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
)


result = collector.collect do |message|
state = search_for_request_state request_id, message, states
next unless state
states << state
:keep
end
end

# helper to send priority request


#send unrelated requests before and our request, to check that it does not interfere
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
end

0 comments on commit 99a3422

Please sign in to comment.