|
27 | 27 | import org.apache.storm.daemon.worker.WorkerState; |
28 | 28 | import org.apache.storm.serialization.KryoTupleDeserializer; |
29 | 29 | import org.apache.storm.serialization.KryoTupleSerializer; |
| 30 | +import org.apache.storm.serialization.TupleDeserializationException; |
30 | 31 | import org.apache.storm.task.GeneralTopologyContext; |
31 | 32 | import org.apache.storm.testing.TestWordCounter; |
32 | 33 | import org.apache.storm.testing.TestWordSpout; |
@@ -137,11 +138,46 @@ public void testUnknownSourceTaskDroppedAndBatchContinues() { |
137 | 138 | out.writeInt(1, true); // default stream id |
138 | 139 | byte[] unknownTask = out.toBytes(); |
139 | 140 |
|
140 | | - assertThrows(IllegalArgumentException.class, () -> new KryoTupleDeserializer(conf, context).deserialize(unknownTask)); |
| 141 | + TupleDeserializationException thrown = assertThrows(TupleDeserializationException.class, |
| 142 | + () -> new KryoTupleDeserializer(conf, context).deserialize(unknownTask)); |
| 143 | + assertTrue(thrown.getMessage().contains("9999"), |
| 144 | + "expected the task id in the message but was: " + thrown.getMessage()); |
141 | 145 |
|
142 | 146 | assertBatchDeliversOnlyValidMessages(conf, unknownTask); |
143 | 147 | } |
144 | 148 |
|
| 149 | + @Test |
| 150 | + public void testUnknownStreamIdDroppedAndBatchContinues() { |
| 151 | + Map<String, Object> conf = baseConf(); |
| 152 | + Output out = new Output(16, 32); |
| 153 | + out.writeInt(SOURCE_TASK_ID, true); // source task that exists in the topology |
| 154 | + out.writeInt(3, true); // stream id the source component does not declare |
| 155 | + byte[] unknownStream = out.toBytes(); |
| 156 | + |
| 157 | + TupleDeserializationException thrown = assertThrows(TupleDeserializationException.class, |
| 158 | + () -> new KryoTupleDeserializer(conf, context).deserialize(unknownStream)); |
| 159 | + assertTrue(thrown.getMessage().contains("id 3"), |
| 160 | + "expected the stream id in the message but was: " + thrown.getMessage()); |
| 161 | + |
| 162 | + assertBatchDeliversOnlyValidMessages(conf, unknownStream); |
| 163 | + } |
| 164 | + |
| 165 | + @Test |
| 166 | + public void testStrictModeMakesFailuresFatal() { |
| 167 | + Map<String, Object> conf = baseConf(); |
| 168 | + conf.put(Config.TOPOLOGY_TUPLE_DESERIALIZATION_STRICT_ENABLE, true); |
| 169 | + byte[] full = serializedTuple(conf, new Values("a-string-long-enough-to-survive-truncation", 7)); |
| 170 | + byte[] truncated = Arrays.copyOf(full, full.length - 10); |
| 171 | + |
| 172 | + WorkerState.ILocalTransferCallback transfer = mock(WorkerState.ILocalTransferCallback.class); |
| 173 | + DeserializingConnectionCallback callback = new DeserializingConnectionCallback(conf, context, transfer); |
| 174 | + |
| 175 | + assertThrows(KryoException.class, () -> callback.recv(Collections.singletonList(taskMessage(truncated)))); |
| 176 | + |
| 177 | + verify(transfer, never()).transfer(any()); |
| 178 | + assertEquals(0L, callback.getAndResetDeserializationFailures()); |
| 179 | + } |
| 180 | + |
145 | 181 | @Test |
146 | 182 | public void testJavaFallbackMissingClassDroppedAndBatchContinues() { |
147 | 183 | Map<String, Object> conf = baseConf(); |
|
0 commit comments