Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(418)

Side by Side Diff: talk/app/webrtc/java/testcommon/src/org/webrtc/PeerConnectionTest.java

Issue 1639583003: Fixing bug in MediaStream.java that caused double disposal of track. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * libjingle 2 * libjingle
3 * Copyright 2013 Google Inc. 3 * Copyright 2013 Google Inc.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright notice, 8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer. 9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice, 10 * 2. Redistributions in binary form must reproduce the above copyright notice,
(...skipping 21 matching lines...) Expand all
32 import org.webrtc.PeerConnection.SignalingState; 32 import org.webrtc.PeerConnection.SignalingState;
33 33
34 import java.io.File; 34 import java.io.File;
35 import java.lang.ref.WeakReference; 35 import java.lang.ref.WeakReference;
36 import java.nio.ByteBuffer; 36 import java.nio.ByteBuffer;
37 import java.nio.charset.Charset; 37 import java.nio.charset.Charset;
38 import java.util.Arrays; 38 import java.util.Arrays;
39 import java.util.IdentityHashMap; 39 import java.util.IdentityHashMap;
40 import java.util.LinkedList; 40 import java.util.LinkedList;
41 import java.util.List; 41 import java.util.List;
42 import java.util.HashSet;
42 import java.util.Map; 43 import java.util.Map;
43 import java.util.TreeSet; 44 import java.util.TreeSet;
44 import java.util.concurrent.CountDownLatch; 45 import java.util.concurrent.CountDownLatch;
45 import java.util.concurrent.TimeUnit; 46 import java.util.concurrent.TimeUnit;
46 47
47 import static junit.framework.Assert.*; 48 import static junit.framework.Assert.*;
48 49
49 /** End-to-end tests for PeerConnection.java. */ 50 /** End-to-end tests for PeerConnection.java. */
50 public class PeerConnectionTest { 51 public class PeerConnectionTest {
51 // Set to true to render video. 52 // Set to true to render video.
(...skipping 29 matching lines...) Expand all
81 private DataChannel dataChannel; 82 private DataChannel dataChannel;
82 private LinkedList<DataChannel.Buffer> expectedBuffers = 83 private LinkedList<DataChannel.Buffer> expectedBuffers =
83 new LinkedList<DataChannel.Buffer>(); 84 new LinkedList<DataChannel.Buffer>();
84 private LinkedList<DataChannel.State> expectedStateChanges = 85 private LinkedList<DataChannel.State> expectedStateChanges =
85 new LinkedList<DataChannel.State>(); 86 new LinkedList<DataChannel.State>();
86 private LinkedList<String> expectedRemoteDataChannelLabels = 87 private LinkedList<String> expectedRemoteDataChannelLabels =
87 new LinkedList<String>(); 88 new LinkedList<String>();
88 private int expectedStatsCallbacks = 0; 89 private int expectedStatsCallbacks = 0;
89 private LinkedList<StatsReport[]> gotStatsReports = 90 private LinkedList<StatsReport[]> gotStatsReports =
90 new LinkedList<StatsReport[]>(); 91 new LinkedList<StatsReport[]>();
92 private final HashSet<MediaStream> gotRemoteStreams =
93 new HashSet<MediaStream>();
91 94
92 public ObserverExpectations(String name) { 95 public ObserverExpectations(String name) {
93 this.name = name; 96 this.name = name;
94 } 97 }
95 98
96 public synchronized void setDataChannel(DataChannel dataChannel) { 99 public synchronized void setDataChannel(DataChannel dataChannel) {
97 assertNull(this.dataChannel); 100 assertNull(this.dataChannel);
98 this.dataChannel = dataChannel; 101 this.dataChannel = dataChannel;
99 this.dataChannel.registerObserver(this); 102 this.dataChannel.registerObserver(this);
100 assertNotNull(this.dataChannel); 103 assertNotNull(this.dataChannel);
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 assertEquals(1, stream.videoTracks.size()); 209 assertEquals(1, stream.videoTracks.size());
207 assertEquals(1, stream.audioTracks.size()); 210 assertEquals(1, stream.audioTracks.size());
208 assertTrue(stream.videoTracks.get(0).id().endsWith("VideoTrack")); 211 assertTrue(stream.videoTracks.get(0).id().endsWith("VideoTrack"));
209 assertTrue(stream.audioTracks.get(0).id().endsWith("AudioTrack")); 212 assertTrue(stream.audioTracks.get(0).id().endsWith("AudioTrack"));
210 assertEquals("video", stream.videoTracks.get(0).kind()); 213 assertEquals("video", stream.videoTracks.get(0).kind());
211 assertEquals("audio", stream.audioTracks.get(0).kind()); 214 assertEquals("audio", stream.audioTracks.get(0).kind());
212 VideoRenderer renderer = createVideoRenderer(this); 215 VideoRenderer renderer = createVideoRenderer(this);
213 stream.videoTracks.get(0).addRenderer(renderer); 216 stream.videoTracks.get(0).addRenderer(renderer);
214 assertNull(renderers.put( 217 assertNull(renderers.put(
215 stream, new WeakReference<VideoRenderer>(renderer))); 218 stream, new WeakReference<VideoRenderer>(renderer)));
219 gotRemoteStreams.add(stream);
216 } 220 }
217 221
218 public synchronized void expectRemoveStream(String label) { 222 public synchronized void expectRemoveStream(String label) {
219 expectedRemoveStreamLabels.add(label); 223 expectedRemoveStreamLabels.add(label);
220 } 224 }
221 225
222 @Override 226 @Override
223 public synchronized void onRemoveStream(MediaStream stream) { 227 public synchronized void onRemoveStream(MediaStream stream) {
224 assertEquals(expectedRemoveStreamLabels.removeFirst(), stream.label()); 228 assertEquals(expectedRemoveStreamLabels.removeFirst(), stream.label());
225 WeakReference<VideoRenderer> renderer = renderers.remove(stream); 229 WeakReference<VideoRenderer> renderer = renderers.remove(stream);
226 assertNotNull(renderer); 230 assertNotNull(renderer);
227 assertNotNull(renderer.get()); 231 assertNotNull(renderer.get());
228 assertEquals(1, stream.videoTracks.size()); 232 assertEquals(1, stream.videoTracks.size());
229 stream.videoTracks.get(0).removeRenderer(renderer.get()); 233 stream.videoTracks.get(0).removeRenderer(renderer.get());
234 gotRemoteStreams.remove(stream);
230 } 235 }
231 236
232 public synchronized void expectDataChannel(String label) { 237 public synchronized void expectDataChannel(String label) {
233 expectedRemoteDataChannelLabels.add(label); 238 expectedRemoteDataChannelLabels.add(label);
234 } 239 }
235 240
236 @Override 241 @Override
237 public synchronized void onDataChannel(DataChannel remoteDataChannel) { 242 public synchronized void onDataChannel(DataChannel remoteDataChannel) {
238 assertEquals(expectedRemoteDataChannelLabels.removeFirst(), 243 assertEquals(expectedRemoteDataChannelLabels.removeFirst(),
239 remoteDataChannel.label()); 244 remoteDataChannel.label());
(...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after
709 offeringExpectations.dataChannel.close(); 714 offeringExpectations.dataChannel.close();
710 715
711 if (RENDER_TO_GUI) { 716 if (RENDER_TO_GUI) {
712 try { 717 try {
713 Thread.sleep(3000); 718 Thread.sleep(3000);
714 } catch (Throwable t) { 719 } catch (Throwable t) {
715 throw new RuntimeException(t); 720 throw new RuntimeException(t);
716 } 721 }
717 } 722 }
718 723
724 // Do another negotiation, removing the video track from one peer.
AlexG 2016/01/26 22:03:36 I think it should be under the boolean flag in doT
Taylor Brandstetter 2016/01/26 22:43:10 I just went ahead and created a separate test meth
725 // This previously caused a crash on pc.dispose().
726 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=5128
727 VideoTrack offererVideoTrack = oLMS.get().videoTracks.get(0);
728 // Note that when we call removeTrack, we regain responsibility for
729 // disposing of the track.
730 oLMS.get().removeTrack(offererVideoTrack);
731 sdpLatch = new SdpObserverLatch();
732 offeringPC.createOffer(sdpLatch, new MediaConstraints());
733 assertTrue(sdpLatch.await());
734 offerSdp = sdpLatch.getSdp();
735 assertEquals(offerSdp.type, SessionDescription.Type.OFFER);
736 assertFalse(offerSdp.description.isEmpty());
737
738 // Set remote offer.
739 sdpLatch = new SdpObserverLatch();
740 answeringExpectations.expectSignalingChange(
741 SignalingState.HAVE_REMOTE_OFFER);
742 answeringPC.setRemoteDescription(sdpLatch, offerSdp);
743 assertEquals(
744 PeerConnection.SignalingState.STABLE, offeringPC.signalingState());
745 assertTrue(sdpLatch.await());
746 assertNull(sdpLatch.getSdp());
747
748 sdpLatch = new SdpObserverLatch();
749 answeringPC.createAnswer(sdpLatch, new MediaConstraints());
750 assertTrue(sdpLatch.await());
751 answerSdp = sdpLatch.getSdp();
752 assertEquals(answerSdp.type, SessionDescription.Type.ANSWER);
753 assertFalse(answerSdp.description.isEmpty());
754
755 // Set local answer.
756 sdpLatch = new SdpObserverLatch();
757 answeringExpectations.expectSignalingChange(SignalingState.STABLE);
758 answeringPC.setLocalDescription(sdpLatch, answerSdp);
759 assertTrue(sdpLatch.await());
760 assertNull(sdpLatch.getSdp());
761
762 // Set local offer.
763 sdpLatch = new SdpObserverLatch();
764 offeringExpectations.expectSignalingChange(SignalingState.HAVE_LOCAL_OFFER);
765 offeringPC.setLocalDescription(sdpLatch, offerSdp);
766 assertTrue(sdpLatch.await());
767 assertNull(sdpLatch.getSdp());
768
769 // Set remote answer.
770 sdpLatch = new SdpObserverLatch();
771 offeringExpectations.expectSignalingChange(SignalingState.STABLE);
772 offeringPC.setRemoteDescription(sdpLatch, answerSdp);
773 assertTrue(sdpLatch.await());
774 assertNull(sdpLatch.getSdp());
775
776 // Make sure the track was really removed.
777 // TODO(deadbeef): Currently the expectation is that the video track's
778 // state will be set to "ended". However, in the future, it's likely that
779 // the video track will be completely removed from the remote stream
780 // (as it is on the C++ level).
781 MediaStream aRMS = answeringExpectations.gotRemoteStreams.iterator().next();
782 assertEquals(aRMS.videoTracks.get(0).state(), MediaStreamTrack.State.ENDED);
783
719 // TODO(fischman) MOAR test ideas: 784 // TODO(fischman) MOAR test ideas:
720 // - Test that PC.removeStream() works; requires a second 785 // - Test that PC.removeStream() works; requires a second
721 // createOffer/createAnswer dance. 786 // createOffer/createAnswer dance.
722 // - audit each place that uses |constraints| for specifying non-trivial 787 // - audit each place that uses |constraints| for specifying non-trivial
723 // constraints (and ensure they're honored). 788 // constraints (and ensure they're honored).
724 // - test error cases 789 // - test error cases
725 // - ensure reasonable coverage of _jni.cc is achieved. Coverage is 790 // - ensure reasonable coverage of _jni.cc is achieved. Coverage is
726 // extra-important because of all the free-text (class/method names, etc) 791 // extra-important because of all the free-text (class/method names, etc)
727 // in JNI-style programming; make sure no typos! 792 // in JNI-style programming; make sure no typos!
728 // - Test that shutdown mid-interaction is crash-free. 793 // - Test that shutdown mid-interaction is crash-free.
729 794
730 // Free the Java-land objects, collect them, and sleep a bit to make sure we 795 // Free the Java-land objects, collect them, and sleep a bit to make sure we
731 // don't get late-arrival crashes after the Java-land objects have been 796 // don't get late-arrival crashes after the Java-land objects have been
732 // freed. 797 // freed.
733 shutdownPC(offeringPC, offeringExpectations); 798 shutdownPC(offeringPC, offeringExpectations);
734 offeringPC = null; 799 offeringPC = null;
735 shutdownPC(answeringPC, answeringExpectations); 800 shutdownPC(answeringPC, answeringExpectations);
736 answeringPC = null; 801 answeringPC = null;
802 offererVideoTrack.dispose();
737 videoSource.dispose(); 803 videoSource.dispose();
738 factory.dispose(); 804 factory.dispose();
739 System.gc(); 805 System.gc();
740 } 806 }
741 807
742 private static void shutdownPC( 808 private static void shutdownPC(
743 PeerConnection pc, ObserverExpectations expectations) { 809 PeerConnection pc, ObserverExpectations expectations) {
744 expectations.dataChannel.unregisterObserver(); 810 expectations.dataChannel.unregisterObserver();
745 expectations.dataChannel.dispose(); 811 expectations.dataChannel.dispose();
746 expectations.expectStatsCallback(); 812 expectations.expectStatsCallback();
(...skipping 26 matching lines...) Expand all
773 TreeSet<String> threads = new TreeSet<String>(); 839 TreeSet<String> threads = new TreeSet<String>();
774 // This pokes at /proc instead of using the Java APIs because we're also 840 // This pokes at /proc instead of using the Java APIs because we're also
775 // looking for libjingle/webrtc native threads, most of which won't have 841 // looking for libjingle/webrtc native threads, most of which won't have
776 // attached to the JVM. 842 // attached to the JVM.
777 for (String threadId : (new File("/proc/self/task")).list()) { 843 for (String threadId : (new File("/proc/self/task")).list()) {
778 threads.add(threadId); 844 threads.add(threadId);
779 } 845 }
780 return threads; 846 return threads;
781 } 847 }
782 } 848 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698