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

1""" 

2Tests of apio_profile.py 

3""" 

4 

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) 

20 

21 

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 

27 

28 

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) 

39 

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 } 

76 

77 

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.""" 

81 

82 with apio_runner.in_sandbox() as sb: 

83 

84 apio_ctx = ApioContext( 

85 project_policy=ProjectPolicy.NO_PROJECT, 

86 remote_config_policy=RemoteConfigPolicy.CACHED_OK, 

87 packages_policy=PackagesPolicy.ENSURE_PACKAGES, 

88 ) 

89 

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 ) 

101 

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 ) 

111 

112 # -- Verify 

113 assert profile.preferences == test_data["preferences"] 

114 assert profile.remote_config == test_data["remote-config"] 

115 

116 

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.""" 

120 

121 with apio_runner.in_sandbox() as sb: 

122 

123 apio_ctx = ApioContext( 

124 project_policy=ProjectPolicy.NO_PROJECT, 

125 remote_config_policy=RemoteConfigPolicy.CACHED_OK, 

126 packages_policy=PackagesPolicy.ENSURE_PACKAGES, 

127 ) 

128 

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) 

135 

136 sb.write_file( 

137 path, 

138 json.dumps( 

139 test_data, 

140 indent=2, 

141 ), 

142 exists_ok=True, 

143 ) 

144 

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 ) 

154 

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 ) 

163 

164 

165def test_datetime_stamp_diff_days(): 

166 """Test the datetime timestamp diff.""" 

167 

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 ) 

174 

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 ) 

184 

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 ) 

193 

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 ) 

202 

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 ) 

211 

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 ) 

220 

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 )