138 lines
5.5 KiB
Python
138 lines
5.5 KiB
Python
from ctf.utils import suggest_patterns
|
|
import pytest
|
|
|
|
# =====================================================================
|
|
# 1. Test Strategy Summary
|
|
# =====================================================================
|
|
# This suite verifies the `suggest_patterns` utility function which parses
|
|
# a sample flag string and generates a prioritized, deduplicated list of
|
|
# candidate regular expression patterns.
|
|
#
|
|
# Core scenarios tested:
|
|
# A. Happy Path:
|
|
# - Verifying pattern suggestion output for typical flags like 'SKY-1111-000'
|
|
# and 'CTF{easy_flag_123}'.
|
|
# - Verifying order and counts of specific vs. general patterns.
|
|
#
|
|
# B. Boundary Conditions:
|
|
# - Handling single character inputs (e.g. 'A', '1', '{').
|
|
# - Handling strings containing only delimiter/special characters (e.g. '---').
|
|
# - Handling inputs with no numeric values or no alphabetic values.
|
|
#
|
|
# C. Edge Cases:
|
|
# - Mixing case strings (e.g., 'AbCdEf') and verifying case-insensitive
|
|
# or case-specific group behavior.
|
|
#
|
|
# D. Error Handling:
|
|
# - Empty strings or strings containing only whitespace characters should
|
|
# raise ValueError.
|
|
# =====================================================================
|
|
|
|
# =====================================================================
|
|
# 2. Mocking/Setup Requirements
|
|
# =====================================================================
|
|
# - No external database, network APIs, or filesystem mocks are needed
|
|
# as `suggest_patterns` is a pure string-processing utility.
|
|
# =====================================================================
|
|
|
|
def test_suggest_patterns_happy_path_sky():
|
|
"""
|
|
Verifies that the suggestions for a hyphenated alpha-numeric flag like 'SKY-1111-000'
|
|
include specific character group counts, variable length matches, and the literal match.
|
|
"""
|
|
patterns = suggest_patterns("SKY-1111-000")
|
|
|
|
# Asserting we get a list of patterns
|
|
assert isinstance(patterns, list)
|
|
assert len(patterns) > 0
|
|
|
|
# Expected options:
|
|
# 1. Specific count: ^[A-Z]{3}-\d{4}-\d{3}$
|
|
assert "^[A-Z]{3}-\\d{4}-\\d{3}$" in patterns
|
|
# 2. Variable: ^[A-Z]+-\d+-\d+$
|
|
assert "^[A-Z]+-\\d+-\\d+$" in patterns
|
|
# 3. Case-insensitive count: ^[A-Za-z]{3}-\d{4}-\d{3}$
|
|
assert "^[A-Za-z]{3}-\\d{4}-\\d{3}$" in patterns
|
|
# 4. Alphanumeric + delimiter class: ^[A-Za-z0-9\-]+$
|
|
assert "^[A-Za-z0-9\\-]+$" in patterns
|
|
# 5. Literal matching: ^SKY-1111-000$
|
|
assert "^SKY-1111-000$" in patterns
|
|
|
|
def test_suggest_patterns_happy_path_ctf():
|
|
"""
|
|
Verifies suggestions for flags with braces and underscores like 'CTF{easy_flag_123}'.
|
|
Note that special regex characters like '{' and '}' are correctly escaped.
|
|
"""
|
|
patterns = suggest_patterns("CTF{easy_flag_123}")
|
|
|
|
# 1. Specific count: ^[A-Z]{3}\{[a-z]{4}_[a-z]{4}_\d{3}\}$
|
|
assert "^[A-Z]{3}\\{[a-z]{4}_[a-z]{4}_\\d{3}\\}$" in patterns
|
|
# 2. Variable: ^[A-Z]+\{[a-z]+_[a-z]+_\d+\}$
|
|
assert "^[A-Z]+\\{[a-z]+_[a-z]+_\\d+\\}$" in patterns
|
|
# 3. Alphanumeric class: ^[A-Za-z0-9_{\}]+$
|
|
assert "^[A-Za-z0-9_\\{\\}]+$" in patterns
|
|
# 4. Literal matching: ^CTF\{easy_flag_123\}$
|
|
assert "^CTF\\{easy_flag_123\\}$" in patterns
|
|
|
|
def test_suggest_patterns_only_specials():
|
|
"""
|
|
Verifies that a string with only special characters works and generates valid patterns.
|
|
"""
|
|
patterns = suggest_patterns("---")
|
|
# All patterns should deduplicate to just the exact literal match or similar
|
|
assert "^---$" in patterns
|
|
|
|
def test_suggest_patterns_single_char():
|
|
"""
|
|
Verifies pattern suggestion on single character flags.
|
|
"""
|
|
assert "^[A-Z]{1}$" in suggest_patterns("A")
|
|
assert "^\\d{1}$" in suggest_patterns("5")
|
|
|
|
def test_suggest_patterns_empty_and_whitespace():
|
|
"""
|
|
Verifies that empty string or whitespace-only inputs trigger a ValueError.
|
|
"""
|
|
with pytest.raises(ValueError, match="Input string cannot be empty or whitespace only."):
|
|
suggest_patterns("")
|
|
|
|
with pytest.raises(ValueError, match="Input string cannot be empty or whitespace only."):
|
|
suggest_patterns(" ")
|
|
|
|
def test_suggest_patterns_with_competition_name_braced():
|
|
"""
|
|
Verifies that when the competition name is matched in a braced flag,
|
|
additional general wildcard patterns like '^CTF\\{.*\\}$' are generated.
|
|
"""
|
|
patterns = suggest_patterns("CTF{easy_flag_123}", comp_name="CTF")
|
|
|
|
# Check that competition prefix is kept literal in specific/variable patterns
|
|
assert "^CTF\\{[a-z]{4}_[a-z]{4}_\\d{3}\\}$" in patterns
|
|
assert "^CTF\\{[a-z]+_[a-z]+_\\d+\\}$" in patterns
|
|
|
|
# Check that braced wildcard options are suggested
|
|
assert "^CTF\\{.*\\}$" in patterns
|
|
assert "^CTF\\{[A-Za-z0-9_\\-]+\\}$" in patterns
|
|
assert "^CTF\\{[a-z0-9_]+\\}$" in patterns
|
|
|
|
def test_suggest_patterns_with_competition_name_non_braced():
|
|
"""
|
|
Verifies that when the competition name is matched in a non-braced flag,
|
|
suffix wildcards like '^SKY-.*$' or '^SKY.*$' are suggested.
|
|
"""
|
|
patterns = suggest_patterns("SKY-1111-000", comp_name="SKY")
|
|
|
|
assert "^SKY-\\d{4}-\\d{3}$" in patterns
|
|
assert "^SKY-.*$" in patterns
|
|
|
|
def test_suggest_patterns_with_competition_name_mismatch():
|
|
"""
|
|
Verifies that if the competition name is not in the example flag,
|
|
it falls back to standard regex suggestion matching.
|
|
"""
|
|
patterns_mismatch = suggest_patterns("CTF{easy_flag_123}", comp_name="SKY")
|
|
patterns_none = suggest_patterns("CTF{easy_flag_123}")
|
|
|
|
assert patterns_mismatch == patterns_none
|
|
|