Update core library GPL boilerplate and (C) from git log
[ardour.git] / libs / pbd / test / timer_test.cc
1 #include "timer_test.h"
2
3 #include <iostream>
4 #include <sstream>
5 #include <algorithm>
6
7 #include "pbd/timer.h"
8
9 #ifdef PLATFORM_WINDOWS
10 #include <windows.h>
11 #endif
12
13 CPPUNIT_TEST_SUITE_REGISTRATION (TimerTest);
14
15 using namespace std;
16
17 #ifdef PLATFORM_WINDOWS
18 UINT&
19 min_timer_resolution ()
20 {
21         static UINT min_res_ms = 0;
22         return min_res_ms;
23 }
24
25 bool
26 set_min_timer_resolution ()
27 {
28         TIMECAPS caps;
29
30         if (timeGetDevCaps(&caps, sizeof(TIMECAPS)) != TIMERR_NOERROR) {
31                 cerr << "Could not get timer device capabilities..." << endl;
32         } else {
33                 if (timeBeginPeriod(caps.wPeriodMin) != TIMERR_NOERROR) {
34                         cerr << "Could not set minimum timer resolution to: " << caps.wPeriodMin << "ms" << endl;
35                         return false;
36                 }
37                 else {
38                         cerr << "Multimedia timer resolution set to: " << caps.wPeriodMin << "ms" << endl;
39                         min_timer_resolution() = caps.wPeriodMin;
40                         return true;
41                 }
42         }
43         return false;
44 }
45
46 bool
47 reset_timer_resolution ()
48 {
49         if (min_timer_resolution()) {
50                 if (timeEndPeriod(min_timer_resolution()) != TIMERR_NOERROR) {
51                         cerr << "Could not reset timer resolution" << endl;
52                         return false;
53                 } else {
54                         cerr << "Multimedia timer resolution reset" << endl;
55                         return true;
56                 }
57         }
58         return true;
59 }
60
61 #endif
62
63 void
64 TimerTest::simulate_load (const string& name, guint64 load_usecs)
65 {
66         PBD::Timing timing;
67         std::ostringstream oss;
68         oss << name << " Load.";
69
70         guint64 i = 0;
71         do {
72                 timing.update ();
73
74                 // totally arbitrary
75                 if (i % 10000 == 0) {
76                         oss << ".";
77                 }
78
79                 ++i;
80         } while (timing.elapsed () < load_usecs);
81
82         oss << "Expected = " << load_usecs;
83         oss << ", Elapsed = " << timing.elapsed ();
84         oss << endl;
85         //cerr << oss.str();
86 }
87
88 void
89 TimerTest::on_second_timeout ()
90 {
91         cerr << endl;
92         cerr << "Timing Summary: " << m_current_test_name << endl;
93
94         if (m_idle_timing_data.size()) {
95                 cerr << "Idle Timing: " << m_idle_timing_data.summary();
96         }
97         if (m_fast_timing_data.size()) {
98                 cerr << "Fast Timing: " << m_fast_timing_data.summary();
99         }
100         if (m_rapid1_timing_data.size()) {
101                 cerr << "Rapid1 Timing: " << m_rapid1_timing_data.summary();
102         }
103         if (m_rapid2_timing_data.size()) {
104                 cerr << "Rapid2 Timing: " << m_rapid2_timing_data.summary();
105         }
106         reset_timing ();
107 }
108
109 bool
110 TimerTest::on_second_timeout_glibmm ()
111 {
112         TimerTest::on_second_timeout ();
113         return true;
114 }
115
116 void
117 TimerTest::on_fast_timeout ()
118 {
119         m_fast_timing_data.add_interval ();
120         if (m_block_idle) {
121                 // do nothing, handled in rapid timers
122         } else {
123                 simulate_load ("Rapid1", 4000);
124         }
125 }
126
127 bool
128 TimerTest::on_fast_timeout_glibmm ()
129 {
130         on_fast_timeout ();
131         return true;
132 }
133
134 void
135 TimerTest::on_rapid1_timeout ()
136 {
137         m_rapid1_timing_data.add_interval ();
138         if (m_block_idle) {
139                 simulate_load ("Rapid1", rapid1_timer_usecs () * 0.5);
140         } else {
141                 simulate_load ("Rapid1", 2000);
142         }
143 }
144
145 bool
146 TimerTest::on_rapid1_timeout_glibmm ()
147 {
148         on_rapid1_timeout ();
149         return true;
150 }
151
152 void
153 TimerTest::on_rapid2_timeout ()
154 {
155         m_rapid2_timing_data.add_interval ();
156         if (m_block_idle) {
157                 simulate_load ("Rapid2", rapid2_timer_usecs () * 0.5);
158         } else {
159                 simulate_load ("Rapid2", 2000);
160         }
161 }
162
163 bool
164 TimerTest::on_rapid2_timeout_glibmm ()
165 {
166         on_rapid2_timeout ();
167         return true;
168 }
169
170 bool
171 TimerTest::on_idle_handler ()
172 {
173         m_idle_timing_data.add_interval ();
174         if (m_block_idle) {
175                 simulate_load ("Idle", rapid2_timer_usecs ());
176         }
177         return true;
178 }
179
180 bool
181 TimerTest::on_quit_handler ()
182 {
183         cerr << "Quit Handler" << endl;
184         m_main->quit ();
185         return false;
186 }
187
188 void
189 TimerTest::reset_timing ()
190 {
191         m_idle_timing_data.reset ();
192         m_fast_timing_data.reset ();
193         m_rapid1_timing_data.reset ();
194         m_rapid2_timing_data.reset ();
195 }
196
197 void
198 TimerTest::start_timing ()
199 {
200         m_idle_timing_data.start_timing ();
201         m_fast_timing_data.start_timing ();
202         m_rapid1_timing_data.start_timing ();
203         m_rapid2_timing_data.start_timing ();
204 }
205
206 gboolean
207 TimerTest::_second_timeout_handler (void *data)
208 {
209         TimerTest *const tt = static_cast<TimerTest*>(data);
210         tt->on_second_timeout ();
211         return TRUE;
212 }
213
214 gboolean
215 TimerTest::_fast_timeout_handler (void *data)
216 {
217         TimerTest *const tt = static_cast<TimerTest*>(data);
218         tt->on_fast_timeout ();
219         return TRUE;
220 }
221
222 gboolean
223 TimerTest::_rapid1_timeout_handler (void *data)
224 {
225         TimerTest *const tt = static_cast<TimerTest*>(data);
226         tt->on_rapid1_timeout ();
227         return TRUE;
228 }
229
230 gboolean
231 TimerTest::_rapid2_timeout_handler (void *data)
232 {
233         TimerTest *const tt = static_cast<TimerTest*>(data);
234         tt->on_rapid2_timeout ();
235         return TRUE;
236 }
237
238 void
239 TimerTest::reset_timing_run_main ()
240 {
241         reset_timing ();
242         start_timing ();
243
244         connect_quit_timeout ();
245
246         m_main = Glib::MainLoop::create (m_context);
247         m_main->run ();
248 }
249
250 void
251 TimerTest::testGlibTimeoutSources ()
252 {
253         m_current_test_name = "testGlibTimeoutSources";
254         _testGlibTimeoutSources ();
255 }
256
257 void
258 TimerTest::_testGlibTimeoutSources ()
259 {
260         m_context = Glib::MainContext::create ();
261
262         GSource * second_timeout_source = g_timeout_source_new (second_timer_ms ());
263
264         g_source_set_callback (second_timeout_source , &TimerTest::_second_timeout_handler, this, NULL);
265
266         g_source_attach (second_timeout_source, m_context->gobj());
267
268         if (m_connect_idle) {
269                 connect_idle_handler ();
270                 reset_timing_run_main ();
271         }
272
273         GSource * fast_timeout_source = g_timeout_source_new (fast_timer_ms ());
274
275         g_source_set_callback (fast_timeout_source , &TimerTest::_fast_timeout_handler, this, NULL);
276
277         g_source_attach (fast_timeout_source, m_context->gobj());
278
279         // now run with fast timeout
280         reset_timing_run_main ();
281
282         GSource * rapid1_timeout_source = g_timeout_source_new (rapid1_timer_ms ());
283
284         g_source_set_callback (rapid1_timeout_source , &TimerTest::_rapid1_timeout_handler, this, NULL);
285
286         g_source_attach (rapid1_timeout_source, m_context->gobj());
287
288         // now run with fast and rapid1 timeouts
289         reset_timing_run_main ();
290
291         GSource * rapid2_timeout_source = g_timeout_source_new (rapid2_timer_ms ());
292
293         g_source_set_callback (rapid2_timeout_source , &TimerTest::_rapid2_timeout_handler, this, NULL);
294
295         g_source_attach (rapid2_timeout_source, m_context->gobj());
296
297         // now run with fast, rapid1 and rapid2 timeouts
298         reset_timing_run_main ();
299
300         // cleanup
301         g_source_destroy (second_timeout_source);
302         g_source_unref (second_timeout_source);
303
304         g_source_destroy (fast_timeout_source);
305         g_source_unref (fast_timeout_source);
306
307         g_source_destroy (rapid1_timeout_source);
308         g_source_unref (rapid1_timeout_source);
309
310         g_source_destroy (rapid2_timeout_source);
311         g_source_unref (rapid2_timeout_source);
312 }
313
314 void
315 TimerTest::testGlibmmSignalTimeouts ()
316 {
317         m_current_test_name = "testGlibmmSignalTimeouts";
318         _testGlibmmSignalTimeouts ();
319 }
320
321 void
322 TimerTest::_testGlibmmSignalTimeouts ()
323 {
324         m_context = Glib::MainContext::get_default ();
325
326         Glib::signal_timeout().connect(sigc::mem_fun(*this, &TimerTest::on_second_timeout_glibmm), second_timer_ms());
327
328         if (m_connect_idle) {
329                 connect_idle_handler ();
330                 reset_timing_run_main ();
331         }
332
333         Glib::signal_timeout().connect(sigc::mem_fun(*this, &TimerTest::on_fast_timeout_glibmm), fast_timer_ms());
334
335         reset_timing_run_main ();
336
337         Glib::signal_timeout().connect(sigc::mem_fun(*this, &TimerTest::on_rapid1_timeout_glibmm), rapid1_timer_ms());
338
339         reset_timing_run_main ();
340
341         Glib::signal_timeout().connect(sigc::mem_fun(*this, &TimerTest::on_rapid2_timeout_glibmm), rapid2_timer_ms());
342
343         reset_timing_run_main ();
344 }
345
346 void
347 TimerTest::testGlibmmTimeoutSources ()
348 {
349         m_current_test_name = "testGlibmmTimeoutSources";
350         _testGlibmmTimeoutSources ();
351 }
352
353 void
354 TimerTest::_testGlibmmTimeoutSources ()
355 {
356         m_context = Glib::MainContext::create ();
357
358         const Glib::RefPtr<Glib::TimeoutSource> second_source = Glib::TimeoutSource::create(second_timer_ms());
359         second_source->connect(sigc::mem_fun(*this, &TimerTest::on_second_timeout_glibmm));
360
361         second_source->attach(m_context);
362
363         if (m_connect_idle) {
364                 connect_idle_handler ();
365                 reset_timing_run_main ();
366         }
367
368         const Glib::RefPtr<Glib::TimeoutSource> fast_source = Glib::TimeoutSource::create(fast_timer_ms());
369         fast_source->connect(sigc::mem_fun(*this, &TimerTest::on_fast_timeout_glibmm));
370
371         fast_source->attach(m_context);
372
373         reset_timing_run_main ();
374
375         const Glib::RefPtr<Glib::TimeoutSource> rapid1_source = Glib::TimeoutSource::create(rapid1_timer_ms());
376         sigc::connection rapid1_connection = rapid1_source->connect(sigc::mem_fun(*this, &TimerTest::on_rapid1_timeout_glibmm));
377
378         rapid1_source->attach(m_context);
379
380         reset_timing_run_main ();
381
382         const Glib::RefPtr<Glib::TimeoutSource> rapid2_source = Glib::TimeoutSource::create(rapid2_timer_ms());
383         sigc::connection rapid2_connection = rapid2_source->connect(sigc::mem_fun(*this, &TimerTest::on_rapid2_timeout_glibmm));
384
385         rapid2_source->attach(m_context);
386
387         reset_timing_run_main ();
388 }
389
390 void
391 TimerTest::connect_idle_handler ()
392 {
393         const Glib::RefPtr<Glib::IdleSource> idle_source = Glib::IdleSource::create();
394         idle_source->connect(sigc::mem_fun(*this, &TimerTest::on_idle_handler));
395
396         idle_source->attach(m_context);
397 }
398
399 void
400 TimerTest::connect_quit_timeout ()
401 {
402         const Glib::RefPtr<Glib::TimeoutSource> quit_source = Glib::TimeoutSource::create(test_length_ms());
403         quit_source->connect(sigc::mem_fun(*this, &TimerTest::on_quit_handler));
404
405         quit_source->attach(m_context);
406 }
407
408 void
409 TimerTest::testTimers ()
410 {
411         m_current_test_name = "testTimers";
412         _testTimers ();
413 }
414
415 void
416 TimerTest::_testTimers ()
417 {
418         m_context = Glib::MainContext::create ();
419
420         PBD::StandardTimer second_timer (second_timer_ms (), m_context);
421         sigc::connection second_connection = second_timer.connect (sigc::mem_fun (this, &TimerTest::on_second_timeout));
422
423         if (m_connect_idle) {
424                 connect_idle_handler ();
425                 // let the idle handler run as fast as it can
426                 reset_timing_run_main();
427         }
428
429         PBD::StandardTimer fast_timer (fast_timer_ms (), m_context);
430         sigc::connection fast_connection = fast_timer.connect (sigc::mem_fun (this, &TimerTest::on_fast_timeout));
431
432         reset_timing_run_main();
433
434         PBD::StandardTimer rapid1_timer (rapid1_timer_ms (), m_context);
435         sigc::connection rapid1_connection = rapid1_timer.connect (sigc::mem_fun (this, &TimerTest::on_rapid1_timeout));
436
437         reset_timing_run_main();
438
439         PBD::StandardTimer rapid2_timer (rapid2_timer_ms (), m_context);
440         sigc::connection rapid2_connection = rapid2_timer.connect (sigc::mem_fun (this, &TimerTest::on_rapid2_timeout));
441
442         reset_timing_run_main();
443 }
444
445 void
446 TimerTest::testTimersIdleFrequency ()
447 {
448         m_current_test_name = "testTimersIdleFrequency";
449         _testTimersIdleFrequency ();
450 }
451
452 void
453 TimerTest::_testTimersIdleFrequency ()
454 {
455         m_block_idle = false;
456         m_connect_idle = true;
457
458         _testTimers ();
459
460         m_block_idle = false;
461         m_connect_idle = false;
462 }
463
464 void
465 TimerTest::testTimersBlockIdle ()
466 {
467         m_current_test_name = "testTimersBlockIdle";
468         _testTimersBlockIdle ();
469 }
470
471 void
472 TimerTest::_testTimersBlockIdle ()
473 {
474         m_block_idle = true;
475         m_connect_idle = true;
476
477         _testTimers ();
478
479         m_block_idle = false;
480         m_connect_idle = false;
481 }
482
483 #ifdef PLATFORM_WINDOWS
484 void
485 TimerTest::testGlibTimeoutSourcesHR ()
486 {
487         CPPUNIT_ASSERT(set_min_timer_resolution());
488
489         m_current_test_name = "testGlibTimeoutSourcesHR";
490         _testGlibTimeoutSources ();
491
492         CPPUNIT_ASSERT(reset_timer_resolution());
493 }
494
495 void
496 TimerTest::testGlibmmSignalTimeoutsHR ()
497 {
498         CPPUNIT_ASSERT(set_min_timer_resolution());
499
500         m_current_test_name = "testGlibmmSignalTimeoutsHR";
501         _testGlibmmSignalTimeouts ();
502
503         CPPUNIT_ASSERT(reset_timer_resolution());
504 }
505
506 void
507 TimerTest::testGlibmmTimeoutSourcesHR ()
508 {
509         CPPUNIT_ASSERT(set_min_timer_resolution());
510
511         m_current_test_name = "testGlibmmTimeoutSourcesHR";
512         _testGlibmmTimeoutSources ();
513
514         CPPUNIT_ASSERT(reset_timer_resolution());
515 }
516
517 void
518 TimerTest::testTimersHR ()
519 {
520         CPPUNIT_ASSERT(set_min_timer_resolution());
521
522         m_current_test_name = "testTimersHR";
523         _testTimers ();
524
525         CPPUNIT_ASSERT(reset_timer_resolution());
526 }
527
528 void
529 TimerTest::testTimersIdleFrequencyHR ()
530 {
531         CPPUNIT_ASSERT(set_min_timer_resolution());
532
533         m_current_test_name = "testTimersIdleFrequencyHR";
534         _testTimersIdleFrequency ();
535
536         CPPUNIT_ASSERT(reset_timer_resolution());
537 }
538
539 void
540 TimerTest::testTimersBlockIdleHR ()
541 {
542         CPPUNIT_ASSERT(set_min_timer_resolution());
543
544         m_current_test_name = "testTimersIdleFrequencyHR";
545         _testTimersBlockIdle ();
546
547         CPPUNIT_ASSERT(reset_timer_resolution());
548 }
549
550 #endif