mirror of
https://github.com/project-zot/zot.git
synced 2026-06-18 05:28:07 +08:00
dfb5d1df54
* fix: make config read/write thread safe and fix some other similar issues 1. The config config has a lock, and safe methods to update and read the attributes 2. The config has methods to retrieve copies of specific attributes, such as the extyensions config, the auth config, and the authz config. These are needed, as the config object may mutate in the middle of an auth/authz requests, and we avoid partial configuration being applied for that request. 3. Fix an issue with the monitoring server not stopping when the controller is shut down. 4. Fix an issue with the HTPasswdWatcher not stopping when the background tasks are supposed to finish. 5. Fix some tests using hardcoded ports. Moved some of the methods which were on the main config to the auth, access control and extension configs Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>
201 lines
6.0 KiB
Go
201 lines
6.0 KiB
Go
package common_test
|
|
|
|
import (
|
|
"os"
|
|
"path"
|
|
"testing"
|
|
"time"
|
|
|
|
. "github.com/smartystreets/goconvey/convey"
|
|
|
|
"zotregistry.dev/zot/v2/pkg/api"
|
|
"zotregistry.dev/zot/v2/pkg/api/config"
|
|
tcommon "zotregistry.dev/zot/v2/pkg/test/common"
|
|
)
|
|
|
|
func TestWaitTillTrivyDBDownloadStarted(t *testing.T) {
|
|
Convey("finishes successfully", t, func() {
|
|
tempDir := t.TempDir()
|
|
go func() {
|
|
tcommon.WaitTillTrivyDBDownloadStarted(tempDir)
|
|
}()
|
|
|
|
time.Sleep(tcommon.SleepTime)
|
|
|
|
_, err := os.Create(path.Join(tempDir, "trivy.db"))
|
|
So(err, ShouldBeNil)
|
|
})
|
|
}
|
|
|
|
func TestControllerManager(t *testing.T) {
|
|
Convey("Test StartServer Init() panic", t, func() {
|
|
port := tcommon.GetFreePort()
|
|
|
|
conf := config.New()
|
|
conf.HTTP.Port = port
|
|
|
|
ctlr := api.NewController(conf)
|
|
ctlrManager := tcommon.NewControllerManager(ctlr)
|
|
|
|
// No storage configured
|
|
So(func() { ctlrManager.StartServer() }, ShouldPanic)
|
|
})
|
|
|
|
Convey("Test RunServer panic", t, func() {
|
|
tempDir := t.TempDir()
|
|
|
|
// Invalid port
|
|
conf := config.New()
|
|
conf.HTTP.Port = "999999"
|
|
conf.Storage.RootDirectory = tempDir
|
|
|
|
ctlr := api.NewController(conf)
|
|
ctlrManager := tcommon.NewControllerManager(ctlr)
|
|
|
|
err := ctlr.Init()
|
|
So(err, ShouldBeNil)
|
|
|
|
So(func() { ctlrManager.RunServer() }, ShouldPanic)
|
|
})
|
|
}
|
|
|
|
func TestWaitForLogMessages(t *testing.T) {
|
|
Convey("Test WaitForLogMessages", t, func() {
|
|
Convey("should return true when message count reaches minimum", func() {
|
|
logBuffer := tcommon.NewThreadSafeLogBuffer()
|
|
|
|
// Write some log messages
|
|
_, _ = logBuffer.Write([]byte("Starting server\n"))
|
|
_, _ = logBuffer.Write([]byte("Server started successfully\n"))
|
|
_, _ = logBuffer.Write([]byte("Starting server\n"))
|
|
_, _ = logBuffer.Write([]byte("Processing request\n"))
|
|
_, _ = logBuffer.Write([]byte("Starting server\n"))
|
|
|
|
// Wait for "Starting server" message to appear at least 3 times
|
|
result := tcommon.WaitForLogMessages(logBuffer, "Starting server", 3, 100*time.Millisecond)
|
|
|
|
So(result, ShouldBeTrue)
|
|
})
|
|
|
|
Convey("should return false when message count never reaches minimum", func() {
|
|
logBuffer := tcommon.NewThreadSafeLogBuffer()
|
|
|
|
// Write some log messages (only 1 occurrence of target message)
|
|
_, _ = logBuffer.Write([]byte("Starting server\n"))
|
|
_, _ = logBuffer.Write([]byte("Server started successfully\n"))
|
|
_, _ = logBuffer.Write([]byte("Processing request\n"))
|
|
|
|
// Wait for "Starting server" message to appear at least 3 times
|
|
result := tcommon.WaitForLogMessages(logBuffer, "Starting server", 3, 50*time.Millisecond)
|
|
|
|
So(result, ShouldBeFalse)
|
|
})
|
|
|
|
Convey("should return true immediately when count already meets requirement", func() {
|
|
logBuffer := tcommon.NewThreadSafeLogBuffer()
|
|
|
|
// Write messages before calling WaitForLogMessages
|
|
_, _ = logBuffer.Write([]byte("Starting server\n"))
|
|
_, _ = logBuffer.Write([]byte("Starting server\n"))
|
|
_, _ = logBuffer.Write([]byte("Starting server\n"))
|
|
|
|
// Wait for "Starting server" message to appear at least 3 times
|
|
result := tcommon.WaitForLogMessages(logBuffer, "Starting server", 3, 100*time.Millisecond)
|
|
|
|
So(result, ShouldBeTrue)
|
|
})
|
|
|
|
Convey("should handle empty log buffer", func() {
|
|
logBuffer := tcommon.NewThreadSafeLogBuffer()
|
|
|
|
// Wait for any message in empty buffer
|
|
result := tcommon.WaitForLogMessages(logBuffer, "Starting server", 1, 50*time.Millisecond)
|
|
|
|
So(result, ShouldBeFalse)
|
|
})
|
|
|
|
Convey("should handle partial message matches", func() {
|
|
logBuffer := tcommon.NewThreadSafeLogBuffer()
|
|
|
|
// Write messages with partial matches
|
|
_, _ = logBuffer.Write([]byte("Starting server process\n"))
|
|
_, _ = logBuffer.Write([]byte("Starting server\n"))
|
|
_, _ = logBuffer.Write([]byte("Starting server instance\n"))
|
|
|
|
// Wait for exact "Starting server" message (not partial matches)
|
|
result := tcommon.WaitForLogMessages(logBuffer, "Starting server", 2, 100*time.Millisecond)
|
|
|
|
So(result, ShouldBeTrue)
|
|
})
|
|
|
|
Convey("should timeout after specified duration", func() {
|
|
logBuffer := tcommon.NewThreadSafeLogBuffer()
|
|
|
|
// Write only one message
|
|
_, _ = logBuffer.Write([]byte("Starting server\n"))
|
|
|
|
// Wait for 3 occurrences with short timeout
|
|
start := time.Now()
|
|
result := tcommon.WaitForLogMessages(logBuffer, "Starting server", 3, 10*time.Millisecond)
|
|
duration := time.Since(start)
|
|
|
|
So(result, ShouldBeFalse)
|
|
So(duration, ShouldBeGreaterThanOrEqualTo, 10*time.Millisecond)
|
|
So(duration, ShouldBeLessThan, 50*time.Millisecond) // Should timeout quickly
|
|
})
|
|
|
|
Convey("should handle concurrent writes", func() {
|
|
logBuffer := tcommon.NewThreadSafeLogBuffer()
|
|
|
|
// Simulate concurrent writes
|
|
go func() {
|
|
for i := 0; i < 5; i++ {
|
|
_, _ = logBuffer.Write([]byte("Starting server\n"))
|
|
|
|
time.Sleep(5 * time.Millisecond)
|
|
}
|
|
}()
|
|
|
|
// Wait for messages to appear
|
|
result := tcommon.WaitForLogMessages(logBuffer, "Starting server", 3, 100*time.Millisecond)
|
|
|
|
So(result, ShouldBeTrue)
|
|
})
|
|
|
|
Convey("should handle case-sensitive message matching", func() {
|
|
logBuffer := tcommon.NewThreadSafeLogBuffer()
|
|
|
|
// Write messages with different cases
|
|
_, _ = logBuffer.Write([]byte("Starting server\n"))
|
|
_, _ = logBuffer.Write([]byte("starting server\n"))
|
|
_, _ = logBuffer.Write([]byte("STARTING SERVER\n"))
|
|
|
|
// Wait for exact case match
|
|
result := tcommon.WaitForLogMessages(logBuffer, "Starting server", 2, 100*time.Millisecond)
|
|
|
|
So(result, ShouldBeFalse) // Only 1 exact match
|
|
})
|
|
|
|
Convey("should handle zero minimum count", func() {
|
|
logBuffer := tcommon.NewThreadSafeLogBuffer()
|
|
|
|
// Wait for 0 occurrences (should always return true)
|
|
result := tcommon.WaitForLogMessages(logBuffer, "Starting server", 0, 100*time.Millisecond)
|
|
|
|
So(result, ShouldBeTrue)
|
|
})
|
|
|
|
Convey("should handle very short timeout", func() {
|
|
logBuffer := tcommon.NewThreadSafeLogBuffer()
|
|
|
|
// Write a message
|
|
_, _ = logBuffer.Write([]byte("Starting server\n"))
|
|
|
|
// Wait with very short timeout
|
|
result := tcommon.WaitForLogMessages(logBuffer, "Starting server", 1, 1*time.Millisecond)
|
|
|
|
So(result, ShouldBeTrue) // Should find it immediately
|
|
})
|
|
})
|
|
}
|