Coverage for tests/unit_tests/commands/test_apio_api.py: 100%

120 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-11-06 10:20 +0000

1"""Test for the "apio api" command.""" 

2 

3# NOTE: 'apio api scan-devices' require apio packages (for libusb1 lib) 

4# and thus, is tested in the integration tests. 

5 

6import json 

7import os 

8from tests.conftest import ApioRunner 

9from apio.commands.apio import apio_top_cli as apio 

10 

11# TODO: Add more tests 

12 

13 

14def test_apio_api_get_boards(apio_runner: ApioRunner): 

15 """Test "apio api get-boards" """ 

16 

17 with apio_runner.in_sandbox() as sb: 

18 

19 # -- Execute "apio api get-boards -t xyz" (stdout) 

20 result = sb.invoke_apio_cmd(apio, ["api", "get-boards", "-t", "xyz"]) 

21 sb.assert_result_ok(result) 

22 assert "xyz" in result.output 

23 assert "alhambra-ii" in result.output 

24 

25 # -- Execute "apio api get-boards -t xyz -o <dir>" (file) 

26 path = sb.proj_dir / "apio.json" 

27 result = sb.invoke_apio_cmd( 

28 apio, ["api", "get-boards", "-t", "xyz", "-o", str(path)] 

29 ) 

30 sb.assert_result_ok(result) 

31 

32 # -- Read and verify the file. 

33 text = sb.read_file(path) 

34 data = json.loads(text) 

35 assert data["timestamp"] == "xyz" 

36 assert data["boards"]["alhambra-ii"] == { 

37 "description": "Alhambra II", 

38 "fpga": { 

39 "id": "ice40hx4k-tq144-8k", 

40 "part-num": "ICE40HX4K-TQ144", 

41 "arch": "ice40", 

42 "size": "8k", 

43 }, 

44 "programmer": {"id": "openfpgaloader"}, 

45 } 

46 

47 

48def test_apio_api_get_fpgas(apio_runner: ApioRunner): 

49 """Test "apio api get-fpgas" """ 

50 

51 with apio_runner.in_sandbox() as sb: 

52 

53 # -- Execute "apio api get-fpgas -t xyz" (stdout) 

54 result = sb.invoke_apio_cmd(apio, ["api", "get-fpgas", "-t", "xyz"]) 

55 sb.assert_result_ok(result) 

56 assert "xyz" in result.output 

57 assert "ice40hx4k-tq144-8k" in result.output 

58 

59 # -- Execute "apio api get-fpgas -t xyz -o <dir>" (file) 

60 path = sb.proj_dir / "apio.json" 

61 result = sb.invoke_apio_cmd( 

62 apio, ["api", "get-fpgas", "-t", "xyz", "-o", str(path)] 

63 ) 

64 sb.assert_result_ok(result) 

65 

66 # -- Read and verify the file. 

67 text = sb.read_file(path) 

68 data = json.loads(text) 

69 assert data["timestamp"] == "xyz" 

70 assert data["fpgas"]["ice40hx4k-tq144-8k"] == { 

71 "part-num": "ICE40HX4K-TQ144", 

72 "arch": "ice40", 

73 "size": "8k", 

74 } 

75 

76 

77def test_apio_api_get_programmers(apio_runner: ApioRunner): 

78 """Test "apio api get-programmers" """ 

79 

80 with apio_runner.in_sandbox() as sb: 

81 

82 # -- Execute "apio api get-programmers -t xyz" (stdout) 

83 result = sb.invoke_apio_cmd( 

84 apio, ["api", "get-programmers", "-t", "xyz"] 

85 ) 

86 sb.assert_result_ok(result) 

87 assert "xyz" in result.output 

88 assert "openfpgaloader" in result.output 

89 

90 # -- Execute "apio api get-programmers -t xyz -o <dir>" (file) 

91 path = sb.proj_dir / "apio.json" 

92 result = sb.invoke_apio_cmd( 

93 apio, ["api", "get-programmers", "-t", "xyz", "-o", str(path)] 

94 ) 

95 sb.assert_result_ok(result) 

96 

97 # -- Read and verify the file. 

98 text = sb.read_file(path) 

99 data = json.loads(text) 

100 assert data["timestamp"] == "xyz" 

101 assert data["programmers"]["openfpgaloader"] == { 

102 "command": "openFPGALoader", 

103 "args": "", 

104 } 

105 

106 

107def test_apio_api_get_commands(apio_runner: ApioRunner): 

108 """Test "apio api get-commands" """ 

109 

110 with apio_runner.in_sandbox() as sb: 

111 

112 # -- Execute "apio api get-commands -t xyz" (stdout) 

113 result = sb.invoke_apio_cmd(apio, ["api", "get-commands", "-t", "xyz"]) 

114 sb.assert_result_ok(result) 

115 assert "xyz" in result.output 

116 assert '"apio"' in result.output 

117 assert '"api"' in result.output 

118 assert '"get-boards"' in result.output 

119 

120 # -- Execute "apio api get-boards -t xyz -o <dir>" (file) 

121 path = sb.proj_dir / "apio.json" 

122 result = sb.invoke_apio_cmd( 

123 apio, ["api", "get-commands", "-t", "xyz", "-o", str(path)] 

124 ) 

125 sb.assert_result_ok(result) 

126 

127 # -- Read and verify the file. 

128 text = sb.read_file(path) 

129 data = json.loads(text) 

130 assert data["timestamp"] == "xyz" 

131 assert ( 

132 data["commands"]["apio"]["commands"]["api"]["commands"][ 

133 "get-boards" 

134 ] 

135 == {} 

136 ) 

137 

138 

139def test_apio_api_get_system(apio_runner: ApioRunner): 

140 """Test "apio api get-system" """ 

141 

