From bdb43025214f29562be4b9ffdbb50d61b066acf6 Mon Sep 17 00:00:00 2001 From: DAVID Axel <axel.david@etu.univ-amu.fr> Date: Sun, 7 May 2023 09:56:23 +0200 Subject: [PATCH] feat: :recycle: Add helper convert_key function --- src/vigenere_api/models/__init__.py | 3 +- src/vigenere_api/models/helpers/__init__.py | 6 +- src/vigenere_api/models/helpers/helper.py | 45 +++ .../models/helpers/vigenere_key.py | 98 +++++ src/vigenere_api/models/vigenere.py | 221 +++++++++++ tests/models/test_helper.py | 120 ++++-- tests/models/test_vigenere.py | 373 ++++++++++++++++++ tests/models/test_vigenere_key.py | 89 +++++ 8 files changed, 910 insertions(+), 45 deletions(-) create mode 100644 src/vigenere_api/models/helpers/vigenere_key.py create mode 100644 src/vigenere_api/models/vigenere.py create mode 100644 tests/models/test_vigenere.py create mode 100644 tests/models/test_vigenere_key.py diff --git a/src/vigenere_api/models/__init__.py b/src/vigenere_api/models/__init__.py index c346974..e777b0f 100644 --- a/src/vigenere_api/models/__init__.py +++ b/src/vigenere_api/models/__init__.py @@ -17,6 +17,7 @@ """All models used by VigenereAPI.""" from .caesar import CaesarData +from .vigenere import VigenereData -__all__ = ["CaesarData"] +__all__ = ["CaesarData", "VigenereData"] diff --git a/src/vigenere_api/models/helpers/__init__.py b/src/vigenere_api/models/helpers/__init__.py index eb8d6ae..35481ef 100644 --- a/src/vigenere_api/models/helpers/__init__.py +++ b/src/vigenere_api/models/helpers/__init__.py @@ -16,7 +16,7 @@ """Helper package for models.""" -from .helper import move_char +from .helper import convert_key, move_char +from .vigenere_key import VigenereKey - -__all__ = ["move_char"] +__all__ = ["move_char", "convert_key", "VigenereKey"] diff --git a/src/vigenere_api/models/helpers/helper.py b/src/vigenere_api/models/helpers/helper.py index 0a5c41f..a91e933 100644 --- a/src/vigenere_api/models/helpers/helper.py +++ b/src/vigenere_api/models/helpers/helper.py @@ -19,12 +19,17 @@ from typing import Literal from .errors import ( + BadKeyError, + EmptyKeyError, + ExpectedKeyType, HelperBadCharValueError, HelperBadFirstLetterValueError, HelperBadLengthCharValueError, HelperCharTypeError, HelperFirstLetterTypeError, HelperKeyTypeError, + KeyTypeError, + TooLongKeyError, ) @@ -80,3 +85,43 @@ def move_char(char: str, key: int, first_letter: Literal["a", "A"]) -> str: raise HelperBadFirstLetterValueError(first_letter) return chr((ord(char) - ord(first_letter) + key) % 26 + ord(first_letter)) + + +def convert_key(key: str) -> int: + """ + Convert the one character string into an integer between 0 and 25. + + Parameters + ---------- + key : str + The key to convert. + + Raises + ------ + KeyTypeError + Thrown if 'key' is not a string. + EmptyKeyError + Thrown if 'key' is an empty string. + TooLongKeyError + Thrown if 'key' is too long. + BadKeyError + Thrown if 'key' is not a one alphabetical character. + + Returns + ------- + key_converted + int + """ + if not isinstance(key, str): + raise KeyTypeError(key, ExpectedKeyType.STRING) + + if len(key) == 0: + raise EmptyKeyError + + if len(key) > 1: + raise TooLongKeyError + + if not key.isalpha(): + raise BadKeyError(key, ExpectedKeyType.STRING) + + return ord(key) - ord("A") if key.isupper() else ord(key) - ord("a") diff --git a/src/vigenere_api/models/helpers/vigenere_key.py b/src/vigenere_api/models/helpers/vigenere_key.py new file mode 100644 index 0000000..db5f46b --- /dev/null +++ b/src/vigenere_api/models/helpers/vigenere_key.py @@ -0,0 +1,98 @@ +# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# Vigenere-API + +# Copyright (C) 2023 Axel DAVID + +# + +# This program is free software: you can redistribute it and/or modify it under + +# the terms of the GNU General Public License as published by the Free Software + +# Foundation, either version 3 of the License, or (at your option) any later version. + +# + +# This program is distributed in the hope that it will be useful, but WITHOUT ANY + +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +# + +# You should have received a copy of the GNU General Public License along with + +# this program. If not, see <https://www.gnu.org/licenses/>. + +# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +"""Utils class for VigenereData.""" + +from typing import final, Final + +from .errors import ( + BadKeyError, + EmptyKeyError, + ExpectedKeyType, + KeyTypeError, + TooShortKeyError, +) + + +@final +class VigenereKey: + """Util class to loop on each character of the key.""" + + def __init__(self, key: str) -> None: + """ + Create a new Vigenere key. + + Parameters + ---------- + key : str + The string used like a key. + + Raises + ------ + KeyTypeError + Thrown if 'key' is not a string. + EmptyKeyError + Thrown if 'key' is empty. + TooShortKeyError + Thrown if 'key' is too short. + BadKeyError + Thrown if 'key' contains invalid characters. + """ + + if not isinstance(key, str): + raise KeyTypeError(key, ExpectedKeyType.STRING) + + if len(key) == 0: + raise EmptyKeyError + + if len(key) == 1: + raise TooShortKeyError + + if not key.isalpha(): + raise BadKeyError(key, ExpectedKeyType.STRING) + + self.__index = 0 + self.__key: Final = key + + def __next__(self) -> str: + """ + Get the next character of the key. + + Returns + ------- + The next character of the key. + str + """ + try: + return self.__key[self.__index] + finally: + self.__increase_index() + + def __increase_index(self) -> None: + """Increase the index of the key.""" + self.__index += 1 + self.__index %= len(self) + + def __len__(self) -> int: + """ + Get the length of the key. + + Returns + ------- + int + The length of the key. + """ + return len(self.__key) diff --git a/src/vigenere_api/models/vigenere.py b/src/vigenere_api/models/vigenere.py new file mode 100644 index 0000000..17ca2aa --- /dev/null +++ b/src/vigenere_api/models/vigenere.py @@ -0,0 +1,221 @@ +# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# Vigenere-API + +# Copyright (C) 2023 Axel DAVID + +# + +# This program is free software: you can redistribute it and/or modify it under + +# the terms of the GNU General Public License as published by the Free Software + +# Foundation, either version 3 of the License, or (at your option) any later version. + +# + +# This program is distributed in the hope that it will be useful, but WITHOUT ANY + +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +# + +# You should have received a copy of the GNU General Public License along with + +# this program. If not, see <https://www.gnu.org/licenses/>. + +# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +"""Caesar model.""" + +from __future__ import annotations + +from enum import auto, unique +from typing import final + +from pydantic import StrictStr, validator + +from strenum import StrEnum +from vigenere_api.helpers import Model +from .errors import ( + AlgorithmExpectedKeyType, + AlgorithmKeyTypeError, + AlgorithmOperationTypeError, + AlgorithmTextTypeError, + ContentTypeError, + EmptyContentError, +) +from .helpers import convert_key, move_char, VigenereKey + + +@final +@unique +class VigenereOperation(StrEnum): + """All possible Vigenere operations.""" + + CIPHER = auto() + DECIPHER = auto() + + +@final +class VigenereData(Model): + """ + Vigenere data to cipher the content or decipher. + + Exemples + -------- + Basic example + + >>> from vigenere_api.models import VigenereData + + >>> vigenere_data = VigenereData(content="Hello World", key="test") + + >>> ciphered_data = vigenere_data.cipher() + >>> deciphered_data = vigenere_data.decipher() + + >>> assert vigenere_data == deciphered_data == "Hello World" + >>> assert vigenere_data.key == ciphered_data.key == deciphered_data.key == "test" + """ + + content: StrictStr + """The content to be ciphered or deciphered.""" + + key: StrictStr + """The key to cipher or decipher the content.""" + + def cipher(self) -> VigenereData: + """ + Cipher the content with the key. + + Returns + ------- + ciphered_data + VigenereData + """ + return VigenereData( + content=self.__algorithm( + self.content, + VigenereKey(self.key), + VigenereOperation.CIPHER, + ), + key=self.key, + ) + + def decipher(self) -> VigenereData: + """ + Decipher the content with the key. + + Returns + ------- + deciphered_data + VigenereData + """ + return VigenereData( + content=self.__algorithm( + self.content, + VigenereKey(self.key), + VigenereOperation.DECIPHER, + ), + key=self.key, + ) + + @staticmethod + def __algorithm(text: str, key: VigenereKey, operation: VigenereOperation) -> str: + """ + Apply the common algorithm for Vigenere. + + Parameters + ---------- + text : str + The text to apply the algorithm. + key : VigenereKey + The key used by the algorithm. + operation : VigenereOperation + The wanted operation. + + Raises + ------ + AlgorithmTextTypeError + Thrown if 'text' is not a string. + AlgorithmKeyTypeError + Thrown if 'key' is not a VigenereKey object. + AlgorithmOperationTypeError + Thrown if 'operation' is not a VigenereOperation object. + + Returns + ------- + converted_text + str + """ + if not isinstance(text, str): + raise AlgorithmTextTypeError(text) + + if not isinstance(key, VigenereKey): + raise AlgorithmKeyTypeError(key, AlgorithmExpectedKeyType.VIGENERE_KEY) + + if not isinstance(operation, VigenereOperation): + raise AlgorithmOperationTypeError(operation) + + result = "" + for char in text: + if char.isalpha(): + index_key = convert_key(next(key)) + if operation == VigenereOperation.DECIPHER: + index_key = -index_key + + if char.isupper(): + result += move_char(char, index_key, "A") + else: + result += move_char(char, index_key, "a") + else: + result += char + + return result + + @validator("content", pre=True) + def validate_content(cls, content: str) -> str: + """ + Check if the affectation to content respects contraints. + + Parameters + ---------- + content : str + The new content. + + Raises + ------ + ContentTypeError + Thrown if 'content' is not a string. + EmptyContentError + Thrown if 'content' is an empty string. + + Returns + ------- + content + str + """ + if not isinstance(content, str): + raise ContentTypeError(content) + + if len(content) == 0: + raise EmptyContentError + + return content + + @validator("key", pre=True) + def validate_key(cls, key: str) -> str: + """ + Check if the affectation to key respects contraints. + + Parameters + ---------- + key : str + The new key. + + Raises + ------ + KeyTypeError + Thrown if 'key' is not a string. + EmptyKeyError + Thrown if 'key' is an empty string. + TooShortKeyError + Thrown if 'key' is a string with a length of 1. + BadKeyError + Thrown if 'key' is not an alphabetic character. + + Returns + ------- + key + str + """ + _key_can_be_instantiate = VigenereKey(key) + + return key diff --git a/tests/models/test_helper.py b/tests/models/test_helper.py index d1f30f7..0b35705 100644 --- a/tests/models/test_helper.py +++ b/tests/models/test_helper.py @@ -18,54 +18,92 @@ import pytest -from vigenere_api.models.helpers import move_char +from vigenere_api.models.helpers import convert_key, move_char from vigenere_api.models.helpers.errors import ( + BadKeyError, + EmptyKeyError, HelperBadCharValueError, HelperBadFirstLetterValueError, HelperBadLengthCharValueError, HelperCharTypeError, HelperFirstLetterTypeError, HelperKeyTypeError, + KeyTypeError, + TooLongKeyError, ) -def test_move_lower_letter() -> None: - moved_letter = move_char("a", 2, "a") - - assert moved_letter == "c" - - -def test_move_upper_letter() -> None: - moved_letter = move_char("A", 2, "A") - - assert moved_letter == "C" - - -@pytest.mark.raises(exception=HelperCharTypeError) -def test_bad_type_char() -> None: - _ignored = move_char(b"r", 2, "a") - - -@pytest.mark.raises(exception=HelperBadLengthCharValueError) -def test_bad_length_char() -> None: - _ignored = move_char("rr", 2, "a") - - -@pytest.mark.raises(exception=HelperBadCharValueError) -def test_bad_alpha_char() -> None: - _ignored = move_char("+", 2, "a") - - -@pytest.mark.raises(exception=HelperKeyTypeError) -def test_bad_type_key() -> None: - _ignored = move_char("a", "v", "a") - - -@pytest.mark.raises(exception=HelperFirstLetterTypeError) -def test_bad_type_first_letter() -> None: - _ignored = move_char("a", 2, b"a") - - -@pytest.mark.raises(exception=HelperBadFirstLetterValueError) -def test_bad_first_letter_value() -> None: - _ignored = move_char("a", 2, "g") +class MoveCharSuite: + @staticmethod + def test_move_lower_letter() -> None: + moved_letter = move_char("a", 2, "a") + + assert moved_letter == "c" + + @staticmethod + def test_move_upper_letter() -> None: + moved_letter = move_char("A", 2, "A") + + assert moved_letter == "C" + + @staticmethod + @pytest.mark.raises(exception=HelperCharTypeError) + def test_bad_type_char() -> None: + _ignored = move_char(b"r", 2, "a") + + @staticmethod + @pytest.mark.raises(exception=HelperBadLengthCharValueError) + def test_bad_length_char() -> None: + _ignored = move_char("rr", 2, "a") + + @staticmethod + @pytest.mark.raises(exception=HelperBadCharValueError) + def test_bad_alpha_char() -> None: + _ignored = move_char("+", 2, "a") + + @staticmethod + @pytest.mark.raises(exception=HelperKeyTypeError) + def test_bad_type_key() -> None: + _ignored = move_char("a", "v", "a") + + @staticmethod + @pytest.mark.raises(exception=HelperFirstLetterTypeError) + def test_bad_type_first_letter() -> None: + _ignored = move_char("a", 2, b"a") + + @staticmethod + @pytest.mark.raises(exception=HelperBadFirstLetterValueError) + def test_bad_first_letter_value() -> None: + _ignored = move_char("a", 2, "g") + + +class ConvertKeySuite: + @staticmethod + def test_convert_lower_key() -> None: + lower_index = convert_key("a") + assert lower_index == 0 + + @staticmethod + def test_convert_upper_key() -> None: + upper_index = convert_key("A") + assert upper_index == 0 + + @staticmethod + @pytest.mark.raises(exception=KeyTypeError) + def test_bad_type_key() -> None: + _ignored = convert_key(b"ter") + + @staticmethod + @pytest.mark.raises(exception=BadKeyError) + def test_bad_key() -> None: + _ignored = convert_key("8") + + @staticmethod + @pytest.mark.raises(exception=EmptyKeyError) + def test_empty_key() -> None: + _ignored = convert_key("") + + @staticmethod + @pytest.mark.raises(exception=TooLongKeyError) + def test_too_long_key() -> None: + _ignored = convert_key("aa") diff --git a/tests/models/test_vigenere.py b/tests/models/test_vigenere.py new file mode 100644 index 0000000..059813f --- /dev/null +++ b/tests/models/test_vigenere.py @@ -0,0 +1,373 @@ +# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# Vigenere-API + +# Copyright (C) 2023 Axel DAVID + +# + +# This program is free software: you can redistribute it and/or modify it under + +# the terms of the GNU General Public License as published by the Free Software + +# Foundation, either version 3 of the License, or (at your option) any later version. + +# + +# This program is distributed in the hope that it will be useful, but WITHOUT ANY + +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +# + +# You should have received a copy of the GNU General Public License along with + +# this program. If not, see <https://www.gnu.org/licenses/>. + +# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +"""Vigenere model tests.""" + +import pytest +from pydantic import ValidationError + +from vigenere_api.models import VigenereData +from vigenere_api.models.errors import ( + AlgorithmKeyTypeError, + AlgorithmOperationTypeError, + AlgorithmTextTypeError, +) +from vigenere_api.models.vigenere import VigenereKey, VigenereOperation + + +class CtorSuite: + @staticmethod + def test_with_key() -> None: + text = "Test" + key = "zz" + data = VigenereData(content=text, key=key) + + assert data.content == text + assert data.key == key + + @staticmethod + @pytest.mark.raises(exception=ValidationError) + def test_missing_content() -> None: + key = "zz" + _ignored_data = VigenereData(key=key) + + @staticmethod + @pytest.mark.raises(exception=ValidationError) + def test_missing_key() -> None: + text = "z" + _ignored_data = VigenereData(content=text) + + @staticmethod + @pytest.mark.raises(exception=ValidationError) + def test_bad_type_content() -> None: + text = b"Test" + key = "zz" + _ignored_data = VigenereData(content=text, key=key) + + @staticmethod + @pytest.mark.raises(exception=ValidationError) + def test_bad_empty_content() -> None: + text = "" + key = "zz" + _ignored_data = VigenereData(content=text, key=key) + + @staticmethod + @pytest.mark.raises(exception=ValidationError) + def test_bad_type_key() -> None: + text = "Test" + key = b"z" + _ignored_data = VigenereData(content=text, key=key) + + @staticmethod + @pytest.mark.raises(exception=ValidationError) + def test_bad_empty_key() -> None: + text = "Test" + key = "" + _ignored_data = VigenereData(content=text, key=key) + + @staticmethod + @pytest.mark.raises(exception=ValidationError) + def test_too_short_key() -> None: + text = "Test" + key = "e" + _ignored_data = VigenereData(content=text, key=key) + + @staticmethod + @pytest.mark.raises(exception=ValidationError) + def test_bad_not_alpha_str_key() -> None: + text = "Test" + key = "$z" + _ignored_data = VigenereData(content=text, key=key) + + +class OperationSuite: + class CipherSuite: + class SimpleKeySuite: + @staticmethod + def test_with_str_lower_key() -> None: + text = "Test" + key = "bb" + data = VigenereData(content=text, key=key) + + assert data.content == text + assert data.key == key + + cipher = data.cipher() + + ciphered_text = "Uftu" + assert cipher.content == ciphered_text + assert cipher.key == key + + @staticmethod + def test_with_str_upper_key() -> None: + text = "Test" + key = "BB" + data = VigenereData(content=text, key=key) + + assert data.content == text + assert data.key == key + + cipher = data.cipher() + + ciphered_text = "Uftu" + assert cipher.content == ciphered_text + assert cipher.key == key + + @staticmethod + def test_with_str_mixed_key() -> None: + text = "Test" + key = "Bb" + data = VigenereData(content=text, key=key) + + assert data.content == text + assert data.key == key + + cipher = data.cipher() + + ciphered_text = "Uftu" + assert cipher.content == ciphered_text + assert cipher.key == key + + @staticmethod + def test_equality_between_keys() -> None: + text = "Test" + data1 = VigenereData(content=text, key="Bb") + data2 = VigenereData(content=text, key="bb") + data3 = VigenereData(content=text, key="BB") + + ciphered1 = data1.cipher() + ciphered2 = data2.cipher() + ciphered3 = data3.cipher() + + assert data1.content == data2.content == data3.content + assert ciphered1.content == ciphered2.content == ciphered3.content + + class ComplexKeySuite: + @staticmethod + def test_with_str_lower_key() -> None: + text = "Test" + key = "abcd" + data = VigenereData(content=text, key=key) + + assert data.content == text + assert data.key == key + + cipher = data.cipher() + + ciphered_text = "Tfuw" + assert cipher.content == ciphered_text + assert cipher.key == key + + @staticmethod + def test_with_str_upper_key() -> None: + text = "Test" + key = "ABCD" + data = VigenereData(content=text, key=key) + + assert data.content == text + assert data.key == key + + cipher = data.cipher() + + ciphered_text = "Tfuw" + assert cipher.content == ciphered_text + assert cipher.key == key + + @staticmethod + def test_with_str_mixed_key() -> None: + text = "Test" + key = "aBcD" + data = VigenereData(content=text, key=key) + + assert data.content == text + assert data.key == key + + cipher = data.cipher() + + ciphered_text = "Tfuw" + assert cipher.content == ciphered_text + assert cipher.key == key + + @staticmethod + def test_equality_between_keys() -> None: + text = "Test" + data1 = VigenereData(content=text, key="aBcD") + data2 = VigenereData(content=text, key="abcd") + data3 = VigenereData(content=text, key="ABCD") + + ciphered1 = data1.cipher() + ciphered2 = data2.cipher() + ciphered3 = data3.cipher() + + assert data1.content == data2.content == data3.content + assert ciphered1.content == ciphered2.content == ciphered3.content + + class DecipherSuite: + class SimpleKeySuite: + @staticmethod + def test_with_str_lower_key() -> None: + text = "Test" + key = "bb" + data = VigenereData(content=text, key=key) + + assert data.content == text + assert data.key == key + + decipher = data.decipher() + + deciphered_text = "Sdrs" + assert decipher.content == deciphered_text + assert decipher.key == key + + @staticmethod + def test_with_str_upper_key() -> None: + text = "Test ui" + key = "BB" + data = VigenereData(content=text, key=key) + + assert data.content == text + assert data.key == key + + decipher = data.decipher() + + deciphered_text = "Sdrs th" + assert decipher.content == deciphered_text + assert decipher.key == key + + @staticmethod + def test_with_str_mixed_key() -> None: + text = "Test ui" + key = "Bb" + data = VigenereData(content=text, key=key) + + assert data.content == text + assert data.key == key + + decipher = data.decipher() + + deciphered_text = "Sdrs th" + assert decipher.content == deciphered_text + assert decipher.key == key + + @staticmethod + def test_equality_between_keys() -> None: + text = "Test" + data1 = VigenereData(content=text, key="Bb") + data2 = VigenereData(content=text, key="bb") + data3 = VigenereData(content=text, key="BB") + + deciphered1 = data1.decipher() + deciphered2 = data2.decipher() + deciphered3 = data3.decipher() + + assert data1.content == data2.content == data3.content + assert deciphered1.content == deciphered2.content == deciphered3.content + + class ComplexKeySuite: + @staticmethod + def test_with_str_lower_key() -> None: + text = "Test" + key = "abcd" + data = VigenereData(content=text, key=key) + + assert data.content == text + assert data.key == key + + decipher = data.decipher() + + deciphered_text = "Tdqq" + assert decipher.content == deciphered_text + assert decipher.key == key + + @staticmethod + def test_with_str_upper_key() -> None: + text = "Test ui" + key = "ABCD" + data = VigenereData(content=text, key=key) + + assert data.content == text + assert data.key == key + + decipher = data.decipher() + + deciphered_text = "Tdqq uh" + assert decipher.content == deciphered_text + assert decipher.key == key + + @staticmethod + def test_with_str_mixed_key() -> None: + text = "Test ui" + key = "aBcD" + data = VigenereData(content=text, key=key) + + assert data.content == text + assert data.key == key + + decipher = data.decipher() + + deciphered_text = "Tdqq uh" + assert decipher.content == deciphered_text + assert decipher.key == key + + @staticmethod + def test_equality_between_keys() -> None: + text = "Test" + data1 = VigenereData(content=text, key="aBcD") + data2 = VigenereData(content=text, key="abcd") + data3 = VigenereData(content=text, key="ABCD") + + deciphered1 = data1.decipher() + deciphered2 = data2.decipher() + deciphered3 = data3.decipher() + + assert data1.content == data2.content == data3.content + assert deciphered1.content == deciphered2.content == deciphered3.content + + +class InternalSuite: + class AlgorithmSuite: + algo_func = VigenereData._VigenereData__algorithm + + @classmethod + @pytest.mark.raises(exception=AlgorithmKeyTypeError) + def test_with_bad_key(cls) -> None: + _ignored = cls.algo_func("test", "A", VigenereOperation.CIPHER) + + @classmethod + @pytest.mark.raises(exception=AlgorithmTextTypeError) + def test_with_bad_text(cls) -> None: + _ignored = cls.algo_func(b"test", 10, VigenereOperation.DECIPHER) + + @classmethod + @pytest.mark.raises(exception=AlgorithmOperationTypeError) + def test_with_bad_operation(cls) -> None: + _ignored = cls.algo_func("test", VigenereKey("test"), b"CIPEHR") + + @classmethod + def test_cipher(cls) -> None: + ciphered_text = cls.algo_func( + "teSt uio", VigenereKey("test"), VigenereOperation.CIPHER + ) + + assert ciphered_text == "miKm nmg" + + @classmethod + def test_decipher(cls) -> None: + ciphered_text = cls.algo_func( + "teSt uio", VigenereKey("test"), VigenereOperation.DECIPHER + ) + + assert ciphered_text == "aaAa bew" diff --git a/tests/models/test_vigenere_key.py b/tests/models/test_vigenere_key.py new file mode 100644 index 0000000..c9da6a0 --- /dev/null +++ b/tests/models/test_vigenere_key.py @@ -0,0 +1,89 @@ +# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# Vigenere-API + +# Copyright (C) 2023 Axel DAVID + +# + +# This program is free software: you can redistribute it and/or modify it under + +# the terms of the GNU General Public License as published by the Free Software + +# Foundation, either version 3 of the License, or (at your option) any later version. + +# + +# This program is distributed in the hope that it will be useful, but WITHOUT ANY + +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +# + +# You should have received a copy of the GNU General Public License along with + +# this program. If not, see <https://www.gnu.org/licenses/>. + +# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +import pytest + +from vigenere_api.models.helpers.errors import ( + BadKeyError, + EmptyKeyError, + KeyTypeError, + TooShortKeyError, +) +from vigenere_api.models.vigenere import VigenereKey + + +class CtorSuite: + @staticmethod + def test_with_key() -> None: + key = "zz" + data = VigenereKey(key) + + assert data._VigenereKey__key == key + assert len(data) == len(key) + + @staticmethod + @pytest.mark.raises(exception=KeyTypeError) + def test_bad_type_key() -> None: + key = b"z" + _ignored_data = VigenereKey(key) + + @staticmethod + @pytest.mark.raises(exception=EmptyKeyError) + def test_bad_empty_key() -> None: + key = "" + _ignored_data = VigenereKey(key) + + @staticmethod + @pytest.mark.raises(exception=TooShortKeyError) + def test_too_short_key() -> None: + key = "e" + _ignored_data = VigenereKey(key) + + @staticmethod + @pytest.mark.raises(exception=BadKeyError) + def test_bad_not_alpha_str_key() -> None: + key = "$z" + _ignored_data = VigenereKey(key) + + +def test_next() -> None: + key = "abcd" + data = VigenereKey(key) + + assert data._VigenereKey__key == key + assert len(data) == len(key) + + for char in key: + assert next(data) == char + + assert next(data) == key[0] + + +def test_increase_index() -> None: + key = "abcd" + data = VigenereKey(key) + + assert data._VigenereKey__key == key + assert len(data) == len(key) + + assert data._VigenereKey__index == 0 + data._VigenereKey__increase_index() + assert data._VigenereKey__index == 1 + + for _ in range(len(data)): + data._VigenereKey__increase_index() + + assert data._VigenereKey__index == 1 -- GitLab