Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions tests/unit/prompt_converter/test_ascii_art_converter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.

import pytest

pytest.importorskip("art")

from pyrit.prompt_converter import AsciiArtConverter, ConverterResult


@pytest.mark.asyncio
async def test_ascii_art_converter_basic():
converter = AsciiArtConverter(font="block")
result = await converter.convert_async(prompt="hi", input_type="text")
assert isinstance(result, ConverterResult)
assert result.output_type == "text"
assert len(result.output_text) > 0
assert "\n" in result.output_text


@pytest.mark.asyncio
async def test_ascii_art_converter_default_random_font():
converter = AsciiArtConverter()
result = await converter.convert_async(prompt="test", input_type="text")
assert isinstance(result, ConverterResult)
assert len(result.output_text) > 0


@pytest.mark.asyncio
async def test_ascii_art_converter_empty():
converter = AsciiArtConverter(font="block")
result = await converter.convert_async(prompt="", input_type="text")
assert isinstance(result, ConverterResult)
assert result.output_type == "text"


@pytest.mark.asyncio
async def test_ascii_art_converter_input_not_supported():
converter = AsciiArtConverter()
with pytest.raises(ValueError, match="Input type not supported"):
await converter.convert_async(prompt="test", input_type="image_path")


def test_ascii_art_converter_input_supported():
converter = AsciiArtConverter()
assert converter.input_supported("text") is True
assert converter.input_supported("image_path") is False


def test_ascii_art_converter_output_supported():
converter = AsciiArtConverter()
assert converter.output_supported("text") is True
assert converter.output_supported("image_path") is False
53 changes: 53 additions & 0 deletions tests/unit/prompt_converter/test_ascii_smuggler_converter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.

import pytest

from pyrit.prompt_converter import AsciiSmugglerConverter, ConverterResult


@pytest.mark.asyncio
async def test_ascii_smuggler_encode_basic():
converter = AsciiSmugglerConverter(action="encode")
result = await converter.convert_async(prompt="hi", input_type="text")
assert isinstance(result, ConverterResult)
assert result.output_type == "text"
for char in result.output_text:
assert ord(char) > 0xE0000


@pytest.mark.asyncio
async def test_ascii_smuggler_decode_roundtrip():
encoder = AsciiSmugglerConverter(action="encode")
encoded = await encoder.convert_async(prompt="hello", input_type="text")

decoder = AsciiSmugglerConverter(action="decode")
decoded = await decoder.convert_async(prompt=encoded.output_text, input_type="text")
assert decoded.output_text == "hello"


@pytest.mark.asyncio
async def test_ascii_smuggler_with_unicode_tags():
converter = AsciiSmugglerConverter(action="encode", unicode_tags=True)
result = await converter.convert_async(prompt="hi", input_type="text")
assert result.output_text.startswith(chr(0xE0001))
assert result.output_text.endswith(chr(0xE007F))


@pytest.mark.asyncio
async def test_ascii_smuggler_empty():
converter = AsciiSmugglerConverter(action="encode")
result = await converter.convert_async(prompt="", input_type="text")
assert result.output_text == ""


def test_ascii_smuggler_invalid_action():
with pytest.raises(ValueError):
AsciiSmugglerConverter(action="invalid")


@pytest.mark.asyncio
async def test_ascii_smuggler_input_not_supported():
converter = AsciiSmugglerConverter(action="encode")
with pytest.raises(ValueError, match="Input type not supported"):
await converter.convert_async(prompt="test", input_type="image_path")
80 changes: 80 additions & 0 deletions tests/unit/prompt_converter/test_atbash_converter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.

import pytest

from pyrit.prompt_converter import AtbashConverter, ConverterResult


@pytest.mark.asyncio
async def test_atbash_converter_basic():
converter = AtbashConverter()
result = await converter.convert_async(prompt="abc", input_type="text")
assert isinstance(result, ConverterResult)
assert result.output_text == "zyx"
assert result.output_type == "text"


