1# SPDX-License-Identifier: Apache-2.0
2
3cmake_minimum_required(VERSION 3.20.0)
4
5if(CMAKE_SCRIPT_MODE_FILE)
6  # Script mode initialization (re-run)
7  set(ZEPHYR_BASE ${CMAKE_CURRENT_LIST_DIR}/../../../)
8  list(APPEND CMAKE_MODULE_PATH "${ZEPHYR_BASE}/cmake/modules")
9  include(extensions)
10else()
11  # Project mode initialization (main CMake invocation)
12  find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
13  project(zephyr_get_test)
14  target_sources(app PRIVATE ${ZEPHYR_BASE}/misc/empty_file.c)
15endif()
16
17if(SYSBUILD)
18  get_property(IMAGE_NAME TARGET sysbuild_cache PROPERTY SYSBUILD_NAME)
19else()
20  set(IMAGE_NAME "no_sysbuild")
21endif()
22
23# Usage:
24#   - run_suite(<test-1> [<test-2> ...])
25#
26# Run tests and count assert failures. An error report will be shown
27# at the end, either here or in sysbuild.cmake.
28#
29macro(run_suite)
30  set(ASSERT_FAIL_COUNT 0 CACHE INTERNAL "")
31
32  foreach(TEST_NAME ${ARGV})
33    cmake_language(CALL ${TEST_NAME})
34  endforeach()
35
36  if($CACHE{ASSERT_FAIL_COUNT} GREATER 0)
37    if(NOT SYSBUILD)
38      set(mode FATAL_ERROR)
39    else()
40      set(mode WARNING)
41    endif()
42    message(${mode} "$CACHE{ASSERT_FAIL_COUNT} assertion(s) failed")
43  endif()
44endmacro()
45
46# Usage:
47#   - assert_equal(<variable> <expected-value>)
48#
49#   - assert_equal(<variable>
50#       IMAGE <image-1> <expected-value-for-image-1>
51#      [IMAGE <image-2> <expected-value-for-image-2> ...]
52#     )
53#
54function(assert_equal variable expected_value)
55  if("${variable}" MATCHES "{.+}$")
56    string(CONFIGURE "$${variable}" actual_value)
57  else()
58    set(actual_value "${${variable}}")
59  endif()
60
61  if(expected_value STREQUAL "IMAGE")
62    set(i 1)
63    while(i LESS ARGC)
64      if(NOT ARGV${i} STREQUAL "IMAGE")
65        message(FATAL_ERROR "Invalid argument ${i}: '${ARGV${i}}' (expected 'IMAGE')")
66      endif()
67      math(EXPR i "${i} + 1")
68      set(image_name "${ARGV${i}}")
69      math(EXPR i "${i} + 1")
70      set(expected_value "${ARGV${i}}")
71      math(EXPR i "${i} + 1")
72
73      if(image_name STREQUAL IMAGE_NAME)
74        break()
75      endif()
76      set(expected_value)
77    endwhile()
78    if(NOT DEFINED expected_value)
79      message(FATAL_ERROR "No value provided for image: '${IMAGE_NAME}'")
80    endif()
81  endif()
82
83  set(info "${TEST_NAME}: ${variable} == '${actual_value}'")
84  if(CMAKE_SCRIPT_MODE_FILE)
85    string(PREPEND info "script mode ")
86  endif()
87  if("${actual_value}" STREQUAL "${expected_value}")
88    message("PASS: ${info}")
89  else()
90    message("FAIL: ${info}\n      expected '${expected_value}'")
91    math(EXPR ASSERT_FAIL_COUNT "$CACHE{ASSERT_FAIL_COUNT} + 1")
92    set(ASSERT_FAIL_COUNT ${ASSERT_FAIL_COUNT} CACHE INTERNAL "")
93  endif()
94endfunction()
95
96
97function(test_precedence)
98  # Test with a local variable not controlled by sysbuild.
99  set(ENV{VARIABLE} "environment")
100  set(VARIABLE "cmake cache" CACHE INTERNAL "")
101  set(VARIABLE "local")
102
103  # CMake cache value has the highest precedence.
104  zephyr_get(VARIABLE)
105  assert_equal(VARIABLE "cmake cache")
106
107  # Environment value has the next highest precedence.
108  unset(VARIABLE CACHE)
109  unset(VARIABLE)
110
111  zephyr_get(VARIABLE)
112  assert_equal(VARIABLE "environment")
113
114  # Environment value is cached after it's retrieved.
115  assert_equal(CACHE{VARIABLE} "environment")
116
117  # Locally scoped value has the lowest precedence.
118  unset(VARIABLE CACHE)
119  unset(ENV{VARIABLE})
120  set(VARIABLE "local")
121
122  zephyr_get(VARIABLE)
123  assert_equal(VARIABLE "local")
124  assert_equal(CACHE{VARIABLE} "")
125
126  unset(VARIABLE)
127  zephyr_get(VARIABLE)
128  assert_equal(VARIABLE "")
129endfunction()
130
131
132function(test_precedence_with_sysbuild)
133  # Test with an external variable provided in testcase.yaml
134  set(ENV{TESTCASE_VARIABLE} "environment")
135  set(TESTCASE_VARIABLE "cmake cache" CACHE INTERNAL "")
136  set(TESTCASE_VARIABLE "local")
137
138  zephyr_get(TESTCASE_VARIABLE SYSBUILD GLOBAL)
139  assert_equal(TESTCASE_VARIABLE
140    IMAGE no_sysbuild    "cmake cache"
141    # Provided -DTESTCASE_VARIABLE=<...> serves as the
142    # LOCAL sysbuild-defined value for this primary image.
143    IMAGE zephyr_get     "sysbuild.main"
144    # Provided -Dzephyr_get_2nd_TESTCASE_VARIABLE=<...> serves as
145    # the LOCAL sysbuild-defined value for this secondary image.
146    IMAGE zephyr_get_2nd "sysbuild.2nd"
147    # Provided -DTESTCASE_VARIABLE=<...> serves as the
148    # GLOBAL sysbuild-defined value for this tertiary image;
149    # it has no LOCAL value of its own.
150    IMAGE zephyr_get_3rd "sysbuild.main"
151  )
152
153  unset(TESTCASE_VARIABLE CACHE)
154  unset(TESTCASE_VARIABLE)
155
156  zephyr_get(TESTCASE_VARIABLE SYSBUILD LOCAL)
157  assert_equal(TESTCASE_VARIABLE
158    IMAGE no_sysbuild    "environment"
159    IMAGE zephyr_get     "sysbuild.main"
160    IMAGE zephyr_get_2nd "sysbuild.2nd"
161    # This image has no LOCAL sysbuild-defined value.
162    IMAGE zephyr_get_3rd "environment"
163  )
164  assert_equal(CACHE{TESTCASE_VARIABLE}
165    IMAGE no_sysbuild    "environment"
166    IMAGE zephyr_get     ""
167    IMAGE zephyr_get_2nd ""
168    IMAGE zephyr_get_3rd "environment"
169  )
170
171  unset(TESTCASE_VARIABLE CACHE)
172  unset(ENV{TESTCASE_VARIABLE})
173  set(TESTCASE_VARIABLE "local")
174
175  # This should be equivalent to: zephyr_get(... SYSBUILD GLOBAL)
176  zephyr_get(TESTCASE_VARIABLE)
177  assert_equal(TESTCASE_VARIABLE
178    IMAGE no_sysbuild    "local"
179    IMAGE zephyr_get     "sysbuild.main"
180    IMAGE zephyr_get_2nd "sysbuild.2nd"
181    IMAGE zephyr_get_3rd "sysbuild.main"
182  )
183endfunction()
184
185
186function(test_merge)
187  # Test with a local variable not controlled by sysbuild.
188  set(ENV{VARIABLE} "environment")
189  set(VARIABLE "cmake cache" CACHE INTERNAL "")
190  set(VARIABLE "local")
191
192  zephyr_get(VARIABLE MERGE)
193  assert_equal(VARIABLE "cmake cache;environment;local")
194
195  # Environment is not cached when using MERGE.
196  unset(VARIABLE CACHE)
197  unset(VARIABLE)
198
199  zephyr_get(VARIABLE MERGE)
200  assert_equal(VARIABLE "environment")
201  assert_equal(CACHE{VARIABLE} "")
202
203  unset(ENV{VARIABLE})
204  set(VARIABLE "cmake cache" CACHE INTERNAL "")
205  set(VARIABLE "local")
206
207  zephyr_get(VARIABLE MERGE)
208  assert_equal(VARIABLE "cmake cache;local")
209
210  unset(VARIABLE CACHE)
211  unset(VARIABLE)
212
213  zephyr_get(VARIABLE MERGE)
214  assert_equal(VARIABLE "")
215
216  # Lists are combined and *rightmost* duplicates are removed.
217  set(ENV{VARIABLE} "A;B;C;D")
218  set(VARIABLE "F;E;D;C")
219
220  zephyr_get(VARIABLE MERGE)
221  assert_equal(VARIABLE "A;B;C;D;F;E")
222
223  # Test with an external variable provided in testcase.yaml
224  unset(ENV{TESTCASE_VARIABLE})
225  unset(TESTCASE_VARIABLE CACHE)
226
227  zephyr_get(TESTCASE_VARIABLE MERGE SYSBUILD LOCAL)
228  assert_equal(TESTCASE_VARIABLE
229    IMAGE no_sysbuild    ""
230    IMAGE zephyr_get     "sysbuild.main"
231    IMAGE zephyr_get_2nd "sysbuild.2nd"
232    # This image has no LOCAL sysbuild-defined value.
233    IMAGE zephyr_get_3rd ""
234  )
235
236  unset(TESTCASE_VARIABLE)
237
238  # Add the GLOBAL sysbuild-defined value.
239  zephyr_get(TESTCASE_VARIABLE MERGE SYSBUILD GLOBAL)
240  assert_equal(TESTCASE_VARIABLE
241    IMAGE no_sysbuild    ""
242    # This image's LOCAL and GLOBAL are identical; duplicates are removed.
243    IMAGE zephyr_get     "sysbuild.main"
244    IMAGE zephyr_get_2nd "sysbuild.2nd;sysbuild.main"
245    IMAGE zephyr_get_3rd "sysbuild.main"
246  )
247
248  # Add more variable scopes.
249  set(ENV{TESTCASE_VARIABLE} "environment")
250  set(TESTCASE_VARIABLE "cmake cache" CACHE INTERNAL "")
251  set(TESTCASE_VARIABLE "local")
252
253  zephyr_get(TESTCASE_VARIABLE MERGE SYSBUILD GLOBAL)
254  assert_equal(TESTCASE_VARIABLE
255    IMAGE no_sysbuild    "cmake cache;environment;local"
256    IMAGE zephyr_get     "sysbuild.main;cmake cache;environment;local"
257    IMAGE zephyr_get_2nd "sysbuild.2nd;sysbuild.main;cmake cache;environment;local"
258    IMAGE zephyr_get_3rd "sysbuild.main;cmake cache;environment;local"
259  )
260
261  unset(TESTCASE_VARIABLE)
262  zephyr_get(TESTCASE_VARIABLE MERGE SYSBUILD LOCAL)
263  assert_equal(TESTCASE_VARIABLE
264    IMAGE no_sysbuild    "cmake cache;environment"
265    IMAGE zephyr_get     "sysbuild.main;cmake cache;environment"
266    IMAGE zephyr_get_2nd "sysbuild.2nd;cmake cache;environment"
267    IMAGE zephyr_get_3rd "cmake cache;environment"
268  )
269
270  unset(TESTCASE_VARIABLE)
271  unset(TESTCASE_VARIABLE CACHE)
272
273  # This should be equivalent to: zephyr_get(... SYSBUILD GLOBAL)
274  zephyr_get(TESTCASE_VARIABLE MERGE)
275  assert_equal(TESTCASE_VARIABLE
276    IMAGE no_sysbuild    "environment"
277    IMAGE zephyr_get     "sysbuild.main;environment"
278    IMAGE zephyr_get_2nd "sysbuild.2nd;sysbuild.main;environment"
279    IMAGE zephyr_get_3rd "sysbuild.main;environment"
280  )
281  assert_equal(CACHE{TESTCASE_VARIABLE} "")
282endfunction()
283
284
285function(test_multivar)
286  # Test with local variables not controlled by sysbuild.
287  foreach(var VARIABLE_1 VARIABLE_2 VARIABLE_3)
288    unset(ENV{${var}})
289    unset(${var} CACHE)
290    unset(${var})
291  endforeach()
292
293  set(ENV{VARIABLE_1} "environment 1")
294  set(ENV{VARIABLE_3} "environment 3")
295  set(VARIABLE_2 "cmake cache 2" CACHE INTERNAL "")
296  set(VARIABLE_2 "local 2")
297  set(VARIABLE_3 "local 3")
298
299  # Highest precedence scope always wins.
300  zephyr_get(RESULT VAR VARIABLE_1 VARIABLE_2 VARIABLE_3)
301  assert_equal(RESULT "cmake cache 2")
302  zephyr_get(RESULT VAR VARIABLE_3 VARIABLE_1 VARIABLE_2)
303  assert_equal(RESULT "cmake cache 2")
304
305  # With multiple variables in the same scope, the first variable wins.
306  set(VARIABLE_1 "cmake cache 1" CACHE INTERNAL "")
307  zephyr_get(RESULT VAR VARIABLE_1 VARIABLE_2 VARIABLE_3)
308  assert_equal(RESULT "cmake cache 1")
309  zephyr_get(RESULT VAR VARIABLE_2 VARIABLE_3 VARIABLE_1)
310  assert_equal(RESULT "cmake cache 2")
311
312  unset(ENV{RESULT})
313  unset(RESULT CACHE)
314  unset(RESULT)
315
316  # With MERGE, all scopes are reflected subject to variable order.
317  zephyr_get(RESULT MERGE VAR VARIABLE_1 VARIABLE_2 VARIABLE_3)
318  assert_equal(RESULT "cmake cache 1;cmake cache 2;environment 1;environment 3;local 2;local 3")
319
320  set(ENV{RESULT} "environment r")
321  set(RESULT "cmake cache r" CACHE INTERNAL "")
322  set(RESULT "local r")
323
324  # Unless RESULT is included in VAR, it does not affect the output.
325  zephyr_get(RESULT MERGE VAR VARIABLE_3 VARIABLE_2 VARIABLE_1)
326  assert_equal(RESULT "cmake cache 2;cmake cache 1;environment 3;environment 1;local 3;local 2")
327
328  set(RESULT "local r")
329  zephyr_get(RESULT MERGE VAR RESULT VARIABLE_3 VARIABLE_2 VARIABLE_1)
330  assert_equal(RESULT "cmake cache r;cmake cache 2;cmake cache 1;environment r;environment 3;environment 1;local r;local 3;local 2")
331
332  set(RESULT "local r")
333  zephyr_get(RESULT MERGE VAR VARIABLE_2 VARIABLE_3 VARIABLE_1 RESULT)
334  assert_equal(RESULT "cmake cache 2;cmake cache 1;cmake cache r;environment 3;environment 1;environment r;local 2;local 3;local r")
335
336  unset(ENV{RESULT})
337  unset(RESULT CACHE)
338  unset(RESULT)
339
340  # If an environment value wins, it is cached afterwards.
341  unset(VARIABLE_1 CACHE)
342  unset(VARIABLE_2 CACHE)
343
344  zephyr_get(RESULT VAR VARIABLE_1 VARIABLE_2 VARIABLE_3)
345  assert_equal(RESULT "environment 1")
346  assert_equal(CACHE{VARIABLE_1} "environment 1")
347  assert_equal(CACHE{VARIABLE_2} "")
348  assert_equal(CACHE{VARIABLE_3} "")
349  assert_equal(CACHE{RESULT} "")
350
351  unset(VARIABLE_1 CACHE)
352  unset(VARIABLE_3)
353
354  zephyr_get(RESULT VAR VARIABLE_3 VARIABLE_1 VARIABLE_2)
355  assert_equal(RESULT "environment 3")
356  assert_equal(CACHE{VARIABLE_1} "")
357  assert_equal(CACHE{VARIABLE_2} "")
358  assert_equal(CACHE{VARIABLE_3} "environment 3")
359  assert_equal(CACHE{RESULT} "")
360
361  set(VARIABLE_2 "cmake cache 2" CACHE INTERNAL "")
362  set(VARIABLE_2 "local 2")
363  set(VARIABLE_3 "local 3")
364  unset(VARIABLE_3 CACHE)
365
366  # Include the external variable provided in testcase.yaml
367  set(ENV{TESTCASE_VARIABLE} "environment s")
368  set(TESTCASE_VARIABLE "cmake cache s" CACHE INTERNAL "")
369  set(TESTCASE_VARIABLE "local s")
370
371  zephyr_get(RESULT SYSBUILD GLOBAL VAR TESTCASE_VARIABLE VARIABLE_1 VARIABLE_2 VARIABLE_3)
372  assert_equal(RESULT
373    IMAGE no_sysbuild    "cmake cache s"
374    IMAGE zephyr_get     "sysbuild.main"
375    IMAGE zephyr_get_2nd "sysbuild.2nd"
376    IMAGE zephyr_get_3rd "sysbuild.main"
377  )
378  zephyr_get(RESULT SYSBUILD LOCAL VAR TESTCASE_VARIABLE VARIABLE_1 VARIABLE_2 VARIABLE_3)
379  assert_equal(RESULT
380    IMAGE no_sysbuild    "cmake cache s"
381    IMAGE zephyr_get     "sysbuild.main"
382    IMAGE zephyr_get_2nd "sysbuild.2nd"
383    IMAGE zephyr_get_3rd "cmake cache s"
384  )
385
386  unset(RESULT)
387  zephyr_get(RESULT SYSBUILD GLOBAL MERGE VAR TESTCASE_VARIABLE VARIABLE_1 VARIABLE_2 VARIABLE_3)
388  assert_equal(RESULT
389    IMAGE no_sysbuild    "cmake cache s;cmake cache 2;environment s;environment 1;environment 3;local s;local 2;local 3"
390    IMAGE zephyr_get     "sysbuild.main;cmake cache s;cmake cache 2;environment s;environment 1;environment 3;local s;local 2;local 3"
391    IMAGE zephyr_get_2nd "sysbuild.2nd;sysbuild.main;cmake cache s;cmake cache 2;environment s;environment 1;environment 3;local s;local 2;local 3"
392    IMAGE zephyr_get_3rd "sysbuild.main;cmake cache s;cmake cache 2;environment s;environment 1;environment 3;local s;local 2;local 3"
393  )
394  unset(RESULT)
395  zephyr_get(RESULT SYSBUILD LOCAL MERGE VAR TESTCASE_VARIABLE VARIABLE_1 VARIABLE_2 VARIABLE_3)
396  assert_equal(RESULT
397    IMAGE no_sysbuild    "cmake cache s;cmake cache 2;environment s;environment 1;environment 3;local s;local 2;local 3"
398    IMAGE zephyr_get     "sysbuild.main;cmake cache s;cmake cache 2;environment s;environment 1;environment 3;local s;local 2;local 3"
399    IMAGE zephyr_get_2nd "sysbuild.2nd;cmake cache s;cmake cache 2;environment s;environment 1;environment 3;local s;local 2;local 3"
400    IMAGE zephyr_get_3rd "cmake cache s;cmake cache 2;environment s;environment 1;environment 3;local s;local 2;local 3"
401  )
402  unset(RESULT)
403  zephyr_get(RESULT SYSBUILD GLOBAL MERGE VAR VARIABLE_3 VARIABLE_2 VARIABLE_1 TESTCASE_VARIABLE)
404  assert_equal(RESULT
405    IMAGE no_sysbuild    "cmake cache 2;cmake cache s;environment 3;environment 1;environment s;local 3;local 2;local s"
406    IMAGE zephyr_get     "sysbuild.main;cmake cache 2;cmake cache s;environment 3;environment 1;environment s;local 3;local 2;local s"
407    IMAGE zephyr_get_2nd "sysbuild.2nd;sysbuild.main;cmake cache 2;cmake cache s;environment 3;environment 1;environment s;local 3;local 2;local s"
408    IMAGE zephyr_get_3rd "sysbuild.main;cmake cache 2;cmake cache s;environment 3;environment 1;environment s;local 3;local 2;local s"
409  )
410  unset(RESULT)
411  zephyr_get(RESULT SYSBUILD LOCAL MERGE VAR VARIABLE_3 VARIABLE_2 VARIABLE_1 TESTCASE_VARIABLE)
412  assert_equal(RESULT
413    IMAGE no_sysbuild    "cmake cache 2;cmake cache s;environment 3;environment 1;environment s;local 3;local 2;local s"
414    IMAGE zephyr_get     "sysbuild.main;cmake cache 2;cmake cache s;environment 3;environment 1;environment s;local 3;local 2;local s"
415    IMAGE zephyr_get_2nd "sysbuild.2nd;cmake cache 2;cmake cache s;environment 3;environment 1;environment s;local 3;local 2;local s"
416    IMAGE zephyr_get_3rd "cmake cache 2;cmake cache s;environment 3;environment 1;environment s;local 3;local 2;local s"
417  )
418endfunction()
419
420
421function(test_merge_reverse)
422  # Test with local variables not controlled by sysbuild.
423  foreach(var VARIABLE_1 VARIABLE_2 VARIABLE_3)
424    unset(ENV{${var}})
425    unset(${var} CACHE)
426    unset(${var})
427  endforeach()
428
429  set(ENV{VARIABLE_1} "environment 1")
430  set(ENV{VARIABLE_2} "environment 2")
431  set(VARIABLE_1 "cmake cache 1" CACHE INTERNAL "")
432  set(VARIABLE_2 "cmake cache 2" CACHE INTERNAL "")
433  set(VARIABLE_1 "local 1")
434  set(VARIABLE_2 "local 2")
435
436  # Only scopes are reversed; not variables.
437  zephyr_get(VARIABLE_1 MERGE REVERSE)
438  assert_equal(VARIABLE_1 "local 1;environment 1;cmake cache 1")
439
440  zephyr_get(RESULT MERGE REVERSE VAR VARIABLE_1 VARIABLE_2)
441  assert_equal(RESULT "local 1;local 2;environment 1;environment 2;cmake cache 1;cmake cache 2")
442
443  # Lists are combined and *leftmost* duplicates are removed.
444  set(ENV{VARIABLE_3} "A;B;C;D")
445  set(VARIABLE_3 "F;E;D;C")
446  unset(RESULT)
447
448  zephyr_get(VARIABLE_3 MERGE REVERSE)
449  assert_equal(VARIABLE_3 "F;E;A;B;C;D")
450
451  zephyr_get(RESULT MERGE REVERSE VAR VARIABLE_1 VARIABLE_2 VARIABLE_3)
452  assert_equal(RESULT "local 1;local 2;F;E;environment 1;environment 2;A;B;C;D;cmake cache 1;cmake cache 2")
453
454  # Test with an external variable provided in testcase.yaml
455  unset(ENV{TESTCASE_VARIABLE})
456  unset(TESTCASE_VARIABLE CACHE)
457
458  # In REVERSE, the GLOBAL value goes before the LOCAL.
459  zephyr_get(TESTCASE_VARIABLE MERGE REVERSE SYSBUILD GLOBAL)
460  assert_equal(TESTCASE_VARIABLE
461    IMAGE no_sysbuild    ""
462    IMAGE zephyr_get     "sysbuild.main"
463    IMAGE zephyr_get_2nd "sysbuild.main;sysbuild.2nd"
464    IMAGE zephyr_get_3rd "sysbuild.main"
465  )
466
467  # Add more variable scopes.
468  set(ENV{TESTCASE_VARIABLE} "environment s")
469  set(TESTCASE_VARIABLE "cmake cache s" CACHE INTERNAL "")
470  set(TESTCASE_VARIABLE "local s")
471
472  zephyr_get(TESTCASE_VARIABLE MERGE REVERSE SYSBUILD GLOBAL)
473  assert_equal(TESTCASE_VARIABLE
474    IMAGE no_sysbuild    "local s;environment s;cmake cache s"
475    IMAGE zephyr_get     "local s;environment s;cmake cache s;sysbuild.main"
476    IMAGE zephyr_get_2nd "local s;environment s;cmake cache s;sysbuild.main;sysbuild.2nd"
477    IMAGE zephyr_get_3rd "local s;environment s;cmake cache s;sysbuild.main"
478  )
479
480  unset(TESTCASE_VARIABLE)
481  zephyr_get(TESTCASE_VARIABLE MERGE REVERSE SYSBUILD LOCAL)
482  assert_equal(TESTCASE_VARIABLE
483    IMAGE no_sysbuild    "environment s;cmake cache s"
484    IMAGE zephyr_get     "environment s;cmake cache s;sysbuild.main"
485    IMAGE zephyr_get_2nd "environment s;cmake cache s;sysbuild.2nd"
486    IMAGE zephyr_get_3rd "environment s;cmake cache s"
487  )
488
489  unset(RESULT)
490  set(TESTCASE_VARIABLE "local s")
491
492  # This should be equivalent to: zephyr_get(... SYSBUILD GLOBAL)
493  zephyr_get(RESULT MERGE REVERSE VAR TESTCASE_VARIABLE VARIABLE_1 VARIABLE_2)
494  assert_equal(RESULT
495    IMAGE no_sysbuild    "local s;local 1;local 2;environment s;environment 1;environment 2;cmake cache s;cmake cache 1;cmake cache 2"
496    IMAGE zephyr_get     "local s;local 1;local 2;environment s;environment 1;environment 2;cmake cache s;cmake cache 1;cmake cache 2;sysbuild.main"
497    IMAGE zephyr_get_2nd "local s;local 1;local 2;environment s;environment 1;environment 2;cmake cache s;cmake cache 1;cmake cache 2;sysbuild.main;sysbuild.2nd"
498    IMAGE zephyr_get_3rd "local s;local 1;local 2;environment s;environment 1;environment 2;cmake cache s;cmake cache 1;cmake cache 2;sysbuild.main"
499  )
500endfunction()
501
502
503function(test_snippets_scope)
504  zephyr_scope_exists(snippets_defined snippets)
505  if(NOT snippets_defined)
506    zephyr_create_scope(snippets)
507  endif()
508
509  zephyr_set(VARIABLE_1 "snippet 1" SCOPE snippets)
510  zephyr_set(VARIABLE_2 "snippet 2" SCOPE snippets)
511  zephyr_set(VARIABLE_3 "snippet 3" SCOPE snippets)
512  zephyr_set(TESTCASE_VARIABLE "snippet s" SCOPE snippets)
513
514  foreach(var VARIABLE_1 VARIABLE_2 VARIABLE_3 TESTCASE_VARIABLE)
515    unset(ENV{${var}})
516    unset(${var} CACHE)
517    unset(${var})
518  endforeach()
519
520  set(ENV{VARIABLE_1} "environment 1")
521  set(ENV{VARIABLE_3} "environment 3")
522  set(VARIABLE_2 "cmake cache 2" CACHE INTERNAL "")
523  set(VARIABLE_3 "cmake cache 3" CACHE INTERNAL "")
524
525  # Snippets have higher precedence than environment, but lower than CMake cache.
526  zephyr_get(VARIABLE_1)
527  assert_equal(VARIABLE_1 "snippet 1")
528  unset(VARIABLE_1)
529  zephyr_get(VARIABLE_1 MERGE)
530  assert_equal(VARIABLE_1 "snippet 1;environment 1")
531
532  zephyr_get(VARIABLE_2)
533  assert_equal(VARIABLE_2 "cmake cache 2")
534  set(VARIABLE_2 "local 2")
535  zephyr_get(VARIABLE_2 MERGE)
536  assert_equal(VARIABLE_2 "cmake cache 2;snippet 2;local 2")
537
538  zephyr_get(VARIABLE_3)
539  assert_equal(VARIABLE_3 "cmake cache 3")
540  set(VARIABLE_3 "local 3")
541  zephyr_get(VARIABLE_3 MERGE)
542  assert_equal(VARIABLE_3 "cmake cache 3;snippet 3;environment 3;local 3")
543
544  unset(VARIABLE_1)
545  set(VARIABLE_2 "local 2")
546  set(VARIABLE_3 "local 3")
547
548  zephyr_get(RESULT MERGE REVERSE VAR VARIABLE_1 VARIABLE_2 VARIABLE_3)
549  assert_equal(RESULT "local 2;local 3;environment 1;environment 3;snippet 1;snippet 2;snippet 3;cmake cache 2;cmake cache 3")
550
551  # Transitively, snippets have lower precedence than sysbuild-defined values.
552  zephyr_get(TESTCASE_VARIABLE)
553  assert_equal(TESTCASE_VARIABLE
554    IMAGE no_sysbuild    "snippet s"
555    IMAGE zephyr_get     "sysbuild.main"
556    IMAGE zephyr_get_2nd "sysbuild.2nd"
557    IMAGE zephyr_get_3rd "sysbuild.main"
558  )
559  zephyr_get(TESTCASE_VARIABLE SYSBUILD LOCAL)
560  assert_equal(TESTCASE_VARIABLE
561    IMAGE no_sysbuild    "snippet s"
562    IMAGE zephyr_get     "sysbuild.main"
563    IMAGE zephyr_get_2nd "sysbuild.2nd"
564    IMAGE zephyr_get_3rd "snippet s"
565  )
566  unset(TESTCASE_VARIABLE)
567  zephyr_get(TESTCASE_VARIABLE MERGE SYSBUILD GLOBAL)
568  assert_equal(TESTCASE_VARIABLE
569    IMAGE no_sysbuild    "snippet s"
570    IMAGE zephyr_get     "sysbuild.main;snippet s"
571    IMAGE zephyr_get_2nd "sysbuild.2nd;sysbuild.main;snippet s"
572    IMAGE zephyr_get_3rd "sysbuild.main;snippet s"
573  )
574
575  # If an environment value wins, it gets cached and promoted above snippets.
576  zephyr_set(VARIABLE_1 SCOPE snippets)
577  zephyr_get(VARIABLE_1)
578  assert_equal(VARIABLE_1 "environment 1")
579  assert_equal(CACHE{VARIABLE_1} "environment 1")
580
581  zephyr_set(VARIABLE_1 "snippet 1" SCOPE snippets)
582  zephyr_get(VARIABLE_1)
583  assert_equal(VARIABLE_1 "environment 1")
584
585  unset(VARIABLE_1 CACHE)
586  zephyr_get(VARIABLE_1)
587  assert_equal(VARIABLE_1 "snippet 1")
588endfunction()
589
590run_suite(
591  test_precedence
592  test_precedence_with_sysbuild
593  test_merge
594  test_multivar
595  test_merge_reverse
596  test_snippets_scope
597)
598
599if (NOT CMAKE_SCRIPT_MODE_FILE AND NOT SYSBUILD)
600  # Re-run this testsuite in plain script mode
601  execute_process(COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_LIST_FILE})
602endif()
603