1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/scheduler/delay_based_time_source.h"
7 #include "base/basictypes.h"
8 #include "base/test/test_simple_task_runner.h"
9 #include "cc/test/scheduler_test_common.h"
10 #include "testing/gtest/include/gtest/gtest.h"
15 base::TimeDelta
Interval() {
16 return base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond
/
20 TEST(DelayBasedTimeSourceTest
, TaskPostedAndTickCalled
) {
21 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner
=
22 new base::TestSimpleTaskRunner
;
23 FakeTimeSourceClient client
;
24 scoped_ptr
<FakeDelayBasedTimeSource
> timer
=
25 FakeDelayBasedTimeSource::Create(Interval(), task_runner
.get());
26 timer
->SetClient(&client
);
28 timer
->SetActive(true);
29 EXPECT_TRUE(timer
->Active());
30 EXPECT_TRUE(task_runner
->HasPendingTask());
32 timer
->SetNow(timer
->Now() + base::TimeDelta::FromMilliseconds(16));
33 task_runner
->RunPendingTasks();
34 EXPECT_TRUE(timer
->Active());
35 EXPECT_TRUE(client
.TickCalled());
38 TEST(DelayBasedTimeSourceTest
, TickNotCalledWithTaskPosted
) {
39 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner
=
40 new base::TestSimpleTaskRunner
;
41 FakeTimeSourceClient client
;
42 scoped_ptr
<FakeDelayBasedTimeSource
> timer
=
43 FakeDelayBasedTimeSource::Create(Interval(), task_runner
.get());
44 timer
->SetClient(&client
);
45 timer
->SetActive(true);
46 EXPECT_TRUE(task_runner
->HasPendingTask());
47 timer
->SetActive(false);
48 task_runner
->RunPendingTasks();
49 EXPECT_FALSE(client
.TickCalled());
52 TEST(DelayBasedTimeSourceTest
, StartTwiceEnqueuesOneTask
) {
53 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner
=
54 new base::TestSimpleTaskRunner
;
55 FakeTimeSourceClient client
;
56 scoped_ptr
<FakeDelayBasedTimeSource
> timer
=
57 FakeDelayBasedTimeSource::Create(Interval(), task_runner
.get());
58 timer
->SetClient(&client
);
59 timer
->SetActive(true);
60 EXPECT_TRUE(task_runner
->HasPendingTask());
61 task_runner
->ClearPendingTasks();
62 timer
->SetActive(true);
63 EXPECT_FALSE(task_runner
->HasPendingTask());
66 TEST(DelayBasedTimeSourceTest
, StartWhenRunningDoesntTick
) {
67 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner
=
68 new base::TestSimpleTaskRunner
;
69 FakeTimeSourceClient client
;
70 scoped_ptr
<FakeDelayBasedTimeSource
> timer
=
71 FakeDelayBasedTimeSource::Create(Interval(), task_runner
.get());
72 timer
->SetClient(&client
);
73 timer
->SetActive(true);
74 EXPECT_TRUE(task_runner
->HasPendingTask());
75 task_runner
->RunPendingTasks();
76 task_runner
->ClearPendingTasks();
77 timer
->SetActive(true);
78 EXPECT_FALSE(task_runner
->HasPendingTask());
81 // At 60Hz, when the tick returns at exactly the requested next time, make sure
82 // a 16ms next delay is posted.
83 TEST(DelayBasedTimeSourceTest
, NextDelaySaneWhenExactlyOnRequestedTime
) {
84 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner
=
85 new base::TestSimpleTaskRunner
;
86 FakeTimeSourceClient client
;
87 scoped_ptr
<FakeDelayBasedTimeSource
> timer
=
88 FakeDelayBasedTimeSource::Create(Interval(), task_runner
.get());
89 timer
->SetClient(&client
);
90 timer
->SetActive(true);
91 // Run the first tick.
92 task_runner
->RunPendingTasks();
94 EXPECT_EQ(16, task_runner
->NextPendingTaskDelay().InMilliseconds());
96 timer
->SetNow(timer
->Now() + Interval());
97 task_runner
->RunPendingTasks();
99 EXPECT_EQ(16, task_runner
->NextPendingTaskDelay().InMilliseconds());
102 // At 60Hz, when the tick returns at slightly after the requested next time,
103 // make sure a 16ms next delay is posted.
104 TEST(DelayBasedTimeSourceTest
, NextDelaySaneWhenSlightlyAfterRequestedTime
) {
105 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner
=
106 new base::TestSimpleTaskRunner
;
107 FakeTimeSourceClient client
;
108 scoped_ptr
<FakeDelayBasedTimeSource
> timer
=
109 FakeDelayBasedTimeSource::Create(Interval(), task_runner
.get());
110 timer
->SetClient(&client
);
111 timer
->SetActive(true);
112 // Run the first tick.
113 task_runner
->RunPendingTasks();
115 EXPECT_EQ(16, task_runner
->NextPendingTaskDelay().InMilliseconds());
117 timer
->SetNow(timer
->Now() + Interval() +
118 base::TimeDelta::FromMicroseconds(1));
119 task_runner
->RunPendingTasks();
121 EXPECT_EQ(16, task_runner
->NextPendingTaskDelay().InMilliseconds());
124 // At 60Hz, when the tick returns at exactly 2*interval after the requested next
125 // time, make sure a 0ms next delay is posted.
126 TEST(DelayBasedTimeSourceTest
,
127 NextDelaySaneWhenExactlyTwiceAfterRequestedTime
) {
128 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner
=
129 new base::TestSimpleTaskRunner
;
130 FakeTimeSourceClient client
;
131 scoped_ptr
<FakeDelayBasedTimeSource
> timer
=
132 FakeDelayBasedTimeSource::Create(Interval(), task_runner
.get());
133 timer
->SetClient(&client
);
134 timer
->SetActive(true);
135 // Run the first tick.
136 task_runner
->RunPendingTasks();
138 EXPECT_EQ(16, task_runner
->NextPendingTaskDelay().InMilliseconds());
140 timer
->SetNow(timer
->Now() + 2 * Interval());
141 task_runner
->RunPendingTasks();
143 EXPECT_EQ(0, task_runner
->NextPendingTaskDelay().InMilliseconds());
146 // At 60Hz, when the tick returns at 2*interval and a bit after the requested
147 // next time, make sure a 16ms next delay is posted.
148 TEST(DelayBasedTimeSourceTest
,
149 NextDelaySaneWhenSlightlyAfterTwiceRequestedTime
) {
150 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner
=
151 new base::TestSimpleTaskRunner
;
152 FakeTimeSourceClient client
;
153 scoped_ptr
<FakeDelayBasedTimeSource
> timer
=
154 FakeDelayBasedTimeSource::Create(Interval(), task_runner
.get());
155 timer
->SetClient(&client
);
156 timer
->SetActive(true);
157 // Run the first tick.
158 task_runner
->RunPendingTasks();
160 EXPECT_EQ(16, task_runner
->NextPendingTaskDelay().InMilliseconds());
162 timer
->SetNow(timer
->Now() + 2 * Interval() +
163 base::TimeDelta::FromMicroseconds(1));
164 task_runner
->RunPendingTasks();
166 EXPECT_EQ(16, task_runner
->NextPendingTaskDelay().InMilliseconds());
169 // At 60Hz, when the tick returns halfway to the next frame time, make sure
170 // a correct next delay value is posted.
171 TEST(DelayBasedTimeSourceTest
, NextDelaySaneWhenHalfAfterRequestedTime
) {
172 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner
=
173 new base::TestSimpleTaskRunner
;
174 FakeTimeSourceClient client
;
175 scoped_ptr
<FakeDelayBasedTimeSource
> timer
=
176 FakeDelayBasedTimeSource::Create(Interval(), task_runner
.get());
177 timer
->SetClient(&client
);
178 timer
->SetActive(true);
179 // Run the first tick.
180 task_runner
->RunPendingTasks();
182 EXPECT_EQ(16, task_runner
->NextPendingTaskDelay().InMilliseconds());
184 timer
->SetNow(timer
->Now() + Interval() +
185 base::TimeDelta::FromMilliseconds(8));
186 task_runner
->RunPendingTasks();
188 EXPECT_EQ(8, task_runner
->NextPendingTaskDelay().InMilliseconds());
191 // If the timebase and interval are updated with a jittery source, we want to
192 // make sure we do not double tick.
193 TEST(DelayBasedTimeSourceTest
, SaneHandlingOfJitteryTimebase
) {
194 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner
=
195 new base::TestSimpleTaskRunner
;
196 FakeTimeSourceClient client
;
197 scoped_ptr
<FakeDelayBasedTimeSource
> timer
=
198 FakeDelayBasedTimeSource::Create(Interval(), task_runner
.get());
199 timer
->SetClient(&client
);
200 timer
->SetActive(true);
201 // Run the first tick.
202 task_runner
->RunPendingTasks();
204 EXPECT_EQ(16, task_runner
->NextPendingTaskDelay().InMilliseconds());
206 // Jitter timebase ~1ms late
207 timer
->SetNow(timer
->Now() + Interval());
208 timer
->SetTimebaseAndInterval(
209 timer
->Now() + base::TimeDelta::FromMilliseconds(1), Interval());
210 task_runner
->RunPendingTasks();
212 // Without double tick prevention, NextPendingTaskDelay would be 1.
213 EXPECT_EQ(17, task_runner
->NextPendingTaskDelay().InMilliseconds());
215 // Jitter timebase ~1ms early
216 timer
->SetNow(timer
->Now() + Interval());
217 timer
->SetTimebaseAndInterval(
218 timer
->Now() - base::TimeDelta::FromMilliseconds(1), Interval());
219 task_runner
->RunPendingTasks();
221 EXPECT_EQ(15, task_runner
->NextPendingTaskDelay().InMilliseconds());
224 TEST(DelayBasedTimeSourceTest
, HandlesSignificantTimebaseChangesImmediately
) {
225 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner
=
226 new base::TestSimpleTaskRunner
;
227 FakeTimeSourceClient client
;
228 scoped_ptr
<FakeDelayBasedTimeSource
> timer
=
229 FakeDelayBasedTimeSource::Create(Interval(), task_runner
.get());
230 timer
->SetClient(&client
);
231 timer
->SetActive(true);
232 // Run the first tick.
233 task_runner
->RunPendingTasks();
235 EXPECT_EQ(16, task_runner
->NextPendingTaskDelay().InMilliseconds());
237 // Tick, then shift timebase by +7ms.
238 timer
->SetNow(timer
->Now() + Interval());
239 task_runner
->RunPendingTasks();
241 EXPECT_EQ(16, task_runner
->NextPendingTaskDelay().InMilliseconds());
244 task_runner
->ClearPendingTasks();
245 task_runner
->RunPendingTasks();
246 base::TimeDelta jitter
= base::TimeDelta::FromMilliseconds(7) +
247 base::TimeDelta::FromMicroseconds(1);
248 timer
->SetTimebaseAndInterval(timer
->Now() + jitter
, Interval());
250 EXPECT_FALSE(client
.TickCalled()); // Make sure pending tasks were canceled.
251 EXPECT_EQ(16 + 7, task_runner
->NextPendingTaskDelay().InMilliseconds());
253 // Tick, then shift timebase by -7ms.
254 timer
->SetNow(timer
->Now() + Interval() + jitter
);
255 task_runner
->RunPendingTasks();
257 EXPECT_EQ(16, task_runner
->NextPendingTaskDelay().InMilliseconds());
260 task_runner
->ClearPendingTasks();
261 task_runner
->RunPendingTasks();
262 timer
->SetTimebaseAndInterval(base::TimeTicks() + Interval(), Interval());
264 EXPECT_FALSE(client
.TickCalled()); // Make sure pending tasks were canceled.
265 EXPECT_EQ(16 - 7, task_runner
->NextPendingTaskDelay().InMilliseconds());
268 TEST(DelayBasedTimeSourceTest
, HanldlesSignificantIntervalChangesImmediately
) {
269 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner
=
270 new base::TestSimpleTaskRunner
;
271 FakeTimeSourceClient client
;
272 scoped_ptr
<FakeDelayBasedTimeSource
> timer
=
273 FakeDelayBasedTimeSource::Create(Interval(), task_runner
.get());
274 timer
->SetClient(&client
);
275 timer
->SetActive(true);
276 // Run the first tick.
277 task_runner
->RunPendingTasks();
279 EXPECT_EQ(16, task_runner
->NextPendingTaskDelay().InMilliseconds());
281 // Tick, then double the interval.
282 timer
->SetNow(timer
->Now() + Interval());
283 task_runner
->RunPendingTasks();
285 EXPECT_EQ(16, task_runner
->NextPendingTaskDelay().InMilliseconds());
288 task_runner
->ClearPendingTasks();
289 task_runner
->RunPendingTasks();
290 timer
->SetTimebaseAndInterval(base::TimeTicks() + Interval(), Interval() * 2);
292 EXPECT_FALSE(client
.TickCalled()); // Make sure pending tasks were canceled.
293 EXPECT_EQ(33, task_runner
->NextPendingTaskDelay().InMilliseconds());
295 // Tick, then halve the interval.
296 timer
->SetNow(timer
->Now() + Interval() * 2);
297 task_runner
->RunPendingTasks();
299 EXPECT_EQ(33, task_runner
->NextPendingTaskDelay().InMilliseconds());
302 task_runner
->ClearPendingTasks();
303 task_runner
->RunPendingTasks();
304 timer
->SetTimebaseAndInterval(base::TimeTicks() + Interval() * 3, Interval());
306 EXPECT_FALSE(client
.TickCalled()); // Make sure pending tasks were canceled.
307 EXPECT_EQ(16, task_runner
->NextPendingTaskDelay().InMilliseconds());
310 TEST(DelayBasedTimeSourceTest
, JitteryRuntimeWithFutureTimebases
) {
311 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner
=
312 new base::TestSimpleTaskRunner
;
313 FakeTimeSourceClient client
;
314 scoped_ptr
<FakeDelayBasedTimeSource
> timer
=
315 FakeDelayBasedTimeSource::Create(Interval(), task_runner
.get());
316 timer
->SetClient(&client
);
317 timer
->SetActive(true);
319 // Run the first tick.
320 task_runner
->RunPendingTasks();
321 EXPECT_EQ(16, task_runner
->NextPendingTaskDelay().InMilliseconds());
323 base::TimeTicks future_timebase
= timer
->Now() + Interval() * 10;
326 base::TimeDelta jitter1
= base::TimeDelta::FromMilliseconds(1);
328 // Tick with +1ms of jitter
329 future_timebase
+= Interval();
330 timer
->SetTimebaseAndInterval(future_timebase
, Interval());
331 timer
->SetNow(timer
->Now() + Interval() + jitter1
);
332 task_runner
->RunPendingTasks();
333 EXPECT_EQ(15, task_runner
->NextPendingTaskDelay().InMilliseconds());
335 // Tick with 0ms of jitter
336 future_timebase
+= Interval();
337 timer
->SetTimebaseAndInterval(future_timebase
, Interval());
338 timer
->SetNow(timer
->Now() + Interval() - jitter1
);
339 task_runner
->RunPendingTasks();
340 EXPECT_EQ(16, task_runner
->NextPendingTaskDelay().InMilliseconds());
342 // Tick with -1ms of jitter
343 future_timebase
+= Interval();
344 timer
->SetTimebaseAndInterval(future_timebase
, Interval());
345 timer
->SetNow(timer
->Now() + Interval() - jitter1
);
346 task_runner
->RunPendingTasks();
347 EXPECT_EQ(17, task_runner
->NextPendingTaskDelay().InMilliseconds());
349 // Tick with 0ms of jitter
350 future_timebase
+= Interval();
351 timer
->SetTimebaseAndInterval(future_timebase
, Interval());
352 timer
->SetNow(timer
->Now() + Interval() + jitter1
);
353 task_runner
->RunPendingTasks();
354 EXPECT_EQ(16, task_runner
->NextPendingTaskDelay().InMilliseconds());
357 base::TimeDelta jitter8
= base::TimeDelta::FromMilliseconds(8);
359 // Tick with +8ms of jitter
360 future_timebase
+= Interval();
361 timer
->SetTimebaseAndInterval(future_timebase
, Interval());
362 timer
->SetNow(timer
->Now() + Interval() + jitter8
);
363 task_runner
->RunPendingTasks();
364 EXPECT_EQ(8, task_runner
->NextPendingTaskDelay().InMilliseconds());
366 // Tick with 0ms of jitter
367 future_timebase
+= Interval();
368 timer
->SetTimebaseAndInterval(future_timebase
, Interval());
369 timer
->SetNow(timer
->Now() + Interval() - jitter8
);
370 task_runner
->RunPendingTasks();
371 EXPECT_EQ(16, task_runner
->NextPendingTaskDelay().InMilliseconds());
373 // Tick with -8ms of jitter
374 future_timebase
+= Interval();
375 timer
->SetTimebaseAndInterval(future_timebase
, Interval());
376 timer
->SetNow(timer
->Now() + Interval() - jitter8
);
377 task_runner
->RunPendingTasks();
378 EXPECT_EQ(24, task_runner
->NextPendingTaskDelay().InMilliseconds());
380 // Tick with 0ms of jitter
381 future_timebase
+= Interval();
382 timer
->SetTimebaseAndInterval(future_timebase
, Interval());
383 timer
->SetNow(timer
->Now() + Interval() + jitter8
);
384 task_runner
->RunPendingTasks();
385 EXPECT_EQ(16, task_runner
->NextPendingTaskDelay().InMilliseconds());
388 base::TimeDelta jitter15
= base::TimeDelta::FromMilliseconds(15);
390 // Tick with +15ms jitter
391 future_timebase
+= Interval();
392 timer
->SetTimebaseAndInterval(future_timebase
, Interval());
393 timer
->SetNow(timer
->Now() + Interval() + jitter15
);
394 task_runner
->RunPendingTasks();
395 EXPECT_EQ(1, task_runner
->NextPendingTaskDelay().InMilliseconds());
397 // Tick with 0ms of jitter
398 future_timebase
+= Interval();
399 timer
->SetTimebaseAndInterval(future_timebase
, Interval());
400 timer
->SetNow(timer
->Now() + Interval() - jitter15
);
401 task_runner
->RunPendingTasks();
402 EXPECT_EQ(16, task_runner
->NextPendingTaskDelay().InMilliseconds());
404 // Tick with -15ms of jitter
405 future_timebase
+= Interval();
406 timer
->SetTimebaseAndInterval(future_timebase
, Interval());
407 timer
->SetNow(timer
->Now() + Interval() - jitter15
);
408 task_runner
->RunPendingTasks();
409 EXPECT_EQ(31, task_runner
->NextPendingTaskDelay().InMilliseconds());
411 // Tick with 0ms of jitter
412 future_timebase
+= Interval();
413 timer
->SetTimebaseAndInterval(future_timebase
, Interval());
414 timer
->SetNow(timer
->Now() + Interval() + jitter15
);
415 task_runner
->RunPendingTasks();
416 EXPECT_EQ(16, task_runner
->NextPendingTaskDelay().InMilliseconds());
419 TEST(DelayBasedTimeSourceTest
, AchievesTargetRateWithNoNoise
) {
420 int num_iterations
= 10;
422 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner
=
423 new base::TestSimpleTaskRunner
;
424 FakeTimeSourceClient client
;
425 scoped_ptr
<FakeDelayBasedTimeSource
> timer
=
426 FakeDelayBasedTimeSource::Create(Interval(), task_runner
.get());
427 timer
->SetClient(&client
);
428 timer
->SetActive(true);
430 double total_frame_time
= 0.0;
431 for (int i
= 0; i
< num_iterations
; ++i
) {
432 int64 delay_ms
= task_runner
->NextPendingTaskDelay().InMilliseconds();
434 // accumulate the "delay"
435 total_frame_time
+= delay_ms
/ 1000.0;
437 // Run the callback exactly when asked
438 timer
->SetNow(timer
->Now() + base::TimeDelta::FromMilliseconds(delay_ms
));
439 task_runner
->RunPendingTasks();
441 double average_interval
=
442 total_frame_time
/ static_cast<double>(num_iterations
);
443 EXPECT_NEAR(1.0 / 60.0, average_interval
, 0.1);
446 TEST(DelayBasedTimeSourceTest
, TestDeactivateWhilePending
) {
447 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner
=
448 new base::TestSimpleTaskRunner
;
449 FakeTimeSourceClient client
;
450 scoped_ptr
<FakeDelayBasedTimeSource
> timer
=
451 FakeDelayBasedTimeSource::Create(Interval(), task_runner
.get());
452 timer
->SetClient(&client
);
453 timer
->SetActive(true); // Should post a task.
454 timer
->SetActive(false);
456 // Should run the posted task without crashing.
457 EXPECT_TRUE(task_runner
->HasPendingTask());
458 task_runner
->RunPendingTasks();
461 TEST(DelayBasedTimeSourceTest
, TestDeactivateAndReactivateBeforeNextTickTime
) {
462 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner
=
463 new base::TestSimpleTaskRunner
;
464 FakeTimeSourceClient client
;
465 scoped_ptr
<FakeDelayBasedTimeSource
> timer
=
466 FakeDelayBasedTimeSource::Create(Interval(), task_runner
.get());
467 timer
->SetClient(&client
);
469 // Should run the activate task, and pick up a new timebase.
470 timer
->SetActive(true);
471 task_runner
->RunPendingTasks();
474 timer
->SetActive(false);
476 // Task will be pending anyway, run it
477 task_runner
->RunPendingTasks();
479 // Start the timer again, but before the next tick time the timer previously
480 // planned on using. That same tick time should still be targeted.
481 timer
->SetNow(timer
->Now() + base::TimeDelta::FromMilliseconds(4));
482 timer
->SetActive(true);
483 EXPECT_EQ(12, task_runner
->NextPendingTaskDelay().InMilliseconds());
486 TEST(DelayBasedTimeSourceTest
, TestDeactivateAndReactivateAfterNextTickTime
) {
487 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner
=
488 new base::TestSimpleTaskRunner
;
489 FakeTimeSourceClient client
;
490 scoped_ptr
<FakeDelayBasedTimeSource
> timer
=
491 FakeDelayBasedTimeSource::Create(Interval(), task_runner
.get());
492 timer
->SetClient(&client
);
494 // Should run the activate task, and pick up a new timebase.
495 timer
->SetActive(true);
496 task_runner
->RunPendingTasks();
499 timer
->SetActive(false);
501 // Task will be pending anyway, run it.
502 task_runner
->RunPendingTasks();
504 // Start the timer again, but before the next tick time the timer previously
505 // planned on using. That same tick time should still be targeted.
506 timer
->SetNow(timer
->Now() + base::TimeDelta::FromMilliseconds(20));
507 timer
->SetActive(true);
508 EXPECT_EQ(13, task_runner
->NextPendingTaskDelay().InMilliseconds());
511 TEST(DelayBasedTimeSourceTest
, TestReturnValueWhenTimerIsDeActivated
) {
512 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner
=
513 new base::TestSimpleTaskRunner
;
514 FakeTimeSourceClient client
;
515 scoped_ptr
<FakeDelayBasedTimeSource
> timer
=
516 FakeDelayBasedTimeSource::Create(Interval(), task_runner
.get());
517 timer
->SetClient(&client
);
519 timer
->SetActive(true);
520 task_runner
->RunPendingTasks();
522 // SetActive should return empty TimeTicks when the timer is deactivated.
523 base::TimeTicks missed_tick_time
= timer
->SetActive(false);
524 EXPECT_TRUE(missed_tick_time
.is_null());