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.local;
17  
18  import org.fourthline.cling.binding.LocalServiceBinder;
19  import org.fourthline.cling.binding.annotations.AnnotationLocalServiceBinder;
20  import org.fourthline.cling.binding.annotations.UpnpAction;
21  import org.fourthline.cling.binding.annotations.UpnpInputArgument;
22  import org.fourthline.cling.binding.annotations.UpnpOutputArgument;
23  import org.fourthline.cling.binding.annotations.UpnpService;
24  import org.fourthline.cling.binding.annotations.UpnpServiceId;
25  import org.fourthline.cling.binding.annotations.UpnpServiceType;
26  import org.fourthline.cling.binding.annotations.UpnpStateVariable;
27  import org.fourthline.cling.binding.xml.DeviceDescriptorBinder;
28  import org.fourthline.cling.binding.xml.ServiceDescriptorBinder;
29  import org.fourthline.cling.mock.MockUpnpService;
30  import org.fourthline.cling.mock.MockUpnpServiceConfiguration;
31  import org.fourthline.cling.model.DiscoveryOptions;
32  import org.fourthline.cling.model.Namespace;
33  import org.fourthline.cling.model.ServerClientTokens;
34  import org.fourthline.cling.model.message.UpnpMessage;
35  import org.fourthline.cling.model.message.header.UpnpHeader;
36  import org.fourthline.cling.model.meta.DeviceDetails;
37  import org.fourthline.cling.model.meta.LocalDevice;
38  import org.fourthline.cling.model.meta.RemoteDevice;
39  import org.fourthline.cling.model.profile.RemoteClientInfo;
40  import org.fourthline.cling.model.types.NotificationSubtype;
41  import org.fourthline.cling.model.types.UDADeviceType;
42  import org.fourthline.cling.test.data.SampleData;
43  import org.seamless.util.URIUtil;
44  import org.testng.annotations.Test;
45  
46  import static org.testng.Assert.assertEquals;
47  import static org.testng.Assert.assertTrue;
48  
49  /**
50   * TODO: These timing-sensitive tests fail sometimes... should use latches instead to coordinate threads
51   */
52  public class LocalDeviceBindingAdvertisementTest {
53  
54      @Test
55      public void registerLocalDevice() throws Exception {
56  
57          MockUpnpService upnpService = new MockUpnpService(true, true);
58  
59          LocalDevice binaryLight = DemoBinaryLight.createTestDevice();
60  
61          upnpService.getRegistry().addDevice(binaryLight);
62  
63          Thread.sleep(2000);
64  
65          assertEquals(upnpService.getRouter().getOutgoingDatagramMessages().size(), 12);
66          for (UpnpMessage msg : upnpService.getRouter().getOutgoingDatagramMessages()) {
67              assertAliveMsgBasics(upnpService.getConfiguration().getNamespace(), msg, binaryLight, 1800);
68          }
69  
70          upnpService.shutdown();
71  
72          DeviceDescriptorBinder dvcBinder = upnpService.getConfiguration().getDeviceDescriptorBinderUDA10();
73          String descriptorXml = dvcBinder.generate(
74              binaryLight,
75              new RemoteClientInfo(),
76              upnpService.getConfiguration().getNamespace()
77          );
78  
79          RemoteDevice testDevice = new RemoteDevice(SampleData.createRemoteDeviceIdentity());
80  
81          testDevice = dvcBinder.describe(testDevice, descriptorXml);
82          assertEquals(testDevice.getDetails().getFriendlyName(), "Example Binary Light");
83  
84          // TODO: more tests
85  
86          ServiceDescriptorBinder svcBinder = upnpService.getConfiguration().getServiceDescriptorBinderUDA10();
87          String serviceXml = svcBinder.generate(binaryLight.getServices()[0]);
88  
89          // TODO: more tests
90      }
91  
92      @Test
93      public void waitForRefresh() throws Exception {
94  
95          MockUpnpService upnpService = new MockUpnpService(true, true);
96  
97          LocalDevice ld =
98              SampleData.createLocalDevice(
99                  SampleData.createLocalDeviceIdentity(1)
100             );
101 
102         upnpService.getRegistry().addDevice(ld);
103         assertEquals(upnpService.getRegistry().getLocalDevices().size(), 1);
104 
105         Thread.sleep(2000);
106 
107         assertEquals(upnpService.getRegistry().getLocalDevices().size(), 1);
108 
109         // 30 from addDevice()
110         // 30 from regular refresh
111         assertTrue(upnpService.getRouter().getOutgoingDatagramMessages().size() >= 60);
112         for (UpnpMessage msg : upnpService.getRouter().getOutgoingDatagramMessages()) {
113             assertAliveMsgBasics(upnpService.getConfiguration().getNamespace(), msg, ld, 1);
114         }
115 
116         upnpService.getRouter().getOutgoingDatagramMessages().clear();
117 
118         upnpService.shutdown();
119 
120         // Check correct byebye
121         assertTrue(upnpService.getRouter().getOutgoingDatagramMessages().size() >= 30);
122         for (UpnpMessage msg : upnpService.getRouter().getOutgoingDatagramMessages()) {
123             assertByeByeMsgBasics(upnpService.getConfiguration().getNamespace(), msg, ld, 1);
124         }
125     }
126 
127     @Test
128     public void waitForAliveFlood() throws Exception {
129 
130         MockUpnpService upnpService = new MockUpnpService(true,
131             new MockUpnpServiceConfiguration(true) {
132                 @Override
133                 public int getAliveIntervalMillis() {
134                     return 2000;
135                 }
136             });
137 
138         LocalDevice ld =
139             SampleData.createLocalDevice(
140                 SampleData.createLocalDeviceIdentity(1000) // Max age ignored
141             );
142 
143         upnpService.getRegistry().addDevice(ld);
144         assertEquals(upnpService.getRegistry().getLocalDevices().size(), 1);
145 
146         Thread.sleep(5000);
147 
148         assertEquals(upnpService.getRegistry().getLocalDevices().size(), 1);
149 
150         // 30 from addDevice()
151         // 30 from first flood
152         // 30 from second flood
153         assertTrue(upnpService.getRouter().getOutgoingDatagramMessages().size() >= 90);
154         for (UpnpMessage msg : upnpService.getRouter().getOutgoingDatagramMessages()) {
155             assertAliveMsgBasics(upnpService.getConfiguration().getNamespace(), msg, ld, 1000);
156         }
157 
158         upnpService.shutdown();
159     }
160 
161     @Test
162     public void byeByeBeforeAlive() throws Exception {
163 
164         MockUpnpService upnpService = new MockUpnpService(true, true);
165 
166         LocalDevice ld =
167             SampleData.createLocalDevice(
168                 SampleData.createLocalDeviceIdentity(60)
169             );
170 
171         upnpService.getRegistry().addDevice(ld, new DiscoveryOptions(true, true));
172 
173         Thread.sleep(2000);
174 
175         assertTrue(upnpService.getRouter().getOutgoingDatagramMessages().size() >= 60);
176         // 30 BYEBYE
177         // 30 ALIVE
178         int i = 0;
179         for (; i < 30; i++) {
180             UpnpMessage msg = upnpService.getRouter().getOutgoingDatagramMessages().get(i);
181             assertByeByeMsgBasics(upnpService.getConfiguration().getNamespace(), msg, ld, 60);
182         }
183         for (; i < 60; i++) {
184             UpnpMessage msg = upnpService.getRouter().getOutgoingDatagramMessages().get(i);
185             assertAliveMsgBasics(upnpService.getConfiguration().getNamespace(), msg, ld, 60);
186         }
187 
188         upnpService.shutdown();
189     }
190 
191 
192     @Test
193     public void registerNonAdvertisedLocalDevice() throws Exception {
194         MockUpnpService upnpService = new MockUpnpService(true, true);
195 
196         LocalDevice binaryLight = DemoBinaryLight.createTestDevice();
197 
198         upnpService.getRegistry().addDevice(binaryLight, new DiscoveryOptions(false)); // Not advertised
199 
200         Thread.sleep(2000);
201 
202         assertEquals(upnpService.getRouter().getOutgoingDatagramMessages().size(), 0);
203 
204         upnpService.shutdown();
205     }
206 
207     protected void assertAliveMsgBasics(Namespace namespace, UpnpMessage msg, LocalDevice device, Integer maxAge) {
208         assertEquals(msg.getHeaders().getFirstHeader(UpnpHeader.Type.NTS).getValue(), NotificationSubtype.ALIVE);
209         assertEquals(
210             msg.getHeaders().getFirstHeader(UpnpHeader.Type.LOCATION).getValue().toString(),
211             URIUtil.createAbsoluteURL(SampleData.getLocalBaseURL(), namespace.getDescriptorPath(device)).toString()
212         );
213         assertEquals(msg.getHeaders().getFirstHeader(UpnpHeader.Type.MAX_AGE).getValue(), maxAge);
214         assertEquals(msg.getHeaders().getFirstHeader(UpnpHeader.Type.SERVER).getValue(), new ServerClientTokens());
215     }
216 
217     protected void assertByeByeMsgBasics(Namespace namespace, UpnpMessage msg, LocalDevice device, Integer maxAge) {
218         assertEquals(msg.getHeaders().getFirstHeader(UpnpHeader.Type.NTS).getValue(), NotificationSubtype.BYEBYE);
219         assertEquals(
220             msg.getHeaders().getFirstHeader(UpnpHeader.Type.LOCATION).getValue().toString(),
221             URIUtil.createAbsoluteURL(SampleData.getLocalBaseURL(), namespace.getDescriptorPath(device)).toString()
222         );
223         assertEquals(msg.getHeaders().getFirstHeader(UpnpHeader.Type.MAX_AGE).getValue(), maxAge);
224         assertEquals(msg.getHeaders().getFirstHeader(UpnpHeader.Type.SERVER).getValue(), new ServerClientTokens());
225     }
226 
227     @UpnpService(
228         serviceId = @UpnpServiceId("SwitchPower"),
229         serviceType = @UpnpServiceType(value = "SwitchPower", version = 1)
230     )
231     public static class DemoBinaryLight {
232 
233         private static LocalDevice createTestDevice() throws Exception {
234             LocalServiceBinder binder = new AnnotationLocalServiceBinder();
235             return new LocalDevice(
236                 SampleData.createLocalDeviceIdentity(),
237                 new UDADeviceType("BinaryLight", 1),
238                 new DeviceDetails("Example Binary Light"),
239                 binder.read(DemoBinaryLight.class)
240             );
241         }
242 
243         @UpnpStateVariable(defaultValue = "0", sendEvents = false)
244         private boolean target = false;
245 
246         @UpnpStateVariable(defaultValue = "0")
247         private boolean status = false;
248 
249         @UpnpAction
250         public void setTarget(@UpnpInputArgument(name = "NewTargetValue") boolean newTargetValue) {
251             target = newTargetValue;
252             status = newTargetValue;
253         }
254 
255         @UpnpAction(out = @UpnpOutputArgument(name = "RetTargetValue"))
256         public boolean getTarget() {
257             return target;
258         }
259 
260         @UpnpAction(out = {@UpnpOutputArgument(name = "ResultStatus")})
261         public boolean getStatus() {
262             return status;
263         }
264 
265     }
266 
267 }
268