def test_get_inbound_phone_entry__one_phone_number_multiple_contacts_on__session_no_contact(
            self):
        """Fall back to lenient query if we can't find the contact returned by the sticky session"""
        channel = SMSChannel(self.domain2_backend.couch_id, self.phone_number)
        info = RunningSessionInfo(None, "fake-owner-missing")
        XFormsSessionSynchronization._set_running_session_info_for_channel(
            channel, info, 60)
        self.addCleanup(
            XFormsSessionSynchronization.
            _release_running_session_info_for_channel, info, channel)
        phone_number, has_domain_two_way_scope = self._get_inbound_phone_entry__backend_domain_2(
        )

        self.assertEqual(phone_number.owner_id, "fake-owner-3")
        self.assertTrue(has_domain_two_way_scope)
        self.assertTrue(
            self.domain2_backend.domain_is_authorized(phone_number.domain))
    def test_get_inbound_phone_entry__one_phone_number_multiple_contacts_on__with_session(
            self):
        """Should return the phone number of the contact associated with the session"""
        channel = SMSChannel(self.domain2_backend.couch_id, self.phone_number)
        info = RunningSessionInfo(uuid.uuid4().hex, "fake-owner-4")
        XFormsSessionSynchronization._set_running_session_info_for_channel(
            channel, info, 60)
        self.addCleanup(
            XFormsSessionSynchronization.
            _release_running_session_info_for_channel, info, channel)
        phone_number, has_domain_two_way_scope = self._get_inbound_phone_entry__backend_domain_2(
        )

        self.assertEqual(phone_number.owner_id, "fake-owner-4")
        self.assertTrue(has_domain_two_way_scope)
        self.assertTrue(
            self.domain2_backend.domain_is_authorized(phone_number.domain))
    def test_get_inbound_phone_entry__one_phone_number_multiple_contacts_on__session_different_domain(
            self):
        """Phone number returned belongs to a domain which does not have access to this backend.
        TODO: This should probably be an error or it should fall back to 'lenient' query"""
        channel = SMSChannel(self.domain2_backend.couch_id, self.phone_number)
        info = RunningSessionInfo(uuid.uuid4().hex, "fake-owner-2")
        XFormsSessionSynchronization._set_running_session_info_for_channel(
            channel, info, 60)
        self.addCleanup(
            XFormsSessionSynchronization.
            _release_running_session_info_for_channel, info, channel)
        phone_number, has_domain_two_way_scope = self._get_inbound_phone_entry__backend_domain_2(
        )

        self.assertEqual(phone_number.owner_id, "fake-owner-2")
        self.assertTrue(has_domain_two_way_scope)
        self.assertFalse(
            self.domain2_backend.domain_is_authorized(
                phone_number.domain))  # bad
def test_auto_clear_stale_session_on_claim():
    phone_number_a = _clean_up_number('15555555555')
    session_a_1 = FakeSession(session_id=str(uuid4()),
                              phone_number=phone_number_a,
                              connection_id='Alpha')
    session_a_2 = FakeSession(session_id=str(uuid4()),
                              phone_number=phone_number_a,
                              connection_id='Beta')

    # Nothing set yet, so it can be claimed
    assert XFormsSessionSynchronization.channel_is_available_for_session(
        session_a_1)
    # And so can the other one
    assert XFormsSessionSynchronization.channel_is_available_for_session(
        session_a_2)
    # Claim succeeds
    assert XFormsSessionSynchronization.claim_channel_for_session(session_a_1)
    # Claim for same channel fails
    assert not XFormsSessionSynchronization.channel_is_available_for_session(
        session_a_2)
    assert not XFormsSessionSynchronization.claim_channel_for_session(
        session_a_2)
    # Set the current active session to closed manually, leaving a dangling/stale session claim
    session_a_1.session_is_open = False
    # Channel is now available
    assert XFormsSessionSynchronization.channel_is_available_for_session(
        session_a_2)
    # And the call above cleared the channel claim but left the contact
    assert (XFormsSessionSynchronization.get_running_session_info_for_channel(
        session_a_2.get_channel()) == RunningSessionInfo(session_id=None,
                                                         contact_id='Alpha'))
    # Claim for the channel now succeeds
    assert XFormsSessionSynchronization.claim_channel_for_session(session_a_2)
    # And it is now the active session for the channel
    assert (XFormsSessionSynchronization.get_running_session_info_for_channel(
        session_a_2.get_channel()).session_id == session_a_2.session_id)
def test_pickle_roundtrip():
    assert pickle.loads(pickle.dumps(SMSChannel('abc', '123'))) == SMSChannel(
        'abc', '123')
    assert pickle.loads(pickle.dumps(RunningSessionInfo(
        'xxx', 'yyy'))) == RunningSessionInfo('xxx', 'yyy')
def _clean_up_number(phone_number):
    XFormsSessionSynchronization._set_running_session_info_for_channel(
        SMSChannel(BACKEND_ID, phone_number),
        RunningSessionInfo(None, None),
        expiry=10)
    return phone_number