private void _testFanoutWithPeek(boolean after) throws Exception {
    Topology t = newTopology();
    Graph g = t.graph();

    /*                            -- Filter -- Sink(.)
     *                           /
     * Source -- Peek -- FanOut ---- Modify -- Sink(@)
     *
     */
    TStream<Integer> d = integers(t, 1, 2, 3);
    List<Integer> peekedValues = new ArrayList<>();

    if (!after) d.peek(tuple -> peekedValues.add(tuple));

    TStream<Integer> df = d.filter(tuple -> tuple.intValue() > 0);
    TStream<Integer> dm = d.modify(tuple -> new Integer(tuple.intValue() + 1));

    if (after) d.peek(tuple -> peekedValues.add(tuple));

    df.sink(tuple -> System.out.print("."));
    dm.sink(tuple -> System.out.print("@"));

    assertEquals(7, g.getVertices().size());
    assertEquals(6, g.getEdges().size());

    // Insert counter metrics into all the streams
    Metrics.counter(t);

    printGraph(g);

    assertEquals(10, g.getVertices().size());
    assertEquals(9, g.getEdges().size());
  }
  @Test
  public void testGraphToJson4() {
    Graph g = getGraph();

    /*                                   /-- V2
     * V0(Integer)-- V1(Double)-- FanOut
     *                                   \-- V3
     */
    Vertex<TestOp<String, Integer>, String, Integer> v0 = g.insert(new TestOp<>(), 1, 1);
    Connector<Integer> out0 = v0.getConnectors().get(0);
    Connector<Double> out1 = g.pipe(out0, new TestOp<Integer, Double>());
    Vertex<TestOp<Double, String>, Double, String> v2 =
        g.insert(new TestOp<Double, String>(), 1, 1);
    Vertex<TestOp<Double, String>, Double, String> v3 =
        g.insert(new TestOp<Double, String>(), 1, 1);
    out1.connect(v2, 0);
    out1.connect(v3, 0);

    Gson gson = new GsonBuilder().setPrettyPrinting().create();
    String json = gson.toJson(new GraphType(g));

    GraphType gt2 = new Gson().fromJson(json, GraphType.class);
    assertEquals(5, gt2.getVertices().size());
    assertEquals(4, gt2.getEdges().size());
  }
  @Test
  public void metricsEverywhereMultiplePeek() throws Exception {

    Topology t = newTopology();
    Graph g = t.graph();

    TStream<String> s = t.strings("a", "b", "c");
    List<String> peekedValues = new ArrayList<>();
    TStream<String> speek = s.peek(tuple -> peekedValues.add(tuple + "1st"));
    TStream<String> speek2 = speek.peek(tuple -> peekedValues.add(tuple + "2nd"));
    TStream<String> speek3 = speek2.peek(tuple -> peekedValues.add(tuple + "3rd"));
    speek3.sink(tuple -> System.out.print("."));

    Collection<Vertex<? extends Oplet<?, ?>, ?, ?>> vertices = g.getVertices();
    assertEquals(5, vertices.size());

    Collection<Edge> edges = g.getEdges();
    assertEquals(4, edges.size());

    Metrics.counter(t);

    printGraph(g);

    // One single counter inserted after the 3rd peek
    vertices = g.getVertices();
    assertEquals(6, vertices.size());

    edges = g.getEdges();
    assertEquals(5, edges.size());
  }
  @Test
  public void metricsEverywhereFanOut() {

    Topology t = newTopology();
    Graph g = t.graph();

    /*                   -- OP_3 (Sink)
     *                  /
     * OP_0 -- FanOut ----- OP_4 (Sink)
     */
    TStream<Integer> d = integers(t, 1, 2, 3);
    d.sink(tuple -> System.out.print("."));
    d.sink(tuple -> System.out.print("@"));

    // Insert counter metrics into all the topology streams
    Metrics.counter(t);

    printGraph(g);

    Collection<Vertex<? extends Oplet<?, ?>, ?, ?>> vertices = g.getVertices();
    assertEquals(5, vertices.size());

    Collection<Edge> edges = g.getEdges();
    assertEquals(4, edges.size());
  }
  @Test
  public void testGraphToJson() {
    Graph g = getGraph();
    TestOp<String, Integer> op = new TestOp<>();
    /* Vertex<TestOp<String, Integer>, String, Integer> v = */ g.insert(op, 1, 1);
    GraphType gt = new GraphType(g);
    Gson gson = new GsonBuilder().setPrettyPrinting().create();
    String json = gson.toJson(gt);

    GraphType gt2 = new Gson().fromJson(json, GraphType.class);
    assertEquals(1, gt2.getVertices().size());
    assertEquals(0, gt2.getEdges().size());
  }
  // Apply Metrics on all streams, graph with split oplet and Metric oplet
  @Test
  public void metricsEverywhereSplit() throws Exception {

    /*                        -- OP_2 (Counter) --- OP_3 (Sink)
     *                       /
     * OP_0 -- OP_1(Split) ----- OP_4 (Sink)
     *                       \
     *                        -- OP_5 (Sink)
     */
    Topology t = newTopology();
    Graph g = t.graph();

    // Source
    TStream<Integer> d = integers(t, 1, 2, 3);

    // Split
    List<TStream<Integer>> splits =
        d.split(
            3,
            tuple -> {
              switch (tuple.intValue()) {
                case 0:
                  return 0;
                case 1:
                  return 1;
                default:
                  return 2;
              }
            });

    // Insert counter metric for the zeroes stream
    Metrics.counter(splits.get(0)).sink(tuple -> System.out.print("."));

    splits.get(1).sink(tuple -> System.out.print("#"));
    splits.get(2).sink(tuple -> System.out.print("@"));

    // Insert counter metrics into all the topology streams
    Metrics.counter(t);

    printGraph(g);

    Collection<Vertex<? extends Oplet<?, ?>, ?, ?>> vertices = g.getVertices();
    assertEquals(11, vertices.size());

    Collection<Edge> edges = g.getEdges();
    assertEquals(10, edges.size());
  }
  @Test
  public void testGraphToJson2() {
    Graph g = getGraph();

    TestOp<String, Integer> op1 = new TestOp<>();
    Vertex<TestOp<String, Integer>, String, Integer> v = g.insert(op1, 1, 1);

    TestOp<Integer, Integer> op2 = new TestOp<>();
    /*Connector<Integer> out2 = */ g.pipe(v.getConnectors().get(0), op2);

    Gson gson = new GsonBuilder().setPrettyPrinting().create();
    String json = gson.toJson(new GraphType(g));

    GraphType gt2 = new Gson().fromJson(json, GraphType.class);
    assertEquals(2, gt2.getVertices().size());
    assertEquals(1, gt2.getEdges().size());
  }
  // Apply Metrics on all streams, simple graph
  @Test
  public void metricsEverywhereSimple() throws Exception {

    Topology t = newTopology();
    Graph g = t.graph();

    // Source
    TStream<Integer> d = integers(t, 1, 2, 3);
    d.sink(tuple -> System.out.print("."));

    // Insert counter metrics into all the topology streams
    Metrics.counter(t);

    printGraph(g);

    Collection<Vertex<? extends Oplet<?, ?>, ?, ?>> vertices = g.getVertices();
    assertEquals(3, vertices.size());

    Collection<Edge> edges = g.getEdges();
    assertEquals(2, edges.size());
  }
  @Test
  public void testGraphToJson5() {
    Graph g = getGraph();

    /*                         /-- V2
     * V0(Double)-- V1(Double)---- V3
     *                         \-- V4
     */
    Random r = new Random();
    Vertex<SupplierPeriodicSource<Double>, Void, Double> v0 =
        g.insert(
            new SupplierPeriodicSource<>(100, TimeUnit.MILLISECONDS, () -> (r.nextDouble() * 3)),
            0,
            1);
    Connector<Double> out0 = v0.getConnectors().get(0);
    out0.tag("dots", "hashes", "ats");

    // Insert split - see ConnectorStream.split()
    Split<Double> splitOp =
        new Split<Double>(
            tuple -> {
              switch (tuple.intValue()) {
                case 0:
                  return 0;
                case 1:
                  return 1;
                default:
                  return 2;
              }
            });
    Vertex<Split<Double>, Double, Double> v1 = g.insert(splitOp, 1, 3);
    out0.connect(v1, 0);

    // Insert and connect sinks
    Vertex<Sink<Double>, Double, Void> v2 =
        g.insert(new Sink<>(tuple -> System.out.print(".")), 1, 0);
    v1.getConnectors().get(0).connect(v2, 0);
    v1.getConnectors().get(0).tag("dots");

    Vertex<Sink<Double>, Double, Void> v3 =
        g.insert(new Sink<>(tuple -> System.out.print("#")), 1, 0);
    v1.getConnectors().get(1).connect(v3, 0);
    v1.getConnectors().get(1).tag("hashes");

    Vertex<Sink<Double>, Double, Void> v4 =
        g.insert(new Sink<>(tuple -> System.out.print("@")), 1, 0);
    v1.getConnectors().get(2).connect(v4, 0);
    v1.getConnectors().get(2).tag("ats");

    Gson gson = new GsonBuilder().setPrettyPrinting().create();
    String json = gson.toJson(new GraphType(g));

    GraphType gt = new Gson().fromJson(json, GraphType.class);
    assertEquals(5, gt.getVertices().size());
    assertEquals(4, gt.getEdges().size());
  }