1+ /*
2+ * Copyright OpenSearch Contributors
3+ * SPDX-License-Identifier: Apache-2.0
4+ */
5+
6+ package org .opensearch .dataprepper .core .livecapture ;
7+
8+ import org .junit .jupiter .api .BeforeEach ;
9+ import org .junit .jupiter .api .Test ;
10+ import org .junit .jupiter .api .extension .ExtendWith ;
11+ import org .mockito .Mock ;
12+ import org .mockito .MockedStatic ;
13+ import org .mockito .junit .jupiter .MockitoExtension ;
14+ import org .opensearch .dataprepper .core .parser .model .DataPrepperConfiguration ;
15+ import org .opensearch .dataprepper .model .configuration .PluginSetting ;
16+ import org .opensearch .dataprepper .model .event .Event ;
17+ import org .opensearch .dataprepper .model .event .EventFactory ;
18+ import org .opensearch .dataprepper .model .plugin .PluginFactory ;
19+ import org .opensearch .dataprepper .model .record .Record ;
20+ import org .opensearch .dataprepper .model .sink .Sink ;
21+ import org .opensearch .dataprepper .model .sink .SinkContext ;
22+ import org .springframework .context .ApplicationContext ;
23+
24+ import java .util .Map ;
25+
26+ import static org .hamcrest .MatcherAssert .assertThat ;
27+ import static org .hamcrest .Matchers .instanceOf ;
28+ import static org .hamcrest .Matchers .notNullValue ;
29+ import static org .mockito .ArgumentMatchers .any ;
30+ import static org .mockito .Mockito .mock ;
31+ import static org .mockito .Mockito .mockStatic ;
32+ import static org .mockito .Mockito .verify ;
33+ import static org .mockito .Mockito .when ;
34+
35+ @ ExtendWith (MockitoExtension .class )
36+ class LiveCaptureAppConfigTest {
37+
38+ @ Mock
39+ private DataPrepperConfiguration dataPrepperConfiguration ;
40+
41+ @ Mock
42+ private LiveCaptureConfiguration liveCaptureConfiguration ;
43+
44+ @ Mock
45+ private EventFactory defaultEventFactory ;
46+
47+ @ Mock
48+ private LiveCaptureOutputManager mockOutputManager ;
49+
50+ @ Mock
51+ private ApplicationContext applicationContext ;
52+
53+ @ Mock
54+ private PluginFactory pluginFactory ;
55+
56+ @ Mock
57+ private Sink <Record <Event >> mockSink ;
58+
59+ private LiveCaptureAppConfig liveCaptureAppConfig ;
60+
61+ @ BeforeEach
62+ void setUp () {
63+ liveCaptureAppConfig = new LiveCaptureAppConfig (dataPrepperConfiguration );
64+ liveCaptureAppConfig .setApplicationContext (applicationContext );
65+ }
66+
67+ @ Test
68+ void initializeLiveCaptureManager_with_valid_configuration () {
69+ when (dataPrepperConfiguration .getLiveCaptureConfiguration ()).thenReturn (liveCaptureConfiguration );
70+ when (liveCaptureConfiguration .isDefaultEnabled ()).thenReturn (true );
71+ when (liveCaptureConfiguration .getDefaultRate ()).thenReturn (5.0 );
72+
73+ try (MockedStatic <LiveCaptureManager > mockedLiveCaptureManager = mockStatic (LiveCaptureManager .class )) {
74+ liveCaptureAppConfig .initializeLiveCaptureManager ();
75+
76+ mockedLiveCaptureManager .verify (() -> LiveCaptureManager .initialize (true , 5.0 ));
77+ }
78+ }
79+
80+ @ Test
81+ void initializeLiveCaptureManager_with_null_configuration () {
82+ when (dataPrepperConfiguration .getLiveCaptureConfiguration ()).thenReturn (null );
83+
84+ try (MockedStatic <LiveCaptureManager > mockedLiveCaptureManager = mockStatic (LiveCaptureManager .class )) {
85+ liveCaptureAppConfig .initializeLiveCaptureManager ();
86+
87+ // Should use defaults: enabled=false, rate=1.0
88+ mockedLiveCaptureManager .verify (() -> LiveCaptureManager .initialize (false , 1.0 ));
89+ }
90+ }
91+
92+ @ Test
93+ void shutdownLiveCapture_calls_output_manager_shutdown () {
94+ try (MockedStatic <LiveCaptureOutputManager > mockedOutputManager = mockStatic (LiveCaptureOutputManager .class )) {
95+ mockedOutputManager .when (LiveCaptureOutputManager ::getInstance ).thenReturn (mockOutputManager );
96+
97+ liveCaptureAppConfig .shutdownLiveCapture ();
98+
99+ verify (mockOutputManager ).shutdown ();
100+ }
101+ }
102+
103+ @ Test
104+ void liveCaptureHandler_returns_handler_instance () {
105+ EventFactory mockEventFactory = mock (EventFactory .class );
106+ LiveCaptureHandler handler = liveCaptureAppConfig .liveCaptureHandler (mockEventFactory );
107+
108+ assertThat (handler , notNullValue ());
109+ assertThat (handler , instanceOf (LiveCaptureHandler .class ));
110+ }
111+
112+
113+
114+ @ Test
115+ void initializeLiveCaptureManager_with_cloudwatch_sink_configuration () {
116+ // Create CloudWatch sink configuration
117+ Map <String , Object > awsConfig = Map .of ("region" , "us-east-1" );
118+ Map <String , Object > cloudwatchConfig = Map .of (
119+ "log_group" , "/dataprepper/livecapture" ,
120+ "log_stream" , "livecapture-events" ,
121+ "aws" , awsConfig
122+ );
123+ Map <String , Object > sinkConfig = Map .of (
124+ "cloudwatch_logs" , cloudwatchConfig ,
125+ "entry_threshold" , 3 ,
126+ "batch_size" , 10
127+ );
128+
129+ when (dataPrepperConfiguration .getLiveCaptureConfiguration ()).thenReturn (liveCaptureConfiguration );
130+ when (liveCaptureConfiguration .isDefaultEnabled ()).thenReturn (true );
131+ when (liveCaptureConfiguration .getDefaultRate ()).thenReturn (2.0 );
132+ when (liveCaptureConfiguration .getLiveCaptureOutputSinkConfig ()).thenReturn (sinkConfig );
133+
134+ // Mock PluginFactory to return a mock sink
135+ when (applicationContext .getBean (PluginFactory .class )).thenReturn (pluginFactory );
136+ when (pluginFactory .loadPlugin (any (Class .class ), any (PluginSetting .class ), any (SinkContext .class ))).thenReturn (mockSink );
137+
138+ try (MockedStatic <LiveCaptureManager > mockedLiveCaptureManager = mockStatic (LiveCaptureManager .class );
139+ MockedStatic <LiveCaptureOutputManager > mockedOutputManager = mockStatic (LiveCaptureOutputManager .class )) {
140+
141+ mockedOutputManager .when (LiveCaptureOutputManager ::getInstance ).thenReturn (mockOutputManager );
142+
143+ liveCaptureAppConfig .initializeLiveCaptureManager ();
144+
145+ // Verify LiveCaptureManager initialization
146+ mockedLiveCaptureManager .verify (() -> LiveCaptureManager .initialize (true , 2.0 ));
147+
148+ // Verify output manager initialization with plugin-based sink
149+ verify (mockOutputManager ).initialize (any (Sink .class ), any (Integer .class ), any (Integer .class ));
150+ verify (mockOutputManager ).enable ();
151+ }
152+ }
153+
154+ @ Test
155+ void initializeLiveCaptureManager_with_invalid_sink_configuration () {
156+ // Create invalid configuration (missing log_group)
157+ Map <String , Object > cloudwatchConfig = Map .of ("log_stream" , "test-stream" );
158+ Map <String , Object > sinkConfig = Map .of ("cloudwatch_logs" , cloudwatchConfig );
159+
160+ when (dataPrepperConfiguration .getLiveCaptureConfiguration ()).thenReturn (liveCaptureConfiguration );
161+ when (liveCaptureConfiguration .isDefaultEnabled ()).thenReturn (true );
162+ when (liveCaptureConfiguration .getDefaultRate ()).thenReturn (2.0 );
163+ when (liveCaptureConfiguration .getLiveCaptureOutputSinkConfig ()).thenReturn (sinkConfig );
164+
165+ // Mock PluginFactory to simulate failure
166+ when (applicationContext .getBean (PluginFactory .class )).thenReturn (pluginFactory );
167+ when (pluginFactory .loadPlugin (any (Class .class ), any (PluginSetting .class ), any (SinkContext .class ))).thenThrow (new RuntimeException ("Plugin creation failed" ));
168+
169+ try (MockedStatic <LiveCaptureManager > mockedLiveCaptureManager = mockStatic (LiveCaptureManager .class );
170+ MockedStatic <LiveCaptureOutputManager > mockedOutputManager = mockStatic (LiveCaptureOutputManager .class )) {
171+
172+ mockedOutputManager .when (LiveCaptureOutputManager ::getInstance ).thenReturn (mockOutputManager );
173+
174+ // Should not throw exception even with invalid config
175+ liveCaptureAppConfig .initializeLiveCaptureManager ();
176+
177+ // Should still initialize LiveCaptureManager
178+ mockedLiveCaptureManager .verify (() -> LiveCaptureManager .initialize (true , 2.0 ));
179+ }
180+ }
181+
182+ @ Test
183+ void testPluginBasedSinkFunctionality () {
184+ // This test exercises the plugin-based sink functionality
185+ Map <String , Object > awsConfig = Map .of ("region" , "us-west-2" );
186+ Map <String , Object > cloudwatchConfig = Map .of (
187+ "log_group" , "/test/livecapture" ,
188+ "log_stream" , "test-stream" ,
189+ "aws" , awsConfig
190+ );
191+ Map <String , Object > sinkConfig = Map .of ("cloudwatch_logs" , cloudwatchConfig );
192+
193+ when (dataPrepperConfiguration .getLiveCaptureConfiguration ()).thenReturn (liveCaptureConfiguration );
194+ when (liveCaptureConfiguration .isDefaultEnabled ()).thenReturn (false );
195+ when (liveCaptureConfiguration .getDefaultRate ()).thenReturn (1.0 );
196+ when (liveCaptureConfiguration .getLiveCaptureOutputSinkConfig ()).thenReturn (sinkConfig );
197+
198+ // Mock PluginFactory to return a mock sink
199+ when (applicationContext .getBean (PluginFactory .class )).thenReturn (pluginFactory );
200+ when (pluginFactory .loadPlugin (any (Class .class ), any (PluginSetting .class ), any (SinkContext .class ))).thenReturn (mockSink );
201+
202+ try (MockedStatic <LiveCaptureManager > mockedLiveCaptureManager = mockStatic (LiveCaptureManager .class );
203+ MockedStatic <LiveCaptureOutputManager > mockedOutputManager = mockStatic (LiveCaptureOutputManager .class )) {
204+
205+ mockedOutputManager .when (LiveCaptureOutputManager ::getInstance ).thenReturn (mockOutputManager );
206+
207+ liveCaptureAppConfig .initializeLiveCaptureManager ();
208+
209+ // Verify that initialize was called with a Sink (which would be our plugin-based sink)
210+ verify (mockOutputManager ).initialize (any (Sink .class ), any (Integer .class ), any (Integer .class ));
211+ }
212+ }
213+ }
0 commit comments