1414import os
1515import pickle
1616import select
17+ import selectors
1718import shutil
1819import signal
1920import socket
@@ -3940,6 +3941,11 @@ def timerfd_create(self, *args, **kwargs):
39403941 self .addCleanup (os .close , fd )
39413942 return fd
39423943
3944+ def read_count_signaled (self , fd ):
3945+ # read 8 bytes
3946+ data = os .read (fd , 8 )
3947+ return int .from_bytes (data , byteorder = sys .byteorder )
3948+
39433949 def test_timerfd_initval (self ):
39443950 fd = self .timerfd_create (time .CLOCK_REALTIME )
39453951
@@ -3962,25 +3968,22 @@ def test_timerfd_initval(self):
39623968 self .assertAlmostEqual (next_expiration , initial_expiration , places = 3 )
39633969
39643970 def test_timerfd_non_blocking (self ):
3965- size = 8 # read 8 bytes
39663971 fd = self .timerfd_create (time .CLOCK_REALTIME , flags = os .TFD_NONBLOCK )
39673972
39683973 # 0.1 second later
39693974 initial_expiration = 0.1
3970- _ , _ = os .timerfd_settime (fd , initial = initial_expiration , interval = 0 )
3975+ os .timerfd_settime (fd , initial = initial_expiration , interval = 0 )
39713976
39723977 # read() raises OSError with errno is EAGAIN for non-blocking timer.
39733978 with self .assertRaises (OSError ) as ctx :
3974- _ = os . read (fd , size )
3979+ self . read_count_signaled (fd )
39753980 self .assertEqual (ctx .exception .errno , errno .EAGAIN )
39763981
39773982 # Wait more than 0.1 seconds
39783983 time .sleep (initial_expiration + 0.1 )
39793984
39803985 # confirm if timerfd is readable and read() returns 1 as bytes.
3981- n = os .read (fd , size )
3982- count_signaled = int .from_bytes (n , byteorder = sys .byteorder )
3983- self .assertEqual (count_signaled , 1 )
3986+ self .assertEqual (self .read_count_signaled (fd ), 1 )
39843987
39853988 def test_timerfd_negative (self ):
39863989 one_sec_in_nsec = 10 ** 9
@@ -3995,25 +3998,24 @@ def test_timerfd_negative(self):
39953998 for flags in test_flags :
39963999 with self .subTest (flags = flags , initial = initial , interval = interval ):
39974000 with self .assertRaises (OSError ) as context :
3998- _ , _ = os .timerfd_settime (fd , flags = flags , initial = initial , interval = interval )
4001+ os .timerfd_settime (fd , flags = flags , initial = initial , interval = interval )
39994002 self .assertEqual (context .exception .errno , errno .EINVAL )
40004003
40014004 with self .assertRaises (OSError ) as context :
40024005 initial_ns = int ( one_sec_in_nsec * initial )
40034006 interval_ns = int ( one_sec_in_nsec * interval )
4004- _ , _ = os .timerfd_settime_ns (fd , flags = flags , initial = initial_ns , interval = interval_ns )
4007+ os .timerfd_settime_ns (fd , flags = flags , initial = initial_ns , interval = interval_ns )
40054008 self .assertEqual (context .exception .errno , errno .EINVAL )
40064009
40074010 def test_timerfd_interval (self ):
4008- size = 8 # read 8 bytes
40094011 fd = self .timerfd_create (time .CLOCK_REALTIME )
40104012
40114013 # 1 second
40124014 initial_expiration = 1
40134015 # 0.5 second
40144016 interval = 0.5
40154017
4016- _ , _ = os .timerfd_settime (fd , initial = initial_expiration , interval = interval )
4018+ os .timerfd_settime (fd , initial = initial_expiration , interval = interval )
40174019
40184020 # timerfd_gettime
40194021 next_expiration , interval2 = os .timerfd_gettime (fd )
@@ -4023,22 +4025,17 @@ def test_timerfd_interval(self):
40234025 count = 3
40244026 t = time .perf_counter ()
40254027 for _ in range (count ):
4026- n = os .read (fd , size )
4027- count_signaled = int .from_bytes (n , byteorder = sys .byteorder )
4028- self .assertEqual (count_signaled , 1 )
4028+ self .assertEqual (self .read_count_signaled (fd ), 1 )
40294029 t = time .perf_counter () - t
40304030
40314031 total_time = initial_expiration + interval * (count - 1 )
40324032 self .assertGreater (t , total_time )
40334033
40344034 # wait 3.5 time of interval
40354035 time .sleep ( (count + 0.5 ) * interval )
4036- n = os .read (fd , size )
4037- count_signaled = int .from_bytes (n , byteorder = sys .byteorder )
4038- self .assertEqual (count_signaled , count )
4036+ self .assertEqual (self .read_count_signaled (fd ), count )
40394037
40404038 def test_timerfd_TFD_TIMER_ABSTIME (self ):
4041- size = 8 # read 8 bytes
40424039 fd = self .timerfd_create (time .CLOCK_REALTIME )
40434040
40444041 now = time .clock_gettime (time .CLOCK_REALTIME )
@@ -4049,7 +4046,7 @@ def test_timerfd_TFD_TIMER_ABSTIME(self):
40494046 # not interval timer
40504047 interval = 0
40514048
4052- _ , _ = os .timerfd_settime (fd , flags = os .TFD_TIMER_ABSTIME , initial = initial_expiration , interval = interval )
4049+ os .timerfd_settime (fd , flags = os .TFD_TIMER_ABSTIME , initial = initial_expiration , interval = interval )
40534050
40544051 # timerfd_gettime
40554052 # Note: timerfd_gettime returns relative values even if TFD_TIMER_ABSTIME is specified.
@@ -4058,15 +4055,13 @@ def test_timerfd_TFD_TIMER_ABSTIME(self):
40584055 self .assertAlmostEqual (next_expiration , offset , places = 3 )
40594056
40604057 t = time .perf_counter ()
4061- n = os .read (fd , size )
4062- count_signaled = int .from_bytes (n , byteorder = sys .byteorder )
4058+ count_signaled = self .read_count_signaled (fd )
40634059 t = time .perf_counter () - t
40644060 self .assertEqual (count_signaled , 1 )
40654061
40664062 self .assertGreater (t , offset - self .CLOCK_RES )
40674063
40684064 def test_timerfd_select (self ):
4069- size = 8 # read 8 bytes
40704065 fd = self .timerfd_create (time .CLOCK_REALTIME , flags = os .TFD_NONBLOCK )
40714066
40724067 rfd , wfd , xfd = select .select ([fd ], [fd ], [fd ], 0 )
@@ -4077,56 +4072,74 @@ def test_timerfd_select(self):
40774072 # every 0.125 second
40784073 interval = 0.125
40794074
4080- _ , _ = os .timerfd_settime (fd , initial = initial_expiration , interval = interval )
4075+ os .timerfd_settime (fd , initial = initial_expiration , interval = interval )
40814076
40824077 count = 3
40834078 t = time .perf_counter ()
40844079 for _ in range (count ):
40854080 rfd , wfd , xfd = select .select ([fd ], [fd ], [fd ], initial_expiration + interval )
40864081 self .assertEqual ((rfd , wfd , xfd ), ([fd ], [], []))
4087- n = os .read (fd , size )
4088- count_signaled = int .from_bytes (n , byteorder = sys .byteorder )
4089- self .assertEqual (count_signaled , 1 )
4082+ self .assertEqual (self .read_count_signaled (fd ), 1 )
40904083 t = time .perf_counter () - t
40914084
40924085 total_time = initial_expiration + interval * (count - 1 )
40934086 self .assertGreater (t , total_time )
40944087
4095- def test_timerfd_epoll (self ):
4096- size = 8 # read 8 bytes
4088+ def check_timerfd_poll (self , nanoseconds ):
40974089 fd = self .timerfd_create (time .CLOCK_REALTIME , flags = os .TFD_NONBLOCK )
40984090
4099- ep = select . epoll ()
4100- ep .register (fd , select . EPOLLIN )
4101- self .addCleanup (ep .close )
4091+ selector = selectors . DefaultSelector ()
4092+ selector .register (fd , selectors . EVENT_READ )
4093+ self .addCleanup (selector .close )
41024094
4095+ sec_to_nsec = 10 ** 9
41034096 # 0.25 second
4104- initial_expiration = 0.25
4097+ initial_expiration_ns = sec_to_nsec // 4
41054098 # every 0.125 second
4106- interval = 0.125
4099+ interval_ns = sec_to_nsec // 8
41074100
4108- _ , _ = os .timerfd_settime (fd , initial = initial_expiration , interval = interval )
4101+ if nanoseconds :
4102+ os .timerfd_settime_ns (fd ,
4103+ initial = initial_expiration_ns ,
4104+ interval = interval_ns )
4105+ else :
4106+ os .timerfd_settime (fd ,
4107+ initial = initial_expiration_ns / sec_to_nsec ,
4108+ interval = interval_ns / sec_to_nsec )
41094109
41104110 count = 3
4111- t = time .perf_counter ()
4111+ if nanoseconds :
4112+ t = time .perf_counter_ns ()
4113+ else :
4114+ t = time .perf_counter ()
41124115 for i in range (count ):
4113- timeout_margin = interval
4116+ timeout_margin_ns = interval_ns
41144117 if i == 0 :
4115- timeout = initial_expiration + interval + timeout_margin
4118+ timeout_ns = initial_expiration_ns + interval_ns + timeout_margin_ns
41164119 else :
4117- timeout = interval + timeout_margin
4118- # epoll timeout is in seconds.
4119- events = ep .poll (timeout )
4120- self .assertEqual (events , [(fd , select .EPOLLIN )])
4121- n = os .read (fd , size )
4122- count_signaled = int .from_bytes (n , byteorder = sys .byteorder )
4123- self .assertEqual (count_signaled , 1 )
4120+ timeout_ns = interval_ns + timeout_margin_ns
41244121
4125- t = time .perf_counter () - t
4122+ ready = selector .select (timeout_ns / sec_to_nsec )
4123+ self .assertEqual (len (ready ), 1 , ready )
4124+ event = ready [0 ][1 ]
4125+ self .assertEqual (event , selectors .EVENT_READ )
41264126
4127- total_time = initial_expiration + interval * (count - 1 )
4128- self .assertGreater (t , total_time )
4129- ep .unregister (fd )
4127+ self .assertEqual (self .read_count_signaled (fd ), 1 )
4128+
4129+ total_time = initial_expiration_ns + interval_ns * (count - 1 )
4130+ if nanoseconds :
4131+ dt = time .perf_counter_ns () - t
4132+ self .assertGreater (dt , total_time )
4133+ else :
4134+ dt = time .perf_counter () - t
4135+ self .assertGreater (dt , total_time / sec_to_nsec )
4136+ selector .unregister (fd )
4137+
4138+ def test_timerfd_poll (self ):
4139+ self .check_timerfd_poll (False )
4140+
4141+ def test_timerfd_ns_poll (self ):
4142+ self .check_timerfd_poll (True )
41304143
41314144 def test_timerfd_ns_initval (self ):
41324145 one_sec_in_nsec = 10 ** 9
@@ -4153,7 +4166,6 @@ def test_timerfd_ns_initval(self):
41534166 self .assertAlmostEqual (next_expiration_ns , initial_expiration_ns , delta = limit_error )
41544167
41554168 def test_timerfd_ns_interval (self ):
4156- size = 8 # read 8 bytes
41574169 one_sec_in_nsec = 10 ** 9
41584170 limit_error = one_sec_in_nsec // 10 ** 3
41594171 fd = self .timerfd_create (time .CLOCK_REALTIME )
@@ -4163,7 +4175,7 @@ def test_timerfd_ns_interval(self):
41634175 # every 0.5 second
41644176 interval_ns = one_sec_in_nsec // 2
41654177
4166- _ , _ = os .timerfd_settime_ns (fd , initial = initial_expiration_ns , interval = interval_ns )
4178+ os .timerfd_settime_ns (fd , initial = initial_expiration_ns , interval = interval_ns )
41674179
41684180 # timerfd_gettime
41694181 next_expiration_ns , interval_ns2 = os .timerfd_gettime_ns (fd )
@@ -4173,23 +4185,18 @@ def test_timerfd_ns_interval(self):
41734185 count = 3
41744186 t = time .perf_counter_ns ()
41754187 for _ in range (count ):
4176- n = os .read (fd , size )
4177- count_signaled = int .from_bytes (n , byteorder = sys .byteorder )
4178- self .assertEqual (count_signaled , 1 )
4188+ self .assertEqual (self .read_count_signaled (fd ), 1 )
41794189 t = time .perf_counter_ns () - t
41804190
41814191 total_time_ns = initial_expiration_ns + interval_ns * (count - 1 )
41824192 self .assertGreater (t , total_time_ns )
41834193
41844194 # wait 3.5 time of interval
41854195 time .sleep ( (count + 0.5 ) * interval_ns / one_sec_in_nsec )
4186- n = os .read (fd , size )
4187- count_signaled = int .from_bytes (n , byteorder = sys .byteorder )
4188- self .assertEqual (count_signaled , count )
4196+ self .assertEqual (self .read_count_signaled (fd ), count )
41894197
41904198
41914199 def test_timerfd_ns_TFD_TIMER_ABSTIME (self ):
4192- size = 8 # read 8 bytes
41934200 one_sec_in_nsec = 10 ** 9
41944201 limit_error = one_sec_in_nsec // 10 ** 3
41954202 fd = self .timerfd_create (time .CLOCK_REALTIME )
@@ -4202,7 +4209,7 @@ def test_timerfd_ns_TFD_TIMER_ABSTIME(self):
42024209 # not interval timer
42034210 interval_ns = 0
42044211
4205- _ , _ = os .timerfd_settime_ns (fd , flags = os .TFD_TIMER_ABSTIME , initial = initial_expiration_ns , interval = interval_ns )
4212+ os .timerfd_settime_ns (fd , flags = os .TFD_TIMER_ABSTIME , initial = initial_expiration_ns , interval = interval_ns )
42064213
42074214 # timerfd_gettime
42084215 # Note: timerfd_gettime returns relative values even if TFD_TIMER_ABSTIME is specified.
@@ -4211,15 +4218,13 @@ def test_timerfd_ns_TFD_TIMER_ABSTIME(self):
42114218 self .assertLess (abs (next_expiration_ns - offset_ns ), limit_error )
42124219
42134220 t = time .perf_counter_ns ()
4214- n = os .read (fd , size )
4215- count_signaled = int .from_bytes (n , byteorder = sys .byteorder )
4221+ count_signaled = self .read_count_signaled (fd )
42164222 t = time .perf_counter_ns () - t
42174223 self .assertEqual (count_signaled , 1 )
42184224
42194225 self .assertGreater (t , offset_ns - self .CLOCK_RES_NS )
42204226
42214227 def test_timerfd_ns_select (self ):
4222- size = 8 # read 8 bytes
42234228 one_sec_in_nsec = 10 ** 9
42244229
42254230 fd = self .timerfd_create (time .CLOCK_REALTIME , flags = os .TFD_NONBLOCK )
@@ -4232,59 +4237,19 @@ def test_timerfd_ns_select(self):
42324237 # every 0.125 second
42334238 interval_ns = one_sec_in_nsec // 8
42344239
4235- _ , _ = os .timerfd_settime_ns (fd , initial = initial_expiration_ns , interval = interval_ns )
4240+ os .timerfd_settime_ns (fd , initial = initial_expiration_ns , interval = interval_ns )
42364241
42374242 count = 3
42384243 t = time .perf_counter_ns ()
42394244 for _ in range (count ):
42404245 rfd , wfd , xfd = select .select ([fd ], [fd ], [fd ], (initial_expiration_ns + interval_ns ) / 1e9 )
42414246 self .assertEqual ((rfd , wfd , xfd ), ([fd ], [], []))
4242- n = os .read (fd , size )
4243- count_signaled = int .from_bytes (n , byteorder = sys .byteorder )
4244- self .assertEqual (count_signaled , 1 )
4247+ self .assertEqual (self .read_count_signaled (fd ), 1 )
42454248 t = time .perf_counter_ns () - t
42464249
42474250 total_time_ns = initial_expiration_ns + interval_ns * (count - 1 )
42484251 self .assertGreater (t , total_time_ns )
42494252
4250- def test_timerfd_ns_epoll (self ):
4251- size = 8 # read 8 bytes
4252- one_sec_in_nsec = 10 ** 9
4253- fd = self .timerfd_create (time .CLOCK_REALTIME , flags = os .TFD_NONBLOCK )
4254-
4255- ep = select .epoll ()
4256- ep .register (fd , select .EPOLLIN )
4257- self .addCleanup (ep .close )
4258-
4259- # 0.25 second
4260- initial_expiration_ns = one_sec_in_nsec // 4
4261- # every 0.125 second
4262- interval_ns = one_sec_in_nsec // 8
4263-
4264- _ , _ = os .timerfd_settime_ns (fd , initial = initial_expiration_ns , interval = interval_ns )
4265-
4266- count = 3
4267- t = time .perf_counter_ns ()
4268- for i in range (count ):
4269- timeout_margin_ns = interval_ns
4270- if i == 0 :
4271- timeout_ns = initial_expiration_ns + interval_ns + timeout_margin_ns
4272- else :
4273- timeout_ns = interval_ns + timeout_margin_ns
4274-
4275- # epoll timeout is in seconds.
4276- events = ep .poll (timeout_ns / one_sec_in_nsec )
4277- self .assertEqual (events , [(fd , select .EPOLLIN )])
4278- n = os .read (fd , size )
4279- count_signaled = int .from_bytes (n , byteorder = sys .byteorder )
4280- self .assertEqual (count_signaled , 1 )
4281-
4282- t = time .perf_counter_ns () - t
4283-
4284- total_time = initial_expiration_ns + interval_ns * (count - 1 )
4285- self .assertGreater (t , total_time )
4286- ep .unregister (fd )
4287-
42884253class OSErrorTests (unittest .TestCase ):
42894254 def setUp (self ):
42904255 class Str (str ):
0 commit comments