|
7 | 7 | from tracarbon import EnergyConsumption |
8 | 8 | from tracarbon import LinuxEnergyConsumption |
9 | 9 | from tracarbon import TracarbonException |
| 10 | +from tracarbon.exceptions import AzureSensorException |
| 11 | +from tracarbon.exceptions import GCPSensorException |
10 | 12 | from tracarbon.hardwares import EnergyUsage |
11 | 13 | from tracarbon.hardwares import HardwareInfo |
12 | 14 | from tracarbon.hardwares import WindowsEnergyConsumption |
13 | 15 | from tracarbon.hardwares.cloud_providers import AWS |
| 16 | +from tracarbon.hardwares.cloud_providers import GCP |
| 17 | +from tracarbon.hardwares.cloud_providers import Azure |
| 18 | +from tracarbon.hardwares.sensors import AzureEnergyConsumption |
| 19 | +from tracarbon.hardwares.sensors import GCPEnergyConsumption |
14 | 20 |
|
15 | 21 |
|
16 | 22 | @pytest.mark.darwin |
@@ -151,3 +157,111 @@ async def test_get_platform_should_return_the_platform_energy_consumption_window |
151 | 157 | with pytest.raises(TracarbonException) as exception: |
152 | 158 | await WindowsEnergyConsumption().get_energy_usage() |
153 | 159 | assert exception.value.args[0] == "This Windows hardware is not yet supported." |
| 160 | + |
| 161 | + |
| 162 | +def test_is_gcp_should_return_false_on_exception(): |
| 163 | + assert GCP.is_gcp() is False |
| 164 | + |
| 165 | + |
| 166 | +def test_is_gcp_should_return_true(mocker): |
| 167 | + mock_response = mocker.Mock() |
| 168 | + mock_response.status_code = 200 |
| 169 | + mocker.patch.object(requests, "get", return_value=mock_response) |
| 170 | + |
| 171 | + assert GCP.is_gcp() is True |
| 172 | + |
| 173 | + |
| 174 | +def test_gcp_from_metadata(mocker): |
| 175 | + mock_machine_response = mocker.Mock() |
| 176 | + mock_machine_response.text = "projects/123456/machineTypes/n2-standard-4" |
| 177 | + |
| 178 | + mock_zone_response = mocker.Mock() |
| 179 | + mock_zone_response.text = "projects/123456/zones/us-central1-a" |
| 180 | + |
| 181 | + mocker.patch.object( |
| 182 | + requests, |
| 183 | + "get", |
| 184 | + side_effect=[mock_machine_response, mock_zone_response], |
| 185 | + ) |
| 186 | + |
| 187 | + gcp = GCP.from_metadata() |
| 188 | + |
| 189 | + assert gcp.instance_type == "n2-standard-4" |
| 190 | + assert gcp.region_name == "us-central1" |
| 191 | + |
| 192 | + |
| 193 | +@pytest.mark.asyncio |
| 194 | +async def test_gcp_sensor_should_return_energy_consumption(mocker): |
| 195 | + gcp_sensor = GCPEnergyConsumption(instance_type="n2-standard-4") |
| 196 | + |
| 197 | + assert gcp_sensor.vcpus == 4.0 |
| 198 | + assert gcp_sensor.memory_gb == 16.0 |
| 199 | + assert gcp_sensor.min_watts > 0 |
| 200 | + assert gcp_sensor.max_watts > gcp_sensor.min_watts |
| 201 | + |
| 202 | + mocker.patch.object(HardwareInfo, "get_cpu_usage", return_value=50) |
| 203 | + from tracarbon.hardwares.gpu import GPUInfo |
| 204 | + |
| 205 | + mocker.patch.object(GPUInfo, "get_gpu_power_usage_or_none", return_value=None) |
| 206 | + |
| 207 | + energy_usage = await gcp_sensor.get_energy_usage() |
| 208 | + |
| 209 | + expected_power = gcp_sensor.min_watts + (gcp_sensor.max_watts - gcp_sensor.min_watts) * 0.5 |
| 210 | + assert abs(energy_usage.host_energy_usage - expected_power) < 0.01 |
| 211 | + |
| 212 | + |
| 213 | +def test_gcp_sensor_should_return_error_when_instance_type_is_missing(): |
| 214 | + instance_type = "unknown-instance-type" |
| 215 | + |
| 216 | + with pytest.raises(GCPSensorException): |
| 217 | + GCPEnergyConsumption(instance_type=instance_type) |
| 218 | + |
| 219 | + |
| 220 | +def test_is_azure_should_return_false_on_exception(): |
| 221 | + assert Azure.is_azure() is False |
| 222 | + |
| 223 | + |
| 224 | +def test_is_azure_should_return_true(mocker): |
| 225 | + mock_response = mocker.Mock() |
| 226 | + mock_response.status_code = 200 |
| 227 | + mocker.patch.object(requests, "get", return_value=mock_response) |
| 228 | + |
| 229 | + assert Azure.is_azure() is True |
| 230 | + |
| 231 | + |
| 232 | +def test_azure_from_metadata(mocker): |
| 233 | + mock_response = mocker.Mock() |
| 234 | + mock_response.json.return_value = {"compute": {"vmSize": "Standard_D2s_v3", "location": "eastus"}} |
| 235 | + mocker.patch.object(requests, "get", return_value=mock_response) |
| 236 | + |
| 237 | + azure = Azure.from_metadata() |
| 238 | + |
| 239 | + assert azure.instance_type == "Standard_D2s_v3" |
| 240 | + assert azure.region_name == "eastus" |
| 241 | + |
| 242 | + |
| 243 | +@pytest.mark.asyncio |
| 244 | +async def test_azure_sensor_should_return_energy_consumption(mocker): |
| 245 | + azure_sensor = AzureEnergyConsumption(instance_type="D2 v3") |
| 246 | + |
| 247 | + assert azure_sensor.vcpus == 2.0 |
| 248 | + assert azure_sensor.memory_gb == 8.0 |
| 249 | + assert azure_sensor.min_watts > 0 |
| 250 | + assert azure_sensor.max_watts > azure_sensor.min_watts |
| 251 | + |
| 252 | + mocker.patch.object(HardwareInfo, "get_cpu_usage", return_value=50) |
| 253 | + from tracarbon.hardwares.gpu import GPUInfo |
| 254 | + |
| 255 | + mocker.patch.object(GPUInfo, "get_gpu_power_usage_or_none", return_value=None) |
| 256 | + |
| 257 | + energy_usage = await azure_sensor.get_energy_usage() |
| 258 | + |
| 259 | + expected_power = azure_sensor.min_watts + (azure_sensor.max_watts - azure_sensor.min_watts) * 0.5 |
| 260 | + assert abs(energy_usage.host_energy_usage - expected_power) < 0.01 |
| 261 | + |
| 262 | + |
| 263 | +def test_azure_sensor_should_return_error_when_instance_type_is_missing(): |
| 264 | + instance_type = "unknown-instance-type" |
| 265 | + |
| 266 | + with pytest.raises(AzureSensorException): |
| 267 | + AzureEnergyConsumption(instance_type=instance_type) |
0 commit comments