1#!./perl
2
3BEGIN {
4    chdir 't' if -d 't';
5    @INC = '../lib';
6    require "./test.pl";
7}
8
9use warnings;
10use strict;
11use Errno;
12
13{ # Test we can seekdir to all positions.
14
15    my $dh;
16    ok(opendir($dh, ".") == 1, "able to opendir('.')");
17
18    # Build up a list of all the files and their positions.
19    my @p_f;  # ([POS_0, FILE_0], [POS_1, FILE_1], ...)
20    while (1) {
21        my $p = telldir $dh;
22        my $f = readdir $dh;
23        last unless defined $f;
24        push @p_f, [$p, $f];
25    }
26
27    # Test we can seekdir() to the given position and that
28    # readdir() returns the expected file name.
29    my $test = sub {
30        my ($p_f, $type) = @_;
31        my ($p, $f) = @$p_f;
32        ok(seekdir($dh, $p), "$type seekdir($p)");
33        ok(readdir($dh) eq $f, "$type readdir() -> $f \tas expected");
34    };
35    # Go forwards.
36    $test->($_, "forward") for @p_f;
37    # Go backwards.
38    $test->($_, "backward") for reverse @p_f;
39    # A mixed traversal: longest file names first.
40    my @sorted_p_f = sort {
41            length $b->[1] <=> length $a->[1]
42                or
43            $a->[1] cmp $b->[1]
44    } @p_f;
45    $test->($_, "mixed") for @sorted_p_f;
46
47    # Test behaviour of seekdir(-1).
48    ok(seekdir($dh, -1), "seekdir(-1) returns true...");
49    ok(!defined readdir($dh), "...but next readdir() gives undef");
50
51    # Test behaviour of seekdir() to a position beyond what we
52    # have read so far.
53    my $final_p_f = $p_f[-1];
54    my $end_pos = $final_p_f->[0] + length $final_p_f->[1];
55    ok(seekdir($dh, $end_pos), "seekdir($end_pos) possible");
56    ok(telldir($dh) == $end_pos, "telldir() equal to where we seekdir()d");
57    # At this point we readdir() the trailing NUL of the last file name.
58    ok(readdir($dh) eq '', "readdir() here gives an empty string");
59
60    # Reached the end of files to seekdir() to.
61    ok(telldir($dh) == -1, "telldir() now equal to -1");
62    ok(!defined readdir($dh), "next readdir() gives undef");
63
64    # NB. `seekdir(DH, POS)` always returns true regardless of the
65    # value of POS, providing DH is a valid directory handle.
66    # However, if POS _is_ out of range then `telldir(DH)` is -1,
67    # and `readdir(DH)` returns undef.
68    ok(seekdir($dh, $end_pos + 1), "seekdir($end_pos + 1) returns true...");
69    ok(telldir($dh) == -1, "....but telldir() == -1 indicating out of range");
70    ok(!defined readdir($dh), "... and next readdir() gives undef");
71
72    ok(closedir($dh) == 1, "Finally. closedir() returns true");
73}
74
75done_testing();
76