|
17 | 17 |
|
18 | 18 | package org.apache.spark.sql.streaming |
19 | 19 |
|
| 20 | +import scala.collection.mutable |
| 21 | + |
20 | 22 | import org.scalactic.TolerantNumerics |
21 | 23 | import org.scalatest.BeforeAndAfter |
22 | 24 | import org.scalatest.PrivateMethodTester._ |
23 | 25 |
|
24 | 26 | import org.apache.spark.SparkException |
| 27 | +import org.apache.spark.scheduler._ |
25 | 28 | import org.apache.spark.sql.DataFrame |
26 | 29 | import org.apache.spark.sql.execution.streaming._ |
27 | 30 | import org.apache.spark.sql.functions._ |
@@ -206,6 +209,45 @@ class StreamingQueryListenerSuite extends StreamTest with BeforeAndAfter { |
206 | 209 | assert(queryQueryTerminated.exception === newQueryTerminated.exception) |
207 | 210 | } |
208 | 211 |
|
| 212 | + test("ReplayListenerBus should ignore broken event jsons generated in 2.0.0") { |
| 213 | + // structured-streaming-query-event-logs-2.0.0.txt has all types of events generated by |
| 214 | + // Structured Streaming in Spark 2.0.0. |
| 215 | + // SparkListenerApplicationEnd is the only valid event and it's the last event. We use it |
| 216 | + // to verify that we can skip broken jsons generated by Structured Streaming. |
| 217 | + testReplayListenerBusWithBorkenEventJsons("structured-streaming-query-event-logs-2.0.0.txt") |
| 218 | + } |
| 219 | + |
| 220 | + test("ReplayListenerBus should ignore broken event jsons generated in 2.0.1") { |
| 221 | + // structured-streaming-query-event-logs-2.0.1.txt has all types of events generated by |
| 222 | + // Structured Streaming in Spark 2.0.1. |
| 223 | + // SparkListenerApplicationEnd is the only valid event and it's the last event. We use it |
| 224 | + // to verify that we can skip broken jsons generated by Structured Streaming. |
| 225 | + testReplayListenerBusWithBorkenEventJsons("structured-streaming-query-event-logs-2.0.1.txt") |
| 226 | + } |
| 227 | + |
| 228 | + private def testReplayListenerBusWithBorkenEventJsons(fileName: String): Unit = { |
| 229 | + val input = getClass.getResourceAsStream(s"/history-server/$fileName") |
| 230 | + val events = mutable.ArrayBuffer[SparkListenerEvent]() |
| 231 | + try { |
| 232 | + val replayer = new ReplayListenerBus() { |
| 233 | + // Redirect all parsed events to `events` |
| 234 | + override def doPostEvent( |
| 235 | + listener: SparkListenerInterface, |
| 236 | + event: SparkListenerEvent): Unit = { |
| 237 | + events += event |
| 238 | + } |
| 239 | + } |
| 240 | + // Add a dummy listener so that "doPostEvent" will be called. |
| 241 | + replayer.addListener(new SparkListener {}) |
| 242 | + replayer.replay(input, fileName) |
| 243 | + // SparkListenerApplicationEnd is the only valid event |
| 244 | + assert(events.size === 1) |
| 245 | + assert(events(0).isInstanceOf[SparkListenerApplicationEnd]) |
| 246 | + } finally { |
| 247 | + input.close() |
| 248 | + } |
| 249 | + } |
| 250 | + |
209 | 251 | private def assertStreamingQueryInfoEquals( |
210 | 252 | expected: StreamingQueryStatus, |
211 | 253 | actual: StreamingQueryStatus): Unit = { |
|
0 commit comments