Skip to content

Commit

Permalink
🔧 Corrigindo bugs, Codcov 100%
Browse files Browse the repository at this point in the history
- Criado teste para cada linha do codigo, CODCOV 100%
- Melhorado a cobertura e a descrição de erros
- Retirado codigo morto do projeto
- [BUG] Corrigido o bug quando passava um valor negativo para o numero de CPU
- Removido lib colorama
- [DEV] adicionado pytest-mock para os teste

closes #2
  • Loading branch information
AyslanBatista committed Jun 4, 2024
1 parent c2f86da commit 7cebd2c
Show file tree
Hide file tree
Showing 38 changed files with 1,738 additions and 59 deletions.
5 changes: 3 additions & 2 deletions encryptdef/__main__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
"""Modulo que é o ponto de entrada do programa"""

from encryptdef.cli import main
from encryptdef.cli import main # pragma: no cover

if __name__ == "__main__": # pragma: no cover

if __name__ == "__main__":
# Passando um contexto vazio
main(ctx=None)
2 changes: 1 addition & 1 deletion encryptdef/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def main(ctx: Optional[click.Context] = None) -> None:
correta, não será possível desencriptar os dados ou arquivos.**
"""
if ctx is None:
ctx = click.Context(main)
ctx = click.Context(main) # pragma: no cover

if ctx.invoked_subcommand is None:
core.interactive_mode()
Expand Down
44 changes: 23 additions & 21 deletions encryptdef/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
TEMPLATE_DECRYPTED,
TEMPLATE_DECRYPTED_FILE,
TEMPLATE_DECRYPTED_MESSAGE,
TEMPLATE_EMPTY_FILE_ERROR,
TEMPLATE_ENCRYPT_FILE,
TEMPLATE_ENCRYPT_KEY,
TEMPLATE_ENCRYPT_MESSAGE,
Expand Down Expand Up @@ -56,6 +57,10 @@ class InvalidKey(Exception):
"""Formato de string criptografada inválido"""


class EmptyFileError(Exception):
"""Formato de string criptografada inválido"""


def encrypt(message: str, password: str) -> str:
"""
Criptografa uma mensagem usando AES GCM com uma chave derivada por Scrypt.
Expand Down Expand Up @@ -227,7 +232,7 @@ def process_lines(


def process_file_content(
file: str,
file_path: str,
key: str,
new_file_path: str,
process_line_func: Callable[[str, str], Union[str, bool]],
Expand All @@ -236,7 +241,7 @@ def process_file_content(
Processa o conteúdo de um arquivo e salva o resultado em um novo arquivo.
Args:
file (str): Caminho do arquivo original.
file_path (str): Caminho do arquivo original.
key (str): Chave para criptografar ou descriptografar.
new_file_path (str): Caminho do novo arquivo.
process_line_func (Callable[[str, str], Union[str, bool]]): Função para
Expand All @@ -245,13 +250,13 @@ def process_file_content(
Returns:
bool: True se o processamento for bem-sucedido, False caso contrário.
"""
lines = read_file(file)
lines = read_file(file_path)
if not lines:
raise EmptyFileError(TEMPLATE_EMPTY_FILE_ERROR % file_path)

max_workers = print_get_max_workers(lines)
processed_lines = process_lines(lines, key, process_line_func, max_workers)

if not processed_lines:
return False

write_file(new_file_path, processed_lines)
print_and_record_log(
(
Expand Down Expand Up @@ -281,24 +286,25 @@ def process_file(
Returns:
bool: True se o processamento for bem-sucedido, False caso contrário.
"""
file, key, new_file = data_list

try:
new_file_path = get_new_file_path(file, new_file, CURRENT_DIR)
file_path, key, new_file = data_list
new_file_path = get_new_file_path(file_path, new_file, CURRENT_DIR)
return process_file_content(
file, key, new_file_path, process_line_func
file_path, key, new_file_path, process_line_func
)

except FileNotFoundError:
print_and_record_log(TEMPLATE_FILE_NOT_FOUND % file, "error")
print_and_record_log(TEMPLATE_FILE_NOT_FOUND % file_path, "error")
console.print(TEMPLATE_INFO_FILE)
return False

except (
TypeError,
IsADirectoryError,
ValueError,
InvalidEncryptedFormat,
InvalidKey,
EmptyFileError,
) as e:
print_and_record_log(str(e), "error")
return False
Expand All @@ -307,7 +313,7 @@ def process_file(
def process_keyfile_and_args(
keyfile: Optional[str],
message: Optional[str],
file: Optional[str],
file_: Optional[str],
template_key: str,
) -> str:
"""
Expand All @@ -321,7 +327,7 @@ def process_keyfile_and_args(
a chave será solicitada.
message (Optional[str]): Dados para criptografar ou descriptografar.
Usado se 'file' não for fornecido.
file (Optional[str]): Caminho do arquivo a ser criptografado ou
file_ (Optional[str]): Caminho do arquivo a ser criptografado ou
descriptografado. Usado se 'message' não for fornecido.
template_key (str): Template para solicitar a chave ao usuário,
se necessário.
Expand All @@ -335,12 +341,12 @@ def process_keyfile_and_args(
SystemExit: Se o arquivo de chave não for encontrado, ou se a chave
fornecida for inválida.
"""
if message and file:
if message and file_:
raise click.UsageError(
"Você deve fornecer apenas um dos argumentos: --message ou --file,"
"não ambos."
" não ambos."
)
if not message and not file:
if not message and not file_:
raise click.UsageError(
"Você deve fornecer um dos argumentos: --message ou --file."
)
Expand All @@ -355,13 +361,9 @@ def process_keyfile_and_args(
else:
while not key or key.isspace():
key = console.input(template_key, password=True).strip()
if key.isspace():
if not key:
print_and_record_log(TEMPLATE_ERROR_EMPTY_FIELD, "error")

if key is None:
print_and_record_log(TEMPLATE_ERROR_EMPTY_FIELD, "error")
sys.exit(1)

return key


Expand Down
13 changes: 7 additions & 6 deletions encryptdef/interactive_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ def validate_and_get_input(prompts: List[str]) -> List[str]:
inputs = [
get_user_input(prompt, "🔑" in prompt) for prompt in prompts
]

if any(not input for input in inputs):
raise ValueError(TEMPLATE_ERROR_EMPTY_FIELD)
return inputs
Expand Down Expand Up @@ -174,15 +173,17 @@ def print_get_max_workers(lines: List[str]) -> int:
max_workers = 1

if len(lines) > 500:
use_more_cores = int(
console.input(TEMPLATE_GET_MAX_WORKERS % max_workers)
)
user_input = console.input(
TEMPLATE_GET_MAX_WORKERS % max_workers
).strip()
console.print("\n", end="")

if not use_more_cores or use_more_cores > max_workers:
if not user_input.isdigit() or not (
0 < int(user_input) <= max_workers
):
raise ValueError(TEMPLATE_ERROR_INVALID_CHOICE)

return use_more_cores
return int(user_input)

return 1

Expand Down
8 changes: 4 additions & 4 deletions encryptdef/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@


def configure_logger(
logfile: Optional[Union[str, os.PathLike[str]]] = None
log_level: str, logfile: Optional[Union[str, os.PathLike[str]]] = None
) -> None:
"""Configura o logger com um handler de arquivo rotativo."""
if logfile is None:
Expand All @@ -32,10 +32,10 @@ def configure_logger(
fh = handlers.RotatingFileHandler(
logfile, maxBytes=10**6, backupCount=10
)
fh.setLevel(LOG_LEVEL)
fh.setLevel(log_level)
fh.setFormatter(fmt)
log_instance.addHandler(fh)
log_instance.setLevel(LOG_LEVEL)
log_instance.setLevel(log_level)


def get_logger() -> logging.Logger:
Expand All @@ -44,7 +44,7 @@ def get_logger() -> logging.Logger:


# Configure o logger ao importar o módulo
configure_logger()
configure_logger(LOG_LEVEL)

log = get_logger()

Expand Down
5 changes: 4 additions & 1 deletion encryptdef/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,10 @@
⚠ ERRO - FORMATO DE STRING CRIPTOGRAFADA INVÁLIDO!"""

TEMPLATE_TYPE_ERROR = """
⚠ ERRO - ESPERADO UMA STRING, OBTIDO '%s'"""
⚠ ERRO - ESPERADO UMA STRING, OBTIDO '%s'."""

TEMPLATE_IS_DIRECTORY = """
⚠ ERRO - '%s' É UM DIRETÓRIO, NÃO UM ARQUIVO."""

TEMPLATE_EMPTY_FILE_ERROR = """
⚠ ERRO - ARQUIVO '%s' ESTÁ VAZIO."""
10 changes: 2 additions & 8 deletions encryptdef/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,8 @@
import re
from typing import List

from colorama import init

from encryptdef.template import TEMPLATE_IS_DIRECTORY

# Inicializa colorama para garantir o funcionamento em sistemas Windows
init()


def get_new_file_path(file: str, new_file: str, current_dir: str) -> str:
"""
Expand Down Expand Up @@ -93,10 +88,9 @@ def write_file(new_file_path: str, processed_lines: List[str]) -> None:


def clear_console():
"""Limpa o console de forma segura."""
"""Limpa o console de forma segura.
Utilizando sequências de escape ANSI"""
if os.name == "posix":
print("\033[H\033[J", end="")
elif os.name == "nt":
# Inicializa o colorama, que é seguro e portátil
init()
print("\033c", end="")
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ local_scheme = "no-local-version" # determina a parte local (como dev1+g7aff1b9.
minversion = "6.0"
addopts = "-ra -q -vv"
testpaths = "tests"
filterwarnings = "ignore::DeprecationWarning:rich_click"

[tool.flake8]
exclude = [".venv", "build", ".vscodelocal", "migrations", "template.py"]
Expand Down
1 change: 1 addition & 0 deletions requirements.test.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#teste
pytest
pytest-mock

# coverage
coverage
Expand Down
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
pycryptodomex >=3.20.0
rich-click >=1.8.2
colorama >=0.4.6
8 changes: 0 additions & 8 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,6 @@

import pytest

MARKER = """\
unit: Mark unit tests
integration: Mark integration tests
high: High Priority
medium: Medium Priority
low: Low Priority
"""


@pytest.fixture(autouse=True)
def go_to_tmpdir(request): # injeção de dependencias
Expand Down
4 changes: 2 additions & 2 deletions tests/test_assigning_a_name_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


def test_assigning_a_name_file_absolute():
"""Test function assigning_a_name_file"""
"""Testando a função assigning_a_name_file"""
file = "/tmp/test/file-test-123.txt"
name = "encrypt-"
expected_result = "/tmp/test/encrypt-file-test-123.txt"
Expand All @@ -14,7 +14,7 @@ def test_assigning_a_name_file_absolute():


def test_assigning_a_name_file_relative():
"""Test function assigning_a_name_file"""
"""Testando a função assigning_a_name_file"""
file = "-123-file-test.txt"
name = "decrypt-"
expected_result = "decrypt--123-file-test.txt"
Expand Down
74 changes: 74 additions & 0 deletions tests/test_decrypt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"""Modulo para testar a função decrypt em core.py"""

from base64 import b64decode, b64encode

import pytest

from encryptdef.core import (
InvalidEncryptedFormat,
InvalidKey,
decrypt,
encrypt,
)
from encryptdef.template import (
TEMPLATE_ERROR_INVALID_ENCRYPTED_FORMAT,
TEMPLATE_INVALID_KEY,
)


def test_decrypt_correct_message():
"""Testa a função decrypt"""
message1 = "Message one: djas;kl/d<j@!#@'>$!@&()&&¨|#!@&*%#312312adasd"
password1 = "strongpassword123"

message2 = "Message two: 1~[]31'2>~[]dADd12<asS&(*¨*&¨#%@!#!@/HDJKA@!#"
password2 = "djas;kl/d<j@!#@'>$!@&()&&¨|#!@&*%#312312adasd"

encrypted_message1 = encrypt(message1, password1)
decrypted_message1 = decrypt(encrypted_message1, password1)

encrypted_message2 = encrypt(message2, password2)
decrypted_message2 = decrypt(encrypted_message2, password2)

assert decrypted_message1 == message1
assert decrypted_message2 == message2


def test_decrypt_with_wrong_password():
"""Testa a função decrypt"""
message = "This is a test message."
password = "strongpassword123"
wrong_password = "wrongpassword456"

encrypted_message = encrypt(message, password)

with pytest.raises(InvalidKey) as excinfo:
decrypt(encrypted_message, wrong_password)
assert str(excinfo.value) == TEMPLATE_INVALID_KEY


def test_decrypt_invalid_format():
"""Testa a função decrypt"""
invalid_encrypted_message = "invalid*encrypted*message-format"
password = "strongpassword123"

with pytest.raises(InvalidEncryptedFormat) as excinfo:
decrypt(invalid_encrypted_message, password)

assert str(excinfo.value) == TEMPLATE_ERROR_INVALID_ENCRYPTED_FORMAT


def test_decrypt_with_modified_message():
"""Testa a função decrypt"""
message = "This is a test message."
password = "strongpassword123"

encrypted_message = encrypt(message, password)
parts = encrypted_message.split("*")
modified_cipher_text = b64encode(b"modified" + b64decode(parts[0])).decode(
"utf-8"
)
modified_encrypted_message = "*".join([modified_cipher_text] + parts[1:])

with pytest.raises(InvalidKey):
decrypt(modified_encrypted_message, password)
Loading

0 comments on commit 7cebd2c

Please sign in to comment.