summaryrefslogtreecommitdiff
path: root/integrationtests/dgrep_literal_info_test.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-07-22 23:51:28 +0300
committerPaul Buetow <paul@buetow.org>2026-07-22 23:51:28 +0300
commitbc2767c87c4090798c4c7d15e101ed066e947301 (patch)
tree0f47a2e0b159a617eb56509bbca1c998196453c4 /integrationtests/dgrep_literal_info_test.go
parent849951be1d1a7ee9f9302006ccb187bf5b4e36f3 (diff)
test: DTail fork — integration test suite and fixtures
Squashed development of the integration test suite (integrationtests/) covering DCat, DGrep, DMap (serverless + server mode), DTail follow, DServer, DTailHealth, journal source reads, auth-key fast reconnect, interactive query reload, client-deadline/timeout behaviour, and the single-mode read/output path. Includes real test fixtures (dserver*.cfg, dmap_csv_multifile_*.csv.in, test_server_*.json, *.expected golden files) and deterministic synchronization helpers (waitContains-style barriers) replacing racy fixed-timing assertions. Accidental debug/output dumps that earlier commits added here (captured client output, strace logs, ad-hoc turbo_test_output/manual_output/test_output files, throwaway debug scripts) are intentionally excluded and gitignored. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diffstat (limited to 'integrationtests/dgrep_literal_info_test.go')
-rw-r--r--integrationtests/dgrep_literal_info_test.go191
1 files changed, 191 insertions, 0 deletions
diff --git a/integrationtests/dgrep_literal_info_test.go b/integrationtests/dgrep_literal_info_test.go
new file mode 100644
index 0000000..cc66c9d
--- /dev/null
+++ b/integrationtests/dgrep_literal_info_test.go
@@ -0,0 +1,191 @@
+package integrationtests
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "strings"
+ "sync"
+ "testing"
+ "time"
+
+ "github.com/mimecast/dtail/internal/config"
+)
+
+// TestDGrepLiteralModeInfo verifies that the server logs info message when using literal mode
+func TestDGrepLiteralModeInfo(t *testing.T) {
+ if !config.Env("DTAIL_INTEGRATION_TEST_RUN_MODE") {
+ t.Log("Skipping")
+ return
+ }
+
+ cleanupTmpFiles(t)
+ testLogger := NewTestLogger("TestDGrepLiteralModeInfo")
+ defer testLogger.WriteLogFile()
+
+ // Create test data
+ testData := `ERROR test line 1
+WARNING test line 2
+ERROR test line 3
+INFO test line 4
+ERROR test line 5
+`
+ testFile := "literal_info_test.log.tmp"
+ if err := os.WriteFile(testFile, []byte(testData), 0644); err != nil {
+ t.Fatal("Failed to create test file:", err)
+ }
+ defer os.Remove(testFile)
+
+ // Test patterns - both literal and regex
+ tests := []struct {
+ name string
+ pattern string
+ expectLiteral bool
+ expectedCount int
+ }{
+ {
+ name: "SimpleLiteral",
+ pattern: "ERROR",
+ expectLiteral: true,
+ expectedCount: 3,
+ },
+ {
+ name: "LiteralWithSpace",
+ pattern: "ERROR test",
+ expectLiteral: true,
+ expectedCount: 3,
+ },
+ {
+ name: "RegexPattern",
+ pattern: "ERROR.*line [0-9]",
+ expectLiteral: false,
+ expectedCount: 3,
+ },
+ {
+ name: "RegexAlternation",
+ pattern: "(ERROR|WARNING)",
+ expectLiteral: false,
+ expectedCount: 4,
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ port := getUniquePortNumber()
+ bindAddress := "localhost"
+
+ ctx, cancel := context.WithCancel(context.Background())
+ ctx = WithTestLogger(ctx, testLogger)
+ defer cancel()
+
+ // Start dserver with info log level to capture our message
+ stdoutCh, stderrCh, _, err := startCommand(ctx, t,
+ "", "../dserver",
+ "--cfg", "none",
+ "--logger", "stdout",
+ "--logLevel", "info", // Changed from error to info
+ "--bindAddress", bindAddress,
+ "--port", fmt.Sprintf("%d", port),
+ )
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ // Capture server output
+ var serverOutput strings.Builder
+ var outputMutex sync.Mutex
+ outputDone := make(chan struct{})
+
+ go func() {
+ defer close(outputDone)
+ for {
+ select {
+ case line := <-stdoutCh:
+ outputMutex.Lock()
+ serverOutput.WriteString(line)
+ serverOutput.WriteString("\n")
+ outputMutex.Unlock()
+ case line := <-stderrCh:
+ outputMutex.Lock()
+ serverOutput.WriteString(line)
+ serverOutput.WriteString("\n")
+ outputMutex.Unlock()
+ case <-ctx.Done():
+ return
+ }
+ }
+ }()
+
+ if err := waitForServerReady(ctx, bindAddress, port); err != nil {
+ t.Error(err)
+ return
+ }
+
+ // Run dgrep
+ outFile := fmt.Sprintf("dgrep_info_%s.stdout.tmp", test.name)
+ defer os.Remove(outFile)
+
+ err = runCommandUntilValid(ctx, t, 5, 200*time.Millisecond, outFile, "../dgrep", func() error {
+ content, readErr := os.ReadFile(outFile)
+ if readErr != nil {
+ return fmt.Errorf("failed to read output file: %w", readErr)
+ }
+
+ lines := strings.Split(strings.TrimSpace(string(content)), "\n")
+ actualCount := 0
+ for _, line := range lines {
+ if line != "" {
+ actualCount++
+ }
+ }
+
+ if actualCount != test.expectedCount {
+ return fmt.Errorf("pattern %q: expected %d matches, got %d", test.pattern, test.expectedCount, actualCount)
+ }
+ return nil
+ },
+ "--plain",
+ "--cfg", "none",
+ "--grep", test.pattern,
+ "--servers", fmt.Sprintf("%s:%d", bindAddress, port),
+ "--trustAllHosts",
+ "--noColor",
+ "--files", testFile)
+
+ if err != nil {
+ t.Errorf("Failed to run dgrep with pattern '%s': %v", test.pattern, err)
+ return
+ }
+
+ // Give time for server output to be captured
+ time.Sleep(500 * time.Millisecond)
+
+ // Stop server
+ cancel()
+
+ // Wait for output capture goroutine to finish
+ select {
+ case <-outputDone:
+ case <-time.After(2 * time.Second):
+ t.Log("Warning: output capture goroutine did not finish in time")
+ }
+
+ // Check server output for literal mode message
+ outputMutex.Lock()
+ serverLog := serverOutput.String()
+ outputMutex.Unlock()
+ // The server uses structured logging, so the message appears as "pattern:|<pattern>"
+ literalMsg := fmt.Sprintf("Using optimized literal string matching for pattern:|%s", test.pattern)
+ containsLiteralMsg := strings.Contains(serverLog, literalMsg)
+
+ if test.expectLiteral && !containsLiteralMsg {
+ t.Errorf("Expected literal mode info message for pattern '%s' but didn't find it", test.pattern)
+ t.Logf("Server output:\n%s", serverLog)
+ } else if !test.expectLiteral && containsLiteralMsg {
+ t.Errorf("Did not expect literal mode info message for pattern '%s' but found it", test.pattern)
+ t.Logf("Server output:\n%s", serverLog)
+ }
+ })
+ }
+}