@@ -204,11 +204,24 @@ mod tests {
204204 use super :: * ;
205205 use std:: fs;
206206
207+ /// Build a platform-absolute path from POSIX-style components. A leading
208+ /// `/` is absolute on Unix but *not* on Windows (which wants a drive
209+ /// prefix), so these fixtures would otherwise be treated as relative there.
210+ /// On Unix the path is returned unchanged.
211+ fn abs_path ( posix : & str ) -> PathBuf {
212+ let rel = posix. trim_start_matches ( '/' ) ;
213+ if cfg ! ( windows) {
214+ PathBuf :: from ( format ! ( "C:\\ {}" , rel. replace( '/' , "\\ " ) ) )
215+ } else {
216+ PathBuf :: from ( format ! ( "/{rel}" ) )
217+ }
218+ }
219+
207220 // ── from_files ──────────────────────────────────────────────────────────
208221
209222 #[ test]
210223 fn from_files_absolute_stays_absolute ( ) {
211- let abs = PathBuf :: from ( "/tmp/song.mod" ) ;
224+ let abs = abs_path ( "/tmp/song.mod" ) ;
212225 let pl = Playlist :: from_files ( vec ! [ abs. clone( ) ] ) ;
213226 assert_eq ! ( pl. entries[ 0 ] , abs) ;
214227 assert ! ( pl. path. is_none( ) ) ;
@@ -235,16 +248,22 @@ mod tests {
235248 fn load_skips_comments_and_blank_lines ( ) {
236249 let dir = tempfile:: tempdir ( ) . unwrap ( ) ;
237250 let pl_path = dir. path ( ) . join ( "list.m3u" ) ;
251+ let song = abs_path ( "/abs/song.mod" ) ;
252+ let other = abs_path ( "/abs/other.xm" ) ;
238253 fs:: write (
239254 & pl_path,
240- "#EXTM3U\n # a comment\n \n /abs/song.mod\n \n # another\n /abs/other.xm\n " ,
255+ format ! (
256+ "#EXTM3U\n # a comment\n \n {}\n \n # another\n {}\n " ,
257+ song. display( ) ,
258+ other. display( )
259+ ) ,
241260 )
242261 . unwrap ( ) ;
243262
244263 let pl = Playlist :: load ( pl_path) . unwrap ( ) ;
245264 assert_eq ! ( pl. entries. len( ) , 2 ) ;
246- assert_eq ! ( pl. entries[ 0 ] , PathBuf :: from ( "/abs/ song.mod" ) ) ;
247- assert_eq ! ( pl. entries[ 1 ] , PathBuf :: from ( "/abs/ other.xm" ) ) ;
265+ assert_eq ! ( pl. entries[ 0 ] , song) ;
266+ assert_eq ! ( pl. entries[ 1 ] , other) ;
248267 }
249268
250269 #[ test]
@@ -262,31 +281,32 @@ mod tests {
262281 fn load_keeps_absolute_paths ( ) {
263282 let dir = tempfile:: tempdir ( ) . unwrap ( ) ;
264283 let pl_path = dir. path ( ) . join ( "list.m3u" ) ;
265- fs:: write ( & pl_path, "/music/song.mod\n " ) . unwrap ( ) ;
284+ let song = abs_path ( "/music/song.mod" ) ;
285+ fs:: write ( & pl_path, format ! ( "{}\n " , song. display( ) ) ) . unwrap ( ) ;
266286
267287 let pl = Playlist :: load ( pl_path) . unwrap ( ) ;
268- assert_eq ! ( pl. entries[ 0 ] , PathBuf :: from ( "/music/ song.mod" ) ) ;
288+ assert_eq ! ( pl. entries[ 0 ] , song) ;
269289 }
270290
271291 // ── navigation ──────────────────────────────────────────────────────────
272292
273293 fn three_entry_playlist ( ) -> Playlist {
274294 Playlist :: from_files ( vec ! [
275- PathBuf :: from ( "/a.mod" ) ,
276- PathBuf :: from ( "/b.mod" ) ,
277- PathBuf :: from ( "/c.mod" ) ,
295+ abs_path ( "/a.mod" ) ,
296+ abs_path ( "/b.mod" ) ,
297+ abs_path ( "/c.mod" ) ,
278298 ] )
279299 }
280300
281301 #[ test]
282302 fn next_after_returns_following_entry ( ) {
283303 let pl = three_entry_playlist ( ) ;
284304 assert_eq ! (
285- pl. next_after( Path :: new ( "/a.mod" ) ) ,
305+ pl. next_after( & abs_path ( "/a.mod" ) ) ,
286306 Some ( pl. entries[ 1 ] . clone( ) )
287307 ) ;
288308 assert_eq ! (
289- pl. next_after( Path :: new ( "/b.mod" ) ) ,
309+ pl. next_after( & abs_path ( "/b.mod" ) ) ,
290310 Some ( pl. entries[ 2 ] . clone( ) )
291311 ) ;
292312 }
@@ -307,11 +327,11 @@ mod tests {
307327 fn prev_before_returns_preceding_entry ( ) {
308328 let pl = three_entry_playlist ( ) ;
309329 assert_eq ! (
310- pl. prev_before( Path :: new ( "/b.mod" ) ) ,
330+ pl. prev_before( & abs_path ( "/b.mod" ) ) ,
311331 Some ( pl. entries[ 0 ] . clone( ) )
312332 ) ;
313333 assert_eq ! (
314- pl. prev_before( Path :: new ( "/c.mod" ) ) ,
334+ pl. prev_before( & abs_path ( "/c.mod" ) ) ,
315335 Some ( pl. entries[ 1 ] . clone( ) )
316336 ) ;
317337 }
@@ -348,9 +368,8 @@ mod tests {
348368
349369 #[ test]
350370 fn shuffle_anchors_on_the_current_track ( ) {
351- let mut pl =
352- Playlist :: from_files ( ( 0 ..16 ) . map ( |i| PathBuf :: from ( format ! ( "/{i}.xm" ) ) ) . collect ( ) ) ;
353- let anchor = PathBuf :: from ( "/7.xm" ) ;
371+ let mut pl = Playlist :: from_files ( ( 0 ..16 ) . map ( |i| abs_path ( & format ! ( "/{i}.xm" ) ) ) . collect ( ) ) ;
372+ let anchor = abs_path ( "/7.xm" ) ;
354373 pl. set_shuffle ( true , Some ( & anchor) ) ;
355374 // The anchor becomes the head so playback continues from it.
356375 assert_eq ! ( pl. start( ) , Some ( & anchor) ) ;
@@ -359,28 +378,22 @@ mod tests {
359378 #[ test]
360379 fn unshuffle_restores_sequential_order ( ) {
361380 let mut pl = Playlist :: from_files ( vec ! [
362- PathBuf :: from ( "/a.xm" ) ,
363- PathBuf :: from ( "/b.xm" ) ,
364- PathBuf :: from ( "/c.xm" ) ,
381+ abs_path ( "/a.xm" ) ,
382+ abs_path ( "/b.xm" ) ,
383+ abs_path ( "/c.xm" ) ,
365384 ] ) ;
366385 pl. set_shuffle ( true , None ) ;
367386 pl. set_shuffle ( false , None ) ;
368387 assert ! ( !pl. is_shuffled( ) ) ;
369- assert_eq ! (
370- pl. next_after( Path :: new( "/a.xm" ) ) ,
371- Some ( PathBuf :: from( "/b.xm" ) )
372- ) ;
388+ assert_eq ! ( pl. next_after( & abs_path( "/a.xm" ) ) , Some ( abs_path( "/b.xm" ) ) ) ;
373389 }
374390
375391 #[ test]
376392 fn push_keeps_order_consistent ( ) {
377- let mut pl = Playlist :: from_files ( vec ! [ PathBuf :: from ( "/a.xm" ) ] ) ;
378- pl. push ( PathBuf :: from ( "/b.xm" ) ) ;
393+ let mut pl = Playlist :: from_files ( vec ! [ abs_path ( "/a.xm" ) ] ) ;
394+ pl. push ( abs_path ( "/b.xm" ) ) ;
379395 assert_eq ! ( pl. len( ) , 2 ) ;
380- assert_eq ! (
381- pl. next_after( Path :: new( "/a.xm" ) ) ,
382- Some ( PathBuf :: from( "/b.xm" ) )
383- ) ;
396+ assert_eq ! ( pl. next_after( & abs_path( "/a.xm" ) ) , Some ( abs_path( "/b.xm" ) ) ) ;
384397 }
385398
386399 #[ test]
@@ -436,10 +449,11 @@ mod tests {
436449 fn file_contains_detects_absolute_entry ( ) {
437450 let dir = tempfile:: tempdir ( ) . unwrap ( ) ;
438451 let pl_path = dir. path ( ) . join ( "list.m3u" ) ;
439- fs:: write ( & pl_path, "#EXTM3U\n /music/song.mod\n " ) . unwrap ( ) ;
452+ let song = abs_path ( "/music/song.mod" ) ;
453+ fs:: write ( & pl_path, format ! ( "#EXTM3U\n {}\n " , song. display( ) ) ) . unwrap ( ) ;
440454
441- assert ! ( file_contains( Path :: new ( "/music/ song.mod" ) , & pl_path) ) ;
442- assert ! ( !file_contains( Path :: new ( "/music/other.mod" ) , & pl_path) ) ;
455+ assert ! ( file_contains( & song, & pl_path) ) ;
456+ assert ! ( !file_contains( & abs_path ( "/music/other.mod" ) , & pl_path) ) ;
443457 }
444458
445459 #[ test]
@@ -456,10 +470,15 @@ mod tests {
456470 fn file_contains_skips_comments_and_blank_lines ( ) {
457471 let dir = tempfile:: tempdir ( ) . unwrap ( ) ;
458472 let pl_path = dir. path ( ) . join ( "list.m3u" ) ;
459- fs:: write ( & pl_path, "#EXTM3U\n # /commented.mod\n \n /real.mod\n " ) . unwrap ( ) ;
473+ let real = abs_path ( "/real.mod" ) ;
474+ fs:: write (
475+ & pl_path,
476+ format ! ( "#EXTM3U\n # /commented.mod\n \n {}\n " , real. display( ) ) ,
477+ )
478+ . unwrap ( ) ;
460479
461- assert ! ( !file_contains( Path :: new ( "/commented.mod" ) , & pl_path) ) ;
462- assert ! ( file_contains( Path :: new ( "/ real.mod" ) , & pl_path) ) ;
480+ assert ! ( !file_contains( & abs_path ( "/commented.mod" ) , & pl_path) ) ;
481+ assert ! ( file_contains( & real, & pl_path) ) ;
463482 }
464483
465484 #[ test]
0 commit comments