/**
   * Test with a distributed execution with explicit colocation of two functions end up on the same
   * container.
   */
  @Test
  public void testSimpleDistributedColocate() throws Exception {
    assumeTrue(SC_OK);
    assumeTrue(getTesterType() == StreamsContext.Type.DISTRIBUTED_TESTER);

    Topology t = newTopology();

    TStream<String> sa = t.strings("a");
    TStream<String> sb = t.strings("b");

    sa = sa.transform(IsolateTest.getContainerId());
    sb = sb.transform(IsolateTest.getContainerId());

    sa.colocate(sb);

    sa = sa.isolate().filter(new AllowAll<String>());
    sb = sb.isolate().filter(new AllowAll<String>());

    sa = sa.union(sb);

    Condition<List<String>> pes = t.getTester().stringContents(sa, "");

    Condition<Long> tc = t.getTester().tupleCount(sa, 2);

    complete(t.getTester(), tc, 10, TimeUnit.SECONDS);

    Set<String> singlePe = new HashSet<>(pes.getResult());

    assertTrue(pes.getResult().toString(), singlePe.size() == 1);
  }
  @Test
  public void testFusing() {
    assumeTrue(isMainRun());
    Topology t = newTopology();
    TStream<String> s1 = t.strings("3");
    TStream<String> s2 = t.strings("3");
    TStream<String> snf = t.strings("3");

    assertTrue(s1.isPlaceable());

    assertSame(s1.colocate(s2), s1);

    String id1 = getFusingId(s1);
    String id2 = getFusingId(s2);

    assertNotNull(id1);
    assertFalse(id1.isEmpty());

    assertEquals(id1, id2);

    TStream<String> s3 = t.strings("3");
    TStream<String> s4 = t.strings("3");
    TSink s5 = s4.print();
    assertTrue(s5.isPlaceable());

    assertSame(s3.colocate(s4, s5), s3);
    assertEquals(getFusingId(s3), getFusingId(s4));
    assertEquals(getFusingId(s3), getColocate(s5.operator()));

    assertFalse(getFusingId(s1).equals(getFusingId(s3)));

    assertNull(getFusingId(snf));

    TStream<String> s6 = StringStreams.toString(s4);
    s1.colocate(s6);
    assertEquals(getFusingId(s1), getFusingId(s6));
  }
  @Test
  public void testTags() {
    assumeTrue(isMainRun());
    Topology t = newTopology();
    TStream<String> s1 = t.strings("3");
    TStream<String> s2 = t.strings("3");
    TStream<String> s3 = t.strings("3");

    s1.addResourceTags();
    assertNull(getResourceTags(s1));

    s2.addResourceTags("A", "B");
    Set<String> s2s = getResourceTags(s2);
    assertEquals(2, s2s.size());
    assertTrue(s2s.contains("A"));
    assertTrue(s2s.contains("B"));

    s3.addResourceTags("C", "D", "E");
    Set<String> s3s = getResourceTags(s3);
    assertEquals(3, s3s.size());
    assertTrue(s3s.contains("C"));
    assertTrue(s3s.contains("D"));
    assertTrue(s3s.contains("E"));

    s2s = getResourceTags(s2);
    assertEquals(2, s2s.size());
    assertTrue(s2s.contains("A"));
    assertTrue(s2s.contains("B"));

    s2.addResourceTags("X", "Y");
    s2s = getResourceTags(s2);
    assertEquals(4, s2s.size());
    assertTrue(s2s.contains("A"));
    assertTrue(s2s.contains("B"));
    assertTrue(s2s.contains("X"));
    assertTrue(s2s.contains("Y"));

    // Colocating means the s1 will inherit
    // s3 resource tags
    s1.colocate(s3);
    Set<String> s1s = getResourceTags(s1);
    assertEquals(3, s1s.size());
    assertTrue(s1s.contains("C"));
    assertTrue(s1s.contains("D"));
    assertTrue(s1s.contains("E"));
  }
  @SuppressWarnings("unused")
  @Test(expected = IllegalStateException.class)
  public void testColocateLowLatencyRegions() throws Exception {
    assumeTrue(isMainRun());

    // ensure colocating two low latency regions doesn't break lowLatancy
    // and colocating is achieved.

    Topology t = newTopology("testColocateLowLatencyRegions");
    Tester tester = t.getTester();
    // getConfig().put(ContextProperties.KEEP_ARTIFACTS, true);

    TStream<String> s1 =
        t.strings("a").lowLatency().modify(getContainerIdAppend()).modify(getContainerIdAppend());
    s1.endLowLatency();

    TStream<String> s2 =
        t.strings("A").lowLatency().modify(getContainerIdAppend()).modify(getContainerIdAppend());
    s2.endLowLatency();

    s1.colocate(s2); // expect throw ISE: colocate in a low latency region

    // once it's supported... (today it breaks the low latency guarantee)
    // and adjust isMainRun() too
    //        // Given the default fuse-island behavior, expect islands to continue
    //        // to be fused, now both in a single container.
    //
    //        // Today FAILING in an interesting way.
    //        // There are 2 PEs:
    //        // - one has just the single colocated s1 and s2 modify ops
    //        // - the other has everything else
    //
    //        TStream<String> all = s1.union(s2);
    //        all.print();
    //        Condition<Long> nTuples = tester.tupleCount(all.filter(new AllowAll<String>()), 2);
    //        Condition<List<String>> contents = tester.stringContents(
    //                all.filter(new AllowAll<String>()), "");
    //
    //        complete(tester, nTuples, 10, TimeUnit.SECONDS);
    //
    //        Set<String> ids = getContainerIds(contents.getResult());
    //        assertEquals("ids: "+ids, 1, ids.size());
  }