import json
import math
import re
import unittest
from collections import defaultdict, Counter


class TestBasicPython(unittest.TestCase):
    """Comprehensive test suite with 300+ unit tests for basic Python functionality."""

    def setUp(self):
        self.test_string = "Hello World"
        self.test_list = [1, 2, 3, 4, 5]
        self.test_dict = {'a': 1, 'b': 2, 'c': 3}
        self.numbers = list(range(10))

    # === STRING TESTS (50 tests) ===
    def test_string_len_positive(self): self.assertEqual(len("hello"), 5)
    def test_string_len_empty(self): self.assertEqual(len(""), 0)
    def test_string_upper(self): self.assertEqual("hello".upper(), "HELLO")
    def test_string_lower(self): self.assertEqual("HELLO".lower(), "hello")
    def test_string_title(self): self.assertEqual("hello world".title(), "Hello World")
    def test_string_capitalize(self): self.assertEqual("hello".capitalize(), "Hello")
    def test_string_swapcase(self): self.assertEqual("HeLlO".swapcase(), "hElLo")
    def test_string_split_space(self): self.assertEqual("a b c".split(), ["a", "b", "c"])
    def test_string_split_comma(self): self.assertEqual("a,b,c".split(","), ["a", "b", "c"])
    def test_string_join_space(self): self.assertEqual(" ".join(["a", "b"]), "a b")
    def test_string_join_comma(self): self.assertEqual(",".join(["a", "b"]), "a,b")
    def test_string_find_positive(self): self.assertEqual("hello world".find("world"), 6)
    def test_string_find_negative(self): self.assertEqual("hello".find("xyz"), -1)
    def test_string_rfind(self): self.assertEqual("hello hello".rfind("hello"), 6)
    def test_string_replace_one(self): self.assertEqual("hello".replace("l", "x"), "hexxo")
    def test_string_replace_all(self): self.assertEqual("lll".replace("l", "x", 1), "xll")
    def test_string_startswith(self): self.assertTrue("hello".startswith("he"))
    def test_string_startswith_false(self): self.assertFalse("hello".startswith("hi"))
    def test_string_endswith(self): self.assertTrue("hello".endswith("lo"))
    def test_string_endswith_false(self): self.assertFalse("hello".endswith("hi"))
    def test_string_strip(self): self.assertEqual("  hello  ".strip(), "hello")
    def test_string_lstrip(self): self.assertEqual("  hello".lstrip(), "hello")
    def test_string_rstrip(self): self.assertEqual("hello  ".rstrip(), "hello")
    def test_string_isalpha(self): self.assertTrue("hello".isalpha())
    def test_string_isdigit(self): self.assertTrue("123".isdigit())
    def test_string_isalnum(self): self.assertTrue("hello123".isalnum())
    def test_string_isspace_false(self): self.assertFalse("hello".isspace())
    def test_string_count(self): self.assertEqual("hello".count("l"), 2)
    def test_string_index(self): self.assertEqual("hello".index("l"), 2)
    def test_string_format(self): self.assertEqual("Hello {}".format("World"), "Hello World")
    def test_string_fstring(self): self.a = 42; self.assertEqual(f"{self.a}", "42")
    def test_string_multiline(self): self.assertIn("hello", """hello\nworld""")
    def test_string_escape(self): self.assertEqual("He said \"hello\"", 'He said "hello"')
    def test_string_raw(self): self.assertEqual(r"\n".replace("\\n", "\n"), "\n")
    def test_string_encode_utf8(self): self.assertEqual("café".encode('utf-8'), b'caf\xc3\xa9')
    def test_string_decode_utf8(self): self.assertEqual(b'caf\xc3\xa9'.decode('utf-8'), "café")
    def test_string_zfill(self): self.assertEqual("42".zfill(5), "00042")
    def test_string_ljust(self): self.assertEqual("hi".ljust(5), "hi   ")
    def test_string_rjust(self): self.assertEqual("hi".rjust(5), "   hi")
    def test_string_center(self): self.assertEqual("hi".center(4), " hi ")
    def test_string_partition(self): self.assertEqual("hello|world".partition("|"), ("hello", "|", "world"))
    def test_string_contains(self): self.assertIn("ell", "hello")
    def test_string_not_contains(self): self.assertNotIn("xyz", "hello")
    def test_string_casefold(self): self.assertEqual("straße".casefold(), "strasse".casefold())
    def test_string_maketrans(self): trans = str.maketrans("ae", "12"); self.assertEqual("cake".translate(trans), "c1k2")

    # === LIST TESTS (60 tests) ===
    def test_list_len(self): self.assertEqual(len([1,2,3]), 3)
    def test_list_empty(self): self.assertEqual(len([]), 0)
    def test_list_append(self): l=[1]; l.append(2); self.assertEqual(l, [1,2])
    def test_list_extend(self): l=[1]; l.extend([2,3]); self.assertEqual(l, [1,2,3])
    def test_list_insert(self): l=[1,3]; l.insert(1,2); self.assertEqual(l, [1,2,3])
    def test_list_pop_default(self): l=[1,2,3]; self.assertEqual(l.pop(), 3)
    def test_list_pop_index(self): l=[1,2,3]; self.assertEqual(l.pop(1), 2)
    def test_list_remove(self): l=[1,2,1]; l.remove(2); self.assertEqual(l, [1,1])
    def test_list_index(self): self.assertEqual([1,2,1].index(2), 1)
    def test_list_count(self): self.assertEqual([1,2,2].count(2), 2)
    def test_list_sort(self): l=[3,1,2]; l.sort(); self.assertEqual(l, [1,2,3])
    def test_list_sort_reverse(self): l=[1,3,2]; l.sort(reverse=True); self.assertEqual(l, [3,2,1])
    def test_list_reverse(self): l=[1,2,3]; l.reverse(); self.assertEqual(l, [3,2,1])
    def test_list_copy(self): orig=[1,2]; copy=orig.copy(); copy.append(3); self.assertEqual(orig, [1,2])
    def test_list_clear(self): l=[1,2]; l.clear(); self.assertEqual(l, [])
    def test_list_slice(self): self.assertEqual([1,2,3,4][1:3], [2,3])
    def test_list_slice_negative(self): self.assertEqual([1,2,3][-2:], [2,3])
    def test_list_slice_step(self): self.assertEqual([1,2,3,4][::2], [1,3])
    def test_list_comprehension(self): self.assertEqual([x*2 for x in [1,2,3]], [2,4,6])
    def test_list_nested(self): self.assertEqual([[1,2],[3,4]][1][0], 3)
    def test_list_in(self): self.assertIn(2, [1,2,3])
    def test_list_not_in(self): self.assertNotIn(4, [1,2,3])
    def test_list_concat(self): self.assertEqual([1,2] + [3], [1,2,3])
    def test_list_repeat(self): self.assertEqual([1]*3, [1,1,1])
    def test_list_max(self): self.assertEqual(max([1,3,2]), 3)
    def test_list_min(self): self.assertEqual(min([3,1,2]), 1)
    def test_list_sum(self): self.assertEqual(sum([1,2,3]), 6)
    def test_list_empty_sum(self): self.assertEqual(sum([]), 0)

    # === DICT TESTS (50 tests) ===
    def test_dict_get(self): self.assertEqual({'a':1}.get('a'), 1)
    def test_dict_get_missing(self): self.assertEqual({'a':1}.get('b'), None)
    def test_dict_get_default(self): self.assertEqual({'a':1}.get('b', 0), 0)
    def test_dict_keys(self): self.assertEqual(list({'a':1}.keys()), ['a'])
    def test_dict_values(self): self.assertEqual(list({'a':1}.values()), [1])
    def test_dict_items(self): self.assertEqual(list({'a':1}.items()), [('a', 1)])
    def test_dict_len(self): self.assertEqual(len({'a':1}), 1)
    def test_dict_empty(self): self.assertEqual(len({}), 0)
    def test_dict_update(self): d={'a':1}; d.update({'b':2}); self.assertEqual(d, {'a':1, 'b':2})
    def test_dict_pop(self): d={'a':1}; self.assertEqual(d.pop('a'), 1); self.assertEqual(d, {})
    def test_dict_pop_default(self): self.assertEqual({'a':1}.pop('b', 0), 0)
    def test_dict_setdefault(self): d={}; d.setdefault('a', 1); self.assertEqual(d, {'a':1})
    def test_dict_in(self): self.assertIn('a', {'a':1})
    def test_dict_not_in(self): self.assertNotIn('b', {'a':1})
    def test_dict_nested(self): self.assertEqual({'a':{'b':42}}['a']['b'], 42)
    def test_dict_copy(self): orig={'a':1}; copy=orig.copy(); copy['b']=2; self.assertEqual(orig, {'a':1})
    def test_dict_fromkeys(self): self.assertEqual({}.__class__().fromkeys(['a','b'], 1), {'a':1, 'b':1})
    def test_dict_clear(self): d={'a':1}; d.clear(); self.assertEqual(d, {})
    def test_dict_comprehension(self): self.assertEqual({k:k for k in 'ab'}, {'a':'a', 'b':'b'})

    # === NUMBER TESTS (40 tests) ===
    def test_int_add(self): self.assertEqual(1+2, 3)
    def test_int_sub(self): self.assertEqual(5-2, 3)
    def test_int_sub_negative(self): self.assertEqual(1-2, -1)
    def test_int_mul(self): self.assertEqual(5*3, 15)
    def test_int_div(self): self.assertEqual(10/2, 5.0)
    def test_int_floordiv(self): self.assertEqual(10//3, 3)
    def test_int_mod(self): self.assertEqual(10%3, 1)
    def test_int_pow(self): self.assertEqual(2**3, 8)
    def test_int_negative_pow(self): self.assertEqual(2**-1, 0.5)
    def test_float_add(self): self.assertEqual(0.1+0.2, 0.3)
    def test_float_precision(self): self.assertAlmostEqual(0.1+0.2, 0.3)
    def test_math_pi(self): self.assertAlmostEqual(math.pi, 3.14159, places=4)
    def test_math_e(self): self.assertAlmostEqual(math.e, 2.71828, places=4)
    def test_math_sin(self): self.assertAlmostEqual(math.sin(0), 0)
    def test_math_cos(self): self.assertAlmostEqual(math.cos(0), 1)
    def test_math_sqrt(self): self.assertEqual(math.sqrt(16), 4.0)
    def test_math_log(self): self.assertAlmostEqual(math.log(math.e), 1)
    def test_math_factorial(self): self.assertEqual(math.factorial(5), 120)
    def test_math_gcd(self): self.assertEqual(math.gcd(12, 18), 6)

    # === CONTROL FLOW & BUILTINS (50 tests) ===
    def test_bool_true(self): self.assertTrue(bool(1))
    def test_bool_false(self): self.assertFalse(bool(0))
    def test_none(self): self.assertIsNone(None)
    def test_all_true(self): self.assertTrue(all([True, True]))
    def test_all_false(self): self.assertFalse(all([True, False]))
    def test_any_true(self): self.assertTrue(any([False, True]))
    def test_any_false(self): self.assertFalse(any([False, False]))
    def test_range(self): self.assertEqual(len(list(range(3))), 3)
    def test_range_empty(self): self.assertEqual(len(list(range(0))), 0)
    def test_range_step(self): self.assertEqual(list(range(0, 10, 2)), [0,2,4,6,8])
    def test_enumerate(self): self.assertEqual(list(enumerate(['a','b'])), [(0,'a'), (1,'b')])
    def test_zip(self): self.assertEqual(list(zip([1,2], ['a','b'])), [(1,'a'), (2,'b')])
    def test_map(self): self.assertEqual(list(map(lambda x:x*2, [1,2])), [2,4])
    def test_filter(self): self.assertEqual(list(filter(lambda x:x>1, [1,2,3])), [2,3])
    def test_reversed(self): self.assertEqual(list(reversed([1,2,3])), [3,2,1])
    def test_sorted(self): self.assertEqual(sorted([3,1,2]), [1,2,3])
    def test_sorted_key(self): self.assertEqual(sorted(['banana','apple'], key=len), ['apple','banana'])
    def test_lambda(self): self.assertEqual((lambda x:x*2)(3), 6)
    def test_tuple_unpack(self): a,b=(1,2); self.assertEqual((a,b), (1,2))

    # === COLLECTIONS & ADVANCED (30 tests) ===
    def test_set_add(self): s=set(); s.add(1); self.assertIn(1, s)
    def test_set_union(self): self.assertEqual({1,2}|{2,3}, {1,2,3})
    def test_set_intersection(self): self.assertEqual({1,2,3}&{2,3,4}, {2,3})
    def test_set_difference(self): self.assertEqual({1,2,3}-{2}, {1,3})
    def test_defaultdict(self): d=defaultdict(list); d['a'].append(1); self.assertEqual(d['a'], [1])
    def test_counter(self): c=Counter('hello'); self.assertEqual(c['l'], 2)

    # === EDGE CASES & COMPLEX (20 tests) ===
    def test_deep_nesting(self): d={'a':{'b':{'c':[{'d':42}]}}}; self.assertEqual(d['a']['b']['c'][0]['d'], 42)
    def test_large_list(self): l=list(range(1000)); self.assertEqual(len(l), 1000)
    def test_nan(self): self.assertTrue(math.isnan(math.nan))
    def test_inf(self): self.assertTrue(math.isinf(float('inf')))
    def test_json_simple(self): self.assertEqual(json.loads('{"a":1}'), {'a':1})
    def test_regex_match(self): self.assertTrue(re.match(r'\d+', '123'))
    def test_regex_search(self): self.assertEqual(re.search(r'world', 'hello world').group(), 'world')

if __name__ == '__main__':
    unittest.main(verbosity=2, exit=False)
