/*
 * libjingle
 * Copyright 2013 Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.webrtc;

import org.webrtc.PeerConnection.IceConnectionState;
import org.webrtc.PeerConnection.IceGatheringState;
import org.webrtc.PeerConnection.SignalingState;

import java.io.File;
import java.lang.ref.WeakReference;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.IdentityHashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.TreeSet;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import static junit.framework.Assert.*;

/** End-to-end tests for PeerConnection.java. */
public class PeerConnectionTest {
  // Set to true to render video.
  private static final boolean RENDER_TO_GUI = false;
  private TreeSet<String> threadsBeforeTest = null;

  private static class ObserverExpectations implements PeerConnection.Observer,
                                                       VideoRenderer.Callbacks,
                                                       DataChannel.Observer,
                                                       StatsObserver {
    private final String name;
    private int expectedIceCandidates = 0;
    private int expectedErrors = 0;
    private int expectedRenegotiations = 0;
    private int previouslySeenWidth = 0;
    private int previouslySeenHeight = 0;
    private int expectedFramesDelivered = 0;
    private LinkedList<SignalingState> expectedSignalingChanges =
        new LinkedList<SignalingState>();
    private LinkedList<IceConnectionState> expectedIceConnectionChanges =
        new LinkedList<IceConnectionState>();
    private LinkedList<IceGatheringState> expectedIceGatheringChanges =
        new LinkedList<IceGatheringState>();
    private LinkedList<String> expectedAddStreamLabels =
        new LinkedList<String>();
    private LinkedList<String> expectedRemoveStreamLabels =
        new LinkedList<String>();
    public LinkedList<IceCandidate> gotIceCandidates =
        new LinkedList<IceCandidate>();
    private Map<MediaStream, WeakReference<VideoRenderer>> renderers =
        new IdentityHashMap<MediaStream, WeakReference<VideoRenderer>>();
    private DataChannel dataChannel;
    private LinkedList<DataChannel.Buffer> expectedBuffers =
        new LinkedList<DataChannel.Buffer>();
    private LinkedList<DataChannel.State> expectedStateChanges =
        new LinkedList<DataChannel.State>();
    private LinkedList<String> expectedRemoteDataChannelLabels =
        new LinkedList<String>();
    private int expectedStatsCallbacks = 0;
    private LinkedList<StatsReport[]> gotStatsReports =
        new LinkedList<StatsReport[]>();

    public ObserverExpectations(String name) {
      this.name = name;
    }

    public synchronized void setDataChannel(DataChannel dataChannel) {
      assertNull(this.dataChannel);
      this.dataChannel = dataChannel;
      this.dataChannel.registerObserver(this);
      assertNotNull(this.dataChannel);
    }

    public synchronized void expectIceCandidates(int count) {
      expectedIceCandidates += count;
    }

    @Override
    public synchronized void onIceCandidate(IceCandidate candidate) {
      --expectedIceCandidates;

      // We don't assert expectedIceCandidates >= 0 because it's hard to know
      // how many to expect, in general.  We only use expectIceCandidates to
      // assert a minimal count.
      gotIceCandidates.add(candidate);
    }

    private synchronized void setSize(int width, int height) {
      assertFalse(RENDER_TO_GUI);
      // Because different camera devices (fake & physical) produce different
      // resolutions, we only sanity-check the set sizes,
      assertTrue(width > 0);
      assertTrue(height > 0);
      if (previouslySeenWidth > 0) {
        assertEquals(previouslySeenWidth, width);
        assertEquals(previouslySeenHeight, height);
      } else {
        previouslySeenWidth = width;
        previouslySeenHeight = height;
      }
    }

    public synchronized void expectFramesDelivered(int count) {
      assertFalse(RENDER_TO_GUI);
      expectedFramesDelivered += count;
    }

    @Override
    public synchronized void renderFrame(VideoRenderer.I420Frame frame) {
      setSize(frame.width, frame.height);
      --expectedFramesDelivered;
    }

    public synchronized void expectSignalingChange(SignalingState newState) {
      expectedSignalingChanges.add(newState);
    }

    @Override
    public synchronized void onSignalingChange(SignalingState newState) {
      assertEquals(expectedSignalingChanges.removeFirst(), newState);
    }

    public synchronized void expectIceConnectionChange(
        IceConnectionState newState) {
      expectedIceConnectionChanges.add(newState);
    }

    @Override
    public synchronized void onIceConnectionChange(
        IceConnectionState newState) {
      // TODO(bemasc): remove once delivery of ICECompleted is reliable
      // (https://code.google.com/p/webrtc/issues/detail?id=3021).
      if (newState.equals(IceConnectionState.COMPLETED)) {
        return;
      }

      assertEquals(expectedIceConnectionChanges.removeFirst(), newState);
    }

    public synchronized void expectIceGatheringChange(
        IceGatheringState newState) {
      expectedIceGatheringChanges.add(newState);
    }

    @Override
    public synchronized void onIceGatheringChange(IceGatheringState newState) {
      // It's fine to get a variable number of GATHERING messages before
      // COMPLETE fires (depending on how long the test runs) so we don't assert
      // any particular count.
      if (newState == IceGatheringState.GATHERING) {
        return;
      }
      assertEquals(expectedIceGatheringChanges.removeFirst(), newState);
    }

    public synchronized void expectAddStream(String label) {
      expectedAddStreamLabels.add(label);
    }

    @Override
    public synchronized void onAddStream(MediaStream stream) {
      assertEquals(expectedAddStreamLabels.removeFirst(), stream.label());
      assertEquals(1, stream.videoTracks.size());
      assertEquals(1, stream.audioTracks.size());
      assertTrue(stream.videoTracks.get(0).id().endsWith("VideoTrack"));
      assertTrue(stream.audioTracks.get(0).id().endsWith("AudioTrack"));
      assertEquals("video", stream.videoTracks.get(0).kind());
      assertEquals("audio", stream.audioTracks.get(0).kind());
      VideoRenderer renderer = createVideoRenderer(this);
      stream.videoTracks.get(0).addRenderer(renderer);
      assertNull(renderers.put(
          stream, new WeakReference<VideoRenderer>(renderer)));
    }

    public synchronized void expectRemoveStream(String label) {
      expectedRemoveStreamLabels.add(label);
    }

    @Override
    public synchronized void onRemoveStream(MediaStream stream) {
      assertEquals(expectedRemoveStreamLabels.removeFirst(), stream.label());
      WeakReference<VideoRenderer> renderer = renderers.remove(stream);
      assertNotNull(renderer);
      assertNotNull(renderer.get());
      assertEquals(1, stream.videoTracks.size());
      stream.videoTracks.get(0).removeRenderer(renderer.get());
    }

    public synchronized void expectDataChannel(String label) {
      expectedRemoteDataChannelLabels.add(label);
    }

    @Override
    public synchronized void onDataChannel(DataChannel remoteDataChannel) {
      assertEquals(expectedRemoteDataChannelLabels.removeFirst(),
                   remoteDataChannel.label());
      setDataChannel(remoteDataChannel);
      assertEquals(DataChannel.State.CONNECTING, dataChannel.state());
    }

    public synchronized void expectRenegotiationNeeded() {
      ++expectedRenegotiations;
    }

    @Override
    public synchronized void onRenegotiationNeeded() {
      assertTrue(--expectedRenegotiations >= 0);
    }

    public synchronized void expectMessage(ByteBuffer expectedBuffer,
                                           boolean expectedBinary) {
      expectedBuffers.add(
          new DataChannel.Buffer(expectedBuffer, expectedBinary));
    }

    @Override
    public synchronized void onMessage(DataChannel.Buffer buffer) {
      DataChannel.Buffer expected = expectedBuffers.removeFirst();
      assertEquals(expected.binary, buffer.binary);
      assertTrue(expected.data.equals(buffer.data));
    }

    @Override
    public synchronized void onStateChange() {
      assertEquals(expectedStateChanges.removeFirst(), dataChannel.state());
    }

    public synchronized void expectStateChange(DataChannel.State state) {
      expectedStateChanges.add(state);
    }

    @Override
    public synchronized void onComplete(StatsReport[] reports) {
      if (--expectedStatsCallbacks < 0) {
        throw new RuntimeException("Unexpected stats report: " + reports);
      }
      gotStatsReports.add(reports);
    }

    public synchronized void expectStatsCallback() {
      ++expectedStatsCallbacks;
    }

    public synchronized LinkedList<StatsReport[]> takeStatsReports() {
      LinkedList<StatsReport[]> got = gotStatsReports;
      gotStatsReports = new LinkedList<StatsReport[]>();
      return got;
    }

    // Return a set of expectations that haven't been satisfied yet, possibly
    // empty if no such expectations exist.
    public synchronized TreeSet<String> unsatisfiedExpectations() {
      TreeSet<String> stillWaitingForExpectations = new TreeSet<String>();
      if (expectedIceCandidates > 0) {  // See comment in onIceCandidate.
        stillWaitingForExpectations.add("expectedIceCandidates");
      }
      if (expectedErrors != 0) {
        stillWaitingForExpectations.add("expectedErrors: " + expectedErrors);
      }
      if (expectedSignalingChanges.size() != 0) {
        stillWaitingForExpectations.add(
            "expectedSignalingChanges: " + expectedSignalingChanges.size());
      }
      if (expectedIceConnectionChanges.size() != 0) {
        stillWaitingForExpectations.add("expectedIceConnectionChanges: " +
                                        expectedIceConnectionChanges.size());
      }
      if (expectedIceGatheringChanges.size() != 0) {
        stillWaitingForExpectations.add("expectedIceGatheringChanges: " +
                                        expectedIceGatheringChanges.size());
      }
      if (expectedAddStreamLabels.size() != 0) {
        stillWaitingForExpectations.add(
            "expectedAddStreamLabels: " + expectedAddStreamLabels.size());
      }
      if (expectedRemoveStreamLabels.size() != 0) {
        stillWaitingForExpectations.add(
            "expectedRemoveStreamLabels: " + expectedRemoveStreamLabels.size());
      }
      if (expectedFramesDelivered > 0) {
        stillWaitingForExpectations.add(
            "expectedFramesDelivered: " + expectedFramesDelivered);
      }
      if (!expectedBuffers.isEmpty()) {
        stillWaitingForExpectations.add(
            "expectedBuffers: " + expectedBuffers.size());
      }
      if (!expectedStateChanges.isEmpty()) {
        stillWaitingForExpectations.add(
            "expectedStateChanges: " + expectedStateChanges.size());
      }
      if (!expectedRemoteDataChannelLabels.isEmpty()) {
        stillWaitingForExpectations.add("expectedRemoteDataChannelLabels: " +
                                        expectedRemoteDataChannelLabels.size());
      }
      if (expectedStatsCallbacks != 0) {
        stillWaitingForExpectations.add(
            "expectedStatsCallbacks: " + expectedStatsCallbacks);
      }
      return stillWaitingForExpectations;
    }

    public void waitForAllExpectationsToBeSatisfied() {
      // TODO(fischman): problems with this approach:
      // - come up with something better than a poll loop
      // - avoid serializing expectations explicitly; the test is not as robust
      //   as it could be because it must place expectations between wait
      //   statements very precisely (e.g. frame must not arrive before its
      //   expectation, and expectation must not be registered so early as to
      //   stall a wait).  Use callbacks to fire off dependent steps instead of
      //   explicitly waiting, so there can be just a single wait at the end of
      //   the test.
      TreeSet<String> prev = null;
      TreeSet<String> stillWaitingForExpectations = unsatisfiedExpectations();
      while (!stillWaitingForExpectations.isEmpty()) {
        if (!stillWaitingForExpectations.equals(prev)) {
          System.out.println(
              name + " still waiting at\n    " +
              (new Throwable()).getStackTrace()[1] +
              "\n    for: " +
              Arrays.toString(stillWaitingForExpectations.toArray()));
        }
        try {
          Thread.sleep(10);
        } catch (InterruptedException e) {
          throw new RuntimeException(e);
        }
        prev = stillWaitingForExpectations;
        stillWaitingForExpectations = unsatisfiedExpectations();
      }
      if (prev == null) {
        System.out.println(name + " didn't need to wait at\n    " +
                           (new Throwable()).getStackTrace()[1]);
      }
    }
  }

