@@ -353,6 +353,75 @@ public void testUnregisterApplicationUsedInStream() throws Exception {
353353 .andExpect (status ().isOk ());
354354 }
355355
356+ @ Test
357+ @ Transactional
358+ public void testUnregisterApplicationUsedInStreamNotDeployed () throws Exception {
359+ // Note, by default there are apps registered from classpath:META-INF/test-apps.properties.
360+
361+ // Register time source v1.2
362+ mockMvc .perform (post ("/apps/source/time" )
363+ .param ("uri" , "maven://org.springframework.cloud.stream.app:time-source-rabbit:1.2.0.RELEASE" ).accept (MediaType .APPLICATION_JSON ))
364+ .andExpect (status ().isCreated ());
365+
366+ // Make sure the 1.2 time source is registered.
367+ mockMvc .perform (get ("/apps/source/time/1.2.0.RELEASE" ).accept (MediaType .APPLICATION_JSON ))
368+ .andExpect (status ().isOk ()).andExpect (jsonPath ("name" , is ("time" )))
369+ .andExpect (jsonPath ("type" , is ("source" )));
370+
371+ // Register log sink v1.2
372+ mockMvc .perform (post ("/apps/sink/log" )
373+ .param ("uri" , "maven://org.springframework.cloud.stream.app:log-sink-rabbit:1.2.0.RELEASE" ).accept (MediaType .APPLICATION_JSON ))
374+ .andExpect (status ().isCreated ());
375+
376+ // Make sure the 1.2 log sink is registered.
377+ mockMvc .perform (get ("/apps/sink/log/1.2.0.RELEASE" ).accept (MediaType .APPLICATION_JSON ))
378+ .andExpect (status ().isOk ()).andExpect (jsonPath ("name" , is ("log" )))
379+ .andExpect (jsonPath ("type" , is ("sink" )));
380+
381+ // Register a transformer
382+ mockMvc .perform (post ("/apps/processor/transformer" )
383+ .param ("uri" , "maven://org.springframework.cloud.stream.app:transformer-processor-rabbit:1.2.0.RELEASE" ).accept (MediaType .APPLICATION_JSON ))
384+ .andExpect (status ().isCreated ());
385+
386+ // Register a task
387+ mockMvc .perform (post ("/apps/task/timestamp" )
388+ .param ("uri" , "maven://org.springframework.cloud.task.app:timestamp-task:1.3.0.RELEASE" )
389+ .accept (MediaType .APPLICATION_JSON ))
390+ .andExpect (status ().isCreated ());
391+
392+ // Create stream definition
393+ StreamDefinition streamDefinition = new StreamDefinition ("ticktock" , "time --fixed-delay=100 | log --level=DEBUG" );
394+ streamDefinitionRepository .save (streamDefinition );
395+
396+ // configure mock SkipperClient
397+ when (skipperClient .manifest (eq ("ticktock" ))).thenThrow (new ReleaseNotFoundException ("" ));
398+ when (skipperClient .status (eq ("ticktock" ))).thenThrow (new ReleaseNotFoundException ("" ));
399+
400+ // This log sink v1.2 is part of a deployed stream, so it can be unregistered
401+ mockMvc .perform (delete ("/apps/sink/log/1.2.0.RELEASE" ).accept (MediaType .APPLICATION_JSON ))
402+ .andExpect (status ().isOk ());
403+
404+ // This log sink v1.0.BS is part of a deployed stream, so it can be unregistered
405+ mockMvc .perform (delete ("/apps/sink/log/1.0.0.BUILD-SNAPSHOT" ).accept (MediaType .APPLICATION_JSON ))
406+ .andExpect (status ().isOk ());
407+
408+ // This time source v1.0 BS is not part of a deployed stream, so it can be unregistered
409+ mockMvc .perform (delete ("/apps/source/time/1.0.0.BUILD-SNAPSHOT" ).accept (MediaType .APPLICATION_JSON ))
410+ .andExpect (status ().isOk ());
411+
412+ // This time source is part of a deployed stream, so it can not be unregistered.
413+ mockMvc .perform (delete ("/apps/source/time/1.2.0.RELEASE" ).accept (MediaType .APPLICATION_JSON ))
414+ .andExpect (status ().isOk ());
415+
416+
417+ // This is unrelated to a stream, so should work
418+ mockMvc .perform (delete ("/apps/task/timestamp/1.3.0.RELEASE" ).accept (MediaType .APPLICATION_JSON ))
419+ .andExpect (status ().isOk ());
420+
421+ // Transformer processor is not deployed, so should work
422+ mockMvc .perform (delete ("/apps/processor/transformer" ).accept (MediaType .APPLICATION_JSON ))
423+ .andExpect (status ().isOk ());
424+ }
356425
357426 @ Test
358427 public void testUnregisterApplicationNotFound () throws Exception {
0 commit comments