File size: 5,167 Bytes
442299c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package com.dalab.discovery.job.callable;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.UUID;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import com.dalab.discovery.catalog.service.ICatalogService;
import com.dalab.discovery.common.model.DiscoveryJob;
import com.dalab.discovery.common.model.enums.CloudProvider;
import com.dalab.discovery.log.service.ICheckpointService;
import com.dalab.discovery.log.service.ILogAnalyzer;
import com.dalab.discovery.log.service.ILogAnalyzerRegistry;

/**
 * Unit tests for LogAnalyzerCallable (Updated for Async).
 */
@ExtendWith(MockitoExtension.class)
public class LogAnalyzerCallableTest {

	@Mock
	private DiscoveryJob job;

	@Mock
	private ILogAnalyzerRegistry analyzerRegistry;

	@Mock
	private ICheckpointService checkpointService;

	@Mock
	private ICatalogService catalogService;

	@Mock
	private ILogAnalyzer logAnalyzer;

	private LogAnalyzerCallable callable;
	private final String accountId = "test-account-123";
	private final CloudProvider provider = CloudProvider.GCP;
	private final Instant lastCheckpoint = Instant.now().minusSeconds(3600); // 1 hour ago
	private final Instant currentCheckpoint = Instant.now();
	private final ZonedDateTime lastCheckpointZdt = lastCheckpoint.atZone(ZoneId.systemDefault());
	private final ZonedDateTime currentCheckpointZdt = currentCheckpoint.atZone(ZoneId.systemDefault());

	@BeforeEach
	void setUp() {
		callable = new LogAnalyzerCallable(job, analyzerRegistry, checkpointService, catalogService);

		// Common job setup
		when(job.getJobId()).thenReturn(UUID.randomUUID());
		when(job.getCloudProvider()).thenReturn(provider);
		when(job.getAccountId()).thenReturn(accountId);
	}

	@Test
	void testCallWithNoNewLogs() throws Exception {
		// Setup analyzer
		when(analyzerRegistry.getAnalyzer(provider)).thenReturn(logAnalyzer);

		// Setup checkpoint
		when(checkpointService.getLastCheckpoint(provider, accountId)).thenReturn(lastCheckpoint);

		// No new logs
		when(logAnalyzer.hasNewLogs(accountId, lastCheckpoint)).thenReturn(false);

		// Execute the callable
		boolean result = callable.call();

		// Verify results
		assertTrue(result, "Call should succeed even with no new logs");

		// Verify interactions
		verify(analyzerRegistry).getAnalyzer(provider);
		verify(checkpointService).getLastCheckpoint(provider, accountId);
		verify(logAnalyzer).hasNewLogs(accountId, lastCheckpoint);
		verify(logAnalyzer, never()).triggerLogAnalysisAsync(anyString(), any(ZonedDateTime.class),
				any(ZonedDateTime.class), isNull(ILogAnalyzer.AnalysisOptions.class));
		verifyNoMoreInteractions(logAnalyzer);
		verifyNoInteractions(catalogService);
	}

	@Test
	void testCallTriggersAsyncAnalysis() throws Exception {
		// Setup analyzer
		when(analyzerRegistry.getAnalyzer(provider)).thenReturn(logAnalyzer);

		// Setup checkpoint
		when(checkpointService.getLastCheckpoint(provider, accountId)).thenReturn(lastCheckpoint);

		// Has new logs
		when(logAnalyzer.hasNewLogs(accountId, lastCheckpoint)).thenReturn(true);

		// Expect the async method to be called (returns void)
		doNothing().when(logAnalyzer).triggerLogAnalysisAsync(eq(accountId),
				any(ZonedDateTime.class),
				any(ZonedDateTime.class),
				isNull(ILogAnalyzer.AnalysisOptions.class));

		// Expect checkpoint update
		when(checkpointService.updateCheckpoint(eq(provider), eq(accountId), any(Instant.class))).thenReturn(true);

		// Execute the callable
		boolean result = callable.call();

		// Verify results
		assertTrue(result, "Call should succeed when triggering async analysis");

		// Verify interactions in order
		verify(analyzerRegistry).getAnalyzer(provider);
		verify(checkpointService).getLastCheckpoint(provider, accountId);
		verify(logAnalyzer).hasNewLogs(accountId, lastCheckpoint);
		verify(logAnalyzer).triggerLogAnalysisAsync(eq(accountId),
				any(ZonedDateTime.class),
				any(ZonedDateTime.class),
				isNull(ILogAnalyzer.AnalysisOptions.class));
		verify(checkpointService).updateCheckpoint(eq(provider), eq(accountId), any(Instant.class));
		verifyNoInteractions(catalogService);
		verifyNoMoreInteractions(logAnalyzer);
	}

	@Test
	void testCallWithMissingProvider() {
		// Setup null provider
		when(job.getCloudProvider()).thenReturn(null);

		// Execute and verify exception
		assertThrows(IllegalArgumentException.class, () -> callable.call());
	}

	@Test
	void testCallWithMissingAccountId() {
		// Setup null account ID
		when(job.getAccountId()).thenReturn(null);

		// Execute and verify exception
		assertThrows(IllegalArgumentException.class, () -> callable.call());
	}

	@Test
	void testCallWithNoAnalyzerFound() {
		// Return null for analyzer
		when(analyzerRegistry.getAnalyzer(provider)).thenReturn(null);

		// Execute and verify exception
		assertThrows(IllegalStateException.class, () -> callable.call());
	}
}