complete_integration_test.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. package nginx_log
  2. import (
  3. "sync"
  4. "testing"
  5. "time"
  6. )
  7. // TestProgressTrackerIntegration tests the complete integration flow to ensure single completion notification
  8. func TestProgressTrackerIntegration(t *testing.T) {
  9. // Test scenario: simulating what happens in ForceReindexFileGroup
  10. mainLogPath := "/var/log/nginx/access.log"
  11. // Step 1: Get progress tracker (simulates what happens in IndexLogFileFull)
  12. progressTracker := GetProgressTracker(mainLogPath)
  13. // Step 2: Add files and set estimates (simulates discovery phase)
  14. files := []struct {
  15. path string
  16. compressed bool
  17. lines int64
  18. }{
  19. {"/var/log/nginx/access.log", false, 1000},
  20. {"/var/log/nginx/access.log.1", false, 800},
  21. {"/var/log/nginx/access.log.2.gz", true, 600},
  22. }
  23. for _, file := range files {
  24. progressTracker.AddFile(file.path, file.compressed)
  25. progressTracker.SetFileEstimate(file.path, file.lines)
  26. }
  27. // Step 3: Simulate concurrent file processing (like what happens in real indexing)
  28. var wg sync.WaitGroup
  29. // Simulate concurrent file processing
  30. for i, file := range files {
  31. wg.Add(1)
  32. go func(f struct {
  33. path string
  34. compressed bool
  35. lines int64
  36. }, index int) {
  37. defer wg.Done()
  38. // Simulate processing time variation
  39. time.Sleep(time.Duration(index*10) * time.Millisecond)
  40. // Start processing
  41. progressTracker.StartFile(f.path)
  42. // Simulate incremental progress
  43. for progress := int64(100); progress <= f.lines; progress += 100 {
  44. progressTracker.UpdateFileProgress(f.path, progress)
  45. time.Sleep(time.Millisecond) // Small delay to simulate work
  46. }
  47. // Complete the file
  48. progressTracker.CompleteFile(f.path, f.lines)
  49. t.Logf("File %s completed with %d lines", f.path, f.lines)
  50. }(file, i)
  51. }
  52. // Wait for all files to complete
  53. wg.Wait()
  54. // Give a small delay to ensure all notifications are processed
  55. time.Sleep(10 * time.Millisecond)
  56. // Verify final state
  57. percentage, stats := progressTracker.GetProgress()
  58. if percentage != 100 {
  59. t.Errorf("Expected 100%% progress, got %.2f%%", percentage)
  60. }
  61. if stats.CompletedFiles != 3 {
  62. t.Errorf("Expected 3 completed files, got %d", stats.CompletedFiles)
  63. }
  64. if !stats.IsCompleted {
  65. t.Errorf("Expected IsCompleted to be true")
  66. }
  67. if stats.ProcessedLines != 2400 {
  68. t.Errorf("Expected 2400 processed lines, got %d", stats.ProcessedLines)
  69. }
  70. // Clean up
  71. RemoveProgressTracker(mainLogPath)
  72. t.Logf("Integration test passed: Progress tracking completed successfully")
  73. }
  74. // TestProgressTrackerRaceCondition tests concurrent CompleteFile calls to ensure no race conditions
  75. func TestProgressTrackerRaceCondition(t *testing.T) {
  76. mainLogPath := "/var/log/nginx/test.log"
  77. progressTracker := GetProgressTracker(mainLogPath)
  78. // Add files
  79. files := []string{
  80. "/var/log/nginx/test.log",
  81. "/var/log/nginx/test.log.1",
  82. "/var/log/nginx/test.log.2",
  83. "/var/log/nginx/test.log.3",
  84. "/var/log/nginx/test.log.4",
  85. }
  86. for _, file := range files {
  87. progressTracker.AddFile(file, false)
  88. progressTracker.SetFileEstimate(file, 100)
  89. }
  90. var wg sync.WaitGroup
  91. // Simulate simultaneous completion of all files (stress test)
  92. for i, file := range files {
  93. wg.Add(1)
  94. go func(f string, index int) {
  95. defer wg.Done()
  96. progressTracker.StartFile(f)
  97. // Try to complete multiple times to test race conditions
  98. for j := 0; j < 3; j++ {
  99. progressTracker.CompleteFile(f, 100)
  100. time.Sleep(time.Microsecond)
  101. }
  102. }(file, i)
  103. }
  104. wg.Wait()
  105. // Should still only have completed state once
  106. percentage, stats := progressTracker.GetProgress()
  107. if percentage != 100 {
  108. t.Errorf("Expected 100%% progress, got %.2f%%", percentage)
  109. }
  110. if !stats.IsCompleted {
  111. t.Errorf("Expected IsCompleted to be true")
  112. }
  113. RemoveProgressTracker(mainLogPath)
  114. t.Logf("Race condition test passed")
  115. }