diff --git a/src/main/java/io/antmedia/AntMediaApplicationAdapter.java b/src/main/java/io/antmedia/AntMediaApplicationAdapter.java index 73dcfeb88..b0448c19d 100644 --- a/src/main/java/io/antmedia/AntMediaApplicationAdapter.java +++ b/src/main/java/io/antmedia/AntMediaApplicationAdapter.java @@ -700,7 +700,7 @@ public void closeBroadcast(String streamId) { notifyHook(listenerHookURL, streamId, mainTrackId, HOOK_ACTION_END_LIVE_STREAM, name, category, null, null, metaData, null); } - + PublishEndedEvent publishEndedEvent = new PublishEndedEvent(); publishEndedEvent.setStreamId(streamId); publishEndedEvent.setDurationMs(System.currentTimeMillis() - broadcast.getStartTime()); diff --git a/src/main/java/io/antmedia/rest/RestServiceBase.java b/src/main/java/io/antmedia/rest/RestServiceBase.java index 51044d5d0..358698fc2 100755 --- a/src/main/java/io/antmedia/rest/RestServiceBase.java +++ b/src/main/java/io/antmedia/rest/RestServiceBase.java @@ -398,9 +398,16 @@ private boolean deleteSubtracks(Broadcast broadcast) { for (Broadcast subtrack : subtracks) { boolean subtrackDeleted = getDataStore().delete(subtrack.getStreamId()); - if (!subtrackDeleted) { - logger.error("Subtrack {} could not be deleted", subtrack.getStreamId()); - result = false; + if (!subtrackDeleted ) { + + //before returning false, check the track exists because it may be deleted automatically if it's zombi and stopped + Broadcast subtrackBroadcast = getDataStore().get(subtrack.getStreamId()); + + if (subtrackBroadcast != null) + { + logger.error("Subtrack {} could not be deleted", subtrack.getStreamId()); + result = false; + } } } diff --git a/src/test/java/io/antmedia/test/rest/BroadcastRestServiceV2UnitTest.java b/src/test/java/io/antmedia/test/rest/BroadcastRestServiceV2UnitTest.java index fe3a9f3de..871e4fcae 100644 --- a/src/test/java/io/antmedia/test/rest/BroadcastRestServiceV2UnitTest.java +++ b/src/test/java/io/antmedia/test/rest/BroadcastRestServiceV2UnitTest.java @@ -905,7 +905,7 @@ public void testRemoveEndpointV2() assertTrue(result.isSuccess()); assertEquals(1, store.get(streamId).getEndPointList().size()); - + BroadcastUpdate broadcastUpdate = new BroadcastUpdate(); broadcastUpdate.setStatus(AntMediaApplicationAdapter.BROADCAST_STATUS_BROADCASTING); broadcastUpdate.setUpdateTime(System.currentTimeMillis()); @@ -1777,7 +1777,7 @@ public void testEnableMp4Muxing() throws Exception BroadcastUpdate broadcastUpdate = new BroadcastUpdate(); broadcastUpdate.setStatus(AntMediaApplicationAdapter.BROADCAST_STATUS_BROADCASTING); broadcastUpdate.setUpdateTime(System.currentTimeMillis()); - + store.updateBroadcastFields(testBroadcast.getStreamId(), broadcastUpdate); assertTrue(restServiceSpy.enableRecordMuxing(testBroadcast.getStreamId(), true, "mp4", 0).isSuccess()); @@ -1946,10 +1946,10 @@ public void testSubscriberNone32BitSecret() { public void testTimeBasedSubscriberOperations() { DataStore store = new MapDBStore(RandomStringUtils.randomAlphanumeric(6) + ".db", vertx); - + AppSettings appSettings = new AppSettings(); appSettings.setWriteSubscriberEventsToDatastore(true); - + store.setAppSettings(appSettings); restServiceReal.setDataStore(store); @@ -1976,22 +1976,22 @@ public void testTimeBasedSubscriberOperations() { assertEquals(2, subscribers.size()); assertEquals(2, subscriberStats.size()); - + List connectionEvents = restServiceReal.getConnectionEvents(subscriber.getStreamId(), 0, 10, null); assertEquals(0, connectionEvents.size()); - + ConnectionEvent event = new ConnectionEvent(); event.setEventType(ConnectionEvent.CONNECTED_EVENT); event.setType(Subscriber.PLAY_TYPE); - assertTrue(store.addSubscriberConnectionEvent(subscriber.getStreamId(), subscriber.getSubscriberId(), event)); - + assertTrue(store.addSubscriberConnectionEvent(subscriber.getStreamId(), subscriber.getSubscriberId(), event)); + connectionEvents = restServiceReal.getConnectionEvents(null, 0, 10, null); assertEquals(0, connectionEvents.size()); - + connectionEvents = restServiceReal.getConnectionEvents(subscriber.getStreamId(), 0, 10, null); assertEquals(1, connectionEvents.size()); - + connectionEvents = restServiceReal.getConnectionEvents(subscriber.getStreamId(), 0, 10, subscriber.getSubscriberId()); assertEquals(1, connectionEvents.size()); @@ -2616,7 +2616,7 @@ public void testUpdateIPCamera() { Mockito.doReturn(true).when(streamSourceRest).checkStreamUrl(any()); Mockito.doReturn(true).when(streamSourceRest).checkStopStreaming(any()); - + BroadcastUpdate broadcastUpdate = new BroadcastUpdate(); broadcastUpdate.setUsername("new_user"); result = streamSourceRest.updateBroadcast(streamSource.getStreamId(), broadcastUpdate); @@ -2626,8 +2626,8 @@ public void testUpdateIPCamera() { - - + + broadcastUpdate = new BroadcastUpdate(); broadcastUpdate.setStreamId("test"); broadcastUpdate.setStreamUrl("rtsp://test2"); @@ -2635,7 +2635,7 @@ public void testUpdateIPCamera() { broadcastUpdate.setUsername(""); broadcastUpdate.setPassword(""); broadcastUpdate.setIpAddr(""); - + result = streamSourceRest.updateBroadcast(broadcastUpdate.getStreamId(), broadcastUpdate); assertEquals(true, result.isSuccess()); @@ -2788,7 +2788,7 @@ public void testUpdateCamInfo() { Mockito.doReturn(false).when(sfm).isStreamRunning(any()); store.save(newCam); - + BroadcastUpdate broadcastUpdate = new BroadcastUpdate(); broadcastUpdate.setSubFolder("testFolder"); @@ -2887,7 +2887,7 @@ public void testAddStreamSourceWithEndPoint() { assertEquals(1, source.getEndPointList().size()); BroadcastUpdate broadcastUpdate = new BroadcastUpdate(); broadcastUpdate.setEndPointList(source.getEndPointList()); - + //update first source now. At the moment we have endpoint_1 result = streamSourceRest.updateBroadcast(source.getStreamId(), broadcastUpdate); assertEquals(1, source.getEndPointList().size()); @@ -2986,7 +2986,7 @@ public void testAddSubtrackWhenThereIsALimit() throws Exception Broadcast mainTrack= new Broadcast(); mainTrack.setStreamId(mainTrackId); - + datastore.save(mainTrack); //it should be false because there is no subtrack @@ -3770,7 +3770,7 @@ public void testCheckURL() { assertFalse(restServiceReal.checkStreamUrl("dummy://something")); } - + @Test public void testDeleteBroadcastWithSubtracks() { AppSettings settings = new AppSettings(); @@ -3784,7 +3784,6 @@ public void testDeleteBroadcastWithSubtracks() { restServiceReal.setAppCtx(context); when(context.containsBean(any())).thenReturn(false); - DataStore store = Mockito.spy(new InMemoryDataStore("testdb")); restServiceReal.setDataStore(store); @@ -3797,7 +3796,7 @@ public void testDeleteBroadcastWithSubtracks() { Mockito.when(appAdaptor.stopStreaming(any(), anyBoolean())).thenReturn(new Result(true)); restServiceReal.setApplication(appAdaptor); - + Broadcast mainTrack = new Broadcast(); try { mainTrack.setStreamId("mainTrack"); @@ -3806,7 +3805,7 @@ public void testDeleteBroadcastWithSubtracks() { } mainTrack.setStatus(IAntMediaStreamHandler.BROADCAST_STATUS_BROADCASTING); mainTrack.setUpdateTime(System.currentTimeMillis()); - + Broadcast subtrack1 = new Broadcast(); try { subtrack1.setStreamId("subtrack1"); @@ -3817,7 +3816,7 @@ public void testDeleteBroadcastWithSubtracks() { subtrack1.setStatus(IAntMediaStreamHandler.BROADCAST_STATUS_BROADCASTING); subtrack1.setUpdateTime(System.currentTimeMillis()); - + Broadcast subtrack2 = new Broadcast(); try { subtrack2.setStreamId("subtrack2"); @@ -3827,7 +3826,7 @@ public void testDeleteBroadcastWithSubtracks() { subtrack2.setMainTrackStreamId(mainTrack.getStreamId()); subtrack2.setStatus(IAntMediaStreamHandler.BROADCAST_STATUS_BROADCASTING); subtrack2.setUpdateTime(System.currentTimeMillis()); - + Broadcast subtrack3 = new Broadcast(); try { subtrack3.setStreamId("subtrack3"); @@ -3838,12 +3837,12 @@ public void testDeleteBroadcastWithSubtracks() { subtrack3.setStatus(IAntMediaStreamHandler.BROADCAST_STATUS_FINISHED); subtrack3.setUpdateTime(System.currentTimeMillis() - 50000); - + store.save(mainTrack); store.save(subtrack1); store.save(subtrack2); store.save(subtrack3); - + assertNotNull(store.get(mainTrack.getStreamId())); assertNotNull(store.get(subtrack1.getStreamId())); assertNotNull(store.get(subtrack2.getStreamId())); @@ -3853,28 +3852,42 @@ public void testDeleteBroadcastWithSubtracks() { assertTrue(result.isSuccess()); verify(appAdaptor).stopStreaming(eq(mainTrack), anyBoolean()); - + assertNull(store.get(mainTrack.getStreamId())); assertNull(store.get(subtrack1.getStreamId())); assertNull(store.get(subtrack2.getStreamId())); assertNull(store.get(subtrack3.getStreamId())); - - + + store.save(mainTrack); store.save(subtrack1); store.save(subtrack2); - + Mockito.doReturn(false).when(store).delete(subtrack1.getStreamId()); Mockito.doReturn(Arrays.asList(subtrack1)).when(store).getSubtracks(anyString(), anyInt(), anyInt(), anyString()); result = restServiceReal.deleteBroadcast(mainTrack.getStreamId(), true); assertFalse(result.isSuccess()); - + assertNull(store.get(mainTrack.getStreamId())); assertNotNull(store.get(subtrack1.getStreamId())); + { + store.save(mainTrack); + store.save(subtrack1); + + Mockito.doReturn(false).when(store).delete(subtrack1.getStreamId()); + Mockito.doReturn(null).when(store).get(subtrack1.getStreamId()); + + result = restServiceReal.deleteBroadcast(mainTrack.getStreamId(), true); + //it's true because get returns null -> Mockito.doReturn(null).when(store).get(subtrack1.getStreamId()); + assertTrue(result.isSuccess()); + + assertNull(store.get(mainTrack.getStreamId())); + + } } - + }