Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable SMP mode on all tests, fix bugs #18531

Merged
merged 11 commits into from Sep 26, 2019

Conversation

andyross
Copy link
Contributor

A bunch of test work to re-enable SMP on all tests (there are two missing, which seem to be bugs in posix and cmsis_v1 -- will file bugs on those), and targetted fixes for the inevitable kernel bugs they exposed.

@andyross andyross requested review from dcpleung, a user and ceolin August 20, 2019 17:11
@andyross andyross changed the title Smpify tests Enable SMP mode on all tests, fix bugs Aug 20, 2019
@zephyrbot zephyrbot added area: Test Framework Issues related not to a particular test, but to the framework instead area: Samples Samples area: Tests Issues related to a particular existing or missing test area: Kernel labels Aug 20, 2019
@zephyrbot
Copy link
Collaborator

zephyrbot commented Aug 20, 2019

All checks are passing now.

Review history of this comment for details about previous failed status.
Note that some checks might have not completed yet.

@andyross
Copy link
Contributor Author

Addresses #14639.

Note that this is never going to pass a regular CI run given how many tests it touches. It has to be validated manually.

Also note that the "long line" errors are entirely lines that were too long already and are single expressions that won't split. Some tests have really long names, and all I'm doing is adding four bytes to the unit_test() macro name.

@ghost
Copy link

ghost commented Aug 21, 2019

Tests are treated with a combination of
flagging specific cases as "1cpu" where we have short-running tests
that can be independently run in an otherwise SMP environment, and via
setting CONFIG_MP_NUM_CPUS=1 where that's not possible (which still
runs the full SMP kernel config, but with only one CPU available).

I'm not convinced this is not just sweeping the problem under the rug again, albeit in a subtly different and more clever fashion. If we're testing features in an SMP environment, shouldn't we replicate an SMP environment? Disabling all CPUs but one, or pegging all the CPUs but one, isn't really representative of normal operation.

If the problem is that the tests are written improperly (that is, assuming one CPU), then shouldn't they be rewritten?

@andyross
Copy link
Contributor Author

If the problem is that the tests are written improperly (that is, assuming one CPU), then shouldn't they be rewritten?

Do we have a volunteer?

