View Javadoc
1   /*
2    * Copyright (C) 2013 4th Line GmbH, Switzerland
3    *
4    * The contents of this file are subject to the terms of either the GNU
5    * Lesser General Public License Version 2 or later ("LGPL") or the
6    * Common Development and Distribution License Version 1 or later
7    * ("CDDL") (collectively, the "License"). You may not use this file
8    * except in compliance with the License. See LICENSE.txt for more
9    * information.
10   *
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14   */
15  
16  package org.fourthline.cling.test.gena;
17  
18  import org.fourthline.cling.UpnpService;
19  import org.fourthline.cling.controlpoint.SubscriptionCallback;
20  import org.fourthline.cling.mock.MockRouter;
21  import org.fourthline.cling.mock.MockUpnpService;
22  import org.fourthline.cling.model.NetworkAddress;
23  import org.fourthline.cling.model.gena.CancelReason;
24  import org.fourthline.cling.model.gena.GENASubscription;
25  import org.fourthline.cling.model.gena.RemoteGENASubscription;
26  import org.fourthline.cling.model.message.StreamRequestMessage;
27  import org.fourthline.cling.model.message.StreamResponseMessage;
28  import org.fourthline.cling.model.message.UpnpRequest;
29  import org.fourthline.cling.model.message.UpnpResponse;
30  import org.fourthline.cling.model.message.gena.IncomingEventRequestMessage;
31  import org.fourthline.cling.model.message.gena.OutgoingEventRequestMessage;
32  import org.fourthline.cling.model.message.header.SubscriptionIdHeader;
33  import org.fourthline.cling.model.message.header.TimeoutHeader;
34  import org.fourthline.cling.model.message.header.UpnpHeader;
35  import org.fourthline.cling.model.meta.RemoteDevice;
36  import org.fourthline.cling.model.meta.RemoteService;
37  import org.fourthline.cling.model.state.StateVariableValue;
38  import org.fourthline.cling.model.types.UnsignedIntegerFourBytes;
39  import org.fourthline.cling.protocol.ReceivingSync;
40  import org.fourthline.cling.test.data.SampleData;
41  import org.fourthline.cling.transport.Router;
42  import org.seamless.util.URIUtil;
43  import org.testng.annotations.Test;
44  
45  import java.net.InetAddress;
46  import java.net.URI;
47  import java.util.ArrayList;
48  import java.util.Collections;
49  import java.util.List;
50  
51  import static org.testng.Assert.assertEquals;
52  
53  
54  public class OutgoingSubscriptionFailureTest {
55  
56  
57      @Test
58      public void subscriptionLifecycleNetworkOff() throws Exception {
59  
60          MockUpnpService upnpService = new MockUpnpService() {
61              @Override
62              protected MockRouter createRouter() {
63                  return new MockRouter(getConfiguration(), getProtocolFactory()) {
64                      @Override
65                      public List<NetworkAddress> getActiveStreamServers(InetAddress preferredAddress) {
66                          // Simulate network switched off
67                          return Collections.EMPTY_LIST;
68                      }
69                      @Override
70                      public StreamResponseMessage[] getStreamResponseMessages() {
71  
72                          return new StreamResponseMessage[]{
73                                  createSubscribeResponseMessage()
74  
75                          };
76                      }
77                  };
78              }
79          };
80  
81          final List<Boolean> testAssertions = new ArrayList<>();
82  
83          // Register remote device and its service
84          RemoteDevice device = SampleData.createRemoteDevice();
85          upnpService.getRegistry().addDevice(device);
86  
87          RemoteService service = SampleData.getFirstService(device);
88  
89          SubscriptionCallback callback = new SubscriptionCallback(service) {
90  
91              @Override
92              protected void failed(GENASubscription subscription,
93                                    UpnpResponse responseStatus,
94                                    Exception exception,
95                                    String defaultMsg) {
96                  // Should fail without response and exception (only FINE log message)
97                  assert responseStatus == null;
98                  assert exception == null;
99                  testAssertions.add(true);
100             }
101 
102             @Override
103             public void established(GENASubscription subscription) {
104                 testAssertions.add(false);
105             }
106 
107             @Override
108             public void ended(GENASubscription subscription, CancelReason reason, UpnpResponse responseStatus) {
109                 testAssertions.add(false);
110             }
111 
112             public void eventReceived(GENASubscription subscription) {
113                 testAssertions.add(false);
114             }
115 
116             public void eventsMissed(GENASubscription subscription, int numberOfMissedEvents) {
117                 testAssertions.add(false);
118             }
119 
120         };
121 
122         upnpService.getControlPoint().execute(callback);
123         for (Boolean testAssertion : testAssertions) {
124             assert testAssertion;
125         }
126     }
127 
128     @Test
129     public void subscriptionLifecycleMissedEvent() throws Exception {
130 
131         MockUpnpService upnpService = new MockUpnpService() {
132             @Override
133             protected MockRouter createRouter() {
134                 return new MockRouter(getConfiguration(), getProtocolFactory()) {
135                     @Override
136                     public StreamResponseMessage[] getStreamResponseMessages() {
137 
138                         return new StreamResponseMessage[]{
139                             createSubscribeResponseMessage(),
140                             createUnsubscribeResponseMessage()
141 
142                         };
143                     }
144                 };
145             }
146         };
147 
148         final List<Boolean> testAssertions = new ArrayList<>();
149 
150         // Register remote device and its service
151         RemoteDevice device = SampleData.createRemoteDevice();
152         upnpService.getRegistry().addDevice(device);
153 
154         RemoteService service = SampleData.getFirstService(device);
155 
156         SubscriptionCallback callback = new SubscriptionCallback(service) {
157 
158             @Override
159             protected void failed(GENASubscription subscription,
160                                   UpnpResponse responseStatus,
161                                   Exception exception,
162                                   String defaultMsg) {
163                 testAssertions.add(false);
164             }
165 
166             @Override
167             public void established(GENASubscription subscription) {
168                 assertEquals(subscription.getSubscriptionId(), "uuid:1234");
169                 assertEquals(subscription.getActualDurationSeconds(), 180);
170                 testAssertions.add(true);
171             }
172 
173             @Override
174             public void ended(GENASubscription subscription, CancelReason reason, UpnpResponse responseStatus) {
175                 assert reason == null;
176                 assertEquals(responseStatus.getStatusCode(), UpnpResponse.Status.OK.getStatusCode());
177                 testAssertions.add(true);
178             }
179 
180             public void eventReceived(GENASubscription subscription) {
181                 assertEquals(subscription.getCurrentValues().get("Status").toString(), "0");
182                 assertEquals(subscription.getCurrentValues().get("Target").toString(), "1");
183                 testAssertions.add(true);
184             }
185 
186             public void eventsMissed(GENASubscription subscription, int numberOfMissedEvents) {
187                 assertEquals(numberOfMissedEvents, 2);
188                 testAssertions.add(true);
189             }
190 
191         };
192 
193         upnpService.getControlPoint().execute(callback);
194 
195         ReceivingSync prot = upnpService.getProtocolFactory().createReceivingSync(
196                 createEventRequestMessage(upnpService, callback, 0)
197         );
198         prot.run();
199 
200         prot = upnpService.getProtocolFactory().createReceivingSync(
201                 createEventRequestMessage(upnpService, callback, 3) // Note the missing event messages
202         );
203         prot.run();
204 
205         callback.end();
206 
207         assertEquals(testAssertions.size(), 5);
208         for (Boolean testAssertion : testAssertions) {
209             assert testAssertion;
210         }
211 
212         List<StreamRequestMessage> sentMessages = upnpService.getRouter().getSentStreamRequestMessages();
213 
214         assertEquals(sentMessages.size(), 2);
215         assertEquals(
216                 sentMessages.get(0).getOperation().getMethod(),
217                 UpnpRequest.Method.SUBSCRIBE
218         );
219         assertEquals(
220                 sentMessages.get(0).getHeaders().getFirstHeader(UpnpHeader.Type.TIMEOUT, TimeoutHeader.class).getValue(),
221                 Integer.valueOf(1800)
222         );
223 
224         assertEquals(
225                 sentMessages.get(1).getOperation().getMethod(),
226                 UpnpRequest.Method.UNSUBSCRIBE
227         );
228         assertEquals(
229                 sentMessages.get(1).getHeaders().getFirstHeader(UpnpHeader.Type.SID, SubscriptionIdHeader.class).getValue(),
230                 "uuid:1234"
231         );
232 
233     }
234 
235     protected StreamResponseMessage createSubscribeResponseMessage() {
236         StreamResponseMessage msg = new StreamResponseMessage(new UpnpResponse(UpnpResponse.Status.OK));
237         msg.getHeaders().add(
238                 UpnpHeader.Type.SID, new SubscriptionIdHeader("uuid:1234")
239         );
240         msg.getHeaders().add(
241                 UpnpHeader.Type.TIMEOUT, new TimeoutHeader(180)
242         );
243         return msg;
244     }
245 
246     protected StreamResponseMessage createUnsubscribeResponseMessage() {
247         return new StreamResponseMessage(new UpnpResponse(UpnpResponse.Status.OK));
248     }
249 
250     protected IncomingEventRequestMessage createEventRequestMessage(UpnpService upnpService, SubscriptionCallback callback, int sequence) {
251 
252         List<StateVariableValue> values = new ArrayList<>();
253         values.add(
254                 new StateVariableValue(callback.getService().getStateVariable("Status"), false)
255         );
256         values.add(
257                 new StateVariableValue(callback.getService().getStateVariable("Target"), true)
258         );
259 
260         OutgoingEventRequestMessage outgoing = new OutgoingEventRequestMessage(
261                 callback.getSubscription(),
262                 URIUtil.toURL(URI.create("http://10.0.0.123/some/callback")),
263                 new UnsignedIntegerFourBytes(sequence),
264                 values
265         );
266         outgoing.getOperation().setUri(
267                 upnpService.getConfiguration().getNamespace().getEventCallbackPath(callback.getService())
268         );
269 
270         upnpService.getConfiguration().getGenaEventProcessor().writeBody(outgoing);
271 
272         return new IncomingEventRequestMessage(outgoing, ((RemoteGENASubscription) callback.getSubscription()).getService());
273     }
274 
275 }