@pytest.mark.asyncio
async def test_atbash_converter_uppercase():
converter = AtbashConverter()
result = await converter.convert_async(prompt="ABC", input_type="text")
assert isinstance(result, ConverterResult)
assert result.output_text == "ZYX"
assert result.output_type == "text"


@pytest.mark.asyncio
async def test_atbash_converter_mixed():
converter = AtbashConverter()
result = await converter.convert_async(prompt="Hello", input_type="text")
assert isinstance(result, ConverterResult)
assert result.output_text == "Svool"
assert result.output_type == "text"


@pytest.mark.asyncio
async def test_atbash_converter_with_description():
converter = AtbashConverter(append_description=True)
result = await converter.convert_async(prompt="hello", input_type="text")
assert isinstance(result, ConverterResult)
assert result.output_type == "text"
# The encoded prompt should be present in the output
assert "svool" in result.output_text


@pytest.mark.asyncio
async def test_atbash_converter_empty_string():
converter = AtbashConverter()
result = await converter.convert_async(prompt="", input_type="text")
assert isinstance(result, ConverterResult)
assert result.output_text == ""
assert result.output_type == "text"


@pytest.mark.asyncio
async def test_atbash_converter_numbers():
converter = AtbashConverter()
result = await converter.convert_async(prompt="012", input_type="text")
assert isinstance(result, ConverterResult)
assert result.output_text == "987"
assert result.output_type == "text"


@pytest.mark.asyncio
async def test_atbash_converter_input_not_supported():
converter = AtbashConverter()
with pytest.raises(ValueError):
await converter.convert_async(prompt="hello", input_type="image_path")


def test_atbash_converter_input_supported():
converter = AtbashConverter()
assert converter.input_supported("text") is True
assert converter.input_supported("image_path") is False


def test_atbash_converter_output_supported():
converter = AtbashConverter()
assert converter.output_supported("text") is True
assert converter.output_supported("image_path") is False
61 changes: 61 additions & 0 deletions tests/unit/prompt_converter/test_base64_converter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.

import pytest

from pyrit.prompt_converter import Base64Converter, ConverterResult


@pytest.mark.asyncio
async def test_base64_converter_default():
converter = Base64Converter()
result = await converter.convert_async(prompt="hello", input_type="text")
assert isinstance(result, ConverterResult)
assert result.output_text == "aGVsbG8="
assert result.output_type == "text"


@pytest.mark.asyncio
async def test_base64_converter_urlsafe():
converter = Base64Converter(encoding_func="urlsafe_b64encode")
result = await converter.convert_async(prompt="hello", input_type="text")
assert isinstance(result, ConverterResult)
assert result.output_text == "aGVsbG8="
assert result.output_type == "text"


@pytest.mark.asyncio
async def test_base64_converter_b16():
converter = Base64Converter(encoding_func="b16encode")
result = await converter.convert_async(prompt="hi", input_type="text")
assert isinstance(result, ConverterResult)
assert result.output_text == "6869"
assert result.output_type == "text"


@pytest.mark.asyncio
async def test_base64_converter_empty():
converter = Base64Converter()
result = await converter.convert_async(prompt="", input_type="text")
assert isinstance(result, ConverterResult)
assert result.output_text == ""
assert result.output_type == "text"


@pytest.mark.asyncio
async def test_base64_converter_input_not_supported():
converter = Base64Converter()
with pytest.raises(ValueError):
await converter.convert_async(prompt="hello", input_type="image_path")


def test_base64_converter_input_supported():
converter = Base64Converter()
assert converter.input_supported("text") is True
assert converter.input_supported("image_path") is False


def test_base64_converter_output_supported():
converter = Base64Converter()
assert converter.output_supported("text") is True
assert converter.output_supported("image_path") is False
78 changes: 78 additions & 0 deletions tests/unit/prompt_converter/test_caesar_converter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.

import pytest

from pyrit.prompt_converter import CaesarConverter, ConverterResult


@pytest.mark.asyncio
async def test_caesar_converter_shift_1():
converter = CaesarConverter(caesar_offset=1)
result = await converter.convert_async(prompt="abc", input_type="text")
assert isinstance(result, ConverterResult)
assert result.output_text == "bcd"
assert result.output_type == "text"


