1 #include "test.h"
2 
3 TEST_CASE("value_task") {
4     auto t = tw::make_value_task(42);
5     REQUIRE(42 == t->get());
6     REQUIRE(42 == t->future().get());
7     REQUIRE(t->was_scheduled());
8     REQUIRE(t->is_ready());
9     REQUIRE(t->edges().empty());
10     auto n = t;
11     REQUIRE(0u == n->id());
12     REQUIRE(tw::task_type::root == n->type());
13     REQUIRE(!n->name());
14     REQUIRE(!n->executor());
15     REQUIRE(n->parents().empty());
16     REQUIRE(0 == n->priority());
17     REQUIRE(!any_data_ok(n->custom_data()));
18     REQUIRE(!n->canceled());
19 }
20 
21 TEST_CASE("value_task_with_name") {
22     const std::string name = "albert";
23     auto t = tw::make_value_task(42)->named(name);
24     REQUIRE(42 == t->get());
25     REQUIRE(42 == t->future().get());
26     REQUIRE(t->was_scheduled());
27     REQUIRE(t->is_ready());
28     REQUIRE(t->edges().empty());
29     auto n = t;
30     REQUIRE(0u == n->id());
31     REQUIRE(tw::task_type::root == n->type());
32 #ifndef TRANSWARP_MINIMUM_TASK_SIZE
33     REQUIRE(name == *n->name());
34 #else
35     REQUIRE(!n->name());
36 #endif
37     REQUIRE(!n->executor());
38     REQUIRE(n->parents().empty());
39     REQUIRE(0 == n->priority());
40     REQUIRE(!any_data_ok(n->custom_data()));
41     REQUIRE(!n->canceled());
42 }
43 
44 TEST_CASE("value_task_with_priority_and_custom_data") {
45     auto t = tw::make_value_task(42);
46     t->set_priority(13);
47     auto data = std::make_shared<double>(13.5);
48     t->set_custom_data(data);
49     auto n = t;
50 #ifndef TRANSWARP_DISABLE_TASK_PRIORITY
51     REQUIRE(13 == n->priority());
52 #else
53     REQUIRE(0 == n->priority());
54 #endif
55 #ifndef TRANSWARP_DISABLE_TASK_CUSTOM_DATA
56     REQUIRE(13.5 == *get_any_data<std::shared_ptr<double>>(n->custom_data()));
57 #else
58     REQUIRE(!any_data_ok(n->custom_data()));
59 #endif
60     t->remove_custom_data();
61     t->reset_priority();
62     REQUIRE(0 == n->priority());
63     REQUIRE(!any_data_ok(n->custom_data()));
64 }
65 
66 TEST_CASE("value_task_with_priority_all_and_custom_data_all") {
67     auto t = tw::make_value_task(42);
68     t->set_priority_all(13);
69     auto data = std::make_shared<double>(13.5);
70     t->set_custom_data_all(data);
71     auto n = t;
72 #ifndef TRANSWARP_DISABLE_TASK_PRIORITY
73     REQUIRE(13 == n->priority());
74 #else
75     REQUIRE(0 == n->priority());
76 #endif
77 #ifndef TRANSWARP_DISABLE_TASK_CUSTOM_DATA
78     REQUIRE(13.5 == *get_any_data<std::shared_ptr<double>>(n->custom_data()));
79 #else
80     REQUIRE(!any_data_ok(n->custom_data()));
81 #endif
82     t->remove_custom_data_all();
83     t->reset_priority_all();
84     REQUIRE(0 == n->priority());
85     REQUIRE(!any_data_ok(n->custom_data()));
86 }
87 
88 TEST_CASE("value_task_in_a_graph") {
89     auto t1 = tw::make_value_task(42);
90     REQUIRE(42 == t1->get());
91     auto t2 = tw::make_value_task(13.3);
92     REQUIRE(13.3 == t2->get());
__anonb62a17580102(int x, double y) 93     auto t3 = tw::make_task(tw::consume, [](int x, double y) { return x + y; }, t1, t2);
94     t3->schedule();
95     REQUIRE(55.3 == t3->get());
96 }
97 
98 TEST_CASE("value_task_and_executor") {
99     auto t = tw::make_value_task(42);
100     REQUIRE(42 == t->get());
101     auto exec = std::make_shared<tw::sequential>();
102     t->set_executor(exec);
103     REQUIRE(!t->executor());
104     t->remove_executor();
105     REQUIRE(!t->executor());
106     REQUIRE(42 == t->get());
107 }
108 
109 TEST_CASE("value_task_and_executor_all") {
110     auto t = tw::make_value_task(42);
111     REQUIRE(42 == t->get());
112     auto exec = std::make_shared<tw::sequential>();
113     t->set_executor_all(exec);
114     REQUIRE(!t->executor());
115     t->remove_executor_all();
116     REQUIRE(!t->executor());
117     REQUIRE(42 == t->get());
118 }
119 
120 TEST_CASE("value_task_and_schedule") {
121     auto t = tw::make_value_task(42);
122     REQUIRE(42 == t->get());
123     tw::sequential exec;
124     t->schedule(true);
125     t->schedule(exec, true);
126     REQUIRE(42 == t->get());
127 }
128 
129 TEST_CASE("value_task_and_schedule_all") {
130     auto t = tw::make_value_task(42);
131     REQUIRE(42 == t->get());
132     tw::sequential exec;
133     t->schedule_all(true);
134     t->schedule_all(exec, true);
135     REQUIRE(42 == t->get());
136 }
137 
138 TEST_CASE("value_task_and_wait") {
139     auto t = tw::make_value_task(42);
140     REQUIRE(42 == t->get());
141     t->wait();
142     REQUIRE(42 == t->get());
143 }
144 
145 TEST_CASE("value_task_and_reset_and_cancel") {
146     auto t = tw::make_value_task(42);
147     REQUIRE(42 == t->get());
148     t->reset();
149     t->cancel(true);
150     REQUIRE(42 == t->get());
151 }
152 
153 TEST_CASE("value_task_and_reset_all_and_cancel_all") {
154     auto t = tw::make_value_task(42);
155     REQUIRE(42 == t->get());
156     t->reset_all();
157     t->cancel_all(true);
158     REQUIRE(42 == t->get());
159 }
160 
161 TEST_CASE("value_task_with_lvalue_reference") {
162     const int x = 42;
163     auto t = tw::make_value_task(x);
164     REQUIRE(x == t->get());
165 }
166 
167 TEST_CASE("value_task_with_rvalue_reference") {
168     int x = 42;
169     auto t = tw::make_value_task(std::move(x));
170     REQUIRE(42 == t->get());
171 }
172 
173 TEST_CASE("value_task_with_changing_value") {
174     int x = 42;
175     auto t = tw::make_value_task(x);
176     x = 43;
177     REQUIRE(42 == t->get());
178 }
179 
180 TEST_CASE("make_ready_future_with_value") {
181     const int x = 42;
182     auto future = tw::detail::make_future_with_value<int>(x);
183     REQUIRE(x == future.get());
184 }
185 
186 TEST_CASE("make_ready_future") {
187     auto future = tw::detail::make_ready_future();
188     REQUIRE(future.valid());
189 }
190 
191 TEST_CASE("make_ready_future_with_exception") {
192     std::runtime_error e{"42"};
193     auto future = tw::detail::make_future_with_exception<int>(std::make_exception_ptr(e));
194     try {
195         future.get();
196     } catch (std::runtime_error& e) {
197         REQUIRE(std::string{"42"} == e.what());
198         return;
199     }
200     throw std::runtime_error{"shouldn't get here"};
201 }
202 
203 TEST_CASE("make_ready_future_with_invalid_exception") {
204     REQUIRE_THROWS_AS(tw::detail::make_future_with_exception<int>(std::exception_ptr{}), tw::transwarp_error);
205 }
206 
207 TEST_CASE("task_set_value_and_remove_value") {
208     const int x = 42;
209     const int y = 55;
__anonb62a17580202null210     auto t = tw::make_task(tw::root, [x]{ return x; });
211     t->schedule();
212     REQUIRE(x == t->get());
213     t->set_value(y);
214     REQUIRE(t->is_ready());
215     REQUIRE(y == t->get());
216     t->reset();
217     REQUIRE_THROWS_AS(t->is_ready(), tw::transwarp_error);
218     t->schedule();
219     REQUIRE(t->is_ready());
220     REQUIRE(x == t->get());
221 }
222 
223 TEST_CASE("task_set_value_and_remove_value_for_mutable_ref") {
224     int x = 42;
225     int y = 55;
__anonb62a17580302null226     auto t = tw::make_task(tw::root, [x]{ return x; });
227     t->schedule();
228     REQUIRE(x == t->get());
229     t->set_value(y);
230     REQUIRE(t->is_ready());
231     REQUIRE(y == t->get());
232     t->reset();
233     REQUIRE_THROWS_AS(t->is_ready(), tw::transwarp_error);
234     t->schedule();
235     REQUIRE(t->is_ready());
236     REQUIRE(x == t->get());
237 }
238 
239 TEST_CASE("task_set_value_and_remove_value_for_void") {
__anonb62a17580402null240     auto t = tw::make_task(tw::root, []{});
241     t->schedule();
242     t->reset();
243     REQUIRE_THROWS_AS(t->is_ready(), tw::transwarp_error);
244     t->set_value();
245     REQUIRE(t->is_ready());
246     t->reset();
247     REQUIRE_THROWS_AS(t->is_ready(), tw::transwarp_error);
248     t->schedule();
249     REQUIRE(t->is_ready());
250 }
251 
252 TEST_CASE("task_set_exception_and_remove_exception") {
253     const int x = 42;
__anonb62a17580502null254     auto t = tw::make_task(tw::root, [x]{ return x; });
255     std::runtime_error e{"blah"};
256     t->set_exception(std::make_exception_ptr(e));
257     REQUIRE(t->is_ready());
258     REQUIRE_THROWS_AS(t->get(), std::runtime_error);
259     t->reset();
260     REQUIRE_THROWS_AS(t->is_ready(), tw::transwarp_error);
261     t->schedule();
262     REQUIRE(t->is_ready());
263     REQUIRE(x == t->get());
264 }
265 
266 TEST_CASE("task_pass_exception_to_set_value") {
__anonb62a17580602null267     auto t = tw::make_task(tw::root, []{ return std::make_exception_ptr(std::runtime_error{"foo"}); });
268     std::runtime_error e{"blah"};
269     t->set_value(std::make_exception_ptr(e));
270     const auto result = t->get();
271     try {
272         std::rethrow_exception(result);
273     } catch (const std::runtime_error& re) {
274         REQUIRE(std::string(e.what()) == std::string(re.what()));
275         return;
276     }
277     throw std::runtime_error{"shouldn't get here"};
278 }
279 
280 TEST_CASE("has_result") {
__anonb62a17580702null281     auto t = tw::make_task(tw::root, []{});
282     REQUIRE(!t->has_result());
283     t->schedule();
284     REQUIRE(t->has_result());
285 }
286 
287 TEST_CASE("has_result_for_value_task") {
288     auto t = tw::make_value_task(42);
289     REQUIRE(t->has_result());
290 }
291 
292 TEST_CASE("value_task_with_volatile_int") {
293     volatile int x = 42;
294     auto t = tw::make_value_task(x);
295     REQUIRE(x == t->get());
296     t->set_value(43);
297     REQUIRE(43 == t->get());
298     x *= 2;
299     t->set_value(x);
300     REQUIRE(x == t->get());
301 }
302