mirror of
https://github.com/roddhjav/apparmor.d.git
synced 2024-12-27 23:48:00 +01:00
344 lines
13 KiB
Go
344 lines
13 KiB
Go
|
/*
|
||
|
* 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)
|
||
|
}
|
||
|
}
|