  private static class SdpObserverLatch implements SdpObserver {
    private boolean success = false;
    private SessionDescription sdp = null;
    private String error = null;
    private CountDownLatch latch = new CountDownLatch(1);

    public SdpObserverLatch() {}

    @Override
    public void onCreateSuccess(SessionDescription sdp) {
      this.sdp = sdp;
      onSetSuccess();
    }

    @Override
    public void onSetSuccess() {
      success = true;
      latch.countDown();
    }

    @Override
    public void onCreateFailure(String error) {
      onSetFailure(error);
    }

    @Override
    public void onSetFailure(String error) {
      this.error = error;
      latch.countDown();
    }

    public boolean await() {
      try {
        assertTrue(latch.await(1000, TimeUnit.MILLISECONDS));
        return getSuccess();
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    }

    public boolean getSuccess() {
      return success;
    }

    public SessionDescription getSdp() {
      return sdp;
    }

    public String getError() {
      return error;
    }
  }

  static int videoWindowsMapped = -1;

  private static class TestRenderer implements VideoRenderer.Callbacks {
    public int width = -1;
    public int height = -1;
    public int numFramesDelivered = 0;

    private void setSize(int width, int height) {
      assertEquals(this.width, -1);
      assertEquals(this.height, -1);
      this.width = width;
      this.height = height;
    }

