1// Copyright 2019 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// +build darwin dragonfly freebsd openbsd netbsd
6
7package unix_test
8
9import (
10	"fmt"
11	"io/ioutil"
12	"os"
13	"path/filepath"
14	"sort"
15	"strings"
16	"testing"
17
18	"golang.org/x/sys/unix"
19)
20
21func TestGetdirentries(t *testing.T) {
22	for _, count := range []int{10, 1000} {
23		t.Run(fmt.Sprintf("n=%d", count), func(t *testing.T) {
24			testGetdirentries(t, count)
25		})
26	}
27}
28func testGetdirentries(t *testing.T, count int) {
29	if count > 100 && testing.Short() && os.Getenv("GO_BUILDER_NAME") == "" {
30		t.Skip("skipping in -short mode")
31	}
32	d, err := ioutil.TempDir("", "getdirentries-test")
33	if err != nil {
34		t.Fatalf("Tempdir: %v", err)
35	}
36	defer os.RemoveAll(d)
37	var names []string
38	for i := 0; i < count; i++ {
39		names = append(names, fmt.Sprintf("file%03d", i))
40	}
41
42	// Make files in the temp directory
43	for _, name := range names {
44		err := ioutil.WriteFile(filepath.Join(d, name), []byte("data"), 0)
45		if err != nil {
46			t.Fatalf("WriteFile: %v", err)
47		}
48	}
49
50	// Read files using Getdirentries
51	fd, err := unix.Open(d, unix.O_RDONLY, 0)
52	if err != nil {
53		t.Fatalf("Open: %v", err)
54	}
55	defer unix.Close(fd)
56	var base uintptr
57	var buf [2048]byte
58	names2 := make([]string, 0, count)
59	for {
60		n, err := unix.Getdirentries(fd, buf[:], &base)
61		if err != nil {
62			t.Fatalf("Getdirentries: %v", err)
63		}
64		if n == 0 {
65			break
66		}
67		data := buf[:n]
68		for len(data) > 0 {
69			var bc int
70			bc, _, names2 = unix.ParseDirent(data, -1, names2)
71			if bc == 0 && len(data) > 0 {
72				t.Fatal("no progress")
73			}
74			data = data[bc:]
75		}
76	}
77
78	sort.Strings(names)
79	sort.Strings(names2)
80	if strings.Join(names, ":") != strings.Join(names2, ":") {
81		t.Errorf("names don't match\n names: %q\nnames2: %q", names, names2)
82	}
83}
84