@@ -219,86 +219,105 @@ def test_buffer_copy_from():
219219 buffer_copy_from (DummyPinnedMemoryResource (device ), device , check = True )
220220
221221
222- def buffer_fill (dummy_mr : MemoryResource , device : Device , check = False ):
223- stream = device .create_stream ()
224-
225- # Test width=1 (byte fill)
226- buffer1 = dummy_mr .allocate (size = 1024 )
227- buffer1 .fill (0x42 , width = 1 , stream = stream )
228- device .sync ()
229-
230- if check :
231- ptr = ctypes .cast (buffer1 .handle , ctypes .POINTER (ctypes .c_byte ))
232- for i in range (10 ):
233- assert ptr [i ] == 0x42
222+ def _bytes_repeat (pattern : bytes , size : int ) -> bytes :
223+ assert len (pattern ) > 0
224+ assert size % len (pattern ) == 0
225+ return pattern * (size // len (pattern ))
234226
235- # Test error: invalid width
236- for bad_width in [w for w in range (- 10 , 10 ) if w not in (1 , 2 , 4 )]:
237- with pytest .raises (ValueError , match = "width must be 1, 2, or 4" ):
238- buffer1 .fill (0x42 , width = bad_width , stream = stream )
239227
240- # Test error: value out of range for width=1
241- for bad_value in [ - 42 , - 1 , 256 ] :
242- with pytest . raises ( ValueError , match = "value must be in range \\ [0, 255 \\ ]" ):
243- buffer1 . fill ( bad_value , width = 1 , stream = stream )
228+ def _pattern_bytes ( value ) -> bytes :
229+ if isinstance ( value , int ) :
230+ return bytes ([ value ])
231+ return bytes ( memoryview ( value ). cast ( "B" ) )
244232
245- # Test error: buffer size not divisible by width
246- for bad_size in [1025 , 1027 , 1029 , 1031 ]: # Not divisible by 2
247- buffer_err = dummy_mr .allocate (size = 1025 )
248- with pytest .raises (ValueError , match = "must be divisible" ):
249- buffer_err .fill (0x1234 , width = 2 , stream = stream )
250- buffer_err .close ()
251-
252- buffer1 .close ()
253-
254- # Test width=2 (16-bit fill)
255- buffer2 = dummy_mr .allocate (size = 1024 ) # Divisible by 2
256- buffer2 .fill (0x1234 , width = 2 , stream = stream )
257- device .sync ()
258-
259- if check :
260- ptr = ctypes .cast (buffer2 .handle , ctypes .POINTER (ctypes .c_uint16 ))
261- for i in range (5 ):
262- assert ptr [i ] == 0x1234
263-
264- # Test error: value out of range for width=2
265- for bad_value in [- 42 , - 1 , 65536 , 65537 , 100000 ]:
266- with pytest .raises (ValueError , match = "value must be in range \\ [0, 65535\\ ]" ):
267- buffer2 .fill (bad_value , width = 2 , stream = stream )
268-
269- buffer2 .close ()
270233
271- # Test width=4 (32-bit fill)
272- buffer4 = dummy_mr .allocate (size = 1024 ) # Divisible by 4
273- buffer4 .fill (0xDEADBEEF , width = 4 , stream = stream )
274- device .sync ()
275-
276- if check :
277- ptr = ctypes .cast (buffer4 .handle , ctypes .POINTER (ctypes .c_uint32 ))
278- for i in range (5 ):
279- assert ptr [i ] == 0xDEADBEEF
280-
281- # Test error: value out of range for width=4
282- for bad_value in [- 42 , - 1 , 4294967296 , 4294967297 , 5000000000 ]:
283- with pytest .raises (ValueError , match = "value must be in range \\ [0, 4294967295\\ ]" ):
284- buffer4 .fill (bad_value , width = 4 , stream = stream )
285-
286- # Test error: buffer size not divisible by width
287- for bad_size in [1025 , 1026 , 1027 , 1029 , 1030 , 1031 ]: # Not divisible by 4
288- buffer_err2 = dummy_mr .allocate (size = bad_size )
289- with pytest .raises (ValueError , match = "must be divisible" ):
290- buffer_err2 .fill (0xDEADBEEF , width = 4 , stream = stream )
291- buffer_err2 .close ()
292-
293- buffer4 .close ()
294-
295-
296- def test_buffer_fill ():
234+ @pytest .fixture (params = ["device" , "unified" , "pinned" ])
235+ def fill_env (request ):
297236 device = Device ()
298237 device .set_current ()
299- buffer_fill (DummyDeviceMemoryResource (device ), device )
300- buffer_fill (DummyUnifiedMemoryResource (device ), device )
301- buffer_fill (DummyPinnedMemoryResource (device ), device , check = True )
238+ if request .param == "device" :
239+ mr = DummyDeviceMemoryResource (device )
240+ elif request .param == "unified" :
241+ mr = DummyUnifiedMemoryResource (device )
242+ else :
243+ mr = DummyPinnedMemoryResource (device )
244+ return device , mr
245+
246+
247+ _FILL_SIZE = 64 # Keep small; divisible by 1/2/4.
248+
249+ _FILL_CASES = [
250+ # int -> 1-byte pattern
251+ pytest .param (0x42 , _FILL_SIZE , None , id = "int-0x42" ),
252+ pytest .param (- 1 , _FILL_SIZE , OverflowError , id = "int-neg" ),
253+ pytest .param (256 , _FILL_SIZE , OverflowError , id = "int-256" ),
254+ pytest .param (1000 , _FILL_SIZE , OverflowError , id = "int-1000" ),
255+ # bad type
256+ pytest .param ("invalid" , _FILL_SIZE , TypeError , id = "bad-type-str" ),
257+ # bytes-like patterns
258+ pytest .param (b"\x7f " , _FILL_SIZE , None , id = "bytes-1" ),
259+ pytest .param (b"\x34 \x12 " , _FILL_SIZE , None , id = "bytes-2" ),
260+ pytest .param (b"\xef \xbe \xad \xde " , _FILL_SIZE , None , id = "bytes-4" ),
261+ pytest .param (b"\x34 \x12 " , _FILL_SIZE + 1 , ValueError , id = "bytes-2-bad-size" ),
262+ pytest .param (b"\xef \xbe \xad \xde " , _FILL_SIZE + 2 , ValueError , id = "bytes-4-bad-size" ),
263+ pytest .param (b"" , _FILL_SIZE , ValueError , id = "bytes-0" ),
264+ pytest .param (b"\x01 \x02 \x03 " , _FILL_SIZE , ValueError , id = "bytes-3" ),
265+ ]
266+
267+ if np is not None :
268+ _FILL_CASES .extend (
269+ [
270+ # 8-bit patterns
271+ pytest .param (np .uint8 (0 ), _FILL_SIZE , None , id = "np-uint8-0" ),
272+ pytest .param (np .uint8 (255 ), _FILL_SIZE , None , id = "np-uint8-255" ),
273+ pytest .param (np .int8 (- 1 ), _FILL_SIZE , None , id = "np-int8--1" ),
274+ pytest .param (np .int8 (127 ), _FILL_SIZE , None , id = "np-int8-127" ),
275+ pytest .param (np .int8 (- 128 ), _FILL_SIZE , None , id = "np-int8--128" ),
276+ # 16-bit patterns
277+ pytest .param (np .uint16 (0x1234 ), _FILL_SIZE , None , id = "np-uint16-0x1234" ),
278+ pytest .param (np .uint16 (0xFFFF ), _FILL_SIZE , None , id = "np-uint16-0xFFFF" ),
279+ pytest .param (np .int16 (- 1 ), _FILL_SIZE , None , id = "np-int16--1" ),
280+ pytest .param (np .int16 (32767 ), _FILL_SIZE , None , id = "np-int16-max" ),
281+ pytest .param (np .int16 (- 32768 ), _FILL_SIZE , None , id = "np-int16-min" ),
282+ pytest .param (np .uint16 (0x1234 ), _FILL_SIZE + 1 , ValueError , id = "np-uint16-bad-size" ),
283+ # 32-bit patterns
284+ pytest .param (np .uint32 (0xDEADBEEF ), _FILL_SIZE , None , id = "np-uint32-0xDEADBEEF" ),
285+ pytest .param (np .uint32 (0xFFFFFFFF ), _FILL_SIZE , None , id = "np-uint32-0xFFFFFFFF" ),
286+ pytest .param (np .int32 (- 1 ), _FILL_SIZE , None , id = "np-int32--1" ),
287+ pytest .param (np .int32 (2147483647 ), _FILL_SIZE , None , id = "np-int32-max" ),
288+ pytest .param (np .int32 (- 2147483648 ), _FILL_SIZE , None , id = "np-int32-min" ),
289+ pytest .param (np .uint32 (0xDEADBEEF ), _FILL_SIZE + 2 , ValueError , id = "np-uint32-bad-size" ),
290+ # float32 (bit-pattern fill)
291+ pytest .param (np .float32 (1.0 ), _FILL_SIZE , None , id = "np-float32-1.0" ),
292+ # 64-bit patterns should error (8-byte pattern)
293+ pytest .param (np .uint64 (0 ), _FILL_SIZE , ValueError , id = "np-uint64-err" ),
294+ pytest .param (np .int64 (0 ), _FILL_SIZE , ValueError , id = "np-int64-err" ),
295+ pytest .param (np .float64 (0 ), _FILL_SIZE , ValueError , id = "np-float64-err" ),
296+ ]
297+ )
298+
299+
300+ @pytest .mark .parametrize ("value,size,exc" , _FILL_CASES )
301+ def test_buffer_fill (fill_env , value , size , exc ):
302+ device , mr = fill_env
303+ stream = device .create_stream ()
304+ buffer = mr .allocate (size = size )
305+ try :
306+ if exc is not None :
307+ with pytest .raises (exc ):
308+ buffer .fill (value , stream = stream )
309+ return
310+
311+ buffer .fill (value , stream = stream )
312+ device .sync ()
313+
314+ # Verify contents only for host-accessible buffers.
315+ if buffer .is_host_accessible :
316+ pat = _pattern_bytes (value )
317+ got = ctypes .string_at (int (buffer .handle ), size )
318+ assert got == _bytes_repeat (pat , size )
319+ finally :
320+ buffer .close ()
302321
303322
304323def buffer_close (dummy_mr : MemoryResource ):
0 commit comments