@pytest.mark.asyncio
async def test_caesar_converter_shift_negative():
converter = CaesarConverter(caesar_offset=-1)
result = await converter.convert_async(prompt="bcd", input_type="text")
assert isinstance(result, ConverterResult)
assert result.output_text == "abc"
assert result.output_type == "text"


@pytest.mark.asyncio
async def test_caesar_converter_wraps_around():
converter = CaesarConverter(caesar_offset=1)
result = await converter.convert_async(prompt="xyz", input_type="text")
assert isinstance(result, ConverterResult)
assert result.output_text == "yza"
assert result.output_type == "text"


@pytest.mark.asyncio
async def test_caesar_converter_preserves_case():
converter = CaesarConverter(caesar_offset=1)
result = await converter.convert_async(prompt="AbC", input_type="text")
assert isinstance(result, ConverterResult)
assert result.output_text == "BcD"
assert result.output_type == "text"


@pytest.mark.asyncio
async def test_caesar_converter_with_description():
converter = CaesarConverter(caesar_offset=1, append_description=True)
result = await converter.convert_async(prompt="hello", input_type="text")
assert isinstance(result, ConverterResult)
assert result.output_type == "text"
# The encoded prompt should be present in the output
assert "ifmmp" in result.output_text


def test_caesar_converter_invalid_offset():
with pytest.raises(ValueError, match="caesar offset value invalid"):
CaesarConverter(caesar_offset=26)


def test_caesar_converter_invalid_negative_offset():
with pytest.raises(ValueError, match="caesar offset value invalid"):
CaesarConverter(caesar_offset=-26)


@pytest.mark.asyncio
async def test_caesar_converter_empty():
converter = CaesarConverter(caesar_offset=1)
result = await converter.convert_async(prompt="", input_type="text")
assert isinstance(result, ConverterResult)
assert result.output_text == ""
assert result.output_type == "text"


@pytest.mark.asyncio
async def test_caesar_converter_input_not_supported():
converter = CaesarConverter(caesar_offset=1)
with pytest.raises(ValueError):
await converter.convert_async(prompt="hello", input_type="image_path")
52 changes: 52 additions & 0 deletions tests/unit/prompt_converter/test_character_space_converter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.

import pytest

from pyrit.prompt_converter import CharacterSpaceConverter, ConverterResult


@pytest.mark.asyncio
async def test_character_space_basic():
converter = CharacterSpaceConverter()
result = await converter.convert_async(prompt="hello", input_type="text")
assert isinstance(result, ConverterResult)
assert result.output_text == "h e l l o"
assert result.output_type == "text"


@pytest.mark.asyncio
async def test_character_space_removes_punctuation():
converter = CharacterSpaceConverter()
result = await converter.convert_async(prompt="hello!", input_type="text")
assert isinstance(result, ConverterResult)
# "hello!" -> " ".join -> "h e l l o !" -> remove "!" -> "h e l l o "
assert "h e l l o" in result.output_text
assert "!" not in result.output_text
assert result.output_type == "text"


@pytest.mark.asyncio
async def test_character_space_with_spaces():
converter = CharacterSpaceConverter()
result = await converter.convert_async(prompt="hi there", input_type="text")
assert isinstance(result, ConverterResult)
# "hi there" -> " ".join -> "h i t h e r e" (3 spaces between i and t)
assert result.output_text == "h i t h e r e"
assert result.output_type == "text"


@pytest.mark.asyncio
async def test_character_space_empty():
converter = CharacterSpaceConverter()
result = await converter.convert_async(prompt="", input_type="text")
assert isinstance(result, ConverterResult)
assert result.output_text == ""
assert result.output_type == "text"


@pytest.mark.asyncio
async def test_character_space_input_not_supported():
converter = CharacterSpaceConverter()
with pytest.raises(ValueError):
await converter.convert_async(prompt="hello", input_type="image_path")
Loading
Loading