~singpolyma/sgx-jmp

bff79b561f5a9b91348f1ed0b9b51cfe1bf78810 — Christopher Vollick 2 years ago 45c0721
Respond to Proper Cancel Stanza

Previously cancels would be treated as an error, but then would be
caught so that they could respond with receipt of the cancel later.

But, we weren't setting @iq in these cases, because it was an error, so
we would actually respond to the wrong stanza; specifically the one
before the cancel.

This was bad and wrong and led to the bot sitting there waiting for the
cancel before moving on with its life.
4 files changed, 71 insertions(+), 16 deletions(-)

M lib/command.rb
A test/test_command.rb
M test/test_helper.rb
M test/test_registration.rb
M lib/command.rb => lib/command.rb +4 -3
@@ 58,12 58,13 @@ class Command
		end

		def reply(stanza=nil)
			stanza ||= iq.reply.tap { |reply|
				reply.status = :executing
			}
			stanza ||= iq.reply.tap { |reply| reply.status = :executing }
			yield stanza if block_given?
			COMMAND_MANAGER.write(stanza).then { |new_iq|
				@iq = new_iq
			}.catch_only(Blather::Stanza::Iq) { |new_iq|
				@iq = new_iq if new_iq.set?
				EMPromise.reject(new_iq)
			}.catch_only(SessionManager::Timeout) do
				EMPromise.reject(Timeout.new)
			end

A test/test_command.rb => test/test_command.rb +54 -0
@@ 0,0 1,54 @@
# frozen_string_literal: true

require "test_helper"
require "command"

Command::COMMAND_MANAGER = Minitest::Mock.new

class CommandTest < Minitest::Test
	def test_cancel_finishes
		blather = Minitest::Mock.new
		iq1 = Blather::Stanza::Iq::Command.new
		iq1.from = "test@example.com"
		iq1.id = "test-id"
		iq1.sessionid = "session-id"

		# The library digests the sessionID I give it...
		session = iq1.sessionid

		iq2 = Blather::Stanza::Iq::Command.new
		iq2.from = "test@example.com"
		iq2.id = "cancel-id"
		iq2.sessionid = "session-id"
		iq2.action = :cancel

		Command::COMMAND_MANAGER.expect(
			:write,
			EMPromise.reject(iq2),
			[Matching.new do |iq|
				assert_equal "test-id", iq.id
				assert_equal session, iq.sessionid
			end]
		)

		blather.expect(
			:<<,
			nil,
			[Matching.new do |iq|
				assert "canceled", iq.status
				assert_equal "cancel-id", iq.id
				assert_equal session, iq.sessionid
			end]
		)

		execute_command(iq1, blather: blather) { |cmd|
			cmd.reply.then do
				raise "Should have cancelled"
			end
		}.then do
			assert_mock blather
			assert_mock Command::COMMAND_MANAGER
		end
	end
	em :test_cancel_finishes
end

M test/test_helper.rb => test/test_helper.rb +13 -0
@@ 118,6 118,19 @@ BLATHER = Class.new {
	def <<(*); end
}.new.freeze

def execute_command(
	iq=Blather::Stanza::Iq::Command.new.tap { |i| i.from = "test@example.com" },
	blather: BLATHER,
	&blk
)
	Command::Execution.new(
		Minitest::Mock.new,
		blather,
		:to_s.to_proc,
		iq
	).execute(&blk).sync
end

class Matching
	def initialize(&block)
		@block = block

M test/test_registration.rb => test/test_registration.rb +0 -13
@@ 4,19 4,6 @@ require "test_helper"
require "customer"
require "registration"

def execute_command(
	iq=Blather::Stanza::Iq::Command.new.tap { |i| i.from = "test@example.com" },
	blather: BLATHER,
	&blk
)
	Command::Execution.new(
		Minitest::Mock.new,
		blather,
		:to_s.to_proc,
		iq
	).execute(&blk).sync
end

class RegistrationTest < Minitest::Test
	def test_for_registered
		sgx = OpenStruct.new(