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.mock.MockUpnpService;
19  import org.fourthline.cling.model.Namespace;
20  import org.fourthline.cling.model.message.StreamRequestMessage;
21  import org.fourthline.cling.model.message.StreamResponseMessage;
22  import org.fourthline.cling.model.message.UpnpRequest;
23  import org.fourthline.cling.model.message.UpnpResponse;
24  import org.fourthline.cling.model.message.gena.OutgoingSubscribeResponseMessage;
25  import org.fourthline.cling.model.message.header.CallbackHeader;
26  import org.fourthline.cling.model.message.header.EventSequenceHeader;
27  import org.fourthline.cling.model.message.header.NTEventHeader;
28  import org.fourthline.cling.model.message.header.SubscriptionIdHeader;
29  import org.fourthline.cling.model.message.header.TimeoutHeader;
30  import org.fourthline.cling.model.message.header.UpnpHeader;
31  import org.fourthline.cling.model.meta.LocalDevice;
32  import org.fourthline.cling.model.meta.LocalService;
33  import org.fourthline.cling.protocol.sync.ReceivingSubscribe;
34  import org.fourthline.cling.protocol.sync.ReceivingUnsubscribe;
35  import org.fourthline.cling.test.data.SampleData;
36  import org.seamless.util.URIUtil;
37  import org.testng.annotations.Test;
38  
39  import java.net.URL;
40  import java.util.List;
41  
42  import static org.testng.Assert.assertEquals;
43  
44  
45  public class IncomingSubscriptionLifecycleTest {
46  
47      @Test
48      public void subscriptionLifecycle() throws Exception {
49  
50          MockUpnpService upnpService = new MockUpnpService();
51  
52          // Register local device and its service
53          LocalDevice device = GenaSampleData.createTestDevice(GenaSampleData.LocalTestService.class);
54          upnpService.getRegistry().addDevice(device);
55  
56          Namespace ns = upnpService.getConfiguration().getNamespace();
57  
58          LocalService<?> service = SampleData.getFirstService(device);
59          URL callbackURL = URIUtil.createAbsoluteURL(
60                  SampleData.getLocalBaseURL(), ns.getEventCallbackPath(service)
61          );
62  
63  
64          StreamRequestMessage subscribeRequestMessage =
65                  new StreamRequestMessage(UpnpRequest.Method.SUBSCRIBE, ns.getEventSubscriptionPath(service));
66  
67          subscribeRequestMessage.getHeaders().add(
68                  UpnpHeader.Type.CALLBACK,
69                  new CallbackHeader(callbackURL)
70          );
71          subscribeRequestMessage.getHeaders().add(UpnpHeader.Type.NT, new NTEventHeader());
72  
73          ReceivingSubscribe subscribeProt = new ReceivingSubscribe(upnpService, subscribeRequestMessage);
74          subscribeProt.run();
75          OutgoingSubscribeResponseMessage subscribeResponseMessage = subscribeProt.getOutputMessage();
76  
77          assertEquals(subscribeResponseMessage.getOperation().getStatusCode(), UpnpResponse.Status.OK.getStatusCode());
78          String subscriptionId = subscribeResponseMessage.getHeaders().getFirstHeader(UpnpHeader.Type.SID, SubscriptionIdHeader.class).getValue();
79          assert subscriptionId.startsWith("uuid:");
80          assertEquals(subscribeResponseMessage.getHeaders().getFirstHeader(UpnpHeader.Type.TIMEOUT, TimeoutHeader.class).getValue(), new Integer(1800));
81          assertEquals(upnpService.getRegistry().getLocalSubscription(subscriptionId).getActualDurationSeconds(), 1800);
82  
83          // Now send the initial event
84          subscribeProt.responseSent(subscribeResponseMessage);
85  
86          // And immediately "modify" the state of the service, this should result in "concurrent" event messages
87          service.getManager().getPropertyChangeSupport().firePropertyChange("Status", false, true);
88  
89          StreamRequestMessage unsubscribeRequestMessage =
90                  new StreamRequestMessage(UpnpRequest.Method.UNSUBSCRIBE, ns.getEventSubscriptionPath(service));
91          unsubscribeRequestMessage.getHeaders().add(UpnpHeader.Type.SID, new SubscriptionIdHeader(subscriptionId));
92  
93          ReceivingUnsubscribe unsubscribeProt = new ReceivingUnsubscribe(upnpService, unsubscribeRequestMessage);
94          unsubscribeProt.run();
95          StreamResponseMessage unsubscribeResponseMessage = unsubscribeProt.getOutputMessage();
96          assertEquals(unsubscribeResponseMessage.getOperation().getStatusCode(), UpnpResponse.Status.OK.getStatusCode());
97          assert(upnpService.getRegistry().getLocalSubscription(subscriptionId) == null);
98  
99          List<StreamRequestMessage> sentMessages = upnpService.getRouter().getSentStreamRequestMessages();
100         assertEquals(sentMessages.size(), 2);
101         assertEquals(
102                 (sentMessages.get(0).getOperation()).getMethod(),
103                 UpnpRequest.Method.NOTIFY
104         );
105         assertEquals(
106                 (sentMessages.get(1).getOperation()).getMethod(),
107                 UpnpRequest.Method.NOTIFY
108         );
109         assertEquals(
110                 sentMessages.get(0).getHeaders().getFirstHeader(UpnpHeader.Type.SID, SubscriptionIdHeader.class).getValue(),
111                 subscriptionId
112         );
113         assertEquals(
114                 sentMessages.get(1).getHeaders().getFirstHeader(UpnpHeader.Type.SID, SubscriptionIdHeader.class).getValue(),
115                 subscriptionId
116         );
117         assertEquals(
118                 (sentMessages.get(0).getOperation()).getURI().toString(),
119                 callbackURL.toString()
120         );
121         assertEquals(
122                 sentMessages.get(0).getHeaders().getFirstHeader(UpnpHeader.Type.SEQ, EventSequenceHeader.class).getValue().getValue(),
123                 new Long(0)
124         );
125         assertEquals(
126                 sentMessages.get(1).getHeaders().getFirstHeader(UpnpHeader.Type.SEQ, EventSequenceHeader.class).getValue().getValue(),
127                 new Long(1)
128         );
129 
130     }
131 
132     @Test
133     public void subscriptionLifecycleFailedResponse() throws Exception {
134 
135         MockUpnpService upnpService = new MockUpnpService();
136 
137         // Register local device and its service
138         LocalDevice device = GenaSampleData.createTestDevice(GenaSampleData.LocalTestService.class);
139         upnpService.getRegistry().addDevice(device);
140 
141         Namespace ns = upnpService.getConfiguration().getNamespace();
142 
143         LocalService<?> service = SampleData.getFirstService(device);
144         URL callbackURL = URIUtil.createAbsoluteURL(
145                 SampleData.getLocalBaseURL(), ns.getEventCallbackPath(service)
146         );
147 
148         StreamRequestMessage subscribeRequestMessage =
149                 new StreamRequestMessage(UpnpRequest.Method.SUBSCRIBE, ns.getEventSubscriptionPath(service));
150 
151         subscribeRequestMessage.getHeaders().add(
152                 UpnpHeader.Type.CALLBACK,
153                 new CallbackHeader(callbackURL)
154         );
155         subscribeRequestMessage.getHeaders().add(UpnpHeader.Type.NT, new NTEventHeader());
156 
157         ReceivingSubscribe subscribeProt = new ReceivingSubscribe(upnpService, subscribeRequestMessage);
158         subscribeProt.run();
159 
160         // From the response the subsciber _should_ receive, keep the identifier for later
161         OutgoingSubscribeResponseMessage subscribeResponseMessage = subscribeProt.getOutputMessage();
162         String subscriptionId = subscribeResponseMessage.getHeaders().getFirstHeader(UpnpHeader.Type.SID, SubscriptionIdHeader.class).getValue();
163 
164         // Now, instead of passing the successful response to the protocol, we make it think something went wrong
165         subscribeProt.responseSent(null);
166 
167         // The subscription should be removed from the registry!
168         assert upnpService.getRegistry().getLocalSubscription(subscriptionId) == null;
169 
170     }
171 }