1+ import pytest
2+ from pydantic import ValidationError
3+ from Algorithms .slidingWindow .longestUnique import lengthOfLongestSubstringTwoDistinct , maximumUniqueSubarray , SlidingWindowParam
4+
5+ # -------------------------
6+ # Basic correctness tests
7+ # -------------------------
8+
9+ @pytest .mark .parametrize (
10+ "input_str, expected" ,
11+ [
12+ ("eceba" , 3 ),
13+ ("ccaabbb" , 5 ),
14+ ("ababffzzeee" , 5 ),
15+ ("aa" , 2 ),
16+ ("a" , 1 ),
17+ ("ab" , 2 ),
18+ ("abc" , 2 ),
19+ ],
20+ )
21+ def test_basic_cases (input_str , expected ):
22+ param = SlidingWindowParam (s = input_str )
23+ assert lengthOfLongestSubstringTwoDistinct (param .s ) == expected
24+
25+ @pytest .mark .parametrize (
26+ "nums, expected" ,
27+ [
28+ ([4 , 2 , 4 , 5 , 6 ], 17 ), # example 1
29+ ([5 , 2 , 1 , 2 , 5 , 2 , 1 , 2 , 5 ], 8 ), # example 2
30+ ([1 ], 1 ),
31+ ([1 , 2 ], 3 ),
32+ ([1 , 1 ], 1 ),
33+ ([1 , 2 , 3 ], 6 ),
34+ ([3 , 3 , 3 ], 3 ),
35+ ],
36+ )
37+ def test_basic_cases (nums , expected ):
38+ assert maximumUniqueSubarray (nums ) == expected
39+
40+ # -------------------------
41+ # Regression / tricky cases
42+ # -------------------------
43+
44+ def test_alternating_characters ():
45+ param = SlidingWindowParam (s = "abababab" )
46+ assert lengthOfLongestSubstringTwoDistinct (param .s ) == 8
47+
48+
49+ def test_three_distinct_repeated ():
50+ param = SlidingWindowParam (s = "abcabcabc" )
51+ assert lengthOfLongestSubstringTwoDistinct (param .s ) == 2
52+
53+
54+ def test_eviction_order_matters ():
55+ # Breaks implementations that don't move_to_end
56+ param = SlidingWindowParam (s = "abaccc" )
57+ # Longest valid substring: "accc"
58+ assert lengthOfLongestSubstringTwoDistinct (param .s ) == 4
59+
60+
61+ def test_multiple_evictions ():
62+ param = SlidingWindowParam (s = "aabbccddeeff" )
63+ assert lengthOfLongestSubstringTwoDistinct (param .s ) == 4
64+
65+ def test_duplicate_at_start ():
66+ # Forces window to jump start
67+ nums = [2 , 1 , 2 , 3 , 4 ]
68+ # Best: [1,2,3,4]
69+ assert maximumUniqueSubarray (nums ) == 10
70+
71+
72+ def test_duplicate_at_end ():
73+ nums = [1 , 2 , 3 , 4 , 1 ]
74+ # Best: [1,2,3,4]
75+ assert maximumUniqueSubarray (nums ) == 10
76+
77+
78+ def test_multiple_duplicates ():
79+ nums = [1 , 2 , 1 , 3 , 2 , 3 , 4 ]
80+ # Best: [1,3,2,3,4] is invalid
81+ # Best valid: [1,3,2] or [2,3,4]
82+ assert maximumUniqueSubarray (nums ) == 9
83+
84+
85+ def test_eviction_jump_needed ():
86+ # Breaks incorrect start updates
87+ nums = [1 , 2 , 3 , 2 , 5 ]
88+ # Best: [3,2,5]
89+ assert maximumUniqueSubarray (nums ) == 10
90+
91+ # -------------------------
92+ # Edge cases
93+ # -------------------------
94+
95+ def test_all_same_character ():
96+ param = SlidingWindowParam (s = "aaaaaaa" )
97+ assert lengthOfLongestSubstringTwoDistinct (param .s ) == 7
98+
99+
100+ def test_two_characters_only ():
101+ param = SlidingWindowParam (s = "abababababab" )
102+ assert lengthOfLongestSubstringTwoDistinct (param .s ) == 12
103+
104+ def test_all_unique ():
105+ nums = [1 , 2 , 3 , 4 , 5 , 6 ]
106+ assert maximumUniqueSubarray (nums ) == sum (nums )
107+
108+
109+ def test_all_same ():
110+ nums = [7 , 7 , 7 , 7 ]
111+ assert maximumUniqueSubarray (nums ) == 7
112+
113+
114+ def test_large_values ():
115+ nums = [10_000 , 9_999 , 10_000 ]
116+ assert maximumUniqueSubarray (nums ) == 19_999
117+
118+ def test_strictly_increasing_then_repeat ():
119+ nums = list (range (1 , 100 )) + [50 ]
120+ assert maximumUniqueSubarray (nums ) == sum (range (1 , 100 ))
121+
122+
123+ def test_alternating_pattern ():
124+ nums = [1 , 2 ] * 50
125+ assert maximumUniqueSubarray (nums ) == 3 # [1,2]
126+
127+ # -------------------------
128+ # Pydantic validation tests
129+ # -------------------------
130+
131+ def test_empty_string_rejected ():
132+ with pytest .raises (ValidationError ):
133+ SlidingWindowParam (s = "" )
134+
135+
136+ def test_non_string_input ():
137+ with pytest .raises (ValidationError ):
138+ SlidingWindowParam (s = 123 )
139+
140+
141+ # -------------------------
142+ # Invariant-style tests
143+ # -------------------------
144+
145+ @pytest .mark .parametrize ("s" , [
146+ "abc" ,
147+ "aabcbcdbca" ,
148+ "xyzzzyx" ,
149+ "pwwkew" ,
150+ ])
151+ def test_result_never_exceeds_string_length (s ):
152+ param = SlidingWindowParam (s = s )
153+ result = lengthOfLongestSubstringTwoDistinct (param .s )
154+ assert 0 < result <= len (s )
155+
156+ @pytest .mark .parametrize ("nums" , [
157+ [1 , 2 , 3 ],
158+ [1 , 2 , 1 , 2 , 3 ],
159+ [5 , 5 , 5 , 1 , 2 ],
160+ [100 , 200 , 300 , 100 , 400 ],
161+ ])
162+ def test_result_never_exceeds_sum (nums ):
163+ result = maximumUniqueSubarray (nums )
164+ assert 0 < result <= sum (nums )
0 commit comments