diff --git a/tests/thread_tests.cpp b/tests/thread_tests.cpp new file mode 100644 index 0000000..01f1db3 --- /dev/null +++ b/tests/thread_tests.cpp @@ -0,0 +1,222 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2017 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +#include + +#include +#include +#include + +#include +#include + +using std::chrono::steady_clock; +using std::this_thread::sleep_for; + +const auto t_100ms = std::chrono::milliseconds(100); + +SUITE(raii_thread_tests) +{ + TEST(raii_thread_same_scope_clock_test) + { + auto start_time = steady_clock::now(); + + gsl::raii_thread t{[&]{ sleep_for(t_100ms); }}; + + auto end_time = steady_clock::now(); + + CHECK(end_time - start_time < t_100ms); + } + + TEST(raii_thread_different_scope_clock_test) + { + auto start_time = steady_clock::now(); + + { + gsl::raii_thread t{[&]{ sleep_for(t_100ms); }}; + } + + auto end_time = steady_clock::now(); + + CHECK(end_time - start_time >= t_100ms); + } + + TEST(raii_thread_ctor_test) + { + auto start_time = steady_clock::now(); + + gsl::raii_thread t1{[&]{ sleep_for(t_100ms); }}; + + { + gsl::raii_thread t2{std::move(t1)}; + } + + auto end_time = steady_clock::now(); + + CHECK(end_time - start_time >= t_100ms); + } + + TEST(raii_thread_assign_test) + { + auto start_time = steady_clock::now(); + + gsl::raii_thread t1{[&]{ sleep_for(t_100ms); }}; + + { + gsl::raii_thread t2; + t2 = std::move(t1); + } + + auto end_time = steady_clock::now(); + + CHECK(end_time - start_time >= t_100ms); + } + + TEST(raii_thread_std_thread_ctor_test) + { + auto start_time = steady_clock::now(); + + std::thread t1{[&]{ sleep_for(t_100ms); }}; + + { + gsl::raii_thread t2{std::move(t1)}; + } + + auto end_time = steady_clock::now(); + + CHECK(end_time - start_time >= t_100ms); + } + + TEST(raii_thread_std_thread_assign_test) + { + auto start_time = steady_clock::now(); + + std::thread t1{[&]{ sleep_for(t_100ms); }}; + + { + gsl::raii_thread t2; + t2 = std::move(t1); + } + + auto end_time = steady_clock::now(); + + CHECK(end_time - start_time >= t_100ms); + } + + TEST(raii_thread_swap_test) + { + gsl::raii_thread t1{[&]{ sleep_for(t_100ms); }}; + gsl::raii_thread t2{[&]{ sleep_for(t_100ms); }}; + + auto id1 = t1.get_id(); + auto id2 = t2.get_id(); + + std::swap(t1, t2); + + CHECK(t1.get_id() == id2); + CHECK(t2.get_id() == id1); + + t1.swap(t2); + + CHECK(t1.get_id() == id1); + CHECK(t2.get_id() == id2); + } +} + +SUITE(detached_thread_tests) +{ + TEST(detached_thread_out_of_scope_test) + { + std::atomic_bool b{false}; + + { + gsl::detached_thread t{[&]{ sleep_for(t_100ms); b = true; }}; + } + + CHECK(b == false); + sleep_for(t_100ms * 2); + CHECK(b == true); + } + + TEST(detached_thread_temporary_test) + { + std::atomic_bool b{false}; + + gsl::detached_thread{[&]{ sleep_for(t_100ms); b = true; }}; + + CHECK(b == false); + sleep_for(t_100ms * 2); + CHECK(b == true); + } + + TEST(detached_thread_ctor_std_thread_test) + { + std::thread t1{[&]{ sleep_for(t_100ms); }}; + gsl::detached_thread t2{std::move(t1)}; + } + + TEST(detached_thread_assign_std_thread_test) + { + std::thread t1{[&]{ sleep_for(t_100ms); }}; + gsl::detached_thread t2; + t2 = std::move(t1); + } + + TEST(detached_thread_temporary_assign_std_thread_test) + { + std::thread t1{[&]{ sleep_for(t_100ms); }}; + gsl::detached_thread{std::move(t1)}; + } + + TEST(detached_thread_swap_test) + { + gsl::detached_thread t1{[&]{ sleep_for(t_100ms); }}; + gsl::detached_thread t2{[&]{ sleep_for(t_100ms); }}; + + auto id1 = t1.get_id(); + auto id2 = t2.get_id(); + + std::swap(t1, t2); + + CHECK(t1.get_id() == id2); + CHECK(t2.get_id() == id1); + + t1.swap(t2); + + CHECK(t1.get_id() == id1); + CHECK(t2.get_id() == id2); + } + + TEST(detached_thread_ctor_from_detached_std_thread) + { + std::thread t{[&]{ sleep_for(t_100ms); }}; + t.detach(); + gsl::detached_thread{std::move(t)}; + sleep_for(t_100ms * 2); + } + + TEST(detached_thread_assign_from_detached_std_thread) + { + std::thread t1{[&]{ sleep_for(t_100ms); }}; + t1.detach(); + gsl::detached_thread t2; + t2 = std::move(t1); + sleep_for(t_100ms * 2); + } +} + +int main() { return UnitTest::RunAllTests(); } +