To be honest, rewriting tests is itself a kind of sweeping under the rug: our promise to users is that the code continues to do what we thought it did. Rewriting tests so that they pass is itself sort of a way to fool ourselves that we haven't broken anything. It's absolutely routine that strange old tests break new code in unexpected ways because of edge case assumptions (c.f. some of the fixes in this very PR about where reschedule points are, which weren't ever really documented). And that's a good thing.

@ghost
Copy link

ghost commented Aug 21, 2019

To be honest, rewriting tests is itself a kind of sweeping under the rug

If I write a test that assumes that char is signed, and it doesn't run properly on a MIPS, then rewriting the test to remove the assumption isn't sweeping anything under the rug, nor is it breaking any promise to users. It's simply fixing a flawed test.

@andyross
Copy link
Contributor Author

Heh, the checkpatch errors hid a commented-out pair of test cases that never got a fix. Fixed now. Note that since there's concern about risk that this involves an actual detectable difference between scheduling in SMP and UP which has been addressed by relaxing the test a bit. See comments in the third-to-last commit that was just added. It wouldn't be impossible to unify the behavior between the two, but there would be significant complexity and some performance cost.

@ghost
Copy link

ghost commented Aug 22, 2019

In effect, in UP mode "yield" and "reschedule" mean very slightly different things where in SMP they act the same.

This touches upon what I was trying to express the other day, that the SMP vs non-SMP schedulers seem rife with lots of subtle differences of this sort, both in observed behavior by clients, and inside the scheduler code. As an RTOS, Zephyr should have rock-solid and well-defined behavior where scheduling is concerned.

Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we have farther to go with SMP testing but this is a step in the right direction...

@ghost
Copy link

ghost commented Aug 22, 2019

We don't document either behavior, as it happens.

(c.f. some of the fixes in this very PR about where reschedule points are, which weren't ever really documented)

Our documentation is weak in a lot of areas, and this is obviously one of those. "Someday" we should really nail down some critical core features, like scheduling ...

@andyross
Copy link
Contributor Author

Ping on this. If there's resistance to merging the ztest and CI-visible configuration changes at this stage, we should at least split out and merge the fixes themselves.

@nashif
Copy link
Member

nashif commented Aug 26, 2019

@andyross getting:

[99/104] Linking C executable zephyr/zephyr_prebuilt.elf
FAILED: zephyr/zephyr_prebuilt.elf
: && ccache /opt/zephyr-sdk-0.10.3/arc-zephyr-elf/bin/arc-zephyr-elf-gcc    zephyr/CMakeFiles/zephyr_prebuilt.dir/misc/empty_file.c.obj  -o zephyr/zephyr_prebuilt.elf  -Wl,-T zephyr/linker.cmd -Wl,-Map=/home/anashif/zephyrproject/zephyr/sanity-out/hsdk/tests/kernel/workq/work_queue_api/kernel.workqueue/zephyr/zephyr_prebuilt.map -Wl,--whole-archive app/libapp.a zephyr/libzephyr.a zephyr/arch/arch/arc/core/libarch__arc__core.a zephyr/lib/libc/minimal/liblib__libc__minimal.a zephyr/subsys/testsuite/ztest/libsubsys__testsuite__ztest.a zephyr/drivers/serial/libdrivers__serial.a -Wl,--no-whole-archive zephyr/kernel/libkernel.a zephyr/CMakeFiles/offsets.dir/arch/arc/core/offsets/offsets.c.obj -L"/opt/zephyr-sdk-0.10.3/arc-zephyr-elf/bin/../lib/gcc/arc-zephyr-elf/8.3.0/hs" -L/home/anashif/zephyrproject/zephyr/sanity-out/hsdk/tests/kernel/workq/work_queue_api/kernel.workqueue/zephyr -lgcc -Wl,--print-memory-usage -Wl,--gc-sections -Wl,--build-id=none -Wl,--sort-common=descending -Wl,--sort-section=alignment -u_OffsetAbsSyms -u_ConfigAbsSyms -nostdlib -static -no-pie -Wl,-X -Wl,-N -Wl,--orphan-handling=warn -Wl,--fatal-warnings && :
Memory region         Used Size  Region Size  %age Used
            SRAM:       36400 B         2 GB      0.00%
        IDT_LIST:          25 B         2 KB      1.22/opt/zephyr-sdk-0.10.3/arc-zephyr-elf/bin/../lib/gcc/arc-zephyr-elf/8.3.0/../../../../arc-zephyr-elf/bin/ld: zephyr/kernel/libkernel.a(sched.c.obj): in function `z_add_thread_to_ready_q':
/home/anashif/zephyrproject/zephyr/kernel/sched.c:340: undefined reference to `z_arch_sched_ipi'
/opt/zephyr-sdk-0.10.3/arc-zephyr-elf/bin/../lib/gcc/arc-zephyr-elf/8.3.0/../../../../arc-zephyr-elf/bin/ld: /home/anashif/zephyrproject/zephyr/kernel/sched.c:340: undefined reference to `z_arch_sched_ipi'
collect2: error: ld returned 1 exit status
%
ninja: build stopped: subcommand failed.
------------sanity-out/hsdk/tests/kernel/workq/work_queue_api/kernel.workqueue/build.log------------

@andyross andyross force-pushed the smpify-tests branch 2 times, most recently from 8b3f0d1 to 446ef85 Compare August 27, 2019 15:59
@andyross
Copy link
Contributor Author

Ugh. Simple build failure on ARC (the SMP support wasn't quite complete and didn't implement the IPI trigger function), but then I made the mistake of running the x86_64 tests here with my rig in #18656 and found that, hey, SMP is showing some spurious failures that are not host load dependent. (That is, the inherent asynchrony between CPUs is causing failures and not the coarse host scheduling due to other processes interfering -- these are certainly real bugs, not artifacts).

I found two. One turned out to be a simple stack overflow in the new cpuhold feature. The other seems to be a qemu race with HPET (time can go backwards between CPUs) which was easy enough to work around.

I'm still seeing maybe one test run out of ~300 fail, so there's probably at least one more bug in there somewhere.

@andyross
Copy link
Contributor Author

Should be good to merge, given that the remaining bugs are present already and the frequency seems well under the threshold that would impact CI.

@zephyrbot zephyrbot added the area: Timer Timer label Aug 27, 2019
@ghost
Copy link

ghost commented Aug 27, 2019

SMP is showing some spurious failures that are not host load dependent. (That is, the inherent asynchrony between CPUs is causing failures and not the coarse host scheduling due to other processes interfering -- these are certainly real bugs, not artifacts).

... hmmm.. what kinds of real bugs?

The other seems to be a qemu race with HPET (time can go backwards between CPUs) which was easy enough to work around.

I feel like every week we've got some bug to blame on QEMU.

@andyross
Copy link
Contributor Author

Per @nashif this is being pushed. Will merge next week.

@wentongwu wentongwu added the area: SMP Symmetric multiprocessing label Aug 29, 2019
@nashif
Copy link
Member

nashif commented Sep 16, 2019

@andyross two tests at least failing:

cat sanity-out/qemu_x86_64/tests/kernel/sched/schedule_api/kernel.sched.multiq/handler.log
SeaBIOS (version rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org)
Booting from ROM..Running test suite threads_scheduling
===================================================================
starting test - test_bad_priorities
PASS - test_bad_priorities
===================================================================
starting test - test_priority_cooperative
PASS - test_priority_cooperative
===================================================================
starting test - test_priority_preemptible
PASS - test_priority_preemptible
===================================================================
starting test - test_yield_cooperative
PASS - test_yield_cooperative
===================================================================
starting test - test_sleep_cooperative
PASS - test_sleep_cooperative
===================================================================
starting test - test_sleep_wakeup_preemptible
PASS - test_sleep_wakeup_preemptible
===================================================================
starting test - test_pending_thread_wakeup
PASS - test_pending_thread_wakeup
===================================================================
starting test - test_time_slicing_preemptible
PASS - test_time_slicing_preemptible
===================================================================
starting test - test_time_slicing_disable_preemptible
PASS - test_time_slicing_disable_preemptible
===================================================================
starting test - test_lock_preemptible
PASS - test_lock_preemptible
===================================================================
starting test - test_unlock_preemptible
PASS - test_unlock_preemptible
===================================================================
starting test - test_unlock_nested_sched_lock
PASS - test_unlock_nested_sched_lock
===================================================================
starting test - test_sched_is_preempt_thread
PASS - test_sched_is_preempt_thread
===================================================================
starting test - test_slice_reset
PASS - test_slice_reset
===================================================================
starting test - test_slice_scheduling
ABCDEFGHI
ABCDEFGHI
ABCD
    Assertion failed at ZEPHYR_BASE/tests/kernel/sched/schedule_api/src/test_slice_scheduling.c:63: thread_tslice: ((tdelta >= expected_slice_min) && (tdelta <= expee

E
    Assertion failed at ZEPHYR_BASE/tests/kernel/sched/schedule_api/src/test_slice_scheduling.c:63: thread_tslice: ((tdelta >= expected_slice_min) && (tdelta <= expee

F
    Assertion failed at ZEPHYR_BASE/tests/kernel/sched/schedule_api/src/test_slice_scheduling.c:63: thread_tslice: ((tdelta >= expected_slice_min) && (tdelta <= expee

G
    Assertion failed at ZEPHYR_BASE/tests/kernel/sched/schedule_api/src/test_slice_scheduling.c:63: thread_tslice: ((tdelta >= expected_slice_min) && (tdelta <= expee

H
    Assertion failed at ZEPHYR_BASE/tests/kernel/sched/schedule_api/src/test_slice_scheduling.c:63: thread_tslice: ((tdelta >= expected_slice_min) && (tdelta <= expee

I
    Assertion failed at ZEPHYR_BASE/tests/kernel/sched/schedule_api/src/test_slice_scheduling.c:63: thread_tslice: ((tdelta >= expected_slice_min) && (tdelta <= expee



    Assertion failed at ZEPHYR_BASE/tests/kernel/sched/schedule_api/src/test_slice_scheduling.c:63: thread_tslice: ((tdelta >= expected_slice_min) && (tdelta <= expee

A
    Assertion failed at ZEPHYR_BASE/tests/kernel/sched/schedule_api/src/test_slice_scheduling.c:63: thread_tslice: ((tdelta >= expected_slice_min) && (tdelta <= expee

B
    Assertion failed at ZEPHYR_BASE/tests/kernel/sched/schedule_api/src/test_slice_scheduling.c:63: thread_tslice: ((tdelta >= expected_slice_min) && (tdelta <= expee

C
    Assertion failed at ZEPHYR_BASE/tests/kernel/sched/schedule_api/src/test_slice_scheduling.c:63: thread_tslice: ((tdelta >= expected_slice_min) && (tdelta <= expee

FAIL - test_slice_scheduling
===================================================================
starting test - test_priority_scheduling
PASS - test_priority_scheduling
===================================================================
starting test - test_wakeup_expired_timer_thread
ABCDEFGHI
PASS - test_wakeup_expired_timer_thread
===================================================================
starting test - test_user_k_wakeup
PASS - test_user_k_wakeup
===================================================================
starting test - test_user_k_is_preempt
PASS - test_user_k_is_preempt
===================================================================
Test suite threads_scheduling failed.
===================================================================
PROJECT EXECUTION FAILED

and tests/kernel/sched/schedule_api/kernel.sched

@galak
Copy link
Collaborator

galak commented Sep 19, 2019

Want to rebase this one?

Andy Ross added 11 commits September 25, 2019 11:56
There were two related bugs when in SMP mode:

1. Underneath z_reschedule(), the code was inexplicably checking the
   swap_ok flag on the current CPU to see if it was OK to preempt the
   current thread, but reschedule is the DEFINITION of a schedule
   point and we always want to swap, even if the current thread is
   non-preemptible.

2. With similar symptoms: in k_yield() a previous fix correct the
   queue handling for SMP, but it missed the case where a thread of
   the SAME priority as _current was on the queue and would fail to
   swap.  Yielding must always add the current thread to the back of
   the current priority.

Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
The loop in thread abort on SMP where we wait for the results on an
IPI correctly handled the case where a thread running on another CPU
gets its interrupt and self-aborts, but it missed the case where the
other thread pends before receiving the interrupt.

Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
In uniprocessor mode, the kernel knows when a context switch "is
coming" because of the cache optimization and can use that to do
things like update time slice state.  But on SMP the scheduler state
may be updated on the other CPU at any time, so we don't know that a
switch is going to happen until the last minute.

Expose reset_time_slice() as a public function and call it when needed
out of z_swap().

Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
Our thread struct gets initialized piecewise in a bunch of locations
(this is sort of a design flaw).  The is_idle field, which was
introduced to identify idle threads in SMP (where there can be more
than one), was correctly set for idle threads but was being left
uninitialized elsewhere, and in a tiny handful of cases was turning up
nonzero.

The case in pipes. was particularly vexsome, as that isn't a thread at
all but one of the "dummy" threads used for timeouts (another design
flaw IMHO).

Get this right everywhere.

Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
Now that we have a working IPI framework, there's no reason for the
default spin loop for the SMP idle thread.  Just use the default
platform idle and send an IPI when a new thread is readied.

Long term, this can be optimized if necessary (e.g. only send the IPI
to idling CPUs, or check priorities, etc...), but for a 2-cpu system
this is a very reasonable default.

Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
The timeout code has an optimization where it refuses to send a new
timeout to the driver unless it is sooner than one already scheduled.
This won't work on SMP, though, because the timeout value when
timeslicing is enabled depends on the current thread, and on SMP the
decision as to the next thread will not be made until later (when we
swap, or exit an interrupt).

Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
This test was testing for an undocumented and somewhat hyperspecific
behavior: when a process reaches a reschedule point and yields to a
higher priority thread, and there is another equal priority thread
active, which thread gets to run when the higher priority thread
finishes its work?  The original scheduler (because it leaves the
older thread in place in the list) implements the preemption like an
interrupt and returns to the original thread, despite the fact that
this then resets is time slice quantum unfairly.  In SMP mode, where
the current threads cannot live in the active list, the thread gets
added back to the end of the queue and the other thread runs.  In
effect, in UP mode "yield" and "reschedule" mean very slightly
different things where in SMP they act the same.

We don't document either behavior, as it happens.  Relax the test
constraints by adding a single deliberate k_yield() to unify behavior.

Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
The test suite is filled with tests that make assumptions (e.g. about
exactly when other threads will be scheduled) that don't work when
there is another CPU available to handle the load.

Add a feature to the test suite that can "hold" all but one CPU while
the test executes, leveraging the very nice setup/teardown callbacks
to do it.  When there is only one CPU, this becomes a very fast noop
of course.

Note that the hold is done by disabling interrupts and spinning, so it
comes with significant CPU cost and tends to drive up the load on the
CI system (and cause other spurious failures on unrelated tests!), so
this can't be used for long-running test cases.

Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
Disabling SMP mode for certain tests was a one-release thing, done to
avoid having to triage every test independently (MANY are not
SMP-safe), and with the knowledge that it was probably hiding bugs in
the kernel.

Turn it on pervasively.  Tests are treated with a combination of
flagging specific cases as "1cpu" where we have short-running tests
that can be independently run in an otherwise SMP environment, and via
setting CONFIG_MP_NUM_CPUS=1 where that's not possible (which still
runs the full SMP kernel config, but with only one CPU available).

Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
At least twice (to be fair: twice among thousands of test runs), I've
seen this device return "backwards" times in SMP, where the counter
value read from one CPU is behind the saved value already seen on the
other.  On hardware this should obviously never happen, HPET is a
single global device.

Add a simple workaround on QEMU targets so the math doesn't blow up.

Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
If an architecture declares support for IPI, we still want to use it
only when running in SMP mode.

(This also fixes a build failure on ARC, which declares
CONFIG_SCHED_IPI_SUPPORTED but doesn't actually implement
z_arch_sched_ipi() yet).

Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
@zephyrbot
Copy link
Collaborator

All checks passed.

checkpatch (informational only, not a failure)

-:377: WARNING:LONG_LINE: line over 80 characters
#377: FILE: subsys/testsuite/ztest/include/ztest_test.h:161:
+	ztest_user_unit_test_setup_teardown(fn, z_test_1cpu_start, z_test_1cpu_stop)

-:793: WARNING:LONG_LINE: line over 80 characters
#793: FILE: tests/kernel/lifo/lifo_usage/src/main.c:471:
+			 ztest_1cpu_unit_test(test_timeout_threads_pend_on_lifo));

-:817: WARNING:LONG_LINE_COMMENT: line over 80 characters
#817: FILE: tests/kernel/mbox/mbox_api/src/main.c:34:
+			 ztest_1cpu_unit_test(test_mbox_kinit),/*keep init first!*/

-:827: WARNING:LONG_LINE: line over 80 characters
#827: FILE: tests/kernel/mbox/mbox_api/src/main.c:41:
+			 ztest_1cpu_unit_test(test_mbox_target_source_thread_block),

-:845: WARNING:LONG_LINE: line over 80 characters
#845: FILE: tests/kernel/mbox/mbox_api/src/main.c:52:
+			 ztest_1cpu_unit_test(test_mbox_async_put_to_waiting_get),

-:984: WARNING:LONG_LINE: line over 80 characters
#984: FILE: tests/kernel/mem_protect/sys_sem/src/main.c:589:
+			ztest_1cpu_user_unit_test(test_sem_take_timeout_forever),

-:988: WARNING:LONG_LINE: line over 80 characters
#988: FILE: tests/kernel/mem_protect/sys_sem/src/main.c:592:
+			ztest_1cpu_user_unit_test(test_sem_multiple_threads_wait));

-:1176: WARNING:LONG_LINE: line over 80 characters
#1176: FILE: tests/kernel/mutex/mutex_api/src/test_mutex_apis.c:149:
+			 ztest_1cpu_user_unit_test(test_mutex_reent_lock_forever),

-:1180: WARNING:LONG_LINE: line over 80 characters
#1180: FILE: tests/kernel/mutex/mutex_api/src/test_mutex_apis.c:152:
+			 ztest_1cpu_user_unit_test(test_mutex_reent_lock_timeout_pass)

-:1278: WARNING:LONG_LINE: line over 80 characters
#1278: FILE: tests/kernel/pipe/pipe_api/src/main.c:65:
+			 ztest_1cpu_user_unit_test(test_pipe_user_thread2thread),

-:1500: WARNING:LONG_LINE: line over 80 characters
#1500: FILE: tests/kernel/semaphore/semaphore/src/main.c:774:
+			 ztest_1cpu_user_unit_test(test_sem_take_timeout_forever),

-:1509: WARNING:LONG_LINE: line over 80 characters
#1509: FILE: tests/kernel/semaphore/semaphore/src/main.c:781:
+			 ztest_1cpu_unit_test(test_sem_multiple_take_and_timeouts),

-:1592: WARNING:LONG_LINE: line over 80 characters
#1592: FILE: tests/kernel/threads/thread_apis/src/main.c:294:
+			 ztest_1cpu_unit_test(test_threads_suspend_resume_cooperative),

-:1609: WARNING:LONG_LINE: line over 80 characters
#1609: FILE: tests/kernel/threads/thread_apis/src/main.c:306:
+			 ztest_1cpu_user_unit_test(test_customdata_get_set_preempt),

-:1735: WARNING:LONG_LINE: line over 80 characters
#1735: FILE: tests/kernel/workq/work_queue_api/src/main.c:537:
+			 ztest_1cpu_user_unit_test(test_user_work_submit_to_queue_thread),

-:1736: WARNING:LONG_LINE: line over 80 characters
#1736: FILE: tests/kernel/workq/work_queue_api/src/main.c:538:
+			 ztest_1cpu_unit_test(test_delayed_work_submit_to_queue_thread),

-:1737: WARNING:LONG_LINE: line over 80 characters
#1737: FILE: tests/kernel/workq/work_queue_api/src/main.c:539:
+			 ztest_1cpu_unit_test(test_delayed_work_submit_to_queue_isr),

-:1740: WARNING:LONG_LINE: line over 80 characters
#1740: FILE: tests/kernel/workq/work_queue_api/src/main.c:542:
+			 ztest_1cpu_unit_test(test_delayed_work_cancel_from_queue_thread),

-:1741: WARNING:LONG_LINE: line over 80 characters
#1741: FILE: tests/kernel/workq/work_queue_api/src/main.c:543:
+			 ztest_1cpu_unit_test(test_delayed_work_cancel_from_queue_isr),

- total: 0 errors, 19 warnings, 1202 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

Your patch has style problems, please review.

NOTE: Ignored message types: AVOID_EXTERNS BRACES CONFIG_EXPERIMENTAL CONST_STRUCT DATE_TIME FILE_PATH_CHANGES MINMAX NETWORKING_BLOCK_COMMENT_STYLE PRINTK_WITHOUT_KERN_LEVEL SPLIT_STRING VOLATILE

NOTE: If any of the errors are false positives, please report
      them to the maintainers.

Tip: The bot edits this comment instead of posting a new one, so you can check the comment's history to see earlier messages.

@carlescufi
Copy link
Member

Any reason we haven't merged this?

@nashif nashif merged commit d82f76a into zephyrproject-rtos:master Sep 26, 2019
@ioannisg ioannisg added the Release Notes To be mentioned in the release notes label Sep 27, 2019
@IRISZZW IRISZZW mentioned this pull request May 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Kernel area: Samples Samples area: SMP Symmetric multiprocessing area: Test Framework Issues related not to a particular test, but to the framework instead area: Tests Issues related to a particular existing or missing test area: Timer Timer Release Notes To be mentioned in the release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants