398 lines
18 KiB
Python
398 lines
18 KiB
Python
from typing import List, Dict, Any
|
|
from .base_tests import BaseTestGenerator
|
|
|
|
|
|
class IdentifierTestGenerator(BaseTestGenerator):
|
|
"""Generate test cases for identifiers and identifier literals."""
|
|
|
|
# Reserved words that might be operators or keywords
|
|
RESERVED_WORDS = [
|
|
'true', 'false', 'if', 'while', 'for', 'match', 'break', 'continue',
|
|
'fn', 'struct', 'union', 'enum', 'trait', 'impl', 'inher',
|
|
'dup', 'drop', 'swap', 'over', 'rot', 'pick', 'roll', 'depth',
|
|
]
|
|
|
|
def generate_basic_identifier_tests(self):
|
|
"""Generate basic identifier tests."""
|
|
# Simple identifiers
|
|
self.make_success_test("Identifier Simple Lowercase", "hello",
|
|
"identifier", "hello")
|
|
self.make_success_test("Identifier Simple Uppercase", "HELLO",
|
|
"identifier", "HELLO")
|
|
self.make_success_test("Identifier Mixed Case", "HelloWorld",
|
|
"identifier", "HelloWorld")
|
|
self.make_success_test("Identifier Single Letter", "x",
|
|
"identifier", "x")
|
|
self.make_success_test("Identifier Single Letter Upper", "X",
|
|
"identifier", "X")
|
|
|
|
# Identifiers with numbers
|
|
self.make_success_test("Identifier With Numbers", "var123",
|
|
"identifier", "var123")
|
|
self.make_success_test("Identifier Numbers End", "myVar2",
|
|
"identifier", "myVar2")
|
|
self.make_success_test("Identifier Mixed Numbers", "a1b2c3",
|
|
"identifier", "a1b2c3")
|
|
|
|
# Identifiers with underscores
|
|
self.make_success_test("Identifier With Underscore", "hello_world",
|
|
"identifier", "hello_world")
|
|
self.make_success_test("Identifier Leading Underscore", "_private",
|
|
"identifier", "_private")
|
|
self.make_success_test("Identifier Multiple Underscores", "my_long_var_name",
|
|
"identifier", "my_long_var_name")
|
|
self.make_success_test("Identifier Double Underscore", "my__var",
|
|
"identifier", "my__var")
|
|
self.make_success_test("Identifier Trailing Underscore", "var_",
|
|
"identifier", "var_")
|
|
self.make_success_test("Identifier Only Underscores", "___",
|
|
"identifier", "___")
|
|
|
|
# Snake case
|
|
self.make_success_test("Identifier Snake Case", "my_variable_name",
|
|
"identifier", "my_variable_name")
|
|
|
|
# Camel case
|
|
self.make_success_test("Identifier Camel Case", "myVariableName",
|
|
"identifier", "myVariableName")
|
|
|
|
# Pascal case
|
|
self.make_success_test("Identifier Pascal Case", "MyClassName",
|
|
"identifier", "MyClassName")
|
|
|
|
# All caps with underscores
|
|
self.make_success_test("Identifier All Caps", "MY_CONSTANT",
|
|
"identifier", "MY_CONSTANT")
|
|
|
|
def generate_identifier_literal_tests(self):
|
|
"""Generate identifier literal tests (with :: prefix)."""
|
|
# Simple identifier literals
|
|
self.make_success_test("Identifier Literal Simple", "::hello",
|
|
"identifier_literal", "hello")
|
|
self.make_success_test("Identifier Literal Uppercase", "::Point",
|
|
"identifier_literal", "Point")
|
|
self.make_success_test("Identifier Literal Snake Case", "::my_var",
|
|
"identifier_literal", "my_var")
|
|
|
|
# Type names
|
|
self.make_success_test("Identifier Literal Type i64", "::i64",
|
|
"identifier_literal", "i64")
|
|
self.make_success_test("Identifier Literal Type String", "::String",
|
|
"identifier_literal", "String")
|
|
self.make_success_test("Identifier Literal Type Point", "::Point",
|
|
"identifier_literal", "Point")
|
|
|
|
# Trait names
|
|
self.make_success_test("Identifier Literal Trait Addable", "::Addable",
|
|
"identifier_literal", "Addable")
|
|
self.make_success_test("Identifier Literal Trait Drawable", "::Drawable",
|
|
"identifier_literal", "Drawable")
|
|
|
|
# Field names
|
|
self.make_success_test("Identifier Literal Field x", "::x",
|
|
"identifier_literal", "x")
|
|
self.make_success_test("Identifier Literal Field width", "::width",
|
|
"identifier_literal", "width")
|
|
|
|
# With underscores
|
|
self.make_success_test("Identifier Literal With Underscore", "::_private",
|
|
"identifier_literal", "_private")
|
|
self.make_success_test("Identifier Literal Multiple Underscores", "::my_long_name",
|
|
"identifier_literal", "my_long_name")
|
|
|
|
# With numbers
|
|
self.make_success_test("Identifier Literal With Numbers", "::var123",
|
|
"identifier_literal", "var123")
|
|
|
|
def generate_whitespace_tests(self):
|
|
"""Generate tests with whitespace around identifiers."""
|
|
# Regular identifiers with whitespace
|
|
self.make_success_test("Identifier Leading Whitespace", " hello",
|
|
"identifier", "hello")
|
|
self.make_success_test("Identifier Trailing Whitespace", "hello ",
|
|
"identifier", "hello")
|
|
self.make_success_test("Identifier Both Whitespace", " hello ",
|
|
"identifier", "hello")
|
|
self.make_success_test("Identifier Tab Before", "\thello",
|
|
"identifier", "hello")
|
|
|
|
# Identifier literals with whitespace
|
|
self.make_success_test("Identifier Literal Leading Whitespace", " ::hello",
|
|
"identifier_literal", "hello")
|
|
self.make_success_test("Identifier Literal Trailing Whitespace", "::hello ",
|
|
"identifier_literal", "hello")
|
|
self.make_success_test("Identifier Literal Both Whitespace", " ::hello ",
|
|
"identifier_literal", "hello")
|
|
|
|
def generate_long_identifier_tests(self):
|
|
"""Generate tests for longer identifiers."""
|
|
# Moderately long
|
|
self.make_success_test("Identifier Moderate Length",
|
|
"thisIsAReasonablyLongVariableName",
|
|
"identifier", "thisIsAReasonablyLongVariableName")
|
|
|
|
# Very long
|
|
long_name = "this_is_a_very_long_identifier_name_that_someone_might_use_for_some_reason"
|
|
self.make_success_test("Identifier Very Long", long_name,
|
|
"identifier", long_name)
|
|
|
|
# Long with numbers
|
|
long_with_nums = "variable_with_many_numbers_123_456_789_000"
|
|
self.make_success_test("Identifier Long With Numbers", long_with_nums,
|
|
"identifier", long_with_nums)
|
|
|
|
def generate_error_tests(self):
|
|
"""Generate error test cases for identifiers."""
|
|
# Starting with number
|
|
self.make_error_test("Identifier Starting With Number",
|
|
"123abc",
|
|
"Invalid identifier: cannot start with digit.")
|
|
|
|
# Invalid characters
|
|
self.make_error_test("Identifier With Hash",
|
|
"my#var",
|
|
"Invalid identifier: '#' is not allowed in identifiers.")
|
|
|
|
self.make_error_test("Identifier With Dash",
|
|
"my-var",
|
|
"Invalid identifier: '-' is not allowed in identifiers.")
|
|
|
|
self.make_error_test("Identifier With Dot",
|
|
"my.var",
|
|
"Invalid identifier: '.' is not allowed in identifiers.")
|
|
|
|
self.make_error_test("Identifier With Space",
|
|
"my var",
|
|
"Invalid identifier: whitespace not allowed in identifiers.")
|
|
|
|
self.make_error_test("Identifier With Colon",
|
|
"my:var",
|
|
"Invalid identifier: ':' is not allowed in identifiers.")
|
|
|
|
# Note: :: is allowed only as prefix for identifier literals
|
|
self.make_error_test("Identifier Double Colon Inside",
|
|
"my::var",
|
|
"Invalid identifier: '::' only allowed as prefix for identifier literals.")
|
|
|
|
# Special characters
|
|
self.make_error_test("Identifier With At",
|
|
"@variable",
|
|
"Invalid identifier: '@' is not allowed in identifiers.")
|
|
|
|
self.make_error_test("Identifier With Dollar",
|
|
"$variable",
|
|
"Invalid identifier: '$' is not allowed in identifiers.")
|
|
|
|
self.make_error_test("Identifier With Percent",
|
|
"%variable",
|
|
"Invalid identifier: '%' is not allowed in identifiers.")
|
|
|
|
# Brackets not allowed
|
|
self.make_error_test("Identifier With Brackets",
|
|
"my[var]",
|
|
"Invalid identifier: brackets not allowed in identifiers.")
|
|
|
|
self.make_error_test("Identifier With Braces",
|
|
"my{var}",
|
|
"Invalid identifier: braces not allowed in identifiers.")
|
|
|
|
self.make_error_test("Identifier With Parens",
|
|
"my(var)",
|
|
"Invalid identifier: parentheses not allowed in identifiers.")
|
|
|
|
# Quotes not allowed
|
|
self.make_error_test("Identifier With Single Quote",
|
|
"my'var",
|
|
"Invalid identifier: quotes not allowed in identifiers.")
|
|
|
|
self.make_error_test("Identifier With Double Quote",
|
|
'my"var',
|
|
"Invalid identifier: quotes not allowed in identifiers.")
|
|
|
|
# Only numbers (not valid identifier)
|
|
self.make_error_test("Identifier Only Numbers",
|
|
"123",
|
|
"Not an identifier: numeric literal.")
|
|
|
|
# Empty identifier literal
|
|
self.make_error_test("Identifier Literal Empty",
|
|
"::",
|
|
"Invalid identifier literal: empty identifier after '::'.")
|
|
|
|
def generate_case_sensitivity_tests(self):
|
|
"""Generate tests showing case sensitivity."""
|
|
# These should all be different identifiers
|
|
self.make_success_test("Identifier Case Lower", "variable",
|
|
"identifier", "variable")
|
|
self.make_success_test("Identifier Case Upper", "VARIABLE",
|
|
"identifier", "VARIABLE")
|
|
self.make_success_test("Identifier Case Mixed", "Variable",
|
|
"identifier", "Variable")
|
|
self.make_success_test("Identifier Case Camel", "variableName",
|
|
"identifier", "variableName")
|
|
self.make_success_test("Identifier Case Pascal", "VariableName",
|
|
"identifier", "VariableName")
|
|
|
|
def generate_reserved_word_tests(self):
|
|
"""Generate tests for words that might be reserved."""
|
|
# Note: In the spec, these are treated as identifiers/operators
|
|
# This tests that they're recognized correctly
|
|
for word in self.RESERVED_WORDS:
|
|
self.make_success_test(f"Identifier Reserved Word {word}",
|
|
word, "identifier", word)
|
|
|
|
def generate_all_tests(self) -> List[Dict[str, Any]]:
|
|
"""Generate all identifier test cases."""
|
|
# Basic identifiers
|
|
self.generate_basic_identifier_tests()
|
|
|
|
# Identifier literals
|
|
self.generate_identifier_literal_tests()
|
|
|
|
# Whitespace handling
|
|
self.generate_whitespace_tests()
|
|
|
|
# Long identifiers
|
|
self.generate_long_identifier_tests()
|
|
|
|
# Error cases
|
|
self.generate_error_tests()
|
|
|
|
# Case sensitivity
|
|
self.generate_case_sensitivity_tests()
|
|
|
|
# Reserved words
|
|
self.generate_reserved_word_tests()
|
|
|
|
return self.get_tests()
|
|
|
|
|
|
class BooleanTestGenerator(BaseTestGenerator):
|
|
"""Generate test cases for boolean literals."""
|
|
|
|
def generate_basic_tests(self):
|
|
"""Generate basic boolean literal tests."""
|
|
# True
|
|
self.make_success_test("Bool True", "true", "bool", True)
|
|
|
|
# False
|
|
self.make_success_test("Bool False", "false", "bool", False)
|
|
|
|
def generate_whitespace_tests(self):
|
|
"""Generate tests with whitespace around booleans."""
|
|
# True with whitespace
|
|
self.make_success_test("Bool True Leading Whitespace", " true",
|
|
"bool", True)
|
|
self.make_success_test("Bool True Trailing Whitespace", "true ",
|
|
"bool", True)
|
|
self.make_success_test("Bool True Both Whitespace", " true ",
|
|
"bool", True)
|
|
self.make_success_test("Bool True Tab Before", "\ttrue",
|
|
"bool", True)
|
|
|
|
# False with whitespace
|
|
self.make_success_test("Bool False Leading Whitespace", " false",
|
|
"bool", False)
|
|
self.make_success_test("Bool False Trailing Whitespace", "false ",
|
|
"bool", False)
|
|
self.make_success_test("Bool False Both Whitespace", " false ",
|
|
"bool", False)
|
|
self.make_success_test("Bool False Tab Before", "\tfalse",
|
|
"bool", False)
|
|
|
|
def generate_error_tests(self):
|
|
"""Generate error test cases for booleans."""
|
|
# Capitalized (case sensitive)
|
|
self.make_error_test("Bool True Capitalized",
|
|
"True",
|
|
"Invalid boolean: 'True' is not a boolean literal (use lowercase 'true').")
|
|
|
|
self.make_error_test("Bool False Capitalized",
|
|
"False",
|
|
"Invalid boolean: 'False' is not a boolean literal (use lowercase 'false').")
|
|
|
|
# All caps
|
|
self.make_error_test("Bool True All Caps",
|
|
"TRUE",
|
|
"Invalid boolean: 'TRUE' is not a boolean literal (use lowercase 'true').")
|
|
|
|
self.make_error_test("Bool False All Caps",
|
|
"FALSE",
|
|
"Invalid boolean: 'FALSE' is not a boolean literal (use lowercase 'false').")
|
|
|
|
# Mixed case
|
|
self.make_error_test("Bool True Mixed Case",
|
|
"tRuE",
|
|
"Invalid boolean: 'tRuE' is not a boolean literal (use lowercase 'true').")
|
|
|
|
self.make_error_test("Bool False Mixed Case",
|
|
"fAlSe",
|
|
"Invalid boolean: 'fAlSe' is not a boolean literal (use lowercase 'false').")
|
|
|
|
# Numeric representations
|
|
self.make_error_test("Bool Numeric 1",
|
|
"1",
|
|
"Not a boolean: numeric literal.")
|
|
|
|
self.make_error_test("Bool Numeric 0",
|
|
"0",
|
|
"Not a boolean: numeric literal.")
|
|
|
|
# String representations
|
|
self.make_error_test("Bool String True",
|
|
'"true"',
|
|
"Not a boolean: string literal.")
|
|
|
|
self.make_error_test("Bool String False",
|
|
'"false"',
|
|
"Not a boolean: string literal.")
|
|
|
|
# Other languages
|
|
self.make_error_test("Bool Yes",
|
|
"yes",
|
|
"Invalid boolean: 'yes' is not a boolean literal.")
|
|
|
|
self.make_error_test("Bool No",
|
|
"no",
|
|
"Invalid boolean: 'no' is not a boolean literal.")
|
|
|
|
# Typos
|
|
self.make_error_test("Bool Typo Ture",
|
|
"ture",
|
|
"Invalid boolean: 'ture' is not a boolean literal.")
|
|
|
|
self.make_error_test("Bool Typo Flase",
|
|
"flase",
|
|
"Invalid boolean: 'flase' is not a boolean literal.")
|
|
|
|
def generate_multiple_bool_tests(self):
|
|
"""Generate tests with multiple boolean values."""
|
|
# Multiple values on stack
|
|
self.make_multi_value_test("Bool Multiple True False",
|
|
"true false",
|
|
[("bool", True), ("bool", False)])
|
|
|
|
self.make_multi_value_test("Bool Multiple Same",
|
|
"true true",
|
|
[("bool", True), ("bool", True)])
|
|
|
|
self.make_multi_value_test("Bool Three Values",
|
|
"true false true",
|
|
[("bool", True), ("bool", False), ("bool", True)])
|
|
|
|
def generate_all_tests(self) -> List[Dict[str, Any]]:
|
|
"""Generate all boolean test cases."""
|
|
# Basic tests
|
|
self.generate_basic_tests()
|
|
|
|
# Whitespace handling
|
|
self.generate_whitespace_tests()
|
|
|
|
# Error cases
|
|
self.generate_error_tests()
|
|
|
|
# Multiple booleans
|
|
self.generate_multiple_bool_tests()
|
|
|
|
return self.get_tests()
|