summaryrefslogtreecommitdiff
path: root/internal/service/file_watcher_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/service/file_watcher_test.go')
-rw-r--r--internal/service/file_watcher_test.go211
1 files changed, 211 insertions, 0 deletions
diff --git a/internal/service/file_watcher_test.go b/internal/service/file_watcher_test.go
new file mode 100644
index 000000000..f4dce095f
--- /dev/null
+++ b/internal/service/file_watcher_test.go
@@ -0,0 +1,211 @@
+package service
+
+import (
+ "context"
+ "os"
+ "path/filepath"
+ "regexp"
+ "testing"
+ "time"
+
+ "github.com/sirupsen/logrus"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+
+ "github.com/authelia/authelia/v4/internal/authentication"
+ "github.com/authelia/authelia/v4/internal/configuration/schema"
+ "github.com/authelia/authelia/v4/internal/logging"
+ "github.com/authelia/authelia/v4/internal/middlewares"
+ "github.com/authelia/authelia/v4/internal/templates"
+)
+
+func TestProvisionUsersFileWatcher(t *testing.T) {
+ dir := t.TempDir()
+
+ f, err := os.Create(filepath.Join(dir, "users.yml"))
+ require.NoError(t, err)
+ require.NoError(t, f.Close())
+
+ tx, err := templates.New(templates.Config{})
+ require.NoError(t, err)
+
+ address, err := schema.NewAddress("tcp://:9091")
+ require.NoError(t, err)
+
+ config := &schema.Configuration{
+ Server: schema.Server{
+ Address: &schema.AddressTCP{Address: *address},
+ },
+ }
+
+ provision := ProvisionUsersFileWatcher
+
+ ctx := &testCtx{
+ Context: context.Background(),
+ Configuration: config,
+ Providers: middlewares.Providers{
+ Templates: tx,
+ },
+ Logger: logrus.NewEntry(logging.Logger()),
+ }
+
+ watcher, err := provision(ctx)
+ assert.NoError(t, err)
+ assert.Nil(t, watcher)
+
+ watcher, err = provision(ctx)
+ assert.NoError(t, err)
+ assert.Nil(t, watcher)
+
+ config.AuthenticationBackend.File = &schema.AuthenticationBackendFile{
+ Path: filepath.Join(dir, "users.yml"),
+ Watch: true,
+ }
+
+ watcher, err = provision(ctx)
+ assert.EqualError(t, err, "error occurred asserting user provider")
+ assert.Nil(t, watcher)
+
+ ctx.Providers.UserProvider = authentication.NewFileUserProvider(config.AuthenticationBackend.File)
+
+ config.AuthenticationBackend.File = &schema.AuthenticationBackendFile{
+ Watch: true,
+ }
+
+ watcher, err = provision(ctx)
+ assert.EqualError(t, err, "error initializing file watcher: path must be specified")
+ assert.Nil(t, watcher)
+
+ config.AuthenticationBackend.File = &schema.AuthenticationBackendFile{
+ Path: filepath.Join(dir, "users.yml"),
+ Watch: true,
+ }
+
+ watcher, err = provision(ctx)
+ assert.NoError(t, err)
+ assert.NotNil(t, watcher)
+ assert.NotNil(t, watcher.Log())
+ assert.Equal(t, "users", watcher.ServiceName())
+ assert.Equal(t, "watcher", watcher.ServiceType())
+
+ watcher.Shutdown()
+}
+
+func TestNewFileWatcher(t *testing.T) {
+ dir := t.TempDir()
+
+ reloader := &testReloader{reload: true}
+
+ f, err := os.Create(filepath.Join(dir, "test.log"))
+ require.NoError(t, err)
+
+ service, err := NewFileWatcher("example", filepath.Join(dir, "test.log"), reloader, logrus.NewEntry(logging.Logger()))
+
+ assert.NoError(t, err)
+
+ go func() {
+ require.NoError(t, service.Run())
+ }()
+
+ // Give the service a moment to start.
+ time.Sleep(100 * time.Millisecond)
+
+ _, err = f.Write([]byte("test"))
+ require.NoError(t, err)
+
+ require.NoError(t, f.Close())
+
+ time.Sleep(time.Second)
+
+ assert.Equal(t, 1, reloader.count)
+
+ assert.NoError(t, os.WriteFile(filepath.Join(dir, "test2.log"), []byte("test"), 0600))
+
+ assert.Equal(t, 1, reloader.count)
+
+ assert.NoError(t, os.Remove(filepath.Join(dir, "test2.log")))
+
+ assert.Equal(t, 1, reloader.count)
+
+ service.Shutdown()
+}
+
+func TestNewFileWatcherDirectory(t *testing.T) {
+ dir := t.TempDir()
+
+ reloader := &testReloader{reload: true}
+
+ service, err := NewFileWatcher("example", dir, reloader, logrus.NewEntry(logging.Logger()))
+
+ assert.NoError(t, err)
+
+ go func() {
+ require.NoError(t, service.Run())
+ }()
+
+ // Give the service a moment to start.
+ time.Sleep(100 * time.Millisecond)
+
+ f, err := os.Create(filepath.Join(dir, "test.log"))
+ require.NoError(t, err)
+
+ _, err = f.Write([]byte("test"))
+ require.NoError(t, err)
+
+ require.NoError(t, f.Close())
+
+ time.Sleep(time.Second)
+
+ assert.Equal(t, 2, reloader.count)
+
+ service.Shutdown()
+}
+
+func TestNewFileWatcherBadPath(t *testing.T) {
+ dir := t.TempDir()
+
+ reloader := &testReloader{reload: true}
+
+ service, err := NewFileWatcher("example", filepath.Join(dir, "test.log"), reloader, logrus.NewEntry(logging.Logger()))
+
+ require.Error(t, err)
+ assert.Regexp(t, regexp.MustCompile(`^error initializing file watcher: error stating file '/tmp/[^/]+/\d+/test.log': file does not exist$`), err.Error())
+
+ assert.Nil(t, service)
+}
+
+func TestNewFileWatcherBadPermission(t *testing.T) {
+ dir := t.TempDir()
+
+ reloader := &testReloader{reload: true}
+
+ require.NoError(t, os.Mkdir(filepath.Join(dir, "tmp"), 0700))
+
+ f, err := os.Create(filepath.Join(dir, "tmp", "test.log"))
+
+ require.NoError(t, err)
+ require.NoError(t, f.Close())
+
+ require.NoError(t, os.Chmod(filepath.Join(dir, "tmp"), 0o000))
+
+ service, err := NewFileWatcher("example", filepath.Join(dir, "tmp", "test.log"), reloader, logrus.NewEntry(logging.Logger()))
+
+ require.Error(t, err)
+ assert.Regexp(t, regexp.MustCompile(`^error initializing file watcher: error stating file '/tmp/[^/]+/\d+/tmp/test.log': permission denied trying to read the file$`), err.Error())
+
+ require.NoError(t, os.Chmod(filepath.Join(dir, "tmp"), 0o700))
+
+ assert.Nil(t, service)
+}
+
+type testReloader struct {
+ count int
+ reload bool
+ err error
+}
+
+func (r *testReloader) Reload() (bool, error) {
+ r.count++
+
+ return r.reload, r.err
+}