(FRONT) FRONT (2025)

Android Test.  Return to main page  

   1:  package com.voipplus.mmsclient;
   2:  
   3:  import android.content.ComponentName;
   4:  import android.content.Context;
   5:  import android.content.Intent;
   6:  import android.content.ServiceConnection;
   7:  import android.content.res.AssetManager;
   8:  import android.os.IBinder;
   9:  import android.util.Log;
  10:  
  11:  import androidx.test.core.app.ApplicationProvider;
  12:  import androidx.test.platform.app.InstrumentationRegistry;
  13:  
  14:  import com.voipplus.mmsclient.WebRTC.WebRTCEventListener;
  15:  import com.voipplus.mmsclient.WebRTC.WebRTCService;
  16:  import com.voipplus.mmsclient.WebRTC.WebRTCServiceStarter;
  17:  import com.voipplus.mmsclient.WebRTC.WebRTCState;
  18:  import com.voipplus.mmsclient.WebRTC.WebRTCUtils;
  19:  
  20:  import org.junit.After;
  21:  import org.junit.Before;
  22:  import org.junit.Test;
  23:  import org.mockito.Mock;
  24:  
  25:  import java.io.ByteArrayOutputStream;
  26:  import java.io.IOException;
  27:  import java.io.InputStream;
  28:  import java.nio.ByteBuffer;
  29:  import java.util.concurrent.CountDownLatch;
  30:  import java.util.concurrent.TimeUnit;
  31:  
  32:  import livekit.org.webrtc.AudioTrack;
  33:  import livekit.org.webrtc.DataChannel;
  34:  import livekit.org.webrtc.IceCandidate;
  35:  import livekit.org.webrtc.MediaStream;
  36:  import livekit.org.webrtc.PeerConnection;
  37:  import livekit.org.webrtc.SessionDescription;
  38:  import livekit.org.webrtc.VideoTrack;
  39:  import okhttp3.OkHttpClient;
  40:  import okhttp3.Request;
  41:  import okhttp3.Response;
  42:  import okhttp3.WebSocket;
  43:  import okhttp3.WebSocketListener;
  44:  
  45:  public class WebRTCServiceTest {
  46:      private static final String TAG = "WebRTCServiceTest";
  47:      private static final String REAL_WEB_SOCKET_URL = "ws://10.0.2.2:3000";
  48:      private WebRTCService webRTCService;
  49:      private CountDownLatch serviceConnectionLatch;
  50:      private DataChannel dataChannel;
  51:      private WebSocket webSocket;
  52:      private WebRTCServiceStarter webRTCServiceStarter;
  53:      private ServiceConnection serviceConnection;
  54:  
  55:      @Mock
  56:      private WebRTCEventListener webRTCEventListener;
  57:  
  58:      //region Setup and Teardown
  59:      @Before
  60:      public void setUp() throws Exception {
  61:          Log.d(TAG, "🛠️ setUp: Starting test setup");
  62:  
  63:          Context context = ApplicationProvider.getApplicationContext();
  64:          serviceConnectionLatch = new CountDownLatch(1); // Ensure service is connected before proceeding
  65:  
  66:          // Define Service Connection
  67:          serviceConnection = new ServiceConnection() {
  68:              @Override
  69:              public void onServiceConnected(ComponentName name, IBinder binder) {
  70:                  Log.d(TAG, "🔗 onServiceConnected: WebRTCService connected");
  71:  
  72:                  WebRTCService.LocalBinder localBinder = (WebRTCService.LocalBinder) binder;
  73:                  webRTCService = localBinder.getService();
  74:  
  75:                  if (webRTCService == null) {
  76:                      Log.e(TAG, "❌ webRTCService is NULL after binding!");
  77:                      throw new IllegalStateException("❌ webRTCService is NULL after binding. Cannot continue.");
  78:                  } else {
  79:                      Log.d(TAG, "✅ webRTCService initialized.");
  80:                      webRTCService.printState("Test", "After service binding");
  81:                  }
  82:  
  83:                  serviceConnectionLatch.countDown(); // Notify that service is ready
  84:              }
  85:  
  86:              @Override
  87:              public void onServiceDisconnected(ComponentName name) {
  88:                  Log.d(TAG, "🔴 onServiceDisconnected: WebRTCService disconnected");
  89:                  webRTCService = null;
  90:              }
  91:          };
  92:  
  93:          // 🚀 Start the WebRTC Service FIRST
  94:          Intent serviceIntent = new Intent(context, WebRTCService.class);
  95:          serviceIntent.putExtra("SIGNALING_SERVER_URL", REAL_WEB_SOCKET_URL);
  96:          context.startService(serviceIntent);
  97:  
  98:          // 🔗 Now BIND to the Service
  99:          boolean bindSuccess = context.bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
 100:          if (!bindSuccess) {
 101:              throw new IllegalStateException("❌ Failed to bind WebRTCService.");
 102:          }
 103:  
 104:          // ⏳ Wait for service to be connected
 105:          boolean serviceReady = serviceConnectionLatch.await(5, TimeUnit.SECONDS);
 106:          if (!serviceReady) {
 107:              throw new IllegalStateException("❌ Service binding timed out. WebRTCService not initialized.");
 108:          }
 109:  
 110:          // 🚨 If service is still null, fail early
 111:          if (webRTCService == null) {
 112:              throw new IllegalStateException("❌ webRTCService is NULL after binding. Cannot continue.");
 113:          }
 114:  
 115:          // ✅ **Now it's safe to call methods on 'webRTCService'**
 116:          WebRTCUtils.debugInfo(TAG, "✅ WebRTCService is fully initialized",
 117:                  webRTCService.getWebRTCState(),
 118:                  webRTCService.safeGetPeerConnection(),
 119:                  webRTCService.safeGetDataChannel(),
 120:                  webRTCService.safeGetWebSocket(),
 121:                  webRTCService.getSafeSignalinServerUrl());
 122:  
 123:          // 🕵️‍♂️ Now wait for WebSocket AFTER service is initialized
 124:          waitForWebSocket();
 125:      }
 126:  
 127:  
 128:      @After
 129:      public void tearDown() {
 130:          Log.d(TAG, "tearDown: Method called");
 131:          if (webSocket != null) {
 132:              webSocket.close(1000, "Test complete");
 133:          }
 134:      }
 135:      private void waitForServiceInitialization() throws InterruptedException {
 136:          int attempts = 0;
 137:          int maxAttempts = 20; // Wait up to ~10 seconds (assuming 500ms delay)
 138:          long waitTimeMs = 500;
 139:  
 140:          while (attempts < maxAttempts) {
 141:              if (webRTCService != null && webRTCService.getWebRTCState() != WebRTCState.IDLE) {
 142:                  WebRTCUtils.debugInfo(TAG, "✅ WebRTCService is initialized. Proceeding with test.", webRTCService.getWebRTCState(),
 143:                          webRTCService.safeGetPeerConnection(), webRTCService.safeGetDataChannel(), webRTCService.safeGetWebSocket(), webRTCService.getSafeSignalinServerUrl());
 144:                  return;
 145:              }
 146:              WebRTCUtils.debugInfo(TAG, "⏳ Waiting for WebRTCService to initialize... Attempt " + (attempts + 1), null, null, null, null, null);
 147:              Thread.sleep(waitTimeMs);
 148:              attempts++;
 149:          }
 150:  
 151:          throw new IllegalStateException("❌ Service binding timed out. WebRTCService not initialized.");
 152:      }
 153:  
 154:      //endregion
 155:  
 156:      //region WebSocket Management
 157:      @Before
 158:      public void initWebSocketConnection() {
 159:          webRTCService.printState(TAG, "initWebSocketConnection: Method called");
 160:          OkHttpClient client = new OkHttpClient();
 161:          Request request = new Request.Builder().url(REAL_WEB_SOCKET_URL).build();
 162:          webSocket = client.newWebSocket(request, new WebSocketListener() {
 163:              @Override
 164:              public void onOpen(WebSocket webSocket, Response response) {
 165:                  webRTCService.printState(TAG, "WebSocket onOpen: WebSocket connection opened");
 166:                  webRTCService.printState(TAG, "Local variables: webSocket=" + webSocket + ", response=" + response);
 167:              }
 168:  
 169:              @Override
 170:              public void onMessage(WebSocket webSocket, String text) {
 171:                  webRTCService.printState(TAG, "WebSocket onMessage: Received message: " + text);
 172:                  webRTCService.printState(TAG, "Local variables: text=" + text);
 173:              }
 174:  
 175:              @Override
 176:              public void onFailure(WebSocket webSocket, Throwable t, Response response) {
 177:                  webRTCService.printState(TAG, "WebSocket onFailure: Error: " + t.getMessage());
 178:                  webRTCService.printState(TAG, "Local variables: t=" + t + ", response=" + response);
 179:              }
 180:          });
 181:      }
 182:  
 183:      private void waitForWebSocket() throws InterruptedException {
 184:          int attempts = 0;
 185:          while (webRTCService == null || !webRTCService.getSignalingManager().isWebSocketConnected()) {
 186:              if (attempts++ > 20) {
 187:                  if (webRTCService != null) {
 188:                      webRTCService.printState(TAG,"❌ WebSocket initialization failed. Cannot proceed with SDP offer.");
 189:                  } else {
 190:                      Log.e(TAG, "❌ webRTCService is NULL in waitForWebSocket()");
 191:                  }
 192:                  return;
 193:              }
 194:              if (webRTCService != null) {
 195:                  webRTCService.printState(TAG, "⏳ Waiting for WebSocket to be ready... Attempt " + attempts);
 196:              } else {
 197:                  Log.e(TAG, "⏳ Waiting for WebSocket, but webRTCService is NULL. Attempt " + attempts);
 198:              }
 199:              Thread.sleep(500);
 200:          }
 201:          webRTCService.printState(TAG, "✅ WebSocket is ready. Proceeding with SDP offer.");
 202:      }
 203:      //endregion
 204:  
 205:      //region Test Methods
 206:      @Test
 207:      public void testSendTestMediaOverDataChannel() throws InterruptedException {
 208:          webRTCService.printState(TAG, "testSendTestMediaOverDataChannel: Starting test");
 209:  
 210:          // Ensure WebSocket is initialized
 211:          waitForWebSocket();
 212:  
 213:          webRTCService.createOffer();
 214:  
 215:          // Ensure WebRTCService is fully bound
 216:          if (webRTCService == null) {
 217:              webRTCService.printState(TAG, "❌ WebRTCService is not initialized.");
 218:              return;
 219:          }
 220:  
 221:          webRTCService.addWebRTCEventListener(new WebRTCEventListener() {
 222:              @Override
 223:              public void onSignalingChange(PeerConnection.SignalingState signalingState) {
 224:                  webRTCService.printState(TAG, "🔄 onSignalingChange: State changed to " + signalingState);
 225:              }
 226:  
 227:              @Override
 228:              public void onIceConnectionChange(PeerConnection.IceConnectionState iceConnectionState) {
 229:                  webRTCService.printState(TAG, "❄️ onIceConnectionChange: IceConnection state changed to " + iceConnectionState);
 230:              }
 231:  
 232:              @Override
 233:              public void onIceConnectionReceivingChange(boolean receiving) {
 234:                  webRTCService.printState(TAG, "📡 onIceConnectionReceivingChange: Receiving=" + receiving);
 235:              }
 236:  
 237:              @Override
 238:              public void onIceGatheringChange(PeerConnection.IceGatheringState iceGatheringState) {
 239:                  webRTCService.printState(TAG, "🧊 onIceGatheringChange: Gathering state changed to " + iceGatheringState);
 240:              }
 241:  
 242:              @Override
 243:              public void onIceCandidate(IceCandidate iceCandidate) {
 244:                  webRTCService.printState(TAG, "📡 Sending ICE Candidate to peer: " + iceCandidate.sdp);
 245:                  sendMessageToPeer("{"type": "candidate", "candidate": "" + iceCandidate.sdp + "", " +""sdpMid": "" + iceCandidate.sdpMid + "", "sdpMLineIndex": " + iceCandidate.sdpMLineIndex + "}");
 246:              }
 247:  
 248:              @Override
 249:              public void onAddStream(MediaStream mediaStream) {
 250:                  webRTCService.printState(TAG, "🎥 onAddStream: Media stream added, ID=" + mediaStream.getId());
 251:              }
 252:  
 253:              @Override
 254:              public void onRemoveStream(MediaStream mediaStream) {
 255:                  webRTCService.printState(TAG, "🛑 onRemoveStream: Media stream removed, ID=" + mediaStream.getId());
 256:              }
 257:  
 258:              @Override
 259:              public void onDataChannel(DataChannel channel) {
 260:                  webRTCService.printState(TAG, "✅ onDataChannel: DataChannel opened. Label=" + channel.label());
 261:                  dataChannel =channel;
 262:              }
 263:  
 264:              @Override
 265:              public void onRenegotiationNeeded() {
 266:                  webRTCService.printState(TAG, "🔄 onRenegotiationNeeded: Renegotiation required.");
 267:              }
 268:  
 269:              @Override
 270:              public void onCallStarted(SessionDescription remoteDescription) {
 271:                  webRTCService.printState(TAG, "📞 onCallStarted: Sending SDP Offer to test peer.");
 272:                  sendMessageToPeer("{"type": "offer", "sdp": "" + remoteDescription.description + ""}");
 273:              }
 274:  
 275:              @Override
 276:              public void onCallEnded() {
 277:                  webRTCService.printState(TAG, "🚫 onCallEnded: Call has ended.");
 278:              }
 279:  
 280:              @Override
 281:              public void onMediaStreamAdded(AudioTrack audioTrack, VideoTrack videoTrack) {
 282:                  webRTCService.printState(TAG, "🎤🎥 onMediaStreamAdded: Audio track=" + (audioTrack != null) + ", Video track=" + (videoTrack != null));
 283:              }
 284:  
 285:              @Override
 286:              public void onError(String error) {
 287:                  webRTCService.printState(TAG, "❌ onError: " +error);
 288:              }
 289:          });
 290:  
 291:          // Wait for DataChannel
 292:          int attempts = 0;
 293:          while (dataChannel == null || dataChannel.state() != DataChannel.State.OPEN) {
 294:              if (attempts++ > 30) {
 295:                  webRTCService.printState(TAG, "❌ Failed to assign DataChannel within timeout.");
 296:                  return;
 297:              }
 298:              webRTCService.printState(TAG, "⏳ Waiting for DataChannel... Attempt " + attempts);
 299:              Thread.sleep(1000);
 300:          }
 301:  
 302:          webRTCService.printState(TAG, "✅ DataChannel is now open. Sending test files.");
 303:          sendFileOverDataChannel("tst1.mp3");
 304:          sendFileOverDataChannel("tst1.mp4");
 305:          sendFileOverDataChannel("tst1.png");
 306:          sendFileOverDataChannel("tst1.txt");
 307:  
 308:          Thread.sleep(5000);
 309:      }
 310:      //endregion
 311:  
 312:      //region Data Channel and File Operations
 313:      private void sendFileOverDataChannel(String fileName) {
 314:          webRTCService.printState(TAG, "sendFileOverDataChannel: Method called with fileName=" + fileName);
 315:          if (dataChannel == null || dataChannel.state() != DataChannel.State.OPEN) {
 316:              webRTCService.printState(TAG, "DataChannel is not open. Cannot send file: " + fileName);
 317:              return;
 318:          }
 319:  
 320:          try {
 321:              AssetManager assetManager = InstrumentationRegistry.getInstrumentation().getContext().getAssets();
 322:              InputStream inputStream = assetManager.open(fileName);
 323:              ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
 324:  
 325:              byte[] buffer = new byte[4096];
 326:              int bytesRead;
 327:              while ((bytesRead = inputStream.read(buffer)) != -1) {
 328:                  byteArrayOutputStream.write(buffer, 0, bytesRead);
 329:              }
 330:  
 331:              inputStream.close();
 332:              byte[] fileData = byteArrayOutputStream.toByteArray();
 333:              ByteBuffer byteBuffer = ByteBuffer.wrap(fileData);
 334:              DataChannel.Buffer dataBuffer = new DataChannel.Buffer(byteBuffer, false);
 335:  
 336:              webRTCService.printState(TAG, "Sending file over DataChannel: " + fileName);
 337:              webRTCService.printState(TAG, "Local variables: fileData=" + fileData + ", byteBuffer=" + byteBuffer + ", dataBuffer=" + dataBuffer);
 338:              dataChannel.send(dataBuffer);
 339:              webRTCService.printState(TAG, "File sent successfully: " + fileName);
 340:          } catch (IOException e) {
 341:              webRTCService.printState(TAG, "Failed to read file: " + fileName + ", Error: " + e.getMessage());
 342:          }
 343:      }
 344:      //endregion
 345:  
 346:      //region Helper Methods
 347:      private void sendMessageToPeer(String message) {
 348:          webRTCService.printState(TAG, "sendMessageToPeer: Method called with message=" + message);
 349:          if (webSocket == null) {
 350:              webRTCService.printState(TAG, "WebSocket is not initialized. Cannot send message.");
 351:              return;
 352:          }
 353:  
 354:          webRTCService.printState(TAG, "Sending message to test peer: " + message);
 355:          webRTCService.printState(TAG, "Local variables: message=" + message);
 356:          webSocket.send(message);
 357:      }
 358:      //endregion
 359:  }
 360:  

Return to main page




Android context:




Testing context:



Comments ( )
Link to this page: http://www.vb-net.com/WebRTCMockitoTest/Test.htm
< THANKS ME>