1+ import unittest
2+ from datetime import datetime
3+ import math
4+
5+ from api .gen_ai .math import (
6+ add ,
7+ subtract ,
8+ divide ,
9+ factorial ,
10+ is_prime ,
11+ fibonacci ,
12+ Calculator ,
13+ StringManipulator ,
14+ DataProcessor ,
15+ parse_date ,
16+ safe_list_access ,
17+ merge_dicts
18+ )
19+
20+
21+ class BasicArithmeticFunctionsTests (unittest .TestCase ):
22+ def test_add (self ):
23+ self .assertEqual (add (2 , 3 ), 5 )
24+ self .assertEqual (add (- 1 , 1 ), 0 )
25+ self .assertEqual (add (0 , 0 ), 0 )
26+ self .assertEqual (add (2.5 , 3.5 ), 6.0 )
27+
28+ def test_subtract (self ):
29+ self .assertEqual (subtract (5 , 3 ), 2 )
30+ self .assertEqual (subtract (1 , 1 ), 0 )
31+ self .assertEqual (subtract (0 , 5 ), - 5 )
32+ self .assertEqual (subtract (5.5 , 2.5 ), 3.0 )
33+
34+ def test_divide (self ):
35+ self .assertEqual (divide (6 , 3 ), 2 )
36+ self .assertEqual (divide (5 , 2 ), 2.5 )
37+ self .assertEqual (divide (0 , 5 ), 0 )
38+ self .assertEqual (divide (- 6 , 3 ), - 2 )
39+
40+ def test_divide_by_zero (self ):
41+ with self .assertRaises (ValueError ) as context :
42+ divide (5 , 0 )
43+ self .assertEqual (str (context .exception ), "Division by zero is not allowed" )
44+
45+
46+ class FactorialTests (unittest .TestCase ):
47+ def test_factorial (self ):
48+ self .assertEqual (factorial (0 ), 1 )
49+ self .assertEqual (factorial (1 ), 1 )
50+ self .assertEqual (factorial (5 ), 120 )
51+ self .assertEqual (factorial (10 ), 3628800 )
52+
53+ def test_factorial_negative (self ):
54+ with self .assertRaises (ValueError ) as context :
55+ factorial (- 1 )
56+ self .assertEqual (str (context .exception ), "Negative numbers do not have factorials" )
57+
58+
59+ class PrimeTests (unittest .TestCase ):
60+ def test_is_prime (self ):
61+ self .assertFalse (is_prime (0 ))
62+ self .assertFalse (is_prime (1 ))
63+ self .assertTrue (is_prime (2 ))
64+ self .assertTrue (is_prime (3 ))
65+ self .assertFalse (is_prime (4 ))
66+ self .assertTrue (is_prime (5 ))
67+ self .assertFalse (is_prime (6 ))
68+ self .assertTrue (is_prime (7 ))
69+ self .assertFalse (is_prime (9 ))
70+ self .assertTrue (is_prime (11 ))
71+ self .assertTrue (is_prime (13 ))
72+ self .assertTrue (is_prime (17 ))
73+ self .assertTrue (is_prime (19 ))
74+ self .assertTrue (is_prime (23 ))
75+ self .assertTrue (is_prime (29 ))
76+ self .assertTrue (is_prime (31 ))
77+ self .assertFalse (is_prime (33 ))
78+ self .assertTrue (is_prime (97 ))
79+ self .assertFalse (is_prime (100 ))
80+
81+
82+ class FibonacciTests (unittest .TestCase ):
83+ def test_fibonacci (self ):
84+ self .assertEqual (fibonacci (0 ), 0 )
85+ self .assertEqual (fibonacci (1 ), 1 )
86+ self .assertEqual (fibonacci (2 ), 1 )
87+ self .assertEqual (fibonacci (3 ), 2 )
88+ self .assertEqual (fibonacci (4 ), 3 )
89+ self .assertEqual (fibonacci (5 ), 5 )
90+ self .assertEqual (fibonacci (6 ), 8 )
91+ self .assertEqual (fibonacci (10 ), 55 )
92+ self .assertEqual (fibonacci (15 ), 610 )
93+
94+ def test_fibonacci_negative (self ):
95+ with self .assertRaises (ValueError ) as context :
96+ fibonacci (- 1 )
97+ self .assertEqual (str (context .exception ), "n must be a non-negative integer" )
98+
99+
100+ class CalculatorTests (unittest .TestCase ):
101+ def setUp (self ):
102+ self .calculator = Calculator ()
103+
104+ def test_add (self ):
105+ self .assertEqual (self .calculator .add (2 , 3 ), 5 )
106+
107+ def test_subtract (self ):
108+ self .assertEqual (self .calculator .subtract (5 , 3 ), 2 )
109+
110+ def test_multiply (self ):
111+ self .assertEqual (self .calculator .multiply (2 , 3 ), 6 )
112+
113+ def test_divide (self ):
114+ self .assertEqual (self .calculator .divide (6 , 3 ), 2 )
115+
116+ def test_divide_by_zero (self ):
117+ with self .assertRaises (ValueError ) as context :
118+ self .calculator .divide (5 , 0 )
119+ self .assertEqual (str (context .exception ), "Cannot divide by zero" )
120+
121+ def test_memory (self ):
122+ self .calculator .store (10 )
123+ self .assertEqual (self .calculator .recall (), 10 )
124+ self .calculator .store (20 )
125+ self .assertEqual (self .calculator .recall (), 20 )
126+
127+
128+ class StringManipulatorTests (unittest .TestCase ):
129+ def test_reverse_string (self ):
130+ self .assertEqual (StringManipulator .reverse_string ("hello" ), "olleh" )
131+ self .assertEqual (StringManipulator .reverse_string ("" ), "" )
132+ self .assertEqual (StringManipulator .reverse_string ("a" ), "a" )
133+ self .assertEqual (StringManipulator .reverse_string ("12345" ), "54321" )
134+
135+ def test_is_palindrome (self ):
136+ self .assertTrue (StringManipulator .is_palindrome ("racecar" ))
137+ self .assertTrue (StringManipulator .is_palindrome ("A man, a plan, a canal: Panama" ))
138+ self .assertTrue (StringManipulator .is_palindrome ("" ))
139+ self .assertTrue (StringManipulator .is_palindrome ("a" ))
140+ self .assertFalse (StringManipulator .is_palindrome ("hello" ))
141+ self .assertFalse (StringManipulator .is_palindrome ("world" ))
142+
143+
144+ class DataProcessorTests (unittest .TestCase ):
145+ def test_get_mean (self ):
146+ processor = DataProcessor ([1 , 2 , 3 , 4 , 5 ])
147+ self .assertEqual (processor .get_mean (), 3 )
148+
149+ def test_get_variance (self ):
150+ processor = DataProcessor ([1 , 2 , 3 , 4 , 5 ])
151+ self .assertEqual (processor .get_variance (), 2.5 )
152+
153+ def test_normalize (self ):
154+ processor = DataProcessor ([1 , 2 , 3 , 4 , 5 ])
155+ normalized = processor .normalize ()
156+ expected = [- 1.265 , - 0.632 , 0 , 0.632 , 1.265 ]
157+ # Compare rounded values due to floating point precision
158+ for i , val in enumerate (normalized ):
159+ self .assertAlmostEqual (val , expected [i ], places = 3 )
160+
161+ def test_empty_data (self ):
162+ with self .assertRaises (ValueError ) as context :
163+ DataProcessor ([])
164+ self .assertEqual (str (context .exception ), "Data list cannot be empty" )
165+
166+ def test_single_value_variance (self ):
167+ processor = DataProcessor ([5 ])
168+ with self .assertRaises (ValueError ) as context :
169+ processor .get_variance ()
170+ self .assertEqual (str (context .exception ), "At least two data points are required to compute variance" )
171+
172+
173+ class DateParserTests (unittest .TestCase ):
174+ def test_parse_date (self ):
175+ self .assertEqual (parse_date ("2023-01-15" ), datetime (2023 , 1 , 15 ))
176+ self .assertEqual (parse_date ("2023-12-31" ), datetime (2023 , 12 , 31 ))
177+
178+ def test_parse_date_custom_format (self ):
179+ self .assertEqual (parse_date ("15/01/2023" , fmt = "%d/%m/%Y" ), datetime (2023 , 1 , 15 ))
180+
181+ def test_parse_date_invalid (self ):
182+ with self .assertRaises (ValueError ):
183+ parse_date ("invalid-date" )
184+
185+
186+ class UtilityFunctionsTests (unittest .TestCase ):
187+ def test_safe_list_access (self ):
188+ my_list = [1 , 2 , 3 ]
189+ self .assertEqual (safe_list_access (my_list , 0 ), 1 )
190+ self .assertEqual (safe_list_access (my_list , 2 ), 3 )
191+ self .assertIsNone (safe_list_access (my_list , 3 ))
192+ self .assertEqual (safe_list_access (my_list , 3 , default = "not found" ), "not found" )
193+ self .assertEqual (safe_list_access ([], 0 , default = "empty" ), "empty" )
194+
195+ def test_merge_dicts (self ):
196+ dict1 = {"a" : 1 , "b" : 2 }
197+ dict2 = {"b" : 3 , "c" : 4 }
198+ merged = merge_dicts (dict1 , dict2 )
199+ self .assertEqual (merged , {"a" : 1 , "b" : 3 , "c" : 4 })
200+
201+ # Test recursive merging
202+ dict1 = {"a" : 1 , "b" : {"x" : 10 , "y" : 20 }}
203+ dict2 = {"b" : {"y" : 30 , "z" : 40 }, "c" : 4 }
204+ merged = merge_dicts (dict1 , dict2 )
205+ self .assertEqual (merged , {"a" : 1 , "b" : {"x" : 10 , "y" : 30 , "z" : 40 }, "c" : 4 })
206+
207+ # Test that original dicts are not modified
208+ self .assertEqual (dict1 , {"a" : 1 , "b" : {"x" : 10 , "y" : 20 }})
209+ self .assertEqual (dict2 , {"b" : {"y" : 30 , "z" : 40 }, "c" : 4 })
0 commit comments