    @Override
    public void renderFrame(VideoRenderer.I420Frame frame) {
      ++numFramesDelivered;
    }
  }

  private static VideoRenderer createVideoRenderer(
      VideoRenderer.Callbacks videoCallbacks) {
    if (!RENDER_TO_GUI) {
      return new VideoRenderer(videoCallbacks);
    }
    ++videoWindowsMapped;
    assertTrue(videoWindowsMapped < 4);
    int x = videoWindowsMapped % 2 != 0 ? 700 : 0;
    int y = videoWindowsMapped >= 2 ? 0 : 500;
    return VideoRenderer.createGui(x, y);
  }

  // Return a weak reference to test that ownership is correctly held by
  // PeerConnection, not by test code.
  private static WeakReference<MediaStream> addTracksToPC(
      PeerConnectionFactory factory, PeerConnection pc,
      VideoSource videoSource,
      String streamLabel, String videoTrackId, String audioTrackId,
      VideoRenderer.Callbacks videoCallbacks) {
    MediaStream lMS = factory.createLocalMediaStream(streamLabel);
    VideoTrack videoTrack =
        factory.createVideoTrack(videoTrackId, videoSource);
    assertNotNull(videoTrack);
    VideoRenderer videoRenderer = createVideoRenderer(videoCallbacks);
    assertNotNull(videoRenderer);
    videoTrack.addRenderer(videoRenderer);
    lMS.addTrack(videoTrack);
    // Just for fun, let's remove and re-add the track.
    lMS.removeTrack(videoTrack);
    lMS.addTrack(videoTrack);
    lMS.addTrack(factory.createAudioTrack(
        audioTrackId, factory.createAudioSource(new MediaConstraints())));
    pc.addStream(lMS);
    return new WeakReference<MediaStream>(lMS);
  }

