Update release in docs/conf.yaml
[transportpce.git] / servicehandler / src / test / java / org / opendaylight / transportpce / servicehandler / ModelMappingUtilsTest.java
1 /*
2  * Copyright © 2018 Orange, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.transportpce.servicehandler;
9
10
11 import static org.junit.jupiter.api.Assertions.assertEquals;
12 import static org.junit.jupiter.api.Assertions.assertNotNull;
13 import static org.junit.jupiter.api.Assertions.assertNull;
14
15 import com.google.common.util.concurrent.ListenableFuture;
16 import com.google.common.util.concurrent.ListeningExecutorService;
17 import com.google.common.util.concurrent.MoreExecutors;
18 import java.time.OffsetDateTime;
19 import java.time.ZoneOffset;
20 import java.time.format.DateTimeFormatter;
21 import java.util.Map;
22 import java.util.Set;
23 import java.util.concurrent.CountDownLatch;
24 import java.util.concurrent.ExecutionException;
25 import java.util.concurrent.Executors;
26 import org.junit.jupiter.api.AfterEach;
27 import org.junit.jupiter.api.BeforeEach;
28 import org.junit.jupiter.api.Test;
29 import org.opendaylight.transportpce.common.ResponseCodes;
30 import org.opendaylight.transportpce.servicehandler.utils.ServiceDataUtils;
31 import org.opendaylight.transportpce.test.AbstractTest;
32 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.PathComputationRequestOutput;
33 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.PathComputationRequestOutputBuilder;
34 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.ConnectionType;
35 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.configuration.response.common.ConfigurationResponseCommonBuilder;
36 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.sdnc.request.header.SdncRequestHeaderBuilder;
37 import org.opendaylight.yang.gen.v1.http.org.openroadm.routing.constraints.rev221209.constraints.CoRoutingBuilder;
38 import org.opendaylight.yang.gen.v1.http.org.openroadm.routing.constraints.rev221209.constraints.co.routing.ServiceIdentifierListBuilder;
39 import org.opendaylight.yang.gen.v1.http.org.openroadm.routing.constraints.rev221209.routing.constraints.HardConstraintsBuilder;
40 import org.opendaylight.yang.gen.v1.http.org.openroadm.routing.constraints.rev221209.routing.constraints.SoftConstraintsBuilder;
41 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.ServiceCreateInput;
42 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.ServiceCreateInputBuilder;
43 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.ServiceCreateOutput;
44 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.ServiceDeleteInput;
45 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.ServiceDeleteInputBuilder;
46 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.ServiceDeleteOutput;
47 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.ServiceFeasibilityCheckInput;
48 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.ServiceFeasibilityCheckInputBuilder;
49 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.ServiceFeasibilityCheckOutput;
50 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.ServiceReconfigureInput;
51 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.ServiceReconfigureInputBuilder;
52 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.ServiceRerouteInput;
53 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.ServiceRerouteInputBuilder;
54 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.ServiceRestorationInput;
55 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.ServiceRestorationInputBuilder;
56 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.ServiceRestorationOutput;
57 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.TempServiceCreateInput;
58 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.TempServiceCreateInputBuilder;
59 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.TempServiceCreateOutput;
60 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.service.list.Services;
61 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.service.list.ServicesBuilder;
62 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.service.list.ServicesKey;
63 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev230501.path.description.AToZDirectionBuilder;
64 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev230501.path.description.ZToADirectionBuilder;
65 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.response.parameters.sp.ResponseParametersBuilder;
66 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.response.parameters.sp.response.parameters.PathDescriptionBuilder;
67 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePaths;
68 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePathsBuilder;
69 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev171017.service.path.list.ServicePathsKey;
70 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime;
71 import org.opendaylight.yangtools.yang.common.RpcResult;
72 import org.opendaylight.yangtools.yang.common.Uint32;
73
74 public class ModelMappingUtilsTest extends AbstractTest {
75
76     private ListeningExecutorService executorService;
77     private CountDownLatch endSignal;
78     private static final int NUM_THREADS = 5;
79
80     @BeforeEach
81     void setUp() {
82         executorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(NUM_THREADS));
83         endSignal = new CountDownLatch(1);
84     }
85
86     @AfterEach
87     void tearDown() {
88         executorService.shutdownNow();
89     }
90
91     private ServiceReconfigureInput buildServiceConfigurationInput() {
92         return new ServiceReconfigureInputBuilder()
93             .setNewServiceName("service 1").setServiceName("service 1").setCommonId("common id")
94             .setConnectionType(ConnectionType.Service).setCustomer("customer").setCustomerContact("customer contact")
95             .setDueDate(new DateAndTime(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssxxx")
96                 .format(OffsetDateTime.now(ZoneOffset.UTC))))
97             .setEndDate(new DateAndTime(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssxxx")
98                 .format(OffsetDateTime.now(ZoneOffset.UTC).plusDays(10))))
99             .setNcCode("nc node").setNciCode("nci node").setSecondaryNciCode("secondry").setOperatorContact("operator")
100             .setServiceAEnd(ServiceDataUtils.getServiceAEndBuildReconfigure().build())
101             .setServiceZEnd(ServiceDataUtils.getServiceZEndBuildReconfigure().build())
102             .setHardConstraints(new HardConstraintsBuilder()
103                 .setCustomerCode(Set.of("Some customer-code"))
104                 .setCoRouting(new CoRoutingBuilder()
105                     .setServiceIdentifierList(Map.of(
106                         new org.opendaylight.yang.gen.v1.http.org.openroadm.routing.constraints.rev221209
107                             .constraints.co.routing.ServiceIdentifierListKey("Some existing-service"),
108                         new ServiceIdentifierListBuilder().setServiceIdentifier("Some existing-service")
109                             .build()))
110                     .build())
111                 .build())
112             .setSoftConstraints(new SoftConstraintsBuilder()
113                 .setCustomerCode(Set.of("Some customer-code"))
114                 .setCoRouting(new CoRoutingBuilder()
115                     .setServiceIdentifierList(Map.of(
116                         new org.opendaylight.yang.gen.v1.http.org.openroadm.routing.constraints.rev221209
117                             .constraints.co.routing.ServiceIdentifierListKey("Some existing-service"),
118                         new ServiceIdentifierListBuilder().setServiceIdentifier("Some existing-service")
119                             .build()))
120                     .build())
121                 .build())
122             .build();
123     }
124
125     private PathComputationRequestOutput buildPathComputationOutput() {
126         return new PathComputationRequestOutputBuilder()
127             .setConfigurationResponseCommon(new ConfigurationResponseCommonBuilder()
128                 .setRequestId("request 1")
129                 .setAckFinalIndicator(ResponseCodes.FINAL_ACK_NO)
130                 .setResponseCode(ResponseCodes.RESPONSE_OK)
131                 .setResponseMessage("PCE calculation in progress")
132                 .build())
133             .setResponseParameters(new ResponseParametersBuilder()
134                 .setPathDescription(new PathDescriptionBuilder()
135                     .setAToZDirection(new AToZDirectionBuilder()
136                         .setAToZWavelengthNumber(Uint32.valueOf(1))
137                         .setRate(Uint32.valueOf(1))
138                         .build())
139                     .setZToADirection(new ZToADirectionBuilder()
140                         .setZToAWavelengthNumber(Uint32.valueOf(1))
141                         .setRate(Uint32.valueOf(1))
142                         .build())
143                     .build())
144                 .build())
145             .build();
146     }
147
148     @Test
149     void mappingServiceNotNullServiceReconfigureInput() {
150         Services services = ModelMappingUtils.mappingServices(null, buildServiceConfigurationInput());
151         assertEquals("service 1", services.getServiceName());
152     }
153
154     @Test
155     void mappingServiceValid() {
156         Services services = ModelMappingUtils.mappingServices(ServiceDataUtils.buildServiceCreateInput(), null);
157         assertEquals("service 1", services.getServiceName());
158     }
159
160     @Test
161     //TODO : is this unit test relevant ?
162     void mappingServicesPathNullServiceCreateInput() {
163         ServicePaths services = ModelMappingUtils.mappingServicePaths(null, buildPathComputationOutput());
164         assertEquals(new ServicePathsBuilder().withKey(new ServicePathsKey("unknown")).build(), services);
165     }
166
167     @Test
168     void mappingServicePathWithServiceInputWithHardConstraints() {
169         ServiceCreateInput createInput = ServiceDataUtils.buildServiceCreateInputWithHardConstraints();
170         ServiceInput serviceInput = new ServiceInput(createInput);
171         ServicePaths services = ModelMappingUtils.mappingServicePaths(serviceInput, buildPathComputationOutput());
172         assertEquals(serviceInput.getServiceName(), services.getServicePathName());
173         assertNotNull(services.getHardConstraints());
174     }
175
176     @Test
177     void mappingServicePathWithServiceInputWithSoftConstraints() {
178         ServiceCreateInput createInput = ServiceDataUtils.buildServiceCreateInputWithSoftConstraints();
179         ServiceInput serviceInput = new ServiceInput(createInput);
180         ServicePaths services = ModelMappingUtils.mappingServicePaths(serviceInput, buildPathComputationOutput());
181         assertEquals(serviceInput.getServiceName(), services.getServicePathName());
182         assertNotNull(services.getSoftConstraints());
183     }
184
185     @Test
186     void createServiceDeleteInputWithServiceRerouteInput() {
187         ServiceRerouteInput serviceRerouteinput = new ServiceRerouteInputBuilder().setServiceName("reroute").build();
188         Services services = new ServicesBuilder()
189                     .withKey(new ServicesKey("reroute"))
190                     .setSdncRequestHeader(new SdncRequestHeaderBuilder().setRequestId("123").build())
191                     .build();
192         var serviceDeleteInput = ModelMappingUtils.createServiceDeleteInput(serviceRerouteinput, services);
193         assertEquals("reroute", serviceDeleteInput.getServiceName());
194         assertEquals("123", serviceDeleteInput.getServiceHandlerHeader().getRequestId());
195     }
196
197     @Test
198     void  createServiceDeleteInputWithServiceReconfigureInput() {
199         ServiceReconfigureInput serviceReconfigureInput = new ServiceReconfigureInputBuilder()
200                 .setServiceName("reconf")
201                 .build();
202         var serviceDeleteInput = ModelMappingUtils.createServiceDeleteInput(serviceReconfigureInput);
203         assertEquals("reconf", serviceDeleteInput.getServiceName());
204         assertEquals("reconf-reconfigure", serviceDeleteInput.getServiceHandlerHeader().getRequestId());
205     }
206
207     @Test
208     void createServiceDeleteInputWithServiceRestorationInput() {
209         Services services = new ServicesBuilder()
210                 .withKey(new ServicesKey("rest"))
211                 .setSdncRequestHeader(new SdncRequestHeaderBuilder().setRequestId("123").build())
212                 .build();
213         ServiceRestorationInput serviceRestorationInput = new ServiceRestorationInputBuilder()
214                 .setServiceName("rest")
215                 .build();
216         var serviceDeleteInput = ModelMappingUtils.createServiceDeleteInput(serviceRestorationInput, services);
217         assertEquals("rest", serviceDeleteInput.getServiceName());
218         assertEquals("123", serviceDeleteInput.getServiceHandlerHeader().getRequestId());
219     }
220
221     @Test
222     void createDeleteServiceReplyWithServiceDeleteInputWithSdncHeader()
223             throws ExecutionException, InterruptedException  {
224         ServiceDeleteInput input = new ServiceDeleteInputBuilder()
225                 .setSdncRequestHeader(new SdncRequestHeaderBuilder().setRequestId("12").build())
226                 .build();
227         ListenableFuture<RpcResult<ServiceDeleteOutput>> serviceDeleteOutputF =
228             ModelMappingUtils.createDeleteServiceReply(input, "ack", "message", "200");
229         serviceDeleteOutputF.addListener(new Runnable() {
230             @Override
231             public void run() {
232                 endSignal.countDown();
233             }
234         }, executorService);
235
236         endSignal.await();
237         RpcResult<ServiceDeleteOutput> serviceDeleteOutput = serviceDeleteOutputF.get();
238         assertEquals("200", serviceDeleteOutput.getResult().getConfigurationResponseCommon().getResponseCode());
239         assertEquals("ack", serviceDeleteOutput.getResult().getConfigurationResponseCommon().getAckFinalIndicator());
240         assertEquals("message", serviceDeleteOutput.getResult().getConfigurationResponseCommon().getResponseMessage());
241         assertEquals("12", serviceDeleteOutput.getResult().getConfigurationResponseCommon().getRequestId());
242     }
243
244     @Test
245     void createDeleteServiceReplyWithServiceDeleteInputWithoutSdncHeader()
246             throws ExecutionException, InterruptedException  {
247         ServiceDeleteInput input = new ServiceDeleteInputBuilder().build();
248         ListenableFuture<RpcResult<ServiceDeleteOutput>> serviceDeleteOutputF =
249             ModelMappingUtils.createDeleteServiceReply(input, "ack", "message", "200");
250         serviceDeleteOutputF.addListener(new Runnable() {
251             @Override
252             public void run() {
253                 endSignal.countDown();
254             }
255         }, executorService);
256
257         endSignal.await();
258         RpcResult<ServiceDeleteOutput> serviceDeleteOutput = serviceDeleteOutputF.get();
259         assertEquals("200", serviceDeleteOutput.getResult().getConfigurationResponseCommon().getResponseCode());
260         assertEquals("ack", serviceDeleteOutput.getResult().getConfigurationResponseCommon().getAckFinalIndicator());
261         assertEquals("message", serviceDeleteOutput.getResult().getConfigurationResponseCommon().getResponseMessage());
262         assertNull(serviceDeleteOutput.getResult().getConfigurationResponseCommon().getRequestId());
263     }
264
265     @Test
266     void createCreateServiceReplyWithServiceCreatInputWithSdncRequestHeader()
267             throws ExecutionException, InterruptedException {
268         ServiceCreateInput input = new ServiceCreateInputBuilder()
269                 .setSdncRequestHeader(new SdncRequestHeaderBuilder().setRequestId("12").build())
270                 .build();
271         ListenableFuture<RpcResult<ServiceCreateOutput>> serviceCreatOutputF =
272             ModelMappingUtils.createCreateServiceReply(input, "ack", "message", "200");
273         serviceCreatOutputF.addListener(new Runnable() {
274             @Override
275             public void run() {
276                 endSignal.countDown();
277             }
278         }, executorService);
279
280         endSignal.await();
281         RpcResult<ServiceCreateOutput> serviceCreatOutput = serviceCreatOutputF.get();
282         assertEquals("200", serviceCreatOutput.getResult().getConfigurationResponseCommon().getResponseCode());
283         assertEquals("ack", serviceCreatOutput.getResult().getConfigurationResponseCommon().getAckFinalIndicator());
284         assertEquals("message", serviceCreatOutput.getResult().getConfigurationResponseCommon().getResponseMessage());
285         assertEquals("12", serviceCreatOutput.getResult().getConfigurationResponseCommon().getRequestId());
286     }
287
288     @Test
289     void createCreateServiceReplyWithServiceCreatInputWithoutSdncRequestHeader()
290         throws ExecutionException, InterruptedException {
291         ServiceCreateInput input = new ServiceCreateInputBuilder().build();
292         ListenableFuture<RpcResult<ServiceCreateOutput>> serviceCreatOutputF =
293             ModelMappingUtils.createCreateServiceReply(input, "ack", "message", "200");
294         serviceCreatOutputF.addListener(new Runnable() {
295             @Override
296             public void run() {
297                 endSignal.countDown();
298             }
299         }, executorService);
300
301         endSignal.await();
302         RpcResult<ServiceCreateOutput> serviceCreatOutput = serviceCreatOutputF.get();
303         assertEquals("200", serviceCreatOutput.getResult().getConfigurationResponseCommon().getResponseCode());
304         assertEquals("ack", serviceCreatOutput.getResult().getConfigurationResponseCommon().getAckFinalIndicator());
305         assertEquals("message", serviceCreatOutput.getResult().getConfigurationResponseCommon().getResponseMessage());
306         assertNull(serviceCreatOutput.getResult().getConfigurationResponseCommon().getRequestId());
307     }
308
309     @Test
310     void createCreateServiceReplyWithTempServiceCreatInputWithSdncRequestHeader()
311         throws ExecutionException, InterruptedException {
312         TempServiceCreateInput input = new TempServiceCreateInputBuilder()
313                 .setSdncRequestHeader(new SdncRequestHeaderBuilder().setRequestId("12").build())
314                 .build();
315         ListenableFuture<RpcResult<TempServiceCreateOutput>> serviceCreatOutputF =
316             ModelMappingUtils.createCreateServiceReply(input, "ack", "message", "200");
317         serviceCreatOutputF.addListener(new Runnable() {
318             @Override
319             public void run() {
320                 endSignal.countDown();
321             }
322         }, executorService);
323
324         endSignal.await();
325         RpcResult<TempServiceCreateOutput> serviceCreatOutput = serviceCreatOutputF.get();
326         assertEquals("200", serviceCreatOutput.getResult().getConfigurationResponseCommon().getResponseCode());
327         assertEquals("ack", serviceCreatOutput.getResult().getConfigurationResponseCommon().getAckFinalIndicator());
328         assertEquals("message", serviceCreatOutput.getResult().getConfigurationResponseCommon().getResponseMessage());
329         assertEquals("12", serviceCreatOutput.getResult().getConfigurationResponseCommon().getRequestId());
330     }
331
332     @Test
333     void createCreateServiceReplyWithTempServiceCreatInputWithoutSdncRequestHeader()
334         throws ExecutionException, InterruptedException {
335         TempServiceCreateInput input = new TempServiceCreateInputBuilder().build();
336         ListenableFuture<RpcResult<TempServiceCreateOutput>> serviceCreatOutputF =
337             ModelMappingUtils.createCreateServiceReply(input, "ack", "message", "200");
338         serviceCreatOutputF.addListener(new Runnable() {
339             @Override
340             public void run() {
341                 endSignal.countDown();
342             }
343         }, executorService);
344
345         endSignal.await();
346         RpcResult<TempServiceCreateOutput> serviceCreatOutput = serviceCreatOutputF.get();
347         assertEquals("200", serviceCreatOutput.getResult().getConfigurationResponseCommon().getResponseCode());
348         assertEquals("ack", serviceCreatOutput.getResult().getConfigurationResponseCommon().getAckFinalIndicator());
349         assertEquals("message", serviceCreatOutput.getResult().getConfigurationResponseCommon().getResponseMessage());
350         assertNull(serviceCreatOutput.getResult().getConfigurationResponseCommon().getRequestId());
351     }
352
353     @Test
354     void createCreateServiceReplyWithServiceFeasibilityCheckInputWithSdncRequestHeader()
355         throws ExecutionException, InterruptedException {
356         ServiceFeasibilityCheckInput input = new ServiceFeasibilityCheckInputBuilder()
357                 .setSdncRequestHeader(new SdncRequestHeaderBuilder().setRequestId("12").build())
358                 .build();
359         ListenableFuture<RpcResult<ServiceFeasibilityCheckOutput>> serviceCreatOutputF =
360             ModelMappingUtils.createCreateServiceReply(input, "ack", "message", "200");
361         serviceCreatOutputF.addListener(new Runnable() {
362             @Override
363             public void run() {
364                 endSignal.countDown();
365             }
366         }, executorService);
367
368         endSignal.await();
369         RpcResult<ServiceFeasibilityCheckOutput> serviceCreatOutput = serviceCreatOutputF.get();
370         assertEquals("200", serviceCreatOutput.getResult().getConfigurationResponseCommon().getResponseCode());
371         assertEquals("ack", serviceCreatOutput.getResult().getConfigurationResponseCommon().getAckFinalIndicator());
372         assertEquals("message", serviceCreatOutput.getResult().getConfigurationResponseCommon().getResponseMessage());
373         assertEquals("12", serviceCreatOutput.getResult().getConfigurationResponseCommon().getRequestId());
374     }
375
376     @Test
377     void createCreateServiceReplyWithServiceFeasibilityCheckInputWithoutSdncRequestHeader()
378         throws ExecutionException, InterruptedException {
379         ServiceFeasibilityCheckInput input = new ServiceFeasibilityCheckInputBuilder().build();
380         ListenableFuture<RpcResult<ServiceFeasibilityCheckOutput>> serviceCreatOutputF =
381             ModelMappingUtils.createCreateServiceReply(input, "ack", "message", "200");
382         serviceCreatOutputF.addListener(new Runnable() {
383             @Override
384             public void run() {
385                 endSignal.countDown();
386             }
387         }, executorService);
388
389         endSignal.await();
390         RpcResult<ServiceFeasibilityCheckOutput> serviceCreatOutput = serviceCreatOutputF.get();
391         assertEquals("200", serviceCreatOutput.getResult().getConfigurationResponseCommon().getResponseCode());
392         assertEquals("ack", serviceCreatOutput.getResult().getConfigurationResponseCommon().getAckFinalIndicator());
393         assertEquals("message", serviceCreatOutput.getResult().getConfigurationResponseCommon().getResponseMessage());
394         assertNull(serviceCreatOutput.getResult().getConfigurationResponseCommon().getRequestId());
395     }
396
397     @Test
398     void testCreateRestoreServiceReply() throws ExecutionException, InterruptedException {
399         ListenableFuture<RpcResult<ServiceRestorationOutput>> serviceRestorationOutputF =
400             ModelMappingUtils.createRestoreServiceReply("message");
401         serviceRestorationOutputF.addListener(new Runnable() {
402             @Override
403             public void run() {
404                 endSignal.countDown();
405             }
406         }, executorService);
407
408         endSignal.await();
409     }
410 }