File size: 11,260 Bytes
b211251
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
"""
Unit tests for input validation functions
"""

import pytest
from app import validate_inputs, validate_component_id


class TestComponentIDValidation:
    """Test component ID validation"""
    
    def test_valid_component_ids(self):
        """Test that valid component IDs pass validation"""
        valid_ids = [
            "api-service",
            "auth-service",
            "payment-service-v2",
            "db-01",
            "cache",
            "a",  # Single character
            "api-gateway-prod-001",
        ]
        
        for component_id in valid_ids:
            is_valid, msg = validate_component_id(component_id)
            assert is_valid is True, f"'{component_id}' should be valid but got: {msg}"
            assert msg == ""
    
    def test_invalid_uppercase(self):
        """Test that uppercase letters are rejected"""
        invalid_ids = ["API-SERVICE", "Auth-Service", "PaymentService"]
        
        for component_id in invalid_ids:
            is_valid, msg = validate_component_id(component_id)
            assert is_valid is False
            assert "lowercase" in msg.lower()
    
    def test_invalid_underscore(self):
        """Test that underscores are rejected"""
        is_valid, msg = validate_component_id("api_service")
        assert is_valid is False
        assert "lowercase" in msg.lower() or "hyphen" in msg.lower()
    
    def test_invalid_special_characters(self):
        """Test that special characters are rejected"""
        invalid_ids = [
            "api@service",
            "api.service",
            "api service",  # Space
            "api/service",
            "api&service",
        ]
        
        for component_id in invalid_ids:
            is_valid, msg = validate_component_id(component_id)
            assert is_valid is False, f"'{component_id}' should be invalid"
    
    def test_empty_string(self):
        """Test that empty string is rejected"""
        is_valid, msg = validate_component_id("")
        assert is_valid is False
        assert "1-255" in msg or "character" in msg.lower()
    
    def test_too_long(self):
        """Test that component IDs longer than 255 chars are rejected"""
        long_id = "a" * 256
        is_valid, msg = validate_component_id(long_id)
        assert is_valid is False
        assert "255" in msg
    
    def test_non_string_type(self):
        """Test that non-string types are rejected"""
        is_valid, msg = validate_component_id(123)
        assert is_valid is False
        assert "string" in msg.lower()


class TestNumericInputValidation:
    """Test numeric input validation"""
    
    def test_valid_inputs(self):
        """Test that valid inputs pass validation"""
        is_valid, msg = validate_inputs(
            latency=150.0,
            error_rate=0.05,
            throughput=1000.0,
            cpu_util=0.7,
            memory_util=0.6
        )
        
        assert is_valid is True
        assert msg == ""
    
    def test_valid_inputs_with_none_optionals(self):
        """Test that None is valid for optional fields"""
        is_valid, msg = validate_inputs(
            latency=150.0,
            error_rate=0.05,
            throughput=1000.0,
            cpu_util=None,
            memory_util=None
        )
        
        assert is_valid is True
        assert msg == ""


class TestLatencyValidation:
    """Test latency validation"""
    
    def test_valid_latency(self):
        """Test valid latency values"""
        valid_values = [0, 1, 100, 500, 1000, 9999]
        
        for latency in valid_values:
            is_valid, msg = validate_inputs(latency, 0.05, 1000, None, None)
            assert is_valid is True, f"Latency {latency} should be valid"
    
    def test_negative_latency(self):
        """Test that negative latency is rejected"""
        is_valid, msg = validate_inputs(-10, 0.05, 1000, None, None)
        assert is_valid is False
        assert "latency" in msg.lower()
    
    def test_excessive_latency(self):
        """Test that excessive latency is rejected"""
        is_valid, msg = validate_inputs(20000, 0.05, 1000, None, None)
        assert is_valid is False
        assert "latency" in msg.lower()
    
    def test_non_numeric_latency(self):
        """Test that non-numeric latency is rejected"""
        is_valid, msg = validate_inputs("invalid", 0.05, 1000, None, None)
        assert is_valid is False
        assert "latency" in msg.lower()


class TestErrorRateValidation:
    """Test error rate validation"""
    
    def test_valid_error_rates(self):
        """Test valid error rate values"""
        valid_values = [0, 0.01, 0.05, 0.5, 0.99, 1.0]
        
        for error_rate in valid_values:
            is_valid, msg = validate_inputs(100, error_rate, 1000, None, None)
            assert is_valid is True, f"Error rate {error_rate} should be valid"
    
    def test_negative_error_rate(self):
        """Test that negative error rate is rejected"""
        is_valid, msg = validate_inputs(100, -0.1, 1000, None, None)
        assert is_valid is False
        assert "error rate" in msg.lower()
    
    def test_error_rate_exceeds_one(self):
        """Test that error rate > 1 is rejected"""
        is_valid, msg = validate_inputs(100, 1.5, 1000, None, None)
        assert is_valid is False
        assert "error rate" in msg.lower()
    
    def test_non_numeric_error_rate(self):
        """Test that non-numeric error rate is rejected"""
        is_valid, msg = validate_inputs(100, "high", 1000, None, None)
        assert is_valid is False
        assert "error rate" in msg.lower()


