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

81 statements  

« prev     ^ index     » next       coverage.py v7.17.2, created at 2026-11-07 05:08 +0000

1# This file is part of the Apio project 

2# (C) 2016-present FPGAwars 

3# Project authors: 

4# * Jesús Arroyo (Jesus89) (2016-2019) 

5# * Juan Gonzalez (obijuan) (2019-2024) 

6# * The Apio Team (2024-present) 

7# License: GPLv2 

8 

9"""Test for the "apio raw" command.""" 

10 

11import os 

12import sys 

13import re 

14from tests.conftest import ApioRunner 

15from apio.commands.apio import apio_top_cli as apio 

16 

17 

18def test_raw(apio_runner: ApioRunner): 

19 """Test "apio raw" with different parameters""" 

20 

21 with apio_runner.in_sandbox() as sb: 

22 

23 # -- NOTE: We run the apio raw command in a sub process to have a 

24 # -- proper sys.argv for it for the '--' separator validation. 

25 

26 # -- Execute "apio raw" 

27 result = sb.invoke_apio_cmd(apio, ["raw"], in_subprocess=True) 

28 assert result.exit_code != 0, result.output 

29 assert ( 

30 "at least one of --verbose or COMMAND must be specified" 

31 in result.output 

32 ) 

33 

34 # -- Execute "apio raw -v" 

35 result = sb.invoke_apio_cmd(apio, ["raw", "-v"], in_subprocess=True) 

36 sb.assert_result_ok(result) 

37 assert "Environment settings:" in result.output 

38 assert "PATH" in result.output 

39 assert "VERILATOR_ROOT" in result.output 

40 

41 # -- Run 'apio raw -- echo hello'. 

42 result = sb.invoke_apio_cmd( 

43 apio, ["raw", "--", "echo", "hello"], in_subprocess=True 

44 ) 

45 sb.assert_result_ok(result, bad_words=[]) 

46 assert "hello" in result.output 

47 

48 # -- Run a command without the required '--' 

49 result = sb.invoke_apio_cmd(apio, ["raw", "echo"], in_subprocess=True) 

50 assert result.exit_code != 0, result.output 

51 assert "command separator '--' was not found" in result.output 

52 

53 # -- Run a command with a token before the '--' separator. 

54 result = sb.invoke_apio_cmd( 

55 apio, ["raw", "echo", "--", "--help"], in_subprocess=True 

56 ) 

57 assert result.exit_code != 0, result.output 

58 assert "Invalid arguments: ['echo']" in result.output 

59 

60 # -- Run 'apio raw -v' 

61 result = sb.invoke_apio_cmd(apio, ["raw", "-v"], in_subprocess=True) 

62 sb.assert_result_ok(result) 

63 assert "Environment settings:" in result.output 

64 assert "VERILATOR_ROOT" in result.output 

65 

66 

67def test_raw_preserves_argv_and_cwd(apio_runner: ApioRunner): 

68 """Tests that 'apio raw' passes the wrapped command's arguments 

69 verbatim as an argv list (no re-splitting at spaces, no quote 

70 mangling) and runs it in the caller's current directory. This is 

71 a regression test for a Windows bug where the args were joined with 

72 POSIX quoting and re-tokenized by cmd.exe, breaking paths with 

73 spaces or backslashes.""" 

74 

75 with apio_runner.in_sandbox() as sb: 

76 

77 # -- A probe command that reports its cwd and its argv, one 

78 # -- element per line. Note that the sandbox's current directory 

79 # -- ('apio proj') contains a space. 

80 probe = ( 

81 "import os, sys; " 

82 "print('PROBE-CWD=<' + os.getcwd() + '>'); " 

83 "[print('PROBE-ARG-%d=<%s>' % (i, a)) " 

84 "for i, a in enumerate(sys.argv[1:])]" 

85 ) 

86 

87 result = sb.invoke_apio_cmd( 

88 apio, 

89 [ 

90 "raw", 

91 "--", 

92 sys.executable, 

93 "-c", 

94 probe, 

95 "a b c.txt", 

96 r"_build\default\hardware.bit", 

97 ], 

98 in_subprocess=True, 

99 ) 

100 sb.assert_result_ok(result, bad_words=[]) 

101 

102 # -- The wrapped command must inherit the caller's cwd. 

103 assert f"PROBE-CWD=<{os.getcwd()}>" in result.output 

