---
title: 'IntelliSIEM and Test-Driven Development: Creating Robust Error Handling and Log Rotation'
url: 'https://bsb.perryconsulting.net/blog/intellisiem-and-test-driven-development-creating-robust-error-handling-and-log-rotation'
markdown: 'https://bsb.perryconsulting.net/blog/intellisiem-and-test-driven-development-creating-robust-error-handling-and-log-rotation.md'
date: '2024-10-01'
description: "Previously, we implemented a basic testing framework to start handling data errors, corrupt data, and edge cases. In Part 4, we're going to kick it up a notch. It's time to implement robust error handling for each discrete task! We left off having implemented a basic testing framework to drive code implementation for edge cases and errors. Now we're going to build up that framework by developing tests specifically for each discrete function and attempting to ensure we have solid error handling for anything that comes our way. We're also going to implement log rotation while we're at it, to ensure that there's a reasonable amount of logs captured without taking up too much drive space. Let's get going! To see this project in its curr"
taxonomy:
  category:
    - projects
  tag:
    - python
    - security
  archives_month:
    - oct_2024
  archives_year:
    - '2024'
---

# IntelliSIEM and Test-Driven Development: Creating Robust Error Handling and Log Rotation

 01 OCT 2024  [python](https://bsb.perryconsulting.net/blog/tag:python) [security](https://bsb.perryconsulting.net/blog/tag:security)  

  *Previously, we implemented a basic testing framework to start handling data errors, corrupt data, and edge cases. In Part 4, we're going to* *kick it up a notch. It's time to implement robust error handling for each discrete task*!

We left off having implemented a basic testing framework to drive code implementation for edge cases and errors. Now we're going to build up that framework by developing tests specifically for each discrete function and attempting to ensure we have solid error handling for anything that comes our way. We're also going to implement log rotation while we're at it, to ensure that there's a reasonable amount of logs captured without taking up too much drive space. Let's get going!

To see this project in its current state, head over to my repo and check it out: [IntelliSIEM on GitHub](https://github.com/perryconsulting/IntelliSIEM)

---

### **Writing Better Tests To Drive Implementation**

One of the unwritten goals of this project is to develop the application while adhering to Test-Driven Development (TDD) principles as much as possible. This means writing tests first and then modifying our code to meet the expectations of those tests. One area where TDD is particularly effective is in implementing robust error handling. In this stage, the aim is to capture as many possible error scenarios in the data collection process as possible, such as invalid data types, missing keys, corrupt data, or empty responses. With those goals in mind, we need to refactor our tests, breaking related tests into their own files and adding more discrete tests to define better how the code should work. This can be a somewhat tedious process, so in the interest of not putting you through it all, here is the newly refactored test suite:

PYTHON

```
<span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 1</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  IntelliSIEM Copyright 2024, Rob Perry</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 2</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 3</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  Licensed under the Apache License, Version 2.0 (the "License");</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 4</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  you may not use this file except in compliance with the License.</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 5</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  You may obtain a copy of the License at</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 6</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 7</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">      http://www.apache.org/licenses/LICENSE-2.0</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 8</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 9</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  Unless required by applicable law or agreed to in writing, software</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">10</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  distributed under the License is distributed on an "AS IS" BASIS,</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">11</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">12</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  See the License for the specific language governing permissions and</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">13</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  limitations under the License.</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">14</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">15</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">import</span><span class="token"> </span><span class="token">pytest</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">16</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">import</span><span class="token"> </span><span class="token">requests</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">17</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">from</span><span class="token"> </span><span class="token">src</span><span class="token">.</span><span class="token">api_client</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">import</span><span class="token"> </span><span class="token">APIClient</span><span class="token">,</span><span class="token"> </span><span class="token">APIError</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">18</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">19</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">test_api_client_success</span><span class="token">(</span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">mocker</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">20</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">21</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    Test API client handling a successful request.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">22</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    This ensures that valid data is returned when the API call is successful.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">23</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">24</span><span class="token">    </span><span class="token">mock_response</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">[</span><span class="token">{</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">id</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">test_data</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">}</span><span class="token">]</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">25</span><span class="token">    </span><span class="token">mocker</span><span class="token">.</span><span class="token">patch</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">requests.get</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">26</span><span class="token">                 </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">return_value</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token">mocker</span><span class="token">.</span><span class="token">Mock</span><span class="token">(</span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">status_code</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">200</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">json</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token">mocker</span><span class="token">.</span><span class="token">Mock</span><span class="token">(</span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">return_value</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token">mock_response</span><span class="token">)</span><span class="token">)</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">27</span><span class="token">    </span><span class="token">client</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">APIClient</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">https://example.com/api</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">,</span><span class="token"> </span><span class="token">{</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Authorization</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Bearer token</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">}</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">28</span><span class="token">    </span><span class="token">result</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">client</span><span class="token">.</span><span class="token">get_data</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">endpoint</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">29</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">assert</span><span class="token"> </span><span class="token">result</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">==</span><span class="token"> </span><span class="token">mock_response</span><span class="token">  </span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc"> Expecting mock response data</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">30</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">31</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">test_api_client_timeout</span><span class="token">(</span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">mocker</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">32</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">33</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    Test API client handling of a timeout error.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">34</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    This ensures that the appropriate exception and message are raised and logged.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">35</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">36</span><span class="token">    </span><span class="token">mocker</span><span class="token">.</span><span class="token">patch</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">requests.get</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">side_effect</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token">requests</span><span class="token">.</span><span class="token">exceptions</span><span class="token">.</span><span class="token">Timeout</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">37</span><span class="token">    </span><span class="token">client</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">APIClient</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">https://example.com/api</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">,</span><span class="token"> </span><span class="token">{</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Authorization</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Bearer token</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">}</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">38</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">with</span><span class="token"> </span><span class="token">pytest</span><span class="token">.</span><span class="token">raises</span><span class="token">(</span><span class="token">APIError</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">match</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">API request timed out.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">39</span><span class="token">        </span><span class="token">client</span><span class="token">.</span><span class="token">get_data</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">endpoint</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">40</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">41</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">test_api_client_rate_limit</span><span class="token">(</span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">mocker</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">42</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">43</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    Test API client handling of rate limiting.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">44</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    This ensures that the APIError exception is raised when the rate limit is exceeded.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">45</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">46</span><span class="token">    </span><span class="token">mock_response</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">mocker</span><span class="token">.</span><span class="token">Mock</span><span class="token">(</span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">status_code</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">429</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">headers</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token">{</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Retry-After</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">5</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">}</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">47</span><span class="token">    </span><span class="token">mocker</span><span class="token">.</span><span class="token">patch</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">requests.get</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">return_value</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token">mock_response</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">48</span><span class="token">    </span><span class="token">client</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">APIClient</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">https://example.com/api</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">,</span><span class="token"> </span><span class="token">{</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Authorization</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Bearer token</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">}</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">49</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">with</span><span class="token"> </span><span class="token">pytest</span><span class="token">.</span><span class="token">raises</span><span class="token">(</span><span class="token">APIError</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">match</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Rate limit exceeded.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">50</span><span class="token">        </span><span class="token">client</span><span class="token">.</span><span class="token">get_data</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">endpoint</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">51</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">52</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">test_api_client_invalid_json</span><span class="token">(</span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">mocker</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">53</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">54</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    Test API client handling of invalid JSON response.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">55</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    This test simulates a ValueError when the JSON response is not valid.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">56</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">57</span><span class="token">    </span><span class="token">mock_response</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">mocker</span><span class="token">.</span><span class="token">Mock</span><span class="token">(</span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">status_code</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">200</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">json</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token">mocker</span><span class="token">.</span><span class="token">Mock</span><span class="token">(</span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">side_effect</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">ValueError</span><span class="token">)</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">58</span><span class="token">    </span><span class="token">mocker</span><span class="token">.</span><span class="token">patch</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">requests.get</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">return_value</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token">mock_response</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">59</span><span class="token">    </span><span class="token">client</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">APIClient</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">https://example.com/api</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">,</span><span class="token"> </span><span class="token">{</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Authorization</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Bearer token</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">}</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">60</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">with</span><span class="token"> </span><span class="token">pytest</span><span class="token">.</span><span class="token">raises</span><span class="token">(</span><span class="token">APIError</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">match</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Invalid response format.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">61</span><span class="token">        </span><span class="token">client</span><span class="token">.</span><span class="token">get_data</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">endpoint</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">62</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">63</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">test_api_client_connection_error</span><span class="token">(</span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">mocker</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">64</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">65</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    Test API client handling of a connection error.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">66</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    This ensures that connection issues are properly caught and logged.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">67</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">68</span><span class="token">    </span><span class="token">mocker</span><span class="token">.</span><span class="token">patch</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">requests.get</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">side_effect</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token">requests</span><span class="token">.</span><span class="token">ConnectionError</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">69</span><span class="token">    </span><span class="token">client</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">APIClient</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">https://example.com/api</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">,</span><span class="token"> </span><span class="token">{</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Authorization</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Bearer token</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">}</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">70</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">with</span><span class="token"> </span><span class="token">pytest</span><span class="token">.</span><span class="token">raises</span><span class="token">(</span><span class="token">APIError</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">match</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Connection error occurred.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">71</span><span class="token">        </span><span class="token">client</span><span class="token">.</span><span class="token">get_data</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">endpoint</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">72</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">73</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">test_api_client_authentication_error</span><span class="token">(</span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">mocker</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">74</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">75</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    Test API client handling of an authentication error.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">76</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    This simulates an authentication failure with a 401 status code.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">77</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">78</span><span class="token">    </span><span class="token">mock_response</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">mocker</span><span class="token">.</span><span class="token">Mock</span><span class="token">(</span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">status_code</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">401</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">79</span><span class="token">    </span><span class="token">mocker</span><span class="token">.</span><span class="token">patch</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">requests.get</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">return_value</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token">mock_response</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">80</span><span class="token">    </span><span class="token">client</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">APIClient</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">https://example.com/api</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">,</span><span class="token"> </span><span class="token">{</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Authorization</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Invalid token</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">}</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">81</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">with</span><span class="token"> </span><span class="token">pytest</span><span class="token">.</span><span class="token">raises</span><span class="token">(</span><span class="token">APIError</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">match</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Authentication failed.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">82</span><span class="token">        </span><span class="token">client</span><span class="token">.</span><span class="token">get_data</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">endpoint</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">83</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">84</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">test_api_client_permission_error</span><span class="token">(</span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">mocker</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">85</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">86</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    Test API client handling of a permission error.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">87</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    This simulates a permission failure with a 403 status code.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">88</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">89</span><span class="token">    </span><span class="token">mock_response</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">mocker</span><span class="token">.</span><span class="token">Mock</span><span class="token">(</span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">status_code</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">403</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">90</span><span class="token">    </span><span class="token">mocker</span><span class="token">.</span><span class="token">patch</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">requests.get</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">return_value</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token">mock_response</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">91</span><span class="token">    </span><span class="token">client</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">APIClient</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">https://example.com/api</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">,</span><span class="token"> </span><span class="token">{</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Authorization</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Bearer token</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">}</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">92</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">with</span><span class="token"> </span><span class="token">pytest</span><span class="token">.</span><span class="token">raises</span><span class="token">(</span><span class="token">APIError</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">match</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Permission denied.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">93</span><span class="token">        </span><span class="token">client</span><span class="token">.</span><span class="token">get_data</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">endpoint</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span>
```

PYTHON

```
<span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 1</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  IntelliSIEM Copyright 2024, Rob Perry</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 2</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 3</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  Licensed under the Apache License, Version 2.0 (the "License");</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 4</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  you may not use this file except in compliance with the License.</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 5</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  You may obtain a copy of the License at</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 6</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 7</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">      http://www.apache.org/licenses/LICENSE-2.0</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 8</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 9</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  Unless required by applicable law or agreed to in writing, software</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">10</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  distributed under the License is distributed on an "AS IS" BASIS,</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">11</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">12</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  See the License for the specific language governing permissions and</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">13</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  limitations under the License.</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">14</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">15</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">import</span><span class="token"> </span><span class="token">pytest</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">16</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">from</span><span class="token"> </span><span class="token">src</span><span class="token">.</span><span class="token">config</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">import</span><span class="token"> </span><span class="token">load_config</span><span class="token">,</span><span class="token"> </span><span class="token">ConfigError</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">17</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">18</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">test_load_config_success</span><span class="token">(</span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">mocker</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">19</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">20</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    Test successful loading of the configuration file.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">21</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    This ensures that a valid configuration is loaded and returned correctly.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">22</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">23</span><span class="token">    </span><span class="token">mock_config</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">24</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    api_keys:
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">25</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">        alien_vault: "VALID_ALIEN_VAULT_API_KEY"
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">26</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">        virus_total: "VALID_VIRUS_TOTAL_API_KEY"
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">27</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">28</span><span class="token">    </span><span class="token">mocker</span><span class="token">.</span><span class="token">patch</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">builtins.open</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">,</span><span class="token"> </span><span class="token">mocker</span><span class="token">.</span><span class="token">mock_open</span><span class="token">(</span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">read_data</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token">mock_config</span><span class="token">)</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">29</span><span class="token">    </span><span class="token">config</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">load_config</span><span class="token">(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">30</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">assert</span><span class="token"> </span><span class="token">config</span><span class="token">[</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">api_keys</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">]</span><span class="token">[</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">alien_vault</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">]</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">==</span><span class="token"> </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">VALID_ALIEN_VAULT_API_KEY</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">31</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">assert</span><span class="token"> </span><span class="token">config</span><span class="token">[</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">api_keys</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">]</span><span class="token">[</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">virus_total</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">]</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">==</span><span class="token"> </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">VALID_VIRUS_TOTAL_API_KEY</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">32</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">33</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">test_load_config_missing_file</span><span class="token">(</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">34</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">35</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    Test configuration loading with a missing file.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">36</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    This ensures that a FileNotFoundError is raised when the config file does not exist.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">37</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">38</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">with</span><span class="token"> </span><span class="token">pytest</span><span class="token">.</span><span class="token">raises</span><span class="token">(</span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">FileNotFoundError</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">39</span><span class="token">        </span><span class="token">load_config</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">config/non_existent_config.yaml</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">40</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">41</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">test_load_config_invalid_format</span><span class="token">(</span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">mocker</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">42</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">43</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    Test configuration loading with an invalid format.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">44</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    This simulates an invalid YAML format and expects a ConfigError.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">45</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">46</span><span class="token">    </span><span class="token">invalid_yaml</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">47</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    api_keys:
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">48</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">        alien_vault: !!invalid
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">49</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">50</span><span class="token">    </span><span class="token">mocker</span><span class="token">.</span><span class="token">patch</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">builtins.open</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">,</span><span class="token"> </span><span class="token">mocker</span><span class="token">.</span><span class="token">mock_open</span><span class="token">(</span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">read_data</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token">invalid_yaml</span><span class="token">)</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">51</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">with</span><span class="token"> </span><span class="token">pytest</span><span class="token">.</span><span class="token">raises</span><span class="token">(</span><span class="token">ConfigError</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">match</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Configuration file error.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">52</span><span class="token">        </span><span class="token">load_config</span><span class="token">(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">53</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">54</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">test_load_config_permission_error</span><span class="token">(</span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">mocker</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">55</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">56</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    Test configuration loading with a permission error.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">57</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    This simulates a PermissionError when accessing the config file.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">58</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">59</span><span class="token">    </span><span class="token">mock_open</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">mocker</span><span class="token">.</span><span class="token">patch</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">builtins.open</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">,</span><span class="token"> </span><span class="token">mocker</span><span class="token">.</span><span class="token">mock_open</span><span class="token">(</span><span class="token">)</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">60</span><span class="token">    </span><span class="token">mock_open</span><span class="token">.</span><span class="token">side_effect</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">PermissionError</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">61</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">with</span><span class="token"> </span><span class="token">pytest</span><span class="token">.</span><span class="token">raises</span><span class="token">(</span><span class="token">ConfigError</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">match</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Permission denied for config file.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">62</span><span class="token">        </span><span class="token">load_config</span><span class="token">(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">63</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">64</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">test_load_config_disk_space_error</span><span class="token">(</span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">mocker</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">65</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">66</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    Test configuration loading with a disk space error.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">67</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    This simulates an OSError due to lack of disk space.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">68</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">69</span><span class="token">    </span><span class="token">mock_open</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">mocker</span><span class="token">.</span><span class="token">patch</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">builtins.open</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">,</span><span class="token"> </span><span class="token">mocker</span><span class="token">.</span><span class="token">mock_open</span><span class="token">(</span><span class="token">)</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">70</span><span class="token">    </span><span class="token">mock_open</span><span class="token">.</span><span class="token">side_effect</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">OSError</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">No space left on device</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">71</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">with</span><span class="token"> </span><span class="token">pytest</span><span class="token">.</span><span class="token">raises</span><span class="token">(</span><span class="token">ConfigError</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">match</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Disk space issue while loading configuration.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">72</span><span class="token">        </span><span class="token">load_config</span><span class="token">(</span><span class="token">)</span><span class="token">
</span></span>
```

PYTHON

```
<span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 1</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  IntelliSIEM Copyright 2024, Rob Perry</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 2</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 3</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  Licensed under the Apache License, Version 2.0 (the "License");</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 4</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  you may not use this file except in compliance with the License.</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 5</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  You may obtain a copy of the License at</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 6</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 7</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">      http://www.apache.org/licenses/LICENSE-2.0</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 8</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 9</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  Unless required by applicable law or agreed to in writing, software</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">10</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  distributed under the License is distributed on an "AS IS" BASIS,</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">11</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">12</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  See the License for the specific language governing permissions and</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">13</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  limitations under the License.</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">14</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc"> tests/test_data_collection.py</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">15</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">16</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">import</span><span class="token"> </span><span class="token">pytest</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">17</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">from</span><span class="token"> </span><span class="token">src</span><span class="token">.</span><span class="token">data_collection</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">import</span><span class="token"> </span><span class="token">fetch_threat_data</span><span class="token">,</span><span class="token"> </span><span class="token">DataError</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">18</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">19</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">test_fetch_threat_data_success</span><span class="token">(</span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">mocker</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">20</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">21</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    Test successful fetching of threat data.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">22</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    This ensures that data is correctly collected from the APIs and returned.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">23</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">24</span><span class="token">    </span><span class="token">mock_data_alien</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">[</span><span class="token">{</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">id</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">test1</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">}</span><span class="token">]</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">25</span><span class="token">    </span><span class="token">mock_data_virus</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">[</span><span class="token">{</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">id</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">test2</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">}</span><span class="token">]</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">26</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">27</span><span class="token">    </span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc"> Create separate mock instances for each APIClient</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">28</span><span class="token">    </span><span class="token">mock_alien_vault_client</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">mocker</span><span class="token">.</span><span class="token">Mock</span><span class="token">(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">29</span><span class="token">    </span><span class="token">mock_alien_vault_client</span><span class="token">.</span><span class="token">get_data</span><span class="token">.</span><span class="token">return_value</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">mock_data_alien</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">30</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">31</span><span class="token">    </span><span class="token">mock_virus_total_client</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">mocker</span><span class="token">.</span><span class="token">Mock</span><span class="token">(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">32</span><span class="token">    </span><span class="token">mock_virus_total_client</span><span class="token">.</span><span class="token">get_data</span><span class="token">.</span><span class="token">return_value</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">mock_data_virus</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">33</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">34</span><span class="token">    </span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc"> Patch the APIClient constructor to return the respective mock instances</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">35</span><span class="token">    </span><span class="token">mocker</span><span class="token">.</span><span class="token">patch</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">src.data_collection.APIClient</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">side_effect</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token">[</span><span class="token">mock_alien_vault_client</span><span class="token">,</span><span class="token"> </span><span class="token">mock_virus_total_client</span><span class="token">]</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">36</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">37</span><span class="token">    </span><span class="token">threats</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">fetch_threat_data</span><span class="token">(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">38</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">39</span><span class="token">    </span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc"> Verify that the mock was called only once per client</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">40</span><span class="token">    </span><span class="token">mock_alien_vault_client</span><span class="token">.</span><span class="token">get_data</span><span class="token">.</span><span class="token">assert_called_once</span><span class="token">(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">41</span><span class="token">    </span><span class="token">mock_virus_total_client</span><span class="token">.</span><span class="token">get_data</span><span class="token">.</span><span class="token">assert_called_once</span><span class="token">(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">42</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">43</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">assert</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">len</span><span class="token">(</span><span class="token">threats</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">==</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">2</span><span class="token">  </span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc"> Expecting two entries: one from each mock data list</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">44</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">assert</span><span class="token"> </span><span class="token">threats</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">==</span><span class="token"> </span><span class="token">[</span><span class="token">{</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">id</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">test1</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">}</span><span class="token">,</span><span class="token"> </span><span class="token">{</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">id</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">test2</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">}</span><span class="token">]</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">45</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">46</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">test_fetch_threat_data_missing_keys</span><span class="token">(</span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">mocker</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">47</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">48</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    Test data collection handling of missing required data keys.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">49</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    This ensures that missing keys in the data trigger the appropriate exception.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">50</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">51</span><span class="token">    </span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc"> Mock get_data to return an entry missing the required 'id' key</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">52</span><span class="token">    </span><span class="token">mocker</span><span class="token">.</span><span class="token">patch</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">src.api_client.APIClient.get_data</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">return_value</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token">[</span><span class="token">{</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">missing_key</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">value</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">}</span><span class="token">]</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">53</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">with</span><span class="token"> </span><span class="token">pytest</span><span class="token">.</span><span class="token">raises</span><span class="token">(</span><span class="token">DataError</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">match</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Missing required data keys.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">54</span><span class="token">        </span><span class="token">fetch_threat_data</span><span class="token">(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">55</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">56</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">test_fetch_threat_data_corrupt_data</span><span class="token">(</span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">mocker</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">57</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">58</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    Test data collection handling of corrupt data.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">59</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    This ensures that corrupt data is caught and triggers the DataError exception.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">60</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">61</span><span class="token">    </span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc"> Mock get_data to return structurally corrupt data with an unexpected type for 'id'</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">62</span><span class="token">    </span><span class="token">mocker</span><span class="token">.</span><span class="token">patch</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">src.api_client.APIClient.get_data</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">63</span><span class="token">                 </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">return_value</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token">[</span><span class="token">{</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">id</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">:</span><span class="token"> </span><span class="token">{</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">unexpected</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">dict</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">}</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">nested_data</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">:</span><span class="token"> </span><span class="token">[</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">unexpected_list</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">]</span><span class="token">}</span><span class="token">]</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">64</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">65</span><span class="token">    </span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc"> Expect DataError to be raised for corrupt data</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">66</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">with</span><span class="token"> </span><span class="token">pytest</span><span class="token">.</span><span class="token">raises</span><span class="token">(</span><span class="token">DataError</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">match</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Corrupt data received.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">67</span><span class="token">        </span><span class="token">fetch_threat_data</span><span class="token">(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">68</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">69</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">test_fetch_threat_data_empty_response</span><span class="token">(</span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">mocker</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">70</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">71</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    Test fetching threat data with an empty response.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">72</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    This ensures that the function handles empty responses gracefully.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">73</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">74</span><span class="token">    </span><span class="token">mocker</span><span class="token">.</span><span class="token">patch</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">src.api_client.APIClient.get_data</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">return_value</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token">[</span><span class="token">]</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">75</span><span class="token">    </span><span class="token">threats</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">fetch_threat_data</span><span class="token">(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">76</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">assert</span><span class="token"> </span><span class="token">threats</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">==</span><span class="token"> </span><span class="token">[</span><span class="token">]</span><span class="token">  </span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc"> Expecting an empty list when no data is returned</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">77</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">78</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">test_fetch_threat_data_invalid_data_type</span><span class="token">(</span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">mocker</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">79</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">80</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    Test data collection handling of invalid data type.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">81</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    This simulates an unexpected data type from the API response.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">82</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">83</span><span class="token">    </span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc"> Mock get_data to return a non-list data type, such as a string</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">84</span><span class="token">    </span><span class="token">mocker</span><span class="token">.</span><span class="token">patch</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">src.api_client.APIClient.get_data</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">return_value</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">invalid_data</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">85</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">with</span><span class="token"> </span><span class="token">pytest</span><span class="token">.</span><span class="token">raises</span><span class="token">(</span><span class="token">DataError</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">match</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Unexpected data type received.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">86</span><span class="token">        </span><span class="token">fetch_threat_data</span><span class="token">(</span><span class="token">)</span><span class="token">
</span></span>
```

PYTHON

```
<span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 1</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  IntelliSIEM Copyright 2024, Rob Perry</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 2</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 3</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  Licensed under the Apache License, Version 2.0 (the "License");</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 4</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  you may not use this file except in compliance with the License.</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 5</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  You may obtain a copy of the License at</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 6</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 7</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">      http://www.apache.org/licenses/LICENSE-2.0</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 8</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 9</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  Unless required by applicable law or agreed to in writing, software</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">10</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  distributed under the License is distributed on an "AS IS" BASIS,</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">11</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">12</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  See the License for the specific language governing permissions and</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">13</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  limitations under the License.</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">14</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">15</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">import</span><span class="token"> </span><span class="token">pytest</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">16</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">from</span><span class="token"> </span><span class="token">src</span><span class="token">.</span><span class="token">error_handling</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">import</span><span class="token"> </span><span class="token">APIError</span><span class="token">,</span><span class="token"> </span><span class="token">ConfigError</span><span class="token">,</span><span class="token"> </span><span class="token">DataError</span><span class="token">,</span><span class="token"> </span><span class="token">log_error</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">17</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">import</span><span class="token"> </span><span class="token">logging</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">18</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">19</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">test_api_error</span><span class="token">(</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">20</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">21</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    Test that the APIError exception can be raised and caught correctly.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">22</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">23</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">with</span><span class="token"> </span><span class="token">pytest</span><span class="token">.</span><span class="token">raises</span><span class="token">(</span><span class="token">APIError</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">match</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">API issue occurred</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">24</span><span class="token">        </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">raise</span><span class="token"> </span><span class="token">APIError</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">API issue occurred.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">25</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">26</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">test_config_error</span><span class="token">(</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">27</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">28</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    Test that the ConfigError exception can be raised and caught correctly.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">29</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">30</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">with</span><span class="token"> </span><span class="token">pytest</span><span class="token">.</span><span class="token">raises</span><span class="token">(</span><span class="token">ConfigError</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">match</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Configuration issue occurred</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">31</span><span class="token">        </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">raise</span><span class="token"> </span><span class="token">ConfigError</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Configuration issue occurred.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">32</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">33</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">test_data_error</span><span class="token">(</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">34</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">35</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    Test that the DataError exception can be raised and caught correctly.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">36</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">37</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">with</span><span class="token"> </span><span class="token">pytest</span><span class="token">.</span><span class="token">raises</span><span class="token">(</span><span class="token">DataError</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">match</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Data issue occurred</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">38</span><span class="token">        </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">raise</span><span class="token"> </span><span class="token">DataError</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Data issue occurred.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">39</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">40</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">test_log_error</span><span class="token">(</span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">mocker</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">41</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">42</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    Test that the log_error function logs an error message correctly.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">43</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">44</span><span class="token">    </span><span class="token">mocker</span><span class="token">.</span><span class="token">patch</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">logging.error</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">45</span><span class="token">    </span><span class="token">log_error</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Test error message.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">46</span><span class="token">    </span><span class="token">logging</span><span class="token">.</span><span class="token">error</span><span class="token">.</span><span class="token">assert_called_once_with</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Test error message.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">47</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">48</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">test_log_warning</span><span class="token">(</span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">mocker</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">49</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">50</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    Test that the log_error function logs a warning message correctly.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">51</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">52</span><span class="token">    </span><span class="token">mocker</span><span class="token">.</span><span class="token">patch</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">logging.warning</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">53</span><span class="token">    </span><span class="token">log_error</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Test warning message.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">level</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">WARNING</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">54</span><span class="token">    </span><span class="token">logging</span><span class="token">.</span><span class="token">warning</span><span class="token">.</span><span class="token">assert_called_once_with</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Test warning message.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">55</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">56</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">test_log_info</span><span class="token">(</span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">mocker</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">57</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">58</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    Test that the log_error function logs an informational message correctly.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">59</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">60</span><span class="token">    </span><span class="token">mocker</span><span class="token">.</span><span class="token">patch</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">logging.info</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">61</span><span class="token">    </span><span class="token">log_error</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Test info message.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">level</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">INFO</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">62</span><span class="token">    </span><span class="token">logging</span><span class="token">.</span><span class="token">info</span><span class="token">.</span><span class="token">assert_called_once_with</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Test info message.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span>
```

PYTHON

```
<span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 1</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  IntelliSIEM Copyright 2024, Rob Perry</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 2</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 3</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  Licensed under the Apache License, Version 2.0 (the "License");</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 4</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  you may not use this file except in compliance with the License.</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 5</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  You may obtain a copy of the License at</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 6</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 7</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">      http://www.apache.org/licenses/LICENSE-2.0</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 8</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 9</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  Unless required by applicable law or agreed to in writing, software</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">10</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  distributed under the License is distributed on an "AS IS" BASIS,</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">11</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">12</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  See the License for the specific language governing permissions and</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">13</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  limitations under the License.</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">14</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">15</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">import</span><span class="token"> </span><span class="token">logging</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">16</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">import</span><span class="token"> </span><span class="token">os</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">17</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">from</span><span class="token"> </span><span class="token">logging</span><span class="token">.</span><span class="token">handlers</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">import</span><span class="token"> </span><span class="token">RotatingFileHandler</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">18</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">import</span><span class="token"> </span><span class="token">pytest</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">19</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">20</span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">@</span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">pytest</span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">.</span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">fixture</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">21</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">setup_rotating_log</span><span class="token">(</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">22</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">23</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    Set up a rotating log handler for testing.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">24</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">25</span><span class="token">    </span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc"> Define the log file path and cleanup if exists</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">26</span><span class="token">    </span><span class="token">log_file</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">data/test_error.log</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">27</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">for</span><span class="token"> </span><span class="token">i</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">in</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">range</span><span class="token">(</span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">6</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">28</span><span class="token">        </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">try</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">29</span><span class="token">            </span><span class="token">os</span><span class="token">.</span><span class="token">remove</span><span class="token">(</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">f</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">{</span><span class="token">log_file</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">}</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">.</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">{</span><span class="token">i</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">}</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">30</span><span class="token">        </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">except</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">FileNotFoundError</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">31</span><span class="token">            </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">pass</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">32</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">try</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">33</span><span class="token">        </span><span class="token">os</span><span class="token">.</span><span class="token">remove</span><span class="token">(</span><span class="token">log_file</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">34</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">except</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">FileNotFoundError</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">35</span><span class="token">        </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">pass</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">36</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">37</span><span class="token">    </span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc"> Set up rotating file handler</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">38</span><span class="token">    </span><span class="token">handler</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">RotatingFileHandler</span><span class="token">(</span><span class="token">log_file</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">maxBytes</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">200</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">backupCount</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">5</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">39</span><span class="token">    </span><span class="token">handler</span><span class="token">.</span><span class="token">setLevel</span><span class="token">(</span><span class="token">logging</span><span class="token">.</span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">ERROR</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">40</span><span class="token">    </span><span class="token">handler</span><span class="token">.</span><span class="token">setFormatter</span><span class="token">(</span><span class="token">logging</span><span class="token">.</span><span class="token">Formatter</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">%(asctime)s</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">%(levelname)s</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">: </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">%(message)s</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">)</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">41</span><span class="token">    </span><span class="token">logger</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">logging</span><span class="token">.</span><span class="token">getLogger</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">test_logger</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">42</span><span class="token">    </span><span class="token">logger</span><span class="token">.</span><span class="token">setLevel</span><span class="token">(</span><span class="token">logging</span><span class="token">.</span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">ERROR</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">43</span><span class="token">    </span><span class="token">logger</span><span class="token">.</span><span class="token">addHandler</span><span class="token">(</span><span class="token">handler</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">44</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">return</span><span class="token"> </span><span class="token">logger</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">45</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">46</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">test_log_rotation</span><span class="token">(</span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">setup_rotating_log</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">47</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">48</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    Test log rotation by generating log entries to exceed maxBytes limit.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">49</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">50</span><span class="token">    </span><span class="token">logger</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">setup_rotating_log</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">51</span><span class="token">    </span><span class="token">log_message</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">This is a test log message to fill up the log file and trigger rotation.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">52</span><span class="token">    </span><span class="token">log_file</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">data/test_error.log</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">53</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">54</span><span class="token">    </span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc"> Write multiple log entries to exceed the maxBytes limit</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">55</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">for</span><span class="token"> </span><span class="token">_</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">in</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">range</span><span class="token">(</span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">50</span><span class="token">)</span><span class="token">:</span><span class="token">  </span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc"> Increase number of entries if needed</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">56</span><span class="token">        </span><span class="token">logger</span><span class="token">.</span><span class="token">error</span><span class="token">(</span><span class="token">log_message</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">57</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">58</span><span class="token">    </span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc"> Ensure the main log file and at least one backup exist</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">59</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">assert</span><span class="token"> </span><span class="token">os</span><span class="token">.</span><span class="token">path</span><span class="token">.</span><span class="token">exists</span><span class="token">(</span><span class="token">log_file</span><span class="token">)</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">f</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Log file </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">{</span><span class="token">log_file</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">}</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff"> does not exist.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">60</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">assert</span><span class="token"> </span><span class="token">os</span><span class="token">.</span><span class="token">path</span><span class="token">.</span><span class="token">exists</span><span class="token">(</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">f</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">{</span><span class="token">log_file</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">}</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">.1</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">f</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Backup log file </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">{</span><span class="token">log_file</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">}</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">.1 does not exist.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">
</span></span>
```

I know there's a lot there, and the TDD purists among you are probably having an apoplectic fit at the moment (I can hear it now: You can't write all these tests in one shot and be doing TDD right!). Please don't misunderstand me, the design and implementation of these tests took considerable time and didn't happen in a vacuum. Each test was designed individually, with the satisfying function developed and modified after each test. Sometimes, the original tests were inadequate or poorly designed and needed reworking. Other tests made a previous implementation fail a prior test and required rethinking the overall approach to allow both tests to pass. This is the most fun and, honestly, the most challenging part for me. I love puzzles, and trying to figure out how to make all these tests simultaneously true is a giant puzzle. The hardest part was probably making the data collection tests pass, specifically the tests for corrupt data, empty responses, and invalid data types. Finding a way through that maze to ensure all three were covered took the most time.

### **Writing Better Functions Based On Tests**

Remember, if you run PyTest right now, there will be a lot of failures because none of the new tests have complementary implementations to meet the requirements. Now that you can see how the tests are designed and what we're testing for let's take a look at how each one was solved.

Let's start by taking a look at `error_handling.py` where I added some new custom exceptions and updated the logging to handle different error levels:

PYTHON

```
<span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 1</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  IntelliSIEM Copyright 2024, Rob Perry</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 2</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 3</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  Licensed under the Apache License, Version 2.0 (the "License");</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 4</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  you may not use this file except in compliance with the License.</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 5</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  You may obtain a copy of the License at</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 6</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 7</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">      http://www.apache.org/licenses/LICENSE-2.0</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 8</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 9</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  Unless required by applicable law or agreed to in writing, software</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">10</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  distributed under the License is distributed on an "AS IS" BASIS,</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">11</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">12</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  See the License for the specific language governing permissions and</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">13</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  limitations under the License.</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">14</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">15</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">import</span><span class="token"> </span><span class="token">logging</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">16</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">from</span><span class="token"> </span><span class="token">logging</span><span class="token">.</span><span class="token">handlers</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">import</span><span class="token"> </span><span class="token">RotatingFileHandler</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">17</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">18</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc"> Set up rotating file handler</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">19</span><span class="token">handler</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">RotatingFileHandler</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">data/error.log</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">maxBytes</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">1000000</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">backupCount</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">5</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">20</span><span class="token">handler</span><span class="token">.</span><span class="token">setLevel</span><span class="token">(</span><span class="token">logging</span><span class="token">.</span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">ERROR</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">21</span><span class="token">handler</span><span class="token">.</span><span class="token">setFormatter</span><span class="token">(</span><span class="token">logging</span><span class="token">.</span><span class="token">Formatter</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">%(asctime)s</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">%(levelname)s</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">: </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">%(message)s</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">)</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">22</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">23</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc"> Add the handler to the root logger</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">24</span><span class="token">logging</span><span class="token">.</span><span class="token">basicConfig</span><span class="token">(</span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">level</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token">logging</span><span class="token">.</span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">ERROR</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">handlers</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token">[</span><span class="token">handler</span><span class="token">]</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">25</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">26</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">class</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">APIError</span><span class="token">(</span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">Exception</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">27</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Custom exception for API-related errors.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">28</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">pass</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">29</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">30</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">class</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">ConfigError</span><span class="token">(</span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">Exception</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">31</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Custom exception for configuration-related errors.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">32</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">pass</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">33</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">34</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">class</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">DataError</span><span class="token">(</span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">Exception</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">35</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Custom exception for data processing errors.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">36</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">pass</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">37</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">38</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">log_error</span><span class="token">(</span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">message</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">level</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">ERROR</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">39</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">40</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    Log error messages to a file with severity level.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">41</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">42</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    :param message: (str) The error message to log.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">43</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    :param level: (str) The severity level (default is "ERROR").
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">44</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">45</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">if</span><span class="token"> </span><span class="token">level</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">==</span><span class="token"> </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">WARNING</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">46</span><span class="token">        </span><span class="token">logging</span><span class="token">.</span><span class="token">warning</span><span class="token">(</span><span class="token">message</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">47</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">elif</span><span class="token"> </span><span class="token">level</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">==</span><span class="token"> </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">INFO</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">48</span><span class="token">        </span><span class="token">logging</span><span class="token">.</span><span class="token">info</span><span class="token">(</span><span class="token">message</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">49</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">else</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">50</span><span class="token">        </span><span class="token">logging</span><span class="token">.</span><span class="token">error</span><span class="token">(</span><span class="token">message</span><span class="token">)</span><span class="token">
</span></span>
```

Along with the new exceptions and better logging, I also added the rotating file handler to keep log files under control. While the test handler was built with a 200KB, the actual implementation uses a 1MB cutoff to trigger rotation.

The next area of focus was the config.py implementation. Here, the focus was predominantly on config file issues such as a missing file, insufficient permissions, or parsing errors.

PYTHON

```
<span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 1</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  IntelliSIEM Copyright 2024, Rob Perry</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 2</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 3</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  Licensed under the Apache License, Version 2.0 (the "License");</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 4</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  you may not use this file except in compliance with the License.</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 5</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  You may obtain a copy of the License at</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 6</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 7</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">      http://www.apache.org/licenses/LICENSE-2.0</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 8</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 9</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  Unless required by applicable law or agreed to in writing, software</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">10</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  distributed under the License is distributed on an "AS IS" BASIS,</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">11</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">12</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  See the License for the specific language governing permissions and</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">13</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  limitations under the License.</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">14</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">15</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">import</span><span class="token"> </span><span class="token">yaml</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">16</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">from</span><span class="token"> </span><span class="token">src</span><span class="token">.</span><span class="token">error_handling</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">import</span><span class="token"> </span><span class="token">log_error</span><span class="token">,</span><span class="token"> </span><span class="token">ConfigError</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">17</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">18</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">load_config</span><span class="token">(</span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">config_file</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">config/config.yaml</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">19</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">20</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    Load configuration from the specified YAML file.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">21</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">22</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    :param config_file: (str) The path to the YAML configuration file.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">23</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    :return: dict: Configuration data.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">24</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    :raises ConfigError: If there is an error with the configuration file.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">25</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">26</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">try</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">27</span><span class="token">        </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">with</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">open</span><span class="token">(</span><span class="token">config_file</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">r</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">as</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">file</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">28</span><span class="token">            </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">return</span><span class="token"> </span><span class="token">yaml</span><span class="token">.</span><span class="token">safe_load</span><span class="token">(</span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">file</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">29</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">except</span><span class="token"> </span><span class="token">yaml</span><span class="token">.</span><span class="token">YAMLError</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">as</span><span class="token"> </span><span class="token">e</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">30</span><span class="token">        </span><span class="token">log_error</span><span class="token">(</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">f</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">YAML parsing error while loading configuration: </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">{</span><span class="token">e</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">}</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">31</span><span class="token">        </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">raise</span><span class="token"> </span><span class="token">ConfigError</span><span class="token">(</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">f</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Configuration file error: </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">{</span><span class="token">e</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">}</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">32</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">except</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">FileNotFoundError</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">33</span><span class="token">        </span><span class="token">log_error</span><span class="token">(</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">f</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Configuration file not found: </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">{</span><span class="token">config_file</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">}</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">34</span><span class="token">        </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">raise</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">FileNotFoundError</span><span class="token">(</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">f</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Configuration file not found: </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">{</span><span class="token">config_file</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">}</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">35</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">except</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">PermissionError</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">36</span><span class="token">        </span><span class="token">log_error</span><span class="token">(</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">f</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Permission denied for config file: </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">{</span><span class="token">config_file</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">}</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">37</span><span class="token">        </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">raise</span><span class="token"> </span><span class="token">ConfigError</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Permission denied for config file.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">38</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">except</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">OSError</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">as</span><span class="token"> </span><span class="token">e</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">39</span><span class="token">        </span><span class="token">log_error</span><span class="token">(</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">f</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Disk space issue while loading configuration: </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">{</span><span class="token">e</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">}</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">40</span><span class="token">        </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">raise</span><span class="token"> </span><span class="token">ConfigError</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Disk space issue while loading configuration.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span>
```

I anticipate quite a bit more work in this implementation when I circle back to implement stronger security controls around the API keys.

The API client itself took quite a bit of reworking, especially when working through the different exceptions and how to isolate the tests correctly to ensure I was getting valid results:

PYTHON

```
<span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 1</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  IntelliSIEM Copyright 2024, Rob Perry</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 2</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 3</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  Licensed under the Apache License, Version 2.0 (the "License");</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 4</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  you may not use this file except in compliance with the License.</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 5</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  You may obtain a copy of the License at</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 6</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 7</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">      http://www.apache.org/licenses/LICENSE-2.0</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 8</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 9</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  Unless required by applicable law or agreed to in writing, software</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">10</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  distributed under the License is distributed on an "AS IS" BASIS,</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">11</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">12</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  See the License for the specific language governing permissions and</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">13</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  limitations under the License.</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">14</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">15</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">import</span><span class="token"> </span><span class="token">requests</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">16</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">from</span><span class="token"> </span><span class="token">src</span><span class="token">.</span><span class="token">error_handling</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">import</span><span class="token"> </span><span class="token">APIError</span><span class="token">,</span><span class="token"> </span><span class="token">log_error</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">17</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">18</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">class</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">APIClient</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">19</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">20</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    A client for interacting with various threat intelligence APIs.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">21</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">22</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">23</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">__init__</span><span class="token">(</span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">self</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">base_url</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">headers</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">24</span><span class="token">        </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">25</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">        Initialize the API client with the base URL and headers.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">26</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">27</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">        :param base_url: (str) The base URL of the API.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">28</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">        :param headers: (dict) Headers required for API requests.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">29</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">        </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">30</span><span class="token">        </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">self</span><span class="token">.</span><span class="token">base_url</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">base_url</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">31</span><span class="token">        </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">self</span><span class="token">.</span><span class="token">headers</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">headers</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">32</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">33</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">get_data</span><span class="token">(</span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">self</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">endpoint</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #0e1116;;--phiki-dark-color: #f0f3f6">params</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">None</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">34</span><span class="token">        </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">35</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">        Fetch data from the specified endpoint.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">36</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">37</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">        :param endpoint: (str) The API endpoint to fetch data from.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">38</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">        :param params: (dict) Optional query parameters.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">39</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">        :return: (dict) JSON response from the API.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">40</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">        :raises APIError: If there is an error with the API request.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">41</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">        </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">42</span><span class="token">        </span><span class="token">url</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">f</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">{</span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">self</span><span class="token">.</span><span class="token">base_url</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">}</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">/</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">{</span><span class="token">endpoint</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">}</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">43</span><span class="token">        </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">try</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">44</span><span class="token">            </span><span class="token">response</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">requests</span><span class="token">.</span><span class="token">get</span><span class="token">(</span><span class="token">url</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">headers</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">self</span><span class="token">.</span><span class="token">headers</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">params</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token">params</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">timeout</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">10</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">45</span><span class="token">            </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">if</span><span class="token"> </span><span class="token">response</span><span class="token">.</span><span class="token">status_code</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">==</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">429</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">46</span><span class="token">                </span><span class="token">retry_after</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">response</span><span class="token">.</span><span class="token">headers</span><span class="token">.</span><span class="token">get</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Retry-After</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">unknown time</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">47</span><span class="token">                </span><span class="token">log_error</span><span class="token">(</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">f</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Rate limit exceeded. Retry after: </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">{</span><span class="token">retry_after</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">}</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">48</span><span class="token">                </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">raise</span><span class="token"> </span><span class="token">APIError</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Rate limit exceeded.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">49</span><span class="token">            </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">if</span><span class="token"> </span><span class="token">response</span><span class="token">.</span><span class="token">status_code</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">==</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">401</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">50</span><span class="token">                </span><span class="token">log_error</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Authentication failed: Invalid API key.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">51</span><span class="token">                </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">raise</span><span class="token"> </span><span class="token">APIError</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Authentication failed.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">52</span><span class="token">            </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">if</span><span class="token"> </span><span class="token">response</span><span class="token">.</span><span class="token">status_code</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">==</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">403</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">53</span><span class="token">                </span><span class="token">log_error</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Permission denied: Access to resource is forbidden.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">54</span><span class="token">                </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">raise</span><span class="token"> </span><span class="token">APIError</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Permission denied.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">55</span><span class="token">            </span><span class="token">response</span><span class="token">.</span><span class="token">raise_for_status</span><span class="token">(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">56</span><span class="token">            </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">return</span><span class="token"> </span><span class="token">response</span><span class="token">.</span><span class="token">json</span><span class="token">(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">57</span><span class="token">        </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">except</span><span class="token"> </span><span class="token">requests</span><span class="token">.</span><span class="token">exceptions</span><span class="token">.</span><span class="token">Timeout</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">58</span><span class="token">            </span><span class="token">log_error</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">API request timed out.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">59</span><span class="token">            </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">raise</span><span class="token"> </span><span class="token">APIError</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">API request timed out.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">60</span><span class="token">        </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">except</span><span class="token"> </span><span class="token">requests</span><span class="token">.</span><span class="token">exceptions</span><span class="token">.</span><span class="token">ConnectionError</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">61</span><span class="token">            </span><span class="token">log_error</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Connection error occurred.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">62</span><span class="token">            </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">raise</span><span class="token"> </span><span class="token">APIError</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Connection error occurred.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">63</span><span class="token">        </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">except</span><span class="token"> </span><span class="token">requests</span><span class="token">.</span><span class="token">exceptions</span><span class="token">.</span><span class="token">RequestException</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">as</span><span class="token"> </span><span class="token">e</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">64</span><span class="token">            </span><span class="token">log_error</span><span class="token">(</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">f</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">API request failed: </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">{</span><span class="token">e</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">}</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">65</span><span class="token">            </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">raise</span><span class="token"> </span><span class="token">APIError</span><span class="token">(</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">f</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">API request failed: </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">{</span><span class="token">e</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">}</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">66</span><span class="token">        </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">except</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">ValueError</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">67</span><span class="token">            </span><span class="token">log_error</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Invalid JSON response format from API.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">68</span><span class="token">            </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">raise</span><span class="token"> </span><span class="token">APIError</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Invalid response format.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span>
```

This particular piece of the implementation should be pretty close to wrapped up now, but I won't feel 100% about it until after some more "live-fire" testing.

The final piece that took a lot of reworking is the data collection function, especially the data validation. Getting the proper order and distinguishing between missing and corrupt data was particularly challenging and effectively required nearly a complete rewrite of the function. The great thing about it, as it is now, is that after I got it to this point, it looks like it'll be a fairly straightforward endeavour to refactor again and make it relatively easy to allow for adding and removing threat feeds based on user preference.

PYTHON

```
<span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 1</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  IntelliSIEM Copyright 2024, Rob Perry</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 2</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 3</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  Licensed under the Apache License, Version 2.0 (the "License");</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 4</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  you may not use this file except in compliance with the License.</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 5</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  You may obtain a copy of the License at</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 6</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 7</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">      http://www.apache.org/licenses/LICENSE-2.0</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 8</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none"> 9</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  Unless required by applicable law or agreed to in writing, software</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">10</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  distributed under the License is distributed on an "AS IS" BASIS,</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">11</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">12</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  See the License for the specific language governing permissions and</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">13</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">  limitations under the License.</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">14</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">15</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">from</span><span class="token"> </span><span class="token">src</span><span class="token">.</span><span class="token">api_client</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">import</span><span class="token"> </span><span class="token">APIClient</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">16</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">from</span><span class="token"> </span><span class="token">src</span><span class="token">.</span><span class="token">error_handling</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">import</span><span class="token"> </span><span class="token">APIError</span><span class="token">,</span><span class="token"> </span><span class="token">DataError</span><span class="token">,</span><span class="token"> </span><span class="token">log_error</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">17</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">from</span><span class="token"> </span><span class="token">src</span><span class="token">.</span><span class="token">config</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">import</span><span class="token"> </span><span class="token">load_config</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">18</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">19</span><span class="token">config</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">load_config</span><span class="token">(</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">20</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">21</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">def</span><span class="token"> </span><span class="token" style="color: #622cbc;;--phiki-dark-color: #dbb7ff">fetch_threat_data</span><span class="token">(</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">22</span><span class="token">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">23</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    Fetch threat data from various sources and return the combined result.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">24</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">25</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    :return: (list) A list of threat intelligence data.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">26</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    :raises DataError: If there is an error with data integrity or structure.
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">27</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">    </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"""</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">28</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">try</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">29</span><span class="token">        </span><span class="token">alien_vault</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">APIClient</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">https://otx.alienvault.com/api/v1</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">,</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">30</span><span class="token">                                </span><span class="token">{</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">X-OTX-API-KEY</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">:</span><span class="token"> </span><span class="token">config</span><span class="token">[</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">api_keys</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">]</span><span class="token">[</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">alien_vault</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">]</span><span class="token">}</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">31</span><span class="token">        </span><span class="token">vt</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">APIClient</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">https://www.virustotal.com/api/v3</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">,</span><span class="token"> </span><span class="token">{</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">x-apikey</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">:</span><span class="token"> </span><span class="token">config</span><span class="token">[</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">api_keys</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">]</span><span class="token">[</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">virus_total</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">]</span><span class="token">}</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">32</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">33</span><span class="token">        </span><span class="token">alien_vault_data</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">alien_vault</span><span class="token">.</span><span class="token">get_data</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">indicators/export</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">34</span><span class="token">        </span><span class="token">vt_data</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">vt</span><span class="token">.</span><span class="token">get_data</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">files</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #702c00;;--phiki-dark-color: #ffb757">params</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token">{</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">limit</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">:</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">10</span><span class="token">}</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">35</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">36</span><span class="token">        </span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc"> Validate that the data is a list</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">37</span><span class="token">        </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">if</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">not</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">isinstance</span><span class="token">(</span><span class="token">alien_vault_data</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">list</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">or</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">not</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">isinstance</span><span class="token">(</span><span class="token">vt_data</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">list</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">38</span><span class="token">            </span><span class="token">log_error</span><span class="token">(</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">f</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Invalid data type received: </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">{</span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">type</span><span class="token">(</span><span class="token">alien_vault_data</span><span class="token">)</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">}</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff"> or </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">{</span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">type</span><span class="token">(</span><span class="token">vt_data</span><span class="token">)</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">}</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">39</span><span class="token">            </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">raise</span><span class="token"> </span><span class="token">DataError</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Unexpected data type received.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">40</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">41</span><span class="token">        </span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc"> Define the required keys for validation</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">42</span><span class="token">        </span><span class="token">required_keys</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">[</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">id</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">]</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">43</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">44</span><span class="token">        </span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc"> Validate data and raise DataError if required keys are missing or if data is corrupt</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">45</span><span class="token">        </span><span class="token">valid_data</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">=</span><span class="token"> </span><span class="token">[</span><span class="token">]</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">46</span><span class="token">        </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">for</span><span class="token"> </span><span class="token">entry</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">in</span><span class="token"> </span><span class="token">alien_vault_data</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">+</span><span class="token"> </span><span class="token">vt_data</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">47</span><span class="token">            </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">if</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">not</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">isinstance</span><span class="token">(</span><span class="token">entry</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">dict</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">48</span><span class="token">                </span><span class="token">log_error</span><span class="token">(</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">f</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Unexpected data type in entry: </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">{</span><span class="token">entry</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">}</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">49</span><span class="token">                </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">raise</span><span class="token"> </span><span class="token">DataError</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Unexpected data type received.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">50</span><span class="token">            </span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc">#</span><span class="token" style="color: #66707b;;--phiki-dark-color: #bdc4cc"> Check if the 'id' key is present and its value is of expected type</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">51</span><span class="token">            </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">if</span><span class="token"> </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">id</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">in</span><span class="token"> </span><span class="token">entry</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">and</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">not</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">isinstance</span><span class="token">(</span><span class="token">entry</span><span class="token">[</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">id</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'</span><span class="token">]</span><span class="token">,</span><span class="token"> </span><span class="token">(</span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">str</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">int</span><span class="token">)</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">52</span><span class="token">                </span><span class="token">log_error</span><span class="token">(</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">f</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Corrupt data in entry: </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">{</span><span class="token">entry</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">}</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">. </span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">'id</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">' key has invalid type.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">53</span><span class="token">                </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">raise</span><span class="token"> </span><span class="token">DataError</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Corrupt data received.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">54</span><span class="token">            </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">if</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">any</span><span class="token">(</span><span class="token">key</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">not</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">in</span><span class="token"> </span><span class="token">entry</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">for</span><span class="token"> </span><span class="token">key</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">in</span><span class="token"> </span><span class="token">required_keys</span><span class="token">)</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">55</span><span class="token">                </span><span class="token">log_error</span><span class="token">(</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">f</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Missing required data keys in entry: </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">{</span><span class="token">entry</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">}</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">56</span><span class="token">                </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">raise</span><span class="token"> </span><span class="token">DataError</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Missing required data keys.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">57</span><span class="token">            </span><span class="token">valid_data</span><span class="token">.</span><span class="token">append</span><span class="token">(</span><span class="token">entry</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">58</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">59</span><span class="token">        </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">return</span><span class="token"> </span><span class="token">valid_data</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">60</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">61</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">except</span><span class="token"> </span><span class="token">APIError</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">as</span><span class="token"> </span><span class="token">e</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">62</span><span class="token">        </span><span class="token">log_error</span><span class="token">(</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">f</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Failed to fetch threat data: </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">{</span><span class="token">e</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">}</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">63</span><span class="token">        </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">return</span><span class="token"> </span><span class="token">[</span><span class="token">]</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">64</span><span class="token">    </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">except</span><span class="token"> </span><span class="token">(</span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">KeyError</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">TypeError</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #023b95;;--phiki-dark-color: #91cbff">ValueError</span><span class="token">)</span><span class="token"> </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">as</span><span class="token"> </span><span class="token">e</span><span class="token">:</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">65</span><span class="token">        </span><span class="token">log_error</span><span class="token">(</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">f</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Data error occurred: </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">{</span><span class="token">e</span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">}</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="line-number" style="color: #88929d;-webkit-user-select: none">66</span><span class="token">        </span><span class="token" style="color: #a0111f;;--phiki-dark-color: #ff9492">raise</span><span class="token"> </span><span class="token">DataError</span><span class="token">(</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">Corrupt data received.</span><span class="token" style="color: #032563;;--phiki-dark-color: #addcff">"</span><span class="token">)</span><span class="token">
</span></span>
```

I find this particular implementation rather clunky at the moment, but it works. I think implementing a better structure for feed sources will make a significant improvement, but this is going on the TODO list for later.

Implementing robust error handling and log rotation features has significantly improved IntelliSIEM’s resilience. The system can now gracefully handle unexpected data scenarios, and we can track issues effectively through logs without worrying about file sizes. Next, we will turn our attention to beginning the basic UI implementation. Stay tuned as we continue to build out this powerful tool!

---

## Navigation

- Parent: [Blog](https://bsb.perryconsulting.net/blog.md)
- Next: [Implementing TDD in IntelliSIEM: Handling Edge Cases and Errors](https://bsb.perryconsulting.net/blog/strengthening-the-foundation-with-comprehensive-testing-in-intellisiem.md)
