예제 #1
0
def test_mark_delete_valid(rescue_sop_fx: Rescue, reporter: str, reason: str):
    """
    Verifies Rescue.mark functions as expected when marking a case for deletion
    """

    rescue_sop_fx.mark_delete(reporter, reason)

    assert rescue_sop_fx.marked_for_deletion.marked
    assert reporter == rescue_sop_fx.marked_for_deletion.reporter
    assert reason == rescue_sop_fx.marked_for_deletion.reason
예제 #2
0
def test_mark_for_deletion_unset(rescue_sop_fx: Rescue):
    """
    Verify unmarking a case that was MD'ed works as expected
    """
    rescue_sop_fx.marked_for_deletion = MarkForDeletion(
        True, "unit_test[BOT]", "unit test reasons!")

    rescue_sop_fx.unmark_delete()
    assert rescue_sop_fx.marked_for_deletion.marked is False
    assert rescue_sop_fx.marked_for_deletion.reporter is None
    assert rescue_sop_fx.marked_for_deletion.reason is None
예제 #3
0
def rescue_sop_fx(request) -> Rescue:
    """
    A Rescue fixture providing Rescue objects for the 3 supported platforms

    Args:
        request (): Provided by fixture Parametrization

    Returns:
        Rescue : Rescue objects
    """
    params = request.param
    myRescue = Rescue(uuid4(), client=params[0], system=params[2], irc_nickname=params[0],
                      board_index=params[3])
    myRescue.platform = params[1]
    return myRescue
예제 #4
0
    def append(self, rescue: Rescue, overwrite: bool = False) -> None:
        """
        Accept a Rescue object and attach it to the board

        Args:
            rescue (Rescue): Rescue object to attach
            overwrite(bool) : **overwrite** existing keys, if necessary.
                requires `rescue` to have a `board_index` set, otherwise it does nothing.

        Returns:
            None

        Raises:
            IndexNotFreeError: Attempt to write a rescue to a key that is already set.
        """
        # if the rescue already has a board index defined
        if rescue.board_index is not None:
            # check if the board index is not in use, or the overwrite flag is set
            if overwrite or rescue.board_index not in self.rescues:
                # write the key,value
                self.rescues[rescue.board_index] = rescue
            else:
                raise IndexNotFreeError(
                    f"Index {rescue.board_index} is in use. If you want to overwrite this you must"
                    f"set the `overwrite` flag.")

        # we need to give it one
        else:
            rescue.board_index = self.next_free_index()
            self.rescues[rescue.board_index] = rescue
예제 #5
0
 def test_rescue_creation_with_overwrite(self):
     """
     Verifies a rescue can be added as to overwrite an existing entry.
     """
     self.board.append(rescue=self.some_rescue)
     my_rescue = Rescue(uuid4(), "foo", "bar", "foo", board_index=-42)
     self.board.append(rescue=my_rescue, overwrite=True)
     self.assertEqual(self.board.rescues[-42], my_rescue)
예제 #6
0
def test_set_unidentified_rats_garbage_in_list(rescue_plain_fx: Rescue):
    """
    Verifies a ValueError is raised if the list passed to Rat.unidentified_Rats contains
    illegal values
    """
    garbage = [12, -42.2, None]
    with pytest.raises(ValueError):
        rescue_plain_fx.unidentified_rats = garbage
예제 #7
0
def rescue_plain_fx() -> Rescue:
    """
    A plain initialized Rescue without parametrization

    Returns:
        Rescue : Plain initialized Rescue
    """
    return Rescue(uuid4(), "UNIT_TEST", "ki", "UNIT_TEST", board_index=42)
예제 #8
0
def test_lang_id_garbage(garbage, rescue_plain_fx: Rescue):
    """
    Verifies throwing garbage types at Rescue.lang_id results in a TypeError
    Args:
        garbage (): Garbage to throw
        rescue_plain_fx (Rescue): Plain rescue Fixture
    """
    with pytest.raises(TypeError):
        rescue_plain_fx.lang_id = garbage
예제 #9
0
def test_irc_nickname_garbage(garbage, rescue_plain_fx: Rescue):
    """
    Verifies throwing garbage types at Rescue.irc_nickname results in a TypeError

       Args:
            garbage (): Garbage to throw
            rescue_plain_fx (Rescue): Plain rescue Fixture
    """
    with pytest.raises(TypeError):
        rescue_plain_fx.irc_nickname = garbage
예제 #10
0
 def test_search_garbage_raises_exception(self, test_input,
                                          rat_board_fx: RatBoard,
                                          rescue_plain_fx: Rescue):
     rescue_plain_fx.uuid = UUID('12345678-9876-53d1-ea5e-0000deadbeef')
     rat_board_fx.append(rescue_plain_fx)
     with pytest.raises((
             TypeError,
             ValueError,
     )):
         rat_board_fx.search(test_input)
