task_recovery_test.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. package nginx_log
  2. import (
  3. "sync/atomic"
  4. "testing"
  5. "time"
  6. "github.com/0xJacky/Nginx-UI/internal/nginx_log/indexer"
  7. )
  8. // TestTaskRecoveryGlobalStatusManagement tests the global status management in task recovery
  9. func TestTaskRecoveryGlobalStatusManagement(t *testing.T) {
  10. // Create a mock task recovery instance
  11. tr := &TaskRecovery{
  12. activeTasks: 0,
  13. }
  14. // Test initial state
  15. if atomic.LoadInt32(&tr.activeTasks) != 0 {
  16. t.Errorf("Expected initial active tasks to be 0, got %d", atomic.LoadInt32(&tr.activeTasks))
  17. }
  18. // Test incrementing active tasks
  19. firstTask := atomic.AddInt32(&tr.activeTasks, 1)
  20. if firstTask != 1 {
  21. t.Errorf("Expected first task counter to be 1, got %d", firstTask)
  22. }
  23. // Test adding more tasks
  24. secondTask := atomic.AddInt32(&tr.activeTasks, 1)
  25. if secondTask != 2 {
  26. t.Errorf("Expected second task counter to be 2, got %d", secondTask)
  27. }
  28. // Test decrementing tasks
  29. afterFirst := atomic.AddInt32(&tr.activeTasks, -1)
  30. if afterFirst != 1 {
  31. t.Errorf("Expected counter after completing first task to be 1, got %d", afterFirst)
  32. }
  33. // Test final task completion
  34. afterLast := atomic.AddInt32(&tr.activeTasks, -1)
  35. if afterLast != 0 {
  36. t.Errorf("Expected counter after completing last task to be 0, got %d", afterLast)
  37. }
  38. }
  39. // TestNeedsRecovery tests the logic for determining if a task needs recovery
  40. func TestNeedsRecovery(t *testing.T) {
  41. tr := &TaskRecovery{}
  42. testCases := []struct {
  43. name string
  44. log *NginxLogWithIndex
  45. expected bool
  46. }{
  47. {
  48. name: "Indexing status needs recovery",
  49. log: &NginxLogWithIndex{
  50. Path: "/test/access.log",
  51. IndexStatus: string(indexer.IndexStatusIndexing),
  52. },
  53. expected: true,
  54. },
  55. {
  56. name: "Queued status needs recovery",
  57. log: &NginxLogWithIndex{
  58. Path: "/test/access.log",
  59. IndexStatus: string(indexer.IndexStatusQueued),
  60. },
  61. expected: true,
  62. },
  63. {
  64. name: "Recent error needs recovery",
  65. log: &NginxLogWithIndex{
  66. Path: "/test/access.log",
  67. IndexStatus: string(indexer.IndexStatusError),
  68. LastIndexed: time.Now().Add(-30 * time.Minute).Unix(), // 30 minutes ago
  69. },
  70. expected: true,
  71. },
  72. {
  73. name: "Old error does not need recovery",
  74. log: &NginxLogWithIndex{
  75. Path: "/test/access.log",
  76. IndexStatus: string(indexer.IndexStatusError),
  77. LastIndexed: time.Now().Add(-2 * time.Hour).Unix(), // 2 hours ago
  78. },
  79. expected: false,
  80. },
  81. {
  82. name: "Indexed status does not need recovery",
  83. log: &NginxLogWithIndex{
  84. Path: "/test/access.log",
  85. IndexStatus: string(indexer.IndexStatusIndexed),
  86. },
  87. expected: false,
  88. },
  89. {
  90. name: "Not indexed status does not need recovery",
  91. log: &NginxLogWithIndex{
  92. Path: "/test/access.log",
  93. IndexStatus: string(indexer.IndexStatusNotIndexed),
  94. },
  95. expected: false,
  96. },
  97. }
  98. for _, tc := range testCases {
  99. t.Run(tc.name, func(t *testing.T) {
  100. result := tr.needsRecovery(tc.log)
  101. if result != tc.expected {
  102. t.Errorf("Expected needsRecovery to return %t, got %t for %s", tc.expected, result, tc.name)
  103. }
  104. })
  105. }
  106. }
  107. // TestTaskRecoveryProgressConfig tests that progress configuration is properly created
  108. func TestTaskRecoveryProgressConfig(t *testing.T) {
  109. // This test ensures that the progress config created in executeRecoveredTask
  110. // has the proper structure and callbacks
  111. progressCallbackCalled := false
  112. completionCallbackCalled := false
  113. // Create a mock progress config similar to what's created in executeRecoveredTask
  114. progressConfig := &indexer.ProgressConfig{
  115. NotifyInterval: 1 * time.Second,
  116. OnProgress: func(progress indexer.ProgressNotification) {
  117. progressCallbackCalled = true
  118. },
  119. OnCompletion: func(completion indexer.CompletionNotification) {
  120. completionCallbackCalled = true
  121. },
  122. }
  123. // Test that config is properly initialized
  124. if progressConfig.NotifyInterval != 1*time.Second {
  125. t.Errorf("Expected notify interval to be 1 second, got %v", progressConfig.NotifyInterval)
  126. }
  127. if progressConfig.OnProgress == nil {
  128. t.Error("Expected OnProgress callback to be set")
  129. }
  130. if progressConfig.OnCompletion == nil {
  131. t.Error("Expected OnCompletion callback to be set")
  132. }
  133. // Test callback execution
  134. if progressConfig.OnProgress != nil {
  135. progressConfig.OnProgress(indexer.ProgressNotification{})
  136. }
  137. if progressConfig.OnCompletion != nil {
  138. progressConfig.OnCompletion(indexer.CompletionNotification{})
  139. }
  140. if !progressCallbackCalled {
  141. t.Error("Progress callback was not called")
  142. }
  143. if !completionCallbackCalled {
  144. t.Error("Completion callback was not called")
  145. }
  146. }