142 with apio_runner.in_sandbox() as sb: 

143 

144 # -- Execute "apio api get-system -t xyz" (stdout) 

145 result = sb.invoke_apio_cmd(apio, ["api", "get-system", "-t", "xyz"]) 

146 sb.assert_result_ok(result) 

147 assert "xyz" in result.output 

148 assert '"apio-version"' in result.output 

149 assert '"python-version"' in result.output 

150 

151 # -- Execute "apio api get-system -t xyz -o <dir>" (file) 

152 path = sb.proj_dir / "apio.json" 

153 result = sb.invoke_apio_cmd( 

154 apio, ["api", "get-system", "-t", "xyz", "-o", str(path)] 

155 ) 

156 sb.assert_result_ok(result) 

157 

158 # -- Read and verify the file. 

159 text = sb.read_file(path) 

160 data = json.loads(text) 

161 assert data["timestamp"] == "xyz" 

162 assert data["system"]["remote-config-url"].endswith(".jsonc") 

163 

164 

165def test_apio_api_get_project(apio_runner: ApioRunner): 

166 """Test "apio api get-project" """ 

167 

168 with apio_runner.in_sandbox() as sb: 

169 

170 # -- Create a fake apio project 

171 sb.write_default_apio_ini() 

172 

173 sb.write_file("synth0.v", "") 

174 sb.write_file("tb_0.sv", "") 

175 

176 os.makedirs("src1") 

177 sb.write_file("src1/synth1.sv", "") 

178 sb.write_file("src1/synth2.sv", "") 

179 sb.write_file("src1/tb1_tb.sv", "") 

180 

181 # -- Execute "apio api get-project -t xyz" (stdout) 

182 result = sb.invoke_apio_cmd(apio, ["api", "get-project", "-t", "xyz"]) 

183 sb.assert_result_ok(result) 

184 assert '"default"' in result.output 

185 assert '"envs"' in result.output 

186 # assert '"apio-version"' in result.output 

187 # assert '"python-version"' in result.output 

188 

189 # -- Execute "apio api get-project -t xyz -o <dir>" (file) 

190 path = sb.proj_dir / "apio.json" 

191 result = sb.invoke_apio_cmd( 

192 apio, ["api", "get-project", "-t", "xyz", "-o", str(path)] 

193 ) 

194 sb.assert_result_ok(result) 

195 

196 # -- Read and verify the file. 

197 text = sb.read_file(path) 

198 data = json.loads(text) 

199 

200 assert data == { 

201 "timestamp": "xyz", 

202 "project": { 

203 "active-env": { 

204 "name": "default", 

205 "options": { 

206 "board": "alhambra-ii", 

207 "top-module": "main", 

208 }, 

209 }, 

210 "envs": [ 

211 "default", 

212 ], 

213 "synth-files": [ 

214 "synth0.v", 

215 "tb_0.sv", 

216 f"src1{os.sep}synth1.sv", 

217 f"src1{os.sep}synth2.sv", 

218 ], 

219 "test-benches": [ 

220 f"src1{os.sep}tb1_tb.sv", 

221 ], 

222 }, 

223 } 

224 

225 

226def test_apio_api_get_examples(apio_runner: ApioRunner): 

227 """Test "apio api get-examples" """ 

228 

229 with apio_runner.in_sandbox() as sb: 

230 

231 # -- Execute "apio api get-examples -t xyz" (stdout) 

232 result = sb.invoke_apio_cmd(apio, ["api", "get-examples", "-t", "xyz"]) 

233 sb.assert_result_ok(result) 

234 assert "xyz" in result.output 

235 assert '"alhambra-ii"' in result.output 

236 assert '"blinky"' in result.output 

237 

238 # -- Execute "apio api get-examples -t xyz -s boards -o <dir>" (file) 

239 path = sb.proj_dir / "apio.json" 

240 result = sb.invoke_apio_cmd( 

241 apio, ["api", "get-examples", "-t", "xyz", "-o", str(path)] 

242 ) 

243 sb.assert_result_ok(result) 

244 

245 # -- Read and verify the file. 

246 text = sb.read_file(path) 

247 data = json.loads(text) 

248 assert data["timestamp"] == "xyz" 

249 assert ( 

250 data["examples"]["alhambra-ii"]["blinky"]["description"] 

251 == "Blinking led" 

252 ) 

253 

254 

255def test_apio_api_scan_devices(apio_runner: ApioRunner): 

256 """Test "apio api scan-devices" """ 

257 

258 with apio_runner.in_sandbox() as sb: 

259 

260 # -- Execute "apio api scan-devices -t xyz". We run it in a 

261 # -- subprocess such that it releases the libusb1 file it uses. 

262 # -- This also means that it's not included in the pytest test 

263 # -- coverage report. 

264 result = sb.invoke_apio_cmd( 

265 apio, ["api", "scan-devices", "-t", "xyz"], in_subprocess=True 

266 ) 

267 sb.assert_result_ok(result) 

268 

269 assert "xyz" in result.output 

270 assert "usb-devices" in result.output 

271 assert "serial-devices" in result.output 

272 

273 # -- Execute "apio api get-boards -t xyz -s boards -o <dir>" (file) 

274 path = sb.proj_dir / "apio.json" 

275 

276 result = sb.invoke_apio_cmd( 

277 apio, 

278 ["api", "scan-devices", "-t", "xyz", "-o", str(path)], 

279 in_subprocess=True, 

280 ) 

281 sb.assert_result_ok(result) 

282 

283 # -- Read and verify the output file. Since we don't know what 

284 # -- devices the platform has, we just check for the section keys. 

285 text = sb.read_file(path) 

286 data = json.loads(text) 

287 assert data["timestamp"] == "xyz" 

288 assert "usb-devices" in data 

289 assert "serial-devices" in data