예제 #11
0
def test_rescue_board_index(rescue_plain_fx):
    """
    Verifies board index is NOT set without a rescue attached
    """
    # Do not set board index
    test_rescue = Rescue(uuid4(), 'Test_Client', 'AliothJr', 'TestClient')
    assert test_rescue.board_index is None

    # Add rescue fixture
    test_rescue = rescue_plain_fx
    assert test_rescue.board_index == 42

    # Add a negative int for board index, ensuring ValueError is thrown
    with pytest.raises(ValueError):
        test_rescue.board_index = -99

    # Add incorrect type, ensuring TypeError is thrown
    with pytest.raises(TypeError):
        test_rescue.board_index = 'Index!'
예제 #12
0
 def setUp(self):
     """
     Set up for each test
     """
     super().setUp()
     self.board = RatBoard()
     self.some_rescue = Rescue(uuid4(),
                               "unit_test[BOT]",
                               "snafu",
                               "unit_test",
                               board_index=-42)
예제 #13
0
def test_irc_nickname_strings(test_input, rescue_plain_fx: Rescue):
    """
    Verifies the irc nickname can be set when passed a string

        Args:
            test_input (str): values to test
            rescue_plain_fx (Rescue): Rescue fixture

    """

    rescue_plain_fx.irc_nickname = test_input
    assert rescue_plain_fx.irc_nickname == test_input
예제 #14
0
def test_lang_id_strings(test_input, rescue_plain_fx: Rescue):
    """
    Verifies the lang id can be set when passed a string

        Args:
            test_input (str): values to test
            rescue_plain_fx (Rescue): Rescue fixture

    """

    rescue_plain_fx.lang_id = test_input
    assert rescue_plain_fx.lang_id == test_input
예제 #15
0
    def test_rescue_Creation_without_index(self):
        """
        Verifies a Rescue can be added without a defined index.
            the board should give our rescue one.
        """
        guid = uuid4()
        name = "SicklyTadPole"
        my_rescue = Rescue(guid, name, "NLTT 48288", name)

        self.board.append(my_rescue)

        found = self.board.find_by_uuid(guid)
        self.assertIsNotNone(found)
        self.assertEqual(found.client, name)
예제 #16
0
    def test_contains_existing_by_uuid(self):
        """
        Verifies `RatBoard.__contains__` returns true when the a case with the same api UUID
        is known and tracked by the board

        Notes:
            This branch should only verify a rescue exists *with the same uuid*,
            it should do no further checks.
        """
        # add a case
        self.board.append(self.some_rescue)
        # make our assertion
        self.assertTrue(
            # spawn a case with the same uuid, and make our check
            Rescue(self.some_rescue.uuid, "nope", "i have no idea!", "nope") in
            self.board)
예제 #17
0
def test_epic_rescue_attached(epic_fx):
    """
    Verifies attached epic object referenced by rescue is the same object, and
    that only one rescue has been added.
    """
    # Create local rescue object
    test_rescue = Rescue(uuid4(),
                         'TestClient',
                         'Alioth',
                         'Test_Client',
                         epic=[epic_fx])

    # One rescue added, the List should return only ONE Epic.
    assert len(test_rescue.epic) == 1

    # Check that the epic object in list is epic_fx
    assert test_rescue.epic[0] is epic_fx
예제 #18
0
    def test_contains_by_key_attributes(self, rescue_sop_fx: Rescue,
                                        rat_board_fx: RatBoard):
        """
        Verifies `Ratboard.__contains__` returns true when looking for a case by
            key attributes only

        Args:
            rescue_sop_fx (Rescue): rescue fixture
            rat_board_fx (RatBoard): RatBoard fixture
        """
        # add our rescue to the board
        rat_board_fx.append(rescue=rescue_sop_fx)

        # overwrite our local rescue objects id
        rescue_sop_fx._api_id = None

        assert rescue_sop_fx in rat_board_fx
예제 #19
0
def test_mark_delete_invalid(rescue_sop_fx: Rescue):
    """
    Verify what happens when garbage gets thrown at `rescue.mark`
    """
    with pytest.raises(TypeError):
        rescue_sop_fx.mark_delete(None, "sna")

        with pytest.raises(TypeError):
            rescue_sop_fx.mark_delete("sna", None)

        with pytest.raises(ValueError):
            rescue_sop_fx.mark_delete("unit_test", "")
예제 #20
0
def test_set_unidentified_rats_incorrect_type(rescue_plain_fx: Rescue):
    """
    Verifies a TypeError is raised if another type other than list is passed.
    """
    with pytest.raises(TypeError):
        rescue_plain_fx.unidentified_rats = 'Snozzberry, Wonka, Doc'
예제 #21
0
 def test_search_garbage_returns_none(self, test_input,
                                      rat_board_fx: RatBoard,
                                      rescue_plain_fx: Rescue):
     rescue_plain_fx.uuid = UUID('12345678-9876-53d1-ea5e-0000deadbeef')
     rat_board_fx.append(rescue_plain_fx)
     assert rat_board_fx.search(test_input) is None
예제 #22
0
 def test_search_valid(self, test_input, rat_board_fx: RatBoard,
                       rescue_plain_fx: Rescue):
     rescue_plain_fx.uuid = UUID('12345678-9876-53d1-ea5e-0000deadbeef')
     rat_board_fx.append(rescue_plain_fx)
     assert rat_board_fx.search(test_input) == rescue_plain_fx
