@@ -53,8 +53,15 @@ class PipelineRunnerTest {
5353 fun `run should execute all pipelines concurrently` () = runTest {
5454 // Given
5555 val pipelineScope = Fixtures .testScope(this .coroutineContext)
56- val runner = PipelineRunner (reconciler, store, listOf (pipeline1, pipeline2, pipeline3), inputStreams, pipelineScope)
57-
56+ val runner =
57+ PipelineRunner (
58+ reconciler,
59+ store,
60+ listOf (pipeline1, pipeline2, pipeline3),
61+ inputStreams,
62+ pipelineScope
63+ )
64+
5865 coEvery { pipeline1.run () } coAnswers { delay(100 ) }
5966 coEvery { pipeline2.run () } coAnswers { delay(50 ) }
6067 coEvery { pipeline3.run () } coAnswers { delay(75 ) }
@@ -79,13 +86,15 @@ class PipelineRunnerTest {
7986 val exception = RuntimeException (" Pipeline failed" )
8087 coEvery { pipeline1.run () } throws exception
8188 val failingScope = Fixtures .testScope(this .coroutineContext)
82- val failingRunner = PipelineRunner (reconciler, store, listOf (pipeline1), inputStreams, failingScope)
89+ val failingRunner =
90+ PipelineRunner (reconciler, store, listOf (pipeline1), inputStreams, failingScope)
8391
8492 // When/Then
85- val thrownException = assertThrows<RuntimeException > {
86- failingRunner.run ()
87- testScheduler.advanceUntilIdle()
88- }
93+ val thrownException =
94+ assertThrows<RuntimeException > {
95+ failingRunner.run ()
96+ testScheduler.advanceUntilIdle()
97+ }
8998
9099 assertEquals(" Pipeline failed" , thrownException.message)
91100
@@ -99,7 +108,8 @@ class PipelineRunnerTest {
99108 // Given
100109 coEvery { pipeline1.run () } just Runs
101110 val singlePipelineScope = Fixtures .testScope(this .coroutineContext)
102- val singlePipelineRunner = PipelineRunner (reconciler, store, listOf (pipeline1), inputStreams, singlePipelineScope)
111+ val singlePipelineRunner =
112+ PipelineRunner (reconciler, store, listOf (pipeline1), inputStreams, singlePipelineScope)
103113
104114 // When
105115 singlePipelineRunner.run ()
@@ -132,7 +142,8 @@ class PipelineRunnerTest {
132142 // Given
133143 coEvery { pipeline1.run () } just Runs
134144 val singlePipelineScope = Fixtures .testScope(this .coroutineContext)
135- val singlePipelineRunner = PipelineRunner (reconciler, store, listOf (pipeline1), inputStreams, singlePipelineScope)
145+ val singlePipelineRunner =
146+ PipelineRunner (reconciler, store, listOf (pipeline1), inputStreams, singlePipelineScope)
136147
137148 // When
138149 singlePipelineRunner.run ()
@@ -151,13 +162,15 @@ class PipelineRunnerTest {
151162 coEvery { pipeline1.run () } just Runs
152163 coEvery { reconciler.disable() } throws RuntimeException (" Failed to disable" )
153164 val singlePipelineScope = Fixtures .testScope(this .coroutineContext)
154- val singlePipelineRunner = PipelineRunner (reconciler, store, listOf (pipeline1), inputStreams, singlePipelineScope)
165+ val singlePipelineRunner =
166+ PipelineRunner (reconciler, store, listOf (pipeline1), inputStreams, singlePipelineScope)
155167
156168 // When/Then
157- val exception = assertThrows<RuntimeException > {
158- singlePipelineRunner.run ()
159- testScheduler.advanceUntilIdle()
160- }
169+ val exception =
170+ assertThrows<RuntimeException > {
171+ singlePipelineRunner.run ()
172+ testScheduler.advanceUntilIdle()
173+ }
161174
162175 assertEquals(" Failed to disable" , exception.message)
163176
@@ -172,13 +185,15 @@ class PipelineRunnerTest {
172185 coEvery { pipeline1.run () } just Runs
173186 every { reconciler.flushCompleteStates() } throws RuntimeException (" Failed to flush" )
174187 val singlePipelineScope = Fixtures .testScope(this .coroutineContext)
175- val singlePipelineRunner = PipelineRunner (reconciler, store, listOf (pipeline1), inputStreams, singlePipelineScope)
188+ val singlePipelineRunner =
189+ PipelineRunner (reconciler, store, listOf (pipeline1), inputStreams, singlePipelineScope)
176190
177191 // When/Then
178- val exception = assertThrows<RuntimeException > {
179- singlePipelineRunner.run ()
180- testScheduler.advanceUntilIdle()
181- }
192+ val exception =
193+ assertThrows<RuntimeException > {
194+ singlePipelineRunner.run ()
195+ testScheduler.advanceUntilIdle()
196+ }
182197
183198 assertEquals(" Failed to flush" , exception.message)
184199
@@ -193,28 +208,30 @@ class PipelineRunnerTest {
193208 // Given
194209 val exception = RuntimeException (" Pipeline failed" )
195210 coEvery { pipeline1.run () } throws exception
196-
211+
197212 val failingScope = Fixtures .testScope(this .coroutineContext)
198- val failingRunner = PipelineRunner (reconciler, store, listOf (pipeline1), inputStreams, failingScope)
213+ val failingRunner =
214+ PipelineRunner (reconciler, store, listOf (pipeline1), inputStreams, failingScope)
199215
200216 // When
201- assertThrows<RuntimeException > {
217+ assertThrows<RuntimeException > {
202218 failingRunner.run ()
203219 testScheduler.advanceUntilIdle()
204220 }
205-
221+
206222 // Then - verify that closeAll was called due to exception handler
207223 verify(atLeast = 1 ) { inputStreams.closeAll() }
208224 }
209225
210226 @Test
211227 fun `run should handle large number of pipelines` () = runTest {
212228 // Given
213- val pipelines = (1 .. 32 ).map {
214- val pipeline = mockk<DataFlowPipeline >()
215- coEvery { pipeline.run () } just Runs
216- pipeline
217- }
229+ val pipelines =
230+ (1 .. 32 ).map {
231+ val pipeline = mockk<DataFlowPipeline >()
232+ coEvery { pipeline.run () } just Runs
233+ pipeline
234+ }
218235
219236 val largeScope = Fixtures .testScope(this .coroutineContext)
220237 val largeRunner = PipelineRunner (reconciler, store, pipelines, inputStreams, largeScope)
@@ -237,28 +254,32 @@ class PipelineRunnerTest {
237254 var pipeline2Complete = false
238255 var reconcilerDisabled = false
239256
240- coEvery { pipeline1.run () } coAnswers {
241- delay(100 )
242- pipeline1Complete = true
243- }
244- coEvery { pipeline2.run () } coAnswers {
245- delay(50 )
246- pipeline2Complete = true
247- }
248- coEvery { reconciler.disable() } answers {
249- reconcilerDisabled = true
250- assertTrue(
251- pipeline1Complete,
252- " Pipeline 1 should be complete before disabling reconciler"
253- )
254- assertTrue(
255- pipeline2Complete,
256- " Pipeline 2 should be complete before disabling reconciler"
257- )
258- }
257+ coEvery { pipeline1.run () } coAnswers
258+ {
259+ delay(100 )
260+ pipeline1Complete = true
261+ }
262+ coEvery { pipeline2.run () } coAnswers
263+ {
264+ delay(50 )
265+ pipeline2Complete = true
266+ }
267+ coEvery { reconciler.disable() } answers
268+ {
269+ reconcilerDisabled = true
270+ assertTrue(
271+ pipeline1Complete,
272+ " Pipeline 1 should be complete before disabling reconciler"
273+ )
274+ assertTrue(
275+ pipeline2Complete,
276+ " Pipeline 2 should be complete before disabling reconciler"
277+ )
278+ }
259279
260280 val twoScope = Fixtures .testScope(this .coroutineContext)
261- val twoRunner = PipelineRunner (reconciler, store, listOf (pipeline1, pipeline2), inputStreams, twoScope)
281+ val twoRunner =
282+ PipelineRunner (reconciler, store, listOf (pipeline1, pipeline2), inputStreams, twoScope)
262283
263284 // When
264285 twoRunner.run ()
@@ -269,39 +290,49 @@ class PipelineRunnerTest {
269290 }
270291
271292 @Test
272- fun `run should throw IllegalStateException when unflushed states exist at sync end` () = runTest {
273- // Given
274- coEvery { pipeline1.run () } just Runs
275- every { store.hasStates() } returns true // Simulate unflushed states exist
276-
277- val singlePipelineScope = Fixtures .testScope(this .coroutineContext)
278- val singlePipelineRunner = PipelineRunner (reconciler, store, listOf (pipeline1), inputStreams, singlePipelineScope)
279-
280- // When/Then
281- val exception = assertThrows<IllegalStateException > {
282- singlePipelineRunner.run ()
283- testScheduler.advanceUntilIdle()
293+ fun `run should throw IllegalStateException when unflushed states exist at sync end` () =
294+ runTest {
295+ // Given
296+ coEvery { pipeline1.run () } just Runs
297+ every { store.hasStates() } returns true // Simulate unflushed states exist
298+
299+ val singlePipelineScope = Fixtures .testScope(this .coroutineContext)
300+ val singlePipelineRunner =
301+ PipelineRunner (
302+ reconciler,
303+ store,
304+ listOf (pipeline1),
305+ inputStreams,
306+ singlePipelineScope
307+ )
308+
309+ // When/Then
310+ val exception =
311+ assertThrows<IllegalStateException > {
312+ singlePipelineRunner.run ()
313+ testScheduler.advanceUntilIdle()
314+ }
315+
316+ // Then
317+ assertEquals(" Sync completed, but unflushed states were detected." , exception.message)
318+
319+ // Verify all operations completed before the check
320+ coVerify(exactly = 1 ) { reconciler.run () }
321+ coVerify(exactly = 1 ) { pipeline1.run () }
322+ coVerify(exactly = 1 ) { reconciler.disable() }
323+ coVerify(exactly = 1 ) { reconciler.flushCompleteStates() }
324+ coVerify(exactly = 1 ) { store.hasStates() }
284325 }
285326
286- // Then
287- assertEquals(" Sync completed, but unflushed states were detected." , exception.message)
288-
289- // Verify all operations completed before the check
290- coVerify(exactly = 1 ) { reconciler.run () }
291- coVerify(exactly = 1 ) { pipeline1.run () }
292- coVerify(exactly = 1 ) { reconciler.disable() }
293- coVerify(exactly = 1 ) { reconciler.flushCompleteStates() }
294- coVerify(exactly = 1 ) { store.hasStates() }
295- }
296-
297327 @Test
298328 fun `run should not throw exception when all states are flushed` () = runTest {
299329 // Given
300330 coEvery { pipeline1.run () } just Runs
301331 every { store.hasStates() } returns false // All states are flushed
302332
303333 val singlePipelineScope = Fixtures .testScope(this .coroutineContext)
304- val singlePipelineRunner = PipelineRunner (reconciler, store, listOf (pipeline1), inputStreams, singlePipelineScope)
334+ val singlePipelineRunner =
335+ PipelineRunner (reconciler, store, listOf (pipeline1), inputStreams, singlePipelineScope)
305336
306337 // When - should complete without exception
307338 singlePipelineRunner.run ()
0 commit comments