public PipelineNode.PTransformNode getProducer(PipelineNode.PCollectionNode pcollection) {
    return (PipelineNode.PTransformNode)
        Iterables.getOnlyElement(pipelineNetwork.predecessors(pcollection));
  }
@Test
  public void getProducer() {
    Pipeline p = Pipeline.create();
    PCollection<Long> longs = p.apply("BoundedRead", Read.from(CountingSource.upTo(100L)));
    PCollectionList.of(longs).and(longs).and(longs).apply("flatten", Flatten.pCollections());

    Components components = PipelineTranslation.toProto(p).getComponents();
    QueryablePipeline qp = QueryablePipeline.forPrimitivesIn(components);

    String impulseOutputName =
        getOnlyElement(
            PipelineNode.pTransform(
                    "BoundedRead-Impulse", components.getTransformsOrThrow("BoundedRead-Impulse"))
                .getTransform()
                .getOutputsMap()
                .values());
    PTransformNode impulseProducer =
        PipelineNode.pTransform(
            "BoundedRead-Impulse", components.getTransformsOrThrow("BoundedRead-Impulse"));
    PCollectionNode impulseOutput =
        PipelineNode.pCollection(
            impulseOutputName, components.getPcollectionsOrThrow(impulseOutputName));
    String flattenOutputName =
        getOnlyElement(
            PipelineNode.pTransform("flatten", components.getTransformsOrThrow("flatten"))
                .getTransform()
                .getOutputsMap()
                .values());
    PTransformNode flattenProducer =
        PipelineNode.pTransform("flatten", components.getTransformsOrThrow("flatten"));
    PCollectionNode flattenOutput =
        PipelineNode.pCollection(
            flattenOutputName, components.getPcollectionsOrThrow(flattenOutputName));

    assertThat(qp.getProducer(impulseOutput), equalTo(impulseProducer));
    assertThat(qp.getProducer(flattenOutput), equalTo(flattenProducer));
  }