Repository: moby/moby
File: daemon/logger/fluentd/fluentd_test.go (Go)

Code before:

	validDurations := map[string]time.Duration{
		"100ms": 100 * time.Millisecond,
		"10s":   10 * time.Second,
		"":      0,
	}
	for k, v := range validDurations {
		t.Run("valid "+k, func(t *testing.T) {
			err := ValidateLogOpt(map[string]string{writeTimeoutKey: k})
			assert.NilError(t, err)
			// Ignore err here since that's already checked in the ValidateLogOpt error check.
			cfg, _ := parseConfig(map[string]string{writeTimeoutKey: k})
			assert.Equal(t, cfg.WriteTimeout, v)
		})
	}
}

// TestWriteTimeoutIsEffective tests that writes timeout when the server is unresponsive.
// The test ensures that instead of hanging forever, the fluentd write operation returns
// an error when writes cannot be completed within the specified duration.
func TestWriteTimeoutIsEffective(t *testing.T) {
	if runtime.GOOS == "windows" {
		t.Skip("windows not supported")
	}

	socketFile := "/tmp/fluent-logger-golang.sock"
	l, err := net.Listen("unix", socketFile)
	assert.NilError(t, err, "unable to create listener for socket %s", socketFile)
	defer l.Close()

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	var connectedWG sync.WaitGroup
	connectedWG.Add(1)

	// Start accepting connections.
	go func(ctx context.Context, wg *sync.WaitGroup) {
		wg.Done()

		for {
			conn, err := l.Accept()
			if err != nil {
				// Unable to process the connection. This can happen if the connection is closed.
				select {
				case <-ctx.Done():
					// If the context is canceled, there's nothing for us to do here.
					return
				default:
					t.Logf("Unable to accept connection: %v", err)
					continue

Review comment (suggestion):
Perhaps we should use `t.TempDir()` for the path to make sure we have a location that exists and is cleaned up;

```go
tmpDir := t.TempDir()
socketFile := filepath.Join(tmpDir, "fluent-logger-golang.sock")
```

Code after:
	}

	validDurations := map[string]time.Duration{
		"100ms": 100 * time.Millisecond,
		"10s":   10 * time.Second,
		"":      0,
	}
	for k, v := range validDurations {
		t.Run("valid "+k, func(t *testing.T) {
			err := ValidateLogOpt(map[string]string{writeTimeoutKey: k})
			assert.NilError(t, err)
			cfg, err := parseConfig(map[string]string{writeTimeoutKey: k})
			// This check is mostly redundant since it's checked in ValidateLogOpt as well.
			// This is here to guard against potential regressions in the future.
			assert.NilError(t, err)
			assert.Equal(t, cfg.WriteTimeout, v)
		})
	}
}

// TestWriteTimeoutIsEffective tests that writes timeout when the server is unresponsive.
// The test ensures that instead of hanging forever, the fluentd write operation returns
// an error when writes cannot be completed within the specified duration.
func TestWriteTimeoutIsEffective(t *testing.T) {
	if runtime.GOOS == "windows" {
		t.Skip("windows not supported")
	}

	// Create a temporary directory for the socket file
	tmpDir := t.TempDir()
	socketFile := filepath.Join(tmpDir, "fluent-logger-golang.sock")
	l, err := net.Listen("unix", socketFile)
	assert.NilError(t, err, "unable to create listener for socket %s", socketFile)
	defer l.Close()

	// This is to guard against potential run-away test scenario so that a future change
	// doesn't cause the tests suite to timeout. It "fluentd-write-timeout" is not set, this
	// test will be blocked on the socket write operation. The timeout guards against that.
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	var connectedWG sync.WaitGroup
	connectedWG.Add(1)

	// Start accepting connections.
	go func(ctx context.Context, wg *sync.WaitGroup) {
		wg.Done()

		for {
			conn, err := l.Accept()
			if err != nil {