/** * Set the output of the current {@link Node}. If the output is new (setOutput has not previously * been called with it as the parameter), the current node is set as the producer of that {@link * POutput}. * * <p>Also validates the output - specifically, a Primitive {@link PTransform} produces all of its * outputs, and a Composite {@link PTransform} produces none of its outputs. Verifies that the * expanded output does not contain {@link PValue PValues} produced by both this node and other * nodes. */ public void setOutput(POutput output) { for (PCollection<?> value : fullyExpand(output).values()) { if (!producers.containsKey(value)) { producers.put(value, current); value.finishSpecifyingOutput( current.getFullName(), unexpandedInputs.get(current), current.transform); } producerInput.put(value, unexpandedInputs.get(current)); } output.finishSpecifyingOutput( current.getFullName(), unexpandedInputs.get(current), current.transform); current.setOutput(output); }
@Test public void testTaggedOutputUnregisteredExplicitCoder() throws Exception { pipeline.enableAbandonedNodeEnforcement(false); PCollection<Integer> input = pipeline.apply(Create.of(Arrays.asList(1, 2, 3))); final TupleTag<Integer> mainOutputTag = new TupleTag<>("main"); final TupleTag<TestDummy> additionalOutputTag = new TupleTag<>("unregisteredSide"); ParDo.MultiOutput<Integer, Integer> pardo = ParDo.of(new TaggedOutputDummyFn(mainOutputTag, additionalOutputTag)) .withOutputTags(mainOutputTag, TupleTagList.of(additionalOutputTag)); PCollectionTuple outputTuple = input.apply(pardo); outputTuple.get(additionalOutputTag).setCoder(new TestDummyCoder()); outputTuple.get(additionalOutputTag).apply(View.asSingleton()); assertEquals(new TestDummyCoder(), outputTuple.get(additionalOutputTag).getCoder()); outputTuple .get(additionalOutputTag) .finishSpecifyingOutput("ParDo", input, pardo); // Check for crashes assertEquals( new TestDummyCoder(), outputTuple.get(additionalOutputTag).getCoder()); // Check for corruption }