예제 #23
0
def test_rescue_defaults():
    """
    Verifies a Rescue can be initialized with all defaults
    """

    Rescue()
예제 #24
0
async def handle_ratmama_announcement(ctx: Context) -> None:
    """
    Handles the Announcement made by RatMama.
    Details are extracted, wrapped in a Rescue object and appended to the Rescue board.
    An appropriate answer will be sent to IRC.

    Args:
        ctx: Context of the announcement

    Returns: None

    """

    if ctx.user.nickname.casefold() not in (
            k.casefold()
            for k in config.config["ratsignal_parser"]["announcer_nicks"]):
        return

    message: str = ctx.words_eol[0]
    result = re.fullmatch(ratmama_regex, message)
    client_name: str = result.group("cmdr")
    system_name: str = result.group("system")
    platform_name: str = result.group("platform")
    o2_status: bool = result.group("o2") == "OK"  # false is CR
    lang_code: str = result.group("language_code")
    nickname: Optional[str] = result.group("nick")

    exist_rescue: Optional[Rescue] = ctx.bot.board.find_by_name(client_name)

    if exist_rescue:
        # we got a case already!
        await ctx.reply(
            f"{client_name} has reconnected! Case #{exist_rescue.board_index}")
        # now let's make it more visible if stuff changed
        diff_response = ""
        if system_name.casefold() != exist_rescue.system.casefold():
            diff_response += f"System changed! "

        if platform_name.casefold() != exist_rescue.platform.name.casefold():
            diff_response += "Platform changed! "

        if not o2_status != exist_rescue.code_red:
            diff_response += "O2 Status changed!" if o2_status else\
                "O2 Status changed, it is now CODE RED!"

        if diff_response:
            await ctx.reply(diff_response)

    else:
        platform = None

        if platform_name.casefold() in ("pc", "ps", "xb"):
            platform = Platforms[platform_name.upper()]
        else:
            LOG.warning(
                f"Got unknown platform from {ctx.user.nickname}: {platform_name}"
            )

        # no case for that name, we have to make our own
        rescue: Rescue = Rescue(client=client_name,
                                system=system_name,
                                irc_nickname=nickname,
                                code_red=not o2_status,
                                lang_id=lang_code,
                                platform=platform)

        ctx.bot.board.append(rescue, overwrite=False)
        index = ctx.bot.board.find_by_name(client=client_name).board_index
        await ctx.reply(
            f"RATSIGNAL - CMDR {client_name} - "
            f"Reported System: {system_name} (distance to be implemented) - "
            f"Platform: {platform_name} - "
            f"O2: {'OK' if o2_status else 'NOT OK'} - "
            f"Language: {result.group('full_language')}"
            f" (Case #{index}) ({platform_name.upper()}_SIGNAL)")
예제 #25
0
async def handle_ratsignal(ctx: Context) -> None:
    """
     Tries to extract as much details as possible from a self-issued ratsignal and appends
      these details to the rescue board.
    Should it be unable to extract the details, it will open a case and ask for the details
      to be set and will only set the name and nick fields of the rescue.

    Args:
        ctx: Context of the self-issued ratsignal

    Returns: None

    """

    message: str = ctx.words_eol[0]
    # the ratsignal is nothing we are interested anymore
    message = re.sub("ratsignal", "", message, flags=re.I)

    for rescue in ctx.bot.board.rescues.values():
        if rescue.irc_nickname.casefold() == ctx.user.nickname.casefold():
            await ctx.reply(
                "You already sent a signal, please be patient while a dispatch is underway."
            )
            return

    sep: Optional[str] = None
    if ',' in message:
        sep = ','
    elif ';' in message:
        sep = ';'
    elif '|' in message:
        sep = '|'
    elif '-' in message:
        sep = '-'

    if not sep:
        ctx.bot.board.append(
            Rescue(irc_nickname=ctx.user.nickname, client=ctx.user.nickname))
        index = ctx.bot.board.find_by_name(ctx.user.nickname)
        await ctx.reply(
            f"Case #{index} created for {ctx.user.nickname}, please set details"
        )
        return
    system: str = None
    cr: bool = False
    platform: Platforms = None
    for part in message.split(sep):
        part = part.strip()
        if part.casefold() in ("pc", ):
            platform = Platforms["PC"]

        elif part.casefold() in ("ps", "ps4", "playstation", "playstation4",
                                 "playstation 4"):
            platform = Platforms["PS"]

        elif part.casefold() in ("xb", "xb1", "xbox", "xboxone", "xbox one"):
            platform = Platforms["XB"]

        elif "o2" in part.casefold():
            cr = "o2 ok" not in part.casefold()

        else:
            system = part

    rescue = Rescue(client=ctx.user.nickname,
                    system=system,
                    irc_nickname=ctx.user.nickname,
                    code_red=cr,
                    platform=platform)
    ctx.bot.board.append(rescue)
    await ctx.reply(f"Case created for {ctx.user.nickname}"
                    f" on {platform.name} in {system}. "
                    f"{'O2 status is okay' if not cr else 'This is a CR!'} "
                    f"- {platform.name.upper()}_SIGNAL")