Coverage for tests/unit_tests/test_profile.py: 100%
44 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-06 10:20 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-06 10:20 +0000
1"""
2Tests of apio_profile.py
3"""
5import json
6from datetime import datetime, timedelta
7from tests.conftest import ApioRunner
8from apio.profile import (
9 Profile,
10 get_datetime_stamp,
11 days_between_datetime_stamps,
12)
13from apio.utils import util
14from apio.apio_context import (
15 ApioContext,
16 PackagesPolicy,
17 ProjectPolicy,
18 RemoteConfigPolicy,
19)
22def get_remote_config_url(apio_ctx: ApioContext) -> str:
23 """Returns a test remote config URL."""
24 url = apio_ctx.config["remote-config-url"]
25 url = url.replace("{V}", util.get_apio_version())
26 return url
29def get_test_data(
30 apio_ctx: ApioContext,
31 loaded_by_apio_version: str,
32 loaded_at_days: int,
33):
34 """Returns a fake profile.json content. 'loaded_at_days' is the value of
35 the remote config "loaded-at" relative to today in days."""
36 loaded_at_datetime = datetime.now() + timedelta(days=loaded_at_days)
37 loaded_at_stamp = get_datetime_stamp(loaded_at_datetime)
38 assert isinstance(loaded_at_stamp, str)
40 return {
41 "preferences": {"theme": "light"},
42 "remote-config": {
43 "metadata": {
44 "loaded-at": loaded_at_stamp,
45 "loaded-by": loaded_by_apio_version,
46 "loaded-from": get_remote_config_url(apio_ctx),
47 },
48 "packages": {
49 "drivers": {
50 "release": {
51 "package-file": (
52 "apio-drivers-${PLATFORM}-${YYYYMMDD}.tgz"
53 ),
54 "release-tag": "${YYYY-MM-DD}",
55 "version": "2025.06.13",
56 },
57 "repository": {
58 "name": "tools-drivers",
59 "organization": "fpgawars",
60 },
61 },
62 "examples": {
63 "release": {
64 "package-file": "apio-examples-${YYYYMMDD}.tgz",
65 "release-tag": "${YYYY-MM-DD}",
66 "version": "2025.06.21",
67 },
68 "repository": {
69 "name": "apio-examples",
70 "organization": "fpgawars",
71 },
72 },
73 },
74 },
75 }
78def test_profile_loading_config_ok(apio_runner: ApioRunner):
79 """Tests the loading and validation of a profile file with no need
80 to fetch a remote config."""
82 with apio_runner.in_sandbox() as sb:
84 apio_ctx = ApioContext(
85 project_policy=ProjectPolicy.NO_PROJECT,
86 remote_config_policy=RemoteConfigPolicy.CACHED_OK,
87 packages_policy=PackagesPolicy.ENSURE_PACKAGES,
88 )
90 # -- Write a test profile.json file.
91 path = sb.home_dir / "profile.json"
92 test_data = get_test_data(apio_ctx, util.get_apio_version(), 0)
93 sb.write_file(
94 path,
95 json.dumps(
96 test_data,
97 indent=2,
98 ),
99 exists_ok=True,
100 )
102 # -- Read back the content.
103 profile = Profile(
104 sb.home_dir,
105 sb.packages_dir,
106 get_remote_config_url(apio_ctx),
107 5, # TTL in days
108 60, # Remote config retry mins.
109 RemoteConfigPolicy.CACHED_OK,
110 )
112 # -- Verify
113 assert profile.preferences == test_data["preferences"]
114 assert profile.remote_config == test_data["remote-config"]
117def test_profile_loading_config_stale_version(apio_runner: ApioRunner):
118 """Tests the loading and validation of a profile file that include
119 an old config that needs to be refreshed."""
121 with apio_runner.in_sandbox() as sb:
123 apio_ctx = ApioContext(
124 project_policy=ProjectPolicy.NO_PROJECT,
125 remote_config_policy=RemoteConfigPolicy.CACHED_OK,
126 packages_policy=PackagesPolicy.ENSURE_PACKAGES,
127 )
129 # -- Write a test profile.json file. We set an old apio version
130 # -- to cause the cached remote config to be classified as stale.
131 path = sb.home_dir / "profile.json"
132 original_loaded_by = "0.9.6"
133 assert original_loaded_by != util.get_apio_version()
134 test_data = get_test_data(apio_ctx, original_loaded_by, 0)
136 sb.write_file(
137 path,
138 json.dumps(
139 test_data,
140 indent=2,
141 ),
142 exists_ok=True,
143 )
145 # -- Read back the content.
146 profile = Profile(
147 sb.home_dir,
148 sb.packages_dir,
149 get_remote_config_url(apio_ctx),
150 5, # TTL in days
151 60, # Remote config retry mins.
152 RemoteConfigPolicy.CACHED_OK,
153 )
155 # -- Verify. Remote config should be a fresh one, loaded by this
156 # -- apio version.
157 assert profile.preferences == test_data["preferences"]
158 # assert profile.installed_packages == test_data["installed-packages"]
159 assert (
160 profile.remote_config["metadata"]["loaded-by"]
161 == util.get_apio_version()
162 )
165def test_datetime_stamp_diff_days():
166 """Test the datetime timestamp diff."""
168 assert (
169 get_datetime_stamp(
170 datetime(year=2025, month=6, day=30, hour=14, minute=45)
171 )
172 == "2025-06-30-14-45"
173 )
175 ts_now = get_datetime_stamp()
176 assert (
177 days_between_datetime_stamps(
178 ts_now,
179 ts_now,
180 default=9999,
181 )
182 == 0
183 )
185 assert (
186 days_between_datetime_stamps(
187 "2025-06-15-07-30",
188 "2025-06-16-00-01",
189 default=9999,
190 )
191 == 1
192 )
194 assert (
195 days_between_datetime_stamps(
196 "2025-06-16-00-01",
197 "2025-06-15-07-30",
198 default=9999,
199 )
200 == -1
201 )
203 assert (
204 days_between_datetime_stamps(
205 "2025-06-15-00-00",
206 "2025-06-15-23-59",
207 default=9999,
208 )
209 == 0
210 )
212 assert (
213 days_between_datetime_stamps(
214 "2025-06-15-00-0x",
215 "2025-06-15-23-59",
216 default=9999,
217 )
218 == 9999
219 )
221 assert (
222 days_between_datetime_stamps(
223 "2025-06-15-20-15",
224 "2025-06-20-00-01",
225 default=9999,
226 )
227 == 5
228 )