|
12 | 12 | # otherwise use the software for commercial activities involving the Arduino |
13 | 13 | # software without disclosing the source code of your own applications. To purchase |
14 | 14 | # a commercial license, send an email to license@arduino.cc. |
15 | | -import json |
16 | | -import os |
17 | | -import platform |
18 | | - |
19 | | -import pytest |
20 | | - |
21 | | -from .common import running_on_ci |
22 | | - |
23 | | - |
24 | | -def test_compile_without_fqbn(run_command): |
25 | | - # Init the environment explicitly |
26 | | - result = run_command("core update-index") |
27 | | - assert result.ok |
28 | | - |
29 | | - # Download latest AVR |
30 | | - result = run_command("core install arduino:avr") |
31 | | - assert result.ok |
32 | | - |
33 | | - # Build sketch without FQBN |
34 | | - result = run_command("compile") |
35 | | - assert result.failed |
36 | | - |
37 | | - |
38 | | -def test_compile_with_simple_sketch(run_command, data_dir, working_dir): |
39 | | - # Init the environment explicitly |
40 | | - result = run_command("core update-index") |
41 | | - assert result.ok |
42 | | - |
43 | | - # Download latest AVR |
44 | | - result = run_command("core install arduino:avr") |
45 | | - assert result.ok |
46 | | - |
47 | | - sketch_name = "CompileIntegrationTest" |
48 | | - sketch_path = os.path.join(data_dir, sketch_name) |
49 | | - fqbn = "arduino:avr:uno" |
50 | | - |
51 | | - # Create a test sketch |
52 | | - result = run_command("sketch new {}".format(sketch_path)) |
53 | | - assert result.ok |
54 | | - assert "Sketch created in: {}".format(sketch_path) in result.stdout |
55 | | - |
56 | | - # Build sketch for arduino:avr:uno |
57 | | - log_file_name = "compile.log" |
58 | | - log_file_path = os.path.join(data_dir, log_file_name) |
59 | | - result = run_command( |
60 | | - "compile -b {fqbn} {sketch_path} --log-format json --log-file {log_file} --log-level trace".format( |
61 | | - fqbn=fqbn, sketch_path=sketch_path, log_file=log_file_path |
62 | | - ) |
63 | | - ) |
64 | | - assert result.ok |
65 | | - |
66 | | - # let's test from the logs if the hex file produced by successful compile is moved to our sketch folder |
67 | | - log_json = open(log_file_path, "r") |
68 | | - json_log_lines = log_json.readlines() |
69 | | - expected_trace_sequence = [ |
70 | | - "Compile {sketch} for {fqbn} started".format(sketch=sketch_path, fqbn=fqbn), |
71 | | - "Compile {sketch} for {fqbn} successful".format(sketch=sketch_name, fqbn=fqbn), |
72 | | - ] |
73 | | - assert is_message_sequence_in_json_log_traces( |
74 | | - expected_trace_sequence, json_log_lines |
75 | | - ) |
76 | | - |
77 | | - # Test the --output flag with absolute path |
78 | | - target = os.path.join(data_dir, "test.hex") |
79 | | - result = run_command( |
80 | | - "compile -b {fqbn} {sketch_path} -o {target}".format( |
81 | | - fqbn=fqbn, sketch_path=sketch_path, target=target |
82 | | - ) |
83 | | - ) |
84 | | - assert result.ok |
85 | | - assert os.path.exists(target) |
86 | | - |
87 | | - |
88 | | -@pytest.mark.skipif( |
89 | | - running_on_ci() and platform.system() == "Windows", |
90 | | - reason="Test disabled on Github Actions Win VM until tmpdir inconsistent behavior bug is fixed", |
91 | | -) |
92 | | -def test_output_flag_default_path(run_command, data_dir, working_dir): |
93 | | - # Init the environment explicitly |
94 | | - result = run_command("core update-index") |
95 | | - assert result.ok |
96 | | - |
97 | | - # Download latest AVR |
98 | | - result = run_command("core install arduino:avr") |
99 | | - assert result.ok |
100 | | - |
101 | | - # Create a test sketch |
102 | | - sketch_path = os.path.join(data_dir, "test_output_flag_default_path") |
103 | | - fqbn = "arduino:avr:uno" |
104 | | - result = run_command("sketch new {}".format(sketch_path)) |
105 | | - assert result.ok |
106 | | - |
107 | | - # Test the --output flag defaulting to current working dir |
108 | | - result = run_command( |
109 | | - "compile -b {fqbn} {sketch_path} -o test".format( |
110 | | - fqbn=fqbn, sketch_path=sketch_path |
111 | | - ) |
112 | | - ) |
113 | | - assert result.ok |
114 | | - assert os.path.exists(os.path.join(working_dir, "test.hex")) |
115 | | - |
116 | | - # Test extension won't be added if already present |
117 | | - result = run_command( |
118 | | - "compile -b {fqbn} {sketch_path} -o test2.hex".format( |
119 | | - fqbn=fqbn, sketch_path=sketch_path |
120 | | - ) |
121 | | - ) |
122 | | - assert result.ok |
123 | | - assert os.path.exists(os.path.join(working_dir, "test2.hex")) |
124 | | - |
125 | | - |
126 | | -def test_compile_with_sketch_with_symlink_selfloop(run_command, data_dir): |
127 | | - # Init the environment explicitly |
128 | | - result = run_command("core update-index") |
129 | | - assert result.ok |
130 | | - |
131 | | - # Download latest AVR |
132 | | - result = run_command("core install arduino:avr") |
133 | | - assert result.ok |
134 | | - |
135 | | - sketch_name = "CompileIntegrationTestSymlinkSelfLoop" |
136 | | - sketch_path = os.path.join(data_dir, sketch_name) |
137 | | - fqbn = "arduino:avr:uno" |
138 | | - |
139 | | - # Create a test sketch |
140 | | - result = run_command("sketch new {}".format(sketch_path)) |
141 | | - assert result.ok |
142 | | - assert "Sketch created in: {}".format(sketch_path) in result.stdout |
143 | | - |
144 | | - # create a symlink that loops on himself |
145 | | - loop_file_path = os.path.join(sketch_path, "loop") |
146 | | - os.symlink(loop_file_path, loop_file_path) |
147 | | - |
148 | | - # Build sketch for arduino:avr:uno |
149 | | - result = run_command( |
150 | | - "compile -b {fqbn} {sketch_path}".format(fqbn=fqbn, sketch_path=sketch_path) |
151 | | - ) |
152 | | - # The assertion is a bit relaxed in this case because win behaves differently from macOs and linux |
153 | | - # returning a different error detailed message |
154 | | - assert "Error during sketch processing" in result.stderr |
155 | | - assert not result.ok |
156 | | - |
157 | | - sketch_name = "CompileIntegrationTestSymlinkDirLoop" |
158 | | - sketch_path = os.path.join(data_dir, sketch_name) |
159 | | - fqbn = "arduino:avr:uno" |
160 | | - |
161 | | - # Create a test sketch |
162 | | - result = run_command("sketch new {}".format(sketch_path)) |
163 | | - assert result.ok |
164 | | - assert "Sketch created in: {}".format(sketch_path) in result.stdout |
165 | | - |
166 | | - # create a symlink that loops on the upper level |
167 | | - loop_dir_path = os.path.join(sketch_path, "loop_dir") |
168 | | - os.mkdir(loop_dir_path) |
169 | | - loop_dir_symlink_path = os.path.join(loop_dir_path, "loop_dir_symlink") |
170 | | - os.symlink(loop_dir_path, loop_dir_symlink_path) |
171 | | - |
172 | | - # Build sketch for arduino:avr:uno |
173 | | - result = run_command( |
174 | | - "compile -b {fqbn} {sketch_path}".format(fqbn=fqbn, sketch_path=sketch_path) |
175 | | - ) |
176 | | - # The assertion is a bit relaxed also in this case because macOS behaves differently from win and linux: |
177 | | - # the cli does not follow recursively the symlink til breaking |
178 | | - assert "Error during sketch processing" in result.stderr |
179 | | - assert not result.ok |
180 | | - |
181 | | - |
182 | | -@pytest.mark.skipif(running_on_ci(), reason="VMs have no serial ports") |
183 | | -def test_compile_and_compile_combo(run_command, data_dir, detected_boards): |
184 | | - # Init the environment explicitly |
185 | | - result = run_command("core update-index") |
186 | | - assert result.ok |
187 | | - |
188 | | - # Install required core(s) |
189 | | - result = run_command("core install arduino:avr") |
190 | | - result = run_command("core install arduino:samd") |
191 | | - assert result.ok |
192 | | - |
193 | | - # Create a test sketch |
194 | | - sketch_name = "CompileAndUploadIntegrationTest" |
195 | | - sketch_path = os.path.join(data_dir, sketch_name) |
196 | | - result = run_command("sketch new {}".format(sketch_path)) |
197 | | - assert result.ok |
198 | | - assert "Sketch created in: {}".format(sketch_path) in result.stdout |
199 | | - |
200 | | - # Build sketch for each detected board |
201 | | - for board in detected_boards: |
202 | | - log_file_name = "{fqbn}-compile.log".format(fqbn=board.fqbn.replace(":", "-")) |
203 | | - log_file_path = os.path.join(data_dir, log_file_name) |
204 | | - command_log_flags = "--log-format json --log-file {} --log-level trace".format( |
205 | | - log_file_path |
206 | | - ) |
207 | | - result = run_command( |
208 | | - "compile -b {fqbn} --upload -p {address} {sketch_path} {log_flags}".format( |
209 | | - fqbn=board.fqbn, |
210 | | - address=board.address, |
211 | | - sketch_path=sketch_path, |
212 | | - log_flags=command_log_flags, |
213 | | - ) |
214 | | - ) |
215 | | - assert result.ok |
216 | | - # check from the logs if the bin file were uploaded on the current board |
217 | | - log_json = open(log_file_path, "r") |
218 | | - json_log_lines = log_json.readlines() |
219 | | - expected_trace_sequence = [ |
220 | | - "Compile {sketch} for {fqbn} started".format( |
221 | | - sketch=sketch_path, fqbn=board.fqbn |
222 | | - ), |
223 | | - "Compile {sketch} for {fqbn} successful".format( |
224 | | - sketch=sketch_name, fqbn=board.fqbn |
225 | | - ), |
226 | | - "Upload {sketch} on {fqbn} started".format( |
227 | | - sketch=sketch_path, fqbn=board.fqbn |
228 | | - ), |
229 | | - "Upload {sketch} on {fqbn} successful".format( |
230 | | - sketch=sketch_name, fqbn=board.fqbn |
231 | | - ), |
232 | | - ] |
233 | | - assert is_message_sequence_in_json_log_traces( |
234 | | - expected_trace_sequence, json_log_lines |
235 | | - ) |
236 | 15 |
|
| 16 | +import os |
| 17 | +import subprocess |
| 18 | +import time |
237 | 19 |
|
238 | | -def is_message_sequence_in_json_log_traces(message_sequence, log_json_lines): |
239 | | - trace_entries = [] |
240 | | - for entry in log_json_lines: |
241 | | - entry = json.loads(entry) |
242 | | - if entry.get("level") == "trace": |
243 | | - if entry.get("msg") in message_sequence: |
244 | | - trace_entries.append(entry.get("msg")) |
245 | | - return message_sequence == trace_entries |
| 20 | +import requests |
| 21 | +import yaml |
| 22 | +from prometheus_client.parser import text_string_to_metric_families |
246 | 23 |
|
247 | 24 |
|
248 | | -def test_compile_blacklisted_sketchname(run_command, data_dir): |
249 | | - """ |
250 | | - Compile should ignore folders named `RCS`, `.git` and the likes, but |
251 | | - it should be ok for a sketch to be named like RCS.ino |
252 | | - """ |
| 25 | +def test_telemetry_prometheus_endpoint(pytestconfig, data_dir, downloads_dir): |
253 | 26 | # Init the environment explicitly |
254 | | - result = run_command("core update-index") |
255 | | - assert result.ok |
256 | | - |
257 | | - # Download latest AVR |
258 | | - result = run_command("core install arduino:avr") |
259 | | - assert result.ok |
260 | | - |
261 | | - sketch_name = "RCS" |
262 | | - sketch_path = os.path.join(data_dir, sketch_name) |
263 | | - fqbn = "arduino:avr:uno" |
264 | | - |
265 | | - # Create a test sketch |
266 | | - result = run_command("sketch new {}".format(sketch_path)) |
267 | | - assert result.ok |
268 | | - assert "Sketch created in: {}".format(sketch_path) in result.stdout |
269 | | - |
270 | | - # Build sketch for arduino:avr:uno |
271 | | - log_file_name = "compile.log" |
272 | | - log_file_path = os.path.join(data_dir, log_file_name) |
273 | | - result = run_command( |
274 | | - "compile -b {fqbn} {sketch_path}".format(fqbn=fqbn, sketch_path=sketch_path) |
275 | | - ) |
276 | | - assert result.ok |
| 27 | + cli_path = os.path.join(str(pytestconfig.rootdir), "..", "arduino-cli") |
| 28 | + env = os.environ.copy() |
| 29 | + env["ARDUINO_DATA_DIR"] = data_dir |
| 30 | + env["ARDUINO_DOWNLOADS_DIR"] = downloads_dir |
| 31 | + env["ARDUINO_SKETCHBOOK_DIR"] = data_dir |
| 32 | + |
| 33 | + subprocess.Popen([cli_path, "daemon"], env=env) |
| 34 | + |
| 35 | + time.sleep(5) |
| 36 | + |
| 37 | + # parse repertory file |
| 38 | + repertory_file = os.path.join(data_dir, "repertory.yaml") |
| 39 | + with open(repertory_file, 'r') as stream: |
| 40 | + repertory = yaml.safe_load(stream) |
| 41 | + |
| 42 | + # Check if :9090/metrics endpoint is alive, |
| 43 | + # telemetry is enabled by default in daemon mode |
| 44 | + metrics = requests.get("http://localhost:9090/metrics").text |
| 45 | + family = next(text_string_to_metric_families(metrics)) |
| 46 | + sample = family.samples[0] |
| 47 | + assert repertory["installation"]["id"] == sample.labels["installationID"] |
0 commit comments