  // Used for making sure thread handles are not leaked.
  // Call initializeThreadCheck before a test and finalizeThreadCheck after
  // a test.
  void initializeThreadCheck() {
    System.gc();  // Encourage any GC-related threads to start up.
    threadsBeforeTest = allThreads();
  }

  void finalizeThreadCheck() throws Exception {
    TreeSet<String> threadsAfterTest = allThreads();
    assertEquals(threadsBeforeTest, threadsAfterTest);
    Thread.sleep(100);
  }

  void doTest() throws Exception {
    PeerConnectionFactory factory = new PeerConnectionFactory();
    // Uncomment to get ALL WebRTC tracing and SENSITIVE libjingle logging.
    // NOTE: this _must_ happen while |factory| is alive!
    // Logging.enableTracing(
    //     "/tmp/PeerConnectionTest-log.txt",
    //     EnumSet.of(Logging.TraceLevel.TRACE_ALL),
    //     Logging.Severity.LS_SENSITIVE);

    // Allow loopback interfaces too since our Android devices often don't
    // have those.
    PeerConnectionFactory.Options options = new PeerConnectionFactory.Options();
    options.networkIgnoreMask = 0;
    factory.setOptions(options);

    MediaConstraints pcConstraints = new MediaConstraints();
    pcConstraints.mandatory.add(
        new MediaConstraints.KeyValuePair("DtlsSrtpKeyAgreement", "true"));

    LinkedList<PeerConnection.IceServer> iceServers =
        new LinkedList<PeerConnection.IceServer>();
    iceServers.add(new PeerConnection.IceServer(
        "stun:stun.l.google.com:19302"));
    iceServers.add(new PeerConnection.IceServer(
        "turn:fake.example.com", "fakeUsername", "fakePassword"));
    ObserverExpectations offeringExpectations =
        new ObserverExpectations("PCTest:offerer");
    PeerConnection offeringPC = factory.createPeerConnection(
        iceServers, pcConstraints, offeringExpectations);
    assertNotNull(offeringPC);

    ObserverExpectations answeringExpectations =
        new ObserverExpectations("PCTest:answerer");
    PeerConnection answeringPC = factory.createPeerConnection(
        iceServers, pcConstraints, answeringExpectations);
    assertNotNull(answeringPC);

    // We want to use the same camera for offerer & answerer, so create it here
    // instead of in addTracksToPC.
    VideoSource videoSource = factory.createVideoSource(
        VideoCapturer.create(""), new MediaConstraints());

    offeringExpectations.expectRenegotiationNeeded();
    WeakReference<MediaStream> oLMS = addTracksToPC(
        factory, offeringPC, videoSource, "offeredMediaStream",
        "offeredVideoTrack", "offeredAudioTrack", offeringExpectations);

    offeringExpectations.expectRenegotiationNeeded();
    DataChannel offeringDC = offeringPC.createDataChannel(
        "offeringDC", new DataChannel.Init());
    assertEquals("offeringDC", offeringDC.label());

    offeringExpectations.setDataChannel(offeringDC);
    SdpObserverLatch sdpLatch = new SdpObserverLatch();
    offeringPC.createOffer(sdpLatch, new MediaConstraints());
    assertTrue(sdpLatch.await());
    SessionDescription offerSdp = sdpLatch.getSdp();
    assertEquals(offerSdp.type, SessionDescription.Type.OFFER);
    assertFalse(offerSdp.description.isEmpty());

    sdpLatch = new SdpObserverLatch();
    answeringExpectations.expectSignalingChange(
        SignalingState.HAVE_REMOTE_OFFER);
    answeringExpectations.expectAddStream("offeredMediaStream");
    // SCTP DataChannels are announced via OPEN messages over the established
    // connection (not via SDP), so answeringExpectations can only register
    // expecting the channel during ICE, below.
    answeringPC.setRemoteDescription(sdpLatch, offerSdp);
    assertEquals(
        PeerConnection.SignalingState.STABLE, offeringPC.signalingState());
    assertTrue(sdpLatch.await());
    assertNull(sdpLatch.getSdp());

    answeringExpectations.expectRenegotiationNeeded();
    WeakReference<MediaStream> aLMS = addTracksToPC(
        factory, answeringPC, videoSource, "answeredMediaStream",
        "answeredVideoTrack", "answeredAudioTrack", answeringExpectations);

    sdpLatch = new SdpObserverLatch();
    answeringPC.createAnswer(sdpLatch, new MediaConstraints());
    assertTrue(sdpLatch.await());
    SessionDescription answerSdp = sdpLatch.getSdp();
    assertEquals(answerSdp.type, SessionDescription.Type.ANSWER);
    assertFalse(answerSdp.description.isEmpty());

    offeringExpectations.expectIceCandidates(2);
    answeringExpectations.expectIceCandidates(2);

    offeringExpectations.expectIceGatheringChange(IceGatheringState.COMPLETE);
    answeringExpectations.expectIceGatheringChange(IceGatheringState.COMPLETE);

    sdpLatch = new SdpObserverLatch();
    answeringExpectations.expectSignalingChange(SignalingState.STABLE);
    answeringPC.setLocalDescription(sdpLatch, answerSdp);
    assertTrue(sdpLatch.await());
    assertNull(sdpLatch.getSdp());

    sdpLatch = new SdpObserverLatch();
    offeringExpectations.expectSignalingChange(SignalingState.HAVE_LOCAL_OFFER);
    offeringPC.setLocalDescription(sdpLatch, offerSdp);
    assertTrue(sdpLatch.await());
    assertNull(sdpLatch.getSdp());
    sdpLatch = new SdpObserverLatch();
    offeringExpectations.expectSignalingChange(SignalingState.STABLE);
    offeringExpectations.expectAddStream("answeredMediaStream");

    offeringExpectations.expectIceConnectionChange(
        IceConnectionState.CHECKING);
    offeringExpectations.expectIceConnectionChange(
        IceConnectionState.CONNECTED);
    // TODO(bemasc): uncomment once delivery of ICECompleted is reliable
    // (https://code.google.com/p/webrtc/issues/detail?id=3021).
    //
    // offeringExpectations.expectIceConnectionChange(
    //     IceConnectionState.COMPLETED);
    answeringExpectations.expectIceConnectionChange(
        IceConnectionState.CHECKING);
    answeringExpectations.expectIceConnectionChange(
        IceConnectionState.CONNECTED);

    offeringPC.setRemoteDescription(sdpLatch, answerSdp);
    assertTrue(sdpLatch.await());
    assertNull(sdpLatch.getSdp());

    assertEquals(offeringPC.getLocalDescription().type, offerSdp.type);
    assertEquals(offeringPC.getRemoteDescription().type, answerSdp.type);
    assertEquals(answeringPC.getLocalDescription().type, answerSdp.type);
    assertEquals(answeringPC.getRemoteDescription().type, offerSdp.type);

    if (!RENDER_TO_GUI) {
      // Wait for at least some frames to be delivered at each end (number
      // chosen arbitrarily).
      offeringExpectations.expectFramesDelivered(10);
      answeringExpectations.expectFramesDelivered(10);
    }

    offeringExpectations.expectStateChange(DataChannel.State.OPEN);
    // See commentary about SCTP DataChannels above for why this is here.
    answeringExpectations.expectDataChannel("offeringDC");
    answeringExpectations.expectStateChange(DataChannel.State.OPEN);

    for (IceCandidate candidate : offeringExpectations.gotIceCandidates) {
      answeringPC.addIceCandidate(candidate);
    }
    offeringExpectations.gotIceCandidates.clear();
    for (IceCandidate candidate : answeringExpectations.gotIceCandidates) {
      offeringPC.addIceCandidate(candidate);
    }
    answeringExpectations.gotIceCandidates.clear();

    offeringExpectations.waitForAllExpectationsToBeSatisfied();
    answeringExpectations.waitForAllExpectationsToBeSatisfied();

    assertEquals(
        PeerConnection.SignalingState.STABLE, offeringPC.signalingState());
    assertEquals(
        PeerConnection.SignalingState.STABLE, answeringPC.signalingState());

    // Test send & receive UTF-8 text.
    answeringExpectations.expectMessage(
        ByteBuffer.wrap("hello!".getBytes(Charset.forName("UTF-8"))), false);
    DataChannel.Buffer buffer = new DataChannel.Buffer(
        ByteBuffer.wrap("hello!".getBytes(Charset.forName("UTF-8"))), false);
    assertTrue(offeringExpectations.dataChannel.send(buffer));
    answeringExpectations.waitForAllExpectationsToBeSatisfied();

    // Construct this binary message two different ways to ensure no
    // shortcuts are taken.
    ByteBuffer expectedBinaryMessage = ByteBuffer.allocateDirect(5);
    for (byte i = 1; i < 6; ++i) {
      expectedBinaryMessage.put(i);
    }
    expectedBinaryMessage.flip();
    offeringExpectations.expectMessage(expectedBinaryMessage, true);
    assertTrue(answeringExpectations.dataChannel.send(
        new DataChannel.Buffer(
            ByteBuffer.wrap(new byte[] { 1, 2, 3, 4, 5 }), true)));
    offeringExpectations.waitForAllExpectationsToBeSatisfied();

    offeringExpectations.expectStateChange(DataChannel.State.CLOSING);
    answeringExpectations.expectStateChange(DataChannel.State.CLOSING);
    offeringExpectations.expectStateChange(DataChannel.State.CLOSED);
    answeringExpectations.expectStateChange(DataChannel.State.CLOSED);
    answeringExpectations.dataChannel.close();
    offeringExpectations.dataChannel.close();

    if (RENDER_TO_GUI) {
      try {
        Thread.sleep(3000);
      } catch (Throwable t) {
        throw new RuntimeException(t);
      }
    }

    // TODO(fischman) MOAR test ideas:
    // - Test that PC.removeStream() works; requires a second
    //   createOffer/createAnswer dance.
    // - audit each place that uses |constraints| for specifying non-trivial
    //   constraints (and ensure they're honored).
    // - test error cases
    // - ensure reasonable coverage of _jni.cc is achieved.  Coverage is
    //   extra-important because of all the free-text (class/method names, etc)
    //   in JNI-style programming; make sure no typos!
    // - Test that shutdown mid-interaction is crash-free.

    // Free the Java-land objects, collect them, and sleep a bit to make sure we
    // don't get late-arrival crashes after the Java-land objects have been
    // freed.
    shutdownPC(offeringPC, offeringExpectations);
    offeringPC = null;
    shutdownPC(answeringPC, answeringExpectations);
    answeringPC = null;
    videoSource.dispose();
    factory.dispose();
    System.gc();
  }