104 

105 # -- An arg with spaces must arrive as a single argv element. 

106 assert "PROBE-ARG-0=<a b c.txt>" in result.output 

107 

108 # -- An arg with backslashes must arrive verbatim, without 

109 # -- added quotes. 

110 assert "PROBE-ARG-1=<_build\\default\\hardware.bit>" in result.output 

111 

112 # -- There must be no extra args from re-splitting. 

113 assert "PROBE-ARG-2" not in result.output 

114 

115 

116def test_raw_icepll(apio_runner: ApioRunner): 

117 """Tests that the icepll raw command works""" 

118 

119 with apio_runner.in_sandbox() as sb: 

120 

121 # -- Run 'apio raw -- icepll -i 20 -i 60 -m -f pll.v' 

122 result = sb.invoke_apio_cmd( 

123 apio, 

124 [ 

125 "raw", 

126 "--", 

127 "icepll", 

128 "-i", 

129 "20", 

130 "-o", 

131 "60", 

132 "-m", 

133 "-f", 

134 "pll.v", 

135 ], 

136 in_subprocess=True, 

137 ) 

138 print(result.output) 

139 sb.assert_result_ok(result) 

140 module = sb.read_file_text("pll.v") 

141 print(module) 

142 

143 assert "module pll" in module 

144 assert "SB_PLL40_CORE" in module 

145 assert re.search(r"Achieved.+60.000", module) 

146 assert "endmodule" in module 

147 

148 

149def test_raw_ecppll(apio_runner: ApioRunner): 

150 """Tests that the ecppll raw command works""" 

151 

152 with apio_runner.in_sandbox() as sb: 

153 

154 # -- Run 'apio raw -- ecppll -i 25 -o 120 -f ecppll.v' 

155 result = sb.invoke_apio_cmd( 

156 apio, 

157 ["raw", "--", "ecppll", "-i", "20", "-o", "60", "-f", "pll.v"], 

158 in_subprocess=True, 

159 ) 

160 print(result.output) 

161 sb.assert_result_ok(result) 

162 module = sb.read_file_text("pll.v") 

163 print(module) 

164 

165 assert "module pll" in module 

166 assert "EHXPLLL" in module 

167 assert re.search(r"clkout0.+60 MHz", module) 

168 assert "endmodule" in module 

169 

170 

171def test_raw_gowin_pll(apio_runner: ApioRunner): 

172 """Tests that the gowin_pll raw command works""" 

173 

174 with apio_runner.in_sandbox() as sb: 

175 

176 # -- Run the command 

177 # 'apio raw -- gowin_pll -d "GW1NR-LV9QN88PC6/I5" 

178 # -i 27 -o 75 -f pll.v' 

179 result = sb.invoke_apio_cmd( 

180 apio, 

181 [ 

182 "raw", 

183 "--", 

184 "gowin_pll", 

185 "-d", 

186 '"GW1NR-LV9QN88PC6/I5"', 

187 "-i", 

188 "20", 

189 "-o", 

190 "60", 

191 "-f", 

192 "pll.v", 

193 ], 

194 in_subprocess=True, 

195 ) 

196 print(result.output) 

197 sb.assert_result_ok(result) 

198 module = sb.read_file_text("pll.v") 

199 print(module) 

200 

201 assert "module pll" in module 

202 assert "rPLL" in module 

203 assert re.search(r"Achieved.+60.000", module) 

204 assert "endmodule" in module 

205 

206 

207def test_raw_xc7pll(apio_runner: ApioRunner): 

208 """Tests that the xc7pll raw command works""" 

209 

210 with apio_runner.in_sandbox() as sb: 

211 

212 # -- Run 'apio raw -- xc7pll -i 100 -o 200 -f pll.v' 

213 result = sb.invoke_apio_cmd( 

214 apio, 

215 [ 

216 "raw", 

217 "--", 

218 "xc7pll", 

219 "-i", 

220 "100", 

221 "-o", 

222 "200", 

223 "-f", 

224 "pll.v", 

225 ], 

226 in_subprocess=True, 

227 ) 

228 print(result.output) 

229 sb.assert_result_ok(result) 

230 module = sb.read_file_text("pll.v") 

231 print(module) 

232 

233 assert "module pll" in module 

234 assert "PLLE2_BASE" in module 

235 assert "requested 200 MHz, exact" in module 

236 assert "endmodule" in module