Skip to content

Commit cb9f782

Browse files
markkasaboskiMark Kasaboski
andauthored
Refactors test_ingest_events.py removing Mocks (#69)
Co-authored-by: Mark Kasaboski <mark.kasaboski@gmail.com>
1 parent b3bd86d commit cb9f782

4 files changed

Lines changed: 355 additions & 214 deletions

File tree

packages/flare/bin/cron_job_ingest_events.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,10 @@ class Application(Protocol):
7676

7777

7878
def main(
79-
logger: Logger, storage_passwords: StoragePasswords, kvstore: KVStoreCollections
79+
logger: Logger,
80+
storage_passwords: StoragePasswords,
81+
kvstore: KVStoreCollections,
82+
flare_api_cls: FlareAPI,
8083
) -> None:
8184
create_collection(kvstore=kvstore)
8285

@@ -107,6 +110,7 @@ def main(
107110
ingest_metadata_only=ingest_metadata_only,
108111
severities=severities_filter,
109112
source_types=source_types_filter,
113+
flare_api_cls=flare_api_cls,
110114
):
111115
save_last_fetched(kvstore=kvstore)
112116

@@ -311,9 +315,10 @@ def fetch_feed(
311315
ingest_metadata_only: bool,
312316
severities: list[str],
313317
source_types: list[str],
318+
flare_api_cls: FlareAPI = FlareAPI,
314319
) -> Iterator[tuple[dict, str]]:
315320
try:
316-
flare_api = FlareAPI(api_key=api_key, tenant_id=tenant_id)
321+
flare_api: FlareAPI = flare_api_cls(api_key=api_key, tenant_id=tenant_id)
317322

318323
next = get_next(kvstore=kvstore, tenant_id=tenant_id)
319324
start_date = get_start_date(kvstore=kvstore)
@@ -354,4 +359,5 @@ def get_splunk_service(logger: Logger) -> Service:
354359
logger=logger,
355360
storage_passwords=app.service.storage_passwords,
356361
kvstore=app.service.kvstore,
362+
flare_api_cls=FlareAPI,
357363
)
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
import json
2+
import os
3+
import pytest
4+
import sys
5+
6+
from datetime import datetime
7+
from pytest import FixtureRequest
8+
from typing import Any
9+
from typing import Dict
10+
from typing import List
11+
from typing import Optional
12+
13+
14+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../../bin"))
15+
from constants import KV_COLLECTION_NAME
16+
17+
18+
class FakeStoragePassword:
19+
def __init__(self, username: str, clear_password: str) -> None:
20+
self._state = {
21+
"username": username,
22+
"clear_password": clear_password,
23+
}
24+
25+
@property
26+
def content(self: "FakeStoragePassword") -> "FakeStoragePassword":
27+
return self
28+
29+
@property
30+
def username(self) -> str:
31+
return self._state["username"]
32+
33+
@property
34+
def clear_password(self) -> str:
35+
return self._state["clear_password"]
36+
37+
38+
class FakeStoragePasswords:
39+
def __init__(self, passwords: List[FakeStoragePassword]) -> None:
40+
self._passwords = passwords
41+
42+
def list(self) -> List[FakeStoragePassword]:
43+
return self._passwords
44+
45+
46+
class FakeKVStoreCollectionData:
47+
def __init__(self) -> None:
48+
self._data: dict[str, str] = {}
49+
50+
def insert(self, data: str) -> dict[str, str]:
51+
entry = json.loads(data)
52+
self._data[entry["_key"]] = entry["value"]
53+
return entry
54+
55+
def update(self, id: str, data: str) -> dict[str, str]:
56+
entry = json.loads(data)
57+
self._data[id] = entry["value"]
58+
return entry
59+
60+
def query(self, **query: dict) -> List[Dict[str, str]]:
61+
return [{"_key": key, "value": value} for key, value in self._data.items()]
62+
63+
64+
class FakeKVStoreCollection:
65+
def __init__(self) -> None:
66+
self._data = FakeKVStoreCollectionData()
67+
68+
@property
69+
def data(self) -> FakeKVStoreCollectionData:
70+
return self._data
71+
72+
73+
class FakeKVStoreCollections:
74+
def __init__(self) -> None:
75+
self._collections: dict[str, Any] = {}
76+
77+
def __getitem__(self, key: str) -> FakeKVStoreCollection:
78+
return self._collections[key]
79+
80+
def __contains__(self, key: str) -> bool:
81+
return key in self._collections
82+
83+
def create(self, name: str, fields: dict) -> dict[str, Any]:
84+
self._collections[name] = FakeKVStoreCollection()
85+
return {"headers": {}, "reason": "Created", "status": 200, "body": ""}
86+
87+
88+
class FakeLogger:
89+
def __init__(self) -> None:
90+
self.messages: List[str] = []
91+
92+
def info(self, message: str) -> None:
93+
self.messages.append(f"INFO: {message}")
94+
95+
def error(self, message: str) -> None:
96+
self.messages.append(f"ERROR: {message}")
97+
98+
99+
class FakeFlareAPI:
100+
def __init__(self, api_key: str, tenant_id: int) -> None:
101+
pass
102+
103+
def fetch_feed_events(
104+
self,
105+
next: Optional[str],
106+
start_date: Optional[datetime],
107+
ingest_metadata_only: bool,
108+
severities: list[str],
109+
source_types: list[str],
110+
) -> List[tuple[dict, str]]:
111+
return [
112+
(
113+
{"actor": "this guy"},
114+
"first_next_token",
115+
),
116+
(
117+
{"actor": "some other guy"},
118+
"second_next_token",
119+
),
120+
]
121+
122+
123+
@pytest.fixture
124+
def storage_passwords(request: FixtureRequest) -> FakeStoragePasswords:
125+
passwords: list[FakeStoragePassword] = []
126+
data: list[tuple[str, str]] = request.param if hasattr(request, "param") else []
127+
128+
if data:
129+
for item in data:
130+
passwords.append(
131+
FakeStoragePassword(username=item[0], clear_password=item[1])
132+
)
133+
134+
return FakeStoragePasswords(passwords=passwords)
135+
136+
137+
@pytest.fixture
138+
def kvstore(request: FixtureRequest) -> FakeKVStoreCollections:
139+
kvstore = FakeKVStoreCollections()
140+
data: list[tuple[str, str]] = request.param if hasattr(request, "param") else []
141+
142+
if data:
143+
kvstore.create(name=KV_COLLECTION_NAME, fields={})
144+
for item in data:
145+
kvstore[KV_COLLECTION_NAME].data.insert(
146+
json.dumps({"_key": item[0], "value": item[1]})
147+
)
148+
149+
return kvstore
150+
151+
152+
@pytest.fixture
153+
def logger() -> FakeLogger:
154+
return FakeLogger()

0 commit comments

Comments
 (0)