  private static void shutdownPC(
      PeerConnection pc, ObserverExpectations expectations) {
    expectations.dataChannel.unregisterObserver();
    expectations.dataChannel.dispose();
    expectations.expectStatsCallback();
    assertTrue(pc.getStats(expectations, null));
    expectations.waitForAllExpectationsToBeSatisfied();
    expectations.expectIceConnectionChange(IceConnectionState.CLOSED);
    expectations.expectSignalingChange(SignalingState.CLOSED);
    pc.close();
    expectations.waitForAllExpectationsToBeSatisfied();
    expectations.expectStatsCallback();
    assertTrue(pc.getStats(expectations, null));
    expectations.waitForAllExpectationsToBeSatisfied();

    System.out.println("FYI stats: ");
    int reportIndex = -1;
    for (StatsReport[] reports : expectations.takeStatsReports()) {
      System.out.println(" Report #" + (++reportIndex));
      for (int i = 0; i < reports.length; ++i) {
        System.out.println("  " + reports[i].toString());
      }
    }
    assertEquals(1, reportIndex);
    System.out.println("End stats.");

    pc.dispose();
  }

  // Returns a set of thread IDs belonging to this process, as Strings.
  private static TreeSet<String> allThreads() {
    TreeSet<String> threads = new TreeSet<String>();
    // This pokes at /proc instead of using the Java APIs because we're also
    // looking for libjingle/webrtc native threads, most of which won't have
    // attached to the JVM.
    for (String threadId : (new File("/proc/self/task")).list()) {
      threads.add(threadId);
    }
    return threads;
  }
}