class TestThroughputValidation:
    """Test throughput validation"""
    
    def test_valid_throughput(self):
        """Test valid throughput values"""
        valid_values = [0, 1, 100, 1000, 10000]
        
        for throughput in valid_values:
            is_valid, msg = validate_inputs(100, 0.05, throughput, None, None)
            assert is_valid is True, f"Throughput {throughput} should be valid"
    
    def test_negative_throughput(self):
        """Test that negative throughput is rejected"""
        is_valid, msg = validate_inputs(100, 0.05, -500, None, None)
        assert is_valid is False
        assert "throughput" in msg.lower()
    
    def test_non_numeric_throughput(self):
        """Test that non-numeric throughput is rejected"""
        is_valid, msg = validate_inputs(100, 0.05, "many", None, None)
        assert is_valid is False
        assert "throughput" in msg.lower()


class TestCPUUtilizationValidation:
    """Test CPU utilization validation"""
    
    def test_valid_cpu_util(self):
        """Test valid CPU utilization values"""
        valid_values = [0, 0.1, 0.5, 0.85, 1.0]
        
        for cpu_util in valid_values:
            is_valid, msg = validate_inputs(100, 0.05, 1000, cpu_util, None)
            assert is_valid is True, f"CPU util {cpu_util} should be valid"
    
    def test_negative_cpu_util(self):
        """Test that negative CPU utilization is rejected"""
        is_valid, msg = validate_inputs(100, 0.05, 1000, -0.1, None)
        assert is_valid is False
        assert "cpu" in msg.lower()
    
    def test_cpu_util_exceeds_one(self):
        """Test that CPU utilization > 1 is rejected"""
        is_valid, msg = validate_inputs(100, 0.05, 1000, 1.5, None)
        assert is_valid is False
        assert "cpu" in msg.lower()
    
    def test_non_numeric_cpu_util(self):
        """Test that non-numeric CPU utilization is rejected"""
        is_valid, msg = validate_inputs(100, 0.05, 1000, "high", None)
        assert is_valid is False
        assert "cpu" in msg.lower()


class TestMemoryUtilizationValidation:
    """Test memory utilization validation"""
    
    def test_valid_memory_util(self):
        """Test valid memory utilization values"""
        valid_values = [0, 0.1, 0.5, 0.85, 1.0]
        
        for memory_util in valid_values:
            is_valid, msg = validate_inputs(100, 0.05, 1000, None, memory_util)
            assert is_valid is True, f"Memory util {memory_util} should be valid"
    
    def test_negative_memory_util(self):
        """Test that negative memory utilization is rejected"""
        is_valid, msg = validate_inputs(100, 0.05, 1000, None, -0.1)
        assert is_valid is False
        assert "memory" in msg.lower()
    
    def test_memory_util_exceeds_one(self):
        """Test that memory utilization > 1 is rejected"""
        is_valid, msg = validate_inputs(100, 0.05, 1000, None, 1.5)
        assert is_valid is False
        assert "memory" in msg.lower()
    
    def test_non_numeric_memory_util(self):
        """Test that non-numeric memory utilization is rejected"""
        is_valid, msg = validate_inputs(100, 0.05, 1000, None, "full")
        assert is_valid is False
        assert "memory" in msg.lower()


class TestEdgeCases:
    """Test edge cases and boundary conditions"""
    
    def test_zero_values(self):
        """Test that zero is valid for all metrics"""
        is_valid, msg = validate_inputs(0, 0, 0, 0, 0)
        assert is_valid is True
    
    def test_maximum_values(self):
        """Test maximum boundary values"""
        is_valid, msg = validate_inputs(10000, 1.0, 999999, 1.0, 1.0)
        assert is_valid is True
    
    def test_float_precision(self):
        """Test that high-precision floats are handled"""
        is_valid, msg = validate_inputs(
            latency=123.456789,
            error_rate=0.123456,
            throughput=1234.56,
            cpu_util=0.87654321,
            memory_util=0.76543210
        )
        assert is_valid is True
    
    def test_integer_inputs(self):
        """Test that integer inputs are accepted"""
        is_valid, msg = validate_inputs(100, 0, 1000, 1, 1)
        assert is_valid is True
    
    def test_string_numbers(self):
        """Test that string numbers are converted"""
        is_valid, msg = validate_inputs("100", "0.05", "1000", "0.7", "0.6")
        assert is_valid is True


class TestErrorMessages:
    """Test that error messages are helpful"""
    
    def test_error_message_contains_field_name(self):
        """Test that error messages identify the problematic field"""
        # Latency error
        is_valid, msg = validate_inputs(-10, 0.05, 1000, None, None)
        assert "latency" in msg.lower()
        
        # Error rate error
        is_valid, msg = validate_inputs(100, 2.0, 1000, None, None)
        assert "error rate" in msg.lower()
        
        # Throughput error
        is_valid, msg = validate_inputs(100, 0.05, -100, None, None)
        assert "throughput" in msg.lower()
    
    def test_error_message_has_emoji(self):
        """Test that error messages include emoji for visibility"""
        is_valid, msg = validate_inputs(-10, 0.05, 1000, None, None)
        assert "❌" in msg
    
    def test_error_message_provides_guidance(self):
        """Test that error messages provide guidance"""
        is_valid, msg = validate_inputs(-10, 0.05, 1000, None, None)
        assert "between" in msg.lower() or "range" in msg.lower() or "0-10000" in msg


if __name__ == "__main__":
    pytest.main([__file__, "-v", "--tb=short"])