apparmor.d/pkg/paths/readdir_test.go

344 lines
13 KiB
Go
Raw Normal View History

/*
* This file is part of PathsHelper library.
*
* Copyright 2018-2022 Arduino AG (http://www.arduino.cc/)
*
* PathsHelper library is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*/
package paths
import (
"fmt"
"io/fs"
"os"
"runtime"
"testing"
"time"
"github.com/stretchr/testify/require"
)
func TestReadDirRecursive(t *testing.T) {
testPath := New("testdata", "fileset")
list, err := testPath.ReadDirRecursive()
require.NoError(t, err)
require.Len(t, list, 16)
pathEqualsTo(t, "testdata/fileset/anotherFile", list[0])
pathEqualsTo(t, "testdata/fileset/file", list[1])
pathEqualsTo(t, "testdata/fileset/folder", list[2])
pathEqualsTo(t, "testdata/fileset/folder/.hidden", list[3])
pathEqualsTo(t, "testdata/fileset/folder/file2", list[4])
pathEqualsTo(t, "testdata/fileset/folder/file3", list[5])
pathEqualsTo(t, "testdata/fileset/folder/subfolder", list[6])
pathEqualsTo(t, "testdata/fileset/folder/subfolder/file4", list[7])
pathEqualsTo(t, "testdata/fileset/symlinktofolder", list[8])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/.hidden", list[9])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/file2", list[10])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/file3", list[11])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/subfolder", list[12])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/subfolder/file4", list[13])
pathEqualsTo(t, "testdata/fileset/test.txt", list[14])
pathEqualsTo(t, "testdata/fileset/test.txt.gz", list[15])
}
func TestReadDirRecursiveSymLinkLoop(t *testing.T) {
// Test symlink loop
tmp, err := MkTempDir("", "")
require.NoError(t, err)
defer tmp.RemoveAll()
folder := tmp.Join("folder")
err = os.Symlink(tmp.String(), folder.String())
require.NoError(t, err)
l, err := tmp.ReadDirRecursive()
require.Error(t, err)
fmt.Println(err)
require.Nil(t, l)
l, err = tmp.ReadDirRecursiveFiltered(nil)
require.Error(t, err)
fmt.Println(err)
require.Nil(t, l)
}
func TestReadDirFiltered(t *testing.T) {
folderPath := New("testdata/fileset/folder")
list, err := folderPath.ReadDir()
require.NoError(t, err)
require.Len(t, list, 4)
pathEqualsTo(t, "testdata/fileset/folder/.hidden", list[0])
pathEqualsTo(t, "testdata/fileset/folder/file2", list[1])
pathEqualsTo(t, "testdata/fileset/folder/file3", list[2])
pathEqualsTo(t, "testdata/fileset/folder/subfolder", list[3])
list, err = folderPath.ReadDir(FilterDirectories())
require.NoError(t, err)
require.Len(t, list, 1)
pathEqualsTo(t, "testdata/fileset/folder/subfolder", list[0])
list, err = folderPath.ReadDir(FilterOutPrefixes("file"))
require.NoError(t, err)
require.Len(t, list, 2)
pathEqualsTo(t, "testdata/fileset/folder/.hidden", list[0])
pathEqualsTo(t, "testdata/fileset/folder/subfolder", list[1])
}
func TestReadDirRecursiveFiltered(t *testing.T) {
testdata := New("testdata", "fileset")
l, err := testdata.ReadDirRecursiveFiltered(nil)
require.NoError(t, err)
l.Sort()
require.Len(t, l, 16)
pathEqualsTo(t, "testdata/fileset/anotherFile", l[0])
pathEqualsTo(t, "testdata/fileset/file", l[1])
pathEqualsTo(t, "testdata/fileset/folder", l[2])
pathEqualsTo(t, "testdata/fileset/folder/.hidden", l[3])
pathEqualsTo(t, "testdata/fileset/folder/file2", l[4])
pathEqualsTo(t, "testdata/fileset/folder/file3", l[5])
pathEqualsTo(t, "testdata/fileset/folder/subfolder", l[6])
pathEqualsTo(t, "testdata/fileset/folder/subfolder/file4", l[7])
pathEqualsTo(t, "testdata/fileset/symlinktofolder", l[8])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/.hidden", l[9])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/file2", l[10])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/file3", l[11])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/subfolder", l[12])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/subfolder/file4", l[13])
pathEqualsTo(t, "testdata/fileset/test.txt", l[14])
pathEqualsTo(t, "testdata/fileset/test.txt.gz", l[15])
l, err = testdata.ReadDirRecursiveFiltered(FilterOutDirectories())
require.NoError(t, err)
l.Sort()
require.Len(t, l, 6)
pathEqualsTo(t, "testdata/fileset/anotherFile", l[0])
pathEqualsTo(t, "testdata/fileset/file", l[1])
pathEqualsTo(t, "testdata/fileset/folder", l[2]) // <- this is listed but not traversed
pathEqualsTo(t, "testdata/fileset/symlinktofolder", l[3]) // <- this is listed but not traversed
pathEqualsTo(t, "testdata/fileset/test.txt", l[4])
pathEqualsTo(t, "testdata/fileset/test.txt.gz", l[5])
l, err = testdata.ReadDirRecursiveFiltered(nil, FilterOutDirectories())
require.NoError(t, err)
l.Sort()
require.Len(t, l, 12)
pathEqualsTo(t, "testdata/fileset/anotherFile", l[0])
pathEqualsTo(t, "testdata/fileset/file", l[1])
pathEqualsTo(t, "testdata/fileset/folder/.hidden", l[2])
pathEqualsTo(t, "testdata/fileset/folder/file2", l[3])
pathEqualsTo(t, "testdata/fileset/folder/file3", l[4])
pathEqualsTo(t, "testdata/fileset/folder/subfolder/file4", l[5])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/.hidden", l[6])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/file2", l[7])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/file3", l[8])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/subfolder/file4", l[9])
pathEqualsTo(t, "testdata/fileset/test.txt", l[10])
pathEqualsTo(t, "testdata/fileset/test.txt.gz", l[11])
l, err = testdata.ReadDirRecursiveFiltered(FilterOutDirectories(), FilterOutDirectories())
require.NoError(t, err)
l.Sort()
require.Len(t, l, 4)
pathEqualsTo(t, "testdata/fileset/anotherFile", l[0])
pathEqualsTo(t, "testdata/fileset/file", l[1])
pathEqualsTo(t, "testdata/fileset/test.txt", l[2])
pathEqualsTo(t, "testdata/fileset/test.txt.gz", l[3])
l, err = testdata.ReadDirRecursiveFiltered(FilterOutPrefixes("sub"), FilterOutSuffixes("3"))
require.NoError(t, err)
l.Sort()
require.Len(t, l, 12)
pathEqualsTo(t, "testdata/fileset/anotherFile", l[0])
pathEqualsTo(t, "testdata/fileset/file", l[1])
pathEqualsTo(t, "testdata/fileset/folder", l[2])
pathEqualsTo(t, "testdata/fileset/folder/.hidden", l[3])
pathEqualsTo(t, "testdata/fileset/folder/file2", l[4])
pathEqualsTo(t, "testdata/fileset/folder/subfolder", l[5]) // <- subfolder skipped by Prefix("sub")
pathEqualsTo(t, "testdata/fileset/symlinktofolder", l[6])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/.hidden", l[7])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/file2", l[8])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/subfolder", l[9]) // <- subfolder skipped by Prefix("sub")
pathEqualsTo(t, "testdata/fileset/test.txt", l[10])
pathEqualsTo(t, "testdata/fileset/test.txt.gz", l[11])
l, err = testdata.ReadDirRecursiveFiltered(FilterOutPrefixes("sub"), AndFilter(FilterOutSuffixes("3"), FilterOutPrefixes("fil")))
require.NoError(t, err)
l.Sort()
require.Len(t, l, 9)
pathEqualsTo(t, "testdata/fileset/anotherFile", l[0])
pathEqualsTo(t, "testdata/fileset/folder", l[1])
pathEqualsTo(t, "testdata/fileset/folder/.hidden", l[2])
pathEqualsTo(t, "testdata/fileset/folder/subfolder", l[3])
pathEqualsTo(t, "testdata/fileset/symlinktofolder", l[4])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/.hidden", l[5])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/subfolder", l[6])
pathEqualsTo(t, "testdata/fileset/test.txt", l[7])
pathEqualsTo(t, "testdata/fileset/test.txt.gz", l[8])
l, err = testdata.ReadDirRecursiveFiltered(FilterOutPrefixes("sub"), AndFilter(FilterOutSuffixes("3"), FilterOutPrefixes("fil"), FilterOutSuffixes(".gz")))
require.NoError(t, err)
l.Sort()
require.Len(t, l, 8)
pathEqualsTo(t, "testdata/fileset/anotherFile", l[0])
pathEqualsTo(t, "testdata/fileset/folder", l[1])
pathEqualsTo(t, "testdata/fileset/folder/.hidden", l[2])
pathEqualsTo(t, "testdata/fileset/folder/subfolder", l[3])
pathEqualsTo(t, "testdata/fileset/symlinktofolder", l[4])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/.hidden", l[5])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/subfolder", l[6])
pathEqualsTo(t, "testdata/fileset/test.txt", l[7])
l, err = testdata.ReadDirRecursiveFiltered(OrFilter(FilterPrefixes("sub"), FilterSuffixes("tofolder")))
require.NoError(t, err)
l.Sort()
require.Len(t, l, 11)
pathEqualsTo(t, "testdata/fileset/anotherFile", l[0])
pathEqualsTo(t, "testdata/fileset/file", l[1])
pathEqualsTo(t, "testdata/fileset/folder", l[2])
pathEqualsTo(t, "testdata/fileset/symlinktofolder", l[3])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/.hidden", l[4])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/file2", l[5])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/file3", l[6])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/subfolder", l[7])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/subfolder/file4", l[8])
pathEqualsTo(t, "testdata/fileset/test.txt", l[9])
pathEqualsTo(t, "testdata/fileset/test.txt.gz", l[10])
l, err = testdata.ReadDirRecursiveFiltered(nil, FilterNames("folder"))
require.NoError(t, err)
l.Sort()
require.Len(t, l, 1)
pathEqualsTo(t, "testdata/fileset/folder", l[0])
l, err = testdata.ReadDirRecursiveFiltered(FilterNames("symlinktofolder"), FilterOutNames(".hidden"))
require.NoError(t, err)
require.Len(t, l, 9)
l.Sort()
pathEqualsTo(t, "testdata/fileset/anotherFile", l[0])
pathEqualsTo(t, "testdata/fileset/file", l[1])
pathEqualsTo(t, "testdata/fileset/folder", l[2])
pathEqualsTo(t, "testdata/fileset/symlinktofolder", l[3])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/file2", l[4])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/file3", l[5])
pathEqualsTo(t, "testdata/fileset/symlinktofolder/subfolder", l[6])
pathEqualsTo(t, "testdata/fileset/test.txt", l[7])
pathEqualsTo(t, "testdata/fileset/test.txt.gz", l[8])
}
func TestReadDirRecursiveLoopDetection(t *testing.T) {
loopsPath := New("testdata", "loops")
unbuondedReaddir := func(testdir string) (PathList, error) {
var files PathList
var err error
done := make(chan bool)
go func() {
files, err = loopsPath.Join(testdir).ReadDirRecursive()
done <- true
}()
require.Eventually(
t,
func() bool {
select {
case <-done:
return true
default:
return false
}
},
5*time.Second,
10*time.Millisecond,
"Infinite symlink loop while loading sketch",
)
return files, err
}
for _, dir := range []string{"loop_1", "loop_2", "loop_3", "loop_4"} {
l, err := unbuondedReaddir(dir)
require.EqualError(t, err, "directories symlink loop detected", "loop not detected in %s", dir)
require.Nil(t, l)
}
{
l, err := unbuondedReaddir("regular_1")
require.NoError(t, err)
require.Len(t, l, 4)
l.Sort()
pathEqualsTo(t, "testdata/loops/regular_1/dir1", l[0])
pathEqualsTo(t, "testdata/loops/regular_1/dir1/file1", l[1])
pathEqualsTo(t, "testdata/loops/regular_1/dir2", l[2])
pathEqualsTo(t, "testdata/loops/regular_1/dir2/file1", l[3])
}
{
l, err := unbuondedReaddir("regular_2")
require.NoError(t, err)
require.Len(t, l, 6)
l.Sort()
pathEqualsTo(t, "testdata/loops/regular_2/dir1", l[0])
pathEqualsTo(t, "testdata/loops/regular_2/dir1/file1", l[1])
pathEqualsTo(t, "testdata/loops/regular_2/dir2", l[2])
pathEqualsTo(t, "testdata/loops/regular_2/dir2/dir1", l[3])
pathEqualsTo(t, "testdata/loops/regular_2/dir2/dir1/file1", l[4])
pathEqualsTo(t, "testdata/loops/regular_2/dir2/file2", l[5])
}
{
l, err := unbuondedReaddir("regular_3")
require.NoError(t, err)
require.Len(t, l, 7)
l.Sort()
pathEqualsTo(t, "testdata/loops/regular_3/dir1", l[0])
pathEqualsTo(t, "testdata/loops/regular_3/dir1/file1", l[1])
pathEqualsTo(t, "testdata/loops/regular_3/dir2", l[2])
pathEqualsTo(t, "testdata/loops/regular_3/dir2/dir1", l[3])
pathEqualsTo(t, "testdata/loops/regular_3/dir2/dir1/file1", l[4])
pathEqualsTo(t, "testdata/loops/regular_3/dir2/file2", l[5])
pathEqualsTo(t, "testdata/loops/regular_3/link", l[6]) // broken symlink is reported in files
}
if runtime.GOOS != "windows" {
dir1 := loopsPath.Join("regular_4_with_permission_error", "dir1")
l, err := unbuondedReaddir("regular_4_with_permission_error")
require.NoError(t, err)
require.NotEmpty(t, l)
dir1Stat, err := dir1.Stat()
require.NoError(t, err)
err = dir1.Chmod(fs.FileMode(0)) // Enforce permission error
require.NoError(t, err)
t.Cleanup(func() {
// Restore normal permission after the test
dir1.Chmod(dir1Stat.Mode())
})
l, err = unbuondedReaddir("regular_4_with_permission_error")
require.Error(t, err)
require.Nil(t, l)
}
}